Families-comparison view: overlay a family's members in one chart (aura chart <family>) #107
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Capability
A families-comparison view:
aura chart <family>overlays the chosen tap (defaultequity) of all members of a family in one self-contained uPlot page — consistent across sweep / MC / walk-forward families. Todayaura chart <name>charts a single run (andaura chart <name>/<member>a single member); this adds the cross-member comparison view that the single-run trace charts (#101) deferred.The view is decoupled from family production: it consumes a "set of runs to compare" (
Vec<(label, RunTraces)>); a family is the first producer of such a set. This is the deliberate first step toward the programmable analysis meta-level (C21) — sweep/MC/WFO becoming composable tools that feed a general comparable-run-set — without rebuilding the orchestration axes in this cycle.Ratified design (in-context brainstorm, Approach A + write-guard)
aura-engine— unchanged (headless serializer, C14).join_on_ts+ColumnarTracealready do the alignment.aura-registry(owner of the trace store + families lineage, C18) — the "set of runs" resolver + name classification:TraceStore::name_kind(name) -> {Run, Family, NotFound}: top-levelindex.json→Run; else member subdirs (each withindex.json) →Family; elseNotFound.TraceStore::read_family(name) -> Result<Vec<FamilyMember{ key, traces }>>: enumerate immediate subdirs withindex.json, read each via the existingread(), sorted by key (deterministic, C1).TraceStore::ensure_name_free(name, kind): the write-guard, called once per command before any write — a single-run write refuses ifnameis already a family; a family write refuses ifnameis already a single run (exit 2, refuse-don't-guess, C10/C18).aura-cli—build_comparison_chart_data(members, tap) -> ChartData(oneSeriesper member, labelled bymember_key, aligned on the union-ts spine via existingjoin_on_ts; mirror ofbuild_chart_datawith members-as-sides);emit_chartbranches onname_kind; new--tap <name>flag (defaultequity);--panelsreused for small-multiples.Cross-kind consistency from one mechanism: sweep/MC members share the window → union spine = shared axis → true overlay; walk-forward members are disjoint OOS windows → null-complementary on the union spine → the stitched curve. Ordinal x (cycle 0057) carries both. No per-family-kind special-casing.
Name-resolution guarantee (the gating condition)
aura chart <name>resolves to exactly one of {single-run, family, not-found} — a total function. The read-rule is structural; the only ambiguous on-disk state (a name used by both a run and a family) is made unreachable by the write-guard, which refuses cross-kind name reuse. Same-kind re-run (overwrite) stays allowed.Scope / non-goals
name_kind+read_family+ensure_name_free+build_comparison_chart_data+ theemit_chartbranch +--tap+ tests.Provenance
Settled in an in-context
brainstormunder/boss(2026-06-21). The user chose Approach A (auto-detectingaura chart, resolver inaura-registry) conditional on a guaranteed unambiguous name resolution, which the write-guard supplies, and ratified all design sections. Scope boundary (view now, meta-level rebuild later) confirmed by the user.Ledger anchors
C21 (the World / meta-level is the product), C22 (playground = trace explorer, web-from-disk), C18 (run registry / families lineage), C14 (headless engine, web face is a downstream consumer).
Design reconciliation (specify)
Spec: 0061-families-comparison-view. One load-bearing fork surfaced while writing the spec; recording the derived decision before the spec is signed.
Basis: derived. The comparison overlays the same tap (default
equity, pips) across members, so the series measure one identical quantity; a shared y-scale is what makes their magnitudes comparable — per-series auto-ranging (the single-run path's behaviour, where the overlaid series are different taps with disjoint ranges, #101/cycle 0056) would defeat the comparison. So: single-run overlay keeps per-series scales (different taps); family-comparison overlay uses one shared scale (same tap across members).--tap exposurelikewise shares one scale across members.