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.
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.
Per-cycle fieldtest over the #246 surface, consumer-perspective, public
interface only: the scaffold quickstart end to end (aura new -> run ->
--list-axes -> override sweep), --list-axes on a partially-open
blueprint, an override family reproduced bit-identically (3/3 members),
and the error surface (wrong axis name, kind-mismatched value — both
exit 2). Corpus under fieldtests/cycle-246-bound-override/.
Dispositions: the one bug (F6) is fixed in this commit — authoring-guide
§1 still asserted a bound param 'never shows up in --list-axes' and 'no
aura sweep --axis can reopen it', contradicting the shipped #246
semantics and the C12 amendment; the three-states paragraph now reads
open = must-bind, bound = overridable default. The friction finding (F5,
KindMismatch/MissingKnob printed as raw Debug structs beside polished
prose) is filed as #247.
refs #246
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
Task 6 of the bound-override cycle: SIGNAL_OPEN_JSON_STD and its write
retire — aura new scaffolds signal.json alone, and the project CLAUDE.md
quickstart advertises run AND sweep against that one file (the sweep line
overrides the bound fast.length; --list-axes shows open + bound axes).
The data-only e2e loop proves it end to end: scaffold, run the closed
starter, sweep it via an override axis, and assert signal.json is the
only starter blueprint. The authoring-guide's starter-pair sentence is
retargeted; the last signal_open reference outside the unrelated #196
fixture string is gone.
refs #246
Consumer-POV fieldtest evidence for the two-tier project model: the
data-only quickstart, the role-2 attach loop, real-data usage inside a
data-only project, and the refusal surfaces all match the docs.
Inline fixes for two of the friction findings:
- docs/project-layout.md: the day-in-the-life run example now shows real
Unix-ms window bounds instead of bare years (--from/--to take ms).
- `aura new` --help one-liner no longer calls the project a crate.
Remaining findings tracked on the Gitea queue (empty first-manifest
provenance on a fresh scaffold; misleading no-data message for an
uncovered --real window; the tier hint missing on the graph-build path;
the raw cargo-metadata leak for a missing [nodes] dir).
refs #241
- 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
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.
The NotFound arm of emit_chart now queries the recorded campaign runs:
records with a persisted trace_name whose stored campaign document
carries name == ARG. A unique match re-dispatches the existing charting
path onto the resolved handle; several matches refuse listing the
candidate handles in append order (refuse-don't-guess — re-running a
named invocation legitimately yields {campaign8}-0, -1, ...); zero
matches keep the not-found message verbatim. The exact trace-store
handle always wins; the name never becomes a store key (C18 untouched).
Guide §3 and the glossary tap entry document the name alternative.
closes#238
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.
- glossary "tap" + authoring-guide §3: the chart handle of a
sweep/walkforward --trace family is the printed family handle
(members keyed <cell>/<member>) — the campaign trace_name analog was
documented, the sweep case was not (fieldtest spec_gap).
- authoring-guide §0: state the input window's financial-style ordering
(index 0 = newest, index k = k cycles back) where the node pattern is
taught — previously only in the design ledger's RingBuffer note.
- authoring-guide §3: the #234 cost block joins the open-slot list, the
worked campaign example, and the prose (charge modes, net-vs-gross
default, manifest stamping) — it was discoverable only via
campaign introspect --unwired.
Fieldtest fixtures: 09da04f.
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
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
New top-level section covering the three-part shape every node type
follows — Node impl (lookbacks/eval/label with the C8 warm-up filter),
PrimitiveBuilder recipe (NodeSchema + positional build closure), and
rostering (project-side aura_project! vs std-side roster macro) — with
the aura-new Scale starter as the verbatim worked example and the five
fresh #236 nodes as arity-variant references. Cross-linked from the
op-script vocabulary note, project-layout, and the README.
closes#228
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
The #28 cycle-close audit found aura graph <file> silently rendered the embedded
sample at exit 0 when the positional named an unreadable blueprint (typo,
nonexistent path, wrong extension): is_blueprint_file returns None both for "no
positional" and for a bad arg, and dispatch_graph's None arm conflated them —
re-introducing the exact #28 "I asked for my graph, got the sample" surprise in
the error path, and diverging from every sibling verb (a bad blueprint arg is a
usage fault, exit 2, per C14). Split the None arm: no positional -> the sample
(unchanged); a positional that is not a readable .json -> a usage error naming
the arg, exit 2, mirroring dispatch_run.
Also close the paired doc drift the audit flagged: the README blueprint-verb
table and the authoring guide now document the aura graph <file> render surface,
absent while graph was the last sample-bound verb.
refs #28
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
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
refs #216
Architect drift review over 68317ec..6e22c98 (two items, both fixed here;
code and ledger verified drift-clean):
- The authoring guide's 'Register and run' transcript still showed the
pre-regime world (2 cells, regime-less family ids) directly under the
worked example this cycle made two-regime / 4-cell. The transcript now
shows the -r1 family-id suffix, per-cell regime fields (ordinal 0
serialize-skipped, the established byte-stability pattern), the four
cells, per-regime generalization entries, and a prose paragraph tying
the 4 cells to the validate count (regimes compared, never pooled).
- The fresh glossary entry declared 'Avoid: stop regime' while this very
cycle ships 'stop regimes' in its hint strings and guide prose — an
Avoid line the codebase itself violates records intent, not reality.
'stop regime' is dropped from Avoid ('risk section' stays: it wrongly
suggests a section rather than an axis list).
What holds (architect): content-id parity untouched (probe is read-only,
canonical bytes unchanged); the validate cell product mirrors the exec
cross-product exactly; all six spec acceptance criteria shipped.
Regression: cargo test --workspace 62 result groups / 0 failures; clippy
-D warnings clean; cargo doc 0 warnings (all at 6e22c98; this commit is
docs-only).
closes#216
The remaining introspection e2e pins: the bare-{} envelope probe (the
issue's exact reproduction) lists the optional risk slot; a bound
(non-empty) risk list closes it (no open slots); an EXPLICIT empty
'risk': [] still counts as open (pins the non-emptiness branch, which an
is_none()-based probe would get wrong); the --block std::risk assert is
sharpened to pin the optional rendering and the block doc line (the old
bare contains("risk") matched std::risk trivially).
Docs: the authoring guide's bare-{} transcript gains the risk line, the
§3 worked example gains a two-regime risk section (heading updated), a
prose paragraph explains the structural risk axis (stop defines R;
absent = the same default vol regime the verbs bind), and both validate
transcripts show the new matrix counts. The glossary gains the
'risk regime' entry (canonical term; avoid: stop regime, risk section).
Verified: cargo test --workspace 62 result groups / 0 failures; clippy
-D warnings clean; cargo doc 0 warnings; the guide's transcript strings
grep-match the shipped hint/summary bytes (1/2/1).
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
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
Drops docs/whitepaper/ (Bevy ECS visualizer concept). The evaluation
against the design ledger found it re-litigates the settled
web-from-disk visual-face fork (#101/#192/#209) on incorrect premises;
the salvageable ideas (on-demand trace slices, sweep-surface heatmaps,
param-binding-path highlighting) belong in the tracker, not a side doc.
Adds a conceptual whitepaper outlining how to use the Bevy game engine and its ECS architecture to build a highly performant, WASM-ready 3D/2D visualization layer (Playground) for Aura's massive backtest datasets.
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 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
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`
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
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
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
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
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
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
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
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
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
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.
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
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.
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
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
4 tasks, strictly sequential: tap vocabulary + UnknownTap intrinsic
validation (deferral eprintln survives until task 3; the 0107 deferral
test splits into its two 0109 pins), trace_name widening + the
claim-sentinel name-composition contract across registry and executor,
persist_campaign_traces (nominee non-reduce re-run, metrics-equality
C1 guard, TraceStore member-dir writes, loud skips, deferral line
dies), gated e2e extension (trace files + chart read-back).
Drafted per-task against the live tree (3 authors); cross-task seams
verified in the notes: campaign_run.rs untouched by tasks 1-2 (task
3's fences stay valid), the task-1(b) test found by fixture not name,
tap->channel mapping verified against persist_traces_r, nominee params
bound from the report manifest via the shipped point_from_params
inverse, reduce/non-reduce metrics equality grounded in the shared
SeriesFold/GatedRecorder ledger construction.
refs #201
Cycle 0109, anchored on #201. Encodes the five swarm-triaged decisions
(#201 comment 2026-07-04; F1-F4 unanimous, F5 4/5 with dissent
recorded): closed tap vocabulary of the wrap convention's four sink
names (escalation = new vocabulary entry or authored blueprint sink,
never an open node-path namespace); nominee-only non-reduce re-run per
cell (bounded, C1/reproduce precedent, equality-asserted); the
existing TraceStore family-shaped under {campaign8}-{run}; wiring
consumer-side after execute() returns (MemberRunner stays one-method,
aura-campaign stays trace-agnostic bar a one-line name stamp);
CampaignRunRecord.trace_name as the one sparse pointer (the 0108-F10
navigability lesson). Seam refinement recorded: the run counter is
assigned in append_campaign_run, so the store write composes the name
from a claim sentinel — contract pinned, exact seam is the planner's.
Boss-signed via grounding-check PASS (11/11). Planner note carried
from the check: the re-run equality assert pins METRICS equality (the
C1 core) — manifest fields are fresh-context and not reconstructed
cross-mode.
refs #201
The std::monte_carlo block doc now names the position-dependent
semantics (pooled OOS after wf / per-survivor otherwise) and the > 0
execution guard the generic u32 slot hint could not carry; the
std::generalize block doc names campaign scope, the >= 2-instrument
need, and the R-expectancy metric family. Glossary: new 'stage
bootstrap' entry defines the realization payload incl. prob_le_zero;
the campaign-run entry gains the generalizations schema and the
stdout-wrapper-vs-bare-store-line note. Introspection text and
glossary only — no document content id moves.
Gates: workspace green, clippy clean.
refs #200
Verdict: honest, recorded, reproducible inference on top of the 0107
loop — pooled_oos provably pools the wf OOS windows (n_trades 948+895
= 1843), per_survivor flags a razor-thin gate-passer at
prob_le_zero 0.525 (the inference layer earning its keep), the
two-instrument std::generalize records worst_case/sign_agreement over
last-wf-window nominees, byte-identical across three runs modulo the
run counter, and all eight boundary probes refuse loudly at the right
tier. 0 bugs.
Triage: F1-F5 carry-on; F6 (campaign validate blesses
executor-unrunnable shapes — the third tier invisible) and F11 (no
CLI read-back for recorded realizations) filed as issues; F7/F9/F10
doc-tightens follow this commit inline; F8 (generalize R-metric set
undiscoverable + misleading refusal prose for R-denominated-but-
unranked metrics) filed with the --metrics tag half. The fieldtest
spec rides in docs/specs/ as next-cycle planner input per convention.
refs #200
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