# 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.
