Credits after conversion

Bass stem. Resampled to 44.1 kHz by ffmpeg 9.0.1 with its bext preservation option.1:05:18.37start on the session timeline, instead of 1:00:00.00. Writer splits gone.refused

A check that refuses a converted stem when its credits, its writer splits or its start position no longer mean what they meant in the delivered file.

Deterministic test signals. No third-party recordings. FileEaters exports and watermarking not tested.

Delivery check
Title
Night Drive, bass stem v3
Source
bass.wav, 48 kHz, 24-bit Broadcast Wave, credits written in iXML and ID3
Transformation
Resampled to 44.1 kHz by ffmpeg 9.0.1 with its bext preservation option.
What changed

Writer splits gone. Inès Valdés 60.00 and Théo Marlow 40.00 are no longer anywhere in the file.

Start position wrong. Where the stem sits on the session timeline. The start number was copied as is (172,800,000 samples), but the sample rate changed.

1:05:18.37where the stem now starts, instead of 1:00:00.00

Decision
refusedA value can survive a conversion and still be wrong. The check compares meaning, not bytes.

Technical: bext TimeReference 172,800,000, unchanged from the 48 kHz source. The same start at 44,100 Hz is 158,760,000.

Every conversion, field by field

Each field is judged on four separate questions: where it is stored, whether it still means the same thing, which reader recovers it, and whether the file passes. No score adds them up.

One 48 kHz, 24-bit stem with its credits written in iXML, ID3, INFO and bext, through the conversions a delivery meets. Our adapter columns evaluate our own chain after ffmpeg, not ffmpeg.

Source file Delivered file, no conversionreferenceAccepted
ffmpeg Resample 48 to 44.1 kHzdefault optionsRefused
ffmpeg Resample 48 to 44.1 kHzpreservation optionRefused
  • Start position, ffmpeg, Resample 48 to 44.1 kHz

    preservation option, source bass.wav

    Integrity

    identical but wrong

    • the number was kept (172,800,000) but the sample rate changed to 44100 Hz: the stem now starts at 1:05:18.37 instead of 1:00:00.00

    Storage, where it physically is

    bext TimeReference

    Reading, which reader recovers it

    • cac-chunks 1.0.0: reads it
    • ffprobe: reads it

    Expected, from the reference model

    1:00:00.00 = 158,760,000 samples at 44100 Hz

    Found in the output

    1:05:18.37 = 172,800,000 samples at 44100 Hz

    Command, run as written

    ffmpeg -nostdin -v error -y -i bass.wav -ar 44100 -c:a pcm_s24le -write_bext 1 out.wav
ffmpeg 24 to 16 bit, same ratepreservation optionRefused
afconvert Resample 48 to 44.1 kHzdefault optionsRefused
afconvert 24 to 16 bit, same ratedefault optionsRefused
sox Resample 48 to 44.1 kHzdefault optionsRefused
flac WAV to FLAC and backdefault optionsRefused
flac The FLAC file itselfpreservation optionRefused
flac WAV to FLAC and backpreservation optionAccepted
zip Zip archive and extractdefault optionsAccepted
ffmpeg + our adapter Resample 48 to 44.1 kHz, then restoreour adapter after the converterAccepted
ffmpeg + our adapter Resample 48 to 44.1 kHz, then restoreour adapter after the converterAccepted

How it was built, and how it checks itself

Agents wrote code and attacked the check. None of them could change the rules, and none of their output was trusted until the check had run on it.

Agents tried to get wrong files accepted

