Commit Graph

140 Commits

Author SHA1 Message Date
claude f0aadb54f8 audit: cycle-close tidy for the #256/#272 latecomer block
Drift review (architect) over a55e4cf..HEAD found the cycle substantially
clean — C25 closed vocabulary, C1 determinism/behaviour-preservation, the
additive-serde widening, exhaustive StageBlock matches, and the uniform exit-3
convention all hold. Two drift items resolved:

- RATIFY: the `SilencedPanic` member-boundary panic-hook silencer (added by the
  #272 implementer, not named in the spec) is a legitimate mechanism — it keeps
  "recorded, campaign continues" observably true on stderr by suppressing the
  default crash backtrace around each contained `catch_unwind`. Its mutex
  serialises only the ref-count/hook-swap (O(1)), never member computation, so
  C1 disjoint-parallel determinism is preserved. Documented in the ledger's
  #272 realization paragraph rather than left as undocumented global state.
- FIX: `cell_fault_kind_label` hand-wrote the snake_case strings that must match
  `CellFaultKind`'s serde `rename_all` (two sources of truth an aggregate over
  campaign_runs.jsonl could silently diverge from). Pinned with a test asserting
  each label equals the serialized form; the efficient `&'static str` stays.

(The #272 commit's own concern-driven doc fixes and the wf panic-containment
test landed in d3b1a1a; this commit carries only the two audit-phase items.)

Suite: cargo test --workspace green (1311 tests, 0 failed); clippy clean.
2026-07-14 17:01:36 +02:00
claude d3b1a1aead feat(campaign,registry,cli): per-cell fault isolation — a failed cell is recorded, never a global abort
closes #272

A member fault (no-data, bind, run, or a caught panic) is now a recorded
per-cell outcome instead of aborting the whole campaign and discarding every
already-computed cell. The incident that motivated this (a 22-instrument
campaign lost ~36 healthy cells ~6.7 min in because Copper had an archive gap)
now completes: the healthy cells persist, the gap cell is recorded as failed,
and the run exits 3.

Direction (owner decision 2026-07-14): run to completion and report
compromised results; no coverage preflight, no window synthesis.

Containment granularity:
- The CELL for a sweep-stage member fault (a grid hole structurally
  compromises winner selection, so the whole cell fails).
- The FOLD for a walk_forward member fault (independent time windows): the
  surviving folds pool into the family, failed folds are recorded as
  StageRealization.window_faults, and the summary names the ratio.

- aura-registry: additive CellFault / CellFaultKind (closed:
  no_data|bind|run|panic|window) / WindowFault / CellCoverage, plus
  fault/coverage fields on CellRealization and window_faults on
  StageRealization — all serde-default-skipped, so pre-#272 campaign_runs
  lines parse and round-trip byte-identical.
- aura-campaign: run_cell returns a fault-annotated CellRealization instead of
  Err (execute's accumulate-then-append-once tail is unchanged and now
  persists every healthy cell + the one run record); a `contain` split keeps
  ExecFault::Registry and doc-shape preflight faults global while Member/Window
  become per-cell/per-fold. Member panics are caught with
  catch_unwind(AssertUnwindSafe) at all three member-run sites (sweep IS/OOS)
  and recorded as MemberFault::Panic — a member panic no longer aborts the
  process. The wf stage partitions Registry faults (global) from Member/Window
  (per-fold) and filters faulted-fold placeholders (the
  "faulted-member-placeholder" broker sentinel) out of the persisted family.
- aura-cli: exec_fault_prose gains the Panic arm; CliMemberRunner::window_coverage
  derives effective bounds + interior gap months from the #264 archive
  primitives; present_campaign prints per-cell failure notes + a completion
  summary and threads the failed-cell count; a run with >=1 failed cell exits 3
  ("completed with failed cells") uniformly across `aura campaign run` and the
  dissolved sweep/walkforward/mc/generalize verbs (exit_on_campaign_result).
  Usage stays 2, refused-before-running stays 1, clean stays 0.

Tests: the global-abort pins flip to containment (execute + the two wf fault
tests → fold-containment + all-folds-fail-the-cell); new panic-containment
tests on both the sweep path (PanicRunner) and the wf path (this commit adds
the wf mirror the loop left uncovered); a new gapped-archive e2e (one covered
cell + one gap cell → exit 3); the ~14 CLI exit-1 pins move to the exit-3
register; a pre-#272-line byte-identical round-trip guard.

Suite: cargo test --workspace green (1309 tests, 0 failed); clippy clean.
Decision log: #272 comments (fork rationale, the fold Registry/Member split,
the placeholder sentinel, uniform exit-3).

Follow-up (minor, not blocking): the plan under-scoped Task 1 to aura-registry
though the additive fields also touch aura-campaign's exec.rs literals — the
loop absorbed it mechanically; a future plan for a cross-crate additive-field
change should scope every crate's construction sites in the first task.
2026-07-14 16:51:31 +02:00
claude ea4e79d73f feat(research,campaign,cli): std::grid — the enumerate-only leading stage
closes #256

Fork B (owner decision 2026-07-14): the dissolved walkforward/mc
translations' leading sweep executed the full grid over the whole campaign
window and persisted a Sweep family, yet only the enumerated parameter
points ever crossed the stage seam (the wf stage re-sweeps them per IS
window itself). The leading stage is now the fieldless vocabulary block
std::grid: it enumerates, executes nothing, persists nothing.

- aura-research: StageBlock::Grid ({"block":"std::grid"}), schema-strict
  parse arm (empty slot list: every key but "block" is refused by the
  generic unknown-slot check), PROCESS_BLOCKS entry, intrinsic-tier no-op
  arm; the vocabulary test's non-empty-slots guard carries a pinned
  std::grid-only exception (a nominal slot would misdescribe the
  vocabulary to describe_block consumers).
- aura-campaign: the inter-stage seam is a typed two-armed StageFlow
  (points-only vs executed members); gate / mc-per-survivor fence the
  points-only arm with defensive PipelineShape faults; preflight admits
  std::grid only as the first stage and only immediately before
  std::walk_forward (every other neighbor consumes executed reports).
- aura-cli: translate_walkforward / translate_mc lead with
  StageBlock::Grid; the two family-shape E2E pins flip to zero Sweep
  families; translate_generalize keeps its executed sweep(argmax) — its
  generalize stage consumes the argmax winner report as the cell nominee.
- docs: dated #256 amendment in the ledger's verb-dissolution narrative;
  the authoring-guide vocabulary transcript gains the std::grid line.

Behaviour preservation: the exact-grade real-data pins
(walkforward_real_e2e_pins_the_exact_current_grade,
mc_r_bootstrap_real_e2e_pins_the_exact_current_grade) pass unmodified —
survivor points reach the wf stage in the same odometer order as before.

Measured (the #256 acceptance measurement; debug build, real GER40 2025,
2x2 grid, `aura walkforward --real`, 3 runs each):
  before (a55e4cf): 6.27 / 6.18 / 6.18 s
  after:            4.52 / 4.49 / 4.45 s   (~ -27% wall clock)

