diff --git a/docs/briefs/t-ground-rust-full-implementation.md b/docs/briefs/t-ground-rust-full-implementation.md new file mode 100644 index 00000000000..1b76acc43df --- /dev/null +++ b/docs/briefs/t-ground-rust-full-implementation.md @@ -0,0 +1,340 @@ +# T-Ground-Rust — Full Rust target-primitive implementation + +**Status:** PROPOSAL — dispatchable when **PR-F** (Q1 `BoundDeclaration` consumer + Q2 Rust structural axes via `ReferenceModel`) merges. PR-F is the **sole hard primary gate** for §A-§E (the Rust primitive structural rows this lane authors). Conditional gates apply only if specific rows are reached: a Substrate parent decision for the §B `Option` row (no top-level `Option` substrate parent at HEAD); the substrate `HigherOrderMethodSpec` shape decision (#1130) only if a primitive declaration requires higher-order method rows (§G, otherwise out of scope). PR-I (Q3 `RealizationCost`) is **NOT** a gate on this lane — `RealizationCost` population is owned by T-Ground-LanguageSpec per §F (out of scope here). Authored 2026-05-05 ahead of PR-F to keep the lane queue warm; consistent with `r2-grounding-manager.md:142` and the manager's directive that brief authoring is the only Day-1-ready Grounding item once host git is restored. No code lands until PR-F clears AND host git is restored AND the manager re-authorizes dispatch. + +**Lane:** T-Ground-Rust (XL) — item 2 of 11 in [`r2-grounding-manager.md`](r2-grounding-manager.md) (line 28 + lane row line 63). + +**Manager:** R3 Grounding Manager (`#1745`) — T-Ground sub-program lives under R3 Grounding per the current live dashboard topology (parent session bold-ferret-748). All STOP-and-escalate routing (§"Manager + escalation routing" + STOP #1-#12) targets `#1745` consistently. + +**Authority-file rename pending (out of scope for this lane):** the live authority document this brief consumes is `r2-grounding-manager.md` (HEAD path) — the file has not been renamed to `r3-grounding-manager.md` yet because the R2→R3 topology rename is owned by a separate program-management lane (Director-routed scope change), not this T-Ground-Rust worker brief. **All `r2-grounding-manager.md:NNN` citations in this brief reference the current HEAD file path verbatim and remain valid until the rename lands.** When the rename lands, this brief's path references migrate in lockstep; STOP routing already targets `#1745` and is unaffected. Treating `r2-grounding-manager.md` (HEAD file) and `R3 Grounding Manager #1745` (live topology routing) as a single coordinated authority — not a contradiction — until the rename completes. + +**Lineage / authorities consumed (no re-litigation):** +- Engine-reframe spec: [`docs/design-emission-model.md`](../design-emission-model.md) — Q1 `BoundDeclaration` (lines 994-1067), Q2 `ReferenceModel` (lines 1068-1117), Q3 `RealizationCost` (lines 1143-1208), Q4 universal four-property gate (line 1234), cadence table (lines 1271-1282). +- Two-authority discipline: `r2-grounding-manager.md:60-74` — **(a) Rust Reference §Types** authority for language-level structural types; **(b) std-library carriers** authority (std documentation) for `String` / `Vec` / `Box` / `Rc` / `Arc` / `HashMap` / `BTreeMap` / `HashSet` / `BTreeSet` / `Option` / `Result`. Each per-primitive row cites its own authority — mixing is a faithfulness violation per `r2-grounding-manager.md:124` (Q4 four-property gate). +- **Pinned external spec version (extdeps fidelity)** — explicit authority pin: + - **Target toolchain**: Rust **1.86 stable** (chosen because it introduced the "dyn-compatibility" rename from "object safety" cited at §A trait-object). + - **Reference URL base**: `https://doc.rust-lang.org/1.86.0/reference/...` (versioned, NOT the unversioned `/reference/...` or `/stable/` aliases that drift each toolchain release). + - **std URL base**: `https://doc.rust-lang.org/1.86.0/std/...` (versioned, NOT `/stable/std/...`). + - **Edition surface**: **Rust 2024 edition** (per RFC 3498 default-capture rules consumed at §A return-position `impl Trait`); pre-2024 editions covered as the "lifetimes-not-captured-by-default" branch in derivation rules. The edition is a *separate* axis from the toolchain — Rust 1.86 supports all editions 2015/2018/2021/2024. + - **RFC pointers** (3498, 3617, 3668): version-stable; no pinning required. + - **Row-citation discipline**: every Rust Reference / std citation in §A and §B MUST consume the pinned versioned URL. A floating `stable` or unversioned URL in a row is a P1 fidelity violation against this pin. + - The pin is itself tracked debt: when implementation dispatches, worker may need to re-pin to whichever toolchain CI runs against, with the same versioned-URL discipline. +- THESIS: `THESIS.md:171` — "Coercion = emission. No separate coercion engine." This lane lands the substrate facts the fold reads; it does NOT introduce selection logic. +- Substrate-fact-introduction: [`INVARIANTS.md`](../../INVARIANTS.md) §P1 (3-step procedure for every new field on `RustPrimitive` or sibling per-primitive carriers). +- Sibling brief shape: [`t-ground-languagespec.md`](t-ground-languagespec.md). +- Pilot precedent: [`grounding-pilot-receipt.md`](grounding-pilot-receipt.md) (variant-aware partition `IntegerPrimitive | NonIntegerPrimitive` locked per codex P2 adjudication 2026-04-25; widening to flat record out of scope). + +--- + +## Framing question this lane answers + +Does Rust's full target-primitive surface (Rust Reference §Types + std-library carriers) declare structurally in `.dag` against `BoundDeclaration` + `ReferenceModel` (per-primitive `RealizationCost` is **NOT** in this lane's scope — see §F; owned by T-Ground-LanguageSpec) with each primitive citing its own authority — so that the inhabitance walk `src/v3/grounding_engine/src/lib.rs:59` can validate every Rust primitive without falling back to `dsl/extdeps/languages/rust/types.dag` table lookup? + +A "yes" populates the substrate that Coercion-Fold reads, retires the table-driven scaffolding under T-Ground-Dissolve, and produces the structural acceptance gate `rust_target_primitives_declared_structurally` (per `r2-grounding-manager.md:124`). + +A "no" — or any discovery that scope is mis-modeled / authorities have drifted / the two-authority split forces a substrate distinction the substrate doesn't carry — escalates to manager per the discipline reminders below; do NOT paper over. + +--- + +## Scope + +### A. Rust Reference §Types primitives — structural declarations against authority (a) + +Author per-primitive structural rows in `dsl/extdeps/languages/rust/primitives.dag` (extending the existing `RustPrimitive` type at line 180 + `rust_pilot_primitives` data at line 208). Authority: (pinned per §Lineage; every row in §A consumes the 1.86.0 reference base). Coverage required: + +- **Numeric — integer family.** Pilot already covers `i8`–`i64`, `u8`–`u64`, plus `i128` (LANDED — manager correction 2026-05-05; `i128` exists in `primitives.dag` and the pilot mirror at HEAD). Remaining: `u128`, `isize`, `usize`. The `isize`/`usize` rows consume Q1's `PlatformDependent` variant of `BoundDeclaration` (`src/v3/std/substrate.dag:136`); this is the first non-pilot exercise of `PlatformDependent` and validates PR-F's Q1 consumer end-to-end. +- **Numeric — floating-point family.** `f32`, `f64`. **NOT DISPATCHABLE AT HEAD — STOP-AND-ESCALATE row.** No live float inhabitance exists at HEAD that the Rust f32/f64 rows can honestly consume: + - **Live float substrate declares an inadequate parent**: `dsl/std/float.dag:14-18` reads `type Float32 = Field` / `type Float64 = Field` / `type Float = Float64` — exact-`Field` over a fixed-width word, which elides IEEE-754's rounding/NaN/signed-zero/subnormal-policy facts entirely. Authoring Rust f32/f64 against this live parent would propagate the elision into the grounding substrate. + - **`ApproximateField` exists as the *intended future parent*** at `src/v3/std/approximate_field.dag:75` but no live `inhabits` declaration ties Float to it. The "Float inhabits ApproximateField" line at `dsl/std/algebra.dag:66` is **prose in a comment block**, NOT a declaration. The Float→ApproximateField migration is owned by T-NumericConstruction-ApproximateField and has not landed. + - **Real / base-carrier STOP** is also active (`src/v3/std/approximate_field.dag:11-14`; audit doc: `docs/audit/t-numeric-construction-approximate-field-real-parameter-stop.md`): even after migration, `F` in `ApproximateField` has no honest substrate target. + - **Therefore the Rust f32/f64 row is held**: worker STOPs and escalates to manager. **Do NOT** phrase Rust f32/f64 as inhabiting or consuming `ApproximateField` at HEAD; `ApproximateField` is the *post-gate candidate parent*, not a dispatchable consumer. **Discipline preserved post-gate**: Rust f32/f64 must NOT claim `OrderedRing` / `Semiring` inhabitance (IEEE-754 fails ring axioms — NaN, signed zero, non-associative addition); the no-ring-axiom discipline applies regardless of which gated parent eventually resolves. Authority cited: Rust Reference §Floating-point types + IEEE-754 §3 + Real-parameter STOP audit + Float-migration ownership in T-NumericConstruction-ApproximateField. +- **Textual.** `char` (32-bit Unicode scalar value) and `str` (UTF-8 byte sequence, dynamically sized). Per `design-emission-model.md:89, :530-532` (locked) **encoding is carried by algebra choice, not a refinement axis** — `str` inhabits `FreeMonoid` (UTF-8 by Rust's definition of `str`); raw-byte sequences (`[u8]`) inhabit `FreeMonoid`. Authoring an `encoding` axis on textual rows would be a P2 parallel-authority violation. Dynamically-sized status remains a structural axis. +- **Never.** `!` — uninhabited. Algebra inhabitance is restricted to algebras that require **no value witnesses** — i.e. operation-only algebras whose witnesses are functions out of the carrier (the elimination `absurd: fn(!) -> T` vacuously satisfies any `fn(!, ...) -> _` shape). `Magma` is constructible because its only field is `op: fn(!, !) -> !`. Algebras with stored value witnesses — `Monoid` requires `identity: T` (`dsl/std/algebra.dag:113`), `Group` requires `identity: T` and `inverse: fn(T) -> T` (`:127`), etc. — are **NOT inhabited** by `!` because no value of type `!` can be supplied for `identity`. The brief's prior universal-bottom framing was incorrect; per Q4 four-property gate (Faithful), claiming inhabitance for algebras whose witnesses cannot be constructed is a faithfulness violation. Per `INVARIANTS.md` §P1, the worker MUST cite which algebras `!` inhabits and which it doesn't, with the witness-constructibility receipt per algebra. Authority: Rust Reference §Never type. +- **Tuple.** Variadic structural product. Each tuple arity is not a separate primitive; the row declares the tuple constructor with arity as a refinement axis. Unit `()` is the 0-arity tuple — already in pilot. +- **Array.** `[T; N]` — fixed-cardinality structural product. **Cardinality carrier — substrate gap noted:** `Interval` is NOT a landed substrate type at HEAD (`grep '^type Cardinal' dsl/std/ src/v3/std/` empty); only `Interval` is instantiated (`src/v3/std/substrate.dag:129`), and the live cardinality carrier is `CardinalityBound = Exact(Int) | AtMostOne | Unbounded` (`src/v3/std/substrate.dag:143`). Until `Interval` lands (PR-PreF cascade per `design-emission-model.md:1023, :1038`), array rows consume `CardinalityBound::Exact(N)`. **Bridge + dissolution trigger:** when the `Cardinal` ordered-domain instance lands, retrofit additively to `Interval::BoundedInterval { lower: N, width: ZeroWidth }` per the Q5 collapse note (`design-emission-model.md:1267`); dissolution trigger is the `Cardinal` substrate landing PR. +- **Slice.** `[T]` — dynamically-sized structural product. Cardinality consumes `CardinalityBound::Unbounded` at HEAD (same substrate gap as Array); retrofits to `Interval::Unbounded` post-`Cardinal`. Authority axis: dynamically-sized. +- **Struct / enum / union — base shapes.** Per `r2-grounding-manager.md` §"T-Ground-Rust" lane row (drift-resistant section anchor). These are *constructor schemas*, not concrete primitives; the row declares the structural shape (named-field record / tagged sum / untagged union with safety-required-by-construction). +- **Function item.** Each named `fn` (or `impl` method, or tuple-struct/enum-variant constructor) has a unique anonymous **function-item type** carrying *identity* + signature. Identity is per-instantiation, NOT per-decl: `foo::` and `foo::` have *distinct* function-item types. The identity record carries `{ item_decl, generic_args: { type_args, const_args, early_bound_lifetimes }, constructor_case }` (see §C); `constructor_case` distinguishes ordinary fns from tuple-struct / enum-variant constructors (also function items per Rust Reference). Zero-sized. Coerces to a function pointer with the same signature; identity is lost on coercion. Authority: Rust Reference §Function item types. +- **Function pointer.** `fn(...) -> ...` — signature-only carrier; pointer-sized; multiple distinct function items with the same signature can be type-erased to the same `fn` pointer. Carries qualifiers as **coordinates on a record** (NOT a sum): `unsafe: Bool` and `abi: AbiTag` are independent — `unsafe extern "C" fn(...)` co-inhabits both, so they cannot collapse into a coproduct. Authority: Rust Reference §Function pointer types. +- **Closure.** Anonymous compiler-generated type carrying captures + `async_kind: AsyncKind` (Sync vs Async — whether the body desugars with `async ||` and returns a future). The **`lends_to_future`** predicate is **derived from `captures`** (not stored) per Rust Reference §async-closure-traits + RFC 3668: an async closure is *lending* iff the returned future captures any of the closure's captures **by mutable reference or by value** (so calling the closure again while a prior future is alive would be a borrow violation); *non-lending* iff the future only borrows captures shared-immutably or owns its own data. Trait inhabitance is **two cumulative towers** per Rust Reference §async-closure-traits — and the `lends_to_future` predicate suppresses the **sync `Fn` / `FnMut` tower**, not the async `AsyncFn*` tower: + - **Sync `Fn*` tower** (every closure regardless of `async_kind`): `FnOnce` always; `FnMut` if the body does not move out of any capture; `Fn` if the body also does not mutate any capture. **Additionally** when `async_kind = Async`: `Fn`/`FnMut` are suppressed if `lends_to_future = Lending` (a lending future cannot share `&self` / `&mut self` with a prior live future). + - **Async `AsyncFn*` tower** (only when `async_kind = Async`): `AsyncFnOnce` always; `AsyncFnMut` if the body does not move out; `AsyncFn` if the body also does not mutate. **Lending does NOT suppress the `AsyncFn*` tower** (the future-return surface is structurally distinct from sync re-call admissibility). + - **Combined**: a non-mutating non-moving non-lending async closure inhabits `Fn ⊇ FnMut ⊇ FnOnce` AND `AsyncFn ⊇ AsyncFnMut ⊇ AsyncFnOnce` simultaneously. A lending async closure with a non-mutating body still inhabits `AsyncFn` but only `FnOnce` (not `Fn`/`FnMut`) — the lending fact suppresses sync repeatable-call admissibility, not async tower membership. + - The `move` keyword controls capture mode (by-ref vs by-value) only; it does NOT directly determine `lends_to_future`. By-value consumption of a capture by the future IS lending (the future owns the consumed value, so the closure cannot be re-called to produce another future from the same capture). The one exception is the **deref-projection exception** per Rust Reference §async-closure-traits: when a deref-projection captures a smart-pointer's *referent* (e.g., a `move` closure that captures `Box` and the future only borrows `&*the_box`), the future holds a borrow but the closure environment retains ownership of the smart pointer — non-lending. This exception is structural and must be encoded in the `lends_to_future` derivation, not papered over. + - Authority: Rust Reference §Closure types §async-closure-traits + RFC 3668 (precise-captures-and-coercions). See §C for the field shape. + +These three are **structurally distinct**, NOT three rows under one `FunctionKind` enum: function-item identity (one row per fn item) is incompatible with function-pointer signature-only shape, and closure captures can't fit either. Worker MUST keep them separate at the `RustPrimitive` variant level (see §C below); collapsing item-identity into pointer-signature loses faithfulness (Q4) at the inhabitance step. +- **Reference.** `&T` (shared, immutable, lifetime-bounded), `&mut T` (exclusive, mutable, lifetime-bounded). Both inhabit `ReferenceModel` with axes (`mutability`, `lifetime`) populated; ownership axis is `Borrowed`. Lifetime is **structural, not annotation-driven** per T-Ground-Lifetime-Analyzer authority (LANDED #1206 / #1218 / #1220) — this lane consumes the lifetime axis as substrate, does NOT re-author it. +- **Raw pointer.** `*const T`, `*mut T`. `ReferenceModel` axes (`mutability`, `representation`); ownership axis is `Raw`; no lifetime. The unsafe/safe distinction is carried by `representation`, not a separate `safety` axis (Q2 lock declares the four-axis set `{lifetime, mutability, ownership, representation}` — workers MUST NOT introduce a parallel `safety` coordinate). +- **Trait object.** `dyn Trait` — dynamically-sized, vtable-bearing. Per Rust Reference §Trait object types, the row carries a structured record (NOT a flat trait-bound set): + - `base_trait: Option` — the primary (non-auto) trait the object is over (`Trait` in `dyn Trait`); **at most one** non-auto base trait per object per Rust Reference §"Trait objects can only contain one trait that is not an auto trait" — zero is valid for auto-traits-only objects (e.g., `dyn Send`, `dyn Send + Sync`, `dyn Send + 'a`). `None` ⇔ object is parameterized solely by auto traits + lifetime; `Some(t)` ⇔ object has a single non-auto base trait. + - `auto_traits: Set` — the set of auto traits (`Send`, `Sync`, `Unpin`, `UnwindSafe`, `RefUnwindSafe`) carried alongside the base trait via `+` syntax (`dyn Trait + Send + Sync`); structurally distinct from the base trait, so collapsing them into one `trait_bounds` set loses the base-vs-auto distinction. + - `object_lifetime: Lifetime` — the lifetime bound on the object (`dyn Trait + 'a`); has default-elision rules per Rust Reference §"Default trait object lifetimes" — the row stores the explicit lifetime if present and records the elision-rule application when absent. + - **Dyn-compatibility constraint validation** (formerly "object safety," renamed in Rust 1.86): when `base_trait = Some(t)`, `t` MUST satisfy the dyn-compatibility rules (no generic methods unless explicitly opted out via `where Self: Sized`; no `Self: Sized` requirement; no associated constants, etc.) per Rust Reference §"Dyn compatibility." Worker validates structurally before declaring the row; a non-dyn-compatible trait used in `dyn Trait` position is an emit-time error, not a substrate-shape choice. When `base_trait = None` (auto-traits-only object), dyn-compatibility is vacuously satisfied — auto traits are always dyn-compatible per Rust Reference §"Auto traits." +- **`impl Trait` — split into two rows per position** (Rust Reference §Impl Trait distinguishes them as separate spec facts): + - **Argument-position `impl Trait`** — anonymous type parameter; caller chooses the concrete type; structurally equivalent to introducing a fresh universal type parameter `` at the call site. Carries the trait-bound set as a structural fact; no opacity (the caller knows the concrete type). Authority: Rust Reference §Impl Trait → Anonymous type parameters. + - **Return-position `impl Trait`** — abstract/opaque return type; *callee* chooses the concrete type and the caller sees only the trait-bound interface. Carries trait-bound set + `opaque_captures` (captured generic params + optional `use<>` precise-capture restriction) + `edition: RustEdition` + `item_kind: ItemKind`. **Default capture is `item_kind`-dependent, NOT edition-only** — per Rust Reference §Impl Trait → "Capturing" + RFC 3498: type and const params in scope are ALWAYS captured (all editions, all `item_kind`s); lifetime capture varies by **(`item_kind`, `edition`)** jointly. The pre-2024 lifetime exception is scoped to free fns + inherent associated fns/methods only; trait methods + trait-impl methods capture ALL in-scope generics including lifetimes regardless of edition. **§C carries the authoritative item_kind-by-item_kind matrix** — §A defers to §C for the structured derivation; consult §C before authoring any RPIT row. **`use<>` precise-capture legality (Rust Reference §precise-capturing) imposes FIVE constraints** on the use-list, all validated before declaring `Some(_)`: (1) all in-scope type/const params MUST be in the list (use<> cannot narrow type/const); (2) all lifetimes appearing in **this** abstract type's own bounds MUST be in the list (per-abstract-type, NOT cross-sibling — see §C); (3) lifetimes not mentioned and not bound-required are excluded — the only narrowing axis is lifetimes; (4) on trait methods, the use-list must include all trait-generics the method captures (RFC 3617); (5) **`use<>` is forbidden when the function uses anonymous argument-position `impl Trait`** (anonymous-parameter `impl Trait` in arg position introduces synthetic generics outside the user's named-generics scope, so return-position `use<>` becomes illegal entirely). See §C for the structured derivation. Existential, not universal. Authority: Rust Reference §Impl Trait → "Capturing" + precise-capturing + RFC 3498 + RFC 3617. + +Collapsing these into one row drops the universal-vs-existential distinction (caller-chooses vs callee-chooses) — a P1/M3 spec-fidelity violation per the reviewer pointer. §C below carries two sibling `RustPrimitive` variants. + +Each primitive row cites its **authority URL** (Rust Reference section or std-doc URL) in a comment adjacent to the row per the brief-authoring-checklist convention. + +### B. std-library carriers — structural declarations against authority (b) + +Authority: per type (pinned per §Lineage; every row in §B consumes the 1.86.0 std base — e.g., `Vec` → `https://doc.rust-lang.org/1.86.0/std/vec/struct.Vec.html`). Coverage required: + +- **`String`** — owned, growable, UTF-8 char sequence. Inhabits `FreeMonoid` (per `design-emission-model.md:534`); the algebra choice IS the encoding distinction (`FreeMonoid` would be raw bytes — `Vec` territory, not a `String` candidate). Refinement axes: ownership = `Owned`; growability = `Growable`; lifetime = `self`. **No `encoding` axis** — that would duplicate the algebra-carried fact. +**std-carrier full-signature discipline.** Per Rust std documentation, every collection carrier carries hidden generic parameters (hasher `S`, and on nightly the allocator `A`) that the brief MUST surface as structural axes **for the parameters stable at the pinned 1.86.0 toolchain**. Dropping stable-surfaced axes loses extdeps-fidelity facts before grounding (P1 violation). Each row enumerates the full Rust 1.86.0 *stable* signature, with the hasher axis carried alongside K/V/T (stable, in scope for Phase 1). The allocator axis is **NOT** authored in Phase 1 — it is unstable at the pin and held under STOP #11 + STOP #12 (see "Allocator parameter status" below + §H STOP table). When the toolchain pin is later raised past `allocator_api` stabilization, the rows must add `A: Allocator` per the new Rust Reference signature; until then, authoring an allocator-axis on a §B row is itself a P1 violation (it would author an unstable spec fact under a stable pin). + +**Trait-bound discipline.** Each row enumerates the full Rust signature *as it appears at the pinned 1.86.0 stable target* (per §Lineage authority pin), including parameter trait bounds (e.g., `T: ?Sized`, `S: BuildHasher`). Bounds are structural admissibility facts; dropping them silently loses std-spec fidelity (P1/P2). + +**Allocator parameter status at 1.86.0**: the `allocator_api` feature (which adds the `A: Allocator` parameter to `Vec` / `Box` / `Rc` / `Arc` / `HashMap` / `HashSet` / `BTreeMap` / `BTreeSet`) is **unstable on 1.86 stable** (gated behind `#![feature(allocator_api)]` on nightly only). The brief therefore authors stable signatures *without* the `A` parameter; the allocator axis is **out of scope for Phase 1** and tracked as a STOP condition (see #11). If the toolchain pin is later raised to a version that stabilizes `allocator_api`, the rows must re-add `A: Allocator` per the Rust Reference signature change — see STOP #12. + +- **`Vec`** — owned, growable, contiguous heap buffer. **Inhabits `List = FreeMonoid`** per the M9 substrate parent (consistent with `String` inhabiting `FreeMonoid` per `design-emission-model.md:534`); the algebra parent identifies the row's structural family before the realization-axis tuple narrows the row. `T: Sized` (required — `Vec` cannot hold unsized elements). Refinement axes: ownership = `Owned`; growability = `Growable`; cardinality: `CardinalityBound::Unbounded` at HEAD (same `Cardinal`-substrate gap as Array/Slice in §A; retrofits to `Interval::Unbounded` when `Cardinal` lands). +- **`Box`** — single-owner heap pointer. `T: ?Sized` is structural — `Box` and `Box<[T]>` are valid because `Box` admits unsized `T`; dropping the `?Sized` relaxation silently loses the trait-object / unsized-slice carrier facts. `ReferenceModel` ownership axis: `Owned`; no lifetime; representation: `Safe` (safe/unsafe distinction on the `representation` axis per Q2 four-axis lock). +- **`Rc`** — shared-ownership reference-counted pointer (single-threaded). `T: ?Sized` (admits `Rc` / `Rc<[T]>`). `ReferenceModel` ownership: `SharedRefCounted { thread_safe: false }`. +- **`Arc`** — shared-ownership atomic-reference-counted pointer (thread-safe). `T: ?Sized` (admits `Arc` / `Arc<[T]>`). `ReferenceModel` ownership: `SharedRefCounted { thread_safe: true }`. +- **`HashMap`** — hash-table-backed associative array. Inhabits `PartialFunction` (`dsl/std/algebra.dag:428`). Refinement axes: `ordering: None`; **key-admissibility** `K: Hash + Eq`; hasher `S: BuildHasher` (default `RandomState`). Hasher choice is a structural fact (FxHashMap vs RandomState differ on collision-resistance vs throughput); distinct hashers produce distinct realization rows. Trait-bound axes are NOT optional: "hash-backed admissibility" distinguishes `HashMap` from `BTreeMap` at the realization step, not just ordering. +- **`BTreeMap`** — B-tree-backed ordered associative array. Inhabits `PartialFunction`; refinement axes: `ordering: Sorted`; **key-admissibility** `K: Ord`. No hasher axis — B-tree ordering doesn't require one. `Hash + Eq` and `Ord` are *distinct* admissibility shapes (a key can be `Ord` without `Hash` — `f64` is `PartialOrd`-only and inhabits neither cleanly, which is itself a structural fact). +- **`HashSet`** — inhabits `Set = BooleanAlgebra` (`dsl/std/types.dag:212`, per M9 DFS). Refinement axes: `ordering: None`; element-admissibility `T: Hash + Eq`; hasher `S: BuildHasher` (default `RandomState`). +- **`BTreeSet`** — inhabits `Set = BooleanAlgebra`. Refinement axes: `ordering: Sorted`; element-admissibility `T: Ord`. No hasher axis. **Do NOT route either Set carrier through `PartialFunction`** — P2 violation (parallel authority for `Set = BooleanAlgebra`). +- **`Option`** — sum carrier `Some(T) | None`. **M9 DFS receipt + substrate-gap gate:** searched `dsl/std/` for an existing optional/cardinality parent — `dsl/std/algebra.dag:517` carries `OptionalOf { inner: AlgebraTypeTemplate }` as an `AlgebraTypeTemplate` *return-type* variant (used for `first` / `last` / `get` etc.), but **no top-level substrate `type Option` / `Optional` / `Maybe` declaration exists at HEAD** (`grep '^type (Option|Optional|Maybe)' dsl/std/` empty). The natural parent is "cardinality `AtMostOne` over a coproduct of (some-inhabitant, none)" — `CardinalityBound::AtMostOne` (`src/v3/std/substrate.dag:144`) carries the cardinality half. **This lane does NOT introduce a new top-level `Option` substrate type** (would be a P1-Step-1 violation given the existing partial machinery). Instead, the `Option` row is **GATED** on a substrate decision Substrate Manager owns: either (a) declare a top-level `type Option` substrate parent (cardinality-`AtMostOne` + coproduct) under R2 Substrate, or (b) extend `OptionalOf` from algebra-template-only to a full substrate carrier. Worker STOP-and-escalate at this row; do not author the row before Substrate adjudication. (`Result` does NOT carry this gate — its parent is live at `dsl/std/error_primitives.dag:12`; see next bullet.) +- **`Result`** — sum carrier `Ok(T) | Err(E)`. **M9 DFS receipt — substrate parent FOUND:** `dsl/std/error_primitives.dag:12` declares `type Result = Ok { value: ok } | Err { value: err }` — this IS the existing top-level `Result` substrate carrier (my earlier DFS missed it; corrected via reviewer pointer). Rust `Result` therefore inhabits the existing `dsl/std/error_primitives.dag` `Result` parent directly — no Substrate-gap gate, no parallel parent. The two-authority discipline still applies (Rust Reference + std citations stay separate). **`Option` does NOT have an analogous existing parent** at HEAD (verified: `grep '^type (Option|Optional|Maybe)' dsl/std/` empty); only `Option` retains the substrate-gap gate above. + +**Two-authority discipline:** A and B rows cite distinct authority URLs. If row layout in a single `primitives.dag` file would mix authorities ambiguously (i.e., a reader can't tell which row claims which authority), split into `dsl/extdeps/languages/rust/primitives.dag` (authority a) + `dsl/extdeps/languages/rust/std_carriers.dag` (authority b). This split is **a discovered necessity, not a default** — author in one file first; split only if the faithfulness review surfaces the ambiguity. Escalate the split decision to manager before landing. + +### C. `RustPrimitive` type extension + grounding-engine walker arms + +The current `RustPrimitive` partition (`primitives.dag:180`) is `IntegerPrimitive { algebra: IntegerAlgebra, .. } | NonIntegerPrimitive { algebra: NonIntegerAlgebra, .. }`. Per `grounding-pilot-receipt.md` lock, the partition is fixed-shape; widening to flat record is out of scope. New variants required for full coverage: + +- `FloatPrimitive { .. }` — **NOT DISPATCHABLE AT HEAD; row shape is post-gate candidate only.** The variant slot is reserved (so the partition can include it once gates clear), but the field set is held until live Float inhabitance exists. Post-gate candidate shape (informational, not dispatchable): a single `approximate_field: ApproximateField` field once the Float→ApproximateField migration AND the Real/base-carrier decision both land; binary32 (`f32`) vs binary64 (`f64`) would then differ on `(precision, special_values, subnormal_policy)` coordinate values, not parent identity. Until both gates clear (see §A), worker STOPs at this variant. Distinct from `NonIntegerPrimitive` because pilot's `NonIntegerAlgebra` was Bool/Unit-only. +- `TextualPrimitive { algebra: TextualAlgebra, sized: SizedKind, .. }` — for `char` / `str`. `TextualAlgebra` selects between `FreeMonoid` (UTF-8 char sequence — `str`) and the per-codepoint shape for `char`; encoding is **not** a separate field per the algebra-carries-encoding lock (`design-emission-model.md:89, :530-532`). +- `NeverPrimitive { .. }` — empty-type marker. +- `CompoundPrimitive { kind: CompoundKind, .. }` — tuple / array / slice / struct / enum / union shapes. CompoundKind is a sub-sum; per Step 2 receipt, these alternate (a value is a tuple OR an array, never both), so sum-shape is correct. +- `FunctionItemPrimitive { identity: FunctionItemIdentity, signature: FnSignature, .. }` — one row per named function (carries identity); zero-sized. The `identity` record carries the full Rust Reference §Function-item-types spec facts: `{ item_decl: DeclarationId, generic_args: GenericArgs, constructor_case: ConstructorCase }` where `GenericArgs = { type_args: List, const_args: List, early_bound_lifetimes: List }`. The `generic_args` record holds **all three kinds** of generic arguments — type, const, and early-bound lifetime — because each independently distinguishes function-item identity: `foo::` ≠ `foo::` (type); `bar::<3>` ≠ `bar::<4>` (const); a function with early-bound lifetimes generates distinct item types per lifetime substitution. `ConstructorCase` is a sum (ordinary fn / tuple-struct constructor / enum-variant constructor) — collapsing under `item_decl` alone loses the constructor distinction. + - **Derived trait-inhabitance receipt** (per Rust Reference §Function item types — https://doc.rust-lang.org/1.86.0/reference/types/function-item.html). The brief MUST emit the following derived facts before dispatch; they are **DERIVED, not stored** (P2 — `item_decl`'s qualifiers + attributes are the source of truth, storing a parallel `traits: Set` would admit divergence): + - **Unconditional**: every function item implements `Copy`, `Clone`, `Send`, `Sync` per Rust Reference §"Function item types" (the type is zero-sized and carries no captured state, so auto-trait inhabitance is structural). + - **Conditional `Fn` / `FnMut` / `FnOnce`** — derived from `item_decl` qualifiers + attributes: + - Reads `item_decl.qualifiers = { unsafe: Bool, abi: AbiTag, target_feature: Option> }`. + - **Inhabits `Fn`/`FnMut`/`FnOnce` (all three) iff** `unsafe = false` AND `abi = Rust` AND `target_feature = None`. + - **Does NOT inhabit `Fn`/`FnMut`/`FnOnce`** iff any of: `unsafe = true` (must be called from an `unsafe` block, not via the `Fn*` traits) OR `abi ≠ Rust` (extern functions are not `Fn`-callable in stable Rust) OR `target_feature = Some(_)` (the `#[target_feature]` attribute likewise blocks `Fn*` inhabitance per Rust Reference §"target_feature attribute"). + - Worker emits the trait-inhabitance set as a derived field at lower time. Storing a parallel `fn_traits: Set` enum would be a P2 violation (mirrors `ClosurePrimitive`'s derived-not-stored rule for the same trait family). +- `FunctionPointerPrimitive { signature: FnSignature, unsafe: Bool, abi: AbiKind, hrtb: List, .. }` — signature-only carrier; pointer-sized; multiple function items collapse to the same row when signatures match. The `unsafe` qualifier is an independent coordinate from `abi` (because `unsafe extern "C" fn(...)` co-inhabits both — `FnQualifiers` is NOT a coproduct over `unsafe`/`abi`, corrects the §H Step-2 example below). However, `variadic` is **NOT** an independent coordinate — it is gated on the ABI shape per Rust Reference §"Variadic functions" (variadic is forbidden under the Rust ABI). To make the illegal `variadic = true` ∧ `abi = Rust` state un-representable at the type level (P2 / API-level enforcement, not validation-by-convention), `variadic` lives inside the `Extern` arm of `AbiKind`, NOT alongside it. + - **`FnSignature` shape** (per Rust Reference §"Function pointer types" — https://doc.rust-lang.org/1.86.0/reference/types/function-pointer.html): `FnSignature = { params: List, return: Type }` where `Param = { ty: Type, .. }` and `Type` is the standard substrate type-reference. The `-> !` divergent return is represented through the existing `NeverPrimitive` row (a `Type` whose row is `NeverPrimitive`), NOT a parallel `Never` enum case in the signature shape — that would author a second authority for the never-type fact (P2 single-authority violation: `NeverPrimitive` already owns the `!` substrate). `-> ()` is a `Type` referencing the unit-tuple `CompoundPrimitive { kind: Tuple, elements: [] }`. Param names are NOT part of the signature for fn pointers (anonymous-position only); the same shape is reused by `FunctionItemPrimitive.signature` and `ClosurePrimitive.signature` so the type is shared substrate, not undefined. + - **`AbiKind` shape** (Rust Reference §"Function pointer types" + §"Variadic functions"): `AbiKind = Rust | Extern { abi: ExternAbi, variadic: Bool }`. The `Rust` arm carries no further coordinates (Rust ABI is non-variadic and structurally fixed); the `Extern` arm carries the named extern ABI (`"C"`, `"system"`, `"cdecl"`, etc.) AND the `variadic: Bool` axis (set iff the signature ends in `...`). This makes `variadic = true` un-representable under the Rust ABI **at the type level**, satisfying P2/API-level enforcement (illegal-states discipline) — no runtime validation gate needed. Variadic remains a structural axis (not derivable from `params`/`return` alone), so storing it inside `Extern` is required to round-trip extern signatures like `unsafe extern "C" fn(*const u8, ...) -> i32` as `AbiKind = Extern { abi: "C", variadic: true }`. + - **`hrtb: List` axis** (Rust Reference §"Higher-ranked trait bounds" → fn-pointer position): the list of lifetime parameters bound by the `for<'a, 'b, ...>` quantifier on the fn pointer (e.g., `for<'a> fn(&'a T) -> &'a T` carries `hrtb = ['a]`); empty list when no HRTB is present. HRTB lifetimes are structurally distinct from outer-scope lifetimes — they introduce a fresh binder, so two fn pointers `for<'a> fn(&'a T)` and `fn(&'static T)` are distinct types and the substrate row MUST distinguish them or P1 spec fidelity is lost. + - **Derived `is_copy`**: `true` unconditionally per the per-variant `is_copy` receipt below (all function pointers are Copy regardless of qualifiers/variadic/HRTB). +- `ClosurePrimitive { signature: FnSignature, captures: CaptureSet, async_kind: AsyncKind, .. }` — anonymous compiler-generated. **`async_kind: AsyncKind = Sync | Async`** records whether the body desugars with `async ||`. **`lends_to_future: LendingPredicate`** is **DERIVED, not stored** — per Rust Reference §async-closure-traits + RFC 3668, lending must read both `mode` AND `body_use` per capture (mode alone misclassifies, since `UniqueImmutableBorrow` is repeatable only when the future *reads* through it; mutating through the &mut referent of a `&uniq T` capture still aliases the underlying mutable place across calls). The future is *lending* iff **any** capture used in the future body satisfies any of: + - `mode = MutableBorrow` (the future re-aliases the mutable referent across calls), OR + - `mode = ByValue` consumed by the future (the future owns the consumed value; the closure cannot be re-called to produce another future from the same capture — includes `move` closures that hand owned data to the future), OR + - `mode = UniqueImmutableBorrow` AND `body_use ∈ {mutate, consume}` (the unique-immutable borrow is itself a `&uniq` of an `&mut T` referent; mutating *through* the referent in the future re-aliases the mutable place across calls — so this counts as lending even though the mode is structurally distinct from `MutableBorrow`). + + *Non-lending* iff every capture used in the future body is either `SharedBorrow` (any body_use) or `UniqueImmutableBorrow` with `body_use = read` only — both repeatable across calls — **OR** satisfies the **deref-projection exception** per Rust Reference §async-closure-traits (the closure owns a smart pointer like `Box` and the future borrows only `&*ptr` — closure environment retains the smart pointer; future holds a borrow into its referent, so the future doesn't lend the closure's *capture* even though something inside the box is borrowed). + + Storing `lends_to_future` would author parallel representation against `captures` (P2). **Two cumulative towers** per Rust Reference §async-closure-traits, with lending suppressing the **sync** tower (NOT the async one): + - **Sync `Fn*` tower** (every closure regardless of `async_kind`): `FnOnce` always; `FnMut` if `captures.body_use` has no consume; `Fn` if also no mutate. **Additionally when `async_kind = Async`**: `Fn` and `FnMut` are suppressed if derived `lends_to_future = Lending` — a lending future cannot share `&self`/`&mut self` with a prior call's still-alive future, so the closure cannot satisfy `Fn`/`FnMut` repeated-call semantics. Sync derivation reads `captures.body_use` + (when async) the derived `lends_to_future`. + - **Async `AsyncFn*` tower** (only when `async_kind = Async`): `AsyncFnOnce` always; `AsyncFnMut` if `captures.body_use` has no consume; `AsyncFn` if also no mutate. **Lending does NOT suppress this tower** — `AsyncFn`/`AsyncFnMut` returns a future, structurally distinct from sync `Fn`/`FnMut` repeated-call admissibility. Derivation reads `captures.body_use` + `async_kind` only. + - **Combined**: a non-mutating non-moving non-lending async closure inhabits `Fn ⊇ FnMut ⊇ FnOnce` AND `AsyncFn ⊇ AsyncFnMut ⊇ AsyncFnOnce` simultaneously. A non-mutating non-moving **lending** async closure inhabits `AsyncFn` but only `FnOnce` in the sync tower (lending suppresses sync `Fn`/`FnMut`). + - All trait inhabitances + the lending predicate are derived from `captures` + `async_kind`. Storing a parallel `fn_traits: Set` enum or a stored `lends_to_future: Bool` would be a P2 violation. **`CaptureSet` shape per Rust Reference §closure-capture:** `List` where each `Capture { path: PlaceExpr, mode: CaptureMode, body_use: CaptureBodyUse }`. The `path` is the **place expression** the capture refers to (`x` whole binding, `x.field`, `x.field.subfield` — Rust 2021+ disjoint captures resolve at field-precision, not whole-binding); the `mode` is one of the **four Rust closure capture modes** per Rust Reference §Closure types: `SharedBorrow` (`&T`) / `UniqueImmutableBorrow` (`&uniq T`, used internally for cases like `&mut x[..]` slice access where the closure needs unique-but-immutable access — distinct from both shared and mutable borrow) / `MutableBorrow` (`&mut T`) / `ByValue` (move). Mode is controlled by `move` and by use-site; the unique-immutable-borrow mode cannot be expressed at user syntax but is observable in borrow-checker behavior, so the substrate row MUST carry it as a distinct variant or the closure model fails P1 spec fidelity; the `body_use` is read / mutate / consume. **Capture-path precision is required** — collapsing `x.field` and `x.other_field` into a single `x` capture loses the disjoint-borrow facts the borrow checker depends on. Body-use → trait derivation rule already stated above (sync `Fn*` from `captures.body_use`; async `AsyncFn*` from `async_kind` + derived `lends_to_future`, which itself reads `captures`). + +These are **three sibling variants**, not one variant with a `kind: FunctionKind` enum — see §A item/pointer/closure justification. +- `ReferencePrimitive { model: ReferenceModel, .. }` — references / raw pointers / `Box` / `Rc` / `Arc` (B's pointer-family carriers re-home here per A's `ReferenceModel` axis). +- `TraitObjectPrimitive { base_trait: Option, auto_traits: Set, object_lifetime: Lifetime, .. }` — structured per §A trait-object bullet. `base_trait` is **at most one** non-auto trait per Rust Reference (zero is valid for auto-traits-only objects like `dyn Send`); `auto_traits` is the set carried via `+` syntax; `object_lifetime` carries the explicit or elision-derived lifetime. **Dyn-compatibility validation** is a worker-side check on `base_trait` (when `Some(_)`) before declaring the row, NOT a stored axis (the dyn-compatibility predicate is fully derived from the trait's own item shape — generic methods, `Self: Sized` bounds, associated constants, etc.); when `base_trait = None`, dyn-compatibility is vacuously satisfied. +- `ImplTraitArgPrimitive { trait_bounds: TraitBoundSet, .. }` — argument-position `impl Trait` (anonymous type parameter, caller-chooses; universal). +- `ImplTraitReturnPrimitive { trait_bounds: TraitBoundSet, opaque_captures: OpaqueCaptureSet, edition: RustEdition, item_kind: ItemKind, .. }` — return-position `impl Trait` (abstract return type, callee-chooses; existential/opaque). `opaque_captures = { type_params: List, const_params: List, lifetime_params: List, precise_capture_restriction: Option }`. **Both `opaque_captures` defaults AND `use<>` legality are derived from SIX inputs** per the Rust Reference precise-capturing legality matrix: (1) `edition` (lifetime default-capture rule per RFC 3498, scoped by item_kind — see below); (2) `item_kind` (free fn / inherent associated fn-or-method / trait method / trait-impl method) — load-bearing for both default-capture and use<> rules, distinct from edition; (3) `trait_bounds` (lifetimes appearing in THIS abstract type's own bounds; per-abstract-type, NOT cross-sibling); (4) `in_scope_generics` (the full set of type/const/lifetime parameters in the enclosing scope — required for the use<> completeness check on type/const); (5) for trait methods, the trait's required generics (RFC 3617); (6) `anonymous_parameter_syntax` (whether the function uses anonymous-parameter `impl Trait` in argument position alongside the return-position one — affects which lifetime parameters are in-scope per Rust Reference §"Anonymous type parameters"). Specifically: + - **Default capture (when `precise_capture_restriction = None`):** type and const params in scope are ALWAYS captured (all editions, all `item_kind`s) per RFC 3498. Lifetime defaults are **`item_kind`-dependent**, not edition-only — collapsing to "edition decides lifetime capture" is a Rust Reference faithfulness defect (the pre-2024 lifetime exception is scoped to specific item kinds). Per Rust Reference §Impl Trait → "Capturing": + - **Free fn / inherent associated fn or method (`item_kind ∈ {FreeFn, InherentAssoc}`)**: Rust 2024+ captures all in-scope lifetimes; Rust 2015/2018/2021 captures lifetimes only if named in `trait_bounds` (bounds-derived). + - **Trait method (`item_kind = TraitMethod`)**: ALL in-scope generic params (type, const, AND lifetime) are captured **regardless of edition** — the pre-2024 lifetime exception does NOT apply. Modeling this as edition-only would under-capture lifetimes on trait-method RPIT rows (P1 violation). + - **Trait-impl method (`item_kind = TraitImplMethod`)**: ALL in-scope generic params captured **regardless of edition**, same rule as trait methods. + Default-capture rule is *derived* from `(edition, item_kind, trait_bounds)` jointly; storing a separate rule field would admit illegal pairs (P2). + - **`use<>` legality** (when `precise_capture_restriction = Some(...)`): the full Rust Reference §precise-capturing legality matrix imposes FIVE constraints on the use-list, all of which the substrate row MUST validate before declaring `Some(_)`: + 1. **All in-scope type and const generic parameters MUST be in the list** — `use<>` is not a narrowing tool for type/const; omission of any in-scope type/const param is rejected. + 2. **All lifetimes appearing in THIS abstract type's own `trait_bounds` MUST be in the list** — e.g., `impl Trait + 'a` or `impl Iterator` requires `'a`. The rule is **per abstract return type**, NOT cross-sibling: lifetimes appearing in *sibling* return bounds (e.g., the `'a` in one return of `(impl Iterator, impl Display)`) are NOT inputs to the other return's `use<>` legality check. Cross-sibling enforcement would author parallel/fictional Rust authority and reject legal Rust signatures (P1/P2 violation per Rust Reference §Impl Trait → "Capturing"). A `use<>` that omits a lifetime mentioned in **its own** abstract type's bounds is rejected. + 3. **Lifetimes NOT mentioned in the list and NOT bound-required are excluded** — this is the only narrowing axis (lifetimes only). + 4. **Trait-method context (RFC 3617 §"Trait methods")**: on trait method definitions, the use-list MUST include every trait-generic the method captures — derived from `item_kind = TraitMethod { trait_required_generics }`. + 5. **Anonymous argument-position `impl Trait` forbids return-position `use<>`** — if the function declares any anonymous-parameter `impl Trait` in argument position (which introduces synthetic generics outside the user's named-generics scope), return-position `use<>` is illegal entirely. Derived from `anonymous_parameter_syntax = Present`. + - Worker validates legality from `in_scope_generics` + `trait_bounds` + `item_kind` + `anonymous_parameter_syntax` enumeration before declaring `Some(_)`. + - The substrate stores the *primary* facts (`edition`, `item_kind`, `trait_bounds`, generic-param kinds via `opaque_captures` shape); defaults + legality are derived. Storing a derived `default_capture` field or a blanket `use_legal_on_trait_methods: Bool` would author parallel representation (P2 illegal-states). + - Authority: Rust Reference §Impl Trait → precise-capturing + RFC 3498 + RFC 3617. + +**Per-variant `is_copy` derivation receipt.** The pilot's `IntegerPrimitive` / `NonIntegerPrimitive` variants each carry a `Copy` / `is_copy` fact that live Rust emission consumers read; the new variants MUST surface the same fact so the C-axis expansion does not regress P2 facts-flow. `is_copy` is **DERIVED, not stored** on every new variant (matching the §B std-carrier and FunctionItemPrimitive precedent — store structural facts, derive trait inhabitance). Per-variant rule per Rust Reference §"Copy" + §"Special types and traits": +- `FloatPrimitive` — `is_copy = true` unconditionally (`f32`, `f64` both `Copy` per std). No structural inputs needed; derivation is constant. +- `TextualPrimitive` — derived from `algebra` + `sized`: `char` (per-codepoint shape) is `Copy`; `str` (`FreeMonoid`, unsized) is NOT `Copy` (unsized types cannot be `Copy` per Rust Reference §"Sized"). Rule: `is_copy = (sized = Sized)` for the textual family. +- `NeverPrimitive` — `is_copy = true` vacuously (the never type `!` has no inhabitants; `Copy` holds vacuously per Rust Reference §"Never type"). +- `CompoundPrimitive` — derived from `kind` + element/field facts: tuple is `Copy` iff every element type is `Copy`; array `[T; N]` is `Copy` iff `T: Copy`; slice `[T]` is unsized, never `Copy`; `struct`/`enum` is `Copy` iff `#[derive(Copy)]` (or manual impl) is present AND every field is `Copy` AND no `Drop` impl exists per Rust Reference §"Copy"; `union` follows the struct rule with the additional restriction that no field may have a `Drop` impl. Reads `kind` + per-field/element `is_copy` recursively. +- `FunctionItemPrimitive` — `is_copy = true` unconditionally (already covered by the trait-inhabitance receipt above; function items are zero-sized and unconditionally `Copy`). +- `FunctionPointerPrimitive` — `is_copy = true` unconditionally (all function pointers are `Copy` per Rust Reference §"Function pointer types"; `unsafe`/`abi` qualifiers do not affect `Copy`). +- `ClosurePrimitive` — derived from `captures`: `is_copy = true` iff every capture's `mode = SharedBorrow` OR (`mode = ByValue` AND the captured place's type is `Copy`). **Both `MutableBorrow` AND `UniqueImmutableBorrow` block `Copy`** per Rust Reference §"Closure types" → "Call traits and coercions" (https://doc.rust-lang.org/1.86.0/reference/types/closure.html): a closure is `Copy`/`Clone` iff it does NOT capture by unique-immutable-borrow or by mutable reference; `Copy` captures are still `Copy`, and moved captures inherit `Copy` from the captured place's type. A non-`Copy` by-value capture also forces `is_copy = false`. Reads `captures.mode` + per-capture `path` type's `is_copy` recursively. +- `ReferencePrimitive` — derived from `model`: `&T` (`SharedBorrow`) is `Copy` unconditionally; `&mut T` (`MutableBorrow`) is NOT `Copy`; raw pointers `*const T` / `*mut T` are `Copy` unconditionally; smart pointers (`Box`, `Rc`, `Arc`) are NOT `Copy` (have `Drop` impls). Rule reads `model.ownership` + `model.mutability`. +- `TraitObjectPrimitive` — `is_copy = false` unconditionally. The trait object type `dyn Trait` is unsized; only `&dyn Trait` / `Box` etc. are sized, and `Copy`-ness of those is derived from the enclosing `ReferencePrimitive`, not from this row. +- `ImplTraitArgPrimitive` — derived from `trait_bounds`: `is_copy = true` iff `Copy ∈ trait_bounds` (the caller-chosen concrete type must satisfy the bound). Reads `trait_bounds` only. +- `ImplTraitReturnPrimitive` — derived from `trait_bounds`: `is_copy = true` iff `Copy ∈ trait_bounds` (the abstract return type's caller-visible interface includes `Copy`); the concrete callee-chosen type may be more specific but the row's exposed interface is the bound set. Reads `trait_bounds` only. + +Worker emits `is_copy` (and any analogous `is_clone`, `is_send`, `is_sync` facts the emission consumer reads, by the same per-variant derivation rules — `Clone` is implied by `Copy`; `Send`/`Sync` derive from per-variant auto-trait rules per Rust Reference §"Auto traits"). All such facts are **derived at lower time, not stored** on the variant; storing a parallel `is_copy: Bool` field would author parallel representation against the structural inputs (P2 violation, mirrors the `lends_to_future`/`fn_traits` discipline in `ClosurePrimitive`). Authority: Rust Reference §"Copy" + §"Special types and traits" + §"Auto traits" (https://doc.rust-lang.org/1.86.0/reference/special-types-and-traits.html). + + +These are sibling variants per the §A position-split; do NOT collapse into one `ImplTraitPrimitive { kind: Position }` (that would re-introduce the parallel-authority shape the position-split specifically dissolves). +- `ContainerPrimitive { algebra: ContainerAlgebra, .. }` — `Vec` / `String` / `HashMap` / `BTreeMap` / `HashSet` / `BTreeSet` / `Option` / `Result` (B's non-pointer carriers). + +Walker arms in `src/v3/grounding_engine/src/lib.rs:59` (`validate_loaded_rust_primitive_type_structure`) extend with a match arm per new `RustPrimitive` variant. Each arm returns `StructureMismatch` on shape violation (per the existing pattern); no new error variants introduced (typed `EmissionDiagnostic` is T-Ground-Diagnostic scope). + +The `src/v3/grounding_pilot/src/lib.rs:106` mirror updates in lockstep until T-Ground-LanguageSpec retires it (Reflective Pattern E retirement scope item D in `t-ground-languagespec.md`); this lane keeps the mirror consistent during expansion, does NOT retire it. + +### D. Q1 `BoundDeclaration` consumer wiring + +Each integer primitive row consumes `BoundDeclaration` (`src/v3/std/substrate.dag:136`) per Q1 lock (`design-emission-model.md:994`). HEAD's substrate shape (`src/v3/std/substrate.dag:123-138`) is `Interval = BoundedInterval { lower: D, width: IntervalWidth } | Unbounded` and `BoundDeclaration = StaticBound(Interval) | PlatformDependent`. Asymmetric match rule (Q1 lock per `r2-grounding-manager.md:56`) phrased against the landed shape: target's `Unbounded` universally accepts; target's `StaticBound(BoundedInterval { lower, width })` requires structural equality on the `(lower, width)` payload (`PlatformDependent` remains a distinct outer variant — it never collapses into `StaticBound`). + +- `i8`–`i128` rows: `StaticBound(BoundedInterval { lower: -2^(N-1), width: PositiveWidth(2^N - 1) })`. +- `u8`–`u128` rows: `StaticBound(BoundedInterval { lower: 0, width: PositiveWidth(2^N - 1) })`. +- `isize` / `usize` rows: `PlatformDependent`. **First non-pilot exercise of the `PlatformDependent` path.** + +If walking PR-F's locked `BoundDeclaration` consumer surface surfaces a structural mismatch with the Rust integer family's actual ranges (e.g., the `Interval` carrier can't express `2^127 - 1` as a literal because `Int` lowering hasn't settled), STOP and escalate — that is a substrate-shape escalation to Substrate Manager via the manager (`#1745`), not a paper-over. + +### E. Q2 `ReferenceModel` axes — Rust per-family axis declarations + +Per Q2 lock (`design-emission-model.md:1100`) and `r2-grounding-manager.md:90`: pointer/reference family shares the `ReferenceModel` parametric parent with the **complete four-axis set** (`lifetime`, `mutability`, `ownership`, `representation`). **Every row populates ALL four axes — no row is allowed to omit an axis.** Per the illegal-states discipline (state-space-vs-behavioral-invariants): a partial record admits combinations that should be structurally impossible. Rust's pointer-family rows: + +- `&T`: `{ ownership: Borrowed, mutability: Immutable, lifetime: Bound, representation: Safe }`. +- `&mut T`: `{ ownership: Borrowed, mutability: Mutable, lifetime: Bound, representation: Safe }`. +- `*const T`: `{ ownership: Raw, mutability: Immutable, lifetime: None, representation: Unsafe }`. +- `*mut T`: `{ ownership: Raw, mutability: Mutable, lifetime: None, representation: Unsafe }`. +- `Box`: `{ ownership: Owned, mutability: ContainerControlled, lifetime: None, representation: Safe }` — `ContainerControlled` means mutability is determined by the binding/container (`Box` itself doesn't constrain), not by the pointer; this is a real fourth value of the `mutability` axis, not a defaulted shorthand. +- `Rc`: `{ ownership: SharedRefCounted { thread_safe: false }, mutability: Immutable, lifetime: None, representation: Safe }` — `Rc` is shared-immutable by structural construction; interior mutability requires `RefCell` wrapping (a separate primitive, out of scope for this row). +- `Arc`: `{ ownership: SharedRefCounted { thread_safe: true }, mutability: Immutable, lifetime: None, representation: Safe }` — same structural shape as `Rc` modulo the thread-safe flag. + +The `ReferenceModel` shared-parent declaration itself lives in `dsl/std/` (substrate-owned per Q2 lock; PR-F lands it). This lane consumes; if PR-F's landed shape doesn't accommodate Rust's coverage as enumerated, STOP and escalate. + +### F. Q3 `RealizationCost` per-primitive population — OUT OF SCOPE (owned by T-Ground-LanguageSpec) + +Per `t-ground-languagespec.md:73` (sibling brief, scope item B): T-Ground-LanguageSpec lane owns per-primitive `RealizationCost` population for **all three targets** (Rust + Python + Go) — that lane consumes the per-target primitive sets the present lane (T-Ground-Rust) lands and attaches the cost coordinates. Authoring `RealizationCost` rows from this T-Ground-Rust brief would create a second lane authority for the same substrate fact (P2 violation: facts flow forward, single authority per substrate fact). + +**This lane's responsibility is limited to:** +- Authoring the structural Rust primitive rows (§A-§E above) **without** `RealizationCost` fields. T-Ground-LanguageSpec adds those fields downstream when PR-I lands. +- If a Rust primitive row's shape forces a coordinate that `RealizationCost` cannot represent, escalate to manager `#1745` (cross-lane signal — T-Ground-LanguageSpec owns `RealizationCost` shape per `t-ground-languagespec.md:73`; this lane only flags). No T-Ground-Rust-internal STOP condition for this case (deferred to T-Ground-LanguageSpec scope per the §F authority split). +- No Phase B / Phase 4 backfill on this lane. The earlier brief revision had a misallocated "Phase 4: RealizationCost backfill" entry — removed in this commit. + +### G. Higher-order MethodTemplateContract rows (Phase 1.5 — separately gated) + +Per `r2-grounding-manager.md:67` Phase 1.5: Rust higher-order rows are gated on Substrate's shape decision for the existing dual-template `HigherOrderMethodSpec` carrier (`dsl/extdeps/languages/rust/emit.dag:265`); cross-manager request live to jolly-ram-908 (#1130). **OUT OF SCOPE for this lane's primary slice**; surfaced here so the worker doesn't accidentally absorb it. If higher-order Rust rows are needed by a primitive declaration this lane authors (e.g., `Vec::map` requires a higher-order spec), STOP and escalate — likely the substrate-shape decision hasn't landed and this lane is blocked on it. + +### H. P1 procedure receipts + +Per `INVARIANTS.md` §P1 (lines 94-129), worker MUST cite receipts in the PR body for every new variant of `RustPrimitive` and every new field on existing variants: + +- **Step 1 (DAG-ancestor):** which existing parent does the new fact attach to? (Worked example: `FloatPrimitive` — does `NonIntegerPrimitive` already host floats? Pilot's `NonIntegerAlgebra` was Bool/Unit-only, so NO; `FloatPrimitive` is a sibling new variant, not a refinement of an existing one.) +- **Step 2 (Coproduct-vs-coordinate):** for each new sum (e.g., `CompoundKind`, `ContainerAlgebra`), do all variants ever co-inhabit (→ record) or alternate (→ sum)? **`FnQualifiers` is NOT a coproduct** — `unsafe` and `extern "ABI"` co-inhabit (per §A function-pointer row), so they are independent record coordinates (`unsafe: Bool`, `abi: AbiTag`); do NOT introduce them as sum variants. **`FnTrait` (Fn / FnMut / FnOnce) is NOT a stored field anywhere** — derived from closure captures per §C `ClosurePrimitive`, so it is not subject to Step-2 sum-vs-record analysis (it has no representation to choose). +- **Step 3 (Primitive-vs-lens-extensible):** for new leaves (e.g., `SizedKind`, `CompoundKind`, `AbiTag`), are they substrate primitives or lens-extensible labels? **`Encoding` is NOT a permissible leaf** under this lane — encoding is carried by algebra choice (`FreeMonoid` vs `FreeMonoid`) per the locked decision at §A textual / §B `String` rows above; introducing an `Encoding` leaf would re-open the parallel-authority shape that lock closes. + +--- + +## Out of scope (do NOT do) + +- **Coercion-Fold body.** This lane lands the substrate facts; the fold itself is T-Ground-Coercion-Fold (S; held per `design-emission-model.md` option (c) until LanguageSpec lands). +- **Lifetime / ownership derivation from program use.** T-Ground-Lifetime-Analyzer (LANDED). This lane consumes the lifetime axis as substrate; does NOT re-author derivation logic. +- **`EmissionDiagnostic` carrier authoring.** T-Ground-Diagnostic (S). This lane uses `StructureMismatch` per existing walker pattern; no new error variants. +- **`MethodTemplateContract` higher-order rows.** Phase 1.5; gated on Substrate shape decision (#1130). +- **Track-13 dissolution.** `TypeCheckpoint` / `InhabitantDecl` / `carrier: String` / `dsl/extdeps/languages/rust/types.dag` deletion stays in T-Ground-Dissolve. +- **Pilot-crate deletion.** T-Ground-Dissolve. +- **`RUST_PILOT_PRIMITIVES` mirror retirement.** T-Ground-LanguageSpec (Reflective Pattern E retirement, scope item D in `t-ground-languagespec.md`). This lane keeps the mirror consistent during variant expansion; does NOT retire it. +- **Touching `src/v3/compiler/`.** SG-0 ratchet. +- **Python / Go target work.** T-Ground-Python / T-Ground-Go (sibling lanes; gated on PR-G / PR-H respectively). +- **Re-litigating Q1 / Q2 / Q3 / Q4 / Q5 / Q6.5 locks.** +- **Re-litigating the variant-aware partition lock** per `grounding-pilot-receipt.md` (codex P2 adjudication 2026-04-25). Adding sibling variants is in scope; flattening to a record is out of scope. +- **Mixing authority (a) and authority (b) into one citation per row.** Faithfulness violation. + +--- + +## Dependencies / gates + +| Gate | Status (at brief authoring 2026-05-05) | Lane impact | +|---|---|---| +| **PR-PreF** (Substrate; `Interval` consolidation) | LANDED — `src/v3/std/substrate.dag:123` | Q1 instance available | +| **PR-F** (Q1 `BoundDeclaration` consumer + Q2 Rust `ReferenceModel` axes) | **PRIMARY GATE — not landed** (`grep ReferenceModel dsl/std/*.dag dsl/extdeps/languages/rust/*.dag` empty at audit 2026-05-05) | Required for D + E | +| **PR-I** (Q3 `RealizationCost` + Q4 universal four-property gate) | not landed | NOT a hard gate for this lane — T-Ground-LanguageSpec consumes PR-I and attaches `RealizationCost` to Rust primitive rows downstream (§F). Q4 four-property gate is consumed by §A-§E inhabitance receipts. | +| **Substrate `HigherOrderMethodSpec` shape decision** (cross-manager #1130 to jolly-ram-908) | in flight | Required only if a primitive declaration needs higher-order rows; otherwise out of scope (G) | +| **T-Ground-Lifetime-Analyzer R2 scope** | LANDED (#1206 / #1218 / #1220) | Lifetime axis available as substrate consumer | +| **#1129 / #1156 / #1162 (Tier 1 locks)** | LIVE on main | Consumed (Q1 / reflection-completeness / Q6.5) | +| **`Cardinal` ordered-domain substrate** (PR-PreF cascade per `design-emission-model.md:1023, :1038`) | NOT landed at HEAD (`grep '^type Cardinal' dsl/std/ src/v3/std/` empty); only `IntInterval = Interval` instantiated | Array/Slice/Vec rows consume `CardinalityBound` at HEAD as a forward-bridge; retrofit to `Interval` on landing (dissolution trigger = the `Cardinal` substrate landing PR) | +| **Option top-level substrate parent** (cardinality-`AtMostOne` + coproduct, or `OptionalOf` carrier promotion) | NOT landed at HEAD (`grep '^type (Option\|Optional\|Maybe)' dsl/std/` empty); only `OptionalOf` algebra-template variant exists | §B `Option` row STOPs-and-escalates; Substrate Manager owns the parent decision. **`Result` parent IS landed** at `dsl/std/error_primitives.dag:12`; that row dispatches normally. | +| **Float migration from `Field` to `ApproximateField`** (live float substrate at `dsl/std/float.dag:14-18` declares the wrong parent) | NOT migrated at HEAD — current declarations are `Float32 = Field` / `Float64 = Field` (exact-Field over fixed-width word; structurally inadequate for IEEE-754) | §A `f32`/`f64` rows STOP-and-escalate; T-NumericConstruction-ApproximateField slice owns the migration | +| **`ApproximateField` Real / base-carrier decision** (`docs/audit/t-numeric-construction-approximate-field-real-parameter-stop.md`) | active STOP — no `Real` alias at HEAD; `F` parameter has no honest substrate target | §A `f32`/`f64` rows STOP-and-escalate (in addition to the Float migration gate above); T-NumericConstruction-ApproximateField slice owns the carrier convention decision | +| **Repository / git prerequisites** | implementation starts when repo/git prerequisites are satisfied (a clean working tree on the dispatching worker's environment) | Required before any code edits | + +**Cross-program signals:** +- **Substrate Manager — ValueBody-list/sum + std.unicode bootstrap:** NOT a hard gate for this lane (Coercion-Fold consumes it). T-Ground-Rust can land structural rows without it. +- **R3 Grounding Manager (`#1745`):** lane closure signal; STOP-and-escalate target for any of the STOP conditions below. + +--- + +## Sizing + +**XL** per `r2-grounding-manager.md:63` and `ROADMAP.md:194`. Distribution (informal; bundle policy per `feedback_bundle_workstreams_per_pr.md`): + +- A — Rust Reference primitive rows (full coverage minus pilot): L (~12 primitive families × authority + axis citations). +- B — std-library carriers: M (11 carriers; some collapse onto `ReferenceModel` from A). +- C — `RustPrimitive` variant extension + walker arms + pilot-mirror lockstep: M. +- D — Q1 `BoundDeclaration` consumer wiring (integer family + `PlatformDependent`): S. +- E — Q2 `ReferenceModel` Rust axis population: M. +- F — Out of scope (owned by T-Ground-LanguageSpec). No sizing contribution. +- G — Higher-order rows: out of scope this lane (Phase 1.5). +- H — P1 receipts: included in each PR body. + +**Recommended slicing** (manager confirms at dispatch): +- **Phase 1 (gated on PR-F):** smallest-meaningful-slice — `u128` + `isize` + `usize` + walker arms + pilot-mirror update. **Validates PR-F's Q1 lock only** (the `BoundDeclaration` + `PlatformDependent` consumer machinery); Q2 (`ReferenceModel`) is **NOT** exercised by this slice because no pointer/reference-family row is included — narrowing Q2 to a separate slice (Phase 1.5 below or a dedicated pointer-family micro-slice) keeps the integer-only gate honest. Per the manager's 2026-05-05 correction, `i128` is NOT in this slice (already landed). **Floats are NOT in Phase 1**: `f32`/`f64` row authoring + `FloatPrimitive` variant population remain held until both Float-substrate gates clear (Float migration from `Field` to `ApproximateField` + Real / base-carrier decision; see §A and STOP condition #7). Phase 1 does not depend on either gate. +- **Phase 2 (within Phase 1 PR or follow-up; manager call):** textual + never + tuple + array + slice. +- **Phase 3:** struct/enum/union/function/closure + trait object + `impl Trait`. +- ~~Phase 4 (RealizationCost backfill)~~ — REMOVED. T-Ground-LanguageSpec owns per-primitive `RealizationCost` population for all targets (`t-ground-languagespec.md:73`); this lane's primitive rows ship without `RealizationCost` fields. +- **Phase 5:** std-library carriers (B) — scheduled after Phase 1's shape is proven; some carriers (`Box` / `Rc` / `Arc`) may move earlier if they're trivially in `ReferenceModel` axis space. + +If Phase 1's `PlatformDependent` consumer surfaces an unanticipated substrate gap, escalate to manager before splitting further. + +--- + +## Test plan + +Per `TESTING.md` — hermetic, behavior-driven, unit-first; sub-second per `feedback_test_timeout_2s.md`. + +Acceptance lifted to a `.dag` `TestClaim` (gate: `rust_target_primitives_declared_structurally` per `r2-grounding-manager.md:124`): + +1. **Per-primitive structural-load test** — every Rust primitive declared in A and B loads through reflection without per-consumer projection (per `design-reflection-completeness.md:103`); the `Dag::rust_pilot_primitives()` accessor (or its post-LanguageSpec successor) walks each row and reaches `validate_loaded_rust_primitive_type_structure` without `StructureMismatch`. +2. **Authority-citation completeness** — every row carries an authority URL comment; each URL resolves to either Rust Reference §Types or a std-doc page; no row mixes both. +3. **Q1 `PlatformDependent` exercise** — `isize` and `usize` rows match against an emit-target's `BoundDeclaration` per the asymmetric match rule (Q1 lock); test asserts `PlatformDependent` resolves to a concrete interval at target-platform time and never collapses into `StaticBound`. +4. **Q2 `ReferenceModel` axis coverage** — every Rust pointer-family row (`&T` / `&mut T` / `*const T` / `*mut T` / `Box` / `Rc` / `Arc`) carries a complete axis tuple per E above; missing axis = `StructureMismatch`. +5. **Variant-partition discipline** — `RustPrimitive`'s variants partition (every Rust value inhabits exactly one variant); the test enumerates a representative value per Rust primitive and asserts a unique walker arm matches. +6. **Float-row STOP assertion (held)** — at HEAD, the test asserts that NO `f32`/`f64` row is authored (i.e., the `FloatPrimitive` variant carries no populated rows) until both Float-substrate gates clear (Float migration from `Field` to `ApproximateField` + Real / base-carrier decision). Post-gate, this test converts to a coordinate-distinguishability check: `f32`/`f64` rows must NOT claim `OrderedRing` / `Semiring` inhabitance (no-ring-axiom discipline preserved per §A); once a parent is honest, `f32` and `f64` must differ on `(precision, special_values, subnormal_policy)` coordinate values per IEEE-754 §3, not on parent identity. +7. **Mirror-consistency probe (held)** — `validate_first_rust_pilot_row_matches_mirror` continues to fire on intentional drift between `Dag::rust_pilot_primitives()` and the Rust mirror until T-Ground-LanguageSpec retires the mirror (Reflective Pattern E retirement). This lane keeps the probe green during variant expansion. +8. ~~`RealizationCost` sparseness~~ — moved to T-Ground-LanguageSpec test plan; not a T-Ground-Rust acceptance check. +9. **Derived `is_copy` / closure-trait correctness** — for each new `RustPrimitive` variant (per the Per-variant `is_copy` derivation receipt), the test enumerates representative inhabitants and asserts the derived `is_copy` value matches the Rust Reference rule. Required closure cases (per Rust Reference §"Closure types" → "Call traits and coercions"): (a) `|| ()` (no captures) → `is_copy = true`; (b) `|| { let r = &x; r }` (capture `x` as `SharedBorrow`) → `true`; (c) `|| { x = 1 }` (capture `x` as `MutableBorrow`) → `false`; (d) **`UniqueImmutableBorrow` negative case** — a closure that captures via `&uniq` (e.g., the borrow-checker-synthesized mode for `&mut x[..]` slice access in a closure body) → `false`; (e) `move || drop(x)` with `x: i32` (Copy by-value) → `true`; (f) `move || drop(x)` with `x: String` (non-Copy by-value) → `false`. Required function-item case: a function with `unsafe` or `extern "C"` qualifier → `Fn`/`FnMut`/`FnOnce` NOT inhabited (per the FunctionItemPrimitive trait-inhabitance receipt). Catches drift in the per-variant derivation rules before walker rows land. + +--- + +## STOP conditions (escalate to manager `#1745`) + +Worker stops + escalates if any of the following occur. Do NOT paper over. + +1. **PR-F's landed Q2 axes can't express a Rust pointer-family row** as enumerated in E (e.g., `ReferenceModel`'s axis set lacks a coordinate Rust requires). Signals PR-F under-specified. +2. **Q1's `Interval` carrier can't represent a Rust integer range literal** (e.g., `2^127 - 1` lowers to `ValueBody::Unparsed`). Signals a substrate-lowering gap escalation, sibling to the loader-close gap that produced #776. +3. **Two-authority split forces a substrate distinction the substrate doesn't carry** — e.g., a Rust Reference type and a std-library carrier collapse into the same structural shape under `RustPrimitive`'s partition, but their authorities require distinct citations. Signals a substrate-shape escalation. +4. **A primitive declaration requires a higher-order `MethodTemplateContract` row** (G — out of scope this lane). Signals Phase 1.5 dependency hit; verify `HigherOrderMethodSpec` Substrate decision (#1130) has landed before resuming. +5. **An emit-pipeline call site reading `dsl/extdeps/languages/rust/types.dag` cannot be left intact while structural rows land** — i.e., the structural row's introduction breaks an existing reader before T-Ground-Dissolve's planned cleanup. Signals T-Ground-Dissolve sequencing conflict; manager routes. +6. **`grounding-pilot-receipt.md`'s variant-aware partition lock breaks** under variant expansion (e.g., a Rust primitive doesn't fit any sibling variant cleanly). Re-opening that lock is a Director-routed scope change, not a worker call. +7. **Float row reached without BOTH Float-substrate gates cleared** — two distinct gates per §A: (a) **Float migration** from `Field` to `ApproximateField` (live `dsl/std/float.dag:14-18` declares the inadequate `Field` parent; migration to `ApproximateField` hasn't landed); (b) **Real / base-carrier decision** (`docs/audit/t-numeric-construction-approximate-field-real-parameter-stop.md`) — `ApproximateField`'s `F` parameter has no honest substrate target at HEAD. Worker STOP-and-escalates at the §A `f32`/`f64` row until BOTH clear; do NOT pick a placeholder for `F`, do NOT consume the live `Field` parent. Separate sub-condition: even after both gates clear, if a Rust-required precision/rounding/special-values/subnormal-policy combination doesn't fit the existing `(precision, rounding, special_values, subnormal_policy)` coordinate space, escalate again — that's a substrate-shape change on `ApproximateField` itself. +8. **Apparent-multi-inhabitance** (e.g., `String` vs `Box` vs `&str` vs `Cow`) requires axis disposition that conflicts with T-Ground-LanguageSpec's apparent-multi-inhabitance audit (scope item F in `t-ground-languagespec.md`). Coordinate via manager; do NOT pre-empt that lane. +9. **`Option` row reached without Substrate parent decision** — no top-level `type Option` substrate parent exists at HEAD; either Substrate Manager has declared one or extended `OptionalOf` (`dsl/std/algebra.dag:517`) to a full carrier, or this row stays unauthored. Worker MUST NOT introduce a new top-level `Option` substrate type unilaterally (P1-Step-1 violation). (`Result` does NOT trigger this STOP — its parent at `dsl/std/error_primitives.dag:12` is live.) +10. **`Cardinal` ordered-domain substrate not landed when retrofit attempted** — array/slice/Vec rows author against `CardinalityBound` at HEAD as a forward-bridge. If a worker reaches retrofit without `Cardinal` having landed, escalate before introducing `Interval` references in `.dag` data (would break the dissolution trigger). +11. **Non-default hasher OR any allocator-bearing instantiation reached** — at the pinned 1.86 stable target, the `allocator_api` (`A: Allocator` parameter on `Vec` / `Box` / `Rc` / `Arc` / `HashMap` / `HashSet` / `BTreeMap` / `BTreeSet`) is **nightly-only** (gated behind `#![feature(allocator_api)]`). Phase-1 dispatch authors only stable signatures with no allocator axis. **Sub-conditions:** (a) Non-default hasher instantiation (`HashMap`, `HashSet`) is a distinct realization row from the default `RandomState` instance — escalate before authoring (expands row inventory; may force a substrate decision on whether hasher carriers are first-class declarations or lens-extensible labels). (b) **Any** allocator-bearing instantiation (`Vec`, `Box`, etc.) reached implies the worker has either deviated from stable Rust or the toolchain pin has been raised — STOP and re-pin per STOP #12 before authoring; allocator-bearing rows require the toolchain to first stabilize `allocator_api`. +12. **Implementation target toolchain or edition differs from the pinned authority** (§Lineage "Pinned external spec version" — currently Rust 1.86 stable + Rust 2024 edition). If CI runs against a different toolchain or edition at implementation dispatch time, worker MUST: (a) re-verify every cited Rust Reference / std spec fact against the new version (allocator/hasher signatures, `?Sized` relaxations, `+ Clone` allocator bound, `dyn`-compatibility rules, precise-capturing constraints, async-closure call traits, etc.); (b) re-pin the §Lineage authority bullet to the new versioned URL base; (c) update any row whose spec fact has changed across the version delta. **Do NOT silently consume a different toolchain's docs without updating the pin** (P1 fidelity violation against extdeps versioning). +13. **Repo / git prerequisites unsatisfied** at dispatch time (no clean working tree on the dispatching worker's environment). Implementation cannot start. + +--- + +## Cross-refs + +- Parent: `r2-grounding-manager.md` (lane row line 63; pending list line 142). +- Engine-reframe spec: `docs/design-emission-model.md` (Q1-Q5 locks; lane row line 384 if present). +- Q6-Q8 (lens framework): `docs/design-lens-framework.md`. +- INVARIANTS substrate-fact-introduction procedure: `INVARIANTS.md` §P1. +- Pilot precedent: `docs/briefs/grounding-pilot-receipt.md`. +- Sibling brief shape: `docs/briefs/t-ground-languagespec.md`. +- Pre-cascade context (historical only): `docs/briefs/grounding-manager.md` (archives on R2 promotion); `docs/briefs/t-ground-engine-phase-1-typestructure.md` (Phase 2 framing held per `design-emission-model.md` option (c)). +- Audit receipts: #1745 comments 4377431312 (initial) + 4377437266 (delta with expanded-scope evidence); manager correction at #1773 comment 4377448850 (`i128` already landed).