Product framing
Problem. A user running rimba status --detail to see worktree disk usage and recent activity gets a literal ? in the SIZE and 7D columns on every worktree row. The flag's headline output is effectively broken, and no error is surfaced to explain why.
Value. Anyone using --detail to triage worktrees (which one is bloated on disk, which is stale) regains trustworthy data. A documented flag stops silently producing ?.
Acceptance criteria.
- Given a repo with worktrees (including a large one), when running
rimba status --detail, then SIZE and 7D show real numbers (not ?) on every row.
- A slow filesystem walk on one worktree does not cause the 7D (commit-count) column to fail for that same worktree.
- A regression test reproduces the shared-budget starvation (fails before the fix, passes after).
Impact / Effort. Impact: M — affects every row of a documented flag's output. Effort: S — localized fix in collectStatusEntries plus one regression test.
Surface affected
Specific surface: internal/operations/status_dashboard.go (collectStatusEntries, lines 119-142), internal/git/timeout.go:10 (WithItemTimeout), cmd/status.go:191-205 (rendering).
rimba version
rimba 1.9.6 (commit 96a2883)
Environment
- OS: macOS (darwin)
- Shell: zsh
- git version: (any)
Reproduction steps
- Create a repo with at least one worktree containing a large directory (e.g.
node_modules).
- Run
rimba status --detail.
- Observe the SIZE and 7D columns.
Expected behavior
SIZE and 7D columns show real values (on-disk size and 7-day commit count) on every worktree row. A slow operation on one column must not starve another.
Actual behavior
Both SIZE and 7D render a literal ? on every worktree row.
Root cause
In internal/operations/status_dashboard.go, collectStatusEntries (lines 119-142) derives ONE 10s timeout context via git.WithItemTimeout(ctx) (internal/git/timeout.go:10) and runs FOUR per-item operations sequentially against that single shared budget:
CollectWorktreeStatus (STATUS column)
git.LastCommitTime (AGE column)
fsutil.DirSize (SIZE column — a full filesystem walk, slow on large worktrees e.g. node_modules)
git.CommitCountSince (7D column)
The DirSize walk consumes the shared budget and times out (SizeBytes stays nil, SIZE shows ?), and the subsequent CommitCountSince then receives an already-expired context and fails too (Recent7D stays nil, 7D shows ?). Both errors are swallowed by the if ... err == nil { se.X = &v } guards; the nil pointers render as ? in cmd/status.go:191-205.
git.WithItemTimeout's own doc comment says it "bounds a single git query" — wrapping four operations (including a filesystem walk) in one budget is the design flaw. The constant is 10s and is likely sufficient per-operation; the problem is the SHARING, not the duration.
Proposed fix direction (minimal)
Give each per-item operation its own git.WithItemTimeout(ctx)-derived budget instead of sharing one, so a slow DirSize can't starve CommitCountSince. This matches the documented "single query" intent. No need to increase the 10s constant.
Logs / screenshots (optional)
Re-run with --debug to capture git command timings on stderr.
Product framing
Problem. A user running
rimba status --detailto see worktree disk usage and recent activity gets a literal?in the SIZE and 7D columns on every worktree row. The flag's headline output is effectively broken, and no error is surfaced to explain why.Value. Anyone using
--detailto triage worktrees (which one is bloated on disk, which is stale) regains trustworthy data. A documented flag stops silently producing?.Acceptance criteria.
rimba status --detail, then SIZE and 7D show real numbers (not?) on every row.Impact / Effort. Impact: M — affects every row of a documented flag's output. Effort: S — localized fix in
collectStatusEntriesplus one regression test.Surface affected
cmd/*)internal/operations/)internal/git/)Specific surface:
internal/operations/status_dashboard.go(collectStatusEntries, lines 119-142),internal/git/timeout.go:10(WithItemTimeout),cmd/status.go:191-205(rendering).rimba version
rimba 1.9.6 (commit 96a2883)
Environment
Reproduction steps
node_modules).rimba status --detail.Expected behavior
SIZE and 7D columns show real values (on-disk size and 7-day commit count) on every worktree row. A slow operation on one column must not starve another.
Actual behavior
Both SIZE and 7D render a literal
?on every worktree row.Root cause
In
internal/operations/status_dashboard.go,collectStatusEntries(lines 119-142) derives ONE 10s timeout context viagit.WithItemTimeout(ctx)(internal/git/timeout.go:10) and runs FOUR per-item operations sequentially against that single shared budget:CollectWorktreeStatus(STATUS column)git.LastCommitTime(AGE column)fsutil.DirSize(SIZE column — a full filesystem walk, slow on large worktrees e.g.node_modules)git.CommitCountSince(7D column)The
DirSizewalk consumes the shared budget and times out (SizeBytes stays nil, SIZE shows?), and the subsequentCommitCountSincethen receives an already-expired context and fails too (Recent7D stays nil, 7D shows?). Both errors are swallowed by theif ... err == nil { se.X = &v }guards; the nil pointers render as?incmd/status.go:191-205.git.WithItemTimeout's own doc comment says it "bounds a single git query" — wrapping four operations (including a filesystem walk) in one budget is the design flaw. The constant is 10s and is likely sufficient per-operation; the problem is the SHARING, not the duration.Proposed fix direction (minimal)
Give each per-item operation its own
git.WithItemTimeout(ctx)-derived budget instead of sharing one, so a slowDirSizecan't starveCommitCountSince. This matches the documented "single query" intent. No need to increase the 10s constant.Logs / screenshots (optional)
Re-run with
--debugto capture git command timings on stderr.