Skip to content

fix(native-chat): a Codex stream retry is one warning row that updates in place - #23684

Merged
brennanb2025 merged 19 commits into
mainfrom
brennanb2025/codex-retry-one-row
Sep 30, 2026
Merged

brennanb2025 merged 19 commits into
mainfrom
brennanb2025/codex-retry-one-row

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 7 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​767 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​767
Prod 19 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​224 $\color{#cf222e}{\Huge{\mathbf{−}}}$​22 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​202

ELI5

When Codex loses its connection mid-answer, it quietly tries again and tells Orca about each try. Orca printed every try as a new red error, so one dropped connection filled the chat with red rows that looked like the turn failing over and over. Now the chat shows one yellow line per reconnect that counts up ("Codex is retrying: Reconnecting... 3/5.") with what went wrong on the line under it. A real failure is still red.

What Changed

The problem (before)

When Codex's connection to the model drops mid-answer, Codex quietly retries ("Reconnecting... 1/5", "2/5", ...) and sends Orca an error notification with willRetry: true for every attempt. Orca drew each one as its own red error row. A single dropped stream filled the chat with five to ten red rows, as if the turn had failed over and over, when Codex was only reconnecting and often recovered on its own. What actually went wrong (Codex's additionalDetails, e.g. "unexpected status 502 Bad Gateway") was hidden behind each row's raw-frame Details.

A second, smaller bug sat under it: every Codex frame row was named provider-frame:codex:<n> from a counter that restarted on each new Codex connection. After a reconnect, the new connection's frame rows reused the old names and silently overwrote the earlier rows in the chat history.

After, for the user

  • A reconnect is one yellow warning row, not a stack of red ones. It reads Codex's own progress, "Codex is retrying: Reconnecting... 3/5.", and counts up in place as attempts arrive.
  • The line under it says what failed, in Codex's words (e.g. "unexpected status 502 Bad Gateway: ..."). If Codex's detail only repeats the message, the row is one line.
  • If Codex later has to reconnect again (for example after falling back from WebSockets to HTTPS, or after making progress), that second reconnect gets its own row below whatever happened in between.
  • An error Codex gives up on (willRetry: false) is unchanged: a red row, and the turn fails.
  • A subagent's reconnect is one row in that subagent's own section and never hides or splits the main conversation's reconnect row, and the other way round.
  • Rows from an earlier Codex connection are no longer overwritten after a reconnect.

Not affected: Claude sessions (its retry rows keep their current behaviour), terminal (TUI) sessions, and orchestration worker transcripts, which still list one row per attempt.

How it works

Host. Each Codex error frame with willRetry: true is written to the session journal as its own warning row, through the same frame-row writer every other Codex frame uses (same caps, admission and backpressure, and it publishes activity, so the idle sweep keeps treating a reconnecting Codex as busy). The row carries a providerRetrying failure fact: Codex's message as the person-facing detail, and retry: { error, status, cause } read from codexErrorInfo and additionalDetails. cause is a new optional field; the shared failure-words table prints it on the line under the sentence. The host keeps no retry state.

Client. The shared structured-message projection, which desktop, mobile and the conversation outline all read, draws only the latest row of each run. A run belongs to one agent: that agent's retry rows with none of its own other rows between them. Another agent's rows never end it, because each agent's rows are drawn apart (the conversation, or the subagent's own section). Rows that draw nothing (turn records, pending approvals) do not end a run; queued sends are drawn after the conversation, so they do not either. Every attempt stays in the journal; only the drawing skips the earlier ones.

Frame row names. Codex frame rows are now named provider-frame:codex:<connection id>:<n>, where the connection id is the random id Orca already mints for each Codex acquisition. The acquire path mints it before creating the translator and passes it in.

Why

A retry is not a failure yet, so a red row per attempt reads as repeated failure and buries the conversation. An earlier revision of this PR rewrote one host row in place per reconnect. That needed the host to decide, while frames streamed past, where a reconnect ends: in-memory run state per thread, run numbers in the row name, classifying every other frame just to end a run, and clearing all of it on session end and restore. Getting that boundary wrong either hides a later reconnect above newer content or splits one reconnect into several rows.

