@junghanacs/entwurf 0.41.2 → 0.50.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.
Files changed (122) hide show
  1. package/AGENTS.md +4 -2
  2. package/BASELINE.md +110 -1
  3. package/CHANGELOG.md +328 -0
  4. package/CONTRIBUTING.md +1 -1
  5. package/ENTWURF-CLI.json +1229 -0
  6. package/ENTWURF.json +284 -0
  7. package/FAQ.md +4 -4
  8. package/README.md +125 -184
  9. package/VERIFY.md +2 -2
  10. package/docs/external-mcp-host.md +3 -3
  11. package/docs/setup-clean-host.md +37 -12
  12. package/mcp/entwurf-bridge/dist/ENTWURF.json +284 -0
  13. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +46 -196
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/agent-guidance.js +299 -0
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +21 -25
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-visible-resume.js +498 -29
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-dispatch.js +47 -10
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +613 -33
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-resume-call.js +497 -0
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +3 -1
  21. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +23 -20
  22. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-resume-call.js +68 -21
  23. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-fresh-preflight.js +7 -1
  24. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-location.js +347 -0
  25. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-owner-fence.js +1132 -0
  26. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-runtime.js +1 -0
  27. package/mcp/entwurf-bridge/dist/pi-extensions/lib/remote-pair-send.js +7 -4
  28. package/mcp/entwurf-bridge/dist/pi-extensions/lib/resume-launch-identity.js +18 -11
  29. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-pi-durable.js +53 -60
  30. package/mcp/entwurf-bridge/dist/scripts/herdr-rails.mjs +40 -7
  31. package/mcp/entwurf-bridge/dist/scripts/meta-bridge-fresh-cut.js +1 -27
  32. package/mcp/entwurf-bridge/dist/scripts/meta-bridge-prune.js +1 -1
  33. package/mcp/entwurf-bridge/dist/scripts/meta-facts.js +1 -1
  34. package/mcp/entwurf-bridge/dist/scripts/peer-facts.js +1 -1
  35. package/mcp/entwurf-bridge/src/index.ts +149 -327
  36. package/mcp/entwurf-bridge/tsconfig.build.json +7 -1
  37. package/native/win32-x64/manifest.json +1 -1
  38. package/package.json +8 -4
  39. package/pi/pi-durable/bootstrap.mjs +179 -6
  40. package/pi/pi-durable/carrier/runtime.js +108 -9
  41. package/pi/pi-durable/carrier/session-name.js +11 -0
  42. package/pi/pi-durable/carrier/sessions.js +96 -20
  43. package/pi/pi-durable/overlay/upstream-pin.json +11 -5
  44. package/pi-extensions/lib/agent-guidance.ts +341 -0
  45. package/pi-extensions/lib/entwurf-v2-surface.ts +25 -31
  46. package/pi-extensions/lib/entwurf-v2-visible-resume.ts +725 -54
  47. package/pi-extensions/lib/fresh-call-dispatch.ts +64 -12
  48. package/pi-extensions/lib/herdr-fresh-call.ts +919 -40
  49. package/pi-extensions/lib/herdr-resume-call.ts +810 -0
  50. package/pi-extensions/lib/meta-session.ts +13 -8
  51. package/pi-extensions/lib/mux-fresh-call.ts +23 -26
  52. package/pi-extensions/lib/mux-resume-call.ts +95 -23
  53. package/pi-extensions/lib/pi-durable-fresh-preflight.ts +9 -2
  54. package/pi-extensions/lib/pi-durable-location.ts +446 -0
  55. package/pi-extensions/lib/pi-durable-owner-fence.ts +1461 -0
  56. package/pi-extensions/lib/pi-durable-runtime.ts +4 -0
  57. package/pi-extensions/lib/remote-pair-send.ts +7 -4
  58. package/pi-extensions/lib/resume-launch-identity.ts +31 -12
  59. package/pi-extensions/meta-bridge-pi-durable.ts +52 -79
  60. package/run.sh +417 -654
  61. package/scripts/build-bridge.sh +10 -0
  62. package/scripts/check-capability-bundle-reach.ts +86 -0
  63. package/scripts/check-claude-launch.ts +341 -0
  64. package/scripts/check-entwurf-self-address.ts +3 -3
  65. package/scripts/check-entwurf-v2-surface.ts +94 -98
  66. package/scripts/check-fresh-call-dispatch.ts +70 -9
  67. package/scripts/check-fresh-cut-gate.sh +23 -9
  68. package/scripts/check-gate-qualification.ts +24 -17
  69. package/scripts/check-herdr-activation.ts +301 -23
  70. package/scripts/check-herdr-fresh-call.ts +161 -25
  71. package/scripts/check-herdr-plugin-build.ts +173 -1
  72. package/scripts/check-herdr-plugin.ts +28 -2
  73. package/scripts/check-herdr-runtime-bootstrap.ts +136 -0
  74. package/scripts/check-install-surface.ts +1236 -6
  75. package/scripts/check-meta-doctor-oracle.sh +1 -1
  76. package/scripts/check-meta-facts.ts +20 -1
  77. package/scripts/check-mux-resume-call.ts +48 -3
  78. package/scripts/check-peer-facts.ts +39 -2
  79. package/scripts/cli-help.mjs +222 -0
  80. package/scripts/dev-bin.sh +39 -2
  81. package/scripts/herdr-activation.mjs +28 -6
  82. package/scripts/herdr-operator-link.mjs +389 -0
  83. package/scripts/herdr-plugin-activate.mjs +5 -0
  84. package/scripts/herdr-plugin-deactivate.mjs +18 -5
  85. package/scripts/herdr-rails.mjs +43 -7
  86. package/scripts/herdr-runtime.mjs +27 -0
  87. package/scripts/meta-bridge-fresh-cut.ts +1 -27
  88. package/scripts/meta-bridge-prune.ts +1 -1
  89. package/scripts/meta-facts.ts +1 -1
  90. package/scripts/mutants/agent-guidance.json +160 -0
  91. package/scripts/mutants/bridge-boot-resume.json +6 -8
  92. package/scripts/mutants/capability-bundle-reach.json +124 -0
  93. package/scripts/mutants/claude-launch.json +142 -0
  94. package/scripts/mutants/cli-help-source.json +420 -0
  95. package/scripts/mutants/control-send-receipt.json +21 -4
  96. package/scripts/mutants/dev-gate-dispatch.json +109 -0
  97. package/scripts/mutants/fresh-call-dispatch.json +38 -2
  98. package/scripts/mutants/fresh-cut.json +15 -0
  99. package/scripts/mutants/herdr-activation.json +128 -0
  100. package/scripts/mutants/herdr-fresh-call.json +278 -5
  101. package/scripts/mutants/herdr-operator-link.json +318 -0
  102. package/scripts/mutants/herdr-plugin-build.json +55 -0
  103. package/scripts/mutants/herdr-plugin.json +17 -0
  104. package/scripts/mutants/herdr-resume-call.json +288 -0
  105. package/scripts/mutants/herdr-runtime-bootstrap.json +48 -0
  106. package/scripts/mutants/meta-facts.json +15 -0
  107. package/scripts/mutants/mux-fresh-call.json +14 -3
  108. package/scripts/mutants/mux-resume-call.json +89 -3
  109. package/scripts/mutants/peer-facts.json +15 -0
  110. package/scripts/mutants/pi-durable.json +996 -6
  111. package/scripts/mutants/remote-pair-send.json +21 -2
  112. package/scripts/mutants/self-address.json +10 -10
  113. package/scripts/mutants/source-install.json +35 -0
  114. package/scripts/mutants/v2-surface.json +50 -64
  115. package/scripts/mutants/v2-visible-resume.json +266 -6
  116. package/scripts/peer-facts.ts +1 -1
  117. package/scripts/smoke-agy-install-state.sh +66 -0
  118. package/scripts/smoke-meta-prune.sh +23 -0
  119. package/scripts/smoke-omp-fresh-live.ts +12 -3
  120. package/scripts/smoke-omp-receive-live.ts +7 -1
  121. package/scripts/smoke-pi-durable-fresh-live.ts +12 -2
  122. package/team.json.example +39 -0
package/run.sh CHANGED
@@ -162,205 +162,10 @@ developer_menu() {
162
162
  }
163
163
 
164
164
  usage() {
165
- cat <<'EOF'
166
- Usage:
167
- ./run.sh menu # source-only Herdr developer board: read-only readiness check or explicitly confirmed return to checkout wiring; never closes sessions or acquires npm artifacts
168
- ./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
169
- ./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.
170
- ./run.sh check-bridge # entwurf-bridge direct MCP smoke + protocol/negative-path test.sh (live substrate = v2 live smokes)
171
- ./run.sh check-entwurf-bridge-boot # deterministic gate (5d-5-pre, G1a/G1b/G1e/G1f/G1h, IN pnpm run check:full): boot start.sh under strip-types + assert v2 fence graph loads + entwurf_v2, entwurf_resume_call and entwurf_callback registered/schema + the tools/list surface is EXACTLY the eight shipped garden verbs; tools/list only, no auth/side-effect
172
- ./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
173
- ./run.sh check-model-lock # deterministic unit test for pi-extensions/model-lock.ts (4-quadrant + edge cases, no API)
174
- ./run.sh check-shell-quote # POSIX-safety gate for shellQuote (remote SSH arg quoting in entwurf paths) — source parity + behavior matrix, no SSH
175
- ./run.sh check-entwurf-session-identity # deterministic gate for record-era session identity (garden-id grammar + readSessionIdentity: first-model_change authority, name-blind — #50 C3), no API
176
- ./run.sh check-meta-session # deterministic gate (#30 step 2, V3-only): fs store — idempotent decideUpsert/upsertMetaSession + mailbox enqueue/read + receipt state, no API
177
- ./run.sh check-meta-v3-record # deterministic gate: the ONE live record schema (v3) — canonical serialize/round-trip/mint, foreign-generation rejections name fresh-cut with the actual version value, strict keyset, no API
178
- ./run.sh check-mailbox-receipt-state # deterministic gate (0.11 Stage 0 step 3B): mailbox receipt state schema + store (stamp→persist→read-back) in a temp mailbox, strict keyset, no API
179
- ./run.sh check-copilot-birth-hook # #82 gate: drives the real Copilot assembler into a temp dir, fires the baked launcher with NO ARGV (the way Copilot's `exec`-string schema forces), and requires a backend:"copilot" v3 record + attach + peer row + a SENDER marker the resolver joins back to that record, and still zero mailbox/receiver marker (who-sent needs a shared parent; a receiver needs a doorbell this backend has not got). Hermetic; no Copilot, no model turn
180
- ./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
181
- ./run.sh check-pi-durable-contact # #129 L-identity gate, CHECKOUT-ONLY (an installed package refuses it in run_ts). Opens the REAL durable app from THIS checkout's verified carrier (pi/pi-durable/carrier/ under its resolver, against the checkout's pinned pi SDK set — refused by name first) with the pi-durable contact, births the citizen and runs its tools adapter-direct through a privately emitted branch bridge (ENTWURF_PI_DURABLE_BRIDGE_ENTRY; its registry must match this checkout). Matrix roots {default, explicit} x {fresh, --continue}: one record keyed by the durable session dir, sender marker on the spawned host pid, exactly one bridge child whose /proc PPID is that host, poisoned identity carriers kept from it, its four root carriers bound to the roots written, the receiver ARMED (raw marker owned by the host pid + start key as pi-durable-host, joined to the sender marker; removed on close), self = the record and replyable, peers from an outside bridge, same garden id on reopen; the bundle's compiled owner join must admit pi-durable-host. Reaps only the host/bridges it owns on any failure. Harness-bypassed: no model turn, no ToolTask. Missing inputs → SKIP (97), never a pass
182
- ./run.sh check-pi-durable-send # #129 L-send FIRST CELL, CHECKOUT-ONLY. Same input as check-pi-durable-contact. One native durable turn: the app's own controller input → GenerationTask → ToolTask → the contact's entwurf_v2 → the private bridge → a seeded self-fetch target (C2 recipe, owned by a separate idle child). S = a 127.0.0.1 scripted OpenAI-compatible endpoint configured through the app's documented models.json (dummy key, PI_OFFLINE); H = the native ToolTask path; V (a vendor turn) is NOT run. Oracles: the wire (tools offered, v2 schema = the bridge's tools/list, exactly two requests, the tool result + receipt in the second), the raw mailbox (.msg 1, signal, sender = the host record), the native view (one call, its settled result, root current). Not exactly-once, not recovery, not a recipient turn. Missing inputs → SKIP (97)
183
- ./run.sh check-demo-reproducibility # source-checkout-only: discover offline demo Node tests; no LIVE, model, render or publication
184
- ./run.sh check-pi-durable-beside # #129 mutant execution coordinate (VERIFY rule 3): run_vitest over four pi-durable beside tests (adapter, carrier/SDK-set verifier, preflight, owner join) — a pi-durable qualification lane gate argv. Same files check-tests-beside-behavior already runs.
185
- ./run.sh check-pi-durable-carrier # #144 mutant execution coordinate (VERIFY rule 3): run_vitest over the carrier test alone (relocation/resolver, owned-source emission and typecheck fence, package file list, task footer, the real bootstrap on the 1.2 SDK, stream transport, skills prompt) — the gate argv of the carrier claims, whose QKs live only in that file. Same file check-tests-beside-behavior already runs.
186
- ./run.sh check-pi-durable-native-module # #144 mutant execution coordinate (VERIFY rule 3): run_vitest over the bootstrap's native-module file and directory ingress test alone — the gate argv of the ingress claims, whose QKs live only in that file. Same file check-tests-beside-behavior already runs.
187
- ./run.sh check-remote-pair-beside # #149 mutant execution coordinate (VERIFY rule 3): run_vitest over the five remote-pair beside tests (send, receive, roundtrip, transport, mailbox body) — the gate argv of the remote-pair claims. Same files check-tests-beside-behavior already runs.
188
- ./run.sh check-pi-durable-receive # #129 L-receive FIRST CELL, CHECKOUT-ONLY. Same input (the bundle must carry the pi-durable-host owner join). The host driver gives the app NO input; a seeded claude-code sender (marker owned by a separate idle child, handed to a gate-owned sending bridge through ENTWURF_META_SENDER_MARKER) enqueues one message, the host's doorbell admits its notice to the ROOT conversation, and the scripted model drains it with entwurf_inbox_read. S withholds response #1 until the ENQUEUE receipt, the .delivered bytes, the signal, the host-owned receiver marker and the notice are captured. Oracles: receiver() admission, native view, raw archive (.delivered.read + lastReadAt), wire (exactly two requests, drain result = view), and after a green reap a forensic read-only SQLite copy (submission row by request id = reported id, root, input, done, placed entry = the notice). V NOT run. Missing inputs → SKIP (97)
189
- ./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
190
- ./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
191
- ./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
192
- ./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
193
- ./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
194
- ./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
195
- ./run.sh check-codex-sender-identity # Codex tools/call _meta triple agreement + addressable record join + cross-carrier conflict refusal
196
- ./run.sh check-codex-bridge-identity # real MCP bridge request identity for entwurf_self/v2/fresh; malformed or conflicting _meta fails loud
197
- ./run.sh check-pi-mcp-register # #125: mutant execution coordinate for pi-extensions/entwurf-control.test.ts — the real extension births through Pi's real loader and registers the compiled bridge after birth, before UI, direct with two hidden. Needs build-bridge
198
- ./run.sh check-pi-mcp-bridge # #125: a real Pi runtime (builtin MCP, default stdio, faux model only) spawns the COMPILED bridge as the born citizen — six prefixed verbs declared, hidden two absent, child env = record = entwurf_self, cwd = session cwd; newSession vendor conformance observed (old child gone, new record+child, old record kept). Needs build-bridge
199
- ./run.sh check-pi-bridge-sender # #125: real bridge pi-session carrier is served only when it names a readable pi RECORD; missing / foreign-backend / unreadable each refuse with their own cause; no socket = replyable:false, not refusal
200
- ./run.sh check-codex-native-push # app-server WebSocket-over-UDS probe + measured one-shot codex queue delivery; no replay
201
- ./run.sh check-codex-birth-hook # sandboxed payload + declaration: first-turn V3 birth, one record per thread, top-level event predicate, no markers
202
- ./run.sh check-codex-fresh-preflight # pre-mutation birth/MCP/thread-title/default-app-server readiness
203
- ./run.sh smoke-codex-config-state # sandboxed MCP + status-line ownership/install/doctor/inverse lifecycle
204
- ./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
205
- ./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)
206
- ./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
207
- ./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
208
- ./run.sh check-bridge-delivery # deterministic gate (IN pnpm run check:full): demo scene 3 recovered — seed strict meta-sender + armed receiver citizens in an isolated temp world, scrub ambient pi/sender carriers, drive the BUILT DIST ENTRY over MCP stdio through a real tools/call entwurf_v2, assert the .msg landed under the seeded sender + doorbell poked. DELIVERS through the artifact, not from source. ENTWURF_DELIVERY_SUBJECT=<launcher> replays the same scene against another consumer artifact (check-pack-install passes the npm-installed bin). No model/network/cost; stale or missing dist FAILS
209
- ./run.sh check-meta-mailbox-state-write # deterministic gate (0.11 Stage 0 step 3D-4 commit2): post-cut receipt is state-only — meta-record file byte-identical across enqueue/read, state carries lastEnqueuedAt/lastReadAt (field isolation), empty inbox no-op on record+state, drift surfaces; no API
210
- ./run.sh check-meta-receiver-marker # deterministic gate (SE-2): receiver marker round-trip/start-key/provenance, UserPromptSubmit cannot mint presence, reader does not gate on record existence — marker SEMANTICS only; launch topology moved to check-hook-launch-topology
211
- ./run.sh check-hook-launch-topology # #51 gate 1: shipped hooks.json is exec form through hook-launch.sh, launcher is loud on an empty argv (older Claude's silent args drop), exec preserves the pid so the hook's parent is Claude, and a space/$/backtick plugin path survives as one argv element
212
- ./run.sh check-meta-hook-session-switch # #101 gate: ONE Claude pid, TWO SessionStarts (resume picker placeholder -> resumed id). The hook retires the marker of the garden it stopped serving (records untouched, same-garden re-registration retires nothing), the reader stays fail-closed on a re-planted stale marker (watchArmed measured against the owner's sender marker, never copied), production dispatch refuses the retired garden and NAMES the failing axis, and exactly one of the two gardens is deliverable. Sandboxed roots, no API
213
- ./run.sh check-meta-identity-consumers # deterministic gate: V3-only consumer seam — per-entry targeted read + addressable read snapshot uniqueness, non-regular rivals never read, drift/unparseable rivals unreachable, unreadable regular rivals fail loud; strict upsert refuses an unreadable store before any write, no API
214
- ./run.sh check-meta-capability-source # deterministic gate (0.11 Stage 0 step 3D-3): capability-source cut-over — mint/parse read wakeMode/deliveryLevel from the registry (metaCapabilityFor, registry-driven via injection), not META_BACKEND_DESCRIPTORS; behaviour-preserving (registry ≡ const); the record.delivery slot 3D-3 preserved was deleted by 3D-4, no API
215
- ./run.sh check-socket-probe # deterministic gate (0.11 Stage 0, F3): three-valued control-socket liveness (alive|dead|indeterminate) — GC reclaims dead only, indeterminate survives; pure classify + 2-socket integration, no API
216
- ./run.sh check-project-trust-handler # deterministic gate (0.11 Stage 0, Trust 2층): project_trust handler — decideProjectTrust matrix (escape=inherited-false+interactive+trust-here→{yes,remember:true}; non-interactive→undecided; never undefined) + adapter single-writer, fake prompt, no UI
217
- ./run.sh check-entwurf-v2-contract # FROZEN entwurf_v2 contract — control-socket liveness domain is currently pi; self-fetch/native-push citizens are out of that domain, not globally unsupported; pure, no IO
218
- ./run.sh check-compaction-send-guard # deterministic gate (#111): control-socket send during Pi compaction — event-armed refuse compacting, quiet unknown non-idle refuse busy (ctx.signal is not isStreaming); no pi.sendMessage, no delivered:true; idle/live-run steer/followUp preserved; pure, no IO
219
- ./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
220
- ./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
221
- ./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
222
- ./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
223
- ./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
224
- ./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
225
- ./run.sh smoke-agy-native-push-live # PAUSED (#152): exits 2 with [entwurf:paused] before it reads LIVE or AGY_CONVERSATION_ID — not a PASS and not a SKIP; OUT of pnpm check. Open no agy conversation for it while the pause holds. Its 봉인 8 native-push round trip (real antigravity adapter + register core + runEntwurfV2) runs only after a separate change lifts the pause.
226
- ./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
227
- ./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
228
- ./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 (the native pi cell names a caller-distinct seat and tmux is asked where the pane landed, #108) -> 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 of the still-live sibling refused target-live, no window opened and no lock residue (its dormant same-id resume is deterministic-only, #147 L2). LIVE=1 ./run.sh smoke-mux-lifecycle-live
229
- ./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
230
- ./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 `herdr integration status` + one `entwurf peer-facts` + one `herdr agent list` per open, in that order (counted, not claimed), through ONE spawn call site; the four blocks each naming their own owner/observation time with no aggregate verdict; the D3=C fallback reading the activation ledger from the path its WRITER owns (XDG state, never the runtime's data root) and only when the phase is `active`, with ENTWURF_BIN and PATH still winning outright; the citizen axis alone skipping by name when no binary is reachable; every broken-evidence state a named red rather than a crash or an empty table, and a selected herdr atom that is `outdated`/`needs repair` as block [1]'s OWN red (`not installed` stays a reported skip); 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
231
- ./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
232
- ./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
233
- ./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
234
- ./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
235
- ./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
236
- ./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
237
- ./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
238
- ./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
239
- ./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
240
- ./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)
241
- ./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
242
- ./run.sh check-native-push-adapter # deterministic gate (봉인 3/8): native-push adapter leaf (antigravity) via a FAKE runner — FULL pid scan (not head -1), dead vs indeterminate, VOLATILE route re-discovery (no cache), send argv+ANTIGRAVITY_LS_ADDRESS env, non-zero exit throws, NO adapter-level retry (executor-owned), resolveNativePushAdapter fail-fast
243
- ./run.sh check-native-push-register # deterministic gate (봉인 5): registerNativeConversation (entwurf_register_native core) via fake adapter + isolated mkdtemp store — live probe→CREATE, re-register→ATTACH (same gid, cwd refreshed, no dup), not-live probe→REFUSE (throws, no record), receiver-marker abstinence (보정① source guard)
244
- ./run.sh check-native-push-paused # #152 mutant execution coordinate: run_vitest over paused.test.ts alone — dispatch, sender replyable and entwurf_register_native refuse a paused backend (antigravity) before any probe. Same file check-tests-beside-behavior already runs.
245
- ./run.sh check-chain-terminus-publication # mutant execution coordinate: run_vitest over test/chain-terminus-publication.test.ts alone — smoke-entwurf-chain-live's terminus wait ends only on a body AND inbox.signal, inside the same deadline.
246
- ./run.sh check-agy-sender-identity # deterministic gate (#46 sender lane): WHO is calling the bridge — real agy hook as a child process writes an antigravity sender marker keyed by its PARENT pid (never on upsert failure), and resolveTrustedMetaSenderIdentity over isolated stores yields 0→null / 1→identity on EITHER backend / two distinct live identities on one owner pid→THROW (never guess, never downgrade to anonymous). This is what turns an agy send from external-mcp/unknown-host into a replyable garden citizen
247
- ./run.sh check-package-source-routing # deterministic gate (#29): package-source -> install-root mapping + fail-fast routing (local/git/npm/missing/project/no-source × local+remote, self-root, resume), no backend
248
- ./run.sh new-session-id # print one fresh garden id from the generateSessionId SSOT (#50 C2: no launcher injection — the record layer is the consumer; pi mints its own session id)
249
- ./run.sh smoke-resident-garden-guard # live resident --entwurf-control garden guard (negative 0-token; SMOKE_RGG_POSITIVE=1 for positive)
250
- ./run.sh smoke-meta-async-drift # 1.0.0 meta-bridge step 1: drift sentinel — version pins + Claude binary undocumented-behavior markers (LIVE=1 adds plugin watch-arm probe)
251
- ./run.sh smoke-meta-honesty # 1.0.0 meta-bridge: honesty regression gate (#30 blockers) — doorbell counts ALL msgs honestly + hook logs failures as ERROR (best-effort, no scream). Offline/deterministic (deps: bash+node+python3)
252
- ./run.sh smoke-meta-install-state # 1.0.0 meta-bridge Phase 2: stateful install/uninstall + store-doctor regression gate. Offline/deterministic (deps: bash+node+python3)
253
- ./run.sh check-meta-doctor-oracle # 0.12.8 (#51): detection power of the release ORACLE — healthy fixture must reach `doctor: PASS`, then 21 planted defects (retired shell form, partial hand-patch, launcher bypass/repoint/provenance loss, malformed exec args, owner type drift, extra leaf/group, doorbell asyncRewake/path/timeout, no live bridge, stale receiver, ambiguous/missing cache, missing hook log/writer, failing CLI probes) must each turn it FAIL naming their own cause, plus a positive case pinning that a long-writing CLI is NOT a false negative. Offline/deterministic (deps: bash+node+python3)
254
- ./run.sh smoke-agy-install-state # agy MCP + exact permission ownership regression: isolated HOME+XDG, adopt/state/inverse, symlink refuse, truthful setup outcomes. Offline/deterministic
255
- ./run.sh smoke-setup-verdict # #86 C1+C3b aggregate setup verdict fixture: all-absent SKIP/green, pi presence+floor, detected-FAIL nonzero, copilot four-unit composition (present=independent PASS/FAIL rows, absent=zero-state SKIP), installed-mode named branch, credential store untouched. Offline/deterministic
256
- ./run.sh check-agy-permission-matrix # AGY permission CONTRACT SPACE as a literal table (55 cells): parser-state × operation × settings × ownership × precedence with stated exclusion rules; expectations are hand-written literals, never read from the SUT. Offline/deterministic (deps: python3)
257
- ./run.sh smoke-omp-fresh-live # #87 bundle C acceptance, RELEASE MUST: omp opened as ONE visible fresh sibling through the PUBLIC entwurf_fresh_call surface (never raw tmux), exact nonce callback -> garden id from the SENDER ENVELOPE -> record/backend identity -> addressed receive -> lastReadAt -> the drain visible in that same native session's own transcript. Needs LIVE=1 and spends real model turns. Self-deciding: omp outside FRESH_CALL_BACKENDS or without a mailbox rail is a protocol SKIP, which --cut reads as RED
258
- ./run.sh smoke-pi-durable-fresh-live # #129 first-admission acceptance, RELEASE MUST: real Pi opens pi-durable through entwurf_fresh_call (managed verb), exact-nonce callback into Pi, Pi→pd addressed receive drained by pd's live turn, pd→Pi dispatch relayed to the collector; pd's actual model + task-wide offering read from its native store (online sqlite backup). LIVE=1; models ENTWURF_PI_DURABLE_FRESH_MODEL / _PI_MODEL (default openai-codex/gpt-6.1-sol)
259
- ./run.sh smoke-omp-receive-live # #87 bundle B acceptance: another harness wakes an ALREADY-OPEN omp citizen, which reads its inbox and answers in the same session. Decides its own outcome from the capability registry — omp without a drainable mailbox is a protocol SKIP (no receiver unit exists to arm), which an unattended release-gate reports and `--cut` reads as RED; a registry that claims a receive rail with no acceptance body here is a FAIL
260
- ./run.sh smoke-entwurf-chain-live # LIVE cross-harness delivery chain: native Claude Code -> pi GPT -> pi ACP Sonnet -> mailbox terminus, proving sender identity/replyable at every hop and a real read receipt at the end. Prerequisites (claude on PATH, pi credentials per backend) report protocol SKIP, never a pass
261
- ./run.sh check-release-gate-outcomes # release-gate STEP OUTCOME protocol (P1): one skip exit code shared by the shell + TS halves, classifier never rounds a skip up to a pass, `--cut` refuses a MUST SKIP while a bare diagnostic stays exit 0, no LIVE smoke keeps the old exit-0 skip shape, and both real skip surfaces are INVOKED and observed to propagate the code
262
- ./run.sh check-gate-manifests # the HEAD of that qualification, on its own: runner self-test + the committed manifests validated against the origin index + the declared lane inventory. Executes ZERO committed mutants (only the self-test's synthetic fixture mutants, in tmp fixture repos) and never snapshots this repo (~20s), which is why it lives in check:hermetic while the body runs only as the optional CI schedule/manual-dispatch drift diagnostic (#144) — three of the five reds qualification ever produced in CI died right here, before a mutant gate ran (#99 B-3)
263
- ./run.sh check-gate-qualification # kill-proof qualification (the gate-of-gates): runner self-test (classifier truth table + synthetic negatives incl. wrong-reason/hang/control-red/impurity) + committed mutant manifests (scripts/mutants/*.json) run in an isolated snapshot repo under control→mutant→restore→control; the real checkout is never written. Evidence = claim IDs + killed mutant IDs, never assertion counts. Bare = the whole body (the CI schedule/dispatch drift diagnostic, #144); `--group '<argv JSON>' --receipt <abs path outside the repo>` = one affected exact-argv group, a PARTIAL receipt (development's run, #133)
264
- ./run.sh check-probe-ordering # §11-7 ordering-probe deterministic gate: raw-client SAMENESS pinned to backend.ts (sequence/args/timeouts/permission policy — the probe may never measure a lookalike), phase attribution incl. set-model, probe-mode fixture wire markers (delay honored, probeRunId REQUIRED, smoke-acp-mcp-live legacy compat), event-log door integrity (reserved keys refused at write; unknown marker name, broken sort axis, or a payload the classifier cannot judge on is MALFORMED, never a quiet event), and the §11-7 paired-verdict truth table (P0/I0 outside the space, phase-qualified D, B promotion ladder, C, A two-delay rule). Offline/deterministic; one product claim (no production prompt cutoff) is replant-qualified via scripts/mutants/probe-ordering.json, while the other assertions are direct [CHECK:*] contracts
265
- ./run.sh check-probe-cli-shim # §11-7-c B-name-snapshot PRODUCER gate: the CLI shim driven as a REAL process against fake CLIs (no API, no cost). Proves what a defect would buy — FABRICATED evidence (a malformed init is never reported as an empty name set; the boot report carries the true target path+sha256 the classifier verifies against the roster), a DESTROYED turn (byte transparency across mid-UTF8/CRLF/oversized/unterminated framing, exit-code fidelity, signal re-raise, inbound signal forwarding, stderr passthrough, stdout backpressure), and LEAKED operator state (exact-allowlist env scrub, no argv/env/prompt body in the log). Offline/deterministic; 20 direct [CHECK:*] contracts, deliberately no longer replant-qualified after #70 subtraction
266
- ./run.sh smoke-agy-statusline-state # agy ambient garden-id statusLine install/doctor/inverse regression. Offline/deterministic
267
- ./run.sh smoke-copilot-statusline-state # Copilot custom-footer install/doctor/inverse regression. Offline/deterministic
268
- ./run.sh smoke-copilot-mcp-state # Copilot MCP install/doctor/inverse regression. Offline/deterministic
269
- ./run.sh smoke-omp-bridge-state # OMP birth-extension install/doctor/inverse regression: placement, stale-writer detection, honest inverse, no-state refusal (structurally VALID as well as foreign), symlink refusal, ambiguous-agent-dir refusal (ledger M6), and a poisoned PI_CODING_AGENT_DIR that attracts no artifact. Fully sandboxed HOME/PI/XDG. Offline/deterministic
270
- ./run.sh smoke-agy-hooks-state # agy PreInvocation birth/sender hook install/doctor/inverse + direct stdin→meta-record regression. Offline/deterministic
271
- ./run.sh smoke-user-scope-citizen # 0.12.6 install-boundary: pi packages[] registration SSOT (register-pi-package.py) — idempotent + preserves unrelated + remove symmetry + fails loud, and the #86 C2 explicit ownership cells (project scope still normalizes ITS OWN stale entries; user scope refuses other owners and only takeover-user-scope moves the shared entry), plus the #110 self-checkout cells: the real `run.sh install <checkout>` drive leaves the tracked .pi/settings.json byte-identical, writes NO project-scope packages[] self-registration, and REPORTS the skip; cell 15 boots the pinned devDep pi against two stand-in checkouts and requires the --entwurf-control collision to APPEAR before asserting its absence. Offline/hermetic (deps: bash+python3+pinned pi)
272
- ./run.sh smoke-meta-prune # 1.0.0 meta-bridge Phase 4: listing-only store janitor regression gate — classify keep/orphan/stale/ambiguous, delete nothing. Offline/deterministic (deps: bash+node)
273
- ./run.sh smoke-meta-keyset-guard # 0.10.0 meta-bridge: keyset-owner guard regression — check-keyset-overlap + managed-keys SSOT (disjoint passes, collisions fail). Offline/hermetic (deps: bash+python3)
274
- ./run.sh check-meta-manifest-schema # 0.12.2 meta-bridge: CLI-version-INDEPENDENT static guard — plugin manifests pinned to the minimal keyset that validates on the lowest supported Claude (closed-schema regression that broke 0.12.1 install on floor) + desired_mcp installed-vs-clone dual-mode. Offline (deps: python3)
275
- ./run.sh smoke-claude-native-resume-live # LIVE-only: Claude Code native fresh→--resume continuity + meta-record uniqueness; proves meta-bridge records identity without touching the backend resume path
276
-
277
- ./run.sh install-meta-bridge # INTERNAL wiring leaf: setup, the source-only developer menu and doctor recovery compose it; stateful GLOBAL install (plugin + USER MCP + settings keyset, honest uninstall state)
278
- ./run.sh uninstall-meta-bridge # 1.0.0 meta-bridge Phase 2: stateful GLOBAL uninstall (restore only keys/items captured in install-state)
279
- ./run.sh doctor-meta-bridge # THE RELEASE ORACLE (#51, Linux-certified repair axis). exit 0 = every required layer was MEASURED on this Linux host: toolchain + state + plugin/MCP + resolved-artifact launch-form classification (all 3 owner hooks + doorbell static contract) + synthetic owner join + store scan + hook errors + SessionStart evidence + REQUIRED live MCP↔marker join + writer-version parity. Missing live evidence is NOT CERTIFIED (open a Claude session and re-run), never a pass; Darwin is NOT CERTIFIED and stays nonzero, on ONE narrowed reason — start-key and ppid are portable there (`ps` fallback, same string the TS core mints), so what holds the lane closed is per-process environment DISCOVERY alone, pending physical-host evidence. Detection power is held by check-meta-doctor-oracle
280
- ./run.sh copilot [args...] # #82 RAIL 7: the MANAGED Copilot launch. exec()s the vendor CLI in THIS terminal (cwd/pid/exit preserved) with COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS set for that one invocation — entwurf owns no part of your shell and writes nothing to it, but it owns the process it is about to become. Without that flag Copilot skips the extension scan SILENTLY. Refuses to launch unless the receiver unit is actually installed. Injects `--model auto` when no --model was given and `--yolo` when no explicit permission/surface policy flag was given, both BEFORE any `--`; every argument you pass is forwarded byte-identical. RUNNING THIS IS YOUR CONSENT to that profile — use plain `copilot` for stock vendor behaviour. Not tmux, not fresh-call, mints no citizen (birth is still the first prompt)
281
- ./run.sh pi-durable [args...] # #129/#130: the MANAGED durable launch. Verifies this package's pi-durable CARRIER (pi/pi-durable/carrier/, emitted deterministically from Entwurf's owned source pi/pi-durable/src) and the pi SDK set it resolves — every declared member/direct edge at exactly the pinned version — refusing by name (package-incomplete / carrier-drift / sdk-absent / sdk-mismatch, exit 3), then exec()s node under the carrier resolver with the packaged bootstrap (pi/pi-durable/bootstrap.mjs) in this terminal. A new session needs --provider <p> --model <exact catalog id> --width task-wide [--entwurf-bootstrap <{v:2,task}>]; --continue (this directory's newest session) and --resume (choose one of its sessions) take none of them. Nothing outside the package is located, installed or repaired
282
- ./run.sh install-copilot-bridge # #82: GLOBAL install of the Copilot BIRTH plugin (own marketplace root; node+entry baked into the no-argv exec string). MCP wiring and the RECEIVER extension are separate install surfaces (install-copilot-mcp, install-copilot-receive). Also retires the stale Claude unit (--keep-stale-claude-unit opts out)
283
- ./run.sh uninstall-copilot-bridge # #86 C3a: honest inverse of install-copilot-bridge from the package-owned install-state (exact qualified id + exact marketplace name/path + recorded assembly only; state deleted LAST; a failing vendor list is UNKNOWN and refuses; never --force, never the stale Claude unit)
284
- ./run.sh doctor-copilot-bridge # #82/#86: fail-loud surface for that unit — runtime axis (red = a hook that RAN and failed, or a broken/unbaked artifact; "installed with zero records" is NOT red and is reported as NOT-YET: a Copilot session is born on its FIRST PROMPT, not when the window opens, measured) + ownership axis (install-state shape/binding, marketplace path drift, UNKNOWN vendor lists; legacy no-state install = named non-green, repair = install-copilot-bridge adoption). Either axis red = red
285
- ./run.sh install-copilot-statusline # own Copilot statusLine + footer.showCustom with an install-state preimage
286
- ./run.sh uninstall-copilot-statusline # honest inverse of install-copilot-statusline
287
- ./run.sh doctor-copilot-statusline # static ownership/config/bin doctor; never claims a render receipt
288
- ./run.sh install-copilot-mcp # #82 RAIL 5: register ONE entwurf-bridge server in ~/.copilot/mcp-config.json (adopt / create / REFUSE symlink), type:local, install-state under $XDG_DATA_HOME/entwurf/copilot-mcp/
289
- ./run.sh uninstall-copilot-mcp # honest inverse of install-copilot-mcp from install-state
290
- ./run.sh doctor-copilot-mcp # static ownership/config/boot doctor; RED only when install-state exists
291
- ./run.sh install-omp-config # #87 follow-on: write the ONE operator setting omp's tool hand requires — `tools.xdev: false` in <omp agent dir>/config.yml. Owns exactly the line(s) it adds (recorded in install-state), refuses a symlinked config, refuses a config it cannot parse, and refuses an EXPLICIT operator `xdev: true` by name rather than overwriting a decision. Without it the vendor default wraps every MCP tool behind `xd://` and the doorbell announces a tool the model cannot call
292
- ./run.sh uninstall-omp-config # honest inverse from install-state: takes back exactly the recorded line(s), removes the file only when entwurf created it, REFUSES when the config changed since install
293
- ./run.sh install-omp-bridge # #87: install the OMP BIRTH extension into <omp agent dir>/extensions/entwurf-meta-omp (index.ts|js + lib + capability registry). No launcher and no bake — an omp hook is an in-process extension. Refuses when an inherited PI_CODING_AGENT_DIR/PI_CONFIG_DIR/PI_PROFILE makes the target agent dir ambiguous (ledger M6), and refuses ANY pre-existing artifact at the unit path that entwurf holds no ownership state for — a shape is not a proof of ownership
294
- ./run.sh uninstall-omp-bridge # honest inverse from install-state (exact unit dir + recorded entry; no-state host REFUSES; state deleted LAST). Records already minted are preserved
295
- ./run.sh doctor-omp-bridge # #87: runtime axis (importable unit, writer/registry parity, mint vs sender-marker errors on SEPARATE axes, scope-fence receipts, a root-grammar preflight that goes RED on a relative ENTWURF_META_* override instead of reporting on some other directory, CERTIFIED omp record count via meta-facts under the omp root policy — never a text grep, live omp processes carrying inherited PI_SESSION_ID/PI_AGENT_ID) + ownership axis. PI_CODING_AGENT_DIR is the vendor's own agent dir here and is reported as ignored, never as contamination. Zero records = NOT-YET, never red
296
- ./run.sh install-omp-receive # #87 bundle B: install the OMP RECEIVER extension into <omp agent dir>/extensions/entwurf-receive-omp. Own unit, own install-state, own doctor, own inverse. It joins the citizen BIRTH minted in the same process (sender marker for this pid + V3 record + the vendor's current session id, all three or refuse), holds an fs.watch on that citizen's mailbox signal, and rings an ANNOUNCE-ONLY doorbell via pi.sendUserMessage. It never assumes it loads after birth: extension handlers run in directory-name order and a before-sorting unit was MEASURED to see no marker, so the arm retries on a bounded ctx.setInterval cancelled with ctx.clearTimer (the vendor exposes no clearInterval)
297
- ./run.sh uninstall-omp-receive # honest inverse from install-state; records and sender identity untouched. A session that ALREADY armed keeps its marker until its process exits
298
- ./run.sh doctor-omp-receive # runtime axis (importable unit, writer parity, arm failures and doorbell failures on SEPARATE axes, who is armed RIGHT NOW through the production marker reader) + ownership axis. Zero armed receivers = NOT-YET, never red. Reports a marker for exactly what a marker proves — a live owner reached the arm emit — and never upgrades that into "a wake will happen"
299
- ./run.sh omp-receive-facts # read-only JSON projection of the omp receive rail: every receiver marker through readMetaReceiverMarker in BOTH readings (live / as-written) plus mailbox counts. The shared oracle so no consumer answers "is a doorbell held?" from a filename
300
- ./run.sh install-omp-mcp # #87 step 5: write ONE omp-native entwurf-bridge server into <omp agent dir>/mcp.json with env ENTWURF_BRIDGE_EXTERNAL_AGENT_ID=external-mcp/omp. The server key is a PINNED LITERAL, byte-identical to the Claude import's — same-key first-wins at native=100 > claude=80 is what SHADOWS the import (never disabledServers, which kills both). Adopt / create / REFUSE symlink, preimage recorded
301
- ./run.sh uninstall-omp-mcp # honest inverse from install-state (restores the preimage, or removes a file we created); the Claude import becomes effective again
302
- ./run.sh doctor-omp-mcp # ownership + config + boot doctor, plus the EFFECTIVE-source read (native-wins / native-invalid / import-wins / both-suppressed) — a configuration read, never a runtime receipt. Runtime validity and ownership are SEPARATE axes: foreign provenance, a disabledServers denylist, and a malformed entry under our key are each RED even with no install-state. tools.xdev is a RUNTIME cell: absent file/key applies the vendor default (true, no inline allowlist) and is RED while the native hand is the effective source; xdev false is ok; a covering xdevInlineDevices glob is ok-with-note
303
- ./run.sh smoke-omp-mcp-state # OMP MCP install/doctor/inverse regression incl. shadowing, the denylist refusal, target confinement + retarget refusal, and a malformed entry going RED with zero install-state. Fully sandboxed HOME/PI/XDG. Offline/deterministic
304
- ./run.sh install-copilot-receive # #82 RAIL 5: install the RECEIVER extension (user scope ~/.copilot/extensions/entwurf-receive). Owns the artifact and CHECKS the launch flag; it never sets one (a launch does — see `./run.sh copilot`). Arms per session after birth
305
- ./run.sh uninstall-copilot-receive # honest inverse from install-state; never removes a unit it did not install
306
- ./run.sh doctor-copilot-receive # artifact + digest, COPILOT_CLI_ENABLED_FEATURE_FLAGS on the LIVE copilot processes (the silent failure), live receiver markers via the production reader, receiver log. RED only when install-state exists
307
- ./run.sh install-agy-bridge # 봉인 7: agy MCP install adapter — register ONE entwurf-bridge server in the agy mcp_config (adopt file / create / REFUSE symlink), stable bin command, install-state under $XDG_DATA_HOME/entwurf/agy-bridge/
308
- ./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)
309
- ./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.
310
- ./run.sh doctor-agy-bridge # fail-loud doctor: MCP config + exact permission rule + state + live probe label
311
- ./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
312
- ./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
313
- ./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)
314
- ./run.sh install-codex-mcp # own only [mcp_servers.entwurf-bridge] in the user's Codex config
315
- ./run.sh uninstall-codex-mcp # remove/restore only the recorded MCP atom
316
- ./run.sh doctor-codex-mcp # effective config + ownership + actual bridge boot
317
- ./run.sh install-codex-statusline # add thread-title to tui.status_line for visible garden ids
318
- ./run.sh uninstall-codex-statusline # remove only the recorded status-line atom
319
- ./run.sh doctor-codex-statusline # effective visible-identity config + ownership verdict
320
- ./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)
321
- ./run.sh uninstall-codex-terminal-title # remove only the recorded terminal-title atom
322
- ./run.sh doctor-codex-terminal-title # effective caller-seat config + ownership verdict
323
- ./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
324
- ./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
325
- ./run.sh install-agy-statusline # own the agy statusLine subtree with bare entwurf-agy-statusline; preserve unrelated settings
326
- ./run.sh uninstall-agy-statusline # honest inverse from statusline install-state
327
- ./run.sh doctor-agy-statusline # fail-loud statusLine config/bin/state doctor + honest live SKIP
328
- ./run.sh install-agy-hooks # #46 agy birth imprint hook — named PreInvocation hook running bare entwurf-agy-imprint, preserving other hooks
329
- ./run.sh uninstall-agy-hooks # honest inverse of install-agy-hooks from install-state
330
- ./run.sh doctor-agy-hooks # fail-loud doctor for agy hooks.json imprint wiring
331
- ./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])
332
- ./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)
333
- ./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])
334
- ./run.sh check-remote-pair-installed # #107 rail 3, CHECKOUT-ONLY: install a caller-supplied candidate tarball (--tgz <abs>) into a sandboxed consumer prefix, check its compiled remote-pair surface, run the installed `entwurf remote-pair-receive` (usage exit 2 = twin reached), run the T2 roundtrip cells against the installed bridge+entry, and audit that the subject processes resolve every module inside the consumer prefix (with a checkout control). Never repacks; no real ssh, no model
335
- ./run.sh check-remote-pair-installed-audit # #107 rail 3: the deterministic counterpart of check-remote-pair-installed — its checkout-invisibility acceptance primitive proven on synthetic logs (real path, root boundary). In check:vitest
336
- ./run.sh remote-pair-receive # #107 rail 1: the RECEIVING half of one operator-declared remote pair. Reads ONE JSON claim {from,fromAgentId,fromCwd,target,message,wantsReply} on stdin, refuses a from/target outside the declared pair before any mutation (a scope limit under the same-operator SSH account trust model, not authentication), then hands a match to the existing v2 dispatch. Ambient sender carriers are never read. Installed, run_ts runs its compiled twin (dist/scripts/remote-pair-receive.js). EXIT: 0 dispatched / 4 dispatched, the dispatch reported an error (delivery not inferred) / 3 pair refused / 2 invalid claim or declaration (JSON receipt) or wrong argv (usage on stderr, no receipt) / 1 uncaught dispatch or store throw (no receipt; the sender reads it as indeterminate) (--pair <absolute declaration file>)
337
- ./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])
338
- ./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)
339
- ./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)
340
- ./run.sh check-dep-versions # local deterministic check that the pi pin agrees across the durable pin's SDK set, package.json (exact production dependencies, no Earendil dev/peer duplicate), run.sh (install pins), the workspace closure and the baseline docs (README/ROADMAP/setup-clean-host/demo/VERIFY/herdr/acp)
341
- ./run.sh check-node-floor-coherence # binds the Node floor (24+, single axis) across engines.node, run.sh setup preflight, meta-bridge install/doctor judgment logic, clean-host docs, the bridge launcher header, and the CI runner node-version — engines.node is the SSOT, everything else is derived; sweeps tracked contract text for an unregistered declaration
342
- ./run.sh check-pack # publish gate (dry-run): npm pack --dry-run + tarball invariants (runtime-critical present, dev residue absent)
343
- ./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 (a prefix-extended @0.86.0-beta.1 and an off-pin @0.85.1 must leak, @0.86.0 bare or with any 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
344
- ./run.sh check-pack-argv-matcher # pure self-test of check-pack-install's dispatcher-verb leak refusal (the copilot and codex-app-server cells): a front-loaded or trailing leak in ~260 KB is refused where the retired printf | grep -qF shape misses it (teeth control measured each run), clean output passes silently, a failing grep is refused by name, and both cells still return through it; snapshot-safe qualification oracle, also run first inside check-pack-install
345
- ./run.sh check-pack-consumer-roots # pure self-test of check-pack-install's consumer sandbox: under a poisoned inherited HOME/XDG/PI_CODING_AGENT_DIR every writable root a consumer subcall sees resolves inside its own consumer home; snapshot-safe qualification oracle, also run first inside check-pack-install
346
- ./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
347
- ./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 SDK (pins derived from the package.json exact production dependency; 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) + the INSTALLED #129 durable bootstrap (pi/pi-durable/bootstrap.mjs) imported from node_modules: main/openDurableCitizen exported and PACKAGED_BRIDGE_ENTRY = the installed package's own dist entry — import only, no runtime/TUI/birth/bridge started + the #130 pi-durable CARRIER on actual npm consumers (Entwurf-only / aligned host / isolated global): the installed verifier, a consumer-contained resolution oracle with a same-sandbox neighbour control, every physical SDK edge at the pin, a mixed tree refused as pi-durable-sdk-mismatch though it still imports, and the public `entwurf pi-durable` reaching the app's own explicit-model refusal before any birth, also with one explicit `--native-module` (the synthetic fixture, initialized first; a reserved extension name refused before anything opens) (offline, sandbox HOME)
348
- ./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)
349
- ./run.sh install [project-dir] # INTERNAL wiring leaf: setup/npm-consumer entry and the source-only developer menu compose it; prefer those owning procedures
350
- ./run.sh remove [project-dir] # remove entwurf entries from project .pi/settings.json (project scope only; global user-scope citizen left intact)
351
- ./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
352
- ./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
353
- ./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. With NO ledger it removes nothing: a clean host exits 0, and anything found at the plugin's journal/runtime/cache addresses is named with a non-zero exit (#135). Static imports only: the process deletes the runtime it is running from, and a lazy import after that fails
354
- ./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)
355
- ./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
356
- ./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
357
-
358
- Notes:
359
- - project-dir defaults to current directory
360
- - Claude Code login should already exist (e.g. ~/.claude.json)
361
- - setup's runtime verification is the v2 install smoke (entwurf-bridge); the v2 dispatch substrate is proven live by release-gate
362
- - API key is optional; this bridge is intended to work with Claude Code auth
363
- EOF
165
+ # The text lives in root ENTWURF-CLI.json, its one editable source; scripts/cli-help.mjs renders
166
+ # it with plain `node` from the bytes this checkout or package carries. A missing or malformed
167
+ # source fails here by name — there is no second copy of the text to fall back to.
168
+ node "$REPO_DIR/scripts/cli-help.mjs"
364
169
  }
