@junghanacs/entwurf 0.25.1 → 0.30.1

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 (86) hide show
  1. package/AGENTS.md +1 -1
  2. package/BASELINE.md +1 -1
  3. package/CHANGELOG.md +190 -0
  4. package/DELIVERY.md +1 -1
  5. package/README.md +183 -674
  6. package/VERIFY.md +21 -17
  7. package/demo/README.md +1 -1
  8. package/docs/acp-backend-rail.md +115 -18
  9. package/docs/external-mcp-host.md +1 -1
  10. package/docs/setup-clean-host.md +346 -10
  11. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +27 -4
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +55 -1
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-peers-render.js +1 -1
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-decider.js +2 -2
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-mailbox.js +2 -2
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-production.js +2 -2
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +3 -5
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-visible-resume.js +3 -3
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-composition.js +13 -6
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-mailbox-body.js +1 -1
  21. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +3 -3
  22. package/mcp/entwurf-bridge/src/index.ts +30 -3
  23. package/package.json +13 -13
  24. package/pi-extensions/entwurf-control.ts +50 -637
  25. package/pi-extensions/lib/acp/backend-adapter.ts +81 -1
  26. package/pi-extensions/lib/acp/backend.ts +41 -5
  27. package/pi-extensions/lib/entwurf-fact-provider.ts +2 -2
  28. package/pi-extensions/lib/entwurf-mcp-server.ts +74 -0
  29. package/pi-extensions/lib/entwurf-peers-render.ts +1 -1
  30. package/pi-extensions/lib/entwurf-v2-decider.ts +2 -2
  31. package/pi-extensions/lib/entwurf-v2-mailbox.ts +2 -2
  32. package/pi-extensions/lib/entwurf-v2-production.ts +3 -3
  33. package/pi-extensions/lib/entwurf-v2-surface.ts +3 -5
  34. package/pi-extensions/lib/entwurf-v2-visible-resume.ts +3 -3
  35. package/pi-extensions/lib/fresh-call-composition.ts +13 -6
  36. package/pi-extensions/lib/meta-mailbox-body.ts +1 -1
  37. package/pi-extensions/lib/mux-fresh-call.ts +3 -3
  38. package/run.sh +177 -53
  39. package/scripts/check-entwurf-peers-surface.ts +8 -15
  40. package/scripts/check-entwurf-self-address.ts +7 -11
  41. package/scripts/check-entwurf-v2-surface.ts +20 -112
  42. package/scripts/check-fresh-call-dispatch.ts +12 -13
  43. package/scripts/check-gate-qualification.ts +250 -5
  44. package/scripts/check-herdr-plugin-build.ts +159 -57
  45. package/scripts/check-install-surface.ts +3 -2
  46. package/scripts/check-mux-resume-call.ts +24 -35
  47. package/scripts/check-pi-bridge-sender.ts +130 -0
  48. package/scripts/check-pi-mcp-bridge.ts +251 -0
  49. package/scripts/fixtures/herdr-supply.json +8 -8
  50. package/scripts/lib/codex-fresh-live-protocol.ts +17 -5
  51. package/scripts/lib/codex-fresh-source-receipts.ts +21 -2
  52. package/scripts/lib/mutation-qualify.ts +269 -44
  53. package/scripts/lib/pi-mcp-bridge-probe.mjs +170 -0
  54. package/scripts/meta-bridge-doctor.sh +16 -5
  55. package/scripts/mutants/acp-foreground-only.json +17 -0
  56. package/scripts/mutants/acp-prompt-lifecycle.json +2 -2
  57. package/scripts/mutants/acp-vendor-rejection.json +62 -0
  58. package/scripts/mutants/codex-native.json +11 -11
  59. package/scripts/mutants/control-send-receipt.json +6 -4
  60. package/scripts/mutants/copilot-birth.json +2 -1
  61. package/scripts/mutants/fresh-call-dispatch.json +3 -14
  62. package/scripts/mutants/gate-qualification.json +59 -0
  63. package/scripts/mutants/herdr-plugin-build.json +11 -0
  64. package/scripts/mutants/herdr-supply.json +3 -3
  65. package/scripts/mutants/mux-fresh-call.json +43 -45
  66. package/scripts/mutants/mux-resume-call.json +11 -35
  67. package/scripts/mutants/pack-install.json +15 -4
  68. package/scripts/mutants/pi-bridge-sender.json +54 -0
  69. package/scripts/mutants/pi-floor.json +6 -2
  70. package/scripts/mutants/pi-mcp-bridge.json +36 -0
  71. package/scripts/mutants/pi-mcp-register.json +51 -0
  72. package/scripts/mutants/v2-surface.json +6 -6
  73. package/scripts/resident-rpc-drive.ts +5 -1
  74. package/scripts/smoke-acp-bundled-mcp-live.ts +3 -1
  75. package/scripts/smoke-acp-cortex-live.ts +3 -1
  76. package/scripts/smoke-acp-raw-turn-live.ts +1 -1
  77. package/scripts/smoke-acp-session-reuse-live.ts +29 -12
  78. package/scripts/smoke-acp-socket-citizen-live.ts +3 -1
  79. package/scripts/smoke-acp-v2-send-live.ts +3 -1
  80. package/scripts/smoke-codex-fresh-live.ts +20 -1
  81. package/scripts/smoke-entwurf-chain-live.ts +6 -2
  82. package/scripts/smoke-entwurf-v2-matrix-live.ts +3 -1
  83. package/scripts/smoke-herdr-fresh-call-live.ts +21 -7
  84. package/scripts/smoke-herdr-raw-install-live.sh +1 -1
  85. package/scripts/smoke-mux-lifecycle-live.ts +1 -1
  86. package/scripts/smoke-resident-garden-guard.sh +3 -1
@@ -54,8 +54,8 @@
54
54
  "claim": "REUSE-CARRIES-CHILD-DIAGNOSTICS",
55
55
  "title": "the reuse path drops the child's stderr tail again — exactly the live sonnet failure that showed only \"ACP connection closed\"",
56
56
  "subject": "pi-extensions/lib/acp/backend.ts",
