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
The two legacy pip-scored demos — the SMA-cross (`sma`/`Strategy::SmaCross`) and
momentum (`momentum`/`Strategy::Momentum`) — and the whole built-in *synthetic*
run/sweep/walkforward/mc + `macd` surface they anchored are dropped, not
migrated: both terminated in a `SimBroker(pip_size)` construction-arg node
absent from the zero-arg std vocabulary and reported the legacy pip yardstick
C10 retired with the realistic broker. With the R-family already migrated to
data (cuts 1-3) the `Strategy` enum held only these two, so the retirement
collapses the entire built-in-strategy machinery: `Strategy`, `HarnessKind`,
`strategy_from`, `run_sweep`/`sweep_family`/`momentum_*`,
`run_sample*`/`sample_*`/`sma_cross`, the built-in
`walkforward_family`/`sweep_over`/`run_oos` and `run_mc`/`mc_family`, the `macd`
composite cluster, and `run_dispatch`/`run_args_from`/`RunCmd.--harness`.
The generic surfaces survive untouched: `aura run <bp.json>`,
`aura sweep <bp.json> --axis`, `aura walkforward|mc --strategy r-sma --real`,
`aura campaign`, `aura generalize`. Grammar consequence (derived forks logged on
#159): `run`/`sweep` now require an explicit blueprint (no synthetic default);
`sma`/`momentum` join the retired r-breakout/r-meanrev tokens in the generic
`Usage:` error, pinned by a new negative
(`sweep_and_walkforward_reject_retired_pip_tokens_as_unrecognized`); bare
`aura graph` renders the shipped `examples/r_sma_open.json` (loaded via
`blueprint_from_json`), and the render self-containment test with it; the
`sample-model.json` viewer corpus + its two `.mjs` tests stay frozen as static
test data.
`member_key`/`MAX_KEY`/`fnv1a64` were removed too. The plan wrongly listed
`member_key` as a survivor; after the built-in sweep/mc retire it has no
production caller (campaign_run derives its own content key), so it and its unit
tests are genuinely dead. The spec-compliance gate surfaced this plan-deviation;
it was ratified after verifying the tree stays green.
Verified: `cargo build --workspace`, `cargo test --workspace` (0 failed), and
`cargo clippy --workspace --all-targets -- -D warnings` all clean.
refs #159
Cut 3 of the hard-wired demo retirement. Unlike r-sma/r-breakout, r-meanrev could
not round-trip as data: its band computes band_k*sigma (a constant times a stream)
and the closed 22-node std_vocabulary had no way to express it (EqConst is i64->bool,
Bias is clamp(signal/scale,±1), Mul is binary, LinComb is excluded as a
construction-arg node; no Div/Const/constant-emitter). Standard operators are missing
by chance, not by design, so this adds the one r-meanrev needs.
Scale node (aura-std): out = input * factor — one f64 input, one f64 `factor` param,
stateless, warm-up-filtered (the EqConst/Bias shape). A zero-input `Const` emitter was
rejected: the per-cycle eval loop gates every node through an input-firing test
(harness.rs `fires()`), so a node with no input never fires without an engine-core
change; `Scale` fits the existing model and, by IEEE-754 commutativity, reproduces the
retiring LinComb's band byte-for-byte. Rostered (`"Scale" => Scale`); the two
vocabulary count-pins bump 22 -> 23.
r-meanrev migration: r_meanrev_signal(window, band_k) is carved out of the fused
r_meanrev_graph as a #[cfg(test)] price->bias Composite whose band is `Scale` in place
of `LinComb(1)`; production loads the shipped JSON (examples/r_meanrev{,_open}.json),
never a builder. Before the fused builder was deleted, an equivalence test proved the
carved Scale-band signal reproduces its grade byte-for-byte on the synthetic stream
(window=3, band_k=2). Durable survivors: the byte-identity of the examples to the
carve, the loaded-grades-identically-to-carve proof, the closed/open introspect
anchors (mean_window.length, var_window.length, band.factor — band_k is now a
first-class sweepable param), and — re-pointed onto the carve rather than dropped —
the fades-short-above/long-below behavioural test, which becomes the durable
carve-correctness gate the deleted equivalence test used to be.
Deletions + the dead-code cascade the retirement opened: r_meanrev_graph,
r_meanrev_sweep_family, Strategy::RMeanRev (+ all arms). r-meanrev was the last reader
of run_sweep's grid, so the whole vestigial built-in-sweep grid apparatus retires with
it: run_sweep's `grid` param, the sweep call-site grid build, and SweepCmd's
--fast/--slow/--stop-length/--stop-k/--window/--band-k (sma/momentum sweeps build their
own blueprints and ignored these; the fast/slow/stop-* had been vestigial since r-sma's
cut 1b). RGrid the struct SURVIVES — the dissolved `generalize` verb resolves its
candidate from its fast/slow/stop_length/stop_k via generalize_args_from — so only its
window/band_k fields go; its stale doc-comment (r-sma-sweep / persist_traces_r / CLI
flags, all now gone) is rewritten to its true generalize-only role. Also retired as
transitively dead: persist_traces_r and the metrics_object test helper (their only
callers were the deleted families/tests); Add/Gt/Latch/Mul/Sqrt imports are now
#[cfg(test)] (their last production caller was r_meanrev_graph).
Test surface: the two built-in --strategy r-meanrev sweep tests drop; a new negative
pins that --strategy r-meanrev on both sweep and walkforward now falls into the generic
usage error; the grid-flag stray-positional negative is re-pointed to a surviving flag.
Verification (own, not the workflow's report): full `cargo test --workspace` green
(0 failed across 62 result lines); `cargo clippy --workspace --all-targets -- -D
warnings` clean, no dead-code residue; the r-sma + r-breakout anchors and the
dissolved-verb real goldens (generalize still reads RGrid) stay green. Bundled as one
commit (the Scale node's count-pin and the r-meanrev anchors share graph_construct.rs,
so a clean two-commit split was not path-separable); the implement-loop ran all three
plan tasks in one pass and the tree was verified by hand.
refs #159
Cut 2 of the hard-wired demo retirement, applying the r-sma template one level
down. The r-breakout signal leg was fused into r_breakout_graph (which also built
the whole pip/R harness inline), so this cut first carves the signal leg out as a
pure price->bias Composite, ships it as a proven blueprint example, then deletes
the fused builder and the built-in --strategy r-breakout surface. The r-breakout
topology now exists only as data (crates/aura-cli/examples/r_breakout{,_open}.json).
Carved: r_breakout_signal(channel) -> Composite, a verbatim lift of the fused
builder's signal leg (Delay/RollingMax/RollingMin/Gt/Latch/Sub) exposing the raw
exposure as "bias"; the generic wrap_r/run_signal_r path (unchanged) supplies the
pip/R harness. It is #[cfg(test)] — its only role is regenerating the examples and
pinning them to a faithful serialisation; production loads the shipped JSON, never
this builder (so no dead-code residue, no production topology constructor — #159's
invariant).
Proof: before the fused builder was deleted, an equivalence test proved the carved
signal, wrapped and run, reproduces the retiring r_breakout_graph grade byte-for-byte
on the synthetic stream at channel=3 with the shared default R-stop (metric
computation is identical on both paths). That gate is deleted with the builder it
references; the durable anchors that survive are the byte-identity of the shipped
examples to the carve, the loaded-example-grades-identically-to-the-carve proof, and
the closed-ness / open-axis introspect anchors (channel_hi.length, channel_lo.length
per-node — ganging is the separate #61).
Deleted: r_breakout_graph, r_breakout_sweep_family (aura sweep --strategy r-breakout),
Strategy::RBreakout + all four match arms, the r-breakout token from the --strategy
usage strings and docs, and the now-dead --channel flag + RGrid.channel field (its
sole reader was r_breakout_sweep_family). The data successors: aura run
examples/r_breakout.json, and aura sweep examples/r_breakout_open.json --axis
channel_hi.length --axis channel_lo.length.
Test surface: the three built-in-surface sweep tests drop; the walkforward
valid-but-unsupported-token test is re-pointed to momentum (the property is generic
and stays live until Cut 4); and a new negative pins that --strategy r-breakout on
both sweep and walkforward now falls into the generic usage error, not a
special-cased message — catching a half-finished retirement that left the token
parseable.
Verification (own, not the workflow's report): full `cargo test --workspace` green
(0 failed across every binary); `cargo clippy --workspace --all-targets -- -D warnings`
clean, no dead-code residue; the r-sma introspect + grade anchors and the
dissolved-verb real goldens stay green. The implement-loop ran both plan tasks in one
pass (task_range was not honoured); the tree was verified by hand — grep-confirmed the
retired surface is gone and the carve is #[cfg(test)]-scoped.
refs #159
Cut 1b of the hard-wired demo retirement — the removal half. With the proven
example shipped in cut 1, delete the r-sma builder and its whole transitive
closure so no production function constructs the r-sma topology any more; it
exists only as data (crates/aura-cli/examples/r_sma{,_open}.json).
Deleted: sma_signal (the builder), r_sma_graph, run_r_sma (aura run --harness
r-sma), r_sma_sweep_family (aura sweep --strategy r-sma), the synthetic inline
r-sma walkforward/mc machinery (r_sma_space/r_sma_sweep_over/run_oos_r/
run_mc_r_bootstrap/mc_r_bootstrap_report + the walkforward_family RSma arm), both
fixture emitters, the round-trip + cut-1 byte-fidelity tests, the R_SMA_FAST/
SLOW/BIAS_SCALE consts, and the Strategy::RSma / HarnessKind::RSma / McArgs::RealR
variants. The three dissolved-verb synth sites (generalize/walkforward/mc
--strategy r-sma --real) now embed the shipped open example via include_str!
instead of building it — byte-safe, guarded by the unchanged dissolved-verb
real-archive goldens. The two now-redundant fixtures move to the examples
(deleted, ~40 readers repointed). The --cost-* flags on `aura run` retire with
the harness (their sole consumer was run_r_sma; cost-model coverage survives
engine/std/composites-level).
The retired demo surfaces (--harness r-sma, sweep/walkforward/mc --strategy r-sma
inline) have working data successors: aura run examples/r_sma.json, aura sweep
examples/r_sma_open.json --axis …, and the --strategy r-sma --real campaign path.
Deviation from the plan, noted: StopArm collapsed to StopRule in wrap_r's
signature (its only other variant, Open, died with r_sma_graph) — cleaner than
the planned vestigial single-variant enum; behaviour-preserving, touching
campaign_run.rs and the r-breakout/r-meanrev call sites.
Follow-up (not this cut): wrap_r's cost-node-building branch is now unreachable
(nothing passes Some(CostConfig) after run_r_sma's deletion) yet clippy-clean —
a latent cleanup for when the inline cost surface fully retires.
The stage1-r param-suffix remapping (r_sma_friendly_name + the FAST/SLOW/
STOP_LENGTH/STOP_K_SUFFIX consts) went dead and was removed, closing #167 by
deletion.
Verification (own, not the workflow's report): full `cargo test --workspace`
green; `cargo clippy --workspace --all-targets -- -D warnings` clean, no
dead-code residue; the cut-1 grade anchor (shipped_r_sma_example_reproduces_the_
builtin_grade) and the dissolved-verb real goldens (generalize/walkforward/mc
_dissolves_through_the_campaign_path) stay byte-identical. A first workflow
attempt was discarded after a subagent's `git checkout -- main.rs` recovery
silently reverted earlier tasks' edits (filed on the plugin tracker as
Brummel/Skills#23); this landing is the hardened re-run, verified by hand.
closes#167
refs #159
Cut 1 of the hard-wired demo retirement — the copy+prove phase. The r-sma demo
strategy now ships as runnable blueprint data under crates/aura-cli/examples/
(r_sma.json closed 2/4, r_sma_open.json open), emitted from the current builder
so it is byte-for-byte the builder's serialization.
Two load-bearing proofs, captured while the builder is still alive:
- byte-fidelity: the shipped examples equal blueprint_to_json(&sma_signal(..)) —
the "the copy is identical to the original" evidence the retirement method
requires before any original is removed;
- grade anchor: `aura run examples/r_sma.json` reproduces the built-in
`--harness r-sma` metrics byte-for-byte (expectancy_r/sqn/total_pips/n_trades).
Plus two property tests on the shipped copies (beyond the plan, kept as on-topic
proof strengthening): the closed example introspects to zero unbound params
(genuinely closed), and the open example lists exactly its two SMA-length axes
from the public gallery location.
Purely additive: the builder (sma_signal) and every inline r-sma surface are
retained. The recon showed deleting the builder has a large transitive closure
(the synthetic inline surface, the Strategy::RSma enum, ~40 integration tests);
that removal is cut 1b, a separate cycle, made safe by the byte-fidelity proof
frozen here.
Full workspace suite green; clippy -D warnings clean.
refs #159
The spec/plan lifecycle is a fixed plugin convention (skills/docs/conventions.md, sections File layout + Lifecycle). Restating it here is a drift vector: it had already gone stale (said git-tracked while the plugin moved to git-ignored on Jul 2). Remove the restated paragraph and enforce the git-ignored model with a project-local docs/.gitignore.
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
Milestone-close fieldtest for "Verb dissolution" (#210), authored from the
public interface only. Three end-to-end scenarios over the real GER40/USDJPY
2025 archive:
1. all four dissolved verbs on the r-sma real path (sweep via blueprint;
generalize/walkforward/mc via --strategy) — correct + deterministic;
2. reach-through — `aura generalize` auto-registers a campaign+process
document and `aura campaign run <id>` reproduces worst_case byte-for-byte;
3. a hand-authored 2-instrument × 2-window × 2-regime matrix (8 cells → 4
generalizations) no verb can express — regimes compared, never argmax'd.
Result: 0 bugs; the core promise holds empirically (behaviour preservation,
campaign-substrate reach-through, and the risk-regime axis all confirmed).
Residual findings are discoverability/ergonomics follow-ups, filed as #216
(risk-axis discoverability), #217 (verb knob asymmetry), #218 (no-project
store litter). The friction-and-bug spec stays a git-ignored working file.
The FOURTH and LAST verb dissolution is closed. Architect drift review
over 18060cb..7f5f576: all design contracts hold, debt only.
What holds (architect-confirmed by reading the diff):
- Pure sugar: only crates/aura-cli/ changed; aura-campaign/aura-engine/
aura-research are byte-for-byte diff-free — invariant 10 (no
verb-special engine logic) and invariant 12 (the World runs it through
the one campaign path) both hold.
- The seed decision is C10/C18-sound: campaign.seed = the mc --seed is a
content-addressed manifest field (reproducible-from-manifest), and the
wf winners are argmax hence seed-independent — the pooled OOS series is
unchanged, only the bootstrap draw moves. Pinned by the dedicated e2e.
- Fork A / Fork C faithful: single RiskRegime::Vol, multi-value stop
refused (aligns with the C20 regimes-are-compared realization);
--name/--trace rejection mirrors the inline r-path; defaults match
McArgs::RealR exactly; zero deletions (run_mc_r_bootstrap / run_mc
retained for the fenced synthetic/non-real paths, until #159).
Regression gate (verified by the orchestrator, not the agent report):
full workspace suite green (0 failed), clippy --all-targets -D warnings
clean, and the byte-identity anchor mc_r_bootstrap_real_e2e ran the real
GER40 archive (6.83s, no skip) and passed byte-for-byte — the
equivalence gate is green.
Deferred debt, tracked, carry-on:
- #214 (arg-bundle consolidation): the fourth stacking of
too_many_arguments/type_complexity across the Generated*/translate_*/
*_args_from families. Deliberately deferred until all four verbs
dissolved; now unblocked — the recommended next iteration.
Ephemera removed at close (per the spec/plan lifecycle): the mc spec +
plan, plus a stray cycle-0110 fieldtest spec
(docs/specs/fieldtest-sweep-dissolution.md, added 36fbf49) that outlived
its cycle and was missed by the intervening closes.
refs #210
The FOURTH and LAST verb dissolution. `aura mc --strategy r-sma --real`
now runs as thin sugar over the one campaign executor: a generated,
content-addressed [std::sweep(argmax), std::walk_forward, std::monte_carlo]
campaign document whose terminal monte_carlo stage produces the same
StageBootstrap::PooledOos(RBootstrap). The sugar reads it from
run.outcome.record.cells[].stages[].bootstrap and reprints the existing
mc_r_bootstrap_json — one line, byte-identical to the inline path.
Pure sugar, NO executor change (aura-campaign/aura-engine/aura-research
diff-free). Mirrors the shipped walkforward dissolution:
- verb_sugar.rs: GeneratedMc, translate_mc, register_generated_mc,
run_mc_sugar (record-read + one grade line, no member lines).
- main.rs: mc_args_from + the dispatch_mc built-in-arm split gated on
`--strategy r-sma && --real`.
The one new load-bearing decision is the seed mapping: translate_mc sets
campaign.seed = the mc --seed. The wf winners are argmax hence
deflation-seed-independent (proven by the shipped walkforward anchor), so
the pooled OOS series is unchanged while the terminal r_bootstrap at that
seed reproduces the inline bootstrap. A new e2e
(mc_dissolved_seed_changes_the_bootstrap_draw_not_the_pooled_series)
pins exactly this: two --seed values yield identical n_trades but a moved
E[R] mean.
Fork C retention (as walkforward): the arm splits, run_mc_r_bootstrap /
run_mc stay inline for the fenced synthetic/non-real paths (until #159).
The three synthetic-r-sma tests use no --real, so they never enter the
sugar branch and run the inline path unchanged. --name/--trace are
rejected on the sugar path, matching the inline mc r-path.
Verification: the committed byte-identity anchor
mc_r_bootstrap_real_e2e_pins_the_exact_current_grade runs the real GER40
archive and passes byte-for-byte through the new path; full workspace
suite green; clippy --all-targets -D warnings clean.
refs #210
The FOURTH and LAST verb dissolution. `aura mc --strategy r-sma --real`
dissolves into thin sugar over the one campaign executor — a generated
[std::sweep(argmax), std::walk_forward, std::monte_carlo] campaign
document whose terminal monte_carlo stage reproduces the current
`mc_r_bootstrap` grade byte-for-byte (the committed anchor 3fc491a gates
it). Pure sugar, no executor change; mirrors the walkforward dissolution.
The one new load-bearing decision is the seed mapping: the campaign
carries the mc `--seed` (the wf winners are argmax hence
deflation-seed-independent, proven by the shipped walkforward anchor).
Fork C retention as walkforward: the built-in arm splits, run_mc_r_bootstrap
/ run_mc stay inline for the fenced synthetic/non-real paths (until #159).
Spec grounding-check PASS, auto-signed on #210 (2026-07-06).
refs #210
The fourth and last verb dissolution (mc's R-bootstrap path) reroutes the inline
`walkforward_family -> pooled_oos_trade_rs -> r_bootstrap` through the campaign
`[std::sweep(argmax), std::walk_forward, std::monte_carlo]` process, whose terminal
monte_carlo stage does the identical `StageBootstrap::PooledOos(r_bootstrap(...))`
seeded from the campaign seed. Before that rewire, this pins the EXACT current
bootstrap grade of a fixed 2025 GER40 invocation (block_len=5, resamples=1000,
seed=42, multi-point fast 3,5 x slow 12,20 grid) so the dissolution must reproduce
it byte-for-byte (the acceptance gate).
The load-bearing subtlety the dissolution rests on: the campaign path uses ONE
campaign seed for both the wf-stage deflation and the mc-stage bootstrap, whereas
the inline path uses a fixed DEFLATION_SEED for the wf winners and the mc `--seed`
for the bootstrap. This reconciles because the wf winners are argmax (deflation
only annotates provenance), so they are seed-independent — the walkforward anchor
already proved it (the campaign path at seed 0 reproduced the inline
DEFLATION_SEED winners byte-for-byte). So `campaign.seed = mc --seed` leaves the
pooled OOS series unchanged and makes the bootstrap match. n_trades=20681 matches
the walkforward multi-grid anchor, confirming mc pools the same OOS-R series.
Deterministic; gated on the local GER40 archive, skips cleanly on a data refusal.
refs #210
Cycle 3 of the verb-dissolution milestone (96dc783..a047af6). Architect drift
review over the range returned clean.
What holds:
- Pure sugar confirmed: `git diff 3a03617..a047af6 -- crates/aura-campaign
crates/aura-engine crates/aura-research` is EMPTY. All walkforward-specific
logic is confined to aura-cli. Invariant 10 (no verb-special engine logic) and
invariant 12 (one campaign path, via run_campaign_returning) preserved.
- No new campaign vocabulary: reuses StageBlock::WalkForward / WfMode::Rolling /
RiskRegime::Vol — the #160 3-copy vocab guard needs no update. C18:
content-addressed process + campaign + run recorded, e2e-verified.
- C10/C20: the stop binds as a single RiskRegime::Vol (structural, not a swept
param axis), consistent with the prior risk-regime cycle; Fork A refuses a
multi-value stop rather than silently re-semanticizing it.
- The two documented inline deviations are sound: full_window == wf_full_span on
the Real arm (both delegate to probe_window); raw_matches_wrapped correctly
matches wrapped fast/slow and the unwrapped stop.
Deferred debt (all [low], tracked, carry-on):
- Fork A narrows the surface: the inline path swept the stop as an IS-refit grid
axis (RGrid.stop_* are Vec); the dissolved path refuses a multi-value stop. The
byte-anchor covers the single-stop grade — "byte-for-byte" is scoped, not total.
Design-ratified on #210 (Fork A / the risk-regime model: the stop defines R and
is compared, never argmax-swept).
- The reducer's .expect()/unreachable! on report shape mirrors the inline
reducer's posture; anchor-guarded for today.
- The #214 arg-bundle is now at its third instance (rule-of-three trip point);
deferral to after the mc dissolution is deliberate (noted on #214).
Full workspace suite green; clippy --all-targets -D warnings clean; the
equivalence anchor walkforward_real_e2e_pins_the_exact_current_grade green through
the dissolution. Spec + plan removed (git rm) per the cycle lifecycle.
refs #210
The dispatch split lands: `dispatch_walkforward`'s built-in arm now routes
`--strategy r-sma --real` through the one campaign path (`run_walkforward_sugar`
-> generated campaign doc -> executor -> summary reprint), reproducing the
`{"walkforward":{…}}` line byte-for-byte. Everything else — synthetic (any
strategy) and non-r-sma real — stays on the inline `run_walkforward`, fenced
until #159 (Reading A). The committed anchor
`walkforward_real_e2e_pins_the_exact_current_grade` passes: the dissolved path
reproduces windows=9, stitched_total_pips, oos_r, and the param_stability means
exactly. `--select plateau:*` is refused (exit 2 -> #215, Fork B); a multi-value
stop is refused (Fork A).
Two plan guesses were wrong and the anchor + real-data e2e caught both; the fixes
are documented inline:
- Window resolution: the plan mirrored generalize's `(--from,--to) -> (f,t)`
shortcut, but the inline `wf_full_span` ALWAYS clips `--from`/`--to` to the
archive's actual first/last bar (`probe_window`), even when both flags are
explicit — a holiday/weekend edge shifts every IS/OOS window's calendar
placement (stitched_total_pips diverged by ~5.16M, param_stability means intact,
confirming only window boundaries moved). The dissolved path now calls
`source.full_window(env)` unconditionally, matching the inline behaviour;
verified byte-for-byte against the still-fenced inline path.
- Reducer axis match: the campaign path records the blueprint axes wrapped
(`sma_signal.fast.length`) while the stop rides unwrapped via the risk regime, so
the reducer's exact-name match panicked on real data. Fixed with the existing
`campaign_run::raw_matches_wrapped` (#203) wrap-convention helper.
Tests: the dissolution-proof e2e `walkforward_dissolves_through_the_campaign_path`
(one process + one campaign + one campaign-run auto-registered, windows=9) plus
front-end refusal coverage (multi-value stop, `--select plateau`, missing knobs,
empty `--real`, unknown `--select`, `--name`/`--trace` exclusivity). Full workspace
suite green; `clippy --all-targets -D warnings` clean.
refs #210
The additive machinery for the walkforward dissolution, unwired this slice
(dispatch_walkforward untouched — `aura walkforward` behaviour byte-for-byte
unchanged). Two pieces, both mirroring the generalize seam:
- `translate_walkforward` + `register_generated_wf` + `GeneratedWalkforward`
(verb_sugar.rs): argv -> a `[std::sweep(argmax), std::walk_forward]` process +
a campaign carrying the multi-value fast/slow IS-refit grid over one instrument
under a single Vol risk regime (the stop). The preceding sweep enumerates the
survivor grid; the wf stage refits it per window.
- `walkforward_summary_json_from_reports` (main.rs): the pure-sugar reducer that
reconstructs the verb's summary line from the campaign's recorded per-window OOS
reports — `stitched_total_pips` = the per-window total_pips summed in roll order,
`param_stability` over the four r-sma axes via the same `MetricStats::from_values`,
pooled `oos_r` via `r_metrics_from_rs`. Byte-identical to the inline
`walkforward_summary_json` (the committed anchor gates it once Task 3 wires it).
Both carry `#[allow(dead_code)]` until Task 3's dispatch split calls them.
The third `Generated*`/`register_generated_*` trio duplicates the sweep/generalize
shape by design (per-verb mirror); the bundle consolidation is deferred to #214.
Unit test note: `r_metrics_from_rs` clears `trade_rs` (it is the terminal pooled
reducer), so the reducer's characterization fixture rebuilds each window's
`RMetrics` with `trade_rs` restored, modelling what a real OOS window's report
carries (from `summarize_r`).
refs #210
Third verb dissolution: route `aura walkforward --strategy r-sma --real`
through the one campaign path as thin sugar, reproducing the summary line
byte-for-byte. Key finding (verified): this is PURE SUGAR — no executor
change — because the campaign walk_forward stage's per-window OOS reports
carry everything the summary needs (stitched_total_pips == the per-window
total_pips summed in roll order; pooled oos_r from the reports' in-memory
trade_rs). The built-in arm SPLITS: only r-sma-real dissolves; the synthetic
and non-r-sma-real branches keep the inline run_walkforward (Reading A). The
--select plateau path is carved out to #215; the equivalence anchor 96dc783
is the acceptance gate.
refs #210
The third verb dissolution (walkforward) reroutes the inline per-window
IS-refit (`walkforward_family` -> `select_winner` -> OOS run -> stitch/pool)
through the campaign `std::walk_forward` stage. Two summary fields have no
campaign equivalent today: `stitched_total_pips` (the runner discards the raw
OOS pip curve, `oos_equity: vec![]`) and pooled `oos_r` (only a following
`std::monte_carlo` stage produces it). Before the executor work that closes
those gaps, this pins the EXACT current grade of a fixed 2025 GER40 invocation
so the dissolution must reproduce it byte-for-byte (the acceptance gate).
The grid is deliberately multi-point (fast 3,5 x slow 12,20): it makes the
per-window winner selection non-degenerate (`param_stability` varies across the
9 windows), so a winner-pick divergence between the inline and campaign refit
cannot ship green — the same gap the generalize anchor closed for its sibling
shape-only test. Deterministic (C1); gated on the local GER40 archive, skips
cleanly on a data refusal.
refs #210
Second verb dissolution (#210) closed drift-clean. Architect: no ledger drift.
What holds (architect, verified against the diff + a live test run):
- Byte-parity proven, not assumed — the exact-grade anchor runs green through
the dissolved path; {"family_id":"generalize-0"} survives (the per-cell Sweep
families take a distinct campaign-prefixed name).
- C18 stamping preserved — the member runner maps cell.regime -> StopRule::Vol
and stamps manifest.instrument; the anchor confirms regime-seam R == former
grid-axis R.
- run_campaign_returning/present_campaign split is behaviour-preserving — the
run record is written inside execute, so the sugar path (bypassing the
presenter) still records it.
- Q4 is not drift — the +2 per-instrument Sweep families are the executor's
uniform, reproducible audit artifacts (sweep-dissolution precedent,
C18-consistent); stdout unchanged; the relaxed family pin is faithful.
Regression: cargo test --workspace green (every crate 0 failed);
clippy --workspace -D warnings clean.
Drift resolution:
- [medium] no-window generalize grades over symbols[0].full_window (one shared
window) vs the inline path's per-instrument windows. RATIFIED: a single shared
window is the campaign model's natural expression, the explicit-window path
(both e2e + the exact-grade anchor) is byte-identical, and symbols[0] is a
pragmatic pick; no value pin because a full-archive grade is fragile against
archive growth. Deferred design reconsideration filed as #213.
- [low] two #[allow(too_many_arguments)] in verb_sugar.rs — carry-on; the
arg-bundling refactor is best done once the remaining verbs dissolve (#214).
Spec + plan removed at cycle close (git-tracked in this project).
refs #210
`generalize_dissolves_through_the_campaign_path` asserts the verb now runs
through the one campaign path: exactly one generated process document, one
generated campaign document (carrying the --name handle and the stop as a
non-empty risk regime), and one campaign-run record are durably auto-registered,
plus the campaign-path family set (1 CrossInstrument grade family + 2
per-instrument Sweep families). The observable proof the inline path is gone.
refs #210
`dispatch_generalize` synthesizes the bare `sma_signal` blueprint, resolves the
window (explicit --from/--to, else the first symbol's full window), and calls
the new `run_generalize_sugar`; the inline `run_generalize` is deleted. The
sugar builds the selection-bearing campaign doc, runs it through
`run_campaign_returning`, reprints the byte-identical `{"generalize":…}` +
`{"family_id":…}` lines, and persists the CrossInstrument family.
The exact-grade anchor stays green through the path shift — proving the two stop
mechanisms (former grid axis, now the risk-regime seam -> StopRule::Vol) yield
identical R. The family pin relaxes to "exactly one CrossInstrument family"
since the campaign executor now also persists a per-instrument Sweep family per
cell (the durable audit trail; #210 Q4). Two new e2e pin the window fallback and
the family member attribution order.
Deviations from the plan (necessary, verified): cross_instrument_members returns
Vec<aura_engine::RunReport> (aura_registry::RunReport is not pub); a shared
validate_before_register helper is factored out of run_sweep_sugar (DRY); the
run_generalize doc-comment and the now-unused `generalization` import removed.
refs #210
`translate_generalize` builds the selection-bearing campaign document
(`[std::sweep(argmax), std::generalize]`, a single risk regime carrying the
stop, the candidate as single-value raw axes) + `GeneratedGeneralize` +
`register_generated_g`, mirroring the sweep translator. A determinism unit test
pins identical-invocation -> identical content id and the regime/pipeline shape.
The new items are unused until the dispatch-rewire task (#210 T3) wires the
runner; a bridge `#![allow(dead_code)]` (removed in T3) mirrors the sweep
sibling's landing.
refs #210
`run_campaign_returning` runs the resolve->execute body and returns a
`CampaignRun` bundle (outcome + campaign/strategies/server); `present_campaign`
consumes it for the stdout tail; `run_campaign_by_id` becomes their composition.
Behaviour-preserving — the existing campaign + sweep-sugar e2e stay green
(research_docs 54/0 incl. the real-data e2e, sweep dissolution e2e green).
Exposes the outcome so the forthcoming generalize sugar can read it without the
presentation tail.
refs #210
Second verb dissolution: `aura generalize` becomes thin sugar over the one
campaign executor, byte-identical output, the stop carried by a single risk
regime. Spec grounding-check PASS (auto-signed) after the exact-grade anchor
(f3f32b8) closed the stop-mechanism R-parity block. Plan derives four
implementation forks (Q1 blueprint source, Q2 run-outcome bundle, Q3 window,
Q4 the campaign-path family set — user-visible), all recorded on #210.
refs #210
The current `aura generalize` binds its protective stop as a grid axis
(`r_sma_sweep_family` with `stop_open=true`); the pending generalize
dissolution rebinds the same stop through the risk-regime seam
(`RiskRegime::Vol -> StopRule::Vol`). The existing generalize e2e
(`generalize_grades_a_candidate_across_two_instruments`) asserts shape
only — `worst_case` and the per-instrument R floats are never checked —
so a divergence between the two stop bindings would ship green.
This adds `generalize_real_e2e_pins_the_exact_current_grade`, capturing
the exact current R grade of the identical invocation (GER40 0.0105637…,
USDJPY 0.0057959…, worst_case 0.0057959…, sign_agreement 2). Green today
against the inline path; after the dissolution the same command must
reproduce these bytes — the acceptance gate that catches a stop-mechanism
divergence loudly instead of silently.
Resolves the generalize-dissolution grounding block (the unpinned
stop-mechanism R equivalence) by the risk-regime characterization-pin
pattern. refs #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
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
The runtime-binding slice — the regime's stop now actually reaches the graph and
the record:
- `StopArm { Open, Bound(StopRule) }` replaces `wrap_r`'s `stop_open: bool` so a
bound stop carries its params; all call sites threaded (the r-sma sweep path
stays Open, every bound site passes the resolved rule).
- `run_blueprint_member` takes a `stop: StopRule` and stamps `stop_length` /
`stop_k` into the member manifest (the ratified C18 extension — the stop is no
longer invisible on the campaign/blueprint path); its callers thread the
default, and `CliMemberRunner` maps `cell.regime` (None -> baked default,
Some(Vol) -> that vol stop).
- The characterization pin flips from asserting the stop's ABSENCE to requiring
the stamped default; a real two-regime e2e pins that each regime stamps its
own k.
Known deferred gap (concern, documented descope): `persist_campaign_traces`
re-runs the nominee to persist its traces and — since `CellRealization` carries
no regime — binds that re-run to the DEFAULT stop, so a non-default-regime
nominee's persisted trace would reflect the wrong stop. Only the persist path
(non-empty `persist_taps`) is affected; the core run/stamp/generalize path is
correct. Filed as a follow-up. Full workspace suite green.
refs #210
The regime becomes the fourth structural coordinate of the campaign matrix, a
kept-separate axis (a peer of window, not aggregated-over like instrument):
- aura-campaign: CellSpec gains `regime` + `regime_ordinal`; the executor
resolves the regime list (absent/empty risk -> one default cell, ordinal 0),
runs a cell per (strategy, instrument, window, regime), and keys the nominee
map by the 3-tuple including the regime ordinal — so generalize aggregates
across instruments WITHIN a regime, never across regimes. Family names gain a
`-r{regime_ordinal}` discriminator so two regimes' families cannot collide.
- aura-registry: `CampaignGeneralization` gains `regime_ordinal` (with
`#[serde(default)]`, so pre-feature stored records still parse — pinned by a
new backward-compat test).
The existing single-regime execute tests shift their family ids by `-r0`; a new
test pins that two regimes yield distinct `-r0`/`-r1` families. `CellSpec.regime`
is write-only in this slice — its sole reader is the deferred member runner
(the next slice) — a held quality nit, seam-prep as the plan prescribes. Full
workspace suite green.
refs #210
The first slice of the risk-regime structural axis (spec/plan abab1f1):
- aura-research: a serializable `RiskRegime` closed vocabulary (externally
tagged, sole variant `Vol { length, k }` — a content-addressable mirror of
the shipped two-variant StopRule, so a future Fixed regime is additive), and
an optional top-level `CampaignDoc.risk: Vec<RiskRegime>` that absent-
serializes (the `description` precedent) — content-id parity for every
risk-less document.
- validate_campaign refuses a non-positive regime (length < 1 or k <= 0, NaN
included) via a new `DocFault::BadRegime`; the CLI renders it as prose at the
research_docs seam (register/validate paths).
- The three CLI-seam E2E tests pin that a well-formed risk section passes
`campaign validate` and a bad one is refused with prose (exit 1, no Debug
leak) — the field is reachable at the seam a data author drives, not only in
library units.
Adding the field is compile-breaking at every `CampaignDoc { .. }` literal
(serde default does not cover Rust construction), so this slice also threads
`risk: vec![]` into the sites across aura-cli and aura-campaign — the
field-addition's compile-gate completion the plan should have scoped here. The
BadRegime prose reads `risk[i]: ...` (the implementer's terser wording over the
plan's illustrative string; the spec pinned no exact text). Full workspace
suite green.
refs #210
Spec auto-signed on a grounding-check PASS: the risk regime becomes a
structural campaign axis (a peer of instruments/windows, kept-separate in
the executor, each member's resolved stop stamped into its manifest;
regimes are compared, never argmax-selected across — a cross-regime E[R]
argmax would mix R units, C10). The 5-task plan threads it through
aura-research (RiskRegime + CampaignDoc.risk), aura-campaign + aura-registry
(matrix expansion + regime_ordinal), and aura-cli (StopArm + wrap_r + the
manifest stamp). Two bounded, documented descopes: the descriptive
CAMPAIGN_SECTIONS introspection entry and multi-regime trace-dir isolation.
refs #210
The dissolved real-data sweep member manifest carries only the swept signal
axes today — no stop param; the R-path stop is a wrap_r constant baked outside
the signal param_space. The existing member-line pin
(sweep_real_blueprint_member_lines_pin_the_dissolved_contract) locates each
binding by `find`, so it never pinned this absence. This characterization pin
does, as the grounding ratification for the risk-regime-axis design pass: the
resolved-regime manifest stamp will flip it to require the stop key — the
ratified additive contract extension, exactly like the instrument stamp.
refs #210
Three test-first fixes from the cycle-0110 fieldtest findings:
- Axis-name preflight on the dissolved sweep arm: every --axis name is
checked against the wrapped probe namespace (the --list-axes names)
BEFORE the #203 strip; an unknown or raw-form name is refused
house-style echoing exactly what the user typed, with a --list-axes
pointer — no more stripped-then-mangled fragments from the deep
referential refusal. Data-free, fires before the archive is touched.
- Validate-before-register in the sweep sugar: intrinsic doc checks +
executor preflight + the pure bind_axes coverage check (reused, not
re-inlined; now pub(crate)) all run in-memory before
register_generated — a refused invocation leaves no generated
document in the content-addressed store and no campaign_runs.jsonl
line (previously P2/P3 refusals littered runs/campaigns, one doc
malformed).
- blueprint_slot_prose: the sweep/walkforward/mc loaded-blueprint slots
share one dispatch-boundary presenter — an op-script array gets a
targeted 'run aura graph build first' hint, every load error goes
through blueprint_load_prose + the missing-project hint, and the raw
{e:?} Debug leak (#184's pattern, deliberately left on these three
slots back then) is gone. Two stale Debug-leak pins flipped, two new
refusal tests.
Suite 1060/0, clippy -D warnings clean.
refs #210
Authoring guide §1: the inline SMA-crossover op-script no longer binds
fast/slow lengths — it is byte-identical to the corpus file it claims
to match (content id 597d719b… verified against the binary), and the
previously unwritten rule is stated: an op-script bind pins a param
OUT of the sweepable space (closed — no campaign axis or --axis can
reopen it). New passage + example distinguishing the raw param-space
namespace (--params, campaign-document axes) from the wrapped
--list-axes/--axis surface; glossary sweep entry carries the same
one-sentence distinction.
refs #210
Consumer scenario against the public surface only: selection-free
process doc round-trip, the dissolved real-data sweep (doc dedupe +
realization accumulation + C1 bit-identity), refusal edges, rank-later
over the persisted family. 0 bugs; the cycle's own axes all came back
working. 4 friction + 2 spec-gap findings on the verb entry ergonomics
and pre-existing guide drift — transcribed in
docs/specs/fieldtest-sweep-dissolution.md for triage.
refs #210
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
aura sweep <bp.json> --real ... --axis ... now runs as thin sugar over
its generated campaign document through the one campaign executor: the
dispatch registers the canonical blueprint (topology_hash IS
content_id_of over the same canonical bytes, so the strategy ref
resolves against the existing single store write), strips the CLI's
wrapped axis names to the raw campaign namespace (#203 bind
convention), converts the probed archive window back through the
ingest seam's own epoch_ns_to_unix_ms (made pub; C3 — the seam owns
the ms/ns convention, never an inline division), and hands off to
verb_sugar::run_sweep_sugar. The inline real-data arm is gone; the
synthetic arm and --list-axes are untouched.
campaign_run gains RunPresentation {Full, MemberLinesOnly}:
run_campaign keeps Full (record line unchanged, project gate
unchanged); the sugar path runs MemberLinesOnly — the generated doc's
emit already limits stdout to family_table member lines, the mode
suppresses only the final record line. The record append is identical
in both modes; no project gate on the by-id path (the dissolved verb
works project-less, exactly as before).
The characterization pin survives the re-cut with exactly the one
sanctioned assertion flip (instrument-absence -> instrument==GER40)
and now also pins the generated artifacts: one process + one campaign
document auto-registered (dedup on a second identical invocation),
raw axis keys in the stored document, the stored window a ms sub-range
of the request, C1 at the member-report level with the registry's
run-suffix increment isolated.
Suite 1055/0, clippy clean, gated real-data paths executed locally.
refs #210
The pure half of the sweep re-cut: translate_sweep maps a real-data
blueprint-sweep invocation (axes, name, symbol, window, canonical
blueprint bytes) to a selection-free single-stage process document plus
a campaign document carrying exactly the invocation's intent (seed 0 —
no stage consumes it — so identical invocations dedupe onto identical
content ids); register_generated puts both into the content-addressed
stores. Unit tests pin determinism, name flow, mixed-kind-axis refusal,
and that generated documents pass intrinsic validation + preflight.
Dead-code-allowed until the dispatch rewire wires the module (next
task removes the bridge attribute). Plan bytes reconciled with three
necessary deviations the spec gate surfaced: derive(Debug) for
unwrap_err, ScalarKind lives in aura_core, and 'gen' is reserved in
edition 2024.
refs #210
The std::sweep selection triple (metric/select/deflate) becomes ONE
optional group, Option<SweepSelection>, serde-flattened so the wire
form keeps the flat slots: every existing document parses to Some and
its canonical bytes — and content id — are unchanged (golden pin
byte-untouched). A half-populated group is refused by the schema-strict
parser (all-or-nothing); a bare {"block":"std::sweep"} is the
selection-free sweep.
Campaign side: preflight permits a selection-free sweep only as the
pipeline's terminal stage (new ExecFault::SelectionFreeSweepNotTerminal,
prose in aura-cli's exhaustive exec_fault_prose); the executor's
selection-free arm appends the family exactly as before but records no
StageSelection and produces no nominee (recording one would fabricate
intent — #210 fork decision 1).
Introspection follows: the sweep block's schema table marks the group
optional; CLI introspection pins updated. New tests: group-or-nothing
refusals, selection-free round-trip + distinct content id, terminal-only
preflight accept/refuse, selection-free execute realization.
refs #210
Cycle 1 of the verb-dissolution milestone (refs #210): the real-data
blueprint sweep re-cut as sugar over a generated, auto-registered
campaign document; optional selection group in the sweep stage
vocabulary; terminal-only preflight rule. Spec auto-signed on a
grounding-check PASS (decision log on #210); ephemeral per convention,
removed at cycle close.
Two green pins the sweep-dissolution cycle rests on (refs #210):
- sweep_real_blueprint_member_lines_pin_the_inline_contract: the inline
real-data blueprint sweep prints one member line per grid point in
odometer axis order, carries the swept bindings in manifest.params,
persists exactly one Sweep family — and never stamps an instrument
key (RunManifest::instrument stays None on this path).
- campaign_run_real_e2e_sweep_gate_walkforward (extended): every
family_table member line emitted by the real campaign member-runner
path is stamped with the instrument under test.
Together they pin the one behavioural delta between the two paths (the
additive instrument stamp) that the dissolution's parity contract is
phrased against.
Close two milestone-fieldtest doc-gaps (F6/F8) with one pass now that the
surfaces are stable. A newcomer could only learn the three headless JSON
artifact kinds from the fieldtest corpus: the op-script grammar was
undocumented (#208) and there was no worked process/campaign example nor a
pointer to the discoverable metric vocabulary (#197).
Add docs/authoring-guide.md — a worked, verified example per artifact kind
(op-script -> graph build; process document -> process validate/register;
campaign document -> campaign validate/register/run), every command run
against the binary and its output transcribed. Documents all six ops
(source/input/add/feed/connect/expose) with their JSON shapes, and teaches
the metric roster split (rankable / gate / | generalize) pointing at
'aura process introspect --metrics' as the source of truth rather than
hand-copying the rosters. A short paragraph in project-layout.md links it.
Docs only; no code or CLI change (the surfaces already suffice). Grammar
grounded on construction.rs; examples faithful to the milestone corpus.
closes#197closes#208
aura run leaked the raw LoadError Debug form (UnknownNodeType("..."))
while graph build already phrased the same fault house-style (#162
convention: engine error types are Display-free, the CLI presents them).
Route the run path through the shared blueprint_load_prose presenter (now
pub(crate), env-agnostic) so both surfaces phrase a LoadError identically
and neither leaks the Debug token (#184). Add unresolved_namespace_hint:
when the unresolved id looks project-namespaced (::) and no project was
loaded (env.provenance() is None), append a hint pointing at the missing
Aura.toml — the newcomer running the host from the wrong directory now
gets an orienting diagnosis instead of a bare type error (#185). The hint
is applied on both the run and graph-build paths. RED-first: the two
existing run-path pins were flipped to assert the prose + absence of the
Debug token before implementing; suite green (1043/0).
closes#184closes#185
DEFLATION_N_RESAMPLES (1000) and DEFLATION_BLOCK_LEN (5) were duplicated
as independent copies in aura-cli and aura-campaign — a silent-drift risk
(an edit in one crate but not the other refuses nothing, it just produces
a wrong deflation result). Promote a single definition into aura-registry,
which owns optimize_deflated (the sole consumer of these counts); aura-cli
imports it and aura-campaign re-exports it to keep its public path stable.
DEFLATION_SEED stays cli-local (no campaign twin). Values unchanged;
behaviour-preserving, suite green unchanged (1043/0).
closes#199
The research-artifacts milestone fieldtest closed GREEN and the milestone
is formally closed; per the ephemeral-artifact convention its spec is
git-rm'd at cycle close. The verdict survives durably in the tracked
corpus (fieldtests/milestone-research-artifacts/FINDINGS.md), the closed
milestone, and the ledger.
Second half of the style pin. assets/aura.css now carries (a) the full
:root token palette (Catppuccin-Mocha-derived; --bg deliberately darker
than Mocha base; new --border3 #585b70 completes the border ladder at an
identical computed value), (b) the shell rules migrated color-literal to
var() with identical computed values (font stacks stay literal — the
--mono token's longer fallback chain would change the computed value),
and (c) an opt-in, class-scoped component library distilled from the
milestone demo page (.aura-doc register, .wrap, .badge, .stats, .cards,
.term, .callout, table.res, .pipe) — unused by the runtime pages, which
render pixel-identically. CHART_CSS migrates to the same tokens (it
lands in the same document after the shell <style>, so :root resolves).
CLAUDE.md gains the binding '## HTML surfaces' rule: every HTML surface
embeds this asset; extend, never fork.
Gates: suite 1043/0, clippy -D warnings clean, doc build 0 warnings;
regenerated chart page resolves all 17 used var() names against its
:root. Independent CSS audit passed (two cosmetic notes: --bg3/--orange
currently unused; the pre-existing html,body height:100% also reaches
future .aura-doc pages).
closes#209
Pure byte-preserving extraction: the CSS block inside SHELL_HEAD moves
verbatim into crates/aura-cli/assets/aura.css and is spliced back via
concat!(.., include_str!(..), ..). Proven against a pre-change baseline:
chart HTML (aura chart 42edebd2-0/597d719b-GER40-w0) and graph HTML
(bare aura graph) regenerate sha256-identical (bcc2cc0f.., a0e6a97f..),
each deterministic across two generations. Suite 1043/0.
First half of the style pin: the asset becomes the single source the
runtime pages embed; tokens + component library follow separately.
refs #209
MILESTONE VERDICT: GREEN — the whole span (0106-0109) holds end to
end as one continuous consumer scenario: authored from a bare {} via
introspection alone, every ref resolved from the public surface, three
validation tiers, run by content id over two real instruments through
the full v2 pipeline, realization recorded (selection/survivors/
bootstrap/generalizations/trace_name), traces on disk and charted,
read back via campaign runs, byte-identical re-runs (C1), refusals
precise. 0 bugs, 0 frictions, 0 spec gaps; 2 doc-gaps.
F7 fixed in this commit (the docs claimed an archive-root path without
naming the key; a guessed [paths] archive silently no-ops): project-
layout and the glossary Aura.toml entry now name [paths] data, and the
aura new template advertises the commented-out key. F8 (op-script
grammar not CLI-discoverable) filed as #208, sibling of the #197 docs
half — one docwriter pass once desired.
The milestone-close gate evidence is this corpus; the formal milestone
close and the push remain user-reserved.
refs #189
The --unwired help line names the whole-envelope starting move (start
from a bare {}), closing the 0106-F1 discoverability gap the narrowed
issue kept open; the wrong-kind refusal names the exact key a blind
author must fix ('the "kind" key must be "process"') instead of
describing the mismatch abstractly. The third original item (block-ids
vs field names in --vocabulary) is sufficiently served by the
envelope probe per the issue's narrowing comment.
RED-first (tdd-author handoff): both pins observed failing on the old
help text / prose.
Gates: workspace 1043/0, clippy -D warnings clean.
closes#193
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