Campaign executor: aura campaign run drives the existing family machinery from persisted intent #198

Closed
opened 2026-07-03 16:52:29 +02:00 by Brummel · 3 comments
Owner

The executor-need re-test the cycle-0106 triage deliberately gated on (#189 decided item 6) has run: the cycle-0106 fieldtest (finding F7, fieldtests/cycle-0106-research-artifacts/FINDINGS.md) confirms the diagnosed intent-persistence gap is closed — a campaign+process pair is now a complete, content-addressed declarative spec of a sweep→gate→walk-forward the engine already runs — and that nothing consumes it: the trail ends at runs/campaigns/.json. The user's standing decision on the existing verbs ('dissolve the existing into the new — but only once the new carries', 2026-07-03, #188 resolution comment) requires the campaign path to carry, i.e. to execute.

Scope sketch (design pass to settle the forks): resolve refs via the referential tier, enumerate the campaign's axes into the existing family machinery (sweep_family/optimize/optimize_deflated/optimize_plateau, walkforward_family, r-bootstrap MC, generalization) stage by stage per the process pipeline, evaluate gates over the declared metrics between stages, record a campaign-level realization in the registry (doc = intent, realized run-set = manifest layer — fork-triage decided item 4 on #189), and honour data-level presentation (persist_taps, emit). Open design forks include: verb shape and id/name addressing, stage→machinery binding semantics (esp. walk_forward fold policy vs the shipped windowing), gate evaluation over families (per-member vs winner), campaign-level registry record shape, and v1 stage coverage.

  • depends on: #196 (blueprint-store on-ramp) naturally lands with it
  • context: the milestone's execution-semantics half ('later cycles' per the milestone description); fieldtest verdict names this the single most valuable next capability.
The executor-need re-test the cycle-0106 triage deliberately gated on (#189 decided item 6) has run: the cycle-0106 fieldtest (finding F7, fieldtests/cycle-0106-research-artifacts/FINDINGS.md) confirms the diagnosed intent-persistence gap is closed — a campaign+process pair is now a complete, content-addressed declarative spec of a sweep→gate→walk-forward the engine already runs — and that nothing consumes it: the trail ends at runs/campaigns/<hash>.json. The user's standing decision on the existing verbs ('dissolve the existing into the new — but only once the new carries', 2026-07-03, #188 resolution comment) requires the campaign path to carry, i.e. to execute. Scope sketch (design pass to settle the forks): resolve refs via the referential tier, enumerate the campaign's axes into the existing family machinery (sweep_family/optimize/optimize_deflated/optimize_plateau, walkforward_family, r-bootstrap MC, generalization) stage by stage per the process pipeline, evaluate gates over the declared metrics between stages, record a campaign-level realization in the registry (doc = intent, realized run-set = manifest layer — fork-triage decided item 4 on #189), and honour data-level presentation (persist_taps, emit). Open design forks include: verb shape and id/name addressing, stage→machinery binding semantics (esp. walk_forward fold policy vs the shipped windowing), gate evaluation over families (per-member vs winner), campaign-level registry record shape, and v1 stage coverage. - depends on: #196 (blueprint-store on-ramp) naturally lands with it - context: the milestone's execution-semantics half ('later cycles' per the milestone description); fieldtest verdict names this the single most valuable next capability.
Brummel added this to the Research artifacts — process & campaign documents milestone 2026-07-03 16:52:29 +02:00
Brummel added the feature label 2026-07-03 16:52:29 +02:00
Author
Owner

Fork triage: campaign-executor design (grounded stance review, 2026-07-03)

The executor's design forks were populated by five adversarial design lenses grounded in the ledger, the shipped cycle-0106 code, the fieldtest corpus, and #188/#189. Decisions below are made where the lenses converged on citable ground (veto by replying here); one fork stays open for a decision.

Decided (with grounds)

  1. Addressing: both file and content id; the content id is canonical. aura campaign run <file|content-id> — a file is sugar that resolves (and registers) to the same content id before anything runs, since the stores are self-keying and the id is always computable from the bytes; id-addressing matches the shipped aura reproduce <family-id> pattern, file-addressing matches the verb family's existing grammar.

  2. The walk_forward stage vocabulary is corrected to machinery-true fields. "Map folds directly" is not an available option: WindowRoller::new takes is_len/oos_len/step/mode and no fold count (folds are a derived output of rolling a span). The folds slot is replaced by the fields the shipped primitive actually accepts; inventing a folds→step heuristic inside executor glue would be an undocumented private mini-DSL. Schema change is cheap now (v1 shipped unpushed this session); a roller extension stays a separate future feature (the ledger itself calls current windowing calibration debt).

  3. Gates filter per-member survivors — and the shipped select field is not in conflict. The ratified P1 text is explicit and user-approved ("stage2 runs on stage1 survivors where net_e_r > 0 …, a filter, not an if" — #188 addendum, ratified "ja, entspricht meiner Intuition" 2026-07-03). Reconciliation with the shipped schema: a sweep stage's mandatory select names the stage's recorded selection (winner annotation + the deflation anchor), while the member population flows onward; a gate filters members over their per-member family records; a following walk_forward takes the survivor set as its in-sample search space. No schema surgery — winner-only flow was a mis-reading of select's role, not a second legitimate semantics.

  4. Realization record: a new campaign-level record type referencing per-stage family ids. FamilyRunRecord/FamilyKind are doc-scoped to ONE orchestration-axis kind (homogeneity is load-bearing); a campaign is a sequence of heterogeneous stage kinds — a thin linking record over untouched family records follows the registry's own growth pattern (new siblings beside runs.jsonl/blueprints, never overloaded fields). [Pre-review enumeration had held this open; closed on the structural citations — veto rides on the notify.]

  5. v1 stage coverage: sweep + gate + walk_forward; monte_carlo/generalize follow in-milestone. The vocabulary itself already separates forwarding stages from "terminal annotator in v1" blocks (their own doc strings), and the fieldtest's diagnosed pipeline is exactly sweep→gate→walk_forward. Continuation semantics for the two annotator kinds is a follow-up, not a silent rejection: v1 refuses a campaign whose process uses them, with prose naming the v1 boundary.

  6. Presentation v1 splits on hard code facts: emit is honored, persist_taps is deferred loudly. emit is data-level by its own contract and the JSON-dump pattern exists (walkforward_summary_json precedent) — family_table/selection_report ship as structured dumps of already-computed structs (exact shapes are spec work). persist_taps has no possible consumer today: every shipped Recorder is hand-wired, and a name→tap wiring mechanism does not exist — v1 prints an explicit "persist_taps not yet honored" line per run (never a silent drop; the F7 lesson), and the wiring lands as its own item. [Held open pre-review; closed on the grep/code facts — veto rides.]

  7. Member unit across data: one pipeline execution per (instrument, window) structural cell. Instruments and windows are C20 structural axes (different harness instances — the experiment matrix), the tuning sweep is the inner loop; gates filter members within a cell; cross-cell aggregation remains the generalize stage's later concern.

  8. Zero survivors at runtime is a clean early termination, not an error. A well-formed gate can legitimately filter out every member for a given cell; the campaign records the realization up to and including the empty-survivor stage and exits 0 — a null result is a valid research result (the inferential-honesty ethos).

  9. Failure/resume: v1 re-runs whole. C1 determinism makes a re-run bit-identical; no checkpoint/resume machinery in v1 (recorded as an explicit non-goal; revisit when campaigns grow long enough to hurt).

  10. Harness binding reuses the shipped loaded-blueprint convention. A strategy ref alone is not a harness (C20); the binding recipe that aura run/sweep <blueprint.json> --real SYM already ships (single price-role binding to the instrument's data window) is the v1 convention — a blueprint whose role set does not fit it is refused with precise prose. The per-strategy enum Strategy match-arms in the current drivers are NOT extended (they remain the condemned pre-C24 scaffolding).

  11. Delivery is sliced into shippable increments in the spec (the registry's own realization history is incremental — never one multi-axis drop).

Open — awaiting a decision (direction fork)

Executor home. Three positions, each with real ground: (i) aura-cli — the existing family drivers and project::Env live there, and the executor's charter is "drive existing machinery"; (ii) a new engine-repo library crate (recommendation) — the cli drivers are the pre-C24 scaffolding the ledger already schedules for retirement (extending a condemned home cements it), aura-registry's own module doc scopes it as memory ("storage…; display is the caller's concern") and C21 distinguishes the World's memory from its orchestration, and a library crate is reachable by more than one consumer (CLI today, playground/tests later) — note this crate is not "the World" (C21's World is a project-side program; this is the reusable campaign-execution library such programs and the CLI drive); (iii) aura-registry — it already owns every selection primitive the executor sequences, and a new crate ahead of the World design could preempt its shape. Put up rather than derived: the pre-review enumeration held it open and the lenses split three ways.

Status: decisions 1–11 fix the executor design; the home fork gates the spec.

## Fork triage: campaign-executor design (grounded stance review, 2026-07-03) The executor's design forks were populated by five adversarial design lenses grounded in the ledger, the shipped cycle-0106 code, the fieldtest corpus, and #188/#189. Decisions below are made where the lenses converged on citable ground (veto by replying here); one fork stays open for a decision. ### Decided (with grounds) 1. **Addressing: both file and content id; the content id is canonical.** `aura campaign run <file|content-id>` — a file is sugar that resolves (and registers) to the same content id before anything runs, since the stores are self-keying and the id is always computable from the bytes; id-addressing matches the shipped `aura reproduce <family-id>` pattern, file-addressing matches the verb family's existing grammar. 2. **The walk_forward stage vocabulary is corrected to machinery-true fields.** "Map folds directly" is not an available option: `WindowRoller::new` takes `is_len/oos_len/step/mode` and no fold count (folds are a derived output of rolling a span). The `folds` slot is replaced by the fields the shipped primitive actually accepts; inventing a folds→step heuristic inside executor glue would be an undocumented private mini-DSL. Schema change is cheap now (v1 shipped unpushed this session); a roller extension stays a separate future feature (the ledger itself calls current windowing calibration debt). 3. **Gates filter per-member survivors — and the shipped `select` field is not in conflict.** The ratified P1 text is explicit and user-approved ("stage2 runs on stage1 survivors where net_e_r > 0 …, a filter, not an if" — #188 addendum, ratified "ja, entspricht meiner Intuition" 2026-07-03). Reconciliation with the shipped schema: a sweep stage's mandatory `select` names the stage's *recorded selection* (winner annotation + the deflation anchor), while the member population flows onward; a gate filters members over their per-member family records; a following walk_forward takes the survivor set as its in-sample search space. No schema surgery — winner-only flow was a mis-reading of `select`'s role, not a second legitimate semantics. 4. **Realization record: a new campaign-level record type referencing per-stage family ids.** `FamilyRunRecord`/`FamilyKind` are doc-scoped to ONE orchestration-axis kind (homogeneity is load-bearing); a campaign is a sequence of heterogeneous stage kinds — a thin linking record over untouched family records follows the registry's own growth pattern (new siblings beside runs.jsonl/blueprints, never overloaded fields). [Pre-review enumeration had held this open; closed on the structural citations — veto rides on the notify.] 5. **v1 stage coverage: sweep + gate + walk_forward; monte_carlo/generalize follow in-milestone.** The vocabulary itself already separates forwarding stages from "terminal annotator in v1" blocks (their own doc strings), and the fieldtest's diagnosed pipeline is exactly sweep→gate→walk_forward. Continuation semantics for the two annotator kinds is a follow-up, not a silent rejection: v1 refuses a campaign whose process uses them, with prose naming the v1 boundary. 6. **Presentation v1 splits on hard code facts: `emit` is honored, `persist_taps` is deferred loudly.** `emit` is data-level by its own contract and the JSON-dump pattern exists (`walkforward_summary_json` precedent) — family_table/selection_report ship as structured dumps of already-computed structs (exact shapes are spec work). `persist_taps` has no possible consumer today: every shipped Recorder is hand-wired, and a name→tap wiring mechanism does not exist — v1 prints an explicit "persist_taps not yet honored" line per run (never a silent drop; the F7 lesson), and the wiring lands as its own item. [Held open pre-review; closed on the grep/code facts — veto rides.] 7. **Member unit across data: one pipeline execution per (instrument, window) structural cell.** Instruments and windows are C20 structural axes (different harness instances — the experiment matrix), the tuning sweep is the inner loop; gates filter members within a cell; cross-cell aggregation remains the generalize stage's later concern. 8. **Zero survivors at runtime is a clean early termination, not an error.** A well-formed gate can legitimately filter out every member for a given cell; the campaign records the realization up to and including the empty-survivor stage and exits 0 — a null result is a valid research result (the inferential-honesty ethos). 9. **Failure/resume: v1 re-runs whole.** C1 determinism makes a re-run bit-identical; no checkpoint/resume machinery in v1 (recorded as an explicit non-goal; revisit when campaigns grow long enough to hurt). 10. **Harness binding reuses the shipped loaded-blueprint convention.** A strategy ref alone is not a harness (C20); the binding recipe that `aura run/sweep <blueprint.json> --real SYM` already ships (single price-role binding to the instrument's data window) is the v1 convention — a blueprint whose role set does not fit it is refused with precise prose. The per-strategy `enum Strategy` match-arms in the current drivers are NOT extended (they remain the condemned pre-C24 scaffolding). 11. **Delivery is sliced into shippable increments** in the spec (the registry's own realization history is incremental — never one multi-axis drop). ### Open — awaiting a decision (direction fork) **Executor home.** Three positions, each with real ground: (i) **aura-cli** — the existing family drivers and `project::Env` live there, and the executor's charter is "drive existing machinery"; (ii) **a new engine-repo library crate** (recommendation) — the cli drivers are the pre-C24 scaffolding the ledger already schedules for retirement (extending a condemned home cements it), aura-registry's own module doc scopes it as memory ("storage…; display is the caller's concern") and C21 distinguishes the World's memory from its orchestration, and a library crate is reachable by more than one consumer (CLI today, playground/tests later) — note this crate is *not* "the World" (C21's World is a project-side program; this is the reusable campaign-execution library such programs and the CLI drive); (iii) **aura-registry** — it already owns every selection primitive the executor sequences, and a new crate ahead of the World design could preempt its shape. Put up rather than derived: the pre-review enumeration held it open and the lenses split three ways. Status: decisions 1–11 fix the executor design; the home fork gates the spec.
Author
Owner

Design decision (user): executor home

The one open fork from the fork-triage comment (2026-07-03, "Fork triage: campaign-executor design") is resolved.

  • Fork: executor home(ii) a new engine-repo library crate.
    Basis: user, 2026-07-03: "ich denke 2 ist korrekt, vor allem wegen der zukünftigen konsumenten" — option (ii), decisive ground the multi-consumer reach (CLI today, playground/tests later; the crate is the reusable campaign-execution library, not C21's project-side World).

Decisions 1–11 of the triage stand un-vetoed. Design settled — ready for spec production.

## Design decision (user): executor home The one open fork from the fork-triage comment (2026-07-03, "Fork triage: campaign-executor design") is resolved. - **Fork: executor home** → **(ii) a new engine-repo library crate.** Basis: user, 2026-07-03: "ich denke 2 ist korrekt, vor allem wegen der zukünftigen konsumenten" — option (ii), decisive ground the multi-consumer reach (CLI today, playground/tests later; the crate is the reusable campaign-execution library, not C21's project-side World). Decisions 1–11 of the triage stand un-vetoed. Design settled — ready for spec production.
Author
Owner

Post-ship decision (derived): register-then-run stores before the gate — ratified as-is (fieldtest 0107, F10)

The cycle-0107 fieldtest observed that aura campaign run <file> registers the campaign into runs/campaigns/ before the referential gate and preflight, so documents that then refuse (bad refs, v1-boundary processes) accumulate in the store, and asked whether the sugar should gate before storing.

  • Decision: keep store-before-gate.
    Basis: derived — the standalone aura campaign register verb already stores on intrinsic validity alone (the referential tier is advisory at register time by design: a ref can become resolvable later when its target is registered), so gating the run-sugar's store write would make the same document storable via one verb and refused via another; the content-addressed store is an idempotent intent archive keyed by bytes, and runnability is time-varying state, not a property of the bytes. Never-runnable documents in the store are inert (nothing consumes them unless addressed).

Veto by replying here.

## Post-ship decision (derived): register-then-run stores before the gate — ratified as-is (fieldtest 0107, F10) The cycle-0107 fieldtest observed that `aura campaign run <file>` registers the campaign into `runs/campaigns/` before the referential gate and preflight, so documents that then refuse (bad refs, v1-boundary processes) accumulate in the store, and asked whether the sugar should gate before storing. - **Decision:** keep store-before-gate. Basis: derived — the standalone `aura campaign register` verb already stores on intrinsic validity alone (the referential tier is advisory at register time by design: a ref can become resolvable later when its target is registered), so gating the run-sugar's store write would make the same document storable via one verb and refused via another; the content-addressed store is an idempotent intent archive keyed by bytes, and runnability is time-varying state, not a property of the bytes. Never-runnable documents in the store are inert (nothing consumes them unless addressed). Veto by replying here.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Brummel/Aura#198