# OPTION B — the Jamendo API path — MEASURED AND REJECTED

**What this is, for a reader who arrived here cold.** Arm 1 of the house adapter programme needs
486 open-licence house tracks on disk. MTG-Jamendo ships them inside 100 tar archives totalling
544.93 GB, measured at 108–250 hours to pull for 5.9 GB of wanted audio. Two cheaper paths were
proposed: **option B**, fetch each track from Jamendo's own API (~500 requests), and **option C**,
walk the remote tars with HTTP range requests and take only the members we want. The orchestrator
ruled B should be gated on a five-file digest check before all 486 were fetched.

**The gate ran on 2026-09-05 at 23:58Z and B failed it — three separate ways, any one of which is
disqualifying.** Option C is running and is the corpus path. This page is the receipt.

**Both ends of the window, in UTC.** The five-file digest gate ran 2026-09-05T23:58Z. The
486-track licence-and-coverage audit and the two decoded-PCM comparisons ran between
2026-09-06T00:00Z and 00:10Z. All of it used the honest user agent
`strata2signal-research/1.0 (private research; contact via strata2signal.com)` at ~3 requests per
second, with the client id read from `.config/estate/jamendo-client-id` (mode 0600) and never
from a command line or a log.

---

## Finding 1 — the digests do not match: 0 of 5

Five tracks, evenly spaced through the manifest so the sample is not one artist's back catalogue.
Verbatim, from `ace-house-data/house-wide/api-digest-check.json`:

| Track | Artist — title | API bytes | API bitrate | API duration | Manifest duration | Digest matches MTG | Licence agrees |
|---|---|---:|---:|---:|---:|---|---|
| `track_0012410` | #Dance 75# — Feel You | 3,231,570 | 156 kbps | 164.754 s | 164.8 s | **no** | **NO — `by-sa/3.0` → `by-nc-nd/3.0`** |
| `track_0860806` | LongTriggerMusic — Backabeat | 3,409,715 | 201 kbps | 134.269 s | 135.1 s | **no** | yes |
| `track_1096815` | — | — | — | — | — | **NOT RETURNED BY THE API** | — |
| `track_1171625` | — | — | — | — | — | **NOT RETURNED BY THE API** | — |
| `track_1321716` | Oilboy's Aftersun — Dont get me down | 10,829,312 | 213 kbps | 405.055 s | 405.1 s | **no** | yes |

Three fetched, three digests differ; two could not be fetched at all; one licence had changed.

## Finding 2 — it is the same music, re-encoded smaller

A digest mismatch alone would only be a provenance downgrade. So two tracks the ranged walk had
already fetched **from MTG, sha256-verified against MTG's published digest**, were fetched again
from the API and compared byte-for-byte, sample-for-sample, and spectrum-for-spectrum by
`intake/compare_encodes.py` on the archive box.

