Skip to content

fix(coding-agent): revive archived sessions on prompt instead of dead-ending - #1039

Closed
junhoyeo wants to merge 28 commits into
PrimeIntellect-ai:mainfrom
junhoyeo:fix/revive-archived-session-on-prompt
Closed

fix(coding-agent): revive archived sessions on prompt instead of dead-ending#1039
junhoyeo wants to merge 28 commits into
PrimeIntellect-ai:mainfrom
junhoyeo:fix/revive-archived-session-on-prompt

Conversation

@junhoyeo

@junhoyeo junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown

Problem

A terminal window attached to a daemon session can outlive the session: the daemon archives an RLM subagent after it delivers its final answer, evicts idle workers, and parents delete finished children. The window receives session_closed, shows the "The daemon stopped this agent session…" banner, and stays open — but every subsequent prompt sends the stale activeSessionId and dead-ends with Unknown active session: <id> forever.

The transcript is saved and resumable the whole time. The agents view already offers exactly this affordance twice — resume-on-open (openAgentsViewSession catches the unknown-session error and resumes the saved file) and resume-on-reply for inactive rows — but the open chat window had no revive path at all.

Observed in the wild: a subagent window left open after the child replied to its parent; the parent archived the child ~20s later, and every keystroke in the still-open window produced Supervisor command prompt failed: Error: Unknown active session: f4e077f832dc with no recovery.

Fix

DaemonAgentConnection.prompt/promptAndWait now treat a typed message as "resume & send": on an unknown-session failure they resume the connection's saved session file via the daemon's idempotent create {sessionPath}, re-attach, emit session_resynced, and retry the prompt once. Revival failure surfaces the original unknown-session error.

Design points (each pinned by a test):

  • The revived binding is never published early. attach() is refactored into attachSessionBinding(target, resetCursors); the connection keeps its previous (dead) binding until the attach to the revived session has succeeded. A concurrently started prompt therefore targets the dead id, fails, and joins the in-flight revival — it structurally cannot race ahead into a session this client has not attached to. Because nothing mutates before attach success, there is no rollback path that could stomp a newer binding.
  • Supersession is safe. Revival captures its source binding and re-checks ownership before trusting create and inside the attach (attachSessionBinding rejects a response whose binding moved mid-flight instead of rebinding backwards). A session switch / reconnect / update recovery landing mid-revival wins; the revival releases the revived session's attachment (plus complete_owned_session for owned lifecycles, also when disposal begins mid-revival).
  • Wire-order race handled. The daemon can write the attach response and the first session_snapshot_begin for the revived session into one socket buffer, so those frames can be parsed before the awaiting continuation publishes the new binding. isMessageForActiveSession now also admits ids in pendingReattachActiveSessionIds (the same set reattachSession already maintains), and attachSessionBinding registers a foreign target there for the duration of the attach. Pre-existing attach paths always target the published id, so their behavior is unchanged. The regression test for this was verified red-green against the unfixed filter.
  • No cross-session injection. The unknown-session match is exact and bound to the id the prompt actually targeted, and a prompt only joins a sibling revival tagged with that same source id; any other rebinding surfaces the original error.
  • Legacy attach shape. With a bare-SessionSummary attach result the resync snapshot comes from separate reads; if those fail the revival still succeeds (the binding is coherently bound and attached, prompts work) and a bounded background retry delivers the session_resynced so the window cannot keep rendering the dead transcript silently.
  • Reviving a killed session on a later prompt is deliberate: the agents view reply flow already resumes killed sessions, the client cannot distinguish "user killed" from "parent archived finished child" (both close with reason killed), and a revived transcript is strictly recoverable. Documented in the revival docstring.

Tests

17 new tests in agent-connection-daemon.test.ts (80 total in the file, all passing): happy path + promptAndWait, signal-carrying prompts, revival failure surfacing the original error, no-session-file and wrong-id negatives (including an id the attempted id merely prefixes), attach-failure recovery on the next prompt, concurrent prompts sharing a single create, dispose-during-create releasing the revived session, owned-lifecycle propagation, prompts staying on the dead binding until the revived attach completes, a mid-revival session switch winning with cleanup, the same-buffer snapshot-frame ordering, and the background resync retry.

