@junghanacs/entwurf 0.20.1 → 0.22.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 (111) hide show
  1. package/AGENTS.md +85 -190
  2. package/BASELINE.md +6 -3
  3. package/CHANGELOG.md +473 -14
  4. package/CONTRIBUTING.md +1 -1
  5. package/DELIVERY.md +332 -60
  6. package/README.md +100 -22
  7. package/VERIFY.md +93 -7
  8. package/docs/acp-backend-rail.md +0 -1
  9. package/docs/external-mcp-host.md +64 -33
  10. package/docs/setup-clean-host.md +151 -17
  11. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +130 -114
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-caller-seat.js +174 -0
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-fresh-preflight.js +519 -0
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-fact-provider.js +22 -2
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-peers-render.js +3 -1
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +6 -7
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-native-push.js +30 -17
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-production.js +7 -1
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-runner.js +3 -2
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-send.js +8 -4
  21. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +7 -4
  22. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-mailbox-body.js +20 -11
  23. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +227 -1
  24. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +189 -19
  25. package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/adapter.js +10 -7
  26. package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/codex-ws-client.js +403 -0
  27. package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/register.js +4 -4
  28. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-hook-codex.js +325 -0
  29. package/mcp/entwurf-bridge/dist/scripts/codex-socket-path.js +30 -0
  30. package/mcp/entwurf-bridge/dist/scripts/meta-bridge-fresh-cut.js +6 -1
  31. package/mcp/entwurf-bridge/src/index.ts +154 -116
  32. package/mcp/entwurf-bridge/tsconfig.build.json +10 -0
  33. package/package.json +13 -4
  34. package/pi-extensions/entwurf-control.ts +71 -19
  35. package/pi-extensions/lib/codex-caller-seat.ts +204 -0
  36. package/pi-extensions/lib/codex-fresh-preflight.ts +580 -0
  37. package/pi-extensions/lib/compaction-send-guard.ts +80 -0
  38. package/pi-extensions/lib/entwurf-fact-provider.ts +29 -3
  39. package/pi-extensions/lib/entwurf-peers-render.ts +4 -1
  40. package/pi-extensions/lib/entwurf-v2-contract.ts +6 -7
  41. package/pi-extensions/lib/entwurf-v2-native-push.ts +35 -18
  42. package/pi-extensions/lib/entwurf-v2-production.ts +10 -3
  43. package/pi-extensions/lib/entwurf-v2-runner.ts +3 -2
  44. package/pi-extensions/lib/entwurf-v2-send.ts +16 -11
  45. package/pi-extensions/lib/entwurf-v2-surface.ts +7 -4
  46. package/pi-extensions/lib/meta-mailbox-body.ts +22 -13
  47. package/pi-extensions/lib/meta-sender-identity.ts +305 -0
  48. package/pi-extensions/lib/mux-fresh-call.ts +233 -29
  49. package/pi-extensions/lib/native-push/adapter.ts +21 -24
  50. package/pi-extensions/lib/native-push/codex-ws-client.ts +506 -0
  51. package/pi-extensions/lib/native-push/register.ts +7 -9
  52. package/pi-extensions/meta-bridge-hook-codex.ts +371 -0
  53. package/run.sh +342 -28
  54. package/scripts/check-agy-sender-identity.ts +1 -1
  55. package/scripts/check-codex-app-server-launch.ts +445 -0
  56. package/scripts/check-codex-birth-hook.ts +264 -0
  57. package/scripts/check-codex-bridge-identity.ts +179 -0
  58. package/scripts/check-codex-native-push.ts +386 -0
  59. package/scripts/check-codex-sender-identity.ts +495 -0
  60. package/scripts/check-compaction-send-guard.ts +130 -0
  61. package/scripts/check-copilot-receive-arm.ts +4 -1
  62. package/scripts/check-entwurf-fact-provider.ts +38 -0
  63. package/scripts/check-entwurf-peers-surface.ts +13 -1
  64. package/scripts/check-entwurf-self-address.ts +15 -16
  65. package/scripts/check-entwurf-v2-contract.ts +4 -3
  66. package/scripts/check-entwurf-v2-decider.ts +7 -5
  67. package/scripts/check-entwurf-v2-native-push.ts +35 -7
  68. package/scripts/check-entwurf-v2-production.ts +245 -12
  69. package/scripts/check-entwurf-v2-runner.ts +1 -1
  70. package/scripts/check-entwurf-v2-send.ts +26 -7
  71. package/scripts/check-entwurf-v2-surface.ts +1 -1
  72. package/scripts/check-gate-qualification.ts +8 -3
  73. package/scripts/check-harness-admission-parity.ts +0 -1
  74. package/scripts/check-mux-launch-tmux.ts +345 -4
  75. package/scripts/check-native-push-adapter.ts +20 -16
  76. package/scripts/check-native-push-register.ts +5 -1
  77. package/scripts/check-release-gate-outcomes.ts +47 -1
  78. package/scripts/check-setup-qualification.sh +3 -1
  79. package/scripts/codex-app-server-launch.sh +275 -0
  80. package/scripts/codex-birth-doctor.sh +276 -0
  81. package/scripts/codex-birth-install.sh +414 -0
  82. package/scripts/codex-birth-uninstall.sh +170 -0
  83. package/scripts/codex-mcp-config.py +435 -0
  84. package/scripts/codex-socket-path.ts +33 -0
  85. package/scripts/codex-statusline-config.py +434 -0
  86. package/scripts/codex-terminal-title-config.py +500 -0
  87. package/scripts/codex_toml_io.py +653 -0
  88. package/scripts/lib/codex-fresh-live-protocol.ts +121 -0
  89. package/scripts/lib/codex-fresh-source-receipts.ts +426 -0
  90. package/scripts/lib/launch-receipt-windows.ts +46 -0
  91. package/scripts/lib/tmux-coordinate-row.ts +58 -0
  92. package/scripts/meta-bridge-fresh-cut.ts +6 -1
  93. package/scripts/mutants/codex-app-server-launch.json +157 -0
  94. package/scripts/mutants/codex-caller-seat.json +336 -0
  95. package/scripts/mutants/codex-native.json +838 -0
  96. package/scripts/mutants/compaction-send-guard.json +103 -0
  97. package/scripts/mutants/entwurf-peers.json +19 -0
  98. package/scripts/mutants/mux-fresh-call.json +93 -10
  99. package/scripts/mutants/omp-fresh.json +6 -4
  100. package/scripts/mutants/release-gate.json +13 -0
  101. package/scripts/mutants/v2-surface.json +75 -1
  102. package/scripts/raw-async-delivery/README.md +2 -1
  103. package/scripts/raw-codex-measure/README.md +114 -46
  104. package/scripts/smoke-agy-native-push-live.ts +3 -1
  105. package/scripts/smoke-codex-birth.sh +347 -0
  106. package/scripts/smoke-codex-config-state.sh +700 -0
  107. package/scripts/smoke-codex-fresh-live.ts +1426 -0
  108. package/scripts/smoke-codex-native-push-live.ts +75 -0
  109. package/scripts/smoke-entwurf-chain-live.ts +50 -0
  110. package/scripts/smoke-setup-verdict.sh +125 -10
  111. package/scripts/tsconfig.json +1 -0