Writing each attempt as its own row and collapsing at draw time removes all of that. The journal stays append-only and keeps an honest record of every attempt. "Which rows belong together" is decided from what the screen actually draws next to each other, which is the question the person is asking. The rule lives in one shared module, so desktop and mobile cannot disagree. Runs are per agent because that is exactly how the transcript splits rows into the conversation and subagent sections; collapsing on the flat list showed two stacked rows whenever another agent wrote between two attempts.

The cause is printed on the row because it is usually the only line that says what actually went wrong, and Codex's own interface shows it under its progress message. It is stored in the row text by the host, like every other row's words, so older clients show it too.

Alternatives considered:

  • Keeping the host-side run tracking (above): more state, more ways to get the boundary wrong.
  • Collapsing inside the transcript's per-section split: mobile does not call that function, so it would need a second call site that could drift.
  • Counting attempts from the message text: breaks on messages without a count ("Reconnecting... waiting for network") and on any wording change.

Differences from the common pattern

  • Intended: the common pattern keeps every attempt and replaces the previous reconnect row with the next adjacent one at render time, within one thread's timeline. Orca does the same, and keys the run on the agent because Orca's structured transcript holds every agent's rows in one journal and splits them into sections when drawing. Safe because the key is the same one the section split uses.
  • Intended: the cause is a second line of the row's text, where the common pattern keeps it in a separate detail field. Orca's rows carry their words as host-written text, and this is what lets older clients show it.
  • Temporary: Claude's retry rows still use the older host-side rewrite of one row per run. The shared collapse already handles those rows (a single row draws as is). The follow-up is to write one Claude row per attempt and delete the Claude run tracker.

Known limits

  • Each attempt is a new row, so a Details panel opened on the retry row closes when the next attempt replaces it a few seconds later.
  • After a successful reconnect the last "Reconnecting... N/M" row stays in the chat as a record, the same as any other warning.
  • An older desktop or phone connected to a newer host draws one yellow row per attempt (with the cause line), never red. A newer client on an older host draws what it drew before.
  • A red "codex · notification:thread/status/changed" row can still appear after a reconnect run that ends in failure; that is a separate bug handled by fix(native-chat): a failed Codex turn shows its error, not a raw thread-status row #23704.

Linked Issue

None.

Visual Proof

Live Electron, real Codex 0.157.0 on macOS, with the model endpoint forced to answer 502 through a per-process Codex flag in an isolated test profile (no Codex config file written). Both builds also carry #23552, which the isolated test setup needs. Before: main at 8b01590. After: this PR at 7af0a14. The red "codex · notification:thread/status/changed" row in both is the separate bug #23704 fixes.

Before (main): one red row per attempt, nine for one dropped stream.

Before, mid-run: WebSocket attempts, fallback warning, then red HTTPS attempts 1/5 to 5/5

Before, final: every attempt is still its own red row above the final error

After (this PR): one yellow row per reconnect with what failed on its second line; the WebSockets-to-HTTPS fallback warning sits between the two reconnects; the red final error ends the turn. Reloading the window draws the same thing from the journal, which still holds all nine attempts.

After, mid-run: one yellow row at 4/5 with the failure on its second line

After, later: the WebSocket reconnect stopped at 5/5, the fallback warning, then one HTTPS reconnect row counting up

After, final: two yellow reconnect rows, the fallback warning, and the red final error

After, following a window reload: the same rows, drawn from the journal

Testing

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

codex-provider-retry-row.test.ts: every attempt writes its own warning row under its own name, with the providerRetrying fact and Codex's cause on the second line; a missing or repeated cause leaves one line; every attempt publishes; a new connection in the same session keeps earlier rows; the real acquire path names rows for the acquisition that received them (fails if the acquire path stops passing the id); a captured real Codex run gives warning rows, then the red row, then a failed turn.

