Commit Graph

657 Commits

Author SHA1 Message Date
Brummel f96796cd08 docs: close the cycle-0110 fieldtest doc-drift findings
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
2026-07-04 19:38:36 +02:00
Brummel 36fbf492ee fieldtest: cycle-0110 sweep-dissolution corpus (GREEN-core)
Consumer scenario against the public surface only: selection-free
process doc round-trip, the dissolved real-data sweep (doc dedupe +
realization accumulation + C1 bit-identity), refusal edges, rank-later
over the persisted family. 0 bugs; the cycle's own axes all came back
working. 4 friction + 2 spec-gap findings on the verb entry ergonomics
and pre-existing guide drift — transcribed in
docs/specs/fieldtest-sweep-dissolution.md for triage.

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

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

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

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

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

refs #210
2026-07-04 19:16:06 +02:00
Brummel b7aaa0ba59 feat(cli): dissolve the real-data blueprint sweep into the campaign path (#210 T4)
aura sweep <bp.json> --real ... --axis ... now runs as thin sugar over
its generated campaign document through the one campaign executor: the
dispatch registers the canonical blueprint (topology_hash IS
content_id_of over the same canonical bytes, so the strategy ref
resolves against the existing single store write), strips the CLI's
wrapped axis names to the raw campaign namespace (#203 bind
convention), converts the probed archive window back through the
ingest seam's own epoch_ns_to_unix_ms (made pub; C3 — the seam owns
the ms/ns convention, never an inline division), and hands off to
verb_sugar::run_sweep_sugar. The inline real-data arm is gone; the
synthetic arm and --list-axes are untouched.

campaign_run gains RunPresentation {Full, MemberLinesOnly}:
run_campaign keeps Full (record line unchanged, project gate
unchanged); the sugar path runs MemberLinesOnly — the generated doc's
emit already limits stdout to family_table member lines, the mode
suppresses only the final record line. The record append is identical
in both modes; no project gate on the by-id path (the dissolved verb
works project-less, exactly as before).

The characterization pin survives the re-cut with exactly the one
sanctioned assertion flip (instrument-absence -> instrument==GER40)
and now also pins the generated artifacts: one process + one campaign
document auto-registered (dedup on a second identical invocation),
raw axis keys in the stored document, the stored window a ms sub-range
of the request, C1 at the member-report level with the registry's
run-suffix increment isolated.

Suite 1055/0, clippy clean, gated real-data paths executed locally.

refs #210
2026-07-04 19:01:27 +02:00
Brummel fd0b21d070 feat(cli): verb_sugar translator — argv to generated campaign documents (#210 T3)
The pure half of the sweep re-cut: translate_sweep maps a real-data
blueprint-sweep invocation (axes, name, symbol, window, canonical
blueprint bytes) to a selection-free single-stage process document plus
a campaign document carrying exactly the invocation's intent (seed 0 —
no stage consumes it — so identical invocations dedupe onto identical
content ids); register_generated puts both into the content-addressed
stores. Unit tests pin determinism, name flow, mixed-kind-axis refusal,
and that generated documents pass intrinsic validation + preflight.

Dead-code-allowed until the dispatch rewire wires the module (next
task removes the bridge attribute). Plan bytes reconciled with three
necessary deviations the spec gate surfaced: derive(Debug) for
unwrap_err, ScalarKind lives in aura_core, and 'gen' is reserved in
edition 2024.