365
170
 
366
171
  require_cmd() {
@@ -1221,6 +1026,14 @@ check_pi_launch() {
1221
1026
  run_ts scripts/check-pi-launch.ts
1222
1027
  }
1223
1028
 
1029
+ check_claude_launch() {
1030
+ # #157 stage 4. The same fake-vendor oracle as check-pi-launch: a real executable named `claude`
1031
+ # on a sandbox PATH reports the argv, cwd, env and pid it was handed, driven through the public
1032
+ # `run.sh claude`. A process replacement has no beside-test home — its subject is this
1033
+ # dispatcher's arm, which the vitest globs do not reach — so it is a spawning gate here.
1034
+ run_ts scripts/check-claude-launch.ts
1035
+ }
1036
+
1224
1037
  check_codex_app_server_launch() {
1225
1038
  # #95: the managed app-server SPELLING, proved against a fake vendor. There is no second
1226
1039
  # spelling of the address to compare any more — the launcher asks `codex-socket-path` — so
@@ -1613,8 +1426,15 @@ check_entwurf_v2_visible_resume() {
1613
1426
  # beside-behaviour test seventeen times. It stays inside check:contracts even though the
1614
1427
  # discovery door also runs this file — see check-release-gate-outcomes: a gate a mutant names
1615
1428
  # must be reachable outside qualification.
1616
- section "visible same-id resume (mutant execution coordinate)"
1617
- run_vitest pi-extensions/lib/entwurf-v2-visible-resume.test.ts
1429
+ #
1430
+ # #157 G1a: the herdr launch of a pi resume (herdr-resume-call.ts) is the other half of this
1431
+ # seam, and its mutants name THIS coordinate rather than a new gate verb — a new run.sh command
1432
+ # would be one more undescribed name for check-install-surface S9. #157 B3: the tmux leaf's
1433
+ # pi-durable window (mux-resume-call.test.ts) joins it for the same reason. #157 S3 joint review:
1434
+ # the owner fence's release-failure facts the pi-durable resume reports (pi-durable-release-failure.test.ts)
1435
+ # join it too, rather than the glob shim's every-test replay per mutant. Named files, no glob.
1436
+ section "visible same-id resume + its herdr and tmux launches (mutant execution coordinate)"
1437
+ run_vitest pi-extensions/lib/entwurf-v2-visible-resume.test.ts pi-extensions/lib/herdr-resume-call.test.ts pi-extensions/lib/mux-resume-call.test.ts pi-extensions/lib/pi-durable-release-failure.test.ts
1618
1438
  }
1619
1439
 
1620
1440
  check_resume_launch_identity() {
@@ -1687,6 +1507,12 @@ check_mux_fresh_call() {
1687
1507
  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 test/pi-durable-fresh-live-receipts.test.ts test/codex-socket-listener.test.ts
1688
1508
  }
1689
1509
 
1510
+ check_agent_guidance_beside() {
1511
+ # #154: mutation execution coordinate only; the beside-behavior glob already discovers it.
1512
+ # Keep the existing run_vitest reporter/attribution, without a build or package lifecycle.
1513
+ run_vitest pi-extensions/lib/agent-guidance.test.ts
1514
+ }
1515
+
1690
1516
  check_pi_durable_beside() {
1691
1517
  # #129: the pi-durable qualification lane's execution coordinate (VERIFY 「Four rules」 rule 3). It is
1692
1518
  # not a discovery path — check-tests-beside-behavior already finds these files. It exists because the
@@ -2209,7 +2035,15 @@ check_herdr_fresh_call() {
2209
2035
  # reason check-mux-placement refuses a fake tmux. Payload literals are verbatim herdr
2210
2036
  # 0.9.0 output (pane/tab replies 2026-09-15, agent_started 2026-09-14); the real-binary
2211
2037
  # half is an isolated private server (c2).
2212
- run_ts scripts/check-herdr-fresh-call.ts
2038
+ #
2039
+ # #157 A-L1: pi-durable's herdr LAYOUT branch (one layout.apply on the caller's own socket) is
2040
+ # proven beside its module, and its mutants name THIS coordinate rather than a new gate verb —
2041
+ # a new run.sh command would be one more undescribed name for check-install-surface S9. The
2042
+ # legacy script runs FIRST and returns on its own failure, so its mutants keep the failure-line
2043
+ # attribution; only when it passes does the beside file run, whose kills are attributed from
2044
+ # its JSON test titles (run.sh:104-113). One named file, no glob.
2045
+ run_ts scripts/check-herdr-fresh-call.ts || return $?
2046
+ run_vitest pi-extensions/lib/herdr-layout-fresh-call.test.ts
2213
2047
  }
2214
2048
 
2215
2049
  check_herdr_sandbox() {
@@ -2859,7 +2693,7 @@ const SITES = [
2859
2693
  ['pi/meta-bridge/entwurf-meta-receive/scripts/hook-launch.sh', /Claude Code >= (\d+\.\d+\.\d+)/g, 1, 'launcher refusal message'],
2860
2694
  ['scripts/meta-bridge-claude-floor.sh', /THE FLOOR IS (\d+\.\d+\.\d+)/g, 1, 'floor helper rationale header'],
2861
2695
  ['docs/setup-clean-host.md', /`>=(\d+\.\d+\.\d+)`\*\* — the exec-form hook floor/g, 1, 'clean-host pin matrix'],
2862
- ['README.md', /supported floor `>=(\d+\.\d+\.\d+)`/g, 1, 'README doctor description'],
2696
+ ['docs/setup-clean-host.md', /supported floor `>=(\d+\.\d+\.\d+)`/g, 1, 'clean-host doctor description'],
2863
2697
  ['scripts/check-hook-launch-topology.ts', /\/(\d+)\\\.(\d+)\\\.(\d+)\//g, 1, 'topology gate floor assertion'],
2864
2698
  ];
2865
2699
  let bound = 0;
@@ -3886,6 +3720,11 @@ check_pack() {
3886
3720
  local required=(
3887
3721
  "package.json" "README.md" "LICENSE" "CHANGELOG.md"
3888
3722
  "protocol.js" "run.sh"
3723
+ # #153 — `entwurf --help` renders from these two at run time and run.sh keeps no copy of the
3724
+ # text to fall back to: without either one the installed CLI cannot describe itself.
3725
+ "ENTWURF-CLI.json" "scripts/cli-help.mjs"
3726
+ # #157 — the files the shipped guide topics point at (`entwurf help team` / `help remote-pair`).
3727
+ "team.json.example" "docs/setup-clean-host.md"
3889
3728
  "pi-extensions/acp-provider.ts"
3890
3729
  "pi-extensions/lib/acp/models.ts" "pi-extensions/lib/acp/model-ids.js" "pi-extensions/lib/acp/backend.ts"
3891
3730
  "pi-extensions/lib/acp/overlay.ts" "pi-extensions/lib/acp/tool-surface.ts"
@@ -3958,6 +3797,7 @@ check_pack() {
3958
3797
  "pi/pi-durable/carrier/harness-setup.js"
3959
3798
  "pi/pi-durable/carrier/prompt.js"
3960
3799
  "pi/pi-durable/carrier/sessions.js"
3800
+ "pi/pi-durable/carrier/session-name.js"
3961
3801
  "pi/pi-durable/carrier/subagent.js"
3962
3802
  "pi/pi-durable/carrier/LICENSE"
3963
3803
  "pi/meta-bridge-omp/entwurf-meta-omp/package.json"
@@ -4422,9 +4262,9 @@ process.exit(ok ? 0 : 1);
4422
4262
  ORACLE
4423
4263
 
4424
4264
  mkdir -p "$box/pd-aligned" "$box/pd-global" "$box/pd-mismatch"
4425
- out=$(cd "$box/pd-aligned" && npm install "$tgz" "${host_specs[@]}" --no-audit --no-fund 2>&1) || {
4265
+ out=$(cd "$box/pd-aligned" && npm install "$tgz" "${host_specs[@]}" --ignore-scripts --no-audit --no-fund 2>&1) || {
4426
4266
  fail "[check-pack-install] pi-durable L1 (aligned host) install failed:"; echo "$out" | tail -10 | sed 's/^/ /' >&2; return 1; }
4427
- out=$(cd "$box" && npm install -g --prefix "$box/pd-global" "$tgz" --no-audit --no-fund 2>&1) || {
4267
+ out=$(cd "$box" && npm install -g --prefix "$box/pd-global" "$tgz" --ignore-scripts --no-audit --no-fund 2>&1) || {
4428
4268
  fail "[check-pack-install] pi-durable L2 (isolated global) install failed:"; echo "$out" | tail -10 | sed 's/^/ /' >&2; return 1; }
4429
4269
 
4430
4270
  for cell in L1s L1 L2; do
@@ -4453,7 +4293,7 @@ ORACLE
4453
4293
  # it imports. pi-codemode 1.3.0 loads, and depends on no SDK member, so this tree carries exactly one
4454
4294
  # depth-2 mismatch (L4 keeps depth 3).
4455
4295
  printf '%s\n' "{\"name\":\"pd-mismatch\",\"version\":\"1.0.0\",\"private\":true,\"overrides\":{\"@earendil-works/pi-durable\":{\"@earendil-works/pi-codemode\":\"1.3.0\"}}}" > "$box/pd-mismatch/package.json"
4456
- out=$(cd "$box/pd-mismatch" && npm install "$tgz" --no-audit --no-fund 2>&1) || {
4296
+ out=$(cd "$box/pd-mismatch" && npm install "$tgz" --ignore-scripts --no-audit --no-fund 2>&1) || {
4457
4297
  fail "[check-pack-install] pi-durable L3 (mismatch control) install failed:"; echo "$out" | tail -10 | sed 's/^/ /' >&2; return 1; }
4458
4298
  pkg="$box/pd-mismatch/node_modules/@junghanacs/entwurf"
4459
4299
  rc=0; out=$(cd "$box" && node "$pkg/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-runtime.js" resolve 2>&1) || rc=$?
@@ -4582,7 +4422,7 @@ ORACLE
4582
4422
  local pin_ceiling="${pin_ver%%.*}.$((pin_minor + 1))"
4583
4423
  mkdir -p "$host_old"
4584
4424
  for spec in "${host_specs[@]}"; do host_old_specs+=("${spec%@*}@$host_old_ver"); done
4585
- out=$(cd "$host_old" && npm install "${host_old_specs[@]}" --no-audit --no-fund 2>&1) || {
4425
+ out=$(cd "$host_old" && npm install "${host_old_specs[@]}" --ignore-scripts --no-audit --no-fund 2>&1) || {
4586
4426
  fail "[check-pack-install] could not install the previous-host pi fixture ($host_old_ver):"; echo "$out" | tail -10 | sed 's/^/ /' >&2; return 1; }
4587
4427
  for cell in old aligned; do
4588
4428
  host_home="$box/pd-host-$cell-home"; host_proj="$box/pd-host-$cell-proj"
@@ -4616,6 +4456,163 @@ ORACLE
4616
4456
  # outside the sandbox (#125, measured 2026-10-01: an inherited agent dir received the npm
4617
4457
  # consumer's settings.json while the gate looked under the temp HOME). Every root is named here,
4618
4458
  # none is left to the caller's environment. One NAME=value per line; read with mapfile.
4459
+ # #153 — the operator entrance on the actual npm consumer. The pnpm self-delete cell calls the
4460
+ # deactivate script by absolute node path; this one goes the operator's way: the INSTALLED runtime's
4461
+ # own bin exposes one `entwurf` into a bin dir first on PATH, that bare name answers help and
4462
+ # withdraw, and the bare deactivate takes the link back with the runtime and the ledger. Journal,
4463
+ # ledger and roots are seeded fixture history: no Pi wiring is made or measured, component teardown
4464
+ # stays the source HAC gate's evidence, and no cache is seeded, so nothing here measures cache removal.
4465
+ # Every call — the seeding and fact-reading node included — runs under env -i with the six consumer
4466
+ # roots, a sandbox cwd and PATH = that bin dir then ten named tools (what run.sh, start.sh and the
4467
+ # bridge's test.sh call), so no identity carrier, NODE_OPTIONS/NODE_PATH or host `entwurf` can answer
4468
+ # instead. The whole helper runs under `||`, where errexit is off, so every write and read below
4469
+ # fails by name. Step files under $o/steps last only until the parent's RETURN trap cleans up; a
4470
+ # failing step prints its raw files, uncut, to the gate log before returning.
4471
+ pack_install_operator_run() { # dynamic scope: o B T s A R L J opl_env of pack_install_operator_cells
4472
+ (cd "$o/cwd" && env -i "PATH=$B:$T" "${opl_env[@]}" "$@")
4473
+ }
4474
+
4475
+ pack_install_operator_facts() {
4476
+ pack_install_operator_run "$T/node" -e '
4477
+ const fs = require("fs");
4478
+ const [link, R, L, J, root] = process.argv.slice(1);
4479
+ const st = (p) => fs.lstatSync(p, { throwIfNoEntry: false });
4480
+ const read = (p) => (st(p) ? JSON.parse(fs.readFileSync(p, "utf8")) : null);
4481
+ const r = read(R), l = read(L), k = st(link);
4482
+ console.log([
4483
+ "link=" + (k ? (k.isSymbolicLink() ? fs.readlinkSync(link) : "not-a-symlink") : "absent"),
4484
+ "receipt=" + (r ? [Object.keys(r).sort().join(","), r.schemaVersion, r.phase, r.binDir, r.linkPath, r.target, r.runtimeRoot].join("|") : "absent"),
4485
+ "ledger=" + (l ? [l.schemaVersion, l.phase, l.components.map((c) => c.backend + ":" + c.state).join(",")].join("|") : "absent"),
4486
+ "journal=" + (st(J) ? "present" : "absent"),
4487
+ "runtime=" + (st(root) ? "present" : "absent"),
4488
+ ].join("\n"));' "$B/entwurf" "$R" "$L" "$J" "${A%/active}"
4489
+ }
4490
+
4491
+ pack_install_operator_dump() { # $1=step
4492
+ local f
4493
+ for f in "$s/$1".{want,rc,out,err,facts}; do
4494
+ [ -e "$f" ] || continue
4495
+ echo " --- ${f##*/}"
4496
+ cat "$f"
4497
+ done >&2
4498
+ }
4499
+
4500
+ pack_install_operator_step() { # $1=step, rest=argv; the argv's own rc is data, recording it is not
4501
+ local name="$1" rc=0
4502
+ shift
4503
+ if ! { : >"$s/$name.out" && : >"$s/$name.err"; }; then
4504
+ fail "[check-pack-install] #153 operator entrance step $name: cannot open its stream files"
4505
+ return 1
4506
+ fi
4507
+ pack_install_operator_run "$@" >"$s/$name.out" 2>"$s/$name.err" || rc=$?
4508
+ if ! { echo "$rc" >"$s/$name.rc" && pack_install_operator_facts >"$s/$name.facts"; }; then
4509
+ fail "[check-pack-install] #153 operator entrance step $name: recording its rc or facts failed (rc=$rc)"
4510
+ pack_install_operator_dump "$name"
4511
+ return 1
4512
+ fi
4513
+ }
4514
+
4515
+ pack_install_operator_expect() { # $1=step $2=rc $3=facts [$4=stdout lines, else $s/$1.want]; rc 0 wants empty stderr
4516
+ if [ $# -ge 4 ] && ! printf '%s\n' "$4" >"$s/$1.want"; then
4517
+ fail "[check-pack-install] #153 operator entrance step $1: cannot write its expected stdout"
4518
+ pack_install_operator_dump "$1"
4519
+ return 1
4520
+ fi
4521
+ if [ "$(cat "$s/$1.rc")" = "$2" ] && cmp -s "$s/$1.want" "$s/$1.out" && [ "$(cat "$s/$1.facts")" = "$3" ] \
4522
+ && { [ "$2" != 0 ] || [ ! -s "$s/$1.err" ]; }; then
4523
+ return 0
4524
+ fi
4525
+ fail "[check-pack-install] #153 operator entrance step $1 — want rc=$2, stdout = $1.want, and facts:"
4526
+ sed 's/^/ /' <<<"$3" >&2
4527
+ pack_install_operator_dump "$1"
4528
+ return 1
4529
+ }
4530
+
4531
+ pack_install_operator_cells() {
4532
+ local npm_tmp="$1" npmroot="$2" help_dir="$3"
4533
+ local o="$npm_tmp/operator" B T s A R L J linked receipt facts_linked facts_gone before after
4534
+ T="$o/tools" s="$o/steps"
4535
+ A="$o/.local/share/entwurf/herdr-plugin/runtime/active" J="$o/.local/share/entwurf/herdr-plugin/journal.json"
4536
+ R="$o/.local/state/entwurf/herdr-plugin/operator-link.json" L="$o/.local/state/entwurf/herdr-plugin/activation.json"
4537
+ local opl_env=()
4538
+ mapfile -t opl_env < <(pack_install_consumer_env "$o")
4539
+ if ! { [ "${#opl_env[@]}" -eq 6 ] && mkdir -p "$o/bin" "$T" "$s" "$o/cwd" "$A" "${L%/*}" && B=$(cd -P "$o/bin" && pwd) \
4540
+ && (for tool in bash node dirname readlink mktemp env grep tail python3 rm; do
4541
+ p=$(command -v "$tool") && ln -s "$p" "$T/$tool" || exit 1
4542
+ done) \
4543
+ && cp -R "$npmroot/node_modules" "$A/node_modules" \
4544
+ && pack_install_operator_run "$T/node" -e 'const fs=require("fs"),path=require("path");const [home,active,journal,ledger]=process.argv.slice(1);const version=JSON.parse(fs.readFileSync(path.join(active,"node_modules","@junghanacs","entwurf","package.json"),"utf8")).version;const artifactIdentity={kind:"herdr-checkout",repository:"junghan0611/entwurf",commit:"c".repeat(40),packageName:"@junghanacs/entwurf",packageVersion:version,observedDigest:"sha256-"+"a".repeat(64)};fs.writeFileSync(journal,JSON.stringify({schemaVersion:2,phase:"runtime-ready",runtimeRoot:active,artifactIdentity,previousRuntime:null}));fs.writeFileSync(ledger,JSON.stringify({schemaVersion:2,phase:"active",runtimeRoot:active,artifactIdentity,piAgentDir:{path:path.join(home,".pi","agent"),source:"PI_CODING_AGENT_DIR"},claudeConfigDir:{path:path.join(home,".claude"),source:"default"},claudeUserConfig:{path:path.join(home,".claude.json"),source:"HOME"},activatedBackends:["pi"],components:[{backend:"pi",state:"active"}]}));' "$o" "$A" "$J" "$L"; }; then
4545
+ fail "[check-pack-install] #153 operator entrance setup (sandbox, ten tools, runtime copy, seeded history) failed"
4546
+ return 1
4547
+ fi
4548
+
4549
+ linked="$A/node_modules/.bin/entwurf"
4550
+ receipt="binDir,linkPath,phase,runtimeRoot,schemaVersion,target|1|linked|$B|$B/entwurf|$linked|$A"
4551
+ facts_linked=$(printf 'link=%s\nreceipt=%s\nledger=3|active|pi:active\njournal=present\nruntime=present' "$linked" "$receipt")
4552
+ facts_gone=$'link=absent\nreceipt=absent\nledger=3|active|pi:active\njournal=present\nruntime=present'
4553
+
4554
+ pack_install_operator_step 01-expose "$linked" herdr-plugin-expose-operator --bin-dir "$B" || return 1
4555
+ pack_install_operator_expect 01-expose 0 "$facts_linked" "[herdr-operator-link] linked $B/entwurf -> $linked" || return 1
4556
+ pack_install_operator_step 02-help entwurf --help || return 1
4557
+ if ! cp "$help_dir/checkout.out" "$s/02-help.want"; then
4558
+ fail "[check-pack-install] #153 operator entrance step 02-help: cannot copy the checkout's help bytes"
4559
+ pack_install_operator_dump 02-help
4560
+ return 1
4561
+ fi
4562
+ pack_install_operator_expect 02-help 0 "$facts_linked" || return 1
4563
+ pack_install_operator_step 03-checkout-command-help bash "$REPO_DIR/run.sh" help herdr-plugin-expose-operator || return 1
4564
+ if [ "$(cat "$s/03-checkout-command-help.rc")" != 0 ] || [ ! -s "$s/03-checkout-command-help.out" ]; then
4565
+ fail "[check-pack-install] #153 checkout \`run.sh help herdr-plugin-expose-operator\` gave no reference bytes"
4566
+ pack_install_operator_dump 03-checkout-command-help
4567
+ return 1
4568
+ fi
4569
+ pack_install_operator_step 03-command-help entwurf help herdr-plugin-expose-operator || return 1
4570
+ if ! cp "$s/03-checkout-command-help.out" "$s/03-command-help.want"; then
4571
+ fail "[check-pack-install] #153 operator entrance step 03-command-help: cannot copy the checkout's command help"
4572
+ pack_install_operator_dump 03-command-help
4573
+ return 1
4574
+ fi
4575
+ pack_install_operator_expect 03-command-help 0 "$facts_linked" || return 1
4576
+ pack_install_operator_step 04-withdraw entwurf herdr-plugin-withdraw-operator || return 1
4577
+ pack_install_operator_expect 04-withdraw 0 "$facts_gone" "[herdr-operator-link] withdrew $B/entwurf" || return 1
4578
+ pack_install_operator_step 05-expose-again "$linked" herdr-plugin-expose-operator --bin-dir "$B" || return 1
4579
+ pack_install_operator_expect 05-expose-again 0 "$facts_linked" "[herdr-operator-link] linked $B/entwurf -> $linked" || return 1
4580
+
4581
+ # Fixture transition: the components are recorded removed, as a finished component teardown leaves them.
4582
+ if ! pack_install_operator_run "$T/node" -e 'const fs=require("fs");const p=process.argv[1];const l=JSON.parse(fs.readFileSync(p,"utf8"));l.phase="deactivating";l.components=[{backend:"pi",state:"removed"}];fs.writeFileSync(p,JSON.stringify(l));' "$L"; then
4583
+ fail "[check-pack-install] #153 operator entrance: the fixture transition to deactivating/pi:removed failed"
4584
+ return 1
4585
+ fi
4586
+ pack_install_operator_step 06-deactivate entwurf herdr-plugin-deactivate || return 1
4587
+ pack_install_operator_expect 06-deactivate 0 $'link=absent\nreceipt=absent\nledger=absent\njournal=absent\nruntime=absent' \
4588
+ $'[herdr-plugin-deactivate] preflight-all ok (nothing left to undo)\n[herdr-plugin-deactivate] done: operator-link -> runtime -> ledger' || return 1
4589
+
4590
+ # No ledger: a certified receipt and its (now dangling) link are named leftovers, by the SURVIVING
4591
+ # original install — the bin that exposed them deleted itself above — and nothing is removed.
4592
+ if ! { mkdir -p "${R%/*}" \
4593
+ && printf '{"schemaVersion":1,"phase":"linked","binDir":"%s","linkPath":"%s/entwurf","target":"%s","runtimeRoot":"%s"}\n' "$B" "$B" "$linked" "$A" >"$R" \
4594
+ && ln -s "$linked" "$B/entwurf" \
4595
+ && before=$(pack_install_operator_facts && sha256sum "$R" && ls -A "$B" "${R%/*}"); }; then
4596
+ fail "[check-pack-install] #153 operator entrance: seeding the no-ledger receipt/link or its before-snapshot failed"
4597
+ return 1
4598
+ fi
4599
+ pack_install_operator_step 07-orphan "$npmroot/node_modules/.bin/entwurf" herdr-plugin-deactivate || return 1
4600
+ if ! after=$(pack_install_operator_facts && sha256sum "$R" && ls -A "$B" "${R%/*}"); then
4601
+ fail "[check-pack-install] #153 operator entrance: the no-ledger after-snapshot failed"
4602
+ pack_install_operator_dump 07-orphan
4603
+ return 1
4604
+ fi
4605
+ if [ "$(cat "$s/07-orphan.rc")" != 1 ] || [ "$before" != "$after" ] \
4606
+ || ! grep -qF "deactivate-unattributed-leftovers" "$s/07-orphan.err" || ! grep -qF "operator-link-receipt ($R)" "$s/07-orphan.err" \
4607
+ || ! grep -qF "operator-link ($B/entwurf)" "$s/07-orphan.err"; then
4608
+ fail "[check-pack-install] #153 no-ledger operator leftovers were not a named exit 1 with nothing removed:"
4609
+ { echo " --- before"; echo "$before"; echo " --- after"; echo "$after"; } >&2
4610
+ pack_install_operator_dump 07-orphan
4611
+ return 1
4612
+ fi
4613
+ echo "[check-pack-install] #153 operator entrance on the npm consumer: installed expose -> bare help/withdraw -> expose -> bare deactivate took link, runtime and ledger back; no-ledger leftovers named by the surviving install"
4614
+ }
4615
+
4619
4616
  pack_install_consumer_env() {
4620
4617
  local h="$1"
4621
4618
  printf '%s\n' \
@@ -4758,6 +4755,8 @@ _check_pack_install_impl() {
4758
4755
  local tar_required=(
4759
4756
  "package.json" "README.md" "LICENSE" "CHANGELOG.md"
4760
4757
  "protocol.js" "run.sh"
4758
+ "ENTWURF-CLI.json" "scripts/cli-help.mjs"
4759
+ "team.json.example" "docs/setup-clean-host.md"
4761
4760
  "pi-extensions/acp-provider.ts"
4762
4761
  "pi-extensions/lib/acp/models.ts" "pi-extensions/lib/acp/model-ids.js" "pi-extensions/lib/acp/backend.ts"
4763
4762
  "pi-extensions/lib/acp/overlay.ts" "pi-extensions/lib/acp/tool-surface.ts"
@@ -4819,6 +4818,7 @@ _check_pack_install_impl() {
4819
4818
  "pi/pi-durable/carrier/harness-setup.js"
4820
4819
  "pi/pi-durable/carrier/prompt.js"
4821
4820
  "pi/pi-durable/carrier/sessions.js"
4821
+ "pi/pi-durable/carrier/session-name.js"
4822
4822
  "pi/pi-durable/carrier/subagent.js"
4823
4823
  "pi/pi-durable/carrier/LICENSE"
4824
4824
  "pi/meta-bridge-omp/entwurf-meta-omp/package.json"
@@ -5240,14 +5240,14 @@ _check_pack_install_impl() {
5240
5240
  fi
5241
5241
  local npmroot="$npm_tmp/npmroot" npmhome="$npm_tmp/npmhome" npmproj="$npm_tmp/npmproj" npm_log npm_pkg wire_log
5242
5242
  mkdir -p "$npmroot" "$npmhome" "$npmproj"
5243
- npm_log=$(cd "$npmroot" && npm install "$tgz_path" --no-audit --no-fund 2>&1) || {
5243
+ npm_log=$(cd "$npmroot" && npm install "$tgz_path" --ignore-scripts --no-audit --no-fund 2>&1) || {
5244
5244
  fail "[check-pack-install] npm-managed neutral install failed:"
5245
5245
  echo "$npm_log" | tail -10 | sed 's/^/ /' >&2
5246
5246
  return 1
5247
5247
  }
5248
5248
  npm_pkg="$npmroot/node_modules/@junghanacs/entwurf"
5249
5249
  if [ ! -x "$npm_pkg/run.sh" ]; then
5250
- fail "[check-pack-install] npm-managed layout missing executable run.sh (postinstall-chmod did not run?) at $npm_pkg"
5250
+ fail "[check-pack-install] npm-managed layout installed with --ignore-scripts: executable run.sh is missing at $npm_pkg"
5251
5251
  return 1
5252
5252
  fi
5253
5253
  if [ ! -x "$npmroot/node_modules/.bin/entwurf" ] || [ ! -x "$npmroot/node_modules/.bin/entwurf-bridge" ] || [ ! -x "$npmroot/node_modules/.bin/entwurf-statusline" ] || [ ! -x "$npmroot/node_modules/.bin/entwurf-agy-statusline" ] || [ ! -x "$npmroot/node_modules/.bin/entwurf-agy-imprint" ]; then
@@ -5280,6 +5280,87 @@ _check_pack_install_impl() {
5280
5280
  fi
5281
5281
  echo "[check-pack-install] npm-managed install regression pass (hoisted-dep run.sh install wrote settings)"
5282
5282
 
5283
+ # #153/#157 — the installed bin describes itself from the description data and renderer the
5284
+ # tarball carries (cli-help.mjs reads only module-relative bytes). Three separate facts:
5285
+ # 1. Byte parity, root/catalog/topics: the consumer's `entwurf --help` (the short root page),
5286
+ # `entwurf help all` (the full catalog) and `entwurf help team` / `help remote-pair` (the two
5287
+ # guide topics) must each be exactly what the checkout renders, on stdout, with an empty
5288
+ # stderr. Streams stay apart and are compared as bytes.
5289
+ # 2. Installed-copy negatives, on root `--help` only: a changed installed root title shows up in
5290
+ # the installed help, and a removed installed renderer fails it with nothing on stdout, so the
5291
+ # answer comes from THIS consumer's installed files, not from the checkout still visible on
5292
+ # this host. Both files are restored and compared back before anything is judged.
5293
+ # 3. Packaged guide references present: team.json.example (byte-equal to the checkout) and
5294
+ # docs/setup-clean-host.md with its section 2c. The user files a guide describes (a project's
5295
+ # team.json, a host's entwurf-remote-pair.json) are the operator's own; nothing installs them.
5296
+ local help_dir="$npm_tmp/cli-help" help_bin="$npmroot/node_modules/.bin/entwurf"
5297
+ local help_json="$npm_pkg/ENTWURF-CLI.json" help_mjs="$npm_pkg/scripts/cli-help.mjs"
5298
+ local help_rc help_co_rc help_all_rc help_all_co_rc help_title_rc help_gone_rc help_restored=1
5299
+ local help_topic help_topic_rc help_topic_co_rc
5300
+ mkdir -p "$help_dir"
5301
+ if env "${consumer_env[@]}" bash "$REPO_DIR/run.sh" --help >"$help_dir/checkout.out" 2>"$help_dir/checkout.err"; then help_co_rc=0; else help_co_rc=$?; fi
5302
+ if (cd "$npmproj" && env "${consumer_env[@]}" "$help_bin" --help) >"$help_dir/installed.out" 2>"$help_dir/installed.err"; then help_rc=0; else help_rc=$?; fi
5303
+ if env "${consumer_env[@]}" bash "$REPO_DIR/run.sh" help all >"$help_dir/checkout-all.out" 2>"$help_dir/checkout-all.err"; then help_all_co_rc=0; else help_all_co_rc=$?; fi
5304
+ if (cd "$npmproj" && env "${consumer_env[@]}" "$help_bin" help all) >"$help_dir/installed-all.out" 2>"$help_dir/installed-all.err"; then help_all_rc=0; else help_all_rc=$?; fi
5305
+ for help_topic in team remote-pair; do
5306
+ if env "${consumer_env[@]}" bash "$REPO_DIR/run.sh" help "$help_topic" >"$help_dir/checkout-$help_topic.out" 2>"$help_dir/checkout-$help_topic.err"; then help_topic_co_rc=0; else help_topic_co_rc=$?; fi
5307
+ if (cd "$npmproj" && env "${consumer_env[@]}" "$help_bin" help "$help_topic") >"$help_dir/installed-$help_topic.out" 2>"$help_dir/installed-$help_topic.err"; then help_topic_rc=0; else help_topic_rc=$?; fi
5308
+ if [ "$help_topic_co_rc" -ne 0 ] || [ -s "$help_dir/checkout-$help_topic.err" ] \
5309
+ || [ "$help_topic_rc" -ne 0 ] || [ -s "$help_dir/installed-$help_topic.err" ] \
5310
+ || ! cmp -s "$help_dir/installed-$help_topic.out" "$help_dir/checkout-$help_topic.out"; then
5311
+ fail "[check-pack-install] installed \`entwurf help $help_topic\` rc=$help_topic_rc (checkout rc=$help_topic_co_rc) is not the checkout's stdout bytes with an empty stderr (stderr: $(head -c 300 "$help_dir/installed-$help_topic.err"))"
5312
+ return 1
5313
+ fi
5314
+ done
5315
+ if [ ! -f "$npm_pkg/team.json.example" ] || ! cmp -s "$npm_pkg/team.json.example" "$REPO_DIR/team.json.example" \
5316
+ || ! grep -q '^## 2c\. ' "$npm_pkg/docs/setup-clean-host.md"; then
5317
+ fail "[check-pack-install] a guide topic points at a file this installed package lacks: team.json.example (byte-equal to the checkout) and docs/setup-clean-host.md with its section 2c"
5318
+ return 1
5319
+ fi
5320
+
5321
+ cp -p "$help_json" "$help_dir/ENTWURF-CLI.json.orig"
5322
+ sed -i 's/^\t\t"title": "entwurf - native harness entrypoints and garden facts",$/\t\t"title": "entwurf (installed copy)",/' "$help_json"
5323
+ if (cd "$npmproj" && env "${consumer_env[@]}" "$help_bin" --help) >"$help_dir/title.out" 2>"$help_dir/title.err"; then help_title_rc=0; else help_title_rc=$?; fi
5324
+ cp -p "$help_dir/ENTWURF-CLI.json.orig" "$help_json"
5325
+
5326
+ mv "$help_mjs" "$help_dir/cli-help.mjs.orig"
5327
+ if (cd "$npmproj" && env "${consumer_env[@]}" "$help_bin" --help) >"$help_dir/gone.out" 2>"$help_dir/gone.err"; then help_gone_rc=0; else help_gone_rc=$?; fi
5328
+ mv "$help_dir/cli-help.mjs.orig" "$help_mjs"
5329
+
5330
+ if cmp -s "$help_json" "$REPO_DIR/ENTWURF-CLI.json" && cmp -s "$help_mjs" "$REPO_DIR/scripts/cli-help.mjs"; then help_restored=0; fi
5331
+ if [ "$help_restored" -ne 0 ]; then
5332
+ fail "[check-pack-install] the installed ENTWURF-CLI.json / scripts/cli-help.mjs did not come back byte-identical after the negatives"
5333
+ return 1
5334
+ fi
5335
+ if [ "$help_co_rc" -ne 0 ] || [ -s "$help_dir/checkout.err" ]; then
5336
+ fail "[check-pack-install] checkout \`run.sh --help\` rc=$help_co_rc (stderr: $(head -c 300 "$help_dir/checkout.err"))"
5337
+ return 1
5338
+ fi
5339
+ if [ "$help_rc" -ne 0 ] || [ -s "$help_dir/installed.err" ] || ! cmp -s "$help_dir/installed.out" "$help_dir/checkout.out"; then
5340
+ fail "[check-pack-install] installed \`entwurf --help\` rc=$help_rc is not the checkout's stdout bytes with an empty stderr (stderr: $(head -c 300 "$help_dir/installed.err"))"
5341
+ return 1
5342
+ fi
5343
+ if [ "$help_all_co_rc" -ne 0 ] || [ -s "$help_dir/checkout-all.err" ]; then
5344
+ fail "[check-pack-install] checkout \`run.sh help all\` rc=$help_all_co_rc (stderr: $(head -c 300 "$help_dir/checkout-all.err"))"
5345
+ return 1
5346
+ fi
5347
+ if [ "$help_all_rc" -ne 0 ] || [ -s "$help_dir/installed-all.err" ] || ! cmp -s "$help_dir/installed-all.out" "$help_dir/checkout-all.out"; then
5348
+ fail "[check-pack-install] installed \`entwurf help all\` rc=$help_all_rc is not the checkout's stdout bytes with an empty stderr (stderr: $(head -c 300 "$help_dir/installed-all.err"))"
5349
+ return 1
5350
+ fi
5351
+ if [ "$help_title_rc" -ne 0 ] || [ "$(head -n 1 "$help_dir/title.out")" != "entwurf (installed copy)" ]; then
5352
+ fail "[check-pack-install] a changed INSTALLED ENTWURF-CLI.json did not change the installed help (rc=$help_title_rc) — it answered from somewhere else"
5353
+ return 1
5354
+ fi
5355
+ if [ "$help_gone_rc" -eq 0 ] || [ -s "$help_dir/gone.out" ]; then
5356
+ fail "[check-pack-install] with the INSTALLED renderer removed, installed \`entwurf --help\` still answered (rc=$help_gone_rc) — it fell back to something else"
5357
+ return 1
5358
+ fi
5359
+ echo "[check-pack-install] installed help from the shipped ENTWURF-CLI.json + scripts/cli-help.mjs: root/catalog/topics byte parity (--help, help all, help team, help remote-pair); installed-copy title/removal negatives on root --help only; packaged guide references present (team.json.example byte-equal, setup-clean-host.md section 2c)"
5360
+
5361
+ # #153 — the operator entrance through this npm consumer's installed bins (helper above).
5362
+ pack_install_operator_cells "$npm_tmp" "$npmroot" "$help_dir" || return 1
5363
+
5283
5364
  # THE 2026-07-03 regression gate: removing `pi install` from setup dropped
5284
5365
  # user-scope citizen registration, so `--entwurf-control` was Unknown in a
5285
5366
  # foreign cwd. Prove the npm consumer path closes it end-to-end: run.sh install
@@ -5327,7 +5408,7 @@ sys.exit(0 if any(isinstance(s,str) and s.endswith('/node_modules/@junghanacs/en
5327
5408
  # operator-explicit takeover is what moves the shared entry, old→new reported.
5328
5409
  local npmroot2="$npm_tmp/npmroot2" npmproj2="$npm_tmp/npmproj2" npm2_log two_root_out two_root_rc npm2_pkg
5329
5410
  mkdir -p "$npmroot2" "$npmproj2"
5330
- npm2_log=$(cd "$npmroot2" && npm install "$tgz_path" --no-audit --no-fund 2>&1) || {
5411
+ npm2_log=$(cd "$npmroot2" && npm install "$tgz_path" --ignore-scripts --no-audit --no-fund 2>&1) || {
5331
5412
  fail "[check-pack-install] second npm root install failed:"
5332
5413
  echo "$npm2_log" | tail -10 | sed 's/^/ /' >&2
5333
5414
  return 1
@@ -7156,6 +7237,9 @@ expose_dev_bin() {
7156
7237
  bash "$REPO_DIR/scripts/dev-bin.sh" expose
7157
7238
  rc=$?
7158
7239
  set -e
7240
+ # 4 = dev-bin refused because this is an installed package (#153): nothing was exposed, so there
7241
+ # is nothing to certify — no verify, no exclusive, no package-manager query.
7242
+ [ "$rc" -eq 4 ] && return 4
7159
7243
 
7160
7244
  if ! bash "$REPO_DIR/scripts/dev-bin.sh" verify entwurf; then
7161
7245
  return 1
@@ -7555,6 +7639,37 @@ release_gate() {
7555
7639
  }
7556
7640
 
7557
7641
  cmd=${1:-}
7642
+ # A request to READ a command's description is answered here, before the dispatch below can run
7643
+ # anything: `entwurf help <command>`, or `<command> -h|--help` with nothing after it, prints that
7644
+ # command's entry from ENTWURF-CLI.json (or refuses, exit 2, when it has none) and exits — no arm
7645
+ # is entered, so a command that ignores its argv can no longer be started by asking about it. A
7646
+ # help form with more argv after it is refused the same way rather than guessed at, and so is
7647
+ # `--help <command>`. The five launchers below hand every argv to a vendor binary that owns its
7648
+ # own --help, so they pass through untouched. Only these exact shapes are help: a flag in another
7649
+ # position, or after `--`, reaches the dispatch as before. `entwurf help all` — exactly those two
7650
+ # words — prints the full catalog, every described command, which the short root page leaves out.
7651
+ # `entwurf help <name>` alone may also print a guide topic (team, remote-pair): static text the
7652
+ # same file holds, never a command, so `<topic> --help` stays the refusal of an undescribed name.
7653
+ # The bare root forms fall through to the unchanged case below.
7654
+ if [ "$cmd" = help ] && [ "$#" -eq 2 ] && [ "$2" = all ]; then
7655
+ exec node "$REPO_DIR/scripts/cli-help.mjs" --all
7656
+ elif [ "$cmd" = help ] && [ "$#" -ge 2 ]; then
7657
+ if [ "$#" -gt 2 ]; then
7658
+ echo 'entwurf: `entwurf help` takes one command or topic name' >&2
7659
+ exit 2
7660
+ fi
7661
+ exec node "$REPO_DIR/scripts/cli-help.mjs" --name "$2"
7662
+ elif { [ "$cmd" = -h ] || [ "$cmd" = --help ]; } && [ "$#" -ge 2 ]; then
7663
+ echo 'entwurf: -h/--help takes nothing after it; for one command use `entwurf help <command>`' >&2
7664
+ exit 2
7665
+ elif [ "$#" -ge 2 ] && { [ "$2" = -h ] || [ "$2" = --help ]; } \
7666
+ && [ "$cmd" != pi ] && [ "$cmd" != pi-durable ] && [ "$cmd" != claude ] && [ "$cmd" != copilot ] && [ "$cmd" != codex-app-server ]; then
7667
+ if [ "$#" -gt 2 ]; then
7668
+ echo 'entwurf: a help request takes nothing after -h/--help; nothing was run' >&2
7669
+ exit 2
7670
+ fi
7671
+ exec node "$REPO_DIR/scripts/cli-help.mjs" --command "$cmd"
7672
+ fi
7558
7673
  case "$cmd" in
7559
7674
  menu)
7560
7675
  shift
@@ -7567,15 +7682,6 @@ case "$cmd" in
7567
7682
  shift || true
7568
7683
  release_gate "$@"
7569
7684
  ;;
7570
- check-bridge)
7571
- check_bridge
7572
- ;;
7573
- check-model-lock)
7574
- check_model_lock
7575
- ;;
7576
- check-shell-quote)
7577
- check_shell_quote
7578
- ;;
7579
7685
  check-install-surface)
7580
7686
  # structural half of the node_modules strip-types fence: run_ts is the only crossing,
7581
7687
  # every operator subcommand has a compiled twin, bin wrappers branch, dev gates stay out
@@ -7585,60 +7691,6 @@ case "$cmd" in
7585
7691
  # check-pack-install owns the dynamic half (it drives the installed commands).
7586
7692
  run_ts scripts/check-install-surface.ts
7587
7693
  ;;
7588
- check-entwurf-session-identity)
7589
- check_entwurf_session_identity
7590
- ;;
7591
- check-meta-session)
7592
- check_meta_session
7593
- ;;
7594
- check-meta-v3-record)
7595
- check_meta_v3_record
7596
- ;;
7597
- check-mailbox-receipt-state)
7598
- check_mailbox_receipt_state
7599
- ;;
7600
- check-entwurf-capabilities)
7601
- check_entwurf_capabilities
7602
- ;;
7603
- check-harness-admission-parity)
7604
- check_harness_admission_parity
7605
- ;;
7606
- check-omp-fresh-preflight)
7607
- check_omp_fresh_preflight
7608
- ;;
7609
- smoke-omp-fresh-live)
7610
- smoke_omp_fresh_live
7611
- ;;
7612
- smoke-pi-durable-fresh-live)
7613
- smoke_pi_durable_fresh_live
7614
- ;;
7615
- check-capability-bundle-reach)
7616
- check_capability_bundle_reach
7617
- ;;
7618
- check-bridge-delivery)
7619
- check_bridge_delivery
7620
- ;;
7621
- smoke-pi-attach)
7622
- smoke_pi_attach
7623
- ;;
7624
- check-meta-mailbox-state-write)
7625
- check_meta_mailbox_state_write
7626
- ;;
7627
- check-meta-receiver-marker)
7628
- check_meta_receiver_marker
7629
- ;;
7630
- check-meta-hook-session-switch)
7631
- check_meta_hook_session_switch
7632
- ;;
7633
- check-meta-identity-consumers)
7634
- check_meta_identity_consumers
7635
- ;;
7636
- check-hook-launch-topology)
7637
- check_hook_launch_topology
7638
- ;;
7639
- check-copilot-birth-hook)
7640
- check_copilot_birth_hook
7641
- ;;
7642
7694
  check-omp-birth-hook)
7643
7695
  # #87 gate: the OMP BIRTH path without omp. Drives the real assembler into a temp dir,
7644
7696
  # then imports the ASSEMBLED index.ts into a mock omp host (mock ExtensionAPI + mock
@@ -7671,183 +7723,6 @@ case "$cmd" in
7671
7723
  # Inputs as check-pi-durable-contact; absent → SKIP 97.
7672
7724
  run_ts scripts/check-pi-durable-receive.ts
7673
7725
  ;;
7674
- check-copilot-statusline)
7675
- check_copilot_statusline
7676
- ;;
7677
- check-codex-app-server-launch)
7678
- check_codex_app_server_launch
7679
- ;;
7680
- check-copilot-launch)
7681
- check_copilot_launch
7682
- ;;
7683
- check-pi-launch)
7684
- check_pi_launch
7685
- ;;
7686
- check-copilot-receive-arm)
7687
- check_copilot_receive_arm
7688
- ;;
7689
- check-meta-capability-source)
7690
- check_meta_capability_source
7691
- ;;
7692
- check-socket-probe)
7693
- check_socket_probe
7694
- ;;
7695
- check-project-trust-handler)
7696
- check_project_trust_handler
7697
- ;;
7698
- check-entwurf-v2-contract)
7699
- check_entwurf_v2_contract
7700
- ;;
7701
- check-entwurf-v2-send)
7702
- check_entwurf_v2_send
7703
- ;;
7704
- check-entwurf-v2-runner)
7705
- check_entwurf_v2_runner
7706
- ;;
7707
- check-control-send-receipt)
7708
- check_control_send_receipt
7709
- ;;
7710
- check-control-retire)
7711
- check_control_retire
7712
- ;;
7713
- check-pi-retire-request)
7714
- check_pi_retire_request
7715
- ;;
7716
- check-cc-retire-pidfd)
7717
- check_cc_retire_pidfd
7718
- ;;
7719
- check-cc-retire-request)
7720
- check_cc_retire_request
7721
- ;;
7722
- check-retirement-event)
7723
- check_retirement_event
7724
- ;;
7725
- check-entwurf-v2-retire)
7726
- check_entwurf_v2_retire
7727
- ;;
7728
- check-win32-preview)
7729
- check_win32_preview
7730
- ;;
7731
- check-entwurf-v2-native-push)
7732
- check_entwurf_v2_native_push
7733
- ;;
7734
- check-native-push-paused)
7735
- check_native_push_paused
7736
- ;;
7737
- check-chain-terminus-publication)
7738
- check_chain_terminus_publication
7739
- ;;
7740
- check-entwurf-control-rpc)
7741
- check_entwurf_control_rpc
7742
- ;;
7743
- check-compaction-send-guard)
7744
- check_compaction_send_guard
7745
- ;;
7746
- check-entwurf-v2-production)
7747
- check_entwurf_v2_production
7748
- ;;
7749
- check-entwurf-v2-surface)
7750
- check_entwurf_v2_surface
7751
- ;;
7752
- check-entwurf-bridge-boot)
7753
- check_entwurf_bridge_boot
7754
- ;;
7755
- check-entwurf-bridge-pi-free)
7756
- check_entwurf_bridge_pi_free
7757
- ;;
7758
- check-entwurf-resume-args)
7759
- check_entwurf_resume_args
7760
- ;;
7761
- check-acp-foreground-only)
7762
- check_acp_foreground_only
7763
- ;;
7764
- check-fresh-call-provider)
7765
- check_fresh_call_provider
7766
- ;;
7767
- check-acp-set-model-readback)
7768
- check_acp_set_model_readback
7769
- ;;
7770
- check-resume-launch-identity)
7771
- check_resume_launch_identity
7772
- ;;
7773
- check-mux-placement)
7774
- check_mux_placement
7775
- ;;
7776
- check-mux-placement-tmux)
7777
- check_mux_placement_tmux
7778
- ;;
7779
- check-mux-launch)
7780
- check_mux_launch
7781
- ;;
7782
- check-mux-fresh-call)
7783
- check_mux_fresh_call
7784
- ;;
7785
- check-pi-durable-beside)
7786
- check_pi_durable_beside
7787
- ;;
7788
- check-pi-durable-carrier)
7789
- check_pi_durable_carrier
7790
- ;;
7791
- check-pi-durable-native-module)
7792
- check_pi_durable_native_module
7793
- ;;
7794
- check-remote-pair-beside)
7795
- check_remote_pair_beside
7796
- ;;
7797
- check-mux-resume-call)
7798
- check_mux_resume_call
7799
- ;;
7800
- check-mux-parent-artifact)
7801
- check_mux_parent_artifact
7802
- ;;
7803
- check-mux-launcher-fence)
7804
- check_mux_launcher_fence
7805
- ;;
7806
- check-typing-call-fence)
7807
- check_typing_call_fence
7808
- ;;
7809
- check-entwurf-v2-visible-resume)
7810
- check_entwurf_v2_visible_resume
7811
- ;;
7812
- smoke-mux-fresh-call-live)
7813
- smoke_mux_fresh_call_live
7814
- ;;
7815
- smoke-mux-lifecycle-live)
7816
- smoke_mux_lifecycle_live
7817
- ;;
7818
- check-mux-launch-tmux)
7819
- check_mux_launch_tmux
7820
- ;;
7821
- smoke-entwurf-v2-matrix-live)
7822
- smoke_entwurf_v2_matrix_live
7823
- ;;
7824
- smoke-acp-raw-turn-live)
7825
- smoke_acp_raw_turn_live
7826
- ;;
7827
- smoke-acp-overlay-live)
7828
- smoke_acp_overlay_live
7829
- ;;
7830
- smoke-acp-memory-containment-live)
7831
- smoke_acp_memory_containment_live
7832
- ;;
7833
- smoke-acp-provider-live)
7834
- smoke_acp_provider_live
7835
- ;;
7836
- smoke-acp-long-turn-live)
7837
- smoke_acp_long_turn_live
7838
- ;;
7839
- smoke-acp-session-reuse-live)
7840
- smoke_acp_session_reuse_live
7841
- ;;
7842
- smoke-acp-mcp-live)
7843
- smoke_acp_mcp_live
7844
- ;;
7845
- smoke-acp-skill-live)
7846
- smoke_acp_skill_live
7847
- ;;
7848
- smoke-acp-bundled-mcp-live)
7849
- smoke_acp_bundled_mcp_live
7850
- ;;
7851
7726
  smoke-omp-receive-live)
