Skip to content

fix(web): show a thread's completion when a watch loop is still live - #7655

Open
liaugust wants to merge 1 commit into
pingdotgg:mainfrom
liaugust:fix/sidebar-completion-behind-monitoring
Open

fix(web): show a thread's completion when a watch loop is still live#7655
liaugust wants to merge 1 commit into
pingdotgg:mainfrom
liaugust:fix/sidebar-completion-behind-monitoring

Conversation

@liaugust

@liaugust liaugust commented Aug 20, 2026

Copy link
Copy Markdown

What Changed

The sidebar row has one status slot, and backgroundLiveness: "monitoring" claimed it ahead of an unread completion, so a finished turn never announced itself. The label now resolves through a pure resolveSidebarThreadTopStatusKind that puts attention states ahead of passive monitoring:

approval → input → failed → working → woke → done → monitoring

working stays ahead of done — real background work means the thread is not finished. Every label, icon and class is unchanged; the existing chain is keyed off the resolved kind. The legacy sidebar's resolveThreadStatusPill had the same ordering, and THREAD_STATUS_PRIORITY is swapped to Completed: 2, Monitoring: 1 so the project rollup keeps its in-code "mirrors the per-thread resolver exactly" invariant.

Why

backgroundLiveness is defined in packages/contracts as "Native background work alive after the turn settles", with "monitoring" meaning "watch loops are the only live work". Whenever the row said Monitoring, the turn had already settled — so the completion the row exists to announce was unreachable.

Monitors are local_bash tasks (ThreadBackgroundLiveness: no agent tasks, ≥1 monitor task), so a thread that leaves a dev server, a tail -f, or a gh pr checks --watch running showed Monitoring for as long as that shell lived and could never show Done again.

Sidebar.tsx already contradicted itself here: shouldRecede contains !isUnread, deliberately keeping an unread monitoring row at full prominence, while the label hid the reason. Sidebar.logic.ts states the principle — "Unread completion is tracked separately: it describes whether a ready thread needs attention, not what the thread is currently doing" — and the neighbouring Plan Ready branch already encodes it.

Approval, Input, Failed and Working already outranked monitoring in resolveSidebarThreadStatus. That was untested, so it is pinned now.

Surfaces

  • Web + desktop: fixed here; desktop wraps the same component.
  • Mobile: does not surface backgroundLiveness at all, so it has no equivalent label to fix.
  • Entry points: all three places this status is derived — the current sidebar row, the legacy sidebar pill (still reachable behind the legacySidebar setting), and the project rollup.
  • Contracts: unchanged; this is a client-side precedence bug.
  • Reverse state: Done is an unread state, so opening the thread returns the slot to Monitoring. Nothing is permanently hidden either way.
  • Performance: one pure call per row render, no new animation, no repaint loop.
  • Docs: no user or internals doc documents these labels, so nothing to update.

UI Changes

Reproduced against a dev build on an isolated T3CODE_HOME: a real turn that leaves a background sleep running so the monitor outlives the settled turn, with the thread left before it finished so the completion landed unseen.

Reported by a nightly user (project, title and branch redacted):

Before — turn finished, completion unseen After

Opening the thread reads the completion and monitoring returns to the slot:

Same live thread in every capture; only this diff differs between them. No motion or timing changes, so no video — the label swap is instant in both directions.

A variant showing both signals at once (Done plus a monitoring dot) was prototyped and left out: a second text label truncated the project name at the row's 238px width, and a new indicator is a design decision rather than part of this fix.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes — not applicable, no motion or interaction behaviour changed

Built with Claude Opus 5 in T3 Code through the Claude Code harness.

The sidebar row has one status slot, and `backgroundLiveness: "monitoring"`
claimed it ahead of an unread completion. Monitors are `local_bash` tasks, so
any thread that leaves a dev server, a `tail -f`, or a `gh pr checks --watch`
running showed `Monitoring` for as long as that shell lived and never showed
`Done` — the user was never told the turn had finished.

Monitoring means watch loops are the ONLY live work, so by then the turn has
already settled: an unread completion or a wake is exactly the news the row
exists to deliver. Resolve the label through a pure resolver that puts those
attention states ahead of monitoring, and keep `working` ahead of them because
real background work means the thread is not done yet. Monitoring returns to
the slot once the completion has been read, so nothing is lost.

The same ordering is fixed in the legacy sidebar's pill, and the project
rollup priority is swapped to match so its documented "mirrors the per-thread
resolver exactly" invariant still holds.

`Approval`, `Input`, `Failed` and `Working` already outranked monitoring in
`resolveSidebarThreadStatus`; that was untested, so it is pinned now too.
@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4553dd2b-104b-4694-8382-bf1f3fc7418b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 20, 2026
@macroscopeapp

macroscopeapp Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — Well-scoped UI fix with good test coverage, but the author has no prior history with this file. The change affects which status indicator users see when watch loops are running alongside unseen completions - recommend human verification of the intended behavior.

You can add or adjust custom eligibility rules. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant