fix(tracker): live AI status takes precedence over stale status.json - #233
Conversation
A worktree's `status.json` lags behind reality whenever the agent forgets to update it on resume. Today the kanban OR'd `aiStatus === 'waiting'` with the file's `waiting_for_input` / `waiting_for_approval` flags, so an actively running agent kept showing yellow "waiting for you" or green "Ready — …" until the agent caught up. Extracted `computeCardStatusFlags` as the single source of truth: when live tmux says `working` / `active`, both file-based waiting states are suppressed. Real consent gates (`aiStatus === 'waiting'`) and no-session fallbacks keep their existing colours. The title-bar `! N waiting / ⟳ N running` count and the project-switcher counts now route through the same helper so all three displays agree. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…eads Per code review: drop the `service` parameter from `computeCardStatusFlags` in favour of pre-evaluated `freshWaiting` / `freshReady` booleans so the helper is pure. Tests no longer need a stub service. Cache `getItemStatus` results in a per-render `Map<slug, ItemStatus>` so the title-bar count loop and the per-card render loop don't both hit disk for the same visible items every keystroke. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code Review — PR #233: live AI status takes precedence over stale status.jsonOverviewThis PR extracts a This is a well-motivated, focused fix. The logic is correct and the test coverage is good. Code Quality
Architecture Concern
Suggestion: move these two pure utility functions to a shared module (e.g. Potential BugThe old const ralphWaiting = !!itemStatus && !readyToAdvance && service.isItemWaiting(itemStatus);The new version drops it: const ralphWaiting = !isWorking && !readyToAdvance && freshWaiting;This is fine as long as Test Coverage9 new cases in One missing case: SummarySolid fix with good tests. Two items to address before merge:
|
…ees] Per PR review: the previous per-render rebuild of `itemStatusBySlug` re-read every item's status.json on every keystroke. Memoize on board + worktrees so reads only fire on the kanban's natural refresh cadence — status.json changes land at the next worktree refresh, which matches the rest of the kanban's update model. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code Review — PR #233: live AI status takes precedence over stale status.jsonOverviewThe fix is conceptually correct and well-executed. The core problem (stale Issues1. Potential display bug —
|
- Move computeCardStatusFlags and isItemPRMerged to src/shared/utils/trackerCardStatus.ts. Screens and dialogs are sibling layers — having a dialog import upward into a screen module was a layering inversion. Both callers now import from the shared utility. - Fix consent-gate vs stale-ready precedence: when live aiStatus === 'waiting', readyToAdvance must also be suppressed, otherwise the green "Ready ✓" branch in getTrackerCardDisplayState wins over the yellow consent-gate render. Adds the matching test case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code Review — PR #233: live AI status takes precedence over stale status.jsonOverviewExtracts status-precedence logic into a shared pure utility ( This is a well-scoped fix for a real UX bug. Code Quality ✅
Precedence chain is correct. Tracing through edge cases:
Performance improvement is real. Suggestions / Minor Issues1. const ralphWaiting = !isWorking && !readyToAdvance && freshWaiting;When const ralphWaiting = !isWorking && !aiWaiting && !readyToAdvance && freshWaiting;This would be logically equivalent (since 2. The }, [board, worktrees, service, projectPath]);
3. Test completeness — one case worth adding: the Test Coverage ✅9 new unit tests covering the key state transitions. The naming is precise ("live working overrides file-based waiting_for_input (yellow → cyan)") which makes failures self-documenting. Security / RiskNo external inputs; all flags are derived from in-memory state. No concerns. Verdict: Approve with minor suggestions. The core logic is correct and well-tested. Suggestions above are non-blocking style/clarity improvements. |
- Make !aiWaiting guard explicit in ralphWaiting (logically equivalent — readyToAdvance already excludes the aiWaiting case — but it documents the precedence chain at a glance). - Comment the load-bearing `worktrees` dep in the itemStatusBySlug memo. - Add precedence test for freshReady=true alone. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code Review — PR #233:
|
Summary
tracker/items/<slug>/status.jsonlags behind reality whenever the agent forgets to update it on resume. The kanban OR'daiStatus === 'waiting'with the file'swaiting_for_input/waiting_for_approvalflags, so an actively running agent kept showing yellow "waiting for you" or green "Ready — …" until the file caught up.computeCardStatusFlagsas the single source of truth: when live tmux saysworking/active, both file-based waiting states are suppressed. Real consent gates (aiStatus === 'waiting') and no-session fallbacks keep their existing colours.! N waiting / ⟳ N runningcount and the project-switcher counts through the same helper so all three displays agree, withgetItemStatusresults cached once per render.Test plan
npx tsc -p tsconfig.test.jsoncleannpx jest tests/unit/TrackerBoardScreen.test.ts— 24/24 (9 new precedence cases)npx jest tests/unit/— 562/563 (one unrelated flake indialog-navigation-bug.test.ts, passes on its own)npm run buildclean🤖 Generated with Claude Code