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
Ratifies the m37 milestone-fieldtest concern: the guide recommended a
once-per-bar trigger without saying whether bars_since_open depends on
it. It does not — the index is clock-derived (ctx.now()), so a denser
trigger stream (raw m1 price, as the shipped corpus wires it) emits
the same per-bar index more often. The once-per-bar wiring is a
convention for one-emission-per-bar, not a correctness requirement.
Fieldtest spec-gap ratified: Count is a plain positive decimal with no
sign and no leading zeros ('03' refuses) — and the per-kind asymmetry
against TimeOfDay's required zero-pad is deliberate, pinned with its
rationale: canonical is each domain's conventional notation,
fixed-width for wall-clock times, minimal for numbers.
refs #271
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
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
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
The binary is the only always-present teacher (C29); the 2026-07-22 external
field test showed the help teaching nothing but the verb inventory. This
cycle makes every closed vocabulary the binary ships listable with a one-line
meaning, and opens the help with the concepts the field agent had to discover
forensically.
#315 — help + introspection:
- `aura --help` opens with the two-layer concepts paragraph (research verbs
as sugar over registered process/campaign documents; the directly
authorable data plane; bias-as-target-position + protective-stop execution
model in R; how traces come to exist).
- Each document-bridged sugar verb's long help names the process shape it
desugars to (sweep -> std::sweep; walkforward -> [std::grid,
std::walk_forward]; mc -> + std::monte_carlo; generalize -> [std::sweep
(selection), std::generalize]). `run` is not verb_sugar-bridged, so its
help points at the canonical document-first form instead of claiming a
desugaring it does not perform.
- `graph introspect --vocabulary` lists each node type with its schema doc
(bare names taught nothing); `--node <T>`'s head line carries the meaning.
- `graph introspect --folds` (new): the tap-fold vocabulary with bind rule,
output kind, and meaning — it existed only as source comments. The rows
live in aura-std (`fold_vocabulary`), unit-pinned against
`fold_binds_at`/`fold_output_kind` so the prose cannot drift from the
executable rules, and doc_gate-checked (C29 entry seam). The discovery
surface is graph introspect because folds bind at graph-declared taps
(C27); the document layer still refuses a folds slot pending #310.
- `process introspect --metrics` lines carry each metric's meaning (the doc
column existed since #316 but was never printed).
- `campaign introspect --block std::presentation` lists the four persisted
taps' meanings under the persist_taps slot.
- The scaffolded project CLAUDE.md teaches the execution semantics (bias as
held target, protective stop, R) and the document data plane.
#323 — C29 authoring surfaces:
- `introspect --unwired` enumerates the optional `description` envelope slot
for both document kinds (absent-only, like risk/cost); the campaign lib
fixture gains a description, and the risk/cost-bound e2e binds description
too so "no open slots" keeps meaning complete.
- `graph build --help` carries the op-list reference: all nine op kinds with
fields and a worked element each (OP_REFERENCE lives beside OpDoc so a new
variant is one screen from its help line).
- The authoring guide's S0 worked literal is byte-pinned to the scaffold's
LIB_RS template (rendered with the guide's my_lab namespace); the scaffold
e2es compile that template for real, so the pin is a transitive compile
guard. The template gains the guide's C29 comment, the guide gains the
template's rename note — one worked example, two surfaces, zero drift.
Deliberately out of scope (ratified #319, 2026-07-24): no doc-strings for
the quintet's 48 flag fields — the sugar surface retires; only the pointer
lines above bridge toward the document layer.
Verification: full workspace suite green, clippy -D warnings clean,
aura-bench exit 0 with all fingerprints OK (help_ms +1.6% — the longer help
text, in tolerance), cargo doc warning count unchanged (7 pre-existing).
9 new e2e pins in tests/help_self_description.rs; guide + CLAUDE.md pins in
scaffold unit tests; fold-vocabulary rules + doc_gate unit-pinned in
aura-std.
closes#315closes#323
Three of the four immediate fieldtest findings for the self-description
cycle:
- authoring-guide S0: the worked Scale literal gains the required
NodeSchema.doc line (+ the C29 comment) -- the shipped example was a
hard E0063 for anyone pasting it (the exact #314 teaching-failure
class, caught from the consumer seat).
- The op table becomes "The nine ops": the C29 doc op is documented
with its JSON shape, the register requirement, the at-most-once rule
and the gate; the README op-kinds list names it too. The fieldtester
had to guess the shape from commit bodies -- now it is on the public
surface.
- The store-gate refusal's fix hint is surface-neutral: builder
.doc(...), blueprint "doc" member, or op-script {"op":"doc"} --
previously it prescribed the Rust builder to a JSON author.
Gates: registry, graph_construct (63) and project_load (14) suites
green; refusal-prose pins unchanged (pinned substrings untouched).
refs #316
Architect review (cycle 757e3ac): core clean — show is pure shell
dispatch over Env::registry() (C28); both ledger amendments match the
F1-F8 decision log exactly; document schema untouched; the #164
no-framing pin is stricter than the spec snippet asked. Four peripheral
drift items, resolved:
- fix: docs/authoring-guide.md verb rosters now name show (process) and
show|runs (campaign) — the guide teaches exactly the
generate->retrieve->extend loop this cycle closed.
- fix: docs/glossary.md campaign/process document entries carry the
settled verb sets (record-reality glossary write).
- fix: show_process's not-found refusal now sources its prose from
ref_fault_prose(ProcessNotFound) instead of a hand-copied format!
(byte-identical, test-pinned; the campaign-side prose has no RefFault
sibling and stays the single campaign instance).
- ratify (log-only): the shipped show helpers use print! (no framing,
#164) where the spec snippet sketched println! — the code is the
stricter, correct form; recorded on the reference issue's decision
log. The spec is a git-ignored working file swept at this close.
Regression: aura-bench report-only run, all fingerprints OK, deltas in
noise (host load 9.6 noted; engine/ingest/campaign/cli lanes all within
±5%). Full aura-cli gates re-run green after the tidy edits.
refs #300
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
The two fieldtest findings, resolved:
- friction: --parallel-instruments 0 now refuses in domain terms ("must be
a whole number of at least 1 — it bounds how many distinct instruments
are resident in parallel") via a custom clap value-parser, instead of
leaking Rust's NonZeroUsize wording; the zero-bound test pins the prose.
- spec_gap: the authoring guide's exit-code contract now states that a
gate-emptied cell (a std::gate leaving no survivors) is a successful
cell — exit 0 with an informational aura: note and a truncated
realization — and that exit 3 is reserved for cells that could not be
evaluated. Records observed behaviour; no code change.
Gates re-verified: workspace suite green, clippy -D warnings clean.
refs #277
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.
closes#256
Fork B (owner decision 2026-07-14): the dissolved walkforward/mc
translations' leading sweep executed the full grid over the whole campaign
window and persisted a Sweep family, yet only the enumerated parameter
points ever crossed the stage seam (the wf stage re-sweeps them per IS
window itself). The leading stage is now the fieldless vocabulary block
std::grid: it enumerates, executes nothing, persists nothing.
- aura-research: StageBlock::Grid ({"block":"std::grid"}), schema-strict
parse arm (empty slot list: every key but "block" is refused by the
generic unknown-slot check), PROCESS_BLOCKS entry, intrinsic-tier no-op
arm; the vocabulary test's non-empty-slots guard carries a pinned
std::grid-only exception (a nominal slot would misdescribe the
vocabulary to describe_block consumers).
- aura-campaign: the inter-stage seam is a typed two-armed StageFlow
(points-only vs executed members); gate / mc-per-survivor fence the
points-only arm with defensive PipelineShape faults; preflight admits
std::grid only as the first stage and only immediately before
std::walk_forward (every other neighbor consumes executed reports).
- aura-cli: translate_walkforward / translate_mc lead with
StageBlock::Grid; the two family-shape E2E pins flip to zero Sweep
families; translate_generalize keeps its executed sweep(argmax) — its
generalize stage consumes the argmax winner report as the cell nominee.
- docs: dated #256 amendment in the ledger's verb-dissolution narrative;
the authoring-guide vocabulary transcript gains the std::grid line.
Behaviour preservation: the exact-grade real-data pins
(walkforward_real_e2e_pins_the_exact_current_grade,
mc_r_bootstrap_real_e2e_pins_the_exact_current_grade) pass unmodified —
survivor points reach the wf stage in the same odometer order as before.
Measured (the #256 acceptance measurement; debug build, real GER40 2025,
2x2 grid, `aura walkforward --real`, 3 runs each):
before (a55e4cf): 6.27 / 6.18 / 6.18 s
after: 4.52 / 4.49 / 4.45 s (~ -27% wall clock)
Suite: cargo test --workspace green (0 failed); clippy clean.
Decision log: #256 comments (fork rationale incl. the StageFlow seam and
the slot-guard exception).
The second risk-regime variant vol_tf{period_minutes, length, k}
computes the vol estimator over completed time buckets: an H1 signal
gets an H1-matched stop in the research matrix instead of a hand-scaled
minute stop (the issue's k-inflation workaround retires). Additive
externally-tagged serde (stored Vol documents keep their content ids);
the executor arm wires the VolTfStop primitive via the builder+bind
chain; validate checks period_minutes/length/k positivity per regime.
The member-manifest round-trip holds for both variants (C1): vol_tf
members stamp stop_period_minutes/stop_length/stop_k and the reproduce
path re-derives the VolTf stop whenever stop_period_minutes is present
— never a silent default-Vol fallback. The Regimes slot label and the
unit notes name the new variant (period_minutes IS the stop's
timescale); glossary, authoring guide, and design ledger record the
second variant. Default regime and sugar paths byte-untouched.
Coverage: node units (rollover-only emission, bucket-delta math, the
constant-|delta| correspondence with the per-cycle regime), executor
fold, serde/validate units, the manifest round-trip unit, and a
hostless two-regime e2e (distinct ordinals; vol_tf members stamp their
timescale, vol members do not).
closes#262
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
- 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 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
- 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.
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
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).
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
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
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