Files
yellowjacket/.pi/skills/yellowjacket-dev/references/fixtures.md
T
logan dfb338fc37
CI / check (push) Skipped
CI / e2e (push) Skipped
CI / check (pull_request) Successful in 2m45s
CI / e2e (pull_request) Successful in 10m12s
docs(skill): the WAV fixtures scan tagged, and have since #104
`fixtures.md` told an agent the WAV fixtures scan in untitled, that
there is no "Field Recordings" artist in the Artists view, and that
this is a known open bug "pinned by TestWAVTagsAreNotReadableYet" — a
test #104 deleted, because it existed to assert the reader did not work
and failed the moment it did.

That last clause is why this is worth a diff rather than being left to
rot: the paragraph is an instruction, and it instructs the next reader
that a spec asserting the *working* behaviour is the mistake. It is the
same #104 staleness #217 removed from `queue-selection.spec.ts`, one
file over, still telling agents to put it back.

Measured against a running app rather than corrected from the issue
text — and the seed had to be rebuilt first, since the one on disk
predated #104 and would have replayed a pre-#104 scan and confirmed the
stale paragraph. On a fresh `make sandbox-seed NAME=default`, both WAVs
carry a title, an artist credit and an album: "Field Recordings" is an
ordinary artist with 2 tracks and "Test Tones" has a cover row. The
only two tracks with no album at all are `unsorted/no-tags-at-all.mp3`
and `unsorted/title-only.mp3`.

The replacement also says that prose written before #104 disagrees,
because it does, and saying nothing is how the next reader reintroduces
the claim from a source this change deliberately does not touch.

Deliberately carries no `Closes` footer. #225 covers two halves, and
the second — the same staleness in two *dated* `.planning/NOTES.md`
entries — is left alone: whether measured history gets a correcting
clause is a judgement about what that file is for, which the issue
raises on purpose and this change must not settle by auto-closing it.
2026-08-30 03:36:54 -04:00

4.0 KiB
Raw Blame History

The fixture library

test_data/music_library_test/ is generated, not committed: make testdata (~1 s) builds 31 deterministic tracks across MP3, FLAC, Ogg Vorbis and WAV. make testdata-force rebuilds unconditionally, make testdata-clean deletes it. make test and make sandbox-seed depend on it, so it is rarely run by hand.

Tests that need it fetch it through internal/testfixtures and skip themselves when it has not been generated.

Select by case, never by path

m := testfixtures.Load(t)
paths := m.Case(t, testfixtures.CaseCoverDedup)
track := m.Track(t, rel)

Cases: cover-dedup, multi-disc, various-artists, flac-album, ogg-album, wav-tracks, partial-tags, unicode, duplicates, edge-lengths, broken.

Two invariants worth not breaking:

  • The clean library is exactly 31 tracks, because sandbox-seed verifies the scan against that count. Deliberately malformed files live in a sibling root, test_data/music_library_broken/ (m.BrokenPath()), so the scanner never sees them.
  • Tags are written by backend/tagwriter, not by ffmpeg (which encodes with -map_metadata -1). Fixture and reader therefore cannot drift into agreeing with each other and disagreeing with reality.

The manifest (test_data/music_library_test.manifest.json, outside the scanned root) hashes the spec — paths, formats, durations, tags, cover identity — not the bytes, because ffmpeg stamps encoder version strings and identical specs produce different bytes on different builds.

In e2e specs

  • Every fixture except one is 26 seconds. A spec that starts playback and then clicks pause races the track ending and fails against a correct UI. Use LONG_TRACK (90 s, edge-lengths) exported from e2e/support/fixtures.ts.
  • WAV tracks scan like every other format. #104 added backend/riff, so the scan reads the id3 chunk backend/tagwriter writes and both WAVs come in fully tagged: "Field Recordings" is an ordinary artist in the Artists view, with a "Test Tones" album and a cover. They are therefore not an example of an untitled or albumless track — the only two tracks with no album are unsorted/no-tags-at-all.mp3 and unsorted/title-only.mp3. Prose written before #104 says the opposite and names TestWAVTagsAreNotReadableYet, a test that change deleted; that is dated history rather than a description of the app.

Seeds

make sandbox-seed NAME=default   # build (boots a fresh YJ_HOME and drives the app)
make sandbox-seeds               # list
make dev-headless SEED=default   # restore into a run

A seed is a tarred YJ_HOME produced by running the app: fresh home → real AddLibrary binding → poll until the real scan reports the manifest's track count → SIGTERM so shutdown hooks persist state → tar. Never hand-write one. Seeding points YJ_CORE_INDEX_URL at a dead address on purpose, so no seed depends on what the explore artifact server happened to be serving.

Rebuild a seed after any schema change. Nothing migrates a restored database: applySchema is CREATE TABLE IF NOT EXISTS, so an old seed keeps its old columns, the app starts, and the first query dies on no such column.

Restoring the seed does not disable the artifact fetch — only building it does. dev-headless leaves YJ_CORE_INDEX_URL alone, so on a developer machine the restored app immediately downloads and imports the real ~1.1M-row catalog, through the one writer connection, while whatever you started it for is running. A full make e2e against that reported 14 failures that were all contention; the same suite against the same seed with

YJ_CORE_INDEX_URL='http://127.0.0.1:1/none.tar.zst' make dev-headless SEED=default

is the configuration CI runs (ci.yml sets exactly that address) and is what to use before believing a failure. The tell is in .dev/app.log — an import logging progress — and in how the failures look: timeouts spread across unrelated specs rather than one surface being wrong.