@junghanacs/entwurf 0.13.0 → 0.13.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 (72) hide show
  1. package/AGENTS.md +5 -3
  2. package/BASELINE.md +57 -203
  3. package/CHANGELOG.md +19 -0
  4. package/CONTRIBUTING.md +1 -1
  5. package/DELIVERY.md +117 -261
  6. package/README.md +68 -408
  7. package/VERIFY.md +58 -87
  8. package/demo/README.md +1 -1
  9. package/docs/acp-backend-rail.md +231 -0
  10. package/docs/external-mcp-host.md +132 -0
  11. package/docs/fresh-cut-policy.md +99 -0
  12. package/docs/setup-clean-host.md +123 -328
  13. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +21 -48
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/acp-client.js +12 -0
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +11 -10
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/config.js +1 -1
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/engraving.js +42 -1
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/models.js +4 -4
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/overlay.js +3 -3
  20. package/mcp/entwurf-bridge/src/index.ts +21 -48
  21. package/package.json +12 -9
  22. package/pi-extensions/entwurf-control.ts +20 -49
  23. package/pi-extensions/lib/acp/acp-client.ts +22 -0
  24. package/pi-extensions/lib/acp/augment.ts +42 -3
  25. package/pi-extensions/lib/acp/backend-adapter.ts +12 -11
  26. package/pi-extensions/lib/acp/backend.ts +305 -36
  27. package/pi-extensions/lib/acp/config.ts +1 -1
  28. package/pi-extensions/lib/acp/engraving.ts +43 -1
  29. package/pi-extensions/lib/acp/event-mapper.ts +16 -13
  30. package/pi-extensions/lib/acp/models.ts +4 -4
  31. package/pi-extensions/lib/acp/overlay.ts +3 -3
  32. package/prompts/engraving.md +13 -5
  33. package/run.sh +244 -108
  34. package/scripts/check-acp-carrier-augment.ts +246 -10
  35. package/scripts/check-acp-cortex.ts +5 -5
  36. package/scripts/check-acp-prompt-lifecycle.ts +565 -0
  37. package/scripts/check-acp-sdk-surface.ts +60 -21
  38. package/scripts/check-acp-stop-reason.ts +342 -0
  39. package/scripts/check-entwurf-v2-surface.ts +41 -0
  40. package/scripts/check-gate-qualification.ts +6 -3
  41. package/scripts/check-probe-ordering.ts +39 -7
  42. package/scripts/check-release-gate-outcomes.ts +332 -0
  43. package/scripts/lib/live-skip.ts +33 -0
  44. package/scripts/lib/probe-acp-turn.ts +33 -12
  45. package/scripts/lib/step-outcome.sh +88 -0
  46. package/scripts/mutants/acp-augment.json +106 -0
  47. package/scripts/mutants/acp-cortex.json +2 -2
  48. package/scripts/mutants/acp-prompt-lifecycle.json +100 -0
  49. package/scripts/mutants/acp-stop-reason.json +80 -0
  50. package/scripts/mutants/probe-ordering.json +27 -5
  51. package/scripts/mutants/release-gate.json +105 -0
  52. package/scripts/mutants/v2-surface.json +26 -15
  53. package/scripts/smoke-acp-bundled-mcp-live.ts +4 -3
  54. package/scripts/smoke-acp-carrier-augment-live.ts +2 -2
  55. package/scripts/smoke-acp-cortex-live.ts +8 -14
  56. package/scripts/smoke-acp-long-turn-live.ts +185 -0
  57. package/scripts/smoke-acp-mcp-live.ts +2 -2
  58. package/scripts/smoke-acp-memory-containment-live.ts +2 -2
  59. package/scripts/smoke-acp-ordering-probe-live.ts +2 -2
  60. package/scripts/smoke-acp-overlay-live.ts +2 -2
  61. package/scripts/smoke-acp-provider-live.ts +2 -2
  62. package/scripts/smoke-acp-raw-turn-live.ts +3 -3
  63. package/scripts/smoke-acp-session-reuse-live.ts +2 -2
  64. package/scripts/smoke-acp-skill-live.ts +2 -2
  65. package/scripts/smoke-acp-socket-citizen-live.ts +4 -3
  66. package/scripts/smoke-acp-v2-send-live.ts +4 -3
  67. package/scripts/smoke-agy-native-push-live.ts +4 -3
  68. package/scripts/smoke-claude-native-resume-live.sh +13 -3
  69. package/scripts/smoke-entwurf-chain-live.ts +352 -0
  70. package/scripts/smoke-entwurf-v2-matrix-live.ts +2 -2
  71. package/scripts/smoke-entwurf-v2-spawn-resume-live.ts +2 -4
  72. package/scripts/smoke-meta-install-state.sh +4 -0
@@ -142,13 +142,13 @@
142
142
  "\t\tawait setConfig.call(connection, { sessionId: acpSessionId, configId: \"model\", value: nativeModelId });",
143
143
  "\t},",
144
144
  "",
145
- "\t// A connection change must invalidate a reused session (§4/§7). Flat,"
145
+ "\t// A connection change must invalidate a reused session (rail: Adapter contract). Flat,"
146
146
  ],
