persist_taps: name-to-tap recorder wiring so campaign presentation can persist traces #201

Closed
opened 2026-07-03 22:07:03 +02:00 by Brummel · 1 comment
Owner

Campaign presentation's persist_taps list is deferred LOUDLY in v1 (#198 triage, decided item 6): every shipped Recorder is hand-wired and no name-to-tap mechanism exists, so 'aura campaign run' prints 'persist_taps not yet honored (N tap(s) ignored)' on stderr. This item ships the wiring: a way to address a tap by name in a wrapped harness and persist its trace under the campaign's realization (TraceStore layout to be decided). depends on: cycle-0107 executor (shipped). context: never a silent drop - the F7 lesson.

Campaign presentation's persist_taps list is deferred LOUDLY in v1 (#198 triage, decided item 6): every shipped Recorder is hand-wired and no name-to-tap mechanism exists, so 'aura campaign run' prints 'persist_taps not yet honored (N tap(s) ignored)' on stderr. This item ships the wiring: a way to address a tap by name in a wrapped harness and persist its trace under the campaign's realization (TraceStore layout to be decided). depends on: cycle-0107 executor (shipped). context: never a silent drop - the F7 lesson.
Brummel added the feature label 2026-07-03 22:07:03 +02:00
Brummel added this to the Research artifacts — process & campaign documents milestone 2026-07-03 22:07:03 +02:00
Author
Owner

Fork triage: persist_taps wiring (grounded stance review, 2026-07-04)

Five design lenses (minimalist / web-face consumer / maintainer / skeptic / methodology designer), grounded in the shipped 0107/0108 executor, the TraceStore/C22 disk contract, and #198 decision 6. Four forks are unanimous; the fifth resolves on a 4/5 majority with the dissent recorded. All decided (veto by replying here); none bounces.

