@junghanacs/entwurf 0.22.0 → 0.23.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 (98) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +380 -0
  3. package/DELIVERY.md +10 -2
  4. package/README.md +43 -4
  5. package/VERIFY.md +6 -0
  6. package/docs/setup-clean-host.md +11 -1
  7. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +39 -40
  8. package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-declaration.js +609 -0
  9. package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-fresh-preflight.js +95 -56
  10. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-control-rpc.js +40 -0
  11. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-fact-provider.js +6 -2
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-facts.js +7 -1
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-peer-observe.js +67 -2
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-peers-render.js +9 -1
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-self-address.js +24 -0
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-composition.js +423 -0
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-dispatch.js +98 -0
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +1018 -0
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-placement.js +213 -0
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +46 -273
  21. package/mcp/entwurf-bridge/dist/scripts/peer-facts.js +109 -0
  22. package/mcp/entwurf-bridge/src/index.ts +41 -41
  23. package/mcp/entwurf-bridge/tsconfig.build.json +1 -0
  24. package/package.json +4 -4
  25. package/pi-extensions/entwurf-control.ts +91 -52
  26. package/pi-extensions/lib/codex-declaration.js +612 -0
  27. package/pi-extensions/lib/codex-fresh-preflight.ts +107 -51
  28. package/pi-extensions/lib/entwurf-control-rpc.ts +46 -0
  29. package/pi-extensions/lib/entwurf-fact-provider.ts +13 -2
  30. package/pi-extensions/lib/entwurf-facts.ts +14 -1
  31. package/pi-extensions/lib/entwurf-peer-observe.ts +72 -2
  32. package/pi-extensions/lib/entwurf-peers-render.ts +9 -1
  33. package/pi-extensions/lib/entwurf-self-address.ts +33 -0
  34. package/pi-extensions/lib/fresh-call-composition.ts +493 -0
  35. package/pi-extensions/lib/fresh-call-dispatch.ts +142 -0
  36. package/pi-extensions/lib/herdr-fresh-call.ts +1378 -0
  37. package/pi-extensions/lib/herdr-placement.ts +276 -0
  38. package/pi-extensions/lib/mux-fresh-call.ts +95 -301
  39. package/run.sh +396 -8
  40. package/scripts/check-codex-birth-hook.ts +187 -0
  41. package/scripts/check-entwurf-control-rpc.ts +138 -0
  42. package/scripts/check-entwurf-fact-provider.ts +4 -2
  43. package/scripts/check-entwurf-facts.ts +12 -6
  44. package/scripts/check-entwurf-peers-surface.ts +3 -1
  45. package/scripts/check-entwurf-self-address.ts +68 -0
  46. package/scripts/check-fresh-call-dispatch.ts +301 -0
  47. package/scripts/check-gate-qualification.ts +16 -4
  48. package/scripts/check-herdr-activation.ts +1293 -0
  49. package/scripts/check-herdr-fresh-call.ts +1250 -0
  50. package/scripts/check-herdr-placement.ts +383 -0
  51. package/scripts/check-herdr-plugin-build.ts +842 -0
  52. package/scripts/check-herdr-plugin-profile.ts +371 -0
  53. package/scripts/check-herdr-plugin.ts +523 -0
  54. package/scripts/check-herdr-runtime-bootstrap.ts +1264 -0
  55. package/scripts/check-herdr-sandbox.ts +456 -0
  56. package/scripts/check-herdr-supply.ts +184 -0
  57. package/scripts/check-mux-launcher-fence.ts +138 -0
  58. package/scripts/check-peer-facts.ts +331 -0
  59. package/scripts/check-release-gate-outcomes.ts +12 -0
  60. package/scripts/check-typing-call-fence.ts +296 -0
  61. package/scripts/codex-birth-doctor.sh +159 -16
  62. package/scripts/codex-birth-install.sh +178 -72
  63. package/scripts/codex-birth-uninstall.sh +162 -7
  64. package/scripts/fixtures/herdr-supply.json +29 -0
  65. package/scripts/herdr-activation.mjs +536 -0
  66. package/scripts/herdr-plugin-activate.mjs +270 -0
  67. package/scripts/herdr-plugin-deactivate.mjs +193 -0
  68. package/scripts/herdr-runtime.mjs +1203 -0
  69. package/scripts/install-herdr-ci.sh +96 -0
  70. package/scripts/lib/codex-fresh-live-protocol.ts +2 -2
  71. package/scripts/lib/tree-digest.ts +97 -0
  72. package/scripts/meta-bridge-install.sh +19 -2
  73. package/scripts/meta-bridge-state.py +167 -11
  74. package/scripts/mutants/codex-caller-seat.json +6 -8
  75. package/scripts/mutants/codex-native.json +195 -29
  76. package/scripts/mutants/control-socket-disconnect.json +57 -0
  77. package/scripts/mutants/fresh-call-dispatch.json +154 -0
  78. package/scripts/mutants/herdr-activation.json +305 -0
  79. package/scripts/mutants/herdr-fresh-call.json +448 -0
  80. package/scripts/mutants/herdr-placement.json +161 -0
  81. package/scripts/mutants/herdr-plugin-build.json +160 -0
  82. package/scripts/mutants/herdr-plugin-profile.json +202 -0
  83. package/scripts/mutants/herdr-plugin.json +133 -0
  84. package/scripts/mutants/herdr-runtime-bootstrap.json +411 -0
  85. package/scripts/mutants/herdr-supply.json +133 -0
  86. package/scripts/mutants/meta-hook-session-switch.json +2 -2
  87. package/scripts/mutants/mux-fresh-call.json +104 -17
  88. package/scripts/mutants/mux-launcher-fence.json +13 -0
  89. package/scripts/mutants/omp-fresh.json +4 -4
  90. package/scripts/mutants/peer-facts.json +98 -0
  91. package/scripts/mutants/self-address.json +33 -0
  92. package/scripts/mutants/typing-call-fence.json +17 -0
  93. package/scripts/peer-facts.ts +120 -0
  94. package/scripts/register-pi-package.py +8 -0
  95. package/scripts/register-pi-provider.py +88 -12
  96. package/scripts/smoke-codex-birth.sh +281 -12
  97. package/scripts/smoke-herdr-fresh-call-live.ts +1027 -0
  98. package/scripts/smoke-herdr-plugin-build-live.ts +543 -0