57
- "find": ["\t\t\tfinishError(err, aborted, session.stderrTail, lifecycle, session.launchObservation);"],
58
- "replace": ["\t\t\tfinishError(err, aborted, undefined, lifecycle, session.launchObservation);"],
57
+ "find": ["\t\t\tfinishError(err, aborted, session.stderrTail, lifecycle, session.launchObservation, adapter);"],
58
+ "replace": ["\t\t\tfinishError(err, aborted, undefined, lifecycle, session.launchObservation, adapter);"],
59
59
  "gate": ["bash", "run.sh", "check-acp-prompt-lifecycle"],
60
60
  "timeoutSeconds": 180,
61
61
  "signature": "[QK:REUSE-CARRIES-CHILD-DIAGNOSTICS]",
@@ -0,0 +1,62 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "acp-vendor-rejection",
4
+ "mutants": [
5
+ {
6
+ "claim": "ACP-INCOMPLETE-TOOL-NO-REPLAY-NEW",
7
+ "title": "finishError stops consulting the adapter's prompt-rejection reader — the vendor's raw 'Internal error' text becomes errorMessage again and pi replays a turn whose tools already ran",
8
+ "subject": "pi-extensions/lib/acp/backend.ts",
9
+ "find": ["\t\tconst rejection = aborted ? undefined : adapter?.readPromptRejection?.(err);"],
10
+ "replace": ["\t\tconst rejection = aborted ? undefined : undefined;"],
11
+ "gate": ["bash", "run.sh", "check-acp-vendor-rejection"],
12
+ "timeoutSeconds": 120,
13
+ "signature": "[QK:ACP-INCOMPLETE-TOOL-NO-REPLAY-NEW]",
14
+ "signatureSource": "pi-extensions/lib/acp/backend.vendor-rejection.test.ts"
15
+ },
16
+ {
17
+ "claim": "ACP-PROMPT-REJECTION-CLAUDE-ONLY",
18
+ "title": "the claude reader stops checking the vendor's errorKind — any -32603 carrying an errorKind (no_result included) is rewritten to the incomplete-tool verdict",
19
+ "subject": "pi-extensions/lib/acp/backend-adapter.ts",
20
+ "find": ["\tif (data.errorKind !== CLAUDE_INCOMPLETE_TOOL_CALL) return undefined;"],
21
+ "replace": ["\tif (data.errorKind === undefined) return undefined;"],
22
+ "gate": ["bash", "run.sh", "check-acp-vendor-rejection"],
23
+ "timeoutSeconds": 120,
24
+ "signature": "[QK:ACP-PROMPT-REJECTION-CLAUDE-ONLY]",
25
+ "signatureSource": "pi-extensions/lib/acp/backend-adapter.test.ts"
26
+ },
27
+ {
28
+ "claim": "ACP-INCOMPLETE-TOOL-RAW-EVIDENCE",
29
+ "title": "the recognised rejection is sealed with the verdict but its raw vendor message, data and stderr are dropped instead of riding a pi diagnostic",
30
+ "subject": "pi-extensions/lib/acp/backend.ts",
31
+ "find": [
32
+ "\t\t\tappendAssistantMessageDiagnostic(",
33
+ "\t\t\t\tstate.output,",
34
+ "\t\t\t\tcreateAssistantMessageDiagnostic(ACP_PROMPT_REJECTION_DIAGNOSTIC, err, {",
35
+ "\t\t\t\t\terrorKind: rejection.errorKind,",
36
+ "\t\t\t\t\tdataJson: rejection.dataJson,",
37
+ "\t\t\t\t\t...(lifecycle ? { lifecycle } : {}),",
38
+ "\t\t\t\t\t...(observed ? { launchSignal: observed } : {}),",
39
+ "\t\t\t\t\t...(tail ? { stderrTail: tail } : {}),",
40
+ "\t\t\t\t\t...(hint ? { hint } : {}),",
41
+ "\t\t\t\t}),",
42
+ "\t\t\t);"
43
+ ],
44
+ "replace": ["\t\t\t// mutant: the raw rejection is not preserved"],
45
+ "gate": ["bash", "run.sh", "check-acp-vendor-rejection"],
46
+ "timeoutSeconds": 120,
47
+ "signature": "[QK:ACP-INCOMPLETE-TOOL-RAW-EVIDENCE]",
48
+ "signatureSource": "pi-extensions/lib/acp/backend.vendor-rejection.test.ts"
49
+ },
50
+ {
51
+ "claim": "ACP-REUSE-COOPERATIVE-CANCEL",
52
+ "title": "a reused session's cooperatively cancelled turn is sealed and retained but no longer persisted — the record lags the live session",
53
+ "subject": "pi-extensions/lib/acp/backend.ts",
54
+ "find": ["\t\t\tfinishSuccess(adapter, session, promptResult);", "\t\t\tpersistRecord(session, deps);"],
55
+ "replace": ["\t\t\tfinishSuccess(adapter, session, promptResult);"],
56
+ "gate": ["bash", "run.sh", "check-acp-vendor-rejection"],
57
+ "timeoutSeconds": 120,
58
+ "signature": "[QK:ACP-REUSE-COOPERATIVE-CANCEL]",
59
+ "signatureSource": "pi-extensions/lib/acp/backend.vendor-rejection.test.ts"
60
+ }
61
+ ]
62
+ }
@@ -393,17 +393,6 @@
393
393
  "signature": "[QK:FRESHCALL-CODEX-PREMUTATION-MCP]",
394
394
  "signatureSource": "test/fresh-call-surfaces.contract.test.ts"
395
395
  },
396
- {
397
- "claim": "FRESHCALL-CODEX-PREMUTATION-PI",
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",
399
- "subject": "pi-extensions/entwurf-control.ts",
400
- "find": ["\t\t\t\t\tbackend: params.backend,"],
401
- "replace": ["\t\t\t\t\tbackend: \"pi\","],
402
- "gate": ["bash", "run.sh", "check-mux-fresh-call"],
403
- "timeoutSeconds": 180,
404
- "signature": "[QK:FRESHCALL-CODEX-PREMUTATION-PI]",
405
- "signatureSource": "test/fresh-call-surfaces.contract.test.ts"
406
- },
407
396
  {
408
397
  "claim": "CODEX-BIRTH-DOCTOR-REQUIRES-TRUST",
409
398
  "title": "the doctor treats the vendor trust receipt as optional, so a declared hook the vendor will never run reports green",
@@ -648,6 +637,17 @@
648
637
  "signature": "[QK:CODEX-LIVE-REPORT-TOKEN-EXACT]",
649
638
  "signatureSource": "test/codex-fresh-live-protocol.test.ts"
650
639
  },