daemon-mode, daemon-supervisor-eviction, daemon-supervisor-lazy-subagents, agents-view-mode, and agents-view-inactive-reply suites all pass unchanged (265 tests).

Note

Revive archived daemon sessions on prompt instead of returning unknown-session errors

  • When a prompt targets an archived or killed daemon session, DaemonAgentConnection now transparently revives the session from its saved file and continues, rather than surfacing an unknown-session error.
  • A new LocalAttachmentTracker tracks per-socket attachment ownership so shared DaemonClient users don't accidentally detach a sibling connection's session.
  • reviveConfig is threaded from call sites (agents-view and main attach) through to DaemonAgentConnection.attach, ensuring revived workers use the same runtime config as the original session, including cwd overrides.
  • Attach/switch binding transitions now buffer catch-up snapshots and gate emissions on the published binding identity to avoid lost or stale snapshots during transitions.
  • Protocol schema bumped to revision 15; attach responses include a new wasAttached flag to support ownership-aware cleanup.

Macroscope summarized d5bc1ee.

…-ending

A window attached to a session the daemon later archives (idle eviction,
RLM subagent archived after its final answer, parent deleting a finished
child) stayed open but every keystroke failed with 'Unknown active
session' forever, even though the transcript is saved and resumable.

DaemonAgentConnection.prompt/promptAndWait now catch the unknown-session
error, resume the saved session file via the daemon's idempotent create
command, re-attach, emit session_resynced, and retry the prompt once.

The revived binding is never published early: attach now takes an
explicit target (attachSessionBinding) and the connection keeps its
previous binding until the attach succeeds, so no concurrently started
prompt can target a session this client has not attached to, and there
is no rollback that could stomp a newer binding installed by a
concurrent transition. A revival superseded by a session switch,
reconnect, or update recovery fails, leaves the newer binding
untouched, and releases the revived session's attachment (plus
complete_owned_session for owned lifecycles, also on disposal
mid-revival). attach() rejects a superseded response instead of
rebinding backwards. The unknown-session match is exact and bound to
the id the prompt targeted, and a concurrent prompt joins only a
sibling revival of that same session. Reviving a killed session on a
later prompt is deliberate: the agents view reply flow already resumes
killed sessions, and a revived transcript is strictly recoverable.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 502e7a496c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…, and failed snapshot streams

Address three review findings on the revival path:

- The revived worker's create command now carries this invocation's
  telemetry opt-out; without it the worker launched under the daemon's
  default policy and assertTelemetryAttachAllowed rejected the attach
  after the worker had already started with telemetry enabled.
- Revival resolves with the revived active session id and both retry
  paths verify the binding still equals it before re-sending the
  prompt, closing the window where a switch to an already-active
  session lands between the revival resolving and the retry
  continuation running.
- A revived attach whose response was applied but whose streamed
  snapshot failed no longer fails the revival: the binding is published
  and the client is attached server-side, so the revival falls through
  to the snapshot reads, which recover or schedule a background resync
  instead of stranding a coherent binding and losing the prompt.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

All three findings addressed in 966c11a (telemetry opt-out through the revival create, post-resolution binding verification before the prompt retry, and fall-through recovery when the revived attach stream fails after publication) — each pinned by a new test. Please re-review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