@@ -46,7 +46,7 @@
46
46
  {
47
47
  "claim": "FRESHCALL-CODEX-ARGV",
48
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",
49
+ "subject": "pi-extensions/lib/fresh-call-composition.ts",
50
50
  "find": ["\t\t\t\t\"--remote\","],
51
51
  "replace": ["\t\t\t\t\"--resume\","],
52
52
  "gate": ["bash", "run.sh", "check-mux-fresh-call"],
@@ -156,7 +156,7 @@
156
156
  },
157
157
  {
158
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",
159
+ "title": "fresh preflight accepts the managed Codex MCP env_vars in any order, as long as the set matches \u2014 a reordered vendor-visible env manifest passes as exact",
160
160
  "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
161
161
  "find": ["\t\tenvVars.some((name, index) => name !== CODEX_MCP_ENV_VARS[index])"],
162
162
  "replace": [
@@ -171,8 +171,8 @@
171
171
  "claim": "FRESHCALL-CODEX-HOOKS-SAFE",
172
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
173
  "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
174
- "find": ["\tif (!isSafeOwnedFile(paths.hooksFile, expectedUid)) return true;"],
175
- "replace": ["\tif (false) return true;"],
174
+ "find": ["\tif (!isSafeOwnedFile(paths.hooksFile, expectedUid)) return null;"],
175
+ "replace": ["\tif (false) return null;"],
176
176
  "gate": ["bash", "run.sh", "check-mux-fresh-call"],
177
177
  "timeoutSeconds": 120,
178
178
  "signature": "[QK:FRESHCALL-CODEX-HOOKS-SAFE]",
@@ -217,14 +217,14 @@
217
217
  },
218
218
  {
219
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,
220
+ "title": "the declaration leaf stops NAMING the extra handler key, so an async or extra-key hook \u2014 still refused by the normalized digest \u2014 arrives as an anonymous mismatch instead of a diagnosis that quotes the key. This claim owns the diagnosis, never the acceptance",
221
+ "subject": "pi-extensions/lib/codex-declaration.js",
222
+ "find": ["\tif (handlerKeys.join(\",\") !== \"command,timeout,type\") {"],
223
+ "replace": ["\tif (false) {"],
224
+ "gate": ["bash", "run.sh", "check-codex-birth-hook"],
225
+ "timeoutSeconds": 180,
226
226
  "signature": "[QK:FRESHCALL-CODEX-HOOK-KEYS]",
227
- "signatureSource": "test/codex-fresh-preflight.test.ts"
227
+ "signatureSource": "scripts/check-codex-birth-hook.ts"
228
228
  },
229
229
  {
230
230
  "claim": "CODEX-TOML-STATE-BEFORE-CONFIG",
@@ -311,14 +311,14 @@
311
311
  "signatureSource": "scripts/smoke-codex-config-state.sh"
312
312
  },
313
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",
314
+ "claim": "CODEX-BIRTH-JOINS-FOREIGN-FILE",
315
+ "title": "the birth unit refuses a hooks.json it did not write instead of joining it, so a host carrying a neighbouring integration can never be installed into",
316
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"],
317
+ "find": [" if (sel.code !== \"declaration-absent\") throw new Error(sel.code + \": \" + sel.detail);"],
318
+ "replace": [" throw new Error(\"hooks.json already exists and no ownership state vouches for it\");"],
319
319
  "gate": ["bash", "run.sh", "smoke-codex-birth"],
320
320
  "timeoutSeconds": 120,
321
- "signature": "[QK:CODEX-BIRTH-FOREIGN-HOOKS-REFUSED]",
321
+ "signature": "[QK:CODEX-BIRTH-JOINS-FOREIGN-FILE]",
322
322
  "signatureSource": "scripts/smoke-codex-birth.sh"
323
323
  },
324
324
  {
@@ -380,10 +380,14 @@
380
380
  },