640
+ {
641
+ "claim": "CODEX-LIVE-PI-MCP-SOURCE-DIALECT",
642
+ "title": "Pi's current qualified fresh-call receipt no longer reaches semantic launch and cleanup authority, recreating the Pi 1.0 timeout",
643
+ "subject": "scripts/lib/codex-fresh-source-receipts.ts",
644
+ "find": ["\t[\"mcp__entwurf_bridge__entwurf_fresh_call\", \"entwurf_fresh_call\"],"],
645
+ "replace": ["\t[\"mcp__entwurf_bridge__entwurf_fresh_call\", \"unrecognized_pi_fresh_call\"],"],
646
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
647
+ "timeoutSeconds": 180,
648
+ "signature": "[QK:CODEX-LIVE-PI-MCP-SOURCE-DIALECT]",
649
+ "signatureSource": "test/codex-fresh-live-protocol.test.ts"
650
+ },
651
651
  {
652
652
  "claim": "CODEX-LIVE-SOURCE-JOIN",
653
653
  "title": "a Pi tool result can be joined to a call whose tool name differs, turning an unrelated result body into launch authority",
@@ -174,14 +174,15 @@
174
174
  "gate": ["bash", "run.sh", "check-tests-beside-behavior"],
175
175
  "timeoutSeconds": 600,
176
176
  "signature": "[QK:VITEST-TEST-DIR-ON-THE-FLOOR]",
177
- "signatureSource": "run.sh"
177
+ "signatureSource": "run.sh",
178
+ "build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
178
179
  },
179
180
  {
180
181
  "claim": "PI-CORE-PIN-TRACKS-FLOOR",
181
182
  "title": "the queue oracle's pi-agent-core pin drifts off the floor the rest of the pi runtime is pinned to, so the oracle keeps answering honestly — about a pi nobody in this repo runs",
182
183
  "subject": "package.json",
183
- "find": ["\"@earendil-works/pi-agent-core\": \"0.87.1\","],
184
- "replace": ["\"@earendil-works/pi-agent-core\": \"0.86.0\","],
184
+ "find": ["\"@earendil-works/pi-agent-core\": \"1.0.0\","],
185
+ "replace": ["\"@earendil-works/pi-agent-core\": \"0.87.1\","],
185
186
  "gate": ["bash", "run.sh", "check-dep-versions"],
186
187
  "timeoutSeconds": 300,
187
188
  "signature": "[QK:PI-CORE-PIN-TRACKS-FLOOR]",
@@ -218,7 +219,8 @@
218
219
  "gate": ["bash", "run.sh", "check-tests-beside-behavior"],
219
220
  "timeoutSeconds": 600,
220
221
  "signature": "[QK:VITEST-TEST-DIR-HAS-COORDINATE]",
221
- "signatureSource": "run.sh"
222
+ "signatureSource": "run.sh",
223
+ "build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
222
224
  },
223
225
  {
224
226
  "claim": "SEND-OUTCOME-LIST-NAMES-EVERY-RAIL",
@@ -101,7 +101,8 @@
101
101
  "gate": ["bash", "run.sh", "check-meta-doctor-oracle"],
102
102
  "timeoutSeconds": 600,
103
103
  "signature": "[QK:HOOK-LOG-RAIL-SCOPED]",
104
- "signatureSource": "scripts/check-meta-doctor-oracle.sh"
104
+ "signatureSource": "scripts/check-meta-doctor-oracle.sh",
105
+ "build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
105
106
  },
106
107
  {
107
108
  "claim": "COPILOT-BIRTH-DOES-NOT-ARM-RECEIVER",
@@ -75,8 +75,8 @@
75
75
  "signatureSource": "scripts/check-fresh-call-dispatch.ts"
76
76
  },
77
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",
78
+ "claim": "FCD-SURFACE-ROOT-ONLY",
79
+ "title": "the one public fresh-call surface goes back to choosing a rail itself instead of reaching the composition root, so rail choice lives outside the root again",
80
80
  "subject": "mcp/entwurf-bridge/src/index.ts",
81
81
  "find": [
82
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});"
@@ -86,18 +86,7 @@
86
86
  ],
87
87
  "gate": ["bash", "run.sh", "check-fresh-call-dispatch"],
88
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]",
89
+ "signature": "[QK:FCD-SURFACE-ROOT-ONLY]",
101
90
  "signatureSource": "scripts/check-fresh-call-dispatch.ts"
102
91
  },