7852
7727
  # #87 bundle B — the acceptance that makes omp's one-way garden executable.
7853
7728
  # Reads the capability registry and reports its own PASS/SKIP/FAIL; see the
@@ -7863,45 +7738,6 @@ case "$cmd" in
7863
7738
  # LIVE=1 ./run.sh smoke-entwurf-chain-live
7864
7739
  run_ts scripts/smoke-entwurf-chain-live.ts
7865
7740
  ;;
7866
- smoke-acp-v2-send-live)
7867
- smoke_acp_v2_send_live
7868
- ;;
7869
- smoke-acp-carrier-augment-live)
7870
- smoke_acp_carrier_augment_live
7871
- ;;
7872
- smoke-acp-rgg-live)
7873
- smoke_acp_rgg_live
7874
- ;;
7875
- smoke-acp-cortex-live)
7876
- smoke_acp_cortex_live
7877
- ;;
7878
- smoke-acp-socket-citizen-live)
7879
- smoke_acp_socket_citizen_live
7880
- ;;
7881
- check-control-socket-path)
7882
- check_control_socket_path
7883
- ;;
7884
- check-meta-listing)
7885
- check_meta_listing
7886
- ;;
7887
- check-meta-facts)
7888
- check_meta_facts
7889
- ;;
7890
- check-herdr-activation)
7891
- check_herdr_activation
7892
- ;;
7893
- check-herdr-runtime-bootstrap)
7894
- check_herdr_runtime_bootstrap
7895
- ;;
7896
- check-herdr-plugin-profile)
7897
- check_herdr_plugin_profile
7898
- ;;
7899
- check-herdr-plugin-build)
7900
- check_herdr_plugin_build
7901
- ;;
7902
- smoke-herdr-plugin-build-live)
7903
- smoke_herdr_plugin_build_live
7904
- ;;
7905
7741
  smoke-herdr-raw-install-live)
