Commit 33794e36 by PLN (Algolia)

docs(log 040 + board): the wrong cut wore the cover art, and the resume points

Captain's log 040 and the pre-compact resume state.

The log's finding, in one line: OPAL-26 sounded broken on SoundCloud while every
rendered file was correct to the millisecond, because SoundCloud will not replace
audio behind a permalink and our uploader is idempotent — so every re-upload
under a fresh slug ADDED a copy. The whole Aug-12 first cut was still up beside
the six correct v4 ones. And the tell PLN was actually reacting to: eight of the
fourteen stale uploads wear cover art and not one of the correct six does. The
superseded audio looked finished. His ear was reading the artwork.

Two lens lessons in it, both recurring. 'Matches to the second' was a tolerance,
not a verdict — SoundCloud reproduces full_duration to the MILLISECOND, so at the
±1.5s a transcode seems to deserve, the Aug-12 and v4 cuts of /wap are the same
track, which is how six stale uploads passed a duration check in August. And roll
call cannot find a stray, because a check that only looks where it expects a
thing can never find that thing somewhere else.

Plus the git one, which cost four commits: this is a shared checkout, another
session moved HEAD between two of my commits, and 'git push origin master' from a
non-master HEAD is a silent no-op that exits 0. The PUSHED in my own log was
something I wrote myself.