103
92
  {
@@ -23,6 +23,65 @@
23
23
  "timeoutSeconds": 120,
24
24
  "signature": "[QK:LANE-INVENTORY-DECLARED]",
25
25
  "signatureSource": "scripts/check-gate-qualification.ts"
26
+ },
27
+ {
28
+ "claim": "QUALIFY-BUILD-TRACKS-MUTATION",
29
+ "title": "the runner keeps the baseline build output across a mutation instead of rebuilding it from the mutated bytes — a gate that reads only the compiled output judges source it was never handed, and every mutant planted in the build's source survives (#125: the compiled entwurf-bridge a pi citizen registers)",
30
+ "subject": "scripts/lib/mutation-qualify.ts",
31
+ "find": ["\t\t\t\t\tconst b = await buildOutput(build, outputAbs, m.timeoutSeconds);"],
32
+ "replace": ["\t\t\t\t\tconst b = { run: pre, digest: baseline };"],
33
+ "gate": ["bash", "run.sh", "check-gate-manifests"],
34
+ "timeoutSeconds": 120,
35
+ "signature": "[QK:QUALIFY-BUILD-TRACKS-MUTATION]",
36
+ "signatureSource": "scripts/check-gate-qualification.ts"
37
+ },
38
+ {
39
+ "claim": "QUALIFY-BUILD-RED-NOT-A-KILL",
40
+ "title": "a mutation that breaks the declared build is attributed like a gate run — the build's own failure output is read for the claim token, so a broken build is certified as the gate killing the defect",
41
+ "subject": "scripts/lib/mutation-qualify.ts",
42
+ "find": [
43
+ "\t\t\t\tsignatureOnFailureLine: !buildRed && signatureAttributedToFailure(run.output, m.signature, run.failedTitles),"
44
+ ],
45
+ "replace": [
46
+ "\t\t\t\tsignatureOnFailureLine: signatureAttributedToFailure(run.output, m.signature, run.failedTitles),"
47
+ ],
48
+ "gate": ["bash", "run.sh", "check-gate-manifests"],
49
+ "timeoutSeconds": 120,
50
+ "signature": "[QK:QUALIFY-BUILD-RED-NOT-A-KILL]",
51
+ "signatureSource": "scripts/check-gate-qualification.ts"
52
+ },
53
+ {
54
+ "claim": "QUALIFY-BUILD-SCOPED-TO-GROUP",
55
+ "title": "the declared build output outlives its group — a later group runs against an input it never declared, and the ignored output is left in the snapshot",
56
+ "subject": "scripts/lib/mutation-qualify.ts",
57
+ "find": ["\t\t\tif (outputAbs) fs.rmSync(outputAbs, { recursive: true, force: true });"],
58
+ "replace": ["\t\t\tif (outputAbs) void 0;"],
59
+ "gate": ["bash", "run.sh", "check-gate-manifests"],
60
+ "timeoutSeconds": 120,
61
+ "signature": "[QK:QUALIFY-BUILD-SCOPED-TO-GROUP]",
62
+ "signatureSource": "scripts/check-gate-qualification.ts"
63
+ },
64
+ {
65
+ "claim": "QUALIFY-BUILD-OUTPUT-GUARDED",
66
+ "title": "a gate that writes into its declared build output keeps its KILLED verdict — the next run is judged against bytes no build produced",
67
+ "subject": "scripts/lib/mutation-qualify.ts",
68
+ "find": ["\t\t\t\t\t\toutputWritten = wroteOutput(b.digest);"],
69
+ "replace": ["\t\t\t\t\t\toutputWritten = false;"],
70
+ "gate": ["bash", "run.sh", "check-gate-manifests"],
71
+ "timeoutSeconds": 120,
72
+ "signature": "[QK:QUALIFY-BUILD-OUTPUT-GUARDED]",
73
+ "signatureSource": "scripts/check-gate-qualification.ts"
74
+ },
75
+ {
76
+ "claim": "QUALIFY-BUILD-GROUP-CONSISTENT",
77
+ "title": "mutants of one gate may declare different builds (or one none) — the same gate is handed different inputs depending on run order, and a group's control no longer describes all of its mutants",
78
+ "subject": "scripts/lib/mutation-qualify.ts",
79
+ "find": ["\t\tif (mine !== first) {"],
80
+ "replace": ["\t\tif (mine !== first && false) {"],
81
+ "gate": ["bash", "run.sh", "check-gate-manifests"],
82
+ "timeoutSeconds": 120,
83
+ "signature": "[QK:QUALIFY-BUILD-GROUP-CONSISTENT]",
84
+ "signatureSource": "scripts/check-gate-qualification.ts"
26
85
  }
27
86
  ]
28
87
  }
@@ -68,6 +68,17 @@
68
68
  "signature": "[QK:HPB-SEQUENTIAL-TWO-STAGE]",
69
69
  "signatureSource": "scripts/check-herdr-plugin-build.ts"
70
70
  },
71
+ {
72
+ "claim": "HPB-DEFAULT-LOCK-READ",
73
+ "title": "reading the default lock from the repository root rather than the plugin directory breaks the real build while source-injected fixture drives stay green; the production composition must consume this plugin's committed source and artifact fields",
74
+ "subject": "plugins/herdr/lib/build.mjs",
75
+ "find": ["\tconst lock = lockReader(PLUGIN_DIR);"],
76
+ "replace": ["\tconst lock = lockReader(CHECKOUT_ROOT);"],
77
+ "gate": ["bash", "run.sh", "check-herdr-plugin-build"],
78
+ "timeoutSeconds": 300,
79
+ "signature": "[QK:HPB-DEFAULT-LOCK-READ]",
80
+ "signatureSource": "scripts/check-herdr-plugin-build.ts"
81
+ },
71
82
  {
72
83
  "claim": "HPB-POST-BUILD-GAP",
73
84
  "title": "claiming Herdr's registration in this runner's own receipt states a step that has not run: herdr commits its checkout and registry only AFTER the build returns, so the next reconcile would be arguing with a lie",
@@ -8,7 +8,7 @@
8
8
  "subject": "scripts/check-herdr-sandbox.ts",
9
9
  "find": ["const SUPPLY_MANIFEST = \"scripts/fixtures/herdr-supply.json\";"],
10
10
  "replace": [
11
- "const SUPPLY_MANIFEST = \"scripts/fixtures/herdr-supply.json\";\nconst PINNED_FALLBACK = \"0.9.1\";\nvoid PINNED_FALLBACK;"
11
+ "const SUPPLY_MANIFEST = \"scripts/fixtures/herdr-supply.json\";\nconst PINNED_FALLBACK = \"0.9.3\";\nvoid PINNED_FALLBACK;"
12
12
  ],
13
13
  "gate": ["bash", "run.sh", "check-herdr-supply"],
14
14
  "timeoutSeconds": 120,
@@ -19,8 +19,8 @@
19
19
  "claim": "HSUP-DIGEST-SHAPE",
20
20
  "title": "a pinned digest is truncated, so the check that is supposed to catch a swapped binary can no longer fail",
21
21
  "subject": "scripts/fixtures/herdr-supply.json",
22
- "find": ["\"sha256\": \"2a02fed16beb651ef006e1d43f048f652ca4dc58ad053cd2d44450563d5c54b7\""],
23
- "replace": ["\"sha256\": \"2a02fed16beb651ef006e1d43f04\""],
22
+ "find": ["\"sha256\": \"18a8dc65f1c2fa485884344356dea1cfd911c6f06cf46fa78e193f4087f4dba7\""],
23
+ "replace": ["\"sha256\": \"18a8dc65f1c2fa485884344356de\""],
24
24
  "gate": ["bash", "run.sh", "check-herdr-supply"],
25
25
  "timeoutSeconds": 120,
26
26
  "signature": "[QK:HSUP-DIGEST-SHAPE]",
@@ -121,8 +121,8 @@
121
121
  "signatureSource": "test/mux-fresh-call.test.ts"
122
122
  },
