Repository navigation
Keep keyboard focus when an approval is answered, its turn folds, Stop ends it, or Jump to latest is used (CF-8) - #342
Conversation
The CF-8 keyboard walkthrough found that pressing Approve or Deny with
the keyboard dropped focus onto the page body: the answer buttons
unmount once pressed, and a finished turn then hides its folded work.
A keyboard or VoiceOver user lost their place twice.
Focus now moves to the card's answer line ("Sending decision…", then
"Approved" or "Denied"). When the finished turn folds work that holds
focus, it moves to the turn's "Worked for" toggle. Focus elsewhere,
such as the composer, is left alone.
Red first: both keyboard tests failed on main (answer line inactive).
e2e/keyboard-answers.spec.ts passes 3/3; the full desktop e2e passes
366 with 6 opt-in skips.
Part of #281 (CF-8), tracker #273.
Coven-Harness: Claude Code / claude-opus-5-5
Coven-Harness: Claude Code / claude-opus-5-5
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The second walkthrough probe found the same defect at Stop: the button goes away when the turn ends, and focus fell onto the page body. When Stop was pressed with focus on it, focus now moves to the message box, where the next message is typed. Red first: the new keyboard test failed on the previous commit (composer inactive); keyboard-answers.spec.ts passes 4/4 and the full desktop e2e passes 367 with 6 opt-in skips. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5
The third walkthrough probe found that Jump to latest, once activated, goes away at the bottom and left focus on the page body. When the button held focus, focus now moves to the message box there. Red first: the new test failed (message box inactive). The keyboard spec passes 5/5, app.spec with it 19/19, and conversation-continuity plus typed-turns, which also scroll, 8/8. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5
A checklist for the human review, with a seed script and an offline review scenario: two approvals, an 8-second command and a reply with a code block. No CLI usage. The expected names, tab order and focus moves come from three walkthrough probes of that scenario, not from assumptions. The probes also found the four focus drops fixed in #342. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5
Coven-Harness: Claude Code / claude-opus-5-5
Code coverage overviewLanguages: TypeScript TypeScript / code-coverage-agent
View coverage of the 1 most impacted file.
ℹ️ Calculations represent line coverage. Results may change as calculations are updated. Updated |
Coven-Harness: Claude Code / claude-opus-5-5
… entry The merge kept both sides of a block #339 had moved, which duplicated the released entries. The page is now main's, plus this PR's one entry. Coven-Harness: Claude Code / claude-opus-5-5
Coven-Harness: Claude Code / claude-opus-5-5
docs/status.md is main's page plus this PR's entry. Coven-Harness: Claude Code / claude-opus-5-5
|
A flaky test from this PR. After focusing The trace is in that run's |
|
Follow-up: this fails often on CI.
#345 changes only What the failure snapshot shows (
So the jump probably scrolls to the bottom, and then the composer grows when the chip appears. The transcript's view shrinks, the reader is no longer at the bottom, and the button stays. That would explain why it fails only on slower CI runners. Either the transcript should stay pinned to the bottom after Jump to latest when the composer resizes, or the test should wait for the chip before pressing Enter. The first is the real fix for a reader. |
…359) * Prepare desktop 0.3.0 and Companion 0.3.0 (8) (#337) * Accept a v<version>-rc.<N> tag in the release identity check Since #186 the identity check refused every tag but v<version>, so a release could no longer be rehearsed with an rc tag. A rehearsal tag now names the package version and an rc number from 1 with no leading zero; the version itself stays strictly x.y.z and the identity output is unchanged. The rc run is the real workflow, lands on a draft named after the rc tag, and is deleted afterwards (docs/release-signing.md, "Rehearsing with an rc tag"). Coven-Harness: Claude Code / claude-opus-5-5 * Bump the desktop app to 0.3.0 Coven-Harness: Claude Code / claude-opus-5-5 * Prepare desktop 0.3.0 and Companion 0.3.0 (8) Companion moves to 0.3.0 (8) so its next TestFlight build, which reads the thread again when the Mac refuses an answer from the phone (#318), is cut from the same tag. The review records the scope since v0.2.0, the v0.3.0-rc.1 hosted rehearsal and the local verification. status.md lists the preparation under In flight. Coven-Harness: Claude Code / claude-opus-5-5 * Record the v0.3.0 local verification Coven-Harness: Claude Code / claude-opus-5-5 * Record the v0.3.0 local verification Coven-Harness: Claude Code / claude-opus-5-5 * Record the v0.3.0 local verification Coven-Harness: Claude Code / claude-opus-5-5 * Leave a request open when saving its answer fails (CF-6, finding 10) (#336) Before this change, answer() and answerQuestion() had the broker accept the answer (the request became resolving) and dropped the pending entry before saving the card. When that save threw, as it does on a full disk, the request stayed resolving with no way to answer it. A retry was refused as already-resolved, the CLI heard nothing, and the in-memory card read as sending until Stop. The card is now saved before the pending entry is dropped. If the save fails, the broker state and the card go back to what they were and the error goes to the caller, so the person can answer again. This is the same rule addItem follows. A failed write that still reached the disk reads as uncertain after a crash, never as sent; a test pins that case. Coven-Harness: Claude Code / claude-opus-5-5 * End a stopped Codex turn's background commands, or say they may still run (#341) Live smoke on 2026-10-20 (codex-cli 0.163.0, unified_exec on): Codex moved `sleep 30` to a background terminal after 1 s, Stop's turn/interrupt ended the turn but not the terminal, and the file was written 30 s later while Modex showed the call interrupted. Modex now opts into the app-server's experimental methods. When Codex reports a turn interrupted with commands still open, it terminates that turn's own background terminals (never an earlier turn's), lists them again, and calls a command interrupted only once Codex no longer lists it. A command Codex cannot confirm, or an older CLI without these methods, reads unknown with a notice. Red first: four new tests failed on main; all five pass, and the Codex backend file passes 34/34. Live: the fixed build passed edit, check, final answer and Stop (the file was never written). Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Record v0.3.0 publication and advance the website fallback (#339) * Advance the website download fallback to 0.3.0 release.json's verified fallback and the site's release tests move from 0.2.0 to 0.3.0, as #314 did for 0.2.0. Site tests: 10 of 10; site e2e: 7 of 7. Coven-Harness: Claude Code / claude-opus-5-5 * Record v0.3.0 publication v0.3.0 was published on 2026-10-20 (07:41 UTC) from signed tag v0.3.0 on 30ee279, with macOS, Windows and Linux installers, at Val's request. Release run 39382565427 passed signing, notarization, stapling, packaged E2E, the Windows and Linux checks and all three signed native updater scenarios, each starting with the automatic download. The downloaded installers passed independent checks, and the packaged E2E passed 363 cases against the download. The updater parser selects the 0.3.0 ZIP and its digest from the live releases/latest for 0.2.0, 0.1.0 and 0.0.12. The publishing request omitted tag_name, and GitHub published the draft as untagged for 25 seconds. Installed Macs saw no update during that window. The review records it. - status: a Shipped row linking the review. "On main, unreleased" moves to the review's What shipped and is empty. The preparation entry becomes the two gates still open: the release Mac's banner upgrade from v0.2.0, and Companion build 8 to TestFlight. These supersede v0.2.0's gates. The fidelity entry points at the review. - review: the release run, download checks, publication, and What shipped. The run's release manifest is kept as evidence. - README: over-the-air updates start with v0.3.0. ios-companion: 0.3.0 (build 8). - landing-page, native-platforms: the fallback and installer publication move to v0.3.0. Coven-Harness: Claude Code / claude-opus-5-5 * Define the Code Review read contract and fixtures (CR-1) (#334) * Define the Code Review read contract and fixtures (CR-1) CR-1 of tracker #319 (#320). The contract every Gate A slice works against, with nothing wired yet: no IPC channel, no UI, no GitHub call. - src/shared/code-review.ts: locator, account-scoped key and revision; ready/partial/stale/unavailable reads; check and diff coverage rules (pending is never passing, a missing patch is not a zero-line change); Gate A capabilities; and validateRequest, main's check on everything the renderer may send. - test/fixtures/code-review.ts: synthetic R1-R4 data and faults, plain data with a fixed clock. Nothing is copied from the screenshots. - docs/design/code-review.md: the decisions Val confirmed on #320, a source map checked at 9c0b063, the reference manifest and calibration, and an owner and test for each of 76 reference controls. - docs/status.md: Code Review under In flight. Coven-Harness: Claude Code / claude-opus-5-5 * Fix the CR-1 review findings: synthetic fixtures, reply scope, re-runs The independent review of #334 found that the fixtures were the reference PRs with the nouns swapped, some sentences verbatim, and that three contract rules did not hold as written. - Fixtures: rewritten from scratch as a made-up library-lending project. Only layout and density carry over. A new test checks that every patch's hunk headers count its lines and the totals add up. - acceptsReply takes the operation and implements the connection exception its comment promised. scopeOf(request, account) defines a reply's scope as its request's, so main and the renderer agree. - summarizeChecks counts only the newest run of a re-run check (ids grow with creation), so a passing re-run replaces its failure. - inboxGroup marks partial groups of a stale inbox stale; knownCount never calls a stale total exact. - validateRequest rejects lone surrogates in any text and invisible format characters in paths and refs. - An unavailable read names no issue: installing or signing in to gh is the person's fix. - Design page: who posted the #320 decisions, typography and spacing measurements with two token proposals, the composer's model and access-mode icons, scroll regions and avatars in the inventory, a seventh open decision, and corrected source-map wording. Coven-Harness: Claude Code / claude-opus-5-5 * Match re-runs by reporter and reject C1 controls (CR-1 re-review) The re-review of #334 confirmed the ten findings fixed and left these: - A check run is matched to its re-run by reporter as well as name and head (PrCheck.reporter: the app slug or the status creator), so another reporter's same-named check is not hidden. Without numeric ids, a queued re-run counts as the latest. - CONTROL covers C0, DEL, C1 and the line and paragraph separators. - Design page: the encodeURIComponent rule moves to the engineering decisions, ModelMenu's line is 195, C82 cites the access pill, and C77-C82 follow C76. Coven-Harness: Claude Code / claude-opus-5-5 * Keep keyboard focus when an approval is answered, its turn folds, Stop ends it, or Jump to latest is used (CF-8) (#342) * Keep keyboard focus when an approval is answered and its turn folds The CF-8 keyboard walkthrough found that pressing Approve or Deny with the keyboard dropped focus onto the page body: the answer buttons unmount once pressed, and a finished turn then hides its folded work. A keyboard or VoiceOver user lost their place twice. Focus now moves to the card's answer line ("Sending decision…", then "Approved" or "Denied"). When the finished turn folds work that holds focus, it moves to the turn's "Worked for" toggle. Focus elsewhere, such as the composer, is left alone. Red first: both keyboard tests failed on main (answer line inactive). e2e/keyboard-answers.spec.ts passes 3/3; the full desktop e2e passes 366 with 6 opt-in skips. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Hand focus to the message box when a keyboard Stop ends the turn The second walkthrough probe found the same defect at Stop: the button goes away when the turn ends, and focus fell onto the page body. When Stop was pressed with focus on it, focus now moves to the message box, where the next message is typed. Red first: the new keyboard test failed on the previous commit (composer inactive); keyboard-answers.spec.ts passes 4/4 and the full desktop e2e passes 367 with 6 opt-in skips. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Hand focus to the message box after Jump to latest from the keyboard The third walkthrough probe found that Jump to latest, once activated, goes away at the bottom and left focus on the page body. When the button held focus, focus now moves to the message box there. Red first: the new test failed (message box inactive). The keyboard spec passes 5/5, app.spec with it 19/19, and conversation-continuity plus typed-turns, which also scroll, 8/8. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Restore main's status.md after the #339 merge, keeping only this PR's entry The merge kept both sides of a block #339 had moved, which duplicated the released entries. The page is now main's, plus this PR's one entry. Coven-Harness: Claude Code / claude-opus-5-5 * Show a Codex web search's query and the results Codex reported (CF-5) (#344) A live codex-cli 0.163.0 capture (test/fixtures/codex-websearch-0.163.0.json) shows the webSearch item starting with an empty query, no action and no results, and completing with the query, a search action and text_result entries (title, url, domain, snippet). Modex titled the row "search " from the empty start, read neither action nor results, and stored the JSON string "" as its output. codexWebSearch (shared/evidence.ts) keeps the query, the action and results with an http(s) link, each text bounded, and counts what it drops. The Codex backend titles the row "search the web" until the query arrives, then "search <query>", and carries the search on the tool item. Expanded, the results show as links with snippets, marked data-provenance="codex-search" and labelled as unchecked. The renderer checks each link again before showing it, and nothing is fetched until a link is clicked. Older searches no longer show "". Red first: the three evidence tests and the Codex backend test failed on a stub, and the e2e test failed ("done", not "2 results"). Now evidence, codex-backend and conversation-events pass 69/69, the conversation-evidence spec passes 7/7, and the desktop unit suite 1,709 passed with 16 skipped. Part of #278 (CF-5), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Land main through a merge queue (#345) main requires branches to be up to date, so every landing sent each open PR back through CI. On 2026-10-19 that cost #309 three extra macOS runs, and on 2026-10-20 #336, #340 and #343 one or more each. The ruleset file gains a merge_queue rule (squash, all-green groups, up to 3 groups building and 5 PRs per merge, a 90-minute check timeout, since the macOS job alone may take 45). It drops the up-to-date requirement, which the queue replaces: a queued PR is tested on top of main and the PRs ahead of it. CI runs on merge_group, so each queued group reports the required unit + e2e (macOS) check; without it the queue drops every PR. The iPhone job and the coverage upload skip queued groups: neither is required, the PR already ran them, and main's push run repeats them. README, AGENTS.md and status.md say PRs land through the queue. The live ruleset (23989202) takes this file once this lands, so the queue starts only after main can report checks for it. Coven-Harness: Claude Code / claude-opus-5-5 * Say the phone no longer shows a withdrawn approval as declined (#343) human-requests.md still said the iPhone shows a withdrawn approval as declined. Since #335, mobileItem (companion.ts) sends a withdrawn, sending or uncertain approval to the phone as a notice that says so. The companion fallback test now covers the withdrawn case, which had no test (CF-6 #279, finding 7). Coven-Harness: Claude Code / claude-opus-5-5 * Note that the merge queue needs auto-merge, and list the keyboard Jump to latest CI failure (steward cycle 17) (#347) The first PR queued after #345 failed to enqueue: "Auto merge is not allowed for this repository". gh pr merge adds a PR to a merge queue by enabling auto-merge, so the repository now allows it, as OpenCoven/coven does, and README says why. e2e/keyboard-answers.spec.ts:88 (#342) failed in three CI runs of #345 in a row and passed on #342, on main and 25/25 locally. It goes under Known rough edges with what the failure snapshot shows and a link to the analysis on #342. Coven-Harness: Claude Code / claude-opus-5-5 * Prove a queue-landed branch merged when its tip merges cleanly into the landed tree (#350) Since #345, main lands through a merge queue, which squashes each PR onto main as it stands at the PR's turn. A branch that merged main into itself, then landed behind another PR, had no proof that worktree.sh remove would accept: - the squash tree also holds the PRs ahead of it, so it is not the tip's tree; - the branch's merge commits rule out the binary-diff proof. cf6-docs-followup (#343) hit this on 2026-10-20 and had to be pointed at its squash commit by hand. The new merge-tree proof merges the exact PR tip onto the squash commit's parent with Git's own merge. It accepts only a clean merge (exit 0) whose tree is exactly the landed tree. A configured merge.<name>.driver turns the check off, because a driver can drop a side's changes and still report a clean merge. New tests: - a queued branch with merge commits is proven and removed, and its archive ref holds the tip; - a wrong head, a wrong base, a different tree, a conflicted merge (even when the squash holds exactly the conflicted tree) and a configured driver that keeps main's side each stay not-proven-merged. Checked against #343's real branch and PR record in a throwaway clone. The old proof returns null. The new proof returns merge-tree with tree 6fc493b, the tree of 0a67354. Coven-Harness: Claude Code / claude-opus-5-5 * Hold Jump to latest when the composer grows or a Page Up is still moving (#352) * Hold Jump to latest when the composer grows or a Page Up is still moving e2e/keyboard-answers.spec.ts:88 (#342) failed on slow CI runners: after Enter, Jump to latest stayed. A trace in the app found two causes. - A scroll event is delivered before the browser reports a resize. If the composer grew right after the jump (a follow-up chip), onScroll measured a shorter view and stopped following. It now keeps following while the view has not moved above where auto-scroll put it, as follow() already did. - A Page Up still animating keeps applying its remaining distance after the page sets a new position: plain assignment, scrollTo instant and an overflow toggle all lose to it. For a second after a jump, a scroll with no wheel, key, pointer or touch input since the jump is that leftover motion, and the view pins back to the bottom. The reader's own scroll still wins at once. Red first, each test alone on main's ThreadView: the composer-growth test failed (the button stayed), the Page Up test failed (the view went back up 138 px), and the scroll-up guard passed. With the fix, keyboard-answers passes 24/24 (8 tests x 3), and app, conversation- continuity, typed-turns, conversation-rendering and layout 43/43. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Move the Jump to latest rough edge to the resolved list, with its cause The entry #347 added leaves Known rough edges, as written, under #352, with the two causes the trace found. Coven-Harness: Claude Code / claude-opus-5-5 * Say whether a check verified a turn's last change (CF-7 verification) (#351) * Say whether a check verified a turn's last change, in its task record (CF-7) verification() in shared/task-context.ts reads a turn's tools in transcript order: - A check is a known test, build, typecheck or lint command, read inside sh/bash/zsh -c with quotes respected. An exit-zero echo or the model saying "tests pass" is not one. - A check passes only as succeeded with exit code 0 or none reported. - A check goes stale when an edit that was not denied, or a command that might write, runs after it. - The turn reads verified, failed, unknown, stale or none. taskRecord carries it, and the note gets a Verification section that marks stale checks. Anything short of verified goes under Not settled; a failure a later fix superseded does not. Plan steps keep the CLI's statuses: neither CLI links a check to a step. Red first: five of six new tests failed on a stub, then edits and displayCommand on theirs. task-context passes 13/13; the desktop unit suite 1,723 passed, 16 skipped. Part of #280 (CF-7), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Show a turn's verification beside Save to Notes (CF-7) A finished turn's footer reads, for example, "Verified: pnpm test passed after the last change" or "Not verified: pnpm test ran before a later change". It also covers a check that failed, a check that did not say how it ended, and a turn whose changes no check followed. A check shows as the script its shell ran, with the exact command on hover. A turn that changed nothing and ran no check shows nothing. Red first: the new e2e test found no verification lines (expected 2, received 0). task-to-notes.spec.ts passes 3/3. docs/task-context.md gains a Verification section, and status.md an entry. Part of #280 (CF-7), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * List #352's Jump to latest fix under On main, unreleased (steward cycle 19) (#353) #352 changed what readers see: after a jump, the transcript no longer stops short of the bottom when the message box grows or a Page Up is still scrolling. It moved the CI rough edge to the resolved list but added no unreleased entry, so the next release review would not have listed it. The entry sits beside CF-8's keyboard entry and links the resolved list's account of the causes. Coven-Harness: Claude Code / claude-opus-5-5
* Prepare desktop 0.3.0 and Companion 0.3.0 (8) (#337) * Accept a v<version>-rc.<N> tag in the release identity check Since #186 the identity check refused every tag but v<version>, so a release could no longer be rehearsed with an rc tag. A rehearsal tag now names the package version and an rc number from 1 with no leading zero; the version itself stays strictly x.y.z and the identity output is unchanged. The rc run is the real workflow, lands on a draft named after the rc tag, and is deleted afterwards (docs/release-signing.md, "Rehearsing with an rc tag"). Coven-Harness: Claude Code / claude-opus-5-5 * Bump the desktop app to 0.3.0 Coven-Harness: Claude Code / claude-opus-5-5 * Prepare desktop 0.3.0 and Companion 0.3.0 (8) Companion moves to 0.3.0 (8) so its next TestFlight build, which reads the thread again when the Mac refuses an answer from the phone (#318), is cut from the same tag. The review records the scope since v0.2.0, the v0.3.0-rc.1 hosted rehearsal and the local verification. status.md lists the preparation under In flight. Coven-Harness: Claude Code / claude-opus-5-5 * Record the v0.3.0 local verification Coven-Harness: Claude Code / claude-opus-5-5 * Record the v0.3.0 local verification Coven-Harness: Claude Code / claude-opus-5-5 * Record the v0.3.0 local verification Coven-Harness: Claude Code / claude-opus-5-5 * Leave a request open when saving its answer fails (CF-6, finding 10) (#336) Before this change, answer() and answerQuestion() had the broker accept the answer (the request became resolving) and dropped the pending entry before saving the card. When that save threw, as it does on a full disk, the request stayed resolving with no way to answer it. A retry was refused as already-resolved, the CLI heard nothing, and the in-memory card read as sending until Stop. The card is now saved before the pending entry is dropped. If the save fails, the broker state and the card go back to what they were and the error goes to the caller, so the person can answer again. This is the same rule addItem follows. A failed write that still reached the disk reads as uncertain after a crash, never as sent; a test pins that case. Coven-Harness: Claude Code / claude-opus-5-5 * End a stopped Codex turn's background commands, or say they may still run (#341) Live smoke on 2026-10-20 (codex-cli 0.163.0, unified_exec on): Codex moved `sleep 30` to a background terminal after 1 s, Stop's turn/interrupt ended the turn but not the terminal, and the file was written 30 s later while Modex showed the call interrupted. Modex now opts into the app-server's experimental methods. When Codex reports a turn interrupted with commands still open, it terminates that turn's own background terminals (never an earlier turn's), lists them again, and calls a command interrupted only once Codex no longer lists it. A command Codex cannot confirm, or an older CLI without these methods, reads unknown with a notice. Red first: four new tests failed on main; all five pass, and the Codex backend file passes 34/34. Live: the fixed build passed edit, check, final answer and Stop (the file was never written). Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Record v0.3.0 publication and advance the website fallback (#339) * Advance the website download fallback to 0.3.0 release.json's verified fallback and the site's release tests move from 0.2.0 to 0.3.0, as #314 did for 0.2.0. Site tests: 10 of 10; site e2e: 7 of 7. Coven-Harness: Claude Code / claude-opus-5-5 * Record v0.3.0 publication v0.3.0 was published on 2026-10-20 (07:41 UTC) from signed tag v0.3.0 on 30ee279, with macOS, Windows and Linux installers, at Val's request. Release run 39382565427 passed signing, notarization, stapling, packaged E2E, the Windows and Linux checks and all three signed native updater scenarios, each starting with the automatic download. The downloaded installers passed independent checks, and the packaged E2E passed 363 cases against the download. The updater parser selects the 0.3.0 ZIP and its digest from the live releases/latest for 0.2.0, 0.1.0 and 0.0.12. The publishing request omitted tag_name, and GitHub published the draft as untagged for 25 seconds. Installed Macs saw no update during that window. The review records it. - status: a Shipped row linking the review. "On main, unreleased" moves to the review's What shipped and is empty. The preparation entry becomes the two gates still open: the release Mac's banner upgrade from v0.2.0, and Companion build 8 to TestFlight. These supersede v0.2.0's gates. The fidelity entry points at the review. - review: the release run, download checks, publication, and What shipped. The run's release manifest is kept as evidence. - README: over-the-air updates start with v0.3.0. ios-companion: 0.3.0 (build 8). - landing-page, native-platforms: the fallback and installer publication move to v0.3.0. Coven-Harness: Claude Code / claude-opus-5-5 * Define the Code Review read contract and fixtures (CR-1) (#334) * Define the Code Review read contract and fixtures (CR-1) CR-1 of tracker #319 (#320). The contract every Gate A slice works against, with nothing wired yet: no IPC channel, no UI, no GitHub call. - src/shared/code-review.ts: locator, account-scoped key and revision; ready/partial/stale/unavailable reads; check and diff coverage rules (pending is never passing, a missing patch is not a zero-line change); Gate A capabilities; and validateRequest, main's check on everything the renderer may send. - test/fixtures/code-review.ts: synthetic R1-R4 data and faults, plain data with a fixed clock. Nothing is copied from the screenshots. - docs/design/code-review.md: the decisions Val confirmed on #320, a source map checked at 9c0b063, the reference manifest and calibration, and an owner and test for each of 76 reference controls. - docs/status.md: Code Review under In flight. Coven-Harness: Claude Code / claude-opus-5-5 * Fix the CR-1 review findings: synthetic fixtures, reply scope, re-runs The independent review of #334 found that the fixtures were the reference PRs with the nouns swapped, some sentences verbatim, and that three contract rules did not hold as written. - Fixtures: rewritten from scratch as a made-up library-lending project. Only layout and density carry over. A new test checks that every patch's hunk headers count its lines and the totals add up. - acceptsReply takes the operation and implements the connection exception its comment promised. scopeOf(request, account) defines a reply's scope as its request's, so main and the renderer agree. - summarizeChecks counts only the newest run of a re-run check (ids grow with creation), so a passing re-run replaces its failure. - inboxGroup marks partial groups of a stale inbox stale; knownCount never calls a stale total exact. - validateRequest rejects lone surrogates in any text and invisible format characters in paths and refs. - An unavailable read names no issue: installing or signing in to gh is the person's fix. - Design page: who posted the #320 decisions, typography and spacing measurements with two token proposals, the composer's model and access-mode icons, scroll regions and avatars in the inventory, a seventh open decision, and corrected source-map wording. Coven-Harness: Claude Code / claude-opus-5-5 * Match re-runs by reporter and reject C1 controls (CR-1 re-review) The re-review of #334 confirmed the ten findings fixed and left these: - A check run is matched to its re-run by reporter as well as name and head (PrCheck.reporter: the app slug or the status creator), so another reporter's same-named check is not hidden. Without numeric ids, a queued re-run counts as the latest. - CONTROL covers C0, DEL, C1 and the line and paragraph separators. - Design page: the encodeURIComponent rule moves to the engineering decisions, ModelMenu's line is 195, C82 cites the access pill, and C77-C82 follow C76. Coven-Harness: Claude Code / claude-opus-5-5 * Keep keyboard focus when an approval is answered, its turn folds, Stop ends it, or Jump to latest is used (CF-8) (#342) * Keep keyboard focus when an approval is answered and its turn folds The CF-8 keyboard walkthrough found that pressing Approve or Deny with the keyboard dropped focus onto the page body: the answer buttons unmount once pressed, and a finished turn then hides its folded work. A keyboard or VoiceOver user lost their place twice. Focus now moves to the card's answer line ("Sending decision…", then "Approved" or "Denied"). When the finished turn folds work that holds focus, it moves to the turn's "Worked for" toggle. Focus elsewhere, such as the composer, is left alone. Red first: both keyboard tests failed on main (answer line inactive). e2e/keyboard-answers.spec.ts passes 3/3; the full desktop e2e passes 366 with 6 opt-in skips. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Hand focus to the message box when a keyboard Stop ends the turn The second walkthrough probe found the same defect at Stop: the button goes away when the turn ends, and focus fell onto the page body. When Stop was pressed with focus on it, focus now moves to the message box, where the next message is typed. Red first: the new keyboard test failed on the previous commit (composer inactive); keyboard-answers.spec.ts passes 4/4 and the full desktop e2e passes 367 with 6 opt-in skips. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Hand focus to the message box after Jump to latest from the keyboard The third walkthrough probe found that Jump to latest, once activated, goes away at the bottom and left focus on the page body. When the button held focus, focus now moves to the message box there. Red first: the new test failed (message box inactive). The keyboard spec passes 5/5, app.spec with it 19/19, and conversation-continuity plus typed-turns, which also scroll, 8/8. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Restore main's status.md after the #339 merge, keeping only this PR's entry The merge kept both sides of a block #339 had moved, which duplicated the released entries. The page is now main's, plus this PR's one entry. Coven-Harness: Claude Code / claude-opus-5-5 * Show a Codex web search's query and the results Codex reported (CF-5) (#344) A live codex-cli 0.163.0 capture (test/fixtures/codex-websearch-0.163.0.json) shows the webSearch item starting with an empty query, no action and no results, and completing with the query, a search action and text_result entries (title, url, domain, snippet). Modex titled the row "search " from the empty start, read neither action nor results, and stored the JSON string "" as its output. codexWebSearch (shared/evidence.ts) keeps the query, the action and results with an http(s) link, each text bounded, and counts what it drops. The Codex backend titles the row "search the web" until the query arrives, then "search <query>", and carries the search on the tool item. Expanded, the results show as links with snippets, marked data-provenance="codex-search" and labelled as unchecked. The renderer checks each link again before showing it, and nothing is fetched until a link is clicked. Older searches no longer show "". Red first: the three evidence tests and the Codex backend test failed on a stub, and the e2e test failed ("done", not "2 results"). Now evidence, codex-backend and conversation-events pass 69/69, the conversation-evidence spec passes 7/7, and the desktop unit suite 1,709 passed with 16 skipped. Part of #278 (CF-5), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Land main through a merge queue (#345) main requires branches to be up to date, so every landing sent each open PR back through CI. On 2026-10-19 that cost #309 three extra macOS runs, and on 2026-10-20 #336, #340 and #343 one or more each. The ruleset file gains a merge_queue rule (squash, all-green groups, up to 3 groups building and 5 PRs per merge, a 90-minute check timeout, since the macOS job alone may take 45). It drops the up-to-date requirement, which the queue replaces: a queued PR is tested on top of main and the PRs ahead of it. CI runs on merge_group, so each queued group reports the required unit + e2e (macOS) check; without it the queue drops every PR. The iPhone job and the coverage upload skip queued groups: neither is required, the PR already ran them, and main's push run repeats them. README, AGENTS.md and status.md say PRs land through the queue. The live ruleset (23989202) takes this file once this lands, so the queue starts only after main can report checks for it. Coven-Harness: Claude Code / claude-opus-5-5 * Say the phone no longer shows a withdrawn approval as declined (#343) human-requests.md still said the iPhone shows a withdrawn approval as declined. Since #335, mobileItem (companion.ts) sends a withdrawn, sending or uncertain approval to the phone as a notice that says so. The companion fallback test now covers the withdrawn case, which had no test (CF-6 #279, finding 7). Coven-Harness: Claude Code / claude-opus-5-5 * Note that the merge queue needs auto-merge, and list the keyboard Jump to latest CI failure (steward cycle 17) (#347) The first PR queued after #345 failed to enqueue: "Auto merge is not allowed for this repository". gh pr merge adds a PR to a merge queue by enabling auto-merge, so the repository now allows it, as OpenCoven/coven does, and README says why. e2e/keyboard-answers.spec.ts:88 (#342) failed in three CI runs of #345 in a row and passed on #342, on main and 25/25 locally. It goes under Known rough edges with what the failure snapshot shows and a link to the analysis on #342. Coven-Harness: Claude Code / claude-opus-5-5 * Prove a queue-landed branch merged when its tip merges cleanly into the landed tree (#350) Since #345, main lands through a merge queue, which squashes each PR onto main as it stands at the PR's turn. A branch that merged main into itself, then landed behind another PR, had no proof that worktree.sh remove would accept: - the squash tree also holds the PRs ahead of it, so it is not the tip's tree; - the branch's merge commits rule out the binary-diff proof. cf6-docs-followup (#343) hit this on 2026-10-20 and had to be pointed at its squash commit by hand. The new merge-tree proof merges the exact PR tip onto the squash commit's parent with Git's own merge. It accepts only a clean merge (exit 0) whose tree is exactly the landed tree. A configured merge.<name>.driver turns the check off, because a driver can drop a side's changes and still report a clean merge. New tests: - a queued branch with merge commits is proven and removed, and its archive ref holds the tip; - a wrong head, a wrong base, a different tree, a conflicted merge (even when the squash holds exactly the conflicted tree) and a configured driver that keeps main's side each stay not-proven-merged. Checked against #343's real branch and PR record in a throwaway clone. The old proof returns null. The new proof returns merge-tree with tree 6fc493b, the tree of 0a67354. Coven-Harness: Claude Code / claude-opus-5-5 * Hold Jump to latest when the composer grows or a Page Up is still moving (#352) * Hold Jump to latest when the composer grows or a Page Up is still moving e2e/keyboard-answers.spec.ts:88 (#342) failed on slow CI runners: after Enter, Jump to latest stayed. A trace in the app found two causes. - A scroll event is delivered before the browser reports a resize. If the composer grew right after the jump (a follow-up chip), onScroll measured a shorter view and stopped following. It now keeps following while the view has not moved above where auto-scroll put it, as follow() already did. - A Page Up still animating keeps applying its remaining distance after the page sets a new position: plain assignment, scrollTo instant and an overflow toggle all lose to it. For a second after a jump, a scroll with no wheel, key, pointer or touch input since the jump is that leftover motion, and the view pins back to the bottom. The reader's own scroll still wins at once. Red first, each test alone on main's ThreadView: the composer-growth test failed (the button stayed), the Page Up test failed (the view went back up 138 px), and the scroll-up guard passed. With the fix, keyboard-answers passes 24/24 (8 tests x 3), and app, conversation- continuity, typed-turns, conversation-rendering and layout 43/43. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Move the Jump to latest rough edge to the resolved list, with its cause The entry #347 added leaves Known rough edges, as written, under #352, with the two causes the trace found. Coven-Harness: Claude Code / claude-opus-5-5 * Say whether a check verified a turn's last change (CF-7 verification) (#351) * Say whether a check verified a turn's last change, in its task record (CF-7) verification() in shared/task-context.ts reads a turn's tools in transcript order: - A check is a known test, build, typecheck or lint command, read inside sh/bash/zsh -c with quotes respected. An exit-zero echo or the model saying "tests pass" is not one. - A check passes only as succeeded with exit code 0 or none reported. - A check goes stale when an edit that was not denied, or a command that might write, runs after it. - The turn reads verified, failed, unknown, stale or none. taskRecord carries it, and the note gets a Verification section that marks stale checks. Anything short of verified goes under Not settled; a failure a later fix superseded does not. Plan steps keep the CLI's statuses: neither CLI links a check to a step. Red first: five of six new tests failed on a stub, then edits and displayCommand on theirs. task-context passes 13/13; the desktop unit suite 1,723 passed, 16 skipped. Part of #280 (CF-7), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Show a turn's verification beside Save to Notes (CF-7) A finished turn's footer reads, for example, "Verified: pnpm test passed after the last change" or "Not verified: pnpm test ran before a later change". It also covers a check that failed, a check that did not say how it ended, and a turn whose changes no check followed. A check shows as the script its shell ran, with the exact command on hover. A turn that changed nothing and ran no check shows nothing. Red first: the new e2e test found no verification lines (expected 2, received 0). task-to-notes.spec.ts passes 3/3. docs/task-context.md gains a Verification section, and status.md an entry. Part of #280 (CF-7), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * List #352's Jump to latest fix under On main, unreleased (steward cycle 19) (#353) #352 changed what readers see: after a jump, the transcript no longer stops short of the bottom when the message box grows or a Page Up is still scrolling. It moved the CI rough edge to the resolved list but added no unreleased entry, so the next release review would not have listed it. The entry sits beside CF-8's keyboard entry and links the resolved list's account of the causes. Coven-Harness: Claude Code / claude-opus-5-5 * Mark the CF-7 verification plan done in #351 (steward cycle 20) (#356) #351 landed every task in docs/superpowers/plans/2026-10-20-cf7-verification.md, but the plan still read as not started. The five boxes are ticked from #351's own evidence: - the red and green unit tests; - the footer e2e (3/3); - task-context.md and status.md updated; - pnpm build and typecheck passed locally; - the full e2e suite passed in CI, on the PR and in the merge queue (run 39508701952). The local run stopped when the disk filled. A dated status line says that linking a check to a plan step stays open on #280. Coven-Harness: Claude Code / claude-opus-5-5
* Keep keyboard focus when an approval is answered, its turn folds, Stop ends it, or Jump to latest is used (CF-8) (#342) * Keep keyboard focus when an approval is answered and its turn folds The CF-8 keyboard walkthrough found that pressing Approve or Deny with the keyboard dropped focus onto the page body: the answer buttons unmount once pressed, and a finished turn then hides its folded work. A keyboard or VoiceOver user lost their place twice. Focus now moves to the card's answer line ("Sending decision…", then "Approved" or "Denied"). When the finished turn folds work that holds focus, it moves to the turn's "Worked for" toggle. Focus elsewhere, such as the composer, is left alone. Red first: both keyboard tests failed on main (answer line inactive). e2e/keyboard-answers.spec.ts passes 3/3; the full desktop e2e passes 366 with 6 opt-in skips. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Hand focus to the message box when a keyboard Stop ends the turn The second walkthrough probe found the same defect at Stop: the button goes away when the turn ends, and focus fell onto the page body. When Stop was pressed with focus on it, focus now moves to the message box, where the next message is typed. Red first: the new keyboard test failed on the previous commit (composer inactive); keyboard-answers.spec.ts passes 4/4 and the full desktop e2e passes 367 with 6 opt-in skips. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Hand focus to the message box after Jump to latest from the keyboard The third walkthrough probe found that Jump to latest, once activated, goes away at the bottom and left focus on the page body. When the button held focus, focus now moves to the message box there. Red first: the new test failed (message box inactive). The keyboard spec passes 5/5, app.spec with it 19/19, and conversation-continuity plus typed-turns, which also scroll, 8/8. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Restore main's status.md after the #339 merge, keeping only this PR's entry The merge kept both sides of a block #339 had moved, which duplicated the released entries. The page is now main's, plus this PR's one entry. Coven-Harness: Claude Code / claude-opus-5-5 * Show a Codex web search's query and the results Codex reported (CF-5) (#344) A live codex-cli 0.163.0 capture (test/fixtures/codex-websearch-0.163.0.json) shows the webSearch item starting with an empty query, no action and no results, and completing with the query, a search action and text_result entries (title, url, domain, snippet). Modex titled the row "search " from the empty start, read neither action nor results, and stored the JSON string "" as its output. codexWebSearch (shared/evidence.ts) keeps the query, the action and results with an http(s) link, each text bounded, and counts what it drops. The Codex backend titles the row "search the web" until the query arrives, then "search <query>", and carries the search on the tool item. Expanded, the results show as links with snippets, marked data-provenance="codex-search" and labelled as unchecked. The renderer checks each link again before showing it, and nothing is fetched until a link is clicked. Older searches no longer show "". Red first: the three evidence tests and the Codex backend test failed on a stub, and the e2e test failed ("done", not "2 results"). Now evidence, codex-backend and conversation-events pass 69/69, the conversation-evidence spec passes 7/7, and the desktop unit suite 1,709 passed with 16 skipped. Part of #278 (CF-5), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Land main through a merge queue (#345) main requires branches to be up to date, so every landing sent each open PR back through CI. On 2026-10-19 that cost #309 three extra macOS runs, and on 2026-10-20 #336, #340 and #343 one or more each. The ruleset file gains a merge_queue rule (squash, all-green groups, up to 3 groups building and 5 PRs per merge, a 90-minute check timeout, since the macOS job alone may take 45). It drops the up-to-date requirement, which the queue replaces: a queued PR is tested on top of main and the PRs ahead of it. CI runs on merge_group, so each queued group reports the required unit + e2e (macOS) check; without it the queue drops every PR. The iPhone job and the coverage upload skip queued groups: neither is required, the PR already ran them, and main's push run repeats them. README, AGENTS.md and status.md say PRs land through the queue. The live ruleset (23989202) takes this file once this lands, so the queue starts only after main can report checks for it. Coven-Harness: Claude Code / claude-opus-5-5 * Say the phone no longer shows a withdrawn approval as declined (#343) human-requests.md still said the iPhone shows a withdrawn approval as declined. Since #335, mobileItem (companion.ts) sends a withdrawn, sending or uncertain approval to the phone as a notice that says so. The companion fallback test now covers the withdrawn case, which had no test (CF-6 #279, finding 7). Coven-Harness: Claude Code / claude-opus-5-5 * Note that the merge queue needs auto-merge, and list the keyboard Jump to latest CI failure (steward cycle 17) (#347) The first PR queued after #345 failed to enqueue: "Auto merge is not allowed for this repository". gh pr merge adds a PR to a merge queue by enabling auto-merge, so the repository now allows it, as OpenCoven/coven does, and README says why. e2e/keyboard-answers.spec.ts:88 (#342) failed in three CI runs of #345 in a row and passed on #342, on main and 25/25 locally. It goes under Known rough edges with what the failure snapshot shows and a link to the analysis on #342. Coven-Harness: Claude Code / claude-opus-5-5 * Prove a queue-landed branch merged when its tip merges cleanly into the landed tree (#350) Since #345, main lands through a merge queue, which squashes each PR onto main as it stands at the PR's turn. A branch that merged main into itself, then landed behind another PR, had no proof that worktree.sh remove would accept: - the squash tree also holds the PRs ahead of it, so it is not the tip's tree; - the branch's merge commits rule out the binary-diff proof. cf6-docs-followup (#343) hit this on 2026-10-20 and had to be pointed at its squash commit by hand. The new merge-tree proof merges the exact PR tip onto the squash commit's parent with Git's own merge. It accepts only a clean merge (exit 0) whose tree is exactly the landed tree. A configured merge.<name>.driver turns the check off, because a driver can drop a side's changes and still report a clean merge. New tests: - a queued branch with merge commits is proven and removed, and its archive ref holds the tip; - a wrong head, a wrong base, a different tree, a conflicted merge (even when the squash holds exactly the conflicted tree) and a configured driver that keeps main's side each stay not-proven-merged. Checked against #343's real branch and PR record in a throwaway clone. The old proof returns null. The new proof returns merge-tree with tree 6fc493b, the tree of 0a67354. Coven-Harness: Claude Code / claude-opus-5-5 * Hold Jump to latest when the composer grows or a Page Up is still moving (#352) * Hold Jump to latest when the composer grows or a Page Up is still moving e2e/keyboard-answers.spec.ts:88 (#342) failed on slow CI runners: after Enter, Jump to latest stayed. A trace in the app found two causes. - A scroll event is delivered before the browser reports a resize. If the composer grew right after the jump (a follow-up chip), onScroll measured a shorter view and stopped following. It now keeps following while the view has not moved above where auto-scroll put it, as follow() already did. - A Page Up still animating keeps applying its remaining distance after the page sets a new position: plain assignment, scrollTo instant and an overflow toggle all lose to it. For a second after a jump, a scroll with no wheel, key, pointer or touch input since the jump is that leftover motion, and the view pins back to the bottom. The reader's own scroll still wins at once. Red first, each test alone on main's ThreadView: the composer-growth test failed (the button stayed), the Page Up test failed (the view went back up 138 px), and the scroll-up guard passed. With the fix, keyboard-answers passes 24/24 (8 tests x 3), and app, conversation- continuity, typed-turns, conversation-rendering and layout 43/43. Part of #281 (CF-8), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Move the Jump to latest rough edge to the resolved list, with its cause The entry #347 added leaves Known rough edges, as written, under #352, with the two causes the trace found. Coven-Harness: Claude Code / claude-opus-5-5 * Invalidate retained PR data after authoritative visibility loss * Say whether a check verified a turn's last change (CF-7 verification) (#351) * Say whether a check verified a turn's last change, in its task record (CF-7) verification() in shared/task-context.ts reads a turn's tools in transcript order: - A check is a known test, build, typecheck or lint command, read inside sh/bash/zsh -c with quotes respected. An exit-zero echo or the model saying "tests pass" is not one. - A check passes only as succeeded with exit code 0 or none reported. - A check goes stale when an edit that was not denied, or a command that might write, runs after it. - The turn reads verified, failed, unknown, stale or none. taskRecord carries it, and the note gets a Verification section that marks stale checks. Anything short of verified goes under Not settled; a failure a later fix superseded does not. Plan steps keep the CLI's statuses: neither CLI links a check to a step. Red first: five of six new tests failed on a stub, then edits and displayCommand on theirs. task-context passes 13/13; the desktop unit suite 1,723 passed, 16 skipped. Part of #280 (CF-7), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Show a turn's verification beside Save to Notes (CF-7) A finished turn's footer reads, for example, "Verified: pnpm test passed after the last change" or "Not verified: pnpm test ran before a later change". It also covers a check that failed, a check that did not say how it ended, and a turn whose changes no check followed. A check shows as the script its shell ran, with the exact command on hover. A turn that changed nothing and ran no check shows nothing. Red first: the new e2e test found no verification lines (expected 2, received 0). task-to-notes.spec.ts passes 3/3. docs/task-context.md gains a Verification section, and status.md an entry. Part of #280 (CF-7), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * List #352's Jump to latest fix under On main, unreleased (steward cycle 19) (#353) #352 changed what readers see: after a jump, the transcript no longer stops short of the bottom when the message box grows or a Page Up is still scrolling. It moved the CI rough edge to the resolved list but added no unreleased entry, so the next release review would not have listed it. The entry sits beside CF-8's keyboard entry and links the resolved list's account of the causes. Coven-Harness: Claude Code / claude-opus-5-5 * Mark the CF-7 verification plan done in #351 (steward cycle 20) (#356) #351 landed every task in docs/superpowers/plans/2026-10-20-cf7-verification.md, but the plan still read as not started. The five boxes are ticked from #351's own evidence: - the red and green unit tests; - the footer e2e (3/3); - task-context.md and status.md updated; - pnpm build and typecheck passed locally; - the full e2e suite passed in CI, on the PR and in the merge queue (run 39508701952). The local run stopped when the disk filled. A dated status line says that linking a check to a plan step stays open on #280. Coven-Harness: Claude Code / claude-opus-5-5 * Invalidate shared read resources without losing partial inbox results
Part of #281 (CF-8), tracker #273. Found while preparing the human keyboard and VoiceOver review.
The defect
A walkthrough probe drove the seeded review scenario with the keyboard alone and recorded
document.activeElementat each step. After Enter on Approve, focus was on<body>, because the answer buttons unmount once pressed. When the finished turn then folds its work (folded items arehidden, not unmounted), focus held there falls to the body as well. A keyboard or VoiceOver user lost their place twice.The fixes (renderer only)
ApprovalItem: when Approve, Always, Always allow in thread or Deny is pressed with focus inside the card, focus moves to the answer line (tabIndex=-1). It reads "Sending decision…", then "Approved" or "Denied".TurnContent: when a live turn finishes and folds work that holds focus, focus moves to its "Worked for …" toggle.Composer(d7ba645): Stop goes away when the turn ends. A second probe found that a keyboard Stop also left focus on<body>. When Stop was pressed with focus on it, focus now moves to the message box.25129c9): a third probe found that the button, once activated, goes away at the bottom and left focus on<body>. When it held focus, focus now moves to the message box.preventScroll. Focus elsewhere, such as the composer, is left alone, and there's a test for that.Evidence
e2e/keyboard-answers.spec.tsonmain(red)inactivefdbb6b5(red)inactiveafter a keyboard Stope2e/keyboard-answers.spec.tsond7ba645pnpm --filter @modex/desktop test:e2eond7ba645d7ba645(red)inactive25129c9:keyboard-answers+app.spec/conversation-continuity+typed-turns(the specs that scroll)pnpm typecheckpassed. CI runs the full suite on this headpnpm typecheckNot covered: QuestionCard's answer path. It keeps its own delivery status region, and the review checklist covers it by hand.
Coven-Harness: Claude Code / claude-opus-5-5