diff --git a/docs/plans/shell-intent-emit-realization-design.md b/docs/plans/shell-intent-emit-realization-design.md index de13f3bfac0..2049895543a 100644 --- a/docs/plans/shell-intent-emit-realization-design.md +++ b/docs/plans/shell-intent-emit-realization-design.md @@ -72,6 +72,25 @@ The load-bearing correction (operator review, 2026-07-19): **"dissolve the raw c So the arc is not "N files onto the bash emitter." It is: route each site to the correct path, and generalize `host_effect_apply` from `ShellCommand{script:String}` toward typed effects — the census authority's central finding. +## The boundary beneath realization — a CLI-backed handler is one cell, not the model (2026-08-19) + +The routing decision above says *where* a site goes. This says what the **realization** column may and may not become, and it is placed here because the layering table's four rows are the exact thing a reader can re-fuse. + +`cli-invocation-emission-design.md` (gunbc#8467) establishes that an argv array is a **serialization** — the same relation bash text bears to a bash AST. Its measured census found 556 `argv:` lines across 124 files and 250 `transport shell` blocks whose three welded facts (what the tool is, how we reached it, what we asked it) are re-decided by hand at every site. That diagnosis is accepted, and the consequence for **this** document is narrow and must stay narrow: + +- The **intent** row is untouched. It named no language before and names no tool now. +- The **realization** row gains an internal structure it did not have: a handler is native (REST, filesystem, library) **or** CLI-backed. Only the second lowers a tool-semantic request through cited CLI grammar rows into a carrier. +- **argv is never the authority**, and **CLI invocation is not the universal effect model.** A native handler reaches no CLI surface at all. Making CLI lowering universal would relocate the authority into one realization technology — the §3 violation this document exists to name, one layer below where it usually appears. + +The invariant this document owns generalizes cleanly and needs no restatement per-target: *the intent imports no language-construction vocabulary* becomes, at the layer below, **the domain imports no tool vocabulary**. A domain module that stops concatenating `sudo -n …` and starts authoring a tool's flags — or a tool's embedded program text — has moved the anemic leaf one layer in, not dissolved it. That is the same relocation-counted-as-progress this lane already priced once (#7004/#7006, §4's "why now"). + +Two facts carried here because they change what the emit row means: + +- **Local process execution has no shell.** The v1 seed realizes `transport shell` as `Command::new(&argv[0]).args(&argv[1..])` — no shell, no word splitting, no quoting. So `transport shell` is a historical DSL keyword at that boundary, not a description, and the emit column's bash grammar is *not* on the local path at all. +- **SSH is a separate target**, not a prefix. RFC 4254 carries one command string; `append(ssh_prefix, inner.argv)` is the shape this document already forbids for transports, and it is forbidden here for the same reason. + +Ownership, so neither lane waits on the other: this document and the census own the semantic destination and site routing; #8467 owns the inside of the CLI-backed cell. The negative falsifier that keeps the boundary honest — a Redfish/REST path reaching no CLI surface, no process-argv carrier and no shell target — is owed by that lane. + ## The carriers and the two enforcement milestones (corrected) The anemic `String` leaves are **more than one**: `host_effect.ShellCommand{script}` (`host_effect.dag:25`), `std.orchestration.Run.command` (the `Do{run}` leaf), and `host_effect.BootstrapFragment.script` (`host_effect.dag:59`) — plus the `ThinInvocation`/`EmitArtifactThenThinRun` medium-as-string scaffolds. The target for all of them is **`Do{effect}` — never a command string** (host-effect-orchestration.md's `std.effect_plan` band). Sequencing is **add-replacement → migrate all consumers → delete at arc close** (§5 construction, but you cannot delete `ShellCommand` while other constructors and consumers still populate it). `host_effect.dag` is a DESIGN-named load-bearing carrier — the delete is escalated/co-designed, not improvised. @@ -79,11 +98,11 @@ The anemic `String` leaves are **more than one**: `host_effect.ShellCommand{scri Two enforcement milestones, kept distinct — my earlier draft conflated them: - **LANDED — bash-AST-vocab containment (#6854).** `realization_vocabulary_containment` reds any intent-layer import of `bash_build` / `ShellStmt` / `serialize_bash`. This confines the *language-AST vocabulary* only; it does **not** recognize `extdeps.shell` or forbid `shell.Exec`. -- **PARTIAL — meta-exec confinement (Wave A1 import wall LANDED #6900; construction wall OPEN).** `shell.Exec` is isolated in `extdeps/shell/exec.dag`, and `v2.lens.meta_exec_confinement` enforces the module-granular import wall. Its exception roster has since shrunk **3 → 0**, so a new intent-layer import outside the declared realization-edge prefixes is a typed leak with no exception to grant. That is validation over the import graph, not the terminal construction wall: `TransportScript` remains a transparent brand over `String`, and direct `shell.Exec.Run` callers on an allowed realization edge can still construct computed/cast inputs. `host_language_transport_script` is live but deliberately green on `ComputedApplication`; it backstops raw literals rather than making the cast path unwritable. Closing that surviving path is the DESIGN-named meta-exec-confinement milestone, coupled to reference/import visibility. +- **PARTIAL — meta-exec confinement (Wave A1 import wall LANDED #6900; construction wall OPEN).** `shell.Exec` is isolated in `extdeps/shell/exec.dag`, and `v2.lens.meta_exec_confinement` enforces the module-granular import wall. Its exception roster has since shrunk **3 → 0**, so a new intent-layer import outside the declared realization-edge prefixes is a typed leak with no exception to grant. That was validation over the import graph rather than the terminal construction wall, and the construction half has **since landed**: `TransportScript` is a **`sole_constructor` record** whose single mint `transport_script_seal` is `admit_callers`-sealed to exactly two production declarations (`gunbc.retained_shell_script` `retained_shell_script_to_transport`, `gunbc.bash_materialized_transport` `bash_materialized_transport`), and the cast form closed with it — `04_infer` `sole_constructor_construction_diags` judges a cast into a sealed type (#7962), so a computed or cast input can no longer reach that edge. `host_language_transport_script` stays live as a raw-literal backstop. The surviving residue is not a construction path but the two admitted bridges' bare-`String` body parameter, counted at every call and dissolved by per-site migration. ### Import-visibility for meta-exec confinement (operator, 2026-07-19; Wave A1 import wall landed, construction wall open) -`shell.Exec.Run` is the honest bottom bash transport — kept, not deleted — but it must be **heavily sequestered** so its only caller is realization and its input is always `emit`'s output. Wave A1's import-graph analysis (`LayerImportFact`) confines the isolated module and now has an empty exception roster. It does **not** constrain how an allowed realization-edge caller obtains a `TransportScript`; because the brand is transparent, a computed `String as TransportScript` remains writable there. Two ways were proposed to sequester the operation; the first landed the import half only: +`shell.Exec.Run` is the honest bottom bash transport — kept, not deleted — but it must be **heavily sequestered** so its only caller is realization and its input is always `emit`'s output. Wave A1's import-graph analysis (`LayerImportFact`) confines the isolated module and now has an empty exception roster. It did not by itself constrain how an allowed realization-edge caller obtains a `TransportScript`; that half landed separately in #7962, which sealed the type and closed the cast form. Two ways were proposed to sequester the operation, and the outcome differed from both: - **(a) Isolate the bottom transport into its own module** (`extdeps/shell/exec.dag`) → the existing module-granular wall confines imports. **Landed (Wave A1), necessary but not sufficient for construction confinement.** - **(b) Add symbol/reference-level visibility** so the bottom transport can be callable only from the emit-owned realization seam — the general feature, converging with the namespace-only-resolution lane (references become `container.member`). This is the still-open construction-confinement direction; do not infer its completion from the empty import-exception roster. diff --git a/docs/plans/shell-to-dag-residual-census-and-arc-completion.md b/docs/plans/shell-to-dag-residual-census-and-arc-completion.md index 7262f35be81..831dea2cad9 100644 --- a/docs/plans/shell-to-dag-residual-census-and-arc-completion.md +++ b/docs/plans/shell-to-dag-residual-census-and-arc-completion.md @@ -26,6 +26,114 @@ A distinct axis from §1's *emission* census: these are ops whose **interface sh --- +## 0c. The named boundary — argv is not the authority, and CLI invocation is not the universal effect model (2026-08-19) + +This lane and the CLI-invocation lane (`cli-invocation-emission-design.md`, gunbc#8467, `sharp-ant-396`) are **one migration program with a named boundary**, not competing destinations. Recorded here because without the boundary stated, #8467's diagnosis — that an argv array is a serialization exactly as bash text is a serialization of a bash AST — reads as replacing every typed effect with a CLI tree, which would move the authority *downward* into one particular realization technology. + +The division: + +- **This lane owns the semantic destination and site routing.** The authority remains the typed domain operation or the typed `HostEffect`. It decides whether a realization is native, REST, filesystem, library, CLI-backed, or necessarily text-emitting. That is unchanged by #8467 and is exactly what §1's five categories already do. +- **#8467 owns one realization sublayer:** how a **CLI-backed** handler lowers a tool-semantic request through cited CLI grammar rows into a carrier. It is the inside of one cell of §1.C, not a replacement for §1. +- **argv is never the authority.** `ArgvCommand` builders and `transport shell { argv: [...] }` are migration substrates. +- **CLI invocation is not the universal effect model.** A native handler reaches no CLI surface at all. + +The complete shape, so the layers are not re-fused by the next reader: + +``` +typed domain operation / HostEffect <- this lane; the authority + | + | realization selection <- this lane + | + +-- native handler: REST / filesystem / library / Redfish / ... + | (no CLI surface is reachable from here) + `-- CLI-backed handler <- #8467 owns everything below this line + | private tool-semantic request + v + admitted tool process plan (tool identity, emitted CLI surface, stdin, + cwd/environment, observation contract) + | + +-- local target: ProcessArgv -> direct process spawn + `-- SSH target: shell simple-command tree -> shell grammar -> RFC 4254 string + | + v + raw ProcessObservation -> tool-policy decoder -> typed tool observation + -> domain decoder -> domain result / reconciliation receipt +``` + +**Two consequences are load-bearing.** Local process execution has **no shell and no quoting** — the v1 seed realizes `transport shell` as `Command::new(&argv[0]).args(&argv[1..])`, with no shell, no word splitting and no quoting layer, so the name is a historical DSL keyword rather than a description (this is why the host-edge carrier is `ProcessArgvExpansion`, not `ShellArgvExpansion` — the §3 nickname class, caught before it spread). And **SSH is a different target**: RFC 4254 carries one command string, and far-side shell interpretation is a deployment capability to be modeled or observed, never assumed. + +### What this corrects in this document + +§5's framing — "the arc needs only ~4 new typed ops", §5.A's new-op list and §5.B's call-an-existing-op table — is **not wrong about the destination** but is written in the vocabulary of the layer #8467 replaces. Typed argv is the terminus for a **CLI-backed** handler only in the sense that argv is what the process boundary consumes; it is not the authority a domain module authors against. Concretely, for the §5.B rows: calling `systemd.Systemctl.ShowProperty` instead of concatenating `systemctl show --property=…` remains exactly the right move and those rows stand as written. What changes is one layer in — the op's *own* realization must not itself be a hand-authored flag list, which is the defect #8467 measured (a dropped `--fail` across eleven curl sites made a 401 read as success). So a §5.B migration is complete at this lane's grain when the concat is gone and the caller names semantics; it is complete at #8467's grain when the op's flags derive from cited rows. **Do not treat a §5.B row as blocked on #8467** — the two grains land independently, and this lane's row is the prerequisite, not the dependent. + +### The measured shape of the remainder (2026-08-19) + +Measured on `dag/**` and `src/v2/**`, excluding `/test/`, `*_test.dag` and fixtures, so these are production populations rather than witness counts: + +| population | production count | +|---|---| +| `transport shell` blocks | 236 lines across 48 files — **230 lines / 45 files in `dag/extdeps`**, 5 lines / 2 files in `dag/gunbc`, 1 in `dag/tools` | +| `argv:` lines | 457 — 275 in `dag/extdeps`, 172 in `dag/gunbc`, 10 in `src/v2` | +| counted retained-script bridge call sites | 48 across 13 files, enumerated below | +| distinct `fn *_argv` builders (whole tree) | 333, of which ~158 lead with `shape`/`witness`/`operation`/`typed` and model no tool at all | + +The 13 files, named rather than counted, because a count cannot expose a misfiled row: + +`gunbc.command_runner` · `gunbc.host_effect_realize` · `gunbc.retained_shell_script` · `gunbc.package_delivery` · +`gunbc.codex_app_server_press` · `gunbc.bmc_netboot_serve` · `gunbc.provider_wire_evidence` · `gunbc.design_document` · +`tools.gunbc_ci` · `tools.emit_host_gate` · `tools.host_prelude` · `tools.interpreter_dispatch_bijection_real_roster_transport` · +`v2.lens.meta_exec_confinement` + +**Three are absent from the §4 punch-list**, which still calls itself the complete per-instance list at `78f43c38`: +`package_delivery`, `codex_app_server_press` and `bmc_netboot_serve` are post-July production work. That heading's +"complete, current" claim is true as of its stated commit and false as of this one; it is a snapshot, and this row is +its correction rather than a second census. + +**And a classification question the count concealed, flagged not settled.** `package_delivery` (7 calls) and +`codex_app_server_press` (3) route through `retained_foreign`, whose `dissolves_to` is `retained_foreign_emit_ref` — +the Bash emitter, the destination for foreign executors and pre-runtime bootstrap. Both appear to run inside a present +gunbc runtime, which would make their destination typed effects (`retained_runtime`) instead. If that is right, ten +bridge calls declare the wrong dissolution target, and the bucket is precisely what a future session reads to decide +where they go. Recorded as a question for their owners — the executor window is the deciding fact and this document +does not own it — not as a verdict rendered from a grep. + +**The load-bearing reading:** `transport shell` is overwhelmingly an `extdeps` population — 230 of 236 production lines — i.e. it sits *beneath already-typed operations*, in the interface layer, not in the intent. This lane's original job, getting shell out of the intent, is therefore substantially done, and most of what remains is transport depth inside a CLI-backed cell. That is #8467's subject, not this document's. + +Two cautions against over-reading it. The `dag/gunbc` argv residue is **172 lines across 41 files** — real intent-adjacent work, not a rounding error (an earlier scoping pass in conversation quoted the 41 *files* as though it were the line count; recorded so the smaller figure does not get re-cited). And a `transport shell` block is not a residual shell program at all: the v1 seed executes it as `Command::new(&argv[0]).args(&argv[1..])`, so 236 blocks are 236 *process invocations*, of which the shell-shaped ones are the SSH-composed subset. + +**Do not turn these counts into a work plan.** Under the replacement-migration rule the unit is a root consumer × subject population, and the census direction reliably overestimates: sizing by argv occurrence, then by executable head, then by tool, each produced an inflated number, because a tool vertical, its site cutovers and its `host_effect_apply` caller are commonly **one** vertical whose acceptance condition is the old site's deletion — not three workstreams. The domain clusters this document already tracks in §5.D, each with its own un-defer trigger, are the better unit. + +**This section is a boundary and scoping increment, NOT a migration closeout receipt.** Neither finish line below is met at the commit introducing this text: `HostEffect.ShellCommand` still exists and is still constructed (including `host_effect_plan`'s empty placeholder), `command_runner`'s argv → text → heredoc route is live, and `retained_runtime` / `retained_srvn` remain defined and populated. Stated because a section naming a finish line reads, at a glance, like a claim to have reached it. + +### Two finish lines, named separately + +The program has two, and conflating them is what makes the remainder look larger than it is: + +``` +SHELL-DAG runtime-present script carriers are zero; + foreign/bootstrap shell is emitted from typed intent; + ShellCommand and the runtime retained-script bridges are deleted. + +CLI-AUTHORITY production CLI-backed realizations derive their concrete argv + from semantic tool requests and cited surface rows. +``` + +SHELL-DAG is this document's; CLI-AUTHORITY is `cli-invocation-emission-design.md`'s. A site can be complete against the first and still owe the second, and that is not a defect in either — it is the boundary in §0c working. The corollary for dispatch: **a SHELL-DAG row is never blocked on DECIDING its semantic destination.** Its production cutover may share a carrier or target increment with CLI-AUTHORITY — `command_runner`'s is the live case: deleting that argv → quoted text → heredoc route needs the structured process-argv carrier, and its SSH arm needs the nested shell-command target — and those shared increments are implemented once, never bypassed with another shell string. *(Corrected 2026-08-19, review on #8535. This read "never blocked on CLI-AUTHORITY" flat, which is true of the homing decision and false as a sequencing rule, and the counter-example was named in the same document.)* + +### A live instance of the forbidden SSH shape + +`extdeps.exec.command` `command_over_transport` constructs `ArgvCommand { argv: append(ssh_exec_prefix(target: t), items: command.argv) }`. That is exactly the `append(ssh_prefix, inner.argv)` composition §0c forbids — SSH is a nested target whose carrier is one RFC 4254 command string, not a prefix on an argument vector. It is production code beneath the generic runner, so every SSH-transported `ArgvCommand` in the tree flows through it, and it is the concrete mechanism by which argument boundaries are lost remotely. + +It sits in the same file as `gunbc.command_runner`'s round trip — `run_shell_command` takes a typed `ArgvCommand`, renders it to quoted text via `shell_command_render`, and posts it through `shell.Exec.Run`'s heredoc transport. That carrier already declares the repair in `command_runner_dissolution_trigger`: *dissolves when `host_effect_apply` binds `ArgvCommand` execution as a typed transport handler*. So the runner cut and the SSH target are one vertical, not two, and the debt was declared before it was scoped. + +### What is owed, and by whom + +- The **negative falsifier** — one witness proving a Redfish/REST path reaches no `JqInvocation`, no `CliSurface`, no `ProcessArgvExpansion` and no shell target — is owed by the CLI lane (`sharp-ant-396`), not by this one. It guards this boundary better than any further argv census would, and per the replacement-migration rule a census over a structure being deleted is the attractor at work. +- The **scoped supersession sentence** in `cli-invocation-emission-design.md` is that document's to place. It supersedes typed argv as the terminal representation *for CLI-backed handlers*; it does not supersede typed domain effects, typed extdeps operations, host-effect routing, or native realizations. +- **`DESIGN.md` needs no edit, and the reason CHANGED under this PR.** The first draft of this clause said its shell → intent open-thread row already routed runtime-present sites to typed effects, so the boundary falsified nothing in it. That row **no longer exists**: #8476 cut DESIGN to ~9.5k words and removed the open-threads section wholesale. What survives, and what the boundary now instantiates, is §3's general paragraph — *interface, realization and policy are three facts, not one row*, with the transport a Realization handler one of N and the dispatch that selects a realization sitting peripheral rather than in the interface. A CLI-backed handler is that paragraph's shape at the tool seam, so the boundary is a consequence of DESIGN rather than an addition to it, and still needs no edit there. *(Rewritten 2026-08-19 while correcting this document's other stale claims — the original clause was accurate when written and was falsified by a merge to main two commits later. Recorded rather than silently swapped, because the failure mode is the subject of this very commit.)* + +--- + ## 1. Residual-shell census (current tree) Five categories. "Genuine emitter" = emits bash that actually runs; "oracle/scaffold" = shell text retained only for a test. *(Corrected 2026-07-26: the oracle/scaffold definition read "`serialize_bash` retained only for a test" — that sidecar is deleted and **no** test retains it, so the definition described an empty class by its mechanism instead of by its role. §4.H is the live statement of this category.)* @@ -143,7 +251,7 @@ Two tracks run in parallel. The v2 bidirectional bash language **is** the single bash authority today. The **Phase-3 wall** that turns *"no sidecar exists"* into *"a hand-built transport string is unwritable"* (§5 construction over validation) has **partially** landed (#7184, operator acceptance 2026-07-24): the free minter is deleted and `RetainedShellScript` — a **record** — is the sole mint **for the `ShellOnHost` realization edge**. -It is **not** the global transport wall. `shell.Exec.Run` still declares `input { script: TransportScript }` over a transparent brand (`dag/extdeps/shell/exec.dag:16,26`), so `String as TransportScript` stays writable outside the record wall — demonstrated in-tree at `src/v2/test/fixture/meta_exec_confinement_scan/leak/plant.dag:6`, and detailed in §4's dissolution trigger and §5's end-state row. So Track 1's **deletion** terminal is behind us; Track 2's **wall** terminal is **not**. What remains is **meta-exec confinement** (§4.F, last row) plus the per-site migration itself. +The construction half of the global transport wall has **since closed too**: `TransportScript` is a **`sole_constructor` record** whose single mint `transport_script_seal` is `admit_callers`-sealed to exactly two production declarations (`gunbc.retained_shell_script` `retained_shell_script_to_transport`, `gunbc.bash_materialized_transport` `bash_materialized_transport`), and the cast form closed with it — `04_infer` `sole_constructor_construction_diags` judges a cast into a sealed type (#7962), so neither a record literal nor a cast can produce one outside those bridges. What remains is not a construction hole but a **String residue** — both admitted bridges take a bare body `String`, so arbitrary text still reaches a transport through a counted, reason-bearing, `dissolves_to`-carrying call. That is conspicuous rather than impossible, and it dissolves with the per-site migration, not with more wall work. So Track 1's **deletion** terminal is behind us and Track 2's **construction** terminal is too; what remains is the per-site migration itself. *(Corrected 2026-07-27, `review 43608`. This read "has also **already landed** … is the sole mint. So Tracks 1 and 2 feed neither a deletion nor a wall; both terminals are behind us." That declared a narrower `ShellOnHost` wall to be the completed **global** transport wall — a §3 violation in which the planning authority overstates a landed scope, and the misdispatch risk is concrete: a worker reading this routes away from the still-open meta-exec confinement work, which is exactly the harm this document exists to prevent. This is the **fifth** site of this same claim corrected in this PR. The first four were fixed while this one survived because each pass swept for the sentences already seen rather than enumerating every sentence that asserts the fact — the standing rule, stated here so it outlives the individual corrections: **enumerate by claim across the whole authority set, then verify each; a correction that fixes only the site under review is not finished.**)* @@ -303,16 +411,16 @@ These are correct as shell (GHA `run:`, cron, git hooks, pre-runtime bootstrap | `roadmap_static_site.dag` body fns | srv1 dashboard (belt B) | E-emit / dissolves with belt B | | `fleet_posix_accounts.dag` `probe_command: "id "` (×4) | account-existence probe | **NOT a shell emit site** — authored provenance metadata; live proof is `deploy_access_check_observed` via typed `SudoNopasswdExecuteProbe` | -### 4.F — bottom transport (Phase-3 WALL — **PARTIALLY LANDED** on the `ShellOnHost` edge, operator acceptance 2026-07-24; the `shell.Exec.Run` sink stays open) +### 4.F — bottom transport (Phase-3 WALL — **LANDED at construction on both edges**: `ShellOnHost` record wall #7184, `TransportScript` seal #7962) -> **Trued up 2026-07-26 (`review 43486`).** This table described the wall as *pending* and directed Phase 3 to "brand `TransportScript`" across "26 sites". **The `ShellOnHost` half of the wall landed on 2026-07-24 and branding was proven ineffective by execution** (the `shell.Exec.Run` sink stays open — see the row below) — both facts were already recorded in §5.E's ruling block ~275 lines below, which superseded this table in place without updating it. A worker reading the action column would have executed superseded work. Corrected against the tree. +> **Trued up 2026-07-26 (`review 43486`).** This table described the wall as *pending* and directed Phase 3 to "brand `TransportScript`" across "26 sites". **The `ShellOnHost` half of the wall landed on 2026-07-24 and branding was proven ineffective by execution** (the `shell.Exec.Run` sink stayed open until #7962 sealed it — see the row below) — both facts were already recorded in §5.E's ruling block ~275 lines below, which superseded this table in place without updating it. A worker reading the action column would have executed superseded work. Corrected against the tree. | surface | status | action | | --- | --- | --- | -| `transport_script_from_body(body: String)` | **DELETED** from `extdeps.shell.exec`. Not 26 live sites — **zero**. Surviving occurrences are a note recording its replacement (`retained_shell_script.dag:15`), two compile-**RED** controls asserting the deleted-minter fake *fails to compile* (`transport_script_wall_compile_red_test.dag`), and v1-seed Rust detector code | **none — done for the `ShellOnHost` edge.** Its realization takes a counted `RetainedShellScript` record. Direct `shell.Exec.Run` remains open: `retained_foreign` / `retained_runtime` accept a bare body `String`, and an authored `String as TransportScript` cast is still legal pending meta-exec construction confinement | -| `TransportScript` branding | **abandoned deliberately, not pending.** `TransportScript = String where brand(…)` is a *transparent* brand: `peel_nominal_alias_identity` peels it to its base, so a bare or computed `String` flows into a `TransportScript` position with no cast. Branding alone cannot make a hand-join a type error | **superseded on `ShellOnHost`** by the record wall — a `String` cannot fill its record-typed field. It does not wall direct `shell.Exec.Run`; see §5.E's design-correction block | +| `transport_script_from_body(body: String)` | **DELETED** from `extdeps.shell.exec`. Not 26 live sites — **zero**. Surviving occurrences are a note recording its replacement (`retained_shell_script.dag:15`), two compile-**RED** controls asserting the deleted-minter fake *fails to compile* (`transport_script_wall_compile_red_test.dag`), and v1-seed Rust detector code | **none — done for the `ShellOnHost` edge.** Its realization takes a counted `RetainedShellScript` record. Direct `shell.Exec.Run` closed at construction with #7962: `TransportScript` is a **`sole_constructor` record** whose single mint `transport_script_seal` is `admit_callers`-sealed to exactly two production declarations (`gunbc.retained_shell_script` `retained_shell_script_to_transport`, `gunbc.bash_materialized_transport` `bash_materialized_transport`), and the cast form closed with it — `04_infer` `sole_constructor_construction_diags` judges a cast into a sealed type (#7962). The residue is the bridges' bare-`String` body parameter, counted at every call, not a construction route | +| `TransportScript` branding | **abandoned deliberately, and now historical.** It *was* `= String where brand(…)`, a transparent brand `peel_nominal_alias_identity` peeled to its base, so branding alone could never make a hand-join a type error | **superseded twice.** The record wall closed `ShellOnHost`; #7962 then made `TransportScript` itself a `sole_constructor` record with an `admit_callers`-sealed mint, closing direct `shell.Exec.Run` and the cast form. Nothing here is pending | | `shell_exec_via_bash` (`shell_bash_runner.dag:32`) | heredoc runner scaffold | dissolves when no caller passes a raw script *(still open)* | -| `host_language_transport_script` lens | **LIVE — activated by #7184**, not inert. `wall_residue_live_test.dag:4`: *"the previously-inert … lens is wired as a per-PR live consumer over the `shell.Exec.Run` anchor sites"*, disposition `ReadsLiveTree`. It reds a **new raw literal** at an enrolled Run position, and stays **deliberately green** on `ComputedApplication` (the counted bridge calls) — which is why it never caught the #7064 computed-join fake | **none — done as a literal-blob backstop.** `RetainedShellScript` closes the computed-join class only at the `ShellOnHost` record field; the lens deliberately permits computed applications and the transparent cast path at direct `shell.Exec.Run` stays open. Do not "promote" the lens — that action presumed a brand that does not work and a lens that was already switched on | +| `host_language_transport_script` lens | **LIVE — activated by #7184**, not inert. `wall_residue_live_test.dag:4`: *"the previously-inert … lens is wired as a per-PR live consumer over the `shell.Exec.Run` anchor sites"*, disposition `ReadsLiveTree`. It reds a **new raw literal** at an enrolled Run position, and stays **deliberately green** on `ComputedApplication` (the counted bridge calls) — which is why it never caught the #7064 computed-join fake | **none — done as a literal-blob backstop.** `RetainedShellScript` closed the computed-join class at the `ShellOnHost` record field and #7962 closed the direct `shell.Exec.Run` sink at the type; the lens deliberately permits computed applications, which are now exactly the counted bridge calls. Do not "promote" the lens — that action presumed a brand that does not work and a lens that was already switched on | | meta-exec module `extdeps.shell.exec` | not walled | module-isolate / symbol-visibility confinement (meta-exec-confinement lane) *(still open — the genuinely remaining Phase-3 item)* | ### 4.G — bash-AST emit vocab (emit-internal — **EXTINCT**, not merely confined) @@ -416,7 +524,7 @@ The state of every PR in this arc, so nothing is missed if work pauses here. **A - **§5.A** — **COMPLETE.** All four ops landed on #7194 and are verified in tree at their post-#7231 homes: `os.Hostname.ReadShort`/`Set` (`dag/extdeps/tools/hostname.dag`), `systemd.Systemctl.ListUnits` and `.Status` (`dag/extdeps/systemd/systemctl.dag:185,219`), `os.Id.Uid` (`dag/extdeps/tools/id.dag:26`). (`ssh.Session.ExecArgv` landed via C5; `Clock.Now` in `dag/extdeps/clock/clock.dag` already existed and is now the single authority for every `date -Iseconds` site.) **The finite new-op list this whole arc needed is closed** — everything remaining in §5.B is calling ops that now exist. - **§5.B** — the call-the-op migrations are **UNPAUSED** (the `ShellOnHost` wall landed, #7184; the still-open direct `shell.Exec.Run` sink does not re-pause them). D1/D2/D3 (#7192/#7193/#7194) and bucket A discharged the hostname, systemctl-read and clock clusters. **The 2026-07-26 “non-deferred queue is empty” conclusion is superseded by merged #7298:** its deploy-access preflight wraps already-modeled C5 operations back into raw `Run.command` strings at a runtime-present edge. The bounded correction is the first current §4.J row. Outside that regression, only the **operator-deferred srv\* cluster** (4.A5, including 4.D) remains in §5.B. -- **§5.E** — the **transport-script construction wall** — **PARTIALLY LANDED #7184** (the `ShellOnHost` record edge only; the `shell.Exec.Run` sink remains open — see §5.E). Built as a `RetainedShellScript` RECORD edge + free-minter deletion + counted bridges + lens activation + compile-fail REDs (see §5.E ruling block; "brand `TransportScript`" was found non-walling because the brand is transparent). The 2026-07-24 wall-first ruling that paused §5.A/§5.B is therefore discharged. +- **§5.E** — the **transport-script construction wall** — **LANDED in two steps**: #7184 walled the `ShellOnHost` record edge, and #7962 sealed `TransportScript` itself, closing the direct `shell.Exec.Run` sink and the cast form. Built as a `RetainedShellScript` RECORD edge + free-minter deletion + counted bridges + lens activation + compile-fail REDs (see §5.E ruling block; "brand `TransportScript`" was found non-walling because the brand is transparent). The 2026-07-24 wall-first ruling that paused §5.A/§5.B is therefore discharged. **⚠ Do-not-miss for wind-down:** @@ -514,7 +622,7 @@ The per-symbol remaining work and batching plan for §4.E CI sites. **Load-beari | Permanent foreign media | `expected_githooks_pre_push_sh`, `build_cron_entry_line` | roadmap `2-emit-partition`; unassigned | their **builders** route through typed intent → Bash; the emitted shell artifacts remain permanently because git/cron require that medium | | Runtime `Run.command` / `ShellCommand` terminal | `live_deploy.emit.deploy_raw` fed by `ensure_apt_package_step`, `apply_systemd_unit_write_step`, `apply_tree_sync_unit_write_step`, `tree_sync_restart_step_with_diagnosis`, `tailscale_serve_apply_step`, `install_d_owned_command`, `deploy_apply_preamble_steps`, `emit_artifact_upsert`, `emit_artifact_teardown`, `emit_deploy_teardown_dependency_refusal`, `apply_intent_from_effects`, `retract_intent_from_effects`; `host_effect_plan_placeholder_effect`; the `gunbc.host_effect.ShellCommand` carrier and its total match consumers `host_effect_realize.resolve_host_effect_cell` and `fleet_converge_cli.converge_cli_applied_knob_count` | roadmap `2-emit-partition`, coordinated with the host-effect lane | replace `Run.command` / `ShellCommand` with `Do{effect}` typed operations, migrate every total match, then delete the carriers; never count Pipeline wrapping as completion | | Deferred runtime srv\* | `host_effect_realize` · `srv3_join_shell_words`, `srv3_transport_witness_bin_success`, `srv3_transport_test_executable`, `srv3_apt_tool_present`, `srv3_tool_bin_path`, `srv3_chown_directory_to_current_user`; `host_build_cache_provision_script` · `build_cache_systemd_user_unit_body`, `build_cache_observe_stats_body`, `build_cache_classify_failure_body`, `build_cache_ensure_daemon_body`, `build_cache_read_back_body`, `build_cache_provision_script_body`, `build_cache_provision_shell_script`; `host_hygiene_reaper_script` · `host_hygiene_reap_install_units_body`, `host_hygiene_reap_classify_and_act_body`, `host_hygiene_reap_stale_override_body`, `host_hygiene_reap_script_body`; `host_hygiene_liveness_script.host_hygiene_liveness_read_body` | operator-deferred surviving srv\* actuator/runtime graph | un-defer a typed-effect migration with its live consumer; the separate dead install/reconcile subgraph is already deleted (#7233/#7237), so do not polish or resurrect it | -| Direct meta-exec construction | `tools.gunbc_ci.main`, `tools.merge_admission_stamp.pr_number_from_event`, `tools.emit_host_gate.gate_failure_exit`, `tools.host_prelude.toolchain_provision_shell_exec`, `gunbc.bmc_netboot_serve.bmc_netboot_run_bmc`, `gunbc.bmc_netboot_serve.bmc_netboot_put_path`, `gunbc.command_runner.run_shell_command`, `gunbc.host_effect_realize.run_shell_transport` — direct `shell.Exec.Run` sites through transparent/counted carriers | node/subtree visibility-grants `Reference` lane; per-site runtime/foreign owners still delete their bodies | confine who may form base→brand/meta-exec edges; `ShellOnHost` is already record-walled, direct `shell.Exec.Run` is not | +| Direct meta-exec construction | `tools.gunbc_ci.main`, `tools.merge_admission_stamp.pr_number_from_event`, `tools.emit_host_gate.gate_failure_exit`, `tools.host_prelude.toolchain_provision_shell_exec`, `gunbc.bmc_netboot_serve.bmc_netboot_run_bmc`, `gunbc.bmc_netboot_serve.bmc_netboot_put_path`, `gunbc.command_runner.run_shell_command`, `gunbc.host_effect_realize.run_shell_transport` — direct `shell.Exec.Run` sites through the two counted bridges | per-site runtime/foreign owners delete their bodies | **construction is closed at both edges** (#7184 record wall, #7962 seal); these rows are migration work, not wall work, and the `Reference`-verb lane is no longer their blocker | **Proposed batching (3 PRs):** @@ -552,7 +660,7 @@ The governing rule for the rest of the sweep, so "all other instances" stays dec **The construction wall this trigger waited on has PARTIALLY landed (#7184, 2026-07-24)** — it record-walls the **`ShellOnHost` realization edge** (`ResolvedHostEffectCell.ShellOnHost { script: RetainedShellScript }`, `dag/gunbc/host_effect_realize.dag:167`) and deletes the free minter `extdeps.shell.exec.transport_script_from_body(body: String)`, so a hand-assembled `String` no longer typechecks *on that edge*, with compile-fail REDs (§4.F, §5.E). -It does **not** close the `shell.Exec.Run` sink. `TransportScript` is a **transparent brand** over `String` (`type TransportScript = String where brand("TransportScript")`, `dag/extdeps/shell/exec.dag:16`) and `shell.Exec.Run` still declares `input { script: TransportScript }` (`:26`) — so `"…" as TransportScript` remains writable from any module, demonstrated live in-tree at `src/v2/test/fixture/meta_exec_confinement_scan/leak/plant.dag:6`. What guards that sink today is **validation, not construction** — the `meta_exec_confinement` scan the fixture feeds, plus `host_language_transport_script` — and DESIGN §5 is explicit that a lens *concedes* the bad state is writable. The code says so itself: `retained_shell_script_wall_note` files the surviving cast-mint's full closure on the node/subtree visibility-grants lane, where the `Reference` verb governs who may cast base→brand. +It did not close the `shell.Exec.Run` sink; **#7962 did.** `TransportScript` is a **`sole_constructor` record** whose single mint `transport_script_seal` is `admit_callers`-sealed to exactly two production declarations (`gunbc.retained_shell_script` `retained_shell_script_to_transport`, `gunbc.bash_materialized_transport` `bash_materialized_transport`), and the cast form closed with it — `04_infer` `sole_constructor_construction_diags` judges a cast into a sealed type (#7962). The `meta_exec_confinement` scan and `host_language_transport_script` remain as validation backstops, but construction is no longer what they guard. The leak fixture at `src/v2/test/fixture/meta_exec_confinement_scan/leak/plant.dag` is now **scan input and historical record only** — it can no longer be cited as evidence that the cast compiles. So *new* instances of the `ShellOnHost` class can no longer be authored; the punch-list is **not** closed at the top. @@ -566,7 +674,7 @@ What the trigger does **not** discharge is the **existing** rows: the wall stops ## 5. Method of Action — the bounded path to bash-free user space (calm-ferret-849, 2026-07-22) -**End state:** no user-space `.dag` constructs a shell string. Every "this `.dag` wants to call a bash script" instance resolves to exactly one of four paths below. The `realization_vocabulary_containment` lens (#6854, LIVE) already forbids bash-AST vocab (`ShellProgram`/`ShellStmt`/`serialize_bash`) in user space — the `shell.Exec.Run(script: TransportScript)` sink remains **open** (§5.E). #7184 retyped the **`ShellOnHost` realization edge** to the `RetainedShellScript` record (`host_effect_realize.dag:167`, `retained_shell_script.dag:9-10`) and deleted the free minter `transport_script_from_body`, so a hand-assembled `String` no longer typechecks *there* — but it did not retype `shell.Exec.Run`, which still declares `input { script: TransportScript }` over a transparent brand (`dag/extdeps/shell/exec.dag:16,26`). On the walled `ShellOnHost` edge what is still possible is **conspicuous**, not silent: authoring a counted `RetainedShellScript` row with a hand-built body is the *reviewed* escape, carrying a `reason` and a `dissolves_to` — that visibility is the mechanism, not a leak in it. The `shell.Exec.Run` sink has no such construction gate; it is lens-guarded only, and closing it is the meta-exec confinement milestone (module-isolate the bottom transport, or symbol-level import visibility). *(Rewritten 2026-07-26, `review 43544`. This sentence previously called that sink "the remaining hole", and my first correction **appended** a supersession notice below it instead of rewriting — leaving two mutually exclusive current-state claims in the same paragraph. That misapplied this document's own rule: strike-in-place is for corrections that are **illegible without the original**, and this one is not — the four-path end state survives the rewrite intact, so only the blocker claim needed replacing.)* +**End state:** no user-space `.dag` constructs a shell string. Every "this `.dag` wants to call a bash script" instance resolves to exactly one of four paths below. The `realization_vocabulary_containment` lens (#6854, LIVE) already forbids bash-AST vocab (`ShellProgram`/`ShellStmt`/`serialize_bash`) in user space — the `shell.Exec.Run(script: TransportScript)` sink **closed at construction with #7962** (§5.E). #7184 retyped the **`ShellOnHost` realization edge** to the `RetainedShellScript` record (`host_effect_realize.dag:167`, `retained_shell_script.dag:9-10`) and deleted the free minter `transport_script_from_body`, so a hand-assembled `String` no longer typechecks *there* — but it did not retype `shell.Exec.Run`; #7962 then sealed `TransportScript` itself, so that edge is closed at the type rather than by the lens. On the walled `ShellOnHost` edge what is still possible is **conspicuous**, not silent: authoring a counted `RetainedShellScript` row with a hand-built body is the *reviewed* escape, carrying a `reason` and a `dissolves_to` — that visibility is the mechanism, not a leak in it. The `shell.Exec.Run` sink now has a construction gate of its own — `TransportScript` is a **`sole_constructor` record** whose single mint `transport_script_seal` is `admit_callers`-sealed to exactly two production declarations (`gunbc.retained_shell_script` `retained_shell_script_to_transport`, `gunbc.bash_materialized_transport` `bash_materialized_transport`), and the cast form closed with it — `04_infer` `sole_constructor_construction_diags` judges a cast into a sealed type (#7962) — so the meta-exec confinement milestone is met at construction; what survives is the bridges' bare-`String` body, dissolved by migration rather than by a further wall. *(Rewritten 2026-07-26, `review 43544`. This sentence previously called that sink "the remaining hole", and my first correction **appended** a supersession notice below it instead of rewriting — leaving two mutually exclusive current-state claims in the same paragraph. That misapplied this document's own rule: strike-in-place is for corrections that are **illegible without the original**, and this one is not — the four-path end state survives the rewrite intact, so only the blocker claim needed replacing.)* **The headline (verified by op inventory @ `78f43c38`):** the arc needs only **~4 new typed ops**. Almost every site calls an op that already exists. @@ -632,11 +740,11 @@ Bash-as-target lives in one isolated backend: `src/v2/extdeps/languages/bash*` + This receipt is deliberately narrower than “all srv3 is gone.” `Srv3NbdProxyServe`, the surviving actuator/toolchain helpers in `host_effect_realize`, build-cache provisioning, and host hygiene are different live/deferred rows with their own triggers above; #7233/#7237 must not be used to mark those complete. -### 5.E — the enabler that had to come first — **PARTIALLY LANDED #7184** (closes the `ShellOnHost` string sink; `shell.Exec.Run` still open) +### 5.E — the enabler that had to come first — **LANDED in two steps**: #7184 closed the `ShellOnHost` string sink, #7962 sealed `TransportScript` and closed direct `shell.Exec.Run` -*(Heading and premise trued up 2026-07-26, `review 43537`. This read "THE ENABLER THAT **MUST COME** FIRST" in the imperative, and the paragraph below was written in the present tense — "can be faked" — as though the sink were still open. The `ShellOnHost` sink is closed, so both are past tense **for that edge** — but the `shell.Exec.Run` sink is **not** closed (transparent `TransportScript` brand, §4.F/§5.E), so the present tense still applies there. (Re-corrected 2026-07-27, `review 43614`.) The §5.A/§5.B rows it gates are the work that remains, not this.)* +*(Trued up again 2026-08-19: the heading and premise below were written while the `shell.Exec.Run` sink was open; #7962 closed it, so the present-tense claims are now past tense for BOTH edges. Original correction note follows. (Heading and premise trued up 2026-07-26, `review 43537`. This read "THE ENABLER THAT **MUST COME** FIRST" in the imperative, and the paragraph below was written in the present tense — "can be faked" — as though the sink were still open. The `ShellOnHost` sink is closed, so both are past tense **for that edge** — but the `shell.Exec.Run` sink is **not** closed (transparent `TransportScript` brand, §4.F/§5.E), so the present tense still applies there. (Re-corrected 2026-07-27, `review 43614`.) The §5.A/§5.B rows it gates are the work that remains, not this.))* -Every §5.A/§5.B row **could be** faked at the former `ShellOnHost{script}` edge, and **can still be** faked at direct `shell.Exec.Run(script)`, by joining argv back into a string — sleek-crab #7064 did exactly this (`argv_join(...) + " 2>/dev/null || true"`). While the `ShellOnHost` sink was reachable from intent, relocation was the path of least resistance and a brief alone could not stop it; the same risk remains live at direct `shell.Exec.Run`. So a construction wall was **not cleanup-after** — it was the enabler. The `ShellOnHost` record wall is now built; direct `shell.Exec.Run` remains writable through the transparent cast and counted string-taking bridges, so its construction/meta-exec confinement is still open. The original plan follows, with each bullet's actual fate marked: +Every §5.A/§5.B row **could be** faked at the former `ShellOnHost{script}` edge and at direct `shell.Exec.Run(script)` by joining argv back into a string — sleek-crab #7064 did exactly this (`argv_join(...) + " 2>/dev/null || true"`). While those sinks were reachable from intent, relocation was the path of least resistance and a brief alone could not stop it. So a construction wall was **not cleanup-after** — it was the enabler. **Both sinks are now walled**: #7184 built the `ShellOnHost` record edge, #7962 sealed `TransportScript`. What survives is the counted string-taking bridges, which are conspicuous by design. The original plan follows, with each bullet's actual fate marked: > ⚠ **The three bullets immediately below are the ORIGINAL plan, superseded by the ruling + design-correction block that follows.** Kept because the correction is only legible against them. **Each bullet failed differently, and the difference decides what a reader should do with it** — a *refuted* plan must never be retried; a *completed* one simply already happened; a *partially superseded* one still has live residue. Do not action them as written; read on. *(Flagged `review 43486`; classifications corrected `review 43522` — the earlier version lumped bullets 1 and 3 together as "refuted by execution", which was wrong for bullet 3 and is exactly the conflation §4.G's method note warns about.)* @@ -676,18 +784,18 @@ Every §5.A/§5.B row **could be** faked at the former `ShellOnHost{script}` edg > `transport_script_from_body(argv_join(...) + " 2>/dev/null || true")` and the vivid-wolf string-into-edge > near-miss), reconstructed as inline sources through `compile_dag_rust_emit_check`, **fail to compile** > (`transport_script_wall_compile_red_test.dag`) — not fail review. -> - **Surviving residue (filed, not closed here):** `x as TransportScript` (transparent-brand cast-mint) -> remains writable anywhere — the wall funnels the sanctioned mint through one -> `retained_shell_script_to_transport` body, but nothing *prevents* a stray cast in a fresh module. That -> is not closable by a record; it needs the **`Reference` verb** to govern who may form a base→brand cast -> edge. Filed as a named row on the node/subtree visibility-grants lane -> ([node-subtree-visibility-grants.md](node-subtree-visibility-grants.md) §3.1), the first brand with a -> concrete displaced cost — NOT an ad-hoc seed feature. +> - **Surviving residue (filed here, CLOSED LATER by #7962):** at the time of this ruling `x as TransportScript` +> remained writable anywhere, and the block below judged it not closable by a record, needing the +> **`Reference` verb**. **That prediction was wrong in a useful way.** #7962 closed it without any +> visibility feature, by making `TransportScript` a `sole_constructor` record AND extending +> `04_infer` `sole_constructor_construction_diags` to judge the cast form — the language grew the +> check rather than the carrier growing a guard. Kept because the reasoning is only legible against +> the original: the error was assuming the cast form was outside what construction could reach. ### Sequence 1. **§5.A** — add the ~4 ops (each cited, typed `exit`, typed-argv transport). Small, finite. -2. **§5.E** — **the construction wall LANDED #7184**, but this step is *not wholly* discharged and the original wording overstated it. What landed: the `RetainedShellScript` **record** edge + free-minter deletion + counted bridges + compile-fail REDs. The branding half was **refuted** (transparent brand). The **typed-argv realization edge is still open** — `RetainedShellScript.body` is a `String`, not `List`, so that path remains §5.A/§5.B work (see §5.E bullet 2). §5.B is already the only writable path for the *retained-script* sink. *(Corrected `review 43522`: previously struck through entirely and marked "LANDED", which retired open work.)* +2. **§5.E** — **the construction wall LANDED #7184**, but this step is *not wholly* discharged and the original wording overstated it. What landed: the `RetainedShellScript` **record** edge + free-minter deletion + counted bridges + compile-fail REDs. The branding half was **refuted** (it was a transparent brand), and the sink it left open was closed separately by #7962's seal. The **typed-argv realization edge is still open** — `RetainedShellScript.body` is a `String`, not `List`, so that path remains §5.A/§5.B work (see §5.E bullet 2). §5.B is already the only writable path for the *retained-script* sink. *(Corrected `review 43522`: previously struck through entirely and marked "LANDED", which retired open work.)* 3. **§5.B** — migrate by construction (call the op), green-by-execution + injection-RED, deleting each concat. 4. **§5.C** — route foreign-executor sites through the bash backend (bounded roster). 5. **§5.D** — un-defer per trigger.