381
381
  {
382
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",
383
+ "title": "the MCP public surface relabels a Codex request as pi at the shared dispatcher seam, so the one central capability preflight is bypassed and placement runs first",
384
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;"],
385
+ "find": [
386
+ "\t\t\tconst dispatched = await dispatchFreshCall({\n\t\t\t\tbackend,\n\t\t\t\tmodel,\n\t\t\t\ttask,\n\t\t\t\tcwd,\n\t\t\t\tplacement,\n\t\t\t\tcallerGardenId,\n\t\t\t\tcallerNativeSessionId,\n\t\t\t\tcallerCwd,\n\t\t\t});"
387
+ ],
388
+ "replace": [
389
+ "\t\t\tconst dispatched = await dispatchFreshCall({\n\t\t\t\tbackend: \"pi\",\n\t\t\t\tmodel,\n\t\t\t\ttask,\n\t\t\t\tcwd,\n\t\t\t\tplacement,\n\t\t\t\tcallerGardenId,\n\t\t\t\tcallerNativeSessionId,\n\t\t\t\tcallerCwd,\n\t\t\t});"
390
+ ],
387
391
  "gate": ["bash", "run.sh", "check-mux-fresh-call"],
388
392
  "timeoutSeconds": 180,
389
393
  "signature": "[QK:FRESHCALL-CODEX-PREMUTATION-MCP]",
@@ -391,10 +395,10 @@
391
395
  },
392
396
  {
393
397
  "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",
398
+ "title": "the native pi public surface relabels a Codex request as pi at the shared dispatcher seam, bypassing the same central preflight from the other public door",
395
399
  "subject": "pi-extensions/entwurf-control.ts",
396
- "find": ["\t\t\t\t\tparams.backend === \"codex\""],
397
- "replace": ["\t\t\t\t\tfalse"],
400
+ "find": ["\t\t\t\t\tbackend: params.backend,"],
401
+ "replace": ["\t\t\t\t\tbackend: \"pi\","],
398
402
  "gate": ["bash", "run.sh", "check-mux-fresh-call"],
399
403
  "timeoutSeconds": 180,
400
404
  "signature": "[QK:FRESHCALL-CODEX-PREMUTATION-PI]",
@@ -445,9 +449,7 @@
445
449
  "claim": "FRESHCALL-CODEX-TRUST-RECEIPT",
446
450
  "title": "fresh preflight opens a Codex sibling whose birth hook the vendor never agreed to run",
447
451
  "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
448
- "find": [
449
- "\tif (config === null || trustReceiptMissing(config, paths.hooksFile)) return \"codex-birth-trust-missing\";"
450
- ],
452
+ "find": ["\tif (config === null || trustReceiptMissing(config, key)) return \"codex-birth-trust-missing\";"],
451
453
  "replace": ["\tif (config === null) return \"codex-birth-trust-missing\";"],
452
454
  "gate": ["bash", "run.sh", "check-mux-fresh-call"],
453
455
  "timeoutSeconds": 180,
@@ -458,8 +460,10 @@
458
460
  "claim": "FRESHCALL-CODEX-STATE-DIGEST",
459
461
  "title": "fresh preflight accepts a birth closure whose bytes no longer match the digests its own ownership state recorded",
460
462
  "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
461
- "find": ["\treturn closureDriftedFromState(paths, expectedUid);"],
462
- "replace": ["\treturn false; // mutant: existence is enough"],
463
+ "find": [
464
+ "\t\tif (typeof member.sha256 !== \"string\" || digest(path.join(paths.helperDir, rel)) !== member.sha256) return null;"
465
+ ],
466
+ "replace": ["\t\tif (typeof member.sha256 !== \"string\") return null; // mutant: existence is enough"],
463
467
  "gate": ["bash", "run.sh", "check-mux-fresh-call"],
464
468
  "timeoutSeconds": 180,
465
469
  "signature": "[QK:FRESHCALL-CODEX-STATE-DIGEST]",
@@ -518,7 +522,7 @@
518
522
  "title": "fresh preflight compares only the digests a state happens to name, so a short inventory hides an unchecked closure member",
519
523
  "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
520
524
  "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;"
525
+ "\tif (named.length !== expected.length) return null;\n\tif (expected.some((name) => !named.includes(name))) return null;\n\tif (named.some((name, index) => named.indexOf(name) !== index)) return null;"
522
526
  ],
523
527
  "replace": ["\t// mutant: judge only the members a state happens to name"],
524
528
  "gate": ["bash", "run.sh", "check-mux-fresh-call"],
@@ -554,7 +558,7 @@
554
558
  "claim": "FRESHCALL-CODEX-STATE-PARENT-AUTHORITY",
555
559
  "title": "fresh preflight trusts a digest inventory sitting in a directory anyone on the host can rewrite",
556
560
  "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
557
- "find": ["\tif (!isSafeOwnedDir(path.dirname(paths.stateFile), expectedUid)) return true;"],
561
+ "find": ["\tif (!isSafeOwnedDir(path.dirname(paths.stateFile), expectedUid)) return null;"],
558
562
  "replace": ["\t// mutant: the directory holding the receipt is nobody's business"],
559
563
  "gate": ["bash", "run.sh", "check-mux-fresh-call"],
560
564
  "timeoutSeconds": 180,
@@ -833,6 +837,168 @@
833
837
  "timeoutSeconds": 180,
834
838
  "signature": "[QK:CODEX-LIVE-RECOVERY-SOURCE-ONLY]",
835
839
  "signatureSource": "test/codex-fresh-live-protocol.test.ts"