147
147
  "replace": [
148
148
  "\t\tawait setConfig.call(connection, { sessionId: acpSessionId, configId: \"model\", value: \"auto\" });",
149
149
  "\t},",
150
150
  "",
151
- "\t// A connection change must invalidate a reused session (§4/§7). Flat,"
151
+ "\t// A connection change must invalidate a reused session (rail: Adapter contract). Flat,"
152
152
  ],
153
153
  "gate": ["bash", "run.sh", "check-acp-cortex"],
154
154
  "timeoutSeconds": 300,
@@ -0,0 +1,100 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "acp-prompt-lifecycle",
4
+ "mutants": [
5
+ {
6
+ "claim": "PROMPT-STALL-NOT-KILLED",
7
+ "title": "an absolute wall clock re-planted on the in-flight prompt — a turn that is still working is cut for being long",
8
+ "subject": "pi-extensions/lib/acp/backend.ts",
9
+ "find": ["\t\treturn await Promise.race([session.connection.prompt(promptArgs), lifecycle]);"],
10
+ "replace": [
11
+ "\t\treturn await Promise.race([\n\t\t\tsession.connection.prompt(promptArgs),\n\t\t\tlifecycle,\n\t\t\tnew Promise<never>((_, reject) => setTimeout(() => reject(new Error(\"prompt timed out after 100ms\")), 100)),\n\t\t]);"
12
+ ],
13
+ "gate": ["bash", "run.sh", "check-acp-prompt-lifecycle"],
14
+ "timeoutSeconds": 180,
15
+ "signature": "[QK:PROMPT-STALL-NOT-KILLED]",
16
+ "signatureSource": "scripts/check-acp-prompt-lifecycle.ts"
17
+ },
18
+ {
19
+ "claim": "ABORT-SENDS-PROTOCOL-CANCEL",
20
+ "title": "abort stops asking the agent to cancel its own turn — back to killing a child mid-tool instead of the protocol ending",
21
+ "subject": "pi-extensions/lib/acp/backend.ts",
22
+ "find": ["\t\t\tsession.connection.cancel?.({ sessionId: promptArgs.sessionId });"],
23
+ "replace": ["\t\t\tvoid promptArgs;"],
24
+ "gate": ["bash", "run.sh", "check-acp-prompt-lifecycle"],
25
+ "timeoutSeconds": 180,
26
+ "signature": "[QK:ABORT-SENDS-PROTOCOL-CANCEL]",
27
+ "signatureSource": "scripts/check-acp-prompt-lifecycle.ts"
28
+ },
29
+ {
30
+ "claim": "ABORT-ESCALATION-BOUNDED",
31
+ "title": "the post-abort grace ignores the bound it was given — an abort against a wedged agent waits on a clock the caller does not control",
32
+ "subject": "pi-extensions/lib/acp/backend.ts",
33
+ "find": ["\t\tgraceTimer = setTimeout(escalateAbort, opts.graceMs);"],
34
+ "replace": ["\t\tgraceTimer = setTimeout(escalateAbort, 5_000);"],
35
+ "gate": ["bash", "run.sh", "check-acp-prompt-lifecycle"],
36
+ "timeoutSeconds": 180,
37
+ "signature": "[QK:ABORT-ESCALATION-BOUNDED]",
38
+ "signatureSource": "scripts/check-acp-prompt-lifecycle.ts"
39
+ },
40
+ {
41
+ "claim": "CHILD-EXIT-DIAGNOSED",
42
+ "title": "a mid-prompt child death stops reporting HOW it ended — the operator is back to an undiagnosable connection error",
43
+ "subject": "pi-extensions/lib/acp/backend.ts",
44
+ "find": [
45
+ "\tconst parts = [\n\t\texit.code !== null ? `exit code ${exit.code}` : undefined,\n\t\texit.signal ? `signal ${exit.signal}` : undefined,\n\t].filter(Boolean);\n\treturn parts.length > 0 ? parts.join(\", \") : \"no exit status\";"
46
+ ],
47
+ "replace": ["\treturn \"no exit status\";"],
48
+ "gate": ["bash", "run.sh", "check-acp-prompt-lifecycle"],
49
+ "timeoutSeconds": 180,
50
+ "signature": "[QK:CHILD-EXIT-DIAGNOSED]",
51
+ "signatureSource": "scripts/check-acp-prompt-lifecycle.ts"
52
+ },
53
+ {
54
+ "claim": "REUSE-CARRIES-CHILD-DIAGNOSTICS",
55
+ "title": "the reuse path drops the child's stderr tail again — exactly the live sonnet failure that showed only \"ACP connection closed\"",
56
+ "subject": "pi-extensions/lib/acp/backend.ts",
57
+ "find": ["\t\t\tfinishError(err, aborted, session.stderrTail);"],
58
+ "replace": ["\t\t\tfinishError(err, aborted);"],
59
+ "gate": ["bash", "run.sh", "check-acp-prompt-lifecycle"],
60
+ "timeoutSeconds": 180,
61
+ "signature": "[QK:REUSE-CARRIES-CHILD-DIAGNOSTICS]",
62
+ "signatureSource": "scripts/check-acp-prompt-lifecycle.ts"
63
+ },
64
+ {
65
+ "claim": "PROMPT-ERROR-NOT-TRANSIENT",
66
+ "title": "a prompt-phase lifecycle failure worded as a timeout — pi reclassifies it as transient and cold-replays the whole prompt",
67
+ "subject": "pi-extensions/lib/acp/backend.ts",
68
+ "find": ["\t\t\t\"this turn has no answer\","],
69
+ "replace": ["\t\t\t\"the prompt timed out\","],
70
+ "gate": ["bash", "run.sh", "check-acp-prompt-lifecycle"],
71
+ "timeoutSeconds": 180,
72
+ "signature": "[QK:PROMPT-ERROR-NOT-TRANSIENT]",
73
+ "signatureSource": "scripts/check-acp-prompt-lifecycle.ts"
74
+ },
75
+ {
76
+ "claim": "IDLE-DEATH-ANNOUNCED",
77
+ "title": "a backend session that died between turns is cleared but never announced — the next turn respawns silently and the operator never learns the session is gone",
78
+ "subject": "pi-extensions/lib/acp/backend.ts",
79
+ "find": [
80
+ "\t\t\tconst priorEnd = takeUnreportedChildEnd(sessionKey);\n\t\t\tif (priorEnd) {\n\t\t\t\tpushAcpLifecycleNotice(\n\t\t\t\t\tstate,\n\t\t\t\t\t`previous ${adapter.backend} session ended between turns (${describeChildEnd(priorEnd)}) — opening a new one`,\n\t\t\t\t);\n\t\t\t}"
81
+ ],
82
+ "replace": ["\t\t\ttakeUnreportedChildEnd(sessionKey);"],
83
+ "gate": ["bash", "run.sh", "check-acp-prompt-lifecycle"],
84
+ "timeoutSeconds": 180,
85
+ "signature": "[QK:IDLE-DEATH-ANNOUNCED]",
86
+ "signatureSource": "scripts/check-acp-prompt-lifecycle.ts"
87
+ },
88
+ {
89
+ "claim": "RETIRED-TEARDOWN-NOT-ANNOUNCED",
90
+ "title": "a teardown we performed ourselves is reported as a death — every ordinary turn-scoped turn cries wolf about its own cleanup",
91
+ "subject": "pi-extensions/lib/acp/backend.ts",
92
+ "find": ["\t} else if (!session.retiring) {"],
93
+ "replace": ["\t} else {"],
94
+ "gate": ["bash", "run.sh", "check-acp-prompt-lifecycle"],
95
+ "timeoutSeconds": 180,
96
+ "signature": "[QK:RETIRED-TEARDOWN-NOT-ANNOUNCED]",
97
+ "signatureSource": "scripts/check-acp-prompt-lifecycle.ts"
98
+ }
99
+ ]
100
+ }
@@ -0,0 +1,80 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "acp-stop-reason",
4
+ "mutants": [
5
+ {
6
+ "claim": "STOP-REFUSAL-NOT-SUCCESS",
7
+ "title": "a model refusal reported as a finished answer — the turn has no content, yet pi seals it done/stop",
8
+ "subject": "pi-extensions/lib/acp/backend.ts",
9
+ "find": [
10
+ "\t\tcase \"refusal\":\n\t\t\treturn {\n\t\t\t\tstopReason: \"error\",\n\t\t\t\trawStopReason: stopReason,\n\t\t\t\terrorMessage: \"ACP backend stopped with: refusal (the model declined to answer; the turn is incomplete)\",\n\t\t\t};"
11
+ ],
12
+ "replace": ["\t\tcase \"refusal\":\n\t\t\treturn { stopReason: \"stop\", rawStopReason: stopReason };"],
13
+ "gate": ["bash", "run.sh", "check-acp-stop-reason"],
14
+ "timeoutSeconds": 120,
15
+ "signature": "[QK:STOP-REFUSAL-NOT-SUCCESS]",
16
+ "signatureSource": "scripts/check-acp-stop-reason.ts"
17
+ },
18
+ {
19
+ "claim": "STOP-TURNBUDGET-NOT-SUCCESS",
20
+ "title": "an exhausted per-turn request budget reported as success — the answer is cut short but pi seals it done",
21
+ "subject": "pi-extensions/lib/acp/backend.ts",
22
+ "find": [
23
+ "\t\tcase \"max_turn_requests\":\n\t\t\treturn {\n\t\t\t\tstopReason: \"error\",\n\t\t\t\trawStopReason: stopReason,\n\t\t\t\terrorMessage:\n\t\t\t\t\t\"ACP backend stopped with: max_turn_requests (the backend's per-turn request budget was exhausted; the turn is incomplete)\",\n\t\t\t};"
24
+ ],
25
+ "replace": ["\t\tcase \"max_turn_requests\":\n\t\t\treturn { stopReason: \"stop\", rawStopReason: stopReason };"],
26
+ "gate": ["bash", "run.sh", "check-acp-stop-reason"],
27
+ "timeoutSeconds": 120,
28
+ "signature": "[QK:STOP-TURNBUDGET-NOT-SUCCESS]",
29
+ "signatureSource": "scripts/check-acp-stop-reason.ts"
30
+ },
31
+ {
32
+ "claim": "STOP-UNKNOWN-NOT-SUCCESS",
33
+ "title": "the collapse-to-stop default returns: any reason this build has never seen becomes a clean success",
34
+ "subject": "pi-extensions/lib/acp/backend.ts",
35
+ "find": [
36
+ "\t\tdefault:\n\t\t\treturn {\n\t\t\t\tstopReason: \"error\",\n\t\t\t\trawStopReason: stopReason,\n\t\t\t\terrorMessage: `ACP backend stopped with an unrecognized reason: ${stopReason}`,\n\t\t\t};"
37
+ ],
38
+ "replace": ["\t\tdefault:\n\t\t\treturn { stopReason: \"stop\", rawStopReason: stopReason };"],
39
+ "gate": ["bash", "run.sh", "check-acp-stop-reason"],
40
+ "timeoutSeconds": 120,
41
+ "signature": "[QK:STOP-UNKNOWN-NOT-SUCCESS]",
42
+ "signatureSource": "scripts/check-acp-stop-reason.ts"
43
+ },
44
+ {
45
+ "claim": "STOP-ABSENT-NOT-SUCCESS",
46
+ "title": "a prompt result carrying NO stop reason treated as a finished turn instead of an error",
47
+ "subject": "pi-extensions/lib/acp/backend.ts",
48
+ "find": [
49
+ "\t\tcase undefined:\n\t\t\treturn {\n\t\t\t\tstopReason: \"error\",\n\t\t\t\terrorMessage: \"ACP backend ended the turn without a stop reason\",\n\t\t\t};"
50
+ ],
51
+ "replace": ["\t\tcase undefined:\n\t\t\treturn { stopReason: \"stop\" };"],
52
+ "gate": ["bash", "run.sh", "check-acp-stop-reason"],
53
+ "timeoutSeconds": 120,
54
+ "signature": "[QK:STOP-ABSENT-NOT-SUCCESS]",
55
+ "signatureSource": "scripts/check-acp-stop-reason.ts"
56
+ },
57
+ {
58
+ "claim": "STOP-RAW-PRESERVED",
59
+ "title": "the raw ACP reason is dropped on the way out, so no consumer can see what the backend actually said",
60
+ "subject": "pi-extensions/lib/acp/backend.ts",
61
+ "find": ["\t\tif (verdict.rawStopReason !== undefined) state.output.rawStopReason = verdict.rawStopReason;\n"],
62
+ "replace": [""],
63
+ "gate": ["bash", "run.sh", "check-acp-stop-reason"],
64
+ "timeoutSeconds": 120,
65
+ "signature": "[QK:STOP-RAW-PRESERVED]",
66
+ "signatureSource": "scripts/check-acp-stop-reason.ts"
67
+ },
68
+ {
69
+ "claim": "STOP-PENDING-SEED",
70
+ "title": "the stream state seeds success: an in-flight turn already reads as a finished stop before any terminal arrives",
71
+ "subject": "pi-extensions/lib/acp/event-mapper.ts",
72
+ "find": ["\t\tstopReason: \"pending\","],
73
+ "replace": ["\t\tstopReason: \"stop\","],
74
+ "gate": ["bash", "run.sh", "check-acp-stop-reason"],
75
+ "timeoutSeconds": 120,
76
+ "signature": "[QK:STOP-PENDING-SEED]",
77
+ "signatureSource": "scripts/check-acp-stop-reason.ts"
78
+ }
79
+ ]
80
+ }
@@ -76,14 +76,36 @@
76
76
  "signatureSource": "scripts/check-probe-ordering.ts"