123
123
  {
124
- "claim": "FRESHCALL-CWD-SURFACE-PARITY",
125
- "title": "one surface drops the optional cwd from its schema, so cross-repo fresh works from pi and silently cannot exist from the MCP bridge",
124
+ "claim": "FRESHCALL-CWD-SURFACE",
125
+ "title": "the fresh-call surface drops the optional cwd from its schema, so cross-repo fresh silently cannot exist from any caller — pi included, which reaches this bridge since #125",
126
126
  "subject": "mcp/entwurf-bridge/src/index.ts",
127
127
  "find": [
128
128
  "\t\tcwd: z\n\t\t\t.string()\n\t\t\t.optional()\n\t\t\t.describe(\n\t\t\t\t\"Optional literal ABSOLUTE path of an existing directory to start the sibling in (cross-repo fresh). Omit or pass \\\"\\\" to start where the CALLER is — this agent's own cwd on BOTH rails, or for a Codex caller its own record directory, because this bridge is the app-server's child and that process's directory is not the caller's. Taken exactly as given: no trim, no realpath, no project-name resolution. '#' is refused on the tmux rail only, because tmux format-expands a start directory; inside herdr it is an ordinary path character. The receipt echoes the directory that was REQUESTED or the caller record it came from, never an observation of where the pane landed.\",\n\t\t\t),\n"
@@ -130,31 +130,7 @@
130
130
  "replace": [""],
131
131
  "gate": ["bash", "run.sh", "check-mux-fresh-call"],
132
132
  "timeoutSeconds": 120,
133
- "signature": "[QK:FRESHCALL-CWD-SURFACE-PARITY]",
134
- "signatureSource": "test/fresh-call-surfaces.contract.test.ts"
135
- },
136
- {
137
- "claim": "FRESHCALL-PI-SURFACE-IDENTITY",
138
- "title": "native pi takes the caller garden id from the environment instead of its own resident closure — the uuidv7 confusion, reintroduced",
139
- "subject": "pi-extensions/entwurf-control.ts",
140
- "find": ["\t\t\t\t\tcallerGardenId: residentGardenId,"],
141
- "replace": ["\t\t\t\t\tcallerGardenId: process.env.PI_SESSION_ID ?? null,"],
142
- "gate": ["bash", "run.sh", "check-mux-fresh-call"],
143
- "timeoutSeconds": 120,
144
- "signature": "[QK:FRESHCALL-PI-SURFACE-IDENTITY]",
145
- "signatureSource": "test/fresh-call-surfaces.contract.test.ts"
146
- },
147
- {
148
- "claim": "FRESHCALL-PI-MODEL-SCHEMA",
149
- "title": "native pi drops the required model field from fresh-call while the composition still expects one",
150
- "subject": "pi-extensions/entwurf-control.ts",
151
- "find": [
152
- "\t\t\tmodel: Type.String({\n\t\t\t\tminLength: 1,\n\t\t\t\tmaxLength: 200,\n\t\t\t\tpattern: \"^[A-Za-z0-9][A-Za-z0-9._/:\\\\[\\\\]-]*$\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Required runtime model: canonical provider/model for pi, a Claude Code model id/alias, or a Copilot/OMP/Codex model name.\",\n\t\t\t}),\n"
153
- ],
154
- "replace": [""],
155
- "gate": ["bash", "run.sh", "check-mux-fresh-call"],
156
- "timeoutSeconds": 120,
157
- "signature": "[QK:FRESHCALL-PI-MODEL-SCHEMA]",
133
+ "signature": "[QK:FRESHCALL-CWD-SURFACE]",
158
134
  "signatureSource": "test/fresh-call-surfaces.contract.test.ts"
159
135
  },
160
136
  {
@@ -196,10 +172,10 @@
196
172
  },
197
173
  {
198
174
  "claim": "FRESHCALL-MODEL-PATTERN-PROVIDER-VALID",
199
- "title": "the same unescape planted on the TypeBox surface rides pi-ai's real anthropic-messages conversion into the request body as an invalid Rust-family pattern",
200
- "subject": "pi-extensions/entwurf-control.ts",
201
- "find": ["\t\t\t\tpattern: \"^[A-Za-z0-9][A-Za-z0-9._/:\\\\[\\\\]-]*$\","],
202
- "replace": ["\t\t\t\tpattern: \"^[A-Za-z0-9][A-Za-z0-9._/:[\\\\]-]*$\","],
175
+ "title": "the #62 unescape planted on the bridge's zod pattern rides Pi's built-in MCP spread and pi-ai's real anthropic-messages conversion into the request body as an invalid Rust-family pattern",
176
+ "subject": "mcp/entwurf-bridge/src/index.ts",
177
+ "find": ["\t\t\t.regex(/^[A-Za-z0-9][A-Za-z0-9._/:\\[\\]-]*$/)"],
178
+ "replace": ["\t\t\t.regex(/^[A-Za-z0-9][A-Za-z0-9._/:[\\]-]*$/)"],
203
179
  "gate": ["bash", "run.sh", "check-mux-fresh-call"],
204
180
  "timeoutSeconds": 120,
205
181
  "signature": "[QK:FRESHCALL-MODEL-PATTERN-PROVIDER-VALID]",
@@ -284,6 +260,39 @@
284
260
  "signature": "[QK:FRESHCALL-COPILOT-CALLBACK-TOOL]",
285
261
  "signatureSource": "test/mux-fresh-call.test.ts"
286
262
  },
263
+ {
264
+ "claim": "FRESHCALL-PI-CALLBACK-DIALECT",
265
+ "title": "pi callback rolls back to the 0.99.1 hyphen spelling, which a 0.99.2 host no longer declares — the first turn is spent on a tool that is not there",
266
+ "subject": "pi-extensions/lib/fresh-call-composition.ts",
267
+ "find": ["\tpi: \"mcp__entwurf_bridge__entwurf_callback\","],
268
+ "replace": ["\tpi: \"mcp__entwurf-bridge__entwurf_callback\","],
269
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
270
+ "timeoutSeconds": 180,
271
+ "signature": "[QK:FRESHCALL-PI-CALLBACK-DIALECT]",
272
+ "signatureSource": "test/mux-fresh-call.test.ts"
273
+ },
274
+ {
275
+ "claim": "FRESHCALL-PI-DELIVERY-DIALECT",
276
+ "title": "pi delivery rolls back to the 0.99.1 hyphen spelling — the result is sent to a tool a 0.99.2 host does not declare",
277
+ "subject": "pi-extensions/lib/fresh-call-composition.ts",
278
+ "find": ["\tpi: \"mcp__entwurf_bridge__entwurf_v2\","],
279
+ "replace": ["\tpi: \"mcp__entwurf-bridge__entwurf_v2\","],
280
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
281
+ "timeoutSeconds": 180,
282
+ "signature": "[QK:FRESHCALL-PI-DELIVERY-DIALECT]",
283
+ "signatureSource": "test/mux-fresh-call.test.ts"
284
+ },
285
+ {
286
+ "claim": "FRESHCALL-PI-PEERS-DIALECT",
287
+ "title": "pi peers offer rolls back to the 0.99.1 hyphen spelling — the corroboration tool is named in a spelling the sibling cannot reach",
288
+ "subject": "pi-extensions/lib/fresh-call-composition.ts",
289
+ "find": ["\tpi: \"mcp__entwurf_bridge__entwurf_peers\","],
290
+ "replace": ["\tpi: \"mcp__entwurf-bridge__entwurf_peers\","],
291
+ "gate": ["bash", "run.sh", "check-mux-fresh-call"],
292
+ "timeoutSeconds": 180,
293
+ "signature": "[QK:FRESHCALL-PI-PEERS-DIALECT]",
294
+ "signatureSource": "test/mux-fresh-call.test.ts"
295
+ },
287
296
  {
288
297
  "claim": "FRESHCALL-COPILOT-PREFLIGHT-PREMUTATION",
289
298
  "title": "the capability preflight is removed — a host missing the birth, MCP, receiver or footer unit gets a real window and a launch receipt for a sibling that can never call home",
@@ -430,17 +439,6 @@
430
439
  "signature": "[QK:FRESHCALL-COPILOT-EXPLICIT-POLICY]",
431
440
  "signatureSource": "test/mux-fresh-call.test.ts"
432
441
  },
433
- {
434
- "claim": "FRESHCALL-BACKEND-SET-SURFACE-PARITY-PI",
435
- "title": "a backend the composition can open is missing from the native pi surface enum — an in-process pi session cannot name a capability the module already opens",
436
- "subject": "pi-extensions/entwurf-control.ts",
437
- "find": ["\t\t\tbackend: StringEnum([\"pi\", \"claude-code\", \"copilot\", \"omp\", \"codex\"], {"],
438
- "replace": ["\t\t\tbackend: StringEnum([\"pi\", \"claude-code\", \"copilot\", \"omp\"], {"],
439
- "gate": ["bash", "run.sh", "check-mux-fresh-call"],
440
- "timeoutSeconds": 180,
441
- "signature": "[QK:FRESHCALL-BACKEND-SET-SURFACE-PARITY-PI]",
442
- "signatureSource": "test/fresh-call-surfaces.contract.test.ts"
443
- },
444
442
  {
445
443
  "claim": "TMUXSESSION-LOOKUP-ENGINE",
446
444
  "title": "the seat lookup goes back to the `-f` filter engine, which was measured to match EVERY session when the name contains a '}' — a fresh sibling then opens in whichever session tmux listed first",
@@ -510,8 +508,8 @@
510
508
  "signatureSource": "test/mux-fresh-call.test.ts"
511
509
  },
512
510
  {
513
- "claim": "FRESHCALL-PLACEMENT-SURFACE-PARITY",
514
- "title": "one surface drops the optional seat from its schema, so opening a sibling in the operator's project session works from pi and silently cannot exist from the MCP bridge",
511
+ "claim": "FRESHCALL-PLACEMENT-SURFACE",
512
+ "title": "the fresh-call surface drops the optional seat from its schema, so opening a sibling in the operator's project session silently cannot exist from any caller",
515
513
  "subject": "mcp/entwurf-bridge/src/index.ts",
516
514
  "find": [
517
515
  "\t\tplacement: z\n\t\t\t.object({\n\t\t\t\ttmuxSession: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.describe(\n\t\t\t\t\t\t\"EXACT name of an EXISTING session on this agent's own tmux server. Nothing is created: an absent session is refused as tmux-session-missing, and a name outside [A-Za-z0-9][A-Za-z0-9_-]* as tmux-session-name-invalid.\",\n\t\t\t\t\t),\n\t\t\t})\n\t\t\t.optional()\n\t\t\t.describe(\n\t\t\t\t\"Optional expert seat override, TMUX ONLY: open the sibling in ONE EXISTING tmux session of this agent's own server, and it always wins. When omitted the seat follows the CALLER, never the backend being opened: a Codex CALLER opens beside its own TUI pane, matched by thread-id in that pane's terminal title (0 or 2+ matching panes refuse, never fall back); every other caller opens in its own session. A pane title is a placement input only — never an address, liveness or delivery fact. Nothing is ever created. Inside herdr this field is refused by name — placement there belongs to herdr, and a tmux session name would silently place the sibling somewhere else. Independent of cwd; neither is inferred from the other. The receipt reports the selected name (absent for the caller-pane rule, which observed a session rather than requesting a name), its source, and resolved target session id.\",\n\t\t\t),\n"
@@ -519,7 +517,7 @@
519
517
  "replace": [""],
520
518
  "gate": ["bash", "run.sh", "check-mux-fresh-call"],
521
519
  "timeoutSeconds": 180,
522
- "signature": "[QK:FRESHCALL-PLACEMENT-SURFACE-PARITY]",
520
+ "signature": "[QK:FRESHCALL-PLACEMENT-SURFACE]",
523
521
  "signatureSource": "test/fresh-call-surfaces.contract.test.ts"
524
522
  },
525
523
  {
@@ -93,55 +93,31 @@
93
93
  "signatureSource": "scripts/check-mux-resume-call.ts"
94
94
  },
95
95
  {
96
- "claim": "MUXRESUME-PI-SURFACE-REGISTERED",
97
- "title": "the native pi registration is never called, so the verb exists in source and nowhere an operator can reach",
98
- "subject": "pi-extensions/entwurf-control.ts",
99
- "find": ["\t\tregisterResumeCallTool(pi);"],
100
- "replace": ["\t\tvoid registerResumeCallTool;"],
101
- "gate": ["bash", "run.sh", "check-mux-resume-call"],
102
- "timeoutSeconds": 60,
103
- "signature": "[QK:MUXRESUME-PI-SURFACE-REGISTERED]",
104
- "signatureSource": "scripts/check-mux-resume-call.ts"
105
- },
106
- {
107
- "claim": "MUXRESUME-PI-SURFACE-TARGET-ONLY",
108
- "title": "a task knob is added to the native schema, re-opening the prompt axis a resume deliberately does not have",
109
- "subject": "pi-extensions/entwurf-control.ts",
96
+ "claim": "MUXRESUME-DESC-CONTRACT-MCP",
97
+ "title": "the MCP description drops the dormant-only scope, inviting callers to aim the verb at live citizens it will refuse",
98
+ "subject": "mcp/entwurf-bridge/src/index.ts",
110
99
  "find": [
111
- "\t\t\t\tdescription: \"Garden id of the DORMANT pi citizen to reopen (discover with entwurf_peers).\",\n\t\t\t}),"
100
+ "\t\"Reopen ONE DORMANT pi citizen under its OWN garden id, in a visible window in the operator's own tmux \""
112
101
  ],
113
102
  "replace": [
114
- "\t\t\t\tdescription: \"Garden id of the DORMANT pi citizen to reopen (discover with entwurf_peers).\",\n\t\t\t}),\n\t\t\ttask: Type.String({ description: \"What the resumed citizen should do.\" }),"
103
+ "\t\"Reopen ONE pi citizen under its OWN garden id, in a visible window in the operator's own tmux \""
115
104
  ],
116
105
  "gate": ["bash", "run.sh", "check-mux-resume-call"],
117
106
  "timeoutSeconds": 60,
118
- "signature": "[QK:MUXRESUME-PI-SURFACE-TARGET-ONLY]",
119
- "signatureSource": "scripts/check-mux-resume-call.ts"
120
- },
121
- {
122
- "claim": "MUXRESUME-DESC-CONTRACT-PI",
123
- "title": "the native description stops saying a resume runs no turn, so a caller reasonably expects the citizen to act on being reopened",
124
- "subject": "pi-extensions/entwurf-control.ts",
125
- "find": ["This runs NO turn: the window comes\nback with the conversation and waits"],
126
- "replace": ["The window comes\nback with the conversation and waits"],
127
- "gate": ["bash", "run.sh", "check-mux-resume-call"],
128
- "timeoutSeconds": 60,
129
- "signature": "[QK:MUXRESUME-DESC-CONTRACT-PI]",
107
+ "signature": "[QK:MUXRESUME-DESC-CONTRACT-MCP]",
130
108
  "signatureSource": "scripts/check-mux-resume-call.ts"
131
109
  },
132
110
  {
133
- "claim": "MUXRESUME-DESC-CONTRACT-MCP",
134
- "title": "the MCP description drops the dormant-only scope, inviting callers to aim the verb at live citizens it will refuse",
111
+ "claim": "MUXRESUME-MCP-TARGET-PASSTHROUGH",
112
+ "title": "the bridge resume handler substitutes a constant id for the caller's target, so the record lookup reopens a citizen nobody named while the target-only schema stays green",
135
113
  "subject": "mcp/entwurf-bridge/src/index.ts",
136
- "find": [
137
- "\t\"Reopen ONE DORMANT pi citizen under its OWN garden id, in a visible window in the operator's own tmux \""
138
- ],
114
+ "find": ["\t\t\tconst result = await visibleResume(target, makeVisibleResumeDeps(visibleResumeLaunch));"],
139
115
  "replace": [
140
- "\t\"Reopen ONE pi citizen under its OWN garden id, in a visible window in the operator's own tmux \""
116
+ "\t\t\tconst result = await visibleResume(\"20260101T000000-feed00\", makeVisibleResumeDeps(visibleResumeLaunch));"
141
117
  ],
142
118
  "gate": ["bash", "run.sh", "check-mux-resume-call"],
143
119
  "timeoutSeconds": 60,
144
- "signature": "[QK:MUXRESUME-DESC-CONTRACT-MCP]",
120
+ "signature": "[QK:MUXRESUME-MCP-TARGET-PASSTHROUGH]",
145
121
  "signatureSource": "scripts/check-mux-resume-call.ts"
146
122
  }
147
123
  ]
@@ -6,8 +6,8 @@
6
6
  "claim": "PACK-INSTALL-PIN-MATCHER-BOUNDED",
7
7
  "title": "the pin-leak matcher loses its version boundary and blesses substring lookalikes — @0.85.10 reads as the pinned 0.85.1 and the gate announces a verified tree it never verified (independent review, 2026-08-25)",
8
8
  "subject": "run.sh",
9
- "find": [" grep '^@earendil-works+' | grep -Ev '@0\\.87\\.1(_|$)' || true"],
10
- "replace": [" grep '^@earendil-works+' | grep -v '@0\\.87\\.0' || true"],
9
+ "find": [" grep '^@earendil-works+' | grep -Ev '@1\\.0\\.0(_|$)' || true"],
10
+ "replace": [" grep '^@earendil-works+' | grep -v '@0\\.87\\.1' || true"],
11
11
  "gate": ["bash", "run.sh", "check-pack-pin-matcher"],
12
12
  "timeoutSeconds": 120,
13
13
  "signature": "[QK:PACK-INSTALL-PIN-MATCHER-BOUNDED]",
@@ -17,12 +17,23 @@
17
17
  "claim": "PACK-INSTALL-PIN-MATCHER-COVERS-CLOSURE",
18
18
  "title": "the pin-leak matcher narrows back to the pi-* families and goes blind to a non-pi member of the same runtime closure — @earendil-works/chord (new in pi 0.85.0, a runtime dependency of pi-coding-agent/pi-agent-core/pi-client/pi-protocol) floats unpinned while the gate prints a verified pin (measured 2026-09-06 on a real 0.85.1 install tree)",
19
19
  "subject": "run.sh",
20
- "find": [" grep '^@earendil-works+' | grep -Ev '@0\\.87\\.1(_|$)' || true"],
21
- "replace": [" grep '^@earendil-works+pi-' | grep -Ev '@0\\.87\\.1(_|$)' || true"],
20
+ "find": [" grep '^@earendil-works+' | grep -Ev '@1\\.0\\.0(_|$)' || true"],
21
+ "replace": [" grep '^@earendil-works+pi-' | grep -Ev '@1\\.0\\.0(_|$)' || true"],
22
22
  "gate": ["bash", "run.sh", "check-pack-pin-matcher"],
23
23
  "timeoutSeconds": 120,
24
24
  "signature": "[QK:PACK-INSTALL-PIN-MATCHER-COVERS-CLOSURE]",
25
25
  "signatureSource": "run.sh"
26
+ },
27
+ {
28
+ "claim": "PACK-INSTALL-CONSUMER-ROOTS-CONTAINED",
29
+ "title": "a consumer subcall stops naming its own PI_CODING_AGENT_DIR, so an inherited agent dir wins over the sandbox HOME and the consumer's user-scope registration lands outside it (measured 2026-10-01, #125)",
30
+ "subject": "run.sh",
31
+ "find": [" \"XDG_CACHE_HOME=$h/.cache\" \\\n \"PI_CODING_AGENT_DIR=$h/.pi/agent\""],
32
+ "replace": [" \"XDG_CACHE_HOME=$h/.cache\""],
33
+ "gate": ["bash", "run.sh", "check-pack-consumer-roots"],
34
+ "timeoutSeconds": 120,
35
+ "signature": "[QK:PACK-INSTALL-CONSUMER-ROOTS-CONTAINED]",
36
+ "signatureSource": "run.sh"
26
37
  }