The board now carries R1-R5 written for a reader with zero context: exact
commands with paths, the artifacts already on disk so nothing is regenerated,
the three decisions that are PLN's and not a machine's, and the shared-checkout
hazard spelled out before anyone commits into it again.
parent 43e46143
......@@ -1883,3 +1883,145 @@ master's tracked copy). Nothing was reset or discarded in a tree shared with
live sessions. **Before merging or rebasing that branch, expect these to
double-apply**`rm` the untracked ones and check out the modified ones from
master rather than committing them twice.
---
## 🔴 RESUME POINTS — written 2026-09-05 pre-compact, for a session with ZERO context
### R1 · Finish the OPAL-26 SoundCloud release ⟵ *the only shipping thread*
**State:** the account holds 6 correct v4 tracks, 14 stale Aug-12 uploads, and 7
v4 tracks never uploaded. Artwork for all 101 arty tracks is archived. The delete
manifest is generated and dry-run clean. **Blocked on PLN's `--go` only.**
Artifacts (all already on disk, do not regenerate):
- `~/Work/Sound/Prod/sc_pull_2026-09-05/catalog.json` — the account, 132 tracks
- `~/Work/Sound/Prod/sc_pull_2026-09-05/artwork/` — 101 originals
- `~/Work/Sound/Prod/sc_pull_2026-09-05/opal26_generation_verdicts.json`
- `~/Work/Sound/Prod/sc_pull_2026-09-05/opal26_delete_manifest.json` — 14 entries
- `~/Work/Sound/Prod/Opal26_master/release/opal26_plan.json` — 15 entries, exact
**Step 1 — delete the 14 (NEEDS PLN'S APPROVAL FIRST):**
```
cd ~/Work/Sound/tidal-ears
.venv/bin/python -m tidal_ears.cli master sc delete \
--manifest ~/Work/Sound/Prod/sc_pull_2026-09-05/opal26_delete_manifest.json
# ^ dry run, expect "14 deletable, 0 refused". Add --go ONLY with his word.
```
⚠️ **The delete transport is UNPROVEN** — no DELETE has ever been issued from this
codebase against api-v2, and `POST /tracks` 400s forever on that path. If `--go`
returns 403 with a captcha body, wire `delete_manifested()`'s existing `deleter`
callable to `scbrowser.Browser.api("DELETE", …)`; there is no `--transport` flag yet.
**Step 2 — re-verify, then upload the 8 (7 missing + take-five once its slug frees):**
```
cd ~/Work/Sound/Tidal
python3 armada/tide-table/sc_generation_lens.py \
~/Work/Sound/Prod/sc_pull_2026-09-05/catalog.json \
--master ~/Work/Sound/Prod/Opal26_master \
--plan ~/Work/Sound/Prod/Opal26_master/release/opal26_plan.json \
--newest tracks_v4_streaming
python3 armada/tide-table/check_permalinks.py \
~/Work/Sound/Prod/Opal26_master/release/opal26_plan.json
cd ~/Work/Sound/tidal-ears && .venv/bin/python -m tidal_ears.cli master sc form-album \
--plan ~/Work/Sound/Prod/Opal26_master/release/opal26_plan.json \
--sharing private --state ~/Work/Sound/Prod/Opal26_master/release/sc_state.json --go
```
**PASS `--state` THIS TIME.** It never has been, which is why the account was the
only record. Re-run `sc pull` after, not just during — uploads have been accepted,
verified, and then vanished.
**Step 3 — re-attach the covers.** They live only on the tracks being deleted.
Artwork can only be SET via `scwrite.py`'s `sc album` PUT path; `scform.py` has no
artwork verb. Source images: `sc_pull_2026-09-05/artwork/`.
**Step 4 — fill `audio:` in `www/content/lives/2026/opal-festival-2026.md`** (empty
today), then the catalog's release links behind it.
**Open decisions, both PLN's:**
- **`/desire`** is the one manifest entry that is not a duplicate. Desire was cut
from the release so no v4 replacement exists — deleting it removes Desire from
SoundCloud entirely. The FLAC is safe locally (`tracks/`, `tracks_v3/`). Cut from
the release ≠ off the platform.
- **`/opal26-remix`** (4273.548 s, unidentified) and **`/opal26_master_raw`**
(5207.454 s, the raw master) are deliberately NOT in the manifest.
- **Suffix policy:** OPAL's uploads are unsuffixed; CosmicFest used
`--permalink-suffix`. Decide before uploading more, or the two gigs stay
inconsistent forever.
### R2 · PLN's hands, 2 minutes, and it is currently FAILING
```
python3 tools/check-mix.py # expect: 0 silent orbits
```
Right now it reports **Tidal 07 / 08 / 10 / 12 at -inf dB** in the saved
`Tidal Live` session — the **third** recurrence (04-08+12, then 02+10, now these).
Raise those four faders in Ardour **and SAVE**, then re-run until clean. Ardour
meters are POST-fader, so a shut fader looks identical to Tidal emitting nothing.
🔎 **Lead worth one look:** the unmerged branch `claude/rig-autoconnect-regression`
(1 commit, `a4da75e`) is *"the two reconcilers that lived only in $HOME — five
orbits reached no Ardour track"*. Five orbits reaching no track and four orbits at
-inf may be the same wound. Check before merging or discarding that branch.
### R3 · Catalog coverage — 14 gigs uncatalogued (unstarted, mid effort)
`catalog_view.json` covers 25 gigs; `www/content/lives/` has **39** gig pages
(2022:2 · 2023:4 · 2024:14 · 2025:14 · 2026:5). Missing: algolia-fdlm-2022,
mephisteuf, 38c3-chaos-music-club, 38c3-house-of-tea, opal-festival-2024,
toplap-solstice-2024, 39c3-house-of-tea, 39c3-toilet-rave, algorave-lyon, ensad,
opal-festival-2025, toplap-fromscratch-2025, ete-surprise, le-vortex.
The hard part is the track↔gig mapping, not the parsing — see
`feedback_locate_matrix_method` (never trust a low-z locate, ear-gate it).
Also still open from the reconciler itself: 3 DIVERGENT tracks (Blue Gold, Love
First, Clameur) and 2 conflicts (Atari-ght, Ere de Jeu).
### R4 · Two parsers disagree about what a gig track IS
`tools/gig-metadata.py` vs `armada/tide-table/build_gig_tracksjson.py`. The latter
drafts NEW pages and never computes the `styleDistribution` that `LiveEvent.js`
renders; they also disagree outright on REVOLUTION's style (jazz vs nujazz). Until
one owns the concept and the other calls it, use `gig-metadata.py --only-played`
for a REGEN of an existing gig. `feedback_one_parser_per_concept`.
### R5 · Small, named, unblocked
- **`test_orphan_orbits.py` FAILS** (16 rows, expects 13) and
**`test_lcxl3_display.py` collects ZERO tests**. Both pre-existing. A test file
that cannot fail is not a passing test. The 16-vs-13 smells like the corpus grew
and the fixture did not — derive the expectation, don't freeze it.
- **`mix/` overlaps tidal-ears' mastering CLI.** Committed (`a14aee7`) so the
overlap is visible in one tree rather than half-invisible in an untracked dir.
PLN's call which one is the spine.
- **Three captain's logs claim `log: 025`**, which `025-fifteen-intros` owns, and
they use dated filenames against the README's `NNN-slug.md`. Their dates
(2026-08-14) land them BEFORE 039, so the next free numbers read out of order.
- **`TODO.md` is deliberately untracked** — a paused 2026-06-22 perf/thermal board
would be a second answer to "what's next". Fold its live items in and delete, or
keep it outside git.
- **www `feat/paradiso`**: 1 unmerged commit (`b130192` "Paradiso: v2").
### ⚠️ SHARED-CHECKOUT HAZARD — read before committing anything in Sound/Tidal
`/home/pln/Work/Sound/Tidal` is checked out on **`claude/rig-streamline`** (another
session, 7 commits ahead of master, tip `c7ac174`). **Verify HEAD before every
commit** (`git rev-parse --abbrev-ref HEAD`) and **verify the push moved the
remote** (`git rev-list --left-right --count origin/master...master` must read
`0 0`) — `git push origin master` from a non-master HEAD exits 0 and pushes
nothing. Commit to master through a temporary worktree; never `git checkout` in
that tree, other sessions and PLN have live uncommitted work in it.
That branch also holds **uncommitted duplicates of work already on master**
`tools/check-mix.py`, `tools/gig-log.py` (modified), `tools/ardour_session.py` and
`armada/tide-table/build_delete_manifest.py` (untracked). Before rebasing or
merging it, `rm` the untracked ones and restore the modified ones from master, or
they double-apply. Also uncommitted there and **not ours**:
`copycat/veridis_quo.tidal`, `perf-tray.py`, `tools/rig_units.py` (the other
session) and PLN's own `piment_bresilien` / `sunny_side_up` / `rose_rouge` /
`tous_ensemble` `.tidal` edits.
### 🧹 Branch hygiene done this session
Pruned (merged, verified): `claude/button-column-migration`, `claude/lcxl3-surface`,
`tidal-to-tracks-tooling`, and tidal-ears' `claude/sc-gated-delete`. Surviving with
reason: `claude/rig-streamline` (active), `claude/rig-autoconnect-regression`
(1 unmerged commit, see R2), www `feat/paradiso` (1 unmerged).
---
log: 040
title: "The wrong cut wore the cover art"
date: 2026-09-05
task: "A3 (SoundCloud uploader) · catalog coherence · check-mix session resolution"
tags: [soundcloud, release, opal2026, tooling, catalog, forensics, git]
shareable: true
---
## Cap (what & why)
PLN opened the day with a complaint and a question: *"on soundcloud i see our
private cuts of OPAL and they are badly cut begin/end unaligned we need to
reupload and save their images tho wheres out catalog at?"*
Two jobs, then. Find out why the OPAL-26 release sounds wrong on SoundCloud, and
report where the catalog actually stands. The board had a theory for the first
one already — a note saying `/take-five-drops` had uploaded "24 s short" while
every other track "matched to the second". That theory was wrong in both halves,
and finding out how it was wrong is the whole log.
## Manœuvre (how)
**First, refuse to re-render.** The obvious move on "the cuts are bad" is to
re-cut. Before touching `apply_boundaries.py` I measured what was on disk:
every one of the 14 `tracks_v4_streaming/` FLACs matches `segments_v4.json` to
the millisecond, CRIME's `pad_end_s: 2.0` rest and REVOLUTION's 5 s reverb tail
included. The upload plan's titles, files and durations line up exactly. The ear
file's mtime (19:33) postdating the renders (19:18) turned out to be the
`release_signoff` record being written, not a late boundary edit — I checked that
specifically because it looked like a smoking gun and would have justified a
re-render. **The local pipeline was clean. The fault had to be downstream.**
**Then read the account instead of reasoning about it.** `master sc pull --out
… --artwork` — read-only, one pass, and the existing token was still live so no
login was needed. 132 tracks, 10 playlists, **101 artwork originals** to
`~/Work/Sound/Prod/sc_pull_2026-09-05/`. That single command was the artwork
rescue PLN asked for, the diagnosis, *and* the state recovery: no
`sc_state.json` had ever been written, so the account itself was the only record
of what had landed.
**Then build the lens, and get it wrong three times.** `sc_generation_lens.py`
compares every upload's duration against every local render generation.
Three defects in my own tool, each left in as a guard:
1. **Filenames are not authoritative.** A title of `Perfect <3` uploads to
`/perfect-3`, so a filename-derived slug reported two live tracks as NOT
UPLOADED. Titles now come from the release plan — what the uploader used.
2. **Streaming and club masters share every duration**, so offering both as
rival candidates marked all 14 AMBIGUOUS. Identical generations collapse into
one; they are one set of boundaries wearing two masters.
3. **A duration collision is not provenance.** `/au-revoir-lord-toyota` (2020)
and `/saria-demo` (2025) matched OPAL cuts to 50 ms by pure chance on a
132-track account. Strays are now hard-gated on a date floor — nothing older
than the oldest render on disk can be a cut of it — and the discards are
printed, not silently dropped.
**Then the second pass, which is the one that earned its keep.** Roll call —
checking each *expected* permalink — structurally cannot see a stale cut hiding
under a different slug. So the lens also scans the whole account by duration.
## Prise (findings / artifacts)
**SoundCloud accumulates generations.** It will not replace the audio behind a
permalink (paid feature), and our uploader is idempotent by permalink, so every
re-upload under a fresh slug *adds* a copy. Nothing ever replaces anything. The
entire Aug-12 first cut of OPAL-26 was still up — all fifteen tracks — beside
the six correct v4 ones:
| | count | |
|---|---|---|
| correct v4 | 6 | `/wap` `/there-s-something-about-drums-3` `/you-my-sunshine` `/piment-bresilien` `/eh-ouais-je-funk` `/ghosts-in-the-toilets` |
| stale | **14** | `/take-five-drops` + 13 under junk slugs: `/opal26-wap`, `/12-mafia-12`, `/ceci-nest-pas-une-bombe`, `/you-my-sunshine-5`, `/desire`, `/15-la-revolution-sera-samplee-15` … |
| never uploaded | 7 | ceci-n-est-pas-une-bombe, am-i-doing-it-right, perfect-3, gimme-acid, mafia, vague-de-crime, revolution |
**`/take-five-drops` was never "24 s short". It was 417.000 s — to the
millisecond, the Aug-12 cut.** Not truncation. A different generation.
**Duration is far sharper than anyone had assumed.** SoundCloud's
`full_duration` reproduces the source *to the millisecond* (477.600 s uploaded →
477.600 s reported). So the working tolerance is **0.05 s**, not the seconds a
transcode seems to deserve. At ±1.5 s, the Aug-12 and v4 cuts of `/wap`
(361.0 vs 361.6) and `/perfect` (315.0 vs 314.6) are the same track — which is
precisely how six stale uploads passed a duration check in August.
**Built:** `armada/tide-table/sc_generation_lens.py` (`fe8ec16`),
`build_delete_manifest.py` (`bd3a680`), and `master sc delete --manifest` in
tidal-ears (`ab3285b`) — the "explicit, separate call" `scwrite.py`'s refusal
message had been promising since August. Dry run: **14 deletable, 0 refused**,
audited independently.
**Catalog** (`f1fa484`): `catalog.generated.json` went 73 → **81 tracks**,
23 → **25 gigs**, now identical to the view with no silent drops, OPAL and
CosmicFest both present. Root cause: `AS_OF = "2026-06-06"` was a hardcoded
literal in `build_catalog_view.py`, so every rebuild re-stamped the same frozen
date. Coverage gap that remains: 39 gig pages in www vs 25 gigs catalogued.
**check-mix** (`27f2351`): the argv-only session resolution is fixed by
extracting gig-log's 3-rung ladder into a shared `tools/ardour_session.py`.
169 gig-log tests pass unchanged. It then failed on its first real run —
**Tidal 07/08/10/12 at -inf dB in the saved session**, the third recurrence.
## Sel (the shareable learning)
**The wrong cut was the one wearing the cover art.** Eight of the fourteen stale
uploads had artwork. Not one of the six correct v4 tracks did. So browsing his
own account, the superseded audio looked *finished* and the correct audio looked
like drafts. PLN's ear was reading the artwork, and the artwork was lying.
Artwork is a completeness signal, and completeness signals attach to whatever
someone last fussed over — which is usually the *older* thing, because it had
more time. When you ask "is this release done?", read the audio, never the
chrome around it.
**Two lessons about lenses, both old friends.** The board's "matches to the
second" was never a verdict, it was a tolerance — the instrument was the bug,
again. And roll call cannot find a stray, because a check that only looks where
it expects a thing can never discover a thing somewhere else. Absence needs
proof.
**And one about git.** Four of my commits landed on a concurrent session's
branch, because this is a shared checkout and another session moved HEAD under
me between two commits. I did not notice for an hour, because **`git push origin
master` from a non-master HEAD is a silent no-op** — it pushes the local
`master` ref, which was already current, prints nothing, exits 0. The "PUSHED"
in my log was something I had written myself. Recovered by cherry-picking onto
master through a temporary worktree, touching neither their branch nor the live
tree. The global rule already said "use a worktree in shared repos"; I had
applied it to delegated agents and quietly exempted the orchestrator, which is
the session that commits most.
## Hameçon (hook)
*"Your ears were right and the audio was fine."* A release that sounded broken,
where every rendered file was correct to the millisecond — because the platform
had quietly kept every draft, and the drafts were the ones with the covers on.
Runner-up, for the git audience: *the commit that reported success for pushing
nothing.*
## Sillage (what it unlocks)
- The delete manifest is generated and dry-run clean; `--go` is PLN's call. Once
the 14 stale uploads go, the 7 missing v4 tracks can be uploaded and the
covers re-attached, which finally fills OPAL's empty `audio:` field on the
website and the release links behind it in the catalog.
- `sc_generation_lens.py` is reusable and CosmicFest will need it — that release
went up under a suffix policy while OPAL's uploads are unsuffixed.
- The check-mix fix makes PLN's parked two-minute fader check *runnable*, and it
went from unrunnable straight to failing. Assembling checks into one caller
revalidates them under fresh conditions.
- The unmerged branch `claude/rig-autoconnect-regression` holds one commit —
*"the two reconcilers that lived only in $HOME — five orbits reached no Ardour
track"*. Five orbits reaching no track, and four orbits at -inf, are close
enough to be worth checking whether they are the same wound.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment