Skip to content

refactor(agent-status): publish structured sessions into the hook server store - #19683

Merged
brennanb2025 merged 11 commits into
mainfrom
brennanb2025/agent-status-store
Sep 10, 2026
Merged

brennanb2025 merged 11 commits into
mainfrom
brennanb2025/agent-status-store

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 11 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​875 $\color{#cf222e}{\Huge{\mathbf{−}}}$​188 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​687
Prod 35 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​509 $\color{#cf222e}{\Huge{\mathbf{−}}}$​120 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​389

ELI5

Orca kept three copies of "what is this agent doing" inside the main process. The hook server's copy is the one with authority and persistence, but structured (native chat) sessions never wrote to it, so worktree ps grew its own adapter in #19217. Now the structured host writes into the hook server like every other agent, and worktree ps just reads the store.

What Changed

  • The hook server gains ingestStructuredStatus / dropStructuredStatus. A structured session's projection lands as a normal status row under the pane key the renderer already derives, stamped with the journal clock and a structuredHost: 'held' | 'owned' marker.
  • The structured status feed takes a statusSink and calls it on every publish, on ownership revocation, and (new) on forget when the host closes the session. The runtime wires that sink to the hook server.
  • worktree ps reads structured rows from the hook snapshot. The separate structured adapter and the host's liveSessionStatusSummaries accessor are deleted. Rows carry structuredHostOwned so the shared freshness rule handles the aged-but-owned case; the hand-rolled bypass is gone.
  • Structured rows are never persisted to last-status.json, and one found on disk is dropped on hydrate.
  • The main process does not yet forward structured rows to the renderer over agentStatus:set / getSnapshot; the renderer's feed bridge still owns those rows until the next PR retires it. This keeps one writer per pane key.
  • docs/reference/agent-status-store.md records the single-store design and the two follow-up PRs. Linked from AGENTS.md.

Why

The execution host should own agent status in one store, and every reader should subscribe to it. An audit found the hook server already is that store for every PTY-based agent on local, WSL, and SSH hosts: hook HTTP, the relays, and main's own OSC parse all converge on it, and it alone holds pane authority and persistence. The structured feed was the one producer bypassing it. Routing it through the store removes a reader-side adapter and makes the CLI, mobile, and (after PR 2) the sidebar read the same row.

Wire compatibility: AgentStatusIpcPayload.structuredHost and RuntimeWorktreeAgentRow.structuredHostOwned are new optional fields (rule 1). worktree ps keeps its shape and vocabulary.

Linked Issue

Follow-up to #19217; design in docs/reference/agent-status-store.md.

Visual Proof

N/A. Main-process only; the desktop sidebar's rendering path is unchanged in this PR.

Testing

  • tsc for node, web, and CLI projects.

  • Focused suites: hook-server structured ingest and persistence, status feed sink, worktree ps source admission and structured rows, the closed-chat liveness chain, the runtime call-site spec, and a wiring test that pins the sink through the @ts-nocheck install path. Broader hook-server, runtime worktree, and structured-session suites re-run.

  • pnpm run check:code-quality:changed.

  • Automated tests added/updated

  • I manually tested these changes locally

Review

…ver store

Structured (native chat) sessions have no PTY and no hook script, so their
status never reached the hook server's store; #19217 gave `worktree ps` its
own adapter over the structured feed instead. The feed now writes every
projection into that store through a status sink the runtime wires, drops
the row when the host closes the session, and `worktree ps` reads the one
snapshot like every other agent.

Rows carry a `structuredHost` marker and the journal clock; they are never
persisted to last-status.json, and the main process does not forward them
to the renderer yet, whose feed bridge still owns them until it is retired.

Design and the two follow-ups: docs/reference/agent-status-store.md.
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review status: no proven in-scope defects found after independent review and readiness scans.

Validation: 33 targeted Vitest tests passed; tsc -p config/tsconfig.node.json --noEmit passed. Readiness review found no P0/P1/P2 issues. Reference comparison was completed privately.

Electron QA was attempted with ORCA_BACKGROUND_LAUNCH=1 and CDP, but the launched identity resolved to an unrelated QA19259 worktree, so the screenshot is incidental and does not provide PR-specific merge confidence.

@coderabbitai

coderabbitai Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 7fe2152a-ba80-4697-b40d-d8a4061a2923

📥 Commits

Reviewing files that changed from the base of the PR and between 3a37982 and e791513.

📒 Files selected for processing (1)
  • src/main/runtime/rpc/methods/orchestration/worker/agent-status-producer-census.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

Structured native-chat sessions now publish status summaries into the hook server’s shared store. The store maps session state, preserves journal timestamps, tracks host ownership, and excludes structured rows from persistence. Runtime wiring sends feed updates and removals to the store. Worktree projections consume hook snapshots instead of separate structured summaries. IPC and renderer paths filter structured-host rows to avoid duplicate updates. Tests cover ingestion, lifecycle events, persistence, freshness, projection, and sink failures.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to dc2ea

This change documents the existing headless status-store wiring in its producer census test. No actionable current-head merge risk remains.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.03% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 29 functions across 42 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: publishing structured sessions into the hook server store.
Description check ✅ Passed The description is mostly complete. It includes the ELI5, change summary, rationale, linked issue reference, visual proof rationale, and testing details. It omits later template sections such as AI Di…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: d635eca3-8a3a-4e3c-bfa0-781b874655b8

📥 Commits

Reviewing files that changed from the base of the PR and between 210ac1f and 9dc54a5.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (36)
  • .gitignore
  • AGENTS.md
  • docs/reference/agent-status-store.md
  • src/main/agent-hooks/server-ingest-structured-status.test.ts
  • src/main/agent-hooks/server/server-ingest-remote.ts
  • src/main/agent-hooks/server/server-ingest-structured.ts
  • src/main/agent-hooks/server/server-persistence-validation.ts
  • src/main/agent-hooks/server/server-persistence.ts
  • src/main/agent-hooks/server/server-state.ts
  • src/main/agent-hooks/server/server-status-application.ts
  • src/main/agent-hooks/server/server-status-identity.ts
  • src/main/agent-hooks/server/server-status-update.ts
  • src/main/ipc/agent-hooks.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-types.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-status-feed.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-status-feed.ts
  • src/main/runtime/orca-runtime-get-worktree-ps.ts
  • src/main/runtime/orca-runtime-preserved-branch-cleanup.ts
  • src/main/runtime/orca-runtime-state-fields.ts
  • src/main/runtime/orca-runtime-structured-status-sink-wiring.test.ts
  • src/main/runtime/orca-runtime-tests/worktree-ps-structured-host.spec.ts
  • src/main/runtime/runtime-worktree-agent-rows-structured.test.ts
  • src/main/runtime/runtime-worktree-agent-rows.ts
  • src/main/runtime/runtime-worktree-agent-source.ts
  • src/main/runtime/runtime-worktree-agent-sources.ts
  • src/main/runtime/runtime-worktree-pty-agent-sources.ts
  • src/main/runtime/runtime-worktree-structured-agent-rows-liveness.test.ts
  • src/main/runtime/runtime-worktree-structured-agent-rows.ts
  • src/main/runtime/structured-agent-session-runtime.ts
  • src/main/startup/main-process-runtime-service.ts
  • src/main/startup/main-window-agent-status.ts
  • src/shared/agent-hook-listener/listener-event.ts
  • src/shared/agent-status-ipc-payload.ts
  • src/shared/agent-status-observation.ts
  • src/shared/runtime-worktree-contracts.ts
💤 Files with no reviewable changes (1)
  • src/main/runtime/runtime-worktree-structured-agent-rows.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 6 remain after this review.


Orca shows "what is this agent doing" in four places: the desktop sidebar, the
`orca worktree ps` command, the mobile app, and the agent dashboard. Before
#19217 those readers did not even share their inputs. After #19217 they share

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the Markdownlint warning.

Line 18 starts with #19217. markdownlint-cli2 reports MD018 for this line. Wrap the issue reference in code formatting or rewrite the sentence so validation has no warning.

🧰 Tools
🪛 markdownlint-cli2 (0.23.2)

[warning] 18-18: No space after hash on atx style heading

(MD018, no-missing-space-atx)

Source: Linters/SAST tools

Comment thread docs/reference/agent-status-store.md Resolved
An unrelated local pnpm run added @pnpm/exe as a packageManagerDependency
with no package.json change, so CI's --frozen-lockfile install failed
before any job ran.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — the refactor is sound and well-characterized by the new tests. Two doc/consistency notes below.

Reviewed changes

  • Structured ingest into the hook server — ingestStructuredStatus / dropStructuredStatus project a structured session's summary into a normal status row under the renderer's pane key, stamped with the journal clock and a structuredHost: 'held' | 'owned' marker.
  • Status feed sink — StructuredAgentSessionStatusFeed gains a statusSink (publish/forget), invoked on every publish, on ownership revocation, and on the new close path, with subscribers kept safe when the sink throws.
  • worktree ps reads the store — the #19217 structured adapter and liveSessionStatusSummaries are deleted; the store snapshot becomes the single source, structuredHost skips the connected-process gate, and structuredHostOwned feeds the shared freshness rule.
  • Persistence hygiene — structured rows are skipped by the serializer and dropped on hydrate in both directions.
  • Renderer deferral — agentStatus:set / agentStatus:getSnapshot filter structured rows so the renderer's feed bridge stays the sole writer for now.
  • Docs + wire — docs/reference/agent-status-store.md and the optional structuredHost / structuredHostOwned fields under rule 1 of the wire doc.

ℹ️ Nitpicks

  • pnpm-lock.yaml adds a @pnpm/exe@12.0.0 packageManagerDependencies entry in the root importer, unrelated to this refactor. Fine to land, but if it was just local pnpm self-registration it could be split out.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

Comment thread docs/reference/agent-status-store.md Resolved

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ Delta is clean — the new commit only removes the stray @pnpm/exe lockfile entry flagged in the prior review. No further issues on the incremental change.

Pullfrog  | Fix it ➔ | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

The design record claimed PR 1 deletes RuntimeAgentRowStore, drops the
retained-versus-hook reconciliation, stamps terminalHandle on OSC rows, and
tags rows with a source field of 'structured-host'. None of that is true of
the shipped code: the retained store and its reconciliation are still in
place, and the row field is structuredHost: 'held' | 'owned'.

AGENTS.md points every future contributor here before they touch agent
status, so split the roadmap into the 1a that landed and the 1b that has not,
and name the fields the code actually writes.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — one minor doc nit inline.

Reviewed changes

  • Doc re-scoped to steps 1a/1b — docs/reference/agent-status-store.md now splits step 1 into PR 1a (this PR) and a not-yet-landed PR 1b (retained-store deletion), moving the RuntimeAgentRowStore / terminalHandle / reader-rewrite content under PR 1b and correcting the retained-versus-hook reconciliation claim that previously over-scoped the doc.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

what the chat shows. When the host revokes live ownership the row is re-set
without the flag; when the host closes or evicts the session the row is
dropped. Both already exist as feed events (`revokeLive` and the roster
filter in `liveSessionSummaries`); PR 1 turns them into store writes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two stale references after the 1a/1b split: PR 1 should be PR 1a (this section), and liveSessionSummaries is the feed method this PR deletes — the close/evict edge is now the new close/forget sink, not a roster filter.

Merge Sim added 6 commits September 8, 2026 23:45
A session dropped from the host's map without an explicit forget left its row
in the store forever: `structuredHostOwned` bypasses the staleness check, so a
failed re-attach (the Claude rewind path reaches one) stranded a permanently
working agent in `worktree ps` and on mobile with no UI able to clear it.
Deletion and forget are now one operation both callers route through.
`orcad` constructed its runtime with neither `getAgentStatusSnapshot` nor
`structuredAgentStatusSink`, so once `worktree ps` sourced rows only from that
snapshot the headless host published nowhere and listed nothing. The hook
server's store is a module singleton whose import tree never reaches Electron,
and its file paths come from `start()`, which orcad never calls.
`dropStructuredStatus` went through `clearPaneState`, which fans a pane clear
out to the renderer for a pane key the renderer's own feed bridge still writes
- so 'exactly one writer per pane key' held for writes and not for deletes.
`dropStatusEntry` routes through the status-drop tap instead, and skips the
resume-identity remnant: a structured session has no pane to resume into, and
every null-status publish would otherwise re-mint one.
Neither the `agentStatus:getSnapshot` filter nor the main-window listener's had
a single assertion, so deleting either — the first step of PR 2 — was green
everywhere. Also covers the perf skip and the drop's lack of a renderer clear.
The sink JSDoc claimed only tests construct a host without one; `orcad` did.
The doc argued a structured row needs no tab mirror 'because headless serve has
no renderer', reasoning about exactly the topology the wiring had not reached.
The deleted runtime adapter's warning that the pane key must be the DERIVED one
- never a bearer handle or minted worker key - was lost with it.
Wiring the hook store into the orcad runtime added a production site that
hands hook rows to a consumer, which the census ratchet pins deliberately.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No new issues in the fixes — one doc nit the latest doc pass still left behind, inline.

Reviewed changes

  • Paired session removal with the status-row forget — forgetStructuredAgentSession makes deleting a session from the host's map and dropping its store row one operation, wired into both the failed-attach cleanup and the eviction forget-session step.
  • Wired orcad into the store — orcad-entry.ts now imports the in-memory agentHookServer and passes getAgentStatusSnapshot / structuredAgentStatusSink, so a headless host lists structured sessions in worktree ps like the desktop.
  • Dropped the row without a renderer clear — dropStructuredStatus routes through dropStatusEntry (preserveResumeIdentity: false) instead of clearPaneState, resolving the earlier agentStatus:clear asymmetry.
  • Pinned both half-migration filters — new tests cover agentStatus:getSnapshot, the main-window agentStatus:set listener, and a source-scan wiring test across both entry points.
  • Corrected the doc — agent-status-store.md re-explains the persist skip, the fan-outs, and the orcad wiring obligation.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

what the chat shows. When the host revokes live ownership the row is re-set
without the flag; when the host closes or evicts the session the row is
dropped. Both already exist as feed events (`revokeLive` and the roster
filter in `liveSessionSummaries`); PR 1 turns them into store writes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 3a37982 doc pass still leaves two stale references on this line: PR 1 should be PR 1a (this doc ships with PR 1a; PR 1 spans the not-yet-landed 1b), and liveSessionSummaries is the accessor this PR deletes — the roster edge is now the sink's forget (forgetStructuredAgentSession), documented two lines below.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No new issues in the merge — one doc nit from the prior reviews is still outstanding.

Reviewed changes

  • Merged origin/main — a clean merge pulling 57 unrelated files from other PRs (orchestration, Claude/Codex dispatch, native-chat task lists); none overlap this PR's 46 files.
  • No behavioral change — the structured ingest, status-feed sink, worktree ps read path, and persistence filters are unchanged from the e791513 state already reviewed. pnpm tc:node and the focused structured-status suites pass.

The docs/reference/agent-status-store.md:108 nit flagged in the prior two reviews remains unaddressed: the sentence still reads PR 1 where the doc elsewhere uses PR 1a, and it still references liveSessionSummaries, the accessor this PR deletes (the close/evict edge is now forgetStructuredAgentSession, documented two lines below).

Pullfrog  | Fix it ➔ | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review status: ready to merge — CI green on dc2ea1f548

Reviewed across four independent lanes — correctness/architecture, a release-readiness checklist, a precedent/design pass, and Electron validation on a real running app. Six defects were found and fixed on the branch; the architecture was challenged and upheld.

Fixed during review

All CI was broken and nothing had actually run. pnpm-lock.yaml carried a stray @pnpm/exe entry with no package.json change, so pnpm install --frozen-lockfile failed and all 15 jobs died at ~30s — before a single real check. Worth knowing for anyone on this setup: a standalone @pnpm/exe pnpm build rewrites the lockfile on every invocation, including pnpm test, so it can reappear on its own. Check git status before committing and use an explicit pathspec.

A structured session could leave a permanent phantom working agent. onAttachFailed deleted a session from the host roster without dropping its status row. On a failed re-attach — reachable through the rewind path — a row last published as structuredHost: 'owned' stayed in the store forever, and because owned rows bypass the staleness window it never decayed: a stuck agent in worktree ps and on mobile with no way to clear it.

This was a regression in kind, which is the interesting part. Before this PR the roster was derived — the reader intersected published rows with the live sessions map, so any deletion dropped the row for free and drift was impossible. The refactor replaced that with a manual obligation honored at one of three deletion sites. The fix restores the invariant instead of patching the site: deletion and forget are now one operation (forgetStructuredAgentSession) that every path routes through.

worktree ps returned no agent rows at all on an orcad headless host. Structured rows now come only from the hook snapshot, and orcad-entry.ts passed neither getAgentStatusSnapshot nor structuredAgentStatusSink — so it published nowhere and read an empty snapshot, where previously it read a module registry independent of constructor deps. orcad serves all RPC methods, so this was a real loss on that topology. Now wired, with a test that fails if either dep is removed from either entry point.

agentStatus:clear was not filtered, so main did write into structured pane keys — the stated one-writer-per-pane-key invariant held for writes but not deletes. Structured drops now use dropStatusEntry. Note this needed a new preserveResumeIdentity option: the default path re-mints a providerSessionOnly remnant whenever a row has a provider session, which a structured summary always does, so the row would not have left the snapshot at all.

Neither half-migration filter had a single test — deleting either was green everywhere, even though removing one is the first step of the follow-up PR. Both are now pinned.

A full status-file walk and JSON.stringify ran per 250ms for the whole duration of every streaming native chat, producing byte-identical output every time. Now skipped for structured rows.

Also corrected five statements this PR made false, including the design record claiming the retained row store was deleted and that reconciliation was removed — neither had happened. AGENTS.md points future contributors at that document, so drift there is costlier than a wrong PR body.

A producer-census ratchet caught the orcad wiring. Giving orcad the store added a production site that hands hook rows to a consumer, which agent-status-producer-census.test.ts pins deliberately. Declared it rather than working around the ratchet — that test exists precisely so a new producer cannot appear silently, which is the rule AGENTS.md states for this store.

Merged main (the branch was 9 behind). One static-analysis failure was a merge-ref artifact in a file this PR never touches — reproduced clean locally on both our head and the merged tree, so it was a transiently-red main since fixed, not a defect here.

Deliberate, now documented

Structured sessions joining the store means a working native chat now holds the power-save blocker and appears in agent-session stats. That is intended — a working native chat is real work and should behave like any other agent — but it was undocumented, and now is.

Electron validation — 5/5 PASS

Real structured Codex chat plus a real PTY Claude TUI in an isolated dev instance (background launch, hidden renderer, CDP screenshots only, no window activation). Instance ownership was proven before any capture, so these are screenshots of the build under test.

# Question Verdict
1 Structured session shows a sidebar agent row PASS
2 Settles to done, no stuck "working" PASS
3 PTY agent row unaffected PASS
4 Exactly one row per session PASS
5 worktree ps lists it live, drops it after close PASS

The decisive check is #4: probed live against both APIs while a structured session was open, agentStatus.getSnapshot() returned 0 structured rows while the renderer store held exactly 1 — the deliberate filter working as designed.

Baseline — idle workspace, no agent rows:
baseline

Q1 — structured Codex session mid-turn, one row, amber working indicator:
q1

Q2 — same session settled to done:
q2

Q3 — PTY Claude row live and updating through its turn:
q3

Q4 — one structured + one PTY agent, exactly two rows, no duplicate:
q4

Q5 — worktree ps --json with the structured row live (structuredHostOwned: true), then after closing the chat:
q5-live
q5-closed

Validation performed

  • Typecheck clean on node, cli and web at the merged head — and the first real typecheck this branch had at all, since CI never got past install.
  • orca-runtime.test.ts aggregator plus every new and touched suite, on the merged tree: 1303 passed, 1 skipped, 0 failed.
  • check:code-quality:changed: 0 findings across 41 changed files, all three gates. Full CI: 23 passed, 0 failed.
  • Ablations, not assertions. Every new test was verified by reverting its production change and confirming the test fails — including multi-file arms so one lever cannot mask another. No pins. The phantom-row test was re-verified independently: with the fix reverted, the session leaves the roster while its row stays in the snapshot.

Architecture

Upheld, with one honest qualifier. The PR removes the failure mechanism rather than guarding it: a session-id-keyed broadcast cache that never reached the store is why worktree ps grew a private adapter and a hand-rolled freshness bypass, and both are now gone. No supersede warranted.

The qualifier: for structured rows this relocates a derivation rather than collapsing one — main and the renderer still derive the row independently from the same summary. The real win is that the CLI and mobile now read the same store, with the single writer in place for the follow-up. That is sound as staging, not as a steady state, so the follow-up should land close behind.

Known gaps, not blockers

  • Validation was a dev build on macOS, local execution host, folder workspace, Codex-only structured lane. No packaged build, no git-worktree path, no interrupt/failure/restart paths.
  • worktree ps human-readable output never prints agent rows (pre-existing formatWorktreePs behavior, not a regression) — the JSON form is the real surface.
  • Mobile still ignores structuredHostOwned, so an owned row decays to idle there. Pre-existing; an incomplete improvement rather than a regression.
  • Two follow-up items for the next PR: main and the renderer key structured panes differently (the renderer's tab id takes a :history-N suffix on collision), which would yield two rows once the filter comes off; and a refused ingest never retries, because the feed's dedupe cache has already recorded the summary.

…atus-store

# Conflicts:
#	src/main/native-chat/agent-session-wire/structured-agent-session-host.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-status-feed.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-status-feed.ts
#	src/main/runtime/orca-runtime-tests/worktree-ps-structured-host.spec.ts

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No new issues in this merge — the reconciliation against origin/main is clean.

Reviewed changes

  • Merged origin/main — the branch now sits on a newer main whose createStructuredAgentSessionHostStatusFeed takes a deps thunk (threading readBackgroundTasks / fence / hasProviderChild); the PR's statusSink is re-wired inside that thunk as statusSink: () => args.deps().statusSink, preserving the same publish/forget behavior.
  • Updated the status-feed test helper — feedFor threads statusSink alongside main's new readBackgroundTasks param, keeping the sink-dedup and sink-throws assertions; the status-feed and forget-status suites pass (25 tests).

The docs/reference/agent-status-store.md:108 nit from the prior reviews is unchanged (stale PR 1 and the deleted liveSessionSummaries reference); it remains the sole item before a clean approval.

Pullfrog  | Fix it ➔ | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@brennanb2025
brennanb2025 merged commit ebb1acf into main Sep 10, 2026
34 checks passed
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