77
77
  },
78
78
  {
79
- "claim": "PROBE-TIMEOUTS-MATCH-PRODUCTION",
80
- "title": "probe prompt boundary drifting from production (120s was the raw smoke's value) — D readings would measure the wrong timeout",
79
+ "claim": "PROBE-BOOTSTRAP-TIMEOUTS-MATCH-PRODUCTION",
80
+ "title": "probe bootstrap boundary drifting from production — a bootstrap-phase D reading would measure the wrong timeout",
81
81
  "subject": "scripts/lib/probe-acp-turn.ts",
82
- "find": ["\tpromptMs: 600_000,"],
83
- "replace": ["\tpromptMs: 120_000,"],
82
+ "find": ["\tsetModelMs: 30_000,"],
83
+ "replace": ["\tsetModelMs: 15_000,"],
84
84
  "gate": ["bash", "run.sh", "check-probe-ordering"],
85
85
  "timeoutSeconds": 120,
86
- "signature": "[QK:PROBE-TIMEOUTS-MATCH-PRODUCTION]",
86
+ "signature": "[QK:PROBE-BOOTSTRAP-TIMEOUTS-MATCH-PRODUCTION]",
87
+ "signatureSource": "scripts/check-probe-ordering.ts"
88
+ },
89
+ {
90
+ "claim": "NO-PRODUCTION-PROMPT-CUTOFF",
91
+ "title": "an absolute wall-clock cutoff re-planted on the prompt — active turns die for being long and pi replays the whole prompt as a transient error",
92
+ "subject": "pi-extensions/lib/acp/backend.ts",
93
+ "find": ["const ABORT_CANCEL_GRACE_MS = 5_000;"],
94
+ "replace": ["const PROMPT_TIMEOUT_MS = 600_000;\nconst ABORT_CANCEL_GRACE_MS = 5_000;"],
95
+ "gate": ["bash", "run.sh", "check-probe-ordering"],
96
+ "timeoutSeconds": 120,
97
+ "signature": "[QK:NO-PRODUCTION-PROMPT-CUTOFF]",
98
+ "signatureSource": "scripts/check-probe-ordering.ts"
99
+ },
100
+ {
101
+ "claim": "PROMPT-HORIZON-NOT-PRODUCTION",
102
+ "title": "the harness's prompt observation horizon folded back into the production-pinned set — a probe-invented number would be reported as the turn contract",
103
+ "subject": "scripts/lib/probe-acp-turn.ts",
104
+ "find": ["\tsetModelMs: 30_000,\n};"],
105
+ "replace": ["\tsetModelMs: 30_000,\n\tpromptMs: 600_000,\n};"],
106
+ "gate": ["bash", "run.sh", "check-probe-ordering"],
107
+ "timeoutSeconds": 120,
108
+ "signature": "[QK:PROMPT-HORIZON-NOT-PRODUCTION]",
87
109
  "signatureSource": "scripts/check-probe-ordering.ts"
88
110
  },
