@junghanacs/entwurf 0.23.0 → 0.24.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.
- package/AGENTS.md +3 -1
- package/BASELINE.md +2 -0
- package/CHANGELOG.md +307 -0
- package/FAQ.md +47 -0
- package/README.md +5 -3
- package/VERIFY.md +43 -2
- package/demo/README.md +1 -1
- package/docs/acp-backend-rail.md +97 -18
- package/docs/setup-clean-host.md +8 -7
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +33 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +2 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/context.js +19 -5
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/tool-surface.js +2 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/callback-env.js +68 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +2 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-lock.js +1 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-composition.js +54 -22
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +7 -3
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-placement.js +13 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +19 -10
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-omp.js +35 -42
- package/mcp/entwurf-bridge/dist/scripts/probe-bridge-command.js +1 -0
- package/mcp/entwurf-bridge/src/index.ts +41 -1
- package/mcp/entwurf-bridge/test.sh +2 -2
- package/package.json +15 -13
- package/pi-extensions/entwurf-control.ts +56 -0
- package/pi-extensions/lib/acp/acp-client.ts +3 -3
- package/pi-extensions/lib/acp/backend-adapter.ts +3 -3
- package/pi-extensions/lib/acp/backend.ts +20 -10
- package/pi-extensions/lib/acp/context.ts +30 -10
- package/pi-extensions/lib/acp/event-mapper.ts +5 -5
- package/pi-extensions/lib/acp/session-store.ts +2 -2
- package/pi-extensions/lib/acp/tool-surface.ts +2 -1
- package/pi-extensions/lib/callback-env.ts +78 -0
- package/pi-extensions/lib/compaction-send-guard.ts +4 -1
- package/pi-extensions/lib/entwurf-v2-contract.ts +2 -2
- package/pi-extensions/lib/entwurf-v2-lock.ts +1 -1
- package/pi-extensions/lib/entwurf-v2-runner.ts +1 -1
- package/pi-extensions/lib/fresh-call-composition.ts +56 -22
- package/pi-extensions/lib/herdr-fresh-call.ts +12 -4
- package/pi-extensions/lib/herdr-placement.ts +13 -4
- package/pi-extensions/lib/mux-fresh-call.ts +23 -8
- package/pi-extensions/meta-bridge-omp.ts +35 -48
- package/run.sh +327 -246
- package/scripts/check-acp-backend-preflight.ts +117 -9
- package/scripts/check-acp-carrier-augment.ts +6 -4
- package/scripts/check-acp-event-mapper.ts +17 -6
- package/scripts/check-acp-prompt-builder.ts +17 -9
- package/scripts/check-acp-prompt-lifecycle.ts +23 -6
- package/scripts/check-acp-session-reuse.ts +64 -51
- package/scripts/check-acp-session-store.ts +31 -8
- package/scripts/check-acp-stop-reason.ts +20 -2
- package/scripts/check-acp-stream-hooks.ts +22 -5
- package/scripts/check-acp-usage-accounting.ts +42 -18
- package/scripts/check-entwurf-bridge-boot.ts +16 -1
- package/scripts/check-fresh-call-dispatch.ts +4 -5
- package/scripts/check-gate-qualification.ts +45 -5
- package/scripts/check-herdr-activation.ts +73 -0
- package/scripts/check-herdr-fresh-call.ts +22 -6
- package/scripts/check-herdr-sandbox.ts +14 -2
- package/scripts/check-install-container.sh +1 -1
- package/scripts/check-pi-launch.ts +361 -0
- package/scripts/check-release-gate-outcomes.ts +7 -0
- package/scripts/inventory-verification-surface.ts +86 -10
- package/scripts/lib/mutation-qualify.ts +1 -1
- package/scripts/mutants/acp-backend-preflight.json +20 -0
- package/scripts/mutants/bridge-boot-resume.json +26 -0
- package/scripts/mutants/herdr-activation.json +16 -0
- package/scripts/mutants/herdr-fresh-call.json +11 -0
- package/scripts/mutants/herdr-plugin-build.json +1 -1
- package/scripts/mutants/mux-fresh-call.json +21 -8
- package/scripts/mutants/omp-fresh.json +5 -9
- package/scripts/mutants/pack-install.json +3 -3
- package/scripts/mutants/pi-launch.json +113 -0
- package/scripts/mutants/resume-args.json +6 -6
- package/scripts/mutants/v2-surface.json +2 -2
- package/scripts/mutants/v2-visible-resume.json +17 -17
- package/scripts/probe-bridge-command.ts +1 -0
- package/scripts/smoke-acp-raw-turn-live.ts +1 -1
- package/scripts/smoke-acp-session-reuse-live.ts +23 -5
- package/scripts/smoke-agy-install-state.sh +2 -2
- package/scripts/smoke-copilot-mcp-state.sh +1 -1
- package/scripts/smoke-entwurf-v2-matrix-live.ts +1 -1
- package/scripts/smoke-herdr-fresh-call-live.ts +56 -28
- package/scripts/smoke-herdr-raw-install-live.sh +877 -0
- package/scripts/smoke-omp-fresh-live.ts +4 -2
- package/scripts/smoke-omp-mcp-state.sh +1 -1
- package/scripts/smoke-pi-provider-state.sh +2 -2
- package/scripts/tsconfig.json +5 -0
- package/scripts/check-entwurf-facts.ts +0 -391
- package/scripts/check-entwurf-resume-args.ts +0 -122
- package/scripts/check-entwurf-v2-decider.ts +0 -657
- package/scripts/check-entwurf-v2-lock.ts +0 -371
- package/scripts/check-entwurf-v2-mailbox.ts +0 -261
- package/scripts/check-entwurf-v2-matrix.ts +0 -401
- package/scripts/check-entwurf-v2-native-push.ts +0 -221
- package/scripts/check-entwurf-v2-release.ts +0 -151
- package/scripts/check-entwurf-v2-runner.ts +0 -448
- package/scripts/check-entwurf-v2-send-fallback.ts +0 -350
- package/scripts/check-entwurf-v2-send.ts +0 -458
- package/scripts/check-entwurf-v2-visible-resume.ts +0 -445
- package/scripts/check-socket-discovery.ts +0 -401
|
@@ -13,6 +13,22 @@
|
|
|
13
13
|
"signature": "[QK:HAC-PI-USER-SCOPE-ONLY]",
|
|
14
14
|
"signatureSource": "scripts/check-herdr-activation.ts"
|
|
15
15
|
},
|
|
16
|
+
{
|
|
17
|
+
"claim": "HAC-PI-FLOOR-BOTH-DOORS",
|
|
18
|
+
"title": "dropping the pi range check from install-user-scope re-opens the door asymmetry: setup refuses a below-floor pi by name while the herdr activation door writes the same registration in silence, so one host reports two verdicts for one citizen",
|
|
19
|
+
"subject": "run.sh",
|
|
20
|
+
"find": [
|
|
21
|
+
" if ! pi_version_in_range \"${pi_ver:-0}\" \"$pi_range\"; then",
|
|
22
|
+
" echo \"[install-user-scope] pi: FAIL — detected pi ${pi_ver:-<unreadable version>} is outside the supported range $pi_range; nothing was written. Align pi, then re-run.\" >&2",
|
|
23
|
+
" exit 1",
|
|
24
|
+
" fi"
|
|
25
|
+
],
|
|
26
|
+
"replace": [" : \"$pi_range\""],
|
|
27
|
+
"gate": ["bash", "run.sh", "check-herdr-activation"],
|
|
28
|
+
"timeoutSeconds": 300,
|
|
29
|
+
"signature": "[QK:HAC-PI-FLOOR-BOTH-DOORS]",
|
|
30
|
+
"signatureSource": "scripts/check-herdr-activation.ts"
|
|
31
|
+
},
|
|
16
32
|
{
|
|
17
33
|
"claim": "HAC-COMMAND-IS-DERIVED",
|
|
18
34
|
"title": "accepting any absolute directory as 'the plugin runtime' is a way to point every pi session at an executable of the caller's choosing — 'absolute' was never the contract, 'this host's stable runtime' was",
|
|
@@ -443,6 +443,17 @@
|
|
|
443
443
|
"timeoutSeconds": 120,
|
|
444
444
|
"signature": "[QK:HFC-WITNESS-BINDING-COMPLETE]",
|
|
445
445
|
"signatureSource": "scripts/check-herdr-fresh-call.ts"
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
"claim": "HFC-CALLBACK-ENV",
|
|
449
|
+
"title": "the launcher-computed callback pair is dropped from herdr --env, so a herdr sibling's first action has to retype a garden id out of prose",
|
|
450
|
+
"subject": "pi-extensions/lib/herdr-fresh-call.ts",
|
|
451
|
+
"find": ["\t\t...callbackEnvAssignments(params.callback).flatMap((assignment) => [\"--env\", assignment]),"],
|
|
452
|
+
"replace": [""],
|
|
453
|
+
"gate": ["bash", "run.sh", "check-herdr-fresh-call"],
|
|
454
|
+
"timeoutSeconds": 120,
|
|
455
|
+
"signature": "[QK:HFC-CALLBACK-ENV]",
|
|
456
|
+
"signatureSource": "scripts/check-herdr-fresh-call.ts"
|
|
446
457
|
}
|
|
447
458
|
]
|
|
448
459
|
}
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"find": [
|
|
111
111
|
"\tprogress.step(",
|
|
112
112
|
"\t\t`fetching and installing the Entwurf runtime from ${describeRequest(plan.requested)} — this is the long step ` +",
|
|
113
|
-
"\t\t\t\"(npm
|
|
113
|
+
"\t\t\t\"(npm acquires the locked artifact; expect minutes of silence)\",",
|
|
114
114
|
"\t);"
|
|
115
115
|
],
|
|
116
116
|
"replace": ["\tprogress.step(\"working\");"],
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"title": "claude-code goes back to the variadic space form, which swallows the prompt as an option value",
|
|
19
19
|
"subject": "pi-extensions/lib/fresh-call-composition.ts",
|
|
20
20
|
"find": [
|
|
21
|
-
"\t\t\treturn [
|
|
21
|
+
"\t\t\treturn [\n\t\t\t\tcomposition.prompt,\n\t\t\t\t`--allowedTools=${FRESH_CALL_CALLBACK_TOOL[\"claude-code\"]},${FRESH_CALL_DELIVERY_TOOL[\"claude-code\"]}`,\n\t\t\t\t`--model=${model}`,\n\t\t\t];"
|
|
22
22
|
],
|
|
23
23
|
"replace": [
|
|
24
24
|
"\t\t\treturn [composition.prompt, \"--allowedTools\", FRESH_CALL_CALLBACK_TOOL[\"claude-code\"], `--model=${model}`];"
|
|
@@ -55,9 +55,11 @@
|
|
|
55
55
|
"title": "Claude Code drops the explicit model token and silently resolves its ambient Opus default again",
|
|
56
56
|
"subject": "pi-extensions/lib/fresh-call-composition.ts",
|
|
57
57
|
"find": [
|
|
58
|
-
"\t\t\treturn [
|
|
58
|
+
"\t\t\treturn [\n\t\t\t\tcomposition.prompt,\n\t\t\t\t`--allowedTools=${FRESH_CALL_CALLBACK_TOOL[\"claude-code\"]},${FRESH_CALL_DELIVERY_TOOL[\"claude-code\"]}`,\n\t\t\t\t`--model=${model}`,\n\t\t\t];"
|
|
59
|
+
],
|
|
60
|
+
"replace": [
|
|
61
|
+
"\t\t\treturn [\n\t\t\t\tcomposition.prompt,\n\t\t\t\t`--allowedTools=${FRESH_CALL_CALLBACK_TOOL[\"claude-code\"]},${FRESH_CALL_DELIVERY_TOOL[\"claude-code\"]}`,\n\t\t\t];"
|
|
59
62
|
],
|
|
60
|
-
"replace": ["\t\t\treturn [composition.prompt, `--allowedTools=${FRESH_CALL_CALLBACK_TOOL[\"claude-code\"]}`];"],
|
|
61
63
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
62
64
|
"timeoutSeconds": 120,
|
|
63
65
|
"signature": "[QK:FRESHCALL-CLAUDE-MODEL-ARGV]",
|
|
@@ -67,8 +69,8 @@
|
|
|
67
69
|
"claim": "FRESHCALL-CALLBACK-PRECEDES-TASK",
|
|
68
70
|
"title": "the task is framed before the callback instruction, so a sibling that stalls in the task never names itself",
|
|
69
71
|
"subject": "pi-extensions/lib/fresh-call-composition.ts",
|
|
70
|
-
"find": ["\t\t`FIRST ACTION, before reading files or anything else: call ${
|
|
71
|
-
"replace": ["\t\t`FINAL ACTION, after completing the task: call ${
|
|
72
|
+
"find": ["\t\t\t\t\t`FIRST ACTION, before reading files or anything else: call ${birthTool} with no arguments.`"],
|
|
73
|
+
"replace": ["\t\t\t\t\t`FINAL ACTION, after completing the task: call ${birthTool} with no arguments.`"],
|
|
72
74
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
73
75
|
"timeoutSeconds": 120,
|
|
74
76
|
"signature": "[QK:FRESHCALL-CALLBACK-PRECEDES-TASK]",
|
|
@@ -275,7 +277,7 @@
|
|
|
275
277
|
"claim": "FRESHCALL-COPILOT-CALLBACK-TOOL",
|
|
276
278
|
"title": "the Copilot callback names Claude Code's `mcp__server__tool` spelling — a dialect copied instead of measured, and the whole first turn is spent looking for a tool that is not there",
|
|
277
279
|
"subject": "pi-extensions/lib/fresh-call-composition.ts",
|
|
278
|
-
"find": ["\tcopilot: \"entwurf-bridge-
|
|
280
|
+
"find": ["\tcopilot: \"entwurf-bridge-entwurf_callback\","],
|
|
279
281
|
"replace": ["\tcopilot: \"mcp__entwurf-bridge__entwurf_v2\","],
|
|
280
282
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
281
283
|
"timeoutSeconds": 180,
|
|
@@ -669,7 +671,7 @@
|
|
|
669
671
|
"title": "the first turn stops naming where the result goes, so a sibling finishes its task, prints the answer in its own window, and the caller never learns it is done",
|
|
670
672
|
"subject": "pi-extensions/lib/fresh-call-composition.ts",
|
|
671
673
|
"find": [
|
|
672
|
-
"\t\t`When the task reaches its requested final result, send that result to the same target with ${
|
|
674
|
+
"\t\t`When the task reaches its requested final result, send that result to the same target with ${deliveryTool}.`,"
|
|
673
675
|
],
|
|
674
676
|
"replace": [""],
|
|
675
677
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
@@ -682,13 +684,24 @@
|
|
|
682
684
|
"title": "the Claude child loses the one sentence that tells it how to load a deferred callback tool — the framing goes back to naming a tool the child cannot call on its first turn, which is the measured silence: 0/5 directly callable, 5 of 14 production launches dead",
|
|
683
685
|
"subject": "pi-extensions/lib/fresh-call-composition.ts",
|
|
684
686
|
"find": [
|
|
685
|
-
"\t\"claude-code\": [\n\t\t\"If ${callbackTool} is not callable yet, the entwurf-bridge server is still connecting or its\",\n\t\t'tools are deferred: load them first with ToolSearch(\"select:${callbackTool},${peersTool}\") —',\n\t\t\"it waits for the server — then call ${callbackTool}.\",\n\t],"
|
|
687
|
+
"\t\"claude-code\": [\n\t\t\"If ${callbackTool} is not callable yet, the entwurf-bridge server is still connecting or its\",\n\t\t'tools are deferred: load them first with ToolSearch(\"select:${callbackTool},${deliveryTool},${peersTool}\") —',\n\t\t\"it waits for the server — then call ${callbackTool}.\",\n\t],"
|
|
686
688
|
],
|
|
687
689
|
"replace": ["\t\"claude-code\": [],"],
|
|
688
690
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
689
691
|
"timeoutSeconds": 300,
|
|
690
692
|
"signature": "[QK:FRESHCOMP-TOOL-LOAD-HINT-CLAUDE-ONLY]",
|
|
691
693
|
"signatureSource": "test/fresh-call-composition.contract.test.ts"
|
|
694
|
+
},
|
|
695
|
+
{
|
|
696
|
+
"claim": "FRESHCALL-CALLBACK-ENV",
|
|
697
|
+
"title": "the launcher-computed callback pair is dropped from tmux -e, so the sibling's first action has to retype a garden id out of prose — Hard Rule 2",
|
|
698
|
+
"subject": "pi-extensions/lib/mux-fresh-call.ts",
|
|
699
|
+
"find": ["\t\t...callbackEnvAssignments(callback).flatMap((assignment) => [\"-e\", assignment]),"],
|
|
700
|
+
"replace": [""],
|
|
701
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
702
|
+
"timeoutSeconds": 120,
|
|
703
|
+
"signature": "[QK:FRESHCALL-CALLBACK-ENV]",
|
|
704
|
+
"signatureSource": "test/mux-fresh-call.test.ts"
|
|
692
705
|
}
|
|
693
706
|
]
|
|
694
707
|
}
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"claim": "FRESHCALL-OMP-CALLBACK-TOOL-DIALECT",
|
|
46
46
|
"title": "the callback tool name spelled the way a reader expects instead of the way omp mints it — `entwurf_v2` keeps its digit, which omp's sanitizer charset [a-z_] eats. The sibling is told to call a tool that does not exist in its session, so the whole first turn is spent and no address ever comes back. A launch receipt still prints",
|
|
47
47
|
"subject": "pi-extensions/lib/fresh-call-composition.ts",
|
|
48
|
-
"find": ["\tomp: \"
|
|
48
|
+
"find": ["\tomp: \"mcp__entwurf_bridge_entwurf_callback\","],
|
|
49
49
|
"replace": ["\tomp: \"mcp__entwurf_bridge_entwurf_v2\","],
|
|
50
50
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
51
51
|
"timeoutSeconds": 300,
|
|
@@ -167,10 +167,8 @@
|
|
|
167
167
|
"claim": "OMP-BOOTSTRAP-CALLBACK-ONLY",
|
|
168
168
|
"title": "the task folded back into the stage-one prompt, so the sibling is asked to call back AND to work in one message. This is the prompt the failed LIVE actually ran, minus the missing tool: a competing goal beside the callback is what the two-stage split exists to remove, and nothing about argv or readiness would notice it coming back",
|
|
169
169
|
"subject": "pi-extensions/meta-bridge-omp.ts",
|
|
170
|
-
"find": ["\t\t\tsend(buildOmpCallbackOnlyPrompt(
|
|
171
|
-
"replace": [
|
|
172
|
-
"\t\t\tsend(`${buildOmpCallbackOnlyPrompt({ target: payload.target, nonce: payload.nonce })}\\n\\n${payload.task}`);"
|
|
173
|
-
],
|
|
170
|
+
"find": ["\t\t\tsend(buildOmpCallbackOnlyPrompt());"],
|
|
171
|
+
"replace": ["\t\t\tsend(`${buildOmpCallbackOnlyPrompt()}\\n\\n${payload.task}`);"],
|
|
174
172
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
175
173
|
"timeoutSeconds": 300,
|
|
176
174
|
"signature": "[QK:OMP-BOOTSTRAP-CALLBACK-ONLY]",
|
|
@@ -204,11 +202,9 @@
|
|
|
204
202
|
"claim": "OMP-BOOTSTRAP-RESULT-ARMS-ONLY",
|
|
205
203
|
"title": "the task sent from inside the tool_result handler again, instead of at the turn_end boundary. `[LIVE 2026-08-30]` this is the exact shape that failed: the hook log showed armed/ready/callback-observed/released, the release predicate was provably correct, and the task still never appeared in the session — because that handler runs while the callback turn is streaming. Every static contract about correlation and readiness stays green while the product delivers nothing",
|
|
206
204
|
"subject": "pi-extensions/meta-bridge-omp.ts",
|
|
207
|
-
"find": [
|
|
208
|
-
"\t\t\tlog(\"INFO\", `bootstrap-released nonce=${payload.nonce} toolCallId=${callId}: task armed for the next turn_end`);"
|
|
209
|
-
],
|
|
205
|
+
"find": ["\t\t\tlog(\"INFO\", `bootstrap-released toolCallId=${callId}: task armed for the next turn_end`);"],
|
|
210
206
|
"replace": [
|
|
211
|
-
"\t\t\tlog(\"INFO\", `bootstrap-released
|
|
207
|
+
"\t\t\tlog(\"INFO\", `bootstrap-released toolCallId=${callId}: task armed for the next turn_end`);\n\t\t\tphase = \"task-sent\";\n\t\t\tsend(payload.task);"
|
|
212
208
|
],
|
|
213
209
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
214
210
|
"timeoutSeconds": 300,
|
|
@@ -6,7 +6,7 @@
|
|
|
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\\.
|
|
9
|
+
"find": [" grep '^@earendil-works+' | grep -Ev '@0\\.86\\.0(_|$)' || true"],
|
|
10
10
|
"replace": [" grep '^@earendil-works+' | grep -v '@0\\.85\\.1' || true"],
|
|
11
11
|
"gate": ["bash", "run.sh", "check-pack-pin-matcher"],
|
|
12
12
|
"timeoutSeconds": 120,
|
|
@@ -17,8 +17,8 @@
|
|
|
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\\.
|
|
21
|
-
"replace": [" grep '^@earendil-works+pi-' | grep -Ev '@0\\.
|
|
20
|
+
"find": [" grep '^@earendil-works+' | grep -Ev '@0\\.86\\.0(_|$)' || true"],
|
|
21
|
+
"replace": [" grep '^@earendil-works+pi-' | grep -Ev '@0\\.86\\.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]",
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"lane": "pi-launch",
|
|
4
|
+
"mutants": [
|
|
5
|
+
{
|
|
6
|
+
"claim": "PILAUNCH-FLAG-SSOT",
|
|
7
|
+
"title": "the launcher spells the control flag itself, so a typo in run.sh silently produces a pi that is not a citizen and reports nothing",
|
|
8
|
+
"subject": "run.sh",
|
|
9
|
+
"find": [" exec \"$entwurf_pi_bin\" --entwurf-control \"$@\""],
|
|
10
|
+
"replace": [" exec \"$entwurf_pi_bin\" --entwurf-controll \"$@\""],
|
|
11
|
+
"gate": ["bash", "run.sh", "check-pi-launch"],
|
|
12
|
+
"timeoutSeconds": 300,
|
|
13
|
+
"signature": "[QK:PILAUNCH-FLAG-SSOT]",
|
|
14
|
+
"signatureSource": "scripts/check-pi-launch.ts"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"claim": "PILAUNCH-VERB-DROPPED",
|
|
18
|
+
"title": "without the shift the dispatcher verb stays in the forwarded argv and `pi` arrives at the vendor as a prompt argument",
|
|
19
|
+
"subject": "run.sh",
|
|
20
|
+
"find": [" shift || true\n if [ -n \"${ENTWURF_PI_LAUNCH_ACTIVE:-}\" ]; then"],
|
|
21
|
+
"replace": [" if [ -n \"${ENTWURF_PI_LAUNCH_ACTIVE:-}\" ]; then"],
|
|
22
|
+
"gate": ["bash", "run.sh", "check-pi-launch"],
|
|
23
|
+
"timeoutSeconds": 300,
|
|
24
|
+
"signature": "[QK:PILAUNCH-VERB-DROPPED]",
|
|
25
|
+
"signatureSource": "scripts/check-pi-launch.ts"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"claim": "PILAUNCH-FLAG-FIRST",
|
|
29
|
+
"title": "injecting the flag AFTER the operator argv puts it behind a positional prompt, where pi reads it as data instead of standing up a control socket",
|
|
30
|
+
"subject": "run.sh",
|
|
31
|
+
"find": [" exec \"$entwurf_pi_bin\" --entwurf-control \"$@\""],
|
|
32
|
+
"replace": [" exec \"$entwurf_pi_bin\" \"$@\" --entwurf-control"],
|
|
33
|
+
"gate": ["bash", "run.sh", "check-pi-launch"],
|
|
34
|
+
"timeoutSeconds": 300,
|
|
35
|
+
"signature": "[QK:PILAUNCH-FLAG-FIRST]",
|
|
36
|
+
"signatureSource": "scripts/check-pi-launch.ts"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"claim": "PILAUNCH-NOTHING-ELSE-INJECTED",
|
|
40
|
+
"title": "a launcher that also injects operator taste stops being a spelling and starts deciding the session (Rule 9)",
|
|
41
|
+
"subject": "run.sh",
|
|
42
|
+
"find": [" exec \"$entwurf_pi_bin\" --entwurf-control \"$@\""],
|
|
43
|
+
"replace": [" exec \"$entwurf_pi_bin\" --entwurf-control --emacs-agent-socket \"$@\""],
|
|
44
|
+
"gate": ["bash", "run.sh", "check-pi-launch"],
|
|
45
|
+
"timeoutSeconds": 300,
|
|
46
|
+
"signature": "[QK:PILAUNCH-NOTHING-ELSE-INJECTED]",
|
|
47
|
+
"signatureSource": "scripts/check-pi-launch.ts"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"claim": "PILAUNCH-ARGV-BYTES",
|
|
51
|
+
"title": "an unquoted forward word-splits the operator argv and drops empty elements, so a quoted prompt silently becomes several arguments",
|
|
52
|
+
"subject": "run.sh",
|
|
53
|
+
"find": [" exec \"$entwurf_pi_bin\" --entwurf-control \"$@\""],
|
|
54
|
+
"replace": [" exec \"$entwurf_pi_bin\" --entwurf-control $@"],
|
|
55
|
+
"gate": ["bash", "run.sh", "check-pi-launch"],
|
|
56
|
+
"timeoutSeconds": 300,
|
|
57
|
+
"signature": "[QK:PILAUNCH-ARGV-BYTES]",
|
|
58
|
+
"signatureSource": "scripts/check-pi-launch.ts"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"claim": "PILAUNCH-EXEC-KEEPS-PID",
|
|
62
|
+
"title": "forking instead of exec leaves run.sh as a parent that supervises nothing and owns neither the terminal nor the exit",
|
|
63
|
+
"subject": "run.sh",
|
|
64
|
+
"find": [" exec \"$entwurf_pi_bin\" --entwurf-control \"$@\""],
|
|
65
|
+
"replace": [" \"$entwurf_pi_bin\" --entwurf-control \"$@\""],
|
|
66
|
+
"gate": ["bash", "run.sh", "check-pi-launch"],
|
|
67
|
+
"timeoutSeconds": 300,
|
|
68
|
+
"signature": "[QK:PILAUNCH-EXEC-KEEPS-PID]",
|
|
69
|
+
"signatureSource": "scripts/check-pi-launch.ts"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"claim": "PILAUNCH-VENDOR-ABSENT",
|
|
73
|
+
"title": "an absent vendor that exits 0 is the false success this repo refuses: nothing launched and the caller was told it worked",
|
|
74
|
+
"subject": "run.sh",
|
|
75
|
+
"find": [
|
|
76
|
+
" echo \" 'entwurf pi' launches the pi coding agent; it does not install one.\" >&2\n exit 1"
|
|
77
|
+
],
|
|
78
|
+
"replace": [
|
|
79
|
+
" echo \" 'entwurf pi' launches the pi coding agent; it does not install one.\" >&2\n exit 0"
|
|
80
|
+
],
|
|
81
|
+
"gate": ["bash", "run.sh", "check-pi-launch"],
|
|
82
|
+
"timeoutSeconds": 300,
|
|
83
|
+
"signature": "[QK:PILAUNCH-VENDOR-ABSENT]",
|
|
84
|
+
"signatureSource": "scripts/check-pi-launch.ts"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"claim": "PILAUNCH-SENTINEL-EXPORTED",
|
|
88
|
+
"title": "a sentinel that is set but not exported is invisible to the re-entered child, so the recursion fence never fires and the terminal hangs",
|
|
89
|
+
"subject": "run.sh",
|
|
90
|
+
"find": [" export ENTWURF_PI_LAUNCH_ACTIVE=1"],
|
|
91
|
+
"replace": [" ENTWURF_PI_LAUNCH_ACTIVE=1"],
|
|
92
|
+
"gate": ["bash", "run.sh", "check-pi-launch"],
|
|
93
|
+
"timeoutSeconds": 300,
|
|
94
|
+
"signature": "[QK:PILAUNCH-SENTINEL-EXPORTED]",
|
|
95
|
+
"signatureSource": "scripts/check-pi-launch.ts"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"claim": "PILAUNCH-RECURSION-FENCE",
|
|
99
|
+
"title": "with the fence removed a PATH `pi` that shells back here spins forever, and the symptom is a hung terminal rather than an error",
|
|
100
|
+
"subject": "run.sh",
|
|
101
|
+
"find": [
|
|
102
|
+
" if [ -n \"${ENTWURF_PI_LAUNCH_ACTIVE:-}\" ]; then\n echo \"entwurf: recursive managed launch detected (ENTWURF_PI_LAUNCH_ACTIVE is already set).\" >&2"
|
|
103
|
+
],
|
|
104
|
+
"replace": [
|
|
105
|
+
" if false; then\n echo \"entwurf: recursive managed launch detected (ENTWURF_PI_LAUNCH_ACTIVE is already set).\" >&2"
|
|
106
|
+
],
|
|
107
|
+
"gate": ["bash", "run.sh", "check-pi-launch"],
|
|
108
|
+
"timeoutSeconds": 300,
|
|
109
|
+
"signature": "[QK:PILAUNCH-RECURSION-FENCE]",
|
|
110
|
+
"signatureSource": "scripts/check-pi-launch.ts"
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"gate": ["bash", "run.sh", "check-entwurf-resume-args"],
|
|
12
12
|
"timeoutSeconds": 60,
|
|
13
13
|
"signature": "[QK:RESUMEARGS-NO-HEADLESS]",
|
|
14
|
-
"signatureSource": "
|
|
14
|
+
"signatureSource": "pi-extensions/lib/entwurf-resume-args.test.ts"
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
17
|
"claim": "RESUMEARGS-CONTROL-FIRST",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"gate": ["bash", "run.sh", "check-entwurf-resume-args"],
|
|
25
25
|
"timeoutSeconds": 60,
|
|
26
26
|
"signature": "[QK:RESUMEARGS-CONTROL-FIRST]",
|
|
27
|
-
"signatureSource": "
|
|
27
|
+
"signatureSource": "pi-extensions/lib/entwurf-resume-args.test.ts"
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"claim": "RESUMEARGS-EXT-ONCE-BEFORE-SESSION",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"gate": ["bash", "run.sh", "check-entwurf-resume-args"],
|
|
38
38
|
"timeoutSeconds": 60,
|
|
39
39
|
"signature": "[QK:RESUMEARGS-EXT-ONCE-BEFORE-SESSION]",
|
|
40
|
-
"signatureSource": "
|
|
40
|
+
"signatureSource": "pi-extensions/lib/entwurf-resume-args.test.ts"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"claim": "RESUMEARGS-SESSION-IS-FILE",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"gate": ["bash", "run.sh", "check-entwurf-resume-args"],
|
|
49
49
|
"timeoutSeconds": 60,
|
|
50
50
|
"signature": "[QK:RESUMEARGS-SESSION-IS-FILE]",
|
|
51
|
-
"signatureSource": "
|
|
51
|
+
"signatureSource": "pi-extensions/lib/entwurf-resume-args.test.ts"
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
"claim": "RESUMEARGS-PROVIDER-OPTIONAL",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"gate": ["bash", "run.sh", "check-entwurf-resume-args"],
|
|
60
60
|
"timeoutSeconds": 60,
|
|
61
61
|
"signature": "[QK:RESUMEARGS-PROVIDER-OPTIONAL]",
|
|
62
|
-
"signatureSource": "
|
|
62
|
+
"signatureSource": "pi-extensions/lib/entwurf-resume-args.test.ts"
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
"claim": "RESUMEARGS-NO-PROMPT-TAIL",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"gate": ["bash", "run.sh", "check-entwurf-resume-args"],
|
|
71
71
|
"timeoutSeconds": 60,
|
|
72
72
|
"signature": "[QK:RESUMEARGS-NO-PROMPT-TAIL]",
|
|
73
|
-
"signatureSource": "
|
|
73
|
+
"signatureSource": "pi-extensions/lib/entwurf-resume-args.test.ts"
|
|
74
74
|
}
|
|
75
75
|
]
|
|
76
76
|
}
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"gate": ["bash", "run.sh", "check-entwurf-v2-send"],
|
|
26
26
|
"timeoutSeconds": 60,
|
|
27
27
|
"signature": "[QK:V2SEND-INBAND-REJECT-REASON]",
|
|
28
|
-
"signatureSource": "
|
|
28
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-send.test.ts"
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"claim": "V2PROD-INBAND-ERROR-WIRED",
|
|
@@ -206,7 +206,7 @@
|
|
|
206
206
|
"gate": ["bash", "run.sh", "check-entwurf-v2-native-push"],
|
|
207
207
|
"timeoutSeconds": 120,
|
|
208
208
|
"signature": "[QK:NATIVE-PUSH-RETRY-BYTE-IDENTITY]",
|
|
209
|
-
"signatureSource": "
|
|
209
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-native-push.test.ts"
|
|
210
210
|
}
|
|
211
211
|
]
|
|
212
212
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
12
12
|
"timeoutSeconds": 60,
|
|
13
13
|
"signature": "[QK:V2RESUME-LIVE-REFUSED]",
|
|
14
|
-
"signatureSource": "
|
|
14
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
17
|
"claim": "V2RESUME-INDETERMINATE-NO-START",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
23
23
|
"timeoutSeconds": 60,
|
|
24
24
|
"signature": "[QK:V2RESUME-INDETERMINATE-NO-START]",
|
|
25
|
-
"signatureSource": "
|
|
25
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
"claim": "V2RESUME-CONFLICT-NO-START",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
34
34
|
"timeoutSeconds": 60,
|
|
35
35
|
"signature": "[QK:V2RESUME-CONFLICT-NO-START]",
|
|
36
|
-
"signatureSource": "
|
|
36
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
"claim": "V2RESUME-LOCKED-NO-RESOLVE",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
45
45
|
"timeoutSeconds": 60,
|
|
46
46
|
"signature": "[QK:V2RESUME-LOCKED-NO-RESOLVE]",
|
|
47
|
-
"signatureSource": "
|
|
47
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
"claim": "V2RESUME-NO-TRANSCRIPT-FAILS-LOUD",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
68
68
|
"timeoutSeconds": 60,
|
|
69
69
|
"signature": "[QK:V2RESUME-NO-TRANSCRIPT-FAILS-LOUD]",
|
|
70
|
-
"signatureSource": "
|
|
70
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
"claim": "V2RESUME-OBSERVE-IS-BOUNDED-WAIT",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
79
79
|
"timeoutSeconds": 60,
|
|
80
80
|
"signature": "[QK:V2RESUME-OBSERVE-IS-BOUNDED-WAIT]",
|
|
81
|
-
"signatureSource": "
|
|
81
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
82
82
|
},
|
|
83
83
|
{
|
|
84
84
|
"claim": "V2RESUME-UNOBSERVED-IS-REAL",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
90
90
|
"timeoutSeconds": 60,
|
|
91
91
|
"signature": "[QK:V2RESUME-UNOBSERVED-IS-REAL]",
|
|
92
|
-
"signatureSource": "
|
|
92
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
"claim": "V2RESUME-RELEASE-FAILURE-LOUD",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
101
101
|
"timeoutSeconds": 60,
|
|
102
102
|
"signature": "[QK:V2RESUME-RELEASE-FAILURE-LOUD]",
|
|
103
|
-
"signatureSource": "
|
|
103
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
104
104
|
},
|
|
105
105
|
{
|
|
106
106
|
"claim": "V2RESUME-ARGV-FROM-RECORD",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
112
112
|
"timeoutSeconds": 60,
|
|
113
113
|
"signature": "[QK:V2RESUME-ARGV-FROM-RECORD]",
|
|
114
|
-
"signatureSource": "
|
|
114
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
115
115
|
},
|
|
116
116
|
{
|
|
117
117
|
"claim": "V2RESUME-RECEIPTS-SEPARATE",
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
125
125
|
"timeoutSeconds": 60,
|
|
126
126
|
"signature": "[QK:V2RESUME-RECEIPTS-SEPARATE]",
|
|
127
|
-
"signatureSource": "
|
|
127
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
128
128
|
},
|
|
129
129
|
{
|
|
130
130
|
"claim": "V2RESUME-RENDER-SEPARATES",
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
138
138
|
"timeoutSeconds": 60,
|
|
139
139
|
"signature": "[QK:V2RESUME-RENDER-SEPARATES]",
|
|
140
|
-
"signatureSource": "
|
|
140
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
141
141
|
},
|
|
142
142
|
{
|
|
143
143
|
"claim": "V2RESUME-IDENTITY-BEFORE-WINDOW",
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
149
149
|
"timeoutSeconds": 60,
|
|
150
150
|
"signature": "[QK:V2RESUME-IDENTITY-BEFORE-WINDOW]",
|
|
151
|
-
"signatureSource": "
|
|
151
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
152
152
|
},
|
|
153
153
|
{
|
|
154
154
|
"claim": "V2RESUME-TIMEOUT-RELEASES",
|
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
162
162
|
"timeoutSeconds": 60,
|
|
163
163
|
"signature": "[QK:V2RESUME-TIMEOUT-RELEASES]",
|
|
164
|
-
"signatureSource": "
|
|
164
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
165
165
|
},
|
|
166
166
|
{
|
|
167
167
|
"claim": "V2RESUME-LOCK-BEFORE-LIVENESS",
|
|
@@ -172,7 +172,7 @@
|
|
|
172
172
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
173
173
|
"timeoutSeconds": 60,
|
|
174
174
|
"signature": "[QK:V2RESUME-LOCK-BEFORE-LIVENESS]",
|
|
175
|
-
"signatureSource": "
|
|
175
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
176
176
|
},
|
|
177
177
|
{
|
|
178
178
|
"claim": "V2RESUME-NOT-PI-REFUSED",
|
|
@@ -183,7 +183,7 @@
|
|
|
183
183
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
184
184
|
"timeoutSeconds": 60,
|
|
185
185
|
"signature": "[QK:V2RESUME-NOT-PI-REFUSED]",
|
|
186
|
-
"signatureSource": "
|
|
186
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
187
187
|
},
|
|
188
188
|
{
|
|
189
189
|
"claim": "V2RESUME-NOT-PI-BY-FIELD",
|
|
@@ -198,7 +198,7 @@
|
|
|
198
198
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
199
199
|
"timeoutSeconds": 60,
|
|
200
200
|
"signature": "[QK:V2RESUME-NOT-PI-BY-FIELD]",
|
|
201
|
-
"signatureSource": "
|
|
201
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
202
202
|
},
|
|
203
203
|
{
|
|
204
204
|
"claim": "V2RESUME-SHARED-ID-GRAMMAR",
|
|
@@ -209,7 +209,7 @@
|
|
|
209
209
|
"gate": ["bash", "run.sh", "check-entwurf-v2-visible-resume"],
|
|
210
210
|
"timeoutSeconds": 60,
|
|
211
211
|
"signature": "[QK:V2RESUME-SHARED-ID-GRAMMAR]",
|
|
212
|
-
"signatureSource": "
|
|
212
|
+
"signatureSource": "pi-extensions/lib/entwurf-v2-visible-resume.test.ts"
|
|
213
213
|
}
|
|
214
214
|
]
|
|
215
215
|
}
|
|
@@ -67,6 +67,7 @@ export const EXPECTED_TOOLS = [
|
|
|
67
67
|
"entwurf_register_native",
|
|
68
68
|
"entwurf_fresh_call",
|
|
69
69
|
"entwurf_resume_call",
|
|
70
|
+
"entwurf_callback",
|
|
70
71
|
] as const;
|
|
71
72
|
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
72
73
|
/** How long a probed child gets to die politely before it is killed outright. */
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// LIVE=1 ./run.sh smoke-acp-raw-turn-live
|
|
4
4
|
//
|
|
5
5
|
// What this proves (and ONLY this): the pinned Claude ACP adapter
|
|
6
|
-
// (@agentclientprotocol/claude-agent-acp@0.
|
|
6
|
+
// (@agentclientprotocol/claude-agent-acp@0.79.0) spawns, speaks the ACP wire
|
|
7
7
|
// protocol over stdio NDJSON, and returns one real model turn. It is the
|
|
8
8
|
// bytes-flow proof that the S2a dep surface is not just installable but
|
|
9
9
|
// actually drivable — before any provider/overlay/streamSimple code (S2b+).
|
|
@@ -24,11 +24,26 @@ import { copyFileSync, mkdirSync, mkdtempSync, rmSync } from "node:fs";
|
|
|
24
24
|
import { tmpdir } from "node:os";
|
|
25
25
|
import { dirname, resolve } from "node:path";
|
|
26
26
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
27
|
-
import type { Api, AssistantMessageEvent,
|
|
27
|
+
import type { Api, AssistantMessageEvent, Model, TranscriptContext } from "@earendil-works/pi-ai";
|
|
28
|
+
import { normalizeContext } from "@earendil-works/pi-ai";
|
|
28
29
|
import { skipLive } from "./lib/live-skip.ts";
|
|
29
30
|
|
|
30
31
|
const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
31
32
|
const MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-5";
|
|
33
|
+
// The pi built-ins the Claude child also exposes natively. pi declares its tool surface on
|
|
34
|
+
// every turn, and since 0.86 that declaration reaches a provider as the leading system
|
|
35
|
+
// message's `toolsAdded` (`normalizeContext`), which backend.ts replays for the exclude-tools
|
|
36
|
+
// truthfulness preflight. A fixture that declares NO tools is therefore not "a turn with the
|
|
37
|
+
// defaults" — it is a turn where the operator excluded everything, and the preflight rejects it
|
|
38
|
+
// before the prompt is ever sent. So every provider-path context here is built through
|
|
39
|
+
// `normalizeContext`, never typed as a raw `Context`: that annotation is exactly what hid this
|
|
40
|
+
// shape from typecheck when the 0.86 pin landed.
|
|
41
|
+
const PI_DECLARED_TOOLS = ["read", "bash", "edit", "write"].map((name) => ({
|
|
42
|
+
name,
|
|
43
|
+
description: "",
|
|
44
|
+
parameters: {} as never,
|
|
45
|
+
}));
|
|
46
|
+
|
|
32
47
|
const TURN_TIMEOUT_MS = Number(process.env.ENTWURF_ACP_PROVIDER_TIMEOUT_MS) || 240_000;
|
|
33
48
|
|
|
34
49
|
function fail(msg: string): never {
|
|
@@ -101,7 +116,8 @@ async function main(): Promise<void> {
|
|
|
101
116
|
console.error(`[smoke-acp-session-reuse-live] codeword: ${codeword}`);
|
|
102
117
|
|
|
103
118
|
// --- turn 1 (new): introduce the codeword, full transcript ---
|
|
104
|
-
const turn1:
|
|
119
|
+
const turn1: TranscriptContext = normalizeContext({
|
|
120
|
+
tools: PI_DECLARED_TOOLS,
|
|
105
121
|
messages: [
|
|
106
122
|
{
|
|
107
123
|
role: "user",
|
|
@@ -109,7 +125,7 @@ async function main(): Promise<void> {
|
|
|
109
125
|
timestamp: 0,
|
|
110
126
|
},
|
|
111
127
|
],
|
|
112
|
-
};
|
|
128
|
+
});
|
|
113
129
|
const r1 = await withTimeout(
|
|
114
130
|
"turn 1",
|
|
115
131
|
consume(backend.streamShellAcp(model, turn1, options) as Stream),
|
|
@@ -121,7 +137,9 @@ async function main(): Promise<void> {
|
|
|
121
137
|
console.error("[smoke-acp-session-reuse-live] starting turn 2 reuse prompt");
|
|
122
138
|
|
|
123
139
|
// --- turn 2 (reuse): ask for the codeword, DELTA ONLY ---
|
|
124
|
-
|
|
140
|
+
// turn1.messages already carries the folded system message, so spreading it keeps the
|
|
141
|
+
// declared surface on the reuse turn too; normalizeContext does not double it.
|
|
142
|
+
const turn2: TranscriptContext = normalizeContext({
|
|
125
143
|
messages: [
|
|
126
144
|
...turn1.messages,
|
|
127
145
|
{
|
|
@@ -147,7 +165,7 @@ async function main(): Promise<void> {
|
|
|
147
165
|
timestamp: 0,
|
|
148
166
|
},
|
|
149
167
|
],
|
|
150
|
-
};
|
|
168
|
+
});
|
|
151
169
|
const r2 = await withTimeout(
|
|
152
170
|
"turn 2",
|
|
153
171
|
consume(backend.streamShellAcp(model, turn2, options) as Stream),
|
|
@@ -67,7 +67,7 @@ write_mcp_fake() { # $1 = path
|
|
|
67
67
|
while IFS= read -r line; do
|
|
68
68
|
case "$line" in
|
|
69
69
|
*'"id":1'*) printf '%s\n' '{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{},"serverInfo":{"name":"fake-entwurf-bridge","version":"0"}}}' ;;
|
|
70
|
-
*'"id":2'*) printf '%s\n' '{"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"entwurf_v2"},{"name":"entwurf_self"},{"name":"entwurf_peers"},{"name":"entwurf_inbox_read"},{"name":"entwurf_register_native"},{"name":"entwurf_fresh_call"},{"name":"entwurf_resume_call"}]}}' ;;
|
|
70
|
+
*'"id":2'*) printf '%s\n' '{"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"entwurf_v2"},{"name":"entwurf_self"},{"name":"entwurf_peers"},{"name":"entwurf_inbox_read"},{"name":"entwurf_register_native"},{"name":"entwurf_fresh_call"},{"name":"entwurf_resume_call"},{"name":"entwurf_callback"}]}}' ;;
|
|
71
71
|
esac
|
|
72
72
|
done
|
|
73
73
|
FAKE
|
|
@@ -89,7 +89,7 @@ if [ "${REVIEW_ENV:-}" = "fail" ]; then echo configured-env-failure >&2; exit 24
|
|
|
89
89
|
while IFS= read -r line; do
|
|
90
90
|
case "$line" in
|
|
91
91
|
*'"id":1'*) printf '%s\n' '{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{},"serverInfo":{"name":"fake-entwurf-bridge","version":"0"}}}' ;;
|
|
92
|
-
*'"id":2'*) printf '%s\n' '{"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"entwurf_v2"},{"name":"entwurf_self"},{"name":"entwurf_peers"},{"name":"entwurf_inbox_read"},{"name":"entwurf_register_native"},{"name":"entwurf_fresh_call"},{"name":"entwurf_resume_call"}]}}' ;;
|
|
92
|
+
*'"id":2'*) printf '%s\n' '{"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"entwurf_v2"},{"name":"entwurf_self"},{"name":"entwurf_peers"},{"name":"entwurf_inbox_read"},{"name":"entwurf_register_native"},{"name":"entwurf_fresh_call"},{"name":"entwurf_resume_call"},{"name":"entwurf_callback"}]}}' ;;
|
|
93
93
|
esac
|
|
94
94
|
done
|
|
95
95
|
FAKE
|