Suite: cargo test --workspace green (0 failed); clippy clean.
Decision log: #256 comments (fork rationale incl. the StageFlow seam and
the slot-guard exception).
2026-07-14 13:07:40 +02:00
claude d1b3a3dd31 feat(research,composites,cli,docs): vol_tf — the timescale-matched stop regime
The second risk-regime variant vol_tf{period_minutes, length, k}
computes the vol estimator over completed time buckets: an H1 signal
gets an H1-matched stop in the research matrix instead of a hand-scaled
minute stop (the issue's k-inflation workaround retires). Additive
externally-tagged serde (stored Vol documents keep their content ids);
the executor arm wires the VolTfStop primitive via the builder+bind
chain; validate checks period_minutes/length/k positivity per regime.

The member-manifest round-trip holds for both variants (C1): vol_tf
members stamp stop_period_minutes/stop_length/stop_k and the reproduce
path re-derives the VolTf stop whenever stop_period_minutes is present
— never a silent default-Vol fallback. The Regimes slot label and the
unit notes name the new variant (period_minutes IS the stop's
timescale); glossary, authoring guide, and design ledger record the
second variant. Default regime and sugar paths byte-untouched.

Coverage: node units (rollover-only emission, bucket-delta math, the
constant-|delta| correspondence with the per-cycle regime), executor
fold, serde/validate units, the manifest round-trip unit, and a
hostless two-regime e2e (distinct ordinals; vol_tf members stamp their
timescale, vol members do not).

closes #262
2026-07-14 02:55:02 +02:00
claude bb0b0aeac2 feat(analysis,campaign,registry,cli): bootstrap net R through the process pipeline
The OOS bootstrap conduit RMetrics.trade_rs becomes net_trade_rs and
carries the COST-NETTED per-trade R (r − cost_in_r, trade order). Every
conduit consumer is thereby net-when-costed: the monte-carlo pooled-OOS
and per-survivor bootstraps, the walk-forward oos_r pooling, and the
deflation null-max — which previously compared a net observed statistic
against a gross-resampled null whenever a costed campaign selected on
net_expectancy_r. An uncosted run is bit-identical (empty cost stream
⇒ cost 0.0 per trade), so every existing golden pin stays green.

Design: one conduit, no knob — an explicit net: knob would let a costed
campaign silently produce a gross headline again (the exact misreading
of the issue's evidence). Per-member RMetrics scalar fields stay gross;
net_expectancy_r keeps its meaning. Wire shape unchanged (serde(skip)).
The net series is materialized as a separate expression in summarize_r;
the pinned-float expressions (net_sum, the SQN pair, the lockstep
r_metrics_from_rs copies) keep their tokens verbatim. Fork decisions
and rationales: issue #259 comments.

New coverage, both hostless over the synthetic SYMA archive: a costed
campaign twin shifts the pooled-OOS bootstrap (sweep→gate→wf→mc) and
every per-survivor bootstrap (sweep→mc) below its gross sibling, with
the trade population unchanged; a unit test pins the conduit as the
cost-netted series with the empty-stream degeneracy. Existing conduit
tests renamed with the field.

Verified: full workspace suite green (71 result blocks), clippy clean,
zero bare trade_rs tokens remain, ledger conduit prose updated in place.

closes #259
2026-07-13 21:21:41 +02:00
claude 1ebb94c1b8 feat(engine,cli): run manifests stamp untouched bound defaults (closes #249)
RunManifest gains defaults: Vec<(String, Scalar)> — the wrap-prefixed
bound_param_space() of the signal, read after axis reopening, so a
bound param an axis overrode has already left the space and flows
through params instead (disjoint by construction; verified end to end:
a sweep member's overridden fast.length sits in params while
slow.length/bias.scale sit in defaults). params keeps its "what varied"
semantics and stays the reproduce input. One-directional serde
widening (#[serde(default)]) per the selection/instrument/topology_hash
idiom — old records deserialize with an empty defaults; unlike the
Option fields it always serializes, mirroring params. ~20
struct-literal sites across five crates gained the field
(compile-mandated breadth, no behaviour change at those sites).

The C14 ledger records the underlying decision (2026-07-13): generated
outcome records spend redundancy on direct readability (single writer,
cannot drift); authored intent artifacts admit none (every redundancy
is a drift site) — so the fix lands in the manifest, never the
blueprint.

Verification: RED test run_manifest_stamps_untouched_bound_defaults
green; cargo build --workspace; cargo test --workspace green; clippy
-D warnings on the touched crates; binary-level sweep exclusivity
check.
2026-07-13 14:20:23 +02:00
claude 487431d97d test(cli): migrate the _open references — closed twins for sweeps, fixtures for open semantics (closes #248)
The references to the relocated _open blueprints follow the plan's
two-way split: tests that only need a sweepable blueprint sweep the
closed twins via bound-override axes (#246) with their axis strings
byte-unchanged (the wrap prefix is the blueprint's internal name,
identical across twins); the 12 tests that genuinely exercise
open-param semantics (run/mc closed-guard refusals, subset-axes
MissingKnob, --list-axes open/bound line mix, gang dissolution and
campaign paths) read the fixtures under tests/fixtures/. The
research_docs/project_load store seeds sweep the closed twin (campaign
axis references resolve via the #246 reopen path); the INDEX.md history
note records the relocation.

Two deviations from the plan, both verified against the tree: doc
comments referencing the bare filename (no examples/ prefix) escaped
the global path swap and were reworded to stay truthful; the seed
variable open_bp was renamed closed_bp (the plan kept it, but the
rename touches only the binding and its uses and removes a
misdescription).

Verification: cargo test -p aura-cli --test cli_run (140 passed, 0
failed, real data exercised); --test research_docs; --test
project_load; the four byte-pinned exact grades unchanged; grep-clean
for examples/r_*_open.json across crates+docs; full workspace suite
green.
2026-07-13 13:36:31 +02:00
claude e4fb64d7c6 docs: bound params are overridable defaults — C12 amendment, glossary, guide
Task 7 of the bound-override cycle: the design ledger's C12 records the
bound-as-default semantics (axis 1 may name a bound param; identity reads
the authored document; the retired axes-bind-only-open-knobs restriction
was an implementation consequence, not a recorded decision), the glossary's
blueprint entry carries the same sentence, and the authoring-guide's
data-only starter section explains the one-file run+sweep quickstart.

closes #246
2026-07-13 04:32:47 +02:00
claude 0170ec277f docs: two-tier project model — layout, guide, glossary, ledger, invariant 9 (#241 T7)
- CLAUDE.md invariant 9 amended end to end: a project is a directory
  anchored by a static Aura.toml, data-only by default; native node
  logic lives in attached node crates (the nodes/ antecedent removed —
  user decision 2026-07-12, re-opened by the role model's diagnosis).
- docs/project-layout.md reworked to the two tiers (data-only default
  tree + sibling node crate, workspace note under the crate half); the
  day-in-the-life walkthrough now attaches the project's node crate
  once and wires the namespace the shown command actually produces.
- docs/authoring-guide.md: data-only quickstart (closed run target,
  open sweep target) + `aura nodes new` as the native entry; section
  cross-reference updated.
- docs/glossary.md: new "data-only project" and "node crate" entries;
  Aura.toml and manifest entries carry the tier split.
- docs/design/INDEX.md: realization note (wiring-only tier, #241) in
  the project-environment section.
- rustdoc: `[nodes]` intra-doc-link escapes in project.rs/main.rs.

Full gates green: workspace suite (all binaries), clippy -D warnings,
doc build without new warnings.

closes #241
2026-07-12 17:45:59 +02:00
Brummel 43a427bfed audit: run-tail close — ledger and glossary reconciled to the shipped state
The tail audit over d1e01ef..62f6592 found no code drift against the
contracts (C18 name-resolution read-only, C23 doc identity-blind and
inline-dissolved, C1 fit deterministic) but four lagging records, fixed
here: the #106 real-roller amendment gains the #239 fit-to-window note
(fixed sizes are a ceiling on the sugar path); a #125 realization note
records the composite doc as a C23 debug symbol with its serde/identity/
viewer treatment; the glossary identity-id and composite entries name
the doc; GraphSession::finish states the deliberate absence of a
doc-carrying op-script surface (refs #125) instead of leaving the
authoring asymmetry silent.
2026-07-11 20:25:09 +02:00
Brummel d1e01efebf audit: fieldtest-tail close — C22 --trace ledger notes reconciled
Tail audit (aaca18c..f591164) over #213, the milestone-fieldtest
fixtures, and the B1 chart fix: #213's intersection semantics conflict
with no ledger contract, the depth-2 trace resolution preserves C1
ordering read-side with the layout unchanged, and the new §0/§3/
glossary docs match the code vocabularies. One HIGH drift item
resolved: the two C22 --trace amendment notes still described the #168
refusal surface and deferred per-member trace-writing to #224 — both
now carry a delivered-2026-07-11 annotation (real-data --trace writes
the depth-2 fan-out, chart resolves it; synthetic still refuses).
Accepted LOW debt, recorded in-code: the disjoint-archive generalize
refusal has no e2e fixture (unreachable on this host's archives), the
pure helper is unit-tested.
2026-07-11 15:12:59 +02:00
Brummel aaca18c6f6 audit: net-r cycle close — ledger reconciled, drift items resolved
Architect review over dd23ea3..HEAD (the #234/#152 cycle, 6 commits).

What holds (architect-confirmed): CostSpec is a closed, deny-unknown-
fields vocabulary with typed slots mirroring RiskRegime, field names
conforming to the builders' ParamSpec names; cost-less docs hash
byte-identically (C18); cost threads through the single MemberRunner
seam so every campaign stage nets uniformly; costed families reproduce
bit-identically incl. Carry; the #221-deleted leg is rebuilt optional
(net = gross under the empty model); both cost_graph leaks replaced by
the interned single source (#152).

Resolved this close: [high] the C10 realization notes contradicted
shipped reality — the two 'wired on the run path via --cost-*' claims
carry superseded-annotations, the 0084 carried-debt note a discharged-
annotation, and a new cycle-net-r realization documents the campaign
cost block, the net-by-default decision, the manifest/reproduce
round-trip, and the returned net_r_equity tap; [medium] two dangling
persist_traces_r docstring references reworded to what exists;
[medium] the one-knob-per-cost-node invariant behind the manifest
round-trip is now unit-pinned (exactly one distinctly-named knob per
shipped builder).

Cycle spec and plan (git-ignored working files) discarded per
convention.

refs #234
2026-07-11 12:28:15 +02:00
Brummel 7748b53a10 feat(cli,docs): the r_channel OHLC example + ledger amendment C26 (#231 tasks 6-7)
The acceptance proof: hl_channel — a causal Donchian channel (Delay(1)
excludes the current bar, C2) consuming high/low/close roles, built from
rostered vocabulary, shipped as the r_channel/r_channel_open example
pair (builder + regenerator + serialize pins, the r_* pattern). Proven
at three layers: a non-gated loaded-vs-carve equivalence over inline
sources (non-zero-bias hardened per review), the unconditional synthetic
multi-column refusal, and archive-gated CLI e2e — aura run on GER40
end-to-end plus a sweep whose members run and reproduce 2/2
bit-identically.

Ledger: new C26 entry (the binding vocabulary — closed column set +
price alias, name-driven default + campaign data.bindings override,
canonical order = the C4 tie-break, Blockly-litmus argument, the #71
extension point for recorded non-price sources) and the C20/C24
scaffolding-clause annotations: the single-price data weld is retired,
wrap_r's remaining R-scaffolding retirement stays #159.

Verified: all proof tests green, full workspace suite green, clippy -D
warnings clean; independent quality review approved.

closes #231
2026-07-11 05:10:05 +02:00
Brummel fc9cf23b87 feat(cli,docs): ship the ganged open examples + document the gang construct (#61 tasks 7-8)
The two open examples now expose their author-intended single knobs — the
closed builders always bound these pairs to one value by hand; the open forms
falsely offered them as independent axes:
- r_breakout_open: channel_hi.length + channel_lo.length -> channel_length
  (the Donchian channel is structurally ONE parameter)
- r_meanrev_open: mean_window.length + var_window.length -> window; the band
  factor stays an independent axis
Regenerated via the emitters (never hand-edited); the closed examples are
byte-unchanged. The carve builders gang in the open branch only.

Test migration: the two axis-namespace pins, five --real e2e invocations
(single gang axis, the 10,20 diagonal for the campaign pair — the mismatched
20,40/10,20 grid was exactly the configuration space the gang retires), and
the param_stability row counts (4 -> 3). The r-sma walkforward golden anchor
is untouched (it never swept a ganged pair).

Docs: authoring-guide gains the seventh op + the third param state
(open/bound/ganged) + the gang wrap note; README op list + Axis concept;
glossary gang entry; ledger C24 records the gang verb and the pre-ship
Tier-2 dormancy (no format-version bump while no out-of-repo reader exists).

Verified: full workspace suite 1104/0 (--real e2e included, local data
present), clippy -D warnings clean, cargo doc clean; live acceptance:
introspect --params prints channel_length:I64 alone / window:I64 +
band.factor:F64.

closes #61
2026-07-10 14:07:22 +02:00
Brummel 35b996e3bf docs(ledger,research): note the metric-vocabulary drift guard (#190 close)
The #190 cycle-close audit found two now-stale claims that predate this
cycle's guard test: the ledger's known-debt note listed the metric-roster
triplication as tracked by #190 (the issue that just added the guard, closing
on push), and metric_vocabulary()'s doc comment told a hand-editor to keep the
list in sync by hand without mentioning that a red test now catches a desync.

Reconcile both to the honest state: the triplication remains (still a
hand-list) but drift from the shipped aura-analysis types is now caught by the
cross-crate guard `aura-campaign/tests/metric_vocabulary_e2e.rs`; the
single-source removal that would delete the hand-list is tracked under #147
(where the metric vocabulary's home is decided).

refs #190, #147
2026-07-10 01:10:32 +02:00
Brummel f2526b1720 docs(cli,ledger): #168 cycle-close audit — reconcile the --trace surfaces (closes #168)
The #168 refusal left sibling --trace surfaces still lying and the design ledger
still describing CLI --trace as a live persist path (surfaced by the cycle-close
architect drift review). Reconcile them to record reality:

- the chart NotFound hint no longer points at `aura run --trace` (itself refused);
  it names the live trace-writer (a campaign document's persist_taps presentation).
- RunCmd/McCmd --trace help stop promising persistence (both flags already refuse).
- README drops --trace from the live naming flags.
- the ledger records the CLI --trace retirement: per-member --trace was never
  wired to the blueprint sweep (`let _ = persist`) and was silently dropped at
  #159/#220 — it never migrated as the old HISTORY note claimed; the single live
  TraceStore::write is the campaign persist_taps; restoration is deferred to #224.

Workspace suite green (62 groups / 0 failed), clippy -D warnings clean.

closes #168
2026-07-10 00:04:27 +02:00
Brummel 68317ec95d chore(cli,ledger): #217 cycle-close audit — coverage backfill + stop-knob helper
Cycle-close audit for the stop-default cycle (af8564d RED + 2102305
GREEN). Architect review: what holds — the argv extractors and the
campaign member runner default to the same single-sourced regime
constants; the multi-value refusal and the C10/C20 regime semantics
survive; manifests stamp the resolved stop (C18). Three drift items,
all resolved fix-path here:

- generalize's default path was shipped untested; added the
  generalize_args_from_defaults_missing_knobs_to_the_regime unit test
  mirroring mc's sibling.
- The None=>default / Some=>parse+single-value stop block recurred 4x
  across the walkforward/mc extractors; extracted into the generic
  stop_knob_or helper (refusal strings byte-identical; generalize's
  typed unwrap_or extractor deliberately not unified — no parsing
  there).
- Ledger stop-defaulting note now records the two default
  representations: sweep binds no regime (late-resolved by the member
  runner), the three verbs bind the default eagerly into the document
  — same R behaviour, deliberately different content ids.

Regression gate green, no baseline moved: full workspace suite 0
failures across all test-result groups; clippy -D warnings clean;
cargo doc 0 warnings. No spec/plan working files existed (tdd entry
path — the committed executable spec is the contract).

refs #217
2026-07-09 16:48:49 +02:00
Brummel 4acea45519 chore(cli,docs): #220 cycle-close audit — doc reconcile + dispatch dedup
Cycle-close audit for the verb-axis-generalization cycle (a2294c7,
e7efe1f, b849bb7). Architect drift review: what holds — all four verbs
route through the one validate_and_register_axes seam into the campaign
executor; RGrid gone workspace-wide; zero too_many_arguments allows in
verb_sugar.rs; no r_sma_open embed at the verb dispatch sites (the
aura-graph default embed survives by design). Five drift items found,
all resolved fix-path in this commit:

- README (blueprint-verbs section + mc row), glossary (walk-forward
  entry), and ledger (verb-dissolution passage) reconciled to the
  shipped generic grammar; the ledger HISTORY note now separates the
  two supersessions correctly (#159 retired the built-in --strategy
  demo surface; #220 de-welded the verbs) instead of mis-attributing
  the weld removal to #159.
- Four stale characterization doc-comments in cli_run.rs reworded:
  the retired welded grammar is now named as the pinned grades'
  provenance, not the current spelling; one dangling reference to a
  deleted test repointed to the live anchor.
- The quadruplicated dispatch blocks extracted into two shared helpers
  beside validate_and_register_axes: exit_axis_register_error (the
  AxisRegisterError exit-map, byte-identical stderr + exit codes) and
  campaign_window_ms (from_choice -> full_window -> unix-ms clip);
  generalize's explicit unclipped (Some, Some) passthrough arm is
  untouched — only its fallback arm, which already ran the identical
  mechanics, calls the helper.

Regression gate green, no baseline moved (nothing to ratify):
cargo test --workspace exit 0, 62 test-result groups, 0 failures;
clippy --workspace --all-targets -D warnings clean; cargo doc
--workspace --no-deps 0 warnings. Spent cycle spec + plan working
files discarded per lifecycle.

refs #220
2026-07-09 15:35:47 +02:00
Brummel 07a73fb66e docs(cli,ledger): sweep #159 demo-retirement drift — stale comments + ledger notes
Cycle-close audit tidy for the #159 demo-retirement arc: behaviour-free
reword of prose/comments/docs left pointing at symbols the arc deleted.
Adversarially verified by the audit workflow; cargo build --workspace
--all-targets green.

- README: drop the removed `--harness` token; restrict the legacy built-in
  form claim to walkforward/mc/generalize (run/sweep no longer resolve one).
- glossary: the built-in `--strategy` sweep surface is retired (#159), not a
  live inline path.
- INDEX.md ledger: append [HISTORY] supersession markers (house style) to the
  dated realization notes advertising the retired `--harness` / built-in
  `--strategy` CLI forms (cost-flag #153, cycles 0065/0066/0067, name-res,
  #210 status); historical text preserved.
- aura-engine test-fixture docs: drop dead cross-crate refs to the deleted
  aura-cli fns sample_harness / build_sample and the deleted `macd` composite.
- cli_run.rs: reword the #159-cut-2 pin doc to the current clap generic-usage
  reality (no strategy_from / Strategy::RBreakout); r_sma_sweep_family ->
  blueprint_sweep_family.
- verb_sugar.rs: fix the pre-existing `E[R]` unresolved-doc-link warning.

Remaining tidy — the main.rs comment cluster plus its rustdoc link at :1546
(the second cargo-doc warning) — held for a follow-up issue. The dead
cost-graph branch is tracked in #221. refs #159
2026-07-08 11:12:22 +02:00
Brummel b761b3c9c2 docs: close the verb-dissolution milestone — ledger status 4/4 + glossary sugar note
The verb-dissolution STATUS paragraph read "cycle 0110 dissolved the first verb
… Remaining: generalize, walkforward, and mc's R-bootstrap path" — stale at HEAD,
where all four verbs are dissolved. The per-cycle audits were each scoped to
their own commit range, so the cumulative status line lagged; the milestone
close fieldtest (#210, 2026-07-07) surfaced the drift.

Refresh the paragraph to the completed state, and record the per-verb
dissolved-form asymmetry as intended scope (ratify): for sweep the dissolved
form is the blueprint file (`<bp.json> --real`) while `aura sweep --strategy
r-sma --real` stays the inline built-in path — the built-in `--strategy` demo
surface is #159's hard-wired-harness retirement target, not the dissolution's;
for generalize/walkforward/mc the dissolved form is `--strategy r-sma --real`.

Glossary: note in the sweep and walk-forward entries that the CLI verbs are now
thin sugar over the campaign path.

Milestone closed 2026-07-07 on a green end-to-end fieldtest (0 bugs). Forward
findings filed: #216 (risk-axis discoverability), #217 (verb knob asymmetry),
#218 (no-project store litter).

refs #210
2026-07-07 10:48:17 +02:00
Brummel d96af7e1a2 audit: cycle close risk-regime axis — drift-clean after the C20 ledger fix (#210)
Architect drift review (c9d962f..HEAD). What holds: the nominee key is the
3-tuple (strategy, window, regime) and no argmax over regime_ordinal exists, so
the ledger's kept-separate / compared-not-selected semantics is what the code
does; the C18 manifest stamp is honest (the characterization pin flipped from
asserting absence to requiring the exact resolved 3/2.0, a strengthening, and a
real two-regime e2e catches per-cell mis-resolution); no dead code (cell.regime
and regime_ordinal are both read after the runtime-binding slice), absent/empty
risk keeps content-id parity, and CampaignGeneralization.regime_ordinal is
serde-default so pre-feature records still parse.

Resolution:
- FIX (inline, this commit): the spec promised a C10 AND a C20 note; only C10
  landed. C20's enumerated structural-axis list (strategy/instrument/broker/
  window) was left silently incomplete — the risk regime is added as the fourth
  matrix axis, with a dated realization pointer to the C10 semantics.
- carry (documented descope): no std::risk descriptor in CAMPAIGN_SECTIONS —
  risk is a top-level array, not a slot-bearing section; no invariant broken.
- carry (filed #212): the persist re-run + campaign_cell_key omit the regime
  because CellRealization gained none; the architect verified this is a LOUD C1
  drift-alarm refusal for a non-default regime + persist_taps, not silent wrong
  data (#212 corrected accordingly).
- trivial: validate_campaign's regime-check comment corrected (it catches NaN,
  not all non-finite; +inf is unreachable via JSON).

Regression gate: full workspace suite green, clippy clean (no dedicated
regression script; the suite + lint are the gate). Spec and plan removed
(git rm) at cycle close per the project convention. No baseline moved.

refs #210
2026-07-06 15:05:21 +02:00
Brummel 50d3db7028 feat(cli): finalize the risk-regime axis — ledger note + clippy-clean regime check (#210 T5)
The last slice of the risk-regime structural axis. The sugar parity
(`translate_sweep` emitting `risk: vec![]`, absent-serializing) and the
real-data two-regime e2e landed in the earlier slices (the loop's self-correction
and its e2e phase), so this closes the remaining pieces:

- design-ledger note: the risk regime realizes the StopRule structural axis at
  the campaign-document level — kept-separate keying, compared-not-selected (the
  R-unit argument), the C18 stamp, absent-parity, and the deferred trace gap
  (#212).
- clippy: `validate_campaign`'s regime check reads `k <= 0.0 || k.is_nan()`
  instead of `!(k > 0.0)` (neg_cmp_op_on_partial_ord), behaviour-identical.

Full workspace suite green; clippy clean.

refs #210
2026-07-06 14:56:16 +02:00
Brummel 2c729965db audit: cycle 0110 tidy — verb-dissolution cycle 1 closed drift-clean
Architect review (scope e7c7bde..b7aaa0b) found three items; resolutions:

- fix: docs/authoring-guide.md + glossary aligned with the shipped
  vocabulary (std::sweep selection group optional/all-or-nothing,
  selection-free = terminal-only, worked example verified against the
  live binary).
- fix: the #203 wrapped/raw axis-name convention is now single-sourced
  in campaign_run.rs (wrapped_to_raw_axis + raw_matches_wrapped, a
  cross-documented inverse pair; dispatch_sweep and both bind sites
  call through it; inverse-property unit test). Ratify note: this
  unifies two previously different algorithms onto the documented
  first-segment semantics — the old loose ends_with suffix-match also
  accepted sub-segment shorthands (e.g. axis "length" against
  "sma_signal.fast.length") that no stored document or test used;
  such shorthands now refuse loudly (unbound/unknown axis) instead of
  matching, the refuse-don't-guess reading of #203.
- carry: run_blueprint_sweep/blueprint_sweep_family remain generically
  real-capable though the dispatch no longer routes real data to them;
  the residual capability is shared DataSource machinery, its removal
  falls out with the built-in/synthetic branch retirement (#159), and
  the synthetic-only status is documented at the fn.

What holds: C24 canonical form (flatten group leaves every stored
content id unchanged, golden pin untouched), C18 lineage (topology_hash
IS content_id_of, single store write resolves the strategy ref;
selection-free arm still persists the full family), C25 closed-
vocabulary discipline (all-or-nothing group, Blockly-clean), C3 (ms/ns
conversion through the ingest seam's own named fn).

Ledger: #109 open-thread status lifted to cycles 0107-0110 reality
(executor shipped, amendment package landed, verb dissolution running
as milestone #210 with sweep dissolved).

Regression gates: cargo test --workspace 1056/0; clippy -D warnings
clean; cargo doc clean. Cycle spec+plan removed at close per
convention.

refs #210
2026-07-04 19:16:06 +02:00
Brummel 179c2f8bf0 audit: cycle 0109 tidy (drift resolved by ledger/glossary lift + tap-channel cross-pin)
Architect verdict: drift_found — the code holds (C1 honored not
assumed: the nominee re-run's metrics-equality hard refusal; C22/C14
clean: existing TraceStore + unchanged viewer, serde-default widening
round-trips, name composition single-sourced in derive_trace_name).
Resolved here:

- C18: the 0107 paragraph's 'persist_taps is deferred' points forward;
  new cycle-0109 realization paragraph records the closed tap
  vocabulary + UnknownTap tier, the nominee-only non-reduce re-run
  with the C1 metrics guard, the campaign trace family layout, the
  trace_name claim contract, the loud-skip lines, and the noted
  chart-over-family-root debt.
- Glossary: tap entry names the closed vocabulary + escalation rule;
  campaign document's presentation clause references it; campaign run
  gains the trace_name pointer.
- Debt fixed inline (architect med): tap_channel gains the
  emit_vocabulary-twin debug_assert cross-pin so a fifth vocabulary
  tap fails loudly instead of silently skipping.

The consumed 0108 fieldtest spec is removed with the cycle's spec+plan
(all its dispositions shipped: F6 #205, F8 #207, F11 #206, F7/F9/F10
doc-tightens).

Regression: cargo test --workspace 1041/0; clippy -D warnings clean;
cargo doc 0 warnings.

refs #201
2026-07-04 04:22:41 +02:00
Brummel ae2fac3212 audit: cycle 0108 tidy (drift resolved by ledger/glossary lift)
Architect verdict: drift_found — the expected pre-audit doc lag; the
code holds (C1: doc-seeded bootstrap + BTreeMap-ordered generalize;
C14/C23 sparse widening pinned by the pre-0108-line parse test;
terminal-annotator dataflow confirmed — nothing flows out, no new
emit kind, no content-id movement). All items resolved here:

- C18: 0107's 'refuse loudly at preflight' points forward; new
  cycle-0108 realization paragraph records the v2 shape, the
  dual-input stage bootstrap, campaign-scope generalize, the tier
  boundary (test-pinned on both sides), the record widenings, and
  the stringly wf-detection debt.
- Glossary: campaign document -> v2 shape; bootstrap and Monte-Carlo
  entries disambiguate the three senses (construction vs statistical
  r_bootstrap vs seed axis — the std::monte_carlo stage IS the
  trade-sequence bootstrap, named for r_bootstrap's arguments);
  generalize gains the campaign-scope realization.

Regression: cargo test --workspace 1025/0; clippy -D warnings clean;
cargo doc 0 warnings. Spec + plan removed at close per convention.

closes #200
2026-07-04 01:33:00 +02:00
Brummel 428f83c542 audit: cycle 0107 tidy (drift resolved by ledger/glossary lift)
Architect verdict: drift_found — the code holds its contracts (C1
determinism incl. lowest-index fault attribution and doc-seeded
deflation; C16 seam: aura-campaign excludes ingest/std/composites,
MemberRunner isolates the condemned CLI scaffolding; the walk_forward
lockstep set moved together), the docs lagged the tree. All six drift
items resolved in this commit:

- C18: 'no executor exists' retired (0106 text now points forward);
  new cycle-0107 realization records the executor, the aura-campaign
  home, ListSpace, the campaign_runs.jsonl sibling store, zero-survivor
  exit-0 semantics, emit/persist_taps split, the #196 on-ramp, and the
  machinery-true std::walk_forward correction.
- C16: aura-campaign added to the non-node crate enumeration
  (cycle-0107 realization; explicitly not C21's World).
- Glossary: campaign document entry corrected (run verb, execution
  prose); new 'campaign run' entry; blueprint entry gains the on-ramp
  verbs.

Carry-on debt (self-noted in code, tracked): metric-roster
triplication #190, deflation-constant duplication #199; cross-cell
fault orphans + nested-parallelism oversubscription noted in the
tasks-6-7 commit body. Follow-ups filed on the milestone: #200
(mc/generalize stage execution), #201 (persist_taps wiring).

Regression: cargo test --workspace 987/0; clippy -D warnings clean;
cargo doc 0 warnings. Spec + plan removed at close per convention
(durable rationale lives in the ledger; the canonical record is the
git history).

closes #198
2026-07-03 22:07:44 +02:00
Brummel e73aadae1e docs(ledger): #188 amendment package — C25 role model, C20/C22 refinements, invariant-10 clarification
C25 (new): the nine authoring roles cut by artifact + surface + iteration
cost, the recognizability test, the 6a/6b split on invariant 12's tier
boundary with the id machinery as interface, the text-first/headless-first
invariant (visual surfaces = stateless projections, viewers over editors),
and the Blockly litmus test as every vocabulary's acceptance criterion.

C20: the 'plain Rust loops, not a config schema' clause and the mini-DSL
forbid are scoped — they forbid an open logic-bearing language, not the
closed-vocabulary campaign document that now carries experiment intent
under the P1 construct tier; generators may stay Rust, what they yield is
data.

C22: stateless-projection refinement generalized to all artifact classes;
the shipped face recorded as the web-from-disk front. Glossary playground
entry aligned (the egui-native wording was stale against the 2026-06
revision).

CLAUDE.md invariant 10: clarified that closed-vocabulary data artifacts
(op-scripts, blueprints, process/campaign documents) are not the forbidden
DSL — RustAst failed as an open logic-bearing language; new logic
escalates to a Rust block, never a freetext hole.

All content ratified on #188 (body + addenda + resolution comments); this
commit is production of the durable record, no new design.

closes #192
2026-07-03 16:30:51 +02:00
Brummel ebe85683c9 audit: cycle 0106 tidy — ledger/glossary lift, unwired-hint fix, spec/plan retired
Architect drift review (holds: C14 headless authoring, C16/C17 no-DSL with
aura-research a true leaf, content-id move behaviour-preserving per the
untouched id goldens). Resolution per item:

- fix (docs): C18 gains the cycle-0106 realization note (processes/ +
  campaigns/ stores, document canonical form, the content-id primitive's
  library home, the referential tier, no-executor status); the #109
  analysis-meta-level open thread records the artifact half shipped v1 and
  what stays open (executor question, verb dissolution 'once it carries',
  the remaining #188 amendment package). Glossary: new campaign document +
  process document entries; content id generalized to all three artifact
  classes; experiment marked superseded by the campaign document (#188
  re-cut of the builder-API thread).
- fix (code): the --unwired guide advertised an identity_id process ref
  that validate_campaign refuses — the process.ref open-slot hint now says
  content-id-only (strategy refs keep both); lib + seam pins updated.
- filed forward: #190 (metric-vocabulary single-sourcing, the 0105 roster
  drift class), #191 (identity-ref store scan is O(store), performance
  only).
- carry-on: regression gates green by hand — cargo test --workspace 916/0,
  clippy -D warnings clean, cargo doc --no-deps 0 warnings; no baseline to
  ratify (project has no metric baseline scripts).

Cycle 0106 spec and plan retired per convention (git rm); durable record
is the ledger notes above plus #188/#189.

refs #189
2026-07-03 16:27:02 +02:00
Brummel 81ac6fd654 docs(ledger): declare the canonical project shape — templates canon, fixture frozen twin
Resolves the #181 design pass (option c: ledger declaration, no lockstep
mechanism). The aura-new templates (scaffold.rs) are the canonical
authoring shape and evolve with the engine; the cycle-0102 demo-project
fixture is an intentionally frozen known-good twin for the load-boundary
tests. Deliberately NOT lockstep-guarded: no consumer requires the copies
to match (skeptic-verified — nothing treats the fixture as what aura new
emits), each is e2e-guarded on its fitness for purpose (build/load/
charter/deterministic run; blueprint wiring is pinned in neither, stated
honestly after an adversarial skeptic pass refuted the stronger claim),
and an equality guard would convert deliberate template improvements into
forced churn of the frozen fixture — the same cross-purpose coupling that
rules out regenerating the fixture from the scaffolder.

closes #181, refs #180
2026-07-02 22:07:40 +02:00
Brummel bd32c4fcb3 audit: cycle 0105 tidy (drift-clean after two doc-mirror alignments)
Architect drift review (range 7b429f9..57f401f): drift_found (low/medium
only), resolved inline as close-fixes:
- crates/aura-std/src/vocabulary.rs — the roster-site doc now names BOTH
  count pins a node addition trips (the in-crate shape test and aura-cli's
  cross-boundary --vocabulary count e2e); the singular phrasing understated
  the cross-crate lockstep the extra e2e introduced.
- docs/design/INDEX.md — the C24 enforcement-shift passage gains the 0105
  delivery note: resolver-vs-list drift closed by construction via the
  roster macro; the un-rostered-node residual stays fail-safe.

Noted, no action: spec/plan predicted 884 (no new test) but delivery added
one e2e (885) — consciously superseded, disclosed in the iter commit body;
the artifacts are ephemeral and removed below.

What holds (architect): byte-preserving refactor confirmed against the
diff (22 keys/order exact, signatures and module doc untouched, every
consumer unchanged); invariant 9 / C24 preserved (compile-time expansion,
no registry); the new e2e count pin is genuinely roster-tied.

Regression gates (all green): cargo build clean; cargo test --workspace
885 passed / 0 failed (884 baseline + 1 new e2e); clippy --all-targets
-D warnings clean; cargo doc --no-deps 0 warnings.

Ephemeral cycle artifacts removed per project convention (git rm):
docs/specs/0105-std-vocabulary-roster-macro.md,
docs/plans/0105-std-vocabulary-roster-macro.md.

refs #180
2026-07-02 22:00:36 +02:00
Brummel 7b429f931a audit: cycle 0104 tidy (drift-clean after three doc-mirror alignments)
Architect drift review (range d5c4361..45fb06d): drift_found, three items,
all doc-mirror — resolved inline as close-fixes:
- docs/design/INDEX.md — the two #171 deferral passages (C18 #158
  realization + C24 status) now record the shipped identity id (additive
  sibling; content id keeps the store/reproduce roles; introspection-only
  until a dedup consumer exists). Whole-harness / structural-axis
  content-addressing stays deferred.
- README.md — introspect table gains the --identity-id row incl. the
  combinable id-flag behaviour.
- docs/glossary.md — three record-reality entries: content id, identity id
  (Avoid: identity hash, topology-identity hash), topology hash; the
  README row aligned to the canonical term.

What holds (architect): additive-sibling discipline intact (no store code
touched, every content-id/topology_hash pin green); C23 honoured precisely
(each strip arm has a protecting property test; factoring byte-preserving
via the canonical golden); the two extra engine tests are genuinely
distinct coverage (recursion arm, role/output arms), no redundancy.

Regression gates (all green): cargo build clean; cargo test --workspace
884 passed / 0 failed (873 baseline + 11 new); clippy --all-targets
-D warnings clean; cargo doc --no-deps 0 warnings.

Ephemeral cycle artifacts removed per project convention (git rm):
docs/specs/0104-topology-identity-hash.md,
docs/plans/0104-topology-identity-hash.md.

refs #180
2026-07-02 21:29:38 +02:00
Brummel d5c4361a97 audit: cycle 0103 tidy (drift-clean after three doc-mirror alignments)
Architect review of b672a37..HEAD. What holds: emitted templates match
the settled contracts (Aura.toml paths-only per C17, cdylib + empty
[workspace] per C16, ::-namespaced ids per the charter, the C14 exit
partition in dispatch_new); the load-bypass guard is narrow and sound
(only the new-project verb exempted, the load arm byte-unchanged for
every other verb); e2e coverage is real (scaffold -> build -> run twice
byte-identical, namespace stamped, introspection, four refusals, the
unbuilt-tree bypass, plus the additive namespace-override test).

Regression: cargo build --workspace rc=0; cargo test --workspace 873
passed / 0 failed (project_new 6/6); clippy --workspace --all-targets
-D warnings rc=0; cargo doc --workspace --no-deps 0 warnings. No
baselines exist to move, so nothing to ratify.

Drift resolved in this commit: three doc mirrors still framing the
scaffolder as future — project-layout.md's 'the future aura new
scaffolder will emit this line; until then, add it by hand', the C24
status paragraph's 'what remains open is the aura new scaffolder (the
milestone's next cycle)', and the #109 open-thread bullet's 'the aura
new scaffolder and the experiment-builder API remain open' — all
rewritten to the landed reading (only the experiment-builder API stays
open in that layer).

Carried debt, filed forward: the scaffold templates and the
demo-project fixture encode one project shape twice with no lockstep
guard and deliberate cosmetic divergences (#181, idea — needs a design
pass, not a mechanical edit).

Process note: one mid-cycle plan-fix commit (derive(Debug) on a
plan-prescribed struct whose own test code required it) — the
implement loop's spec gate correctly blocked the necessary deviation;
resolution followed the fix-plan/commit-subset/re-run path.

Ephemeral cycle artifacts removed per convention: spec 0103, plan 0103.

refs #180
2026-07-02 19:24:03 +02:00
Brummel b672a37903 audit: cycle 0102 tidy (drift-clean after two ledger-mirror alignments)
Architect review of d7c935d..HEAD. What holds: C13/C16 separation
verified by diff (descriptor in aura-core::project, loader entirely in
aura-cli::project, aura-engine gains only the additive provenance
field); the C-tier-before-Rust-tier discipline is enforced in load()
(magic -> version -> stamps, fn pointers touched only after Ok);
C17/C24/invariant-9 hold (paths-only Aura.toml, injected merged
resolver, charter at the one seam); outside-a-project byte-identity
confirmed by the full green suite incl. every golden-bearing test.

Regression: cargo build --workspace rc=0; cargo test --workspace 862
passed / 0 failed (cli_run 133, project_load 7 e2e); clippy
--workspace --all-targets -D warnings rc=0; cargo doc --workspace
--no-deps 0 warnings. No baselines exist to move, so nothing to
ratify.

Drift resolved in this commit: two stale project-as-crate ledger
mirrors — the C24 status paragraph still calling the layer
sequencing-coupled/unbuilt, and the #109 open-thread bullet naming it
an unbuilt half — rewritten to record the landed load boundary (the
aura new scaffolder and the experiment-builder API stay open).

Carried holds (plan-prescribed bytes, cosmetic): the unreachable
rsplit fallback in node_name, the unreachable! build closure in one
aura-core test.

Ephemeral cycle artifacts removed per convention: spec 0102, plan 0102.

refs #180
2026-07-02 18:20:23 +02:00
Brummel 4928e289f7 feat(project): the project-as-crate load boundary (cycle 0102)
A research project is now a loadable external cdylib crate. Inside a
directory whose ancestry holds an Aura.toml, aura discovers the project
root cargo-style, locates the compiled dylib via cargo metadata (debug
default, --release opt-in), loads it load-and-hold, and refuses
mismatches before trusting anything: the AURA_PROJECT descriptor
(aura-core::project, #[repr(C)]) carries a C-ABI stamp prefix (rustc +
aura-core version, baked per consuming build by the new aura-core
build.rs) validated before any Rust-ABI field is read. The vocabulary
charter gates the merged resolution: project type ids are ::-namespaced
(std stays bare), duplicates refuse, and the enumerable type-id list
must agree with the resolver, so introspection can never silently omit
a project type.

All blueprint verbs resolve through the merged project + std vocabulary
via a per-invocation Env threaded through the dispatch chains;
registry, trace-store, and data paths anchor at the project runs root
(Aura.toml [paths], paths-only by design — instrument geometry stays
the recorded sidecar, C15). RunManifest gains the Tier-1 project
provenance field (namespace + dylib sha256 + best-effort commit),
stamped beside topology_hash on the blueprint-run paths; pre-0102
registry lines load unchanged. Default node names strip the namespace,
so :: never reaches the param-path address space.

Proven by the demo-project fixture (built by the e2e via cargo,
path-dep on this workspace): run twice bit-identical, provenance
recorded, introspection lists demo::* beside std, registry anchors at
the discovered root from a subdirectory; the badcharter fixture proves
the charter refusal through the real libloading path; a never-built
project refuses with a cargo-build hint. Outside a project every path
collapses to the previous literals — goldens and manifest pins
byte-identical.

Verification: cargo build --workspace clean; cargo test --workspace 862
passed / 0 failed (incl. 7 project_load e2e); clippy -D warnings clean
(one precedent-matching allow(too_many_arguments) on run_oos_blueprint,
whose arity the Env threading raised to 8); doc build unchanged.
Docs/ledger aligned: Aura.toml field lists are paths-only in
project-layout.md, glossary, C16/C17; new C13 realization note records
the per-invocation-reload reading and the load-and-hold one-shot scope
boundary.

New deps, per-case review (aura-cli leaf binary only, never the frozen
artifact): libloading, toml.

refs #180
2026-07-02 18:13:37 +02:00
Brummel d7c935dd77 audit: cycle 0101 tidy (drift-clean after one ledger alignment)
Architect review of 8814e295..HEAD. What holds: the cosmetic-only claim is
verified (every -/+ pair in the code diff is a string literal; no exit(),
channel, or control-flow byte moved; the C14 usage=2/runtime=1 partition
preserved at every touched site); grep gates exact (zero lowercase usage:
literals, 11 'Usage: aura' source lines = 10 edited + the pre-conforming
run_args_from); fieldtests corpus and refusal diagnostics byte-identical.
The recorded spec deviation (3 additive house-style pins) strengthens
coverage over a real pin gap and is decision-logged on the issue.

Regression: cargo build rc=0, cargo test --workspace rc=0 (cli_run 133
passed / 0 failed), clippy -D warnings rc=0, doc build rc=0. No baselines
exist to move, so nothing to ratify.

Drift resolved in this commit: the C14 ledger note still described the
casing normalization as deferred after #179 landed - rewritten to record
the landed house style (usage lines 'Usage: aura <verb> ...', refusal
diagnostics deliberately unprefixed).

Ephemeral cycle artifacts removed per convention: spec 0101, plan 0101.

refs #179
2026-07-02 12:59:36 +02:00
Brummel 8814e29597 audit: cycle 0100 tidy (drift-clean after one ledger alignment)
Architect review of 88e9c9a..HEAD. What holds: token purity of the rename
(removed + mapping == added, 33 sanctioned prose rewordings, numeric golden
bytes untouched); CLAUDE.md invariant 7 now matches the ledger C10 section
clause-by-clause; no silent alias for the old selectors (unknown-selector
exit-2 path is tested).

Regression: cargo build / clippy -D warnings / doc build clean; cargo test
--workspace rc=0, 51 targets, 0 failures. No baselines exist to move, so
nothing to ratify.

Drift resolved in this commit: the C10 terminology note (INDEX.md) still
called Stage-1 a surviving identifier name after the glossary recorded the
rename - aligned to name the r-family rename (#174). Remaining low items:
the spec's own survivor-list contradiction was ratified and recorded on the
issue; the RGrid const-seeding debt is recorded on the harness-retirement
issue (refs #159).

Ephemeral cycle artifacts removed per convention: spec 0100, plan 0100, and
the spent prior-milestone fieldtest spec.

refs #174
2026-07-02 12:11:33 +02:00
Brummel 4de6d5cbad rename: retire the stage1-* family for the r-family (r-sma / r-breakout / r-meanrev)
The stage1 ordinal has been dead vocabulary since the C10 reframe dropped
the two-stage research model: a 1 structurally implies a 2 that no longer
exists. The family is renamed by its live discriminator - the R yardstick -
with members named by their signal, uniform with their signal-named
siblings (sma, macd, momentum):

- selectors: stage1-r -> r-sma, stage1-breakout -> r-breakout,
  stage1-meanrev -> r-meanrev (old tokens are usage errors, exit 2 - no
  silent alias)
- identifiers: Strategy::RSma/RBreakout/RMeanRev, HarnessKind::RSma,
  r_sma_*/r_breakout_*/r_meanrev_*, wrap_r, run_signal_r, RGrid, R_SMA_*
- persisted identity: the sma_signal composite (param prefix
  sma_signal.fast.length / .slow.length; fixtures regenerated; content-ids
  shift - no test pins a literal hash, the registry parses no record names)
- e2e test files git-mv'd to r_sma_e2e / r_breakout_e2e / r_meanrev_e2e
- dead Stage-1/Stage-2 prose reworded to post-C10 vocabulary across
  rustdoc, Cargo.tomls, ledger live lines, and the glossary (historical
  entries stay; fieldtests corpus untouched)
- CLAUDE.md invariant 7 rewritten to record the ratified C10 reframe
  faithfully (the token-swap alone would have laundered the retired
  gated-currency/realistic-broker design into unmarked live prose); the
  unbacked account-mode clause dropped

Verification: cargo build/test --workspace green (51 targets), clippy
-D warnings clean, doc build clean, acceptance grep gate leaves exactly
the one resampling-stage false positive (harness.rs), smoke: --harness
r-sma runs, --harness stage1-r exits 2 with the new usage line.

Decision log: forks and rationale recorded on the issue (reconciliation
+ implementation-phase comments).

closes #174
2026-07-02 12:03:09 +02:00
Brummel 88e9c9a539 fix(cli): symmetric sweep/mc family-verb polish (closed error, mc seed label, mandatory-knob docs)
Three polish items surfaced by the World/C21 milestone fieldtest:

- A sweep of a fully-bound (closed) blueprint is refused up front with a clear
  "this blueprint is fully bound; nothing to sweep" message — the symmetric
  inverse of blueprint_mc_family's closed-blueprint guard — instead of leaking a
  misleading UnknownKnob for a knob that is not unknown but bound out.
  blueprint_sweep_family's error contract widens to String; the sweep terminal's
  BindError (a genuine unknown/kind-mismatch axis) still surfaces verbatim.
- mc reproduce lines now carry each member's seed=<N> label. Monte-Carlo members
  hold no tuning params, so the member label was blank; the seed is each draw's
  realization identity. Sweep / walk-forward labels (which echo params) unchanged.
- docs (design ledger + glossary): state that every open knob --list-axes prints
  is mandatory on sweep / walkforward — a subset is refused with the missing knob
  named (BindError::MissingKnob), there is no default; pin a knob you do not want
  to vary with a single-value axis.

RED-first for the two behaviour items. One existing unknown-axis E2E is re-pointed
from the closed fixture (which now hits the new "nothing to sweep" pre-check) to
the open fixture; it still exercises UnknownKnob("nope") specifically — resolve
raises UnknownKnob in phase 1 before MissingKnob in phase 2 — so the property is
preserved, not weakened.

closes #178
2026-07-02 09:41:54 +02:00
Brummel 27f0f8ea11 audit(0099): cycle close — CLI clap adoption; ledger refreshed (C14); rm ephemeral spec/plan
Architect drift review (scope 780d823..HEAD, the sole gate — no regression
script) returned one medium ledger-gap, now resolved; otherwise drift-clean with
a positive What-holds:
- invariant 8 / C16 engine-domain separation preserved: clap is confined to
  crates/aura-cli/Cargo.toml; the whole diff touches only aura-cli/ + Cargo.lock
  + ephemeral docs; no engine/std/composites/analysis/registry/core/ingest crate
  mentions clap, so the frozen deploy artifact structurally cannot pick it up
  (aura-cli is a leaf binary). The 16 new lock entries are exactly clap's tree.
- C16 per-case admission honest: clap admitted with a documented rationale at the
  Cargo.toml site (replaces the hand-rolled parser + ten help surfaces; dev-loop
  tax, not frozen-artifact tax), the same admission form as sha2/libc.
- C14 automation-face served, execution layer intact: the usage=2/runtime=1
  partition, scoped --help, --version, and GNU flags match the spec; the domain
  fns keep their signatures (arg-plumbing via thin *_from adapters); new
  behaviour is pinned (partition property test, version, scoped-help, dual-grammar
  stray-positional guard).

Ledger refreshed: the C14 realization block now records the clap adoption + the
exit-code partition (usage=2/runtime=1) as a durable automation contract, before
the ephemeral spec that first stated it is removed (the drift item the architect
raised).

Deferred/forward: error-message casing normalization (#179, idea); the
machine-first help surface stays on the #157/C21 track (Fork B settled this cycle
as human/GNU convention compliance).

Verified green (orchestrator, this session): cargo build --workspace clean; cargo
clippy --workspace --all-targets -- -D warnings clean; cargo test --workspace
green. Cycle drift-clean.

closes #175
2026-07-01 20:11:11 +02:00
Brummel 4710fccf32 audit(0097): cycle close — IS-refit walk-forward over a loaded blueprint; ledger refreshed (C24/C18); rm ephemeral spec/plan
cycle 0097 tidy (clean). Architect drift review over 485f3c8..HEAD: no code
drift, no debt. Regression: no dedicated script (architect is the sole gate);
its "What holds" is non-empty (design commitments confirmed against the diff):
- Inv. 8 / 9: the cycle touches only crates/aura-cli (main.rs + cli_run.rs +
  the ephemeral spec/plan); walk_forward/WindowRoller/FamilyKind::WalkForward/
  append_family/put_blueprint are read-only reuse, no engine/registry change.
- Inv. 1 / 2: blueprint_walkforward_family reuses the generic walk_forward roller
  (windows disjoint-parallel, across-sim); each IS-sweep/OOS-run sees only its
  window's windowed_sources; IS precedes OOS per window — no look-ahead.
- Reproduce lockstep: the reproduce_family_in WalkForward arm rebuilds each OOS
  slice from stored.manifest.window (before the _ => run_sources fallthrough that
  would rebuild the wrong full-window source); winner params via the shared
  manifest->cells recovery; pinned by the reproduces_bit_identically E2E.
- Structural mirror + panic-safety: one-substitution-deep twin of the hard-wired
  Stage1R arm (select_winner + walk_forward reused, metric sqn_normalized);
  run_blueprint_walkforward follows the content-addressed sibling pattern (no
  ensure_name_free); blueprint_sweep_over returns Result<_,BindError>, a bad axis
  is in-closure exit 2 (never a panic); run_oos_blueprint derives pip internally
  (7 args, no #[allow]).

Ledger: refreshed the C24 realization block (docs/design/INDEX.md) — replaced the
now-false "Walk-forward is deferred (#173, dep #169)" sentence with the "IS-refit
walk-forward shipped (cycle 0097)" note; and extended the C18 reproduction note —
reproduce now spans the third family kind (WalkForward), so all three FamilyKind
variants persist AND reproduce through the one shared topology_hash+put_blueprint
hook.

Milestone: the World/C21 blueprint-data family surface (run/sweep/mc/walkforward/
list-axes/reproduce) is coherent and complete per the architect review — no
structural gap. This audit proves drift-clean; a green end-to-end MILESTONE
FIELDTEST remains the deliberate gate to formally close the World/C21 milestone.
Ephemeral spec/plan git-rm'd per the lifecycle convention.

refs #173
2026-07-01 16:44:54 +02:00
Brummel 485f3c8c89 audit(0096): cycle close — axis discovery over a loaded blueprint; ledger refreshed (C24); rm ephemeral spec/plan
cycle 0096 tidy (clean). Architect drift review over ebebc24..HEAD: no drift,
no debt. Regression: no dedicated script (architect is the sole gate); its
"What holds" is non-empty (design commitments confirmed against the diff + a
green test run, not the commit body):
- Inv. 8 / 9: the cycle touches only crates/aura-cli (main.rs + cli_run.rs +
  the ephemeral spec/plan) — no engine/registry/blueprint.rs change; those are
  read-only callees.
- Inv. 1: --list-axes is a pure read-only probe (short-circuits before
  run_blueprint_sweep; builds the wrapped composite, reads param_space, prints
  — no run, no seed, no engine execution).
- Behaviour-preserving single-source: blueprint_axis_probe is token-identical to
  the two former inline probes; three copies (sweep/mc/list) collapse to one; the
  reload closures survive (topology_hash + per-member run); clippy -D warnings
  clean, no dead code; the subsumed tests
  (blueprint_sweep_member_equals_single_run_and_shares_topology_hash,
  blueprint_mc_family_rejects_an_open_blueprint) stayed green.
- The blueprint_axis_probe .expect is not a latent panic: the ["sweep",..] arm
  validates blueprint_from_json first (exit 2), pinned by the shipped
  aura_sweep_list_axes_rejects_malformed_blueprint E2E (no panic).

Ledger: refreshed the C24 realization block (docs/design/INDEX.md) — reclassified
the "axis-name discovery surface" from tracked debt to shipped (cycle 0096),
recording the single-sourced blueprint_axis_probe and the listed==swept-by-
construction property. Per-member trace-writing (#168) remains the one tracked
debt in that block.

Milestone World/C21 stays OPEN — the walk-forward half (#173, IS-refit, now
unblocked by this #169) remains. Ephemeral spec/plan git-rm'd per the lifecycle
convention.

refs #169
2026-07-01 14:59:36 +02:00
Brummel ebebc2401b audit(0095): cycle close — MC over a loaded blueprint; ledger refreshed (C18/C21); rm ephemeral spec/plan
Architect drift review (scope cec7811..HEAD, the sole gate — no regression
script) returned drift-clean with positive What-holds:
- invariants 8/9: the whole cycle is aura-cli (main.rs + cli_run.rs + ephemeral
  docs); nothing entered aura-engine/aura-registry; FamilyKind::MonteCarlo,
  monte_carlo, append_family, mc_member_reports are pre-existing seams reused.
- invariant 1 / C1: draws run disjoint-parallel via the engine monte_carlo seam
  (seed-input order, no within-sim concurrency); bit-identity proven by the
  reproduce round-trip (unit + E2E).
- the C1 lockstep is a single shared fn: synthetic_walk_sources (one fixed
  SyntheticSpec) is called by BOTH the persist path and the reproduce MonteCarlo
  branch; pip is lockstepped too (both pass DataSource::Synthetic).
- the sweep-sibling pattern matches: Result<McFamily,String> + boundary render.
- scope honesty: WF deferral (#173, dep #169) and synthetic-walk-DGP (#172) are
  named in the spec + feat body, not silent.

Carry-on debt (does NOT block close, filed forward, NOT new-this-cycle drift):
synthetic_walk_sources' len:60 is hand-calibrated to the shallow stage1 warm-up;
a deep-lookback closed blueprint warms poorly -> silent-vacuous draws with no
error, and the anti-degenerate test only exercises the shallow fixture. Folded
into #172 (real-data DGP retires the length calibration) per the architect's
recommendation, rather than a new thread.

Ledger refreshed: the C21 realization block now records the MC verb shipped
(cycle 0095) with WF deferred; the C18 reproduction block notes aura reproduce
now spans FamilyKind::MonteCarlo.

Verified green (orchestrator, this session): cargo build --workspace clean;
cargo clippy --workspace --all-targets -- -D warnings clean; cargo test
--workspace green. Cycle is drift-clean (not a milestone close — #170's WF half
remains, milestone stays open).

refs #170
2026-07-01 13:24:47 +02:00
Brummel cec7811c32 audit(0094): cycle close — content-addressed reproduction; ledger refreshed, coverage closed; rm ephemeral spec/plan
Architect drift review (4751d4b..HEAD): drift_found — ledger-currency only; the
code is clean.

What holds (architect, confirmed by diff + green tests):
- Inv 8 / C9: aura-engine byte-untouched; content_id + sha2 in aura-cli, the
  store in aura-registry.
- Inv 9: Registry::{put,get}_blueprint is a dumb bytes-by-key store (opaque
  String keyed by String hash; no sha2, no parse, no sha256==hash verify — the
  caller owns the hash). No domain knowledge crept into the engine or registry.
- C1: the run_blueprint_member extraction is behaviour-preserving (keystone
  blueprint_sweep_member_equals_single_run_and_shares_topology_hash unchanged +
  green); serde_json/float_roundtrip serves determinism (disk==recomputed), not a
  mask (1-ULP canary green).
- C11/C12: one blueprint stored per family, keyed by the shared topology_hash.

Resolutions:
- [ledger] Refreshed C18 + C24: added the cycle-0094 Realization (the
  content-addressed store runs/blueprints/<hash>.json + aura reproduce), and
  retired the now-false "content-addressed identity / full reproduction deferred"
  claims (INDEX.md:1261, C24 deferred block). Only the structural-axis /
  whole-harness content-id (and the debug-name-in-id question) genuinely remains,
  filed forward (#171, #170).
- [debt->closed] Added the two untested refuse-don't-guess E2E arms
  (aura_reproduce_rejects_a_non_generated_family — a hard-wired sweep member has
  no topology_hash; aura_reproduce_rejects_a_missing_stored_blueprint — the store
  was deleted), and a cross-surface unit pin
  (topology_hash_is_the_content_id_of_the_canonical_form) so the two acc-1 paths
  cannot silently drift.
- [scaling] MC/walk-forward-from-blueprint (#170) will need the same put_blueprint
  hook or reproduce won't cover them — noted on #170.

No regression scripts in this project (Test is the gate): full workspace suite
green (51 suites), clippy -D warnings clean, binary verified end-to-end.

Ephemeral spec/plan git-rm'd per the lifecycle convention; durable rationale is in
the ledger. The World/C21 milestone stays open (#170 remains).

closes #158
2026-07-01 03:15:39 +02:00
Brummel 4751d4b590 audit(0093): cycle close — sweep-from-blueprint; ledger refreshed, debt filed; rm ephemeral spec/plan
Cycle-close drift review (architect) for cycle 0093 / #166 (aura sweep
<blueprint.json>). Drift-found on debt only; no contract violation.

What holds (architect, evidence of review): invariant 9 fail-clean (resolve_axes
runs before the sweep closure → named BindError UnknownKnob/MissingKnob/KindMismatch,
exit 2; UnknownNodeType on load; no registry); C1/C12/C18 shape verbatim from
stage1_r_sweep_family (members disjoint + enumeration-ordered; shared topology_hash
correct, consistent with the cycle-1 #158 signal-only scope; append_family/
sweep_member_reports reused); reload-per-member is sound (Composite !Clone, #164);
stdout uses family_member_line with family_id, run_sweep-consistent.

Resolved: ledger refreshed (C24 Status — the cycle-0093 realization: the World now
orchestrates FAMILIES from blueprint-data; the open-vs-bound fixture fact + the
reload-per-member rationale recorded). Drift filed forward: #168 (--trace writes no
per-member traces — silently like --name, debt-med), #169 (no axis-name discovery
for loaded sweeps, debt-low), #170 (MC/walk-forward over a loaded blueprint — the
next family-verb cycle, assigned to the milestone).

Ephemeral 0093 spec + plan git-rm'd per the lifecycle convention.

closes #166
2026-07-01 00:35:23 +02:00
Brummel 327d71b1d4 audit(0092): cycle close — run-from-blueprint; ledger refreshed, drift filed; rm ephemeral spec/plan
Cycle-close drift review (architect) for cycle 0092 / #165 (aura run
<blueprint.json>). Drift-found on ledger currency only; the code is clean and
correct.

What holds (architect, evidence of review): the stage1_signal/wrap_stage1r split
is behaviour-preserving (golden metrics byte-unchanged; loaded_signal bit-identical
green; the STAGE1_R_SMA_* constants keep the hashed signal == the executed signal);
sha2 + the topology_hash helper live in aura-cli only, aura-engine stays sha2-free
(invariant 8 / C16); the resolver resolves the closed std_vocabulary set, unknown
type -> UnknownNodeType, no registry (invariant 9); topology_hash is a correct
Tier-1 optional and the RunManifest <-> RunManifestRead read-mirror both carry it.

Resolved: ledger refreshed (C24 Status — the cycle-0092 run-from-blueprint
realization + the topology_hash #158 anchor landing; #158 reframed from "premature"
to "field landed, full reproduction remains"). Drift filed forward: #167
(single-source the stage1-r suffix-remapping lockstep — debt-med), and a scope note
on #158 (the hash currently covers the signal only; a structural-variant content-id
is the #158/#166 concern). The spec's illustrative instrument:"GER40" example
(note-low) is moot — the ephemeral spec is removed here.

Ephemeral 0092 spec + 0092/0092b plans git-rm'd per the lifecycle convention.

closes #165
2026-06-30 22:45:01 +02:00
Brummel df228986c4 docs(ledger): C24 enforcement shift — invariant 9 moves from structural to resolver-seam
A cycle-0091 design analysis (adversarially verified) of "does invariant 9
survive lifting blueprints onto the data plane?" records a load-bearing finding
in the C24 entry.

Pre-C24 a blueprint referencing another project's node was a compile error
(topology was in-process Rust — structurally impossible). Post-C24 it is a
type-id string refused only by the injected resolver's closed set
(UnknownNodeType). The anti-NIH rationale survives (logic stays cargo+Gitea-only;
the format distributes topology-as-content, never logic, C17) and std_vocabulary
stays a compiled-in dispatch table, not a registry — but enforcement of the
engine/project boundary degrades from compiler-guaranteed to resolver-seam
discipline. Two consequences recorded: #160 becomes the data-plane face of that
boundary (no longer droppable; its own drift still fails safe), and the injected
per-project resolver is the genuinely new, deferred invariant-9 surface (a
project can express a marketplace one layer above the engine contract) — a
World/C21-layer charter point. Invariant 8 (frozen) is reframed alongside:
runtime topology generation (research plane) + frozen deploy artifact +
deterministic-once-instantiated (C1).

refs #160
2026-06-30 17:27:11 +02:00
Brummel b8b83cf1c9 feat(0091): byte-canonical blueprint emit; record the equality-surface decision
#164 — tighten the C24 "canonical, versioned" blueprint contract on two corners
the milestone fieldtest surfaced. Both forks were derivable; resolved with
rationale (recorded on #164).

Fork 1 — canonical artifact carries no trailing newline. `blueprint_to_json`
returns the JSON value with no trailing newline (647 bytes for the SMA-cross
fixture); `aura graph build` had framed it with a `println!` (648). The library
serializer is the single canonical source — the form content-addressed topology
identity (#158) hashes — so the CLI is a transport that must not mutate the
bytes: `build_cmd` now `print!`s the canonical bytes verbatim, making the CLI and
library emit paths byte-identical. RED-first: the new E2E
`graph_build_emit_is_byte_canonical_no_trailing_newline` pinned the trailing
newline (FAIL), green after the one-line change. The two cycle-0088 `.out.json`
goldens are re-recorded at 647 bytes. The loader stays lenient (a trailing
newline on input still parses, Tier-1 robustness; the milestone fieldtest's
`mt_4` tolerance check is unaffected).

Fork 2 — the canonical JSON is the blueprint equality/identity surface; no
second in-memory PartialEq/Debug is added. `Composite`/`BlueprintNode` cannot
derive them: `PrimitiveBuilder` (aura-core node.rs) holds a
`build: Box<dyn Fn(&[Cell]) -> Box<dyn Node>>` closure, neither comparable nor
printable. Equality could only be defined over the serialized data, of which
`blueprint_to_json` is already the single source; a separate in-memory equality
notion would be a redundant second source of truth and a drift hazard against
the form #158 hashes. Recorded the decision (discharges acceptance box 2's "or
JSON-string is the intended equality surface" arm) in the C24 ledger; no code
added for it.

Verified: cargo test --workspace green (51 suites, incl. the new RED->green E2E);
cargo clippy --workspace --all-targets -D warnings clean.

closes #164
2026-06-30 15:57:15 +02:00
Brummel 8bb21b1c16 docs(0088): document op-script grammar; refresh stale cycle-0088 example corpus
#163 — the construction op-script (`aura graph build`) had no durable public
schema doc, and the only worked-example corpus had drifted out of sync with the
current binary, so a consumer copying the visible example was misled.

Grammar reference (durable): a compact op-script grammar — the six verbs
(source/input/add/feed/connect/expose), their keys, the typed-Scalar bind form
({"I64":2}) and the capitalized ScalarKind, the by-identifier / dotted-port
model, and the add-`name` vs expose-`as` distinction — added to the C24 ledger
entry, with a correct worked-example pointer. Surfacing the same grammar in
`aura graph build --help` is left to ride with the CLI-discoverability work
(#159), keeping this change decoupled from the deferred World/project-as-crate
layer.

Corpus refresh: the cycle-0088 fixture corpus replayed against the current
binary failed on two accumulated drifts. (1) `add`'s naming key was renamed
`as` -> `name` (3c4b667; `expose` keeps `as` as a real alias) — the inputs now
use `name` for `add` ops only. (2) The dataflow-cycle bug the 0088 fieldtest
found was fixed (1652042, closes #161), so `c0088_3m_two_cycle` is now a
rejection fixture: the gap-era cyclic-blueprint golden is removed and
`c0088_3m.err` carries the eager cycle-rejection message. FINDINGS.md gets a
dated refresh stamp; its findings are preserved as written at fieldtest time.

Verified: the four golden-bearing success fixtures (_1, _2_completed,
_2_partial via --unwired) reproduce byte-identically; all 15 error fixtures
produce the intended by-identifier `op N (kind): cause` (or finalize) message.
Doc + fixtures only, no engine/CLI code touched.

closes #163
2026-06-30 15:45:23 +02:00
Brummel 3f75d59598 audit(0090): cycle + C24 milestone close — fieldtest green; ledger + rm ephemeral spec/plan
Closes the cycle-0090 (#156) work and delivers the "Topology-as-data:
blueprint serialization & loader (C24)" milestone.

Cycle-0090 audit (architect drift review, range 7ad7f58..HEAD): drift-clean
on substance. Tier-1 forward-tolerance is genuinely serde-default
(deny_unknown_fields = 0 in every production struct), pinned at envelope +
primitive across both the in-crate and public-seam tests; Tier-2 refusals
real and green; no struct/signature/runtime change; the invariant-5
acyclicity lockstep (construction gate <-> bootstrap Kahn sort) undisturbed;
invariant-9 resolver stays injected, no registry. The one medium item the
architect flagged — the C24 Remaining block carried no deferral signal for
#158/#159 — is fixed in this commit's ledger update.

Milestone fieldtest (fieldtests/milestone-topology-as-data/, the close-gate
evidence): GREEN, 0 behavioural bugs. A downstream consumer ran the full
author -> serialize -> load -> construct -> introspect -> reproduce story from
the public surface alone — round-trip bit-exact on both authoring surfaces
(Rust builder + op-script CLI), build-free introspection, Tier-1/Tier-2
forward-compat by name, fail-fast diagnostics by identifier. Verified the
headline claims myself (the two Rust binaries + the CLI build/diff + the
fail-fast exits), not just the agent's report.

Findings triaged to the forward queue (none blocking): op-script grammar
undocumented + a stale cycle-0088 example (#163); canonical trailing-newline
divergence + Composite Debug/PartialEq ergonomics (#164); CLI discoverability
of build/introspect + no `graph run` (commented on #159); the newline as a
content-addressing prerequisite (commented on #158).

#158 (content-address topology in the manifest) and #159 (retire the
hard-wired harnesses) were moved OUT of this milestone: both are premature
until the World generates runs from blueprint-data (commit still fully
identifies every hard-wired topology), so they belong to the
project-as-crate / World cycle. The C24 ledger Status records the delivery
and the deferral.

Ephemeral cycle-0090 spec + plan removed per the lifecycle convention.
The Gitea milestone container is closed on user ratification (this run
tees up the close, does not click it).
2026-06-30 14:43:28 +02:00
Brummel cdd2da6337 feat(0090): blueprint format forward-compat — Tier-1 tolerance pinned, two-tier discipline codified (closes #156)
The blueprint data format (C24) extends additively under one codified
two-tier discipline:
- Tier-1 (additive-optional): a new optional field/section is tolerated by an
  older reader (serde ignores unknown fields — no deny_unknown_fields), with no
  format_version bump; by C1 a new optional field defaults to prior behaviour,
  so an old blueprint reproduces the same graph.
- Tier-2 (must-understand: a new node type, edge semantics, or structural-axis
  kind): bumps format_version, so an old reader refuses cleanly
  (LoadError::UnsupportedVersion / UnknownNodeType) rather than silently
  building a different graph.

Most of #156 already shipped with #155 (cycle 0087): the envelope, omit-defaults
canonical form, and both Tier-2 load-path refusals were present and green. This
cycle pins the one previously-unproven property — Tier-1 forward-tolerance of an
unknown optional field on the current loader — and codifies the discipline.

Changes:
- New characterization pin (in-crate, blueprint_serde.rs):
  unknown_optional_field_is_tolerated_byte_identically — an unknown optional key
  at doc and primitive level loads byte-identically and runs bit-identically.
- Two public-seam E2E pins (blueprint_serde_e2e.rs, added by the E2E phase):
  unknown_envelope_field_tolerated_through_public_api and
  unknown_primitive_field_tolerated_through_public_api — split the two distinct
  tolerance surfaces (envelope vs primitive) across the World/cdylib crate
  boundary, where a deny_unknown_fields added to one would break forward-compat
  while leaving the in-crate test green.
- LoadError::UnsupportedVersion doc reworded from the deferred "is #156" note to
  the settled two-tier discipline statement.
- C24 ledger (docs/design/INDEX.md): Status codification sentence added; #156
  dropped from Remaining (#158/#159 stay).

Derived fork (recorded on #156): the per-section required-flag mechanism (PNG
critical-vs-ancillary) is NOT built — the version envelope already gives the
must-understand refusal at version granularity, no current Tier-2 section
validates a finer scheme, and C1 holds either way.

The pin is a characterization test (GREEN on first run) — it documents existing
serde silent-ignore behaviour, no production code changed. Verified: cargo test
-p aura-engine green (all targets, three new tests confirmed by name); cargo
clippy --workspace --all-targets -- -D warnings clean.
2026-06-30 13:28:25 +02:00