if ("snapshot" in result) {
const snapshot = result.snapshotStream
? await this.waitForSnapshot(result.snapshotStream.id)
: result.snapshot;
this.latestSnapshot = mapDaemonSessionSnapshot(snapshot, result.replay);

P2 Badge Revalidate the binding after awaiting the revival snapshot

When the revived attach response publishes its ID and then waits for a chunked snapshot, a concurrent switchSession or reconnect can bind and apply a different session before this await completes. The late revived snapshot is nevertheless applied to latestSnapshot (and completeSnapshotAssembly also updates the attached identity), so the active binding can point to the newly selected session while cached state and a subsequent session_resynced event describe the revived one; that revived attachment is not released either. Fresh evidence beyond the earlier retry finding is this unguarded post-publication snapshot await: the new check before retrying the prompt runs only after these state mutations have already occurred.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…oves mid-stream

A concurrent session switch or reconnect can rebind the connection
while the revived attach's chunked snapshot is still streaming. The
late snapshot then described a session the window no longer shows:
attachSessionBinding applied it to latestSnapshot after the await, and
completeSnapshotAssembly rewrote the attached identity and snapshot
cache from the frame handler, while the revived attachment was never
released.

attachSessionBinding now revalidates the published binding after
awaiting the streamed snapshot and throws the supersession error
instead of applying it (the revival's catch then releases the revived
attachment), completeSnapshotAssembly only mutates shared identity and
cache state - and only emits replacement/resync events - for snapshots
belonging to the published binding, and the revival's own resync
emission is skipped once the binding has moved on.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Addressed in 4d987e7: attachSessionBinding revalidates the published binding after awaiting the streamed snapshot and throws the supersession error instead of applying a late snapshot (the revival's catch then releases the revived attachment); completeSnapshotAssembly only mutates the shared identity/snapshot cache — and only emits replacement/resync events — for snapshots belonging to the published binding; and the revival's own resync emission is skipped once the binding has moved. Pinned by the new test "discards a late revived snapshot when a switch lands during the stream and releases the revived session". Please re-review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4d987e7008

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts Outdated
…current switch

The revived attach publishes its binding and then awaits the chunked
snapshot stream; a switch/reconnect landing in that window could rebind
the connection while the late revived snapshot was still applied to the
shared snapshot cache and attached identity, and a session_resynced
describing the revived session could follow.

- attachSessionBinding revalidates the published binding after awaiting
  the streamed snapshot and rejects as superseded instead of applying a
  snapshot for a session the connection no longer shows
- completeSnapshotAssembly only mutates shared identity/cursor/snapshot
  state and emits session_replaced/session_resynced when the snapshot
  belongs to the published binding (pending-transition waiters still get
  their resolved snapshot)
- the revival's own resync emission re-checks the binding, and a revived
  attachment released on the superseded-attach path now completes owned
  workers (releaseRevivedSession) instead of only detaching

Pinned by two new tests: the mid-stream switch race (snapshot discarded,
revived attachment released, next prompt targets the switched session)
and the owned-worker release on a failed post-revival attach (red-green
verified against the raw-detach variant).
…nding targets

The pending-target admission added for the same-buffer attach race let
EVERY outbound frame addressed to the pending id through, not just the
snapshot transfer it exists for. After a supersession the revived id
stays pending until the snapshot waiter finishes, so a live
session_event, session_status, session_resynced, or session_closed for
the superseded session was processed against the newly switched
binding - a session_closed would emit a terminal close for a window
showing a different session.

isMessageForActiveSession now admits a pending target's frames only
for session_snapshot_begin/chunk/end/failed; those handlers are keyed
by snapshotId and completeSnapshotAssembly already refuses to mutate
shared state for a non-published binding. Live frames for a pending
target are dropped. Red-green verified: with the broad admission the
new test observes the spurious terminal close.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-3 finding addressed in a59f857 (pending-target admission restricted to snapshot transfer frames, red-green verified) plus 3201db6 (owned-worker release on the superseded-attach path). Please re-review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a59f857cd9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…prompt

When a signal-carrying prompt's unknown-session failure races its abort,
promptWithAdmissionCancellation rethrows the failure as an
AgentConnectionPromptAdmissionError carrying the same
'Unknown active session: <id>' message, which canReviveFromSavedSession
matched — so cancelling a prompt against an archived session created and
attached a revived worker only for the retry to observe the aborted
signal and reject.

promptWithSessionRevival now refuses to start or join a revival once the
prompt's signal has aborted and surfaces the failure as-is. Pinned by a
red-green-verified test that races the abort against the gated
unknown-session response and asserts no create is issued.
…nding was pending

The daemon queues events that land during an attach snapshot and
delivers them afterwards as a catch-up resync. When that resync is
addressed to a revival target that is still pending - sharing the
socket buffer with the attach response and completing before the
attach continuation publishes the binding - it had no waiter:
completeSnapshotAssembly stored it in completedSnapshots, nothing
consumed it, and the older attach snapshot became current with the
intervening events lost until some later resync.

completeSnapshotAssembly now buffers the newest unsolicited catch-up
per pending target, and attachSessionBinding applies it via
applyReplacementSnapshot once the binding publishes, so the revival's
resync emission carries the caught-up state. A failed or superseded
transition discards the buffered catch-up along with the admission,
and transport resets clear the buffer. Red-green verified: without the
flush, the new test observes the revival resync carrying the older
attach snapshot instead of the catch-up.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-4 findings addressed: the pending-target catch-up buffering in df0cf07 (thread 3742775069) and the cancelled-prompt revival guard in 6470a60 (thread 3742775074), plus the owned-worker release on the superseded-attach path in 3201db6. Head is df0cf07: tsc clean, biome clean, 88/88 connection tests (18 revival-specific), 353/353 across the six related suites, all new behaviors red-green pinned.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: df0cf07528

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…tion targets

session_snapshot_failed is admitted for pending binding targets so the
transfer can settle, but the handler then ran recoverFailedSnapshot for
replacement/resync purposes unconditionally. For a catch-up that fails
while its revival target is still pending, recovery re-read state
against the still-published archived selector, failed with the same
unknown-session error, and emitted a terminal close - killing the
window even though the revived attach was about to succeed.

Recovery now runs only when the failed snapshot belongs to the
published binding. A failed pending catch-up needs no recovery: once
the binding publishes, the transition re-reads fresh state anyway, and
on supersession the buffered state is discarded. Red-green verified:
without the gate the new test observes the spurious terminal close.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-5 finding addressed in 50b835d (recovery gated to the published binding; failed pending catch-ups settle without terminal-close side effects). Head is 50b835d: tsc clean, biome clean, 89/89 connection tests (19 revival-specific), 354/354 across the six related suites, all behaviors red-green pinned.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 50b835d498

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…e publication

The round-5 gate stopped terminal recovery for a catch-up that fails
while its transition target is pending, but the events that catch-up
carried were then silently dropped: the successful attach snapshot was
cached fresh, so the transition's post-publication read served the
cache instead of re-reading from the daemon.

A failed pending catch-up is now recorded per target
(pendingBindingCatchupFailures). At publication, a buffered successful
catch-up supersedes it (newest wins, applied from the buffer); with no
successful catch-up the cached attach snapshot is invalidated so the
mandatory read actually re-reads. The marker is discarded with the
admission on failed/superseded transitions and cleared on transport
resets. Red-green verified: with the invalidation disabled, the
revival resync serves the stale attach snapshot instead of the
re-read state.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-6 finding addressed in 8109307 (failed pending catch-ups invalidate the attach snapshot's freshness at publication unless a later successful catch-up superseded them, so the post-publication read is genuinely fresh). Head is 8109307: tsc clean, biome clean, 90/90 connection tests (20 revival-specific), 355/355 across the six related suites, all behaviors red-green pinned.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8109307ac3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…led one

Round-6 made a buffered successful catch-up clear an earlier failure
marker, but the symmetric ordering leaked stale state: a success
buffered at T1 followed by a NEWER catch-up failing at T2 left the T1
snapshot in the buffer, so publication applied state-at-T1, cleared
the failure marker, and the [T1, T2] events carried by the failed
catch-up were lost with no re-read.

Recording a pending-target failure now also drops any buffered
snapshot for that target - newest wins in both directions - so
publication finds no buffer, consumes the marker, invalidates the
cached attach snapshot, and the mandatory read fetches state at or
beyond T2. Red-green verified: without the drop, the new test observes
the revival resync serving the stale T1 buffer instead of the re-read
state.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-7 finding addressed in ba1ad54 (a newer failed catch-up evicts an older buffered success, so publication re-reads instead of serving stale state; the pending catch-up state machine is closed under both orderings, each red-green pinned). Head is ba1ad54: tsc clean, biome clean, 91/91 connection tests (21 revival-specific), 356/356 across the six related suites.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ba1ad540dd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts Outdated
…apshot await

The daemon can deliver the attach snapshot's end frame and a queued
catch-up resync in one socket read. With the binding already published,
completeSnapshotAssembly applies the newer resync (and emits it) before
the waitForSnapshot continuation resumes; the continuation then
overwrote latestSnapshot with the OLDER attach snapshot and re-marked
it fresh, so the revival's resync served stale state and the
intervening events were dropped. The binding-supersession check cannot
catch this: the binding never moved.

The continuation now skips its assignment when a fresh snapshot other
than the pre-await one carries a higher event sequence - newest wins by
sequence, guarded by an identity check first because a sequence is only
comparable within one session (an unchanged latestSnapshot can still
describe the previous binding). Red-green verified: without the guard,
the new post-publication wire-order test observes the attach snapshot
overwriting the catch-up.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-8 finding addressed in 0d2e4ed (a catch-up applied to the published binding during the attach snapshot await is kept by sequence-based newest-wins instead of being overwritten by the older attach snapshot). Head is 0d2e4ed: tsc clean, biome clean, 92/92 connection tests (22 revival-specific), 357/357 across the six related suites, red-green pinned.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0d2e4ed732

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts Outdated
Comment thread packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts Outdated
…blished the same binding

A concurrent switchSession targeting the connection's own saved session
file lands as SessionAlreadyActiveError for the id the revival's create
just produced; reattachSession publishes that id as the new binding. The
revival's post-create supersession check then released the revived
session — detaching the connection's currently PUBLISHED binding, so it
stayed bound locally but stopped receiving daemon events.

The supersession path now releases the revived session only when the
newer binding differs from the revived id; the supersession error is
still thrown (the switch's reattach owns the binding, the failed prompt
surfaces its original error, and subsequent prompts flow to the live
binding). Pinned by a red-green-verified test asserting no detach or
complete_owned_session is issued for the revived id and the next prompt
targets it.
Both openAgentsViewSession attach paths omitted reviveConfig, so a
chat opened from the agents view - the archetypal window for the
revive-on-prompt fallback - recreated its session under daemon
defaults instead of the launch context resumeSavedAgentsViewSession
uses.

The resume-config computation is extracted into
agentsViewSessionRuntimeConfig (shared by resumeSavedAgentsViewSession
and both attach call-sites, so the revival's create is byte-identical
to the resume's), the live-attach path derives it from the summary,
and the resume path passes through the exact config it just created
with. Pinned by a parity test covering the intact-cwd and
missing-cwd-fallback cases.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-14 finding addressed in 837be68 (both agents-view attach paths now carry the shared resume config as reviveConfig; parity pinned). Please re-review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 837be68249

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts Outdated
Comment thread packages/coding-agent/src/modes/daemon/daemon-protocol.ts
… transcript

The wasAttached reliance is now gated on a negotiated attach_ownership
server capability. Against a daemon that cannot report ownership the
client keeps the historical unconditional detach on a superseded
revival: skipping it there would leave a stale socket attachment that
inflates attachedClients and blocks the revived worker's idle eviction
until the socket closes, which is worse than the pre-existing
shared-client edge that detach carries. Both mixed-version directions
are pinned: capability present + duplicate attach preserves the
sibling's subscription; capability absent keeps the legacy detach.

The revival config also stops leaking across session switches: the
connection records which transcript its reviveConfig was computed for
(first attach), and reviving a different transcript drops the config's
cwd - the daemon then resumes in the switched transcript's own
directory instead of treating the previous project's cwd as an
explicit override. Red-green verified for both changes.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-15 findings addressed in c5e9a2a: attach_ownership is a negotiated server capability with legacy fallback to the historical detach (both mixed-version directions pinned), and the revival config tracks its transcript — a session switch drops the stale cwd so the revived prompt runs in the switched transcript's own directory. Both red-green verified. Please re-review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5e9a2a5f7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts Outdated
…nse, not post-stream state

A replacement snapshot landing while the revived attach snapshot was
still streaming could rewrite the attached identity before the revival
captured its transcript binding; matchesRevivedBinding then passed
against the switched transcript and the failed prompt was resent into
it. The identity published by the attach response is now recorded
before the snapshot await (lastAttachPublishedIdentity) and the
revival builds its binding from that, so a mid-stream replacement
fails the identity check and the prompt's original error surfaces.
Red-green verified.

The agents-view reply fallback (the telemetry-disabled sendPrompt
attach) also carries reviveConfig now, computed from the reply
target's summary with the shared agents-view helper - the last attach
site that could revive under daemon defaults.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-16 findings addressed in ae2db8c (revived identity captured from the attach response before the snapshot await; the last agents-view attach site carries reviveConfig). Red-green verified. Please re-review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ae2db8c32c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…lback cwd

A transcript switched in over a missing recorded directory only opened
because the user selected a fallback cwd; the revival's stale-cwd strip
then recreated it with no override, so the create failed on the missing
directory and the prompt dead-ended - the exact failure this branch
exists to fix.

switchSession records the cwd override alongside the transcript it
switched to (cleared when a switch needs none), and the revival re-applies
it whenever it recreates that transcript, independent of whether an
invocation config is present. Red-green verified: without the retention,
the new test observes the recreate dropping the fallback cwd.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-17 finding addressed in 48fae2a (switchSession records its cwd override per transcript; revival re-applies it). Red-green verified. Please re-review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 48fae2a5a2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/coding-agent/src/modes/agents-view/agents-view-mode.ts Outdated
Comment thread packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts Outdated
…connection

A reply that resumed an inactive transcript recomputed the delivery
connection's revive config from the now-live summary, stripping a
fallback cwd the resume was opened with (its recorded directory is
missing); a revival of that connection then failed on the missing
directory. The resume's own config now travels through sendPrompt and
wins over the summary-derived recomputation.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-18: the reply-path config carry is fixed in 8436157; the legacy-daemon detach finding is declined with reasoning on its thread (it inverts round 15's demanded trade-off; the complete fix is a per-client attachment refcount, proposed as a follow-up PR). Please re-review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8436157579

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/coding-agent/src/modes/daemon/daemon-protocol.ts
… path

A switch to a missing-cwd transcript that resolves as a reattach (the
transcript is live under another worker) skipped the override
recording, so a later revival of that transcript recreated it against
the still-missing recorded directory and dead-ended. The catch path
now records the override too, keyed by the canonical file the reattach
reported. Red-green verified.

Also adds the old-client/new-daemon direction test the wire-change
rule requires: a daemon that reports wasAttached against a client
without the negotiated capability behaves identically to a
pre-revision-15 client - the field is ignored and the historical
unconditional detach is kept.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-19 findings addressed in b2bb37b (reattach path retains the fallback cwd; old-client/new-daemon direction test added). Red-green verified. Please re-review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b2bb37bb27

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…transcript

A --no-session chat's initial attach has no session file, leaving the
revive-config transcript marker unset; a transcript resumed later then
matched the undefined marker check and inherited the launch cwd as an
explicit override into the wrong directory. The marker now records
null for a fileless first attach, so any later transcript counts as
foreign and the cwd is dropped. Red-green verified.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-20 finding addressed in c3adf81 (fileless first attach recorded as null marker; later transcripts drop the launch cwd). Red-green verified. Please re-review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c3adf81be0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts Outdated
…onnects

The null marker for a fileless first attach was assigned with ??=,
which re-assigns over null - a reconnect after resuming a saved
transcript adopted that transcript as the config's own and the launch
cwd leaked back into its revival. The capture now checks strictly for
undefined. Red-green verified.
@junhoyeo

junhoyeo commented Aug 9, 2026

Copy link
Copy Markdown
Author

@codex review

Round-21 finding addressed in 1ca7353 (strict undefined check preserves the fileless marker across reconnects). Red-green verified. Please re-review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1ca7353702

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@sethkarten

Copy link
Copy Markdown
Contributor

Thank you for the report and proposed work. This root cause is now covered by maintainer-owned stacked PR #1162, authored independently from upstream/main.

We did not inspect or reuse this PR's diff, branch, commits, implementation code, or tests; its public description/comments were used only as a bug report. To keep one review surface, this PR is superseded by #1162 and is being closed.

The complete review stack is #1158#1165. It is being left unmerged for human review after CI and review-bot findings are cleared.

@sethkarten sethkarten closed this Aug 10, 2026
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.

2 participants