89
111
  {
@@ -0,0 +1,105 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "release-gate",
4
+ "mutants": [
5
+ {
6
+ "claim": "SKIP-EXIT-ONE-PROTOCOL",
7
+ "title": "the shell and TS halves name different skip codes — every honest skip silently reclassifies, and the summary says nothing",
8
+ "subject": "scripts/lib/step-outcome.sh",
9
+ "find": ["ENTWURF_STEP_SKIP_EXIT=97"],
10
+ "replace": ["ENTWURF_STEP_SKIP_EXIT=96"],
11
+ "gate": ["bash", "run.sh", "check-release-gate-outcomes"],
12
+ "timeoutSeconds": 180,
13
+ "signature": "[QK:SKIP-EXIT-ONE-PROTOCOL]",
14
+ "signatureSource": "scripts/check-release-gate-outcomes.ts"
15
+ },
16
+ {
17
+ "claim": "STEP-OUTCOME-SKIP-NOT-PASS",
18
+ "title": "the classifier rounds a skip up to PASS — the pre-P1 defect restored at its source: a step that declined is reported as acceptance",
19
+ "subject": "scripts/lib/step-outcome.sh",
20
+ "find": ["\t\t\"$ENTWURF_STEP_SKIP_EXIT\") printf 'SKIP\\n' ;;"],
21
+ "replace": ["\t\t\"$ENTWURF_STEP_SKIP_EXIT\") printf 'PASS\\n' ;;"],
22
+ "gate": ["bash", "run.sh", "check-release-gate-outcomes"],
23
+ "timeoutSeconds": 180,
24
+ "signature": "[QK:STEP-OUTCOME-SKIP-NOT-PASS]",
25
+ "signatureSource": "scripts/check-release-gate-outcomes.ts"
26
+ },
27
+ {
28
+ "claim": "CUT-REFUSES-SKIP",
29
+ "title": "--cut stops refusing a MUST SKIP — the release procedure goes back to prose and a 14-SKIP run can be quoted as acceptance",
30
+ "subject": "scripts/lib/step-outcome.sh",
31
+ "find": ["\tif [ \"$cut\" = \"1\" ] && [ \"$skipc\" -gt 0 ]; then"],
32
+ "replace": ["\tif [ \"$cut\" = \"1\" ] && [ \"$skipc\" -lt 0 ]; then"],
33
+ "gate": ["bash", "run.sh", "check-release-gate-outcomes"],
34
+ "timeoutSeconds": 180,
35
+ "signature": "[QK:CUT-REFUSES-SKIP]",
36
+ "signatureSource": "scripts/check-release-gate-outcomes.ts"
37
+ },
38
+ {
39
+ "claim": "NO-SMOKE-SKIPS-WITH-ZERO",
40
+ "title": "one LIVE smoke goes back to exiting 0 on its skip — the hole re-opens for that lane alone, which is how it survived unnoticed",
41
+ "subject": "scripts/smoke-acp-mcp-live.ts",
42
+ "find": ["\tskipLive(\"smoke-acp-mcp-live\", \"set LIVE=1 to run the real pi provider turn.\");"],
43
+ "replace": [
44
+ "\tconsole.error(\"[smoke-acp-mcp-live] skipped — set LIVE=1 to run the real pi provider turn.\");",
45
+ "\tprocess.exit(0);"
46
+ ],
47
+ "gate": ["bash", "run.sh", "check-release-gate-outcomes"],
48
+ "timeoutSeconds": 180,
49
+ "signature": "[QK:NO-SMOKE-SKIPS-WITH-ZERO]",
50
+ "signatureSource": "scripts/check-release-gate-outcomes.ts"
51
+ },
52
+ {
53
+ "claim": "LIVE-SKIP-IS-PROTOCOL-EXIT",
54
+ "title": "skipLive exits 0 — every smoke still LOOKS converted (imports, no old shape) while the aggregate reads all of them as PASS",
55
+ "subject": "scripts/lib/live-skip.ts",
56
+ "find": ["\tprocess.exit(LIVE_SKIP_EXIT);"],
57
+ "replace": ["\tprocess.exit(0);"],
58
+ "gate": ["bash", "run.sh", "check-release-gate-outcomes"],
59
+ "timeoutSeconds": 180,
60
+ "signature": "[QK:LIVE-SKIP-IS-PROTOCOL-EXIT]",
61
+ "signatureSource": "scripts/check-release-gate-outcomes.ts"
62
+ },
63
+ {
64
+ "claim": "WRAPPER-SKIP-IS-PROTOCOL-EXIT",
65
+ "title": "a run.sh smoke wrapper returns 0 on a missing prerequisite — the second skip surface, where cortex/matrix/spawn decline before their .ts is ever reached",
66
+ "subject": "run.sh",
67
+ "find": [
68
+ " echo \"[entwurf:skip] smoke-acp-cortex-live — set LIVE=1 (+ ENTWURF_ACP_CORTEX_CONNECTION) to run.\"",
69
+ " return \"$ENTWURF_STEP_SKIP_EXIT\""
70
+ ],
71
+ "replace": [
72
+ " echo \"[entwurf:skip] smoke-acp-cortex-live — set LIVE=1 (+ ENTWURF_ACP_CORTEX_CONNECTION) to run.\"",
73
+ " return 0"
74
+ ],
75
+ "gate": ["bash", "run.sh", "check-release-gate-outcomes"],
76
+ "timeoutSeconds": 180,
77
+ "signature": "[QK:WRAPPER-SKIP-IS-PROTOCOL-EXIT]",
78
+ "signatureSource": "scripts/check-release-gate-outcomes.ts"
79
+ },
80
+ {
81
+ "claim": "CUT-VERDICT-NAMES-CAUSE",
82
+ "title": "a cut blocked only by SKIP reports itself as a FAIL block — the record can no longer tell a broken call from an absent prerequisite",
83
+ "subject": "scripts/lib/step-outcome.sh",
84
+ "find": ["\t\tprintf 'cut: BLOCKED (MUST SKIP)\\n'"],
85
+ "replace": ["\t\tprintf 'cut: BLOCKED (MUST FAIL)\\n'"],
86
+ "gate": ["bash", "run.sh", "check-release-gate-outcomes"],
87
+ "timeoutSeconds": 180,
88
+ "signature": "[QK:CUT-VERDICT-NAMES-CAUSE]",
89
+ "signatureSource": "scripts/check-release-gate-outcomes.ts"
90
+ },
91
+ {
92
+ "claim": "NO-SILENT-AGGREGATE-OMISSION",
93
+ "title": "the cross-harness delivery chain drops out of the aggregate — a green cut goes back to saying nothing about multi-harness delivery, with no doc stating the exclusion",
94
+ "subject": "run.sh",
95
+ "find": [
96
+ " run_live_step \"smoke-entwurf-chain-live (P3: Claude Code -> pi GPT -> pi ACP Sonnet -> mailbox, identity + receipt)\" gate bash \"$self\" smoke-entwurf-chain-live"
97
+ ],
98
+ "replace": [" : # the chain quietly dropped from the aggregate"],
99
+ "gate": ["bash", "run.sh", "check-release-gate-outcomes"],
100
+ "timeoutSeconds": 180,
101
+ "signature": "[QK:NO-SILENT-AGGREGATE-OMISSION]",
102
+ "signatureSource": "scripts/check-release-gate-outcomes.ts"
103
+ }
104
+ ]
105
+ }
@@ -7,16 +7,13 @@
7
7
  "title": "MCP long description reverts to the false \"socket paths take a per-target lock\" claim",