codex-provider-retry-idle-sweep.test.ts: retry frames ten minutes apart keep the conversation open past the thirty-minute idle window; once they stop, the sweep closes it.

native-chat-provider-retry-runs.test.ts: a run draws only its latest row; the same agent's other rows split it; agents retrying at once each keep one row; another agent's row does not split a run, checked through the transcript's section split (one row in the conversation, one in the subagent's section); rows that draw nothing and queued sends do not split it; an older host's single row draws as is; nothing changes when nothing retried.

NativeChatMessageList.provider-retry-runs.test.tsx (desktop) and use-mobile-structured-agent-session-retry-rows.test.tsx (mobile): a three-attempt run renders as one row whose text carries the cause on its second line.

agent-session-failure-words.test.ts and agent-session-failure.test.ts: the cause prints on the second line and survives a read, bounded like any provider detail.

Each piece was ablated and turned at least one test red. Related suites pass: Codex journal translation, settlement, subagents, turn-ending replays, session adapter and lifecycle, generic frames, idle sweep, transcript projection, conversation outline, the desktop message list (including subagent sections) and mobile session tests. tc:node, tc:web and mobile typecheck, oxlint, and check:code-quality:changed pass.

AI Disclosure

Review

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.

Notes

SSH: rows are written on the execution host like every other journal row, and the collapse runs wherever the transcript is drawn. No path, shell or platform-specific behaviour. Folder workspaces and git worktrees behave the same.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

…try row

A retry row whose fact carries a detail the provider wrote for a person now
quotes it, the same way a rejected message or failed compaction does, so the
row says how the retry is going. A log detail still stays out of the sentence.
…s in place

An error Codex says it will retry used to fall through to the generic frame
row: red, and a new row for every attempt. It now writes one providerRetrying
row per retry run, warning-toned, revised by each attempt with Codex's own
progress sentence. A run is the retry frames of one turn with nothing else the
thread journals between them; every attempt still publishes, so the idle sweep
keeps seeing activity. Errors Codex will not retry are unchanged.
… frame behind Details

The quoted retry sentence leads with "is retrying", which holds for any
provider's progress text. The Codex retry row also keeps the whole bounded
frame behind the row's Details, as the generic row did, so Codex's
additionalDetails stays available to diagnose a retry.
…its one row

Pins the run being opened before the write: a first attempt whose publish is
refused and is handed back must revise the row it already wrote, not open a
second run. Also stops the fixture claiming Codex sends an idle thread status
beside each retry, which the app server does not do.
…fied

Ending a retry run classified every non-retry frame, and classifying walks the
whole payload: every streaming delta, and every large item/completed, paid a
walk about as costly as parsing the frame. Only a thread with a run open needs
the answer, so the classification now runs only there.
…th what failed on its second line

A stream error Codex says it will retry is written as its own warning row
with a providerRetrying fact, under the same per-frame identity every
Codex frame row gets. The host no longer tracks retry runs or rewrites
one row in place, so there is no run state to open, end or clear, and no
frame has to be classified to end a run. Every attempt publishes, which
keeps renewing the idle clock while Codex retries.

Codex's additionalDetails, which its own UI shows under the progress
message, is kept on the fact as the retry's cause and printed on the
row's second line. Errors Codex will not retry are unchanged.
…r retry run

The shared structured message projection, which both the desktop and the
mobile transcript read, collapses a run of retry rows into its latest
row. A run is retry rows from the same agent with no other drawn row
between them; a row that draws nothing, or a queued send drawn after the
conversation, does not split it. The earlier attempts stay in the
journal.
… later one never revises it

Frame rows were named provider-frame:codex:<n> from a counter that starts
over with every connection, so the first frame row after a reconnect in the
same session revised an earlier connection's row in place, at its old spot.
Each connection's frame rows now carry the acquisition generation, minted
once before the translator is built: provider-frame:codex:<generation>:<n>.
Rows already written keep their identities.
…never splits it