refs #210
2026-07-04 18:01:51 +02:00
Brummel c37abb2a27 feat(research,campaign): optional selection group on the sweep stage (#210 T1-T2)
The std::sweep selection triple (metric/select/deflate) becomes ONE
optional group, Option<SweepSelection>, serde-flattened so the wire
form keeps the flat slots: every existing document parses to Some and
its canonical bytes — and content id — are unchanged (golden pin
byte-untouched). A half-populated group is refused by the schema-strict
parser (all-or-nothing); a bare {"block":"std::sweep"} is the
selection-free sweep.

Campaign side: preflight permits a selection-free sweep only as the
pipeline's terminal stage (new ExecFault::SelectionFreeSweepNotTerminal,
prose in aura-cli's exhaustive exec_fault_prose); the executor's
selection-free arm appends the family exactly as before but records no
StageSelection and produces no nominee (recording one would fabricate
intent — #210 fork decision 1).

Introspection follows: the sweep block's schema table marks the group
optional; CLI introspection pins updated. New tests: group-or-nothing
refusals, selection-free round-trip + distinct content id, terminal-only
preflight accept/refuse, selection-free execute realization.

refs #210
2026-07-04 17:43:53 +02:00
Brummel 3fd1cf9593 docs(cycle): sweep-dissolution spec + plan (cycle-live working artifacts)
Cycle 1 of the verb-dissolution milestone (refs #210): the real-data
blueprint sweep re-cut as sugar over a generated, auto-registered
campaign document; optional selection group in the sweep stage
vocabulary; terminal-only preflight rule. Spec auto-signed on a
grounding-check PASS (decision log on #210); ephemeral per convention,
removed at cycle close.
2026-07-04 16:59:44 +02:00
Brummel 8235cee4d7 test(cli): characterization pins ahead of the sweep dissolution
Two green pins the sweep-dissolution cycle rests on (refs #210):

- sweep_real_blueprint_member_lines_pin_the_inline_contract: the inline
  real-data blueprint sweep prints one member line per grid point in
  odometer axis order, carries the swept bindings in manifest.params,
  persists exactly one Sweep family — and never stamps an instrument
  key (RunManifest::instrument stays None on this path).
- campaign_run_real_e2e_sweep_gate_walkforward (extended): every
  family_table member line emitted by the real campaign member-runner
  path is stamped with the instrument under test.

Together they pin the one behavioural delta between the two paths (the
additive instrument stamp) that the dissolution's parity contract is
phrased against.
2026-07-04 16:31:30 +02:00
Brummel e7c7bded3e docs: authoring guide for op-scripts, process & campaign documents
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 #197
closes #208
2026-07-04 15:30:03 +02:00
Brummel 61c8828fad feat(cli): house-style loader-error prose + missing-project hint on the run path
aura run leaked the raw LoadError Debug form (UnknownNodeType("..."))
while graph build already phrased the same fault house-style (#162
convention: engine error types are Display-free, the CLI presents them).
Route the run path through the shared blueprint_load_prose presenter (now
pub(crate), env-agnostic) so both surfaces phrase a LoadError identically
and neither leaks the Debug token (#184). Add unresolved_namespace_hint:
when the unresolved id looks project-namespaced (::) and no project was
loaded (env.provenance() is None), append a hint pointing at the missing
Aura.toml — the newcomer running the host from the wrong directory now
gets an orienting diagnosis instead of a bare type error (#185). The hint
is applied on both the run and graph-build paths. RED-first: the two
existing run-path pins were flipped to assert the prose + absence of the
Debug token before implementing; suite green (1043/0).

closes #184
closes #185
2026-07-04 15:19:58 +02:00
Brummel 5256b3d0ca refactor(registry): single-source the deflation-bootstrap constants (#199)
DEFLATION_N_RESAMPLES (1000) and DEFLATION_BLOCK_LEN (5) were duplicated
as independent copies in aura-cli and aura-campaign — a silent-drift risk
(an edit in one crate but not the other refuses nothing, it just produces
a wrong deflation result). Promote a single definition into aura-registry,
which owns optimize_deflated (the sole consumer of these counts); aura-cli
imports it and aura-campaign re-exports it to keep its public path stable.
DEFLATION_SEED stays cli-local (no campaign twin). Values unchanged;
behaviour-preserving, suite green unchanged (1043/0).

closes #199
2026-07-04 15:12:40 +02:00
Brummel 71e5a6b9c3 chore(docs): remove ephemeral milestone fieldtest spec at cycle close
The research-artifacts milestone fieldtest closed GREEN and the milestone
is formally closed; per the ephemeral-artifact convention its spec is
git-rm'd at cycle close. The verdict survives durably in the tracked
corpus (fieldtests/milestone-research-artifacts/FINDINGS.md), the closed
milestone, and the ledger.
2026-07-04 14:58:21 +02:00
Brummel 7604651579 feat(cli): aura.css becomes the style pin — tokens, component library, CLAUDE.md rule
Second half of the style pin. assets/aura.css now carries (a) the full
:root token palette (Catppuccin-Mocha-derived; --bg deliberately darker
than Mocha base; new --border3 #585b70 completes the border ladder at an
identical computed value), (b) the shell rules migrated color-literal to
var() with identical computed values (font stacks stay literal — the
--mono token's longer fallback chain would change the computed value),
and (c) an opt-in, class-scoped component library distilled from the
milestone demo page (.aura-doc register, .wrap, .badge, .stats, .cards,
.term, .callout, table.res, .pipe) — unused by the runtime pages, which
render pixel-identically. CHART_CSS migrates to the same tokens (it
lands in the same document after the shell <style>, so :root resolves).
CLAUDE.md gains the binding '## HTML surfaces' rule: every HTML surface
embeds this asset; extend, never fork.

Gates: suite 1043/0, clippy -D warnings clean, doc build 0 warnings;
regenerated chart page resolves all 17 used var() names against its
:root. Independent CSS audit passed (two cosmetic notes: --bg3/--orange
currently unused; the pre-existing html,body height:100% also reaches
future .aura-doc pages).

closes #209
2026-07-04 11:24:07 +02:00
Brummel 652ad34b3f refactor(cli): extract the shared shell stylesheet into assets/aura.css
Pure byte-preserving extraction: the CSS block inside SHELL_HEAD moves
verbatim into crates/aura-cli/assets/aura.css and is spliced back via
concat!(.., include_str!(..), ..). Proven against a pre-change baseline:
chart HTML (aura chart 42edebd2-0/597d719b-GER40-w0) and graph HTML
(bare aura graph) regenerate sha256-identical (bcc2cc0f.., a0e6a97f..),
each deterministic across two generations. Suite 1043/0.

First half of the style pin: the asset becomes the single source the
runtime pages embed; tokens + component library follow separately.

refs #209
2026-07-04 11:11:09 +02:00
Brummel 6f2cf443c4 fieldtest: milestone-research-artifacts corpus (GREEN) + Aura.toml data-key doc fix (F7)
MILESTONE VERDICT: GREEN — the whole span (0106-0109) holds end to
end as one continuous consumer scenario: authored from a bare {} via
introspection alone, every ref resolved from the public surface, three
validation tiers, run by content id over two real instruments through
the full v2 pipeline, realization recorded (selection/survivors/
bootstrap/generalizations/trace_name), traces on disk and charted,
read back via campaign runs, byte-identical re-runs (C1), refusals
precise. 0 bugs, 0 frictions, 0 spec gaps; 2 doc-gaps.

F7 fixed in this commit (the docs claimed an archive-root path without
naming the key; a guessed [paths] archive silently no-ops): project-
layout and the glossary Aura.toml entry now name [paths] data, and the
aura new template advertises the commented-out key. F8 (op-script
grammar not CLI-discoverable) filed as #208, sibling of the #197 docs
half — one docwriter pass once desired.

The milestone-close gate evidence is this corpus; the formal milestone
close and the push remain user-reserved.

refs #189
2026-07-04 04:45:36 +02:00
Brummel 01925e0619 feat(cli): envelope-probe discoverability + kind-key refusal prose (#193 residue)
The --unwired help line names the whole-envelope starting move (start
from a bare {}), closing the 0106-F1 discoverability gap the narrowed
issue kept open; the wrong-kind refusal names the exact key a blind
author must fix ('the "kind" key must be "process"') instead of
describing the mismatch abstractly. The third original item (block-ids
vs field names in --vocabulary) is sufficiently served by the
envelope probe per the issue's narrowing comment.

RED-first (tdd-author handoff): both pins observed failing on the old
help text / prose.

Gates: workspace 1043/0, clippy -D warnings clean.

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

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

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

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

refs #201
2026-07-04 04:22:41 +02:00
Brummel 46a85d3ea4 feat(cli): persist_campaign_traces — campaign presentation persists nominee traces (0109 tasks 3-4)
The deferral line dies; persist_taps is honored: after execute()
returns with a claimed trace_name, the CLI re-runs each cell's nominee
once in non-reduce mode (all four channels drained; windowed to the
nominee manifest's own ns bounds; bound via the shipped
point_from_params inverse against the wrapped probe space), asserts
METRICS equality against the recorded nominee (the C1 drift alarm —
hard refusal on divergence), and writes the requested-and-producible
taps through the existing TraceStore as
traces/{campaign8}-{run}/{strategy8}-{instrument}-w{n}/{tap}.json
(ensure_name_free once; window ordinal doc-derived by position match).
Loud lines: per-cell no-nominee skip, per-run net_r_equity
unproducible skip (no cost leg in the campaign runner), one summary.
The Task-1(b) seam test tightened to pin the deferral line's absence.

Gated e2e extended: persist_taps [equity, r_equity] over GER40 —
trace_name in the record, both tap files on disk, aura chart reads
the cell back — ran its FULL path on this host (local archive
present), not the skip branch.

Gates: workspace 1041/0, clippy -D warnings clean.

closes #201
2026-07-04 04:16:22 +02:00
Brummel b8ef77b1c7 feat(research,registry,campaign): tap vocabulary + trace_name record contract (0109 tasks 1-2)
Task 1: the tap namespace is a closed vocabulary — tap_vocabulary()
(the wrap convention's four sink names; escalation = new entry or an
authored blueprint sink, never an open node-path namespace) with
DocFault::UnknownTap in validate_campaign (index-addressed, prose
enumerating the vocabulary via the single source), SlotKind::TapKinds
on the persist_taps slot, open-slot hint naming the taps. The 0107
deferral seam test split into its two 0109 pins (unknown tap refuses
at validate; a valid tap passes validate and hits the member-data
seam) — the deferral eprintln itself survives until task 3.

Task 2: CampaignRunRecord.trace_name lands serde-default sparse; the
claim contract holds across the seam — execute stamps the sentinel iff
persist_taps is non-empty, append_campaign_run composes
Some("{campaign8}-{run}") onto the stored line (safe prefix take at
the registry seam), execute mirrors the same derivation onto the
returned copy; None stays None; the hand-seeded byte-identity dump pin
survives (absent -> skipped).

Gates: workspace 1037/0, clippy -D warnings clean.

refs #201
2026-07-04 03:41:01 +02:00
Brummel ef7579f8fb plan: 0109 persist_taps wiring
4 tasks, strictly sequential: tap vocabulary + UnknownTap intrinsic
validation (deferral eprintln survives until task 3; the 0107 deferral
test splits into its two 0109 pins), trace_name widening + the
claim-sentinel name-composition contract across registry and executor,
persist_campaign_traces (nominee non-reduce re-run, metrics-equality
C1 guard, TraceStore member-dir writes, loud skips, deferral line
dies), gated e2e extension (trace files + chart read-back).

Drafted per-task against the live tree (3 authors); cross-task seams
verified in the notes: campaign_run.rs untouched by tasks 1-2 (task
3's fences stay valid), the task-1(b) test found by fixture not name,
tap->channel mapping verified against persist_traces_r, nominee params
bound from the report manifest via the shipped point_from_params
inverse, reduce/non-reduce metrics equality grounded in the shared
SeriesFold/GatedRecorder ledger construction.

refs #201
2026-07-04 03:07:48 +02:00
Brummel a25046e574 spec: 0109 persist_taps wiring (boss-signed)
Cycle 0109, anchored on #201. Encodes the five swarm-triaged decisions
(#201 comment 2026-07-04; F1-F4 unanimous, F5 4/5 with dissent
recorded): closed tap vocabulary of the wrap convention's four sink
names (escalation = new vocabulary entry or authored blueprint sink,
never an open node-path namespace); nominee-only non-reduce re-run per
cell (bounded, C1/reproduce precedent, equality-asserted); the
existing TraceStore family-shaped under {campaign8}-{run}; wiring
consumer-side after execute() returns (MemberRunner stays one-method,
aura-campaign stays trace-agnostic bar a one-line name stamp);
CampaignRunRecord.trace_name as the one sparse pointer (the 0108-F10
navigability lesson). Seam refinement recorded: the run counter is
assigned in append_campaign_run, so the store write composes the name
from a claim sentinel — contract pinned, exact seam is the planner's.

Boss-signed via grounding-check PASS (11/11). Planner note carried
from the check: the re-run equality assert pins METRICS equality (the
C1 core) — manifest fields are fresh-context and not reconstructed
cross-mode.

refs #201
2026-07-04 02:39:37 +02:00
Brummel 0bb203a38f feat(cli): aura campaign runs — read-back for stored realizations (fieldtest 0108 F11)
The recorded bootstrap/generalization evidence is no longer write-only:
'aura campaign runs' lists every stored record (campaign id, run
counter, cell count, first cell's stage signature); 'aura campaign
runs <id> [run]' dumps the BARE stored line(s) — the store form,
byte-identical, never the {"campaign_run": ...} run-emit wrapper (the
F10 parsing trap). A lookup, not an action: empty/unmatched notes and
exits 0 (the runs-family convention); outside a project the campaign
family's project refusal.

RED-first (tdd-author handoff): hermetic seed of one hand-written
store line into the fixture project, list + byte-identical dump pinned,
observed failing on clap's unknown-subcommand exit 2.

Gates: workspace 1027/0, clippy -D warnings clean.

closes #206
2026-07-04 02:22:36 +02:00
Brummel 891c40d64b feat(cli): generalize applicability tag + honest R-expectancy refusal prose (fieldtest 0108 F8)
--metrics now tags the four generalizable names (expectancy_r,
net_expectancy_r, sqn, sqn_normalized) via check_r_metric as the
predicate — the registry's own R-expectancy rule, no fourth roster
site (#190). The GeneralizeNonRMetric refusal names the real rule
with the roster pointer instead of mislabeling R-denominated-but-
unranked metrics (max_r_drawdown is a drawdown in R, not a 'pip
metric').

RED-first (tdd-author handoff): the extended --metrics pins and the
flipped prose pins (unit + seam) observed failing on the old output.

Gates: workspace 1026/0, clippy -D warnings clean.

closes #207
2026-07-04 02:14:58 +02:00
Brummel 38ffe50b57 feat(cli): campaign validate runs the executor preflight as a third tier (fieldtest 0108 F6)
valid == runnable for every pure document/campaign property: inside a
project, once intrinsic + referential pass, validate fetches the
referenced process from the store and runs the data-free
aura_campaign::preflight (promoted to pub) — an executable shape gains
'campaign document valid (executable): pipeline shape and static
guards pass'; a shape/param/metric/instrument fault refuses under
'campaign is not executable:' with the exec_fault_prose detail, exit 1,
before any member runs. Outside a project the skip line is unchanged
(the third tier needs the store like the second).

Collateral the RED author predicted: the referential e2e's OK fixture
(PROCESS_DOC: deflate+plateau sweep, overfit_probability gate) was
intrinsically-valid-but-never-executable — that test now registers an
executable twin (argmax/no-deflate, per-member gate metric); the base
PROCESS_DOC fixture stays untouched for all other consumers.

RED-first (tdd-author handoff): the third-tier pin observed failing on
the two-line validate output.

Gates: workspace 1026/0, clippy -D warnings clean.

closes #205
2026-07-04 02:08:28 +02:00
Brummel 197936b27d docs: annotator-stage discoverability tightens (fieldtest 0108 F7/F9/F10)
The std::monte_carlo block doc now names the position-dependent
semantics (pooled OOS after wf / per-survivor otherwise) and the > 0
execution guard the generic u32 slot hint could not carry; the
std::generalize block doc names campaign scope, the >= 2-instrument
need, and the R-expectancy metric family. Glossary: new 'stage
bootstrap' entry defines the realization payload incl. prob_le_zero;
the campaign-run entry gains the generalizations schema and the
stdout-wrapper-vs-bare-store-line note. Introspection text and
glossary only — no document content id moves.

Gates: workspace green, clippy clean.

refs #200
2026-07-04 01:56:48 +02:00
Brummel 6138894b07 fieldtest: cycle-0108 annotator-stages corpus (GREEN)
Verdict: honest, recorded, reproducible inference on top of the 0107
loop — pooled_oos provably pools the wf OOS windows (n_trades 948+895
= 1843), per_survivor flags a razor-thin gate-passer at
prob_le_zero 0.525 (the inference layer earning its keep), the
two-instrument std::generalize records worst_case/sign_agreement over
last-wf-window nominees, byte-identical across three runs modulo the
run counter, and all eight boundary probes refuse loudly at the right
tier. 0 bugs.

Triage: F1-F5 carry-on; F6 (campaign validate blesses
executor-unrunnable shapes — the third tier invisible) and F11 (no
CLI read-back for recorded realizations) filed as issues; F7/F9/F10
doc-tightens follow this commit inline; F8 (generalize R-metric set
undiscoverable + misleading refusal prose for R-denominated-but-
unranked metrics) filed with the --metrics tag half. The fieldtest
spec rides in docs/specs/ as next-cycle planner input per convention.

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

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

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

closes #200
2026-07-04 01:33:00 +02:00
Brummel 7e4e9a8827 feat(cli): annotator-stage seam flips + doc tidy + gated e2e with the mc suffix (0108 task 5)
The retired v1-boundary test is replaced by v2 pins: mc-before-wf
refuses with the executor shape prose (while process validate accepts
the same doc — the tier boundary observable across two commands, added
by the task-2 e2e phase and kept), single-instrument generalize
refuses data-free on the built fixture project, and the two
addressing-mode tests' stale rationale comments now name the
member-data seam they actually hit. PROCESS_BLOCKS doc strings drop
'in v1' (introspection text only — no content id moves). The gated
real-data e2e extends its process with the monte_carlo suffix and
asserts the pooled_oos bootstrap in the final campaign_run line — ran
its full assert path on this host.

Task-5 duplicates the plan had double-drafted (task 2's e2e phase
pre-landed three of its tests) were correctly NOT re-added.

Gates: workspace 1025/0 (fully green again), clippy -D warnings clean.

refs #200
2026-07-04 01:28:06 +02:00
Brummel a1cd7bc6f5 feat(campaign): monte_carlo stage arm + campaign-scope generalize phase (0108 tasks 3-4)
The mc arm bootstraps the stage's incoming R-evidence with one
semantics, input-shaped by position (#200 decision 1): after a
walk_forward it pools the wf family's per-window OOS trade_rs in roll
order into ONE r_bootstrap (PooledOos); after sweep/gates it
bootstraps each surviving member's fresh in-memory series
(PerSurvivor, ordinals into the population family; a zero-trade
member records the engine's defined all-zero degenerate). Seeded from
the campaign doc's seed (C1). The wf family is read by reference from
the cell's families vec — no clone. run_cell's Generalize arm is an
explicit no-op naming the campaign scope.

The generalize phase runs after the cell loop (#200 decision 2):
nominees (last wf window's OOS report, else the sweep winner; None on
gate truncation) grouped by (strategy, window) across instruments via
a BTreeMap (deterministic order); >= 2 winners feed the shipped
generalization(), fewer record the shortfall (generalization: None,
missing named) — divergent per-instrument winners are exposed via
their params, never averaged away.

Gates: campaign 40/0 (4 execute_mc + 3 execute_generalize new),
workspace build clean; the known-RED cli integration test flips in
task 5.

refs #200
2026-07-04 00:57:35 +02:00
Brummel ab778f2361 feat(campaign,registry,engine): record widenings + preflight v2 fault set (0108 tasks 1-2)
Task 1: RBootstrap and Generalization gain serde derives;
lineage.rs gains StageBootstrap (per_survivor | pooled_oos) and
CampaignGeneralization; StageRealization.bootstrap and
CampaignRunRecord.generalizations land serde-default sparse (a
pre-0108 campaign_runs.jsonl line still parses — pinned), threaded
None/empty through every literal site. No behaviour change.

Task 2: ExecFault::UnsupportedStage is gone; the preflight now admits
the v2 shape sweep [gate]* [wf]? [mc]? [generalize]? via a monotone
rank walk (precise per-pair PipelineShape prose) and statically
refuses: single-instrument generalize (GeneralizeNeedsInstruments),
non-R generalize metrics via check_r_metric (GeneralizeNonRMetric —
no fourth roster site), zero mc params (ZeroBootstrapParam). CLI
prose swapped accordingly. The loop's E2E phase added a tier-boundary
pin: process validate accepts [sweep, mc, walk_forward] while campaign
run refuses it data-free.

KNOWN RED (documented in the plan, flips in task 5):
crates/aura-cli/tests/research_docs.rs::campaign_run_v1_boundary_refuses_mc_process
still pins the retired 'not executable in v1' prose. Interim gates:
registry 57/0, campaign 33/0, cli --bin 111/0, workspace build clean.

refs #200
2026-07-04 00:38:25 +02:00
Brummel 3454459e6d plan: 0108 annotator stages
5 tasks, strictly sequential: record widenings + serde derives
(workspace-green), preflight v2 + fault-set swap (leaves ONE known-RED
aura-cli integration test, documented loudly, flipped by task 5;
interim gates exclude the aura-cli integration targets), the mc stage
arm (dual-input bootstrap), the campaign-scope generalize phase
(nominee threading), CLI seam flips + doc tidy + gated e2e extension
restoring full workspace green.

Drafted per-task against the live tree (4 authors), assembled with two
reconciliations: the task-2 typo-trap fence replaced by its
authoritative form (plans carry only literally-applicable bytes), and
task 4's old-quote aligned to task 1's record-literal bytes (comment
lines included). Cross-task byte seams verified: task 3 quotes the
pre-task-2 unreachable-arm (task 2 does not touch exec.rs); task 5
pins the prose task 2 defines (substrings verified compatible).

refs #200
2026-07-04 00:09:39 +02:00
Brummel 38f7098bdb spec: 0108 annotator stages (boss-signed) + tier-boundary characterization pin
Cycle 0108, anchored on #200. Encodes the five swarm-triaged decisions
(#200 comment 2026-07-03, all convergent on cited ground, no bounce):
std::monte_carlo bootstraps the stage's incoming R-evidence (per-survivor
after sweep/gates, pooled per-window OOS series after walk_forward) via
the shipped r_bootstrap; std::generalize runs at campaign scope over
per-cell nominees per (strategy, window); both stay terminal annotators
(unanimous); realization widens existing records (StageRealization.bootstrap,
CampaignRunRecord.generalizations, serde-default); v2 executable shape
sweep [gate]* [wf]? [mc]? [generalize]? with static preflight guards.
No document-schema bytes move — every existing content id survives.

Boss-signed via grounding-check PASS (11/11). The first dispatch
BLOCKed on one unpinned current-behaviour assumption ([sweep, mc,
walk_forward] passes the intrinsic tier); the gap was closed by the
green characterization test
validate_process_permits_walk_forward_after_an_annotator (pins the
intrinsic/executor tier boundary), and the fresh re-dispatch ratified
all eleven assumptions.

refs #200
2026-07-03 23:44:20 +02:00
Brummel 4da47cb919 fix(cli): aura new skips git init inside an existing work tree (0107 fieldtest, orthogonal)
The cargo-new mirror completed: a scaffold landing inside a tracked
tree no longer nests a .git (the gitlink/submodule hazard that bit the
fieldtest corpus); outside a work tree the best-effort init is
unchanged. Oracle: git rev-parse --is-inside-work-tree in the target
dir; any failure reads as not-in-a-work-tree so the init stays
best-effort.

RED-first (tdd-author handoff): the inside-a-work-tree pin observed
failing on the nested .git; the outside guard pinned against
over-removal.

Gates: workspace 1003/0, clippy -D warnings clean.

closes #204
2026-07-03 23:19:34 +02:00
Brummel 8ef829b8cc feat(cli): process|campaign introspect --metrics — the roster split becomes discoverable (0107 F9)
The 17-name metric vocabulary lists with applicability tags derived
from aura-campaign's existing pub rosters (rankable | gate |
annotation) — no fourth roster site (#190); the mode rides the shared
introspect struct and answers for both doc families. The three
metric refusals (intrinsic unknown-metric, executor unrankable and
gate-not-per-member) now point at the mode, so the
exists-but-not-rankable split (profit_factor is emitted per member yet
not selectable) is no longer trial-and-error.

RED-first (tdd-author handoff): six same-seam pins (roster lines +
tags, one-mode guard incl. the extended usage line, both-families
parity, three refusal pointers) observed failing, then the mode +
hints landed.

The worked-examples half of #197 stays open (docwriter territory
post-stability, per the issue itself).

Gates: workspace 1001/0, clippy -D warnings clean.

refs #197
2026-07-03 23:15:16 +02:00
Brummel 1d87397c95 feat(research): draft placeholder refs ({} / null) read as open slots in the unwired probe
A campaign draft can now validate-so-far AND report its open ref slots
(0106 fieldtest F4): open_slots_campaign treats an absent ref, {} and
null uniformly as the open slot (strategies[i].ref with the two-arm
hint; process.ref with the content-id-only hint). Draft affordance of
the probe only — the strict parse tier keeps refusing placeholders (a
placeholder is not a valid document form; canonical bytes stay
untouched).

RED-first (tdd-author handoff): library pin + CLI --unwired e2e
observed failing (probe reported 'no open slots' over placeholder
refs), then the two ref predicates routed through ref_slot_is_open.

Gates: workspace 995/0, clippy -D warnings clean.

closes #195
2026-07-03 23:07:10 +02:00
Brummel 63d2657850 feat(cli): one bare content-id display form; CLI targets tolerate the content: prefix (0106 F3 / 0107 F6)
The copyable token is now the valid ref form everywhere: all three
register lines print 'registered <family> <id> (<path>)' and both doc
introspect --content-id modes print the bare 64-hex id (converging on
graph introspect's existing form). CLI FILE-or-id targets (campaign
run, graph introspect --params) strip a leading 'content:' before
resolving — a CLI arg is ephemeral input, leniency costs nothing. Doc
ref FIELDS stay bare-only (two accepted spellings would make
semantically identical docs hash apart — canonical-form byte
stability outranks input leniency); instead the referential not-found
prose appends 'refs use the bare 64-hex id — drop the content: prefix'
when the offending ref carries it.

RED-first (tdd-author handoff): eight same-seam assertions across the
three surfaces observed failing on the prefixed forms, then the five
display sites, two target ladders, and the conditional hint landed.

Gates: workspace 993/0, clippy -D warnings clean.

closes #194
2026-07-03 23:01:20 +02:00
Brummel c3d62f2ce3 feat(cli): graph register / --params accept the op-script form (fieldtest 0107 F5)
Both verbs now route through the same composite_from_any shape
discrimination file-mode --content-id shipped with (op-script array ->
one-build tail; envelope object -> loader), so the three on-ramp verbs
agree on accepted shapes and an op-script registers under the same
shape-invariant content id as its built envelope — no more raw serde
refusal ('invalid type: map, expected u32') hiding the graph build
bridge.

RED-first (tdd-author handoff): two same-seam behavioural pins
(register stores the envelope id for an op-script; --params matches
the envelope's axis lines) observed failing on the serde refusal, then
the two call sites rerouted.

Gates: workspace 990/0, clippy -D warnings clean.

closes #202
2026-07-03 22:49:12 +02:00
Brummel 2968fbef40 feat(registry,cli): referential tier requires full open-param coverage; bind refusal speaks the raw namespace
validate == runnable (fieldtest 0107 F7): validate_campaign_refs now
checks the reverse direction — every open param of the resolved
strategy must be bound by some campaign axis — emitting the new
RefFault::ParamNotCovered { strategy, param } with the RAW
param_space() path; ref_fault_prose phrases it ('open param "X" is
bound by no campaign axis'). The executor's every-open-knob-required
rule is thereby mirrored at validate time, and campaign run's
referential gate catches an uncovered knob before any member binds.
The e2e fixture that legitimately under-covered (fast only) gains the
slow.length axis.

Second half, RED-first: the member-bind refusal no longer leaks the
wrapped bind-time path — it names the raw campaign-axis namespace with
the wrapped path as a parenthetical ('open param "threshold" ...
(wrapped path: sma.threshold)').

RED evidence: E0599 on the pinned ParamNotCovered test (tdd-author
handoff), then the flipped bind_axes prose pin observed failing on the
wrapped form.

Gates: workspace 988/0, clippy -D warnings clean.

closes #203
2026-07-03 22:44:26 +02:00
Brummel 978ba15bd3 fix(campaign): walk_forward window-fit refusal speaks ms prose, not Debug (fieldtest 0107 F8)
The roller refusal leaked its raw Rust form through ExecFault::Window
(SpanTooShort { span: (Timestamp(...), ...), need: ... }) — the one
break in the cycle's Debug-free prose seam. The detail now phrases
both roller refusals in the doc's own ms unit:
'in_sample_ms + out_of_sample_ms = N ms exceeds the campaign window
[a, b] (L ms)'. RED-first: the wf_roller_refusal_maps_to_window_fault
pin was flipped to the prose form (observed RED on the old Debug
output), then the map_err phrased; live repro confirmed against the
fieldtest fixture.

Gates: workspace 987/0, clippy -D warnings clean.

refs #198
2026-07-03 22:32:06 +02:00
Brummel 71405d4d86 fieldtest: cycle-0107 campaign executor + on-ramp corpus (GREEN-core)
Verdict: the 0106 F7 wire is closed — campaign+process documents drive
aura campaign run through sweep -> gate -> walk_forward over the real
GER40 archive, realization recorded as a thin family-linking
CampaignRunRecord, bit-identical on re-run and across file/id
addressing (C1). 0106 F1/F5 on-ramp gaps confirmed repaired; the
honest-refusal surface (v1 boundary, empty gate exit 0 + truncation,
plateau/deflate composition, stale wf vocabulary, bad targets,
persist_taps loud deferral) exercised and clean. 0 bugs.

Findings triaged: F5 -> #202 (op-script vs envelope shape on the
on-ramp verbs), F6 -> #194 comment (content: prefix trap re-confirmed,
now spans graph register), F7 -> #203 (open-param coverage at validate;
raw-vs-wrapped path prose), F8 -> RED-first fix follows this commit
(SpanTooShort Debug leak), F9 -> #197 comment (rankable/per-member
roster split undiscoverable), F10 -> ratified store-before-gate on
#198 (derived: consistent with campaign register's intrinsic-only
gate; content-addressed store is an idempotent intent archive).
Orthogonal: #204 (aura new nested-.git gitlink hazard).

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

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

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

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

closes #198
2026-07-03 22:07:44 +02:00
Brummel 367f8678f1 feat(cli): #196 blueprint on-ramp — graph register, introspect --params, blueprint-file --content-id (0107 task 10)
Closes the F5 authoring gap: a campaign's strategy ref + axes are now
authorable from the public surface without running a sweep first.
'aura graph register <blueprint.json>' puts the canonical form into the
content-addressed store (id == topology hash) and prints the stored
path via the pub blueprint_path accessor; 'aura graph introspect
--params <FILE|64-hex-ID>' lists the RAW composite param_space — the
exact namespace campaign axes are validated against (the wrapped
--list-axes namespace stays the sweep-verb view); --content-id gains an
optional FILE that shape-discriminates a blueprint envelope from an
op-list document (stdin behaviour byte-identical without FILE).
is_content_id promoted pub(crate) and shared with graph_construct so
the two FILE-or-id surfaces cannot drift on the id shape.

RED evidence was produced retroactively by the loop (stash-probe: the
5 new tests fail for the expected reasons without the src changes) —
ordering deviation noted, outcome unaffected.

Gates: graph_ 46/0, workspace 987/0, clippy -D warnings clean.

closes #196
refs #198
2026-07-03 22:00:14 +02:00
Brummel aeb0366aed feat(cli): aura campaign run — the executor verb over the MemberRunner driver (0107 tasks 8-9)
campaign_run.rs: target resolution (file is register-then-run sugar;
bare 64-hex is the canonical id — #198 decision 1), project gate before
any store write, zero-fault referential gate, process fetch + v1
preflight, then aura_campaign::execute with the CLI MemberRunner over
the shipped loaded-blueprint convention: per-member blueprint reload,
reduce-mode wrap, unique suffix-join of raw campaign axis names onto
the wrapped param_space, windowed real data via the shipped ms->ns
source seam (absent archive/zero-bar windows -> NoData). Emission:
family_table / selection_report lines gated on the doc's emit list
(names debug_asserted against emit_vocabulary), the campaign_run
record line always, persist_taps deferred LOUDLY on stderr before
execution (F7 lesson), zero-survivor cells noted on stderr with exit 0.
exec_fault_prose/member_fault_prose keep the Debug-free house seam.

Seam tests: 8 campaign_run_* e2e tests incl. outside-project, bogus
target, unknown id, v1-boundary (mc process registers fine, run
refuses), persist_taps ordering, and the gated real-data
sweep->gate->walkforward e2e — which ran its full assert path on this
host (local GER40 2024-09 archive) rather than the data-less skip.
Also: exec.rs campaign-id guard tightened to lowercase hex, matching
is_content_id and the store's self-keyed form (review nit).

Gates: workspace 975/0, clippy -D warnings clean.

refs #198
2026-07-03 21:33:29 +02:00
Brummel b15ad07208 feat(campaign): execute — cell loop, sweep/gate stages, walk-forward stage (0107 tasks 6-7)
The execution core: cells iterate strategy x instrument x window in doc
order (sequential — C1 keeps parallelism across sims); the sweep stage
enumerates the axes odometer (BTreeMap order, last axis fastest) through
the engine sweep over a ListSpace with lowest-index-deterministic fault
capture; selection dispatches optimize / optimize_plateau /
optimize_deflated (deflation nulls seeded from the campaign doc's seed);
gates filter per-member via member_metric (metrics.r == None fails an R
predicate, conservative); an empty survivor set truncates the cell's
realization and the run continues (exit-0 semantics at the caller). The
walk-forward stage rolls the declared cell window in ms (WfMode ->
RollMode), IS-sweeps ONLY the survivor points per window, stamps
manifest.selection on OOS winner reports, and appends a WalkForward
family; realization = CampaignRunRecord over untouched family records.

The loop's task-7 BLOCKED was review-exhaustion on the task-6 stub
wording the plan itself prescribed (task 7 deletes that stub); a fresh
post-loop quality review on the final diff returned one Minor — the
campaign_id prefix slice could panic on a malformed id — fixed as a
typed PipelineShape refusal + test (execute_refuses_malformed_campaign_id).
Known and accepted: a cross-cell member fault leaves earlier cells'
families as unreferenced records in the append-only store; nested
window/member parallelism can oversubscribe cores on large campaigns.

Gates: aura-campaign 29/0, workspace 961+/0, clippy -D warnings clean.

refs #198
2026-07-03 20:53:18 +02:00
Brummel 3a4f1c4597 feat(campaign): aura-campaign crate — types, member_metric, preflight (0107 tasks 4-5)
New leaf library crate: the campaign-execution semantics home (#198
home decision — reusable beyond the CLI; NOT C21's project-side
World). CellSpec + the MemberRunner seam (the only thing a consumer
implements), MemberFault/ExecFault (Display-free, prose at the binary
seam), member_metric over the 14 per-member scalars (third roster
site, refs #190 — drift fails safe as a preflight refusal), and
preflight: v1 pipeline shape std::sweep [std::gate]* [std::walk_forward],
rankable-metric and gate-metric rosters, plateau-in-wf and
deflate+plateau refusals, i64-fit guard on wf lengths — all before any
member runs.

Post-loop: the held quality finding (untested i64-fit arm) verified
real and closed by hand — preflight_refuses_wf_length_exceeding_i64.

Gates: aura-campaign 14/0, clippy -D warnings clean.

refs #198
2026-07-03 19:59:21 +02:00
Brummel b43def7d75 feat(engine,registry): ListSpace + campaign-run realization store (0107 tasks 2-3)
aura-engine: ListSpace — explicit point set implementing Space beside
GridSpace/RandomSpace (a gate's survivor subset has no cartesian
structure); GridSpace-identical arity/kind validation reusing the
existing SweepError variants (KindMismatch.value_index carries the
point ordinal for a list); empty point list is valid and sweeps to an
empty family; re-exported at the crate root.

aura-registry: CampaignRunRecord/CellRealization/StageRealization/
StageSelection — the thin campaign-level linking record over untouched
family records (#198 decision 4) — with append_campaign_run (assigns
run via next_campaign_run, a parallel counter beside next_run) and
load_campaign_runs (missing file => empty) on the campaign_runs.jsonl
sibling store; blueprint_path and find_blueprint_by_identity promoted
to pub (the campaign executor resolves the same refs the referential
tier validates).

Gates: engine 290/0, registry 54/0, clippy -D warnings clean.

refs #198
2026-07-03 19:34:08 +02:00
Brummel 67aff34923 feat(research): std::walk_forward vocabulary corrected to machinery-true fields (0107 task 1)
folds/in_sample_bars/out_of_sample_bars mapped to nothing
WindowRoller::new accepts; the block now carries in_sample_ms/
out_of_sample_ms/step_ms/mode (WfMode: rolling|anchored) — the
roller's three lengths in the campaign window's own epoch-ms unit
plus both shipped RollModes (#198 decision 2). New intrinsic fault
ZeroWalkForwardLength (path-addressed) refuses zero lengths at the
doc tier, earlier than the roller's NonPositiveLength. Golden
canonical pin, PROCESS_FIXTURE, introspection tables, and the
aura-cli prose/fixture twins moved together; fieldtest corpus
untouched (historical record — stored walk_forward docs get new
content ids by design).

Gates: aura-research 14/14, aura-cli green, workspace build clean.

refs #198
2026-07-03 19:17:54 +02:00
Brummel 0cc1858d86 plan: 0107 campaign executor
10 tasks, strictly sequential: walk_forward vocabulary correction
(research + cli twins, workspace-green per task), engine ListSpace,
registry campaign-run store + visibility promotions, aura-campaign
crate (scaffold/types, preflight, execute sweep+gate, walk-forward
stage via byte-exact stub replacement), CLI verb + MemberRunner driver,
seam tests + gated real-data e2e, #196 on-ramp verbs.

Drafted per-task against the live tree, seam-reconciled (task 6/7
signature + module home unified; scaffold dead-code allowances dropped
by the task that consumes them), self-reviewed per the planner
checklist (no placeholders, single-filter test gates, compile-gate
ordering honoured via partial -p gates in task 1).

refs #198, refs #196
2026-07-03 18:49:56 +02:00
Brummel 12f48001af spec: 0107 campaign executor (boss-signed)
Cycle 0107, anchored on #198 (campaign executor; #196 blueprint on-ramp
rides along). Encodes the twelve decisions recorded on #198: eleven from
the fork triage (2026-07-03) plus the user-decided executor home (a new
library crate, 2026-07-03). Scope: aura-campaign library crate
(MemberRunner seam, execute, gate evaluation, preflight, realization
assembly), std::walk_forward vocabulary correction to machinery-true
fields, engine ListSpace, registry CampaignRunRecord + campaign_runs
store, CLI campaign-run verb + driver, #196 on-ramp verbs.

Boss-signed via grounding-check PASS (17/17 load-bearing assumptions
ratified against currently-green tests). One construction note carried
to the plan: a private Registry::blueprint_path already exists and is
promoted to public rather than duplicated.

refs #198, refs #196
2026-07-03 18:00:19 +02:00
Brummel e8f919d956 fix(research): process_ref describe advertises content-id only
Fieldtest finding F2 (cycle-0106 corpus): aura campaign introspect --block
std::process_ref rendered the generic dual-form ref label ('one of
{ content_id } | { identity_id }') while validate_campaign refuses an
identity_id process ref — the authoring guide offered a value the
validator rejects. The --unwired hint was narrowed in the 0106 audit; this
narrows the parallel describe path: std::process_ref's slot moves to a
distinct content-only SlotKind::ContentRef whose label names only the
content-id form. Strategy refs keep the dual-form label (both ids are
valid there) — pinned by the same RED test.

RED-first: tests::process_ref_describe_advertises_content_id_only failed
on the shared-label tree, passes now; workspace 917/0, clippy clean, doc
0 warnings.

refs #189
2026-07-03 16:58:25 +02:00