7906
7742
  # #118 홉 1: the FIRST USER PATH. Every other herdr gate proves the plugin against a
7907
7743
  # source we control — a stub, or the product remote redirected by git insteadOf to a
@@ -7916,51 +7752,6 @@ case "$cmd" in
7916
7752
  shift
7917
7753
  (cd "$REPO_DIR" && bash scripts/smoke-herdr-raw-install-live.sh "$@")
7918
7754
  ;;
7919
- check-peer-facts)
7920
- check_peer_facts
7921
- ;;
7922
- check-herdr-plugin)
7923
- check_herdr_plugin
7924
- ;;
7925
- check-entwurf-fact-provider)
7926
- check_entwurf_fact_provider
7927
- ;;
7928
- check-herdr-placement)
7929
- check_herdr_placement
7930
- ;;
7931
- check-herdr-fresh-call)
7932
- check_herdr_fresh_call
7933
- ;;
7934
- check-herdr-sandbox)
7935
- check_herdr_sandbox
7936
- ;;
7937
- check-herdr-supply)
7938
- check_herdr_supply
7939
- ;;
7940
- check-fresh-call-dispatch)
7941
- check_fresh_call_dispatch
7942
- ;;
7943
- smoke-herdr-fresh-call-live)
7944
- smoke_herdr_fresh_call_live
7945
- ;;
7946
- check-entwurf-peers-surface)
7947
- check_entwurf_peers_surface
7948
- ;;
7949
- check-entwurf-self-address)
7950
- check_entwurf_self_address
7951
- ;;
7952
- check-entwurf-deliverability)
7953
- check_entwurf_deliverability
7954
- ;;
7955
- check-native-push-adapter)
7956
- check_native_push_adapter
7957
- ;;
7958
- check-native-push-register)
7959
- check_native_push_register
7960
- ;;
7961
- check-agy-sender-identity)
7962
- check_agy_sender_identity
7963
- ;;
7964
7755
  new-session-id)
