@junghanacs/entwurf 0.30.0 → 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.
- package/CHANGELOG.md +117 -0
- package/README.md +6 -1
- package/VERIFY.md +6 -3
- package/docs/acp-backend-rail.md +111 -18
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +43 -0
- package/package.json +4 -4
- package/pi-extensions/lib/acp/backend-adapter.ts +68 -0
- package/pi-extensions/lib/acp/backend.ts +41 -5
- package/run.sh +14 -3
- package/scripts/check-gate-qualification.ts +2 -1
- package/scripts/check-herdr-plugin-build.ts +159 -57
- package/scripts/fixtures/herdr-supply.json +8 -8
- package/scripts/mutants/acp-prompt-lifecycle.json +2 -2
- package/scripts/mutants/acp-vendor-rejection.json +62 -0
- package/scripts/mutants/herdr-plugin-build.json +11 -0
- package/scripts/mutants/herdr-supply.json +3 -3
- package/scripts/smoke-acp-raw-turn-live.ts +1 -1
- package/scripts/smoke-herdr-fresh-call-live.ts +21 -7
|
@@ -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
|
+
}
|
|
@@ -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.
|
|
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\": \"
|
|
23
|
-
"replace": ["\"sha256\": \"
|
|
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]",
|
|
@@ -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
|
|
6
|
+
// (@agentclientprotocol/claude-agent-acp, exact pin in package.json) 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+).
|
|
@@ -196,10 +196,9 @@ function transcriptRecords(file: string): string[] {
|
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
/**
|
|
199
|
-
* The
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
* writes `"type":"toolCall","name":"entwurf_callback"`; neither records
|
|
199
|
+
* The verb names as the CLAUDE MCP activity log spells them — NOT the model-facing dialect.
|
|
200
|
+
* `[측정 2026-09-20, this smoke's own red fixture]` that log carries `Calling MCP tool:
|
|
201
|
+
* entwurf_callback` / `Tool 'entwurf_callback' completed`, never
|
|
203
202
|
* `mcp__entwurf-bridge__entwurf_callback`. The per-host dialect is owned by
|
|
204
203
|
* `FRESH_CALL_CALLBACK_TOOL` / `FRESH_CALL_DELIVERY_TOOL` in `fresh-call-composition.ts` and is
|
|
205
204
|
* what the FRAMING says; these two are what an OBSERVER sees, and conflating them is what this
|
|
@@ -208,6 +207,17 @@ function transcriptRecords(file: string): string[] {
|
|
|
208
207
|
const CALLBACK_VERB = "entwurf_callback";
|
|
209
208
|
const DELIVERY_VERB = "entwurf_v2";
|
|
210
209
|
|
|
210
|
+
/**
|
|
211
|
+
* The callback as a Pi 1.0 TRANSCRIPT spells it. Pi's built-in MCP is the tool ingress since
|
|
212
|
+
* 0.30.0, and Pi records the qualified name the model called. The bare `entwurf_callback` this
|
|
213
|
+
* smoke read on 2026-09-20 belonged to the retired native-tool registration; a pi→pi child that
|
|
214
|
+
* called back correctly would then never match, which is a red about the oracle, not the rail.
|
|
215
|
+
* Declared here as the OBSERVED literal, not imported from the compositor, so a change to the
|
|
216
|
+
* production framing cannot quietly move this expectation with it — the same rule as
|
|
217
|
+
* `PI_SOURCE_VERBS` in `lib/codex-fresh-source-receipts.ts`. No prefix strip, no legacy OR.
|
|
218
|
+
*/
|
|
219
|
+
const PI_CALLBACK_TOOL = "mcp__entwurf_bridge__entwurf_callback";
|
|
220
|
+
|
|
211
221
|
/**
|
|
212
222
|
* The id of the CALLBACK toolCall in this record, or null. Pi writes a call and its result as two
|
|
213
223
|
* records; this is one half of the join that replaces a same-record read.
|
|
@@ -238,7 +248,9 @@ function entwurfCallIdFor(record: string, nonce: string, callerGid: string): str
|
|
|
238
248
|
if (!Array.isArray(content)) return null;
|
|
239
249
|
for (const part of content) {
|
|
240
250
|
const call = part as { type?: unknown; name?: unknown; id?: unknown; arguments?: unknown };
|
|
241
|
-
if (call.type !== "toolCall"
|
|
251
|
+
if (call.type !== "toolCall") continue;
|
|
252
|
+
if (call.name === CALLBACK_VERB) throw new Error(`${LABEL}: retired raw Pi tool name ${CALLBACK_VERB}`);
|
|
253
|
+
if (call.name !== PI_CALLBACK_TOOL) continue;
|
|
242
254
|
// Zero-argument verb: absent, null and `{}` are all the shape it is called with. A supplied
|
|
243
255
|
// target or message is a model naming an address the env already owns — not this act.
|
|
244
256
|
const args = call.arguments as { message?: unknown; target?: unknown } | undefined | null;
|
|
@@ -444,8 +456,10 @@ async function main(): Promise<void> {
|
|
|
444
456
|
childBackend: "pi",
|
|
445
457
|
callerKind: "pi",
|
|
446
458
|
childKind: "pi",
|
|
447
|
-
|
|
448
|
-
|
|
459
|
+
// The approved roster's lighter Pi GPT tier (agent-config MODELS.md, 2026-09-30); gpt-5.6-sol
|
|
460
|
+
// is still in the catalog but no longer on the roster. A LIVE cost choice, not a product set.
|
|
461
|
+
callerModel: "openai-codex/gpt-6-luna",
|
|
462
|
+
childModel: "openai-codex/gpt-6-luna",
|
|
449
463
|
},
|
|
450
464
|
{
|
|
451
465
|
label: "claude→claude",
|