fieldtest: bound-override cycle — 4 examples, 6 findings (4 working, 1 friction, 1 bug)
Per-cycle fieldtest over the #246 surface, consumer-perspective, public interface only: the scaffold quickstart end to end (aura new -> run -> --list-axes -> override sweep), --list-axes on a partially-open blueprint, an override family reproduced bit-identically (3/3 members), and the error surface (wrong axis name, kind-mismatched value — both exit 2). Corpus under fieldtests/cycle-246-bound-override/. Dispositions: the one bug (F6) is fixed in this commit — authoring-guide §1 still asserted a bound param 'never shows up in --list-axes' and 'no aura sweep --axis can reopen it', contradicting the shipped #246 semantics and the C12 amendment; the three-states paragraph now reads open = must-bind, bound = overridable default. The friction finding (F5, KindMismatch/MissingKnob printed as raw Debug structs beside polished prose) is filed as #247. refs #246
This commit is contained in:
@@ -259,14 +259,16 @@ purpose — three open campaign axes, see §3. This is the milestone fieldtest
|
|||||||
corpus's own example, verified below; byte-identical to the on-disk
|
corpus's own example, verified below; byte-identical to the on-disk
|
||||||
`fieldtests/milestone-research-artifacts/mra_1_strategy_smacross.json`.)
|
`fieldtests/milestone-research-artifacts/mra_1_strategy_smacross.json`.)
|
||||||
|
|
||||||
A `bind` in an `add` op pins that param to a fixed value and **removes it
|
A `bind` in an `add` op pins that param to a value and removes it from the
|
||||||
from the sweepable param space**: a bound param is closed — it never shows
|
**open** param space (`--params`): a bound param is a **default** (#246) — a
|
||||||
up in `--params`/`--list-axes`, and no campaign axis and no `aura sweep
|
run uses it as-is, while any campaign axis or `aura sweep --axis` naming it
|
||||||
--axis` can reopen it. `bind` is for a constant the strategy never varies;
|
re-opens it for that family and binds it per cell. `--list-axes` lists it
|
||||||
leave a param unbound, as all three are here, to keep it open for sweeping.
|
after the open knobs as `<name>:<KIND> default=<value>`. `bind` is for a
|
||||||
|
value the strategy carries by default; leave a param unbound, as all three
|
||||||
|
are here, to make binding it mandatory for every sweep.
|
||||||
|
|
||||||
A param therefore has three states: **open** (a sweepable axis), **bound**
|
A param therefore has three states: **open** (an axis every sweep MUST bind),
|
||||||
(closed by a `bind` — gone from the axis namespace), and **ganged** (open, but
|
**bound** (a default any axis MAY override, #246), and **ganged** (open, but
|
||||||
fused with its siblings under ONE public knob declared by a `gang` op; the
|
fused with its siblings under ONE public knob declared by a `gang` op; the
|
||||||
member addresses are unbindable and only the gang's own single-segment name —
|
member addresses are unbindable and only the gang's own single-segment name —
|
||||||
wrapped like any knob, e.g. `graph.channel_length` — appears in `--list-axes`).
|
wrapped like any knob, e.g. `graph.channel_length` — appears in `--list-axes`).
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
{"format_version":1,"blueprint":{"name":"graph","nodes":[{"primitive":{"type":"SMA","name":"fast"}},{"primitive":{"type":"SMA","name":"slow","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":4}}]}},{"primitive":{"type":"Sub","name":"sub"}},{"primitive":{"type":"Bias","name":"bias"}}],"edges":[{"from":0,"to":2,"slot":0,"from_field":0},{"from":1,"to":2,"slot":1,"from_field":0},{"from":2,"to":3,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0}],"source":"F64"}],"output":[{"node":3,"field":0,"name":"bias"}]}}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[
|
||||||
|
{"op": "source", "role": "price", "kind": "F64"},
|
||||||
|
{"op": "add", "type": "SMA", "name": "fast"},
|
||||||
|
{"op": "add", "type": "SMA", "name": "slow", "bind": {"length": {"I64": 4}}},
|
||||||
|
{"op": "feed", "role": "price", "into": ["fast.series", "slow.series"]},
|
||||||
|
{"op": "add", "type": "Sub", "name": "sub"},
|
||||||
|
{"op": "connect", "from": "fast.value", "to": "sub.lhs"},
|
||||||
|
{"op": "connect", "from": "slow.value", "to": "sub.rhs"},
|
||||||
|
{"op": "add", "type": "Bias", "name": "bias"},
|
||||||
|
{"op": "connect", "from": "sub.value", "to": "bias.signal"},
|
||||||
|
{"op": "expose", "from": "bias.bias", "as": "bias"}
|
||||||
|
]
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
Field test — cycle-246-bound-override — verbatim transcript
|
||||||
|
Binary: target/debug/aura (built from HEAD 9d4e4c7, `cargo build -p aura-cli`)
|
||||||
|
All runs synthetic (no --real). Project = the scaffolded signal-lab/.
|
||||||
|
|
||||||
|
=====================================================================
|
||||||
|
EXAMPLE 1 — quickstart end to end (axis 1), exactly as scaffolded CLAUDE.md
|
||||||
|
=====================================================================
|
||||||
|
|
||||||
|
$ aura new signal-lab
|
||||||
|
created project "signal-lab" (data-only; attach native nodes later with `aura nodes new`)
|
||||||
|
# scaffold ships ONE blueprint: signal-lab/blueprints/signal.json (all params bound)
|
||||||
|
|
||||||
|
# CLAUDE.md quickstart advertises, verbatim:
|
||||||
|
# Run: aura run blueprints/signal.json
|
||||||
|
# Sweep: aura sweep blueprints/signal.json --axis signal_lab_signal.fast.length=2,4,8
|
||||||
|
# (aura sweep <bp> --list-axes lists open + bound-overridable axes)
|
||||||
|
|
||||||
|
$ aura run blueprints/signal.json # [exit 0]
|
||||||
|
{"manifest":{...,"params":[],...},"metrics":{"total_pips":0.3418...,"r":{"expectancy_r":1.271...,"n_trades":3,...}}}
|
||||||
|
|
||||||
|
$ aura sweep blueprints/signal.json --list-axes # [exit 0]
|
||||||
|
signal_lab_signal.fast.length:I64 default=2
|
||||||
|
signal_lab_signal.slow.length:I64 default=4
|
||||||
|
signal_lab_signal.bias.scale:F64 default=0.5
|
||||||
|
|
||||||
|
$ aura sweep blueprints/signal.json --axis signal_lab_signal.fast.length=2,4,8 # [exit 0]
|
||||||
|
{"family_id":"sweep-0","report":{"manifest":{"params":[["signal_lab_signal.fast.length",{"I64":2}],["stop_length",{"I64":3}],["stop_k",{"F64":2.0}]],...}}}
|
||||||
|
{"family_id":"sweep-0","report":{"manifest":{"params":[["signal_lab_signal.fast.length",{"I64":4}],...]}}}
|
||||||
|
{"family_id":"sweep-0","report":{"manifest":{"params":[["signal_lab_signal.fast.length",{"I64":8}],...]}}}
|
||||||
|
# bound fast.length overridden per member; slow.length + bias.scale stay at their bound defaults.
|
||||||
|
|
||||||
|
=====================================================================
|
||||||
|
EXAMPLE 2 — --list-axes on a partially-open blueprint (axis 2)
|
||||||
|
=====================================================================
|
||||||
|
# op-script bo_2_partial_open_opscript.json binds slow.length=4, leaves fast.length + bias.scale open.
|
||||||
|
|
||||||
|
$ aura graph build < bo_2_partial_open_opscript.json > bo_2_partial_open.json # [exit 0] (name = "graph")
|
||||||
|
|
||||||
|
$ aura graph introspect --params bo_2_partial_open.json # [exit 0] (raw namespace, OPEN only)
|
||||||
|
fast.length:I64
|
||||||
|
bias.scale:F64
|
||||||
|
|
||||||
|
$ aura sweep bo_2_partial_open.json --list-axes # [exit 0]
|
||||||
|
graph.fast.length:I64 # open knobs first, NO default=
|
||||||
|
graph.bias.scale:F64
|
||||||
|
graph.slow.length:I64 default=4 # bound param last, WITH default=
|
||||||
|
|
||||||
|
# bound is optional (uses default); open is still required:
|
||||||
|
$ aura sweep blueprints/partial.json --axis graph.fast.length=2,4 --axis graph.bias.scale=0.5 --name bo2d # [exit 0]
|
||||||
|
# 2 members run; slow.length omitted -> stays at default 4 (absent from manifest params).
|
||||||
|
$ aura sweep blueprints/partial.json --axis graph.fast.length=2,4 # [exit 2]
|
||||||
|
aura: MissingKnob("graph.bias.scale") # <-- raw Debug enum print (see finding F5)
|
||||||
|
|
||||||
|
=====================================================================
|
||||||
|
EXAMPLE 3 — override sweep + reproduce (axis 3)
|
||||||
|
=====================================================================
|
||||||
|
$ aura sweep blueprints/signal.json --axis signal_lab_signal.fast.length=2,4,8 --name bo3-override # [exit 0]
|
||||||
|
$ aura runs families # [exit 0]
|
||||||
|
{"family_id":"sweep-0","kind":"Sweep","members":3}
|
||||||
|
{"family_id":"bo2d-0","kind":"Sweep","members":2}
|
||||||
|
{"family_id":"bo3-override-0","kind":"Sweep","members":3}
|
||||||
|
|
||||||
|
$ aura reproduce bo3-override-0 # [exit 0] (help says "content id"; the name works too)
|
||||||
|
bo3-override-0 member signal_lab_signal.fast.length=2, stop_length=3, stop_k=2 reproduced: bit-identical
|
||||||
|
bo3-override-0 member signal_lab_signal.fast.length=4, stop_length=3, stop_k=2 reproduced: bit-identical
|
||||||
|
bo3-override-0 member signal_lab_signal.fast.length=8, stop_length=3, stop_k=2 reproduced: bit-identical
|
||||||
|
reproduced 3/3 members bit-identically
|
||||||
|
|
||||||
|
=====================================================================
|
||||||
|
EXAMPLE 4 — error surface (axis 4)
|
||||||
|
=====================================================================
|
||||||
|
$ aura sweep blueprints/signal.json --axis signal_lab_signal.nonexistent=1,2 # [exit 2] CLEAN
|
||||||
|
aura: axis signal_lab_signal.nonexistent: names no param of this blueprint (open or bound) — see `aura sweep <bp> --list-axes`
|
||||||
|
|
||||||
|
$ aura sweep blueprints/signal.json --axis totally.bogus=1 # [exit 2] CLEAN (retired "nothing to sweep" gone)
|
||||||
|
aura: axis totally.bogus: names no param of this blueprint (open or bound) — see `aura sweep <bp> --list-axes`
|
||||||
|
|
||||||
|
$ aura sweep blueprints/signal.json --axis signal_lab_signal.fast.length=1.5,2.5 # [exit 2] RAW DEBUG (finding F5)
|
||||||
|
aura: KindMismatch { knob: "signal_lab_signal.fast.length", expected: I64, got: F64 }
|
||||||
|
|
||||||
|
# run/mc still refuse open blueprints:
|
||||||
|
$ aura run blueprints/partial.json # [exit 2]
|
||||||
|
aura: run requires a closed blueprint (no free parameters); 2 free knob(s) — bind them or use `aura sweep --axis`
|
||||||
|
$ aura mc blueprints/partial.json # [exit 2] (generic usage error, not the open-param prose)
|
||||||
|
$ aura run blueprints/signal.json # [exit 0] (all bound = closed)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/runs
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Static project context only (C17); paths only.
|
||||||
|
[paths]
|
||||||
|
runs = "runs"
|
||||||
|
# data = "/path/to/archive" # the recorded-data root; defaults to the built-in path
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# signal-lab — an aura research project (data-only)
|
||||||
|
|
||||||
|
This directory is an aura project: blueprints + research documents over the
|
||||||
|
std vocabulary, anchored by `Aura.toml`. There is no crate and no build step.
|
||||||
|
|
||||||
|
- Run: `aura run blueprints/signal.json` (the starter is closed — all
|
||||||
|
params bound; bound values are defaults — any `--axis` may override them
|
||||||
|
(#246))
|
||||||
|
- Sweep: `aura sweep blueprints/signal.json --axis signal_lab_signal.fast.length=2,4,8`
|
||||||
|
(`aura sweep <bp> --list-axes` lists the open + bound-overridable axes)
|
||||||
|
- Native nodes: when the project needs its first project-specific node,
|
||||||
|
`aura nodes new <name>` scaffolds a node crate beside this project and
|
||||||
|
attaches it via `[nodes]` in `Aura.toml` (build it with `cargo build`).
|
||||||
|
- Topology is data (`blueprints/*.json`); results land in `runs/`.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"format_version":1,"blueprint":{"name":"graph","nodes":[{"primitive":{"type":"SMA","name":"fast"}},{"primitive":{"type":"SMA","name":"slow","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":4}}]}},{"primitive":{"type":"Sub","name":"sub"}},{"primitive":{"type":"Bias","name":"bias"}}],"edges":[{"from":0,"to":2,"slot":0,"from_field":0},{"from":1,"to":2,"slot":1,"from_field":0},{"from":2,"to":3,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0}],"source":"F64"}],"output":[{"node":3,"field":0,"name":"bias"}]}}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"format_version":1,"blueprint":{"name":"signal_lab_signal","nodes":[{"primitive":{"type":"SMA","name":"fast","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":2}}]}},{"primitive":{"type":"SMA","name":"slow","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":4}}]}},{"primitive":{"type":"Sub"}},{"primitive":{"type":"Bias","name":"bias","bound":[{"pos":0,"name":"scale","kind":"F64","value":{"F64":0.5}}]}}],"edges":[{"from":0,"to":2,"slot":0,"from_field":0},{"from":1,"to":2,"slot":1,"from_field":0},{"from":2,"to":3,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0}],"source":"F64"}],"output":[{"node":3,"field":0,"name":"bias"}]}}
|
||||||
Reference in New Issue
Block a user