8
8
  "subject": "mcp/entwurf-bridge/src/index.ts",
9
9
  "find": [
10
- "\t\t\"(delivered / rejected / lock-retained / delivered-but-lock-dirty). LOCK POLICY (do not \" +",
11
- "\t\t\"over-generalize it): the per-target lock is taken for a control-socket-DOMAIN dispatch, which is \" +",
12
- "\t\t\"both the live send AND the dormant cell's spawn-bg resume — spawn-bg is a separate relaunch \" +",
13
- "\t\t\"transport yet it still runs under that domain's lock. The mailbox and native-push rails are \" +",
14
- "\t\t\"lock-free: the mailbox is guarded instead by active-receiver deliverability, and native-push by \" +",
15
- "\t\t\"its adapter probe. The decider — not the \" +"
10
+ "\t\t\"native-push-no-resume-authority. LOCK: taken for a control-socket-DOMAIN dispatch — the live send AND \" +",
11
+ "\t\t\"the dormant cell's spawn-bg resume, a separate transport that still runs under that domain's lock. The \" +",
12
+ "\t\t\"mailbox and native-push rails are lock-free — deliverability and the adapter probe guard them. mode \" +"
16
13
  ],
17
14
  "replace": [
18
- "\t\t\"(delivered / rejected / lock-retained / delivered-but-lock-dirty). LOCK POLICY: socket paths \" +",
19
- "\t\t\"take a per-target lock; the mailbox path does not. The decider — not the \" +"
15
+ "\t\t\"native-push-no-resume-authority. LOCK POLICY: socket paths take a per-target lock; the mailbox path \" +",
16
+ "\t\t\"does not. mode \" +"
20
17
  ],
