@junghanacs/entwurf 0.20.1 → 0.21.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 +85 -190
- package/BASELINE.md +4 -3
- package/CHANGELOG.md +195 -14
- package/CONTRIBUTING.md +1 -1
- package/DELIVERY.md +202 -60
- package/README.md +49 -22
- package/VERIFY.md +37 -7
- package/docs/acp-backend-rail.md +0 -1
- package/docs/external-mcp-host.md +54 -33
- package/docs/setup-clean-host.md +110 -17
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +101 -109
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-fresh-preflight.js +326 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-fact-provider.js +22 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-peers-render.js +3 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +6 -7
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-native-push.js +30 -17
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-production.js +7 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +7 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-mailbox-body.js +20 -11
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +227 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +50 -15
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/adapter.js +10 -7
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/codex-ws-client.js +403 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/register.js +4 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-hook-codex.js +325 -0
- package/mcp/entwurf-bridge/dist/scripts/meta-bridge-fresh-cut.js +6 -1
- package/mcp/entwurf-bridge/src/index.ts +115 -111
- package/mcp/entwurf-bridge/tsconfig.build.json +1 -0
- package/package.json +13 -4
- package/pi-extensions/entwurf-control.ts +71 -19
- package/pi-extensions/lib/codex-fresh-preflight.ts +363 -0
- package/pi-extensions/lib/compaction-send-guard.ts +80 -0
- package/pi-extensions/lib/entwurf-fact-provider.ts +29 -3
- package/pi-extensions/lib/entwurf-peers-render.ts +4 -1
- package/pi-extensions/lib/entwurf-v2-contract.ts +6 -7
- package/pi-extensions/lib/entwurf-v2-native-push.ts +35 -18
- package/pi-extensions/lib/entwurf-v2-production.ts +10 -3
- package/pi-extensions/lib/entwurf-v2-surface.ts +7 -4
- package/pi-extensions/lib/meta-mailbox-body.ts +22 -13
- package/pi-extensions/lib/meta-sender-identity.ts +305 -0
- package/pi-extensions/lib/mux-fresh-call.ts +64 -19
- package/pi-extensions/lib/native-push/adapter.ts +21 -24
- package/pi-extensions/lib/native-push/codex-ws-client.ts +506 -0
- package/pi-extensions/lib/native-push/register.ts +7 -9
- package/pi-extensions/meta-bridge-hook-codex.ts +371 -0
- package/run.sh +218 -28
- package/scripts/check-agy-sender-identity.ts +1 -1
- package/scripts/check-codex-birth-hook.ts +264 -0
- package/scripts/check-codex-bridge-identity.ts +179 -0
- package/scripts/check-codex-native-push.ts +386 -0
- package/scripts/check-codex-sender-identity.ts +495 -0
- package/scripts/check-compaction-send-guard.ts +130 -0
- package/scripts/check-copilot-receive-arm.ts +4 -1
- package/scripts/check-entwurf-fact-provider.ts +38 -0
- package/scripts/check-entwurf-peers-surface.ts +13 -1
- package/scripts/check-entwurf-self-address.ts +15 -16
- package/scripts/check-entwurf-v2-contract.ts +4 -3
- package/scripts/check-entwurf-v2-decider.ts +7 -5
- package/scripts/check-entwurf-v2-native-push.ts +35 -7
- package/scripts/check-entwurf-v2-production.ts +203 -11
- package/scripts/check-entwurf-v2-runner.ts +1 -1
- package/scripts/check-entwurf-v2-surface.ts +1 -1
- package/scripts/check-gate-qualification.ts +6 -3
- package/scripts/check-harness-admission-parity.ts +0 -1
- package/scripts/check-mux-launch-tmux.ts +47 -2
- package/scripts/check-native-push-adapter.ts +20 -16
- package/scripts/check-native-push-register.ts +5 -1
- package/scripts/check-release-gate-outcomes.ts +47 -1
- package/scripts/check-setup-qualification.sh +3 -1
- package/scripts/codex-birth-doctor.sh +276 -0
- package/scripts/codex-birth-install.sh +414 -0
- package/scripts/codex-birth-uninstall.sh +170 -0
- package/scripts/codex-mcp-config.py +435 -0
- package/scripts/codex-statusline-config.py +434 -0
- package/scripts/codex_toml_io.py +532 -0
- package/scripts/lib/codex-fresh-live-protocol.ts +113 -0
- package/scripts/lib/codex-fresh-source-receipts.ts +399 -0
- package/scripts/lib/launch-receipt-windows.ts +46 -0
- package/scripts/lib/tmux-coordinate-row.ts +58 -0
- package/scripts/meta-bridge-fresh-cut.ts +6 -1
- package/scripts/mutants/codex-native.json +838 -0
- package/scripts/mutants/compaction-send-guard.json +103 -0
- package/scripts/mutants/entwurf-peers.json +19 -0
- package/scripts/mutants/mux-fresh-call.json +19 -8
- package/scripts/mutants/omp-fresh.json +6 -4
- package/scripts/mutants/release-gate.json +13 -0
- package/scripts/mutants/v2-surface.json +53 -1
- package/scripts/raw-async-delivery/README.md +2 -1
- package/scripts/raw-codex-measure/README.md +114 -46
- package/scripts/smoke-agy-native-push-live.ts +3 -1
- package/scripts/smoke-codex-birth.sh +347 -0
- package/scripts/smoke-codex-config-state.sh +511 -0
- package/scripts/smoke-codex-fresh-live.ts +1186 -0
- package/scripts/smoke-codex-native-push-live.ts +75 -0
- package/scripts/smoke-setup-verdict.sh +123 -10
- package/scripts/tsconfig.json +1 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { makeProductionEntwurfV2Deps } from "../pi-extensions/lib/entwurf-v2-production.ts";
|
|
6
|
+
import { runEntwurfV2 } from "../pi-extensions/lib/entwurf-v2-runner.ts";
|
|
7
|
+
import { upsertMetaSession } from "../pi-extensions/lib/meta-session.ts";
|
|
8
|
+
import { probeCodexThread } from "../pi-extensions/lib/native-push/codex-ws-client.ts";
|
|
9
|
+
import { skipLive } from "./lib/live-skip.ts";
|
|
10
|
+
|
|
11
|
+
if (process.env.LIVE !== "1") {
|
|
12
|
+
skipLive(
|
|
13
|
+
"smoke-codex-native-push-live",
|
|
14
|
+
"set LIVE=1 + CODEX_LIVE_THREAD_ID to run (sends a real turn to an already-loaded Codex thread).",
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const threadId = process.env.CODEX_LIVE_THREAD_ID?.trim();
|
|
19
|
+
if (!threadId) {
|
|
20
|
+
skipLive(
|
|
21
|
+
"smoke-codex-native-push-live",
|
|
22
|
+
"set CODEX_LIVE_THREAD_ID to a thread loaded by a TUI attached to the default Codex app-server.",
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "entwurf-codex-live-"));
|
|
27
|
+
process.on("exit", () => fs.rmSync(root, { recursive: true, force: true }));
|
|
28
|
+
const sessionsDir = path.join(root, "meta-sessions");
|
|
29
|
+
const born = upsertMetaSession({
|
|
30
|
+
dir: sessionsDir,
|
|
31
|
+
input: {
|
|
32
|
+
backend: "codex",
|
|
33
|
+
nativeSessionId: threadId,
|
|
34
|
+
cwd: process.cwd(),
|
|
35
|
+
model: process.env.CODEX_LIVE_MODEL?.trim() || null,
|
|
36
|
+
transcriptPath: path.join(root, "codex-live-transcript.jsonl"),
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const before = await probeCodexThread(threadId);
|
|
41
|
+
assert.equal(before.status, "alive", `[QK:CODEX-LIVE-PROBE] ${before.status === "alive" ? "" : before.reason}`);
|
|
42
|
+
|
|
43
|
+
const token = `CODEX-NATIVE-LIVE-${Date.now()}`;
|
|
44
|
+
const result = await runEntwurfV2(
|
|
45
|
+
{
|
|
46
|
+
target: born.record.gardenId,
|
|
47
|
+
intent: "fire-and-forget",
|
|
48
|
+
wantsReply: true,
|
|
49
|
+
message: `Entwurf native-push live acceptance. Reply with exactly ${token}`,
|
|
50
|
+
},
|
|
51
|
+
makeProductionEntwurfV2Deps({
|
|
52
|
+
senderProvider: () => ({
|
|
53
|
+
sessionId: born.record.gardenId,
|
|
54
|
+
agentId: "meta-session/codex",
|
|
55
|
+
cwd: process.cwd(),
|
|
56
|
+
timestamp: new Date().toISOString(),
|
|
57
|
+
origin: "meta-session",
|
|
58
|
+
replyable: true,
|
|
59
|
+
}),
|
|
60
|
+
sessionsDir,
|
|
61
|
+
mailboxDir: path.join(root, "mailbox"),
|
|
62
|
+
controlSocketDir: path.join(root, "control"),
|
|
63
|
+
lockDir: path.join(root, "locks"),
|
|
64
|
+
}),
|
|
65
|
+
);
|
|
66
|
+
assert.equal(result.kind, "executed", `[QK:CODEX-LIVE-PUBLIC-DISPATCH] ${JSON.stringify(result)}`);
|
|
67
|
+
assert.equal(result.kind === "executed" ? result.transport : null, "native-push");
|
|
68
|
+
const after = await probeCodexThread(threadId);
|
|
69
|
+
assert.equal(after.status, "alive", "Codex thread remains loaded after the one-shot queue acceptance");
|
|
70
|
+
|
|
71
|
+
console.log(`smoke-codex-native-push-live: delivered ${token}`);
|
|
72
|
+
console.log(` gardenId: ${born.record.gardenId}`);
|
|
73
|
+
console.log(` threadId: ${threadId}`);
|
|
74
|
+
console.log(` socket: ${before.status === "alive" ? before.route.socketPath : "unreachable"}`);
|
|
75
|
+
console.log(" verify the exact token appears in that visible Codex TUI; the delivery receipt is not the model result");
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
# core and later components still attempted
|
|
17
17
|
# S-8 omp present → the four omp units compose (birth/MCP/tools.xdev
|
|
18
18
|
# setting/receiver), states exist, second run idempotent
|
|
19
|
+
# S-8c codex present → birth publishes but stays a named FAIL until the vendor trust
|
|
20
|
+
# receipt exists; all three atoms compose twice, preserve foreign
|
|
21
|
+
# config, stay idempotent, and go green on the trusted rerun
|
|
19
22
|
# S-5 installed mode → the installed-vs-source branch is a NAMED verdict
|
|
20
23
|
# printed before anything else, and never reaches
|
|
21
24
|
# the source pnpm bootstrap
|
|
@@ -27,12 +30,15 @@
|
|
|
27
30
|
# below-floor and false-green shapes as living end-to-end evidence.
|
|
28
31
|
#
|
|
29
32
|
# Deterministic: no model, no network, no cost. Presence probes are pinned via
|
|
30
|
-
# PI_BIN / CLAUDE_BIN / AGY_BIN / COPILOT_BIN / OMP_BIN (the same hermetic seam
|
|
33
|
+
# PI_BIN / CLAUDE_BIN / AGY_BIN / COPILOT_BIN / OMP_BIN / CODEX_BIN (the same hermetic seam
|
|
31
34
|
# smoke-agy-install-state
|
|
32
35
|
# uses), and every write root is sandboxed: HOME, XDG roots, the pi agent dir,
|
|
33
|
-
# and the dev-bin dir.
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
+
# and the dev-bin dir. Source-mode cells put a strict fixture `pnpm` first on PATH:
|
|
37
|
+
# it accepts the no-op `install --frozen-lockfile` and the source-owned `run build-bridge`
|
|
38
|
+
# emit only. Package-manager behavior belongs to the package gates. This is load-bearing
|
|
39
|
+
# under mutation qualification, whose snapshot shares node_modules read-only — a real pnpm
|
|
40
|
+
# follows that symlink and attempts to rewrite the origin checkout. Any dist this gate had
|
|
41
|
+
# to build is removed on exit, restoring the snapshot's pre-gate surface.
|
|
36
42
|
set -euo pipefail
|
|
37
43
|
|
|
38
44
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -51,7 +57,13 @@ esac
|
|
|
51
57
|
export PYTHONDONTWRITEBYTECODE=1
|
|
52
58
|
|
|
53
59
|
SB="$(mktemp -d -t entwurf-setup-verdict.XXXXXX)"
|
|
54
|
-
|
|
60
|
+
DIST_ROOT="$REPO_DIR/mcp/entwurf-bridge/dist"
|
|
61
|
+
DIST_PREEXISTED=0
|
|
62
|
+
[ -d "$DIST_ROOT" ] && DIST_PREEXISTED=1
|
|
63
|
+
cleanup() {
|
|
64
|
+
[ "$DIST_PREEXISTED" -eq 1 ] || rm -rf "$DIST_ROOT"
|
|
65
|
+
rm -rf "$SB"
|
|
66
|
+
}
|
|
55
67
|
trap cleanup EXIT
|
|
56
68
|
|
|
57
69
|
export HOME="$SB/home"
|
|
@@ -62,12 +74,27 @@ export XDG_CONFIG_HOME="$SB/home/.config"
|
|
|
62
74
|
export PI_CODING_AGENT_DIR="$SB/home/.pi/agent"
|
|
63
75
|
export ENTWURF_DEV_BIN_DIR="$SB/bin"
|
|
64
76
|
export PATH="$SB/bin:$PATH"
|
|
65
|
-
mkdir -p "$HOME" "$PI_CODING_AGENT_DIR" "$SB/bin" "$SB/harness"
|
|
77
|
+
mkdir -p "$HOME" "$PI_CODING_AGENT_DIR" "$SB/bin" "$SB/harness" "$SB/bootstrap-bin"
|
|
78
|
+
cat > "$SB/bootstrap-bin/pnpm" <<'SH'
|
|
79
|
+
#!/bin/sh
|
|
80
|
+
if [ "$#" -eq 2 ] && [ "$1" = install ] && [ "$2" = --frozen-lockfile ]; then
|
|
81
|
+
exit 0
|
|
82
|
+
fi
|
|
83
|
+
if [ "$#" -eq 2 ] && [ "$1" = run ] && [ "$2" = build-bridge ]; then
|
|
84
|
+
# The qualification snapshot is process-exclusive. Invoke the source-owned emit
|
|
85
|
+
# directly so the production lock wrapper cannot leave its ignored parent dir.
|
|
86
|
+
exec bash scripts/build-bridge.sh
|
|
87
|
+
fi
|
|
88
|
+
echo "fixture pnpm accepts only: install --frozen-lockfile | run build-bridge" >&2
|
|
89
|
+
exit 64
|
|
90
|
+
SH
|
|
91
|
+
chmod +x "$SB/bootstrap-bin/pnpm"
|
|
92
|
+
export PATH="$SB/bootstrap-bin:$PATH"
|
|
66
93
|
|
|
67
94
|
# Presence pins: default every harness to a definitely-absent path; each cell
|
|
68
95
|
# re-pins what it needs. Production leaves these unset.
|
|
69
96
|
ABSENT="$SB/harness/definitely-absent"
|
|
70
|
-
export PI_BIN="$ABSENT" CLAUDE_BIN="$ABSENT" AGY_BIN="$ABSENT" COPILOT_BIN="$ABSENT" OMP_BIN="$ABSENT"
|
|
97
|
+
export PI_BIN="$ABSENT" CLAUDE_BIN="$ABSENT" AGY_BIN="$ABSENT" COPILOT_BIN="$ABSENT" OMP_BIN="$ABSENT" CODEX_BIN="$ABSENT"
|
|
71
98
|
|
|
72
99
|
PASS=0
|
|
73
100
|
ok() { PASS=$((PASS + 1)); printf ' ok %s\n' "$*"; }
|
|
@@ -94,7 +121,8 @@ echo "[smoke-setup-verdict] S-1 all-harness-absent setup"
|
|
|
94
121
|
PROJ1="$SB/proj1"; mkdir -p "$PROJ1"
|
|
95
122
|
seed_auth
|
|
96
123
|
set +e; OUT="$(bash "$REPO_DIR/run.sh" setup "$PROJ1" 2>&1)"; RC=$?; set -e
|
|
97
|
-
want "S-1: all-absent setup exits 0
|
|
124
|
+
want "S-1: all-absent setup exits 0 with a Codex SKIP" \
|
|
125
|
+
"[ '$RC' -eq 0 ] && printf '%s' \"\$OUT\" | grep -q 'codex: SKIP'"
|
|
98
126
|
want "S-1: mode is a named source-checkout branch, printed first" \
|
|
99
127
|
"printf '%s' \"\$OUT\" | head -n 1 | grep -q 'mode: source checkout'"
|
|
100
128
|
want "S-1: pi absent is an explicit zero-state SKIP" "printf '%s' \"\$OUT\" | grep -q 'pi: SKIP'"
|
|
@@ -112,6 +140,7 @@ want "S-1: no user-scope pi settings were created" "[ ! -e '$PI_CODING_AGENT_DIR
|
|
|
112
140
|
want "S-1: no agy config was created" "[ ! -e '$HOME/.gemini' ]"
|
|
113
141
|
want "S-1: no Copilot config/units were created" "[ ! -e '$HOME/.copilot' ]"
|
|
114
142
|
want "S-1: no OMP config/units were created" "[ ! -e '$HOME/.omp' ]"
|
|
143
|
+
want "S-1: no Codex config/units were created" "[ ! -e '$HOME/.codex' ]"
|
|
115
144
|
want_auth_untouched "S-1"
|
|
116
145
|
|
|
117
146
|
# ── S-2: pi resolvable but BELOW floor → detected FAIL, never SKIP, no writes ──
|
|
@@ -287,6 +316,90 @@ rm -rf "$HOME/.omp" "$XDG_DATA_HOME/entwurf/omp-bridge" "$XDG_DATA_HOME/entwurf/
|
|
|
287
316
|
"$XDG_DATA_HOME/entwurf/omp-config" "$XDG_DATA_HOME/entwurf/omp-receive" \
|
|
288
317
|
"$XDG_DATA_HOME/entwurf/meta-bridge-omp" "$XDG_DATA_HOME/entwurf/omp-receive"
|
|
289
318
|
|
|
319
|
+
# ── S-8c: codex PRESENT → setup publishes birth, and stays NON-GREEN until the vendor agrees ──
|
|
320
|
+
# The birth unit's paths are the operator's own, so setup installs it here for real, inside the
|
|
321
|
+
# fixture's HOME/CODEX_HOME/XDG. What setup CANNOT do is answer the vendor's one-time trust
|
|
322
|
+
# prompt: that is the operator's, in their own visible Codex. So the first run writes every
|
|
323
|
+
# byte and is honestly non-green, the two config atoms compose anyway, and the run after a
|
|
324
|
+
# vendor receipt appears is green and byte-idempotent. Nothing here ever writes [hooks.state] —
|
|
325
|
+
# the receipt is forged by the FIXTURE to stand in for the vendor, never by setup.
|
|
326
|
+
echo "[smoke-setup-verdict] S-8c codex present — incomplete three-unit composition"
|
|
327
|
+
PROJ8C="$SB/proj8c"; mkdir -p "$PROJ8C"
|
|
328
|
+
FAKE_CODEX="$SB/harness/codex-fake"; mkdir -p "$FAKE_CODEX"
|
|
329
|
+
printf '#!/usr/bin/env bash\necho "codex-cli 0.153.4"\n' > "$FAKE_CODEX/codex"
|
|
330
|
+
chmod +x "$FAKE_CODEX/codex"
|
|
331
|
+
CODEX_HOME_SANDBOX="$HOME/.codex"
|
|
332
|
+
mkdir -p "$CODEX_HOME_SANDBOX"
|
|
333
|
+
cat > "$CODEX_HOME_SANDBOX/config.toml" <<'TOML'
|
|
334
|
+
model = "operator-model"
|
|
335
|
+
|
|
336
|
+
[projects."/operator/keep"]
|
|
337
|
+
trust_level = "trusted"
|
|
338
|
+
|
|
339
|
+
[mcp_servers.operator-owned]
|
|
340
|
+
command = "/operator/bin/server"
|
|
341
|
+
args = ["--keep"]
|
|
342
|
+
|
|
343
|
+
[tui]
|
|
344
|
+
status_line = ["model-with-reasoning"]
|
|
345
|
+
TOML
|
|
346
|
+
REAL_BASH="$(command -v bash)"
|
|
347
|
+
CODEX_BIRTH_UNIT_ROOT="$XDG_DATA_HOME/entwurf/codex-birth"
|
|
348
|
+
seed_auth
|
|
349
|
+
set +e
|
|
350
|
+
OUT="$(CODEX_BIN="$FAKE_CODEX/codex" CODEX_HOME="$CODEX_HOME_SANDBOX" PATH="$FAKE_CODEX:$PATH" "$REAL_BASH" "$REPO_DIR/run.sh" setup "$PROJ8C" 2>&1)"
|
|
351
|
+
RC=$?
|
|
352
|
+
set -e
|
|
353
|
+
want "[QK:CODEX-SETUP-NEVER-PRESEEDS-TRUST] S-8c: setup wrote NO vendor trust receipt of its own" \
|
|
354
|
+
"! grep -q 'hooks.state' '$CODEX_HOME_SANDBOX/config.toml' && ! grep -q 'trusted_hash' '$CODEX_HOME_SANDBOX/config.toml'"
|
|
355
|
+
want "S-8c: detected-incomplete Codex is a named nonzero result, never an absent SKIP [QK:CODEX-SETUP-BIRTH-COSMETIC-PASS]" \
|
|
356
|
+
"[ '$RC' -ne 0 ] && printf '%s' \"\$OUT\" | grep -q 'codex-birth: FAIL' && ! printf '%s' \"\$OUT\" | grep -q 'codex: SKIP'"
|
|
357
|
+
want "S-8c: both user-owned Codex atoms still compose independently as PASS [QK:CODEX-SETUP-BIRTH-INDEPENDENT]" \
|
|
358
|
+
"printf '%s' \"\$OUT\" | grep -q 'codex-mcp: PASS' && printf '%s' \"\$OUT\" | grep -q 'codex-statusline: PASS'"
|
|
359
|
+
want "S-8c: summary is NON-GREEN and attributes it to the untrusted birth unit" \
|
|
360
|
+
"printf '%s' \"\$OUT\" | grep -q 'NON-GREEN (FAIL: codex-birth)' && ! printf '%s' \"\$OUT\" | grep -q 'result: green'"
|
|
361
|
+
want "S-8c: the reason names the operator's one-time answer, not a repair setup could have made" \
|
|
362
|
+
"printf '%s' \"\$OUT\" | grep -q 'no trust receipt' && printf '%s' \"\$OUT\" | grep -q 'Trust all and continue'"
|
|
363
|
+
want "S-8c: setup PUBLISHED the birth unit — declaration, launcher closure and ownership state" \
|
|
364
|
+
"[ -f '$CODEX_HOME_SANDBOX/hooks.json' ] && [ -x '$CODEX_BIRTH_UNIT_ROOT/helper/codex-birth-launch.sh' ] && [ -f '$CODEX_BIRTH_UNIT_ROOT/install-state.json' ]"
|
|
365
|
+
CODEX_MCP_STATE="$XDG_DATA_HOME/entwurf/codex-mcp/install-state.json"
|
|
366
|
+
CODEX_STATUSLINE_STATE="$XDG_DATA_HOME/entwurf/codex-statusline/install-state.json"
|
|
367
|
+
want "S-8c: both user atoms wrote their package-owned install states inside the sandbox" \
|
|
368
|
+
"[ -f '$CODEX_MCP_STATE' ] && [ -f '$CODEX_STATUSLINE_STATE' ] && grep -q '\"atom\": \"codex-mcp\"' '$CODEX_MCP_STATE' && grep -q '\"atom\": \"codex-statusline\"' '$CODEX_STATUSLINE_STATE'"
|
|
369
|
+
want "S-8c: MCP and visible-identity atoms landed in the sandbox Codex config" \
|
|
370
|
+
"grep -q '\\[mcp_servers\\.entwurf-bridge\\]' '$CODEX_HOME_SANDBOX/config.toml' && grep -q 'status_line = \\[\"thread-title\", \"model-with-reasoning\"\\]' '$CODEX_HOME_SANDBOX/config.toml'"
|
|
371
|
+
want "S-8c: unrelated operator config survives both atom writers" \
|
|
372
|
+
"grep -q 'model = \"operator-model\"' '$CODEX_HOME_SANDBOX/config.toml' && grep -q '\\[mcp_servers\\.operator-owned\\]' '$CODEX_HOME_SANDBOX/config.toml' && grep -q 'command = \"/operator/bin/server\"' '$CODEX_HOME_SANDBOX/config.toml'"
|
|
373
|
+
CODEX_CONFIG_AFTER="$(sha256sum "$CODEX_HOME_SANDBOX/config.toml" | cut -d' ' -f1)"
|
|
374
|
+
CODEX_MCP_STATE_AFTER="$(sha256sum "$CODEX_MCP_STATE" | cut -d' ' -f1)"
|
|
375
|
+
CODEX_STATUSLINE_STATE_AFTER="$(sha256sum "$CODEX_STATUSLINE_STATE" | cut -d' ' -f1)"
|
|
376
|
+
set +e
|
|
377
|
+
OUT2="$(CODEX_BIN="$FAKE_CODEX/codex" CODEX_HOME="$CODEX_HOME_SANDBOX" PATH="$FAKE_CODEX:$PATH" "$REAL_BASH" "$REPO_DIR/run.sh" setup "$PROJ8C" 2>&1)"
|
|
378
|
+
RC2=$?
|
|
379
|
+
set -e
|
|
380
|
+
want "S-8c: second setup still reports the untrusted birth FAIL and both user atoms PASS" \
|
|
381
|
+
"[ '$RC2' -ne 0 ] && printf '%s' \"\$OUT2\" | grep -q 'codex-birth: FAIL' && printf '%s' \"\$OUT2\" | grep -q 'codex-mcp: PASS' && printf '%s' \"\$OUT2\" | grep -q 'codex-statusline: PASS'"
|
|
382
|
+
want "S-8c: second setup is byte-idempotent for config and both ownership receipts" \
|
|
383
|
+
"[ \"\$(sha256sum '$CODEX_HOME_SANDBOX/config.toml' | cut -d' ' -f1)\" = '$CODEX_CONFIG_AFTER' ] && [ \"\$(sha256sum '$CODEX_MCP_STATE' | cut -d' ' -f1)\" = '$CODEX_MCP_STATE_AFTER' ] && [ \"\$(sha256sum '$CODEX_STATUSLINE_STATE' | cut -d' ' -f1)\" = '$CODEX_STATUSLINE_STATE_AFTER' ]"
|
|
384
|
+
want "S-8c: second setup rechecks rather than faking the missing receipt" \
|
|
385
|
+
"! printf '%s' \"\$OUT2\" | grep -q 'codex-birth: PASS' && ! grep -q 'trusted_hash' '$CODEX_HOME_SANDBOX/config.toml'"
|
|
386
|
+
|
|
387
|
+
# The vendor answers. Written by the FIXTURE, exactly as the vendor writes it after one
|
|
388
|
+
# 'Trust all': the receipt keyed to this declaration, carrying its own hash.
|
|
389
|
+
printf '\n[hooks.state."%s/hooks.json:session_start:0:0"]\ntrusted_hash = "sha256:%s"\n' \
|
|
390
|
+
"$CODEX_HOME_SANDBOX" "$(printf '4%.0s' $(seq 64))" >> "$CODEX_HOME_SANDBOX/config.toml"
|
|
391
|
+
CODEX_CONFIG_TRUSTED="$(sha256sum "$CODEX_HOME_SANDBOX/config.toml" | cut -d' ' -f1)"
|
|
392
|
+
set +e
|
|
393
|
+
OUT3="$(CODEX_BIN="$FAKE_CODEX/codex" CODEX_HOME="$CODEX_HOME_SANDBOX" PATH="$FAKE_CODEX:$PATH" "$REAL_BASH" "$REPO_DIR/run.sh" setup "$PROJ8C" 2>&1)"
|
|
394
|
+
RC3=$?
|
|
395
|
+
set -e
|
|
396
|
+
want "[QK:CODEX-SETUP-TRUSTED-RERUN-GREEN] S-8c: once the vendor receipt exists the same setup is GREEN" \
|
|
397
|
+
"[ '$RC3' -eq 0 ] && printf '%s' \"\$OUT3\" | grep -q 'codex-birth: PASS' && printf '%s' \"\$OUT3\" | grep -q 'result: green'"
|
|
398
|
+
want "S-8c: the trusted rerun is byte-idempotent — it neither rewrote the config nor touched the receipt" \
|
|
399
|
+
"[ \"\$(sha256sum '$CODEX_HOME_SANDBOX/config.toml' | cut -d' ' -f1)\" = '$CODEX_CONFIG_TRUSTED' ]"
|
|
400
|
+
want_auth_untouched "S-8c"
|
|
401
|
+
rm -rf "$HOME/.codex" "$XDG_DATA_HOME/entwurf/codex-mcp" "$XDG_DATA_HOME/entwurf/codex-statusline" "$CODEX_BIRTH_UNIT_ROOT"
|
|
402
|
+
|
|
290
403
|
# ── S-9: rail certification is a SEPARATE axis from install success (#78 D1) ──
|
|
291
404
|
# The 0.20.0 macOS lane opened the installers to Darwin (meta-bridge-install.sh's
|
|
292
405
|
# platform gate became its own python3/node dependency instead of the platform
|
|
@@ -379,8 +492,8 @@ PROJ9C="$SB/proj9c"; mkdir -p "$PROJ9C"
|
|
|
379
492
|
seed_auth
|
|
380
493
|
set +e; OUT="$(PATH="$FAKE_UNAME:$PATH" bash "$REPO_DIR/run.sh" setup "$PROJ9C" 2>&1)"; RC=$?; set -e
|
|
381
494
|
want "S-9c: a harness-free uncertified host still exits 0" "[ '$RC' -eq 0 ]"
|
|
382
|
-
want "S-9c: all
|
|
383
|
-
"printf '%s' \"\$OUT\" | grep -q 'pi: SKIP' && printf '%s' \"\$OUT\" | grep -q 'claude: SKIP' && printf '%s' \"\$OUT\" | grep -q 'agy: SKIP' && printf '%s' \"\$OUT\" | grep -q 'copilot: SKIP' && printf '%s' \"\$OUT\" | grep -q 'omp: SKIP'"
|
|
495
|
+
want "S-9c: all six harness probes are still zero-state SKIPs" \
|
|
496
|
+
"printf '%s' \"\$OUT\" | grep -q 'pi: SKIP' && printf '%s' \"\$OUT\" | grep -q 'claude: SKIP' && printf '%s' \"\$OUT\" | grep -q 'agy: SKIP' && printf '%s' \"\$OUT\" | grep -q 'copilot: SKIP' && printf '%s' \"\$OUT\" | grep -q 'omp: SKIP' && printf '%s' \"\$OUT\" | grep -q 'codex: SKIP'"
|
|
384
497
|
want "S-9c: core still PASSes and the computed summary is still green" \
|
|
385
498
|
"printf '%s' \"\$OUT\" | grep -q 'core: PASS' && printf '%s' \"\$OUT\" | grep -q 'result: green (computed from the component outcomes above)'"
|
|
386
499
|
want "S-9c: an absent harness is never given a rail verdict it did not earn" \
|
package/scripts/tsconfig.json
CHANGED
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"../pi-extensions/model-lock.ts",
|
|
32
32
|
"../pi-extensions/meta-bridge-hook.ts",
|
|
33
33
|
"../pi-extensions/meta-bridge-hook-copilot.ts",
|
|
34
|
+
"../pi-extensions/meta-bridge-hook-codex.ts",
|
|
34
35
|
"../pi-extensions/meta-bridge-omp.ts",
|
|
35
36
|
"../pi-extensions/meta-bridge-receive-omp.ts",
|
|
36
37
|
"../mcp/entwurf-bridge/src/resume-mode.ts"
|