@junghanacs/entwurf 0.41.2 → 0.45.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 +1 -0
- package/CHANGELOG.md +159 -0
- package/ENTWURF.json +236 -0
- package/README.md +12 -7
- package/docs/setup-clean-host.md +8 -8
- package/mcp/entwurf-bridge/dist/ENTWURF.json +236 -0
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +27 -188
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/agent-guidance.js +299 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +21 -25
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-visible-resume.js +15 -11
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +23 -20
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-resume-call.js +18 -16
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/remote-pair-send.js +7 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-pi-durable.js +23 -45
- package/mcp/entwurf-bridge/src/index.ts +121 -319
- package/package.json +3 -2
- package/pi-extensions/lib/agent-guidance.ts +341 -0
- package/pi-extensions/lib/entwurf-v2-surface.ts +25 -31
- package/pi-extensions/lib/entwurf-v2-visible-resume.ts +15 -16
- package/pi-extensions/lib/mux-fresh-call.ts +23 -26
- package/pi-extensions/lib/mux-resume-call.ts +18 -19
- package/pi-extensions/lib/remote-pair-send.ts +7 -4
- package/pi-extensions/meta-bridge-pi-durable.ts +23 -64
- package/run.sh +9 -0
- package/scripts/build-bridge.sh +10 -0
- package/scripts/check-capability-bundle-reach.ts +86 -0
- package/scripts/check-entwurf-self-address.ts +3 -3
- package/scripts/check-entwurf-v2-surface.ts +94 -98
- package/scripts/check-gate-qualification.ts +9 -7
- package/scripts/check-mux-resume-call.ts +20 -3
- package/scripts/mutants/agent-guidance.json +160 -0
- package/scripts/mutants/bridge-boot-resume.json +6 -8
- package/scripts/mutants/capability-bundle-reach.json +124 -0
- package/scripts/mutants/control-send-receipt.json +21 -4
- package/scripts/mutants/mux-fresh-call.json +14 -3
- package/scripts/mutants/mux-resume-call.json +28 -3
- package/scripts/mutants/pi-durable.json +17 -5
- package/scripts/mutants/remote-pair-send.json +21 -2
- package/scripts/mutants/self-address.json +10 -10
- package/scripts/mutants/v2-surface.json +50 -64
- package/scripts/mutants/v2-visible-resume.json +11 -0
|
@@ -19,11 +19,9 @@
|
|
|
19
19
|
"claim": "BRIDGEBOOT-RESUME-CALL-TARGET-ONLY",
|
|
20
20
|
"title": "a model knob is added to the resume schema, giving the caller a second way to decide what a resumed citizen is after the record already decided",
|
|
21
21
|
"subject": "mcp/entwurf-bridge/src/index.ts",
|
|
22
|
-
"find": [
|
|
23
|
-
"\t\t\t.describe(\"Garden id of the DORMANT pi or Claude Code citizen to reopen (discover with entwurf_peers).\"),"
|
|
24
|
-
],
|
|
22
|
+
"find": ["\t\t\t.describe(ENTWURF_TOOL_GUIDANCE.entwurf_resume_call.parameters[\"target\"]),"],
|
|
25
23
|
"replace": [
|
|
26
|
-
"\t\t\t.describe(\"
|
|
24
|
+
"\t\t\t.describe(ENTWURF_TOOL_GUIDANCE.entwurf_resume_call.parameters[\"target\"]),",
|
|
27
25
|
"\t\tmodel: z.string().optional().describe(\"Override the recorded model.\"),"
|
|
28
26
|
],
|
|
29
27
|
"gate": ["bash", "run.sh", "check-entwurf-bridge-boot"],
|
|
@@ -48,9 +46,9 @@
|
|
|
48
46
|
"claim": "BRIDGEBOOT-CALLBACK-REGISTERED",
|
|
49
47
|
"title": "the callback verb is imported but never registered — invisible to every host, while every import-level assertion stays green",
|
|
50
48
|
"subject": "mcp/entwurf-bridge/src/index.ts",
|
|
51
|
-
"find": ["server.tool(\
|
|
49
|
+
"find": ["server.tool(\"entwurf_callback\","],
|
|
52
50
|
"replace": [
|
|
53
|
-
"const _unregisteredCallbackTool = (...a: unknown[]) => void a;\n_unregisteredCallbackTool(\
|
|
51
|
+
"const _unregisteredCallbackTool = (...a: unknown[]) => void a;\n_unregisteredCallbackTool(\"entwurf_callback\","
|
|
54
52
|
],
|
|
55
53
|
"gate": ["bash", "run.sh", "check-entwurf-bridge-boot"],
|
|
56
54
|
"timeoutSeconds": 120,
|
|
@@ -61,9 +59,9 @@
|
|
|
61
59
|
"claim": "BRIDGEBOOT-CALLBACK-ZERO-ARG",
|
|
62
60
|
"title": "a target parameter is added to the callback schema, giving the model a way to supply an address the env pair was meant to own",
|
|
63
61
|
"subject": "mcp/entwurf-bridge/src/index.ts",
|
|
64
|
-
"find": ["\
|
|
62
|
+
"find": ["server.tool(\"entwurf_callback\", ENTWURF_TOOL_GUIDANCE.entwurf_callback.descriptions.mcp, {},"],
|
|
65
63
|
"replace": [
|
|
66
|
-
"\
|
|
64
|
+
"server.tool(\"entwurf_callback\", ENTWURF_TOOL_GUIDANCE.entwurf_callback.descriptions.mcp, { target: z.string().optional() },"
|
|
67
65
|
],
|
|
68
66
|
"gate": ["bash", "run.sh", "check-entwurf-bridge-boot"],
|
|
69
67
|
"timeoutSeconds": 120,
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"lane": "capability-bundle-reach",
|
|
4
|
+
"mutants": [
|
|
5
|
+
{
|
|
6
|
+
"claim": "BUNDLE-REACH-GUIDANCE-CARRIER",
|
|
7
|
+
"title": "the private build appends one LF to the emitted guidance carrier: valid JSON and all decoded exports stay identical, but canonical raw-byte parity must fail before the reader import",
|
|
8
|
+
"subject": "scripts/build-bridge.sh",
|
|
9
|
+
"find": ["cp \"$GUIDANCE_SOURCE\" \"$REPO_DIR/mcp/entwurf-bridge/dist/ENTWURF.json\""],
|
|
10
|
+
"replace": [
|
|
11
|
+
"cp \"$GUIDANCE_SOURCE\" \"$REPO_DIR/mcp/entwurf-bridge/dist/ENTWURF.json\"",
|
|
12
|
+
"printf '\\n' >> \"$REPO_DIR/mcp/entwurf-bridge/dist/ENTWURF.json\""
|
|
13
|
+
],
|
|
14
|
+
"gate": ["bash", "run.sh", "check-capability-bundle-reach"],
|
|
15
|
+
"timeoutSeconds": 300,
|
|
16
|
+
"signature": "[QK:BUNDLE-REACH-GUIDANCE-CARRIER]",
|
|
17
|
+
"signatureSource": "scripts/check-capability-bundle-reach.ts",
|
|
18
|
+
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"claim": "BUNDLE-REACH-REJECT-HINTS",
|
|
22
|
+
"title": "the compiled reader exports one static reject hint with a trailing space while the carrier keeps canonical Root bytes and the version/tools exports stay identical, so only the compiled hint-family reach can fail",
|
|
23
|
+
"subject": "pi-extensions/lib/agent-guidance.ts",
|
|
24
|
+
"find": ["export const ENTWURF_REJECT_HINTS = guidance.rejectHints;"],
|
|
25
|
+
"replace": [
|
|
26
|
+
"export const ENTWURF_REJECT_HINTS: typeof guidance.rejectHints = Object.freeze({",
|
|
27
|
+
"\t...guidance.rejectHints,",
|
|
28
|
+
"\t\"native-push-paused\": `${guidance.rejectHints[\"native-push-paused\"]} `,",
|
|
29
|
+
"});"
|
|
30
|
+
],
|
|
31
|
+
"gate": ["bash", "run.sh", "check-capability-bundle-reach"],
|
|
32
|
+
"timeoutSeconds": 300,
|
|
33
|
+
"signature": "[QK:BUNDLE-REACH-REJECT-HINTS]",
|
|
34
|
+
"signatureSource": "scripts/check-capability-bundle-reach.ts",
|
|
35
|
+
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"claim": "BUNDLE-REACH-RESUME-REJECT-HINTS",
|
|
39
|
+
"title": "the compiled reader exports one static visible-resume reject hint with a trailing space while the carrier keeps canonical Root bytes and the version/tools/reject-hint exports stay identical, so only the compiled resume-hint-family reach can fail",
|
|
40
|
+
"subject": "pi-extensions/lib/agent-guidance.ts",
|
|
41
|
+
"find": ["export const ENTWURF_RESUME_REJECT_HINTS = guidance.resumeRejectHints;"],
|
|
42
|
+
"replace": [
|
|
43
|
+
"export const ENTWURF_RESUME_REJECT_HINTS: typeof guidance.resumeRejectHints = Object.freeze({",
|
|
44
|
+
"\t...guidance.resumeRejectHints,",
|
|
45
|
+
"\t\"launch-refused\": `${guidance.resumeRejectHints[\"launch-refused\"]} `,",
|
|
46
|
+
"});"
|
|
47
|
+
],
|
|
48
|
+
"gate": ["bash", "run.sh", "check-capability-bundle-reach"],
|
|
49
|
+
"timeoutSeconds": 300,
|
|
50
|
+
"signature": "[QK:BUNDLE-REACH-RESUME-REJECT-HINTS]",
|
|
51
|
+
"signatureSource": "scripts/check-capability-bundle-reach.ts",
|
|
52
|
+
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"claim": "BUNDLE-REACH-LAUNCH-REJECT-HINTS",
|
|
56
|
+
"title": "the compiled reader exports one fresh launch-stage hint with a trailing space while the carrier keeps canonical Root bytes and every earlier export stays identical, so only the compiled launch-family reach can fail",
|
|
57
|
+
"subject": "pi-extensions/lib/agent-guidance.ts",
|
|
58
|
+
"find": ["export const ENTWURF_FRESH_LAUNCH_REJECT_HINTS = guidance.freshLaunchRejectHints;"],
|
|
59
|
+
"replace": [
|
|
60
|
+
"export const ENTWURF_FRESH_LAUNCH_REJECT_HINTS: typeof guidance.freshLaunchRejectHints = Object.freeze({",
|
|
61
|
+
"\t...guidance.freshLaunchRejectHints,",
|
|
62
|
+
"\t\"runtime-missing\": `${guidance.freshLaunchRejectHints[\"runtime-missing\"]} `,",
|
|
63
|
+
"});"
|
|
64
|
+
],
|
|
65
|
+
"gate": ["bash", "run.sh", "check-capability-bundle-reach"],
|
|
66
|
+
"timeoutSeconds": 300,
|
|
67
|
+
"signature": "[QK:BUNDLE-REACH-LAUNCH-REJECT-HINTS]",
|
|
68
|
+
"signatureSource": "scripts/check-capability-bundle-reach.ts",
|
|
69
|
+
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"claim": "BUNDLE-REACH-DELIVERY-RESULT-CLAUSES",
|
|
73
|
+
"title": "the compiled reader exports one delivery-result clause with a trailing space while the carrier keeps canonical Root bytes and every earlier export stays identical, so only the compiled delivery-clause reach can fail",
|
|
74
|
+
"subject": "pi-extensions/lib/agent-guidance.ts",
|
|
75
|
+
"find": ["export const ENTWURF_DELIVERY_RESULT_CLAUSES = guidance.deliveryResultClauses;"],
|
|
76
|
+
"replace": [
|
|
77
|
+
"export const ENTWURF_DELIVERY_RESULT_CLAUSES: typeof guidance.deliveryResultClauses = Object.freeze({",
|
|
78
|
+
"\t...guidance.deliveryResultClauses,",
|
|
79
|
+
"\t\"dirty-lock\": `${guidance.deliveryResultClauses[\"dirty-lock\"]} `,",
|
|
80
|
+
"});"
|
|
81
|
+
],
|
|
82
|
+
"gate": ["bash", "run.sh", "check-capability-bundle-reach"],
|
|
83
|
+
"timeoutSeconds": 300,
|
|
84
|
+
"signature": "[QK:BUNDLE-REACH-DELIVERY-RESULT-CLAUSES]",
|
|
85
|
+
"signatureSource": "scripts/check-capability-bundle-reach.ts",
|
|
86
|
+
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"claim": "BUNDLE-REACH-SLOTTED-REJECT-HINTS",
|
|
90
|
+
"title": "the compiled reader exports one slotted reject-hint segment with a trailing space while the carrier keeps canonical Root bytes and every earlier export stays identical, so only the compiled slotted-family reach can fail",
|
|
91
|
+
"subject": "pi-extensions/lib/agent-guidance.ts",
|
|
92
|
+
"find": ["export const ENTWURF_SLOTTED_REJECT_HINTS = guidance.slottedRejectHints;"],
|
|
93
|
+
"replace": [
|
|
94
|
+
"export const ENTWURF_SLOTTED_REJECT_HINTS: typeof guidance.slottedRejectHints = Object.freeze({",
|
|
95
|
+
"\t\"record-less-socket\": Object.freeze({",
|
|
96
|
+
"\t\t...guidance.slottedRejectHints[\"record-less-socket\"],",
|
|
97
|
+
"\t\tafterFreshCutPrescription: `${guidance.slottedRejectHints[\"record-less-socket\"].afterFreshCutPrescription} `,",
|
|
98
|
+
"\t}),",
|
|
99
|
+
"});"
|
|
100
|
+
],
|
|
101
|
+
"gate": ["bash", "run.sh", "check-capability-bundle-reach"],
|
|
102
|
+
"timeoutSeconds": 300,
|
|
103
|
+
"signature": "[QK:BUNDLE-REACH-SLOTTED-REJECT-HINTS]",
|
|
104
|
+
"signatureSource": "scripts/check-capability-bundle-reach.ts",
|
|
105
|
+
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"claim": "BUNDLE-REACH-RECORD-LESS-SOCKET-CONSUMER",
|
|
109
|
+
"title": "the surface source returns a hand-kept copy of the record-less-socket hint, one byte off the Root segments, instead of composing them with the owner's fix command; the build carries it into the compiled surface while the carrier and every reader export stay canonical, so only the compiled consumer cell can fail",
|
|
110
|
+
"subject": "pi-extensions/lib/entwurf-v2-surface.ts",
|
|
111
|
+
"find": [
|
|
112
|
+
"\t\t\treturn `${hint.beforeFreshCutPrescription}${FRESH_CUT_PRESCRIPTION}${hint.afterFreshCutPrescription}`;"
|
|
113
|
+
],
|
|
114
|
+
"replace": [
|
|
115
|
+
"\t\t\treturn `a control socket exists at this garden id but NO meta-record claims it — the record is the sole address authority, so a bare socket is not an addressable citizen. If a pre-record-era resident owns that socket, restart it under the current runtime (session_start births its record); if the store predates the current generation, quiesce and archive it with ${FRESH_CUT_PRESCRIPTION}. A stale/forged socket should be removed.`;"
|
|
116
|
+
],
|
|
117
|
+
"gate": ["bash", "run.sh", "check-capability-bundle-reach"],
|
|
118
|
+
"timeoutSeconds": 300,
|
|
119
|
+
"signature": "[QK:BUNDLE-REACH-RECORD-LESS-SOCKET-CONSUMER]",
|
|
120
|
+
"signatureSource": "scripts/check-capability-bundle-reach.ts",
|
|
121
|
+
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
@@ -153,7 +153,7 @@
|
|
|
153
153
|
"title": "the dirty-lock line goes back to `DELIVERED (<route>)` for all three shapes that reach it — a refusal that delivered nothing, a message lying in a volatile queue, and a durable mailbox file all read as one word, at the exact moment an operator is deciding BY HAND whether anything still needs sending",
|
|
154
154
|
"subject": "pi-extensions/lib/entwurf-v2-surface.ts",
|
|
155
155
|
"find": [
|
|
156
|
-
"\t\t\t\t\t\t? `rejected${result.finalizedRejectReason ? ` (${result.finalizedRejectReason})` : \"\"} —
|
|
156
|
+
"\t\t\t\t\t\t? `rejected${result.finalizedRejectReason ? ` (${result.finalizedRejectReason})` : \"\"} — ${ENTWURF_DELIVERY_RESULT_CLAUSES[\"finalized-rejected\"]}`"
|
|
157
157
|
],
|
|
158
158
|
"replace": ["\t\t\t\t\t\t? `DELIVERED (${result.finalizedOutcome})`"],
|
|
159
159
|
"gate": ["bash", "run.sh", "check-entwurf-v2-surface"],
|
|
@@ -161,6 +161,19 @@
|
|
|
161
161
|
"signature": "[QK:SEND-DIRTY-LOCK-NAMES-ACCEPTANCE]",
|
|
162
162
|
"signatureSource": "scripts/check-entwurf-v2-surface.ts"
|
|
163
163
|
},
|
|
164
|
+
{
|
|
165
|
+
"claim": "V2SURF-DELIVERY-RESULT-CLAUSES-FROM-ROOT",
|
|
166
|
+
"title": "the dirty-lock receipt reads a hand-kept copy of its clause, one byte off the Root text, instead of the Root lookup: DIRTY and do NOT retry still read on every shape, so only the whole-line comparison against Root can see the drift",
|
|
167
|
+
"subject": "pi-extensions/lib/entwurf-v2-surface.ts",
|
|
168
|
+
"find": ["\t\t\t\t\t\t`${ENTWURF_DELIVERY_RESULT_CLAUSES[\"dirty-lock\"]}\\n error: ${result.error}`,"],
|
|
169
|
+
"replace": [
|
|
170
|
+
"\t\t\t\t\t\t`the lock is DIRTY (release failed) — do NOT retry automatically. Inspect the reported acceptance and have the operator resolve the lock before deciding whether to resend.\\n error: ${result.error}`,"
|
|
171
|
+
],
|
|
172
|
+
"gate": ["bash", "run.sh", "check-entwurf-v2-surface"],
|
|
173
|
+
"timeoutSeconds": 300,
|
|
174
|
+
"signature": "[QK:V2SURF-DELIVERY-RESULT-CLAUSES-FROM-ROOT]",
|
|
175
|
+
"signatureSource": "scripts/check-entwurf-v2-surface.ts"
|
|
176
|
+
},
|
|
164
177
|
{
|
|
165
178
|
"claim": "VITEST-TEST-DIR-ON-THE-FLOOR",
|
|
166
179
|
"title": "the pi queue oracle's public coordinate is dropped from `check:vitest`, so the file that proves every claim the receipt makes about a receiver's queues is green only when somebody runs `pnpm test` by hand — the discovery door deliberately does not select `test/**`, so nothing else would notice",
|
|
@@ -225,9 +238,13 @@
|
|
|
225
238
|
{
|
|
226
239
|
"claim": "SEND-OUTCOME-LIST-NAMES-EVERY-RAIL",
|
|
227
240
|
"title": "the caller-facing outcome list drops the native-push rail, so a caller reading the one blurb it reads before dispatching is told the control rail's vocabulary covers a rail that answers with a direct injection instead",
|
|
228
|
-
"subject": "
|
|
229
|
-
"find": [
|
|
230
|
-
|
|
241
|
+
"subject": "ENTWURF.json",
|
|
242
|
+
"find": [
|
|
243
|
+
"native-push INJECTION, a rejection, or lock-dirty. This receipt is not the colleague's reply or evidence of reading. EXISTING targets only; discover with "
|
|
244
|
+
],
|
|
245
|
+
"replace": [
|
|
246
|
+
"a rejection, or lock-dirty. This receipt is not the colleague's reply or evidence of reading. EXISTING targets only; discover with "
|
|
247
|
+
],
|
|
231
248
|
"gate": ["bash", "run.sh", "check-entwurf-v2-surface"],
|
|
232
249
|
"timeoutSeconds": 300,
|
|
233
250
|
"signature": "[QK:SEND-OUTCOME-LIST-NAMES-EVERY-RAIL]",
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
"title": "the fresh-call surface drops the optional cwd from its schema, so cross-repo fresh silently cannot exist from any caller — pi included, which reaches this bridge since #125",
|
|
128
128
|
"subject": "mcp/entwurf-bridge/src/index.ts",
|
|
129
129
|
"find": [
|
|
130
|
-
"\t\tcwd: z
|
|
130
|
+
"\t\tcwd: z.string().optional().describe(ENTWURF_TOOL_GUIDANCE.entwurf_fresh_call.parameters[\"cwd\"]),\n"
|
|
131
131
|
],
|
|
132
132
|
"replace": [""],
|
|
133
133
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
@@ -153,7 +153,7 @@
|
|
|
153
153
|
"title": "MCP drops the required model field from fresh-call while the composition still expects one",
|
|
154
154
|
"subject": "mcp/entwurf-bridge/src/index.ts",
|
|
155
155
|
"find": [
|
|
156
|
-
"\t\tmodel: z\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.max(200)\n\t\t\t// The `\\[` below is USELESS TO JS AND LOAD-BEARING TO THE HOST. zod emits this source\n\t\t\t// text verbatim as the JSON Schema `pattern`, and the host's tool-schema validator is a\n\t\t\t// Rust regex engine that rejects an unescaped `[` inside a character class as \"unclosed\n\t\t\t// character class\" — a 400 on tools/list that stops EVERY Claude session from opening\n\t\t\t// (7-M-fix). Biome's safe fix removes it; do not accept that fix. The suppression must\n\t\t\t// stay on the line DIRECTLY above the expression, or it attaches to nothing and reads\n\t\t\t// as an unused suppression while the escape goes back to being fixable.\n\t\t\t// biome-ignore lint/complexity/noUselessEscapeInRegex: emitted to a Rust regex validator, see above\n\t\t\t.regex(/^[A-Za-z0-9][A-Za-z0-9._/:\\[\\]-]*$/)\n\t\t\t.describe(\
|
|
156
|
+
"\t\tmodel: z\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.max(200)\n\t\t\t// The `\\[` below is USELESS TO JS AND LOAD-BEARING TO THE HOST. zod emits this source\n\t\t\t// text verbatim as the JSON Schema `pattern`, and the host's tool-schema validator is a\n\t\t\t// Rust regex engine that rejects an unescaped `[` inside a character class as \"unclosed\n\t\t\t// character class\" — a 400 on tools/list that stops EVERY Claude session from opening\n\t\t\t// (7-M-fix). Biome's safe fix removes it; do not accept that fix. The suppression must\n\t\t\t// stay on the line DIRECTLY above the expression, or it attaches to nothing and reads\n\t\t\t// as an unused suppression while the escape goes back to being fixable.\n\t\t\t// biome-ignore lint/complexity/noUselessEscapeInRegex: emitted to a Rust regex validator, see above\n\t\t\t.regex(/^[A-Za-z0-9][A-Za-z0-9._/:\\[\\]-]*$/)\n\t\t\t.describe(ENTWURF_TOOL_GUIDANCE.entwurf_fresh_call.parameters[\"model\"]),\n"
|
|
157
157
|
],
|
|
158
158
|
"replace": [""],
|
|
159
159
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
@@ -514,7 +514,7 @@
|
|
|
514
514
|
"title": "the fresh-call surface drops the optional seat from its schema, so opening a sibling in the operator's project session silently cannot exist from any caller",
|
|
515
515
|
"subject": "mcp/entwurf-bridge/src/index.ts",
|
|
516
516
|
"find": [
|
|
517
|
-
"\t\tplacement: z\n\t\t\t.object({\n\t\t\t\ttmuxSession: z
|
|
517
|
+
"\t\tplacement: z\n\t\t\t.object({\n\t\t\t\ttmuxSession: z.string().describe(ENTWURF_TOOL_GUIDANCE.entwurf_fresh_call.parameters[\"placement.tmuxSession\"]),\n\t\t\t})\n\t\t\t.optional()\n\t\t\t.describe(ENTWURF_TOOL_GUIDANCE.entwurf_fresh_call.parameters[\"placement\"]),\n"
|
|
518
518
|
],
|
|
519
519
|
"replace": [""],
|
|
520
520
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
@@ -781,6 +781,17 @@
|
|
|
781
781
|
"timeoutSeconds": 120,
|
|
782
782
|
"signature": "[QK:PD-FRESH-LIVE-BOOTSTRAP-ORDER]",
|
|
783
783
|
"signatureSource": "test/pi-durable-fresh-live-receipts.test.ts"
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
"claim": "FRESHCALL-LAUNCH-REJECT-HINTS-FROM-ROOT",
|
|
787
|
+
"title": "one static tmux launch-stage hint is inlined as a literal one byte away from the Root text, so the reader and its byte oracle stay green and only the rendered refusal can disagree with Root",
|
|
788
|
+
"subject": "pi-extensions/lib/mux-fresh-call.ts",
|
|
789
|
+
"find": ["\t\"anchor-malformed\": ENTWURF_FRESH_LAUNCH_REJECT_HINTS[\"anchor-malformed\"],"],
|
|
790
|
+
"replace": ["\t\"anchor-malformed\": \"TMUX_PANE is not a native pane id\","],
|
|
791
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
792
|
+
"timeoutSeconds": 120,
|
|
793
|
+
"signature": "[QK:FRESHCALL-LAUNCH-REJECT-HINTS-FROM-ROOT]",
|
|
794
|
+
"signatureSource": "test/mux-fresh-call.test.ts"
|
|
784
795
|
}
|
|
785
796
|
]
|
|
786
797
|
}
|
|
@@ -98,12 +98,12 @@
|
|
|
98
98
|
{
|
|
99
99
|
"claim": "MUXRESUME-DESC-CONTRACT-MCP",
|
|
100
100
|
"title": "the MCP description drops the dormant-only scope, inviting callers to aim the verb at live citizens it will refuse",
|
|
101
|
-
"subject": "
|
|
101
|
+
"subject": "ENTWURF.json",
|
|
102
102
|
"find": [
|
|
103
|
-
"
|
|
103
|
+
"Only on an explicit operator request, reopen ONE DORMANT pi or Claude Code citizen under its OWN garden id, in a visible window in the operator's "
|
|
104
104
|
],
|
|
105
105
|
"replace": [
|
|
106
|
-
"
|
|
106
|
+
"Only on an explicit operator request, reopen ONE pi or Claude Code citizen under its OWN garden id, in a visible window in the operator's "
|
|
107
107
|
],
|
|
108
108
|
"gate": ["bash", "run.sh", "check-mux-resume-call"],
|
|
109
109
|
"timeoutSeconds": 60,
|
|
@@ -155,6 +155,31 @@
|
|
|
155
155
|
"timeoutSeconds": 60,
|
|
156
156
|
"signature": "[QK:MUXRESUME-ARGV-IDENTITY-SCRUB]",
|
|
157
157
|
"signatureSource": "scripts/check-mux-resume-call.ts"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"claim": "MUXRESUME-LAUNCH-REJECT-HINTS-FROM-ROOT",
|
|
161
|
+
"title": "one launch-stage resume hint is inlined as a literal one byte away from the Root text, so the reader and its byte oracle stay green and only the table-to-Root wiring can disagree",
|
|
162
|
+
"subject": "pi-extensions/lib/mux-resume-call.ts",
|
|
163
|
+
"find": ["\t\"anchor-malformed\": ENTWURF_RESUME_LAUNCH_REJECT_HINTS[\"anchor-malformed\"],"],
|
|
164
|
+
"replace": ["\t\"anchor-malformed\": \"TMUX_PANE is not a native pane id\","],
|
|
165
|
+
"gate": ["bash", "run.sh", "check-mux-resume-call"],
|
|
166
|
+
"timeoutSeconds": 60,
|
|
167
|
+
"signature": "[QK:MUXRESUME-LAUNCH-REJECT-HINTS-FROM-ROOT]",
|
|
168
|
+
"signatureSource": "scripts/check-mux-resume-call.ts"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"claim": "MUXRESUME-IMPORT-SET",
|
|
172
|
+
"title": "the resume composition gains a bare side-effect import, the weakest static form, which loads and runs fine, so only the exact import-set parser can see the new lane",
|
|
173
|
+
"subject": "pi-extensions/lib/mux-resume-call.ts",
|
|
174
|
+
"find": ["import { ENTWURF_RESUME_LAUNCH_REJECT_HINTS } from \"./agent-guidance.ts\";"],
|
|
175
|
+
"replace": [
|
|
176
|
+
"import { ENTWURF_RESUME_LAUNCH_REJECT_HINTS } from \"./agent-guidance.ts\";",
|
|
177
|
+
"import \"node:path\";"
|
|
178
|
+
],
|
|
179
|
+
"gate": ["bash", "run.sh", "check-mux-resume-call"],
|
|
180
|
+
"timeoutSeconds": 60,
|
|
181
|
+
"signature": "[QK:MUXRESUME-IMPORT-SET]",
|
|
182
|
+
"signatureSource": "scripts/check-mux-resume-call.ts"
|
|
158
183
|
}
|
|
159
184
|
]
|
|
160
185
|
}
|
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"lane": "pi-durable",
|
|
4
4
|
"mutants": [
|
|
5
|
+
{
|
|
6
|
+
"claim": "PI-DURABLE-DESCRIPTION-DRIFT-REFUSED",
|
|
7
|
+
"title": "schema comparison ignores description-only drift while still comparing structural schema fields",
|
|
8
|
+
"subject": "pi-extensions/meta-bridge-pi-durable.ts",
|
|
9
|
+
"find": ["canonicalJson(found.inputSchema) !== canonicalJson(PI_DURABLE_TOOL_SCHEMAS[name])"],
|
|
10
|
+
"replace": [
|
|
11
|
+
"canonicalJson(JSON.parse(JSON.stringify(found.inputSchema, (key, value) => key === \"description\" ? undefined : value))) !== canonicalJson(JSON.parse(JSON.stringify(PI_DURABLE_TOOL_SCHEMAS[name], (key, value) => key === \"description\" ? undefined : value)))"
|
|
12
|
+
],
|
|
13
|
+
"gate": ["bash", "run.sh", "check-pi-durable-beside"],
|
|
14
|
+
"timeoutSeconds": 300,
|
|
15
|
+
"signature": "[QK:PI-DURABLE-DESCRIPTION-DRIFT-REFUSED]",
|
|
16
|
+
"signatureSource": "pi-extensions/meta-bridge-pi-durable.test.ts",
|
|
17
|
+
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
18
|
+
},
|
|
5
19
|
{
|
|
6
20
|
"claim": "PI-DURABLE-RETIRE-CALL",
|
|
7
21
|
"title": "retirement alone drops the actual request cancellation signal",
|
|
@@ -24,13 +38,11 @@
|
|
|
24
38
|
{
|
|
25
39
|
"claim": "PI-DURABLE-RETIRE-POLICY",
|
|
26
40
|
"title": "the native retirement description treats actor identity as a standing grant",
|
|
27
|
-
"subject": "
|
|
41
|
+
"subject": "ENTWURF.json",
|
|
28
42
|
"find": [
|
|
29
|
-
"
|
|
30
|
-
],
|
|
31
|
-
"replace": [
|
|
32
|
-
"\t\t\"A caller record alone authorizes this target/work: make ONE retirement attempt for that request \" +"
|
|
43
|
+
"Only when the human operator explicitly requested this particular target/work: make ONE retirement attempt for that request "
|
|
33
44
|
],
|
|
45
|
+
"replace": ["A caller record alone authorizes this target/work: make ONE retirement attempt for that request "],
|
|
34
46
|
"gate": ["bash", "run.sh", "check-pi-durable-beside"],
|
|
35
47
|
"timeoutSeconds": 300,
|
|
36
48
|
"signature": "[QK:PI-DURABLE-RETIRE-POLICY]",
|
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
{
|
|
130
130
|
"claim": "REMOTE-ROUTE-RECEIPT-PATHS-OTHER-HOST",
|
|
131
131
|
"title": "the accepted receipt drops the note that its paths are on the other host, so the other host's messagePath reads as a file the sender could open",
|
|
132
|
-
"subject": "
|
|
132
|
+
"subject": "ENTWURF.json",
|
|
133
133
|
"find": ["read/answer unknown until a reply arrives; paths below are on the other host)"],
|
|
134
134
|
"replace": ["read/answer unknown until a reply arrives)"],
|
|
135
135
|
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
@@ -141,6 +141,25 @@
|
|
|
141
141
|
"output": "mcp/entwurf-bridge/dist"
|
|
142
142
|
}
|
|
143
143
|
},
|
|
144
|
+
{
|
|
145
|
+
"claim": "REMOTE-DELIVERY-RESULT-CLAUSES-FROM-ROOT",
|
|
146
|
+
"title": "the accepted receipt reads a hand-kept copy of its clause, one byte off the Root text, instead of the Root lookup: it still names acceptance and still says its paths are on the other host, so only the byte comparison against Root can see the drift",
|
|
147
|
+
"subject": "pi-extensions/lib/remote-pair-send.ts",
|
|
148
|
+
"find": [
|
|
149
|
+
"\t\t\t\ttext: `entwurf_v2 remote ${via} → ${ENTWURF_DELIVERY_RESULT_CLAUSES[\"remote-accepted\"]}\\n${o.text}`,"
|
|
150
|
+
],
|
|
151
|
+
"replace": [
|
|
152
|
+
"\t\t\t\ttext: `entwurf_v2 remote ${via} → accepted by the other host (its fact; read/answer unknown until a reply arrives; paths below are on the other host)\\n${o.text}`,"
|
|
153
|
+
],
|
|
154
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
155
|
+
"timeoutSeconds": 600,
|
|
156
|
+
"signature": "[QK:REMOTE-DELIVERY-RESULT-CLAUSES-FROM-ROOT]",
|
|
157
|
+
"signatureSource": "pi-extensions/lib/remote-pair-send.test.ts",
|
|
158
|
+
"build": {
|
|
159
|
+
"argv": ["bash", "scripts/build-bridge.sh"],
|
|
160
|
+
"output": "mcp/entwurf-bridge/dist"
|
|
161
|
+
}
|
|
162
|
+
},
|
|
144
163
|
{
|
|
145
164
|
"claim": "REMOTE-PAIR-OPT-IN-ABSENT-IS-OFF",
|
|
146
165
|
"title": "an absent opt-in file throws instead of meaning off, so every local send on a host that never opted in fails",
|
|
@@ -176,7 +195,7 @@
|
|
|
176
195
|
"title": "an error the other host reports after a possible write is headed as a non-delivery, inviting a resend that would deliver twice",
|
|
177
196
|
"subject": "pi-extensions/lib/remote-pair-send.ts",
|
|
178
197
|
"find": [
|
|
179
|
-
"\t\t\t\ttext: `entwurf_v2 remote ${via} →
|
|
198
|
+
"\t\t\t\ttext: `entwurf_v2 remote ${via} → ${ENTWURF_DELIVERY_RESULT_CLAUSES[\"remote-reported-error\"]}\\n${o.text}`,"
|
|
180
199
|
],
|
|
181
200
|
"replace": [
|
|
182
201
|
"\t\t\t\ttext: `entwurf_v2 remote ${via} → the other host did not deliver (paths below are on the other host)\\n${o.text}`,"
|
|
@@ -7,19 +7,19 @@
|
|
|
7
7
|
"title": "entwurf_self reverts to an empty self-fetch guard + unconditional mailbox render (ordering-not-containment)",
|
|
8
8
|
"subject": "mcp/entwurf-bridge/src/index.ts",
|
|
9
9
|
"find": [
|
|
10
|
-
"\t\t\
|
|
11
|
-
"\t\t\t\t\tconst mailboxPath = path.join(defaultMetaMailboxDir(), sender.sessionId);",
|
|
12
|
-
"\t\t\t\t\textra.mailboxPath = mailboxPath;",
|
|
13
|
-
"\t\t\t\t\tlines.push(`mailboxPath: ${mailboxPath}`);",
|
|
14
|
-
"\t\t\t\t} else if (rail === \"native-push\") {"
|
|
15
|
-
],
|
|
16
|
-
"replace": [
|
|
17
|
-
"\t\t\t\tif (rail === \"self-fetch\") {",
|
|
18
|
-
"\t\t\t\t}",
|
|
10
|
+
"\t\t\tif (rail === \"self-fetch\") {",
|
|
19
11
|
"\t\t\t\tconst mailboxPath = path.join(defaultMetaMailboxDir(), sender.sessionId);",
|
|
20
12
|
"\t\t\t\textra.mailboxPath = mailboxPath;",
|
|
21
13
|
"\t\t\t\tlines.push(`mailboxPath: ${mailboxPath}`);",
|
|
22
|
-
"\t\t\t
|
|
14
|
+
"\t\t\t} else if (rail === \"native-push\") {"
|
|
15
|
+
],
|
|
16
|
+
"replace": [
|
|
17
|
+
"\t\t\tif (rail === \"self-fetch\") {",
|
|
18
|
+
"\t\t\t}",
|
|
19
|
+
"\t\t\tconst mailboxPath = path.join(defaultMetaMailboxDir(), sender.sessionId);",
|
|
20
|
+
"\t\t\textra.mailboxPath = mailboxPath;",
|
|
21
|
+
"\t\t\tlines.push(`mailboxPath: ${mailboxPath}`);",
|
|
22
|
+
"\t\t\tif (rail === \"native-push\") {"
|
|
23
23
|
],
|
|
24
24
|
"gate": ["bash", "run.sh", "check-entwurf-self-address"],
|
|
25
25
|
"timeoutSeconds": 60,
|