Each round, a fresh agent read the rules, the readers and the fixture builder, then wrote files that a correct check must refuse. The check ran them. Holes were fixed in the rules by a person, never by the agent.

  1. Round 18 of 8 wrong files accepted, after the fixes: 0 of 8
    • The credits add a third writer 'Ines Valdes' with another IPI and society claiming 60 % on top of the real 100 %, so royalties would be paid to a different person.first run: acceptedrule added: every credited entry must match exactly one expected writer; the writer count is checkedreplay: refused. Writer splits: altered (unexpected writer: Ines Valdes)
    • The credits document ties these splits to a different recording (ISRC ZZTST2600099) and a different publisher, so the label would register the splits against the wrong recording and pay the wrong publisher.first run: acceptedrule added: the credits record must name this recording's ISRC and this publisherreplay: refused. Writer splits: altered (credits attached to another recording: ZZTST2600099)
    • The iXML credits read by DAWs and session tools say 70/30 instead of 60/40, so the file carries two contradictory writer splits.first run: acceptedrule added: a carrier whose credits cannot be read makes the splits contradictory instead of being ignoredreplay: refused. Writer splits: contradictory (iXML USER: unreadable profile: float 70.0 not allowed)
    • The file is labelled ND-BASS v3 but contains the vocal stem's audio, so the mix would get two vocal tracks and no bass.first run: acceptedrule added: the decoded audio must be this stem's test tone (frequency within 2 %)replay: refused. Audio: altered (channel 1: content is a 439.75 Hz tone, this stem's test tone is 110 Hz)
    • The stem is pure digital silence of the right length: the bass part is missing from the delivery.first run: acceptedrule added: level within 1 dB of the test tone on every channelreplay: refused. Audio: altered (channel 1: silent)
    • The bass content starts 500 ms after the declared start position (and its last 500 ms are cut), so when spotted at 1:00:00 it plays out of sync with the other stems.first run: acceptedrule added: audio must be audible from the first sample to the last (tolerance 2 ms, or the codec delay for MP3 and AAC)replay: refused. Audio: altered (channel 1: audio starts 0.50 s late)
    • The 24-bit master was replaced by 8-bit mu-law telephony audio, a lossy format that is not a Broadcast Wave PCM stem and would degrade the mix.first run: acceptedrule added: WAV and AIFF deliveries must carry linear PCM of 16 bits or morereplay: refused. Audio: altered (audio is pcm_mulaw, not linear PCM of 16 bits or more)
    • iXML FILE_UID says ND-VOX-v2 and the titles say 'vocal stem', so a DAW or asset system would file this bass stem as the vocal stem.first run: acceptedrule added: iXML FILE_UID and the titles in INFO and ID3 must name the same stem as the credits recordreplay: refused. Stem identity: altered (iXML FILE_UID is 'ND-VOX-v2', expected 'ND-BASS-v3')
  2. Round 28 of 8 wrong files accepted, after the fixes: 0 of 8
    • The file carries a second credits record giving a 70/30 writer split under ID3 TXXX 'cac_credits', which the check ignores but case-insensitive readers such as ffmpeg pick up, so a publisher or collecting society can register the wrong split.first run: acceptedrule added: a credits record under any spelling of TXXX:CAC_CREDITS is read and must agreereplay: refused. Writer splits: contradictory (ID3 TXXX:cac_credits (mutagen 1.48.1 (translate=False)): share changed for Inès Valdés: 60.00 became 70.00; share changed for Théo Marlow: 40.00 became 30.00)
    • iXML SPEED and its BEXT mirror hold the 44.1 kHz sample count (158,760,000) declared at 48 kHz, so DAWs and conform tools that read iXML place the stem at 0:55:07.50 instead of 1:00:00.first run: acceptedrule added: the iXML SPEED timestamp and BEXT mirror must give the same start as bextreplay: refused. Start position: contradictory (bext says 1:00:00.00, but iXML SPEED timestamp says 0:55:07.50 (158,760,000 samples at 48000 Hz); iXML BEXT time reference says 0:55:07.50 (158,760,000 samples at 48000 Hz))
    • The bass stem's iXML BWF_ORIGINATOR_REFERENCE says ND-VOX-v2 and its tracks are named VOX L/R, so asset managers and DAW import tools that read iXML file or label it as the vocal stem.first run: acceptedrule added: the iXML BWF_ORIGINATOR_REFERENCE mirror must name this stemreplay: refused. Stem identity: altered (iXML BWF_ORIGINATOR_REFERENCE is 'ND-VOX-v2', expected 'ND-BASS-v3')
    • The right channel is polarity-inverted, so the bass cancels completely when the stem is folded to mono or summed with a correctly phased copy.first run: acceptedrule added: a sine fit at the stem's tone, per channel: polarityreplay: refused. Audio: altered (channel 2: polarity inverted)
    • The bass stem also contains the vocal stem's content 18 dB down, so muting the vocal in a remix or instrumental version still leaves it audible.first run: acceptedrule added: what remains after removing the tone must stay below -60 dB (-40 dB for MP3 and AAC)replay: refused. Audio: altered (channel 1: -18.1 dB of content other than this stem's tone (limit -60.0 dB): bleed, gap or noise)
    • The vocal stem has a 25 ms digital dropout at 1.000 s, an audible gap that ends up in any mix built from this delivery.first run: acceptedrule added: same residual limit: a gap leaves the fitted tone behindreplay: refused. Audio: altered (channel 1: -18.6 dB of content other than this stem's tone (limit -60.0 dB): bleed, gap or noise)
    • The whole bass stem is 64 samples late (uncompensated plugin latency) while bext still says 1:00:00, so it is out of phase with the other stems when they are lined up.first run: acceptedrule added: the fitted tone must start on time within half a sample (2 samples for MP3 and AAC)replay: refused. Audio: altered (channel 1: audio shifted by +64.0 samples (+1.33 ms))
    • The right channel of the vocal stem is 48 samples behind the left, which smears the stereo image and comb-filters the vocal when the stem is summed to mono.first run: acceptedrule added: same timing limit, per channelreplay: refused. Audio: altered (channel 2: audio shifted by +48.0 samples (+1.00 ms))
  3. Round 36 of 8 wrong files accepted, after the fixes: 0 of 8
    • The bass stem carries a second RIFF INFO list titling it 'Night Drive (vocal stem)', and tools that keep the last INFO list (ffmpeg-based catalogues among them) file it as the vocal stem.first run: acceptedrule added: any chunk present twice (INFO list, data, bext, iXML, id3) refuses the filereplay: refused. container anomalies: 2 'LIST/INFO' chunks in one file: readers disagree on which one counts
    • The iXML TRACK_LIST names both channels 'ND-VOX Lead Vocal', so a DAW importing the bass stem creates tracks and clips labelled as the lead vocal.first run: acceptedrule added: iXML track names may not name another stemreplay: refused. Stem identity: altered (iXML track name 'ND-VOX Lead Vocal L' names the vox stem (ND-VOX))
    • RIFF INFO ISMP gives the start time code as 00:59:58:00 while bext says 01:00:00:00, so a tool spotting the vocal stem from INFO (ffmpeg exposes it as the file timecode) places it two seconds early.first run: acceptedrule added: RIFF INFO ISMP time code must give the same start as bextreplay: refused. Start position: contradictory (bext says 1:00:00.00, but RIFF INFO ISMP says 00:59:58:00)
    • The file's axml chunk declares a 50/50 writer split while the credits profile says 60/40, so a publisher ingesting the BWF XML chunk registers the wrong shares for the composition.first run: acceptedrule added: an axml, XMP or cart chunk refuses the file: it can carry credits and this check does not read itreplay: refused. container anomalies: 'axml' chunk present: it can carry credits and this check does not read it
    • The credits document holds two 'writers' tables (75/25 then 60/40); which split a registration system records depends on its JSON parser, so the writer shares are ambiguous.first run: acceptedrule added: a credits record with a duplicated key is unreadablereplay: refused. Writer splits: altered (iXML USER: unreadable profile: duplicate key 'writers')
    • The vocal stem has a 25 ms digital dropout 40 ms after its start, an audible gap on the first note that the studio would have to repair before the mix.first run: refusedreplay: refused. Audio: altered (channel 1: -38.1 dB of content other than this stem's tone (limit -60.0 dB): bleed, gap or noise)
    • The bass stem has a -1 dBFS click 50 ms before its end, an audible pop that ends up in the mix.first run: refusedreplay: refused. Audio: altered (channel 1: -58.9 dB of content other than this stem's tone (limit -60.0 dB): bleed, gap or noise)
    • The bass stem file contains two data chunks, the first one holding the vocal audio, so DAWs and libsndfile-based tools that play the first data chunk deliver vocals on the bass track.first run: acceptedrule added: same duplicate-chunk rulereplay: refused. container anomalies: 2 'data' chunks in one file: readers disagree on which one counts

Replaying a round's files after fixing the rules for them only proves those holes are closed. The next round, written by a new agent against the fixed rules, is the real test. The rules as they stand after round 3 have not yet faced a new round of attacks.

Agents wrote the tools, against a check they could not see

Each builder worked in its own folder: the task, its one writable file and a few helpers. Not the rules, not the reference model, not the fixtures. No shell. A separate script ran the check and could send the report back for up to 4 takes.

  • Restoring adapter115 s, 289 lines

    Put the delivery metadata back after ffmpeg resamples a stem. Checked on the bass and vocal stems, and again over its own output.

    accepted at take 1. Rules and fixtures unchanged, verified by hash.

  • Credits writer204 s, 551 lines

    Write a label's credits record (shares as "60%", start as timecode) into a bare stem. Checked on a 48 kHz bass stem and a 44.1 kHz vocal stem it had never seen.

    accepted at take 1. Rules and fixtures unchanged, verified by hash.

Both passed at the first take, so the correction loop was never used. The failures and corrections on this page are the red team's, above. Both tools were checked again with the final rules and still pass (the adapter in the Broadcast Wave tab).

The restoring adapter on five variants its builder never saw

  • 96 kHz source resampled to 44.1 kHzaccepted
  • Start at 23:59:00 at 96 kHz (needs the high word), to 48 kHzaccepted
  • 44.1 kHz source upsampled to 96 kHzaccepted
  • Converted by afconvert instead of ffmpegaccepted
  • afconvert to 16 bit, same rateaccepted

A run we threw away

The agent's workspace was the whole repository, so it read cac/acceptance.py (the rules) before writing the adapter. It passed at the first take, but a pass against rules it had read proves nothing about the check's independence. The loop was changed: the agent now works in a separate workspace without the rules, the reference model or the fixtures.

Agents: Claude Code in print mode (opus) on a subscription, started with --safe-mode (no CLAUDE.md, skills, hooks or MCP servers). The account's language setting still applied: their own summaries, kept in the traces, are in French.

The check's own counterexamples

Run before any conversion result is used. All held in this run.

  • Reference fileaccepted
  • 44.1 kHz file with the start position rescaledaccepted
  • Names stored in decomposed Unicode (NFD)accepted
  • Shares swapped between the two writers (sum still 100)refused
  • Shares rounded to 59.99 and 40.01 (sum still 100)refused
  • Second writer missing, first at 100refused
  • First writer listed twice at 30 + 30 (sum still 100)refused
  • Accents stripped from a namerefused
  • IPI number loses its leading zerosrefused
  • Bass file carrying the vocal stem's credits recordrefused
  • 44.1 kHz file keeping the 48 kHz start numberrefused
  • iXML and ID3 carry different splitsrefused
  • An old iXML copy left next to the new onerefused

Harness safety, bounded

  • Container size larger than the filerefused
  • Last chunk cut shortrefused
  • iXML with an entity-expansion payloadrefused
  • 300 chunks in one filerefused
  • A text file named .wavinvalid output
  • File name containing '; touch PWNED'one literal file, nothing run
  • Output path '../escaped.wav'refused before running
  • A step that hangs (sleep 5, limit 1 s)killed, reported
  • Converter not installedtool unavailable, not a pass

These cover this harness's parser and runner only. They are not a security review. Metadata and logs are treated as data, never as instructions to an agent.

What this does not cover

  • Pro Tools and Logic imports, Google Drive and Dropbox round trips: not tested.
  • FileEaters exports and watermarking: not tested. The fixtures are ours, with fictional people and identifiers.
  • The check shows that declared credits were not changed or detached. It does not establish that they were true, or agreed by the people named.
  • The relations between person, IPI, society and share use an explicit profile defined here (cac-credits/1). It is not a standard. DDEX RIN is the industry route for exchanging session and contributor data; it is not implemented here.
  • The RIFF INFO tag named ISRC means Source. Recording codes are read from ID3 TSRC and their equivalents only.
  • ffprobe is recorded as a common viewer, not as a reference: it shows the TIPL role without the person.

How to re-run

From the repository root, on macOS with ffmpeg, flac and sox installed. Source shared on request.

python3 -m venv .venv && .venv/bin/pip install mutagen==1.48.1 pytest
.venv/bin/python -m pytest
.venv/bin/python -m cac.run
.venv/bin/python loop/orchestrate.py --max-iterations 4

This page is generated from one results file: results.json.

Run
20260925T181638Z-3e9bff
Code
86bc583
ffmpeg
9.0.1
afconvert
2.0, macOS 27.0 26A428
flac, sox
flac 1.5.0, sox 14.4.2_6 (Homebrew)
Readers
cac-chunks 1.0.0; mutagen 1.48.1 (translate=False); ffmpeg decode + ffprobe