27
38
  ]
28
39
  }
@@ -0,0 +1,54 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "pi-bridge-sender",
4
+ "mutants": [
5
+ {
6
+ "claim": "PI-BRIDGE-SENDER-RECORD-BACKED",
7
+ "title": "the backing check starts treating a missing control socket as inadmissible, so a dormant pi citizen loses its own identity instead of answering replyable:false",
8
+ "subject": "mcp/entwurf-bridge/src/index.ts",
9
+ "find": ["\tif (identity.backend !== \"pi\") {"],
10
+ "replace": [
11
+ "\tif (identity.backend !== \"pi\" || !existsSync(controlSocketPathIn(ENTWURF_DIR, envelope.sessionId))) {"
12
+ ],
13
+ "gate": ["bash", "run.sh", "check-pi-bridge-sender"],
14
+ "timeoutSeconds": 60,
15
+ "signature": "[QK:PI-BRIDGE-SENDER-RECORD-BACKED]",
16
+ "signatureSource": "scripts/check-pi-bridge-sender.ts"
17
+ },
18
+ {
19
+ "claim": "PI-BRIDGE-SENDER-MISSING-REFUSED",
20
+ "title": "the pi branch returns the raw carrier again, so any well-formed PI_SESSION_ID is served as a sender whether or not a record exists",
21
+ "subject": "mcp/entwurf-bridge/src/index.ts",
22
+ "find": ["\tif (pi && pi.sessionId === selected.id) return { envelope: requirePiSenderRecord(pi) };"],
23
+ "replace": ["\tif (pi && pi.sessionId === selected.id) return { envelope: pi };"],
24
+ "gate": ["bash", "run.sh", "check-pi-bridge-sender"],
25
+ "timeoutSeconds": 60,
26
+ "signature": "[QK:PI-BRIDGE-SENDER-MISSING-REFUSED]",
27
+ "signatureSource": "scripts/check-pi-bridge-sender.ts"
28
+ },
29
+ {
30
+ "claim": "PI-BRIDGE-SENDER-BACKEND-REFUSED",
31
+ "title": "the backend check is dropped, so a PI_SESSION_ID naming another harness's record is served as a pi sender",
32
+ "subject": "mcp/entwurf-bridge/src/index.ts",
33
+ "find": ["\tif (identity.backend !== \"pi\") {"],
34
+ "replace": ["\tif (identity.backend === undefined) {"],
35
+ "gate": ["bash", "run.sh", "check-pi-bridge-sender"],
36
+ "timeoutSeconds": 60,
37
+ "signature": "[QK:PI-BRIDGE-SENDER-BACKEND-REFUSED]",
38
+ "signatureSource": "scripts/check-pi-bridge-sender.ts"
39
+ },
40
+ {
41
+ "claim": "PI-BRIDGE-SENDER-UNREADABLE-CAUSE",
42
+ "title": "reader failures are flattened into the absent-record refusal, so a corrupt store reads as a citizen that simply does not exist",
43
+ "subject": "mcp/entwurf-bridge/src/index.ts",
44
+ "find": ["\tconst identity = readMetaIdentityByGardenId(envelope.sessionId);"],
45
+ "replace": [
46
+ "\tconst identity = (() => {\n\t\ttry {\n\t\t\treturn readMetaIdentityByGardenId(envelope.sessionId);\n\t\t} catch {\n\t\t\tthrow new Error(`no meta-record for garden id \"${envelope.sessionId}\"`);\n\t\t}\n\t})();"
47
+ ],
48
+ "gate": ["bash", "run.sh", "check-pi-bridge-sender"],
49
+ "timeoutSeconds": 60,
50
+ "signature": "[QK:PI-BRIDGE-SENDER-UNREADABLE-CAUSE]",
51
+ "signatureSource": "scripts/check-pi-bridge-sender.ts"
52
+ }
53
+ ]
54
+ }
@@ -6,8 +6,12 @@
6
6
  "claim": "PI-FLOOR-SINGLE-SOURCE",
