# TASKS_DUMP — ParVagues / L'Armada board reconstruction

**Written 2026-08-16.** The Claude-Code Task API is not reachable from this session
(`TaskList`/`TaskCreate`/`TaskUpdate`/`TaskGet` all absent), so the live board — last seen at
112 tasks — could not be read or rewritten programmatically. This file rebuilds the tree from
durable sources instead, and is meant to be the thing you edit or re-import from.

**Provenance of every id below**

| source | trust |
|---|---|
| `armada/tasks/board-archive.md` | verbatim, ids exact (completed through 2026-07-29) |
| `armada/tasks/NNN-*.md` (001–025) + dated logs | verbatim, narrative achievement logs |
| memory store + this session's context | ids **recalled**, not verified — treat as labels |
| git log | authoritative for what actually shipped |

Ids in the #150+ range come from the lost board via session context. They are almost
certainly right but I cannot re-read them, so **treat a #17x number as a name, not a key**.

---

## EPIC A — OPAL-26 release  ⟵ *the only epic blocking a shipment*

North star: get "Sunset Forest" (opal-festival-2026, 2026-08-08) released. 14 tracks —
**#14 Desire is cut**, PLN confirmed 2026-08-16; #13 Vague de CRIME becomes the last official
track, #15 REVOLUTION stays the Encore.

### A1 · #177 — Re-cut v4 from ear-verified boundaries  🔴 IN PROGRESS · blocks everything below

Ground truth: `armada/tide-table/judge_specs/opal26_boundaries_ear.json` — **do not overwrite
from a detector.** Nine boundaries verified by ear (#3 893.0 · #4 1118.4 · #5 1549.4 ·
#6 1808.1 · #7 2248.8 · #8 2726.4 (alt 2730.9) · #9 2954.4 already correct · #10 3269.0).

- [x] **#1 leading-silence measured** — 1.452 s of *literal digital silence* (all samples zero
      to sample 64038; first transient −28 dBFS). Objective, no ear needed.
- [x] **A1.1 #1 head trim recorded** — `start: 1.45` in the ear-boundary file, with the
      sample-exact measurement stored alongside for audit (`d3dbe59`). Kept as *data*, not
      baked into the rendered flac, because A1.4 regenerates the tracks from this file.
