feat(ui): sidebar groups, dock editor, worklist rows [no-ticket] - #38
Closed
matthias-scale wants to merge 30 commits into
Closed
feat(ui): sidebar groups, dock editor, worklist rows [no-ticket]#38matthias-scale wants to merge 30 commits into
matthias-scale wants to merge 30 commits into
Conversation
Surface the closing block as three independent channels -- blocking gates, running agents, idle -- instead of collapsing them into one screen-scraped status. Screen scraping sees Claude's prompt box the instant a turn ends and calls the pane idle (manifests/claude.toml live_prompt_box, priority 950). That is right about the harness and wrong about the work: agents may still be running, or a Gate may be waiting on a human. Adds the closing-block sources to full_lifecycle_hook_authority so the Stop hook outranks the prompt box, with a regression test asserting the authority does not outlive the agent process. Demo harness under demo/.
Replace prose-shaped reporting with a structured payload any coding agent can
emit from its own turn-end hook:
{"v":1,"agent":"claude","blocking":2,"agents":3,"gates":[...]}
blocking (items only a human can clear) and agents (still working) are
independent, so "nothing for you, but 3 agents are still running" becomes
visible for the first time.
The hook is the trigger, not the model: a turn-end hook fires deterministically,
a tool call the model must remember does not. Transport is the existing herdr
socket, with an atomic JSON mirror under XDG_STATE_HOME as durable fallback.
is_closing_block_source admits any herdr:<agent>-closing-block whose suffix
names the agent it speaks for, so adopting the contract needs no herdr release.
hook_authority_is_effective still requires that agent's process to be present.
Adapters for Claude (Stop) and Codex (notify), plus a dependency-free CLI.
The turn-end status contract was accepted at the RPC edge and then dropped
inside TerminalState, while the caller still saw {"type":"ok"} because
handle_pane_report_agent discards the mutation.
Two gates rejected it, both keyed on session identity:
- route_full_lifecycle_hook_report requires an AgentSessionRef, but
agent_resume::session_ref_from_report mints one only for sources on the
is_official_agent_source allowlist. A closing-block source reports what the
agent just said, not where to resume it, so its ref is always None and every
admitting path was unreachable.
- set_hook_authority_at rejected the report as an owner conflict on any pane
where the real agent had already announced itself under herdr:<agent> -- that
is, every pane that matters.
Accept on process presence instead, which is the only guarantee this source
claims; accept_hook_report still enforces per-source sequence monotonicity.
The existing test passed a session ref the RPC can never produce, so it stayed
green while the live path dropped every report. It now reports with None
against a pane whose session is owned by herdr:claude, and fails without the
fix.
Verified end-to-end against a live claude process: blocked survives the visible
prompt box, repeated detection ticks, and focusing the tab.
Sidebar labels are now "gate" and plain "working". One gate or three, the action is the same; running agents just mean "not done", which the working dot already says. The counts still ride along in the closing_* tokens. Adds INSTALL.md with the wiring verified live for both agents, including the two traps: --settings never loads hooks, and project-scoped hooks are silently skipped until the folder is trusted.
Codex sets its terminal title to the cwd and its rollout files carry no title, so a codex pane has nothing to name it by. The notify handler now derives one from the first turn's user message -- the same thing codex's own resume picker previews -- and pins it in the mirror so later turns do not rename the pane. Rides along as a `session_title` metadata token.
A full-lifecycle source that stays silent leaves its last report standing forever, so a pane that reported a gate kept showing it with nothing able to clear it.
Use recent PTY output as a bounded fallback when Codex has no positive idle or blocker evidence. Codex's non-empty OSC cwd title still resolves Idle but no longer sets visible_idle, so pending-idle confirmation and blocker arbitration can observe the difference. Claude's live prompt box and blocker rules remain unchanged.
Verified against live `agent.read` captures of a codex 0.147 pane: a real turn prints no block marker, so the block-marker region emptied the rule and the only working evidence codex has stopped firing.
source commit: 8605133
A live codex 0.147 turn goes silent for 3.6s between erasing its progress line and the first streamed token; a two-second window showed that gap as `done` mid-turn.
The Blocked and Pinned groups shipped with header rows that reserved a line but never drew one, so the groups read as unexplained gaps above the tree. Paint them with the same chevron a space row uses, and make that chevron real: clicking a header folds its group away, count kept so the header still says how much is hidden. The tree earns a Spaces header -- and a fold of its own -- whenever a group sits above it.
The Blocked and Pinned groups repeated the tree's own row template -- two lines ending in claude or codex -- which answers a question nobody asks of a gate. A grouped row is now a single line: state dot, thread title, then the space it belongs to. Cards carry their row index so a pane listed both in a group and in the tree renders each row in its own shape instead of twice in the first one's.
source commit: f92bc73
This was referenced Aug 9, 2026
matthias-scale
marked this pull request as ready for review
August 10, 2026 07:04
Owner
Author
|
Superseded by repaired PR #46, which carries the rebased head mat125/ui-churn-split-repair against fork/pr-base. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
fork/pr-basedemo/duplicate; canonical payload-v2 closing-block assets remain undersrc/integration/assets/closing-block/Rebase
4f82ffc18ff3cca4d41381b4eb856b05b53ae1d8725cf298d03b7c353b57e4d1704aed1e22e98010Validation
just check-parallelcompleted with the documentedwork_context_gitparallel flake; both affected tests pass when rerun serially