840
+ },
841
+ {
842
+ "claim": "CODEX-DECL-CANONICAL-KEY-ORDER",
843
+ "title": "the declaration digest is taken over unsorted keys, so a neighbour re-serializing the document reads as an edited entwurf declaration",
844
+ "subject": "pi-extensions/lib/codex-declaration.js",
845
+ "find": ["\tconst keys = Object.keys(value).sort();"],
846
+ "replace": ["\tconst keys = Object.keys(value);"],
847
+ "gate": ["bash", "run.sh", "check-codex-birth-hook"],
848
+ "timeoutSeconds": 180,
849
+ "signature": "[QK:CODEX-DECL-CANONICAL-KEY-ORDER]",
850
+ "signatureSource": "scripts/check-codex-birth-hook.ts"
851
+ },
852
+ {
853
+ "claim": "CODEX-DECL-SELECT-BY-COMMAND",
854
+ "title": "entwurf's declaration is selected by POSITION instead of by its launcher command, so a neighbour at index 0 is certified as ours",
855
+ "subject": "pi-extensions/lib/codex-declaration.js",
856
+ "find": [
857
+ "\t\t\tif (handler !== null && typeof handler === \"object\" && !Array.isArray(handler) && handler.command === want) {"
858
+ ],
859
+ "replace": [
860
+ "\t\t\tif (handler !== null && typeof handler === \"object\" && !Array.isArray(handler) && h === 0) {"
861
+ ],
862
+ "gate": ["bash", "run.sh", "check-codex-birth-hook"],
863
+ "timeoutSeconds": 180,
864
+ "signature": "[QK:CODEX-DECL-SELECT-BY-COMMAND]",
865
+ "signatureSource": "scripts/check-codex-birth-hook.ts"
866
+ },
867
+ {
868
+ "claim": "CODEX-DECL-SPLICE-KEEPS-FOREIGN-BYTES",
869
+ "title": "a certified splice returns a RE-SERIALIZED document instead of the spliced text, rewriting every byte a neighbouring integration owns",
870
+ "subject": "pi-extensions/lib/codex-declaration.js",
871
+ "find": ["\treturn spliced;"],
872
+ "replace": ["\treturn JSON.stringify(reparsed, null, 2);"],
873
+ "gate": ["bash", "run.sh", "check-codex-birth-hook"],
874
+ "timeoutSeconds": 180,
875
+ "signature": "[QK:CODEX-DECL-SPLICE-KEEPS-FOREIGN-BYTES]",
876
+ "signatureSource": "scripts/check-codex-birth-hook.ts"
877
+ },
878
+ {
879
+ "claim": "CODEX-DECL-SPLICE-CERTIFIED",
880
+ "title": "the span splice is written out on the span reader's word alone, with no re-parse proving it landed where the caller intended",
881
+ "subject": "pi-extensions/lib/codex-declaration.js",
882
+ "find": ["\tif (canonicalJson(reparsed) !== canonicalJson(expected)) {"],
883
+ "replace": ["\tif (false) {"],
884
+ "gate": ["bash", "run.sh", "check-codex-birth-hook"],
885
+ "timeoutSeconds": 180,
886
+ "signature": "[QK:CODEX-DECL-SPLICE-CERTIFIED]",
887
+ "signatureSource": "scripts/check-codex-birth-hook.ts"
888
+ },
889
+ {
890
+ "claim": "CODEX-DECLARATION-DUPLICATED",
891
+ "title": "a duplicated entwurf declaration is first-match accepted, so the vendor runs the birth hook twice and only one position carries the receipt",
892
+ "subject": "pi-extensions/lib/codex-declaration.js",
893
+ "find": ["\tif (mine.length > 1) {"],
894
+ "replace": ["\tif (mine.length > 2) {"],
895
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
896
+ "timeoutSeconds": 180,
897
+ "signature": "[QK:CODEX-DECLARATION-DUPLICATED]",
898
+ "signatureSource": "test/codex-fresh-preflight.test.ts"
899
+ },
900
+ {
901
+ "claim": "CODEX-DECLARATION-TRUST-INDEX",
902
+ "title": "fresh preflight reads the vendor trust receipt at the constant :0:0, so a neighbour's approval at index 0 admits a birth hook the vendor never agreed to run",
903
+ "subject": "pi-extensions/lib/codex-fresh-preflight.ts",
904
+ "find": ["\tconst key = trustReceiptKey(paths.hooksFile, declaration.groupIndex, declaration.handlerIndex);"],
905
+ "replace": ["\tconst key = trustReceiptKey(paths.hooksFile, 0, 0);"],
906
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
907
+ "timeoutSeconds": 180,
908
+ "signature": "[QK:CODEX-DECLARATION-TRUST-INDEX]",
909
+ "signatureSource": "test/codex-fresh-preflight.test.ts"
910
+ },
911
+ {
912
+ "claim": "CODEX-BIRTH-TRUST-INDEX-MEASURED",
913
+ "title": "the doctor reads the vendor trust receipt at the constant :0:0, reporting a neighbour's approval as entwurf's own",
914
+ "subject": "scripts/codex-birth-doctor.sh",
915
+ "find": [" TRUST_KEY=\"$HOOKS_FILE:session_start:$DECL_GROUP_INDEX:$DECL_HANDLER_INDEX\""],
916
+ "replace": [" TRUST_KEY=\"$HOOKS_FILE:session_start:0:0\""],
917
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
918
+ "timeoutSeconds": 180,
919
+ "signature": "[QK:CODEX-BIRTH-TRUST-INDEX-MEASURED]",
920
+ "signatureSource": "scripts/smoke-codex-birth.sh"
921
+ },
922
+ {
923
+ "claim": "CODEX-BIRTH-SHARED-FILE-OWNERSHIP",
924
+ "title": "the shared ownership predicate stops seeing a group/world-writable file, so all four surfaces write into and certify bytes somebody else can rewrite",
925
+ "subject": "pi-extensions/lib/codex-declaration.js",
926
+ "find": ["\tif ((stat.mode & 0o022) !== 0) return \"writable-by-others\";"],
927
+ "replace": [""],
928
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
929
+ "timeoutSeconds": 300,
930
+ "signature": "[QK:CODEX-BIRTH-SHARED-FILE-OWNERSHIP]",
931
+ "signatureSource": "scripts/smoke-codex-birth.sh"
932
+ },
933
+ {
934
+ "claim": "CODEX-BIRTH-DOCTOR-SHARED-OWNERSHIP",
935
+ "title": "the doctor stops asking who owns the shared file and goes straight to the digest, so it reports green on a host every launch refuses",
936
+ "subject": "scripts/codex-birth-doctor.sh",
937
+ "find": [" if (owned !== \"ok\") {"],
938
+ "replace": [" if (false) {"],
939
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
940
+ "timeoutSeconds": 300,
941
+ "signature": "[QK:CODEX-BIRTH-DOCTOR-SHARED-OWNERSHIP]",
942
+ "signatureSource": "scripts/smoke-codex-birth.sh"
943
+ },
944
+ {
945
+ "claim": "CODEX-BIRTH-INVERSE-SHARED-OWNERSHIP",
946
+ "title": "the inverse stops asking and rewrites a shared file it cannot bind, instead of leaving it as found and counting the drift",
947
+ "subject": "scripts/codex-birth-uninstall.sh",
948
+ "find": [" if [ \"$owned\" != \"ok\" ]; then"],
949
+ "replace": [" if false; then"],
950
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
951
+ "timeoutSeconds": 300,
952
+ "signature": "[QK:CODEX-BIRTH-INVERSE-SHARED-OWNERSHIP]",
953
+ "signatureSource": "scripts/smoke-codex-birth.sh"
954
+ },
955
+ {
956
+ "claim": "CODEX-BIRTH-INVERSE-KEEPS-PRE-EXISTING-FILE",
957
+ "title": "the FILE verdict goes back to asking only whether our group was the last declaration, so a hooks.json that existed before this unit is deleted with its owners top-level bytes",
958
+ "subject": "scripts/codex-birth-uninstall.sh",
959
+ "find": [
960
+ " if (createdByUs === \"yes\" && soleDeclaration && topLevel === \"description,hooks\" && ourDescription) {"
961
+ ],
962
+ "replace": [" if (soleDeclaration) {"],
963
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
964
+ "timeoutSeconds": 300,
965
+ "signature": "[QK:CODEX-BIRTH-INVERSE-KEEPS-PRE-EXISTING-FILE]",
966
+ "signatureSource": "scripts/smoke-codex-birth.sh"
967
+ },
968
+ {
969
+ "claim": "CODEX-BIRTH-DOCTOR-ORPHAN-RED",
970
+ "title": "the doctor stops looking for our own bytes when the receipt is gone, so a half-removed unit reads as a clean host and invites a reinstall over bytes the inverse will refuse",
971
+ "subject": "scripts/codex-birth-doctor.sh",
972
+ "find": [" if [ \"$ORPHAN_DECLARATION\" = \"1\" ] || [ -e \"$HELPER_DIR\" ]; then"],
973
+ "replace": [" if false; then"],
974
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
975
+ "timeoutSeconds": 300,
976
+ "signature": "[QK:CODEX-BIRTH-DOCTOR-ORPHAN-RED]",
977
+ "signatureSource": "scripts/smoke-codex-birth.sh"
978
+ },
979
+ {
980
+ "claim": "CODEX-BIRTH-INVERSE-KEEPS-FOREIGN",
981
+ "title": "the text splice takes a fixed group index instead of the one the selector measured, so the inverse reaches for a neighbours declaration and the post-condition is the only thing standing between that and a written file",
982
+ "subject": "scripts/codex-birth-uninstall.sh",
983
+ "find": [" let spliced = m.certifySplice(m.removeSessionStartGroup(text, sel.groupIndex), want);"],
984
+ "replace": [" let spliced = m.certifySplice(m.removeSessionStartGroup(text, 0), want);"],
985
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
986
+ "timeoutSeconds": 300,
987
+ "signature": "[QK:CODEX-BIRTH-INVERSE-KEEPS-FOREIGN]",
988
+ "signatureSource": "scripts/smoke-codex-birth.sh"
989
+ },
990
+ {
991
+ "claim": "CODEX-BIRTH-INVERSE-SOLE-OWNER",
992
+ "title": "the FILE arm drops the target from its own removal, so a hooks.json this unit created and was the sole declaration in survives an uninstall that reports it gone",
993
+ "subject": "scripts/codex-birth-uninstall.sh",
994
+ "find": [
995
+ " FILE) rm -f -- \"$tmp\" \"$target\"; note \"removed $target (entwurf was its only declaration)\" ;;"
996
+ ],
997
+ "replace": [" FILE) rm -f -- \"$tmp\"; note \"removed $target (entwurf was its only declaration)\" ;;"],
998
+ "gate": ["bash", "run.sh", "smoke-codex-birth"],
999
+ "timeoutSeconds": 300,
1000
+ "signature": "[QK:CODEX-BIRTH-INVERSE-SOLE-OWNER]",
1001
+ "signatureSource": "scripts/smoke-codex-birth.sh"
836
1002
  }
