@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
|
@@ -26,7 +26,7 @@ write_mcp_fake() {
|
|
|
26
26
|
while IFS= read -r line; do
|
|
27
27
|
case "$line" in
|
|
28
28
|
*'"id":1'*) printf '%s\n' '{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{},"serverInfo":{"name":"fake-entwurf-bridge","version":"0"}}}' ;;
|
|
29
|
-
*'"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"}]}}' ;;
|
|
29
|
+
*'"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"}]}}' ;;
|
|
30
30
|
esac
|
|
31
31
|
done
|
|
32
32
|
FAKE
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* smoke-entwurf-v2-matrix-live — the 5d-5 D4-b LIVE sentinel for the release-gate matrix.
|
|
3
3
|
*
|
|
4
|
-
* The deterministic sibling (
|
|
4
|
+
* The deterministic sibling (pi-extensions/lib/entwurf-v2-decider.matrix.test.ts) drives the REAL decider over fakes with
|
|
5
5
|
* ZERO IO — it fixes every (target kind → transport → lock) cell as a table. This LIVE sentinel
|
|
6
6
|
* drives the REAL production `runEntwurfV2` deps against REAL OS objects on the substrate's
|
|
7
7
|
* happy path, to catch what fakes cannot: a real `pi --entwurf-control` control socket + RPC,
|
|
@@ -186,17 +186,38 @@ function transcriptRecords(file: string): string[] {
|
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
/**
|
|
189
|
-
* The
|
|
190
|
-
*
|
|
189
|
+
* The BARE verb names, as the two surfaces this smoke reads actually spell them — NOT the
|
|
190
|
+
* model-facing dialect. `[측정 2026-09-20, this smoke's own red fixture]` the claude MCP activity
|
|
191
|
+
* log carries `Calling MCP tool: entwurf_callback` / `Tool 'entwurf_callback' completed`, and pi
|
|
192
|
+
* writes `"type":"toolCall","name":"entwurf_callback"`; neither records
|
|
193
|
+
* `mcp__entwurf-bridge__entwurf_callback`. The per-host dialect is owned by
|
|
194
|
+
* `FRESH_CALL_CALLBACK_TOOL` / `FRESH_CALL_DELIVERY_TOOL` in `fresh-call-composition.ts` and is
|
|
195
|
+
* what the FRAMING says; these two are what an OBSERVER sees, and conflating them is what this
|
|
196
|
+
* pair of constants exists to stop.
|
|
197
|
+
*/
|
|
198
|
+
const CALLBACK_VERB = "entwurf_callback";
|
|
199
|
+
const DELIVERY_VERB = "entwurf_v2";
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* The id of the CALLBACK toolCall in this record, or null. Pi writes a call and its result as two
|
|
203
|
+
* records; this is one half of the join that replaces a same-record read.
|
|
191
204
|
*
|
|
192
|
-
* WHAT MAKES IT THE CALLBACK
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
205
|
+
* WHAT MAKES IT THE CALLBACK `[ff09522]`. It used to be the ARGUMENTS: message === nonce, target
|
|
206
|
+
* === the caller, intent === fire-and-forget. That predicate is gone because the thing it read is
|
|
207
|
+
* gone — the birth verb takes ZERO arguments and reads the caller and the nonce out of its own
|
|
208
|
+
* process env, so there is nothing in the call for a model to get wrong and nothing here to
|
|
209
|
+
* compare. What identifies the callback now is the verb plus the ABSENCE of an address: a call
|
|
210
|
+
* carrying a target or a message is a model supplying an address, which is the second address axis
|
|
211
|
+
* Hard Rule 2 refuses, and it is not this act.
|
|
212
|
+
*
|
|
213
|
+
* The nonce↔sender correlation the old predicate carried did not disappear with it — it moved to
|
|
214
|
+
* the DELIVERED ARTIFACT, which this smoke checks independently and earlier ("the child's callback
|
|
215
|
+
* ARRIVED … its body is a production nonce and its sender is the child the direct witness resolved
|
|
216
|
+
* to"). Two records, one event, same as before; only the half that names the call has changed.
|
|
198
217
|
*/
|
|
199
218
|
function entwurfCallIdFor(record: string, nonce: string, callerGid: string): string | null {
|
|
219
|
+
void nonce;
|
|
220
|
+
void callerGid;
|
|
200
221
|
let parsed: unknown;
|
|
201
222
|
try {
|
|
202
223
|
parsed = JSON.parse(record);
|
|
@@ -207,16 +228,14 @@ function entwurfCallIdFor(record: string, nonce: string, callerGid: string): str
|
|
|
207
228
|
if (!Array.isArray(content)) return null;
|
|
208
229
|
for (const part of content) {
|
|
209
230
|
const call = part as { type?: unknown; name?: unknown; id?: unknown; arguments?: unknown };
|
|
210
|
-
if (call.type !== "toolCall" || call.name !==
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if (
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
// The framing asks for no reply; a call that asked for one is a different act.
|
|
219
|
-
if (args.wants_reply === true) continue;
|
|
231
|
+
if (call.type !== "toolCall" || call.name !== CALLBACK_VERB) continue;
|
|
232
|
+
// Zero-argument verb: absent, null and `{}` are all the shape it is called with. A supplied
|
|
233
|
+
// target or message is a model naming an address the env already owns — not this act.
|
|
234
|
+
const args = call.arguments as { message?: unknown; target?: unknown } | undefined | null;
|
|
235
|
+
if (args !== undefined && args !== null) {
|
|
236
|
+
if (typeof args !== "object" || Array.isArray(args)) continue;
|
|
237
|
+
if (args.target !== undefined || args.message !== undefined) continue;
|
|
238
|
+
}
|
|
220
239
|
return typeof call.id === "string" ? call.id : null;
|
|
221
240
|
}
|
|
222
241
|
return null;
|
|
@@ -864,23 +883,27 @@ async function main(): Promise<void> {
|
|
|
864
883
|
// OFFERS exactly that corroboration ("you can corroborate the caller first if you
|
|
865
884
|
// want to"), so the old oracle contradicted our own prompt and would have forbidden
|
|
866
885
|
// the behaviour we asked for. What still must hold is everything the claim was
|
|
867
|
-
// actually about — the callback lands before any work, it completes, and
|
|
868
|
-
//
|
|
886
|
+
// actually about — the callback lands before any work, it completes, and neither the
|
|
887
|
+
// callback verb nor the delivery verb failed or timed out anywhere in the log.
|
|
888
|
+
// `[ff09522]` the verb this joins on MOVED: the birth callback is `entwurf_callback`
|
|
889
|
+
// and `entwurf_v2` is now only the DELIVERY the closing line asks for. Joining on the
|
|
890
|
+
// old name does not merely miss — it mis-attributes, finding the result-delivery call
|
|
891
|
+
// and then reporting the real callback as forbidden work before it.
|
|
869
892
|
// ONLY what the framing actually offers. `entwurf_self` used to sit in this set and
|
|
870
893
|
// nothing ever proposed it to the child — an allowance for a tool we do not mention
|
|
871
894
|
// widens the oracle without widening the contract (sol D1, 2026-09-18).
|
|
872
895
|
const READ_ONLY_FIRST = new Set(["entwurf_peers"]);
|
|
873
|
-
const beforeCallback = order.slice(0, Math.max(order.indexOf(
|
|
896
|
+
const beforeCallback = order.slice(0, Math.max(order.indexOf(CALLBACK_VERB), 0));
|
|
874
897
|
// THE JOIN THIS AXIS CAN ACTUALLY MAKE. The claude MCP log records WHICH tool was
|
|
875
898
|
// called and whether it completed — never its arguments or its result body — so
|
|
876
|
-
// "the first
|
|
899
|
+
// "the first callback completed" alone would also be true of a call that delivered
|
|
877
900
|
// somebody else's nonce or came back as a semantic reject over a successful
|
|
878
901
|
// transport. The second artifact closes it: the caller's own delivered message
|
|
879
902
|
// carries the EXACT nonce and the child as its sender, and its enqueue timestamp has
|
|
880
903
|
// to fall inside the window of that first call. Two independent records, one event.
|
|
881
|
-
const callAt = indexOfEntry(childActivity, (e) => (e.debug ?? "") ===
|
|
904
|
+
const callAt = indexOfEntry(childActivity, (e) => (e.debug ?? "") === `Calling MCP tool: ${CALLBACK_VERB}`);
|
|
882
905
|
const doneAt = indexOfEntry(childActivity, (e) =>
|
|
883
|
-
(e.debug ?? "").startsWith(
|
|
906
|
+
(e.debug ?? "").startsWith(`Tool '${CALLBACK_VERB}' completed successfully`),
|
|
884
907
|
);
|
|
885
908
|
const callbackStamp = deliveredMessages(String(fenced.ENTWURF_META_MAILBOX_DIR), callerGid)[0]?.file ?? "";
|
|
886
909
|
const stampedAt = Date.parse(
|
|
@@ -902,14 +925,19 @@ async function main(): Promise<void> {
|
|
|
902
925
|
// here, and a claim about "any work" is wider than the oracle. What IS observed, and
|
|
903
926
|
// is the thing the framing actually asks for, is the ORDER OF TOOLS: the first
|
|
904
927
|
// non-read-only tool this child called was the callback.
|
|
905
|
-
`${cell.label}: the child's FIRST non-read-only tool call was the
|
|
928
|
+
`${cell.label}: the child's FIRST non-read-only tool call was the zero-argument ${CALLBACK_VERB} — it completed successfully and the delivered callback carrying this exact nonce was enqueued inside that call's own window, preceded only by the read-only corroboration the framing offers, with neither ${CALLBACK_VERB} nor ${DELIVERY_VERB} failing or timing out anywhere in its log (this cell reads tool activity only; assistant text is not observable on this rail)`,
|
|
906
929
|
childActivity.length > 0 &&
|
|
907
|
-
order.includes(
|
|
930
|
+
order.includes(CALLBACK_VERB) &&
|
|
908
931
|
beforeCallback.every((name) => READ_ONLY_FIRST.has(name)) &&
|
|
909
932
|
within &&
|
|
910
933
|
callbackArrived &&
|
|
911
|
-
|
|
912
|
-
|
|
934
|
+
// BOTH verbs, because the child uses both: the birth callback and, after the
|
|
935
|
+
// work, the delivery verb the framing's closing line names. A failed delivery
|
|
936
|
+
// is as fatal to this rail as a failed callback.
|
|
937
|
+
![CALLBACK_VERB, DELIVERY_VERB].some((verb) =>
|
|
938
|
+
childActivity.some(
|
|
939
|
+
(e) => (e.debug ?? "").startsWith(`Tool '${verb}' failed`) || (e.error ?? "").includes(verb),
|
|
940
|
+
),
|
|
913
941
|
),
|
|
914
942
|
);
|
|
915
943
|
}
|