@junghanacs/entwurf 0.25.0 → 0.30.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 -1
- package/BASELINE.md +1 -1
- package/CHANGELOG.md +182 -0
- package/CONTRIBUTING.md +1 -1
- package/DELIVERY.md +1 -1
- package/README.md +178 -674
- package/VERIFY.md +17 -16
- package/demo/README.md +1 -1
- package/docs/acp-backend-rail.md +6 -2
- package/docs/external-mcp-host.md +1 -1
- package/docs/setup-clean-host.md +346 -10
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +27 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +12 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-peers-render.js +1 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-decider.js +2 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-mailbox.js +2 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-production.js +2 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +3 -5
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-visible-resume.js +3 -3
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-composition.js +13 -6
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-mailbox-body.js +1 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +3 -3
- package/mcp/entwurf-bridge/src/index.ts +30 -3
- package/package.json +11 -11
- package/pi-extensions/entwurf-control.ts +50 -637
- package/pi-extensions/lib/acp/backend-adapter.ts +13 -1
- package/pi-extensions/lib/entwurf-fact-provider.ts +2 -2
- package/pi-extensions/lib/entwurf-mcp-server.ts +74 -0
- package/pi-extensions/lib/entwurf-peers-render.ts +1 -1
- package/pi-extensions/lib/entwurf-v2-decider.ts +2 -2
- package/pi-extensions/lib/entwurf-v2-mailbox.ts +2 -2
- package/pi-extensions/lib/entwurf-v2-production.ts +3 -3
- package/pi-extensions/lib/entwurf-v2-surface.ts +3 -5
- package/pi-extensions/lib/entwurf-v2-visible-resume.ts +3 -3
- package/pi-extensions/lib/fresh-call-composition.ts +13 -6
- package/pi-extensions/lib/meta-mailbox-body.ts +1 -1
- package/pi-extensions/lib/mux-fresh-call.ts +3 -3
- package/run.sh +168 -54
- package/scripts/check-entwurf-peers-surface.ts +8 -15
- package/scripts/check-entwurf-self-address.ts +7 -11
- package/scripts/check-entwurf-v2-surface.ts +20 -112
- package/scripts/check-fresh-call-dispatch.ts +12 -13
- package/scripts/check-gate-qualification.ts +2741 -157
- package/scripts/check-install-surface.ts +3 -2
- package/scripts/check-mux-resume-call.ts +24 -35
- package/scripts/check-pi-bridge-sender.ts +130 -0
- package/scripts/check-pi-mcp-bridge.ts +251 -0
- package/scripts/lib/codex-fresh-live-protocol.ts +17 -5
- package/scripts/lib/codex-fresh-source-receipts.ts +21 -2
- package/scripts/lib/mutation-qualify.ts +269 -44
- package/scripts/lib/pi-mcp-bridge-probe.mjs +170 -0
- package/scripts/lib/qualification-acceptance.ts +146 -0
- package/scripts/lib/qualification-artifact.ts +359 -0
- package/scripts/lib/qualification-collection.ts +384 -0
- package/scripts/lib/qualification-gh.ts +231 -0
- package/scripts/lib/qualification-ledger.ts +669 -0
- package/scripts/lib/qualification-oracle-core.ts +279 -0
- package/scripts/lib/qualification-receipt.ts +561 -0
- package/scripts/lib/qualification-release.ts +271 -0
- package/scripts/meta-bridge-doctor.sh +16 -5
- package/scripts/mutants/acp-foreground-only.json +17 -0
- package/scripts/mutants/codex-native.json +11 -11
- package/scripts/mutants/control-send-receipt.json +6 -4
- package/scripts/mutants/copilot-birth.json +2 -1
- package/scripts/mutants/fresh-call-dispatch.json +3 -14
- package/scripts/mutants/gate-qualification.json +59 -0
- package/scripts/mutants/mux-fresh-call.json +43 -45
- package/scripts/mutants/mux-resume-call.json +11 -35
- package/scripts/mutants/pack-install.json +15 -4
- package/scripts/mutants/pi-bridge-sender.json +54 -0
- package/scripts/mutants/pi-floor.json +6 -2
- package/scripts/mutants/pi-mcp-bridge.json +36 -0
- package/scripts/mutants/pi-mcp-register.json +51 -0
- package/scripts/mutants/qualification-ledger.json +489 -0
- package/scripts/mutants/v2-surface.json +6 -6
- package/scripts/qualification-oracle.ts +124 -0
- package/scripts/resident-rpc-drive.ts +5 -1
- package/scripts/smoke-acp-bundled-mcp-live.ts +3 -1
- package/scripts/smoke-acp-cortex-live.ts +3 -1
- package/scripts/smoke-acp-session-reuse-live.ts +29 -12
- package/scripts/smoke-acp-socket-citizen-live.ts +3 -1
- package/scripts/smoke-acp-v2-send-live.ts +3 -1
- package/scripts/smoke-codex-fresh-live.ts +20 -1
- package/scripts/smoke-entwurf-chain-live.ts +6 -2
- package/scripts/smoke-entwurf-v2-matrix-live.ts +3 -1
- package/scripts/smoke-herdr-raw-install-live.sh +8 -3
- package/scripts/smoke-mux-lifecycle-live.ts +1 -1
- package/scripts/smoke-resident-garden-guard.sh +3 -1
|
@@ -169,7 +169,11 @@ const result: DriveResult = {
|
|
|
169
169
|
timedOut: false,
|
|
170
170
|
};
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
// `--no-extensions` keeps ambient discovery out, and since Pi 0.99 it also turns the BUILT-IN
|
|
173
|
+
// extensions off: a citizen born here had no MCP, so its entwurf-bridge registration threw
|
|
174
|
+
// `register_mcp_server` (`[측정 2026-10-02]` pi 0.99.2 and 1.0.0 alike). `-e builtin:mcp` restores
|
|
175
|
+
// that one built-in — the MCP a resident has — and nothing else.
|
|
176
|
+
const piArgs = ["--no-extensions", "-e", "builtin:mcp", "-e", REPO_ROOT, "--entwurf-control"];
|
|
173
177
|
// NO --session-id. That injection is what the #50 C2 cut removed: pi mints its own
|
|
174
178
|
// id and the record mints the address. A resume names the FILE, never an id.
|
|
175
179
|
if (sessionFile) piArgs.push("--session", sessionFile);
|
|
@@ -62,7 +62,9 @@ const REAL_CONTROL_DIR = path.join(os.homedir(), ".pi", "entwurf-control");
|
|
|
62
62
|
const SOCKET_SUFFIX = ".sock";
|
|
63
63
|
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
64
64
|
// Load ONLY this checkout's extensions so the resident registers THIS acp-provider.ts.
|
|
65
|
-
|
|
65
|
+
// `builtin:mcp`: `--no-extensions` also turns off Pi's built-in MCP, which a citizen's entwurf-bridge
|
|
66
|
+
// registration needs (scripts/resident-rpc-drive.ts has the measurement).
|
|
67
|
+
const REPO_EXTENSION_ARGS = ["--no-extensions", "-e", "builtin:mcp", "-e", REPO_ROOT] as const;
|
|
66
68
|
|
|
67
69
|
const BOOT_TIMEOUT_MS = PI_BOOT_TIMEOUT_MS; // shared: pi lock-stale window + boot (see pi-record-discovery)
|
|
68
70
|
const TURN_TIMEOUT_MS = Number(process.env.ENTWURF_ACP_PROVIDER_TIMEOUT_MS) || 240_000;
|
|
@@ -68,7 +68,9 @@ const CORTEX_OVERLAYS_ROOT = path.join(os.homedir(), ".pi", "agent", "cortex-ove
|
|
|
68
68
|
const SOCKET_SUFFIX = ".sock";
|
|
69
69
|
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
70
70
|
// Load ONLY this checkout's extensions so the resident registers THIS acp-provider.ts.
|
|
71
|
-
|
|
71
|
+
// `builtin:mcp`: `--no-extensions` also turns off Pi's built-in MCP, which a citizen's entwurf-bridge
|
|
72
|
+
// registration needs (scripts/resident-rpc-drive.ts has the measurement).
|
|
73
|
+
const REPO_EXTENSION_ARGS = ["--no-extensions", "-e", "builtin:mcp", "-e", REPO_ROOT] as const;
|
|
72
74
|
|
|
73
75
|
const BOOT_TIMEOUT_MS = PI_BOOT_TIMEOUT_MS; // shared: pi lock-stale window + boot (see pi-record-discovery)
|
|
74
76
|
// The cortex CLI self-extracts on first launch and its newSession alone is
|
|
@@ -3,13 +3,20 @@
|
|
|
3
3
|
// LIVE=1 ./run.sh smoke-acp-session-reuse-live
|
|
4
4
|
//
|
|
5
5
|
// The deterministic gate (check-acp-session-reuse) proves the prompt SCOPE
|
|
6
|
-
// (delta-only) and the wiring with a fake seam. This
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// (
|
|
12
|
-
//
|
|
6
|
+
// (delta-only) and the wiring with a fake seam. This drives the REAL backend
|
|
7
|
+
// (real overlay + spawn + vendor) through TWO ACP turns in one process-scoped
|
|
8
|
+
// process and asserts that turn 2 took the REUSE path.
|
|
9
|
+
//
|
|
10
|
+
// The reuse verdict is the production lifecycle notice, NOT the recall. A
|
|
11
|
+
// respawned (`new`) turn re-sends the FULL transcript (context.ts
|
|
12
|
+
// buildAcpPrompt "new"), and turn 2's context below carries turn 1's codeword, so
|
|
13
|
+
// a respawn-per-turn backend would recall it just as well — recall alone cannot
|
|
14
|
+
// tell reuse from rebuild. Turn 2 must therefore announce `[acp: reusing live
|
|
15
|
+
// session]` and must not announce `[acp: preparing …]`; check-acp-session-reuse
|
|
16
|
+
// pins that the reuse branch emits exactly that and the new branch the opposite.
|
|
17
|
+
// The recall is kept as a supporting check that the reused session still answers
|
|
18
|
+
// from its own history. Delta-only on the wire stays the deterministic gate's
|
|
19
|
+
// claim: the vendor stdio is not observed here.
|
|
13
20
|
//
|
|
14
21
|
// It forces process-scoped by pushing the real `--entwurf-control` resident flag
|
|
15
22
|
// into argv (resolveLifecyclePolicy reads process.argv), then calls the REAL
|
|
@@ -175,18 +182,28 @@ async function main(): Promise<void> {
|
|
|
175
182
|
if (!r2.done) fail("turn 2 did not complete");
|
|
176
183
|
console.error(`[smoke-acp-session-reuse-live] turn 2 reply: ${JSON.stringify(r2.text.slice(-120))}`);
|
|
177
184
|
|
|
178
|
-
// The
|
|
179
|
-
//
|
|
185
|
+
// The reuse verdict: the backend's own lifecycle notices ride the text stream, so
|
|
186
|
+
// turn 2 names the path it took. A rebuild would announce `preparing` instead.
|
|
187
|
+
assert.ok(
|
|
188
|
+
r2.text.includes("[acp: reusing live session]"),
|
|
189
|
+
`turn 2 did not take the reuse path — no "[acp: reusing live session]" notice (reply: ${JSON.stringify(r2.text.slice(-200))})`,
|
|
190
|
+
);
|
|
191
|
+
assert.ok(
|
|
192
|
+
!r2.text.includes("[acp: preparing"),
|
|
193
|
+
`turn 2 re-bootstrapped a session ("[acp: preparing …]") instead of reusing turn 1's (reply: ${JSON.stringify(r2.text.slice(-200))})`,
|
|
194
|
+
);
|
|
195
|
+
// Supporting only: the reused session still answers from its own history. A rebuild
|
|
196
|
+
// would pass this too (it re-sends the codeword), which is why it is not the verdict.
|
|
180
197
|
assert.ok(
|
|
181
198
|
r2.text.includes(codeword),
|
|
182
|
-
`turn 2 reply did not contain the turn-1 codeword ${codeword} —
|
|
199
|
+
`turn 2 reply did not contain the turn-1 codeword ${codeword} — the reused session lost its history (reply: ${JSON.stringify(r2.text.slice(-200))})`,
|
|
183
200
|
);
|
|
184
201
|
|
|
185
202
|
console.log(
|
|
186
|
-
"[smoke-acp-session-reuse-live] PASS —
|
|
203
|
+
"[smoke-acp-session-reuse-live] PASS — turn 2 took the reuse path ([acp: reusing live session], no re-bootstrap) and recalled the turn-1 codeword",
|
|
187
204
|
);
|
|
188
205
|
console.log(` model: entwurf/${MODEL}`);
|
|
189
|
-
console.log(` codeword: ${codeword} recalled in turn 2 (delta-only)`);
|
|
206
|
+
console.log(` codeword: ${codeword} recalled in turn 2 (supporting; delta-only is check-acp-session-reuse's claim)`);
|
|
190
207
|
}
|
|
191
208
|
|
|
192
209
|
main()
|
|
@@ -41,7 +41,9 @@ const REAL_CONTROL_DIR = path.join(os.homedir(), ".pi", "entwurf-control");
|
|
|
41
41
|
const SOCKET_SUFFIX = ".sock";
|
|
42
42
|
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
43
43
|
// Load ONLY this checkout's extensions so the resident registers THIS acp-provider.ts.
|
|
44
|
-
|
|
44
|
+
// `builtin:mcp`: `--no-extensions` also turns off Pi's built-in MCP, which a citizen's entwurf-bridge
|
|
45
|
+
// registration needs (scripts/resident-rpc-drive.ts has the measurement).
|
|
46
|
+
const REPO_EXTENSION_ARGS = ["--no-extensions", "-e", "builtin:mcp", "-e", REPO_ROOT] as const;
|
|
45
47
|
|
|
46
48
|
const BOOT_TIMEOUT_MS = PI_BOOT_TIMEOUT_MS; // shared: pi lock-stale window + boot (see pi-record-discovery)
|
|
47
49
|
const POLL_MS = 100;
|
|
@@ -95,7 +95,9 @@ const REAL_CONTROL_DIR = path.join(os.homedir(), ".pi", "entwurf-control");
|
|
|
95
95
|
const SOCKET_SUFFIX = ".sock";
|
|
96
96
|
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
97
97
|
// Load ONLY this checkout's extensions so the resident registers THIS acp-provider.ts.
|
|
98
|
-
|
|
98
|
+
// `builtin:mcp`: `--no-extensions` also turns off Pi's built-in MCP, which a citizen's entwurf-bridge
|
|
99
|
+
// registration needs (scripts/resident-rpc-drive.ts has the measurement).
|
|
100
|
+
const REPO_EXTENSION_ARGS = ["--no-extensions", "-e", "builtin:mcp", "-e", REPO_ROOT] as const;
|
|
99
101
|
|
|
100
102
|
const BOOT_TIMEOUT_MS = PI_BOOT_TIMEOUT_MS; // shared: pi lock-stale window + boot (see pi-record-discovery)
|
|
101
103
|
const TURN_TIMEOUT_MS = Number(process.env.ENTWURF_ACP_PROVIDER_TIMEOUT_MS) || 240_000;
|
|
@@ -75,6 +75,7 @@ import {
|
|
|
75
75
|
import {
|
|
76
76
|
buildCodexInstruction,
|
|
77
77
|
buildInitialPiPhaseOne,
|
|
78
|
+
buildInitialPiRelay,
|
|
78
79
|
runCleanupStages,
|
|
79
80
|
selectReport,
|
|
80
81
|
} from "./lib/codex-fresh-live-protocol.ts";
|
|
@@ -954,6 +955,8 @@ async function run(): Promise<void> {
|
|
|
954
955
|
model: piModel,
|
|
955
956
|
cwd: scratch,
|
|
956
957
|
task:
|
|
958
|
+
"Session-info already supplies device and time. Do not recheck time, cwd, or identity with shell or other tools. " +
|
|
959
|
+
"Your FIRST tool call must be mcp__entwurf_bridge__entwurf_callback with no arguments, and nothing before it. " +
|
|
957
960
|
`After your required callback receipt, end the turn and wait passively for one addressed message containing ${initialPiWaitToken}. ` +
|
|
958
961
|
"That message is the only authority to open the Codex sibling. Do not call shell, sleep, terminal, or any tool to wait.",
|
|
959
962
|
});
|
|
@@ -1070,7 +1073,6 @@ async function run(): Promise<void> {
|
|
|
1070
1073
|
codexWaitToken,
|
|
1071
1074
|
codexModel,
|
|
1072
1075
|
scratch,
|
|
1073
|
-
codexInstruction,
|
|
1074
1076
|
});
|
|
1075
1077
|
|
|
1076
1078
|
// The model is asked to operate public tools, but every launch and delivery assertion below
|
|
@@ -1190,6 +1192,23 @@ async function run(): Promise<void> {
|
|
|
1190
1192
|
`requested=${scratch}\npane=${codexPaneCwd}\nrollout-session_meta=${codexRolloutCwd}\n` +
|
|
1191
1193
|
`record=${codexIdentity.cwd}\napp-server=${appServerCwd}`;
|
|
1192
1194
|
|
|
1195
|
+
// Only after the exact callback and record/cwd joins: instruct the initial Pi to relay,
|
|
1196
|
+
// never deliver the Codex payload on its behalf.
|
|
1197
|
+
const relayInitialPi = await bridge.call("entwurf_v2", {
|
|
1198
|
+
target: initialPiGid,
|
|
1199
|
+
intent: "fire-and-forget",
|
|
1200
|
+
message: buildInitialPiRelay({ codexGardenId, codexInstruction }),
|
|
1201
|
+
});
|
|
1202
|
+
receipts["8c-fixture-to-initial-pi-relay"] = relayInitialPi.text;
|
|
1203
|
+
ok(
|
|
1204
|
+
"the fixture addressed the initial Pi relay phase through the control socket",
|
|
1205
|
+
!relayInitialPi.isError &&
|
|
1206
|
+
/entwurf_v2 control-socket → (?:sent|queued-steer|queued-follow-up|accepted-unknown-boundary)/.test(
|
|
1207
|
+
relayInitialPi.text,
|
|
1208
|
+
),
|
|
1209
|
+
relayInitialPi.text,
|
|
1210
|
+
);
|
|
1211
|
+
|
|
1193
1212
|
const initialPiToCodex = await awaitOrRecover("the initial Pi joined native-push receipt", SOURCE_WAIT_MS, () => {
|
|
1194
1213
|
const piSources = piSourceToolReceipts(readInitialPiEntries());
|
|
1195
1214
|
assertSourceCallScopes(piSources, "entwurf_v2", "target", [callerGid, codexGardenId], "initial Pi v2 roles");
|
|
@@ -67,7 +67,9 @@ import { terminateChild } from "./lib/acp-child-cleanup.ts";
|
|
|
67
67
|
import { skipLive } from "./lib/live-skip.ts";
|
|
68
68
|
|
|
69
69
|
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
70
|
-
|
|
70
|
+
// `builtin:mcp`: `--no-extensions` also turns off Pi's built-in MCP, which a citizen's entwurf-bridge
|
|
71
|
+
// registration needs (scripts/resident-rpc-drive.ts has the measurement).
|
|
72
|
+
const REPO_EXTENSION_ARGS = ["--no-extensions", "-e", "builtin:mcp", "-e", REPO_ROOT] as const;
|
|
71
73
|
const REAL_CONTROL_DIR = path.join(os.homedir(), ".pi", "entwurf-control");
|
|
72
74
|
const SOCKET_SUFFIX = ".sock";
|
|
73
75
|
|
|
@@ -329,9 +331,11 @@ async function main(): Promise<void> {
|
|
|
329
331
|
`Call the tool mcp__entwurf-bridge__entwurf_v2 exactly once with target=${gidD}, intent=fire-and-forget,`,
|
|
330
332
|
`and message=${nonce} terminus. Then reply with only the tool's outcome line.`,
|
|
331
333
|
].join(" ");
|
|
334
|
+
// hop2 is read by B, a NATIVE pi citizen: Pi folds the server key's hyphen, so B is declared
|
|
335
|
+
// `mcp__entwurf_bridge__entwurf_v2`. hop1 (Claude Code) and hop3 (ACP Claude) keep the hyphen.
|
|
332
336
|
const hop2 = [
|
|
333
337
|
`${nonce} hop2. You are the second hop of a delivery chain.`,
|
|
334
|
-
`Call the tool
|
|
338
|
+
`Call the tool mcp__entwurf_bridge__entwurf_v2 exactly once with target=${gidC}, intent=fire-and-forget,`,
|
|
335
339
|
"and message set to exactly the text between INNER-BEGIN and INNER-END.",
|
|
336
340
|
"Then reply with only the tool's outcome line.",
|
|
337
341
|
"INNER-BEGIN",
|
|
@@ -76,7 +76,9 @@ const SOCKET_SUFFIX = ".sock";
|
|
|
76
76
|
// Release-gate topology: repo-under-test, not deployment smoke. Load only this
|
|
77
77
|
// checkout's extension so resident behavior is independent of global pi packages.
|
|
78
78
|
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
79
|
-
|
|
79
|
+
// `builtin:mcp`: `--no-extensions` also turns off Pi's built-in MCP, which a citizen's entwurf-bridge
|
|
80
|
+
// registration needs (scripts/resident-rpc-drive.ts has the measurement).
|
|
81
|
+
const REPO_EXTENSION_ARGS = ["--no-extensions", "-e", "builtin:mcp", "-e", REPO_ROOT] as const;
|
|
80
82
|
|
|
81
83
|
// Staged timeouts (automation): short and per-stage so a stall is attributable.
|
|
82
84
|
//
|
|
@@ -491,7 +491,7 @@ for (const name of ["entwurf", "entwurf-bridge", "entwurf-statusline"]) {
|
|
|
491
491
|
|
|
492
492
|
// The REAL subcommand, from the installed bin, under node_modules — which is the branch of
|
|
493
493
|
// start.sh that runs the prebuilt dist. Its own oracle is an EXACT set (`EXPECT_TOOLS` in run.sh check-bridge), so a
|
|
494
|
-
// zero exit here is the artifact listing all
|
|
494
|
+
// zero exit here is the artifact listing all eight garden verbs and no ninth.
|
|
495
495
|
const run = spawnSync(path.join(binDir, "entwurf"), ["check-bridge"], { encoding: "utf8" });
|
|
496
496
|
const said = `${run.stdout ?? ""}${run.stderr ?? ""}`;
|
|
497
497
|
// [a-z0-9_] and not [a-z_]: the first draft of this line printed `entwurf_v` for entwurf_v2
|
|
@@ -714,8 +714,13 @@ run_fan() {
|
|
|
714
714
|
fan_no_server="$(run_fan)"; fan_no_server_rc=$?
|
|
715
715
|
echo "$fan_no_server" | sed 's/^/ /'
|
|
716
716
|
echo " → exit $fan_no_server_rc"
|
|
717
|
-
|
|
718
|
-
|
|
717
|
+
# Since #120, each block owns its own verdict: a failed `agent list` is indented inside
|
|
718
|
+
# [4] CITIZENS, not at column zero above the report. Anchor both the owner block and its
|
|
719
|
+
# exact failure line; a mention in the closing guidance or a different block is no receipt.
|
|
720
|
+
if [ "$fan_no_server_rc" -ne 0 ] &&
|
|
721
|
+
printf '%s\n' "$fan_no_server" | grep -q '^\[4\] CITIZENS — owner: entwurf; read now, this open$' &&
|
|
722
|
+
printf '%s\n' "$fan_no_server" | grep -q '^ herdr-agent-list-failed: exit [1-9]'; then
|
|
723
|
+
ok "with no herdr server the CITIZENS block names herdr-agent-list-failed and goes red (not an empty table)"
|
|
719
724
|
else
|
|
720
725
|
bad "with no herdr server the fan answered rc=$fan_no_server_rc without naming herdr-agent-list-failed"
|
|
721
726
|
fi
|
|
@@ -108,7 +108,7 @@ const BRIDGE_LAUNCHER = path.join(REPO, "mcp", "entwurf-bridge", "start.sh");
|
|
|
108
108
|
|
|
109
109
|
/** The two pi shapes. They differ in exactly one thing that matters here — whether the record
|
|
110
110
|
* carries `provider=entwurf`, which is what makes the resume argv re-inject the bridge (#29). */
|
|
111
|
-
const PI_NATIVE_MODEL = "openai-codex/gpt-
|
|
111
|
+
const PI_NATIVE_MODEL = "openai-codex/gpt-6-luna";
|
|
112
112
|
const PI_ACP_MODEL = "entwurf/claude-sonnet-5";
|
|
113
113
|
const CLAUDE_MODEL = "claude-sonnet-5";
|
|
114
114
|
|
|
@@ -91,7 +91,9 @@ TIMEOUT="${SMOKE_RGG_TIMEOUT:-90}"
|
|
|
91
91
|
# Release-gate topology: this is a repo-under-test smoke, not a deployment smoke.
|
|
92
92
|
# Load ONLY this checkout's extension so results do not depend on device-local global
|
|
93
93
|
# packages / current branch wiring.
|
|
94
|
-
|
|
94
|
+
# `builtin:mcp`: `--no-extensions` also turns off Pi's built-in MCP, which a citizen's entwurf-bridge
|
|
95
|
+
# registration needs (scripts/resident-rpc-drive.ts has the measurement).
|
|
96
|
+
REPO_EXTENSION_ARGS=(--no-extensions -e builtin:mcp -e "$REPO")
|
|
95
97
|
|
|
96
98
|
pass=0
|
|
97
99
|
fail=0
|