Each agent's rows are drawn apart: the session's own rows are the conversation,
and a subagent's rows open in that subagent's section. Splitting a run on any
other row in the flat list left two adjacent retry rows on screen whenever
another agent wrote between two attempts: a subagent finishing a command while
the session reconnected, or the session working while a subagent reconnected.

A run is now per agent: an agent's retry rows with none of its own other rows
between them, drawn as its latest.
@brennanb2025

brennanb2025 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor Author

Review status: clean at 04467ce, CI green (still a draft)

Where it stands. Review loops are finished and the last loop came back clean. The branch includes current main (7afa4ee). tc:node, tc:web and the mobile typecheck pass at the head. The PR's own tests pass (92 desktop, 1 mobile), and so do the neighbouring Codex translation, transcript projection, subagent section and mobile session suites. oxlint and check:code-quality:changed are clean.

What the review changed

  • 252cd9c: when two agents are retrying at the same time, each one keeps its own single retry row, and one agent's retry never hides another's.
  • 100e92c: a test that goes through the real acquire path and checks that each reconnect names its rows after its own connection. With the wiring removed, the test fails.
  • 1a86450: fixes a bug that appeared once main started drawing each subagent's rows in its own section (refactor(native-chat): a subagent's rows live in its own section, not in the parent's conversation #23752). When another agent wrote a row between two retry attempts, the user saw two stacked retry rows. A retry run now belongs to one agent, and only that agent's own rows end it.
  • 04467ce: CI's mobile test typecheck caught the PR's new mobile test. Its stubbed RPC reply was missing id, and two variables declared inside the test body were typed as always-null. Both are fixed; the change is test-only. The mobile test ratchet passes, and CI is green at this head: 18 checks passed, 15 skipped, none failed.
  • 7af0a14: the subagent case is now tested through the same section split the transcript uses. Comments that still described the old rule are corrected.

Architecture check. More than three loops ran, so a separate review questioned the design itself. Its verdict was to keep it.

  • Every attempt is saved as its own row, and runs are collapsed only when drawing. The collapse happens in the one shared projection that desktop, mobile and the conversation outline all read.
  • The key for a run is the same one the transcript uses to split rows into sections. Earlier findings came from those two disagreeing, so that kind of bug is now closed.
  • Orchestration worker transcripts are correctly left out, because their paging depends on having one message per item.

Readiness checklist. It passed at the start (100e92c, with one P2) and at the end (7af0a14). The P2 was the subagent-section issue fixed in 1a86450.

Live QA. Real Codex 0.157.0 in live Electron. A local stand-in server answered 502 to every model request, set by a per-process Codex flag in an isolated test profile. No Codex config file was written, and the real Codex hook and config files were hashed before and after every run with no change.

Before (main): every attempt is its own red row.
Before: red row per attempt

After (7af0a14): one yellow row per reconnect, counting up, with the failure on its second line.
After, mid-run
After, final

After reloading the window, the transcript is identical and the journal still holds all nine attempts. The renderer console showed no errors.

Known and out of scope

  • The red codex · notification:thread/status/changed row that appears in both before and after is fix(native-chat): a failed Codex turn shows its error, not a raw thread-status row #23704.
  • Claude's retry rows still rewrite one row per run on the host. That is a follow-up.
  • Each new attempt replaces the drawn row, so an opened Details panel closes at the next attempt.
  • QA covered a single agent. Subagent sections are covered by tests, not by live QA.

@brennanb2025
brennanb2025 marked this pull request as ready for review September 30, 2026 09:04
@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Repository guideline files applied to this review (1)
AGENTS.md — auto-discovered

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: b39580b6-61b4-4ecd-8dde-a610f5c98bd1

📥 Commits

Reviewing files that changed from the base of the PR and between afa81dc and bc37c61.

