@junghanacs/entwurf 0.20.1 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/AGENTS.md +85 -190
  2. package/BASELINE.md +4 -3
  3. package/CHANGELOG.md +195 -14
  4. package/CONTRIBUTING.md +1 -1
  5. package/DELIVERY.md +202 -60
  6. package/README.md +49 -22
  7. package/VERIFY.md +37 -7
  8. package/docs/acp-backend-rail.md +0 -1
  9. package/docs/external-mcp-host.md +54 -33
  10. package/docs/setup-clean-host.md +110 -17
  11. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +101 -109
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-fresh-preflight.js +326 -0
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-fact-provider.js +22 -2
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-peers-render.js +3 -1
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +6 -7
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-native-push.js +30 -17
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-production.js +7 -1
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +7 -4
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-mailbox-body.js +20 -11
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +227 -1
  21. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +50 -15
  22. package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/adapter.js +10 -7
  23. package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/codex-ws-client.js +403 -0
  24. package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/register.js +4 -4
  25. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-hook-codex.js +325 -0
  26. package/mcp/entwurf-bridge/dist/scripts/meta-bridge-fresh-cut.js +6 -1
  27. package/mcp/entwurf-bridge/src/index.ts +115 -111
  28. package/mcp/entwurf-bridge/tsconfig.build.json +1 -0
  29. package/package.json +13 -4
  30. package/pi-extensions/entwurf-control.ts +71 -19
  31. package/pi-extensions/lib/codex-fresh-preflight.ts +363 -0
  32. package/pi-extensions/lib/compaction-send-guard.ts +80 -0
  33. package/pi-extensions/lib/entwurf-fact-provider.ts +29 -3
  34. package/pi-extensions/lib/entwurf-peers-render.ts +4 -1
  35. package/pi-extensions/lib/entwurf-v2-contract.ts +6 -7
  36. package/pi-extensions/lib/entwurf-v2-native-push.ts +35 -18
  37. package/pi-extensions/lib/entwurf-v2-production.ts +10 -3
  38. package/pi-extensions/lib/entwurf-v2-surface.ts +7 -4
  39. package/pi-extensions/lib/meta-mailbox-body.ts +22 -13
  40. package/pi-extensions/lib/meta-sender-identity.ts +305 -0
  41. package/pi-extensions/lib/mux-fresh-call.ts +64 -19
  42. package/pi-extensions/lib/native-push/adapter.ts +21 -24
  43. package/pi-extensions/lib/native-push/codex-ws-client.ts +506 -0
  44. package/pi-extensions/lib/native-push/register.ts +7 -9
  45. package/pi-extensions/meta-bridge-hook-codex.ts +371 -0
  46. package/run.sh +218 -28
  47. package/scripts/check-agy-sender-identity.ts +1 -1
  48. package/scripts/check-codex-birth-hook.ts +264 -0
  49. package/scripts/check-codex-bridge-identity.ts +179 -0
  50. package/scripts/check-codex-native-push.ts +386 -0
  51. package/scripts/check-codex-sender-identity.ts +495 -0
  52. package/scripts/check-compaction-send-guard.ts +130 -0
  53. package/scripts/check-copilot-receive-arm.ts +4 -1
  54. package/scripts/check-entwurf-fact-provider.ts +38 -0
  55. package/scripts/check-entwurf-peers-surface.ts +13 -1
  56. package/scripts/check-entwurf-self-address.ts +15 -16
  57. package/scripts/check-entwurf-v2-contract.ts +4 -3
  58. package/scripts/check-entwurf-v2-decider.ts +7 -5
  59. package/scripts/check-entwurf-v2-native-push.ts +35 -7
  60. package/scripts/check-entwurf-v2-production.ts +203 -11
  61. package/scripts/check-entwurf-v2-runner.ts +1 -1
  62. package/scripts/check-entwurf-v2-surface.ts +1 -1
  63. package/scripts/check-gate-qualification.ts +6 -3
  64. package/scripts/check-harness-admission-parity.ts +0 -1
  65. package/scripts/check-mux-launch-tmux.ts +47 -2
  66. package/scripts/check-native-push-adapter.ts +20 -16
  67. package/scripts/check-native-push-register.ts +5 -1
  68. package/scripts/check-release-gate-outcomes.ts +47 -1
  69. package/scripts/check-setup-qualification.sh +3 -1
  70. package/scripts/codex-birth-doctor.sh +276 -0
  71. package/scripts/codex-birth-install.sh +414 -0
  72. package/scripts/codex-birth-uninstall.sh +170 -0
  73. package/scripts/codex-mcp-config.py +435 -0
  74. package/scripts/codex-statusline-config.py +434 -0
  75. package/scripts/codex_toml_io.py +532 -0
  76. package/scripts/lib/codex-fresh-live-protocol.ts +113 -0
  77. package/scripts/lib/codex-fresh-source-receipts.ts +399 -0
  78. package/scripts/lib/launch-receipt-windows.ts +46 -0
  79. package/scripts/lib/tmux-coordinate-row.ts +58 -0
  80. package/scripts/meta-bridge-fresh-cut.ts +6 -1
  81. package/scripts/mutants/codex-native.json +838 -0
  82. package/scripts/mutants/compaction-send-guard.json +103 -0
  83. package/scripts/mutants/entwurf-peers.json +19 -0
  84. package/scripts/mutants/mux-fresh-call.json +19 -8
  85. package/scripts/mutants/omp-fresh.json +6 -4
  86. package/scripts/mutants/release-gate.json +13 -0
  87. package/scripts/mutants/v2-surface.json +53 -1
  88. package/scripts/raw-async-delivery/README.md +2 -1
  89. package/scripts/raw-codex-measure/README.md +114 -46
  90. package/scripts/smoke-agy-native-push-live.ts +3 -1
  91. package/scripts/smoke-codex-birth.sh +347 -0
  92. package/scripts/smoke-codex-config-state.sh +511 -0
  93. package/scripts/smoke-codex-fresh-live.ts +1186 -0
  94. package/scripts/smoke-codex-native-push-live.ts +75 -0
  95. package/scripts/smoke-setup-verdict.sh +123 -10
  96. package/scripts/tsconfig.json +1 -0