21
18
  "gate": ["bash", "run.sh", "check-entwurf-v2-surface"],
22
19
  "timeoutSeconds": 60,
@@ -68,20 +65,34 @@
68
65
  "title": "MCP long description merges the two owned rejects back under backend-liveness-unsupported",
69
66
  "subject": "mcp/entwurf-bridge/src/index.ts",
70
67
  "find": [
71
- "\t\t\"owned-outcome is ONLY for waking a DORMANT socket-domain citizen (spawn-bg resume, currently \" +",
72
- "\t\t\"backend pi); on a live target it is rejected as owned-live-no-autosend. Neither self-fetch nor \" +",
73
- "\t\t\"native-push has resume authority, but they reject under DIFFERENT reasons — self-fetch as \" +",
74
- "\t\t\"backend-liveness-unsupported, native-push as native-push-no-resume-authority. \" +"
68
+ "\t\t\"owned-outcome wakes a DORMANT socket-domain citizen by spawn-bg resume ONLY — live target → \" +",
69
+ "\t\t\"owned-live-no-autosend, self-fetch → backend-liveness-unsupported, native-push → \" +",
70
+ "\t\t\"native-push-no-resume-authority. LOCK: taken for a control-socket-DOMAIN dispatch — the live send AND \" +"
75
71
  ],