Decided (with grounds)

  1. Tap namespace: a closed vocabulary of the wrap-convention's own sinks — equity, exposure, r_equity, net_r_equity — validated intrinsically beside emit_vocabulary (unanimous). These are exactly the tap names the shipped trace path writes (persist_traces_r's ColumnarTrace names) and the chart/viewer contract already keys on. A vocabulary tap the run's configuration cannot produce (net_r_equity needs a cost run; the campaign runner wires none today) is skipped with a loud per-run line — the F7 lesson one level down, never a silent drop. Escalation path (methodologist's clause, adopted): a genuinely new observable becomes a new vocabulary entry or an authored sink in the strategy blueprint (C22: the choice of sinks is part of the experiment) — never an open node-path namespace in the campaign document (the RustAst-shaped hole).

  2. Member scope: the per-cell NOMINEE only (unanimous). One non-reduce re-run per cell after the pipeline settles — bounded (one full-trace run per cell), bit-identical under C1 (the shipped reproduce precedent), sequential and outside the engine sweep's parallel region. The nominee recipe already exists first-class (CellOutcome.nominee). A gate-truncated cell persists nothing, with a loud per-cell line. Skeptic's guard adopted: the re-run's report is equality-asserted against the recorded nominee report (a drift alarm, not a silent divergence). Every-member persistence re-imports the O(cycles) cost reduce-mode exists to kill; a scope knob is vocabulary before any consumer asked.

  3. Layout: the existing TraceStore verbatim, family-shaped (unanimous)traces/<campaign8>-<run>/<cell-key>/<tap>.json, ensure_name_free(WriteKind::Family) per campaign run, the run counter the SAME one the CampaignRunRecord carries, cell keys content-derived filesystem-portable components (the member_key discipline, never a runtime ordinal). Inlining traces into campaign_runs.jsonl is refused outright (traces are O(cycles); the record is thin by design). The web face's read-from-disk contract (chart / the C22 trace explorer read traces/<name>/<member> today) is served unchanged.

  4. Wiring home: consumer-side, after execute() returns (unanimous). aura-campaign stays byte-untouched and trace-agnostic; the MemberRunner seam stays one-method. The CLI walks outcome.cells, re-runs each nominee once through its own non-reduce machinery (the shipped run_signal_r-style channel drain over the wrap convention), and persists via the TraceStore — replacing the loud-deferral eprintln at exactly today's site. A separate post-run verb would relocate the intent-drop #201 exists to close.

  5. Record: ONE sparse pointer — CampaignRunRecord.trace_name: Option<String> (4/5 majority). The TraceStore family name (<campaign8>-<run>), serde-default, None when nothing persisted; tap names and cell keys are NOT duplicated into the record (the store's own index.json carries manifest + tap order; read_family/name_kind enumerate the rest). Grounds: the 0108-F10 lesson is that reader-side convention knowledge is exactly the trap — one navigable pointer beats a derivation rule; per-cell fields and tap lists would be a second source of truth that drifts. [Dissent recorded: the minimalist held the name is a pure function of fields the record already carries and nothing should be stored; overruled by the navigability ground, veto rides here.]

Consequence noted: the intrinsic tier gains UnknownTap validation over persist_taps — a document naming an unknown tap refuses at validate from this cycle on (no content-id movement; validation only).

Status: decisions 1–5 settle #201's design; ready for spec production.

## Fork triage: persist_taps wiring (grounded stance review, 2026-07-04) Five design lenses (minimalist / web-face consumer / maintainer / skeptic / methodology designer), grounded in the shipped 0107/0108 executor, the TraceStore/C22 disk contract, and #198 decision 6. Four forks are unanimous; the fifth resolves on a 4/5 majority with the dissent recorded. All decided (veto by replying here); none bounces. ### Decided (with grounds) 1. **Tap namespace: a closed vocabulary of the wrap-convention's own sinks — `equity`, `exposure`, `r_equity`, `net_r_equity` — validated intrinsically beside `emit_vocabulary` (unanimous).** These are exactly the tap names the shipped trace path writes (`persist_traces_r`'s ColumnarTrace names) and the chart/viewer contract already keys on. A vocabulary tap the run's configuration cannot produce (`net_r_equity` needs a cost run; the campaign runner wires none today) is skipped with a loud per-run line — the F7 lesson one level down, never a silent drop. **Escalation path (methodologist's clause, adopted):** a genuinely new observable becomes a new vocabulary entry or an authored sink in the strategy blueprint (C22: the choice of sinks is part of the experiment) — never an open node-path namespace in the campaign document (the RustAst-shaped hole). 2. **Member scope: the per-cell NOMINEE only (unanimous).** One non-reduce re-run per cell after the pipeline settles — bounded (one full-trace run per cell), bit-identical under C1 (the shipped reproduce precedent), sequential and outside the engine sweep's parallel region. The nominee recipe already exists first-class (`CellOutcome.nominee`). A gate-truncated cell persists nothing, with a loud per-cell line. Skeptic's guard adopted: the re-run's report is equality-asserted against the recorded nominee report (a drift alarm, not a silent divergence). Every-member persistence re-imports the O(cycles) cost reduce-mode exists to kill; a scope knob is vocabulary before any consumer asked. 3. **Layout: the existing TraceStore verbatim, family-shaped (unanimous)** — `traces/<campaign8>-<run>/<cell-key>/<tap>.json`, `ensure_name_free(WriteKind::Family)` per campaign run, the run counter the SAME one the CampaignRunRecord carries, cell keys content-derived filesystem-portable components (the member_key discipline, never a runtime ordinal). Inlining traces into `campaign_runs.jsonl` is refused outright (traces are O(cycles); the record is thin by design). The web face's read-from-disk contract (chart / the C22 trace explorer read `traces/<name>/<member>` today) is served unchanged. 4. **Wiring home: consumer-side, after `execute()` returns (unanimous).** `aura-campaign` stays byte-untouched and trace-agnostic; the `MemberRunner` seam stays one-method. The CLI walks `outcome.cells`, re-runs each nominee once through its own non-reduce machinery (the shipped `run_signal_r`-style channel drain over the wrap convention), and persists via the TraceStore — replacing the loud-deferral eprintln at exactly today's site. A separate post-run verb would relocate the intent-drop #201 exists to close. 5. **Record: ONE sparse pointer — `CampaignRunRecord.trace_name: Option<String>` (4/5 majority).** The TraceStore family name (`<campaign8>-<run>`), serde-default, `None` when nothing persisted; tap names and cell keys are NOT duplicated into the record (the store's own `index.json` carries manifest + tap order; `read_family`/`name_kind` enumerate the rest). Grounds: the 0108-F10 lesson is that reader-side convention knowledge is exactly the trap — one navigable pointer beats a derivation rule; per-cell fields and tap lists would be a second source of truth that drifts. [Dissent recorded: the minimalist held the name is a pure function of fields the record already carries and nothing should be stored; overruled by the navigability ground, veto rides here.] Consequence noted: the intrinsic tier gains `UnknownTap` validation over `persist_taps` — a document naming an unknown tap refuses at validate from this cycle on (no content-id movement; validation only). Status: decisions 1–5 settle #201's design; ready for spec production.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Brummel/Aura#201