Milestone-close gate for milestone 37 (data-authorability boundary,
#310/#317/#271): source-blind consumer fieldtest against the release
binary at eb2b0a1, scenarios derived top-down from the milestone
promise rather than per-cycle axes.
- m37_1: NY Session authored via args + fold-selected taps, run e2e
over US500 (default and --tap plans; summaries correct, unlisted
tap inert).
- m37_2: London anchor registered by name, spliced via use into a
consumer with open SMA lengths, swept over GER40, reproduced 2/2
bit-identical (v2 propagates through the splice).
- m37_3a-e: five-way boundary-refusal battery; all exit 1 with
actionable prose, escalation path named for namespaced types.
Gate verdict: green — all three boundary mechanisms deliver the
promise; genuinely-new logic is turned away toward Rust. Findings
routed: fold-summary read-back absorbed into #309, cross-run tap-file
lifecycle evidence onto #311, bare-refusal escalation-pointer parity
onto #341 (refs #309, refs #311, refs #341).
6.5 KiB
Fieldtest transcript — milestone-37 (data-authorability boundary)
Milestone-scope field test: the three data-authorability sites as ONE downstream story — fold selection as run-mode data (#310), a registered composite spliced by name (#317), construction args configuring non-scalar structure (#271) — and the boundary refusing what stays Rust-only.
Binary: target/release/aura, built from HEAD eb2b0a1 via
cargo build --workspace --release (Finished in 5.53s, incremental — HEAD
builds clean). Scratch project aura new m37_lab in /tmp/m37_lab; real data
from the built-in Pepperstone archive. Public interface only (README,
authoring-guide, glossary, design ledger, aura … --help, graph introspect) —
no crate source read.
Scenario 1 — m37_1_ny_momentum — Session args + fold-selected taps, e2e
A NY first-session-bar momentum strategy authored purely as data: Session
configured to America/New_York / 09:30 through the args channel, gating a
SMA(5)−SMA(20) sign onto the first 15m session bar. Four declared taps
(spread, first_bar, gated_signal, slow_ma).
$ aura graph build < m37_1_ny_momentum.ops.json > m37_1_ny_momentum.bp.json
$ head -c 25 m37_1_ny_momentum.bp.json
{"format_version":2,"blue # arg-bearing Session -> v2
$ aura graph introspect --params m37_1_ny_momentum.ops.json
# (empty = closed, runnable)
$ aura graph introspect --content-id --identity-id < m37_1_ny_momentum.ops.json
c8e123f0a8948034592eb5b15f32e9a3d6b0705c4c942e7563f655faa0d1e9f1
31de7ebd09122b9cef690618dbbdc08257056745b948840734982cd62a611265
# default plan (record all four taps):
$ aura run m37_1_ny_momentum.bp.json --real US500 --from 1725148800000 --to 1725580800000
{"manifest":{... "topology_hash":"c8e123f0..." ...},"metrics":{"total_pips":-2.099...,
"r":{"expectancy_r":0.1566...,"n_trades":10, ...}}} (exit 0, no stderr)
# fold-selected plan: spread=mean, first_bar=count, gated_signal=last; slow_ma unlisted
$ aura run m37_1_ny_momentum.bp.json --real US500 --from 1725148800000 --to 1725580800000 \
--tap spread=mean --tap first_bar=count --tap gated_signal=last
{"manifest":{...IDENTICAL manifest+metrics as the default run...}} (exit 0)
# stderr: aura: note: declared tap "slow_ma" unbound this run
The fold summary rows (the reason to pick a fold over record) land ONLY in
the trace store, not on the run's stdout (see m37_1_fold_summary_rows.txt):
runs/traces/graph/index.json "taps":["spread","first_bar","gated_signal"] # slow_ma excluded
spread.json {"tap":"spread","kinds":["F64"],"ts":[...],"columns":[[-0.2033544...]]} # mean
first_bar.json {"tap":"first_bar","kinds":["I64"],"ts":[...],"columns":[[5239.0]]} # count = warm rows
gated_signal.json {"tap":"gated_signal","kinds":["F64"],"ts":[...],"columns":[[0.0]]} # last
aura run prints only manifest+metrics; aura chart graph emits HTML (exit 0),
index-gated (the stale slow_ma.json from the default run lingers on disk but
is NOT in the index and does NOT leak into the chart). There is no CLI verb that
prints a fold's scalar summary as text. (Findings F1, SG1.)
Scenario 2 — m37_2 — registered composite spliced by name + args, swept
A London-open session anchor (open input pattern, Session → Europe/London
/ 08:00 via args) registered under a label, then spliced by name into a
swept consumer.
$ aura graph build < m37_2_london_anchor.ops.json > m37_2_london_anchor.bp.json # v2
$ aura graph register m37_2_london_anchor.bp.json --name london_anchor
registered blueprint 2deeddd943c9...
label "london_anchor" -> 2deeddd943c9...
$ aura graph introspect --registered
london_anchor 2deeddd943c9 London cash-open session anchor: bars elapsed since the 08:00 Europe/London open
$ aura graph build < m37_2_consumer.ops.json > m37_2_consumer.bp.json
# stderr: aura: note: use "anchor": london_anchor -> 2deeddd943c9...
$ head -c 25 m37_2_consumer.bp.json
{"format_version":2,"blue # v2 propagates THROUGH the splice
$ aura graph introspect --content-id --identity-id < m37_2_consumer.ops.json
38369f968b9c10e6a56bca6ac1c347955492e4f58b125510cb09f4609502ad46
f964f3b0dadb8d04e73696bc61119222755c7feef81c55e35e5b85b91bcee7ec
$ aura sweep m37_2_consumer.bp.json --list-axes
graph.fast.length:I64
graph.slow.length:I64
graph.anchor.sess.period_minutes:I64 default=15 # spliced-instance param, path-qualified
...
$ aura sweep m37_2_consumer.bp.json --real GER40 --from 1725148800000 --to 1725580800000 \
--axis graph.fast.length=5,10 --axis graph.slow.length=20 --name m37_london
# 2 members, exit 0
$ aura reproduce d5259c94-0-GER40-w0-r0-s0-0
... member graph.fast.length=5, ... reproduced: bit-identical
... member graph.fast.length=10, ... reproduced: bit-identical
reproduced 2/2 members bit-identically
Everything worked first try. (Finding W3.)
Scenario 3 — the boundary refuses what stays Rust-only
# genuinely-new logic as a namespaced type -> refused, NAMES the Rust escalation verb
$ aura graph build < m37_3a_new_logic.ops.json
aura: op 2 (add): unknown node type "my_lab::ThirdCandle" — type id looks
project-namespaced but this project binds no node crate — attach one
with `aura nodes new <name>` (exit 1)
# same, but bare (un-namespaced) type -> refused, but NO escalation pointer
$ echo '[...{"op":"add","type":"ThirdCandle",...}...]' | aura graph build
aura: op 1 (add): unknown node type "ThirdCandle" (exit 1) # F2
# arg-bearing type entered half-configured -> MissingArg
$ aura graph build < m37_3b_session_no_args.ops.json
aura: op 2 (add): node sess is missing required arg "tz" (exit 1)
# construction args on an arg-less type -> refused
$ aura graph build < m37_3c_args_on_argless.ops.json
aura: op 2 (add): node fast takes no construction args (exit 1)
# a fold that is not a registered fold -> roster-enumerating refusal
$ aura run m37_1_ny_momentum.bp.json --real US500 --from ... --to ... --tap spread=median
aura: unknown fold 'median' — available: count, first, last, max, mean, min, record, sum (exit 1)
# splice a composite that was never registered -> refused, enumerates labels
$ aura graph build < m37_3e_unknown_label.ops.json
aura: op 2 (use "anchor"): no registered blueprint labeled "tokyo_anchor"
— registered labels: london_anchor (exit 1)
Every boundary holds: exit 1, actionable prose. (Finding W4.)