76
72
  "replace": [
77
- "\t\t\"owned-outcome is ONLY for waking a DORMANT socket-domain citizen (spawn-bg resume, currently \" +",
78
- "\t\t\"backend pi); on a live target it is rejected as owned-live-no-autosend, and on self-fetch and \" +",
79
- "\t\t\"native-push alike it is rejected as backend-liveness-unsupported. \" +"
73
+ "\t\t\"owned-outcome wakes a DORMANT socket-domain citizen by spawn-bg resume ONLY — live target → \" +",
74
+ "\t\t\"owned-live-no-autosend, and on self-fetch and native-push alike it is rejected as \" +",
75
+ "\t\t\"backend-liveness-unsupported. LOCK: taken for a control-socket-DOMAIN dispatch — the live send AND \" +"
80
76
  ],
81
77
  "gate": ["bash", "run.sh", "check-entwurf-v2-surface"],
82
78
  "timeoutSeconds": 60,
83
79
  "signature": "[QK:V2SURF-MERGED-REJECT]",
84
80
  "signatureSource": "scripts/check-entwurf-v2-surface.ts"
81
+ },
82
+ {
83
+ "claim": "V2SURF-DESC-FITS-HOST-CAP",
84
+ "title": "the v2 tool description grows back past the host's 2048-char cap — the INTENT contract is silently cut off before the model that must choose an intent ever reads it",
85
+ "subject": "mcp/entwurf-bridge/src/index.ts",
86
+ "find": [
87
+ "\t\"CANONICAL DELIVERY SURFACE for garden ids: message, reply, or hand off to whoever an id names. The id \" +"
88
+ ],
89
+ "replace": [
90
+ "\t\"CANONICAL DELIVERY SURFACE for garden ids: message, reply, or hand off to whoever an id names. The id \" +\n\t\t\"PADDING PADDING PADDING PADDING PADDING PADDING PADDING PADDING PADDING PADDING PADDING PADDING \" +\n\t\t\"PADDING PADDING PADDING PADDING PADDING PADDING PADDING PADDING PADDING PADDING PADDING PADDING \" +"
91
+ ],
92
+ "gate": ["bash", "run.sh", "check-entwurf-v2-surface"],
93
+ "timeoutSeconds": 60,
94
+ "signature": "[QK:V2SURF-DESC-FITS-HOST-CAP]",
95
+ "signatureSource": "scripts/check-entwurf-v2-surface.ts"
85
96
  }
86
97
  ]
87
98
  }
@@ -52,6 +52,7 @@ import * as readline from "node:readline";
52
52
  import { fileURLToPath } from "node:url";
53
53
  import { fetchControlSocketRuntimeInfo, formatRuntimeModel } from "../pi-extensions/lib/entwurf-control-rpc.ts";
54
54
  import { terminateChild } from "./lib/acp-child-cleanup.ts";
55
+ import { skipLive } from "./lib/live-skip.ts";
55
56
  import { waitForPiRecord } from "./lib/pi-record-discovery.ts";
56
57
 
57
58
  const ACP_PROVIDER = "entwurf";
@@ -160,10 +161,10 @@ function driveSelfTurn(child: ChildProcess, prompt: string): Promise<TurnCapture
160
161
 
