From 6138894b072ba1119e3e217a7daaabb7dfab9e0f Mon Sep 17 00:00:00 2001 From: Brummel Date: Sat, 4 Jul 2026 01:52:09 +0200 Subject: [PATCH] fieldtest: cycle-0108 annotator-stages corpus (GREEN) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verdict: honest, recorded, reproducible inference on top of the 0107 loop — pooled_oos provably pools the wf OOS windows (n_trades 948+895 = 1843), per_survivor flags a razor-thin gate-passer at prob_le_zero 0.525 (the inference layer earning its keep), the two-instrument std::generalize records worst_case/sign_agreement over last-wf-window nominees, byte-identical across three runs modulo the run counter, and all eight boundary probes refuse loudly at the right tier. 0 bugs. Triage: F1-F5 carry-on; F6 (campaign validate blesses executor-unrunnable shapes — the third tier invisible) and F11 (no CLI read-back for recorded realizations) filed as issues; F7/F9/F10 doc-tightens follow this commit inline; F8 (generalize R-metric set undiscoverable + misleading refusal prose for R-denominated-but- unranked metrics) filed with the --metrics tag half. The fieldtest spec rides in docs/specs/ as next-cycle planner input per convention. refs #200 --- docs/specs/fieldtest-annotator-stages.md | 133 ++++++++++++ .../cycle-0108-annotator-stages/FINDINGS.md | 198 ++++++++++++++++++ .../c0108_campaign_2instr_generalize.json | 22 ++ .../c0108_campaign_full_pooled.json | 19 ++ .../c0108_campaign_mc_persurvivor.json | 19 ++ .../c0108_probe_campaign_dup_mc.json | 57 +++++ .../c0108_probe_campaign_gen_not_last.json | 58 +++++ .../c0108_probe_campaign_nonr_generalize.json | 58 +++++ ...probe_campaign_singleinstr_generalize.json | 57 +++++ .../c0108_probe_campaign_wf_after_mc.json | 57 +++++ .../c0108_probe_campaign_zero_blocklen.json | 57 +++++ .../c0108_probe_campaign_zero_resamples.json | 57 +++++ .../c0108_probe_dup_mc.json | 6 + .../c0108_probe_gate_after_mc.json | 6 + .../c0108_probe_gen_not_last.json | 6 + .../c0108_probe_generalize_maxrdrawdown.json | 3 + .../c0108_probe_nonr_generalize.json | 5 + .../c0108_probe_wf_after_mc.json | 6 + .../c0108_probe_zero_blocklen.json | 5 + .../c0108_probe_zero_resamples.json | 5 + .../c0108_process_full_generalize.json | 13 ++ .../c0108_process_full_pooled.json | 12 ++ .../c0108_process_mc_persurvivor.json | 11 + .../c0108_realization_campaign_runs.jsonl | 8 + .../c0108_strategy_smacross.json | 12 ++ .../c0108_strategy_smacross_built.json | 1 + .../demo_project/.gitignore | 3 + .../demo_project/Aura.toml | 3 + .../demo_project/CLAUDE.md | 10 + .../demo_project/Cargo.toml | 14 ++ .../demo_project/blueprints/signal.json | 1 + .../demo_project/src/lib.rs | 76 +++++++ 32 files changed, 998 insertions(+) create mode 100644 docs/specs/fieldtest-annotator-stages.md create mode 100644 fieldtests/cycle-0108-annotator-stages/FINDINGS.md create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_campaign_2instr_generalize.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_campaign_full_pooled.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_campaign_mc_persurvivor.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_dup_mc.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_gen_not_last.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_nonr_generalize.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_singleinstr_generalize.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_wf_after_mc.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_zero_blocklen.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_zero_resamples.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_dup_mc.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_gate_after_mc.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_gen_not_last.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_generalize_maxrdrawdown.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_nonr_generalize.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_wf_after_mc.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_zero_blocklen.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_probe_zero_resamples.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_process_full_generalize.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_process_full_pooled.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_process_mc_persurvivor.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_realization_campaign_runs.jsonl create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_strategy_smacross.json create mode 100644 fieldtests/cycle-0108-annotator-stages/c0108_strategy_smacross_built.json create mode 100644 fieldtests/cycle-0108-annotator-stages/demo_project/.gitignore create mode 100644 fieldtests/cycle-0108-annotator-stages/demo_project/Aura.toml create mode 100644 fieldtests/cycle-0108-annotator-stages/demo_project/CLAUDE.md create mode 100644 fieldtests/cycle-0108-annotator-stages/demo_project/Cargo.toml create mode 100644 fieldtests/cycle-0108-annotator-stages/demo_project/blueprints/signal.json create mode 100644 fieldtests/cycle-0108-annotator-stages/demo_project/src/lib.rs diff --git a/docs/specs/fieldtest-annotator-stages.md b/docs/specs/fieldtest-annotator-stages.md new file mode 100644 index 0000000..522b5e7 --- /dev/null +++ b/docs/specs/fieldtest-annotator-stages.md @@ -0,0 +1,133 @@ +# Fieldtest — cycle 0108 (annotator stages, #200) — 2026-07-04 + +**Status:** Draft — awaiting orchestrator triage +**Author:** fieldtester (dispatched by fieldtest skill) + +## Scope +Cycle 0108 makes the two terminal annotator stages execute on top of the 0107 +campaign loop. The v2 pipeline shape is +`std::sweep [std::gate]* [std::walk_forward]? [std::monte_carlo]? [std::generalize]?`. +`std::monte_carlo` bootstraps the stage's incoming R-evidence with +position-dependent semantics (PooledOos over the walk_forward OOS series, else +PerSurvivor over each gate survivor's in-sample series); `std::generalize` runs +at campaign scope over per-cell nominees per (strategy, window), scoring the +cross-instrument worst-case R floor. Both are terminal (nothing flows out). The +realization records widen serde-default-sparse (`StageRealization.bootstrap`, +`CampaignRunRecord.generalizations`). A static preflight admits the shape and +refuses the eight off-shape/param/metric/instrument faults. + +## Examples +### fieldtests/cycle-0108-annotator-stages/c0108_campaign_full_pooled.json — full-suffix pooled campaign +- sweep(deflate) → gate → walk_forward → monte_carlo over GER40 2024-09. +- Fits scope: exercises the PooledOos mc path — the headline new surface. +- Outcome: built ✓, ran ✓ (exit 0), matched expected ✓ (`pooled_oos` bootstrap, + `n_trades:1843` = the two wf OOS windows 948+895 pooled). + +### fieldtests/cycle-0108-annotator-stages/c0108_campaign_mc_persurvivor.json — no-wf per-survivor campaign +- sweep → gate → monte_carlo over GER40 2024-09. +- Fits scope: exercises the PerSurvivor mc path (the other input shape). +- Outcome: built ✓, ran ✓ (exit 0), matched expected ✓ (`per_survivor` list of + `[ordinal, bootstrap]` over survivors [0,1,2]; survivor 1 flagged + `prob_le_zero:0.525`). + +### fieldtests/cycle-0108-annotator-stages/c0108_campaign_2instr_generalize.json — end-to-end generalize +- sweep → gate → wf → mc → generalize over GER40 + FRA40, 2024-09. +- Fits scope: exercises campaign-scope `std::generalize` (needs ≥2 instruments). +- Outcome: built ✓, ran ✓ (exit 0), matched expected ✓ (`generalizations` entry, + `worst_case:0.0437`, `sign_agreement:2`, nominees = each cell's last wf-OOS + winner; sparse widening present only on this line in the store). + +### fieldtests/cycle-0108-annotator-stages/c0108_probe_*.json — annotator boundary probes +- gate-after-mc, wf-after-mc, dup-mc, gen-not-last, zero-resamples, zero-blocklen, + non-R-generalize, single-instrument-generalize (+ their campaign runners). +- Fits scope: probes both refusal tiers (intrinsic vs executor preflight). +- Outcome: built ✓, ran ✓, matched expected ✓ (all refuse; exit 1; one intrinsic, + seven executor-tier — see F5). + +## Findings +### [working] F1 — full annotator suffix closes; pooled_oos over the wf OOS series +- `c0108_campaign_full_pooled.json`. mc records `pooled_oos` with `n_trades:1843` + provably = 948+895 (the two wf OOS windows pooled in roll order). Honest, + recorded, seeded. Recommended action: carry-on. + +### [working] F2 — no-wf campaign records one bootstrap per survivor; honesty seam bites +- `c0108_campaign_mc_persurvivor.json`. `per_survivor` over gate survivors + [0,1,2] each over the member's in-sample R series; survivor 1 passes the gate at + `expectancy_r:0.0019` but the bootstrap flags `prob_le_zero:0.525`. Carry-on. + +### [working] F3 — determinism is byte-identical modulo the run counter +- Three runs of `c0108_campaign_full_pooled.json`; every bootstrap percentile / + `prob_le_zero` / survivor set / selection reproduces. C1 intact. Carry-on. + +### [working] F4 — campaign-scope generalize closes end-to-end over two instruments +- `c0108_campaign_2instr_generalize.json`. `worst_case:0.0437`, + `sign_agreement:2`, nominees = last wf-OOS winner per cell, divergent winners + exposed via params; sparse `generalizations` key present only on this line. + Carry-on. + +### [working] F5 — the annotator tier boundary is honest and precise on both sides +- All `c0108_probe_*` runners. Intrinsic (`process validate`) catches only + gate-after-terminal; the executor preflight catches wf-after-mc, dup-mc, + gen-not-last, zero resamples/block_len, non-R metric, single-instrument + generalize — each with per-pair prose, exit 1. Carry-on. + +### [friction] F6 — `campaign validate` blesses executor-refused process shapes +- `c0108_probe_campaign_{wf_after_mc,dup_mc,gen_not_last}.json`: `campaign + validate` returns exit 0, only `campaign run` refuses. wf-after-mc is a pure + process-shape fault detectable without data. The three-tier model is invisible + from validate. Recommended action: plan (run the executor shape/param preflight + at validate time, or name the third tier in the validate output). + +### [doc-gap] F7 — pooled-vs-per-survivor duality invisible to the author surface +- `--block std::monte_carlo` says only "R-bootstrap over realised R". Nothing on + the CLI/glossary surface tells the author the output shape+semantics flip on + whether wf precedes mc (documented only in ledger C18 0108). Recommended + action: tighten docs (fold position-dependent semantics into `--block` / + glossary). + +### [doc-gap] F8 — generalize R-metric set unpredictable; refusal prose misleads +- Accepted: expectancy_r, net_expectancy_r, sqn, sqn_normalized. Refused: + total_pips + max_drawdown (both rankable), win_rate, and `max_r_drawdown` — + R-denominated yet refused as "not an R metric (… pip metrics do not)". + `--metrics` has no R/generalizable tag. Fixture: + `c0108_probe_generalize_maxrdrawdown.json`. Recommended action: tighten (add + applicability tag to `--metrics`; correct refusal prose for R-but-unranked + metrics). + +### [doc-gap] F9 — mc slot hint says "non-negative" but the executor refuses 0 +- `--block std::monte_carlo` labels resamples/block_len "non-negative integer + (u32)" (the type), but 0 is refused (`… must be > 0`). Fixture: + `c0108_probe_campaign_zero_resamples.json`. Recommended action: tighten the + slot hint to "positive integer". + +### [doc-gap] F10 — the recorded realization output schema is undocumented +- `prob_le_zero`, `per_survivor`, `pooled_oos`, `worst_case`, `sign_agreement`, + `e_r` percentiles appear in no public prose (only internal enum names in the + ledger). Stdout wraps as `{"campaign_run":…}` but the persisted JSONL is bare. + Recommended action: tighten docs (define the realization fields; a + glossary/introspect schema). + +### [friction] F11 — annotator realizations are write-only (no CLI read-back) +- `aura runs` exposes only families; no verb reads back a `campaign_run`. The + bootstrap/generalization records live only in run stdout + a gitignored JSONL, + one unbounded line per run. Recommended action: plan (an `aura campaign runs` / + `run ` read-back verb). + +## Recommendation summary +| finding | class | action | +|---|---|---| +| F1 pooled_oos over wf OOS | working | carry-on | +| F2 per_survivor + honesty seam | working | carry-on | +| F3 determinism byte-identical | working | carry-on | +| F4 campaign-scope generalize | working | carry-on | +| F5 tier boundary precise | working | carry-on | +| F6 validate blesses unrunnable shapes | friction | plan | +| F7 pooled-vs-per-survivor undiscoverable | doc-gap | tighten the design ledger / introspection | +| F8 generalize R-metric set + prose | doc-gap | tighten docs / prose | +| F9 "non-negative" hint vs >0 guard | doc-gap | tighten introspection hint | +| F10 realization output schema undocumented | doc-gap | tighten docs | +| F11 no realization read-back | friction | plan | + +**Verdict:** Yes — the annotator stages deliver honest, recorded, reproducible +inference on the 0107 loop. No bugs. Residue is discoverability at the author's +first contact with the two new stages (F6–F11). diff --git a/fieldtests/cycle-0108-annotator-stages/FINDINGS.md b/fieldtests/cycle-0108-annotator-stages/FINDINGS.md new file mode 100644 index 0000000..8117fdb --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/FINDINGS.md @@ -0,0 +1,198 @@ +# Fieldtest — cycle 0108 — annotator stages execute (#200) — 2026-07-04 + +**Role:** downstream consumer (methodology / campaign designer), public +interface only (ledger C18 0107/0108 realization paragraphs + C1, glossary, +CLI `--help` + introspection verbs, the cycle-0107 fieldtest corpus as shape +hints). No `crates/` source read. Binary built from HEAD +(`cargo build --workspace`, `target/debug/aura`, commit +`ae2fac3212f931bf5a3b277ba36fbe4010bf7b9d`). Real data: scaffolded a fresh +`demo_project/` (`aura new` — nested `.git` correctly skipped, 0107 orthogonal +fix confirmed), `cargo build` for the dylib, ran the executor over the local +Pepperstone archive (`/mnt/tickdata/Pepperstone`, GER40 + FRA40, 2024-09). + +## Fixtures (this directory) + +- `c0108_strategy_smacross.json` / `_built.json` — the open (sweepable) SMA-cross + strategy op-script + its `graph build` envelope (content id `597d71…`, 3 open + params `fast.length` / `slow.length` / `bias.scale`) +- `c0108_process_full_pooled.json` — sweep(deflate) → gate → walk_forward → + monte_carlo (the PooledOos path) +- `c0108_process_mc_persurvivor.json` — sweep → gate → monte_carlo (no wf → the + PerSurvivor path) +- `c0108_process_full_generalize.json` — sweep → gate → wf → mc → generalize + (the full v2 suffix) +- `c0108_campaign_full_pooled.json` / `_mc_persurvivor.json` — GER40 2024-09 +- `c0108_campaign_2instr_generalize.json` — GER40 + FRA40, the end-to-end + generalize +- `c0108_probe_{gate_after_mc,wf_after_mc,dup_mc,gen_not_last,zero_resamples,` + `zero_blocklen,nonr_generalize}.json` — boundary probes + their + `c0108_probe_campaign_*.json` runners; `c0108_probe_campaign_singleinstr_` + `generalize.json`, `c0108_probe_generalize_maxrdrawdown.json` +- `c0108_realization_campaign_runs.jsonl` — the recorded realization (copied out + of the project-gitignored `runs/` store): 3 pooled runs, 1 per-survivor, 1 + two-instrument-with-generalizations, 3 sweep→generalize metric probes + +## Findings + +### F1 [working] The full annotator suffix closes — pooled_oos over the wf OOS series +`aura campaign run c0108_campaign_full_pooled.json` executes +`sweep → gate → walk_forward → monte_carlo` over GER40 2024-09 (exit 0). The +`std::monte_carlo` stage records exactly the ledger's PooledOos semantics: +`"bootstrap":{"pooled_oos":{"e_r":{"mean":0.02572811864069487,…}, +"prob_le_zero":0.274,"n_trades":1843,"block_len":5,"n_resamples":1000}}`. +`n_trades:1843` is exactly the two wf OOS windows pooled in roll order +(948 + 895 — the two walk_forward OOS member counts). One `r_bootstrap` over the +whole pooled series, seeded from the doc `seed=42`. Intent → execution → +recorded, honest inference. → carry-on. + +### F2 [working] No-wf campaign records one bootstrap per survivor; the honesty seam bites +`aura campaign run c0108_campaign_mc_persurvivor.json` (sweep → gate → mc, no wf) +records `per_survivor` as `[[ordinal, bootstrap], …]` — one entry per gate +survivor `[0,1,2]`, each an `r_bootstrap` over that member's full in-memory R +series (`n_trades` 3903 / 2581 / 3811, matching the sweep members). Survivor 1 +(fast=2/slow=16) passed the `expectancy_r > 0` gate at a razor-thin +`expectancy_r = 0.0019`, yet its bootstrap shows `prob_le_zero: 0.525` — the mc +annotator correctly flags a gate-passing member as coin-flip noise. This is the +inference layer earning its keep. → carry-on. + +### F3 [working] Determinism is byte-identical across re-runs (modulo the run counter) +Three runs of `c0108_campaign_full_pooled.json` (run 0/1/2) produce +byte-identical `campaign_run` lines after normalizing only the per-campaign run +counter (the `"run"` field + the family-id trailing run index). Every bootstrap +percentile, `prob_le_zero`, gate survivor set, and selection reproduces exactly. +C1's "pure function of doc + stores + data" holds through the annotator stages. +→ carry-on. + +### F4 [working] Campaign-scope generalize closes end-to-end over two instruments +`aura campaign run c0108_campaign_2instr_generalize.json` +(sweep → gate → wf → mc → generalize, GER40 + FRA40, exit 0) runs both cells then +records a campaign-scope `generalizations` entry keyed (strategy 0 × window 0): +`"generalization":{"selection_metric":"expectancy_r","n_instruments":2, +"worst_case":0.04367535583327283,"sign_agreement":2, +"per_instrument":[["GER40",0.0437…],["FRA40",0.0484…]]}`. +The nominees are each cell's last wf-OOS winner (fast=4/slow=8), not the +sweep winner (fast=2/slow=8) — matching the ledger. `worst_case` is the weaker +instrument (GER40); divergent winners would surface via `winners[]` params, +never averaged. The serde-default sparse widening is visible in the store: the +`generalizations` key appears only on this two-instrument line; the four +single-cell lines omit it entirely. → carry-on. + +### F5 [working] The annotator tier boundary is honest and precise on both sides +Every boundary probe refuses cleanly with per-pair prose and the right exit code: +- gate after mc — intrinsic (`process validate`) — `stage 2: a gate cannot follow a terminal stage (monte_carlo/generalize)` — exit 1 +- wf after mc — executor (`campaign run`; validate passes) — `process pipeline is not executable: stage 2: std::walk_forward cannot follow std::monte_carlo` — exit 1 +- dup monte_carlo — executor — `stage 2: std::monte_carlo may appear at most once` — exit 1 +- generalize not last — executor — `stage 2: std::monte_carlo cannot follow std::generalize` — exit 1 +- zero resamples — executor — `process stage 1: monte_carlo resamples must be > 0` — exit 1 +- zero block_len — executor — `process stage 1: monte_carlo block_len must be > 0` — exit 1 +- non-R generalize metric — executor — `std::generalize metric "total_pips" is not an R metric (gross/net R families generalize; pip metrics do not)` — exit 1 +- single-instrument generalize — executor — `campaign has 1 instrument(s); std::generalize needs at least 2` — exit 1 + +The intrinsic tier catches only gate-after-terminal; the executor preflight +catches the shape/param/metric faults — exactly the "test-pinned on both sides" +boundary the ledger describes. → carry-on. + +### F6 [friction] `campaign validate` blesses process shapes the executor then refuses +`wf after mc` is a pure process-shape fault — no data or instrument count needed +to detect it — yet `aura campaign validate c0108_probe_campaign_wf_after_mc.json` +returns exit 0 (`valid (intrinsic) … valid (referential): all references +resolve`), and only `campaign run` refuses it. Same for dup-mc and +generalize-not-last. The author sees a green validate, authors on, and is +stopped only at run time. The three-tier model (intrinsic / referential / +executor-preflight) is invisible from the validate surface. (Kin to 0107 F7: +"valid" ≠ "runnable".) Repro: `campaign validate` then `campaign run` on any of +the three shape probes. +→ plan: run the executor shape/param preflight at `campaign validate` time (it is +a pure process property), or name the third tier in the validate output. + +### F7 [doc-gap] The pooled-vs-per-survivor duality is invisible to the author surface +`aura process introspect --block std::monte_carlo` says only +`R-bootstrap over realised R (terminal annotator)` + `resamples` / `block_len`. +Nothing in `--block`, `--vocabulary`, `--metrics`, or the glossary tells the +author that the stage's output shape and semantics flip on whether a +walk_forward precedes it (one pooled-OOS bootstrap vs one bootstrap per +survivor over in-sample series). The distinction is documented only in the +design ledger (C18 0108) — not on the surface a headless campaign author reads. +A user cannot predict from introspection what `std::monte_carlo` will produce. +→ tighten docs: fold the position-dependent semantics into the `--block` +description (and/or a glossary `stage bootstrap` entry with the two output +shapes). + +### F8 [doc-gap] The generalize R-metric set is unpredictable, and the refusal prose misleads +`std::generalize` requires an "R metric", but no introspection surface says which +of the 17 metrics qualify. `--metrics` tags are `rankable | gate | annotation` — +none marks R / generalizable. Probing the boundary: +- accepted: `expectancy_r`, `net_expectancy_r`, `sqn`, `sqn_normalized` +- refused: `total_pips`, `max_drawdown` (both rankable!), `win_rate`, and + `max_r_drawdown` — the last is R-denominated (its name literally contains + `_r`, it is a drawdown in R) yet is refused with + `… is not an R metric (gross/net R families generalize; pip metrics do not)`. + Calling `max_r_drawdown` a "pip metric" is wrong; the real rule is "the + rankable gross/net-R expectancy family", which no surface states. +So the author must guess the metric, and the one honest hint (the refusal) both +under-describes the accepted set and mis-describes why an R metric was refused. +Repro: `aura campaign run c0108_probe_campaign_nonr_generalize.json` and the +`c0108_probe_generalize_maxrdrawdown.json` process. +→ tighten: add a `generalize`/R applicability tag to `--metrics`; correct the +refusal prose for R-denominated-but-unranked metrics. + +### F9 [doc-gap] The mc slot hint says "non-negative" but the executor refuses 0 +`--block std::monte_carlo` labels both `resamples` and `block_len` +`required, non-negative integer (u32)`. Non-negative includes 0, but 0 is +refused at run (`… must be > 0`). The hint describes the u32 type, not the +valid range, so it silently contradicts the guard the executor enforces. +Repro: `aura campaign run c0108_probe_campaign_zero_resamples.json`. +→ tighten the slot hint to "positive integer" (or "≥ 1"). + +### F10 [doc-gap] The recorded realization's output schema is undocumented +The realization a consumer reads — `prob_le_zero`, `per_survivor`, `pooled_oos`, +`e_r` percentiles, `worst_case`, `sign_agreement`, `n_instruments` — appears in +no public prose (grep of glossary + INDEX finds none of the wire-format field +names; only the internal enum names `PooledOos` / `PerSurvivor` are in the +ledger). A user seeing `prob_le_zero: 0.274` has no public definition (it is +P[bootstrap E[R] ≤ 0]). Also undocumented: the stdout emit wraps each record as +`{"campaign_run": …}` while the persisted `campaign_runs.jsonl` line is the +bare record — a consumer parsing the store must know to drop the wrapper. +→ tighten docs: define the campaign-run realization output fields (a glossary +entry or a `campaign introspect --realization` schema dump). + +### F11 [friction] The annotator realizations are write-only — no CLI read-back +`aura runs` exposes only `families` / `family`; there is no verb to read back a +recorded `campaign_run`. The bootstrap distributions and generalization scores +the annotator stages compute are visible only in the run's own stdout; once the +terminal scrolls, the only access is hand-parsing `runs/campaign_runs.jsonl` +(which is also project-gitignored). Every cell × stage × per-survivor bootstrap +is concentrated into one JSONL line, which grows unboundedly with campaign size +and is unreadable raw. → plan: an `aura campaign runs` / `run ` read-back +verb, at least for the realized bootstrap / generalization records. + +## Verdict + +Yes — the annotator stages deliver honest, recorded, reproducible inference on +top of the 0107 loop. The v2 suffix `sweep [gate]* [wf]? [mc]? [generalize]?` +executes end to end over real data: `std::monte_carlo` bootstraps the stage's +incoming R-evidence with the exact position-dependent semantics the ledger +promises (PooledOos over the wf OOS series — `n_trades` provably the pooled OOS +count; PerSurvivor over each gate survivor's in-sample series), and +`std::generalize` runs at campaign scope over per-cell nominees, scoring the +worst-case R floor and exposing divergent winners rather than averaging them. +The inference is honest (a gate-passing survivor is flagged +`prob_le_zero=0.525`; a single-instrument generalize refuses rather than +fabricating a floor), recorded (the sparse serde widening lands cleanly — the +`generalizations` key appears only where earned), and reproducible +(byte-identical across three runs modulo the run counter, C1 intact). The +annotator tier boundary is a genuine strength: eight distinct +shape/param/metric/instrument faults each refuse loudly, precisely, and at the +right tier with exit 1. + +Nothing here is a bug. What remains is discoverability, concentrated at the +author's first contact with the two new stages: the mc pooled-vs-per-survivor +duality (F7), the generalize R-metric set + misleading refusal prose (F8), the +"non-negative" slot hint that contradicts the `>0` guard (F9), the entirely +undocumented realization output schema (F10), a validate tier that greenlights +executor-unrunnable shapes (F6), and the absence of any read-back for the +realizations the stages so carefully record (F11). The engine is honest; the +map to it is thin. + +Counts: working 5 (F1–F5), friction 2 (F6, F11), doc-gap 4 (F7–F10), +spec_gap 0, bugs 0. diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_campaign_2instr_generalize.json b/fieldtests/cycle-0108-annotator-stages/c0108_campaign_2instr_generalize.json new file mode 100644 index 0000000..6255670 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_campaign_2instr_generalize.json @@ -0,0 +1,22 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "ger40-fra40-smacross-full-suffix", + "seed": 42, + "data": { + "instruments": ["GER40", "FRA40"], + "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] + }, + "strategies": [ + { + "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, + "axes": { + "fast.length": { "kind": "I64", "values": [2, 4] }, + "slow.length": { "kind": "I64", "values": [8, 16] }, + "bias.scale": { "kind": "F64", "values": [0.5] } + } + } + ], + "process": { "ref": { "content_id": "f73db6e6b918fdcde51b9572435af9612fa213679a0c92fe194c46bcc98a2d62" } }, + "presentation": { "persist_taps": [], "emit": ["family_table", "selection_report"] } +} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_campaign_full_pooled.json b/fieldtests/cycle-0108-annotator-stages/c0108_campaign_full_pooled.json new file mode 100644 index 0000000..1979381 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_campaign_full_pooled.json @@ -0,0 +1,19 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "ger40-smacross-wf-mc", + "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ + { + "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, + "axes": { + "fast.length": { "kind": "I64", "values": [2, 4] }, + "slow.length": { "kind": "I64", "values": [8, 16] }, + "bias.scale": { "kind": "F64", "values": [0.5] } + } + } + ], + "process": { "ref": { "content_id": "c94d0a59c347275c1df85fd6d08993774b61c629dc1c5595498d73100ed462c7" } }, + "presentation": { "persist_taps": [], "emit": ["family_table", "selection_report"] } +} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_campaign_mc_persurvivor.json b/fieldtests/cycle-0108-annotator-stages/c0108_campaign_mc_persurvivor.json new file mode 100644 index 0000000..b920195 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_campaign_mc_persurvivor.json @@ -0,0 +1,19 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "ger40-smacross-mc-persurvivor", + "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ + { + "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, + "axes": { + "fast.length": { "kind": "I64", "values": [2, 4] }, + "slow.length": { "kind": "I64", "values": [8, 16] }, + "bias.scale": { "kind": "F64", "values": [0.5] } + } + } + ], + "process": { "ref": { "content_id": "26a206a82f2e654df8fea920c199f26039cc915bef413f54d446b160ce72321e" } }, + "presentation": { "persist_taps": [], "emit": ["family_table", "selection_report"] } +} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_dup_mc.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_dup_mc.json new file mode 100644 index 0000000..ede88f0 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_dup_mc.json @@ -0,0 +1,57 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "probe-dup-mc", + "seed": 42, + "data": { + "instruments": [ + "GER40" + ], + "windows": [ + { + "from_ms": 1725148800000, + "to_ms": 1727740800000 + } + ] + }, + "strategies": [ + { + "ref": { + "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" + }, + "axes": { + "fast.length": { + "kind": "I64", + "values": [ + 2, + 4 + ] + }, + "slow.length": { + "kind": "I64", + "values": [ + 8, + 16 + ] + }, + "bias.scale": { + "kind": "F64", + "values": [ + 0.5 + ] + } + } + } + ], + "process": { + "ref": { + "content_id": "d969be348c2280a031bca585d408c77e94ff69aac534a73366b0fb4dd3a60594" + } + }, + "presentation": { + "persist_taps": [], + "emit": [ + "family_table" + ] + } +} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_gen_not_last.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_gen_not_last.json new file mode 100644 index 0000000..b588d4e --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_gen_not_last.json @@ -0,0 +1,58 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "probe-gen-not-last", + "seed": 42, + "data": { + "instruments": [ + "GER40", + "FRA40" + ], + "windows": [ + { + "from_ms": 1725148800000, + "to_ms": 1727740800000 + } + ] + }, + "strategies": [ + { + "ref": { + "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" + }, + "axes": { + "fast.length": { + "kind": "I64", + "values": [ + 2, + 4 + ] + }, + "slow.length": { + "kind": "I64", + "values": [ + 8, + 16 + ] + }, + "bias.scale": { + "kind": "F64", + "values": [ + 0.5 + ] + } + } + } + ], + "process": { + "ref": { + "content_id": "775bca753bcee755767d96ff05371b1b3669d3191bf52507fe7bb9d16bf2fe36" + } + }, + "presentation": { + "persist_taps": [], + "emit": [ + "family_table" + ] + } +} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_nonr_generalize.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_nonr_generalize.json new file mode 100644 index 0000000..1f2bead --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_nonr_generalize.json @@ -0,0 +1,58 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "probe-nonr-generalize", + "seed": 42, + "data": { + "instruments": [ + "GER40", + "FRA40" + ], + "windows": [ + { + "from_ms": 1725148800000, + "to_ms": 1727740800000 + } + ] + }, + "strategies": [ + { + "ref": { + "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" + }, + "axes": { + "fast.length": { + "kind": "I64", + "values": [ + 2, + 4 + ] + }, + "slow.length": { + "kind": "I64", + "values": [ + 8, + 16 + ] + }, + "bias.scale": { + "kind": "F64", + "values": [ + 0.5 + ] + } + } + } + ], + "process": { + "ref": { + "content_id": "9ae08fb2f5eef3f12c8918b88fb171b2a2715c021f212fa7a42dcac7fc2e7551" + } + }, + "presentation": { + "persist_taps": [], + "emit": [ + "family_table" + ] + } +} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_singleinstr_generalize.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_singleinstr_generalize.json new file mode 100644 index 0000000..e345250 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_singleinstr_generalize.json @@ -0,0 +1,57 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "probe-singleinstr-generalize", + "seed": 42, + "data": { + "instruments": [ + "GER40" + ], + "windows": [ + { + "from_ms": 1725148800000, + "to_ms": 1727740800000 + } + ] + }, + "strategies": [ + { + "ref": { + "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" + }, + "axes": { + "fast.length": { + "kind": "I64", + "values": [ + 2, + 4 + ] + }, + "slow.length": { + "kind": "I64", + "values": [ + 8, + 16 + ] + }, + "bias.scale": { + "kind": "F64", + "values": [ + 0.5 + ] + } + } + } + ], + "process": { + "ref": { + "content_id": "f73db6e6b918fdcde51b9572435af9612fa213679a0c92fe194c46bcc98a2d62" + } + }, + "presentation": { + "persist_taps": [], + "emit": [ + "family_table" + ] + } +} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_wf_after_mc.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_wf_after_mc.json new file mode 100644 index 0000000..1769458 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_wf_after_mc.json @@ -0,0 +1,57 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "probe-wf-after-mc", + "seed": 42, + "data": { + "instruments": [ + "GER40" + ], + "windows": [ + { + "from_ms": 1725148800000, + "to_ms": 1727740800000 + } + ] + }, + "strategies": [ + { + "ref": { + "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" + }, + "axes": { + "fast.length": { + "kind": "I64", + "values": [ + 2, + 4 + ] + }, + "slow.length": { + "kind": "I64", + "values": [ + 8, + 16 + ] + }, + "bias.scale": { + "kind": "F64", + "values": [ + 0.5 + ] + } + } + } + ], + "process": { + "ref": { + "content_id": "847d5f487101827b9de029b8be45f8f31bd6be7a795a42b30d54112117beac2e" + } + }, + "presentation": { + "persist_taps": [], + "emit": [ + "family_table" + ] + } +} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_zero_blocklen.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_zero_blocklen.json new file mode 100644 index 0000000..cb9c6b1 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_zero_blocklen.json @@ -0,0 +1,57 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "probe-zero-blocklen", + "seed": 42, + "data": { + "instruments": [ + "GER40" + ], + "windows": [ + { + "from_ms": 1725148800000, + "to_ms": 1727740800000 + } + ] + }, + "strategies": [ + { + "ref": { + "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" + }, + "axes": { + "fast.length": { + "kind": "I64", + "values": [ + 2, + 4 + ] + }, + "slow.length": { + "kind": "I64", + "values": [ + 8, + 16 + ] + }, + "bias.scale": { + "kind": "F64", + "values": [ + 0.5 + ] + } + } + } + ], + "process": { + "ref": { + "content_id": "528ac3d80c1183a625dfb75959eac9fe8b4d0b8d594072a53c77d56bee7c47e2" + } + }, + "presentation": { + "persist_taps": [], + "emit": [ + "family_table" + ] + } +} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_zero_resamples.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_zero_resamples.json new file mode 100644 index 0000000..0b63f3b --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_campaign_zero_resamples.json @@ -0,0 +1,57 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "probe-zero-resamples", + "seed": 42, + "data": { + "instruments": [ + "GER40" + ], + "windows": [ + { + "from_ms": 1725148800000, + "to_ms": 1727740800000 + } + ] + }, + "strategies": [ + { + "ref": { + "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" + }, + "axes": { + "fast.length": { + "kind": "I64", + "values": [ + 2, + 4 + ] + }, + "slow.length": { + "kind": "I64", + "values": [ + 8, + 16 + ] + }, + "bias.scale": { + "kind": "F64", + "values": [ + 0.5 + ] + } + } + } + ], + "process": { + "ref": { + "content_id": "90fa4f42f67937967e67f071c87b4d29e28562908fcb98536cc200134b3c998c" + } + }, + "presentation": { + "persist_taps": [], + "emit": [ + "family_table" + ] + } +} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_dup_mc.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_dup_mc.json new file mode 100644 index 0000000..d8866fa --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_dup_mc.json @@ -0,0 +1,6 @@ +{ "format_version": 1, "kind": "process", "name": "probe-dup-mc", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::monte_carlo", "resamples": 1000, "block_len": 5 }, + { "block": "std::monte_carlo", "resamples": 500, "block_len": 3 } + ] } diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_gate_after_mc.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_gate_after_mc.json new file mode 100644 index 0000000..b92ced1 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_gate_after_mc.json @@ -0,0 +1,6 @@ +{ "format_version": 1, "kind": "process", "name": "probe-gate-after-mc", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::monte_carlo", "resamples": 1000, "block_len": 5 }, + { "block": "std::gate", "all": [ { "metric": "expectancy_r", "cmp": "gt", "value": 0.0 } ] } + ] } diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_gen_not_last.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_gen_not_last.json new file mode 100644 index 0000000..9328edd --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_gen_not_last.json @@ -0,0 +1,6 @@ +{ "format_version": 1, "kind": "process", "name": "probe-gen-not-last", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::generalize", "metric": "expectancy_r" }, + { "block": "std::monte_carlo", "resamples": 1000, "block_len": 5 } + ] } diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_generalize_maxrdrawdown.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_generalize_maxrdrawdown.json new file mode 100644 index 0000000..9d606bf --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_generalize_maxrdrawdown.json @@ -0,0 +1,3 @@ +{ "format_version": 1, "kind": "process", "name": "genprobe-max_r_drawdown", + "pipeline": [ { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::generalize", "metric": "max_r_drawdown" } ] } diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_nonr_generalize.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_nonr_generalize.json new file mode 100644 index 0000000..6c4113b --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_nonr_generalize.json @@ -0,0 +1,5 @@ +{ "format_version": 1, "kind": "process", "name": "probe-nonr-generalize", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::generalize", "metric": "total_pips" } + ] } diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_wf_after_mc.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_wf_after_mc.json new file mode 100644 index 0000000..50420b9 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_wf_after_mc.json @@ -0,0 +1,6 @@ +{ "format_version": 1, "kind": "process", "name": "probe-wf-after-mc", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::monte_carlo", "resamples": 1000, "block_len": 5 }, + { "block": "std::walk_forward", "in_sample_ms": 1209600000, "out_of_sample_ms": 604800000, "step_ms": 604800000, "mode": "rolling", "metric": "sqn", "select": "argmax" } + ] } diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_zero_blocklen.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_zero_blocklen.json new file mode 100644 index 0000000..cabb0a6 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_zero_blocklen.json @@ -0,0 +1,5 @@ +{ "format_version": 1, "kind": "process", "name": "probe-zero-blocklen", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::monte_carlo", "resamples": 1000, "block_len": 0 } + ] } diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_probe_zero_resamples.json b/fieldtests/cycle-0108-annotator-stages/c0108_probe_zero_resamples.json new file mode 100644 index 0000000..5ea0be3 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_probe_zero_resamples.json @@ -0,0 +1,5 @@ +{ "format_version": 1, "kind": "process", "name": "probe-zero-resamples", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::monte_carlo", "resamples": 0, "block_len": 5 } + ] } diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_process_full_generalize.json b/fieldtests/cycle-0108-annotator-stages/c0108_process_full_generalize.json new file mode 100644 index 0000000..a7c6cb8 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_process_full_generalize.json @@ -0,0 +1,13 @@ +{ + "format_version": 1, + "kind": "process", + "name": "sweep-gate-wf-mc-generalize", + "description": "The full annotator suffix: sweep, gate, rolling walk-forward, pooled-OOS R-bootstrap, then a campaign-scope cross-instrument generalize on expectancy_r.", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax", "deflate": true }, + { "block": "std::gate", "all": [ { "metric": "expectancy_r", "cmp": "gt", "value": 0.0 } ] }, + { "block": "std::walk_forward", "in_sample_ms": 1209600000, "out_of_sample_ms": 604800000, "step_ms": 604800000, "mode": "rolling", "metric": "sqn", "select": "argmax" }, + { "block": "std::monte_carlo", "resamples": 1000, "block_len": 5 }, + { "block": "std::generalize", "metric": "expectancy_r" } + ] +} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_process_full_pooled.json b/fieldtests/cycle-0108-annotator-stages/c0108_process_full_pooled.json new file mode 100644 index 0000000..763654a --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_process_full_pooled.json @@ -0,0 +1,12 @@ +{ + "format_version": 1, + "kind": "process", + "name": "robust-sweep-gate-wf-mc", + "description": "Sweep with deflation, gate on positive expectancy, rolling walk-forward, then a moving-block R-bootstrap of the pooled OOS series.", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax", "deflate": true }, + { "block": "std::gate", "all": [ { "metric": "expectancy_r", "cmp": "gt", "value": 0.0 } ] }, + { "block": "std::walk_forward", "in_sample_ms": 1209600000, "out_of_sample_ms": 604800000, "step_ms": 604800000, "mode": "rolling", "metric": "sqn", "select": "argmax" }, + { "block": "std::monte_carlo", "resamples": 1000, "block_len": 5 } + ] +} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_process_mc_persurvivor.json b/fieldtests/cycle-0108-annotator-stages/c0108_process_mc_persurvivor.json new file mode 100644 index 0000000..fa981ac --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_process_mc_persurvivor.json @@ -0,0 +1,11 @@ +{ + "format_version": 1, + "kind": "process", + "name": "sweep-gate-mc-persurvivor", + "description": "Sweep, gate on positive expectancy, then a moving-block R-bootstrap of each surviving member's fresh in-memory R series (no walk-forward, so per-survivor).", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::gate", "all": [ { "metric": "expectancy_r", "cmp": "gt", "value": 0.0 } ] }, + { "block": "std::monte_carlo", "resamples": 1000, "block_len": 5 } + ] +} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_realization_campaign_runs.jsonl b/fieldtests/cycle-0108-annotator-stages/c0108_realization_campaign_runs.jsonl new file mode 100644 index 0000000..6ec35ac --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_realization_campaign_runs.jsonl @@ -0,0 +1,8 @@ +{"campaign":"4d14d5ec431b7767b85b5be04a5165f5e6127c6486a9249b306c7f2aeebf14e0","process":"c94d0a59c347275c1df85fd6d08993774b61c629dc1c5595498d73100ed462c7","run":0,"seed":42,"cells":[{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"GER40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"4d14d5ec-0-GER40-w0-s0-0","selection":{"winner_ordinal":0,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":1.0540214890316064,"mode":"Argmax","deflated_score":-1.0290009962190139,"overfit_probability":0.3876123876123876,"n_resamples":1000,"block_len":5,"seed":42}}},{"block":"std::gate","survivor_ordinals":[0,1,2]},{"block":"std::walk_forward","family_id":"4d14d5ec-0-GER40-w0-s2-0"},{"block":"std::monte_carlo","bootstrap":{"pooled_oos":{"e_r":{"mean":0.02572811864069487,"p5":-0.045358717986233116,"p25":-0.003867370198210889,"p50":0.025041122400765753,"p75":0.054149001087649175,"p95":0.09609753891677572},"prob_le_zero":0.274,"n_trades":1843,"block_len":5,"n_resamples":1000}}}]}]} +{"campaign":"4b558e12a78fc4234cb5f9d475205ce56ce742f7a9aacaec3770f1d4a679f6e4","process":"26a206a82f2e654df8fea920c199f26039cc915bef413f54d446b160ce72321e","run":0,"seed":42,"cells":[{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"GER40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"4b558e12-0-GER40-w0-s0-0","selection":{"winner_ordinal":0,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":1.0540214890316064,"mode":"Argmax"}}},{"block":"std::gate","survivor_ordinals":[0,1,2]},{"block":"std::monte_carlo","bootstrap":{"per_survivor":[[0,{"e_r":{"mean":0.025298818957544374,"p5":-0.01849982068009793,"p25":0.005707492926717921,"p50":0.024186660903793872,"p75":0.045175657505028846,"p95":0.07270312095687298},"prob_le_zero":0.184,"n_trades":3903,"block_len":5,"n_resamples":1000}],[1,{"e_r":{"mean":-0.0007863451183027098,"p5":-0.06191237500077215,"p25":-0.02635431542922357,"p50":-0.0015498863526125085,"p75":0.024015596809324934,"p95":0.06066777913809223},"prob_le_zero":0.525,"n_trades":2581,"block_len":5,"n_resamples":1000}],[2,{"e_r":{"mean":0.025873482678292634,"p5":-0.02258807583447356,"p25":0.004121717360938905,"p50":0.024475583833216418,"p75":0.045850761312665606,"p95":0.07739775879325204},"prob_le_zero":0.21,"n_trades":3811,"block_len":5,"n_resamples":1000}]]}}]}]} +{"campaign":"4d14d5ec431b7767b85b5be04a5165f5e6127c6486a9249b306c7f2aeebf14e0","process":"c94d0a59c347275c1df85fd6d08993774b61c629dc1c5595498d73100ed462c7","run":1,"seed":42,"cells":[{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"GER40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"4d14d5ec-0-GER40-w0-s0-1","selection":{"winner_ordinal":0,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":1.0540214890316064,"mode":"Argmax","deflated_score":-1.0290009962190139,"overfit_probability":0.3876123876123876,"n_resamples":1000,"block_len":5,"seed":42}}},{"block":"std::gate","survivor_ordinals":[0,1,2]},{"block":"std::walk_forward","family_id":"4d14d5ec-0-GER40-w0-s2-1"},{"block":"std::monte_carlo","bootstrap":{"pooled_oos":{"e_r":{"mean":0.02572811864069487,"p5":-0.045358717986233116,"p25":-0.003867370198210889,"p50":0.025041122400765753,"p75":0.054149001087649175,"p95":0.09609753891677572},"prob_le_zero":0.274,"n_trades":1843,"block_len":5,"n_resamples":1000}}}]}]} +{"campaign":"4d14d5ec431b7767b85b5be04a5165f5e6127c6486a9249b306c7f2aeebf14e0","process":"c94d0a59c347275c1df85fd6d08993774b61c629dc1c5595498d73100ed462c7","run":2,"seed":42,"cells":[{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"GER40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"4d14d5ec-0-GER40-w0-s0-2","selection":{"winner_ordinal":0,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":1.0540214890316064,"mode":"Argmax","deflated_score":-1.0290009962190139,"overfit_probability":0.3876123876123876,"n_resamples":1000,"block_len":5,"seed":42}}},{"block":"std::gate","survivor_ordinals":[0,1,2]},{"block":"std::walk_forward","family_id":"4d14d5ec-0-GER40-w0-s2-2"},{"block":"std::monte_carlo","bootstrap":{"pooled_oos":{"e_r":{"mean":0.02572811864069487,"p5":-0.045358717986233116,"p25":-0.003867370198210889,"p50":0.025041122400765753,"p75":0.054149001087649175,"p95":0.09609753891677572},"prob_le_zero":0.274,"n_trades":1843,"block_len":5,"n_resamples":1000}}}]}]} +{"campaign":"18ab89606044e981ac30b091973b4d5b0b2cc0b3bf1c6825742ad9a7ae6b4a32","process":"f73db6e6b918fdcde51b9572435af9612fa213679a0c92fe194c46bcc98a2d62","run":0,"seed":42,"cells":[{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"GER40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"18ab8960-0-GER40-w0-s0-0","selection":{"winner_ordinal":0,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":1.0540214890316064,"mode":"Argmax","deflated_score":-1.0290009962190139,"overfit_probability":0.3876123876123876,"n_resamples":1000,"block_len":5,"seed":42}}},{"block":"std::gate","survivor_ordinals":[0,1,2]},{"block":"std::walk_forward","family_id":"18ab8960-0-GER40-w0-s2-0"},{"block":"std::monte_carlo","bootstrap":{"pooled_oos":{"e_r":{"mean":0.02572811864069487,"p5":-0.045358717986233116,"p25":-0.003867370198210889,"p50":0.025041122400765753,"p75":0.054149001087649175,"p95":0.09609753891677572},"prob_le_zero":0.274,"n_trades":1843,"block_len":5,"n_resamples":1000}}}]},{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"FRA40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"18ab8960-0-FRA40-w0-s0-0","selection":{"winner_ordinal":2,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":4}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":2.1027529408673753,"mode":"Argmax","deflated_score":-0.25026485410828503,"overfit_probability":0.08491508491508491,"n_resamples":1000,"block_len":5,"seed":42}}},{"block":"std::gate","survivor_ordinals":[0,1,2]},{"block":"std::walk_forward","family_id":"18ab8960-0-FRA40-w0-s2-0"},{"block":"std::monte_carlo","bootstrap":{"pooled_oos":{"e_r":{"mean":0.013305753279586063,"p5":-0.09686234697635485,"p25":-0.02935938855824511,"p50":0.014375417056209604,"p75":0.0572151928623397,"p95":0.11740134416304716},"prob_le_zero":0.412,"n_trades":1272,"block_len":5,"n_resamples":1000}}}]}],"generalizations":[{"strategy_ordinal":0,"window_ordinal":0,"generalization":{"selection_metric":"expectancy_r","n_instruments":2,"worst_case":0.04367535583327283,"sign_agreement":2,"per_instrument":[["GER40",0.04367535583327283],["FRA40",0.048403786424396446]]},"winners":[["GER40",[["graph.fast.length",{"I64":4}],["graph.slow.length",{"I64":8}],["graph.bias.scale",{"F64":0.5}]]],["FRA40",[["graph.fast.length",{"I64":4}],["graph.slow.length",{"I64":8}],["graph.bias.scale",{"F64":0.5}]]]]}]} +{"campaign":"f385116e32fa23775e59ca9f853a3c42a70ba61b38aa004ac02c105b30f21a2b","process":"1263772be43db2771a55d3c0b345bdacfa701f6358c3fc72122f48361783a539","run":0,"seed":42,"cells":[{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"GER40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"f385116e-0-GER40-w0-s0-0","selection":{"winner_ordinal":0,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":1.0540214890316064,"mode":"Argmax"}}}]},{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"FRA40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"f385116e-0-FRA40-w0-s0-0","selection":{"winner_ordinal":2,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":4}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":2.1027529408673753,"mode":"Argmax"}}}]}],"generalizations":[{"strategy_ordinal":0,"window_ordinal":0,"generalization":{"selection_metric":"net_expectancy_r","n_instruments":2,"worst_case":0.028321444460569407,"sign_agreement":2,"per_instrument":[["GER40",0.028321444460569407],["FRA40",0.09120457579140544]]},"winners":[["GER40",[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]]],["FRA40",[["bias.scale",{"F64":0.5}],["fast.length",{"I64":4}],["slow.length",{"I64":8}]]]]}]} +{"campaign":"b0bc058aa20675e05599e3b333e07be18eec84e3d23e58cd97cae644f4802fb7","process":"845ab7392b6be7b6650e05282e729d3c42c61c5b1f1a536bac261bf59e3317ce","run":0,"seed":42,"cells":[{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"GER40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"b0bc058a-0-GER40-w0-s0-0","selection":{"winner_ordinal":0,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":1.0540214890316064,"mode":"Argmax"}}}]},{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"FRA40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"b0bc058a-0-FRA40-w0-s0-0","selection":{"winner_ordinal":2,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":4}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":2.1027529408673753,"mode":"Argmax"}}}]}],"generalizations":[{"strategy_ordinal":0,"window_ordinal":0,"generalization":{"selection_metric":"sqn","n_instruments":2,"worst_case":1.0540214890316064,"sign_agreement":2,"per_instrument":[["GER40",1.0540214890316064],["FRA40",2.1027529408673753]]},"winners":[["GER40",[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]]],["FRA40",[["bias.scale",{"F64":0.5}],["fast.length",{"I64":4}],["slow.length",{"I64":8}]]]]}]} +{"campaign":"033d8cd0cab382c2cc2393877af919f050dcf7aed3033664fed7bc2ed756cd51","process":"236fb6363106e993b3b9c634987a765c482a2c4c76da78dbdb6f711ac65e1708","run":0,"seed":42,"cells":[{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"GER40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"033d8cd0-0-GER40-w0-s0-0","selection":{"winner_ordinal":0,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":1.0540214890316064,"mode":"Argmax"}}}]},{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"FRA40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"033d8cd0-0-FRA40-w0-s0-0","selection":{"winner_ordinal":2,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":4}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":2.1027529408673753,"mode":"Argmax"}}}]}],"generalizations":[{"strategy_ordinal":0,"window_ordinal":0,"generalization":{"selection_metric":"sqn_normalized","n_instruments":2,"worst_case":0.16871363772287948,"sign_agreement":2,"per_instrument":[["GER40",0.16871363772287948],["FRA40",0.4182978458755474]]},"winners":[["GER40",[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]]],["FRA40",[["bias.scale",{"F64":0.5}],["fast.length",{"I64":4}],["slow.length",{"I64":8}]]]]}]} diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_strategy_smacross.json b/fieldtests/cycle-0108-annotator-stages/c0108_strategy_smacross.json new file mode 100644 index 0000000..ccbeb1a --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_strategy_smacross.json @@ -0,0 +1,12 @@ +[ + {"op": "source", "role": "price", "kind": "F64"}, + {"op": "add", "type": "SMA", "name": "fast"}, + {"op": "add", "type": "SMA", "name": "slow"}, + {"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"} +] diff --git a/fieldtests/cycle-0108-annotator-stages/c0108_strategy_smacross_built.json b/fieldtests/cycle-0108-annotator-stages/c0108_strategy_smacross_built.json new file mode 100644 index 0000000..83ba539 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/c0108_strategy_smacross_built.json @@ -0,0 +1 @@ +{"format_version":1,"blueprint":{"name":"graph","nodes":[{"primitive":{"type":"SMA","name":"fast"}},{"primitive":{"type":"SMA","name":"slow"}},{"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"}]}} \ No newline at end of file diff --git a/fieldtests/cycle-0108-annotator-stages/demo_project/.gitignore b/fieldtests/cycle-0108-annotator-stages/demo_project/.gitignore new file mode 100644 index 0000000..af5cf3d --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/demo_project/.gitignore @@ -0,0 +1,3 @@ +/target +Cargo.lock +/runs diff --git a/fieldtests/cycle-0108-annotator-stages/demo_project/Aura.toml b/fieldtests/cycle-0108-annotator-stages/demo_project/Aura.toml new file mode 100644 index 0000000..af335c1 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/demo_project/Aura.toml @@ -0,0 +1,3 @@ +# Static project context only (C17); paths only. +[paths] +runs = "runs" diff --git a/fieldtests/cycle-0108-annotator-stages/demo_project/CLAUDE.md b/fieldtests/cycle-0108-annotator-stages/demo_project/CLAUDE.md new file mode 100644 index 0000000..6215473 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/demo_project/CLAUDE.md @@ -0,0 +1,10 @@ +# demo_project — an aura research project + +This crate is an aura project: a cdylib of node/strategy blueprints the +`aura` host loads during research (see the engine's docs/project-layout.md). + +- Build: `cargo build` (the next `aura` invocation loads the fresh dylib) +- Run: `aura run blueprints/signal.json` (from anywhere inside this dir) +- Nodes live in `src/`; each is registered in `vocabulary()`/`type_ids()` + under the `demo_project::` namespace prefix. +- Topology is data (`blueprints/*.json`), node logic is Rust. diff --git a/fieldtests/cycle-0108-annotator-stages/demo_project/Cargo.toml b/fieldtests/cycle-0108-annotator-stages/demo_project/Cargo.toml new file mode 100644 index 0000000..a1a64b5 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/demo_project/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "demo_project" +version = "0.1.0" +edition = "2024" +publish = false + +[lib] +crate-type = ["cdylib"] + +[dependencies] +aura-core = { path = "/home/brummel/dev/aura/crates/aura-core" } + +# Standalone workspace root: never a member of an enclosing workspace. +[workspace] diff --git a/fieldtests/cycle-0108-annotator-stages/demo_project/blueprints/signal.json b/fieldtests/cycle-0108-annotator-stages/demo_project/blueprints/signal.json new file mode 100644 index 0000000..f5b0f4e --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/demo_project/blueprints/signal.json @@ -0,0 +1 @@ +{"format_version":1,"blueprint":{"name":"demo_project_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}}]}},{"primitive":{"type":"demo_project::Identity"}}],"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},{"from":3,"to":4,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0}],"source":"F64"}],"output":[{"node":4,"field":0,"name":"bias"}]}} \ No newline at end of file diff --git a/fieldtests/cycle-0108-annotator-stages/demo_project/src/lib.rs b/fieldtests/cycle-0108-annotator-stages/demo_project/src/lib.rs new file mode 100644 index 0000000..80ad233 --- /dev/null +++ b/fieldtests/cycle-0108-annotator-stages/demo_project/src/lib.rs @@ -0,0 +1,76 @@ +//! demo_project — an aura research project: node logic + the exported vocabulary. +//! +//! Every node type this crate provides is registered in `vocabulary()` / +//! `type_ids()` under the `demo_project::` namespace prefix; the `aura` host loads +//! this cdylib per invocation and merges it with the std vocabulary. + +use aura_core::{ + Cell, Ctx, FieldSpec, Firing, Node, NodeSchema, PortSpec, PrimitiveBuilder, + ScalarKind, +}; + +/// One-input f64 pass-through. Emits `None` until its input has a value. +pub struct Identity { + out: [Cell; 1], +} + +impl Identity { + pub fn new() -> Self { + Self { out: [Cell::from_f64(0.0)] } + } + pub fn builder() -> PrimitiveBuilder { + PrimitiveBuilder::new( + "demo_project::Identity", + NodeSchema { + inputs: vec![PortSpec { + kind: ScalarKind::F64, + firing: Firing::Any, + name: "value".into(), + }], + output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::F64 }], + params: vec![], + }, + |_| Box::new(Identity::new()), + ) + } +} + +impl Default for Identity { + fn default() -> Self { + Self::new() + } +} + +impl Node for Identity { + fn lookbacks(&self) -> Vec { + vec![1] + } + fn eval(&mut self, ctx: Ctx<'_>) -> Option<&[Cell]> { + let w = ctx.f64_in(0); + if w.is_empty() { + return None; + } + self.out[0] = Cell::from_f64(w[0]); + Some(&self.out) + } + fn label(&self) -> String { + "demo_project::Identity".to_string() + } +} + +fn vocabulary(type_id: &str) -> Option { + match type_id { + "demo_project::Identity" => Some(Identity::builder()), + _ => None, + } +} + +fn type_ids() -> &'static [&'static str] { + &["demo_project::Identity"] +} + +aura_core::aura_project! { + namespace: "demo_project", + vocabulary: vocabulary, + type_ids: type_ids, +}