837
1003
  ]
838
1004
  }
@@ -0,0 +1,57 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "control-socket-disconnect",
4
+ "mutants": [
5
+ {
6
+ "claim": "CONTROL-SOCKET-NO-UNCAUGHT",
7
+ "title": "the accepted connection carries no disconnect policy, so a peer that hangs up mid-exchange reaches the process as an uncaught exception and kills the resident session",
8
+ "subject": "pi-extensions/lib/entwurf-control-rpc.ts",
9
+ "find": [
10
+ "\tsocket.on(\"error\", (error: NodeJS.ErrnoException) => {",
11
+ "\t\tif (isPeerDisconnect(error)) return;",
12
+ "\t\tdiagnose(`[entwurf-control] control socket error (${error.code ?? \"no code\"}): ${error.message}`);",
13
+ "\t});"
14
+ ],
15
+ "replace": ["\t// the accepted connection no longer carries a disconnect policy"],
16
+ "gate": ["bash", "run.sh", "check-entwurf-control-rpc"],
17
+ "timeoutSeconds": 90,
18
+ "signature": "[QK:CONTROL-SOCKET-NO-UNCAUGHT]",
19
+ "signatureSource": "scripts/check-entwurf-control-rpc.ts"
20
+ },
21
+ {
22
+ "claim": "CONTROL-SOCKET-ABSORBS-PEER-DISCONNECT",
23
+ "title": "a peer that went away is diagnosed instead of absorbed, so ordinary client timeouts spray the resident session with stderr about someone else state",
24
+ "subject": "pi-extensions/lib/entwurf-control-rpc.ts",
25
+ "find": ["\t\tif (isPeerDisconnect(error)) return;"],
26
+ "replace": ["\t\t// a vanished peer is no longer absorbed"],
27
+ "gate": ["bash", "run.sh", "check-entwurf-control-rpc"],
28
+ "timeoutSeconds": 90,
29
+ "signature": "[QK:CONTROL-SOCKET-ABSORBS-PEER-DISCONNECT]",
30
+ "signatureSource": "scripts/check-entwurf-control-rpc.ts"
31
+ },
32
+ {
33
+ "claim": "CONTROL-SOCKET-DIAGNOSES-UNEXPECTED",
34
+ "title": "an error that is NOT a peer disconnect is swallowed silently, hiding exactly the class this listener was never meant to absorb",
35
+ "subject": "pi-extensions/lib/entwurf-control-rpc.ts",
36
+ "find": [
37
+ "\t\tdiagnose(`[entwurf-control] control socket error (${error.code ?? \"no code\"}): ${error.message}`);"
38
+ ],
39
+ "replace": ["\t\treturn;"],
40
+ "gate": ["bash", "run.sh", "check-entwurf-control-rpc"],
41
+ "timeoutSeconds": 90,
42
+ "signature": "[QK:CONTROL-SOCKET-DIAGNOSES-UNEXPECTED]",
43
+ "signatureSource": "scripts/check-entwurf-control-rpc.ts"
44
+ },
45
+ {
46
+ "claim": "CONTROL-SOCKET-POLICY-FIRST",
47
+ "title": "the policy is attached after setEncoding, leaving a window in which the first write on a freshly accepted connection can still kill the session",
48
+ "subject": "pi-extensions/entwurf-control.ts",
49
+ "find": ["\t\tattachAcceptedSocketDisconnectPolicy(socket);", "\t\tsocket.setEncoding(\"utf8\");"],
50
+ "replace": ["\t\tsocket.setEncoding(\"utf8\");", "\t\tattachAcceptedSocketDisconnectPolicy(socket);"],
51
+ "gate": ["bash", "run.sh", "check-entwurf-control-rpc"],
52
+ "timeoutSeconds": 90,
53
+ "signature": "[QK:CONTROL-SOCKET-POLICY-FIRST]",
54
+ "signatureSource": "scripts/check-entwurf-control-rpc.ts"
55
+ }
56
+ ]
57
+ }
@@ -0,0 +1,154 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "fresh-call-dispatch",
4
+ "mutants": [
5
+ {
6
+ "claim": "FCD-RAIL-IS-CAPABILITY",
7
+ "title": "the herdr marker is read loosely, so a process carrying HERDR_ENV=0 is treated as being inside herdr",
8
+ "subject": "pi-extensions/lib/fresh-call-dispatch.ts",
9
+ "find": ["\treturn env.HERDR_ENV === \"1\" ? \"herdr\" : \"tmux\";"],
10
+ "replace": ["\treturn env.HERDR_ENV !== undefined ? \"herdr\" : \"tmux\";"],
11
+ "gate": ["bash", "run.sh", "check-fresh-call-dispatch"],
12
+ "timeoutSeconds": 120,
13
+ "signature": "[QK:FCD-RAIL-IS-CAPABILITY]",
14
+ "signatureSource": "scripts/check-fresh-call-dispatch.ts"
15
+ },
16
+ {
17
+ "claim": "FCD-NO-RAIL-PARAMETER",
18
+ "title": "the request gains a caller-chosen rail, so someone can ask for tmux placement from inside herdr and fail after a mutation",
19
+ "subject": "pi-extensions/lib/fresh-call-dispatch.ts",
20
+ "find": ["export interface FreshCallRequest {"],
21
+ "replace": ["export interface FreshCallRequest {\n\treadonly rail?: FreshCallRail;"],
22
+ "gate": ["bash", "run.sh", "check-fresh-call-dispatch"],
23
+ "timeoutSeconds": 120,
24
+ "signature": "[QK:FCD-NO-RAIL-PARAMETER]",
25
+ "signatureSource": "scripts/check-fresh-call-dispatch.ts"
26
+ },
27
+ {
28
+ "claim": "FCD-NO-FALLBACK",
29
+ "title": "an incomplete herdr context falls back to tmux, opening a window the operator cannot see from where they are standing",
30
+ "subject": "pi-extensions/lib/fresh-call-dispatch.ts",
31
+ "find": ["\t\t\treturn { rail: \"herdr\", result: { ok: false, reason: context.reason } };"],
32
+ "replace": ["\t\t\treturn { rail: \"tmux\", result: freshCall(request as never, env, nonce) };"],
33
+ "gate": ["bash", "run.sh", "check-fresh-call-dispatch"],
34
+ "timeoutSeconds": 120,
35
+ "signature": "[QK:FCD-NO-FALLBACK]",
36
+ "signatureSource": "scripts/check-fresh-call-dispatch.ts"
37
+ },
38
+ {
39
+ "claim": "FCD-HERDR-BACKEND-FIRST",
40
+ "title": "the herdr branch runs the Codex preflight before refusing a non-pilot backend, answering an irrelevant question first",
41
+ "subject": "pi-extensions/lib/fresh-call-dispatch.ts",
42
+ "find": [
43
+ "\t\tconst run: HerdrRun = createHerdrRunner(context.context.bin, env, spawn ?? (spawnChildProcess as SpawnFn));"
44
+ ],
45
+ "replace": [
46
+ "\t\tif (request.backend === \"codex\") await codexFreshPreflight(env);\n\t\tconst run: HerdrRun = createHerdrRunner(context.context.bin, env, spawn ?? (spawnChildProcess as SpawnFn));"
47
+ ],
48
+ "gate": ["bash", "run.sh", "check-fresh-call-dispatch"],
49
+ "timeoutSeconds": 120,
50
+ "signature": "[QK:FCD-HERDR-BACKEND-FIRST]",
51
+ "signatureSource": "scripts/check-fresh-call-dispatch.ts"
52
+ },
53
+ {
54
+ "claim": "FCD-CODEX-PREFLIGHT-TMUX",
55
+ "title": "the Codex preflight moves after the composition, so a window opens before the capability question is asked",
56
+ "subject": "pi-extensions/lib/fresh-call-dispatch.ts",
57
+ "find": [
58
+ "\tconst targetMissing = request.backend === \"codex\" ? await codexFreshPreflight(env) : null;\n\tconst callerMissing =\n\t\ttargetMissing === null && request.callerNativeSessionId !== undefined && request.placement === undefined\n\t\t\t? codexCallerFreshPreflight(env)\n\t\t\t: null;\n\tconst missing = targetMissing ?? callerMissing;\n\tif (missing) return { rail: \"tmux\", result: { ok: false, reason: missing } };"
59
+ ],
60
+ "replace": [""],
61
+ "gate": ["bash", "run.sh", "check-fresh-call-dispatch"],
62
+ "timeoutSeconds": 120,
63
+ "signature": "[QK:FCD-CODEX-PREFLIGHT-TMUX]",
64
+ "signatureSource": "scripts/check-fresh-call-dispatch.ts"
65
+ },
66
+ {
67
+ "claim": "FCD-ONE-NONCE",
68
+ "title": "the rail mints its own second nonce, so the sibling calls back with a tag the caller never recorded",
69
+ "subject": "pi-extensions/lib/fresh-call-dispatch.ts",
70
+ "find": ["\t\treturn { rail: \"herdr\", result: await herdrFreshCall(request, run, env, nonce) };"],
71
+ "replace": ["\t\treturn { rail: \"herdr\", result: await herdrFreshCall(request, run, env, mintNonce()) };"],
72
+ "gate": ["bash", "run.sh", "check-fresh-call-dispatch"],
73
+ "timeoutSeconds": 120,
74
+ "signature": "[QK:FCD-ONE-NONCE]",
75
+ "signatureSource": "scripts/check-fresh-call-dispatch.ts"
76
+ },
77
+ {
78
+ "claim": "FCD-SURFACE-PARITY",
79
+ "title": "the MCP surface goes back to calling a rail directly, so the two public surfaces can drift on rail choice",
80
+ "subject": "mcp/entwurf-bridge/src/index.ts",
81
+ "find": [
82
+ "\t\t\tconst dispatched = await dispatchFreshCall({\n\t\t\t\tbackend,\n\t\t\t\tmodel,\n\t\t\t\ttask,\n\t\t\t\tcwd,\n\t\t\t\tplacement,\n\t\t\t\tcallerGardenId,\n\t\t\t\tcallerNativeSessionId,\n\t\t\t\tcallerCwd,\n\t\t\t});"
83
+ ],
84
+ "replace": [
85
+ "\t\t\tconst dispatched = { rail: \"tmux\" as const, result: { ok: false, reason: \"caller-identity-unavailable\" as const } };\n\t\t\tvoid selectFreshCallRail;"
86
+ ],
87
+ "gate": ["bash", "run.sh", "check-fresh-call-dispatch"],
88
+ "timeoutSeconds": 120,
89
+ "signature": "[QK:FCD-SURFACE-PARITY]",
90
+ "signatureSource": "scripts/check-fresh-call-dispatch.ts"
91
+ },
92
+ {
93
+ "claim": "FCD-PI-DYNAMIC-IMPORT",
94
+ "title": "pi reaches the composition root by a literal path again, which is how the lazy import fence erodes",
95
+ "subject": "pi-extensions/entwurf-control.ts",
96
+ "find": ["const FRESH_CALL_DISPATCH_MODULE = \"./lib/fresh-call-dispatch.ts\";"],
97
+ "replace": ["const FRESH_CALL_DISPATCH_MODULE = \"./lib/fresh-call-dispatch-renamed.ts\";"],
98
+ "gate": ["bash", "run.sh", "check-fresh-call-dispatch"],
99
+ "timeoutSeconds": 120,
100
+ "signature": "[QK:FCD-PI-DYNAMIC-IMPORT]",
101
+ "signatureSource": "scripts/check-fresh-call-dispatch.ts"
102
+ },
103
+ {
104
+ "claim": "FCD-RENDER-PER-RAIL",
105
+ "title": "both rails render through the tmux renderer, so a herdr caller is told their sibling is in a tmux window",
106
+ "subject": "pi-extensions/lib/fresh-call-dispatch.ts",
107
+ "find": [
108
+ "\treturn dispatched.rail === \"herdr\" ? renderHerdrFreshCall(dispatched.result) : renderFreshCall(dispatched.result);"
109
+ ],
110
+ "replace": ["\treturn renderFreshCall(dispatched.result as never);"],
111
+ "gate": ["bash", "run.sh", "check-fresh-call-dispatch"],
112
+ "timeoutSeconds": 120,
113
+ "signature": "[QK:FCD-RENDER-PER-RAIL]",
114
+ "signatureSource": "scripts/check-fresh-call-dispatch.ts"
115
+ },
116
+ {
117
+ "claim": "FCD-HERDR-VIEW-NOT-ADDRESS",
118
+ "title": "the herdr receipt stops saying its coordinates are a view, which is the first step to someone dispatching at a pane id",
119
+ "subject": "pi-extensions/lib/herdr-fresh-call.ts",
120
+ "find": [
121
+ "` pane: ${r.herdrPaneId} terminal ${r.herdrTerminalId} — the tab's initial pane; herdr VIEW coordinates, not an address\\n` +"
122
+ ],
123
+ "replace": ["` pane: ${r.herdrPaneId} terminal ${r.herdrTerminalId}\\n` +"],
124
+ "gate": ["bash", "run.sh", "check-fresh-call-dispatch"],
125
+ "timeoutSeconds": 120,
126
+ "signature": "[QK:FCD-HERDR-VIEW-NOT-ADDRESS]",
127
+ "signatureSource": "scripts/check-fresh-call-dispatch.ts"
128
+ },
129
+ {
130
+ "claim": "FCD-RECOVERY-VISIBLE",
131
+ "title": "an unreclaimed orphan renders as if it had been closed, so nobody goes to look at the pane still sitting there",
132
+ "subject": "pi-extensions/lib/herdr-fresh-call.ts",
133
+ "find": [
134
+ "\t\t\treturn ` recovery: orphan-unreclaimed:${recovery.reason} (${recovery.paneId}) — this pane was NOT closed, on purpose\\n`;"
135
+ ],
136
+ "replace": ["\t\t\treturn ` recovery: closed ${recovery.paneId}\\n`;"],
137
+ "gate": ["bash", "run.sh", "check-fresh-call-dispatch"],
138
+ "timeoutSeconds": 120,
139
+ "signature": "[QK:FCD-RECOVERY-VISIBLE]",
140
+ "signatureSource": "scripts/check-fresh-call-dispatch.ts"
141
+ },
142
+ {
143
+ "claim": "FCD-NO-SYNC-SPAWN",
144
+ "title": "the composition root regains synchronous child authority, which is how a blocking runner gets wired back in without anyone reading the runner",
145
+ "subject": "pi-extensions/lib/fresh-call-dispatch.ts",
146
+ "find": ["import { spawn as spawnChildProcess } from \"node:child_process\";"],
147
+ "replace": ["import { spawn as spawnChildProcess, spawnSync } from \"node:child_process\";"],
148
+ "gate": ["bash", "run.sh", "check-fresh-call-dispatch"],
149
+ "timeoutSeconds": 120,
150
+ "signature": "[QK:FCD-NO-SYNC-SPAWN]",
151
+ "signatureSource": "scripts/check-fresh-call-dispatch.ts"
152
+ }
153
+ ]
154
+ }