audit(0088): cycle close — drift fixes + C24 ledger refresh; close construction service

Architect drift review of cycle 0088 (#157, the introspectable fail-fast
construction service: §A shared gate predicates, §B the GraphSession/Op/replay
per-op surface + introspection, §C the aura graph build/introspect CLI).

What holds (confirmed against the diff): no-second-validator (C24) — edge_kind_check
is the single kind-check site called by both validate_wiring and
GraphSession::connect, and validate_wiring / check_param_namespace_injective are
reused verbatim in finish(); engine domain-free (invariant 9) — construction takes an
injected Fn(&str)->Option<PrimitiveBuilder>, no registry, the closed match +
std_vocabulary_types live in aura-std; topology-as-data / no DSL (C24/C17/inv 10) —
the engine Op is serde-free, the OpDoc wire DTO is CLI-side, ops are static and
non-Turing-complete; replay-equals-builder byte-identity (construction_e2e.rs) protects
C9/C19/C23.

Resolution:
- fix (drift-med): the root-role-boundness gate was the one holistic check finish()
  re-implemented instead of sharing — extracted check_root_roles_bound (blueprint.rs)
  and called from BOTH compile_with_cells and finish(), so finish() now reuses ALL the
  holistic gates and the no-second-validator claim is literally true. Behaviour-
  preserving (same UnboundRootRole variant; unbound_root_role_is_rejected stays green).
- fix (drift-med): removed the #![allow(dead_code)] on construction.rs — empirically
  unnecessary (the pub re-exported surface is reachable; clippy -D warnings green
  without it) — and its now-inaccurate comment (it claimed removal "when the consumer
  lands", but the consumer is a separate crate). Also tidied a stale graph_construct.rs
  module-doc line.
- fix (ledger): C24 Status refreshed — #157 moved out of "Remaining" with a cycle-0088
  realization note (the construction service: eager/holistic gate split, build-free
  introspection, emits the #155 blueprint); #159 reframed as paired with #157.
- carry-on (debt-med, forward-noted): the std_vocabulary roster is now a third hand-kept
  copy (match + test list + std_vocabulary_types) and introspect --vocabulary escalates
  #160's gap to user-facing — noted on #160; still fails safe.
- carry-on (scaling-low, forward-noted): the engine Op -> wire OpDoc direction is
  unguarded for future Op variants — noted on #156 (the format-extension track).

No architect-sweep / regression script is declared in the project facts, so the suite
is the gate: cargo test --workspace 51 suites green; clippy --all-targets -D warnings
clean. Cycle drift-clean.

Ephemeral cycle artifacts removed (lifecycle convention): docs/specs/0088-*,
docs/plans/0088-*.

closes #157
This commit is contained in:
2026-06-29 21:48:40 +02:00
parent 25e452aaf7
commit 86841b0740
6 changed files with 42 additions and 2260 deletions
+21 -7
View File
@@ -1780,7 +1780,8 @@ thread) force the **value**. The engine already treats topology as a runtime val
(C9 graph-as-data, C19 "cheap graph re-compilation, not a code recompile", C23 the
flat graph as the optimisation target); C24 only adds that the value **serializes out
of Rust and loads back in**.
**Status (2026-06-29; first cut shipped — cycle 0087 / #155, `d5602ec`).** The
**Status (2026-06-29; first cut shipped — cycle 0087 / #155, `d5602ec`;
construction service shipped — cycle 0088 / #157).** The
**principle** is settled (this contract, ratified in an in-context design discussion
— the #109 resolution). The **first cut now ships**: a `Composite` blueprint
serializes to a **canonical, versioned** data value (`format_version` envelope,
@@ -1791,12 +1792,25 @@ whose concrete closed `match` over the `aura-std` vocabulary lives outside the e
(`aura-std::std_vocabulary`) — the engine stays domain-free, no node registry
(invariant 9). Acceptance met: a serialized blueprint runs **bit-identical** (C1) to
its Rust-built twin. `model_to_json` (C9) remains the render half; this closes the
loop for the round-trippable vocabulary. **Remaining** (each its own milestone
issue): the forward-compat *must-understand* gate (#156); the introspectable
construction service that *emits* blueprints (#157); content-addressed topology
identity in the manifest (#158, C18); retiring the pre-C24 hard-wired `aura-cli`
harnesses (`HarnessKind`, `run_stage1_r`, `*_sweep_family`) once the construction +
project-as-crate layers land (#159). **Out of the first cut's round-trippable set**
loop for the round-trippable vocabulary. **Cycle 0088 (#157) adds the
introspectable construction service**: a declarative, replayable by-identifier
op-script (`aura graph build` / `introspect` over a JSON op-list, the engine
`GraphSession` / `replay`) builds a runnable blueprint through validated ops — the
engine's construction gates split into *eager* per-op checks (name resolution, edge
kind-match, the double-wire arm, param bind) and *holistic* finalize checks (wiring
totality, param-namespace injectivity, root-role boundness), **both cadences calling
the same extracted predicates** (`edge_kind_check`, the shared resolution helpers,
`check_root_roles_bound` — no second validator) — plus build-free introspection over
the closed vocabulary (types, a node's ports/kinds, a partial document's unwired
slots). It **emits** the #155 blueprint; acceptance met: a graph built purely through
the ops compiles identical (C1) to its Rust-built twin, an invalid op is rejected at
the op naming the cause, introspection answers without a build. The engine `Op` stays
serde-free (the wire DTO is CLI-side); the vocabulary's enumerable companion
(`std_vocabulary_types`) lives in `aura-std` (no registry, invariant 9). **Remaining**
(each its own milestone issue): the forward-compat *must-understand* gate (#156);
content-addressed topology identity in the manifest (#158, C18); retiring the pre-C24
hard-wired `aura-cli` harnesses (`HarnessKind`, `run_stage1_r`, `*_sweep_family`) once
the project-as-crate layer lands (#159, paired with #157's data-authoring surface). **Out of the first cut's round-trippable set**
(deliberate; fails clean as `UnknownNodeType`, never a silent wrong graph): recording
sinks (capture an `mpsc::Sender` — runtime identity, not param-generic data, C19) and
construction-arg builders (`LinComb` / `CostSum` / `SimBroker` / `Session`