4fac529de0
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.
184 lines
11 KiB
Markdown
184 lines
11 KiB
Markdown
# 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.
|