Files
Aura/docs/specs/fieldtest-milestone-walking-skeleton.md
T
Brummel 4fac529de0 fieldtest: milestone walking-skeleton — 3 e2e scenarios, delivers end-to-end
Milestone-scope fieldtest (the functional leg of the Walking-skeleton
milestone-close gate), from the public interface only. Three end-to-end
scenarios, all green:
- the newcomer CLI path: `aura run` -> single-line {manifest,metrics} JSON,
  exit 0, byte-identical twice (C1), non-degenerate trace (C22), bad-args ->
  exit 2;
- the real-data thread: real AAPL.US 2006-08 M1 bars -> load_m1_window ->
  close_stream -> SMA-cross -> Exposure -> SimBroker -> summarize -> RunReport,
  deterministic AND populated;
- epoch-ns coherence: C3 normalization holds ingest -> run -> sink.

Roll-up: the milestone DELIVERS its promise end to end (ingest -> one signal ->
exposure -> sim-optimal broker -> pip-equity metric -> structured RunReport,
deterministic, populated) on BOTH the synthetic and real-data paths. 0 bugs.

Headline concern (verified by the orchestrator): issue #19's premise is WRONG at
the shipped SMA(2)/SMA(4) demo config — 21 AAPL.US bars warm the cross and
produce a populated trace (total_pips=-1.5, max_drawdown=65.5, 6 sign flips),
not all-zero. The degeneracy #19 saw was deep-SMA/param-dependent, not intrinsic
to the symbol. #19 to be re-scoped. Other findings: `aura run <junk>` exit 0
(already #16), `aura --help` lands on the exit-2 error path (friction), SimBroker
two-f64-slot order unchecked at bootstrap (documented footgun) — both filed.
2026-06-04 22:25:01 +02:00

184 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Fieldtest — milestone "Walking skeleton" — 2026-06-04
**Status:** Draft — awaiting orchestrator triage
**Author:** fieldtester (dispatched by fieldtest skill, milestone-scope variant)
**Scope mode:** MILESTONE (closing functional gate), not per-cycle.
## Scope
The "Walking skeleton" milestone (Gitea Brummel/Aura issues #4#8) promises a
runnable end-to-end thread (design ledger INDEX.md ~line 20): **ingest → one
signal (SMA-cross) → exposure/intent stream → sim-optimal broker → synthetic
pip-equity signal-quality metric**, foldable into a structured RunReport
(manifest + metrics, C18/C14), deterministic (C1), reachable via the `aura run`
CLI (#8), and — per C22 — populated enough that "a newcomer sees a populated
trace immediately."
This fieldtest derives three end-to-end scenarios top-down from that promise and
drives them from the **public interface only** (the `aura` binary's observable
behaviour, rustdoc, INDEX.md, public re-exports, data-server's public rustdoc).
No `crates/*/src` was read. The artefact under test was built from HEAD
(`cargo build -p aura-cli`; the consumer crate compiled against the current
path-dep'd engine crates).
## Examples
### fieldtests/milestone-walking-skeleton/ms_1_newcomer_cli.sh — the newcomer CLI path
- Invokes the real `target/debug/aura` binary (built from HEAD) as a downstream
user with nothing but the rustdoc module blurb. Checks: single-line JSON
RunReport with the documented `{manifest, metrics}` shape; exit 0;
byte-identical across two runs (C1); a NON-degenerate trace (≥1 exposure sign
flip, C22); and the bad-args / usage contract.
- Fits the promise: this is the one-command surface the milestone says makes the
whole thread runnable, and the C22 "populated trace" demonstrator.
- Outcome: built? yes. ran? yes. matched expected? **yes** — single-line
`{manifest,metrics}`, exit 0, byte-identical, metrics
`total_pips=-0.13, max_drawdown=0.17, exposure_sign_flips=1` (populated).
Bad/empty subcommand → exit 2, `aura: usage: aura run` on stderr, empty stdout.
### fieldtests/milestone-walking-skeleton/ms_2_real_data_thread.rs — the real-data thread
- A standalone consumer crate (own `[workspace]`, path-deps on
aura-core/std/engine/ingest + git dep on data-server — the shape a C16 project
takes) wires the WHOLE thread over real recorded M1 bars:
`load_m1_window(AAPL.US, 2006-08) → close_stream → SMA(2)/SMA(4) → Sub →
Exposure(0.5) → SimBroker(1e-4) → 2×Recorder → f64_field → summarize →
RunReport`, then folds the report twice and asserts determinism.
- Fits the promise: this is the literal ingest→…→metric thread over REAL bars,
the substance #7 + the milestone claim.
- Outcome: built? **yes, first try.** ran? yes (21 M1 bars ingested). matched
expected? **yes, and better than the carrier predicted** — the run is
deterministic (cross-process byte-identical RunReport, C1) AND **non-degenerate**:
`total_pips=-1.5, max_drawdown=65.5, exposure_sign_flips=6`. Window timestamps
are canonical epoch-ns. See finding [spec_gap] on the #19 premise.
### fieldtests/milestone-walking-skeleton/ms_3_epoch_ns_coherence.rs — epoch-ns coherence
- Hand-builds 4 `M1Parsed` bars (data-server's public AoS record) with known
`time_ms`, runs `transpose_m1 → close_stream → SMA(2) → Recorder`, and asserts
the recorded sink-trace timestamps equal `unix_ms_to_epoch_ns(time_ms)`
(= ms·1e6) — the C3 normalization carried intact from ingest through the run
loop into the recorded metric stream. No external data needed.
- Fits the promise: closes the loop on C3 ("normalize at the one boundary") —
proves the metric stream a newcomer reads is in aura's canonical time unit.
- Outcome: built? yes. ran? yes. matched expected? **yes** — ingest stamps
`[…400e9, …460e9, …520e9, …580e9]`; sink trace is the warmed suffix in the same
epoch-ns stamps.
## Findings
### [working] The full real-data thread is authorable from the public interface and is deterministic + populated
- Example: ms_2_real_data_thread.rs.
- What happened: the entire ingest→signal→exposure→broker→metrics→RunReport thread
compiled on the first attempt from rustdoc signatures alone (Harness::bootstrap,
Edge/Target/SourceSpec field layout, summarize/f64_field, the aura-std node
ctors, load_m1_window/close_stream). Two in-process folds and two separate
processes produced byte-identical RunReports.
- Why working: the milestone's headline promise — a real ingest→metric thread,
deterministic (C1) — is delivered, and the public surface is self-sufficient
for a downstream author to wire it. This is the milestone's central win.
- Recommended action: carry-on.
### [working] `aura run` delivers the C22 populated-trace newcomer path
- Example: ms_1_newcomer_cli.sh.
- What happened: one command, single-line `{manifest,metrics}` JSON, exit 0,
byte-identical twice, non-degenerate (1 sign flip, real drawdown). Bad/missing
subcommand → exit 2 + usage on stderr + empty stdout.
- Why working: C22 ("a newcomer sees a populated trace immediately") and C14
(structured face from a binary) are both satisfied by the shipped binary.
- Recommended action: carry-on.
### [working] C3 epoch-ns normalization is coherent end to end
- Example: ms_3_epoch_ns_coherence.rs.
- What happened: `close_stream` timestamps equal `unix_ms_to_epoch_ns(time_ms)`,
and the recorded sink trace carries exactly those epoch-ns stamps (warmed
suffix). ms·1e6 holds.
- Why working: C3's "one boundary normalizes, nowhere else" is observably true
through ingest → run → sink; the metric stream is in canonical time.
- Recommended action: carry-on.
### [spec_gap] The #19 "AAPL.US too sparse → degenerate metrics" premise does NOT hold for the SMA(2)/SMA(4) demo config
- Example: ms_2_real_data_thread.rs.
- What happened: the carrier (and issue #19, from the cycle-0011 per-cycle
fieldtest) asserts AAPL.US 2006 is too sparse (~21 M1 bars/month) to warm an
SMA-cross, so the real-data run yields all-zero degenerate metrics. **Empirically
this is false for the SMA(2)/SMA(4) cross** (the same fast/slow pair the shipped
`aura run` sample uses): 21 bars warm SMA(4) after 4 bars, the cross produces
**6 exposure sign flips**, `total_pips=-1.5`, `max_drawdown=65.5` — a populated,
non-degenerate trace over REAL bars. The degeneracy #19 observed is
**window/param-dependent** (a deeper SMA, e.g. the longer lengths a realistic
daily cross would use, would not warm on 21 bars), not intrinsic to the symbol.
- Why spec_gap: the milestone never pins the "real-data demo" SMA lengths or
window, so two equally-plausible readings diverge on whether the real-data path
is degenerate. I picked the shipped `aura run` config (SMA 2/4); under it the
real-data thread is **populated**, not degenerate. The honest milestone roll-up
therefore differs from the carrier's pre-stated assumption: the real-data thread
is *also* a populated-trace demonstrator at the shipped param config, not merely
"correct but degenerate." #19's concern remains valid for *deeper* SMAs / the
C22 "name a denser demo symbol" recommendation, but it is not a blocker and the
milestone promise is met on real bars at the demo config.
- Recommended action: ratify (record that the walking-skeleton real-data demo is
pinned to SMA 2/4 over 2006-08 and is populated there) AND re-scope #19 to
"denser demo data for *deep/daily* crosses" rather than "real path is
degenerate" — the latter is no longer accurate.
### [spec_gap] `aura run <trailing junk>` → exit 0, trailing args silently ignored
- Example: ms_1_newcomer_cli.sh (`aura run extra junk` → exit 0, full report).
- What happened: the arg parser keys only on the first token being `run` and
ignores everything after. `aura run garbage` runs the sample harness and exits 0.
- Why spec_gap: re-confirmation at the milestone gate of the cycle-0010 finding
(already filed). The milestone's CLI contract does not unambiguously cover
`run <extra>`; the binary chose the lenient reading. Not a regression — same
behaviour as cycle-0010.
- Recommended action: ratify-or-tighten (decide whether trailing args reject with
exit 2 or are deliberately ignored). Low priority; carried from #?/cycle-0010.
### [friction] `aura --help` lands on the error path (exit 2, bare usage line)
- Example: ms_1_newcomer_cli.sh (`aura --help` → exit 2, `aura: usage: aura run`
on stderr, empty stdout).
- What happened: a newcomer's reflex first command (`--help`) is treated as an
unknown subcommand: exit 2, no help text, just the one-line usage on stderr.
- Why friction: the task (discover how to run) completes — the usage line *does*
name `aura run` — but the conventional discovery affordance returns a nonzero
error path rather than help on stdout. For a "newcomer sees a populated trace"
milestone (C22), the first-contact ergonomics are slightly off.
- Recommended action: plan (tidy) — make `--help`/`-h` print the usage to stdout
with exit 0; keep unknown subcommands at exit 2. Trivial, optional.
### [friction] SimBroker slot order is load-bearing, both f64, unchecked at bootstrap
- Example: ms_2_real_data_thread.rs (had to consult rustdoc to wire slot 0 =
exposure, slot 1 = price correctly).
- What happened: SimBroker's two inputs are both `f64`, so a swapped wiring is not
caught at bootstrap (the rustdoc explicitly warns it "would silently produce a
wrong equity curve"). The downstream author must read prose to get it right;
there is no typed guard.
- Why friction: the thread is wireable correctly *only* by reading the rustdoc
carefully — a known, documented footgun, but a footgun. Not a bug (it is
documented and the wiring API offers no kind to distinguish the two f64 slots).
- Recommended action: plan (consider a named-role or distinct-newtype wiring for
broker inputs in a later cycle); or carry-on if deemed acceptable given the
rustdoc warning. Documented, so low urgency.
## Recommendation summary
| Finding | Class | Action |
|---|---|---|
| Real-data thread authorable, deterministic, populated | working | carry-on |
| `aura run` C22 populated-trace newcomer path | working | carry-on |
| C3 epoch-ns coherence ingest→run→sink | working | carry-on |
| #19 "real path degenerate" false at SMA 2/4 demo config | spec_gap | ratify + re-scope #19 |
| `aura run <junk>` → exit 0 (lenient) | spec_gap | ratify-or-tighten |
| `aura --help` → exit 2, no help text | friction | plan (tidy) |
| SimBroker slot order load-bearing, unchecked | friction | plan / carry-on |
## Milestone roll-up
**The "Walking skeleton" milestone DELIVERS its promise end to end.** The full
thread — ingest → SMA-cross → exposure → sim-optimal broker → pip-equity
metric → structured RunReport — runs deterministically (C1, cross-process
byte-identical), in canonical epoch-ns time (C3), reachable via `aura run`
(#8/C14), and produces a **populated** trace (C22) on **both** the synthetic
sample harness AND the real AAPL.US 2006-08 bars at the shipped SMA(2)/SMA(4)
config. The carrier's pre-stated worry — that the real-data path is correct-but-
degenerate — did not reproduce at the demo configuration; #19's degeneracy is a
deep-SMA / dense-data concern, not a milestone failure. No bugs found. Two
spec_gaps and two friction items, none blocking.