📒 Files selected for processing (26)
  • mobile/src/session/use-mobile-structured-agent-session-retry-rows.test.tsx
  • src/main/codex/codex-provider-retry-idle-sweep.test.ts
  • src/main/codex/codex-provider-retry-row.test.ts
  • src/main/codex/codex-provider-retry-row.ts
  • src/main/codex/codex-structured-journal-contracts.ts
  • src/main/codex/codex-structured-journal-generic-frames.ts
  • src/main/codex/codex-structured-journal-translation.ts
  • src/main/codex/codex-structured-session-acquire.ts
  • src/main/codex/codex-structured-thread-facts.ts
  • src/renderer/src/components/native-chat/NativeChatMessageList.provider-retry-runs.test.tsx
  • src/renderer/src/components/native-chat/agent-session-failure-words-text.ts
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json
  • src/shared/agent-session-failure-copy.ts
  • src/shared/agent-session-failure-words.test.ts
  • src/shared/agent-session-failure-words.ts
  • src/shared/agent-session-failure.test.ts
  • src/shared/agent-session-failure.ts
  • src/shared/native-chat-provider-retry-runs.test.ts
  • src/shared/native-chat-provider-retry-runs.ts
  • src/shared/structured-agent-session-message-projection.ts

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


📝 Walkthrough

Walkthrough

Codex retry notifications now produce warning journal rows with provider details and acquisition-specific identities. Shared failure facts preserve sanitized retry causes, and retry copy can include provider details. Structured-session projection collapses consecutive retry rows for each agent. Added tests cover journal handling, idle sweeps, retry-row projection, and desktop and mobile rendering.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to bc37c

No merge-blocking issue is established. Retry attempts remain in the journal while the transcript displays the latest warning per agent; merge after normal checks pass.

Security Architecture Review

Security architecture risk: 🔵 Low · up to bc37c

The change improves retry-history isolation and keeps diagnostic text bounded. No introduced security vulnerability was established, but diagnostic confidentiality and some failure-recovery behavior remain incompletely verified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The inspected exposure is provider-authored diagnostic content entering the originating session's journal and client transcript. Thread attribution and per-agent projection constrain the examined flow; this does not establish backend authorization or prove isolation across every storage and transport boundary.

Trust Boundaries and Controls

  • observed — The checked conversion path treats diagnostics as strings, limits copied causes, and bounds retained frame payloads to a 16 KiB inline head with truncation metadata. Desktop warning rows route to the notice renderer. These are size and presentation controls, not evidence of secret filtering or complete downstream rendering safety.

Resilience and Maintainability Implications

  • inferred — Accepted append followed by rejected publication can cause notification replay to allocate another frame identity. The same sequence and separate publication pattern exists in the inspected base, so this is an existing recovery limitation rather than a demonstrated PR regression. The notification retry queue bounds retained events and fails explicitly when ownership is lost or capacity is exceeded.

Hardening Proposals

  • proposed — If provider diagnostics can contain credentials or private infrastructure details, define an explicit redaction and audience policy before copying additionalDetails into prominent transcript text. This is conditional hardening, not an observed credential leak.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is detailed and covers the user impact, implementation, rationale, visual proof, testing, scope, and checklist. However, the required Linked Issue section states "None," while the repo… Add the actual linked issue under "Fixes #". If the contributor is a maintainer, attach a pre-existing issue instead of opening a new one. Complete the AI Disclosure section if the contributor is external and used AI assistance.
