spec: 0040 correct blast radius to four (empirically probed)

The boss-signed 0040 spec's blast-radius section claimed "exactly three" flipping
tests, named from a hand-trace. A throwaway probe (the check implemented, full
workspace suite run, then discarded) found FOUR: the three named negative tests plus
`param_space_mirrors_compiled_flat_node_param_order_under_nesting`, a compile-success
param-order test that today compiles a deliberately under-wired nested graph (LinComb's
two term inputs never wired) just to read its flat param order. The new check rejects
it where it currently returns Ok.

Correction is editorial, not a design change: the check itself is unchanged. The
fourth test's fix differs from the three negative tests — it needs the contrived graph
fully wired (fan fast_slow's output into both LinComb terms + a covering root role),
not just a covering role — so the §Blast radius and §Acceptance criteria now enumerate
all four with their distinct fixes. Verified empirically (119 passed, 4 failed; every
other crate green), the strongest possible grounding for the count.

refs #65
This commit is contained in:
2026-06-14 16:14:52 +02:00
parent 07b1ae1c63
commit 69b16f7d39
+43 -18
View File
@@ -264,27 +264,49 @@ need all faults are out of scope (the existing variants are first-fault too).
the lowered `FlatGraph` is unchanged (the existing identity test covers this; the
check adds nothing to lowering).
### Blast radius (named — fixed in this iteration, not deferred)
### Blast radius (empirically enumerated — fixed in this iteration, not deferred)
Three currently-green negative tests in `crates/aura-engine/src/blueprint.rs` wrap a
single-role composite `c` in a root with **empty** `edges` and **empty** `roles`
(`vec![BlueprintNode::Composite(c)], vec![], vec![], vec![]`). That leaves the root's
one interior node (a composite exposes one derived input port per role,
blueprint.rs:76-99) **uncovered**, so `check_ports_connected` — running at the root
level before the recursion — returns `UnconnectedPort { node: 0, slot: 0 }` and
pre-empts the deeper fault each test targets:
The authoritative blast radius was determined by a throwaway probe (the check
implemented, `cargo test --workspace --no-fail-fast` run, then discarded): **exactly
four** currently-green tests flip, all in `crates/aura-engine/src/blueprint.rs` (119
passed, 4 failed; every other crate — including the aura-cli sample/sweep/param_space/
render tests — stays green). Three are negative tests that wrap a single-role composite
`c` in a root with **empty** `edges` and **empty** `roles`
(`vec![BlueprintNode::Composite(c)], vec![], vec![], vec![]`), leaving the root's one
interior node (a composite exposes one derived input port per role, blueprint.rs:76-99)
**uncovered**, so `check_ports_connected` — running at the root level before the
recursion — returns `UnconnectedPort { node: 0, slot: 0 }` and pre-empts the deeper
fault each targets:
- `bad_interior_index_rejected` (~1372) — asserts `BadInteriorIndex` (a fault inside `c`).
- `role_kind_mismatch_rejected` (~1440) — asserts `RoleKindMismatch { role: 0 }`.
- `output_port_out_of_range_rejected` (~1463) — asserts `OutputPortOutOfRange`.
Resolution (in this iteration): make each root wrapper **minimally valid** so the test
still reaches its intended fault — give the root a covering input `Role` whose target is
`c`'s input slot (or, where the fault under test does not require `c` to expose an input
port, drop that port). The asserted deep-fault variant is unchanged; these fixtures
merely relied incidentally on under-wiring being accepted, which this cycle makes
invalid. This is the load-bearing test maintenance a new structural invariant entails —
named here, not discovered at implement time.
The fourth is a **compile-success** param-order test,
`param_space_mirrors_compiled_flat_node_param_order_under_nesting` (~1856), which today
compiles a deliberately **under-wired** nested graph just to read its flat param order:
the inner `strategy` composite (~1877) holds `[Composite(fast_slow), LinComb(2)]` but
wires neither of `LinComb`'s two `term` inputs, and the root (~1885) wraps `strategy`
with empty edges/roles, leaving `strategy`'s `price` input uncovered too. The new check
rejects it (`UnconnectedPort`) where it currently returns `Ok`.
Resolution (in this iteration):
- The **three negative tests**: give each root a covering input `Role` whose target is
`c`'s input slot (`Role { name: "src".into(), targets: vec![Target { node: 0, slot: 0 }],
source: Some(ScalarKind::F64) }`, mirroring the existing covering-role pattern at
~1414). The root level then passes and the recursion surfaces the intended deep fault
(the index/kind/output checks run before `c`'s own connectivity check), so each STILL
asserts its original variant.
- The **fourth (param-order) test**: fully wire the contrived graph — fan `fast_slow`'s
output into both `LinComb` terms (`Edge { from: 0, to: 1, slot: 0, from_field: 0 }`
and `Edge { from: 0, to: 1, slot: 1, from_field: 0 }` in `strategy`) and add a
covering root role for `strategy`'s `price` input. Wiring does not change node order
or params, so the asserted `param_space == compiled-flat-param-order` equality is
unchanged; only the graph becomes valid.
These fixtures merely relied incidentally on under-wiring being accepted, which this
cycle makes invalid — the load-bearing test maintenance a new structural invariant
entails.
Two adjacent negative tests are **safe by ordering** and need no change:
`compile_rejects_kind_mismatch_without_building` (~2013) — the edge kind-check fires
@@ -301,9 +323,12 @@ slot is covered by its role target, and `UnboundRootRole` is checked after
**each** surface for at least `UnconnectedPort`, and at least one
`DoubleWiredPort` test).
- The nested-level test (3) and the open-role-boundary test (4) pass.
- The three named blast-radius tests (`bad_interior_index_rejected`,
`role_kind_mismatch_rejected`, `output_port_out_of_range_rejected`) are re-wired to a
minimally-valid root and still assert their original deep-fault variant (green).
- All four empirically-enumerated blast-radius tests are fixed and green: the three
negative tests (`bad_interior_index_rejected`, `role_kind_mismatch_rejected`,
`output_port_out_of_range_rejected`) re-wired with a covering root role and still
asserting their original deep-fault variant; and the param-order test
(`param_space_mirrors_compiled_flat_node_param_order_under_nesting`) fully wired and
still asserting its `param_space == compiled-flat-param-order` equality.
- The full existing suite stays green (regression 5) and the compilat is
byte-identical for graphs that still compile (regression 6).
- The C8 ledger realization note is landed.