@@ -0,0 +1,838 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "codex-native",
4
+ "mutants": [
5
+ {
6
+ "claim": "CODEX-BRIDGE-REQUEST-IDENTITY",
7
+ "title": "the Codex MCP provenance label drifts from the vendor host label, leaving request metadata present but anonymous",
8
+ "subject": "pi-extensions/lib/meta-sender-identity.ts",
9
+ "find": ["export const CODEX_BRIDGE_PROVENANCE_LABEL = \"codex\";"],
10
+ "replace": ["export const CODEX_BRIDGE_PROVENANCE_LABEL = \"external-mcp/codex\";"],
11
+ "gate": ["bash", "run.sh", "check-codex-bridge-identity"],
12
+ "timeoutSeconds": 120,
13
+ "signature": "[QK:CODEX-BRIDGE-REQUEST-IDENTITY]",
14
+ "signatureSource": "scripts/check-codex-bridge-identity.ts"
15
+ },
16
+ {
17
+ "claim": "CODEX-NATIVE-LOADED-PROBE",
18
+ "title": "the Codex app-server probe ignores a loaded target and reports the live thread dead",
19
+ "subject": "pi-extensions/lib/native-push/codex-ws-client.ts",
20
+ "find": [
21
+ "\t\t\tif (result.data.includes(nativeSessionId)) return { status: \"alive\", route: { backend: \"codex\", socketPath } };"
22
+ ],
23
+ "replace": [
24
+ "\t\t\tif (false && result.data.includes(nativeSessionId)) return { status: \"alive\", route: { backend: \"codex\", socketPath } };"
25
+ ],
26
+ "gate": ["bash", "run.sh", "check-codex-native-push"],
27
+ "timeoutSeconds": 120,
28
+ "signature": "[QK:CODEX-NATIVE-LOADED-PROBE]",
29
+ "signatureSource": "scripts/check-codex-native-push.ts"
30
+ },
31
+ {
32
+ "claim": "CODEX-NATIVE-VENDOR-QUEUE",
33
+ "title": "native delivery invokes a different Codex subcommand instead of the measured one-shot queue surface",
34
+ "subject": "pi-extensions/lib/native-push/codex-ws-client.ts",
35
+ "find": [
36
+ "\t\t[\"codex\", \"queue\", \"--remote\", `unix://${route.socketPath}`, \"--thread\", nativeSessionId, \"--message\", content],"
37
+ ],
38
+ "replace": [
39
+ "\t\t[\"codex\", \"exec\", \"--remote\", `unix://${route.socketPath}`, \"--thread\", nativeSessionId, \"--message\", content],"
40
+ ],
41
+ "gate": ["bash", "run.sh", "check-codex-native-push"],
42
+ "timeoutSeconds": 120,
43
+ "signature": "[QK:CODEX-NATIVE-VENDOR-QUEUE]",
44
+ "signatureSource": "scripts/check-codex-native-push.ts"
45
+ },
46
+ {
47
+ "claim": "FRESHCALL-CODEX-ARGV",
48
+ "title": "Codex fresh launch drops the remote app-server attachment flag and opens an unrelated local session",
49
+ "subject": "pi-extensions/lib/mux-fresh-call.ts",
50
+ "find": ["\t\t\t\t\"--remote\","],
51
+ "replace": ["\t\t\t\t\"--resume\","],
52
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
53
+ "timeoutSeconds": 180,
54
+ "signature": "[QK:FRESHCALL-CODEX-ARGV]",
55
+ "signatureSource": "test/mux-fresh-call.test.ts"
56
+ },
57
+ {
58
+ "claim": "CODEX-BIRTH-MINTS-CODEX",
59
+ "title": "the Codex SessionStart hook writes a record into another backend domain",
60
+ "subject": "pi-extensions/meta-bridge-hook-codex.ts",
61
+ "find": ["\t\t\tbackend: \"codex\","],
62
+ "replace": ["\t\t\tbackend: \"omp\","],
63
+ "gate": ["bash", "run.sh", "check-codex-birth-hook"],
64
+ "timeoutSeconds": 180,
65
+ "signature": "[QK:CODEX-BIRTH-MINTS-CODEX]",
66
+ "signatureSource": "scripts/check-codex-birth-hook.ts"
67
+ },
68
+ {
69
+ "claim": "CODEX-NATIVE-PRODUCTION-WIRING",
70
+ "title": "the native-push backend set drops Codex, so production routes a live app-server citizen to no delivery rail",
71
+ "subject": "pi-extensions/lib/entwurf-v2-contract.ts",
72
+ "find": ["export const NATIVE_PUSH_BACKENDS = [\"antigravity\", \"codex\"] as const;"],
73
+ "replace": ["export const NATIVE_PUSH_BACKENDS = [\"antigravity\"] as const;"],
74
+ "gate": ["bash", "run.sh", "check-entwurf-v2-production"],
75
+ "timeoutSeconds": 120,
76
+ "signature": "[QK:CODEX-NATIVE-PRODUCTION-WIRING]",
77
+ "signatureSource": "scripts/check-entwurf-v2-production.ts"
78
+ },
79
+ {
80
+ "claim": "CODEX-NATIVE-NO-RETRY",
81
+ "title": "Codex queue delivery is marked retriable, so an accepted message may be replayed after its receipt is lost",
82
+ "subject": "pi-extensions/lib/native-push/codex-ws-client.ts",
83
+ "find": ["\t\tretriable: false,"],
84
+ "replace": ["\t\tretriable: true,"],
85
+ "gate": ["bash", "run.sh", "check-codex-native-push"],
86
+ "timeoutSeconds": 120,
87
+ "signature": "[QK:CODEX-NATIVE-NO-RETRY]",
88
+ "signatureSource": "scripts/check-codex-native-push.ts"
89
+ },
90
+ {
91
+ "claim": "CODEX-BIRTH-REQUIRES-MODEL",
92
+ "title": "the Codex birth reader silently maps a missing measured model field to null",
93
+ "subject": "pi-extensions/meta-bridge-hook-codex.ts",
94
+ "find": ["\tif (!(\"model\" in env)) {"],
95
+ "replace": ["\tif (false && !(\"model\" in env)) {"],
96
+ "gate": ["bash", "run.sh", "check-codex-birth-hook"],
97
+ "timeoutSeconds": 180,
98
+ "signature": "[QK:CODEX-BIRTH-REQUIRES-MODEL]",
99
+ "signatureSource": "scripts/check-codex-birth-hook.ts"
100
+ },
101
+ {
102
+ "claim": "FRESHCALL-CODEX-MCP-EXACT",
103
+ "title": "fresh preflight accepts extra keys in the managed Codex MCP table",
104
+ "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
105
+ "find": ["\tif (Object.keys(server).sort().join(\",\") !== \"command,env,env_vars\") return true;"],
106
+ "replace": ["\tif (false) return true;"],
107
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
108
+ "timeoutSeconds": 120,
109
+ "signature": "[QK:FRESHCALL-CODEX-MCP-EXACT]",
110
+ "signatureSource": "test/codex-fresh-preflight.test.ts"
111
+ },
112
+ {
113
+ "claim": "CODEX-MCP-UNINSTALL-REFUSES-DRIFT",
114
+ "title": "the Codex MCP inverse restores its preimage over operator-modified managed-table bytes",
115
+ "subject": "scripts/codex-mcp-config.py",
116
+ "find": [" if entry != expected:"],
117
+ "replace": [" if False and entry != expected:"],
118
+ "gate": ["bash", "run.sh", "smoke-codex-config-state"],
119
+ "timeoutSeconds": 120,
120
+ "signature": "[QK:CODEX-MCP-UNINSTALL-REFUSES-DRIFT]",
121
+ "signatureSource": "scripts/smoke-codex-config-state.sh"
122
+ },
123
+ {
124
+ "claim": "CODEX-SETUP-ZERO-STATE",
125
+ "title": "setup ignores the explicit absent-Codex seam and enters the detected harness branch, so a harness-free package consumer is no longer zero-write",
126
+ "subject": "run.sh",
127
+ "find": [" if ! command -v \"${CODEX_BIN:-codex}\" >/dev/null 2>&1; then"],
128
+ "replace": [" if false; then"],
129
+ "gate": ["bash", "scripts/check-setup-qualification.sh"],
130
+ "timeoutSeconds": 180,
131
+ "signature": "[QK:CODEX-SETUP-ZERO-STATE]",
132
+ "signatureSource": "scripts/check-setup-qualification.sh"
133
+ },
134
+ {
135
+ "claim": "CODEX-NATIVE-WS-TERMINAL",
136
+ "title": "both redundant oversize-frame guards on the 127-length WebSocket path are disabled, so a frame declaring an unbounded length is treated as merely incomplete and the parser waits forever for bytes that will never arrive instead of terminating the connection",
137
+ "subject": "pi-extensions/lib/native-push/codex-ws-client.ts",
138
+ "find": [
139
+ "\t\t\tif (wide > BigInt(MAX_MESSAGE_BYTES)) return this.protocolFailure(\"WebSocket frame exceeds 1 MiB\");",
140
+ "\t\t\tlength = Number(wide);",
141
+ "\t\t\toffset = 10;",
142
+ "\t\t}",
143
+ "\t\tif (length > MAX_MESSAGE_BYTES) return this.protocolFailure(\"WebSocket frame exceeds 1 MiB\");"
144
+ ],
145
+ "replace": [
146
+ "\t\t\tif (false) return this.protocolFailure(\"WebSocket frame exceeds 1 MiB\");",
147
+ "\t\t\tlength = Number(wide);",
148
+ "\t\t\toffset = 10;",
149
+ "\t\t}",
150
+ "\t\tif (false) return this.protocolFailure(\"WebSocket frame exceeds 1 MiB\");"
151
+ ],
152
+ "gate": ["bash", "run.sh", "check-codex-native-push"],
153
+ "timeoutSeconds": 120,
154
+ "signature": "[QK:CODEX-NATIVE-WS-TERMINAL]",
155
+ "signatureSource": "scripts/check-codex-native-push.ts"
156
+ },
157
+ {
158
+ "claim": "FRESHCALL-CODEX-MCP-ENV-ORDER",
159
+ "title": "fresh preflight accepts the managed Codex MCP env_vars in any order, as long as the set matches — a reordered vendor-visible env manifest passes as exact",
160
+ "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
161
+ "find": ["\t\tenvVars.some((name, index) => name !== CODEX_MCP_ENV_VARS[index])"],
162
+ "replace": [
163
+ "\t\tenvVars.some((name) => !CODEX_MCP_ENV_VARS.includes(name as (typeof CODEX_MCP_ENV_VARS)[number]))"
164
+ ],
165
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
166
+ "timeoutSeconds": 120,
167
+ "signature": "[QK:FRESHCALL-CODEX-MCP-ENV-ORDER]",
168
+ "signatureSource": "test/codex-fresh-preflight.test.ts"
169
+ },
170
+ {
171
+ "claim": "FRESHCALL-CODEX-HOOKS-SAFE",
172
+ "title": "fresh preflight stops checking the operator-owned hooks.json for unsafe ownership/permissions/symlinks, so a world-writable or symlinked hooks.json is treated as a safe published birth unit",
173
+ "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
174
+ "find": ["\tif (!isSafeOwnedFile(paths.hooksFile, expectedUid)) return true;"],
175
+ "replace": ["\tif (false) return true;"],
176
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
177
+ "timeoutSeconds": 120,
178
+ "signature": "[QK:FRESHCALL-CODEX-HOOKS-SAFE]",
179
+ "signatureSource": "test/codex-fresh-preflight.test.ts"
180
+ },
181
+ {
182
+ "claim": "CODEX-SETUP-BIRTH-COSMETIC-PASS",
183
+ "title": "setup swallows the birth doctor's verdict, so an untrusted unit reads as a cosmetic PASS",
184
+ "subject": "run.sh",
185
+ "find": [" codex_rc=0; (cd \"$REPO_DIR\" && bash scripts/codex-birth-doctor.sh) >/dev/null || codex_rc=$?"],
186
+ "replace": [" codex_rc=0; (cd \"$REPO_DIR\" && bash scripts/codex-birth-doctor.sh) >/dev/null || true"],
187
+ "gate": ["bash", "run.sh", "smoke-setup-verdict"],
188
+ "timeoutSeconds": 600,
189
+ "signature": "[QK:CODEX-SETUP-BIRTH-COSMETIC-PASS]",
190
+ "signatureSource": "scripts/smoke-setup-verdict.sh"
191
+ },
192
+ {
193
+ "claim": "CODEX-SETUP-BIRTH-INDEPENDENT",
194
+ "title": "an untrusted birth unit aborts the whole Codex composition, so the two config atoms never get their independent outcome",
195
+ "subject": "run.sh",
196
+ "find": [
197
+ " else\n setup_result codex-birth FAIL \"the birth unit is published, but the vendor has recorded no trust receipt for it yet, so the hook is declared and never runs. Open a visible plain Codex, answer its prompt with 'Trust all and continue', send one first turn, then re-run setup (or './run.sh doctor-codex-birth')\"\n fi"
198
+ ],
199
+ "replace": [
200
+ " else\n setup_result codex-birth FAIL \"the birth unit is published, but the vendor has recorded no trust receipt for it yet\"\n return 1\n fi"
201
+ ],
202
+ "gate": ["bash", "run.sh", "smoke-setup-verdict"],
203
+ "timeoutSeconds": 600,
204
+ "signature": "[QK:CODEX-SETUP-BIRTH-INDEPENDENT]",
205
+ "signatureSource": "scripts/smoke-setup-verdict.sh"
206
+ },
207
+ {
208
+ "claim": "FRESHCALL-CODEX-APP-SERVER-LIVE",
209
+ "title": "fresh preflight reports the app-server ready on the inode check alone, so a stale socket file no live process answers passes and the visible launch dies afterwards",
210
+ "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
211
+ "find": ["\treturn live ? null : \"codex-app-server-unavailable\";"],
212
+ "replace": ["\treturn null;"],
213
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
214
+ "timeoutSeconds": 120,
215
+ "signature": "[QK:FRESHCALL-CODEX-APP-SERVER-LIVE]",
216
+ "signatureSource": "test/codex-fresh-preflight.test.ts"
217
+ },
218
+ {
219
+ "claim": "FRESHCALL-CODEX-HOOK-KEYS",
220
+ "title": "fresh preflight stops requiring the exact birth handler key set, so an async or extra-key hook — one the installer would never publish and one that lets the turn proceed before the record exists — reads as an installed birth unit",
221
+ "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
222
+ "find": ["\t\tif (Object.keys(hook).sort().join(\",\") !== \"command,timeout,type\") return true;"],
223
+ "replace": ["\t\tif (false) return true;"],
224
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
225
+ "timeoutSeconds": 120,
226
+ "signature": "[QK:FRESHCALL-CODEX-HOOK-KEYS]",
227
+ "signatureSource": "test/codex-fresh-preflight.test.ts"
228
+ },
229
+ {
230
+ "claim": "CODEX-TOML-STATE-BEFORE-CONFIG",
231
+ "title": "the MCP atom writes its config before its durable state receipt, so a state-write fault can no longer stop an already-mutated operator config",
232
+ "subject": "scripts/codex-mcp-config.py",
233
+ "find": [
234
+ " atomic_write_state(state_path, state)",
235
+ " # Strongest idempotence is an untouched file: same bytes, same mtime.",
236
+ " if candidate != (text if text is not None else \"\"):",
237
+ " atomic_write(config_path, candidate, prefix=\".codex-mcp-\")"
238
+ ],
239
+ "replace": [
240
+ " # mutant: config write reordered before state write",
241
+ " if candidate != (text if text is not None else \"\"):",
242
+ " atomic_write(config_path, candidate, prefix=\".codex-mcp-\")",
243
+ " atomic_write_state(state_path, state)"
244
+ ],
245
+ "gate": ["bash", "run.sh", "smoke-codex-config-state"],
246
+ "timeoutSeconds": 120,
247
+ "signature": "[QK:CODEX-TOML-STATE-BEFORE-CONFIG]",
248
+ "signatureSource": "scripts/smoke-codex-config-state.sh"
249
+ },
250
+ {
251
+ "claim": "CODEX-TOML-CONFIG-REPLACE-ROLLBACK",
252
+ "title": "the MCP atom's config write drops its fault-injection prefix, so an injected replace fault silently stops firing and a broken write reports success",
253
+ "subject": "scripts/codex-mcp-config.py",
254
+ "find": [
255
+ " if candidate != (text if text is not None else \"\"):",
256
+ " atomic_write(config_path, candidate, prefix=\".codex-mcp-\")"
257
+ ],
258
+ "replace": [
259
+ " if candidate != (text if text is not None else \"\"):",
260
+ " atomic_write(config_path, candidate)"
261
+ ],
262
+ "gate": ["bash", "run.sh", "smoke-codex-config-state"],
263
+ "timeoutSeconds": 120,
264
+ "signature": "[QK:CODEX-TOML-CONFIG-REPLACE-ROLLBACK]",
265
+ "signatureSource": "scripts/smoke-codex-config-state.sh"
266
+ },
267
+ {
268
+ "claim": "CODEX-TOML-FAMILY-EXCLUDES-SEPARATOR",
269
+ "title": "the managed table family swallows the blank separator before the next neighbour, so an idempotent reinstall deletes a byte the vendor wrote outside our atom",
270
+ "subject": "scripts/codex_toml_io.py",
271
+ "find": [" while end > start + 1 and lines[end - 1].strip() == \"\":"],
272
+ "replace": [" while False: # mutant: keep the trailing blank separator inside the family"],
273
+ "gate": ["bash", "run.sh", "smoke-codex-config-state"],
274
+ "timeoutSeconds": 120,
275
+ "signature": "[QK:CODEX-TOML-FAMILY-EXCLUDES-SEPARATOR]",
276
+ "signatureSource": "scripts/smoke-codex-config-state.sh"
277
+ },
278
+ {
279
+ "claim": "CODEX-MCP-RESHAPED-REFUSES-KEEPS-STATE",
280
+ "title": "the MCP inverse's reshaped-entry refusal is disabled, so a present-but-unlocatable owned entry is silently treated as genuinely gone",
281
+ "subject": "scripts/codex-mcp-config.py",
282
+ "find": [" elif entry is not None:"],
283
+ "replace": [" elif False: # mutant: reshaped-owned refusal disabled"],
284
+ "gate": ["bash", "run.sh", "smoke-codex-config-state"],
285
+ "timeoutSeconds": 120,
286
+ "signature": "[QK:CODEX-MCP-RESHAPED-REFUSES-KEEPS-STATE]",
287
+ "signatureSource": "scripts/smoke-codex-config-state.sh"
288
+ },
289
+ {
290
+ "claim": "CODEX-SL-GENUINELY-ABSENT-CLEARS-STATE",
291
+ "title": "the statusline inverse always treats a missing key as reshaped, so a genuinely absent thread-title membership refuses instead of clearing state",
292
+ "subject": "scripts/codex-statusline-config.py",
293
+ "find": [" if shape == \"has-key\" and REQUIRED_ITEM in value:"],
294
+ "replace": [" if True: # mutant: genuinely-absent path always refuses"],
295
+ "gate": ["bash", "run.sh", "smoke-codex-config-state"],
296
+ "timeoutSeconds": 120,
297
+ "signature": "[QK:CODEX-SL-GENUINELY-ABSENT-CLEARS-STATE]",
298
+ "signatureSource": "scripts/smoke-codex-config-state.sh"
299
+ },
300
+ {
301
+ "claim": "CODEX-SL-DOCTOR-REQUIRES-VISIBLE-IDENTITY",
302
+ "title": "the statusline doctor lets ownership rescue a missing required axis, so a host with no thread-title reports green as long as no receipt binds it",
303
+ "subject": "scripts/codex-statusline-config.py",
304
+ "find": [" if effective != \"thread-title-present\":"],
305
+ "replace": [
306
+ " if owned and effective != \"thread-title-present\": # mutant: unowned rescues the required axis"
307
+ ],
308
+ "gate": ["bash", "run.sh", "smoke-codex-config-state"],
309
+ "timeoutSeconds": 120,
310
+ "signature": "[QK:CODEX-SL-DOCTOR-REQUIRES-VISIBLE-IDENTITY]",
311
+ "signatureSource": "scripts/smoke-codex-config-state.sh"
312
+ },
313
+ {
314
+ "claim": "CODEX-BIRTH-FOREIGN-HOOKS-REFUSED",
315
+ "title": "the user-layer birth unit stops refusing a hooks.json no ownership state vouches for, so a declaration somebody else wrote is treated as one of ours",
316
+ "subject": "scripts/codex-birth-install.sh",
317
+ "find": [" if [ \"$STATE_PRESENT\" = \"0\" ]; then"],
318
+ "replace": [" if false; then # mutant: treat a foreign hooks.json as ours"],
319
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
320
+ "timeoutSeconds": 120,
321
+ "signature": "[QK:CODEX-BIRTH-FOREIGN-HOOKS-REFUSED]",
322
+ "signatureSource": "scripts/smoke-codex-birth.sh"
323
+ },
324
+ {
325
+ "claim": "CODEX-BIRTH-REINSTALL-REFUSES-CLOSURE-DRIFT",
326
+ "title": "reinstall stops licensing the live closure by digest, so publishing a new generation copies over an operator's edited helper member and destroys the only copy of it",
327
+ "subject": "scripts/codex-birth-install.sh",
328
+ "find": [" if [ \"$MEMBER_LIVE\" != \"$want\" ]; then"],
329
+ "replace": [" if false; then # mutant: republish over a drifted closure member"],
330
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
331
+ "timeoutSeconds": 120,
332
+ "signature": "[QK:CODEX-BIRTH-REINSTALL-REFUSES-CLOSURE-DRIFT]",
333
+ "signatureSource": "scripts/smoke-codex-birth.sh"
334
+ },
335
+ {
336
+ "claim": "CODEX-THREAD-READ-DIALECT",
337
+ "title": "the visible-title read-back sends the thread id under a name the vendor app-server does not accept, so first-admission LIVE is the first place the dialect is tried",
338
+ "subject": "pi-extensions/lib/native-push/codex-ws-client.ts",
339
+ "find": ["\t\tconst result = (await protocol.request(\"thread/read\", { threadId, includeTurns })) as {"],
340
+ "replace": [
341
+ "\t\tconst result = (await protocol.request(\"thread/read\", { thread_id: threadId, includeTurns })) as {"
342
+ ],
343
+ "gate": ["bash", "run.sh", "check-codex-native-push"],
344
+ "timeoutSeconds": 120,
345
+ "signature": "[QK:CODEX-THREAD-READ-DIALECT]",
346
+ "signatureSource": "scripts/check-codex-native-push.ts"
347
+ },
348
+ {
349
+ "claim": "CODEX-THREAD-READ-REFUSES-MALFORMED",
350
+ "title": "a thread/read reply carrying no thread object is read as a thread with no title, so a broken read becomes an empty visible title instead of a refusal",
351
+ "subject": "pi-extensions/lib/native-push/codex-ws-client.ts",
352
+ "find": ["\t\tif (thread == null || typeof thread !== \"object\" || Array.isArray(thread)) {"],
353
+ "replace": ["\t\tif (false) {"],
354
+ "gate": ["bash", "run.sh", "check-codex-native-push"],
355
+ "timeoutSeconds": 120,
356
+ "signature": "[QK:CODEX-THREAD-READ-REFUSES-MALFORMED]",
357
+ "signatureSource": "scripts/check-codex-native-push.ts"
358
+ },
359
+ {
360
+ "claim": "CODEX-ORPHAN-WINDOW-RECOVERY",
361
+ "title": "the orphan-window parser reinstates an arbitrary length bound, so a receipt carrying a real project cwd and a seat recovers nothing",
362
+ "subject": "scripts/lib/launch-receipt-windows.ts",
363
+ "find": ["\tfor (const line of text.split(LINE)) {"],
364
+ "replace": ["\tfor (const line of text.slice(0, 300).split(LINE)) {"],
365
+ "gate": ["bash", "run.sh", "check-codex-native-push"],
366
+ "timeoutSeconds": 120,
367
+ "signature": "[QK:CODEX-ORPHAN-WINDOW-RECOVERY]",
368
+ "signatureSource": "scripts/check-codex-native-push.ts"
369
+ },
370
+ {
371
+ "claim": "FRESHCALL-CODEX-APP-SERVER-NO-LEAK",
372
+ "title": "an app-server connection that opens after the preflight bound expired is left open, leaking a live socket into the host for the rest of the process",
373
+ "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
374
+ "find": ["\t\t\t\t\tlate.close();"],
375
+ "replace": ["\t\t\t\t\tvoid late;"],
376
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
377
+ "timeoutSeconds": 120,
378
+ "signature": "[QK:FRESHCALL-CODEX-APP-SERVER-NO-LEAK]",
379
+ "signatureSource": "test/codex-fresh-preflight.test.ts"
380
+ },
381
+ {
382
+ "claim": "FRESHCALL-CODEX-PREMUTATION-MCP",
383
+ "title": "the MCP surface stops asking the Codex TARGET capability question before placement, so a host with no birth unit, no vendor trust receipt, no MCP hand or no app-server reaches tmux first — a window opens, and the operator is told about the missing capability only after something visible already exists",
384
+ "subject": "mcp/entwurf-bridge/src/index.ts",
385
+ "find": ["\t\t\tconst targetMissing = backend === \"codex\" ? await codexFreshPreflight(process.env) : null;"],
386
+ "replace": ["\t\t\tconst targetMissing = null;"],
387
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
388
+ "timeoutSeconds": 180,
389
+ "signature": "[QK:FRESHCALL-CODEX-PREMUTATION-MCP]",
390
+ "signatureSource": "test/fresh-call-surfaces.contract.test.ts"
391
+ },
392
+ {
393
+ "claim": "FRESHCALL-CODEX-PREMUTATION-PI",
394
+ "title": "the native pi public surface stops running the Codex capability preflight, so the same window opens from the other public door",
395
+ "subject": "pi-extensions/entwurf-control.ts",
396
+ "find": ["\t\t\t\t\tparams.backend === \"codex\""],
397
+ "replace": ["\t\t\t\t\tfalse"],
398
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
399
+ "timeoutSeconds": 180,
400
+ "signature": "[QK:FRESHCALL-CODEX-PREMUTATION-PI]",
401
+ "signatureSource": "test/fresh-call-surfaces.contract.test.ts"
402
+ },
403
+ {
404
+ "claim": "CODEX-BIRTH-DOCTOR-REQUIRES-TRUST",
405
+ "title": "the doctor treats the vendor trust receipt as optional, so a declared hook the vendor will never run reports green",
406
+ "subject": "scripts/codex-birth-doctor.sh",
407
+ "find": [
408
+ "if [ \"$UNIT_ONLY\" = \"1\" ]; then\n info \"--unit-only: the vendor receipt was NOT read. This is a skipped axis, not a green one.\""
409
+ ],
410
+ "replace": [
411
+ "if [ \"$UNIT_ONLY\" = \"1\" ] || true; then # mutant: never read the vendor receipt\n info \"--unit-only: the vendor receipt was NOT read. This is a skipped axis, not a green one.\""
412
+ ],
413
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
414
+ "timeoutSeconds": 120,
415
+ "signature": "[QK:CODEX-BIRTH-DOCTOR-REQUIRES-TRUST]",
416
+ "signatureSource": "scripts/smoke-codex-birth.sh"
417
+ },
418
+ {
419
+ "claim": "CODEX-SETUP-NEVER-PRESEEDS-TRUST",
420
+ "title": "setup answers the vendor's trust prompt on the operator's behalf by writing the receipt itself",
421
+ "subject": "run.sh",
422
+ "find": [" section \"codex units (native harness detected: OpenAI Codex CLI)\""],
423
+ "replace": [
424
+ " section \"codex units (native harness detected: OpenAI Codex CLI)\"\n printf '\\n[hooks.state.\"%s/hooks.json:session_start:0:0\"]\\ntrusted_hash = \"sha256:%064d\"\\n' \"$(_codex_home)\" 0 >> \"$(_codex_config)\" # mutant: forge the operator approval"
425
+ ],
426
+ "gate": ["bash", "run.sh", "smoke-setup-verdict"],
427
+ "timeoutSeconds": 300,
428
+ "signature": "[QK:CODEX-SETUP-NEVER-PRESEEDS-TRUST]",
429
+ "signatureSource": "scripts/smoke-setup-verdict.sh"
430
+ },
431
+ {
432
+ "claim": "CODEX-SETUP-TRUSTED-RERUN-GREEN",
433
+ "title": "setup can never report the Codex birth unit green, so an operator who has answered the vendor prompt still never gets a composed host",
434
+ "subject": "run.sh",
435
+ "find": [
436
+ " setup_harness_result codex-birth \"SessionStart birth unit published and trusted by the vendor\" \"./run.sh doctor-codex-birth\""
437
+ ],
438
+ "replace": [" setup_result codex-birth FAIL \"mutant: the trusted unit is never reported green\""],
439
+ "gate": ["bash", "run.sh", "smoke-setup-verdict"],
440
+ "timeoutSeconds": 300,
441
+ "signature": "[QK:CODEX-SETUP-TRUSTED-RERUN-GREEN]",
442
+ "signatureSource": "scripts/smoke-setup-verdict.sh"
443
+ },
444
+ {
445
+ "claim": "FRESHCALL-CODEX-TRUST-RECEIPT",
446
+ "title": "fresh preflight opens a Codex sibling whose birth hook the vendor never agreed to run",
447
+ "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
448
+ "find": [
449
+ "\tif (config === null || trustReceiptMissing(config, paths.hooksFile)) return \"codex-birth-trust-missing\";"
450
+ ],
451
+ "replace": ["\tif (config === null) return \"codex-birth-trust-missing\";"],
452
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
453
+ "timeoutSeconds": 180,
454
+ "signature": "[QK:FRESHCALL-CODEX-TRUST-RECEIPT]",
455
+ "signatureSource": "test/codex-fresh-preflight.test.ts"
456
+ },
457
+ {
458
+ "claim": "FRESHCALL-CODEX-STATE-DIGEST",
459
+ "title": "fresh preflight accepts a birth closure whose bytes no longer match the digests its own ownership state recorded",
460
+ "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
461
+ "find": ["\treturn closureDriftedFromState(paths, expectedUid);"],
462
+ "replace": ["\treturn false; // mutant: existence is enough"],
463
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
464
+ "timeoutSeconds": 180,
465
+ "signature": "[QK:FRESHCALL-CODEX-STATE-DIGEST]",
466
+ "signatureSource": "test/codex-fresh-preflight.test.ts"
467
+ },
468
+ {
469
+ "claim": "CODEX-BIRTH-DOCTOR-ABSENT-IS-RED",
470
+ "title": "the doctor calls a completely absent unit an informational note, so a host carrying a stale vendor receipt reports green with nothing installed",
471
+ "subject": "scripts/codex-birth-doctor.sh",
472
+ "find": [
473
+ " bad \"no Codex birth unit is installed here (no ownership state at $STATE_FILE, no declaration, no closure), so no Codex thread on this host can become a citizen."
474
+ ],
475
+ "replace": [
476
+ " info \"no Codex birth unit is installed here (no ownership state at $STATE_FILE, no declaration, no closure), so no Codex thread on this host can become a citizen."
477
+ ],
478
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
479
+ "timeoutSeconds": 180,
480
+ "signature": "[QK:CODEX-BIRTH-DOCTOR-ABSENT-IS-RED]",
481
+ "signatureSource": "scripts/smoke-codex-birth.sh"
482
+ },
483
+ {
484
+ "claim": "CODEX-BIRTH-INSTALL-SAFE-UMASK",
485
+ "title": "the installer lets an inherited umask decide the mode of the directories it creates, publishing a closure anyone on the host can rewrite between the digest and the exec",
486
+ "subject": "scripts/codex-birth-install.sh",
487
+ "find": ["umask 022"],
488
+ "replace": ["umask 000 # mutant: let the caller decide"],
489
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
490
+ "timeoutSeconds": 180,
491
+ "signature": "[QK:CODEX-BIRTH-INSTALL-SAFE-UMASK]",
492
+ "signatureSource": "scripts/smoke-codex-birth.sh"
493
+ },
494
+ {
495
+ "claim": "CODEX-BIRTH-EXACT-CLOSURE-INVENTORY",
496
+ "title": "the installer accepts an ownership state naming fewer closure members than it publishes, leaving files nothing compares and nothing can reclaim",
497
+ "subject": "scripts/codex-birth-install.sh",
498
+ "find": [" if (missing.length || extra.length || duplicate.length) {"],
499
+ "replace": [" if (false) { // mutant: any inventory will do"],
500
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
501
+ "timeoutSeconds": 180,
502
+ "signature": "[QK:CODEX-BIRTH-EXACT-CLOSURE-INVENTORY]",
503
+ "signatureSource": "scripts/smoke-codex-birth.sh"
504
+ },
505
+ {
506
+ "claim": "CODEX-BIRTH-REFUSES-RELATIVE-ROOT",
507
+ "title": "the installer accepts a relative CODEX_HOME, so the launcher path the vendor keys its trust receipt to depends on the caller's cwd",
508
+ "subject": "scripts/codex-birth-install.sh",
509
+ "find": ["case \"$CODEX_HOME\" in /*) : ;; *) die \"CODEX_HOME resolves to a relative path"],
510
+ "replace": ["case \"$CODEX_HOME\" in *) : ;; /*) die \"CODEX_HOME resolves to a relative path"],
511
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
512
+ "timeoutSeconds": 180,
513
+ "signature": "[QK:CODEX-BIRTH-REFUSES-RELATIVE-ROOT]",
514
+ "signatureSource": "scripts/smoke-codex-birth.sh"
515
+ },
516
+ {
517
+ "claim": "FRESHCALL-CODEX-EXACT-INVENTORY",
518
+ "title": "fresh preflight compares only the digests a state happens to name, so a short inventory hides an unchecked closure member",
519
+ "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
520
+ "find": [
521
+ "\tif (named.length !== expected.length) return true;\n\tif (expected.some((name) => !named.includes(name))) return true;\n\tif (named.some((name, index) => named.indexOf(name) !== index)) return true;"
522
+ ],
523
+ "replace": ["\t// mutant: judge only the members a state happens to name"],
524
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
525
+ "timeoutSeconds": 180,
526
+ "signature": "[QK:FRESHCALL-CODEX-EXACT-INVENTORY]",
527
+ "signatureSource": "test/codex-fresh-preflight.test.ts"
528
+ },
529
+ {
530
+ "claim": "CODEX-BIRTH-INSTALL-REFUSES-UNKNOWN-STATUS",
531
+ "title": "the installer adopts an ownership state in a status it never writes, so a receipt this unit did not produce can license its next publish",
532
+ "subject": "scripts/codex-birth-install.sh",
533
+ "find": [
534
+ " if (s.status !== \"installed\" && s.status !== \"publishing\") throw new Error(\"unknown state status \" + JSON.stringify(s.status));"
535
+ ],
536
+ "replace": [" // mutant: any status will do"],
537
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
538
+ "timeoutSeconds": 180,
539
+ "signature": "[QK:CODEX-BIRTH-INSTALL-REFUSES-UNKNOWN-STATUS]",
540
+ "signatureSource": "scripts/smoke-codex-birth.sh"
541
+ },
542
+ {
543
+ "claim": "CODEX-BIRTH-STATE-PARENT-AUTHORITY",
544
+ "title": "the installer judges the ownership state without judging the directory that holds it, so a receipt anyone can replace still licenses the publish",
545
+ "subject": "scripts/codex-birth-install.sh",
546
+ "find": ["[ -e \"$UNIT_ROOT\" ] && safe_own_dir \"$UNIT_ROOT\" \"the unit root (it holds the ownership state)\""],
547
+ "replace": ["true # mutant: do not judge the directory holding the receipt"],
548
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
549
+ "timeoutSeconds": 180,
550
+ "signature": "[QK:CODEX-BIRTH-STATE-PARENT-AUTHORITY]",
551
+ "signatureSource": "scripts/smoke-codex-birth.sh"
552
+ },
553
+ {
554
+ "claim": "FRESHCALL-CODEX-STATE-PARENT-AUTHORITY",
555
+ "title": "fresh preflight trusts a digest inventory sitting in a directory anyone on the host can rewrite",
556
+ "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
557
+ "find": ["\tif (!isSafeOwnedDir(path.dirname(paths.stateFile), expectedUid)) return true;"],
558
+ "replace": ["\t// mutant: the directory holding the receipt is nobody's business"],
559
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
560
+ "timeoutSeconds": 180,
561
+ "signature": "[QK:FRESHCALL-CODEX-STATE-PARENT-AUTHORITY]",
562
+ "signatureSource": "test/codex-fresh-preflight.test.ts"
563
+ },
564
+ {
565
+ "claim": "TMUX-COORDINATE-FORMAT-PID",
566
+ "title": "the coordinate format asks tmux for a server-pid key that answers empty, so a metered LIVE fails at a field the format never filled",
567
+ "subject": "scripts/lib/tmux-coordinate-row.ts",
568
+ "find": ["export const TMUX_COORDINATE_FORMAT = \"#{pid}\\t#{session_id}\\t#{window_id}\\t#{pane_id}\";"],
569
+ "replace": [
570
+ "export const TMUX_COORDINATE_FORMAT = \"#{server_pid}\\t#{session_id}\\t#{window_id}\\t#{pane_id}\";"
571
+ ],
572
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
573
+ "timeoutSeconds": 180,
574
+ "signature": "[QK:TMUX-COORDINATE-FORMAT-PID]",
575
+ "signatureSource": "test/tmux-coordinate-row.test.ts"
576
+ },
577
+ {
578
+ "claim": "TMUX-COORDINATE-ROW-NO-SHIFT",
579
+ "title": "the positional row is trimmed instead of having exactly one terminal newline removed, so an empty leading field shifts every later coordinate one place left",
580
+ "subject": "scripts/lib/tmux-coordinate-row.ts",
581
+ "find": [
582
+ "\tlet line = raw;\n\tif (line.endsWith(\"\\r\\n\")) line = line.slice(0, -2);\n\telse if (line.endsWith(\"\\n\")) line = line.slice(0, -1);"
583
+ ],
584
+ "replace": ["\tconst line = raw.trim(); // mutant: reshape the row instead of removing one newline"],
585
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
586
+ "timeoutSeconds": 180,
587
+ "signature": "[QK:TMUX-COORDINATE-ROW-NO-SHIFT]",
588
+ "signatureSource": "test/tmux-coordinate-row.test.ts"
589
+ },
590
+ {
591
+ "claim": "CODEX-LIVE-CODEX-TASK-WAITS-INNER-TOKEN",
592
+ "title": "the fresh Codex task waits for the initial Pi trigger instead of the token that begins its own later addressed payload, so the public chain stalls after callback",
593
+ "subject": "scripts/lib/codex-fresh-live-protocol.ts",
594
+ "find": ["containing ${input.codexWaitToken}. ` +"],
595
+ "replace": ["containing ${input.initialPiWaitToken}. ` +"],
596
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
597
+ "timeoutSeconds": 180,
598
+ "signature": "[QK:CODEX-LIVE-CODEX-TASK-WAITS-INNER-TOKEN]",
599
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
600
+ },
601
+ {
602
+ "claim": "CODEX-LIVE-CLEANUP-FAILSAFE",
603
+ "title": "a thrown recovery aborts the teardown pipeline, so owned windows and fixture artifacts after it are never cleaned",
604
+ "subject": "scripts/lib/codex-fresh-live-protocol.ts",
605
+ "find": [
606
+ "\t\t\tfailures.push(`${stage.label}: threw: ${error instanceof Error ? error.message : String(error)}`);"
607
+ ],
608
+ "replace": ["\t\t\tthrow error; // mutant: an earlier cleanup failure aborts every later stage"],
609
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
610
+ "timeoutSeconds": 180,
611
+ "signature": "[QK:CODEX-LIVE-CLEANUP-FAILSAFE]",
612
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
613
+ },
614
+ {
615
+ "claim": "CODEX-LIVE-PHASE-SEPARATION",
616
+ "title": "the initial Pi is again asked to model-report a launch coordinate instead of leaving the forwarded Codex payload as its final source-observed action",
617
+ "subject": "scripts/lib/codex-fresh-live-protocol.ts",
618
+ "find": ["\t\t\"nobody else.\\n\" +"],
619
+ "replace": ["\t\t\"nobody else; then report PI-REPORTS-CODEX-LAUNCH to the fixture.\\n\" +"],
620
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
621
+ "timeoutSeconds": 180,
622
+ "signature": "[QK:CODEX-LIVE-PHASE-SEPARATION]",
623
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
624
+ },
625
+ {
626
+ "claim": "CODEX-LIVE-REPORT-SENDER-FILTER",
627
+ "title": "the final mailbox body is selected by token alone, so a body from the wrong sender can satisfy the fixture-read claim",
628
+ "subject": "scripts/lib/codex-fresh-live-protocol.ts",
629
+ "find": ["\t\tif (reportSender(body) !== expectedSender) continue;"],
630
+ "replace": ["\t\t// mutant: take the first exact-token body, whoever sent it"],
631
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
632
+ "timeoutSeconds": 180,
633
+ "signature": "[QK:CODEX-LIVE-REPORT-SENDER-FILTER]",
634
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
635
+ },
636
+ {
637
+ "claim": "CODEX-LIVE-REPORT-TOKEN-EXACT",
638
+ "title": "the final mailbox selector accepts a token missing its last character, recreating the 600-second model-truncation false wait",
639
+ "subject": "scripts/lib/codex-fresh-live-protocol.ts",
640
+ "find": ["\t\tif (!body.includes(token)) continue;"],
641
+ "replace": ["\t\tif (!body.includes(token.slice(0, -1))) continue; // mutant: fuzzy truncated token"],
642
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
643
+ "timeoutSeconds": 180,
644
+ "signature": "[QK:CODEX-LIVE-REPORT-TOKEN-EXACT]",
645
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
646
+ },
647
+ {
648
+ "claim": "CODEX-LIVE-SOURCE-JOIN",
649
+ "title": "a Pi tool result can be joined to a call whose tool name differs, turning an unrelated result body into launch authority",
650
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
651
+ "find": ["\t\tif (result.toolName !== call.toolName)"],
652
+ "replace": ["\t\tif (false && result.toolName !== call.toolName)"],
653
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
654
+ "timeoutSeconds": 180,
655
+ "signature": "[QK:CODEX-LIVE-SOURCE-JOIN]",
656
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
657
+ },
658
+ {
659
+ "claim": "CODEX-LIVE-SOURCE-JOIN-UNIQUE",
660
+ "title": "two source tool calls in the same backend or target scope are accepted instead of failing closed as ambiguous",
661
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
662
+ "find": [
663
+ "\tif (matchingScope.length > 1) throw new Error(`${label}: duplicate source tool calls (${matchingScope.length})`);"
664
+ ],
665
+ "replace": [
666
+ "\tif (false && matchingScope.length > 1) throw new Error(`${label}: duplicate source tool calls (${matchingScope.length})`);"
667
+ ],
668
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
669
+ "timeoutSeconds": 180,
670
+ "signature": "[QK:CODEX-LIVE-SOURCE-JOIN-UNIQUE]",
671
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
672
+ },
673
+ {
674
+ "claim": "CODEX-LIVE-SOURCE-ERROR-REJECT",
675
+ "title": "a Pi toolResult without explicit boolean isError=false is normalized into successful receipt authority",
676
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
677
+ "find": ["\t\t\tif (typeof message.isError !== \"boolean\")"],
678
+ "replace": ["\t\t\tif (false && typeof message.isError !== \"boolean\")"],
679
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
680
+ "timeoutSeconds": 180,
681
+ "signature": "[QK:CODEX-LIVE-SOURCE-ERROR-REJECT]",
682
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
683
+ },
684
+ {
685
+ "claim": "CODEX-LIVE-SOURCE-UNMATCHED-REJECT",
686
+ "title": "an unmatched Pi toolResult is silently accepted as a complete transcript",
687
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
688
+ "find": ["\t\tif (!calls.has(id)) throw new Error(`unmatched Pi toolResult id ${id}`);"],
689
+ "replace": ["\t\tif (false && !calls.has(id)) throw new Error(`unmatched Pi toolResult id ${id}`);"],
690
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
691
+ "timeoutSeconds": 180,
692
+ "signature": "[QK:CODEX-LIVE-SOURCE-UNMATCHED-REJECT]",
693
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
694
+ },
695
+ {
696
+ "claim": "CODEX-LIVE-RAW-CALLBACK-REQUIRED",
697
+ "title": "a Pi callback with arbitrary bytes after its sender envelope is accepted as exact",
698
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
699
+ "find": ["\tif (!text.startsWith(prefix) || !text.endsWith(suffix)) return null;"],
700
+ "replace": [
701
+ "\tif (!text.startsWith(prefix)) return null;\n\tconst suffixAt = text.indexOf(suffix, prefix.length);\n\tif (suffixAt < 0) return null;\n\ttext = text.slice(0, suffixAt + suffix.length); // mutant: discard callback suffix"
702
+ ],
703
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
704
+ "timeoutSeconds": 180,
705
+ "signature": "[QK:CODEX-LIVE-RAW-CALLBACK-REQUIRED]",
706
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
707
+ },
708
+ {
709
+ "claim": "CODEX-LIVE-OUTER-FRAME-EXACT",
710
+ "title": "mailbox parsing trims payload bytes and can approve a whitespace-different callback or final body",
711
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
712
+ "find": ["\treturn { sender: match[1] as string, payload: text.slice(match[0].length, -1) };"],
713
+ "replace": ["\treturn { sender: match[1] as string, payload: text.slice(match[0].length, -1).trim() };"],
714
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
715
+ "timeoutSeconds": 180,
716
+ "signature": "[QK:CODEX-LIVE-OUTER-FRAME-EXACT]",
717
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
718
+ },
719
+ {
720
+ "claim": "CODEX-LIVE-JSONL-COMPLETE-ERROR",
721
+ "title": "a corrupt complete Pi JSONL row is misclassified as a partial final append and hidden until timeout",
722
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
723
+ "find": ["\t\t\tif (isIncompleteLastAppend) return entries;"],
724
+ "replace": ["\t\t\tif (true) return entries; // mutant: hide every parse error as a partial append"],
725
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
726
+ "timeoutSeconds": 180,
727
+ "signature": "[QK:CODEX-LIVE-JSONL-COMPLETE-ERROR]",
728
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
729
+ },
730
+ {
731
+ "claim": "CODEX-LIVE-CODEX-PENDING",
732
+ "title": "Codex inProgress MCP state is treated as terminal instead of remaining pending until thread_history completes it",
733
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
734
+ "find": ["\t\t\tif (item.status === \"inProgress\") {"],
735
+ "replace": ["\t\t\tif (false && item.status === \"inProgress\") {"],
736
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
737
+ "timeoutSeconds": 180,
738
+ "signature": "[QK:CODEX-LIVE-CODEX-PENDING]",
739
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
740
+ },
741
+ {
742
+ "claim": "CODEX-LIVE-CODEX-SOURCE",
743
+ "title": "a non-Entwurf Codex MCP item is admitted as source tool authority",
744
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
745
+ "find": ["\t\t\tif (item.type !== \"mcpToolCall\" || item.server !== \"entwurf-bridge\") continue;"],
746
+ "replace": ["\t\t\tif (item.type !== \"mcpToolCall\") continue; // mutant: any MCP server"],
747
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
748
+ "timeoutSeconds": 180,
749
+ "signature": "[QK:CODEX-LIVE-CODEX-SOURCE]",
750
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
751
+ },
752
+ {
753
+ "claim": "CODEX-LIVE-SOURCE-ROLE-AUDIT",
754
+ "title": "the final exact-once source audit is bypassed, allowing late duplicate or wrong-axis calls to disappear after an earlier selection",
755
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
756
+ "find": ["\tif (receipts.length !== expected.length)"],
757
+ "replace": [
758
+ "\tif (true) return; // mutant: bypass the final source-role audit\n\tif (receipts.length !== expected.length)"
759
+ ],
760
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
761
+ "timeoutSeconds": 180,
762
+ "signature": "[QK:CODEX-LIVE-SOURCE-ROLE-AUDIT]",
763
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
764
+ },
765
+ {
766
+ "claim": "CODEX-LIVE-TURN-TERMINAL-EXACT",
767
+ "title": "a missing or future Codex turn status is accepted as terminal completion",
768
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
769
+ "find": ["\t\tif (status !== \"completed\") throw new Error(`unknown Codex turn status ${String(status)}`);"],
770
+ "replace": [
771
+ "\t\tif (false && status !== \"completed\") throw new Error(`unknown Codex turn status ${String(status)}`);"
772
+ ],
773
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
774
+ "timeoutSeconds": 180,
775
+ "signature": "[QK:CODEX-LIVE-TURN-TERMINAL-EXACT]",
776
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
777
+ },
778
+ {
779
+ "claim": "CODEX-LIVE-FINAL-DIAGNOSTIC-VERDICT",
780
+ "title": "token and sender selection is logged as exact acceptance even when the mailbox payload differs from the source-call argument",
781
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
782
+ "find": ["\tif (parsed.payload !== expectedPayload)"],
783
+ "replace": ["\tif (false && parsed.payload !== expectedPayload)"],
784
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
785
+ "timeoutSeconds": 180,
786
+ "signature": "[QK:CODEX-LIVE-FINAL-DIAGNOSTIC-VERDICT]",
787
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
788
+ },
789
+ {
790
+ "claim": "CODEX-LIVE-SOURCE-PATH-RE-RESOLVED",
791
+ "title": "an empty source-path cache never re-reads its record, so a transcriptPath written after callback correlation is frozen out and every later source observation stays permanently empty",
792
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
793
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
794
+ "find": ["\treturn readRecordPath() ?? \"\";"],
795
+ "replace": ["\treturn cached; // mutant: an empty cache is answered without re-reading the record"],
796
+ "timeoutSeconds": 120,
797
+ "signature": "[QK:CODEX-LIVE-SOURCE-PATH-RE-RESOLVED]",
798
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
799
+ },
800
+ {
801
+ "claim": "CODEX-LIVE-EVIDENCE-RECORD-PATH",
802
+ "title": "the evidence manifest points at gardenId.json instead of the record owner's gardenId.meta.json filename",
803
+ "subject": "scripts/smoke-codex-fresh-live.ts",
804
+ "find": ["\t\tinitialPiRecordPath: path.join(defaultMetaSessionsDir(), metaRecordFilename(initialPiIdentity)),"],
805
+ "replace": ["\t\tinitialPiRecordPath: path.join(defaultMetaSessionsDir(), `${initialPiGid}.json`),"],
806
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
807
+ "timeoutSeconds": 180,
808
+ "signature": "[QK:CODEX-LIVE-EVIDENCE-RECORD-PATH]",
809
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
810
+ },
811
+ {
812
+ "claim": "CODEX-LIVE-EVIDENCE-RECOVERY-FAILSAFE",
813
+ "title": "optional source identity recovery runs outside its evidence guard, so corruption prevents raw snapshot copies",
814
+ "subject": "scripts/smoke-codex-fresh-live.ts",
815
+ "find": ["\ttry {\n\t\trecoverCodexThreadAuthority();\n\t} catch (recoveryError) {"],
816
+ "replace": [
817
+ "\trecoverCodexThreadAuthority(); // mutant: throws before raw source copies\n\ttry {\n\t\t// optional recovery guard bypassed\n\t} catch (recoveryError) {"
818
+ ],
819
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
820
+ "timeoutSeconds": 180,
821
+ "signature": "[QK:CODEX-LIVE-EVIDENCE-RECOVERY-FAILSAFE]",
822
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
823
+ },
824
+ {
825
+ "claim": "CODEX-LIVE-RECOVERY-SOURCE-ONLY",
826
+ "title": "smoke cleanup reconnects untrusted mailbox prose directly to the window allowlist",
827
+ "subject": "scripts/smoke-codex-fresh-live.ts",
828
+ "find": ["\tconst found = [...recoverCodexWindows(), ...(await recoverOutboundPiWindows())];"],
829
+ "replace": [
830
+ "\tconst found = [...seenInbox.flatMap(() => ['@999']), ...recoverCodexWindows(), ...(await recoverOutboundPiWindows())];"
831
+ ],
832
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
833
+ "timeoutSeconds": 180,
834
+ "signature": "[QK:CODEX-LIVE-RECOVERY-SOURCE-ONLY]",
835
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
836
+ }
837
+ ]
838
+ }