Docstring Coverage ⚠️ Warning Docstring coverage is 37.14% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 35 functions across 19 files. (7 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: Codex stream retries appear as one warning row that updates in place.
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.
Full details: Description check

Explanation

The description is detailed and covers the user impact, implementation, rationale, visual proof, testing, scope, and checklist. However, the required Linked Issue section states "None," while the repository template requires an actual issue reference.

Full details: Docstring Coverage

Explanation

Docstring coverage is 37.14% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 35 functions across 19 files. (7 skipped: 7 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
  • 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 Sep 30, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Changes how Codex stream retry errors appear in chat.

The PR appears safe to merge based on the reviewed changes.

Summary

The PR records each Codex reconnect attempt in the journal while showing only the latest warning in each agent’s visible retry run. It also gives frame rows acquisition-specific identities so a reconnect does not overwrite earlier rows.

  • Retry details remain visible beneath the progress message; terminal errors remain separate error rows.
  • Desktop and mobile use the shared transcript projection.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Codex retry frame] --> B[Append warning row to journal]
  B --> C[Shared transcript projection]
  C --> D[Collapse visible retry run per agent]
  D --> E[Desktop and mobile transcript]
Loading

Reviews (2) · Last reviewed commit: "Merge remote-tracking branch 'origin/mai..."

@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 found.

Reviewed changes — full review of this PR's 17 files: the host-side warning row, the client-side run collapse, and the per-connection frame-row identity, plus seven new test suites.

  • Host writes one warning row per attempt. Each Codex error frame with willRetry: true is journaled as its own tone: 'warning' status row via a new providerRetrying fact; detail carries Codex's own message and retry carries {error, status, cause}, with cause a new optional field. The frame is written through appendFrameRow, so it publishes and keeps the idle sweep treating a reconnecting Codex as busy.
  • Shared client collapse draws only the latest row. collapseProviderRetryRuns drops every retry row but the latest of each run, keyed by agentJournalItemSubagentId — the same key the transcript's subagent-section split uses — and wired into projectStructuredAgentSessionMessages, so desktop, mobile and the conversation outline agree.
  • Per-connection frame-row names. Frame rows are now provider-frame:codex:<acquisitionId>:<n>, ending the reconnect overwrite; the acquire path mints the generation before creating the translator and passes it in.
  • The cause prints on the second line. The providerRetrying sentence now quotes a person-audience detail and appends retry.cause; Codex messages are person text, so Claude's log-audience retry rows keep their old wording.

Verified against callers and adjacent behavior: the retry branch sits after item routing and before the generic notification:error fallback; retry frames no longer reach commands.errorShown, which already no-ops for willRetry frames (src/main/codex/codex-journal-command-turn.ts:151); orchestration worker transcripts intentionally still call projectStructuredItemsToNativeChat directly; and NativeChatMessageRow prefers the toned notice over providerFrame, so the sentence renders yellow with the raw frame behind Details.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

…try-one-row

# Conflicts:
#	src/main/codex/codex-structured-journal-generic-frames.ts
#	src/shared/agent-session-failure-words.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 found.

Reviewed changes — the merge with origin/main since the prior review, where the branch reconciled its Codex retry-row feature with main's failure-copy refactor (#23674).

  • Retry sentence ported onto the shared copy table. providerRetrying now composes providerRetrying / providerRateLimited / providerRetryingQuoted through the say function, and quotingPersonDetail takes the quoted sentence's copy id instead of concatenating strings.
  • New quoted copy and translations. providerRetryingQuoted ({{agent}} is retrying: {{detail}}.) joins AGENT_SESSION_FAILURE_COPY, en-runtime-required.json, all six locale catalogs, and the desktop PIECES map.
  • withRetryCause extracted. The provider's own account of what failed still prints on the row's second line, and a read now re-bounds the cause through readProviderRetry / readAgentSessionFailureFact.
  • Main's frame-classification signature adopted in codex-structured-journal-generic-frames / translation; per-connection frame-row naming is unchanged.

Verified the reconciliation is behavior-preserving: the person-detail path yields the same sentence as before, the log-audience Claude path keeps its rate-limited/temporary wording with no cause, and the focused host/shared/render suites pass (93 tests).

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@brennanb2025
brennanb2025 merged commit b4b708c into main Sep 30, 2026
35 checks passed
brennanb2025 added a commit that referenced this pull request Sep 30, 2026
…, where main's tests still used the old calls

#24006 moved the store into the journal database and #23684 added a test on the
old open call; main's close now takes a cause. Four tests catch up.
brennanb2025 added a commit that referenced this pull request Sep 30, 2026
…ges crossed (#24231)

* test: two tests catch up with the journal-database store and the close cause

#24006 moved the session store into the chat journal database, and #23467 made close take a cause; #23684's and an older tab-table test still used the old calls, so main's typecheck fails.

* test: the startup-reconcile close test passes the close cause too
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