| | `track_0012414` (#Dance 75# — Neverever) | `track_1105514` (Dj Quincy Ortiz — Sunny Morning) |
|---|---|---|
| MTG bytes / bitrate | 5,322,754 / **320 kbps** | 12,533,595 / **320 kbps** |
| API bytes / bitrate | 2,706,718 / **161 kbps** | 7,957,851 / **203 kbps** |
| API size as a share of MTG | **51 %** | **63 %** |
| Duration (MTG / API) | 133.016 s / 132.991 s | 313.287 s / 313.287 s |
| File sha256 identical | no | no |
| **Decoded-PCM sha256 identical** | **no** | **no** |
| Null test, sample-aligned | **r = 0.9972**, residual 17.8 dB below reference | **r = 0.9990**, residual 19.7 dB below reference |
| Bandwidth ceiling (MTG → API) | 17.05 → 17.03 kHz (−0.02) | 19.95 → **18.69 kHz (−1.26)** |

**Read that null-test row carefully, because it is the whole finding.** A correlation of 0.997–0.999
says this is *the same recording*, not a different master or a different mix — nobody needs to worry
that the API would return the wrong song. But the residual sits only 18–20 dB below the reference,
where a transparent re-encode would be 40 dB down or better, and the second track loses **1.26 kHz
of top end**. Jamendo is serving a materially lower-fidelity encode than the one MTG packed.

A style adapter is trained on the spectral character of its corpus. Taking a 40 % smaller,
1.3 kHz-duller copy to save a few hours is exactly the trade the estate's own bandwidth-audit
lesson exists to prevent.

**A note on how this number was arrived at, because the first version of it was wrong.** The
initial null test reported r = 0.859 and a residual only 5.8 dB down — which would have said
"different audio". It was measuring a 2,180-sample decoder offset, not the music. The alignment
search was refined to sample-exact parity and the honest numbers are the ones above. The coarse
result is recorded here rather than quietly replaced.

## Finding 3 — the catalogue has decayed, and it is now measured properly

This is the finding that ends the discussion, and it is worth more than this train.

**The census, run at 1 request per second with full coverage.** `intake/licence_census.py` asked
Jamendo about all **574** tracks of the union pool — metadata only, no audio — at the ruled polite
rate, with backoff and a stop-on-storm guard. **574 read, 0 unread.** For every track it records
today's licence, today's availability, and the **UTC moment the record was read**, because a
licence census is a reading taken at a moment and a row without its moment is not evidence.

| Census result | Tracks | Share of the union |
|---|---:|---:|
| Read | **574** | 100 % |
| Unread | **0** | 0 % |
| Still on the live catalogue | 290 | 50.5 % |
| **Absent from the live catalogue** | **284** | **49.5 %** |
| **Relicensed OFF the CC0/BY/BY-SA rung** | **20** | 3.5 % |

**Half of a 2019 open-licence house corpus is no longer on the live catalogue at all.** And of the
290 still there, twenty have been re-licensed away from the open rung by their own authors:

| Licence in MTG's file (2019) | Licence on Jamendo today | In the union | Removed from the corpus |
|---|---|---:|---:|
| CC-BY-SA | **CC-BY-NC** | 8 | 8 |
| CC-BY | **CC-BY-NC-ND** | 7 | 6 |
| CC-BY-SA | **CC-BY-NC-ND** | 4 | 2 |
| CC-BY-SA | **CC-BY-NC-SA** | 1 | 1 |
| **TOTAL** | | **20** | **17** |

The two columns differ by 3 because those three tracks were already outside the corpus — the style
fence had removed them before the licence question arose.

**Every drift is in the same direction:** towards NonCommercial, towards NoDerivatives, never
towards more open. Ruling **D-20260905-92** removes the 17 of them that had survived the style
fence, as the named exclusion class `relicensed-since-2019`; each is listed with its old licence,
its new licence and its read timestamp in `PROVENANCE.md`, `CREDITS.md` and
`relicensed-excluded.jsonl`.

**How this number was got wrong first, recorded rather than tidied away.** Three earlier readings
of "how many are gone" returned **244, 269 and 124**, and a confirmation pass returned **124
consecutive HTTP 429s** — proving nothing at all. Two bugs and one bad habit caused it:

- **Jamendo caps a multi-value parameter at 50**, not the 200 its `limit` accepts; the first audit
  died on `Jamendo Api Type Error: The maximum number of multiple values a parameter can receive
  is: 50`.
- **Whole pages silently answer `success` with `results_count: 0`.** Two consecutive audits of the
  same ids disagreed on **125** tracks, and the disagreements came in blocks of exactly 50 and 75
  — multiples of the page size. Taken at face value, that reports live tracks as withdrawn.
- **And then I went too fast.** Retrying hard burnt the rate budget, so the pass that should have
  settled it could not run at all.

The fix was not cleverer code, it was **one request per second, one track per request, a timestamp
on every row, and a stop-on-storm guard** — after which the answer came back complete and stable
on the first try. *An API that answers `success` with zero results is not an API that says a thing
is gone*, and a lane that does not slow down will publish a false number with total confidence.

---

## The verdict

**Option B cannot supply this corpus.** Not because of one flaw but three, and they compound:

1. **it cannot deliver 284 of the 574 tracks at all** — 49.5 % of the pool is off the live
   catalogue (Finding 3);
2. what it does deliver is a 51–63 %-size re-encode, up to 1.26 kHz duller;
3. **20 tracks it would deliver are no longer openly licensed**, so fetching them today and
   training on them would breach the licence rung the whole programme rests on.

**Option C is the corpus path**, and it is the *provenance-clean* one: every file it places is
verified against MTG's own published per-track sha256 before it is written, so the corpus is
byte-identical to the dataset the licences were read from. It was running throughout this
investigation and has not dropped a file.

## What this is worth beyond arm 1

**The open-licence pool decays, and the frozen mirror is the archive.** Of 574 open-licence house
tracks catalogued in 2019, **284 (49.5 %) are no longer on the live catalogue** and **20 more have
been re-licensed to NonCommercial or NoDerivatives by their own authors** — entirely their right,
and entirely invisible to anyone who trusts a dataset's licence file without re-checking. Rather
more than half of a 2019 open-music corpus is, seven years later, either gone or no longer open at
source. MTG-Jamendo's frozen mirror is the only place most of it still exists in the licence state
it was published under.

That has a straight consequence for the estate's method, and it is a candidate ruling rather than
something this lane decides: **a corpus's licence evidence is only as good as the date it was
read.** The mnml pattern already re-reads each item's licence at intake time from the item's own
metadata record. This train cannot do that — re-reading today would *remove* 28 legitimately
intaken tracks whose licence at the time of MTG's cut was open, and the CC licences are
irrevocable for copies already distributed under them. Both readings are defensible. The choice
belongs to the operator, and it is written up as an open question in the lane report.

---

Receipts: `ace-house-data/house-wide/api-digest-check.json`,
`ace-house-data/house-wide/api-licence-audit.json`,
`house-wide-intake/compare-track_0012414.json`,
`house-wide-intake/compare-track_1105514.json`.
Tools: `intake/api_digest_check.py`, `intake/api_licence_audit.py`, `intake/compare_encodes.py`,
`intake/fetch_via_api.py`.
