Skip to content

Commit d3323e3

Browse files
committed
test(daemon): model attachment proof in resume fixture
1 parent c27e1b6 commit d3323e3

2 files changed

Lines changed: 25 additions & 8 deletions

File tree

‎.pylon/upstream-review.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,5 +104,6 @@ This ledger records Prime upstream evidence and the decision taken for each over
104104
- Runtime-frame fence: correlated `session_event`, `prompt_lifecycle`, and attributed extension frames received while the exact attach request is active are withheld under independent 128-frame and 256 KiB cumulative conservative structural-weight limits. The iterative accounting does not serialize or copy payloads and rejects cycles, unsupported values, unsafe accounting, individual overflow, and cumulative overflow before retention. Frames are released through ordinary ordered dispatch only after the validated capability echo and snapshot commit publish the matching transport proof. They are discarded with a fixed payload-free error on missing echo, invalidation, failure, overflow, or disposal. The atomic chunked-replacement fence applies the same 128-frame/256 KiB structural limits to all queued daemon frames. Same-connection attach/reattach admission retires it synchronously; attachment-epoch change, transport loss, disposal, and matching session close also discard its header, bounded queue, begun assembly, and delayed unsolicited transfer before a later proof can publish. Peer-only attachment mutation does not retire another logical connection's route-local fence. Runtime snapshot shaping uses the committed echo rather than the hello offer. A peer-only shared-client mutation racing the lifecycle query strips stale shaping but may still commit the connection's own unshaped replacement. Any same-connection admission, epoch, route, transport, terminal, update, or disposal change discards the entire old replacement handler so it cannot rewind route identity under a newer proof. Offer-without-echo resync remains compatible without accepting correlated data.
105105
- Disposal: public attach/reattach admission and the accessor fail closed from the first synchronous disposal step. An already-running owned-session recovery may perform one serialized, unproved internal reattach only to reach authoritative `complete_owned_session`; it cannot publish proof or restoration events. This preserves cleanup without reopening the public attachment API during disposal.
106106
- Compatibility: keep `supportsCorrelatedPromptLifecycle()` as documented offer evidence because it constructs the pre-attach request. Strict consumers use only the new post-attach accessor. Offer-without-echo attaches and resynchronizes successfully with proof false and without requiring a lifecycle snapshot. Stock 0.8.1 remains loadable but lacks the feature token/accessor. Replacement intentionally clears public proof until a later attach result re-establishes it; already-echoed runtime shaping stays bound to the unchanged physical client transport and is cleared before any later capability mutation.
107-
- Repair validation: focused daemon connection/client tests pass 219/219. They cover exact post-commit proof; same-stack queued and active B/C attach admission-token races; a superseded active B/C reattach with commit-time proof observation; synchronous admission fencing of every outstanding snapshot assembly and headerless old-route begin/end/failed frames; current-admission revision binding for the only legitimate request-attempt exception; pre-begin failure admission only for an existing assembly, exact active request, or current route-local replacement fence; retired same-route begin and failure tombstones across duplicate terminal frames, later request attempts, and post-commit replay; permanent fixed fail-close instead of tombstone eviction on the 129th distinct ignored ID while active B and queued C remain uncommitted; exact current-request same-ID begin reuse without allowing a pre-descriptor runtime commit; terminal and update close retirement of ordinary begin/chunk/end tails before close or authoritative restoration publication; full tombstone-budget message-first and socket-first update, killed/shutdown, and explicit owner-close classification before pending-fence or dead-transport retirement, with idempotent duplicate closes, first-owner contradictory update/terminal ordering, exactly one authoritative outcome, and no per-snapshot recovery attach; direct replacement/resync suppression throughout newer cross-route inline/streamed admission, terminal/update ownership, and disposal await windows, with immediate fresh-route close delivery and no stale post-close publication; prompt release after a newer admission retires a stalled streamed attach; cumulative and individual pre-proof weight overflow below the count cap; successful release/discard accounting resets; payload-free fail-close; peer-only unshaped replacement commit; full stale same-connection route discard after B reattach; bounded chunked-replacement queue overflow; header-only A-fence retirement before B reattach and physical reconnect; matching session-close bypass/retirement; delayed retired-A begin/end and pre-begin failed-frame discard during gated B admission; exact current-attempt binding for legitimate failure-before-begin; stale queued-frame discard and fresh B-route event delivery; permanent fail-closed retry rejection; transport-reset fences; target-reattach invalidation; shared-client serialization and global overwrite invalidation; terminal direct-close generation, active/socketless notification, normal/update in-flight recovery suppression, duplicate-event prevention, and payload-free public close; disposal re-entry; unproved owned cleanup reattach; valid same-generation resync; offer-without-echo resync and frame suppression; fixed malformed/wrong-client errors; duplicate/unrequested/unknown/non-array/non-string proof rejection; replacement/socket-close clearing; and frozen public-root export. The renewed root build, `npm run check`, `git diff --check`, six isolated process files (79/79), and clean real supervisor process suite pass; the latter records 13 passes with 8 fixture-gated skips. With the installed pinned stock 0.8.1 CLI (`package.json` version 0.8.1; launcher SHA-256 `c5dffcd16a401551986023134fbc05457775e1eeed618a5a6ae0d0cee1772d5f`), both runtime adoption directions pass against the rebuilt current CLI. Namespace probes confirm stock 0.8.1 has neither token nor accessor while the rebuilt candidate exports both. Exact committed-head reviews remain mandatory.
107+
- Repair validation: focused daemon connection/client tests pass 219/219.
108+
- Hosted exact-head CI on `c27e1b6ea329aabe19ec70f768bcbf37c79a6bef` exposed a deterministic `ResumeDaemonClient` fixture incompatibility in shard 1/3: the cast fake lacked `getTransportGeneration()` and returned a stale fixed attachment identity/capability echo. The test-only repair gives the fake one stable transport generation and echoes each request's exact client ID/capabilities; the exact ENG-4656 file passes 3/3 and local shard 1/3 passes 1,466/1,466. They cover exact post-commit proof; same-stack queued and active B/C attach admission-token races; a superseded active B/C reattach with commit-time proof observation; synchronous admission fencing of every outstanding snapshot assembly and headerless old-route begin/end/failed frames; current-admission revision binding for the only legitimate request-attempt exception; pre-begin failure admission only for an existing assembly, exact active request, or current route-local replacement fence; retired same-route begin and failure tombstones across duplicate terminal frames, later request attempts, and post-commit replay; permanent fixed fail-close instead of tombstone eviction on the 129th distinct ignored ID while active B and queued C remain uncommitted; exact current-request same-ID begin reuse without allowing a pre-descriptor runtime commit; terminal and update close retirement of ordinary begin/chunk/end tails before close or authoritative restoration publication; full tombstone-budget message-first and socket-first update, killed/shutdown, and explicit owner-close classification before pending-fence or dead-transport retirement, with idempotent duplicate closes, first-owner contradictory update/terminal ordering, exactly one authoritative outcome, and no per-snapshot recovery attach; direct replacement/resync suppression throughout newer cross-route inline/streamed admission, terminal/update ownership, and disposal await windows, with immediate fresh-route close delivery and no stale post-close publication; prompt release after a newer admission retires a stalled streamed attach; cumulative and individual pre-proof weight overflow below the count cap; successful release/discard accounting resets; payload-free fail-close; peer-only unshaped replacement commit; full stale same-connection route discard after B reattach; bounded chunked-replacement queue overflow; header-only A-fence retirement before B reattach and physical reconnect; matching session-close bypass/retirement; delayed retired-A begin/end and pre-begin failed-frame discard during gated B admission; exact current-attempt binding for legitimate failure-before-begin; stale queued-frame discard and fresh B-route event delivery; permanent fail-closed retry rejection; transport-reset fences; target-reattach invalidation; shared-client serialization and global overwrite invalidation; terminal direct-close generation, active/socketless notification, normal/update in-flight recovery suppression, duplicate-event prevention, and payload-free public close; disposal re-entry; unproved owned cleanup reattach; valid same-generation resync; offer-without-echo resync and frame suppression; fixed malformed/wrong-client errors; duplicate/unrequested/unknown/non-array/non-string proof rejection; replacement/socket-close clearing; and frozen public-root export. The renewed root build, `npm run check`, `git diff --check`, six isolated process files (79/79), and clean real supervisor process suite pass; the latter records 13 passes with 8 fixture-gated skips. With the installed pinned stock 0.8.1 CLI (`package.json` version 0.8.1; launcher SHA-256 `c5dffcd16a401551986023134fbc05457775e1eeed618a5a6ae0d0cee1772d5f`), both runtime adoption directions pass against the rebuilt current CLI. Namespace probes confirm stock 0.8.1 has neither token nor accessor while the rebuilt candidate exports both. Exact committed-head reviews remain mandatory.
108109
- Cross-repository merge order: Prime issue #17 and a reproducible artifact, Pylon issue #190 consuming the exact post-attach proof, then Comet issue #7. Exact committed-head API/security/test review and trusted hosted CI remain mandatory. Revisit when upstream offers an equivalent generation-scoped proof and both consumers can remove this token without weakening fail-closed negotiation.

