@junghanacs/entwurf 0.21.0 → 0.23.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 -2
- package/BASELINE.md +3 -1
- package/CHANGELOG.md +658 -0
- package/DELIVERY.md +167 -29
- package/README.md +104 -14
- package/VERIFY.md +73 -11
- package/docs/external-mcp-host.md +16 -6
- package/docs/setup-clean-host.md +73 -22
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +54 -31
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-caller-seat.js +174 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-declaration.js +609 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-fresh-preflight.js +289 -57
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-control-rpc.js +40 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-fact-provider.js +6 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-facts.js +7 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-peer-observe.js +67 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-peers-render.js +9 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-self-address.js +24 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-runner.js +3 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-send.js +8 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-composition.js +423 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-dispatch.js +98 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +1018 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-placement.js +213 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +171 -263
- package/mcp/entwurf-bridge/dist/scripts/codex-socket-path.js +30 -0
- package/mcp/entwurf-bridge/dist/scripts/peer-facts.js +109 -0
- package/mcp/entwurf-bridge/src/index.ts +65 -31
- package/mcp/entwurf-bridge/tsconfig.build.json +10 -0
- package/package.json +4 -4
- package/pi-extensions/entwurf-control.ts +91 -52
- package/pi-extensions/lib/codex-caller-seat.ts +204 -0
- package/pi-extensions/lib/codex-declaration.js +612 -0
- package/pi-extensions/lib/codex-fresh-preflight.ts +325 -52
- package/pi-extensions/lib/entwurf-control-rpc.ts +46 -0
- package/pi-extensions/lib/entwurf-fact-provider.ts +13 -2
- package/pi-extensions/lib/entwurf-facts.ts +14 -1
- package/pi-extensions/lib/entwurf-peer-observe.ts +72 -2
- package/pi-extensions/lib/entwurf-peers-render.ts +9 -1
- package/pi-extensions/lib/entwurf-self-address.ts +33 -0
- package/pi-extensions/lib/entwurf-v2-runner.ts +3 -2
- package/pi-extensions/lib/entwurf-v2-send.ts +16 -11
- package/pi-extensions/lib/fresh-call-composition.ts +493 -0
- package/pi-extensions/lib/fresh-call-dispatch.ts +142 -0
- package/pi-extensions/lib/herdr-fresh-call.ts +1378 -0
- package/pi-extensions/lib/herdr-placement.ts +276 -0
- package/pi-extensions/lib/mux-fresh-call.ts +257 -304
- package/run.sh +522 -10
- package/scripts/check-codex-app-server-launch.ts +445 -0
- package/scripts/check-codex-birth-hook.ts +187 -0
- package/scripts/check-entwurf-control-rpc.ts +138 -0
- package/scripts/check-entwurf-fact-provider.ts +4 -2
- package/scripts/check-entwurf-facts.ts +12 -6
- package/scripts/check-entwurf-peers-surface.ts +3 -1
- package/scripts/check-entwurf-self-address.ts +68 -0
- package/scripts/check-entwurf-v2-production.ts +42 -1
- package/scripts/check-entwurf-v2-send.ts +26 -7
- package/scripts/check-fresh-call-dispatch.ts +301 -0
- package/scripts/check-gate-qualification.ts +19 -5
- package/scripts/check-herdr-activation.ts +1293 -0
- package/scripts/check-herdr-fresh-call.ts +1250 -0
- package/scripts/check-herdr-placement.ts +383 -0
- package/scripts/check-herdr-plugin-build.ts +842 -0
- package/scripts/check-herdr-plugin-profile.ts +371 -0
- package/scripts/check-herdr-plugin.ts +523 -0
- package/scripts/check-herdr-runtime-bootstrap.ts +1264 -0
- package/scripts/check-herdr-sandbox.ts +456 -0
- package/scripts/check-herdr-supply.ts +184 -0
- package/scripts/check-mux-launch-tmux.ts +331 -35
- package/scripts/check-mux-launcher-fence.ts +138 -0
- package/scripts/check-peer-facts.ts +331 -0
- package/scripts/check-release-gate-outcomes.ts +12 -0
- package/scripts/check-typing-call-fence.ts +296 -0
- package/scripts/codex-app-server-launch.sh +275 -0
- package/scripts/codex-birth-doctor.sh +159 -16
- package/scripts/codex-birth-install.sh +178 -72
- package/scripts/codex-birth-uninstall.sh +162 -7
- package/scripts/codex-socket-path.ts +33 -0
- package/scripts/codex-terminal-title-config.py +500 -0
- package/scripts/codex_toml_io.py +121 -0
- package/scripts/fixtures/herdr-supply.json +29 -0
- package/scripts/herdr-activation.mjs +536 -0
- package/scripts/herdr-plugin-activate.mjs +270 -0
- package/scripts/herdr-plugin-deactivate.mjs +193 -0
- package/scripts/herdr-runtime.mjs +1203 -0
- package/scripts/install-herdr-ci.sh +96 -0
- package/scripts/lib/codex-fresh-live-protocol.ts +13 -5
- package/scripts/lib/codex-fresh-source-receipts.ts +29 -2
- package/scripts/lib/tree-digest.ts +97 -0
- package/scripts/meta-bridge-install.sh +19 -2
- package/scripts/meta-bridge-state.py +167 -11
- package/scripts/mutants/codex-app-server-launch.json +157 -0
- package/scripts/mutants/codex-caller-seat.json +334 -0
- package/scripts/mutants/codex-native.json +195 -29
- package/scripts/mutants/control-socket-disconnect.json +57 -0
- package/scripts/mutants/fresh-call-dispatch.json +154 -0
- package/scripts/mutants/herdr-activation.json +305 -0
- package/scripts/mutants/herdr-fresh-call.json +448 -0
- package/scripts/mutants/herdr-placement.json +161 -0
- package/scripts/mutants/herdr-plugin-build.json +160 -0
- package/scripts/mutants/herdr-plugin-profile.json +202 -0
- package/scripts/mutants/herdr-plugin.json +133 -0
- package/scripts/mutants/herdr-runtime-bootstrap.json +411 -0
- package/scripts/mutants/herdr-supply.json +133 -0
- package/scripts/mutants/meta-hook-session-switch.json +2 -2
- package/scripts/mutants/mux-fresh-call.json +184 -25
- package/scripts/mutants/mux-launcher-fence.json +13 -0
- package/scripts/mutants/omp-fresh.json +4 -4
- package/scripts/mutants/peer-facts.json +98 -0
- package/scripts/mutants/self-address.json +33 -0
- package/scripts/mutants/typing-call-fence.json +17 -0
- package/scripts/mutants/v2-surface.json +22 -0
- package/scripts/peer-facts.ts +120 -0
- package/scripts/register-pi-package.py +8 -0
- package/scripts/register-pi-provider.py +88 -12
- package/scripts/smoke-codex-birth.sh +281 -12
- package/scripts/smoke-codex-config-state.sh +192 -3
- package/scripts/smoke-codex-fresh-live.ts +277 -37
- package/scripts/smoke-entwurf-chain-live.ts +50 -0
- package/scripts/smoke-herdr-fresh-call-live.ts +1027 -0
- package/scripts/smoke-herdr-plugin-build-live.ts +543 -0
- package/scripts/smoke-setup-verdict.sh +13 -11
package/run.sh
CHANGED
|
@@ -120,7 +120,7 @@ usage() {
|
|
|
120
120
|
cat <<'EOF'
|
|
121
121
|
Usage:
|
|
122
122
|
./run.sh setup [project-dir] # ONE presence-driven composition (#86): per-component PASS/SKIP/FAIL for pi/claude/agy/copilot/omp/codex + stable dev bins + v2 install smoke. Codex birth/MCP/status-line atoms are composed at user scope; setup stays non-green until the operator trusts the birth declaration once in visible Codex. Absent harness = zero-state SKIP, detected-incomplete = named FAIL + nonzero exit. Never installs a harness, starts a daemon, touches credentials, or writes the vendor trust receipt
|
|
123
|
-
./run.sh release-gate [project-dir] [--cut] [--allow-skip-gemini] # SINGLE release gate: full static (pnpm run check:full) + the v2-native live gates (v2 matrix-live, check-bridge, doctor-pi-provider, RGG) + the ACP plugin acceptance floor (12 LIVE smokes: socket-citizen/raw-turn/overlay/provider/session-reuse/carrier-augment/memory-containment/rgg/mcp/skill/bundled-mcp/v2-send) + the one surviving axis the aggregate used to omit silently (claude-native-resume; Cortex stays a documented on-demand direct call) + the cross-harness delivery chain (smoke-entwurf-chain-live) + the Codex
|
|
123
|
+
./run.sh release-gate [project-dir] [--cut] [--allow-skip-gemini] # SINGLE release gate: full static (pnpm run check:full) + the v2-native live gates (v2 matrix-live, check-bridge, doctor-pi-provider, RGG) + the ACP plugin acceptance floor (12 LIVE smokes: socket-citizen/raw-turn/overlay/provider/session-reuse/carrier-augment/memory-containment/rgg/mcp/skill/bundled-mcp/v2-send) + the one surviving axis the aggregate used to omit silently (claude-native-resume; Cortex stays a documented on-demand direct call) + the cross-harness delivery chain (smoke-entwurf-chain-live) + the Codex Pi -> visible Codex -> visible Pi receipt chain (smoke-codex-fresh-live; initial Pi and the Codex it opens in one session S, explicit operator-owned app-server PID in a DIFFERENT session — that separation is the lane B claim). TWO-TIER summary: MUST (release-blocking, owns the exit code — "green" applies here) + BEHAVIOR (advisory, non-blocking: RGG positives model-in-loop turn). STEP OUTCOME protocol: every step is INVOKED and reports its own PASS / SKIP (exit 97, a prerequisite it does not have) / FAIL — a skip is never counted as a pass. Without --cut this is the unattended diagnostic (SKIPs reported, exit 0). WITH --cut it is read as release acceptance and ANY MUST SKIP is red, which is what makes "a CUT needs LIVE=1, SKIP=0" executable instead of prose. --allow-skip-gemini accepted-but-ignored (back-compat). final cut authorization is GLG's.
|
|
124
124
|
./run.sh check-bridge # entwurf-bridge direct MCP smoke + protocol/negative-path test.sh (live substrate = v2 live smokes)
|
|
125
125
|
./run.sh check-entwurf-bridge-boot # deterministic gate (5d-5-pre, G1a/G1b/G1e/G1f, IN pnpm run check:full): boot start.sh under strip-types + assert v2 fence graph loads + entwurf_v2 and entwurf_resume_call registered/schema + the tools/list surface is EXACTLY the seven shipped garden verbs; tools/list only, no auth/side-effect
|
|
126
126
|
./run.sh check-entwurf-bridge-pi-free # deterministic gate (0.12.1 A, IN pnpm check): static — bridge index eager value-import closure must carry no @earendil-works/pi-* (type-only + dynamic import excluded); proves the meta-bridge boots pi-free
|
|
@@ -134,6 +134,7 @@ Usage:
|
|
|
134
134
|
./run.sh check-omp-birth-hook # #87 gate: drives the real OMP assembler into a temp dir, imports the ASSEMBLED index.ts into a MOCK omp host and fires session_start/session_switch. tui mints one backend:"omp" record + a sender marker keyed to the host's OWN pid (the one-process join) + the garden id on the status line; print/rpc/json mint NOTHING (hasUI is true on the rpc rows, as in the vendor); switch attaches on the same native id and mints the replacement on a new one; the CERTIFIED receiver reader still finds no marker. Also the four-root joint binding: extension and omp-labeled bridge child resolve the same sessions/mailbox/senders/receivers bundle against test-built literals (never the production resolver as its own oracle), under a poisoned PI_CODING_AGENT_DIR and under four distinct ENTWURF_META_* overrides; the override grammar is absolute-or-~ and both halves plus the doctor refuse anything else by name; and a drifted provenance label selects no root policy at all. Hermetic; no omp, no model turn
|
|
135
135
|
./run.sh check-copilot-receive-arm # #82 RAIL 5 gate: the REAL receiver installer + the REAL extension.mjs forked with a stubbed SDK. Arms only after birth, marker owned by the WATCHER pid, self-fetch dispatch answer, doorbell carries the garden id and NOT the body, id-drift/foreign-parent refusals. Hermetic; no Copilot, no model turn
|
|
136
136
|
./run.sh check-copilot-launch # #82 RAIL 7 gate: the MANAGED launch `entwurf copilot`, driven through its public address against a FAKE VENDOR on a sandbox PATH. Receiver precondition refusals, EXTENSIONS token + operator token preservation, injected defaults before the `--` terminator, byte-identical argv, the 11 explicit permission/surface policy overrides that suppress `--yolo`, exec (not fork) pid identity, exit passthrough, recursion refusal. Hermetic; no Copilot, no model turn
|
|
137
|
+
./run.sh check-codex-app-server-launch # #95 gate: the MANAGED app-server launch `entwurf codex-app-server`, driven through its public address against a FAKE VENDOR on a sandbox PATH. The injected `app-server --listen unix://<socket>` required to equal the product's own resolveCodexDefaultSocketPath over an env matrix that includes the inputs a bash transcription was MEASURED to diverge on (BOM-only CODEX_HOME, trailing slash, `..`), non-absolute and control-character addresses refused before any write, byte-identical operator argv, exec (not fork) parent identity, exit passthrough, live-socket and indeterminate-socket and second---listen and recursion refusals, dead-socket launch-over, the tmux fact line, and both identity carriers stripped. Hermetic; no Codex, no app-server, no model turn
|
|
137
138
|
./run.sh check-copilot-statusline # #82 Copilot custom-footer renderer. session_id → ready/?/gid + rail `cop`; exit 0. IN pnpm check. No Copilot, no model turn
|
|
138
139
|
./run.sh check-entwurf-capabilities # deterministic gate (0.11 Stage 0 step 3C): backend capability registry (pi/entwurf-capabilities.json) — coverage==META_CITIZEN_BACKENDS + agrees with live META_BACKEND_DESCRIPTORS + strict keyset, no API
|
|
139
140
|
./run.sh check-omp-fresh-preflight # #87 C: the OMP fresh preflight reproduces omp_agent_dir and the tools.xdev read in TS (it runs from two emit depths and cannot call a sibling script). This drives the SHIPPED shell/python leaves over the same inputs — refusals included — and requires the TS half to agree, so the reproduction cannot silently drift from the installer's own oracle
|
|
@@ -143,7 +144,7 @@ Usage:
|
|
|
143
144
|
./run.sh check-codex-birth-hook # sandboxed payload + declaration: first-turn V3 birth, one record per thread, top-level event predicate, no markers
|
|
144
145
|
./run.sh check-codex-fresh-preflight # pre-mutation birth/MCP/thread-title/default-app-server readiness
|
|
145
146
|
./run.sh smoke-codex-config-state # sandboxed MCP + status-line ownership/install/doctor/inverse lifecycle
|
|
146
|
-
./run.sh smoke-codex-birth # sandboxed birth unit: exact trust identity, the vendor trust receipt read (never written), config.toml untouched, foreign/
|
|
147
|
+
./run.sh smoke-codex-birth # sandboxed birth unit: exact trust identity, the vendor trust receipt read at our MEASURED index (never written), config.toml untouched, coexistence with a foreign SessionStart group in either ordering (joined not adopted, reported not certified, byte-preserved across install and inverse), own-declaration drift/duplication refusals, drift-refusing inverse
|
|
147
148
|
./run.sh check-harness-admission-parity # #87 C: the EDGE the two closed parity loops never had. Every citizen backend is fresh-openable or a declared pre-#82 legacy admission whose exception a reader finds in DELIVERY.md — so a post-contract harness that mints records but cannot be opened by entwurf_fresh_call blocks the release package instead of only carrying an `unsupported` note (docs/adding-a-harness.md step 9)
|
|
148
149
|
./run.sh check-capability-bundle-reach # deterministic gate (IN pnpm check): re-ask EVERY shipped copy of meta-session (source + bridge bundle emit) whether metaCapabilitiesFilePath() reaches the registry — the artifact-depth check the source-path gates cannot make; needs a built dist, missing dist FAILS
|
|
149
150
|
./run.sh smoke-pi-attach # deterministic gate (#50 C2 checkpoint + C3 ACP tail): a pi session attaches as a V3 meta-record citizen (backend:"pi"), the gardenId is the RECORD's not pi's session id, the control socket is keyed on it, a re-open ATTACHES to the same address (never a second mint), the BUILT DIST ENTRY driven over MCP stdio lists the citizen + delivers entwurf_v2 to that socket with an RPC ack, and the ACP identity chain lands a send AS the host record (enrichMcpServersWithEnvelope env → bridge sender = host gardenId). mkdtemp-isolated; the live store is never read
|
|
@@ -170,18 +171,26 @@ Usage:
|
|
|
170
171
|
./run.sh check-mux-resume-call # deterministic gate: S1 resume PLACEMENT composition (mux-resume-call.ts). No fake tmux. cwd rules are MEASURED tmux 3.6a behaviours, each a way a resume looks successful while being wrong: a nonexistent `-c` exits 0 and lands the child in $HOME (so it is refused HERE), `-c` is FORMAT-EXPANDED so `#{…}` silently rewrites the path and `#(…)` was observed running a command (so `#` is refused), and whitespace measured SAFE (so no escaping layer is owed). Also pins `-c` reaching tmux, runtime after `--`, carrier-free argv, zero identity in this module, and the surface seam that keeps the v2 composition from importing mux
|
|
171
172
|
./run.sh check-mux-parent-artifact # deterministic gate for the tracked scrubbed parent-transcript fixture — a version-pinned sample of the PARENT-SIDE shape (fresh_call toolResult + the later callback custom_message) so downstream never opens a private transcript. Pins event order, the toolCallId join on the RESULT (pi writes no separate toolCall row), the launch nonce reappearing verbatim in the callback body, the <sender_info> envelope field names, and the absence of operator paths / real garden ids / real uuids. NOT placement evidence
|
|
172
173
|
./run.sh check-mux-launcher-fence # deterministic gate for the shared operator-launcher fence (issue #67): scripts/lib/claude-launcher-fence.ts + its wiring into BOTH mux LIVE smokes. Replants the observed install-destruction shape (real HOME + fixture XDG_DATA_HOME → self-update retargets the real `claude` launcher into the fixture tree, teardown deletes it) wholly inside disposable mkdtemp roots — the real launcher is never inspected. Pins fail-closed preflight, retarget/content-change detection before cleanup, removal BLOCKED on fixture reference / unproven safety / surviving tracked panes, exact operator-parity XDG restore (absent = DELETED, not canonical defaults), the lifecycle cell-branch topology, and one shared helper consumed by both smokes
|
|
174
|
+
./run.sh check-typing-call-fence # deterministic gate for the boundary nobody has broken: this product composes ARGUMENTS and LETTERS, never keystrokes. Scans every tracked production source under pi-extensions/ and mcp/ — comments blanked, string literals kept — for tmux send-keys/paste-buffer/load-buffer and herdr's PTY verbs (agent.prompt, agent.send_keys, pane.send_text, pane.input.set). Prose is exempt on purpose: the sentence stating the rule names the very calls it forbids, and a scanner that read prose could be made green by deleting the law. Carries its own oracle — the detector is proven on planted code, proven blind to comments, and the scanned inventory is measured
|
|
173
175
|
./run.sh check-entwurf-v2-visible-resume # deterministic gate: S1 visible-resume COMPOSITION (entwurf-v2-visible-resume.ts) with every seam injected — the whole state machine incl. the timeout branch runs with no tmux/lock/socket/clock. Pins lock BEFORE liveness, identity under the lock and before any window (no-transcript citizen fails loud, opens nothing), live/indeterminate/address-conflict refused unlaunched, observation as a BOUNDED WAIT (measured: socket answers ~2–4s after launch, so one immediate probe would call a successful resume unobserved), exactly ONE launch on every path, timeout → lock released + window left open + nothing retried/killed, failed release throws, and the two receipts staying separate in type and text
|
|
174
176
|
./run.sh check-resume-launch-identity # deterministic gate for resume-launch-identity.ts, the record-authoritative launch-identity leaf preserved through the visible-first cut (spawn-bg and all its callers are gone; this leaf answers "which being is this, and which conversation is theirs"). Temp meta-store fixture: gardenId→record.transcriptPath happy path with header cwd/provider/model; C3 integrity (header id ≠ record.nativeSessionId → refused, never resumed); #52 ADDRESSABLE read (a gid that no longer holds its nativeSessionId alone is refused from EITHER side — the plain targeted read would resume one transcript twice under two locks); cause fidelity per impossible resume incl. the F7 pin (recorded-but-deleted transcript → MISSING, not "no recorded model"); header↔gate SSOT. No spawn/socket/timer
|
|
175
177
|
./run.sh smoke-entwurf-v2-matrix-live # LIVE sentinel (0.11 Stage 0 step 5d-5, D4-b) — OUT of pnpm check, needs LIVE=1. Drives REAL production runEntwurfV2 deps over REAL OS objects, 4 cells: C1 control-socket (real pi --entwurf-control resident → RPC send → lock acquire→release ×1), C1b record-less socket (#50 C4: live record-less pi → EVERY intent rejected pre-probe record-less-socket, no lock, rendered hint names record authority + fresh-cut), C2 meta-mailbox deliverable (armed self-fetch citizen → real .msg enqueue, lock-free), C3 meta-mailbox guard (no armed receiver → reject, no garbage). Model-in-loop OUT (transport/lock/enqueue gate, GPT Q2); negative/timeout stay deterministic. Model: ENTWURF_LIVE_TARGET=<provider>/<model> (default openai-codex/gpt-5.6-luna). LIVE=1 ./run.sh smoke-entwurf-v2-matrix-live
|
|
176
178
|
./run.sh smoke-agy-native-push-live # 봉인 8 LIVE acceptance for the native-push (agy) rail — OUT of pnpm check, needs LIVE=1 + AGY_CONVERSATION_ID (a live agy conversation). Drives the REAL antigravity adapter + register core + runEntwurfV2 (production deps): doctor-static preflight (dangling→FAIL, the ③ gate), probe route, register create/attach idempotency, fire→native-push delivered, post-send re-probe (D7 partial), bogus-conv→native-push-probe-indeterminate. Meta-store isolated to a temp dir (only the agy round-trip is real; no real-store residue). COST FENCE: open that agy conversation on gemini-3.6-flash (free account) — never a Pro tier; entwurf never selects the agy model and no assertion reads it. LIVE=1 AGY_CONVERSATION_ID=<convId> ./run.sh smoke-agy-native-push-live
|
|
177
179
|
./run.sh smoke-codex-native-push-live # on-demand LIVE acceptance for Codex native-push — needs LIVE=1 + CODEX_LIVE_THREAD_ID loaded by a visible TUI attached to the default app-server; probes the real UDS, routes through production runEntwurfV2, queues one exact-token turn without retry, re-probes, and leaves the visible TUI to show the model result
|
|
178
|
-
./run.sh smoke-codex-fresh-live # #95
|
|
180
|
+
./run.sh smoke-codex-fresh-live # #95 RELEASE MUST: record-backed receipt fixture -> PUBLIC initial Pi fresh/callback in a session S that is NOT the app-server's -> Pi PUBLIC omitted-placement Codex fresh/exact callback, also in S -> Pi-to-Codex addressed native-push v2 -> Codex PUBLIC omitted-placement AND omitted-cwd fresh Pi/exact callback IN S beside its own TUI (lane B claim: the app-server env names another session, so S can only come from the caller's pane title; lane C claim: no cwd was asked for, so the directory can only come from the Codex caller's own record — and the Codex thread's own rollout session_meta.cwd, its pane and its record must all be the requested scratch, not the app-server's repo) -> Codex final v2 evidence. Needs LIVE=1 + ENTWURF_CODEX_APP_SERVER_PID + ENTWURF_CODEX_FRESH_MODEL + ENTWURF_CODEX_FRESH_PI_MODEL, and its ONE stable launch directory answered 'Trust' once in a plain codex -C there: codex records its direct consent per exact directory, so a directory with no answer at all opens a consent screen instead of a first turn. Only THIS gate treats that as a precondition and fails up front as codex-launch-cwd-undecided rather than timing out on a callback — an ordinary entwurf_fresh_call only prints the note and opens the window, because a human can answer the screen. The smoke PRINTS that directory as 'launch-cwd <dir>' and repeats it in the failure as a ready-to-run repair command — do not retype it from memory, and do not write it as \$TMPDIR/... (os.tmpdir() falls back to /tmp when TMPDIR is unset, so that spelling names a different directory in the filesystem root). The PID names the operator-owned app-server, which must sit in a DIFFERENT session from S; the smoke checks/prints all four coordinates, never starts/stops/guesses the app-server/session, never reads screen text, interrupts only its exact still-running Codex turn, and cleans only receipt-named window ids
|
|
179
181
|
./run.sh smoke-mux-lifecycle-live # RELEASE MUST integrated LIVE lifecycle acceptance for mux, through the REAL MCP surface — OUT of pnpm check, needs LIVE=1 and spends model turns (two pi siblings: native + recorded-ACP provider, each resumed once; one Claude Code sibling). tools/call fresh_call -> nonce callback sender envelope -> v2 control send landing in the sibling's own transcript -> resume_call REFUSED while live (window count unchanged) -> stable-handle close (pane gone, socket dead, record kept) -> dormant delivery refused honestly -> public entwurf_resume_call with LAUNCH and OBSERVATION receipts kept apart, same-gid socket alive, zero new citizens, zero lock residue, resumed pane_start_path == RECORD cwd (separate tmux query), transcript byte-identical across the resume -> v2 recall of the pre-close fact. claude-code resume refused target-not-pi, no window opened and no lock residue. LIVE=1 ./run.sh smoke-mux-lifecycle-live
|
|
180
182
|
./run.sh check-entwurf-facts # deterministic gate (0.11 Stage 0 step 4, fact-provider slice 1+2): PURE PeerFact core + resolveFactList union — R1 out-of-domain→unsupported, R3b socket-domain 4-value, facts-only keyset; union: PeerFact + RecordLessSocketFact by gardenId (#50 C4: record-less socket = diagnostic subject, gid+liveness only), dormant→dead, F3 indeterminate preserved, out-of-socket-domain+socket fail-loud; pure, no IO
|
|
181
183
|
./run.sh check-socket-discovery # deterministic gate (0.11 Stage 0 step 4, fact-provider slice 3): SOCKET-axis scanSocketProbes — probes (dir sockets) ∪ (in-domain citizen canonical paths) 3-valued; dormant citizen no-file → dead (resumable, not unprobed), stall → indeterminate (F3), dir hygiene/dedup/missing-dir + e2e → resolveFactList; readdir/probe injected, no IO
|
|
182
184
|
./run.sh check-meta-facts # deterministic gate for the meta-facts projection (#65): drives the REAL CLI — full-record join, parse-before-uniqueness, no-winner duplicates, drift/symlink/invalid-UTF-8 defects in-band, deterministic bytes, exit contract 0/2/3, dispatch+emit reachability
|
|
185
|
+
./run.sh check-herdr-plugin # deterministic gate for the #116 M2-b herdr plugin (`plugins/herdr/`): STATIC manifest shape for herdr 0.9.0 + the forbidden sections ([[startup]]/[[events]]/[[actions]]/[[link_handlers]]) asserted absent ([[build]] is check-herdr-plugin-build's subject since #116 M3-b3); BEHAVIOURAL drive of the REAL pane entry against a stub `entwurf` and stub HERDR_BIN_PATH that LOG every call — exactly one peer-facts + one agent list per open (counted, not claimed), skip-by-name when Entwurf is absent, four distinct named refusals instead of an empty table, ambiguous never first-wins, diagnostics shown, activity in its own column, and zero writes to the plugin state/config dirs. No herdr binary, no Entwurf install
|
|
186
|
+
./run.sh check-herdr-runtime-bootstrap # deterministic gate for the #116 M3-b1 runtime leaf (`plugins/herdr/lib/runtime-bootstrap.mjs`): the Entwurf-owned stable active root as a REAL directory (nothing is put on PATH — the scoped wiring above names ABSOLUTE commands under it), ownership decided BEFORE the first mkdir, disk facts from lstat (a dangling symlink is not 'absent' and a link into another tree is not a directory), exact name@version + compiled entry + all three required bins present AND executable + a real `check-bridge`, the plugin-owned artifact lock coherent with the checkout, the owned npm cache and --ignore-scripts, a CERTIFIED journal (non-object/array/scalar/blank-identity/phase-contradicting-digest all refused) as the only ownership proof, all EIGHT active/staging/previous combinations named, the last good runtime never lost (torn swap AND corrupt-active beside a good backup), prior provenance carried across an install that may not finish, a failed candidate leaving the running runtime byte-identical, idempotent same-spec reinstall, a journal believed only while the disk backs it, a preflight-then-mutate inverse taking runtime last, and the refusal to record Herdr's commit as ours. NETWORK ZERO, npm ZERO — it drives a FIXTURE package, so the ACTUAL package proof lives in check-pack-install
|
|
187
|
+
./run.sh check-herdr-activation # deterministic gate for the #116 M3-b2 scoped activation: the pi user-scope-ONLY forward seam (no project write, OpenCode byte-untouched), the absolute command DERIVED from the runtime root for BOTH harnesses (relative/unnormalised refused), default bare/clone bytes unchanged when no mode is asked, the pi inverse refusing a drifted command instead of deleting an override, a certified activation ledger that can never name an atom outside {pi, claude-code}, add-only reinstall (a shrinking H retains, never removes), a roots-drift refusal before the first byte, the teardown order components->runtime->ledger LAST, one refused preflight leaving every byte untouched, and no deferred module load on the path that deletes its own runtime. Drives the REAL pi writers; the vendor `claude` CLI is NOT invoked and its acceptance of an absolute executable stays a named LIVE boundary
|
|
188
|
+
./run.sh check-herdr-plugin-profile # deterministic gate for the #116 M3-a PURE activation leaf (`plugins/herdr/lib/integration-profile.mjs`): the closed {pi→pi, claude→claude-code} table, exactly-one-row-or-named-refusal, the FRONT-ANCHORED state grammar (a `/srv/current (v9)/` directory name may not decide a verdict), no path in the plan, outdated/needs-repair as named FAILs, not-installed as a zero-write SKIP, `current` as herdr's admission with no floor of our own, OpenCode observed but never planned, and the leaf's purity. Listing strings only — no herdr binary, no install, no environment, no writes
|
|
189
|
+
./run.sh check-herdr-plugin-build # deterministic gate for the #116 M3-b3 build runner (`plugins/herdr/lib/build.mjs`): the ONE command Herdr's [[build]] calls, composing integration status -> pure profile -> runtime bootstrap -> activation THROUGH THE INSTALLED PACKAGE (never this checkout, which herdr deletes on uninstall with no cleanup hook). Pins one [[build]] with argv `node lib/build.mjs` and a runner npm does not ship, missing-herdr vs unanswerable-status as separate named refusals, a selected outdated/needs-repair/malformed/duplicate atom failing BEFORE any runtime work, A-empty as exit 0 with ZERO writes, absent/incapable activation entries as distinct refusals, the two-stage {pi} -> {pi, claude-code} composition with OpenCode never named, and the post-build herdr commit gap named rather than called atomic. Listing via the runner's own spawn seam (no fake herdr); one cell drives the REAL binary, named SKIP without it
|
|
190
|
+
./run.sh check-peer-facts # deterministic gate for the peer-facts projection (#116 M2-a): drives the REAL CLI with every ambient root sandboxed — placement crosses STRUCTURED (never the human `herdr <pane>` string), the peer keyset is exactly the provider's facts (no herdr agent_status may enter an entwurf payload), no socket coordinate is published (#50 C4), diagnostics in-band, the probed socket world is the one ENTWURF_DIR names (proved by a record-less socket surfacing — there is no field to echo), no observation budget, exit contract 0/2/3, dispatch+emit reachability. No herdr binary
|
|
183
191
|
./run.sh check-meta-listing # deterministic gate: META-STORE facts axis — kind-carrying entries; non-regular records are never read, parse/drift become diagnostics, duplicate nativeSessionId quarantines every rival but not unrelated citizens; strict throws / collect partial; pure injected IO
|
|
184
192
|
./run.sh check-entwurf-fact-provider # deterministic gate (0.11 Stage 0 step 4, fact-provider slice 4b): ASSEMBLY listEntwurfFacts — full-store parse/probe/quarantine/resolve stays intact; #112 bounds expensive receiver/transcript observation to the newest 32 rendered rows while older machine rows say unobserved; Q112 pins full payload + exact observer budget; C-원칙 keeps corruption diagnostic and impossible wiring loud; deps injected, no IO
|
|
193
|
+
./run.sh check-herdr-placement # deterministic gate (#116 S1): the PURE placement-evidence axis — herdr `pane list` parse (unreadable payload → null → `unobserved`, never `none`), the two measured join rules (claude kind=id byte equality / pi kind=path uuid tail of a .jsonl basename, both strict), unmeasured kind → NO key, two panes on one key → `ambiguous` (never last-write-wins), provider reads the placement owner EXACTLY ONCE per listing (anti-watcher, docs/mux-launch-rail.md §7), and no entwurf_v2 dispatch module names or imports the axis (Hard Rule 16 — a pane is a view, not a rail). No fake herdr, no binary, no IO
|
|
185
194
|
./run.sh check-entwurf-peers-surface # deterministic gate (0.11 Stage 0 step 4, fact-provider slice 4c): MCP entwurf_peers RENDER renderEntwurfPeers (#50 C4) — payload keyset exactly {peers, diagnostics}; FORBIDDEN keys sessions/socketOnly/controlDir/socketPath/count + no .sock in text (socket is transport, never identity); record-less socket = aggregated record-less-socket diagnostic (F8, liveness-keyed message, alive names fresh-cut); NO verb-routing key (JSON deep scan) NOR word (text), diagnostics both surfaces, empty→(none), unsupported shown; WIRING guard: both surfaces call provider+render, getLiveSessions + /entwurf-sessions gone; facts fabricated, no IO
|
|
186
195
|
./run.sh check-entwurf-self-address # deterministic gate (SE-1/SE-2 slice 1): self-addressability honesty predicate computeSelfAddressability — pi replyable ⟺ live socket; meta splits by RAIL: self-fetch ⟺ recordBacked ∧ ownerAlive ∧ watchArmed (regression-proof record-present rows), native-push ⟺ recordBacked ∧ probeAlive (separate axis — no mailbox fact may rescue or sink it), unsupplied rail fail-closed; SOURCE GUARD buildStrictPiSenderEnvelope drops hardcoded replyable:true + existsSync-probes socket, entwurf_self renders alive vs expected AND renders the meta rail per-rail (mailbox only inside the self-fetch branch; native-push denies an inbox and gates injection on the probe)
|
|
187
196
|
./run.sh check-entwurf-deliverability # deterministic gate (SE-1/SE-2 slice 2c): conversational-mailbox deliverability predicate — computeMetaReceiverActive (recordBacked ∧ ownerAlive ∧ watchArmed) + mailboxConversationalDeliverable (self-fetch AND active); direct-inject pi refused (SE-1), self-fetch dead/unarmed refused (SE-2); self-address shares the same atom
|
|
@@ -250,15 +259,20 @@ Usage:
|
|
|
250
259
|
./run.sh uninstall-agy-bridge # 봉인 7: honest inverse of install-agy-bridge from install-state (restore preimage / remove key; refuse if config became a symlink)
|
|
251
260
|
./run.sh probe-bridge-command <cmd> [args...] # #81: BOOT the given bridge invocation and require the entwurf MCP tool surface back. `--invocation-json '{"command":"…","args":[],"env":{}}'` preserves a harness config exactly. It waits for a valid initialize response, then sends initialized + tools/list only (no tools/call, lock, record, or delivery). exit 0 = it serves the bridge; 1 = it does not. The pi/agy doctors use this leaf.
|
|
252
261
|
./run.sh doctor-agy-bridge # fail-loud doctor: MCP config + exact permission rule + state + live probe label
|
|
253
|
-
./run.sh install-codex-birth # publish $CODEX_HOME/hooks.json + the helper closure; no root, and the operator trusts the declaration once in their own Codex
|
|
254
|
-
./run.sh uninstall-codex-birth # exact inverse from the install-state digest inventory; refuses drifted bytes instead of deleting them
|
|
255
|
-
./run.sh doctor-codex-birth # RUNTIME + UNIT bytes/ownership + the vendor TRUST receipt
|
|
262
|
+
./run.sh install-codex-birth # publish ONE SessionStart declaration inside $CODEX_HOME/hooks.json (a file it shares) + the helper closure; no root, and the operator trusts the declaration once in their own Codex
|
|
263
|
+
./run.sh uninstall-codex-birth # exact inverse from the install-state digest inventory; removes only entwurf's own declaration (foreign groups byte-for-byte) and refuses drifted bytes instead of deleting them
|
|
264
|
+
./run.sh doctor-codex-birth # RUNTIME + UNIT bytes/ownership + FOREIGN neighbours (reported, never certified) + the vendor TRUST receipt at this declaration's measured index (--unit-only skips the receipt; sandboxes only)
|
|
256
265
|
./run.sh install-codex-mcp # own only [mcp_servers.entwurf-bridge] in the user's Codex config
|
|
257
266
|
./run.sh uninstall-codex-mcp # remove/restore only the recorded MCP atom
|
|
258
267
|
./run.sh doctor-codex-mcp # effective config + ownership + actual bridge boot
|
|
259
268
|
./run.sh install-codex-statusline # add thread-title to tui.status_line for visible garden ids
|
|
260
269
|
./run.sh uninstall-codex-statusline # remove only the recorded status-line atom
|
|
261
270
|
./run.sh doctor-codex-statusline # effective visible-identity config + ownership verdict
|
|
271
|
+
./run.sh install-codex-terminal-title # add thread-id to tui.terminal_title so the multiplexer reports the caller's thread in #{pane_title} (#95 placement input, never an address)
|
|
272
|
+
./run.sh uninstall-codex-terminal-title # remove only the recorded terminal-title atom
|
|
273
|
+
./run.sh doctor-codex-terminal-title # effective caller-seat config + ownership verdict
|
|
274
|
+
./run.sh codex-socket-path # #95 INTERNAL (the launcher asks this; you do not need it): print the Codex app-server default control-socket path for this environment, from the SAME resolver delivery and preflight read
|
|
275
|
+
./run.sh codex-app-server [args...] # #95: the ONE COMMAND that starts the operator's Codex app-server. exec()s `codex app-server --listen "unix://$CODEX_HOME/app-server-control/app-server-control.sock"` in THIS terminal (cwd/pid/exit are the vendor's, Ctrl-C is yours) — entwurf owns the SPELLING of that address, never the process's lifecycle: no supervisor, no restart, no daemon, no pid file. It does no path arithmetic: the address comes from `codex-socket-path`, the one leaf every other Codex surface reads, and a resolved address that is not absolute or carries a control character is refused before anything is created. Your arguments are forwarded byte-identical after it; a second --listen is refused by name. Refuses on a live socket (names the /proc owner it can read) or an indeterminate one, and reports which tmux server this seat gives caller-seat lookups. Run it in a DETACHED tmux session other than the one you work in
|
|
262
276
|
./run.sh install-agy-statusline # own the agy statusLine subtree with bare entwurf-agy-statusline; preserve unrelated settings
|
|
263
277
|
./run.sh uninstall-agy-statusline # honest inverse from statusline install-state
|
|
264
278
|
./run.sh doctor-agy-statusline # fail-loud statusLine config/bin/state doctor + honest live SKIP
|
|
@@ -268,6 +282,7 @@ Usage:
|
|
|
268
282
|
./run.sh meta-bridge-prune # 1.0.0 meta-bridge Phase 4: LISTING-ONLY store hygiene — classify orphan/stale/ambiguous/keep, print manual rm commands, delete NOTHING ([dir] [--ttl-days N])
|
|
269
283
|
./run.sh meta-bridge-fresh-cut # the ONE generation verb (the verb every v3-only rejection names): quiesce-check live sockets/markers/native-push conversations (refusing any surface it cannot inspect), archive meta-sessions/ + meta-mailbox/ to `<dir>.archive-<ts>`, clear dead transport residue, open an empty v3 generation. No migration, no restore — the archive is forensic only. EXIT CONTRACT (#54, `--help` prints it): 0 complete / 1 NOTHING MOVED (re-run, do not setup) / 2 usage / 3 cut transition incomplete (inspect) / 4 cut complete but residue cleanup failed (`setup` may run; re-run only before new citizen birth, otherwise remove residue manually)
|
|
270
284
|
./run.sh meta-facts # #65 owner-normalized READ-ONLY store projection: deterministic JSON {schemaVersion:1, storeDir, citizens: full v3 records sorted by gardenId, defects: {filename,message}} — THE listing contract emitted by the owner so consumers stop copying the certification. No liveness/sockets/transcript contents. EXIT: 0 readable (defects in-band; missing store = empty), 2 usage, 3 unreadable ([dir])
|
|
285
|
+
./run.sh peer-facts # #116 M2-a owner-normalized READ-ONLY peer projection: the same listEntwurfFacts provider through the same renderer entwurf_peers uses, emitted as deterministic JSON {schemaVersion:1, storeDir, peers, diagnostics} so a consumer never re-implements the placement join (whose pi half is a measured vendor floor). NOT the same bytes as an entwurf_peers call and deliberately so: that surface is a human listing (observationLimit, text over the wire), this is a machine projection with UNBOUNDED observation, because a rationed row says `unobserved` and a machine cannot tell that from "nobody could look". `placement` stays a STRUCTURED tagged union ({kind:"herdr-pane",paneId} / unobserved / none / ambiguous) — never the human `herdr <pane>` string. Publishes NO socket coordinate (ENTWURF_DIR selects what is PROBED, #50 C4) and NO herdr agent_status / interactive_ready / screen text. One placement read per listing, no watcher. EXIT: 0 readable (diagnostics in-band; missing store = empty), 2 usage, 3 unreadable ([dir])
|
|
271
286
|
./run.sh meta-bridge-managed-keys # 0.10.0 meta-bridge: print the SSOT of settings keys entwurf OWNS (consumers read this to stay disjoint — keyset-owner invariant)
|
|
272
287
|
./run.sh check-keyset-overlap <fragment.json...> # 0.10.0 meta-bridge: PREVENTIVE keyset guard — fail if a consumer fragment collides with any pi-owned key (cross-repo; not in pnpm check)
|
|
273
288
|
./run.sh check-dep-versions # local deterministic check that the pi pin agrees across package.json (devDeps + peer range), run.sh (peer-install pins), and the baseline docs (AGENTS/README/ROADMAP/setup-clean-host/demo)
|
|
@@ -275,10 +290,13 @@ Usage:
|
|
|
275
290
|
./run.sh check-pack # publish gate (dry-run): npm pack --dry-run + tarball invariants (runtime-critical present, dev residue absent)
|
|
276
291
|
./run.sh check-pack-pin-matcher # pure self-test of check-pack-install's pin-leak matcher against synthetic .pnpm lookalikes, one cell per property: version boundary (@0.85.10 must leak, @0.85.1 bare or with either measured peer-hash must pass) and closure prefix (an off-pin @earendil-works/chord must leak — it carries no `pi-` prefix); snapshot-safe qualification oracle, also run first inside check-pack-install
|
|
277
292
|
./run.sh check-fresh-cut-gate # SOURCE cell of the generation-boundary proof (IN pnpm run check:full): drives real install/setup/fresh-cut in a sandbox; certification refusal is pre-write, quiescence is fail-closed, archives preserve bytes, and the #54 exit matrix distinguishes complete / no-move / usage / incomplete transition / complete-with-cleanup-residue. No model/network/cost
|
|
278
|
-
./run.sh check-pack-install # heavy publish gate (prepublishOnly): actual npm pack + tar -tf + fresh-temp install smoke with the pinned pi peers (pins derived from the package.json devDep; check-dep-versions binds them) + the npm-installed bridge BOOTS (tools/list) and DELIVERS (tools/call entwurf_v2 → .msg lands) + the installed all-absent and copilot-present (four-unit fake-vendor) `entwurf setup` rows + the INSTALLED generation lifecycle on a seeded previous-generation host (REFUSE before activation writes / zero Claude invocations → installed fresh-cut archives + opens empty → install-meta-bridge PASSES) + the INSTALLED-PACKAGE branch of the Copilot and OMP birth installers actually RUN (compiled entry selected, no raw .ts, and a real birth edge mints a citizen — the half a required-artifact list can never stand in for)
|
|
293
|
+
./run.sh check-pack-install # heavy publish gate (prepublishOnly): actual npm pack + tar -tf + fresh-temp install smoke + the #116 M3-b1 herdr-plugin RUNTIME VERIFIER run against that actual installed tarball (the focused check-herdr-runtime-bootstrap drives a fixture; THIS is where the real package is proven) with the pinned pi peers (pins derived from the package.json devDep; check-dep-versions binds them) + the npm-installed bridge BOOTS (tools/list) and DELIVERS (tools/call entwurf_v2 → .msg lands) + the installed all-absent and copilot-present (four-unit fake-vendor) `entwurf setup` rows + the INSTALLED generation lifecycle on a seeded previous-generation host (REFUSE before activation writes / zero Claude invocations → installed fresh-cut archives + opens empty → install-meta-bridge PASSES) + the INSTALLED-PACKAGE branch of the Copilot and OMP birth installers actually RUN (compiled entry selected, no raw .ts, and a real birth edge mints a citizen — the half a required-artifact list can never stand in for)
|
|
279
294
|
./run.sh check-install-container # 0.12.8 (#51 C): Linux artifact-CONSUMER gate — one candidate .tgz handed read-only to a checkout-invisible node:<engines-major>-bookworm cell. Default packs once to temp; ENTWURF_CANDIDATE_TGZ=/absolute/preserved.tgz consumes those exact bytes with no re-pack and prints canonical path+sha256 for release. Non-root global PATH install, frozen package, MCP tools/list, fake-Claude install-meta-bridge, path+sha256 fence, strict doctor, and the GENERATION host-state matrix (clean / v3-only store bytes unchanged / previous-generation REFUSE→fresh-cut→retry PASS) seeded inline. Docker missing = honest SKIP; ENTWURF_REQUIRE_DOCKER=1 makes that RED (required CI)
|
|
280
295
|
./run.sh install [project-dir] # INTERNAL part of `setup` (project .pi/settings.json wiring) + npm-consumer entry — prefer `setup`, don't call directly for dev
|
|
281
296
|
./run.sh remove [project-dir] # remove entwurf entries from project .pi/settings.json (project scope only; global user-scope citizen left intact)
|
|
297
|
+
./run.sh install-user-scope [--plugin-runtime <root>] # #116 M3-b2 PLUGIN-ONLY forward seam: compose ONLY the global pi citizen (user-scope packages[] + provider), never a project `.pi/settings.json` — a Herdr plugin activation has no project and must not invent one. With --plugin-runtime the provider's managed command becomes the absolute bridge under that certified stable runtime (a clean host has nothing entwurf on PATH); without it every byte is the historical bare-bin install. Inverse: remove-user-scope
|
|
298
|
+
./run.sh herdr-plugin-activate <backend...> # #116 M3-b2 public forward activation. Takes a subset of {pi, claude-code} and NOTHING else — the stable runtime root is DERIVED from XDG here and handed down, and both harness writers accept a named root only when it IS that derived one. Certifies the runtime-ready journal AND the installed tree, certifies the existing ledger and its recorded harness roots, plans ADD-ONLY (a backend absent from this request is retained, never removed), preflights every selected component before the first byte, then writes each component `pending` BEFORE mutating and checkpoints `active` the moment its writer returns — so a run that dies halfway leaves a record of how far it got. Which backends is M3-b3's question: this verb is handed the answer, it does not read Herdr's integration status
|
|
299
|
+
./run.sh herdr-plugin-deactivate # #116 M3-b2 public teardown of a Herdr-plugin activation. Herdr's `plugin uninstall` deletes its checkout and calls NO cleanup hook, so the harness wiring and the stable runtime are retained, not cleaned — this is the shipped verb that takes them back. Certifies the activation ledger, the resolved Pi/Claude roots and BOTH component inverses read-only first; mutates only when every preflight is green; then Claude -> Pi user scope -> runtime -> ledger LAST. A component failure stops with the runtime and ledger intact as retry authority. Static imports only: the process deletes the runtime it is running from, and a lazy import after that fails
|
|
282
300
|
./run.sh remove-user-scope # explicit GLOBAL inverse of install's user-scope citizen: drop entwurf from ~/.pi/agent/settings.json packages[] (affects ALL cwds — shared entry, not per-project). #86 C2: same-owner-only — a LIVE foreign owner refuses; a MISSING owner is removed only when package entry + package state + provider installerRoot all align (reported orphan cleanup)
|
|
283
301
|
./run.sh takeover-user-scope # #86 C2: operator-EXPLICIT ownership move of the shared user-scope registration to THIS root (old→new reported, packages[] entry + provider installerRoot together). The only writer over another owner — normal install/setup/remove refuse instead. No --force exists
|
|
284
302
|
./run.sh doctor-pi-package # #86 C2: package-side user-scope ownership verdict — unregistered / owned / owned-by-other(live) / legacy-no-state / mismatch / missing-owner (nonzero on defect verdicts). Provider runtime verdicts stay with doctor-pi-provider
|
|
@@ -604,6 +622,7 @@ _codex_home() { echo "${CODEX_HOME:-$HOME/.codex}"; }
|
|
|
604
622
|
_codex_config() { echo "$(_codex_home)/config.toml"; }
|
|
605
623
|
_codex_mcp_state() { echo "${XDG_DATA_HOME:-$HOME/.local/share}/entwurf/codex-mcp/install-state.json"; }
|
|
606
624
|
_codex_statusline_state() { echo "${XDG_DATA_HOME:-$HOME/.local/share}/entwurf/codex-statusline/install-state.json"; }
|
|
625
|
+
_codex_terminal_title_state() { echo "${XDG_DATA_HOME:-$HOME/.local/share}/entwurf/codex-terminal-title/install-state.json"; }
|
|
607
626
|
|
|
608
627
|
codex_mcp() {
|
|
609
628
|
local verb="$1" config state
|
|
@@ -632,8 +651,32 @@ codex_statusline() {
|
|
|
632
651
|
esac
|
|
633
652
|
}
|
|
634
653
|
|
|
654
|
+
# #95 lane B: the SECOND visible-identity atom, and a different axis from the
|
|
655
|
+
# status line. `status_line`'s thread-title is what a HUMAN reads in the TUI;
|
|
656
|
+
# `terminal_title`'s thread-id is what the MULTIPLEXER reports back as
|
|
657
|
+
# `#{pane_title}`, which is the only value a Codex caller's `_meta.threadId`
|
|
658
|
+
# can be matched against to find the pane it is sitting in. Placement input
|
|
659
|
+
# only — never an address, delivery or liveness fact.
|
|
660
|
+
codex_terminal_title() {
|
|
661
|
+
local verb="$1" config state
|
|
662
|
+
config="$(_codex_config)"
|
|
663
|
+
state="$(_codex_terminal_title_state)"
|
|
664
|
+
case "$verb" in
|
|
665
|
+
install) python3 "$REPO_DIR/scripts/codex-terminal-title-config.py" install "$config" "$state" ;;
|
|
666
|
+
uninstall) python3 "$REPO_DIR/scripts/codex-terminal-title-config.py" uninstall "$state" ;;
|
|
667
|
+
doctor) python3 "$REPO_DIR/scripts/codex-terminal-title-config.py" doctor-static "$config" "$state" ;;
|
|
668
|
+
esac
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
# $1 (optional): a certified stable plugin runtime root. Given, the provider half is written in
|
|
672
|
+
# PLUGIN MODE — its managed command becomes the absolute bridge under that root instead of the bare
|
|
673
|
+
# bin. That is the whole difference, and it exists because a Herdr plugin activates on a host where
|
|
674
|
+
# nothing entwurf is on PATH, so a bare command cannot resolve. Absent, every byte is what it has
|
|
675
|
+
# always been (#116 M3-b2).
|
|
635
676
|
register_user_scope_citizen() {
|
|
636
677
|
local agent_dir="${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}"
|
|
678
|
+
local plugin_mode=()
|
|
679
|
+
[ -n "${1:-}" ] && plugin_mode=(--plugin-runtime "$1")
|
|
637
680
|
# Shared idempotent implementation (also driven by smoke-user-scope-citizen).
|
|
638
681
|
# #86 C2: user scope carries a recorded OWNER (packageRoot in the pi-package
|
|
639
682
|
# install-state). Another owner — live or missing — makes this a zero-write
|
|
@@ -646,7 +689,7 @@ register_user_scope_citizen() {
|
|
|
646
689
|
python3 "$REPO_DIR/scripts/register-pi-package.py" "$agent_dir/settings.json" "$REPO_DIR" \
|
|
647
690
|
--scope user --state "$(_pi_package_state)" --preflight >/dev/null
|
|
648
691
|
python3 "$REPO_DIR/scripts/register-pi-provider.py" install "$agent_dir/settings.json" "$REPO_DIR" \
|
|
649
|
-
--scope user --state "$(_pi_provider_state)" --preflight >/dev/null
|
|
692
|
+
--scope user --state "$(_pi_provider_state)" ${plugin_mode[@]+"${plugin_mode[@]}"} --preflight >/dev/null
|
|
650
693
|
python3 "$REPO_DIR/scripts/register-pi-package.py" "$agent_dir/settings.json" "$REPO_DIR" \
|
|
651
694
|
--scope user --state "$(_pi_package_state)"
|
|
652
695
|
# #46 Task 2: own entwurfProvider.mcpServers.entwurf-bridge as the bare stable bin at USER scope
|
|
@@ -655,7 +698,33 @@ register_user_scope_citizen() {
|
|
|
655
698
|
# local and covered by `run.sh remove` (no state) — deliberate, reasoned asymmetry.
|
|
656
699
|
# #86 C2: the provider state records installerRoot, so the same foreign-owner refusal
|
|
657
700
|
# holds here — and the package refusal above fires FIRST, before any provider write.
|
|
658
|
-
python3 "$REPO_DIR/scripts/register-pi-provider.py" install "$agent_dir/settings.json" "$REPO_DIR" --scope user --state "$(_pi_provider_state)"
|
|
701
|
+
python3 "$REPO_DIR/scripts/register-pi-provider.py" install "$agent_dir/settings.json" "$REPO_DIR" --scope user --state "$(_pi_provider_state)" ${plugin_mode[@]+"${plugin_mode[@]}"}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
# install-user-scope — the PLUGIN-ONLY forward seam (#116 M3-b2). Generic `install` writes both a
|
|
705
|
+
# project `.pi/settings.json` and the global user-scope citizen; a Herdr plugin activation has no
|
|
706
|
+
# project and must not invent one, so this verb composes the user-scope half and nothing else. Its
|
|
707
|
+
# inverse is the one that already existed, `remove-user-scope` — the asymmetry this closes is that
|
|
708
|
+
# the inverse was public and the forward was not.
|
|
709
|
+
install_user_scope() {
|
|
710
|
+
command -v python3 >/dev/null 2>&1 || { echo "[install-user-scope] requires python3 on PATH; nothing was written." >&2; exit 1; }
|
|
711
|
+
local plugin_runtime=""
|
|
712
|
+
while [ $# -gt 0 ]; do
|
|
713
|
+
case "$1" in
|
|
714
|
+
--plugin-runtime)
|
|
715
|
+
shift
|
|
716
|
+
# A flag with no value must not fall through to bare mode: the caller asked for the plugin
|
|
717
|
+
# runtime and would otherwise be told, silently, that it got it.
|
|
718
|
+
[ -n "${1:-}" ] || { echo "run.sh install-user-scope: --plugin-runtime requires a value" >&2; exit 2; }
|
|
719
|
+
plugin_runtime="$1" ;;
|
|
720
|
+
*) echo "usage: run.sh install-user-scope [--plugin-runtime <stable active root>]" >&2; exit 2 ;;
|
|
721
|
+
esac
|
|
722
|
+
shift
|
|
723
|
+
done
|
|
724
|
+
preflight_v3_store install-user-scope
|
|
725
|
+
section "install-user-scope: the GLOBAL pi citizen only (no project wiring)"
|
|
726
|
+
register_user_scope_citizen "$plugin_runtime"
|
|
727
|
+
ok "install-user-scope: user-scope packages[] + provider registered${plugin_runtime:+ (plugin runtime: $plugin_runtime)}"
|
|
659
728
|
}
|
|
660
729
|
|
|
661
730
|
# takeover-user-scope — the operator-explicit ownership move (#86 C2). The ONLY
|
|
@@ -1026,6 +1095,14 @@ check_copilot_launch() {
|
|
|
1026
1095
|
run_ts scripts/check-copilot-launch.ts
|
|
1027
1096
|
}
|
|
1028
1097
|
|
|
1098
|
+
check_codex_app_server_launch() {
|
|
1099
|
+
# #95: the managed app-server SPELLING, proved against a fake vendor. There is no second
|
|
1100
|
+
# spelling of the address to compare any more — the launcher asks `codex-socket-path` — so
|
|
1101
|
+
# these cells are a WIRING oracle, and they carry the hostile inputs a transcription was
|
|
1102
|
+
# measured to diverge on so that re-deriving the path here goes red rather than passing.
|
|
1103
|
+
run_ts scripts/check-codex-app-server-launch.ts
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1029
1106
|
check_copilot_receive_arm() {
|
|
1030
1107
|
# #82 RAIL 5 gate: drives the REAL receiver installer into a temp extensions dir, then
|
|
1031
1108
|
# forks the REAL extension.mjs with the SDK specifier resolved by a loader hook (the
|
|
@@ -1317,6 +1394,17 @@ check_mux_launcher_fence() {
|
|
|
1317
1394
|
run_ts scripts/check-mux-launcher-fence.ts
|
|
1318
1395
|
}
|
|
1319
1396
|
|
|
1397
|
+
check_typing_call_fence() {
|
|
1398
|
+
# The rule kept since day one, now kept by NAME: entwurf composes arguments and letters, never
|
|
1399
|
+
# keystrokes. An outside reader measured the tree on 2026-09-17 and found the law perfectly kept
|
|
1400
|
+
# and nothing keeping it — zero typing calls in pi-extensions/, zero checks and zero mutants that
|
|
1401
|
+
# would notice one arriving. Scans tracked production sources under pi-extensions/ and mcp/ with
|
|
1402
|
+
# comments blanked and string literals kept, because a typing call spelled as a string is the
|
|
1403
|
+
# call. Comment exemption is load-bearing: the sentence that states the rule contains the names
|
|
1404
|
+
# the rule forbids. Offline, no binaries, no fixtures on disk.
|
|
1405
|
+
run_ts scripts/check-typing-call-fence.ts
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1320
1408
|
check_mux_parent_artifact() {
|
|
1321
1409
|
# Deterministic gate for the tracked scrubbed parent-transcript fixture
|
|
1322
1410
|
# (scripts/fixtures/mux-parent-transcript.scrubbed.jsonl). The fixture is a version-pinned
|
|
@@ -1414,7 +1502,10 @@ check_mux_fresh_call() {
|
|
|
1414
1502
|
# tmux-coordinate-row rides here because it is the parse every tmux COORDINATE in this lane's
|
|
1415
1503
|
# LIVE siblings depends on, and because it is the only half of a measured LIVE failure that a
|
|
1416
1504
|
# deterministic gate can own: the row is the input, so no tmux and no model turn is needed.
|
|
1417
|
-
|
|
1505
|
+
# codex-caller-seat rides here for the same reason as the two preflights: the leaf exists
|
|
1506
|
+
# only as freshCall's Codex placement input (#95 lane B), so certifying it apart from the
|
|
1507
|
+
# composition it feeds would let the two halves of one seat decision drift.
|
|
1508
|
+
run_vitest test/mux-fresh-call.test.ts test/fresh-call-composition.contract.test.ts test/copilot-fresh-preflight.test.ts test/codex-fresh-preflight.test.ts test/fresh-call-surfaces.contract.test.ts test/fresh-call-provider.contract.test.ts test/omp-fresh-bootstrap.contract.test.ts test/tmux-coordinate-row.test.ts test/codex-fresh-live-protocol.test.ts test/codex-caller-seat.test.ts
|
|
1418
1509
|
}
|
|
1419
1510
|
|
|
1420
1511
|
smoke_mux_fresh_call_live() {
|
|
@@ -1771,6 +1862,117 @@ check_meta_facts() {
|
|
|
1771
1862
|
run_ts scripts/check-meta-facts.ts
|
|
1772
1863
|
}
|
|
1773
1864
|
|
|
1865
|
+
check_herdr_plugin() {
|
|
1866
|
+
# Deterministic gate for the #116 M2-b herdr plugin (`plugins/herdr/`). Two halves.
|
|
1867
|
+
# STATIC: the manifest is parsed with the package's own TOML reader and held to the
|
|
1868
|
+
# shape herdr 0.9.0 accepts (min_herdr_version required + semver, dot-free pane id,
|
|
1869
|
+
# popup-only sizing, argv arrays), and the ABSENT sections are asserted as hard as the
|
|
1870
|
+
# present ones — [[startup]]/[[events]] are where a watcher would grow, [[actions]]
|
|
1871
|
+
# would send a report nobody can read into a 64 KiB log. ([[build]] LEFT that list in
|
|
1872
|
+
# #116 M3-b3; the one runner it may call is check-herdr-plugin-build's subject.)
|
|
1873
|
+
# BEHAVIOURAL: the REAL pane entry is
|
|
1874
|
+
# spawned with a stub `entwurf` and a stub HERDR_BIN_PATH that log every call, so
|
|
1875
|
+
# "exactly one read each per open" is COUNTED; success, skip-by-name, four distinct
|
|
1876
|
+
# named refusals, the ambiguous pane, diagnostics and the no-write claim are each
|
|
1877
|
+
# driven for real. The stub stands for the CONSUMER's input, never for herdr's
|
|
1878
|
+
# behaviour — no claim about herdr is made here, which is why this is not the fake
|
|
1879
|
+
# fixture check-herdr-sandbox forbids. No herdr binary, no Entwurf install, no writes
|
|
1880
|
+
# outside mkdtemp.
|
|
1881
|
+
run_ts scripts/check-herdr-plugin.ts
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
check_herdr_activation() {
|
|
1885
|
+
# Deterministic gate for the #116 M3-b2 scoped activation. The pi cells drive the REAL writers
|
|
1886
|
+
# (run.sh install-user-scope, register-pi-provider.py, remove-user-scope) against a sandboxed
|
|
1887
|
+
# HOME/XDG/PI_CODING_AGENT_DIR, so the bytes asserted are bytes those writers produced. The Claude
|
|
1888
|
+
# cells drive the REAL state owner's pure surfaces; the vendor `claude` CLI is NOT invoked and its
|
|
1889
|
+
# acceptance of an absolute executable stays a named LIVE boundary. The oracle for a roundtrip is
|
|
1890
|
+
# JSON equality plus unrelated-key survival, never byte equality: the pi settings writer preserves
|
|
1891
|
+
# semantics but may reindent (measured 2026-09-16). No network, no operator HOME.
|
|
1892
|
+
run_ts scripts/check-herdr-activation.ts
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
check_herdr_runtime_bootstrap() {
|
|
1896
|
+
# Deterministic gate for the #116 M3-b1 runtime transaction. Every root comes from XDG, so the
|
|
1897
|
+
# gate hands the module a mkdtemp HOME and asserts nothing appeared outside the two XDG roots it
|
|
1898
|
+
# was given. `acquire` is a FUNCTION seam: the fixture stands in for the REGISTRY, so this gate
|
|
1899
|
+
# proves the transaction (ownership certification, torn-swap recovery, leftover states, rollback,
|
|
1900
|
+
# idempotence, the inverse) but NOT that the real Entwurf package boots — that actual-package
|
|
1901
|
+
# proof is a named cell inside check-pack-install, which runs this module's own
|
|
1902
|
+
# verifyInstalledRuntime against the tarball it packed and installed. npm is pinned here the only
|
|
1903
|
+
# way a hermetic gate honestly can: the production pack/install argv and the npm environment are
|
|
1904
|
+
# pure functions and are asserted directly. No network, no npm, no operator HOME, no writes
|
|
1905
|
+
# outside mkdtemp.
|
|
1906
|
+
run_ts scripts/check-herdr-runtime-bootstrap.ts
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
check_herdr_plugin_profile() {
|
|
1910
|
+
# Deterministic gate for the #116 M3-a pure leaf: the function that turns ONE
|
|
1911
|
+
# `herdr integration status` listing into this plugin's activation plan. Every listing
|
|
1912
|
+
# is an INPUT STRING (verbatim herdr 0.9.0 rows measured 2026-09-16 in a sandboxed
|
|
1913
|
+
# HOME/XDG, plus the two forms cross-checked in herdr source at c77af189), so nothing
|
|
1914
|
+
# here claims a fact about herdr. Pins: the closed atom->backend table, exactly one row
|
|
1915
|
+
# per selected atom or a NAMED refusal (never a first/last-match guess), the state read
|
|
1916
|
+
# FRONT-ANCHORED so an operator's directory name cannot spell a verdict, the display
|
|
1917
|
+
# path leaving no trace in the plan, outdated/needs-repair as named FAILs (measured:
|
|
1918
|
+
# empty, unreadable and marker-less files all collapse into `outdated`), not-installed
|
|
1919
|
+
# as a zero-write SKIP, `current` as herdr's admission with no second floor invented
|
|
1920
|
+
# here, OpenCode observed but never planned, and the leaf's purity. No herdr binary, no
|
|
1921
|
+
# Entwurf install, no environment read, no writes.
|
|
1922
|
+
run_ts scripts/check-herdr-plugin-profile.ts
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
check_herdr_plugin_build() {
|
|
1926
|
+
# Deterministic gate for the #116 M3-b3 build runner (`plugins/herdr/lib/build.mjs`) — the ONE
|
|
1927
|
+
# command Herdr's `[[build]]` calls, and the order it composes: integration status -> pure
|
|
1928
|
+
# profile -> runtime bootstrap -> activation THROUGH THE INSTALLED PACKAGE. There is no fake
|
|
1929
|
+
# herdr binary here (the repo forbids one); the listing arrives through the runner's own spawn
|
|
1930
|
+
# seam as the prose shape 0.9.0 emits, and one cell drives the REAL binary with a named SKIP
|
|
1931
|
+
# when the host has none (ENTWURF_REQUIRE_HERDR=1 makes absence red). Pins: exactly one
|
|
1932
|
+
# [[build]] whose argv is `node lib/build.mjs` and a runner the npm package does NOT ship;
|
|
1933
|
+
# missing herdr vs unanswerable status as separate named refusals with zero writes; a selected
|
|
1934
|
+
# atom that is outdated/needs-repair/malformed/duplicated failing BEFORE any runtime work;
|
|
1935
|
+
# A-empty as a clean exit 0 that writes nothing (no runtime, no wiring, no removal); the
|
|
1936
|
+
# activation entry resolved under the stable runtime with absent/incapable as distinct named
|
|
1937
|
+
# refusals and no checkout fallback; the two-stage {pi} -> {pi, claude-code} composition where a
|
|
1938
|
+
# new commit reinstalls and OpenCode is never named; and the post-build Herdr commit gap being a
|
|
1939
|
+
# NAMED gap, not an atomic transaction. The real `herdr plugin install` + real `npm pack
|
|
1940
|
+
# git+https://...#<sha>` journey needs the network and lives in smoke-herdr-plugin-build-live.
|
|
1941
|
+
run_ts scripts/check-herdr-plugin-build.ts
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1944
|
+
smoke_herdr_plugin_build_live() {
|
|
1945
|
+
# #116 M3-b3 LIVE: a REAL `herdr plugin install` drives this plugin's REAL `[[build]]`, which
|
|
1946
|
+
# packs the FIXED product git spec for real. Needs LIVE=1, herdr/git/npm, and the NETWORK (a
|
|
1947
|
+
# git-spec pack builds the bridge through `prepare`, which installs devDependencies) — which is
|
|
1948
|
+
# the axis check-herdr-plugin-build cannot have and does not claim. Hermetic by two substitutions
|
|
1949
|
+
# only: sandbox HOME/XDG, and git `insteadOf` redirecting the unchanged product remote to a local
|
|
1950
|
+
# bare clone of this worktree, so an unpushed candidate is testable without weakening the argv.
|
|
1951
|
+
# Cells 1/2/4 are the real-Herdr journey: remote-commit available, reinstall widening to
|
|
1952
|
+
# {pi, claude-code} with OpenCode zero-write and ONE COUNTED vendor MCP owner entry, and the
|
|
1953
|
+
# post-build gap where herdr's own commit fails after our runner already rebound the activation.
|
|
1954
|
+
# Cell 3 is deliberately NOT a journey: it calls the shipped runtime leaf directly with the fixed
|
|
1955
|
+
# product argv at a commit the remote lacks, so it is acquisition-leaf evidence — named refusal,
|
|
1956
|
+
# active runtime/ledger/harness bytes preserved, journal left as the certified retry authority.
|
|
1957
|
+
run_ts scripts/smoke-herdr-plugin-build-live.ts
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
check_peer_facts() {
|
|
1961
|
+
# Deterministic gate for the #116 M2-a observed-peer projection. Drives the REAL
|
|
1962
|
+
# scripts/peer-facts.ts as a subprocess with every ambient root replaced (store,
|
|
1963
|
+
# ENTWURF_DIR, HOME, XDG_DATA_HOME, pi agent dir), so the live store, sockets and
|
|
1964
|
+
# markers are never read. Owns only what this verb ADDS on top of the provider:
|
|
1965
|
+
# placement crosses as the structured tagged union rather than the human string,
|
|
1966
|
+
# the peer keyset is exactly the provider's facts (no herdr agent_status may enter
|
|
1967
|
+
# an entwurf payload — that is the door observed activity would use to become
|
|
1968
|
+
# delivery liveness) and no socket coordinate is published at all, diagnostics ride
|
|
1969
|
+
# in-band, the probed socket world is the one ENTWURF_DIR names (proved by a
|
|
1970
|
+
# record-less socket surfacing — there is no field to echo), no observation budget
|
|
1971
|
+
# rations a machine projection, exit contract 0/2/3,
|
|
1972
|
+
# plus dispatch + compiled-twin reachability. No herdr binary, no model turn.
|
|
1973
|
+
run_ts scripts/check-peer-facts.ts
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1774
1976
|
check_entwurf_fact_provider() {
|
|
1775
1977
|
# Deterministic gate for 0.11 Stage 0 step 4 (fact-provider slice 4b): the
|
|
1776
1978
|
# ASSEMBLY layer listEntwurfFacts. listAllMetaIdentities → scanSocketProbes →
|
|
@@ -1785,6 +1987,94 @@ check_entwurf_fact_provider() {
|
|
|
1785
1987
|
run_ts scripts/check-entwurf-fact-provider.ts
|
|
1786
1988
|
}
|
|
1787
1989
|
|
|
1990
|
+
check_herdr_placement() {
|
|
1991
|
+
# Deterministic gate for #116 S1: the placement evidence axis
|
|
1992
|
+
# (pi-extensions/lib/herdr-placement.ts) plus the ONE read the fact provider is
|
|
1993
|
+
# allowed. Pins only what is decidable WITHOUT a herdr binary — payload parse, the
|
|
1994
|
+
# two measured join rules, the ambiguity rule, the four-word vocabulary, the render,
|
|
1995
|
+
# the once-per-listing read, and the STRUCTURAL absence of placement from every
|
|
1996
|
+
# entwurf_v2 dispatch module. There is no fake herdr here for the same reason
|
|
1997
|
+
# check-mux-placement refuses a fake tmux: a stand-in authors the contract before the
|
|
1998
|
+
# real thing is measured. Every payload literal is verbatim herdr 0.9.0 output
|
|
1999
|
+
# recorded 2026-09-14. The real-binary half is an isolated private herdr server
|
|
2000
|
+
# (sandbox HOME/XDG, no client attach); the join/callback round trip stays LIVE.
|
|
2001
|
+
run_ts scripts/check-herdr-placement.ts
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
check_herdr_fresh_call() {
|
|
2005
|
+
# Deterministic gate for #116 S2-c1: the herdr LAUNCH rail core
|
|
2006
|
+
# (pi-extensions/lib/herdr-fresh-call.ts). Pins only what is decidable WITHOUT a herdr
|
|
2007
|
+
# binary — the import fence that keeps the two rails separately deletable, the closed
|
|
2008
|
+
# pi|claude-code pilot, the option-G one-line JSON encoding (exact round trip, zero
|
|
2009
|
+
# Unicode Cc including the C1 block JSON.stringify leaves literal, max public task),
|
|
2010
|
+
# the pre-mutation refusals with the CLI never invoked, the ONE placement policy (a new
|
|
2011
|
+
# tab in the caller's own workspace, read from herdr's own answer about the caller's pane
|
|
2012
|
+
# and never from a pane id's shape, focus left alone), tab-create/start/get/close argv
|
|
2013
|
+
# grammar, strict response parsing, the opaque pane id, the receipt's missing address,
|
|
2014
|
+
# and the conditional-close matrix. No fake herdr executable and no fake server, for the
|
|
2015
|
+
# reason check-mux-placement refuses a fake tmux. Payload literals are verbatim herdr
|
|
2016
|
+
# 0.9.0 output (pane/tab replies 2026-09-15, agent_started 2026-09-14); the real-binary
|
|
2017
|
+
# half is an isolated private server (c2).
|
|
2018
|
+
run_ts scripts/check-herdr-fresh-call.ts
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
check_herdr_sandbox() {
|
|
2022
|
+
# REAL herdr acceptance for #116 C2a: a PRIVATE herdr server in a fully sandboxed
|
|
2023
|
+
# HOME/XDG/PI_CODING_AGENT_DIR creates a tab with the production placement argv, installs
|
|
2024
|
+
# herdr's own pi integration, and starts a BLANK pi in that tab's initial pane from ONE
|
|
2025
|
+
# checkout package registration. Asserts the official witness
|
|
2026
|
+
# triple, the strict path->native id join, exactly one sandbox V3 record, a control socket
|
|
2027
|
+
# that answers the production probe, and the conditional-close decision in both directions
|
|
2028
|
+
# (refuses a pane holding an agent, reclaims one we own and with it the tab it was the
|
|
2029
|
+
# whole of). No fake herdr, no model turn, no
|
|
2030
|
+
# credentials, no keystrokes; the fixture's `pi --approve` is a one-run authorisation that
|
|
2031
|
+
# writes no trust state and never enters production argv. herdr is an OPTIONAL rail: an
|
|
2032
|
+
# absent binary prints a named SKIP and exits 0, a PRESENT-but-incomplete rail FAILS, and
|
|
2033
|
+
# ENTWURF_REQUIRE_HERDR=1 turns absence itself into a failure (CI admission is C2b).
|
|
2034
|
+
run_ts scripts/check-herdr-sandbox.ts
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
check_herdr_supply() {
|
|
2038
|
+
# Deterministic supply-authority gate for #116 C2b: WHICH herdr bytes CI runs, and who
|
|
2039
|
+
# decides. No herdr binary and no network — it reads scripts/fixtures/herdr-supply.json,
|
|
2040
|
+
# scripts/install-herdr-ci.sh and .github/workflows/ci.yml as text. Pins the manifest as the
|
|
2041
|
+
# only copy of version/tag/digest, the digest shape, the fail-closed architecture map, the
|
|
2042
|
+
# verify-before-chmod order, the absence of curl-pipe/latest/package-manager/global install,
|
|
2043
|
+
# the absence of a `gh attestation verify` dependency (measured: gh 2.97.0 cannot close
|
|
2044
|
+
# herdr's in-toto release predicate), the CI install-before-floor order with
|
|
2045
|
+
# ENTWURF_REQUIRE_HERDR=1, Linux-job-only wiring, that no product script or bin reaches the
|
|
2046
|
+
# installer (Hard Rule 17), and that the x86_64 asset stays recorded as never executed.
|
|
2047
|
+
run_ts scripts/check-herdr-supply.ts
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
check_fresh_call_dispatch() {
|
|
2051
|
+
# Deterministic gate for #116 C3: the seam ABOVE the two rails. Pins that the rail is a
|
|
2052
|
+
# capability fact (exactly HERDR_ENV=1) and never a caller parameter, that neither direction
|
|
2053
|
+
# falls back, that a non-pilot backend refuses inside herdr before any preflight or mutation,
|
|
2054
|
+
# that the Codex preflight keeps its pre-existing ordering on the tmux path only, that one
|
|
2055
|
+
# nonce per call reaches the selected rail, that BOTH public surfaces reach one composition
|
|
2056
|
+
# root (no second copy of rail choice, preflight ordering or rendering), that pi still uses
|
|
2057
|
+
# its lazy dynamic import, and that herdr rendering shows view-not-address plus which recovery
|
|
2058
|
+
# happened. No tmux and no herdr binary: the seam runs with an injected spawn.
|
|
2059
|
+
run_ts scripts/check-fresh-call-dispatch.ts
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
smoke_herdr_fresh_call_live() {
|
|
2063
|
+
# LIVE acceptance for the #116 herdr rail: a REAL caller that is itself inside a herdr pane
|
|
2064
|
+
# invokes the REAL PUBLIC entwurf_fresh_call, and a REAL child's first model action is the
|
|
2065
|
+
# nonce callback. Opt-in (LIVE=1), four model turns, one private herdr server PER CELL —
|
|
2066
|
+
# herdr's socket follows XDG_CONFIG_HOME and each cell is fenced into its own.
|
|
2067
|
+
# `[측정 2026-09-14]` BOTH runtimes keep the operator's REAL HOME and real auth roots: a pi
|
|
2068
|
+
# given a fixture HOME dies before readiness (an installed extension resolves its npm
|
|
2069
|
+
# dependency through $HOME) and a claude given one enters first-run onboarding. Only
|
|
2070
|
+
# Entwurf-OWNED writes are fenced into the fixture (XDG roots, the meta roots, the v2 lock
|
|
2071
|
+
# dir). Evidence is source receipts only, in two named grades: pi from its own vendor
|
|
2072
|
+
# transcript, claude from the runtime's own entwurf-bridge MCP activity log joined by exact
|
|
2073
|
+
# sessionId plus entwurf's mailbox artifact and hook journal — never screen text, never a
|
|
2074
|
+
# keystroke. The operator's herdr panes are snapshotted before and after.
|
|
2075
|
+
run_ts scripts/smoke-herdr-fresh-call-live.ts
|
|
2076
|
+
}
|
|
2077
|
+
|
|
1788
2078
|
check_entwurf_peers_surface() {
|
|
1789
2079
|
# Deterministic gate for 0.11 Stage 0 step 4 (fact-provider slice 4c; #50 C4
|
|
1790
2080
|
# re-author): the MCP entwurf_peers RENDER/PAYLOAD layer renderEntwurfPeers.
|
|
@@ -3100,6 +3390,10 @@ check_pack() {
|
|
|
3100
3390
|
# #65 — the owner-normalized store projection consumers call INSTEAD of
|
|
3101
3391
|
# parsing the store; installed hosts are exactly where those consumers live.
|
|
3102
3392
|
"mcp/entwurf-bridge/dist/scripts/meta-facts.js"
|
|
3393
|
+
# #116 M2-a — the owner-normalized PEER projection, for the same reason one step
|
|
3394
|
+
# out: the placement join it emits is the copy a herdr-side consumer would
|
|
3395
|
+
# otherwise fork, and such a consumer runs against an installed host.
|
|
3396
|
+
"mcp/entwurf-bridge/dist/scripts/peer-facts.js"
|
|
3103
3397
|
# #87 Bundle B — omp-receive-doctor drives this operator projection through
|
|
3104
3398
|
# run.sh, so installed node_modules must have the compiled twin too.
|
|
3105
3399
|
"mcp/entwurf-bridge/dist/scripts/omp-receive-facts.js"
|
|
@@ -3395,6 +3689,8 @@ _check_pack_install_impl() {
|
|
|
3395
3689
|
"mcp/entwurf-bridge/dist/scripts/meta-bridge-fresh-cut.js"
|
|
3396
3690
|
# #65 — the owner-normalized store projection (see check-pack).
|
|
3397
3691
|
"mcp/entwurf-bridge/dist/scripts/meta-facts.js"
|
|
3692
|
+
# #116 M2-a — the owner-normalized peer projection (see check-pack).
|
|
3693
|
+
"mcp/entwurf-bridge/dist/scripts/peer-facts.js"
|
|
3398
3694
|
# #87 Bundle B — omp-receive-doctor reaches this through the installed dispatcher.
|
|
3399
3695
|
"mcp/entwurf-bridge/dist/scripts/omp-receive-facts.js"
|
|
3400
3696
|
# 0.12.5 — node_modules-safe plugin hook + lib (see check-pack). The installed
|
|
@@ -3582,6 +3878,60 @@ _check_pack_install_impl() {
|
|
|
3582
3878
|
}
|
|
3583
3879
|
echo "[check-pack-install] installed: $probe"
|
|
3584
3880
|
|
|
3881
|
+
# #116 M3-b1/b2 — THE ACTUAL-PACKAGE RUNTIME PROOF, THROUGH THE SHIPPED OWNER.
|
|
3882
|
+
# The Herdr plugin's runtime verifier decides whether a tree npm placed is a runtime the scoped
|
|
3883
|
+
# wiring may name: exact name@version, the compiled entry, all three required bins present AND
|
|
3884
|
+
# executable, and a real `entwurf check-bridge`. Its own focused gate drives that verifier against
|
|
3885
|
+
# a FIXTURE package, which proves the transaction but not this package — so the real artifact is
|
|
3886
|
+
# verified HERE, against the tarball this gate already packed and installed. No second pack, no
|
|
3887
|
+
# network.
|
|
3888
|
+
#
|
|
3889
|
+
# It imports from the INSTALLED tree's own scripts/herdr-runtime.mjs, not from the checkout. That
|
|
3890
|
+
# is the point: Herdr's `plugin uninstall` deletes the plugin checkout and calls no cleanup hook,
|
|
3891
|
+
# so the code that retires a runtime has to be IN the package. Reaching into $REPO_DIR here would
|
|
3892
|
+
# prove the checkout works and say nothing about what a clean host receives.
|
|
3893
|
+
local runtime_proof
|
|
3894
|
+
runtime_proof=$(cd "$tmp" && node --input-type=module -e "
|
|
3895
|
+
const pkg = process.cwd() + '/node_modules/@junghanacs/entwurf';
|
|
3896
|
+
const { verifyInstalledRuntime, readCheckoutPackageSpec, REQUIRED_BINS } =
|
|
3897
|
+
await import(pkg + '/scripts/herdr-runtime.mjs');
|
|
3898
|
+
const spec = readCheckoutPackageSpec(pkg);
|
|
3899
|
+
const seen = verifyInstalledRuntime(process.cwd(), spec);
|
|
3900
|
+
console.log(seen.name + '@' + seen.version + ' verified through the SHIPPED owner (' + REQUIRED_BINS.join(', ') + ')');
|
|
3901
|
+
" 2>&1) || {
|
|
3902
|
+
fail "[check-pack-install] #116 runtime verifier REFUSED the actual installed package (or does not ship):"
|
|
3903
|
+
echo "$runtime_proof" | sed 's/^/ /' >&2
|
|
3904
|
+
return 1
|
|
3905
|
+
}
|
|
3906
|
+
echo "[check-pack-install] herdr-plugin runtime verifier: $runtime_proof"
|
|
3907
|
+
|
|
3908
|
+
# #116 M3-b2 — THE DEACTIVATE VERB MUST ACTUALLY TEAR DOWN, WITH NO CHECKOUT. Herdr's `plugin
|
|
3909
|
+
# uninstall` deletes the plugin checkout and calls no cleanup hook, so the teardown entry has to
|
|
3910
|
+
# be IN the package AND has to survive deleting the runtime it is executing from. So this does not
|
|
3911
|
+
# settle for the "nothing to undo" verdict: it stages the real shape — the installed package
|
|
3912
|
+
# sitting AT the stable active root, a certified runtime journal, and a certified activation
|
|
3913
|
+
# ledger whose components are already removed — then runs THAT copy's own entry with a throwaway
|
|
3914
|
+
# HOME/XDG and no reference to this repo. What it proves is the self-delete: the process removes
|
|
3915
|
+
# the tree it is executing from and still finishes retiring the ledger.
|
|
3916
|
+
local deact_home deact_active deact_pkg deact_proof deact_rc runtime_left ledger_left
|
|
3917
|
+
deact_home=$(mktemp -d -t entwurf-deact.XXXXXX)
|
|
3918
|
+
deact_active="$deact_home/.data/entwurf/herdr-plugin/runtime/active"
|
|
3919
|
+
mkdir -p "$deact_active" "$deact_home/.state/entwurf/herdr-plugin"
|
|
3920
|
+
cp -R "$tmp/node_modules" "$deact_active/node_modules"
|
|
3921
|
+
deact_pkg="$deact_active/node_modules/@junghanacs/entwurf"
|
|
3922
|
+
node -e 'const fs=require("fs"),path=require("path");const [home,active]=process.argv.slice(1);const pkg=path.join(active,"node_modules","@junghanacs","entwurf");const version=JSON.parse(fs.readFileSync(path.join(pkg,"package.json"),"utf8")).version;fs.writeFileSync(path.join(home,".data","entwurf","herdr-plugin","journal.json"),JSON.stringify({schemaVersion:2,phase:"runtime-ready",runtimeRoot:active,artifactIdentity:{kind:"herdr-checkout",repository:"junghan0611/entwurf",commit:"c".repeat(40),packageName:"@junghanacs/entwurf",packageVersion:version,observedDigest:"sha256-"+"a".repeat(64)},previousRuntime:null}));fs.writeFileSync(path.join(home,".state","entwurf","herdr-plugin","activation.json"),JSON.stringify({schemaVersion:2,phase:"deactivating",runtimeRoot:active,artifactIdentity:{kind:"herdr-checkout",repository:"junghan0611/entwurf",commit:"c".repeat(40),packageName:"@junghanacs/entwurf",packageVersion:version,observedDigest:"sha256-"+"a".repeat(64)},piAgentDir:{path:path.join(home,".pi","agent"),source:"default"},claudeConfigDir:{path:path.join(home,".claude"),source:"default"},claudeUserConfig:{path:path.join(home,".claude.json"),source:"HOME"},activatedBackends:["pi"],components:[{backend:"pi",state:"removed"}]}));' "$deact_home" "$deact_active"
|
|
3923
|
+
deact_proof=$(env -i PATH="$PATH" HOME="$deact_home" XDG_DATA_HOME="$deact_home/.data" XDG_STATE_HOME="$deact_home/.state" XDG_CACHE_HOME="$deact_home/.cache" node "$deact_pkg/scripts/herdr-plugin-deactivate.mjs" 2>&1)
|
|
3924
|
+
deact_rc=$?
|
|
3925
|
+
runtime_left=$([ -e "$deact_home/.data/entwurf/herdr-plugin/runtime" ] && echo yes || echo no)
|
|
3926
|
+
ledger_left=$([ -e "$deact_home/.state/entwurf/herdr-plugin/activation.json" ] && echo yes || echo no)
|
|
3927
|
+
rm -rf "$deact_home"
|
|
3928
|
+
if [ "$deact_rc" -ne 0 ] || [ "$runtime_left" != "no" ] || [ "$ledger_left" != "no" ]; then
|
|
3929
|
+
fail "[check-pack-install] #116 M3-b2 installed herdr-plugin-deactivate did not complete the self-delete (rc=$deact_rc runtime-left=$runtime_left ledger-left=$ledger_left):"
|
|
3930
|
+
echo "$deact_proof" | sed 's/^/ /' >&2
|
|
3931
|
+
return 1
|
|
3932
|
+
fi
|
|
3933
|
+
echo "[check-pack-install] installed herdr-plugin-deactivate removed its OWN runtime and retired the ledger with no checkout: $deact_proof"
|
|
3934
|
+
|
|
3585
3935
|
# Pi package loader smoke — actual `pi` reads the manifest and
|
|
3586
3936
|
# registers the provider. rc=0 + the curated model list in the
|
|
3587
3937
|
# output means pi accepted the package as a real extension, not
|
|
@@ -4498,6 +4848,57 @@ JS
|
|
|
4498
4848
|
fi
|
|
4499
4849
|
echo "[check-pack-install] installed 'entwurf copilot' reached the vendor with the scan flag and the managed argv"
|
|
4500
4850
|
|
|
4851
|
+
# #95 — the managed app-server SPELLING, from the INSTALLED package. Same packaging risk as
|
|
4852
|
+
# the copilot cell above and the same reason a file-list assertion cannot stand in for it:
|
|
4853
|
+
# `scripts/codex-app-server-launch.sh` has to be in the tarball AND resolve its siblings
|
|
4854
|
+
# correctly once it lives under node_modules. What makes this cell worth its seconds is the
|
|
4855
|
+
# ADDRESS: this verb exists so a consumer never types that socket path, so the one thing an
|
|
4856
|
+
# installed run must prove is that the path it hands the vendor is the one the product's own
|
|
4857
|
+
# resolver computes — read here from the INSTALLED tree, never from this checkout.
|
|
4858
|
+
local cx_launch_home="$npm_tmp/codex-appserver-home" cx_launch_bin="$npm_tmp/codex-appserver-bin"
|
|
4859
|
+
mkdir -p "$cx_launch_home" "$cx_launch_bin"
|
|
4860
|
+
{
|
|
4861
|
+
printf '#!/usr/bin/env bash\n'
|
|
4862
|
+
printf 'for a in "$@"; do printf "ARG<%%s>\\n" "$a"; done\n'
|
|
4863
|
+
} > "$cx_launch_bin/codex"
|
|
4864
|
+
chmod +x "$cx_launch_bin/codex"
|
|
4865
|
+
# The expectation is read from the INSTALLED COMPILED resolver, not from this checkout and
|
|
4866
|
+
# not transcribed here: compiled JS is what an installed consumer surface reaches (Hard Rule
|
|
4867
|
+
# 11), so this asks the packed tree itself what address it believes in.
|
|
4868
|
+
local cx_resolver="$npm_pkg/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/codex-ws-client.js" cx_want
|
|
4869
|
+
if [ ! -f "$cx_resolver" ]; then
|
|
4870
|
+
fail "[check-pack-install] the tarball carries no compiled Codex socket resolver at $cx_resolver"
|
|
4871
|
+
return 1
|
|
4872
|
+
fi
|
|
4873
|
+
if ! cx_want=$(CODEX_HOME="$cx_launch_home/.codex" node --input-type=module -e "
|
|
4874
|
+
import { resolveCodexDefaultSocketPath } from '$cx_resolver';
|
|
4875
|
+
process.stdout.write(resolveCodexDefaultSocketPath(process.env));
|
|
4876
|
+
" 2>&1); then
|
|
4877
|
+
fail "[check-pack-install] the INSTALLED compiled socket resolver would not load:"
|
|
4878
|
+
echo "$cx_want" | tail -4 | sed 's/^/ /' >&2
|
|
4879
|
+
return 1
|
|
4880
|
+
fi
|
|
4881
|
+
if ! op_out=$(env -u ENTWURF_CODEX_APP_SERVER_ACTIVE -u TMUX \
|
|
4882
|
+
HOME="$cx_launch_home" CODEX_HOME="$cx_launch_home/.codex" PATH="$cx_launch_bin:$PATH" \
|
|
4883
|
+
"$installed_entwurf" codex-app-server --config probe=1 2>&1); then
|
|
4884
|
+
fail "[check-pack-install] installed 'entwurf codex-app-server' FAILED to reach the vendor:"
|
|
4885
|
+
echo "$op_out" | tail -8 | sed 's/^/ /' >&2
|
|
4886
|
+
return 1
|
|
4887
|
+
fi
|
|
4888
|
+
for want in "ARG<app-server>" "ARG<--listen>" "ARG<unix://$cx_want>" "ARG<--config>" "ARG<probe=1>"; do
|
|
4889
|
+
if ! printf '%s' "$op_out" | grep -qF "$want"; then
|
|
4890
|
+
fail "[check-pack-install] installed 'entwurf codex-app-server' did not hand the vendor the resolved address and argv (missing $want):"
|
|
4891
|
+
echo "$op_out" | tail -8 | sed 's/^/ /' >&2
|
|
4892
|
+
return 1
|
|
4893
|
+
fi
|
|
4894
|
+
done
|
|
4895
|
+
if printf '%s' "$op_out" | grep -qF 'ARG<codex-app-server>'; then
|
|
4896
|
+
fail "[check-pack-install] installed 'entwurf codex-app-server' leaked the dispatcher verb into the vendor's argv:"
|
|
4897
|
+
echo "$op_out" | tail -8 | sed 's/^/ /' >&2
|
|
4898
|
+
return 1
|
|
4899
|
+
fi
|
|
4900
|
+
echo "[check-pack-install] installed 'entwurf codex-app-server' reached the vendor at the INSTALLED resolver's address ($cx_want)"
|
|
4901
|
+
|
|
4501
4902
|
# The generation verb must reach its verdict from under node_modules. On the
|
|
4502
4903
|
# sandbox 0-record agent dir it archives nothing and opens a fresh generation.
|
|
4503
4904
|
# The exit code alone can't tell a verdict from a fence crash, so read the line.
|
|
@@ -5313,6 +5714,12 @@ setup_all() {
|
|
|
5313
5714
|
else
|
|
5314
5715
|
setup_result codex-statusline FAIL "detected codex, but the visible-identity setting did not complete (see above)"
|
|
5315
5716
|
fi
|
|
5717
|
+
codex_rc=0; codex_terminal_title install || codex_rc=$?
|
|
5718
|
+
if [ "$codex_rc" -eq 0 ]; then
|
|
5719
|
+
setup_harness_result codex-terminal-title "thread-id terminal title enabled (caller-seat placement input)" "./run.sh doctor-codex-terminal-title"
|
|
5720
|
+
else
|
|
5721
|
+
setup_result codex-terminal-title FAIL "detected codex, but the terminal-title setting did not complete (see above)"
|
|
5722
|
+
fi
|
|
5316
5723
|
fi
|
|
5317
5724
|
# ── core bridge boundary ── deterministic preflight lives in `pnpm run
|
|
5318
5725
|
# check:full`; live substrate acceptance lives in `LIVE=1 ./run.sh
|
|
@@ -5992,6 +6399,9 @@ case "$cmd" in
|
|
|
5992
6399
|
check-copilot-statusline)
|
|
5993
6400
|
check_copilot_statusline
|
|
5994
6401
|
;;
|
|
6402
|
+
check-codex-app-server-launch)
|
|
6403
|
+
check_codex_app_server_launch
|
|
6404
|
+
;;
|
|
5995
6405
|
check-copilot-launch)
|
|
5996
6406
|
check_copilot_launch
|
|
5997
6407
|
;;
|
|
@@ -6082,6 +6492,9 @@ case "$cmd" in
|
|
|
6082
6492
|
check-mux-launcher-fence)
|
|
6083
6493
|
check_mux_launcher_fence
|
|
6084
6494
|
;;
|
|
6495
|
+
check-typing-call-fence)
|
|
6496
|
+
check_typing_call_fence
|
|
6497
|
+
;;
|
|
6085
6498
|
check-entwurf-v2-visible-resume)
|
|
6086
6499
|
check_entwurf_v2_visible_resume
|
|
6087
6500
|
;;
|
|
@@ -6169,9 +6582,48 @@ case "$cmd" in
|
|
|
6169
6582
|
check-meta-facts)
|
|
6170
6583
|
check_meta_facts
|
|
6171
6584
|
;;
|
|
6585
|
+
check-herdr-activation)
|
|
6586
|
+
check_herdr_activation
|
|
6587
|
+
;;
|
|
6588
|
+
check-herdr-runtime-bootstrap)
|
|
6589
|
+
check_herdr_runtime_bootstrap
|
|
6590
|
+
;;
|
|
6591
|
+
check-herdr-plugin-profile)
|
|
6592
|
+
check_herdr_plugin_profile
|
|
6593
|
+
;;
|
|
6594
|
+
check-herdr-plugin-build)
|
|
6595
|
+
check_herdr_plugin_build
|
|
6596
|
+
;;
|
|
6597
|
+
smoke-herdr-plugin-build-live)
|
|
6598
|
+
smoke_herdr_plugin_build_live
|
|
6599
|
+
;;
|
|
6600
|
+
check-peer-facts)
|
|
6601
|
+
check_peer_facts
|
|
6602
|
+
;;
|
|
6603
|
+
check-herdr-plugin)
|
|
6604
|
+
check_herdr_plugin
|
|
6605
|
+
;;
|
|
6172
6606
|
check-entwurf-fact-provider)
|
|
6173
6607
|
check_entwurf_fact_provider
|
|
6174
6608
|
;;
|
|
6609
|
+
check-herdr-placement)
|
|
6610
|
+
check_herdr_placement
|
|
6611
|
+
;;
|
|
6612
|
+
check-herdr-fresh-call)
|
|
6613
|
+
check_herdr_fresh_call
|
|
6614
|
+
;;
|
|
6615
|
+
check-herdr-sandbox)
|
|
6616
|
+
check_herdr_sandbox
|
|
6617
|
+
;;
|
|
6618
|
+
check-herdr-supply)
|
|
6619
|
+
check_herdr_supply
|
|
6620
|
+
;;
|
|
6621
|
+
check-fresh-call-dispatch)
|
|
6622
|
+
check_fresh_call_dispatch
|
|
6623
|
+
;;
|
|
6624
|
+
smoke-herdr-fresh-call-live)
|
|
6625
|
+
smoke_herdr_fresh_call_live
|
|
6626
|
+
;;
|
|
6175
6627
|
check-entwurf-peers-surface)
|
|
6176
6628
|
check_entwurf_peers_surface
|
|
6177
6629
|
;;
|
|
@@ -6616,6 +7068,35 @@ case "$cmd" in
|
|
|
6616
7068
|
doctor-codex-statusline)
|
|
6617
7069
|
codex_statusline doctor
|
|
6618
7070
|
;;
|
|
7071
|
+
install-codex-terminal-title)
|
|
7072
|
+
codex_terminal_title install
|
|
7073
|
+
;;
|
|
7074
|
+
uninstall-codex-terminal-title)
|
|
7075
|
+
codex_terminal_title uninstall
|
|
7076
|
+
;;
|
|
7077
|
+
doctor-codex-terminal-title)
|
|
7078
|
+
codex_terminal_title doctor
|
|
7079
|
+
;;
|
|
7080
|
+
codex-socket-path)
|
|
7081
|
+
# #95 INTERNAL: print the Codex app-server default control-socket path for this
|
|
7082
|
+
# environment. It exists because `entwurf codex-app-server` is bash and cannot import
|
|
7083
|
+
# `resolveCodexDefaultSocketPath`; re-deriving that path in bash was MEASURED to diverge
|
|
7084
|
+
# (BOM-only CODEX_HOME, path normalization), so the launcher asks instead of transcribing.
|
|
7085
|
+
# `run_ts` is the crossing (compiled twin when installed, strip-types in a clone), which is
|
|
7086
|
+
# the whole reason this sits in the dispatcher rather than inside the leaf.
|
|
7087
|
+
shift || true
|
|
7088
|
+
run_ts scripts/codex-socket-path.ts "$@"
|
|
7089
|
+
;;
|
|
7090
|
+
codex-app-server)
|
|
7091
|
+
# #95: the managed app-server SPELLING. Same shape and same reasons as the `copilot`
|
|
7092
|
+
# branch below — `exec`, no subshell and no cd, because this operates on the operator's
|
|
7093
|
+
# own session rather than on the repo, and the `shift` keeps the dispatcher verb out of
|
|
7094
|
+
# the vendor's argv. It is NOT the same KIND of thing: `entwurf copilot` becomes a
|
|
7095
|
+
# sibling-bearing CLI, while this becomes the long-lived server those siblings' MCP
|
|
7096
|
+
# children hang off. Neither one supervises what it becomes.
|
|
7097
|
+
shift || true
|
|
7098
|
+
exec bash "$REPO_DIR/scripts/codex-app-server-launch.sh" "$@"
|
|
7099
|
+
;;
|
|
6619
7100
|
copilot)
|
|
6620
7101
|
# #82 RAIL 7: the managed launch. `exec` and NO subshell/cd on purpose — the vendor
|
|
6621
7102
|
# must inherit this terminal exactly: the caller's cwd, this pid, this tty, and its own
|
|
@@ -6802,6 +7283,22 @@ case "$cmd" in
|
|
|
6802
7283
|
shift || true
|
|
6803
7284
|
run_ts scripts/meta-facts.ts "$@"
|
|
6804
7285
|
;;
|
|
7286
|
+
peer-facts)
|
|
7287
|
+
# #116 M2-a READ-ONLY projection of the OBSERVED peer listing: one provider
|
|
7288
|
+
# (`listEntwurfFacts`) through one renderer (`renderEntwurfPeers().payload`), so
|
|
7289
|
+
# the payload SHAPE is the entwurf_peers payload shape and the join is never
|
|
7290
|
+
# re-implemented — the pi half of that join is a measured vendor floor, and a
|
|
7291
|
+
# forked copy decays silently. It is NOT the same bytes as an entwurf_peers call:
|
|
7292
|
+
# that surface rations observation and returns text, this one is unbounded because
|
|
7293
|
+
# a rationed row says `unobserved` and a machine consumer cannot tell that from
|
|
7294
|
+
# "nobody could look". `placement` stays the structured tagged union. No socket
|
|
7295
|
+
# coordinate is published (#50 C4 retired the legacy listing with the controlDir it
|
|
7296
|
+
# exposed; ENTWURF_DIR only selects what is probed) and herdr's own
|
|
7297
|
+
# agent_status/screen verdicts are absent (docs/herdr-launch-rail.md §9). No
|
|
7298
|
+
# writes, no watcher, no dispatch. Same exit contract as meta-facts.
|
|
7299
|
+
shift || true
|
|
7300
|
+
run_ts scripts/peer-facts.ts "$@"
|
|
7301
|
+
;;
|
|
6805
7302
|
meta-bridge-managed-keys)
|
|
6806
7303
|
# 0.10.0 meta-bridge: emit the SSOT of settings.json/~/.claude.json keys that
|
|
6807
7304
|
# entwurf's install OWNS. Consumers (agent-config fragment, future
|
|
@@ -6960,6 +7457,21 @@ case "$cmd" in
|
|
|
6960
7457
|
remove)
|
|
6961
7458
|
remove_local_package "$TARGET_PROJECT_DIR"
|
|
6962
7459
|
;;
|
|
7460
|
+
herdr-plugin-activate)
|
|
7461
|
+
# #116 M3-b2 public forward verb. Takes a subset of {pi, claude-code} and NOTHING else — the
|
|
7462
|
+
# stable runtime root is derived, never supplied. Plain `node` in both modes: shipped .mjs.
|
|
7463
|
+
shift
|
|
7464
|
+
(cd "$REPO_DIR" && node "$REPO_DIR/scripts/herdr-plugin-activate.mjs" "$@")
|
|
7465
|
+
;;
|
|
7466
|
+
herdr-plugin-deactivate)
|
|
7467
|
+
# #116 M3-b2 public verb. Plain `node` in BOTH modes on purpose: this is shipped .mjs, not TS,
|
|
7468
|
+
# because it has to run from an installed package after Herdr deleted the plugin checkout.
|
|
7469
|
+
(cd "$REPO_DIR" && node "$REPO_DIR/scripts/herdr-plugin-deactivate.mjs" "$@")
|
|
7470
|
+
;;
|
|
7471
|
+
install-user-scope)
|
|
7472
|
+
shift
|
|
7473
|
+
install_user_scope "$@"
|
|
7474
|
+
;;
|
|
6963
7475
|
remove-user-scope)
|
|
6964
7476
|
remove_user_scope_citizen
|
|
6965
7477
|
;;
|