# Corner-B EDA Grounding — plan (the 1/63 gap)

_Drafted 2026-06-06. Goal: trustable, audio-grounded EDA across the catalog so
corner B stops being "metadata prior; nothing verified." Surfaced live by the
triangle's `EDA coverage N/63`._

## The reframe — don't ground 63, ground ~9
Most tracks live inside a few big **SET** takes, so corner B for the **40 recorded
tracks** is covered by only **12 distinct candidate takes** (1 done = Take89).
Strip the date-join noise (Take63 `empty`, Take64 `sketch` — same ENSAD date, no
real audio) and the real targets are ~**9 takes**:

| take | type | #tracks | note |
|---|---|--:|---|
| Take89 | SET | 15 | ✅ done (Montreuil) |
| Take70 | SET | 14 | CosmicFest v0 |
| Take65 | SET | 10 | ENSAD |
| Take66 | SET | 10 | ENSAD |
| Take20 | SET | 9 | CCC Live |
| Take36 | SET | 5 | 38C3 Toilet |
| Take18/19/21/80 | track | 9 | La French Stack / CCC / Bunker |

Grounding these climbs `EDA coverage` from 1 → ~10 takes and lights corner B for
all 40 recorded tracks. The other ~50 takes are lower priority (sketches, empties,
unreleased sets) — ground later, by release value.

## Reachability — freebox is SSOT, MINIMIZE seeks (don't avoid it)
The freebox disk is the single source of truth for stems/masters; we work with it.
The discipline is **seek-minimizing**: plan a fetch *manifest*, pull everything for
the priority takes in ONE batched pass, treat local files as a cache, then EDA
offline. Never per-lookup `stat` the disk.
- **Already cached locally:** Take89 full (EDA done); proxies Take87/89; mix Take35;
  **31 Ardour export stems** (recent set(s)) → analyze now, no fetch needed.
- **On freebox SSOT:** older takes' per-orbit stems (`export_archive_pre2026`) +
  masters (`Prod/…`). Resolve what's needed for the ~9 priority takes, fetch once.

## Staged approach
- **Stage 0 — EDA-status ledger** (cheap, no freebox): per priority take, classify
  reachability `{local-stems | local-proxy | freebox-stems | none}`; map the 31
  local stems → their take(s). Output feeds `eda_index()` and the triangle.
- **Stage 1 — `build_eda.py {take}`**: generalize `build_player_data`/`audio_lens`
  into a per-take emitter → `eda_{take}.json` (dur, level, broad centroid, per-orbit
  activity). Run on every locally-reachable priority take first. Coverage jumps.
- **Stage 2 — one batched freebox pass**: transcode lightweight proxies for the
  *remaining priority takes only*, then Stage-1 EDA locally.
- **Stage 3 — full per-orbit lens**: only for ship-intent takes, using stems
  (`audio_lens` family/centroid/bands). Prioritize by release value, not chronology.

## Mechanical gate (parsers-over-copy, tested)
- A `TakeEDA` pydantic model; each `eda_{take}.json` validated on emit.
- `eda_index()` already auto-discovers `eda_*.json` → coverage rises with no wiring.
- A test asserts coverage is monotonic (never silently regresses) and that each
  grounded take's orbits reconcile with its `.tidal` score (corner A ⋈ B).
- Add `build_eda` as a `tide.py` step.

## Refinement spotted en route
`takes_for_gig` should drop `empty`/`sketch` take-types from candidate links
(Take63/64 polluting the priority list) — cheap fix in `build_catalog_view`.
