feat(cli,ledger): supply CLI run sources by role key; ledger note
closes #275 The CLI half of by-name source binding, plus the ledger record. Every production run site that carries a ResolvedBinding — `run_signal_r`, `run_blueprint_member` (sweep / reproduction), and the campaign re-run/trace path — now keys its opened sources by role name via `key_supply(binding, sources)` and drives the harness through `Harness::run_bound` instead of the positional `run(sources)`. `key_supply` pairs each opened column with its declared role from `binding.entries()` — the one place open-order and role-order meet, made explicit so `bind_sources` verifies the wiring↔supply role match by name rather than by a maintained canonical-order convention. Because the current single-binding CLI derives both the `SourceSpec` roles (via `wrap_r`) and the supply roles (via `key_supply`) from the same `binding.entries()`, the bind cannot fail on this path — so the call site asserts the invariant with `.expect`, matching the adjacent `close_handle.expect("ResolvedBinding guarantees a close entry")` idiom. The named `SourceBindError` refusal path lives in `bind_sources` for future decoupled-supply callers (independently-built multi-feed / recorded sources, #124), where a mismatch becomes reachable. Ledger: a C4 realization note (supply resolved by name into declaration order, so supply order is no longer load-bearing; the tie-break guarantee is unchanged) and a scoped C23 refinement (a `SourceSpec.role` is load-bearing for source binding; every other flat-graph name stays a non-load-bearing raw-index symbol). The fieldtest-corpus `SourceSpec` sweep (planned Task 5) was reverted: the fieldtest packages already fail to build against the current engine API for reasons unrelated to `SourceSpec` (bootstrap arity, removed `InputSpec`, drifted `Recorder`/`SimBroker`/`RMetrics`, renamed `Scalar` helpers) — pre-existing bit-rot from earlier cycles. A partial `SourceSpec` migration neither revives nor further breaks them, so the scope decision to touch them (premised on their being otherwise-buildable) was withdrawn; reviving the corpus is separate from #275. Verification: `cargo test --workspace` green (0 failed; the real-data OHLC channel e2e exercises the migrated `run_bound` path byte-identically); `cargo build --workspace --all-targets` clean; `cargo clippy --workspace --all-targets -D warnings` clean.
This commit is contained in:
@@ -160,6 +160,16 @@ multiple sources) break by source declaration order.
|
||||
either wastes empty cycles or clumps ticks. Backtest and live differ only in the
|
||||
origin of records, not the cycle semantics. Tie determinism preserves C1.
|
||||
|
||||
**Realization (#275, 2026-07-15).** Ingestion sources are supplied to `run` **by
|
||||
role name**, not by list position. `SourceSpec` carries a `role: Option<String>`
|
||||
(the bound `Role`'s name, load-bearing for source binding), and `Harness::run_bound`
|
||||
resolves a keyed supply against those roles, emitting sources in `SourceSpec`
|
||||
declaration order. The C4 tie-break stays "source declaration order" — now
|
||||
independent of how the caller orders the supply — and a mis-bound feed is a named
|
||||
`SourceBindError` at start time rather than a silently wrong run. The raw-index
|
||||
`run(Vec)` primitive (positional, C23) is unchanged; every hand-built graph keeps
|
||||
`role: None`.
|
||||
|
||||
### C5 — Freshness-gated recompute and sample-and-hold
|
||||
**Guarantee.** The `cycle_id` advances everywhere (a cheap counter), but a node
|
||||
re-evaluates only when ≥1 of its own inputs is fresh this cycle (detected by
|
||||
@@ -1658,6 +1668,12 @@ cdylib** rebuild (C12/C13: the cdylib loads once); re-deriving an instance per
|
||||
param-set is a cheap **graph re-compilation**, not a code recompile. Naming the
|
||||
build phase a compilation makes its successor explicit: the flat graph is the target
|
||||
of behaviour-preserving optimisation (C23).
|
||||
**Refinement (#275, 2026-07-15).** One narrow exception to "role names demoted to
|
||||
non-load-bearing": a `SourceSpec.role` (the lowered bound-`Role` name) is
|
||||
**load-bearing for source binding** — the key `Harness::run_bound` / `bind_sources`
|
||||
resolve a keyed source supply against. Every other flat-graph name (edges, ports,
|
||||
composite boundaries) stays a non-load-bearing debug symbol; the raw-index
|
||||
positional `run` path carries no role.
|
||||
**Realization (cycle 0016 — param-set injection).** The bootstrap now binds an
|
||||
injected param-set, realizing C12's "params injected at graph build (the optimizer
|
||||
sees a generic vector of typed ranges)" and C19's "factory `params → sized node`"
|
||||
|
||||
Reference in New Issue
Block a user