‎packages/coding-agent/test/suite/regressions/4656-resume-active-session.test.ts‎

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class ResumeDaemonClient {
3535
type: "response",
3636
command: command.type,
3737
success: true,
38-
data: createAttachResult(command.activeSessionId),
38+
data: createAttachResult(command.activeSessionId, [], command.clientId, command.capabilities),
3939
};
4040
}
4141
if (command.type === "switch_session") {
@@ -52,9 +52,12 @@ class ResumeDaemonClient {
5252
};
5353
}
5454
if (command.type === "reattach") {
55-
const result = createAttachResult(command.targetActiveSessionId, [
56-
{ role: "user", content: "target prompt", timestamp: 2 },
57-
]);
55+
const result = createAttachResult(
56+
command.targetActiveSessionId,
57+
[{ role: "user", content: "target prompt", timestamp: 2 }],
58+
command.clientId,
59+
command.capabilities,
60+
);
5861
const snapshotId = "target-snapshot";
5962
const { messages, ...snapshot } = result.snapshot;
6063
this.emitMessage({
@@ -118,6 +121,10 @@ class ResumeDaemonClient {
118121
}
119122
}
120123

124+
getTransportGeneration(): number {
125+
return 1;
126+
}
127+
121128
supportsServerCapability(): boolean {
122129
return false;
123130
}
@@ -154,7 +161,16 @@ function createConnectionState(activeSessionId: string): AgentConnectionState {
154161
};
155162
}
156163

157-
function createAttachResult(activeSessionId: string, messages: AgentMessage[] = []): DaemonAttachResult {
164+
function createAttachResult(
165+
activeSessionId: string,
166+
messages: AgentMessage[] = [],
167+
clientId = "client-1",
168+
clientCapabilities: readonly NonNullable<DaemonAttachResult["client"]>["capabilities"][number][] = [
169+
"attach_snapshot",
170+
"event_sequence",
171+
"chunked_snapshot",
172+
],
173+
): DaemonAttachResult {
158174
const state = createConnectionState(activeSessionId);
159175
const lastEventCursor = { generation: `generation-${activeSessionId}`, sequence: 3 };
160176
const summary: SessionSummary = {
@@ -187,8 +203,8 @@ function createAttachResult(activeSessionId: string, messages: AgentMessage[] =
187203
lastEventSequence: 3,
188204
lastEventCursor,
189205
client: {
190-
id: "client-1",
191-
capabilities: ["attach_snapshot", "event_sequence", "chunked_snapshot"],
206+
id: clientId,
207+
capabilities: [...clientCapabilities],
192208
},
193209
};
194210
}

0 commit comments

Comments
 (0)