7965
7756
  # Print one fresh garden sessionId (SSOT: generateSessionId). #50 C2 retired
7966
7757
  # the operator-launcher --session-id injection; the record layer is the
@@ -8504,6 +8295,68 @@ case "$cmd" in
8504
8295
  export ENTWURF_PI_LAUNCH_ACTIVE=1
8505
8296
  exec "$entwurf_pi_bin" --entwurf-control "$@"
8506
8297
  ;;
8298
+ claude)
8299
+ # #157 stage 4: the Claude Code launch. The same posture as `pi` above — `exec`, no subshell
8300
+ # and no cd (Claude Code owns this terminal, the caller's cwd, this pid and its exit status),
8301
+ # `shift` so the verb never reaches the vendor argv, `type -P` so only a PATH file is exec'd,
8302
+ # never a function or alias — but its precondition and its fence count are its own.
8303
+ #
8304
+ # NOTHING IS ADDED TO THE ARGV AND NOTHING IS CHECKED FIRST. A Claude Code session becomes a
8305
+ # garden citizen through the meta-bridge plugin and hooks `setup` installed in its own user
8306
+ # scope, and through nothing this launch could add: on a host without them it is plain Claude
8307
+ # Code, exactly as `claude` would be, and the help says so rather than promising a citizen.
8308
+ # Checking for them here would be a second doctor (`doctor-meta-bridge` owns that) and a
8309
+ # promise this spelling cannot keep. Auth, model, permission and settings stay Claude Code's
8310
+ # (Hard Rule 9); `--help` reaches it because the help preflight above lets this verb through.
8311
+ #
8312
+ # TWO RECURSION FENCES, NOT PI'S ONE, because pi's reason for one does not hold here. pi
8313
+ # injects --entwurf-control ahead of the operator argv, so a PATH `pi` symlinked to run.sh
8314
+ # re-enters as an unknown verb. This launch injects nothing: a PATH `claude` that resolves to
8315
+ # run.sh would re-enter with the OPERATOR's argv as the verb, and `entwurf claude setup` would
8316
+ # run setup. So, as `scripts/copilot-launch.sh` does, the exported sentinel closes the
8317
+ # wrapper-script loop and the resolved path refuses this run.sh even when the sentinel was
8318
+ # stripped. The vendor is exec'd by the path `type -P` returned, not the resolved one, so
8319
+ # argv[0] is what a shell would have given it.
8320
+ #
8321
+ # ONE environment change besides the sentinel, and it is a removal. A complete
8322
+ # PI_SESSION_ID/PI_AGENT_ID pair is trusted ahead of a native sender marker, so inherited from
8323
+ # a pi citizen's shell it is another citizen's identity; both go, as in copilot-launch.sh and
8324
+ # codex-app-server-launch.sh. Nothing is substituted: this session's identity is its own hooks'.
8325
+ shift || true
8326
+ if [ -n "${ENTWURF_CLAUDE_LAUNCH_ACTIVE:-}" ]; then
8327
+ echo "entwurf: recursive managed launch detected (ENTWURF_CLAUDE_LAUNCH_ACTIVE is already set)." >&2
8328
+ echo " Something on PATH named 'claude' resolves back to this launcher. Fix PATH so" >&2
8329
+ echo " 'claude' is Claude Code, or run the vendor binary by its full path." >&2
8330
+ exit 1
8331
+ fi
8332
+ entwurf_claude_bin="$(type -P claude 2>/dev/null || true)"
8333
+ if [ -z "$entwurf_claude_bin" ]; then
8334
+ echo "entwurf: no 'claude' executable found on PATH." >&2
8335
+ echo " 'entwurf claude' launches Claude Code; it does not install one." >&2
8336
+ exit 1
8337
+ fi
8338
+ if [ ! -f "$entwurf_claude_bin" ] || [ ! -x "$entwurf_claude_bin" ]; then
8339
+ echo "entwurf: '$entwurf_claude_bin' is not an executable regular file — refusing to exec it." >&2
8340
+ exit 1
8341
+ fi
8342
+ entwurf_claude_real="$entwurf_claude_bin"
8343
+ while [ -L "$entwurf_claude_real" ]; do
8344
+ entwurf_claude_dir="$(cd -P -- "$(dirname -- "$entwurf_claude_real")" && pwd)"
8345
+ entwurf_claude_link="$(readlink -- "$entwurf_claude_real")"
8346
+ case "$entwurf_claude_link" in
8347
+ /*) entwurf_claude_real="$entwurf_claude_link" ;;
8348
+ *) entwurf_claude_real="$entwurf_claude_dir/$entwurf_claude_link" ;;
8349
+ esac
8350
+ done
8351
+ entwurf_claude_real="$(cd -P -- "$(dirname -- "$entwurf_claude_real")" && pwd)/$(basename -- "$entwurf_claude_real")"
8352
+ if [ "$entwurf_claude_real" = "$REPO_DIR/run.sh" ]; then
8353
+ echo "entwurf: 'claude' on PATH resolves to entwurf's own '$entwurf_claude_real' — that is a launch loop, not Claude Code." >&2
8354
+ exit 1
8355
+ fi
8356
+ unset PI_SESSION_ID PI_AGENT_ID
8357
+ export ENTWURF_CLAUDE_LAUNCH_ACTIVE=1
8358
+ exec "$entwurf_claude_bin" "$@"
8359
+ ;;
8507
8360
  install-copilot-receive)
8508
8361
  # #82 RAIL 5: install the RECEIVER extension into the Copilot USER extensions dir.
8509
8362
  # Artifact ownership only — it sets no launch flag (`run.sh copilot` owns one
@@ -8720,105 +8573,9 @@ case "$cmd" in
8720
8573
  shift || true
8721
8574
  (cd "$REPO_DIR" && python3 scripts/check-keyset-overlap.py "$@")
8722
8575
  ;;
8723
- check-package-source-routing)
8724
- check_package_source_routing
8725
- ;;
8726
- check-dep-versions)
8727
- check_dep_versions
8728
- ;;
8729
- check-node-floor-coherence)
8730
- check_node_floor_coherence
8731
- ;;
8732
- check-claude-floor-coherence)
8733
- check_claude_floor_coherence
8734
- ;;
8735
- check-install-preflight)
8736
- check_install_preflight
8737
- ;;
8738
- check-pi-import-surface)
8739
- check_pi_import_surface
8740
- ;;
8741
- check-env-namespace)
8742
- check_env_namespace
8743
- ;;
8744
- check-pi-runtime-version)
8745
- check_pi_runtime_version
8746
- ;;
8747
- check-pi-preflight)
8748
- check_pi_preflight
8749
- ;;
8750
- check-auth-boundary)
8751
- check_auth_boundary
8752
- ;;
8753
- check-acp-provider-surface)
8754
- check_acp_provider_surface
8755
- ;;
8756
- check-acp-sdk-surface)
8757
- check_acp_sdk_surface
8758
- ;;
8759
- check-pi-queue-oracle)
8760
- check_pi_queue_oracle
8761
- ;;
8762
- check-remote-pair-installed-audit)
8763
- check_remote_pair_installed_audit
8764
- ;;
8765
- check-demo-reproducibility)
8766
- check_demo_reproducibility
8767
- ;;
8768
- check-tests-beside-behavior)
8769
- check_tests_beside_behavior
8770
- ;;
8771
- check-acp-overlay)
8772
- check_acp_overlay
8773
- ;;
8774
- check-acp-tool-surface)
8775
- check_acp_tool_surface
8776
- ;;
8777
- check-acp-event-mapper)
8778
- check_acp_event_mapper
8779
- ;;
8780
- check-acp-usage-accounting)
8781
- check_acp_usage_accounting
8782
- ;;
8783
- check-acp-stop-reason)
8784
- check_acp_stop_reason
8785
- ;;
8786
- check-acp-prompt-lifecycle)
8787
- check_acp_prompt_lifecycle
8788
- ;;
8789
- check-acp-vendor-rejection)
8790
- check_acp_vendor_rejection
8791
- ;;
8792
- check-acp-launch-namespace)
8793
- check_acp_launch_namespace
8794
- ;;
8795
- check-acp-stream-hooks)
8796
- check_acp_stream_hooks
8797
- ;;
8798
- check-acp-prompt-builder)
8799
- check_acp_prompt_builder
8800
- ;;
8801
- check-acp-config)
8802
- check_acp_config
8803
- ;;
8804
- check-acp-session-store)
8805
- check_acp_session_store
8806
- ;;
8807
- check-acp-backend-preflight)
8808
- check_acp_backend_preflight
8809
- ;;
8810
- check-acp-session-reuse)
8811
- check_acp_session_reuse
8812
- ;;
8813
8576
  check-release-gate-outcomes)
8814
8577
  run_ts scripts/check-release-gate-outcomes.ts
8815
8578
  ;;
8816
- check-acp-carrier-augment)
8817
- check_acp_carrier_augment
8818
- ;;
8819
- check-acp-cortex)
8820
- check_acp_cortex
8821
- ;;
8822
8579
  check-fresh-cut-gate)
8823
8580
  # SOURCE cell of the generation-boundary proof: a host whose store the live
8824
8581
  # schema cannot read must be refused BEFORE any write, told the fresh-cut
@@ -8838,9 +8595,6 @@ case "$cmd" in
8838
8595
  shift || true
8839
8596
  run_ts scripts/check-pi-bridge-sender.ts "$@"
8840
8597
  ;;
8841
- check-pi-mcp-register)
8842
- check_pi_mcp_register
8843
- ;;
8844
8598
  check-pi-mcp-bridge)
8845
8599
  shift || true
8846
8600
  run_ts scripts/check-pi-mcp-bridge.ts "$@"
@@ -8865,24 +8619,6 @@ case "$cmd" in
8865
8619
  shift || true
8866
8620
  (cd "$REPO_DIR" && bash scripts/smoke-codex-birth.sh "$@")
8867
8621
  ;;
8868
- check-pack)
8869
- check_pack
8870
- ;;
8871
- check-pack-pin-matcher)
8872
- check_pack_pin_matcher
8873
- ;;
8874
- check-pack-argv-matcher)
8875
- check_pack_argv_matcher
8876
- ;;
8877
- check-pack-win32-carrier)
8878
- check_pack_win32_carrier
8879
- ;;
8880
- check-pack-consumer-roots)
8881
- check_pack_consumer_roots
8882
- ;;
8883
- check-pack-install)
8884
- check_pack_install
8885
- ;;
8886
8622
  check-install-container)
8887
8623
  # 0.12.8 (#51 gate C): the Linux artifact-CONSUMER lane. check-pack-install is
8888
8624
  # the strongest HOST gate and still only ever proves this machine's shape —
@@ -8910,6 +8646,18 @@ case "$cmd" in
8910
8646
  # because it has to run from an installed package after Herdr deleted the plugin checkout.
8911
8647
  (cd "$REPO_DIR" && node "$REPO_DIR/scripts/herdr-plugin-deactivate.mjs" "$@")
8912
8648
  ;;
8649
+ herdr-plugin-expose-operator)
8650
+ # #153: the operator's ONE explicit link to the Herdr runtime's `entwurf`, owned by a receipt
8651
+ # beside the activation ledger and undone by herdr-plugin-withdraw-operator or deactivate. No cd:
8652
+ # the caller's cwd is part of what its PATH means, and this verb judges that PATH.
8653
+ shift
8654
+ node "$REPO_DIR/scripts/herdr-operator-link.mjs" expose "$@"
8655
+ ;;
8656
+ herdr-plugin-withdraw-operator)
8657
+ # #153: the opt-out — removes exactly the receipt's link and the receipt; the ledger floor stays.
8658
+ shift
8659
+ node "$REPO_DIR/scripts/herdr-operator-link.mjs" withdraw "$@"
8660
+ ;;
8913
8661
  install-user-scope)
8914
8662
  shift
8915
8663
  install_user_scope "$@"
@@ -8932,8 +8680,23 @@ case "$cmd" in
8932
8680
  usage
8933
8681
  ;;
8934
8682
  *)
8935
- echo "Unknown command: $cmd" >&2
8936
- usage
8937
- exit 1
8683
+ # A dev gate with nothing to say beyond its own name is dispatched by that name: `check-x` runs
8684
+ # `check_x`, the convention check_tests_beside_behavior already reads back — so a top-level
8685
+ # check_/smoke_ function in this file IS a public dev command. The prefix guard keeps every
8686
+ # other function (usage, run_ts, the install writers) from answering as one; the provenance
8687
+ # test admits only a function THIS file defined (extdebug reports `<line> <source>`, and an
8688
+ # imported BASH_FUNC_* reads `0 environment`), switched on inside the lookup's own subshell.
8689
+ # An explicit arm above always wins; anything else stays the Unknown command it always was.
8690
+ gate_fn=${cmd//-/_} gate_decl=
8691
+ if [[ $cmd =~ ^(check|smoke)-[a-z0-9-]+$ ]] \
8692
+ && gate_decl=$(shopt -s extdebug; declare -F "$gate_fn") \
8693
+ && [[ ${gate_decl#"$gate_fn "} =~ ^[1-9][0-9]*\ (.*)$ ]] \
8694
+ && [ "${BASH_REMATCH[1]}" = "${BASH_SOURCE[0]}" ]; then
8695
+ "$gate_fn"
8696
+ else
8697
+ echo "Unknown command: $cmd" >&2
8698
+ usage
8699
+ exit 1
8700
+ fi
8938
8701
  ;;
8939
8702
  esac