Skip to content

feat(tui): read-only Next Work page over engine-local work (T6 slice) - #432

Open
BunsDev wants to merge 5 commits into
feat/411-tool-approvalfrom
feat/413-work-view
Open

BunsDev wants to merge 5 commits into
feat/411-tool-approvalfrom
feat/413-work-view

Conversation

@BunsDev

@BunsDev BunsDev commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Context

Implementation

  • Projection (crates/tui/src/application/work.rs): turns a snapshot of the background registry, the model task list and the session goal into rows.
    • Every row keeps its origin label ([background], [model task], [session goal]) and full id. Rows that share a title are never merged.
    • A blocker that matches no listed task, including a deleted one, is flagged as missing. Nothing is inferred to be ready from its dependencies.
    • States say who reported them. A cancelled background task reads "cancel signalled; exit not confirmed" (Complete foreground shell descendant cancellation and Windows cleanup #373). A completed model task reads "completed (reported by the model)", because TaskStop also writes Completed. A budget-limited goal is its own state, not a failure. Deleted model tasks are not listed.
    • All store text is terminal-safe and kept to one row.
  • Inspector: a Work page between Session and Views. Its header always shows that the rows are engine-local, that in-memory tasks span the process rather than the session, and that canonical tasks need Psyche feat(tui): surface build & turn completion via toast + bell #11/feat(familiars): add access tier so build-tier familiars can use git/shell #12. It reports an unreadable goal store. The Views entry for Work now reads "local only".
  • Snapshot (crates/cli/src/main.rs): taken just before each frame, and only while the Work page is open.
    • Background tasks keep only their last output line.
    • The goal is read at most every 2 s, and at once when the session changes, so another session's goal is never shown.
    • The goal is read through a new GoalStore::open_read_only_nowait (crates/core/src/goal.rs): existing database only, read-only, zero busy timeout. A locked store keeps this session's last good goal instead of stalling the UI.
  • User-visible behavior: Next only. Alt+I, then Tab to Work. Classic is unchanged.
  • Compatibility notes: no storage, protocol or command changes. One new public core function.

Verification

  • cargo fmt --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace --locked: 2873 passed, 0 failed, 52 ignored
  • n/a python3 scripts/check-secrets.py: this repository has no such script. The diff adds no credentials, tokens or private paths.
  • Additional manual checks: every new test was seen failing first, against a stub or with the behavior disabled. The tests cover projection (8), Next render at 80x40, 80x24, 40x12, 20x6 and 1x1 (9), goal display-open (2) and the CLI snapshot (4).

Independent review

A fresh reviewer read 57768b8. Verdict: ready after fixes, nothing blocking. Resolved in 2bfbc6b:

Finding Resolution
Goal read on the UI thread could wait 5 s behind a writer Read-only open with zero busy timeout; a locked store keeps the last good goal
Whole background output cloned every frame Snapshot keeps the last line only
"In this session" overclaimed; in-memory stores are process-wide Wording says "in this process" and "not just this session"
Scope notes could scroll out of view Moved into the inspector header, with a scroll test
Multi-line goal error not kept to one row Folded to one row
Budget limited shown as failure New Limited state, pending color
#[allow] without a reason Justified
No-action test could not fail Checks the real stores and that nothing would be submitted

Accepted and documented: an open page can show a goal changed within the same session up to 2 s late.

Risk and Rollback

  • Risk level: low. Display only, behind the Next renderer, and inactive unless the Work page is open.
  • Rollback plan: revert this PR. No data or format migrates.

Agent Handoff

The first T6 slice. Psyche #11/#12 have not published canonical task,
lane or lease contracts, so this shows only the engine-local stores and
offers no action that starts, stops or retries work.

- application::work projects the background registry, the model task
  list and the session goal into rows that keep their origin and full
  id. Rows that share a title are never merged. A blocker that matches
  no listed task is flagged as missing; nothing is inferred to be ready.
- States say who reported them: a cancelled background task reads
  "cancel signalled; exit not confirmed" (#373), and a completed model
  task reads "completed (reported by the model)", since TaskStop also
  writes Completed. Deleted model tasks are not listed. All store text
  is terminal-safe and kept to one row.
- The inspector gains a Work page between Session and Views. It leads
  with an engine-local note and the Psyche #11/#12 blocker, and reports
  an unreadable goal store. The Views entry for Work now reads "local
  only" and points at the page.
- The interactive loop snapshots the stores into App.work_sources just
  before drawing, only while the Work page is open. The goal is read from
  SQLite at most every two seconds, and at once when the session id
  changes, so another session's goal is never shown.

Tests (seen failing first): projection unit tests for origin
separation, missing blockers, reported states, goal budget and read
errors, and terminal safety; Next render tests at 80x24 and 80x40; CLI
tests for the session-switch re-read (red without the session check)
and the store copy.
- The session goal is read through GoalStore::open_read_only_nowait: an
  existing database only, read-only, with a zero busy timeout, so a
  writer in another process can no longer stall the UI thread. A failed
  read keeps this session's last good goal and reports the error only
  when there is nothing to keep; it never keeps another session's goal.
- The per-frame snapshot keeps only each background task's last output
  line, the only line the page shows.
- The scope notes move into the inspector header, so scrolling cannot
  hide them, and say the in-memory tasks span the process, not just the
  session. The empty state says "in this process".
- A budget-limited goal has its own Limited state, shown as pending
  rather than as a failure. A goal-store error stays on one row.
- The no-action test now checks the real task stores and that nothing
  would be submitted; new tests cover ordering, a deleted blocker,
  scrolling, and 40x12, 20x6 and 1x1 rendering.

Each changed behaviour has a test seen failing first. Within a session
an open page can show a changed goal up to two seconds late; this is
documented on refresh_work_sources.
@vercel

vercel Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docs Ready Ready Preview Nov 2, 2026 6:44am UTC

Request Review

This branch was successfully deployed

1 active deployment
Preview — 47970cad Deployed Nov 2, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant