Skip to content

refactor(native-chat): the rest of structured chat reports failures through the host's logger - #24504

Open
brennanb2025 wants to merge 5 commits into
mainfrom
brennanb2025/structured-chat-logger-followups
Open

brennanb2025 wants to merge 5 commits into
mainfrom
brennanb2025/structured-chat-logger-followups

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 66 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​775 $\color{#cf222e}{\Huge{\mathbf{−}}}$​127 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​648
Prod 62 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​422 $\color{#cf222e}{\Huge{\mathbf{−}}}$​161 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​261

What this fixes

Some failures in structured native chat (the Codex/Claude chat UI) still leave no record anyone can find. When a background step fails, for example saving Claude's resume point when the agent exits, rolling back a chat-journal transaction, importing or retiring a legacy journal, repairing queued messages, or retiring a worker's chat tab, the error goes only to console.warn/console.error. A packaged Electron main process has no console, so in a shipped app those errors vanish. That is what kept the Sep 10 "native Codex chat cannot resume after update" P0 invisible.

#24312 fixed this for the chat host and its collaborators by giving them a required logger that writes to the local diagnostics trace (<userData>/logs/main.trace.ndjson, which the share-diagnostics bundle collects). Its own description lists the rest as a Temporary follow-up: "give the journal database the host's logger, and pass it to the orchestration and session-environment callers", with the WSL transcript gate listed alongside. This PR is that follow-up. It also supersedes #24079, an earlier attempt at the same fix with a different mechanism; #24079 was closed in favour of #24312's design.

Scope: structured native chat only (behind experimentalStructuredNativeChat, off by default), in the main process and the headless orcad host, plus the WSL transcript gate #24312 listed. Terminal agents and the renderer are not touched.

What is different for the user: nothing visible in the chat. These failures now also land in the diagnostics trace, with the chat's session id, instead of disappearing.

What changes

  • The chat journal database takes the host's logger, as a required dependency. JournalHostDatabase.open/openWith, openJournalDatabase and runJournalTransaction take it. Rollback, legacy import verify/retire, queued-message repair, row bookkeeping and restart reconciliation's "unknown" outcome report through it, with the chat's session id, instead of to the console.
  • Claude and Codex structured adapters take the logger as a required dependency. Each Claude session carries its session id and logger, so the exit cursor, the turn-end resume point, attachment reads, dispatch writes, the history window, the option-restore timeout, a child process that survives close, and a failed slash-command scan report with the chat's session id. The child CLI launcher warning (session environment) reports through it too. These adapter sites go a little beyond refactor(native-chat): structured chat failures always reach the diagnostics log #24312's named list; they are the same failure class, and the session-environment item needs the logger in both adapters anyway.
  • The runtime holds one logger and passes it to the host install instead of making a new one per install. The callers outside the host get it from there: uncommitted-create refusal, worker tab retirement (close, teardown, discard, stopping a worker), coordinator mail redrive, a failed host install before a structured worker's stop or release (logged by dispatch id, never by the worker's handle), and a forced workspace removal that could not close its chats.
  • One reporting-only optional callback is gone. onStopChildError? (added in fix(native-chat): a Codex Stop that Codex refuses or never answers ends the Codex process #24334) went the way refactor(native-chat): structured chat failures always reach the diagnostics log #24312 removed the others: cancel reports stop-child through the logger.
  • The restart-offer failure logs name the chats. "Completing a restart offer", "recording a restart failure" and "rolling back a restart offer" already carried the operation id. Each now also carries sessionIds: the completed, the failed, or every settled session respectively. They are still one record per failure, and still have no error object and no prompt, since refactor(native-chat): structured chat failures always reach the diagnostics log #24312's privacy rule for recovery payloads still holds.
  • The WSL transcript gate's stall timeout is now a trace entry (wslTranscriptFs.timeout, with the task's priority, timeout and key). The gate is shared with the session-history scanners, which are not chat, so it writes through the existing tracer directly rather than the chat logger.
  • A ratchet test fails if console.warn/console.error (any spelling) or an optional on*Error? / on*Failed? / on*Failure? callback comes back in structured-chat production code. It covers native-chat/agent-session-{wire,journal} and native-chat/structured-agent-session-*, claude/claude-structured-*, codex/codex-structured-*, the runtime's structured-* and orchestration-structured files, their RPC methods, and four files whose names don't say so: the Claude stream connection and slash-command catalog (used only by structured chats), and worker stop and worker release (which install the structured host first). It exempts the logger's own sink and the four callbacks that carry behavior rather than reporting: onAcquisitionFailed, onBackgroundTaskJournalFailure, the event sink's onFailed and onEventSinkFailure.
  • Supporting change: the Claude provider-handle publication mints its generation, link id and timestamp in one place, in the same order and with the same values, to stay under the file-length limit.

Why this design

A failure's destination should not be optional. With an optional callback, forgetting to wire it is silent, and the console fallback does not exist in a shipped app. #24312 established the required-logger mechanism for the host; this PR finishes moving the remaining structured-chat code onto it, rather than adding a second mechanism. The ratchet makes the class hard to reintroduce: a new console-only failure, or a new optional error callback, fails a test rather than shipping silently.

Where this differs from the common pattern, beyond what #24312 already records:

  • Intended: repeat suppression now lasts for the runtime's lifetime, not one host install. The runtime owns the one logger, as the common pattern creates one logger per process at its root. Before, each install built a fresh logger and threw it away; the only in-process reinstall is the retry after a failed install, and a new failure always has a new suppression key, so no first failure is hidden.
  • Intended: the WSL gate's timeout keeps its console line next to the trace entry, and has no 5-minute repeat suppression. The gate also runs inside the session-history scanner's worker thread and forked process, which install no trace sink, so the console line is the only record there. Repeats are already bounded by the gate's per-route quarantine (at most two concurrent tasks, each needing 30-60 s to time out), and it fires exactly as often as the old console line did.

Testing

  • CI on ef3f0358b28 is green: typecheck, static analysis, all five unit-test shards, cross-version wire compatibility, and mac and Windows packaging.

  • Locally: the node typecheck through the machine-wide gate after each fix, and explicit vitest runs over every touched test, its importers, orca-runtime.test.ts and the tests/e2e unit files that build these dependencies (latest broad run: 137 files, 2551 passed, 2 skipped). The real-CLI Claude tests were excluded; they write into the real ~/.claude.

  • The ratchet fails against main's journal-row-writer.ts and turns-cancel.ts, and against a console.warn planted in each of the 19 files the widened scope added. New tests assert the session id or dispatch id on the import-retire, option-restore, stream-close, slash-command-scan, worker-stop, forced-removal and restart-offer entries; the import-retire and worker-stop assertions were confirmed to fail with the field removed.

  • Live QA on Windows (a separate machine, isolated profiles, dev builds of this PR and of origin/main 9e34bd0): a seeded Claude chat with a leftover old-format journal file that cannot be deleted (a deny-delete permission on its folder). On restart, this PR wrote one failed agentSession.journal-import-retire entry to main.trace.ndjson with sessionId, the folder and EPERM; origin/main wrote nothing to the trace, only a console line. The restored chat looks the same on both builds:

    This PR (ef3f0358b28) origin/main
    Restored Claude chat on this PR Restored Claude chat on main
  • Not verified live: failures that need a running, logged-in agent (exit cursor, resume point, dispatch write, Stop). Unit tests cover them. A remote orcad host's trace was checked by unit tests only.

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

…hrough the host's logger

The structured chat host's required logger (#24312) did not reach the chat journal, the Claude
and Codex adapters, or the runtime and orchestration callers outside the host, so their failures
still went to console.warn/console.error, which a packaged desktop build never shows. These now
report through the same logger:

- The journal database takes the logger at open and every chat's journal reports through it:
  a failed rollback, an import that reads back different, a retired import file left behind,
  a skipped queued-message repair, skipped row bookkeeping, and an unconfirmed submission.
- The Claude and Codex adapters take it as a required dependency: exit cursor and turn-end
  resume point writes, unreadable attachments, failed message writes, an unprovable history
  window, an option restore that was never answered, and a child CLI launcher that did not
  resolve.
- The runtime holds the logger it hands the host, so a create refused before the host exists,
  chat-tab retirement, mail redrive and worker discard report to it too. A failed Stop child end
  reports from the turn context instead of through an optional callback.
- Restart-offer bookkeeping failures name the affected session ids as well as the operation id,
  still with no error object, since those errors can quote the recovery payload.

A ratchet test fails on console.warn/console.error or an optional on*Error/on*Failed/on*Failure
callback in structured chat production code; the behavioral optional hooks are listed by file.
…ed-chat-logger-followups

# Conflicts:
#	src/main/runtime/structured-agent-session-held-signal.test.ts
…through the logger, and widen the ratchet to match

- Claude: a descendant that survives a close and a failed at-rest `/` command scan now go to the
  chat's logger with its session id. The stream-json connection and the at-rest catalog take the
  logger as a required dependency; only structured Claude code opens or builds either.
- Runtime: a failed structured host install before a worker stop or release, and a forced
  worktree removal that leaves structured sessions unclosed, report through the runtime's logger.
  The removal keeps its console line when no runtime is passed. The runtime wraps an injected
  logger so a throwing one cannot fail the step it reports.
- The structured mail redrive's catch moves into structured-session-mail-target.ts, so the
  ratchet covers it without scanning the PTY record file's own mailbox warnings.
- The WSL transcript gate's deadline warning also writes a failed span to the trace file through
  the existing tracer; the console line stays because scanner workers install no trace sink.
- Ratchet scope: drop the trailing dash that skipped rpc/methods/structured-agent-session.ts,
  cover the runtime's structured-* files, the structured worker stop/release files and the two
  Claude files, and fail if a listed file stops being scanned.
- The held-signal test is back to main's version (#24494 fixed it the same way).
- The option-restore test asserts the logger entry instead of a console spy that no longer fired.
…belonged to

The journal-import-retire entry carried only the legacy directory; its one caller holds the
chat's session id, so the entry now carries it like the other per-chat journal sites.
…he dispatch, not the worker handle

A structured worker's handle is a bearer credential, and the entry now reaches the trace file and
the diagnostic bundle. Log the dispatch id instead, as the release path already does.
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review status: ready for review (head ef3f035)

The problem. In structured native chat, some background failures were reported only with console.warn/console.error. A packaged app's main process has no console, so in a shipped build those errors vanished. Examples: Claude's resume point not saving when the agent exits, a chat-journal transaction rolling back, an old per-chat journal that can't be imported or deleted, queued-message repair, and retiring a worker's chat tab. #24312 gave the chat host a required logger that writes to the diagnostics trace and listed these remaining sites as a Temporary follow-up. This PR is that follow-up.

What changes for you. Nothing in the chat UI. These failures now also go to <userData>/logs/main.trace.ndjson (which the share-diagnostics bundle collects) as failed agentSession.<scope> entries carrying the chat's session id. Before, they appeared only in a console nobody can read.

Fixed during review (each with tests):

  • The test that keeps console-only failures out of structured-chat code missed some of that code: the agentSession RPC file, the coordinator mail redrive this PR had converted, and several structured worker files. Its scope now covers them, plus four structured-only files whose names don't say so. A planted console.warn in each of the 19 newly covered files fails the test.
  • More structured-chat failures were still console-only, and they now go through the logger:
    • a Claude child process that survives close;
    • a failed Claude slash-command scan;
    • a failed host install before a structured worker's stop or release;
    • a forced workspace removal that could not close its chats;
    • the WSL transcript gate's stall timeout, which refactor(native-chat): structured chat failures always reach the diagnostics log #24312 also listed. The gate is shared with the session-history scanners, so it writes through the existing tracer and keeps its console line.
  • A failed delete of an imported old journal now names the chat (sessionId).
  • A new log written by an earlier review fix recorded a structured worker's handle, which works like a password for that worker, in the trace. It now logs the dispatch id instead.
  • The runtime now wraps any logger it is given so it can't throw, which keeps reporting from ever blocking the step being reported.
  • Merged current main. A test both sides had fixed now matches main exactly. One options test was still checking a console call that no longer happens; it now checks the logger.
  • PR body corrected: the removed onStopChildError? came from fix(native-chat): a Codex Stop that Codex refuses or never answers ends the Codex process #24334. It now notes that repeat suppression lasts for the runtime's lifetime (Intended) and explains why the WSL gate keeps its console line.

Deferred (P3, not fixing here):

  • The held-chats registry finds its logger by checking the host's shape, and calls it as possibly missing. Before any host is installed, a warning there is dropped instead of reaching the console. Better: pass the logger in explicitly.
  • Session ids are passed separately in a few places where a logger bound to the session would carry them (reconcile input, Claude resume point and exit lifecycle).
  • Some new log sites have no test of their own: transaction rollback, submission reconcile, held-chats, history window, worker release.
  • An unused logger parameter on a journal test helper.
  • A few entries now write file paths into the trace (transcript path, old journal folder, WSL task key, worktree id). The trace already carries paths in errors and stacks, and refactor(native-chat): structured chat failures always reach the diagnostics log #24312's redactor keeps them by design.

Scope note. The Claude/Codex adapter sites go slightly beyond the list #24312 named. They are the same failure class, and its session-environment item already needs the logger in both adapters. I kept them; the PR can't be split usefully because the ratchet test must land with every conversion.

Verified:

  • Two review rounds: four independent area and architecture reviews of the whole PR, then a fresh review of the fixes. A readiness checklist found no P0, P1 or P2.
  • Behavior is unchanged at every converted site: same returns, catches, awaits and ordering.
  • CI is green on ef3f0358b28.
  • Node typecheck after every fix, plus explicit vitest runs (latest broad run: 137 files, 2551 passed).
  • Live QA on the Windows test machine. The M4Air was unreachable; Codex ran the checks because Grok was not signed in there. Dev builds of this PR and of origin/main each ran with an isolated profile and a seeded Claude chat whose old journal file could not be deleted. On restart this PR wrote one failed agentSession.journal-import-retire entry with sessionId, the folder and EPERM. Main wrote only a console line. The restored chat looked the same on both builds (screenshots in the PR body).

Not verified:

  • Failures that need a running, logged-in agent (exit cursor, resume point, dispatch write, Stop) were not forced live. Unit tests cover them.
  • A remote orcad host's trace output was checked only by unit tests.
  • The real-CLI Claude tests were not run, because they write into the real ~/.claude.

@brennanb2025
brennanb2025 marked this pull request as ready for review October 2, 2026 04:33
@coderabbitai

coderabbitai Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 9 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 3f820020-801a-43f2-87e5-ab1b04b661a2

📥 Commits

Reviewing files that changed from the base of the PR and between 9e34bd0 and ef3f035.

📒 Files selected for processing (128)
  • src/main/claude/claude-adapter-capture-replay.test.ts
  • src/main/claude/claude-agent-sdk-contract-pins.test.ts
  • src/main/claude/claude-at-rest-commands.ts
  • src/main/claude/claude-child-work-producer-harness.test-fixture.ts
  • src/main/claude/claude-command-lifecycle.test.ts
  • src/main/claude/claude-fold-steer-receipt.test.ts
  • src/main/claude/claude-history-window-source-budget.test.ts
  • src/main/claude/claude-stop-ack-race.test.ts
  • src/main/claude/claude-stream-json-connection-close.test.ts
  • src/main/claude/claude-stream-json-connection.test.ts
  • src/main/claude/claude-stream-json-connection.ts
  • src/main/claude/claude-structured-auth-parity.test.ts
  • src/main/claude/claude-structured-dispatch-attachment-rejection.test.ts
  • src/main/claude/claude-structured-dispatch-content.ts
  • src/main/claude/claude-structured-dispatch-test-support.ts
  • src/main/claude/claude-structured-dispatch.test.ts
  • src/main/claude/claude-structured-dispatch.ts
  • src/main/claude/claude-structured-effort-default-at-rest.test.ts
  • src/main/claude/claude-structured-history-window.test.ts
  • src/main/claude/claude-structured-history-window.ts
  • src/main/claude/claude-structured-launch-resolution.test.ts
  • src/main/claude/claude-structured-launch-resolution.ts
  • src/main/claude/claude-structured-options.test.ts
  • src/main/claude/claude-structured-options.ts
  • src/main/claude/claude-structured-real-cli-fold.test.ts
  • src/main/claude/claude-structured-real-cli.test.ts
  • src/main/claude/claude-structured-resume-point.test.ts
  • src/main/claude/claude-structured-resume-point.ts
  • src/main/claude/claude-structured-session-acquisition-processless.test.ts
  • src/main/claude/claude-structured-session-acquisition.ts
  • src/main/claude/claude-structured-session-adapter.ts
  • src/main/claude/claude-structured-session-close.test.ts
  • src/main/claude/claude-structured-session-exit-lifecycle.ts
  • src/main/claude/claude-structured-session-publication.ts
  • src/main/claude/claude-structured-session-reading-control.test.ts
  • src/main/claude/claude-structured-session-recovery.test.ts
  • src/main/claude/claude-structured-session-state.ts
  • src/main/claude/claude-structured-session-test-support.ts
  • src/main/claude/claude-structured-turn-resume-point.test.ts
  • src/main/claude/claude-supervised-stop-real-cli.test.ts
  • src/main/codex/codex-collab-call-frames-fixture.ts
  • src/main/codex/codex-default-mode-subagents.test.ts
  • src/main/codex/codex-structured-acquisition-exit-proof.test.ts
  • src/main/codex/codex-structured-child-environment.test.ts
  • src/main/codex/codex-structured-child-environment.ts
  • src/main/codex/codex-structured-child-work-producer.test.ts
  • src/main/codex/codex-structured-dispatch-test-support.ts
  • src/main/codex/codex-structured-session-acquire.ts
  • src/main/codex/codex-structured-session-adapter-fixture.ts
  • src/main/codex/codex-structured-session-adapter-lifecycle.test.ts
  • src/main/codex/codex-structured-session-adapter.test.ts
  • src/main/codex/codex-structured-session-background-tasks.test.ts
  • src/main/codex/codex-structured-session-cancel.test.ts
  • src/main/codex/codex-structured-session-close.test.ts
  • src/main/codex/codex-structured-session-shutdown.test.ts
  • src/main/codex/codex-structured-session-state.ts
  • src/main/native-chat/agent-session-journal/journal-database-records-migration.test.ts
  • src/main/native-chat/agent-session-journal/journal-database.test.ts
  • src/main/native-chat/agent-session-journal/journal-database.ts
  • src/main/native-chat/agent-session-journal/journal-host-database-test-support.ts
  • src/main/native-chat/agent-session-journal/journal-host-database.ts
  • src/main/native-chat/agent-session-journal/journal-open-failure.test.ts
  • src/main/native-chat/agent-session-journal/journal-per-session-import.test.ts
  • src/main/native-chat/agent-session-journal/journal-per-session-import.ts
  • src/main/native-chat/agent-session-journal/journal-per-session-source.ts
  • src/main/native-chat/agent-session-journal/journal-queued-messages.ts
  • src/main/native-chat/agent-session-journal/journal-restart-reconciliation.test.ts
  • src/main/native-chat/agent-session-journal/journal-restart-reconciliation.ts
  • src/main/native-chat/agent-session-journal/journal-row-writer.ts
  • src/main/native-chat/agent-session-journal/journal-store.ts
  • src/main/native-chat/agent-session-journal/queued-message-bookkeeping-failure.test.ts
  • src/main/native-chat/agent-session-journal/queued-message-store.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-at-rest-commands.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-attach.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-chat-stop.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-compact-stop.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-echo-working.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-queued-stop.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-ends-session.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-turn-end.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-unproven-stop-send.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-owed-work-release.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-provider-started.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-registry.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-failure-ledger.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-failure-ledger.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-turns-cancel.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-view-start-after-failed-start.test.ts
  • src/main/native-chat/agent-session-wire/structured-chat-logger-ratchet.test.ts
  • src/main/native-chat/wsl-transcript-fs-gate.test.ts
  • src/main/native-chat/wsl-transcript-fs-gate.ts
  • src/main/native-chat/wsl-transcript-fs-timeout-report.ts
  • src/main/runtime/claude-structured-fake-connection-test-fixture.ts
  • src/main/runtime/orca-runtime-get-pty-record-for-pane-key.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/orchestration/structured-mailbox-pointer-host.ts
  • src/main/runtime/orchestration/structured-session-mail-target.test.ts
  • src/main/runtime/orchestration/structured-session-mail-target.ts
  • src/main/runtime/rpc/methods/orchestration-structured-worker-lifecycle.test.ts
  • src/main/runtime/rpc/methods/orchestration-structured-worker-lifecycle.ts
  • src/main/runtime/rpc/methods/orchestration-structured-worker-session.test.ts
  • src/main/runtime/rpc/methods/orchestration-structured-worker-session.ts
  • src/main/runtime/rpc/methods/orchestration/worker/worker-release-completion.ts
  • src/main/runtime/rpc/methods/orchestration/worker/worker-stop.ts
  • src/main/runtime/rpc/methods/structured-agent-session-create.ts
  • src/main/runtime/rpc/methods/structured-agent-session-precommit-refusal.test.ts
  • src/main/runtime/rpc/methods/structured-agent-session-precommit-refusal.ts
  • src/main/runtime/rpc/methods/structured-agent-session.ts
  • src/main/runtime/rpc/methods/structured-worker-stop-receipt.test.ts
  • src/main/runtime/rpc/methods/structured-worker-tab-retirement.test.ts
  • src/main/runtime/structured-agent-session-close.ts
  • src/main/runtime/structured-agent-session-journal-open.ts
  • src/main/runtime/structured-agent-session-runtime.test.ts
  • src/main/runtime/structured-agent-session-runtime.ts
  • src/main/runtime/structured-agent-session-tab-retirement.ts
  • src/main/runtime/structured-claude-pending-rewind.test.ts
  • src/main/runtime/structured-claude-runtime-adapter.ts
  • src/main/runtime/structured-claude-scripted-runtime-test-support.ts
  • src/main/runtime/structured-session-child-identity-env.test.ts
  • src/main/runtime/structured-session-child-identity-env.ts
  • src/main/runtime/structured-session-login-shell-test-harness.ts
  • src/main/runtime/structured-session-mail-redrive-wiring.test.ts
  • src/main/runtime/structured-session-worktree-teardown.test.ts
  • src/main/runtime/structured-session-worktree-teardown.ts
  • src/main/runtime/structured-worker-identity.test.ts
  • src/main/runtime/worktree-teardown.ts
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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.

@greptile-apps

greptile-apps Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[Medium risk] Refactors error logging across the Claude chat adapter.

The PR appears safe to merge; the remaining issue is a non-blocking gap in the new regression test.

Findings

  1. P2 Structured reporting paths escape the ratchet ▶

Summary

The PR routes additional structured-chat journal, adapter, worker and orchestration failures through the host logger, adds a WSL timeout trace entry, and introduces a regression ratchet. The ratchet leaves some changed structured-chat paths outside its scan.

Reviews (1) · Last reviewed commit: "fix(orchestration): a failed host instal..."

Comment on lines +30 to +37
const SCOPE_FILES = new Set([
// Opened and built only by structured Claude chats.
'main/claude/claude-stream-json-connection.ts',
'main/claude/claude-at-rest-commands.ts',
// Install the structured host before a structured worker's stop or release.
'main/runtime/rpc/methods/orchestration/worker/worker-stop.ts',
'main/runtime/rpc/methods/orchestration/worker/worker-release-completion.ts'
])

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Structured reporting paths escape the ratchet The scan excludes worktree-teardown.ts, where this PR adds structured-chat logging, and the orca-runtime-* files that wire the logger and mail redrive. A future console-only failure in those paths would pass this test and could go unrecorded in a packaged app. Include those paths, with narrow allowances for unrelated console warnings.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@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 scope gap in the new ratchet guard, noted below.

Reviewed changes

  • Required logger replaces the last console failures in structured chat. The runtime now mints one StructuredAgentSessionLogger and threads it through the host install, the Claude/Codex adapters, the journal database, launch resolution, and the child-identity env, so rollback, import verify/retire, queued-message repair, row bookkeeping, restart reconciliation, exit cursor, resume point, attachment/dispatch writes, history window, option-restore timeout, close-descendant, at-rest scans, and the child CLI launcher report with the chat's sessionId instead of vanishing into a console a packaged app does not have.
  • One optional reporting callback removed. onStopChildError? is gone; performCancel reports stop-child through ctx.logger directly.
  • Restart-offer failures now name the chats. The three ledger warn sites add sessionIds (completed / failed / all-settled) while still omitting any error object and prompt.
  • Worker host-install failures log the dispatch, not the handle. worker-stop/worker-release now report dispatchId, with a test pinning that the worker's bearer handle never reaches the record.
  • Publication minting moved into createClaudeSessionPublication. Supporting change to stay under the file-length limit; verified behavior-preserving (exactly-once acquisitionGeneration/linkId/observedAt, same order, continuesChain untouched).
  • WSL transcript timeout now emits a trace span in addition to its console line, through the existing tracer rather than the chat logger since the gate is shared with non-chat scanners.
  • New ratchet test fails on console.warn/console.error (three spellings) and reporting-only on*Error?/on*Failed?/on*Failure? callbacks across the structured-chat scope, with the logger sink and four behavioral hooks allowlisted.

ℹ️ The ratchet's scope list skips two structured-chat files that its own regex would flag

structured-background-logger-ratchet.test.ts claims no structured-chat production code reports a failure only to the console or through a reporting-only optional on*Failure? callback. But SCOPE_PREFIXES/SCOPE_FILES never feed src/main/claude/claude-background-task-rows.ts or src/main/claude/claude-background-task-row-writer.ts to the scanner, and both are structured Claude-session production code (used by claude-structured-journal-translation.ts) that declare an optional onPersistenceFailure? callback. The guard's own OPTIONAL_FAILURE_CALLBACK regex matches onPersistenceFailure, so widening the scope without allowlisting it would turn the guard red — the current green state depends on the omission. No failure is dropped today (the callback is always wired by createClaudeJournalFailureHandler), so this is a guard-completeness gap rather than a runtime bug, but it is the exact class the ratchet exists to make hard to reintroduce.

Technical details
# Ratchet scope gap: background-task row persistence failures

## Affected sites
- `src/main/native-chat/agent-session-wire/structured-chat-logger-ratchet.test.ts` — `SCOPE_PREFIXES` has no `main/claude/claude-background-task-` entry and `SCOPE_FILES` does not list either file, so `inScope` returns false for both.
- `src/main/claude/claude-background-task-rows.ts:56` — `onPersistenceFailure?: (error: Error) => void` on `ClaudeBackgroundTaskRowsDeps`.
- `src/main/claude/claude-background-task-row-writer.ts:24,48,55,75` — constructor param and the three `?.()` call sites.
- `src/main/claude/claude-structured-journal-translation.ts:15,111,120` — imports `ClaudeBackgroundTaskRows` and forwards the callback, which is how these files are reached from structured chat.

## Required outcome
The guard's stated guarantee should either hold for this code or be explicitly out of scope. If these files are in scope, add them (to `SCOPE_FILES` or a `main/claude/claude-background-task-` prefix) and add `onPersistenceFailure` to `BEHAVIORAL_OPTIONAL_HOOKS` for the two paths, since the callback changes behavior (ends the session) rather than merely reporting. If they are deliberately out of scope, say so in the comment so the next reader does not read the guard as covering all structured Claude journaling.

## Suggested approach (optional)
Check first whether every `onPersistenceFailure` call site has a logger-equivalent already; if a future omission would silently drop the failure, prefer widening the scope over documenting the gap.

Pullfrog  | Fix it ➔ | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

This branch has not been deployed

No deployments
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