481add0ca2
Cycle 2 of the World/C21 milestone (#166): the World now orchestrates FAMILIES from blueprint-data. `aura sweep <blueprint.json> --axis <name>=<csv> …` loads an OPEN signal blueprint, grids the by-name axes against its param_space, builds each member via cycle-1's wrap_stage1r seam, and aggregates to a FamilyKind::Sweep family — byte-identical in shape to the hard-wired sweep. - `parse_sweep_blueprint_args` + `SweepBlueprintArgs`: repeatable `--axis name=csv` (lexed i64-then-f64; resolve_axes kind-checks), `--name`/`--trace`, the shared `--real/--from/--to` accumulator → DataChoice. - `blueprint_sweep_family` (pure) + `run_blueprint_sweep` (IO) mirror stage1_r_sweep_family with three deviations: by-name axes (verbatim param_space names, e.g. `stage1_signal.fast.length`), reload-per-member (Composite is !Clone — its build closures are Box<dyn Fn>, #164 — so a fresh signal is re-loaded from the doc per member), and a per-member shared topology_hash. Members share the hash (same signal topology, only params vary); member_key distinguishes them. - The `aura sweep <file.json>` `.json`-discriminator arm mirrors cycle 1; the hard-wired `--strategy` sweep is untouched (#159). Task-3 design gap resolved: a sweep needs an OPEN blueprint (open knobs to grid), distinct from cycle-1's fully-bound run fixture (a bound blueprint has an empty param_space). New `tests/fixtures/stage1_signal_open.json` = blueprint_to_json(stage1_signal(None,None)); a sweep must bind ALL open knobs, so the E2E grids fast×slow (2×2 = 4 members). Verified end-to-end by running the binary: `aura sweep stage1_signal_open.json --axis stage1_signal.fast.length=2,4 --axis stage1_signal.slow.length=8,16 --trace f` persists a discoverable 4-member Sweep family; an unknown axis fails clean. Member equivalence vs run_signal_stage1r + shared-hash/distinct-member_key unit-tested. Full workspace suite green; clippy --all-targets -D warnings clean. refs #166