161
162
  async function main(): Promise<void> {
162
163
  if (process.env.LIVE !== "1") {
163
- console.log(
164
- "[smoke-acp-bundled-mcp-live] skipped — set LIVE=1 to run (spawns a real pi --entwurf-control resident + drives one model turn).",
164
+ skipLive(
165
+ "smoke-acp-bundled-mcp-live",
166
+ "set LIVE=1 to run (spawns a real pi --entwurf-control resident + drives one model turn).",
165
167
  );
166
- return;
167
168
  }
168
169
 
169
170
  const tmp = os.tmpdir();
@@ -45,6 +45,7 @@ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
45
45
  import { tmpdir } from "node:os";
46
46
  import { dirname, join, resolve } from "node:path";
47
47
  import { fileURLToPath } from "node:url";
48
+ import { skipLive } from "./lib/live-skip.ts";
48
49
 
49
50
  const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
50
51
  const MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-5";
@@ -57,8 +58,7 @@ function fail(msg: string): never {
57
58
  }
58
59
 
59
60
  if (process.env.LIVE !== "1") {
60
- console.error("[smoke-acp-carrier-augment-live] skipped — set LIVE=1 to run the real pi provider turn.");
61
- process.exit(0);
61
+ skipLive("smoke-acp-carrier-augment-live", "set LIVE=1 to run the real pi provider turn.");
62
62
  }
63
63
 
64
64
  // Billing-reclassification canaries (핀1). The empty carrier must NOT trip metered
@@ -5,7 +5,7 @@
5
5
  //
6
6
  // LIVE=1 ENTWURF_ACP_CORTEX_CONNECTION=<conn> ./run.sh smoke-acp-cortex-live
7
7
  //
8
- // WHY this exact axis. The CP0 audit (docs/acp-backend-rail.md §11-8) measured
8
+ // WHY this exact axis. The CP0 audit (docs/acp-backend-rail.md, Cortex D1–D10) measured
9
9
  // three things no offline gate can prove:
10
10
  // - D9/D10: cortex ignores the wire `mcpServers` param, so the bundled
11
11
  // entwurf-bridge reaches a cortex session ONLY through the overlay-private
@@ -32,7 +32,7 @@
32
32
  // LIVE-only and OUTSIDE the claude-only AGGREGATE release floor (capability
33
33
  // dignity): a host that runs no cortex must not redden a claude release. That is
34
34
  // a wiring decision — shipping cortex still owes a deliberate run of this smoke,
35
- // and the aggregate gate's silence is not a pass (rail §11-8 tail).
35
+ // and the aggregate gate's silence is not a pass (ACP rail verification boundary).
36
36
  // Honest skip when LIVE!=1, when `cortex` is not on PATH, or when
37
37
  // ENTWURF_ACP_CORTEX_CONNECTION is unset — the overlay denies the operator's
38
38
  // cortex settings.json (where a default connection would live), so the
@@ -53,6 +53,7 @@ import * as readline from "node:readline";
53
53
  import { fileURLToPath } from "node:url";
54
54
  import { upsertMetaSession, writeMetaReceiverMarker } from "../pi-extensions/lib/meta-session.ts";
55
55
  import { terminateChild } from "./lib/acp-child-cleanup.ts";
56
+ import { skipLive } from "./lib/live-skip.ts";
56
57
  import { waitForPiRecord } from "./lib/pi-record-discovery.ts";
57
58
 
58
59
  const ACP_PROVIDER = "entwurf";
@@ -189,24 +190,17 @@ function driveTurn(child: ChildProcess, prompt: string): Promise<TurnCapture> {
189
190
 
190
191
  async function main(): Promise<void> {
191
192
  if (process.env.LIVE !== "1") {
192
- console.log(
193
- "[smoke-acp-cortex-live] skipped — set LIVE=1 to run (spawns a real cortex ACP resident + one model turn).",
194
- );
195
- return;
193
+ skipLive("smoke-acp-cortex-live", "set LIVE=1 to run (spawns a real cortex ACP resident + one model turn).");
196
194
  }
197
195
  const connection = process.env.ENTWURF_ACP_CORTEX_CONNECTION?.trim();
198
196
  if (!connection) {
199
- console.log(
200
- "[smoke-acp-cortex-live] skipped — set ENTWURF_ACP_CORTEX_CONNECTION=<snowflake connection> (the dual-HOME " +
201
- "overlay denies the operator cortex settings.json, so the connection must ride the adapter's own seam).",
197
+ skipLive(
198
+ "smoke-acp-cortex-live",
199
+ "set ENTWURF_ACP_CORTEX_CONNECTION=<snowflake connection> (the dual-HOME overlay denies the operator cortex settings.json, so the connection must ride the adapter's own seam).",
202
200
  );
203
- return;
204
201
  }
205
202
  if ("CORTEX_HOME" in process.env) {
206
- console.log(
207
- "[smoke-acp-cortex-live] skipped — unset CORTEX_HOME first (the adapter refuses its presence, CP0 D3).",
208
- );
209
- return;
203
+ skipLive("smoke-acp-cortex-live", "unset CORTEX_HOME first (the adapter refuses its presence, CP0 D3).");
210
204
  }
211
205
 
212
206
  // One temp root holding the whole garden this smoke can see: store, mailbox