@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.
@@ -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.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]",
@@ -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.79.0) spawns, speaks the ACP wire
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 BARE verb names, as the two surfaces this smoke reads actually spell them — NOT the
200
- * model-facing dialect. `[측정 2026-09-20, this smoke's own red fixture]` the claude MCP activity
201
- * log carries `Calling MCP tool: entwurf_callback` / `Tool 'entwurf_callback' completed`, and pi
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" || call.name !== CALLBACK_VERB) continue;
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
- callerModel: "openai-codex/gpt-5.6-sol",
448
- childModel: "openai-codex/gpt-5.6-sol",
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",