You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
run: npx tsx ../../node_modules/vitest/dist/cli.js --run test/daemon-supervisor-process.test.ts -t "proves exact owned cleanup over a Windows named pipe"
upstream_support: Prime upstream does not expose a frozen caller-owned exact-environment contract, secret-free current-attachment proof, or bounded structured cleanup result that survives worker and supervisor replacement without weakening owner isolation.
281
+
revisit_when:
282
+
- Prime upstream exposes an equivalent public-root token, exact caller environment reuse, generation-scoped post-attach proof, and structured bounded cleanup outcomes.
283
+
- Pylon can remove the fork token without weakening native multi-instance isolation or its pre-create ACP fallback.
Copy file name to clipboardExpand all lines: .pylon/upstream-review.md
+9Lines changed: 9 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -118,3 +118,12 @@ This ledger records Prime upstream evidence and the decision taken for each over
118
118
- Large-transcript handling prepares one immutable payload, bounds framing and drain waits, avoids quadratic private-buffer shifting, and preserves spill ownership and cleanup across cancellation, crash, and stale generations. Stock/current `v0.8.1` supervisor and worker directions retain their mixed-version fallback.
119
119
- The pre-ledger source candidate `8b504e3774875c241c5d0d3b4b588a09f4aa3f8e` passed `npm run check`, package build, 246 conflict-affected exact-head tests after rebase, 16 real supervisor-process tests with 8 fixture-gated skips, stock/current compatibility in both directions, a 36 MiB exact-package transfer, a 10,000-message preparation probe, a 131,000-fragment framing probe, and two independent adversarial reviews. The ledger correction changes the exact head and therefore requires renewed targeted checks and hosted CI before merge.
120
120
- Revisit when Prime upstream supplies the same capability-gated fresh-generation identity, attachment-local retry containment, mixed-version behavior, and bounded preparation/framing guarantees without weakening Pylon's correlated lifecycle or cleanup contracts.
121
+
122
+
## 2026-08-31 — caller-owned session environment and cleanup contract candidate
123
+
124
+
- Prime issue [#33](https://github.com/pylon-code/prime-agent/issues/33) freezes `caller_owned_session_environment_cleanup_v1` for the Pylon [#199](https://github.com/pylon-code/pylon/issues/199) native multi-instance gate. The public-root SDK token plus the daemon hello offers for the contract and authoritative cleanup form the preflight that selects native before create. Native attach must then return a current successful proof; a missing post-attach proof triggers bounded native cleanup and fails closed rather than pretending ACP cleaned a partial native create.
125
+
- Opted-in client-owned workers use one validated caller snapshot as the exact launch environment across create, attach fallback, worker recovery, and supervisor replacement. Legacy callers keep ambient merge behavior and never advertise the contract. Durable worker state stores only a non-secret contract marker, never the snapshot or an environment identity.
126
+
- Public proof is limited to protocol/app/build and supervisor/transport generations. Observable cleanup is single-flight and bounded, with fixed completed, already-completed, replacement-settled, owner-mismatch, uncertain, transport-failure, and unsupported outcomes. Arbitrary owners still cannot attach to or complete another owner's worker.
127
+
- The additive wire change keeps protocol version 7 and advances the schema revision from 28 to 29. Mixed-version clients remain usable through the legacy path when opt-in is absent.
128
+
- Local validation covers protocol and environment validation, old/new offer and echo compatibility, two-owner isolation, worker recovery, supervisor replacement, proof invalidation/republishing, wrong-owner denial, descriptor/log redaction, and cleanup. The Windows named-pipe case is committed but must run on the hosted `windows-latest` gate before merge.
129
+
- Cross-repository order remains Prime #33 and a reproducible package artifact first, then Pylon #199 consuming the exact proof. Revisit when upstream provides an equivalent frozen contract and Pylon can remove the fork token without weakening its ACP fallback.
Copy file name to clipboardExpand all lines: packages/coding-agent/docs/sdk.md
+18Lines changed: 18 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -77,6 +77,24 @@ if (!connection.supportsNegotiatedCapability("correlated_prompt_lifecycle_v1"))
77
77
78
78
`supportsNegotiatedCapability()` is false before attach, while a new attach or reattach is pending, after transport or attachment invalidation, and after disposal. It becomes true only after the same physical transport returns a validated client capability echo and the exact snapshot commit succeeds. `supportsCorrelatedPromptLifecycle()` remains server-offer evidence used to construct the attach request. It is not negotiation proof. Do not substitute a hello offer, method presence, attach success, or package version for the post-attach accessor. Correlated runtime frames are withheld until the attach-side echo commits and are discarded when the echo omits the capability. Pre-proof retention is bounded by both frame count and conservative cumulative structural weight; overflow fails the adapter closed without retaining or reporting attributed payload content. A chunked replacement uses the same count and weight bounds for frames held behind its atomic snapshot fence. New same-connection attachment admission, attachment-epoch change, transport loss, disposal, or matching session close retires that old fence before any later proof can publish; delayed old snapshot frames are ignored until a fresh attachment commits.
79
79
80
+
### Caller-owned daemon session environments and cleanup
81
+
82
+
Native multi-instance hosts must gate caller-owned daemon sessions with the exact `caller_owned_session_environment_cleanup_v1` contract. Require all three proofs:
83
+
84
+
1.`PRIME_AGENT_SDK_FEATURES` from the package root includes the token.
85
+
2. The connected daemon hello offers both the same token and `authoritative_owned_session_cleanup_v1`.
86
+
3.`connection.getOwnedSessionContractProof()` returns the current post-attach proof.
87
+
88
+
If either package-root or daemon-offer preflight fails, select ACP fallback before sending the native client-owned `create`. ACP fallback never cleans up a partially created native session. If the later attach does not return the current proof, fail native admission, run bounded native cleanup, and report that failure; do not treat ACP as retroactive cleanup for that partial native create. Do not infer support from a package version, method presence, constructor shape, protocol version, schema revision, or daemon offer alone.
89
+
90
+
Pass one defensively captured `ownedSessionLaunchEnv` and a fresh `ownedSessionRecoveryConfig` to `DaemonAgentConnection`. Recovery config is required whenever the exact environment option is present; omitting it fails synchronously before attach. Use that same environment snapshot and `launchEnvMode: "replace"` on the preceding client-owned `create` request. The SDK validates and clones the option synchronously. A negotiated daemon uses the snapshot as the worker's whole caller-owned environment, adds only Prime-owned worker bootstrap variables, and reuses it with the recovery config for attach fallback and recovery. Without the exact options and negotiated token, legacy environment merging remains unchanged and the connection does not advertise this contract.
91
+
92
+
The contract proof contains only the feature/status, protocol identity, schema revision, app/build identity, supervisor generation, and SDK-local transport generation. It is absent before attach, during reattach, after transport or attachment invalidation, after promotion/disposal, and for unproved peers. It never contains the environment, home, path, secret, hash, fingerprint, PID, socket, owner token, or canary.
93
+
94
+
Use `disposeOwnedSession({ timeoutMs })` when cleanup must be observable. Concurrent calls join one operation, and `timeoutMs` is one strict total deadline for reconnection, authoritative queries, completion, side-question aborts, and unsupported-peer finalization. Its fixed statuses are `completed`, `already_completed`, `replacement_settled`, `owner_mismatch`, `uncertain`, `transport_failure`, and `unsupported`; `uncertain` also reports whether the last authoritative state was `active` or `stopping`. `replacement_settled` means an authenticated supervisor with a different generation answered the read-only cleanup query with `settled` for the connection's previously proved opaque route. Cleanup never sends completion on a replacement or pending route without a current internal attach proof. Each strict cleanup request is transport-bound and is never replayed after reconnect. Public attachment proof remains absent throughout disposal. Results never return raw errors or environment identity. `dispose()` remains the legacy best-effort `Promise<void>` API.
95
+
96
+
`DaemonClient.request()` keeps legacy reconnect replay by default. Pass `{ recoverAcrossReconnect: false }` only when one request must fail on transport close instead of crossing to a new daemon transport.
97
+
80
98
`DaemonClient.close()` is terminal owner disposal. `isClosed` becomes true, later `connect()` calls reject, and a live `DaemonAgentConnection` emits one terminal close. Normal and update recovery stop before any later restart, connect, attach, or restored-session query; already-running recovery callbacks are not cancellable but their results are discarded.
81
99
82
100
`DaemonClientOptions.maxInboundFrameBytes` is the maximum raw bytes before LF in one inbound JSONL frame. It defaults to `DEFAULT_DAEMON_CLIENT_MAX_INBOUND_FRAME_BYTES` (128 MiB) and must be a positive safe integer. LF is excluded. A CR immediately before LF is counted and then stripped.
0 commit comments