14c43474ab
Source-blind consumer run over the #271 surface: a NY first-bar- momentum Session authored purely as data and run e2e over --real US500; a LinComb{arity:3} blend binding the arity-unlocked weights with the Session period swept (4 members, reproduced 4/4 bit-identically); eight strict-form refusal probes (all exit 1, actionable prose); an args composite registered and use-spliced into a consumer (v2 propagates, ids stable, C29 doc gate holds). Findings routed: Count lexical form + asymmetry ratified into glossary/guide (follow-up commit); introspect dead-end on arg-bearing ports and the missing CostSum wiring path absorbed into #341. refs #271
218 lines
9.4 KiB
Markdown
218 lines
9.4 KiB
Markdown
# Fieldtest transcript — cycle #271 (typed construction args)
|
||
|
||
Verbatim command/output capture for the `fieldtests/construction-args/` fixtures.
|
||
Binary: `target/debug/aura` built from HEAD `6ca359a` via `cargo build --workspace`
|
||
(debug profile). Runs used a scratch project `aura new ca_lab` (in `/tmp/ca_lab`);
|
||
real data resolved from the built-in archive (`/mnt/tickdata/Pepperstone`). All
|
||
op-scripts authored from the public interface only (README, authoring guide,
|
||
glossary, design ledger C24, `aura graph introspect`).
|
||
|
||
Public interface only — no crate source read.
|
||
|
||
---
|
||
|
||
## Discovery loop (axis 3) — is the args grammar learnable from the binary?
|
||
|
||
```
|
||
$ aura graph introspect --vocabulary | wc -l
|
||
36
|
||
|
||
$ aura graph introspect --node Session
|
||
Session — bars elapsed since the session open, from the configured open time and timezone
|
||
arg tz: Tz (IANA timezone name, e.g. Europe/Berlin)
|
||
arg open: TimeOfDay (local wall-clock HH:MM)
|
||
note ports and params form at construction; args are required
|
||
|
||
$ aura graph introspect --node LinComb
|
||
LinComb — linear combination of its inputs with constant weights
|
||
arg arity: Count (positive integer count)
|
||
note ports and params form at construction; args are required
|
||
|
||
$ aura graph introspect --node CostSum
|
||
CostSum — sums cost-model contributions into one cost-in-R stream
|
||
arg n_costs: Count (positive integer count)
|
||
note ports and params form at construction; args are required
|
||
```
|
||
|
||
The arg *grammar* (name, kind, hint) is fully self-describing. But `--node <T>`
|
||
stops at the note — it does NOT reveal the post-construction ports/params. To
|
||
learn the port names you must author a partial op-list carrying the args and pipe
|
||
it through `--unwired`; to learn the param names you must build and `--list-axes`.
|
||
Nothing on the `--node` surface names those follow-up steps. First naive guess at
|
||
LinComb's input port was `lc.in0` — wrong:
|
||
|
||
```
|
||
$ echo '[{"op":"add","type":"LinComb","name":"lc","args":{"arity":"3"}}]' \
|
||
| aura graph introspect --unwired
|
||
lc.term[0]:F64
|
||
lc.term[1]:F64
|
||
lc.term[2]:F64
|
||
|
||
$ echo '[{"op":"add","type":"CostSum","name":"cs","args":{"n_costs":"3"}}]' \
|
||
| aura graph introspect --unwired
|
||
cs.cost[0].cost_in_r:F64
|
||
cs.cost[0].cum_cost_in_r:F64
|
||
cs.cost[0].open_cost_in_r:F64
|
||
cs.cost[1].cost_in_r:F64 (… ×3 slots, 3 fields each)
|
||
```
|
||
|
||
Weight param names, discovered only after a build:
|
||
|
||
```
|
||
$ aura graph build < lc_probe.ops.json > lc_probe.bp.json
|
||
$ aura sweep lc_probe.bp.json --list-axes
|
||
graph.lc.weights[0]:F64 # open by default → sweepable (C24)
|
||
graph.lc.weights[1]:F64
|
||
...
|
||
```
|
||
|
||
---
|
||
|
||
## Example 1 — `ca_1_ny_session` (axis 1: non-Frankfurt Session as data)
|
||
|
||
```
|
||
$ aura graph build < ca_1_ny_session.ops.json > ca_1_ny_session.bp.json
|
||
$ head -c 25 ca_1_ny_session.bp.json
|
||
{"format_version":2,"blue # arg-bearing → v2
|
||
|
||
$ aura graph introspect --content-id --identity-id < ca_1_ny_session.ops.json
|
||
5b085a5b3f411072e48d4b54717b3d09e88be50b0bd797d345c2ee90baa41c37 # content id
|
||
4bf0513a4d2e852ab580fd8846737f57c1825b944ff9df1a48040a07fe92446b # identity id
|
||
|
||
# --- inside ca_lab/ ---
|
||
$ aura run ca_1_ny_session.bp.json --real US500 --from 1725148800000 --to 1725580800000
|
||
{"manifest":{... "topology_hash":"5b085a5b...b40d95cf"? -> 5b085a5b... (== content id) ...},
|
||
"metrics":{... "expectancy_r":0.7853745294474523,"n_trades":18 ...}} (exit 0)
|
||
|
||
# synthetic refuses cleanly (OHLC strategy, close-only synthetic stream):
|
||
$ aura run ca_1_ny_session.bp.json
|
||
aura: strategy "graph" consumes columns beyond close (open, high, low) —
|
||
synthetic data generates a close series only; run with --real <SYMBOL>
|
||
```
|
||
|
||
Full report captured in `ca_1_ny_session.run.json`.
|
||
|
||
---
|
||
|
||
## Example 2 — `ca_2_lincomb_blend` (axis 2: LinComb arity + weights + swept period)
|
||
|
||
Three SMA spreads blended through `LinComb(arity 3)` with bound `weights[i]`,
|
||
NY-session-gated, `Session.period_minutes` left OPEN (sweepable).
|
||
|
||
```
|
||
$ aura graph build < ca_2_lincomb_blend.ops.json > ca_2_lincomb_blend.bp.json
|
||
$ head -c 25 ca_2_lincomb_blend.bp.json
|
||
{"format_version":2,"blue
|
||
|
||
$ aura sweep ca_2_lincomb_blend.bp.json --list-axes
|
||
graph.sess.period_minutes:I64 # open
|
||
graph.lc.weights[0]:F64 default=0.5 # bound (re-openable by --axis)
|
||
graph.lc.weights[1]:F64 default=0.3
|
||
graph.lc.weights[2]:F64 default=0.2
|
||
...
|
||
|
||
# --- inside ca_lab/ --- sweep the arity-unlocked weight AND the period param:
|
||
$ aura sweep ca_2_lincomb_blend.bp.json --real US500 --from 1725148800000 --to 1725580800000 \
|
||
--axis graph.sess.period_minutes=15,30 --axis 'graph.lc.weights[0]=0.3,0.5' --name ca2_blend
|
||
{"family_id":"caa3508a-0-US500-w0-r0-s0-0", ... 4 members ...} (exit 0)
|
||
|
||
$ aura reproduce caa3508a-0-US500-w0-r0-s0-0
|
||
... member graph.lc.weights[0]=0.3, graph.sess.period_minutes=15 ... reproduced: bit-identical
|
||
... (×4)
|
||
reproduced 4/4 members bit-identically
|
||
```
|
||
|
||
Sweep output in `ca_2_lincomb_blend.sweep.jsonl`. NB: at this gating, the two
|
||
`weights[0]` values yield identical member metrics (the gated blend's sign is
|
||
weight-insensitive here) — a semantic property of the strategy, not the arg
|
||
channel; the params bound and swept correctly.
|
||
|
||
CostSum arity probe: `ca_2b_costsum_arity.ops.json` → `--unwired` shows
|
||
`cost[i].{cost_in_r,cum_cost_in_r,open_cost_in_r}` (3 slots × 3 fields). Wiring
|
||
CostSum end to end needs the RiskExecutor context (cost nodes take
|
||
`closed/open/entry_price/stop_price`) — no op-script path for that exists in the
|
||
public corpus (see finding SG2).
|
||
|
||
---
|
||
|
||
## Example 3 — refusal battery (axis 4: strict-form refusal prose)
|
||
|
||
Every case: `aura graph build < FIXTURE`, stderr + exit code.
|
||
|
||
```
|
||
ca_3a_bad_tz aura: op 1 (add): node sess arg "tz" expects Tz (IANA timezone name, e.g. Europe/Berlin) — got "berlin" exit 1
|
||
ca_3b_unpadded_time aura: op 1 (add): node sess arg "open" expects TimeOfDay (local wall-clock HH:MM) — got "9:30" exit 1
|
||
ca_3c_zero_count aura: op 2 (add): node lc arg "arity" expects Count (positive integer count) — got "0" exit 1
|
||
ca_3d_garbage_count aura: op 1 (add): node lc arg "arity" expects Count (positive integer count) — got "three" exit 1
|
||
ca_3e_missing_arg aura: op 1 (add): node sess is missing required arg "tz" exit 1
|
||
ca_3f_args_on_argless aura: op 1 (add): node a takes no construction args exit 1
|
||
ca_3g_unknown_arg_key aura: op 1 (add): node sess has no construction arg "region" exit 1
|
||
ca_3h_partial_args aura: op 1 (add): node sess is missing required arg "open" exit 1
|
||
```
|
||
|
||
Edge-form strictness (ad-hoc, `--unwired`):
|
||
|
||
```
|
||
Count arity: "3"→ok "03"→refuse "+3"→refuse "3.0"→refuse "1e1"→refuse "-2"→refuse " 3"→refuse "0x3"→refuse
|
||
Time open: "09:30"→ok "00:00"→ok "23:59"→ok "24:00"→refuse "09:60"→refuse "9:05"→refuse "09:5"→refuse "09:30:00"→refuse "0930"→refuse
|
||
```
|
||
|
||
Note the padding asymmetry: `open` REQUIRES a zero-padded hour (`09:05`), but
|
||
`arity` REFUSES a leading zero (`03`). See finding SG1.
|
||
|
||
---
|
||
|
||
## Example 4 — `ca_4` register → use (axis 5: #317 interplay)
|
||
|
||
```
|
||
$ aura graph build < ca_4_ny_anchor_pattern.ops.json > ca_4_ny_anchor_pattern.bp.json
|
||
$ head -c 25 ca_4_ny_anchor_pattern.bp.json
|
||
{"format_version":2,"blue
|
||
$ aura graph introspect --content-id --identity-id < ca_4_ny_anchor_pattern.ops.json
|
||
d51132463b2d1780b3ed9b83dc9f9a229a9d6b93fce3e15c7c0572970e2e4564
|
||
863c89ddeaa2dfe7d79c7e55944263145399c67397a27c0955bdd768cc6ed72e
|
||
|
||
# --- inside ca_lab/ ---
|
||
$ aura graph register .../ca_4_ny_anchor_pattern.bp.json --name ny_anchor
|
||
registered blueprint d51132463b2d... (.../runs/blueprints/d51132463b2d....json)
|
||
label "ny_anchor" -> d51132463b2d...
|
||
|
||
$ aura graph introspect --registered
|
||
ny_anchor d51132463b2d NY cash-open session anchor: bars elapsed since the 09:30 America/New_York open
|
||
|
||
$ aura graph build < ca_4_consumer.ops.json > consumer.bp.json
|
||
# stderr: aura: note: use "anchor": ny_anchor -> d51132463b2d...
|
||
$ head -c 25 consumer.bp.json
|
||
{"format_version":2,"blue # v2 propagates THROUGH the splice
|
||
$ aura graph introspect --content-id --identity-id < ca_4_consumer.ops.json
|
||
985991f62cc6b92895018312c5ea86e493ef1c09dd53cf6e0813551baa97b671
|
||
bbe7060f4136255e594e1b01242ae80c3f5decfc543f23198d66adff6ce52a7b
|
||
|
||
$ aura run consumer.bp.json --real US500 --from 1725148800000 --to 1725580800000
|
||
{"manifest":{... "topology_hash":"985991f6..." (== content id),
|
||
"defaults":[["graph.anchor.sess.period_minutes",{"I64":15}], ...] ...},
|
||
"metrics":{... "n_trades":8 ...}} (exit 0)
|
||
|
||
# doc gate on the args-bearing composite (doc stripped):
|
||
$ aura graph register ca4_docless.bp.json --name ny_docless
|
||
aura: blueprint: composite `graph` carries no doc — a registered composite
|
||
describes itself (C29); add a doc line (...) before register exit 1
|
||
```
|
||
|
||
Consumer report captured in `ca_4_consumer.run.json`.
|
||
|
||
---
|
||
|
||
## Cross-cutting confirmations
|
||
|
||
```
|
||
# args-free document stays format_version 1 (byte-stability invariant, C18):
|
||
$ echo '[{"op":"source",...},{"op":"add","type":"SMA",...},...]' | aura graph build | head -c 25
|
||
{"format_version":1,"blue
|
||
|
||
# content id deterministic across builds:
|
||
$ aura graph introspect --content-id < ca_1_ny_session.ops.json (×2) -> identical
|
||
5b085a5b3f411072e48d4b54717b3d09e88be50b0bd797d345c2ee90baa41c37
|
||
5b085a5b3f411072e48d4b54717b3d09e88be50b0bd797d345c2ee90baa41c37
|
||
```
|