feat(0074): source real-path pip from the geometry sidecar; drop the authored floor

The data-server now ships per-symbol geometry sidecars, so aura no longer
hard-codes instrument geometry. A consumption grep showed production reads
exactly one `InstrumentSpec` field — `pip_size` — at the real-data path; the
other eight (incl. `instrument_id`) were constructed but never read.

- aura-cli resolves the real-path pip from the recorded sidecar
  (`instrument_geometry` -> `InstrumentGeometry.pip_size`), refusing (exit 2)
  on absent geometry. The authored table no longer gates: any symbol with a
  sidecar + bars now runs (new test: USDJPY, never vetted, resolves its JPY
  pip 0.01 from the sidecar).
- Removed the redundant authored floor: `InstrumentSpec`, `instrument_spec`,
  `VETTED_SYMBOLS`, and the table-only tests. The `InstrumentGeometry` seam
  (the surviving pip source) and its nameability guard are kept.
- `instrument_id` (the "find out"): no production consumer. The position-event
  table's `instrument_id` is a decoupled caller parameter; the engine never
  imports an instrument spec. Dropped with the struct.
- The example `pip_size_of` is re-sourced to the sidecar; the pure-structural
  blueprint tests use a literal pip to stay archive-independent.

Speculative deploy-grade fields and the #124 override/floor tiers are deferred
to the Stage-2 broker that will consume them, read from the sidecar geometry
then. Ledger (C8/C15/#22/#106) updated; #124 collapses to "recorded sidecar
geometry -> refuse" in the meantime.

Verified: cargo test --workspace (all green), clippy -D warnings clean, cargo
doc clean, with the local archive present so the sidecar paths run.

refs #124
This commit is contained in:
2026-06-25 19:06:12 +02:00
parent 4fd047adf3
commit 7e4b91ab5f
11 changed files with 198 additions and 464 deletions
+30 -26
View File
@@ -602,11 +602,14 @@ table (buy/sell/close, `position_id`, partial closes) from the exposure history,
and the realistic broker nodes that consume it — is deliberately **not** built
this cycle; it remains the decoupled, derived, deferred layer described above.
**Realization (per-instrument pip channel, 2026-06, #22).** `SimBroker`'s
`pip_size` is now sourced **per instrument**, not from one global literal. A typed
`InstrumentSpec { pip_size }` + `instrument_spec(symbol) -> Option<InstrumentSpec>`
lookup — a Rust-authored vetted table in `aura-ingest`, at the ingestion/source
edge where the symbol still exists (never `Aura.toml`, never `Ctx`) — supplies the
divisor; the engine stays domain-free (no instrument identity reaches the hot path).
`pip_size` is now sourced **per instrument**, not from one global literal. The
divisor is resolved from the recorded geometry sidecar (`instrument_geometry`, over
data-server's `symbol_meta`), at the ingestion/source edge where the symbol still
exists (never `Aura.toml`, never `Ctx`); the engine stays domain-free (no instrument
identity reaches the hot path). (The original cycle-0022 form was a Rust-authored
vetted floor `InstrumentSpec { pip_size }` + `instrument_spec(symbol)`; cycle 0074
removed that floor — see the C15 note below — once the sidecar geometry made it
redundant for the real path. Refuse-don't-guess on absent geometry.)
**Realization (position-event schema, cycle 0063, #114).** The position-management
half's **schema** now landed (its derivation and the brokers remain deferred): a
closed `PositionAction { Buy, Sell, Close }` enum + the `PositionEvent` row
@@ -706,7 +709,8 @@ stop-then-same-cycle reopen) emitting **Close then the opposite open at one `eve
table, not a per-`eval` output). The close sizes the **actual book** (the closed
position's stored volume), never an exposure delta — the post-reframe replacement for the
rolled-back 0064 exposure-integral derive (#117). `instrument_id` is a caller-supplied
scalar (`aura-engine` depends only on `aura-core`, so it never imports `InstrumentSpec`).
scalar (`aura-engine` depends only on `aura-core`, so it never imports an instrument
spec from `aura-ingest`).
A position open at window end emits its open with **no synthetic `Close`** (the table
records actual executed events; `summarize_r`'s force-close is for the R metric only).
The `r_col` ⟷ PM-record lockstep is now guard-pinned for `direction` too. **Still #116:**
@@ -812,26 +816,25 @@ session open" is then a plain node checking `bars_since_open == 3`.
stream model.
**Why.** Keeps the line consistent — everything a signal needs arrives as a
stream; reference data feeds source/session nodes from beside the hot path.
**Realization (instrument specs, 2026-06, #22).** The "instrument specs are
metadata" half of this contract is first realized by `aura-ingest`'s
`InstrumentSpec` (initially a single `pip_size`) + `instrument_spec(symbol)`
non-scalar reference data held beside the hot path, keyed by symbol, feeding the
sim-optimal broker's pip divisor (C10). Extended in cycle 0063 (#113) to a six-field
deploy-grade floor (`instrument_id`, `contract_size`, `pip_value_per_lot`, `min_lot`,
`lot_step`, `quote_currency`) for the realistic broker's currency conversion — the
permanent authored floor of the override hierarchy (#124), the refuse-don't-guess
arm preserved. NB: `quote_currency` is `&'static str` (keeps the struct `Copy`); how
the #124 resolver's runtime-sourced tier carries currency (a distinct resolved type,
or widening the field) is that cycle's decision — see #124. Cycle 0073 (#143)
appended `tick_size` + `digits` (provider price-rounding geometry; still additive and
`Copy`) and surfaced the **recorded-metadata tier-2 source** at the ingestion edge:
**Realization (instrument specs, 2026-06, #22 → #124).** The "instrument specs are
metadata" half of this contract is realized by the **recorded geometry sidecar**:
`instrument_geometry(server, symbol)`, over data-server's `symbol_meta`, returns
neutral broker-agnostic `InstrumentGeometry` (the raw provider JSON never enters this
repo), and a build/test-time cross-check pins the authored floor against that provider
truth for the vetted set. The geometry is an untrusted input the authored override
supersedes — non-scalar metadata beside the hot path, never a `Source`. The
tier-*composing* resolver, and the `quote_currency` runtime-type transition, remain
#124's.
repo) — non-scalar reference data held beside the hot path, keyed by symbol, feeding
the sim-optimal broker's pip divisor (C10). The real-path pip is sourced from
`InstrumentGeometry.pip_size`; refuse-don't-guess on absent geometry. **History:**
cycles 0022/0063 first carried a Rust-authored vetted floor (`InstrumentSpec` — a
single `pip_size`, later a six-field deploy-grade row `instrument_id`,
`contract_size`, `pip_value_per_lot`, `min_lot`, `lot_step`, `quote_currency`, plus
`tick_size`/`digits`), cross-checked against the sidecar geometry. **Cycle 0074
removed that floor**: with the sidecar geometry supplying the real-path pip, the
authored table was redundant, so `InstrumentSpec` / `instrument_spec` / the vetted
list were deleted. The speculative deploy-grade fields and the override/floor tiers
of the #124 hierarchy (tier 1 authored override, tier 3 authored floor) are
**deferred** until a consumer — the Stage-2 realistic broker — needs them, read from
the sidecar geometry then. The `quote_currency` runtime-type transition is likewise
deferred to that consumer; #124 collapses to **recorded sidecar geometry → refuse**
in the meantime.
### C16 — Engine / project separation; three-tier node reuse
**Guarantee.** aura is the reusable **engine**; each research project is a
@@ -1233,8 +1236,9 @@ families-comparison amendment below).
`M1FieldSource` seam — C6 record-then-replay: a pre-recorded archive, never a live
call mid-sim) instead of the built-in synthetic stream, per family member. A
CLI-side `DataSource` provider (synthetic | real) supplies each member's source,
pip (`instrument_spec` — C10 refuse-don't-guess; an un-vetted symbol exits 2 before
any data access), window, and — for walk-forward — its `WindowRoller` sizes
pip (resolved from the recorded geometry sidecar (`instrument_geometry`) — C10
refuse-don't-guess; a symbol with no recorded geometry exits 2 before any data
access), window, and — for walk-forward — its `WindowRoller` sizes
(synthetic: bar-index 24/12/12; real: fixed calendar-time 90d/30d/30d in ns; CLI
flags for these are deferred). The engine, ingest, and registry are untouched (C9 —
the whole change is in `aura-cli`); the synthetic path is byte-unchanged.