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
This commit is contained in:
+60
-17
@@ -1253,6 +1253,13 @@ manifest stamps the untouched bound defaults (`defaults`, one-directionally
|
||||
widened beside `params`, which keeps its "what varied" reproduce semantics) so
|
||||
a raw reader of a fully-bound run no longer sees a misleading `"params": []`;
|
||||
the blueprint itself carries no such duplication.
|
||||
**Amendment (2026-07-20, #295 — the programmatic face is an executor).** The
|
||||
member-run recipe — the definition of what a standard aura backtest is — is
|
||||
library content (`aura-runner`/`aura-backtest`/`aura-measurement`, C28
|
||||
assembly position), not CLI content: the binary is argv → document →
|
||||
executor → presentation, and a downstream World program reaches the same
|
||||
recipe with no binary involved. See C25's control-surface amendment for the
|
||||
projection rule.
|
||||
|
||||
### C15 — Resampling-as-node; sessions/calendars
|
||||
**Guarantee.** A resampler is a node (finer stream → coarser bar stream),
|
||||
@@ -2508,6 +2515,15 @@ throughput lives. Realization: cycle 0106 (#189) shipped roles 5/6b their
|
||||
artifacts (process/campaign documents, C18 realization note); roles 4/7/8 remain
|
||||
technically present but faceless (no addressed verb families yet); role homes in
|
||||
the project layout and docs-by-role are open (#192 context).
|
||||
**Amendment (2026-07-20, #295 — control surfaces are projections).** The
|
||||
text-first invariant fixes the control-surface layering: the text artifact
|
||||
vocabulary (blueprints, process/campaign documents, registry records) is the
|
||||
canonical layer, and every control surface — the one-shot CLI's executor
|
||||
verbs, any future long-running host, any MCP face, a World program — is a
|
||||
projection/executor over those artifacts, never a second home for intent.
|
||||
Which projection is built next (document-first flag-vocabulary completion, a
|
||||
typed-protocol host, an MCP face, or none until demand) is deliberately open
|
||||
— recorded as an open direction fork on #295.
|
||||
|
||||
### C26 — Harness input binding: role names bind archive columns
|
||||
**Guarantee.** A strategy blueprint declares WHICH data it consumes as the NAMES
|
||||
@@ -2518,10 +2534,11 @@ the campaign cell's (or run invocation's) instrument. A campaign document may
|
||||
**override** the name default per role via the additive `data.bindings` block
|
||||
(`role name → column name`; serde `default` + skip-if-empty, so binding-less
|
||||
documents keep their content ids) — the 6b rebind seam: the blueprint's content
|
||||
identity never changes. Resolution (`aura-cli`'s `binding` module,
|
||||
`resolve_binding`) produces ONE ordered plan consumed by BOTH halves of the old
|
||||
weld: the columns are opened (`aura_ingest::open_columns`, the generalization of
|
||||
`open_ohlc`/#92) and the wrapped root roles declared (`wrap_r`) in the **same
|
||||
identity never changes. Resolution (`aura-runner`'s `binding` module,
|
||||
`resolve_binding` — moved out of the shell with #295) produces ONE ordered
|
||||
plan consumed by BOTH halves of the old weld: the columns are opened
|
||||
(`aura_ingest::open_columns`, the generalization of `open_ohlc`/#92) and the
|
||||
wrapped root roles declared (`aura-runner::member`'s `wrap_r`) in the **same
|
||||
canonical order** — `M1Field` declaration order (open, high, low, close, spread,
|
||||
volume), filtered to the consumed set — which is the C4 merge tie-break order,
|
||||
so role i receives source i by construction. A close column is always part of
|
||||
@@ -2544,7 +2561,7 @@ the binding VALUE-space grows additively from archive columns to recorded-stream
|
||||
references — a root role like `sentiment` becomes bindable to a recorded stream
|
||||
then, and until then refuses with the vocabulary-naming message. The role-name
|
||||
key-space and the campaign `bindings` carrier are unchanged by that growth.
|
||||
**Why.** The single-price weld (`wrap_r`'s hard-wired `price`←close and the six
|
||||
**Why.** The single-price weld (`aura-runner::member`'s `wrap_r`'s hard-wired `price`←close and the six
|
||||
`M1Field::Close`-only open sites) made every strategy monocular regardless of
|
||||
what its blueprint declared; binding by role name keeps the blueprint the single
|
||||
source of its own data needs (C24: topology-as-data carries its input contract),
|
||||
@@ -2625,19 +2642,32 @@ outer:
|
||||
Beside the ladder stands the **process column** — the research-process machinery
|
||||
(the run registry C18, the process/campaign document types, campaign execution).
|
||||
It consumes run *artifacts*, not market streams, and orchestrates runs of any
|
||||
ladder layer; it stands beside the ladder, not on a rung. The **shell** (the
|
||||
`aura` CLI) imports everything and is imported by nothing.
|
||||
ladder layer; it stands beside the ladder, not on a rung. Between ladder/column
|
||||
and the shell stands the **assembly** position (`aura-runner`, #295): it
|
||||
composes the rungs into the canonical member-run recipe — harness assembly,
|
||||
input binding (C26), the C1-load-bearing param↔config translators, and the
|
||||
shipped default `MemberRunner` — importing the ladder rungs, `aura-composites`,
|
||||
`aura-ingest`, and the process column, and imported only by the shell and by
|
||||
downstream World programs. The **shell** (the `aura` CLI) imports everything,
|
||||
is imported by nothing, exports nothing, and holds no domain logic:
|
||||
argv/dispatch, argv→document translation, and presentation only (rendering
|
||||
stays in the shell until the C22 web face provides its second consumer — #295
|
||||
deferral).
|
||||
|
||||
**Import rule.** An outer ladder layer may import inner layers, never the
|
||||
reverse; *measurement* and *strategy* are siblings (no import either way);
|
||||
*backtest* may import *strategy*. The process column imports the engine layer
|
||||
plus the run-artifact and metric interfaces, and is imported by no ladder crate;
|
||||
column-internal edges are free. The shell imports all; nothing imports the
|
||||
shell. **`dev-dependencies` are exempt** — tests may cross layers (the existing
|
||||
`engine`/`ingest`/`registry` → `std` edges are dev-only and stay). The rule
|
||||
binds **crate structure, not graph composition**: a blueprint may feed a
|
||||
measurement statistic into a bias input — data flow inside a graph is free (C24);
|
||||
layers govern imports, graphs compose freely.
|
||||
plus the run-artifact and metric interfaces — realized since #291/#292 as a
|
||||
production dependency on `aura-backtest` (the trading instantiation
|
||||
`M = RunMetrics`) — and is imported by no ladder crate; column-internal edges
|
||||
are free. The assembly position imports ladder and column alike and is
|
||||
imported by neither; the shell imports all; nothing imports the shell — both
|
||||
now enforced by the full-workspace `c28_layering` table plus its shell-content
|
||||
check (#295). **`dev-dependencies` are exempt** — tests may cross layers (the
|
||||
existing `engine`/`ingest`/`registry` → `std` edges are dev-only and stay).
|
||||
The rule binds **crate structure, not graph composition**: a blueprint may
|
||||
feed a measurement statistic into a bias input — data flow inside a graph is
|
||||
free (C24); layers govern imports, graphs compose freely.
|
||||
|
||||
**Forbids.** An inner layer importing an outer one — most sharply the engine
|
||||
layer importing backtest reductions, or market importing strategy. A ladder crate
|
||||
@@ -2719,9 +2749,16 @@ cleanly by layer, so the layering is realized only partially:
|
||||
`aura-backtest`, the statistics kernel to `aura-analysis`, dependency
|
||||
inversion, ladder enforced by the structural test; realizes item 1 of #147);
|
||||
(3) the #286
|
||||
shape dispatch plus the per-run scaffold as a library (seeds an `aura-backtest`
|
||||
crate, gives *measurement* its run verb, removes the measured O(cycles) run-time
|
||||
retention); (4) split the `aura-std` roster along engine / market / strategy /
|
||||
shape dispatch plus the per-run scaffold as a library — **done** (#295: the
|
||||
pure per-run scaffold pieces live in `aura-backtest::scaffold`; the composed
|
||||
recipe — harness assembly, binding, translators, the default `MemberRunner`
|
||||
— is the assembly crate `aura-runner`; the measurement rung is seeded as
|
||||
`aura-measurement` with the IC; the shell is reduced to
|
||||
argv/translation/presentation, enforced structurally. Residual: ~20 refusal
|
||||
sites inside `aura-runner`'s single-run verb paths still terminate the
|
||||
process; their conversion to `RunnerError` propagation is tracked as #297 —
|
||||
the campaign path already refuses via `MemberFault`, never a process exit);
|
||||
(4) split the `aura-std` roster along engine / market / strategy /
|
||||
backtest — **done** (#288: four `aura-core`-only node crates, the closed roster
|
||||
moved to `aura-vocabulary`, the ladder direction enforced by a structural test);
|
||||
(5) split `aura-analysis` into generic statistics and backtest metrics —
|
||||
@@ -2731,6 +2768,12 @@ cleanly by layer, so the layering is realized only partially:
|
||||
names now realized (`aura-market`/`aura-strategy`/`aura-backtest`/
|
||||
`aura-vocabulary`); full evidence on #288, #286 and the milestone.
|
||||
|
||||
Provenance note (#295): the shell-boundary cut closes a ratified structural
|
||||
debt (this contract's own phase plan) and un-blocks the future World program;
|
||||
it was not a demonstrated downstream blocker — the first downstream project's
|
||||
observed friction was document-vocabulary gaps, never Rust-level recipe
|
||||
reachability.
|
||||
|
||||
---
|
||||
|
||||
## Open architectural threads not yet resolved
|
||||
|
||||
Reference in New Issue
Block a user