ede26bb231a2bb07a8504295c043fa825c477eee
188 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ede26bb231 |
fix(aura-cli, docs): fieldtest bugs — a refusal that misdirects, a handle denied, a stale signature
RED-first fixes for the three bugs the source-blind field test caught. Two
are the same failure the whole cycle keeps circling: prose that tells a
caller something the code does not do.
- The chart not-found refusal prescribed `aura exec --tap <NODE.FIELD>=<FOLD>`.
The selector takes a declared tap NAME, so following the refusal verbatim
earns a second refusal ("the tap plan names 'sub.value', but the blueprint
declares no such tap"), and the flag is not needed at all — a plain run
records every declared tap. This sentence predates the cycle and was carried
over verbatim while the rest of the refusal was corrected; the field test
ran it as written, which is exactly why it ran it.
- `aura measure ic <family-handle>` answered "no recorded run '…' under
runs/traces" for a handle that IS recorded — the value the campaign run
printed, that `chart` renders, whose directory exists. A family holds
members rather than one series, so IC is measured over a member. The
refusal now says that and lists the member keys, which also closes the
friction that nothing on any text surface prints them: reaching a member
previously meant the very `ls runs/traces/` this cycle set out to retire.
- C28's #297 note still gave the entry points' signature as the retired
`(_, Vec<String>)` pair in the present tense, contradicting C27 one contract
over. The close commit claimed lockstep; this makes it true.
Both code fixes have tests that fail without them. The field test also found
four friction items and two spec gaps, filed rather than fixed here.
refs #309
|
||
|
|
9f87e5a583 |
audit: trace-handle cycle close — refusal parity, measurement pin, ledger lockstep
Architect review over 9636b00..9221bcd. What holds, confirmed against the diff rather than the commit body: no stored record shape moved (neither `aura-engine/src/report.rs` nor the registry compat mirror appears in the change at all, and the byte pins pass unedited); the handle travels the beside-the-report route C27/#297 established for the unbound-tap names, with the library still printing nothing; trace enumeration landed inside `aura-registry` where C22 puts trace file I/O; no C14 exit class moved, both refusal arms falling through to the same exit 1. Two high drift items, both fixed here: - The corrected refusal claimed a campaign run prints its handle as `trace_name` on stdout. It prints `campaign_run.trace_name` — the campaign leg wraps its record, as the glossary states outright — so the chain the refusal advertised returns null there. This is the third instance of one error class in this cycle: a false claim inside the very prose meant to stop misdirecting callers. Grounding caught the first two, review the third. - The measurement leg shipped without the handle pin the spec asked for. All three new pins drove the strategy path, so the measurement leg emitted a handle nothing asserted. It has its own test now, on the shared bind pair the two legs cannot drift across. Ledger and vocabulary brought into lockstep: C27's current state records the `RunOutcome` carrier that replaced the pair; the glossary's tap entry names the single-run handle and warns that a family id is not one; the authoring guide's own single-run tap example now says the name is printed rather than guessed. The suggestion line gained the `aura:` prefix every other stderr line carries. Bench: all five fingerprints OK — the decisive signal, since they hang on the record bytes this cycle was required not to move. Timing deltas are load noise (loadavg 8.7 under concurrent agents), not regressions. refs #309 |
||
|
|
9221bcd167 |
feat(aura-runner, aura-cli): a run reports the trace handle it recorded under
A single run persisted its taps and then said nothing about where: the only way to learn the directory name was `ls runs/traces/`, and the chart intake's not-found refusal pointed at "the handle a sweep/walk-forward/campaign run printed" — two verbs retired with #319, and a single run printed no handle at all. A caller holding a family id from a families listing was stuck: that id is not a trace handle, and nothing said so. The handle now rides BESIDE the report, not inside it. Both declared-tap entry points return `RunOutcome { report, skipped, trace_name }` in place of the `(report, skipped)` pair, and the CLI composes report + handle into one stdout object through a `serde(flatten)` wrapper. `RunReport`, `MeasurementReport`, `RunManifest` and the registry's compat mirror are untouched, so no stored record shape moves and a tap-free run's line stays byte-identical. Placement is the load-bearing decision, and it follows a precedent rather than inventing one: the report is the durable C18 run record — its manifest states what the run *was* — while a trace directory is where its output went. The project settled this exact question one cycle earlier for the sibling value, where the unbound-tap names ride beside the report so the CLI, not the library, prints the note (C27/#297). An embedding host gets the handle as a value, never as text to parse back. The chart refusal gains a second arm. A family id (`{campaign8}-{strategy_ordinal}-{instrument}-w..-r..-s..-{run}`) is recognised syntactically — the trailing segment shape plus an 8-hex head, the form `derive_trace_name` mints — and answered with the campaign's REAL recorded handles, filtered to those `chart` would accept, suggesting one only when exactly one matches. It never derives a handle by truncating the id: the id's second segment counts strategies while the handle's counts runs, and one campaign run mints family ids at several strategy ordinals whose traces all live under that single run's handle. `TraceStore::names()` supplies the enumeration, keeping trace file I/O in the store where C22 puts it. Verification caught three errors worth recording. The first spec draft claimed the handle was the id's leading pair — refuted by a green test where a run-0 campaign mints ordinal-1 ids. The second draft's replacement refusal said a campaign run "prints one handle per family"; it prints one per run. Review then found the `NotFound` filter untested — deleting it left the suite green — so the case now has a test that fails without it. closes #309 |
||
|
|
99e93000c5 |
fix(aura-runner, aura-cli): milestone-fieldtest bugs — library exposes-neither guard, override class, doc truth
RED-first fixes for the two code bugs the safe-to-embed milestone fieldtest caught: (1) run_signal_r panicked (exit 101) on a blueprint exposing neither bias nor a declared tap — the CLI pre-validated but the library seam, the very surface the milestone promises is kill-free, did not; the guard now refuses class 2 with the CLI's prose family before wrap_r (run_measurement has no wrap seam and no hole). (2) The override unknown-param refusal exited 1 through the one inline site the #297 adjudication missed; it and its wrapped-retired sibling are class 2 now, three existing pins re-pinned with the adjudication comment. Doc truth from the same fieldtest: the guide's campaign no-data class corrected (contained cell faults exit 3, not 1), TapPlanError's rustdoc no longer advertises the retired exit-1 register, and C30 records that rev + the embedding's committed lockfile are the reproducible-build contract (branch-referenced engine deps resolve at lock time). refs #296 |
||
|
|
32f6be8552 |
audit: M4 cycle close — drift fixes, bench ratified clean
Architect review over 024e865..HEAD (issues #296/#348/#297/#299). Holds confirmed: zero process::exit in the assembly crate with the milestone promise pinned in-process; C1/C18 record shapes untouched with guard and stamp sharing one label constructor; the C30/#348 re-arm transition-safe with no stale references. Drift resolved in this commit: the C14 contract now records the context-borne reproduce guard classes (#299), C30 carries the source-level-identity limit in the contract itself (not only in build.rs), the guide's exit-class prose no longer names the retired run verb, C28 durably enumerates the deliberate print residuum, and the pip_or_refuse doc names reproduce (not 'the CLI shell') as the from_choice home. Bench: all 5 fingerprints OK (engine/ingest/campaign_sweep/campaign_heavy/ cli_fixed_cost); metric deltas within load noise on a busy box (loadavg 12 warning), report-only, no baseline moved. |
||
|
|
fd303de94d |
feat(aura-runner, aura-cli): RunnerError propagation — the assembly crate stops killing the host
All 14 process::exit sites in aura-runner (member x8, measure x5,
translate x1) convert to RunnerError { exit_code, message } propagation;
run_signal_r / run_measurement return Result tuples carrying the
skipped-tap names beside the C18 reports (record shapes untouched), and
the CLI owns printing via the shared exit_on_runner_error arm (the
dispatch_reproduce pattern — reproduce now uses the same helper).
cost_knob becomes fallible: the sweep worker maps it into the cell's
MemberFault (closing the one hole in 'a worker never process-exits'),
the persist path keeps its string channel. The skipped-tap note is
CLI-printed from returned data, byte-identical.
The one deliberate behaviour change is the minuted C14 adjudication:
refusals in the content of what argv named (binding, synthetic mismatch,
compile, tap-bind content, exposes-neither) move exit 1 -> 2; the
boundary is FORM vs VALUE — an out-of-domain override value keeps the
runtime class via the panic containment, matching the campaign leg.
Environment/data/IO refusals stay 1 (TapPlanError::exit_class is the
single source). Named re-pins in exec.rs, run_refuses_unrunnable_
blueprint.rs, tap_recording.rs, graph_construct.rs; new library-level
test pins the milestone promise (a refusal returns in-process, the
embedding host survives). Prose is byte-identical everywhere.
Docs in lockstep: C28 deferred block closed (14 sites, hole closed),
C14 partition + form-vs-value boundary, C27 note emission, guide exit
classes. Fork minutes: issues/297#issuecomment-4868 and -4873.
closes #297
|
||
|
|
57c56ee4e2 |
feat(aura-core, aura-runner): re-arm the ABI handshake — source fingerprint replaces the frozen version stamp
The load seam's aura-core stamp becomes AURA_CORE_FINGERPRINT: an FNV-1a
64 hash over aura-core's sorted src/**/*.rs (prefix-free records: path,
NUL, u64-LE content length, contents), emitted by build.rs beside the
rustc stamp and baked into the descriptor by aura_project!. validate_c_tier
compares fingerprints ('aura-core build'); a stale dylib — same rustc,
different aura-core sources — is refused instead of trusted at the
Rust-ABI tier. RED-first: the headline test pins that the frozen crate
version is never again the host stamp (plus a version-bump-proof twin and
an aura-core shape pin: 16 hex, never CARGO_PKG_VERSION).
Descriptor field renamed aura_core_version -> aura_core_fingerprint
(engine-internal; field names are not ABI, order is). Documented accepted
C30 limit: source-level identity only — the consuming build's lockfile/
features stay outside the stamp. C13/C30 prose aligned.
closes #348
|
||
|
|
d87f534e85 |
docs(design): C30 — stability discipline: artifacts stable, code movable
Decide #296: no Rust-API stability before 1.0 (no semver, no shims; the workspace version communicates nothing). Two consumer classes with two mechanisms — native node crates ride the engine checkout as path deps (what the scaffolder already emits), external embeddings pin a rev. The compatibility promise attaches to the artifact plane (C18/C29/invariant 8), never to Rust API, with an erosion guard against 'stable API' claims. The skeptic pass surfaced that a frozen 0.1.0 disarms the cdylib handshake's CORE_VERSION refusal; the contract commits the load seam to a build-identity fingerprint instead (transition tracked as #348). Decision minutes: #296 (options a-e, rationale). closes #296 |
||
|
|
f108291b7f |
audit: harvest 2026-07-26 cycle close — intake enumeration completed, ledger notes, stale comments
Architect drift review (scope 77ad046..HEAD): What holds — the #343 reference-semantics hash is code-backed on both output surfaces (record line + trace index), the RiskRegime::Fixed stamp/re-derive lockstep is complete both ways, and both new guide examples build against the binary. Drift resolved in this commit: C24's root-name-gated intake enumeration gains the introspect --taps FILE branch plus its missing per-site pin (byte-identical refusal to the register sibling — the #331 class-enumeration lesson applied); C27 gains the #337 realization note (positive discovery view closes the recovery-only gap); C12's inline-hash sentence updated to the topo parameter; five stale dispatch_run comments reworded to name exec_blueprint_leg as the surviving owner. Remaining drift routed: the unpinned guide op-scripts are a durable debt class, filed as #344 (idea) rather than swept here. Regression gate: aura-bench all five fingerprints OK (report-only deltas within noise on a loaded box; no baseline move, nothing to ratify). refs #337 refs #343 |
||
|
|
ef24f06547 |
fix(aura-cli, ledger): review fixes — override stamps the base hash (#343 revised), prose corrections
Harvest sweep, whole-diff review fix block. The review refuted the #343 ratification's factual premise: the campaign leg does NOT mint a reopened member's hash — runner.rs passes the stored strategy_id as topo even for reopened members (reference semantics). Decision revised on the issue (fix, not ratify): exec's override run now stamps the LOADED base document's content id (computed before reopen_all; RED-first — the inverted pin failed on the old reopened-hash behaviour), keeping topology_hash store-resolvable and identical in meaning across both legs; the variation lives in manifest.params. C24/C12/C18 rewritten to the corrected reading. Also per review: C24's retired build-free-introspection sentence updated (old wording archived in the history sidecar, #339 item 4); C14's partition key precisely scoped to the routing seam, naming the legs' differing content-validation exits honestly; measure.rs's false unreachability comment corrected; --taps added to the guide's introspect cheat-sheet and pinned on the content-id path; the zero-trade-cell note routed through the diag macro; doc-comment, issue-ref, and gate-name corrections; the Fixed-regime NaN branch pinned. refs #339 refs #342 refs #343 |
||
|
|
2e532bce00 |
docs(ledger), fix(aura-cli): override-hash ratified, exec exit partition pinned, cost-wiring example
Harvest sweep, batch 6 of 6. - #343 ratified (per the decision minuted on the issue): an override IS a topology-parameter variation — the executed run's topology_hash is the reopened topology's own, deliberately not required to resolve in the store; the manifest's params map plus the base document reconstruct the variant. C24 carries the full clause, C12/C18 cross-reference it; pinned by a bare-vs-noop-override hash test (distinct, and stable across runs). - #342 item 5: C14 pins exec's unresolved-target exit partition on the existing usage/runtime line — file-content faults (not-JSON, op-script, wrong-kind) exit 2, missing-state faults (unreadable non-id target, unregistered content id) exit 1. One sanctioned realignment: the wrong-kind refusal moves 1 → 2 to join its file-content siblings (RED-first on the updated pin); the unregistered-id row gains its missing sibling pin. - #341 item 4: the authoring guide gains a worked cost-wiring op-script (ConstantCost → CostSum via PositionManagement geometry, built and verified), honest about being a wiring reference — production cost models still come from a campaign document's cost block (C10). closes #341 closes #342 closes #343 |
||
|
|
2b692a71e3 |
feat(aura-research, aura-runner): RiskRegime::Fixed — the fixed stop is campaign-reachable
Harvest sweep, batch 3 of 6 (second half).
The third externally-tagged variant ('{"fixed":{"distance":..}}',
additive — stored Vol/VolTf documents keep their bytes): doc-tier
validation mirrors FixedStop::new's distance>0 assert (NaN refused)
so the assert is unreachable from a document; stop_rule_for_regime
binds the shipped FixedStop composite; run_blueprint_member stamps
stop_distance beside the vol knobs' precedent and
stop_rule_from_params re-derives Fixed from it (stamps are mutually
exclusive; the pre-#233 no-knob fallback is unchanged). BadRegime
prose widened to name the distance rule. C10's risk-axis paragraph
updates from 'additive when needed' to shipped; glossary gains the
fixed variant.
closes #338
|
||
|
|
1476990cfd |
audit: #319 cycle close — architect drift resolved, bench green
Architect review over 9cfe296..dc5f174 (drift_found -> all five items fixed in this close): C24's family-machinery sentence re-amended to current truth (synthetic walks are reproduce-only inputs since the builder retirement; superseded text to the sidecar); the ported generalize test's doc no longer promises the retired CrossInstrument family handle and its stale section header is gone; FamilyKind::CrossInstrument carries its C18 dead-machinery/read-back note in code; live comments in campaign_run, bench surfaces, and graph_construct name exec instead of the retired verbs; the five inlined topology_hash copies in the bin test module consolidated into one test helper. What holds, per the architect: C24<->code gated-intake lockstep exact, C12's single-hash claim true in code, exec dispatch matches C14's amended text. Bench (regression gate) exit 0, all five fingerprints OK: engine_throughput bars_per_s 14014049 (+0.1%), ingest_throughput 12935441 (-0.5%), campaign_sweep wall 1.407s (+0.9%), campaign_heavy wall 5.688s (+2.1%), cli_fixed_cost run_ms 3.6 (+6.6%, spawn-floor jitter under parallel-agent load, report-only). No baseline moved. Also rides: the reviewer re-check's two comment nits (classify-once wording, SIGPIPE example verb). refs #319 |
||
|
|
dc5f1742f4 |
fix(aura-cli, aura-runner): review findings — duplicate --override refusal, live discovery prose, neutral JSON refusal
In-cycle fixes for the independent review of the #319 package, RED-first for both Importants. A repeated --override path now refuses at the shared lexer (exit 2, path named) instead of panicking exit 101 through reopen_all — which also un-misattributes the campaign leg's collision prose for duplicates. override_paths' refusal points at aura graph introspect --params (the retired --list-axes reference swept from every live comment, one explicitly-historical mention remains). exec classifies file targets through a Result-bearing peek: unparseable JSON refuses neutrally before any leg is chosen. RunPresentation (single-variant) removed; run_campaign_returning's contract note names its one deliberate usage-class exit; C14's routing sentence and C20's family-builder paragraph amended to current truth (superseded text to the history sidecars); bench error strings and deletion blank-line runs tidied. refs #319 |
||
|
|
9eb6d6b4f6 |
docs(readme, guides, glossary, ledger), bench: the surviving surface everywhere
Slice 8, closing the #319 retirement's prose and bench debt. Bench argv rides exec (fixed_cost single-run probe, campaign surfaces, and the seed helper that still called the retired sweep at runtime — caught by the bench run itself); all five fingerprints unchanged against the committed baselines, confirming record-line parity through the retirement. Live docs (README, authoring guide, project layout, glossary) describe only exec + campaign documents + graph introspect --params; three glossary entries explicitly mark their verb retired. Ledger amendments per the C29 discipline — C25's executor-verb-set re-settled (exec + the --override residue), C14's dual grammar reduced to the one dispatch, C24's document-built runs/families + gated-intake route list (lockstep with the code comment), C12's override clause and identity anchor repointed to the runner-layer hash computation, C18/C22/C27/C01 mention rewrites — superseded sentences moved verbatim to the history sidecars (c25's created). Stale dual-grammar doc comment on is_blueprint_file rewritten. refs #319 |
||
|
|
564a767974 |
fix(aura-cli): sweep --list-axes joins the gated intake class
Fieldtest finding B1: the one remaining authored-envelope FILE route, sweep --list-axes, skipped the root-name gate — a hand-edited "name":"../escape" listed mangled, non-bindable wrapped axis names at exit 0 while every sibling intake refused. The discovery surface now gates before any axis line prints (exit 1, shared prose), restoring both the #331 every-authored-intake claim and #328's discovery-surface identity. RED-first: the e2e refusal test was written and observed failing (exit 0, axis lines printed) before the fix. Re-enumeration of every read_to_string-fed envelope load confirms the class is now closed; C24 additionally ratifies the fieldtest's SG1 — the refusal core sentence is byte-uniform across sites while the leading context prefix varies by site convention. refs #331, #328 |
||
|
|
4ff85b94e5 |
audit: #331 cycle close — every authored intake gates the root name, cli_fixed_cost re-pinned
Architect drift review (drift_found) resolved fix-path on all three items. [high] The sweep/walkforward/mc family builders and validate_and_register_axes read authored envelope files and put_blueprint'd them ungated — falsifying the C29 exemption's premise that the store is populated through gated intakes; all four sites now gate the root name before the family/axis build (placing the gate after the build produced a misleading unknown-axis error instead of the gate refusal — RED-verified), with an e2e pin on the synthetic sweep route. The decision was gate-the-routes, not weaken-the-prose: the exemption's premise is the invariant, not a wording choice. [medium] C24 now states the gate rule as the class it is (the op intake plus every CLI intake reading an authored envelope from a file; store read-back exempt, C29). [low] C23 reconciles names-as-debug-symbols with the render name's one operational role (trace-directory key — never compilation, identity, or execution semantics). Ratify: aura-bench cli_fixed_cost baseline re-pinned (run_line_fnv 6bb0d796f760d140 -> 9bdbc3acf7b2926a). The moved metric was caused by the #328 tidy ( |
||
|
|
10570b75f8 |
docs(guide, ledger, glossary): the eleventh op — naming a blueprint from the script
The authoring guide's ops table grows the name row (ten -> eleven) plus a paragraph on what the graph default costs a multi-strategy project (indistinguishable store entries, one shared trace directory, colliding use-splice instance defaults). C24's op-script grammar records the eleventh verb and the two-seam shape gate with its C29 read-back exemption; the glossary's blueprint-label entry now separates the render name (op-settable, keys trace runs and instance defaults) from the registry label (register --name, explicit, orthogonal). refs #331 |
||
|
|
b3b7115825 |
docs(ledger, glossary, guide): the one-namespace axis prose
The C24 axis-discovery paragraph loses its obsolete rationale (names prefixed by the wrapping, discovery pinned to the sweep verb) in favour of the one-raw-namespace statement; C18 records the ratified #246 bound-override coincidence contract (param_space OR bound_param_space, no schema flag) as the document-side absorption #328 demanded; the glossary sweep and use entries, the authoring-guide worked block, and the README axis examples move to raw names. Refusal transcripts quote the byte-actual binary output (review caught an invented aura: error: prefix; the campaign-validate transcript shows the real fault_block shape). Frozen corpora (fieldtests/, *.history.md) keep their historical wrapped prose. refs #328 |
||
|
|
6ca359ae00 |
audit: #271 cycle close — C24 reconciled with its own args paragraphs
Architect drift review (fable gate) on 26b3d68..HEAD, full diff read. What holds: invariant 4 stays clean (ArgKind a separate closed enum at every surface), minuted scope held (aura-research and SessionFrankfurt untouched, no matrix surfacing), C18/C19 discipline held (args-free bytes golden-pinned at v1, args id-bearing, no pending builder reaches a graph on op or load path). Fixed here (high/medium items): C24's out-of-the-round-trippable-set paragraph still listed LinComb/CostSum/Session — now records their #271 entry, with SimBroker as the remaining (scalar-typed, narrower) exclusion; the pre-ship-dormancy paragraph's 'first ship freezes v1' sentence stales against the shipped data-driven v2 writer — the dormancy is recorded as ended by #271, the first exercised Tier-2 bump. Routed (low items): #341 — refuse serializing a still-pending builder on the Rust path (silent unloadable v1 artifact); version-refusal prose prints only the ceiling. Regression: aura-bench all five surfaces fingerprint OK, deltas within noise (max +2.3% wall at loadavg 2.7, report-only) — the hot path is untouched by design (bootstrap-only channel). Full workspace suite independently re-run by the orchestrator: test-exit 0. Spec and plan swept per lifecycle. refs #271, refs #341 |
||
|
|
bc8fb46110 |
docs(ledger, glossary, guide): construction args across the surfaces
C24 gains the add-op args clause and the data-driven format-version paragraph (tier-2 discipline with id-stability); C15's current state records Session as args-authorable; the glossary defines construction arg and arg kind (and de-stales the session-node entry to aura-market); the authoring guide fixes the moved roster path, extends the Session-anchoring section with the args path, and teaches the add-op args row; the README op-list sentence notes args on arg-bearing types. refs #271 |
||
|
|
26b3d689df |
docs: open patterns run when the harness can bind them; README's tenth op; C29 backstop
Fieldtest truth pass (composites-use, B1/S1/S2/S3):
- The "running an open pattern standalone refuses" sentence was wrong — and
it was this cycle's own ratification prose, not code. Reality (ratified
as-is): the harness binds input roles to archive columns BY NAME (C26), so
an open pattern whose roles match the data runs standalone as a matter of
design; what refuses, by name, is a role the harness cannot bind, or the
run surface's other gates (bias/tap, free knobs). The authoring guide's
input row now states exactly that; C24's input row ("only compile/
bootstrap require it bound") and the glossary's "requires them bound"
were already accurate and stand.
- README enumerated nine op kinds — the tenth (use) added (S2).
- The use-seam C29 doc gate is stated as what it is: a backstop — the
register verb already gates both input forms, so it fires only for store
content written before C29 or through the raw in-crate path (S3,
ratified).
B1's fieldtest classification was bug->debug; overridden to ratify+document:
the observed behaviour is C26-coherent and useful (quick-testing a pattern
against real data), the defect was the sentence. Minuted on #317.
refs #317, refs #339
|
||
|
|
2c2c2fdef6 |
docs(ledger, glossary, guide): the ten-verb grammar, the use seam, open patterns
C24: the op-script grammar section is rewritten to the ten verbs — repairing a pre-existing drift on the way (it read "The eight verbs" and omitted the doc op shipped with #316) — with the new use row and the open-pattern reading of input roles; a "Registered-blueprint splice" paragraph records the resolution split (all store I/O CLI-side at DTO conversion; the engine's second injected closure mirrors vocab, the §"Enforcement shift" permission extended to registered-blueprint references); the construction-gates paragraph moves root-role boundness from the holistic finalize list to compile/bootstrap only (#317 comment 4627). C29: the register-seam wording drops "named" — the code gates EVERY nested composite, recon-confirmed pre-existing prose/code mismatch — and the use seam joins the seam list (build-time gate on fetched store content; no retroactive invalidation of existing reads). Glossary: use (op) and blueprint label entries. Authoring guide: ten ops (the stale "nine ops" heading + the input row's obsolete finalize-refusal claim corrected), the use row, and the register --name / discovery paragraph. Prose truth per review: instance params are sweepable, NOT gangable (the gang op refuses a composite instance's member path) — stated as such everywhere; the gangability of spliced instances is recorded residue, not a claim. refs #317 |
||
|
|
120d116982 |
audit: harvest-sweep cycle close — C29 forward-pointers lifted to shipped state
Architect drift review (range 7cc3ce0..HEAD): holds confirmed — C27 unbound-inert intact (the #334 note is C14's promised benign class, structurally dead under record-all); #326's exit-1 matches C14's class-1 wording and the pinned #175 attribution family; C29 discipline moved with the FoldSchema retirement (registry roster doc-gated + prose pinned against the executable rules); commit bodies substantiate against the diff. Drift resolved: [medium] C29's closing forward-pointers still described #315 rendering as pending, #267 as upcoming, and a fold introspection surface as blocked on #310 — all shipped/retired; updated to the shipped state including the #332 registry-roster form. [low] the runner-side eprintln register family grew by the note and the roster-carrying refusal — tracked forward on #297 (scope comment there), consistent with the C14 tension already routed in the #310 audit. Regression check (aura-bench, report-only): all five fingerprints OK. engine_throughput 14002097 bars/s (-0.0%), ingest 12982397 (-0.1%), campaign_sweep wall 1.402s (+0.5%), campaign_heavy wall 5.588s (+0.3%, peak_rss +7.7%), cli_fixed_cost help 1.7ms (+11.4% NOTICE) — the NOTICE and rss delta measured at loadavg 8.9 with a parallel build running; sub-2ms jitter, not ratified as a real move (no baseline change; harness is report-only). Erratum to 8dbca82's body: the blast-radius corpus is 24 committed *.ops.json files, not 21 (all verified building; the count was understated). refs #297 |
||
|
|
98342246f6 |
docs(ledger, glossary): ratify the fold summary-row timestamp semantics
Fieldtest spec_gap (#335): the timestamp a fold's one summary row carries was undocumented. Ratified as-is (derived decision, minuted on the issue): the row is emitted at finalize and stamped with the instant of the last contributing (warm) value (TapFold::last_ts) — first alone pins the first contributing instant, and min/max deliberately do not carry the extremum's instant (a whole-window row privileges no interior instant, and the extremum ts would cost extra state for no consumer). The issue's initial finalize-ts reading (and the first draft of this ratification) was refuted in review against tap_fold.rs: a tap that goes cold before run end stamps the last WARM eval's instant, not the run-end instant — observationally identical only while the tap stays warm to the end, which is what the fieldtest fixtures did. Correction minuted on the issue. Recorded in C27's Current state and the glossary tap-plan paragraph; the fold-registry roster doc lines state it on the surface itself (sibling commit). closes #335 |
||
|
|
fa7453dd9f |
feat(aura-runner): skipped-tap note; undeclared-tap refusal enumerates declared taps
Two fold-selector fieldtest findings on the --tap seam, RED-first. Skipped-tap note (#334): an explicit --tap plan replaces the record-all default entirely (C27: unbound is inert) but gave no runtime signal that unlisted declared taps went unbound — a forgotten tap surfaced only as a missing trace file. bind_tap_plan's unbound arm now emits the C14 benign note (aura: note: declared tap "<name>" unbound this run) per skipped tap, exit unaffected. No new carrier: the arm is only reachable when plan.default_named is None (an explicit plan) — under record-all it is structurally dead, so the default emits nothing. Emitted runner-side beside the existing eprintln registers; the runner->CLI print migration is #297. Undeclared-tap refusal (#333): --tap on a tap the blueprint does not declare was refused without naming the valid taps, forcing the author back into the blueprint JSON. TapPlanError::UnknownTap now carries the declared-tap roster and Display appends it, mirroring UnknownLabel's fold-roster idiom (C29: a refusal names the closed set it checks against). Decision minuted on #333 (refusal roster over a new introspect view). Rider (#335): the fold roster doc lines now state the summary-row timestamp — the accumulator folds (count/sum/mean/min/max) land one row at the last warm (contributing) value's ts, and last gains the same at-its-own-timestamp wording first already carried. The ratification record lands in the sibling ledger/glossary commit. closes #334 closes #333 |
||
|
|
1baee774bb |
feat(aura-cli): --tap TAP=FOLD fold-subscription selector on aura run
Decide #310's data-authorability fork as (b), split by run-mode authority: selecting a Named fold subscription is data-reachable on the one-shot run path; adding a fold stays a Rust entry (role 2, C25). `aura run` gains a repeatable --tap TAP=FOLD selector feeding the existing TapPlan seam: no flag keeps the record-all default; any flag replaces the plan entirely (unlisted taps stay unbound — C27 inert, non-error). Validation stays in bind_tap_plan (roster-enumerating label refusal, typed UndeclaredTap, both before store I/O); parse-level refusals (malformed pair, duplicate tap) exit 2 via the verb's usage convention. Rejected alternatives (minuted on #310 with the skeptic-pass rationale): an op-script/blueprint carrier (C27 forbids recording policy in the serialized fragment); ratifying Rust-only (softens a designed-in promise with effort as the only rationale). The campaign/document carrier and the persist_taps/declared-tap namespace reconciliation are deferred to the Measurement-reachable milestone (#312/#327, minuted on #312). Ledger: C27 Current state records the boundary; the superseded sentence moved verbatim to the new c27-declared-taps.history.md sidecar; the glossary tap-plan paragraph updated, fixing the pre-existing inaccuracy that named `aura measure` a record-all-passing verb (it is the post-hoc IC analysis and constructs no tap plan). Verification: 5 new unit tests (parse branches), 5 new binary-level selector tests incl. a byte-identity pin of an explicit all-record plan vs the record-all default (C1), 1 measurement-arm test; full workspace suite green; clippy -D warnings clean. Independent opus diff review: approved, no Important/Minor findings (nits: inert-arm generic refusal, a=b=c falling to the roster refusal — accepted as-is). closes #310 |
||
|
|
913d18755e |
docs(ledger, glossary): the stderr class-marker grammar joins C14
Iteration stderr-markers-2 close, task 5 of the stderr-class-markers plan. C14's Current state gains the marker paragraph — note/warning classes for continuing-run diagnostics, bare `aura: ` for exit-carrying error lines and plain info lines, grep-stable grammar, single source in aura-cli/src/diag.rs — and the glossary gains the `stderr class marker` entry. No new C-number: C14 already owns the CLI stderr conventions and the exit-code partition this grammar completes (derivation logged on the #278 decision thread). With this the milestone promise is shipped: the two diagnostic classes are machine-separable on stderr (#278), and the all-zero-trade walk-forward announces itself instead of completing silently (#313). Exit-code semantics unchanged throughout. closes #278 closes #313 |
||
|
|
cfc2d9f5b1 |
feat(core): doc_gate refuses the namespaced short-name alibi (GREEN)
The fieldtest's spec_gap closed per the #316 decision (tighten, not ratify): doc_gate normalizes the doc against both the full entry name and its bare display segment after the last :: -- an extension node ns::Scale with doc "Scale" now refuses (RestatesName), matching the register seam's effective bare-name behaviour. Unnamespaced entries are unchanged (the checks coincide); genuine meaning lines containing the name as a substring stay accepted (equality, not containment). The C29 contract sentence carries the precision. Gates: workspace green (98 suites, 0 failed -- incl. the C29 coverage walk over every shipped doc under the tightened gate), clippy clean. refs #316 |
||
|
|
bd7585b609 |
audit(cycle 316): drift disposition, bench seed docs + ratified re-pin, C29 scope paragraph
Cycle-close audit for the self-description cycle. Architect: drift_found (mild), core holds -- the gate is pure string shape in core imported by every seam (C28), the engine never evaluates description text (C17/inv 10), determinism pins untouched (C1); the store boundary is gated by construction with the raw write private; Op::Doc is a closed typed construct (C25). Regression: aura-bench green (exit 0) after one cycle-caused infra fix and one ratified re-pin. Infra fix: the bench campaign seeds (BP_SMA_A/B) predate C29 and were refused by the store gate (exit 2, infrastructure-first rule) -- both thread the authored sma_signal meaning line. Ratify: cli_fixed_cost's run_line_fnv moved because bench_sma_a.json now carries its doc -- the blueprint's content id shifts exactly as the spec anticipates for fixtures gaining docs; campaign result fingerprints are unchanged (descriptions stay out of execution, C29). Baselines re-pinned via aura-bench pin (throughput baselines re-pinned in the same sweep, all deltas within tolerance at pin time). Drift disposition: - [high] C29 guarantee overclaim vs emit/binding-column vocabularies -> contract now carries an explicit Scope paragraph naming the residue, tracked as #321 (also covers the [medium] non-roster schema walk gap). - [low] Delay's meaning line cited the stale C5 for the delay register; corrected to C9. refs #316, refs #321 |
||
|
|
9c7f60b269 |
docs(ledger): C29 self-description contract -- INDEX entry + domain invariant 13
The cycle's design principle enters the ledger: every closed-vocabulary entry the binary exposes carries a one-line meaning behind one shared deterministic shape gate (doc_gate) at three seams -- compile/unit for engine-shipped entries, load for native node crates, register for the content-addressed store (documents: an additive-optional gated description). Forbids the engine evaluating description text (C17 / invariant 10), any influence on execution/identity/determinism (C1), retroactive invalidation of registered artifacts, and machine-invented meaning lines. Why: the audience is headless LLM agents (#319); field evidence #314 showed schema knowledge being recovered by CAS forensics from the release binary -- the removed failure class. All spec acceptance criteria are now met across the four iterations of this cycle (core carrier + std texts; domain threading; load seam; register seam + op-script doc slot + document description). closes #316 |
||
|
|
bd0c557f16 |
docs(ledger, glossary): tap-subscribers cycle tidy — C8/C27/C28 lifts, tap subscription vocabulary
Cycle-close audit for the #283/#77 tap-subscribers cycle (09994b8..6e3f394). Architect review: code contract-clean; what holds — C1/C7/C8 (empty-output caller-built consumers, (Timestamp, Cell) zero-heap payload, lifecycle hooks inside the sequential loop, byte-identical twin-run and streamed-vs-legacy byte-equality pins), C28 (assembly-crate placement of the writer-holding consumer, c28_layering guard green), C25 (registry growth = new Rust entry, data-expressible Named form, roster-enumerating refusals). All drift items were doc lifts, resolved in this commit: - C8: the lifecycle is now a symmetric pair — initialize() as finalize's start-of-stream mirror (infallible by signature; acquire-in-initialize, degrade-to-inert, surface-once-at-finalize); history sidecar records the refinement and the #77 resolution the old Deferred paragraph still carried as open. - C27: Guarantee and Current state now describe the shipped model — tap plan (Named{label, params} | Live) over the layered fold registry, BOTH entry points (run_signal_r AND run_measurement) on the one shared wiring pair, record streaming at constant memory. - C28: aura-runner now defines one graph node of its own (the in-graph record consumer — exactly the graph-meets-persistence assembly position); the #297 refusal-site count grows ~20 → ~24 (the four tap-plan refusals, already typed before the exit). - glossary §tap: the subscription/fold-registry sense added; Avoid line steers probe/monitor/scope away from the observation slot. Bench (report-only, loadavg 5.8 > 2 on the box — read with care), all fingerprints OK, no regression: engine_throughput bars_per_s 14005262 wall_s 0.714s Δ bars_per_s +3.0% wall_s -3.0% ingest_throughput bars_per_s 12970670 wall_s 0.387s Δ bars_per_s +0.5% wall_s -0.5% campaign_sweep cpu_percent 2202.0 peak_rss_mb 92.2 wall_s 1.396s Δ cpu_percent +1.5% peak_rss_mb -6.1% wall_s -1.5% campaign_heavy cpu_percent 2155.0 peak_rss_mb 94.8 wall_s 5.585s Δ cpu_percent +1.8% peak_rss_mb -3.5% wall_s -0.4% cli_fixed_cost help_ms 1.5ms run_ms 3.6ms Δ help_ms -1.8% run_ms -2.6% No baseline update (report-only surface; no ratify due). Correction on 6e3f394's body: "no Probe symbol is introduced anywhere" — introduced is the operative word; the pre-existing aura-core test fixture `struct Probe` stays, as the cycle's design record specified. Follow-ups on the tracker: #308 (legacy Recorder surface migration), #307 (binary trace format). Cycle spec/plan working files discarded. refs #283 refs #77 |
||
|
|
8688a60ded |
docs(ledger): split the design ledger into an INDEX map, per-contract live files, and history sidecars
The single-file ledger had grown to 2968 lines / ~42k tokens, mixing current design law with accreted history: 59 cycle-stamped realization blocks, 18 [HISTORY] passages, 22 supersession markers, and the C10 / C22 / C24 reframe sagas layered several supersessions deep. A code-grounding audit (31 agents, adversarially verified) confirmed 11 defects stated as current truth: stale crate homes from the C28 #288 roster split (cost nodes, PositionManagement, PositionEvent, Session), the renamed InputSpec->PortSpec, the pre-#241 project model in C16 and the open-threads section, a stale HarnessKind retirement deferral in C24, and three C28-internal inconsistencies. New shape, per the ailang precedent: - INDEX.md stays the sole addressable entry point: foundation, external components, a C-id-keyed contract map (one line per contract), and only the genuinely open architectural threads. - contracts/cNN-<slug>.md carries each contract's current truth only: Guarantee / Forbids / Why with ratified refinements integrated, plus a code-anchored Current state. All confirmed defects are fixed here; crate anchors were re-verified against the tree. - contracts/cNN-<slug>.history.md (18 sidecars) and INDEX.history.md preserve every superseded block verbatim, stamps and issue refs intact, under a frozen-record banner. Nothing was deleted: superseded design intent remains an addressable working-tree artifact, off the per-cycle audit walk. - Ledger discipline is now stated in INDEX.md: live files are edited in place at cycle close, superseded text moves verbatim to the sidecar, and a supersession marker in a live file is itself an audit finding. Every contract file was verified against its old text by an independent zero-loss pass (statement-by-statement) plus a code-accuracy spot check; C-ids and contract titles are unchanged, so existing C-id citations in code, tests, and issues resolve as before. |
||
|
|
757e3ac1bd |
feat: the document-first surface closes — show read-back, typed stops, bare plateau
The #300 keystone cycle: the residual run-quintet flags were already document vocabulary on the --real arm (#210/#220); this closes the loop and ratifies the surface. - `aura process|campaign show <content-id>` prints a registered document's canonical bytes (print!, no framing — #164), so generate -> retrieve -> hand-extend -> re-register needs no direct store filesystem access. Refusals reuse the store-hint prose, exit 1. - walkforward/mc --stop-length/--stop-k become clap-typed i64/f64 (generalize's form); stop_knob_or and its parse_csv_list helper are deleted (multi-value/invalid input is now clap's exit-2 rejection — the two dissolved-verb refusal tests retarget, the type-dead unit test is deleted). - --select accepts bare `plateau` as the documented default plateau:mean (#227 carry); document schema untouched — the two spellings generate content-id-identical campaigns (test-pinned). - family.rs's quadruplicated demo stop literal collapses onto one DEFAULT_STOP const (maintainer-lens drift finding). - Ledger: C25's "which projection next" line resolved (document-first delivered, per-verb identity re-ratified — F8; host/MCP stay demand-driven); C18 records the read-back. Design triage, fork decisions F1-F8, and the auto-signed spec live on the reference issue. Verification: full workspace suite 1482 passed / 0 failed with the real GER40 archive exercised (the byte-identity round-trips ran, not skipped); clippy -D warnings clean. closes #300 |
||
|
|
4ed6455b64 |
fix: load_family resolves the enumerated family name, refusing ambiguity (#298)
GREEN for 78e68e6's RED. aura_runner::reproduce::load_family resolved
only the derived C18 handle '{family}-{run}' while the registry's
enumeration exposes the bare name factor — the natural
list-then-reproduce library workflow dead-ended (found by the #295
fieldtest; predates the extraction byte-identically). Resolution now:
exact-handle match keeps first precedence; a bare name naming exactly
one stored run resolves as fallback; an ambiguous name (several runs,
or a name/handle collision) refuses without guessing, listing the
candidate handles. Two additional tests pin the ambiguity refusal and
the handle-precedence-on-collision semantics.
Ledger record-reality rider: the C18 #158 paragraph claimed reproduce
refuses an unknown id with exit 2; the code has always exited 1 —
correct per C14's partition (the id names missing recorded state, a
runtime failure, not a usage error). The paragraph now records the
actual behaviour and the new name-fallback semantics.
Verification: cargo test --workspace green (1477 passed, 0 failed);
clippy --workspace --all-targets -D warnings clean.
closes #298
|
||
|
|
5006766579 |
audit: shell-boundary cycle close — drift resolved in-commit
Cycle-close audit (architect: drift_found; design core clean). What holds, architect-confirmed with the guard run and the diff read in full: the shell boundary is real and enforced (full-workspace c28_layering incl. completeness + shell-content checks, acceptance grep clean — no member-run symbol left under crates/aura-cli/src); aura-campaign keeps zero production dependency on the runner; the IC move is verbatim against the anchor; the new library-only E2E pins C1 (two independent runners, byte-identical RunReport). Drift items, all resolved as fixes in this commit: - design ledger: the C28 status sentence "No crate exists yet for measurement" contradicted this cycle's own phase-3 done line — now records aura-measurement as seeded (#295), execution still unbuilt. - the #147 registry-dispatch acceptance tests (IC deflation null, seeded determinism, cross-vocabulary refusal) were pure library properties stranded in the shell's test module — relocated to aura-measurement/tests/registry_dispatch.rs (engine/registry as dev-only, layering-exempt edges), per the cycle's own tests-move- with-their-module rule. - aura-runner's direct production edge on the external data-server tree was structurally invisible (the direction table checks aura-* keys only) and unrecorded — the C28 assembly prose now names it, and a new c28_layering test pins the external tree's entry points to exactly {aura-ingest, aura-runner, aura-cli}. - the C28 shell prose named three buckets that did not cover two real shell residents — it now names the op-script construction front-end (translation) and the `aura new` scaffolder (authoring-tooling, shell-resident like rendering until a second consumer wants it). Deliberately deferred, tracker homes exist (not drift): #297 (process::exit sites in aura-runner's single-run verb paths), #294 (IC duplicate-timestamp semantics), #288-era rustdoc unresolved-link warnings in aura-std/aura-backtest (pre-existing byte-identically at the anchor). No regression scripts are configured (the bench is report-only); the architect review is the gate. Verification: cargo test --workspace green (1474 passed, 0 failed) incl. the relocated registry-dispatch tests and the new data-server guard; clippy --workspace --all-targets -D warnings clean. refs #295 |
||
|
|
170c6c82dc |
feat: full-workspace C28 guard — the shell boundary is structural (#295 part 2)
Completes the shell-boundary cycle (tasks 10-13): - c28_layering now enumerates the FULL workspace: every crate row is reconciled against its real production [dependencies], a completeness assertion pins the table to the on-disk crates/ set (a new crate can no longer escape the guard silently), the shell/assembly imported-by- nothing rule is asserted, and a shell-content check pins aura-cli to no-[lib] plus a closed allow-list of argv/translation/presentation modules. A new domain module in the shell now fails the suite. - Ledger amendments: C28 gains the assembly position (aura-runner) and the corrected import-rule prose (the ratified aura-campaign -> aura-backtest production edge, #291/#292); phase 3 is marked done with the #297 process::exit residual named; a provenance note records this as structural-debt closure, not a demonstrated downstream blocker. C25 records the control-surface decision: the text artifact vocabulary is canonical, every control surface (CLI executor verbs, a future host, an MCP face, a World program) is a projection/executor over it — the which-projection-next ranking deliberately open on #295. C14 gets the executor-face amendment, C26 the binding-module relocation. - aura_campaign::MemberRunner's doc names the shipped default implementor (aura-runner::DefaultMemberRunner) while the column keeps zero dependency on it. - New library-only E2E fixture (aura-runner/tests/world_member_run_e2e): runs the canonical member recipe over a tiny synthetic archive with no aura-cli in the link graph, and pins C1 determinism (two independently constructed runners produce a byte-identical RunReport). - campaign_run.rs module doc: intra-doc MemberRunner link re-anchored to aura_campaign::MemberRunner (the impl moved out with part 1). Verification: cargo test --workspace green (1473 passed, 0 failed); clippy --workspace --all-targets -D warnings clean; cargo doc clean of NEW warnings (the five unresolved-link warnings in aura-std/aura-backtest predate this cycle byte-identically at the anchor — #288-era doc drift, left for the cycle audit). refs #295 |
||
|
|
2cf4574e33 |
audit: cycle metric-vocabulary tidy — ledger records the retired #147 deferral
Cycle-close audit (architect: drift_found, design core clean). What holds, architect-confirmed: C18 bit-identity for RunMetrics (prose derived byte-identically, rng order preserved, registry suite unchanged); the C10 wall (monomorphic R-gates, r_based in the R vocabulary, cross-vocabulary refusal tested both ways — no leak); C28 direction (trait in aura-analysis, vocabulary supplied from the outer rungs, zero Cargo edge changes); C1 determinism pinned through the generic path. Drift items, all resolved as fixes in this commit: - design ledger: the C28 #147 disposition now records item 2 SHIPPED (the A1 cut) with A2 still deliberately deferred; the #136 one-implementor clause carries a supersession note (the IC is the second implementor). - seven stale doc comments describing the pre-#147 or mid-cycle state (analysis trait + estimator docs, registry check_r_metric C9 claim, engine re-export note, campaign PER_MEMBER_METRICS roster note, member-seam guard comment, research vocabulary note) updated to the shipped state. - R_BASED_METRICS is now oracle-pinned against RunMetricKey::r_based() in the vocabulary test (it feeds the NonRMetric refusal prose; a divergence would have misreported the R-gate silently). Noted, not amended (history stays): commit 6744f67's body says 'three syntax-only edits' where the test module actually took five. No regression scripts are configured (the bench is report-only); the architect review is the gate. Verification: extended vocabulary test, campaign suites, analysis/research suites green; clippy --workspace -D warnings clean. refs #147 |
||
|
|
a56ab7859d |
refactor: cut the engine's backtest-metrics edge via RunReport<M>
C28 phase 2 (Stratification); realizes item 1 of the deferred #147. The engine's production surface no longer names a backtest-metric type: - RunReport becomes generic over its metric payload M; sweep/mc/walkforward/ blueprint thread the parameter (SweepPoint<M>, SweepFamily<M>, WindowRun<M>, WalkForwardResult<M>). RunManifest stays concrete and engine-owned (its selection: Option<FamilySelection> embeds the foundation-grade analysis type). - summarize and the MC assembly (McDraw/McFamily/McAggregate/RBootstrap/ r_bootstrap/monte_carlo) move to aura-backtest - McAggregate::from_draws reads RunMetrics fields by name, so generifying it is the phase-6 metric-vocabulary abstraction (#147 item 2), still deferred; wholesale relocation is the honest cut. The concrete instantiation lives in aura-backtest as `type RunReport = aura_engine::RunReport<RunMetrics>` + sibling aliases. - the statistics kernel (MetricStats/quantile/resample_block/SplitMix64) moves to the aura-analysis foundation; the engine re-imports it (inner->foundation, legal) and re-exports it so existing consumers stay source-compatible. Dependency inversion in one commit: aura-engine drops aura-backtest from [dependencies] (back to dev-deps for its SimBroker/RunMetrics test fixtures); aura-backtest gains aura-engine. Cycle-free for lib targets - the cycle closes only through the engine's dev-dep edge, the pattern aura-vocabulary already uses. aura-backtest reaches the kernel transitively through the engine re-export, so no aura-backtest -> aura-analysis edge exists (the C28 ladder permits backtest -> {core, engine} only). run_indexed / SplitMix64::next_f64 widened pub(crate) -> pub for cross-crate use. Consumers (registry/campaign/cli/composites/ingest/bench) rewired by import path only, no call-site logic changed. The c28_layering structural test extends to the full ladder: aura-analysis (no aura-* deps), aura-engine ⊆ {core, analysis}, aura-backtest ⊆ {core, engine}. Behaviour-preserving: 1448/0 tests, clippy -D warnings clean, serde shapes byte-identical (C18 - RunReport<M> keeps field order manifest,metrics; the CLI pre-serialized-splice contract unchanged), moved code traceable via git rename detection. Cycle-introduced broken intra-doc links fixed. closes #292 |
||
|
|
94aaa4cde8 |
refactor: split aura-analysis into statistics and backtest metrics
C28 phase 5 (Stratification): the backtest reductions - RunMetrics, RMetrics, summarize_r, r_metrics_from_rs, and the position-event table - move verbatim into aura-backtest::metrics, beside the position_management producer whose record layout they read (the r_col/cost_col lockstep contract is now intra-crate; its stale "aura-std" comment corrected). aura-analysis is reduced to the domain-free half: the multiple-comparison hurdle math (inv_norm_cdf, expected_max_of_normals) and the selection-provenance types (FamilySelection/SelectionMode - kept beside the statistics so RunManifest.selection embeds a foundation-grade type), [dependencies] = serde only. The engine re-export surface is name-unchanged (report.rs re-imports from both crates), so no indirect consumer needed a source edit; aura-backtest moves from aura-engine's dev-dependencies into [dependencies] as a commented TRANSIENT widening of the C28 violation, removed by the phase-2 edge cut on this branch. The campaign drift guard imports its pinned types from their new source crates. Behaviour-preserving: 1448/0 tests, clippy -D warnings clean, serde shapes byte-identical (C18), moved code traceable via git copy detection. closes #291 |
||
|
|
b39fd63396 |
refactor: split the aura-std roster into C28 layer crates
Phase 4 of the Stratification milestone. aura-std held four C28 ladder layers in one roster; this cuts them into layer-aligned, aura-core-only node crates so the import direction is enforced by the crate graph: - aura-std — engine nodes only (arithmetic/logic/rolling + sinks) - aura-market — session, resample - aura-strategy — bias, stops, sizer, cost-model machinery - aura-backtest — sim_broker, position_management - aura-vocabulary — the relocated closed std_vocabulary roster Node modules move verbatim (byte-identical renames); consumers are rewired by import path only. A new structural test (aura-vocabulary/tests/c28_layering.rs) asserts each node crate's [dependencies] stay within its C28-permitted inner set, catching the acyclic-but-outward violation the compiler misses. Behaviour byte-identical: full workspace suite green (1448 tests), no golden edited, clippy -D warnings clean. C28 Status block updated. closes #288 |
||
|
|
1c49d5dce2 |
design: ratify C28 — internal stratification (ladder, process column, shell)
Codify the layer model settled with the user: an inner-to-outer ladder
engine -> market -> {measurement | strategy} -> backtest -> execution,
the research-process column beside the ladder, the shell outside. States
the import rule (inner never imports outer; measurement/strategy
siblings; column imported by no ladder crate; shell imports all;
dev-deps exempt), the six seams (five already ratified contracts —
C8/C24/C27/C18/C10-C13 — only the metric interface new), and an honest
Status recording the one hard production violation (engine -> analysis
via report.rs re-exports + the R-typed mc.rs fields) and its coupling to
the deferred #147.
Also restore the "### C19" header, deleted as collateral of
|
||
|
|
a5e02ff541 |
docs: SessionFrankfurt output semantics + declared-tap authoring (#285)
Surfaced by the measurement-milestone fieldtest: a downstream author reaching for session anchoring or declared taps had no public statement of either — the semantics lived only in node source / the design ledger. SessionFrankfurt / Session output semantics: - glossary `session node`: corrected — it claimed three streams (`bars_since_open`, `in_session`, `session_open_ts`), but the shipped node emits ONE `i64` field `bars_since_open`. Now states the real contract: the count of completed bar-periods since the local (tz-aware, DST-correct) session open, close-instant indexed (09:15->1, 09:45->3; pre-open <=0), with the Frankfurt 09:00 Europe/Berlin open + `period_minutes` knob + the value-ignored `trigger`. - authoring-guide: a "Session anchoring: the SessionFrankfurt preset" subsection — schema (trigger / period_minutes / bars_since_open), the close-instant multiples, the EqConst gating pattern, DST handling, and the add-snippet. Verified against `aura graph introspect --node SessionFrankfurt`. Declared-tap authoring (C27 / the #284 tap op): - authoring-guide: the `tap` op-table row (seven ops -> eight) + a worked "declaring a measurement tap" example. The example is verified: piping it through `aura graph build` emits `taps:[{"name":"spread","from":{"node":2,"field":0}}]`. - design ledger op-list (INDEX.md): a `tap` bullet (seven verbs -> eight); also corrected the `expose` "only verb that keeps `as`" claim — `tap` keeps it too. - README op-kind enumeration: adds `tap`. Docs only; no code change. Both worked examples were run through the built `aura` binary; the SessionFrankfurt schema was checked against introspect. closes #285 |
||
|
|
7a4e5eb99d |
docs(ledger): C27 — declared taps contract (#282)
Records the tap/binding contract: taps are the output-side twin of input_roles (C26), resolved and hoisted at compile, bound run-mode-aware via a caller-built sink (engine stays aura-core-only), recorded on the single run and inert in a sweep. Documents the deliberate DCE-deferral — build-time elision now, chain-pruning when DCE (C23) lands — and the unbound-is-inert non-error asymmetry vs a mandatory input role. refs #282 |
||
|
|
07c94433f3 |
audit: cycle-close tidy for #191 — C18 realization note for the identity index
Cycle #191 (identity-ref index) closes drift-resolved. Architect review
held: results stay scan-identical via verify-on-hit (the same-identity-
twin choice was order-unspecified before and stays unspecified in kind);
zero caller/write-path/engine changes; the #276 append-lock discipline
correctly extended to the fourth JSONL path. No regression scripts are
configured; the architect review is the gate.
Drift items and resolution:
- C18 lacked a realization note for the new persistent sidecar store and
its index-first/verify-on-hit/repair-walk mechanism, and the "identity
refs by store scan" line was stale -> this commit adds the #191
realization note and dates the scan wording (fix, ledger-only).
- The repair pass grew the sidecar without bound while same-identity
twins coexisted (per-entry comparison against a mid-walk-stale
snapshot) -> fixed in-cycle via RED pin
|
||
|
|
69bb2fc978 |
audit: cycle-close tidy for #277 — preflight duplicate refusal, zero-bound pin, C1 realization note
Resolutions for the architect's four drift items (all fix/document, none ratified away): - [medium] execute enforced family-name uniqueness only via the CLI's validate tier: preflight now refuses duplicate campaign instruments itself (defense in depth for direct callers), RED-first (execute_refuses_duplicate_instruments). - [medium] the parallel cell loop's C1 relationship lived only in the git-ignored spec: C1 gains a realization note (docs/design/INDEX.md) recording the chunked instrument-major schedule, the structural residency bound, and the two scheduling-dependent fatal-path carve-outs (fault attribution among completed cells; already-written family lines) — both inert and outside the success-path bit-identity. - [low] the fatal-path orphan-line honesty is part of that note. - [low] the --parallel-instruments zero-reject acceptance criterion had no protecting test: campaign_run_rejects_a_zero_parallel_instruments_bound pins clap's NonZeroUsize usage error (exit 2). Gates re-verified: workspace suite green, clippy -D warnings clean. refs #277 |
||
|
|
9e30805fcc |
feat(cli,ledger): supply CLI run sources by role key; ledger note
closes #275 The CLI half of by-name source binding, plus the ledger record. Every production run site that carries a ResolvedBinding — `run_signal_r`, `run_blueprint_member` (sweep / reproduction), and the campaign re-run/trace path — now keys its opened sources by role name via `key_supply(binding, sources)` and drives the harness through `Harness::run_bound` instead of the positional `run(sources)`. `key_supply` pairs each opened column with its declared role from `binding.entries()` — the one place open-order and role-order meet, made explicit so `bind_sources` verifies the wiring↔supply role match by name rather than by a maintained canonical-order convention. Because the current single-binding CLI derives both the `SourceSpec` roles (via `wrap_r`) and the supply roles (via `key_supply`) from the same `binding.entries()`, the bind cannot fail on this path — so the call site asserts the invariant with `.expect`, matching the adjacent `close_handle.expect("ResolvedBinding guarantees a close entry")` idiom. The named `SourceBindError` refusal path lives in `bind_sources` for future decoupled-supply callers (independently-built multi-feed / recorded sources, #124), where a mismatch becomes reachable. Ledger: a C4 realization note (supply resolved by name into declaration order, so supply order is no longer load-bearing; the tie-break guarantee is unchanged) and a scoped C23 refinement (a `SourceSpec.role` is load-bearing for source binding; every other flat-graph name stays a non-load-bearing raw-index symbol). The fieldtest-corpus `SourceSpec` sweep (planned Task 5) was reverted: the fieldtest packages already fail to build against the current engine API for reasons unrelated to `SourceSpec` (bootstrap arity, removed `InputSpec`, drifted `Recorder`/`SimBroker`/`RMetrics`, renamed `Scalar` helpers) — pre-existing bit-rot from earlier cycles. A partial `SourceSpec` migration neither revives nor further breaks them, so the scope decision to touch them (premised on their being otherwise-buildable) was withdrawn; reviving the corpus is separate from #275. Verification: `cargo test --workspace` green (0 failed; the real-data OHLC channel e2e exercises the migrated `run_bound` path byte-identically); `cargo build --workspace --all-targets` clean; `cargo clippy --workspace --all-targets -D warnings` clean. |
||
|
|
f0aadb54f8 |
audit: cycle-close tidy for the #256/#272 latecomer block
Drift review (architect) over a55e4cf..HEAD found the cycle substantially clean — C25 closed vocabulary, C1 determinism/behaviour-preservation, the additive-serde widening, exhaustive StageBlock matches, and the uniform exit-3 convention all hold. Two drift items resolved: - RATIFY: the `SilencedPanic` member-boundary panic-hook silencer (added by the #272 implementer, not named in the spec) is a legitimate mechanism — it keeps "recorded, campaign continues" observably true on stderr by suppressing the default crash backtrace around each contained `catch_unwind`. Its mutex serialises only the ref-count/hook-swap (O(1)), never member computation, so C1 disjoint-parallel determinism is preserved. Documented in the ledger's #272 realization paragraph rather than left as undocumented global state. - FIX: `cell_fault_kind_label` hand-wrote the snake_case strings that must match `CellFaultKind`'s serde `rename_all` (two sources of truth an aggregate over campaign_runs.jsonl could silently diverge from). Pinned with a test asserting each label equals the serialized form; the efficient `&'static str` stays. (The #272 commit's own concern-driven doc fixes and the wf panic-containment test landed in d3b1a1a; this commit carries only the two audit-phase items.) Suite: cargo test --workspace green (1311 tests, 0 failed); clippy clean. |
||
|
|
d3b1a1aead |
feat(campaign,registry,cli): per-cell fault isolation — a failed cell is recorded, never a global abort
closes #272 A member fault (no-data, bind, run, or a caught panic) is now a recorded per-cell outcome instead of aborting the whole campaign and discarding every already-computed cell. The incident that motivated this (a 22-instrument campaign lost ~36 healthy cells ~6.7 min in because Copper had an archive gap) now completes: the healthy cells persist, the gap cell is recorded as failed, and the run exits 3. Direction (owner decision 2026-07-14): run to completion and report compromised results; no coverage preflight, no window synthesis. Containment granularity: - The CELL for a sweep-stage member fault (a grid hole structurally compromises winner selection, so the whole cell fails). - The FOLD for a walk_forward member fault (independent time windows): the surviving folds pool into the family, failed folds are recorded as StageRealization.window_faults, and the summary names the ratio. - aura-registry: additive CellFault / CellFaultKind (closed: no_data|bind|run|panic|window) / WindowFault / CellCoverage, plus fault/coverage fields on CellRealization and window_faults on StageRealization — all serde-default-skipped, so pre-#272 campaign_runs lines parse and round-trip byte-identical. - aura-campaign: run_cell returns a fault-annotated CellRealization instead of Err (execute's accumulate-then-append-once tail is unchanged and now persists every healthy cell + the one run record); a `contain` split keeps ExecFault::Registry and doc-shape preflight faults global while Member/Window become per-cell/per-fold. Member panics are caught with catch_unwind(AssertUnwindSafe) at all three member-run sites (sweep IS/OOS) and recorded as MemberFault::Panic — a member panic no longer aborts the process. The wf stage partitions Registry faults (global) from Member/Window (per-fold) and filters faulted-fold placeholders (the "faulted-member-placeholder" broker sentinel) out of the persisted family. - aura-cli: exec_fault_prose gains the Panic arm; CliMemberRunner::window_coverage derives effective bounds + interior gap months from the #264 archive primitives; present_campaign prints per-cell failure notes + a completion summary and threads the failed-cell count; a run with >=1 failed cell exits 3 ("completed with failed cells") uniformly across `aura campaign run` and the dissolved sweep/walkforward/mc/generalize verbs (exit_on_campaign_result). Usage stays 2, refused-before-running stays 1, clean stays 0. Tests: the global-abort pins flip to containment (execute + the two wf fault tests → fold-containment + all-folds-fail-the-cell); new panic-containment tests on both the sweep path (PanicRunner) and the wf path (this commit adds the wf mirror the loop left uncovered); a new gapped-archive e2e (one covered cell + one gap cell → exit 3); the ~14 CLI exit-1 pins move to the exit-3 register; a pre-#272-line byte-identical round-trip guard. Suite: cargo test --workspace green (1309 tests, 0 failed); clippy clean. Decision log: #272 comments (fork rationale, the fold Registry/Member split, the placeholder sentinel, uniform exit-3). Follow-up (minor, not blocking): the plan under-scoped Task 1 to aura-registry though the additive fields also touch aura-campaign's exec.rs literals — the loop absorbed it mechanically; a future plan for a cross-crate additive-field change should scope every crate's construction sites in the first task. |
||
|
|
ea4e79d73f |
feat(research,campaign,cli): std::grid — the enumerate-only leading stage
closes #256
Fork B (owner decision 2026-07-14): the dissolved walkforward/mc
translations' leading sweep executed the full grid over the whole campaign
window and persisted a Sweep family, yet only the enumerated parameter
points ever crossed the stage seam (the wf stage re-sweeps them per IS
window itself). The leading stage is now the fieldless vocabulary block
std::grid: it enumerates, executes nothing, persists nothing.
- aura-research: StageBlock::Grid ({"block":"std::grid"}), schema-strict
parse arm (empty slot list: every key but "block" is refused by the
generic unknown-slot check), PROCESS_BLOCKS entry, intrinsic-tier no-op
arm; the vocabulary test's non-empty-slots guard carries a pinned
std::grid-only exception (a nominal slot would misdescribe the
vocabulary to describe_block consumers).
- aura-campaign: the inter-stage seam is a typed two-armed StageFlow
(points-only vs executed members); gate / mc-per-survivor fence the
points-only arm with defensive PipelineShape faults; preflight admits
std::grid only as the first stage and only immediately before
std::walk_forward (every other neighbor consumes executed reports).
- aura-cli: translate_walkforward / translate_mc lead with
StageBlock::Grid; the two family-shape E2E pins flip to zero Sweep
families; translate_generalize keeps its executed sweep(argmax) — its
generalize stage consumes the argmax winner report as the cell nominee.
- docs: dated #256 amendment in the ledger's verb-dissolution narrative;
the authoring-guide vocabulary transcript gains the std::grid line.
Behaviour preservation: the exact-grade real-data pins
(walkforward_real_e2e_pins_the_exact_current_grade,
mc_r_bootstrap_real_e2e_pins_the_exact_current_grade) pass unmodified —
survivor points reach the wf stage in the same odometer order as before.
Measured (the #256 acceptance measurement; debug build, real GER40 2025,
2x2 grid, `aura walkforward --real`, 3 runs each):
before (
|