- [ ] **A1.2 Settle #11, #12** — machine proposals now live in a `candidates` block in the
      ear-boundary file, structurally separate from `verified`. Audition **`takeover` first**:
      it landed within 0.7 s on both boundaries that also have ear answers (#8, #10) — n=2 and
      on the easy cases, so it earns first listen, not trust.
- [ ] **A1.3 Settle #13, #15** — 🚨 **ear-only, no candidates will ever come from the timbral lens** (see B1).
- [x] **A1.4 DONE** — `apply_boundaries.py` → `segments_v4.json` → `render_release.py`
      (split · verify · continuous). 14 tracks × streaming+club, durations exact, 48 kHz/24-bit.
      Continuous mixes re-rendered drop-free.
- [x] **A1.5 Seam pass** — release check at `bounds.html?set=<gig>-release`; PLN's five fixes
      applied as `edits` (trims/fades), each verified by gain-ratio against the unfiltered master.
- [x] **A1.6 Close reverb** — A/B rendered (dry/subtle/more), PLN picked **subtle**. Applied
      as `reverb_tail_s: 5.0` + `reverb_preset: subtle`. Record now ends on a decay to −85 dB
      with **zero** trailing silence.
- [ ] **A1.7 PLN CONFIRM (5 min)** — re-listen to **seam 13** and the **close** at
      `bounds.html?set=opal-festival-2026-release`. Both are audio built *from* his approvals,
      not audio he approved: seam 13 now carries the 1 s duck + 2 s drum fade, the close carries
      the reverb. **This is the last gate before upload.**

**RENDERED AND READY** (2026-08-16): 14 tracks × streaming + club, durations exact, 48 kHz/24-bit;
continuous drop-free mixes `*_v4_{streaming,club}_nodrop.flac` at 4358.94 s = 72.6 min.
Three gaps = the trims: 1.00 s (silence), 0.04 s (WAP burst), 410.17 s (Desire + CRIME/REV trims).

### A2 · #183 — REVOLUTION mix fix  · blocked by A1

- [ ] Cut **d5 `the_revolution`**, *not* d10. PLN's first guess was wrong: measured
      band-limited (400 Hz–8 k, what a laptop reproduces) d5 leads d10 by **13.7 dB**;
      cutting d10 changes nothing he can hear. See memory `reference_small_speaker_and_rights`.
- [ ] Root-cause **d9 SUGAR CHOIR = digital silence** (−240 dB) while declared in the score.
      Two independent measurements agree. This is the finding that motivated D2's "shout until played".
- [ ] Measure the bass-"saturation" claim separately — it is a different question from loudness.

### A3 · #179 — SoundCloud uploader (Playwright)  🔴 **NEXT — A1 is done, this is unblocked**

Still **NOT BUILT**. PLN 2026-08-16: *"yes go build the uploader. im open to giving you SC
pass/user as in the .env if the cookie approach doesnt suffice. imo we need headful browser
automation."*

**Design settled by research** (see memory `reference_soundcloud_datadome`): SoundCloud is a
confirmed DataDome customer, and stealth/headless degrades to ~0 within 24 h. But that
literature is about impersonating many users; we automate PLN's own account with his own
music. So: **headful `launch_persistent_context` on `/usr/bin/chromium` with a real
user-data-dir holding the logged-in session** — be a real browser, don't defeat detection.
Browser for the FILE step only; metadata PUT is unwalled, so titles/artwork/tags/playlist go
through the plain API. `.env` credentials are the fallback only — a scripted login is the most
bot-shaped action in the flow.

- [ ] Build it. Only `/uploads/*` is DataDome-walled; **metadata PUT is free** — see
      `reference_soundcloud_write_path`, `reference_soundcloud_cli`.
- [ ] **Uploaded ≠ cleared.** Content-ID flags arrive by *email*, never through the API, so the
      tool must model those as separate states.
- [ ] Destructive calls must pass an allowlist predicate on a test-namespace permalink prefix.
      The 110 real tracks must be unreachable **by construction**.
- [ ] Delete playlist `2282681433` — sanctioned by PLN, **only once v4 is up**.

### A4 · Rights / Content ID

- [ ] **#4 "Am i Doing it Right" is flagged on SC** and it is a *true* positive — the score
      literally uses the `daft` sample bank. The durable asymmetry: the same audio **passed
      inside the 87-minute continuous mix** and flagged as a 7-minute standalone.
- [ ] Consequence to act on: static-check every track's `.tidal` sample banks **before**
      planning a per-track release. The full-set upload is the lower-risk path.

---

## EPIC B — Cut / boundary detection

### B1 · #178 — Crossfade-blind cut detection  ⚰️ **DEAD END, declared 2026-08-16**

Three attempts, all validated against the ear and all recorded in-code with their numbers:

| | approach | median err | coverage |
|---|---|---|---|
| `cut_lens.py` | midpoint reference, weighted mean, threshold | 24.0 s | — |
| `cut_lens2.py` | adjacent refs, median over orbits, CUSUM | 16.6 s | 8/14 |
| `cut_lens3.py` run 1 | span + self-calibrating fraction `u` | 3.7 s *(n=2)* | 8/14 |
| `cut_lens3.py` run 2 | medoid refs + effect-size gate | 0.4 s *(n=2)* | **4/14** ↓ |

**Do not tune this a fourth time.** The accuracy figures are not evidence — n=2, and those two
boundaries (#8, #10) already had ear answers; a metric computed on the cases that were already
easy measures nothing. The real result is the pattern: **#13 and #15 produced zero voting
orbits across all three gates and two estimators.** Those transitions have no orbit whose
timbre changes materially across the switch — the outgoing and incoming tracks share their
sounds — so a timbral lens is structurally blind there, exactly as an activity lens is blind
to a crossfade. Loosening further can only admit noise.

Two ways out, if ever revisited:
- [ ] **Change the feature** — harmonic/key change, or per-sample identity from the score's
      sample banks (which differ even when the spectrum does not).
- [ ] **Accept ear-only** for the blind cases. Cheap and honest: two timestamps, seconds each.

Standing rule: validate any new attempt against `Montreuil26_master/boundaries_ground_truth.json`
(14 user-confirmed) **first**. Note Montreuil has no per-orbit stems, so a stem-based lens
cannot use it — that gap is itself worth fixing before attempt four.

### B2 · Boundary lab  ✅ SHIPPED (`192c6e9`)

**→ http://192.168.1.3:8799/bounds.html** (LAN, phone-capable; smoke-tested against this
exact server, 11/11). `j`/`k` next-prev · space play/pause · **Enter takes the playhead** ·
drag to loop a span · candidate buttons audition from 4 s before. Export writes
`boundaries-<gig>.json` in **master** seconds — merge into `verified` in the ear file.

- [x] `build_bounds_set.py` renders a ±45 s clip per cut (not seeking the 817 MB master) and
      emits peaks + candidates. Re-encoded, never `-c copy` — FLAC stream-copy snaps to frame
      boundaries and every marker would inherit the offset.
- [x] #13/#15 show an explicit **ear-only notice** rather than being omitted; they are exactly
      the cuts that need a human.
- [ ] **PLN: make the four calls.** ~1 min each. Then A1.4.

### B3 · The set-judge  ✅ SHIPPED

`9c6a24c`, `20b9151`, `73e9d79` · log `armada/tasks/025-fifteen-intros-are-not-a-set.md` ·
memory `reference_set_judge`. Reusable per-gig via `judge_specs/<gig>.json`.

---

## EPIC C — The floor problem  ⟵ *the highest-value non-release thread*

Origin, PLN verbatim: *"I DIDNT KEEP THE KICK LONG ENOUGH. MAIN criticism / negfb I GOT:
'destructure. les gens etaient un peu perdu'."*

**Measured, and the data agrees with the floor: the kick was audible 59% of OPAL-26.**
13 of 15 tracks under 70%. Longest kickless stretch 164 s (#4). `f1798e7`.

### C1 · #180 — Pre-gig floor lens
- [ ] Static + stem analysis that flags a track's kickless stretches **before** the gig.
- [ ] **Count BARS, not seconds** — the set ran 89–166 BPM, so a seconds budget is wrong by 2×.

### C2 · #181 — HUD v2: debts + instruments  🎯 *the design is settled, see memory*
PLN: *"HUD needs evolve from 'just a lcxl repr' to proper parvagues success metrics/tooling/
state helper"* · *"things should shout at me until playd"* · *"2am-elevated-UX … like
macdonalds' screens help avoid cold burgers"*.

One mechanism — **DEBTS**, things that accrue until discharged:
- [ ] **floor debt** — bars since the kick last sounded. Must be a *budget* (≈16 bars calm →
      amber → red past 32) with an explicit "holding a breakdown" override. **A drop is
      supposed to remove the kick**; an alarm that fires on every intentional breakdown is
      ignored within one set, and then it is worse than nothing. This is the make-or-break.
- [ ] **unplayed debt** — an orbit declared in the buffer that has produced no events since
      the track loaded. Shouts until it plays. (Born from d9 SUGAR CHOIR, A2.)
- [ ] Two registers: **alarms** at the screen edge, colour **+ motion**, no numbers; **instruments**
      (kick % this track / this gig) in the topbar, never blinking.
- [ ] **Signal source**: the buffer parse structurally cannot answer any of this — it only knows
      what was *written*. Add an OSC target aimed at the HUD (`BootTidal.hs` already defines
      57120 / 1818 / 6013, so this is a one-line change avoiding contention). One stream answers
      all of it. Prior art `tidal_ears/osc_monitor.py`. **Verify the cost first** —
      `feedback_observer_perturbs`.

### C3 · #176 — `^41` standardisation across the corpus
- [ ] Verified from source: `midiOn ch pat = someCyclesBy (orDef 0 ch) pat`. So `^41` is a
      **fraction-of-cycles** control, *not* an on/off mute, and `orDef 0` means an untouched
      `^41` is safe (no mute-bomb). A mid value like 64 = the kick on ~half the cycles —
      literally structure that comes and goes, so **`^41`'s value is a first-class HUD signal**.

### C4 · HUD touched/untouched + scenes  · plan file exists, unstarted
Plan: `~/.claude/plans/zazzy-honking-waterfall.md` (touched-state tracker via `aseqdump`
read-only MIDI tap + perf-isolated scene backdrop). **The law: the HUD must never be able to
stall the editor or audio.**

---

## EPIC D — Rig & hardware

- [ ] **#154 — USB hub is a single point of failure** (drops interface + LCXL together).
- [ ] **LCXL v3 ordered** (2026-08-16). Retires: pot-pickup value jump (endless encoders send
      relative deltas — *the whole class disappears*), much of the LED-signalling cost (OLED
      renders values natively), and the USB SPOF (**DIN path is independent of USB**).
      🔍 **UNVERIFIED and it matters:** can third-party SysEx paint *arbitrary* text to the
      OLED? Documented behaviour is only "shows parameter values". C2's alarms are **derived**
      state, not control values — if the OLED is closed, the alarms stay on screen.
- [ ] CC numbering + relative-encoder mode will differ from v2. Change it in `lcxl_grid.py`
      and **regenerate** — never in a copy (`feedback_one_parser_per_concept`).

## EPIC E — Open taste calls  ⟵ *waiting on PLN's eyes/ears, not on work*
- [ ] **#11** LED brightness · **#70** cut groups. See memory `project_open_taste_calls`.

## EPIC F — Completed
Full tracker history in **`armada/tasks/board-archive.md`** (#1–#103, through 2026-07-29).
Narrative logs in **`armada/tasks/001-*.md` … `025-*.md`** + dated logs. Structured long-form
archive in **`armada/tasks/completed-archive.md`**.

---

## Recommended order

1. **A1.1** — the 1.452 s head trim. Independent, measured, done in minutes.
2. **B2** — the audition-and-mark webview, now simpler than specced.
3. **A1.2 + A1.3** in one sitting at that webview → **A1.4** → unblocks **A2** and **A3**.

C2 is the highest-value thread once the release ships, and its design is already settled —
it needs building, not deciding.