7
7
  "title": "one row of the pnpm workspace closure is left on the previous floor while every other surface moved — the shape a version bump actually fails in. Nothing else reads that file, so the stranded row surfaces only at install time, in a different command, far from the change that stranded it",
8
8
  "subject": "pnpm-workspace.yaml",
9
- "find": [" - '@earendil-works/pi-telemetry@0.85.0 || 0.85.1 || 0.86.0 || 0.87.0 || 0.87.1'"],
10
- "replace": [" - '@earendil-works/pi-telemetry@0.85.0 || 0.85.1 || 0.86.0'"],
9
+ "find": [
10
+ " - '@earendil-works/pi-telemetry@0.85.0 || 0.85.1 || 0.86.0 || 0.87.0 || 0.87.1 || 0.99.1 || 0.99.2 || 1.0.0'"
11
+ ],
12
+ "replace": [
13
+ " - '@earendil-works/pi-telemetry@0.85.0 || 0.85.1 || 0.86.0 || 0.87.0 || 0.87.1 || 0.99.1 || 0.99.2'"
14
+ ],
11
15
  "gate": ["bash", "run.sh", "check-dep-versions"],
12
16
  "timeoutSeconds": 300,
13
17
  "signature": "[QK:PI-FLOOR-SINGLE-SOURCE]",