@@ -0,0 +1,1186 @@
1
+ /**
2
+ * First-admission LIVE acceptance for Codex visible fresh.
3
+ *
4
+ * The operator owns the existing exact `codex` tmux home and Codex app-server. This smoke neither
5
+ * creates nor supervises them: an explicit ENTWURF_CODEX_APP_SERVER_PID names the already-running
6
+ * process whose /proc environment must corroborate the home. It starts from a DIFFERENT caller
7
+ * session; omitted Codex placement selects the home by exact name. The attached TUI pane is never guessed.
8
+ *
9
+ * RELEASE MUST once Codex is admitted. LIVE!=1 is the only host-prerequisite SKIP. With LIVE=1,
10
+ * missing system birth, user MCP/status config, app-server, models, runtime, bridge, or tmux seat
11
+ * is a FAIL. The smoke drives only public MCP calls, then joins Pi's native toolCall/toolResult
12
+ * rows and Codex app-server thread events as receipt authority; screen text and model-reformatted
13
+ * reports are never oracles.
14
+ *
15
+ * A record-backed self-fetch fixture opens a real visible Pi caller through public fresh_call.
16
+ * That Pi opens Codex, correlates Codex's raw callback, and addresses Codex through v2. Codex then
17
+ * opens outbound Pi, correlates that raw callback, and sends one final exact message that the
18
+ * fixture must actually read.
19
+ */
20
+
21
+ import type { ChildProcess } from "node:child_process";
22
+ import { spawn, spawnSync } from "node:child_process";
23
+ import { createHash } from "node:crypto";
24
+ import * as fs from "node:fs";
25
+ import * as os from "node:os";
26
+ import * as path from "node:path";
27
+ import { CODEX_PREFLIGHT_HINT, codexFreshPreflight } from "../pi-extensions/lib/codex-fresh-preflight.ts";
28
+ import {
29
+ defaultMetaMailboxDir,
30
+ defaultMetaSessionsDir,
31
+ metaRecordFilename,
32
+ readMetaIdentityByGardenId,
33
+ readMetaInbox,
34
+ upsertMetaSession,
35
+ writeMetaReceiverMarker,
36
+ writeMetaSenderMarker,
37
+ } from "../pi-extensions/lib/meta-session.ts";
38
+ import { CODEX_HOME_TMUX_SESSION, FRESH_CALL_BACKENDS } from "../pi-extensions/lib/mux-fresh-call.ts";
39
+ import {
40
+ readCodexThread,
41
+ realCodexProtocolOpener,
42
+ resolveCodexDefaultSocketPath,
43
+ } from "../pi-extensions/lib/native-push/codex-ws-client.ts";
44
+ import {
45
+ buildCodexInstruction,
46
+ buildInitialPiPhaseOne,
47
+ runCleanupStages,
48
+ selectReport,
49
+ } from "./lib/codex-fresh-live-protocol.ts";
50
+ import {
51
+ assertExactSourceToolCalls,
52
+ assertSourceCallScopes,
53
+ codexCallbackSenders,
54
+ codexSourceToolReceipts,
55
+ codexThreadIsTerminal,
56
+ mailboxCallbacks,
57
+ parseJsonLines,
58
+ parseMetaMailboxBody,
59
+ piCallbackSenders,
60
+ piSourceToolReceipts,
61
+ resolveSourceTranscriptPath,
62
+ selectExactSourceToolReceipt,
63
+ sourceCleanupWindows,
64
+ validateFinalMailboxBody,
65
+ } from "./lib/codex-fresh-source-receipts.ts";
66
+ import { skipLive } from "./lib/live-skip.ts";
67
+ import { parseTmuxRow, TMUX_COORDINATE_FIELDS, TMUX_COORDINATE_FORMAT } from "./lib/tmux-coordinate-row.ts";
68
+
69
+ const LABEL = "smoke-codex-fresh-live";
70
+ const REPO = path.resolve(import.meta.dirname, "..");
71
+ const GARDEN_ID = /^\d{8}T\d{6}-[0-9a-f]{6}$/;
72
+ const WINDOW_ID = /^@\d+$/;
73
+ const CALLBACK_WAIT_MS = 300_000;
74
+ // Source calls in accepted runs arrive in under a minute. Five minutes preserves cold-start room
75
+ // without repeating the old blind ten-minute model-report wait.
76
+ const SOURCE_WAIT_MS = 300_000;
77
+ const META_CONTEXT_ENV_KEYS = [
78
+ "HOME",
79
+ "CODEX_HOME",
80
+ "PI_CODING_AGENT_DIR",
81
+ "ENTWURF_META_SESSIONS_DIR",
82
+ "ENTWURF_META_MAILBOX_DIR",
83
+ "ENTWURF_META_SENDERS_DIR",
84
+ "ENTWURF_META_RECEIVERS_DIR",
85
+ ] as const;
86
+
87
+ type ToolResult = { text: string; isError: boolean };
88
+ type RpcReply = { result?: unknown; error?: unknown };
89
+ interface TmuxCoordinate {
90
+ serverPid: string;
91
+ sessionId: string;
92
+ windowId: string;
93
+ paneId: string;
94
+ }
95
+
96
+ const receipts: Record<string, string> = {};
97
+ let passed = 0;
98
+ let appServerEnv: NodeJS.ProcessEnv | null = null;
99
+ let bridge: BridgeClient | null = null;
100
+ const openedWindows: string[] = [];
101
+ const fixtureArtifacts: string[] = [];
102
+ // What a LATER receipt would have named. A timeout is exactly where a visible window
103
+ // becomes an orphan, so the two authorities that already hold the exact handles — the
104
+ // caller Pi's own transcript and the Codex thread's own tool-call results — are recorded
105
+ // as they become known.
106
+ let codexSocketPath = "";
107
+ let initialPiTranscript = "";
108
+ let initialPiGardenId = "";
109
+ // Set once run() owns its evidence file, so a path resolved DURING a poll is recorded there too.
110
+ let recordEvidence: ((patch: Record<string, unknown>) => void) | null = null;
111
+ let codexLaunchNonce = "";
112
+ let codexThreadId = "";
113
+ let codexGardenId = "";
114
+ // Reachable from the EXIT path, not just from a wait: an assertion that throws must still be
115
+ // able to ask the fixture's own mailbox which windows this run opened.
116
+ let fixtureGid = "";
117
+ let evidenceDir = "";
118
+ const seenInbox: string[] = [];
119
+ const expectedReportTokens: string[] = [];
120
+ const relatedRecordPaths = new Set<string>();
121
+ const relatedTranscripts = new Set<string>();
122
+
123
+ function ok(label: string, condition: unknown, detail = ""): asserts condition {
124
+ if (!condition) throw new Error(`${label}${detail ? `\n${detail}` : ""}`);
125
+ console.log(` ok ${label}`);
126
+ passed++;
127
+ }
128
+
129
+ function printReceipts(): void {
130
+ if (Object.keys(receipts).length === 0) return;
131
+ console.log(`\n[${LABEL}] decisive receipts`);
132
+ for (const [name, receipt] of Object.entries(receipts)) console.log(`--- ${name} ---\n${receipt}`);
133
+ }
134
+
135
+ function parseNulFile(file: string): string[] {
136
+ return fs
137
+ .readFileSync(file)
138
+ .toString("utf8")
139
+ .split("\0")
140
+ .filter((value) => value.length > 0);
141
+ }
142
+
143
+ function readProcessEnvironment(pid: number): NodeJS.ProcessEnv {
144
+ const result: NodeJS.ProcessEnv = {};
145
+ for (const entry of parseNulFile(`/proc/${pid}/environ`)) {
146
+ const equals = entry.indexOf("=");
147
+ if (equals > 0) result[entry.slice(0, equals)] = entry.slice(equals + 1);
148
+ }
149
+ return result;
150
+ }
151
+
152
+ function resolveExecutable(name: string, env: NodeJS.ProcessEnv): string | null {
153
+ for (const dir of (env.PATH ?? "").split(path.delimiter)) {
154
+ if (!dir) continue;
155
+ const candidate = path.resolve(dir, name);
156
+ try {
157
+ fs.accessSync(candidate, fs.constants.X_OK);
158
+ if (!fs.statSync(candidate).isFile()) continue;
159
+ return candidate;
160
+ } catch {
161
+ // Continue through the app-server's literal PATH; do not consult a shell alias.
162
+ }
163
+ }
164
+ return null;
165
+ }
166
+
167
+ function inspectTmuxCoordinate(label: string, env: NodeJS.ProcessEnv): TmuxCoordinate {
168
+ const tmuxValue = env.TMUX ?? "";
169
+ const paneValue = env.TMUX_PANE ?? "";
170
+ const tmuxMatch = /^(.*),(\d+),(\d+)$/.exec(tmuxValue);
171
+ ok(
172
+ `${label} carries an inspectable absolute TMUX socket tuple`,
173
+ tmuxMatch !== null && path.isAbsolute(tmuxMatch[1] ?? ""),
174
+ `TMUX=${JSON.stringify(tmuxValue)}`,
175
+ );
176
+ ok(`${label} carries a native TMUX_PANE handle`, /^%\d+$/.test(paneValue));
177
+ const inspected = spawnSync("tmux", ["display-message", "-p", "-t", paneValue, TMUX_COORDINATE_FORMAT], {
178
+ env,
179
+ encoding: "utf8",
180
+ });
181
+ ok(
182
+ `${label} tmux coordinate answers through its own environment`,
183
+ inspected.status === 0,
184
+ String(inspected.stderr ?? ""),
185
+ );
186
+ // Positionally, with empty fields preserved: a format key that answers with nothing must
187
+ // fail at ITS coordinate instead of shifting every later one left (measured on tmux 3.6a,
188
+ // where `#{server_pid}` is empty — see scripts/lib/tmux-coordinate-row.ts).
189
+ let row: string[];
190
+ try {
191
+ row = parseTmuxRow(String(inspected.stdout ?? ""), TMUX_COORDINATE_FIELDS);
192
+ } catch (error) {
193
+ throw new Error(
194
+ `${label} tmux coordinate row is malformed: ${error instanceof Error ? error.message : String(error)}`,
195
+ );
196
+ }
197
+ const [serverPid, sessionId, windowId, paneId] = row;
198
+ ok(
199
+ `${label} resolves its exact server/session/window/pane coordinate`,
200
+ serverPid === tmuxMatch?.[2] &&
201
+ /^\$\d+$/.test(sessionId ?? "") &&
202
+ WINDOW_ID.test(windowId ?? "") &&
203
+ paneId === paneValue,
204
+ `coordinate=${JSON.stringify({ serverPid, sessionId, windowId, paneId })}`,
205
+ );
206
+ return {
207
+ serverPid: serverPid as string,
208
+ sessionId: sessionId as string,
209
+ windowId: windowId as string,
210
+ paneId: paneId as string,
211
+ };
212
+ }
213
+
214
+ function cleanupWindows(): string[] {
215
+ const failures: string[] = [];
216
+ if (!appServerEnv) return failures;
217
+ for (const windowId of [...openedWindows].reverse()) {
218
+ if (!WINDOW_ID.test(windowId)) {
219
+ failures.push(`refused malformed recorded window handle ${JSON.stringify(windowId)}`);
220
+ continue;
221
+ }
222
+ const killed = spawnSync("tmux", ["kill-window", "-t", windowId], {
223
+ env: appServerEnv,
224
+ encoding: "utf8",
225
+ });
226
+ if (killed.status !== 0) {
227
+ failures.push(
228
+ `${windowId}: tmux kill-window failed (${killed.status ?? "signal"}): ${(killed.stderr ?? killed.stdout ?? "").trim()}`,
229
+ );
230
+ } else {
231
+ console.log(` cleanup removed smoke-opened window ${windowId}`);
232
+ }
233
+ }
234
+ openedWindows.length = 0;
235
+ return failures;
236
+ }
237
+
238
+ async function preservePreCleanupEvidence(reason: unknown): Promise<string[]> {
239
+ if (evidenceDir === "") return [];
240
+ const failures: string[] = [];
241
+ const snapshot = path.join(evidenceDir, "pre-cleanup-snapshot");
242
+ try {
243
+ fs.mkdirSync(snapshot, { recursive: true, mode: 0o700 });
244
+ fs.writeFileSync(
245
+ path.join(snapshot, "reason.txt"),
246
+ `${reason instanceof Error ? reason.stack : String(reason)}\n`,
247
+ {
248
+ mode: 0o600,
249
+ },
250
+ );
251
+ } catch (snapshotError) {
252
+ return [`failure evidence root: ${String(snapshotError)}`];
253
+ }
254
+ // Recovery is optional enrichment. A corrupt source is exactly when the raw files matter most,
255
+ // so its failure is recorded but can never prevent the known sources below from being copied.
256
+ try {
257
+ recoverCodexThreadAuthority();
258
+ } catch (recoveryError) {
259
+ failures.push(`optional identity recovery: ${String(recoveryError)}`);
260
+ }
261
+ const sources = [
262
+ ...(fixtureGid === "" ? [] : [path.join(defaultMetaMailboxDir(), fixtureGid)]),
263
+ ...fixtureArtifacts,
264
+ ...relatedRecordPaths,
265
+ ...relatedTranscripts,
266
+ ];
267
+ for (const [index, source] of sources.entries()) {
268
+ if (!fs.existsSync(source)) {
269
+ failures.push(`missing expected evidence source ${source}`);
270
+ continue;
271
+ }
272
+ try {
273
+ fs.cpSync(source, path.join(snapshot, `${String(index).padStart(2, "0")}-${path.basename(source)}`), {
274
+ recursive: true,
275
+ });
276
+ } catch (copyError) {
277
+ failures.push(`${source}: ${String(copyError)}`);
278
+ }
279
+ }
280
+ if (codexThreadId !== "" && codexSocketPath !== "") {
281
+ try {
282
+ const thread = await readCodexThread(codexSocketPath, codexThreadId, true);
283
+ fs.writeFileSync(path.join(snapshot, "codex-thread.json"), `${JSON.stringify(thread, null, 2)}\n`, {
284
+ mode: 0o600,
285
+ });
286
+ } catch (threadError) {
287
+ failures.push(`Codex thread ${codexThreadId}: ${String(threadError)}`);
288
+ }
289
+ }
290
+ console.error(` evidence preserved pre-cleanup snapshot at ${snapshot}`);
291
+ return failures;
292
+ }
293
+
294
+ function cleanupFixture(): string[] {
295
+ const failures: string[] = [];
296
+ for (const artifact of fixtureArtifacts.reverse()) {
297
+ try {
298
+ fs.rmSync(artifact, { recursive: true, force: true });
299
+ } catch (error) {
300
+ failures.push(`${artifact}: ${String(error)}`);
301
+ }
302
+ }
303
+ fixtureArtifacts.length = 0;
304
+ return failures;
305
+ }
306
+
307
+ function readInitialPiEntries(): unknown[] {
308
+ const before = initialPiTranscript;
309
+ initialPiTranscript = resolveSourceTranscriptPath(initialPiTranscript, () =>
310
+ initialPiGardenId === "" ? "" : readMetaIdentityByGardenId(initialPiGardenId).transcriptPath,
311
+ );
312
+ if (initialPiTranscript !== before && initialPiTranscript !== "") {
313
+ relatedTranscripts.add(initialPiTranscript);
314
+ recordEvidence?.({ initialPiTranscript, initialPiTranscriptResolvedLate: true });
315
+ }
316
+ if (initialPiTranscript === "" || !fs.existsSync(initialPiTranscript)) return [];
317
+ return parseJsonLines(fs.readFileSync(initialPiTranscript, "utf8"));
318
+ }
319
+
320
+ /** Exact joined fresh-call receipts from the initial Pi's own call/result rows. */
321
+ function readInitialPiFreshReceipts(backend: "codex" | "pi"): string[] {
322
+ return piSourceToolReceipts(readInitialPiEntries())
323
+ .filter(
324
+ (receipt) =>
325
+ receipt.toolName === "entwurf_fresh_call" &&
326
+ !receipt.isError &&
327
+ new RegExp(`^\\[entwurf fresh call →\\]\\n\\s*backend:\\s+${backend}\\b`, "m").test(receipt.text),
328
+ )
329
+ .map((receipt) => receipt.text);
330
+ }
331
+
332
+ /** The Codex window handle as the initial Pi caller's OWN transcript recorded its tool result. */
333
+ function recoverCodexWindows(): string[] {
334
+ return sourceCleanupWindows(piSourceToolReceipts(readInitialPiEntries()));
335
+ }
336
+
337
+ /** Recover the exact launch nonce from the initial Pi's one raw Codex tool receipt. */
338
+ function recoverCodexLaunchNonce(): void {
339
+ if (codexLaunchNonce !== "") return;
340
+ const receipts = readInitialPiFreshReceipts("codex");
341
+ if (receipts.length !== 1) return;
342
+ codexLaunchNonce = /^\s*nonce:\s*(mux-fresh-call-[0-9a-f]+)/m.exec(receipts[0] ?? "")?.[1] ?? "";
343
+ }
344
+
345
+ /**
346
+ * Recover the launched Codex thread from its exact nonce callback in the initial Pi transcript,
347
+ * then validate that carrier through the V3 record authority. The ordinary and failure paths use
348
+ * the same source-owned callback; model report prose has no identity role.
349
+ */
350
+ function recoverCodexThreadAuthority(): void {
351
+ recoverCodexLaunchNonce();
352
+ if (codexThreadId !== "" || initialPiTranscript === "" || codexLaunchNonce === "") return;
353
+ try {
354
+ const senders = piCallbackSenders(readInitialPiEntries(), codexLaunchNonce);
355
+ if (senders.length > 1) throw new Error(`duplicate exact Codex callbacks (${senders.length})`);
356
+ const sender = senders[0];
357
+ if (sender === undefined || !GARDEN_ID.test(sender)) return;
358
+ const identity = readMetaIdentityByGardenId(sender);
359
+ if (identity.backend !== "codex") return;
360
+ codexGardenId = sender;
361
+ codexThreadId = identity.nativeSessionId;
362
+ relatedRecordPaths.add(path.join(defaultMetaSessionsDir(), metaRecordFilename(identity)));
363
+ if (identity.transcriptPath != null) relatedTranscripts.add(identity.transcriptPath);
364
+ console.error(` recovered Codex thread ${codexThreadId} from its exact nonce callback`);
365
+ return;
366
+ } catch {
367
+ // The later cleanup stages still remove every stable window handle already recorded.
368
+ }
369
+ }
370
+
371
+ /** The outbound Pi handle as the Codex thread's own mcpToolCall result recorded it. */
372
+ async function recoverOutboundPiWindows(): Promise<string[]> {
373
+ if (codexThreadId === "" || codexSocketPath === "") return [];
374
+ try {
375
+ const thread = await readCodexThread(codexSocketPath, codexThreadId, true);
376
+ return sourceCleanupWindows(codexSourceToolReceipts(thread));
377
+ } catch {
378
+ return [];
379
+ }
380
+ }
381
+
382
+ /**
383
+ * Wait for source evidence, and when it never comes, hand cleanup the exact handles the two
384
+ * transcript authorities already hold before rethrowing. No tmux inventory scan and no guess:
385
+ * a handle no joined fresh-call result recorded stays unrecovered.
386
+ */
387
+ async function awaitOrRecover<T>(what: string, timeoutMs: number, probe: () => T | null): Promise<T> {
388
+ try {
389
+ return await until(what, timeoutMs, probe);
390
+ } catch (error) {
391
+ recoverCodexThreadAuthority();
392
+ for (const windowId of [...recoverCodexWindows(), ...(await recoverOutboundPiWindows())]) {
393
+ if (openedWindows.includes(windowId)) continue;
394
+ openedWindows.push(windowId);
395
+ console.error(` recovered ${windowId} from its own receipt authority after: ${what}`);
396
+ }
397
+ // A source that never appeared leaves no cleanup authority, and mailbox prose or a tmux
398
+ // listing must not be promoted into one. Name the state instead of leaking it silently.
399
+ if (initialPiTranscript === "") {
400
+ const unrecoverable = "initial Pi record still carries no transcriptPath; no unverified child window killed";
401
+ console.error(` cleanup ${unrecoverable}`);
402
+ recordEvidence?.({ sourcePathUnresolved: unrecoverable });
403
+ }
404
+ throw error;
405
+ }
406
+ }
407
+
408
+ /**
409
+ * Every stable window handle the initial Pi or Codex source transcript recorded in an exact
410
+ * fresh-call tool result. Mailbox prose is diagnostic evidence, never cleanup authority.
411
+ */
412
+ async function recoverEveryRecordedWindow(): Promise<void> {
413
+ recoverCodexThreadAuthority();
414
+ const found = [...recoverCodexWindows(), ...(await recoverOutboundPiWindows())];
415
+ for (const windowId of found) {
416
+ if (!WINDOW_ID.test(windowId) || openedWindows.includes(windowId)) continue;
417
+ openedWindows.push(windowId);
418
+ console.error(` recovered ${windowId} from a receipt this run already held`);
419
+ }
420
+ }
421
+
422
+ /**
423
+ * Interrupt only this smoke's exact still-running Codex turn before its visible window closes.
424
+ * `[source]` rust-v0.153.4 `app-server-protocol/src/protocol/v2/turn.rs:311-319` owns
425
+ * `{threadId,turnId}` and the empty acknowledgement; no app-server lifecycle is touched here.
426
+ */
427
+ async function interruptCodexSmokeTurn(): Promise<string[]> {
428
+ if (codexThreadId === "" || codexSocketPath === "") return [];
429
+ try {
430
+ const thread = (await readCodexThread(codexSocketPath, codexThreadId, true)) as {
431
+ turns?: Array<{ id?: unknown; status?: unknown }>;
432
+ };
433
+ const turn = [...(thread.turns ?? [])].reverse().find((candidate) => candidate.status === "inProgress");
434
+ if (typeof turn?.id !== "string" || turn.id === "") return [];
435
+ const protocol = await realCodexProtocolOpener.open(codexSocketPath);
436
+ try {
437
+ await protocol.request("initialize", {
438
+ clientInfo: { name: "entwurf-codex-live-cleanup", title: "entwurf-codex-live-cleanup", version: "0" },
439
+ capabilities: { experimentalApi: true, requestAttestation: false },
440
+ });
441
+ protocol.notify("initialized");
442
+ await protocol.request("turn/interrupt", { threadId: codexThreadId, turnId: turn.id });
443
+ } finally {
444
+ protocol.close();
445
+ }
446
+ console.error(` cleanup interrupted smoke-owned Codex turn ${turn.id}`);
447
+ return [];
448
+ } catch (error) {
449
+ return [`codex turn ${codexThreadId}: ${String(error)}`];
450
+ }
451
+ }
452
+
453
+ async function until<T>(what: string, timeoutMs: number, probe: () => T | null): Promise<T> {
454
+ const deadline = Date.now() + timeoutMs;
455
+ for (;;) {
456
+ const found = probe();
457
+ if (found !== null) return found;
458
+ if (Date.now() >= deadline) throw new Error(`timed out after ${timeoutMs}ms waiting for ${what}`);
459
+ await new Promise<void>((resolve) => setTimeout(resolve, 500));
460
+ }
461
+ }
462
+
463
+ async function untilAsync<T>(what: string, timeoutMs: number, probe: () => Promise<T | null>): Promise<T> {
464
+ const deadline = Date.now() + timeoutMs;
465
+ for (;;) {
466
+ const found = await probe();
467
+ if (found !== null) return found;
468
+ if (Date.now() >= deadline) throw new Error(`timed out after ${timeoutMs}ms waiting for ${what}`);
469
+ await new Promise<void>((resolve) => setTimeout(resolve, 500));
470
+ }
471
+ }
472
+
473
+ class BridgeClient {
474
+ private readonly child: ChildProcess;
475
+ private buffer = "";
476
+ private stderr = "";
477
+ private nextId = 1;
478
+ private readonly waiters = new Map<number, (reply: RpcReply) => void>();
479
+
480
+ constructor(command: string, env: NodeJS.ProcessEnv) {
481
+ this.child = spawn(command, [], { env, stdio: ["pipe", "pipe", "pipe"] });
482
+ this.child.stderr?.on("data", (chunk) => {
483
+ this.stderr += chunk.toString();
484
+ });
485
+ this.child.stdout?.on("data", (chunk) => {
486
+ this.buffer += chunk.toString();
487
+ const lines = this.buffer.split("\n");
488
+ this.buffer = lines.pop() ?? "";
489
+ for (const line of lines) {
490
+ if (!line.trim().startsWith("{")) continue;
491
+ try {
492
+ const reply = JSON.parse(line) as { id?: unknown; result?: unknown; error?: unknown };
493
+ if (typeof reply.id !== "number") continue;
494
+ const waiter = this.waiters.get(reply.id);
495
+ if (!waiter) continue;
496
+ this.waiters.delete(reply.id);
497
+ waiter({ result: reply.result, error: reply.error });
498
+ } catch {
499
+ // A non-protocol stdout line is diagnostic, never evidence.
500
+ }
501
+ }
502
+ });
503
+ }
504
+
505
+ private send(message: unknown): void {
506
+ this.child.stdin?.write(`${JSON.stringify(message)}\n`);
507
+ }
508
+
509
+ private rpc(method: string, params: unknown, timeoutMs = 60_000): Promise<RpcReply> {
510
+ const id = this.nextId++;
511
+ return new Promise<RpcReply>((resolve, reject) => {
512
+ const timer = setTimeout(() => {
513
+ this.waiters.delete(id);
514
+ reject(new Error(`${method} did not answer in ${timeoutMs}ms\n${this.stderrTail()}`));
515
+ }, timeoutMs);
516
+ this.waiters.set(id, (reply) => {
517
+ clearTimeout(timer);
518
+ resolve(reply);
519
+ });
520
+ this.send({ jsonrpc: "2.0", id, method, params });
521
+ });
522
+ }
523
+
524
+ async initialize(): Promise<string[]> {
525
+ const initialized = await this.rpc("initialize", {
526
+ protocolVersion: "2024-11-05",
527
+ capabilities: {},
528
+ clientInfo: { name: LABEL, version: "0" },
529
+ });
530
+ if (initialized.error !== undefined)
531
+ throw new Error(`installed bridge initialize failed: ${JSON.stringify(initialized.error)}`);
532
+ this.send({ jsonrpc: "2.0", method: "notifications/initialized" });
533
+ const listed = await this.rpc("tools/list", {});
534
+ if (listed.error !== undefined)
535
+ throw new Error(`installed bridge tools/list failed: ${JSON.stringify(listed.error)}`);
536
+ const tools = (listed.result as { tools?: Array<{ name?: unknown }> } | undefined)?.tools;
537
+ if (!Array.isArray(tools))
538
+ throw new Error(`installed bridge returned malformed tools/list: ${JSON.stringify(listed.result)}`);
539
+ return tools.map((tool) => tool.name).filter((name): name is string => typeof name === "string");
540
+ }
541
+
542
+ async call(name: string, args: Record<string, unknown>, timeoutMs = 60_000): Promise<ToolResult> {
543
+ const reply = await this.rpc("tools/call", { name, arguments: args }, timeoutMs);
544
+ if (reply.error !== undefined) throw new Error(`${name} RPC error: ${JSON.stringify(reply.error)}`);
545
+ const result = reply.result as { content?: Array<{ text?: unknown }>; isError?: unknown } | undefined;
546
+ return {
547
+ text: (result?.content ?? []).map((item) => (typeof item.text === "string" ? item.text : "")).join("\n"),
548
+ isError: result?.isError === true,
549
+ };
550
+ }
551
+
552
+ stderrTail(): string {
553
+ return this.stderr.slice(-3000);
554
+ }
555
+
556
+ close(): void {
557
+ this.child.kill("SIGTERM");
558
+ }
559
+ }
560
+
561
+ function closeBridge(): void {
562
+ const activeBridge = bridge;
563
+ if (activeBridge !== null) activeBridge.close();
564
+ }
565
+
566
+ async function run(): Promise<void> {
567
+ if (!(FRESH_CALL_BACKENDS as readonly string[]).includes("codex")) {
568
+ skipLive(
569
+ LABEL,
570
+ "codex is not admitted in FRESH_CALL_BACKENDS, so there is no visible-fresh product to accept; admission parity owns that composition state.",
571
+ );
572
+ }
573
+ if (process.env.LIVE !== "1") {
574
+ skipLive(
575
+ LABEL,
576
+ "set LIVE=1 plus ENTWURF_CODEX_APP_SERVER_PID, ENTWURF_CODEX_FRESH_MODEL, and ENTWURF_CODEX_FRESH_PI_MODEL to run; this opens real Codex and Pi windows and spends model turns.",
577
+ );
578
+ }
579
+ ok("the measured/certified host axis is Linux", process.platform === "linux", `host=${process.platform}`);
580
+
581
+ const pidText = process.env.ENTWURF_CODEX_APP_SERVER_PID?.trim() ?? "";
582
+ ok(
583
+ "ENTWURF_CODEX_APP_SERVER_PID explicitly names the existing operator-owned app-server",
584
+ /^[1-9]\d*$/.test(pidText),
585
+ );
586
+ const appServerPid = Number(pidText);
587
+ const procDir = `/proc/${appServerPid}`;
588
+ ok(
589
+ "the explicit app-server PID names a currently inspectable Linux process",
590
+ fs.existsSync(procDir),
591
+ `missing ${procDir}`,
592
+ );
593
+ const procStat = fs.statSync(procDir);
594
+ if (typeof process.getuid === "function") {
595
+ ok("the named app-server process belongs to this operator", procStat.uid === process.getuid());
596
+ }
597
+ const argv = parseNulFile(path.join(procDir, "cmdline"));
598
+ const codexArg = argv.some((arg) => /(^|\/)codex(?:\.js)?$/.test(arg) || arg.includes("@openai/codex"));
599
+ ok(
600
+ "the explicit PID argv is a Codex app-server, not a guessed Codex-related process",
601
+ codexArg && argv.includes("app-server"),
602
+ `argv=${JSON.stringify(argv)}`,
603
+ );
604
+
605
+ const procEnv = readProcessEnvironment(appServerPid);
606
+ ok(
607
+ "the app-server /proc environment carries its own absolute HOME",
608
+ typeof procEnv.HOME === "string" && path.isAbsolute(procEnv.HOME),
609
+ `HOME=${JSON.stringify(procEnv.HOME)}`,
610
+ );
611
+ ok(
612
+ "the app-server /proc environment carries its own non-empty PATH",
613
+ typeof procEnv.PATH === "string" && procEnv.PATH.length > 0,
614
+ `PATH=${JSON.stringify(procEnv.PATH)}`,
615
+ );
616
+ // Reproduce only the app-server's environment. Release-shell values absent from /proc
617
+ // cannot be borrowed into a claim about what a Codex MCP child inherits.
618
+ appServerEnv = { ...procEnv };
619
+ codexSocketPath = resolveCodexDefaultSocketPath(appServerEnv);
620
+ const expectedListen = `unix://${codexSocketPath}`;
621
+ const listensOnDefaultSocket = argv.some(
622
+ (arg, index) => (arg === "--listen" && argv[index + 1] === expectedListen) || arg === `--listen=${expectedListen}`,
623
+ );
624
+ ok(
625
+ "the explicit app-server PID owns the same default UDS the fresh Codex runtime will use",
626
+ listensOnDefaultSocket,
627
+ `expected --listen ${expectedListen}; argv=${JSON.stringify(argv)}`,
628
+ );
629
+ const appServerCoordinate = inspectTmuxCoordinate("Codex app-server/MCP inherited seat", appServerEnv);
630
+ const fixtureCoordinate = inspectTmuxCoordinate("fixture/initial-Pi caller seat", process.env);
631
+ ok(
632
+ "the fixture/initial-Pi seat and Codex home share one tmux server but are different sessions",
633
+ fixtureCoordinate.serverPid === appServerCoordinate.serverPid &&
634
+ fixtureCoordinate.sessionId !== appServerCoordinate.sessionId,
635
+ `fixture=${fixtureCoordinate.serverPid}/${fixtureCoordinate.sessionId} app-server=${appServerCoordinate.serverPid}/${appServerCoordinate.sessionId}`,
636
+ );
637
+ receipts["1-codex-app-server-mcp-coordinate"] =
638
+ `pid=${appServerPid}\nargv=${argv.join(" ")}\nserver=${appServerCoordinate.serverPid}\n` +
639
+ `session=${appServerCoordinate.sessionId}\nwindow=${appServerCoordinate.windowId}\npane=${appServerCoordinate.paneId}\n` +
640
+ `fixture-session=${fixtureCoordinate.sessionId}\nfixture-window=${fixtureCoordinate.windowId}`;
641
+
642
+ const codexModel = process.env.ENTWURF_CODEX_FRESH_MODEL?.trim() ?? "";
643
+ const piModel = process.env.ENTWURF_CODEX_FRESH_PI_MODEL?.trim() ?? "";
644
+ ok("ENTWURF_CODEX_FRESH_MODEL explicitly names the Codex runtime model", codexModel.length > 0);
645
+ ok("ENTWURF_CODEX_FRESH_PI_MODEL explicitly names the Pi callback sibling model", piModel.length > 0);
646
+ const codexRuntime = resolveExecutable("codex", appServerEnv);
647
+ ok("the Codex runtime resolves on the app-server PATH", codexRuntime !== null);
648
+ const bridgeRuntime = resolveExecutable("entwurf-bridge", appServerEnv);
649
+ ok("the installed compiled entwurf-bridge resolves on the app-server PATH", bridgeRuntime !== null);
650
+
651
+ const missing = await codexFreshPreflight(appServerEnv);
652
+ ok(
653
+ "the real installed Codex birth, MCP, visible identity, and default app-server preflight is green",
654
+ missing === null,
655
+ missing === null ? "" : `${missing}: ${CODEX_PREFLIGHT_HINT[missing]}`,
656
+ );
657
+
658
+ // The fixture and every bridge it talks to must resolve the same real stores the app-server
659
+ // forwards into Codex MCP children. This is not an isolated lookalike store.
660
+ for (const key of META_CONTEXT_ENV_KEYS) {
661
+ const value = appServerEnv[key];
662
+ if (typeof value === "string") process.env[key] = value;
663
+ else delete process.env[key];
664
+ }
665
+
666
+ const scratch = fs.mkdtempSync(path.join(os.tmpdir(), "entwurf-codex-fresh-live-"));
667
+ fixtureArtifacts.push(scratch);
668
+ fs.mkdirSync(path.join(REPO, ".probe-artifacts"), { recursive: true, mode: 0o700 });
669
+ evidenceDir = fs.mkdtempSync(path.join(REPO, ".probe-artifacts", "codex-fresh-live-"));
670
+ fs.chmodSync(evidenceDir, 0o700);
671
+ console.log(` evidence ${evidenceDir}`);
672
+ const nativeSessionId = `codex-fresh-live-fixture-${process.pid}-${Date.now()}`;
673
+ const caller = upsertMetaSession({
674
+ input: { backend: "claude-code", nativeSessionId, cwd: scratch },
675
+ });
676
+ const callerGid = caller.record.gardenId;
677
+ fixtureGid = callerGid;
678
+ relatedRecordPaths.add(caller.path);
679
+ const receiverMarker = writeMetaReceiverMarker({
680
+ gardenId: callerGid,
681
+ backend: "claude-code",
682
+ nativeSessionId,
683
+ ownerPid: process.pid,
684
+ armProvenance: "session-start",
685
+ });
686
+ const senderMarker = writeMetaSenderMarker({
687
+ backend: "claude-code",
688
+ gardenId: callerGid,
689
+ nativeSessionId,
690
+ cwd: scratch,
691
+ ownerPid: process.pid,
692
+ });
693
+ fixtureArtifacts.push(path.join(defaultMetaMailboxDir(), callerGid), receiverMarker, senderMarker, caller.path);
694
+ const evidenceManifest: Record<string, unknown> = {
695
+ runPid: process.pid,
696
+ scratch,
697
+ appServerPid,
698
+ appServerCoordinate,
699
+ fixtureCoordinate,
700
+ fixtureGardenId: callerGid,
701
+ fixtureRecordPath: caller.path,
702
+ resolvedRoots: Object.fromEntries(META_CONTEXT_ENV_KEYS.map((key) => [key, appServerEnv?.[key] ?? null])),
703
+ resolvedMetaSessionsDir: defaultMetaSessionsDir(),
704
+ resolvedMetaMailboxDir: defaultMetaMailboxDir(),
705
+ };
706
+ const writeEvidenceManifest = (patch: Record<string, unknown>): void => {
707
+ Object.assign(evidenceManifest, patch);
708
+ fs.writeFileSync(path.join(evidenceDir, "run-manifest.json"), `${JSON.stringify(evidenceManifest, null, 2)}\n`, {
709
+ mode: 0o600,
710
+ });
711
+ };
712
+ recordEvidence = writeEvidenceManifest;
713
+ writeEvidenceManifest({ phase: "fixture-ready" });
714
+ ok("the original caller is a record-backed fixture on the app-server's real meta roots", GARDEN_ID.test(callerGid));
715
+
716
+ const callerBridgeEnv: NodeJS.ProcessEnv = {
717
+ ...appServerEnv,
718
+ // The fixture launches the initial Pi from THIS operator session, not from Codex's
719
+ // app-server seat. Store/runtime facts come from the app-server environment above;
720
+ // only placement comes from the fixture's own exact tmux anchor.
721
+ TMUX: process.env.TMUX,
722
+ TMUX_PANE: process.env.TMUX_PANE,
723
+ ENTWURF_META_SENDER_MARKER: senderMarker,
724
+ };
725
+ delete callerBridgeEnv.ENTWURF_BRIDGE_NATIVE_HOST;
726
+ delete callerBridgeEnv.PI_SESSION_ID;
727
+ delete callerBridgeEnv.PI_AGENT_ID;
728
+ bridge = new BridgeClient(bridgeRuntime, callerBridgeEnv);
729
+ const tools = await bridge.initialize();
730
+ ok(
731
+ "the installed compiled bridge boots and exposes both public calls used by this acceptance",
732
+ tools.includes("entwurf_fresh_call") && tools.includes("entwurf_v2"),
733
+ `tools=${tools.join(",")}`,
734
+ );
735
+
736
+ const initialPiWaitToken = `INITIAL-PI-WAIT-${Math.random().toString(36).slice(2, 10).toUpperCase()}`;
737
+ const initialPiLaunch = await bridge.call("entwurf_fresh_call", {
738
+ backend: "pi",
739
+ model: piModel,
740
+ cwd: scratch,
741
+ task:
742
+ `After your required callback receipt, end the turn and wait passively for one addressed message containing ${initialPiWaitToken}. ` +
743
+ "That message is the only authority to open the Codex sibling. Do not call shell, sleep, terminal, or any tool to wait.",
744
+ });
745
+ receipts["2-initial-pi-launch"] = initialPiLaunch.text;
746
+ ok(
747
+ "the record-backed fixture opened a real initial Pi caller through public entwurf_fresh_call",
748
+ !initialPiLaunch.isError,
749
+ `${initialPiLaunch.text}\nbridge stderr:\n${bridge.stderrTail()}`,
750
+ );
751
+ const initialPiNonce = /nonce:\s*(mux-fresh-call-[0-9a-f]+)/.exec(initialPiLaunch.text)?.[1] ?? "";
752
+ const initialPiWindow = /window:\s+(@\d+)/.exec(initialPiLaunch.text)?.[1] ?? "";
753
+ const initialPiTmuxSession = /window:\s+@\d+.*\bin session (\$\d+)/.exec(initialPiLaunch.text)?.[1] ?? "";
754
+ ok("the initial Pi LAUNCH receipt carries a stable cleanup handle", WINDOW_ID.test(initialPiWindow));
755
+ openedWindows.push(initialPiWindow);
756
+ ok("the initial Pi LAUNCH receipt carries its exact callback nonce", initialPiNonce.length > 0);
757
+ ok(
758
+ "the initial Pi caller is visible in the fixture's non-Codex session",
759
+ initialPiTmuxSession === fixtureCoordinate.sessionId && initialPiTmuxSession !== appServerCoordinate.sessionId,
760
+ `initial-pi=${initialPiTmuxSession} fixture=${fixtureCoordinate.sessionId} codex-home=${appServerCoordinate.sessionId}`,
761
+ );
762
+ receipts["3-initial-caller-pi-coordinate"] =
763
+ `session=${initialPiTmuxSession}\nwindow=${initialPiWindow}\ncodex-home-session=${appServerCoordinate.sessionId}`;
764
+
765
+ let drainedCount = 0;
766
+ const drain = (): void => {
767
+ for (const message of readMetaInbox({ gardenId: callerGid }).messages) {
768
+ const index = String(++drainedCount).padStart(3, "0");
769
+ const bodyFile = path.join(evidenceDir, `mailbox-${index}.txt`);
770
+ fs.writeFileSync(bodyFile, message.body, { mode: 0o600 });
771
+ const parsed = parseMetaMailboxBody(message.body);
772
+ const matchingTokens = expectedReportTokens.filter((token) => message.body.includes(token));
773
+ const observedTokens = message.body.match(/\b(?:INITIAL-PI-WAIT|CODEX-WAIT|CODEX-PI-FINAL)-[A-Z0-9]+\b/g) ?? [];
774
+ const observation = {
775
+ kind: "candidate",
776
+ file: message.file,
777
+ bytes: Buffer.byteLength(message.body),
778
+ sha256: createHash("sha256").update(message.body).digest("hex"),
779
+ sender: parsed?.sender ?? null,
780
+ matchingTokens,
781
+ observedTokens,
782
+ bodyArtifact: path.basename(bodyFile),
783
+ };
784
+ fs.appendFileSync(path.join(evidenceDir, "mailbox-observations.jsonl"), `${JSON.stringify(observation)}\n`, {
785
+ mode: 0o600,
786
+ });
787
+ seenInbox.push(message.body);
788
+ }
789
+ };
790
+ const recordMailboxSelection = (phase: string, body: string, selected: boolean, reason: string): void => {
791
+ const parsed = parseMetaMailboxBody(body);
792
+ fs.appendFileSync(
793
+ path.join(evidenceDir, "mailbox-selections.jsonl"),
794
+ `${JSON.stringify({
795
+ phase,
796
+ sha256: createHash("sha256").update(body).digest("hex"),
797
+ sender: parsed?.sender ?? null,
798
+ selected,
799
+ reason,
800
+ })}\n`,
801
+ { mode: 0o600 },
802
+ );
803
+ };
804
+ const initialPiCallback = await awaitOrRecover("the initial Pi exact nonce callback", CALLBACK_WAIT_MS, () => {
805
+ drain();
806
+ const matching = mailboxCallbacks(seenInbox, initialPiNonce);
807
+ if (matching.length > 1) throw new Error(`duplicate exact initial Pi callbacks (${matching.length})`);
808
+ return matching[0] ?? null;
809
+ });
810
+ for (const body of seenInbox) {
811
+ recordMailboxSelection(
812
+ "initial-pi-callback",
813
+ body,
814
+ body === initialPiCallback.body,
815
+ body === initialPiCallback.body
816
+ ? "selected: exact outer frame, nonce, and sender"
817
+ : "excluded: not the exact callback",
818
+ );
819
+ }
820
+ receipts["4-initial-pi-callback"] = initialPiCallback.body;
821
+ const initialPiGid = initialPiCallback.sender;
822
+ ok(
823
+ "the initial Pi callback carries the exact launch nonce",
824
+ mailboxCallbacks([initialPiCallback.body], initialPiNonce).length === 1,
825
+ );
826
+ ok("the initial Pi callback sender envelope supplies its garden address", GARDEN_ID.test(initialPiGid));
827
+ const initialPiIdentity = readMetaIdentityByGardenId(initialPiGid);
828
+ ok("the initial caller callback resolves to a real Pi V3 citizen", initialPiIdentity.backend === "pi");
829
+ relatedRecordPaths.add(path.join(defaultMetaSessionsDir(), metaRecordFilename(initialPiIdentity)));
830
+ initialPiGardenId = initialPiGid;
831
+ initialPiTranscript = initialPiIdentity.transcriptPath ?? "";
832
+ if (initialPiTranscript !== "") relatedTranscripts.add(initialPiTranscript);
833
+ writeEvidenceManifest({
834
+ phase: "initial-pi-correlated",
835
+ initialPiGardenId: initialPiGid,
836
+ initialPiTranscript,
837
+ initialPiRecordPath: path.join(defaultMetaSessionsDir(), metaRecordFilename(initialPiIdentity)),
838
+ });
839
+
840
+ const codexWaitToken = `CODEX-WAIT-${Math.random().toString(36).slice(2, 10).toUpperCase()}`;
841
+ const finalToken = `CODEX-PI-FINAL-${Math.random().toString(36).slice(2, 10).toUpperCase()}`;
842
+ expectedReportTokens.push(finalToken);
843
+ const outboundPiTask = "After your automatic callback succeeds, answer ACK and stop. Do not open another sibling.";
844
+ const codexTask =
845
+ `After your required callback receipt, end the turn and wait passively for the addressed instruction containing ${codexWaitToken}. ` +
846
+ "Do not call shell, sleep, terminal, or any tool to wait.";
847
+ const codexInstruction = buildCodexInstruction({
848
+ waitToken: codexWaitToken,
849
+ finalToken,
850
+ callerGid,
851
+ piModel,
852
+ scratch,
853
+ });
854
+ const initialPiInstruction = buildInitialPiPhaseOne({
855
+ initialPiWaitToken,
856
+ codexWaitToken,
857
+ codexModel,
858
+ scratch,
859
+ codexInstruction,
860
+ });
861
+
862
+ // The model is asked to operate public tools, but every launch and delivery assertion below
863
+ // joins the harness's source-owned call arguments to its native result. Model reports are not
864
+ // coordinates and never enter the cleanup allowlist.
865
+ const instructInitialPi = await bridge.call("entwurf_v2", {
866
+ target: initialPiGid,
867
+ intent: "fire-and-forget",
868
+ message: initialPiInstruction,
869
+ });
870
+ receipts["5-fixture-to-initial-pi-v2"] = instructInitialPi.text;
871
+ ok(
872
+ "the fixture addressed the real initial Pi caller through an actual control-socket entwurf_v2 receipt",
873
+ !instructInitialPi.isError &&
874
+ /control-socket/i.test(instructInitialPi.text) &&
875
+ /(?:sent|delivered)/i.test(instructInitialPi.text),
876
+ instructInitialPi.text,
877
+ );
878
+
879
+ const piFreshReceipt = await awaitOrRecover("the initial Pi source-owned Codex LAUNCH receipt", SOURCE_WAIT_MS, () =>
880
+ selectExactSourceToolReceipt(
881
+ piSourceToolReceipts(readInitialPiEntries()),
882
+ "entwurf_fresh_call",
883
+ { backend: "codex", model: codexModel, cwd: scratch, task: codexTask },
884
+ "initial Pi Codex fresh call",
885
+ ),
886
+ );
887
+ const codexLaunchReceipt = piFreshReceipt.text;
888
+ receipts["6-initial-pi-source-codex-launch"] = codexLaunchReceipt;
889
+ const codexNonce = /^\s*nonce:\s*(mux-fresh-call-[0-9a-f]+)/m.exec(codexLaunchReceipt)?.[1] ?? "";
890
+ codexLaunchNonce = codexNonce;
891
+ const codexReceiptCoordinate = /^\s*window:\s+(@\d+).*?\bin session (\$\d+)/m.exec(codexLaunchReceipt);
892
+ const codexWindow = codexReceiptCoordinate?.[1] ?? "";
893
+ const codexLaunchSession = codexReceiptCoordinate?.[2] ?? "";
894
+ ok(
895
+ "the initial Pi's joined source receipt names Codex and a stable cleanup handle",
896
+ WINDOW_ID.test(codexWindow) && /^\s*backend:\s+codex\b/m.test(codexLaunchReceipt),
897
+ );
898
+ if (!openedWindows.includes(codexWindow)) openedWindows.push(codexWindow);
899
+ ok("the source-owned Codex LAUNCH receipt carries its exact callback nonce", codexNonce.length > 0);
900
+ ok(
901
+ "omitted placement opened fresh Codex in exact named `codex` home, resolved to the app-server session",
902
+ codexLaunchSession === appServerCoordinate.sessionId &&
903
+ codexLaunchReceipt.includes(
904
+ `seat: ${CODEX_HOME_TMUX_SESSION} (Codex home tmux session, resolved to ${appServerCoordinate.sessionId})`,
905
+ ),
906
+ `codex=${codexLaunchSession} app-server=${appServerCoordinate.sessionId}`,
907
+ );
908
+ receipts["7-fresh-codex-coordinate"] = `session=${codexLaunchSession}\nwindow=${codexWindow}`;
909
+
910
+ const codexCallbackSender = await awaitOrRecover(
911
+ "the exact Codex callback in initial Pi source",
912
+ CALLBACK_WAIT_MS,
913
+ () => {
914
+ const senders = piCallbackSenders(readInitialPiEntries(), codexNonce);
915
+ if (senders.length > 1) throw new Error(`duplicate exact Codex callbacks (${senders.length})`);
916
+ return senders[0] ?? null;
917
+ },
918
+ );
919
+ ok("the Codex callback sender envelope supplies its garden address", GARDEN_ID.test(codexCallbackSender));
920
+ const codexIdentity = readMetaIdentityByGardenId(codexCallbackSender);
921
+ ok("the callback-derived citizen resolves to a real Codex V3 citizen", codexIdentity.backend === "codex");
922
+ codexGardenId = codexCallbackSender;
923
+ codexThreadId = codexIdentity.nativeSessionId;
924
+ relatedRecordPaths.add(path.join(defaultMetaSessionsDir(), metaRecordFilename(codexIdentity)));
925
+ if (codexIdentity.transcriptPath != null) relatedTranscripts.add(codexIdentity.transcriptPath);
926
+ writeEvidenceManifest({
927
+ phase: "codex-correlated",
928
+ codexGardenId,
929
+ codexThreadId,
930
+ codexRecordPath: path.join(defaultMetaSessionsDir(), metaRecordFilename(codexIdentity)),
931
+ });
932
+ receipts["8-initial-pi-source-codex-callback"] =
933
+ `nonce=${codexNonce}\ngarden=${codexGardenId}\nthread=${codexThreadId}`;
934
+
935
+ const initialPiToCodex = await awaitOrRecover("the initial Pi joined native-push receipt", SOURCE_WAIT_MS, () => {
936
+ const piSources = piSourceToolReceipts(readInitialPiEntries());
937
+ assertSourceCallScopes(piSources, "entwurf_v2", "target", [callerGid, codexGardenId], "initial Pi v2 roles");
938
+ return selectExactSourceToolReceipt(
939
+ piSources,
940
+ "entwurf_v2",
941
+ {
942
+ target: codexGardenId,
943
+ intent: "fire-and-forget",
944
+ wants_reply: false,
945
+ message: codexInstruction,
946
+ },
947
+ "initial Pi addressed Codex call",
948
+ );
949
+ });
950
+ ok(
951
+ "initial Pi -> Codex used an actual joined native-push entwurf_v2 receipt",
952
+ initialPiToCodex.text === "entwurf_v2 native-push → delivered",
953
+ initialPiToCodex.text,
954
+ );
955
+ receipts["9-initial-pi-source-native-push"] = initialPiToCodex.text;
956
+
957
+ let codexThread = await readCodexThread(codexSocketPath, codexThreadId, true);
958
+ writeEvidenceManifest({
959
+ phase: "codex-thread-read",
960
+ codexThreadPath: (codexThread as { path?: unknown }).path ?? null,
961
+ });
962
+ receipts["10-codex-live-thread-title"] =
963
+ `threadId=${codexThreadId}\nlive name=${JSON.stringify(codexThread.name)}\ngarden=${codexGardenId}`;
964
+ ok(
965
+ "the LIVE Codex thread's visible title IS its garden id (read back through the operator's app-server)",
966
+ codexThread.name === codexGardenId,
967
+ `thread/read name=${JSON.stringify(codexThread.name)} garden=${codexGardenId}`,
968
+ );
969
+ ok("the live thread the title was read from is the record's own thread", codexThread.id === codexThreadId);
970
+
971
+ const codexPiFreshReceipt = await untilAsync(
972
+ "the Codex thread source-owned outbound Pi LAUNCH receipt",
973
+ SOURCE_WAIT_MS,
974
+ async () => {
975
+ codexThread = await readCodexThread(codexSocketPath, codexThreadId, true);
976
+ return selectExactSourceToolReceipt(
977
+ codexSourceToolReceipts(codexThread),
978
+ "entwurf_fresh_call",
979
+ { backend: "pi", model: piModel, cwd: scratch, task: outboundPiTask },
980
+ "Codex outbound Pi fresh call",
981
+ );
982
+ },
983
+ );
984
+ const outboundPiReceipt = codexPiFreshReceipt.text;
985
+ receipts["11-codex-source-outbound-pi-launch"] = outboundPiReceipt;
986
+ const outboundPiNonce = /^\s*nonce:\s*(mux-fresh-call-[0-9a-f]+)/m.exec(outboundPiReceipt)?.[1] ?? "";
987
+ const outboundPiReceiptCoordinate = /^\s*window:\s+(@\d+).*?\bin session (\$\d+)/m.exec(outboundPiReceipt);
988
+ const outboundPiWindow = outboundPiReceiptCoordinate?.[1] ?? "";
989
+ const outboundPiSession = outboundPiReceiptCoordinate?.[2] ?? "";
990
+ ok(
991
+ "the Codex thread's joined source receipt names Pi and a stable cleanup handle",
992
+ WINDOW_ID.test(outboundPiWindow) && /^\s*backend:\s+pi\b/m.test(outboundPiReceipt),
993
+ );
994
+ if (!openedWindows.includes(outboundPiWindow)) openedWindows.push(outboundPiWindow);
995
+ ok("the source-owned outbound Pi LAUNCH receipt carries its exact nonce", outboundPiNonce.length > 0);
996
+ ok(
997
+ "supported Codex-home topology: a Pi in another session opens Codex in exact home; Codex opens outbound Pi " +
998
+ "beside itself and the operator-owned app-server. This does not claim arbitrary attached-TUI seat inference",
999
+ initialPiTmuxSession !== appServerCoordinate.sessionId &&
1000
+ codexLaunchSession === appServerCoordinate.sessionId &&
1001
+ outboundPiSession === appServerCoordinate.sessionId,
1002
+ `initial-pi=${initialPiTmuxSession} codex=${codexLaunchSession} app-server=${appServerCoordinate.sessionId} outbound-pi=${outboundPiSession}`,
1003
+ );
1004
+ receipts["12-outbound-fresh-pi-coordinate"] = `session=${outboundPiSession}\nwindow=${outboundPiWindow}`;
1005
+
1006
+ const outboundPiGid = await untilAsync(
1007
+ "the exact outbound Pi callback in Codex source",
1008
+ CALLBACK_WAIT_MS,
1009
+ async () => {
1010
+ codexThread = await readCodexThread(codexSocketPath, codexThreadId, true);
1011
+ const senders = codexCallbackSenders(codexThread, outboundPiNonce);
1012
+ if (senders.length > 1) throw new Error(`duplicate exact outbound Pi callbacks (${senders.length})`);
1013
+ return senders[0] ?? null;
1014
+ },
1015
+ );
1016
+ ok(
1017
+ "the outbound fresh Pi callback names a new citizen, not the initial Pi or Codex",
1018
+ GARDEN_ID.test(outboundPiGid) && outboundPiGid !== initialPiGid && outboundPiGid !== codexGardenId,
1019
+ );
1020
+ const outboundPiIdentity = readMetaIdentityByGardenId(outboundPiGid);
1021
+ ok("the outbound Pi callback address resolves to a real Pi V3 citizen", outboundPiIdentity.backend === "pi");
1022
+ relatedRecordPaths.add(path.join(defaultMetaSessionsDir(), metaRecordFilename(outboundPiIdentity)));
1023
+ if (outboundPiIdentity.transcriptPath != null) relatedTranscripts.add(outboundPiIdentity.transcriptPath);
1024
+ writeEvidenceManifest({
1025
+ phase: "outbound-pi-correlated",
1026
+ outboundPiGardenId: outboundPiGid,
1027
+ outboundPiRecordPath: path.join(defaultMetaSessionsDir(), metaRecordFilename(outboundPiIdentity)),
1028
+ outboundPiTranscript: outboundPiIdentity.transcriptPath ?? null,
1029
+ });
1030
+ receipts["13-codex-source-outbound-pi-callback"] = `nonce=${outboundPiNonce}\ngarden=${outboundPiGid}`;
1031
+
1032
+ const expectedFinalMessage =
1033
+ `${finalToken}\nPI_LAUNCH_NONCE=${outboundPiNonce}\nPI_CALLBACK_NONCE=${outboundPiNonce}\n` +
1034
+ `PI_CALLBACK_FROM=${outboundPiGid}\nPI_SESSION_ID=${outboundPiSession}\nPI_WINDOW_ID=${outboundPiWindow}`;
1035
+ const codexFinalReceipt = await untilAsync("the Codex joined final mailbox receipt", SOURCE_WAIT_MS, async () => {
1036
+ codexThread = await readCodexThread(codexSocketPath, codexThreadId, true);
1037
+ const codexSources = codexSourceToolReceipts(codexThread);
1038
+ assertSourceCallScopes(codexSources, "entwurf_v2", "target", [initialPiGid, callerGid], "Codex v2 roles");
1039
+ return selectExactSourceToolReceipt(
1040
+ codexSources,
1041
+ "entwurf_v2",
1042
+ { target: callerGid, intent: "fire-and-forget", wants_reply: false, message: expectedFinalMessage },
1043
+ "Codex final fixture call",
1044
+ );
1045
+ });
1046
+ ok(
1047
+ "Codex -> fixture used an actual joined meta-mailbox entwurf_v2 receipt",
1048
+ /^entwurf_v2 meta-mailbox → enqueued \([^\n]+\.msg\)$/.test(codexFinalReceipt.text),
1049
+ codexFinalReceipt.text,
1050
+ );
1051
+ receipts["14-codex-source-final-mailbox"] = codexFinalReceipt.text;
1052
+
1053
+ const finalBody = await awaitOrRecover(
1054
+ "the fixture read Codex's final exact source message",
1055
+ CALLBACK_WAIT_MS,
1056
+ () => {
1057
+ drain();
1058
+ return selectReport(seenInbox, finalToken, codexGardenId);
1059
+ },
1060
+ );
1061
+ for (const body of seenInbox) {
1062
+ recordMailboxSelection(
1063
+ "codex-final-candidate",
1064
+ body,
1065
+ body === finalBody,
1066
+ body === finalBody
1067
+ ? "candidate selected: exact token and sender; body validation pending"
1068
+ : "candidate excluded: token or sender differs",
1069
+ );
1070
+ }
1071
+ receipts["15-fixture-read-codex-final"] = finalBody;
1072
+ const finalValidation = validateFinalMailboxBody(finalBody, codexGardenId, expectedFinalMessage);
1073
+ recordMailboxSelection("codex-final-validation", finalBody, finalValidation.accepted, finalValidation.reason);
1074
+ ok(
1075
+ "the fixture read one exact outer-framed final message from the same Codex citizen",
1076
+ finalValidation.parsed?.sender === codexGardenId,
1077
+ );
1078
+ ok(
1079
+ "the fixture mailbox payload exactly equals the source-validated Codex call argument",
1080
+ finalValidation.accepted,
1081
+ `expected=${JSON.stringify(expectedFinalMessage)}\nactual=${JSON.stringify(finalValidation.parsed?.payload)}`,
1082
+ );
1083
+
1084
+ // Final audit closes the race left by polling a completed subset. Codex's final tool result can
1085
+ // precede turn completion, so wait for the app-server's own terminal turn state before recounting.
1086
+ codexThread = await untilAsync("the Codex final turn to become terminal", SOURCE_WAIT_MS, async () => {
1087
+ const observed = await readCodexThread(codexSocketPath, codexThreadId, true);
1088
+ return codexThreadIsTerminal(observed) ? observed : null;
1089
+ });
1090
+ assertExactSourceToolCalls(
1091
+ piSourceToolReceipts(readInitialPiEntries()),
1092
+ [
1093
+ {
1094
+ toolName: "entwurf_v2",
1095
+ arguments: {
1096
+ target: callerGid,
1097
+ intent: "fire-and-forget",
1098
+ message: initialPiNonce,
1099
+ wants_reply: false,
1100
+ },
1101
+ },
1102
+ {
1103
+ toolName: "entwurf_fresh_call",
1104
+ arguments: { backend: "codex", model: codexModel, cwd: scratch, task: codexTask },
1105
+ },
1106
+ {
1107
+ toolName: "entwurf_v2",
1108
+ arguments: {
1109
+ target: codexGardenId,
1110
+ intent: "fire-and-forget",
1111
+ wants_reply: false,
1112
+ message: codexInstruction,
1113
+ },
1114
+ },
1115
+ ],
1116
+ "initial Pi final exact-once audit",
1117
+ );
1118
+ assertExactSourceToolCalls(
1119
+ codexSourceToolReceipts(codexThread),
1120
+ [
1121
+ {
1122
+ toolName: "entwurf_v2",
1123
+ arguments: {
1124
+ target: initialPiGid,
1125
+ intent: "fire-and-forget",
1126
+ wants_reply: false,
1127
+ message: codexNonce,
1128
+ },
1129
+ },
1130
+ {
1131
+ toolName: "entwurf_fresh_call",
1132
+ arguments: { backend: "pi", model: piModel, cwd: scratch, task: outboundPiTask },
1133
+ },
1134
+ {
1135
+ toolName: "entwurf_v2",
1136
+ arguments: {
1137
+ target: callerGid,
1138
+ intent: "fire-and-forget",
1139
+ wants_reply: false,
1140
+ message: expectedFinalMessage,
1141
+ },
1142
+ },
1143
+ ],
1144
+ "Codex final exact-once audit",
1145
+ );
1146
+ receipts["16-source-final-audit"] = "initial-pi=3/3 completed exact\ncodex=3/3 completed exact";
1147
+ }
1148
+
1149
+ let failure: unknown = null;
1150
+ try {
1151
+ await run();
1152
+ } catch (error) {
1153
+ failure = error;
1154
+ }
1155
+ // Cleanup authority runs on EVERY exit, not only on a wait that timed out. Only joined source
1156
+ // fresh-call receipts may add stable handles to the allowlist; mailbox prose is preserved as
1157
+ // diagnostic evidence but never authorizes a kill. Every stage is attempted even when an earlier
1158
+ // stage throws. A mandatory snapshot is copied after source recovery and before any destructive
1159
+ // turn/window/fixture cleanup, so cleanup-only failures cannot erase their own evidence.
1160
+ const cleanupFailures = await runCleanupStages([
1161
+ { label: "bridge", run: closeBridge },
1162
+ { label: "recovery", run: recoverEveryRecordedWindow },
1163
+ {
1164
+ label: "evidence",
1165
+ run: () => preservePreCleanupEvidence(failure ?? "run succeeded; mandatory pre-cleanup evidence checkpoint"),
1166
+ },
1167
+ { label: "codex-turn", run: interruptCodexSmokeTurn },
1168
+ { label: "window", run: cleanupWindows },
1169
+ { label: "fixture", run: cleanupFixture },
1170
+ ]);
1171
+ printReceipts();
1172
+ if (cleanupFailures.length > 0) {
1173
+ const cleanupError =
1174
+ `[${LABEL}] CLEANUP FAILURE — only the exact smoke-owned Codex turn, recorded stable window ids, and exact fixture artifacts were targeted:\n` +
1175
+ cleanupFailures.join("\n");
1176
+ console.error(cleanupError);
1177
+ failure = failure === null ? new Error(cleanupError) : new Error(`${String(failure)}\n${cleanupError}`);
1178
+ }
1179
+ if (failure !== null) {
1180
+ console.error(`[${LABEL}] FAIL: ${failure instanceof Error ? failure.message : String(failure)}`);
1181
+ process.exitCode = 1;
1182
+ } else {
1183
+ console.log(
1184
+ `[${LABEL}] ${passed} assertions ok — fixture -> initial visible Pi -> visible Codex/exact callback -> Pi-addressed native-push v2 -> Codex outbound v2 -> visible Pi/exact callback`,
1185
+ );
1186
+ }