Documentation
¶
Overview ¶
Package unfinished provides background scanning for git worktrees that have uncommitted changes, commits ahead of the default branch, or commits behind.
Index ¶
- Constants
- func ComputeDiffHash(worktreePath string) (string, error)
- func SortByLastModified(results []ScanResult)
- type ScanResult
- type ScanResultStatus
- type Scanner
- func (s *Scanner) AddPinnedRepo(repoPath string) error
- func (s *Scanner) AddRepo(repoPath string)
- func (s *Scanner) EnqueueRepo(repoPath string)
- func (s *Scanner) GetAllResults() []ScanResult
- func (s *Scanner) GetResultByKey(repoPath, branch string) (ScanResult, bool)
- func (s *Scanner) InvalidateCache(worktreePath string)
- func (s *Scanner) RemovePinnedRepo(repoPath string)
- func (s *Scanner) RemoveRepo(repoPath string)
- func (s *Scanner) RemoveResult(repoPath, branch string)
- func (s *Scanner) ScanDone() <-chan time.Time
- func (s *Scanner) SetAutoSpider(enabled bool)
- func (s *Scanner) SetTickInterval(d time.Duration)
- func (s *Scanner) Start(ctx context.Context)
- func (s *Scanner) TriggerScan()
- type StateStore
- func (s *StateStore) AutoSpiderEnabled() bool
- func (s *StateStore) CacheSummary(repoPath, branch, diffHash, summary string) error
- func (s *StateStore) Dismiss(repoPath, branch string) error
- func (s *StateStore) GetCachedSummary(repoPath, branch, diffHash string) (string, bool)
- func (s *StateStore) IsDismissed(repoPath, branch string) bool
- func (s *StateStore) IsSnoozed(repoPath, branch, currentHeadSHA string) bool
- func (s *StateStore) Load() error
- func (s *StateStore) PinnedRepos() []string
- func (s *StateStore) SetConfig(autoSpider bool, watchDirs, pinnedRepos []string) error
- func (s *StateStore) Snooze(repoPath, branch, headSHA string) error
- func (s *StateStore) Undismiss(repoPath, branch string) error
- func (s *StateStore) Unsnooze(repoPath, branch string) error
- func (s *StateStore) WatchDirs() []string
- type UnfinishedEvent
- type WatchDirWatcher
- type WorktreeInfo
Constants ¶
const ( // EventUnfinishedWorkUpdated is published when a worktree scan result changes. EventUnfinishedWorkUpdated events.EventType = "unfinished.work_updated" // EventUnfinishedWorkRemoved is published when a worktree is dismissed/snoozed/gone. EventUnfinishedWorkRemoved events.EventType = "unfinished.work_removed" // EventUnfinishedScanCompleted is published after each full scan pass. EventUnfinishedScanCompleted events.EventType = "unfinished.scan_completed" )
Variables ¶
This section is empty.
Functions ¶
func ComputeDiffHash ¶
ComputeDiffHash runs `git -C path diff HEAD` and SHA256-hashes the output.
func SortByLastModified ¶
func SortByLastModified(results []ScanResult)
SortByLastModified sorts a slice of ScanResult descending by LastModified. Equal times are broken by RepoPath+Branch for stability.
Types ¶
type ScanResult ¶
type ScanResult struct {
RepoPath string
Branch string
WorktreePath string
RepoName string
DisplayPath string
HasUncommitted bool
AheadCount int
BehindCount int
DefaultBranch string
ChangedFiles int
LinesAdded int
LinesRemoved int
AheadMessages []string
LastModified time.Time
ScanTime time.Time
Status ScanResultStatus
ErrorMsg string
// SessionID is non-empty if an active stapler-squad session tracks this branch.
SessionID string
}
ScanResult holds the complete unfinished-work state for a single git worktree.
func (ScanResult) IsUnfinished ¶
func (r ScanResult) IsUnfinished() bool
IsUnfinished returns true when at least one unfinished-work criterion is met.
type ScanResultStatus ¶
type ScanResultStatus int
ScanResultStatus describes the quality of a scan result.
const ( ScanResultStatusOK ScanResultStatus = 0 ScanResultStatusTimeout ScanResultStatus = 1 ScanResultStatusPermission ScanResultStatus = 2 ScanResultStatusError ScanResultStatus = 3 )
type Scanner ¶
type Scanner struct {
// contains filtered or unexported fields
}
Scanner is the central coordinator for the unfinished-work background scan.
func NewScanner ¶
func NewScanner(eventBus *events.EventBus, stateStore *StateStore) *Scanner
NewScanner constructs a Scanner. Call Start(ctx) to begin background processing.
func (*Scanner) AddPinnedRepo ¶
AddPinnedRepo validates that path is a git repo, then adds it.
func (*Scanner) EnqueueRepo ¶
EnqueueRepo queues a repo for scanning if it's not cached recently.
func (*Scanner) GetAllResults ¶
func (s *Scanner) GetAllResults() []ScanResult
GetAllResults returns a snapshot of all stored scan results (excluding dismissed/snoozed).
func (*Scanner) GetResultByKey ¶
func (s *Scanner) GetResultByKey(repoPath, branch string) (ScanResult, bool)
GetResultByKey returns a single stored result by (repoPath, branch).
func (*Scanner) InvalidateCache ¶
InvalidateCache invalidates the cache for a given worktree path.
func (*Scanner) RemovePinnedRepo ¶
RemovePinnedRepo removes a pinned repo from scanning.
func (*Scanner) RemoveRepo ¶
RemoveRepo removes a repo from the scan set and purges its results.
func (*Scanner) RemoveResult ¶
RemoveResult removes a result from the store (called after dismiss/snooze).
func (*Scanner) ScanDone ¶
ScanDone returns a channel that receives the completion time of each full scan.
func (*Scanner) SetAutoSpider ¶
SetAutoSpider enables or disables auto-spider of session paths.
func (*Scanner) SetTickInterval ¶
SetTickInterval overrides the default 30-second scan tick (for tests).
func (*Scanner) Start ¶
Start launches the coordinator goroutine and 4 worker goroutines. All goroutines exit cleanly when ctx is cancelled.
func (*Scanner) TriggerScan ¶
func (s *Scanner) TriggerScan()
TriggerScan signals the coordinator to run a full scan immediately.
type StateStore ¶
type StateStore struct {
// contains filtered or unexported fields
}
StateStore manages persistent state for the unfinished-work feature. All public methods are thread-safe.
func NewStateStore ¶
func NewStateStore(path string) (*StateStore, error)
NewStateStore loads (or creates) the state file at the given path.
func (*StateStore) AutoSpiderEnabled ¶
func (s *StateStore) AutoSpiderEnabled() bool
AutoSpiderEnabled returns whether auto-spider is enabled.
func (*StateStore) CacheSummary ¶
func (s *StateStore) CacheSummary(repoPath, branch, diffHash, summary string) error
CacheSummary stores an AI summary in the cache.
func (*StateStore) Dismiss ¶
func (s *StateStore) Dismiss(repoPath, branch string) error
Dismiss permanently hides (repoPath, branch) from unfinished-work results.
func (*StateStore) GetCachedSummary ¶
func (s *StateStore) GetCachedSummary(repoPath, branch, diffHash string) (string, bool)
GetCachedSummary returns a cached AI summary for (repoPath, branch, diffHash). Returns ("", false) on cache miss or expiry.
func (*StateStore) IsDismissed ¶
func (s *StateStore) IsDismissed(repoPath, branch string) bool
IsDismissed returns true when (repoPath, branch) has been permanently dismissed.
func (*StateStore) IsSnoozed ¶
func (s *StateStore) IsSnoozed(repoPath, branch, currentHeadSHA string) bool
IsSnoozed returns true if the worktree is snoozed and the HEAD SHA has not changed. When currentSHA differs from the snooze-time SHA, the snooze is auto-cleared. Note: currentSHA here is the worktree path (we'll look up HEAD SHA on demand if needed). For simplicity, we accept the HEAD SHA directly.
func (*StateStore) Load ¶
func (s *StateStore) Load() error
Load reads the state file from disk. Returns os.ErrNotExist if the file is missing.
func (*StateStore) PinnedRepos ¶
func (s *StateStore) PinnedRepos() []string
PinnedRepos returns the configured pinned repos.
func (*StateStore) SetConfig ¶
func (s *StateStore) SetConfig(autoSpider bool, watchDirs, pinnedRepos []string) error
SetConfig atomically replaces config fields and saves.
func (*StateStore) Snooze ¶
func (s *StateStore) Snooze(repoPath, branch, headSHA string) error
Snooze hides (repoPath, branch) until its HEAD SHA changes.
func (*StateStore) Undismiss ¶
func (s *StateStore) Undismiss(repoPath, branch string) error
Undismiss removes the dismiss record for (repoPath, branch).
func (*StateStore) Unsnooze ¶
func (s *StateStore) Unsnooze(repoPath, branch string) error
Unsnooze removes the snooze record.
func (*StateStore) WatchDirs ¶
func (s *StateStore) WatchDirs() []string
WatchDirs returns the configured watch directories.
type UnfinishedEvent ¶
type UnfinishedEvent struct {
events.Event
ScanResult ScanResult
CompletedAt time.Time
}
UnfinishedEvent extends events.Event with extra fields for unfinished-work events. It reuses the existing events.Event type by embedding the ScanResult in Context.
type WatchDirWatcher ¶
type WatchDirWatcher struct {
// contains filtered or unexported fields
}
WatchDirWatcher discovers git repos under configured watch directories and triggers scans via fsnotify on .git/ changes.
func NewWatchDirWatcher ¶
func NewWatchDirWatcher(scanner *Scanner, stateStore *StateStore) *WatchDirWatcher
NewWatchDirWatcher creates a WatchDirWatcher. It attempts to create an fsnotify watcher and falls back to polling if the system doesn't support it.
func (*WatchDirWatcher) AddPinnedRepo ¶
func (w *WatchDirWatcher) AddPinnedRepo(repo string)
AddPinnedRepo adds a pinned repo and triggers an immediate scan.
func (*WatchDirWatcher) AddWatchDir ¶
func (w *WatchDirWatcher) AddWatchDir(dir string)
AddWatchDir adds a new watch directory at runtime and walks it immediately.
func (*WatchDirWatcher) RemoveWatchDir ¶
func (w *WatchDirWatcher) RemoveWatchDir(dir string)
RemoveWatchDir removes a watch directory (repos only removed if not covered by other sources).
func (*WatchDirWatcher) Start ¶
func (w *WatchDirWatcher) Start(ctx context.Context)
Start begins watching all configured watch dirs and pinned repos. It performs an initial walk then starts the event loop.
type WorktreeInfo ¶
type WorktreeInfo struct {
Path string
HEAD string
Branch string
IsBare bool
IsDetached bool
IsPrunable bool
IsLocked bool
}
WorktreeInfo is parsed from `git worktree list --porcelain`.
func ParseAllWorktrees ¶
func ParseAllWorktrees(output string) []WorktreeInfo
ParseAllWorktrees parses `git worktree list --porcelain` output into WorktreeInfo slices. It does NOT filter—the caller decides what to skip.