# PRE-REGISTRATION — THE HOUSE ADAPTER PROGRAMME (arms 1–4), the gate written before any preprocessing step

**Status: v4 — SEALED 2026-09-06T00:32Z by the orchestrator (Fable) with ⧖ H-1 → (b) [D-20260905-95], ⧖ H-2 → P43 variant [D-20260905-96], A5-HOUSE → not taken, arm 1 Jamendo-only [D-20260905-97]; v3 text below is otherwise unchanged. Was: DRAFT v3, PANEL-HARDENED, ORCHESTRATOR-RULED. NOT SEALED. Nothing has been preprocessed,
trained, rendered or embedded for any house arm.** Drafted **2026-09-05T23:1xZ**; v2 (panel folds)
**2026-09-05T23:5xZ**; **v3 2026-09-06T00:2xZ**, folding the orchestrator's rulings on the three seal
questions — **D-20260905-88** (the fence's source-file error, rowed), **D-20260905-91** (THE FENCE v2,
machine-readable at `ace-house-data/house-wide-fence.json`), the resolved acquisition route (§2.7),
and the gate's shape accepted as v2 registered it (§7.3). Written by the `prereg` lane under
`estate/bench/ace-house-2026-09/CONTEXT.md` and `BRIEF-prereg.md`, after a two-lens hardening panel
(`panel/PANEL-method.md`, `panel/PANEL-laws-ops.md`). **The seal is the orchestrator's; §15 now carries
two open rulings, not five.**

---

## §0 — WHAT THIS FILE IS, FOR A READER WHO ARRIVED COLD

### 0.1 The one-paragraph version

An operator is training LoRA style adapters on ACE-Step 1.5 — a local, MIT-licensed text-to-music
model — from open-licence music corpora. The previous train (`mnml0`, 159 tracks of "minimal techno"
matched by an archive.org subject tag) produced an adapter the operator's blind ear **rejected**, and
the write-up named **placeholder captions** as its most quotable causal candidate. This programme runs
four arms over house music to separate the things that trained together last time: **size** (arm 1, a
~433-track wide corpus), **coherence at matched size** (arm 2), **one artist at scale** (arm 3), and
**the unchanged instrument** (arm 4, the base model). This file fixes, in advance of the first
preprocessing step, what each arm's corpus is, how it is acquired, how it is split, how its captions
are written, what recipe trains it, which checkpoint ships, how the result is judged, and — written
before any result exists — **the sentence a passing result is allowed to support and the sentence it
is not.**

### 0.2 Dated at both ends

Registered **2026-09-05 (UTC)**. Governs every acquisition, preprocessing, training, render and
embedding step of house arms 1–4 from the seal onward, until superseded by a dated amendment appended
below §16. Nothing had been preprocessed or trained for any house arm when this was written; no house
audio existed on any estate box (receipt: `music/corpus/` held only `19add ·
bach-shakedown · pd-shakedown · sousa-shakedown` at 2026-09-05T23:1xZ).

**Stamp discipline.** Every time in this file is `date -u` on the laptop at the moment of writing. v1
carried three stamps ~50 minutes ahead of its own file mtime; they were corrected in v2, because a
document whose entire value is chronological priority may not carry a stamp from the future.

### 0.3 The standing constraint that outranks every number in this file

**MEASURED, NEVER GATING** (D-20260831-17). No embedding number, no loss, no automatic score
promotes or retires an adapter. The instrument of record is **the operator's blind ear** (§7). Every
other number rides beside that verdict and never in front of it. *(The one inherited exception, named:
the Audiobox PQ floor of §7.5.1, which is a degradation detector, not a preference one.)*

### 0.4 Seal

`sha256(this file at registration) = 182e3361747811f2080c0c7f984630109fc4a0cbf559d2b67ca9bbf60495e3f2`

Computed with that line reading exactly `sha256(this file at registration) = ⧖ TO BE FILLED AT SEAL`.
**To verify:** copy the sealed file, restore that one line to the placeholder text, `sha256sum` the
copy, compare. Timebase: **UTC** throughout.

**A run whose manifest names no prereg sha is UNGATED, not passed.**

### 0.5 Location, ledger rows, amendment rule

- **Location of record:** `estate/bench/ace-house-2026-09/PREREG-HOUSE-ARMS.md` (this file), on
  **the laptop**, inside the `estate` git repo — the commit timestamp is the
  "provably before the first GPU call" evidence. **The seal commit names this file by explicit path**
  (the shared-checkout law: `estate` carries other sessions' uncommitted work; `git add <path>`,
  never `git add .`, and `git show --stat HEAD` is read before any push).
- **Ledger rows, added in the same stroke as the seal** (LAW 1). **Two rows are owed, not one:**
  1. **`PREREG-ROUND4.md` has no ledger row and no seal** (measured: `grep -c 'PREREG-ROUND4'
     PREREG-LEDGER-OF-LEDGERS.md` → 0), yet this file inherits its twelve prompts, seeds and render
     pins **verbatim**. That is the 46ef99db failure the ledger was founded to prevent. **Row 26 =
     Round 4**, labelled honestly as body-not-sha-sealed, its pins receipted from
     `music/out/mnml-round4/round-4/records.json`.
  2. **Row 27 = this file** (§14 carries both proposed row texts).
- **A rule-2 hunt must read this row and rows 24, 25 and 26**: the eval instrument pin (Amendment A1)
  lives in row 24, the coherence instrument in row 25, and the twelve prompts / seeds / render pins
  this file reuses verbatim in row 26.
- **Amendment rule.** Amendments are **numbered, additive, dated, and never rewrite history**. An
  amendment may only be filed **before the first step of the thing it governs**. Owed amendments are
  named in §12 with the step each must precede. **If an owed amendment is not filed before the step
  it governs, the criterion it carries degrades to DESCRIPTIVE for that run** — it does not silently
  become a pass. (Inherited verbatim from `PREREG-ACE-LORA-FIRST-TRAIN-2026-08-27.md` §0.)

### 0.6 What this file inherits, and the two places it declines an inheritance

| inherited | from | what it means here |
|---|---|---|
| the 2AFC instrument, the binomial tables, the sentinel band, the non-claim, the Rung-2 conjunction | `PREREG-ACE-LORA-FIRST-TRAIN-2026-08-27.md` §1–§5, §9 | reused; §7 states the deltas, and §7.6 restores the conjunction v1 had dropped |
| the eval instrument pin (Audiobox-Aesthetics 0.0.4, CLAP-laion-music, torch 2.8.0+cpu, weight shas) | **Amendment A1**, filed 2026-08-29 | **A1 is FILED, so §7.5.1's floor check is BINDING** — verified live: `music/venvs/eval/freeze-A1.txt` sha256 `258a10ee9966ed60eb7839ce9ae9695c431277e4e324564c9fe2bf4e2550ebb1`, matching A1 to the digit, both weight files present at A1's byte counts |
| the coherence crop policy, estimator, seeds, duplicate-pair rule, non-claims | `PREREG-COHERENCE.md` §4–§9 + its A1 pin | §8 re-runs that instrument; **the archived embeddings are reused at their pinned sha and never re-cut** (§8.3) |
| the twelve Round-4 prompts, seeds, arms and render pins | `PREREG-ROUND4.md` §3–§4 (row 26) | reused **verbatim** (§7.2), including its **shift 1.0 / 30 s** pins, which differ from the first prereg's §1 |
| the licence rung and the share-alike posture | D-20260831-01 | §2.2 |
| ~20 % holdout, no unit straddles | D-20260831-03 | escalated from release-level to **artist-level**, §3 |
| checkpoint by best loss; epochs scale down with corpus size | `AUDIO-WORKFLOW-LESSONS-2026-08-30.md` 1–2 | §5.2, §6 |
| the style fence | **D-20260905-84** as amended → **corrected by D-20260905-88** → **re-ruled as FENCE v2 by D-20260905-91**, machine-readable at `ace-house-data/house-wide-fence.json` | §2.3 |
| the 240 s sample cap | **D-20260905-86** | §5.1, §5.6 |

**DECLINED, and declining is registered rather than slipped through:**

1. **The first prereg's §8 null-instrument stop condition is NOT inherited.** §7.4 explains why, and
   the declination is filed as its own numbered amendment against row 24 **in the same stroke as this
   seal** — not recorded only here.
2. **The first prereg's §1 clip length and shift (25 s, shift 3.0) are NOT inherited.** Round 4's pins
   (30 s, shift 1.0) are, so the arms compare across articles. Registered in §7.4.

---

## §1 — THE FOUR ARMS, AND WHAT EACH ISOLATES

| arm | slug | corpus | isolates | trains |
|---|---|---|---|---|
| **1 — WIDE** | `house-wide` | every open-licence house track the intake lanes clear (§2) | **size** | this week |
| 2 — COHERENT CORE | `house-core` | arm 1's **training side** pruned by CLAP distance to a seed set the operator picks by ear, cut to **159 TRAINING tracks** | **coherence at matched size** | later, §13.1 |
| 3 — ONE ARTIST AT SCALE | `house-artist` | the top open house artist by track count (§13.2) | the one-artist control's shape at larger N | later, §13.2 |
| 4 — baseline | — | none: the unmodified base model | **the instrument stays the same** | never (it is the base arm of every trial) |

**Arms 2 and 3 are registered NOW, before arm 1 trains, so their later runs cannot move the
goalposts.** §13 fixes the pruning instrument, the artist-pick rule, the size-match level, the recipe
each inherits, and the two degeneracies the panel measured in them.

### 1.1 The confound this programme must not pretend away, stated first

Arm 1 differs from `mnml0` in **at least six** ways at once: genre, source host, corpus size, caption
regime, training box, and epoch count. **No arm-1 result — good or bad — can attribute a difference
to captions**, which is the variable the mnml write-up flagged as its most quotable causal candidate.
The caption regime is applied here because D-20260827-P43 requires it and because placeholders are
known to be bad practice, **not as an experiment about captions.** §10.3 states this again as a
non-claim, in the form the article must carry.

---

## §2 — THE CORPUS FREEZE RULE

### 2.1 What "frozen" means

The corpus is frozen **once**, after both intake lanes report and the orchestrator rules §15. The
freeze emits:

1. `ace-house-data/house-wide/manifest.jsonl` — one line per accepted track: `track_id`,
   `artist_id`, `artist_name`, `album_id`, `title`, source URL, licence (short form **and** the
   verbatim URL as the source wrote it), duration, tag list, dataset path, acquisition route (§2.7),
   and — once the audio exists — the file's `sha256`, byte count, **measured bandwidth ceiling** and
   integrated LUFS.
2. `MANIFEST.sha256` over the audio bytes, on the box that holds them.
3. **`record_manifest_sha256` = sha256 of `manifest.jsonl` itself** — the corpus freeze identity.
   ⚠ **It is NOT what `freeze_point.manifest_sha256` holds.** That column is defined as *"sha256 of
   the manifest.sha256 file itself"* (`0001_v0.sql:161`) and mnml0's row holds that; putting a
   different artifact there would make the house row non-comparable in the same column (§11.3 gap 7).
4. `PROVENANCE.md` + `CREDITS.md` beside the audio, in the mnml pattern
   (`music/corpus/mnml-shakedown/PROVENANCE.md`), per D-20260831-04's named bypass.
5. **The audio-product assertion.** For every accepted file the freeze records `ffprobe`'s measured
   duration and compares it to the tag file's `DURATION`. **STOP CONDITION: if the median absolute
   difference exceeds 2 s, or the median measured duration is below 60 s, the wrong audio product was
   pulled (MTG's 30 s excerpt set rather than full tracks) and the freeze aborts.** Measured
   expectation from the metadata, recorded before the pull: median **288.0 s**, min **30.1 s**, max
   **905.2 s**, 0 tracks below 30 s, 0 tracks at or above 20 min. *(The registered tag file is called
   `raw_30s.tsv` and MTG ships both products; the name is about the tag-extraction window, not the
   audio. This assertion is what makes that safe.)*

6. **The fence spec, pinned.** `house-wide-fence.json`'s sha256 (§2.3.1) is asserted by read-back and
   recorded in the freeze beside the tag file's sha, so "which fence produced this corpus" is a hash,
   not a memory.
7. **The acquisition digest chain** (§2.7): for every API-fetched file, MTG's published per-track
   digest and the fetched bytes' own `local_sha256`, plus the match/mismatch verdict per file.

**A track that is not in the frozen manifest is not in the corpus.** After the freeze, adding or
removing a track is a **new freeze with a new sha and a dated amendment**, never an edit.

### 2.2 The licence rung (D-20260831-01)

**CC0 · CC BY · CC BY-SA only. NC and ND never.** Licence is read per track from the source's own
record, stored verbatim; the record's URL is the evidence.

- Licence source of record for the Jamendo arm: `ace-house-data/metadata/mtg/audio_licenses.txt`
  (sha256 `c207c476d1714dfc9061f5ae9f2047c0490bfaa5d861dc090acc786508948933`, 12,686,550 B,
  222,804 lines, read 2026-09-05T23:1xZ). **That file IS the attribution source.**
- Measured census over all 55,701 entries: `by-nc-sa 21,399 · by-nc-nd 15,584 · by-sa 9,933 ·
  by-nd 3,303 · by 3,122 · by-nc 2,274 · no CC licence line 86`. **Zero CC0.** The open rung for the
  Jamendo arm is therefore **BY + BY-SA only**.
- ⚠ **The 86 entries with no CC licence line are not "unlicensed".** They are **Licence Art Libre
  (LAL)** — an open copyleft licence the estate has never ruled on. **REGISTERED: LAL tracks are
  EXCLUDED from arm 1** under E1, named as their own class, because D-20260831-01's rung names
  CC0/BY/BY-SA and LAL is not among them. Ruling LAL in is a separate DECISIONS row, not a lane's
  reading. *(None is in the house pool; the exclusion is registered so the class cannot be quietly
  absorbed later.)*
- **The adapter is share-alike-encumbered** (D-20260831-01): it leaves the estate only as BY-SA with
  credits; estate-internal use unaffected. `adapter.licence_posture = 'share_alike_encumbered'`,
  asserted by read-back.
- **The egress ladder is NOT inherited by default.** D-20260827-P45: tier (a) estate-internal is
  standing; **tier (b) the gated review shelf and tier (c) public need the operator's fresh, named go per
  artifact.** Renders made with a share-alike-encumbered adapter **do not automatically inherit a
  posture** — every listening clip that reaches the shelf needs an `egress_grant` row carrying
  the operator's own words, and `egress_event` records the act. **No lane publishes anything.**
- **A track whose licence cannot be read first-hand is excluded, not assumed open** (class E2).
- **⚠ THE LICENCE SURFACE MOVED UNDER THE DATASET, and D-20260905-92 rules what happens
  (the operator: "Drop the 30, keep the rest").** MTG-Jamendo's licence file records each track's licence
  **as it stood when the dataset was cut in 2019**. The API audit of 2026-09-06
  (`ace-house-data/house-wide/api-licence-audit.json`, 486 rows; summarised in
  `OPTION-B-VERDICT.md` Finding 3) re-read the *live* catalogue and found **30 tracks whose authors
  have since relicensed them OFF the open rung** — `CC-BY-SA → CC-BY-NC` ×12, `CC-BY-SA →
  CC-BY-NC-ND` ×9, `CC-BY → CC-BY-NC-ND` ×8, `CC-BY-SA → CC-BY-NC-SA` ×1. **Measured against the
  FENCE v2 cut: 26 of the 30 are in the 433** (the other 4 were already fenced out on style).
  **They leave the corpus as exclusion class E9 `relicensed-since-2019`, with the API evidence
  recorded beside each.**
  **The estate's rung is stricter than the law, and that is the point:** a CC grant is irrevocable
  for copies already distributed, so training on the 2019 grant would be *lawful*. **An artist who
  withdrew the open grant has said what they want**, and D-20260905-92 rules that the corpus honours
  the statement rather than the loophole. **This is a first-class finding for the article** — an
  open-licence dataset is a **snapshot of consent, not a standing one**, and nobody who reuses a 2019
  research corpus is told when its authors change their minds.
  **The 124 tracks whose current licence could not be read (HTTP 429, of which 105 are in the 433)
  STAY IN under their frozen 2019 licence** until the census completes; **the same rule applies to
  any of them found relicensed before the freeze** — each such track joins E9 with its evidence. The
  **census result is stated in the article**, including how many were never readable.

### 2.3 THE STYLE FENCE (D-20260905-84 → corrected by D-20260905-88 → FENCE v2 by D-20260905-91)

the operator, verbatim:

> "let's try to keep acid house out of this set, but deep house, house, tech house, (those all are
> adjacent enough imo to sound ok together)"

and, amending the same night:

> "and maybe remove 'hard house' too, can we see what actual tags exist in our training set before we
> begin?"

**IN:** house · deep house · tech house. **OUT:** acid house, and the block-list below.

### 2.3.1 FENCE v2 — the ruling of record, and it is MACHINE-READABLE

**D-20260905-84 as amended is CORRECTED by D-20260905-88 and RE-RULED as FENCE v2 by
D-20260905-91.** The correction, in one sentence: the tag list shown to the operator and D-84's own
`570 → 486 / "Acid = 0 tracks in the pool"` figures came from
`raw_30s_cleantags_50artists.tsv` (the repo's `autotagging.tsv` **symlink**), whose tag-cleaning
**deletes rare tags including `acidhouse` and `techhouse`** — so the fence had been disarmed by the
file, not satisfied by the corpus, and the eight acid tracks would all have trained. the operator was then
shown the **real** vocabulary from `raw_30s.tsv` (the open IN-set carries **85 genre / 38 instrument /
73 mood** tags) and re-ruled the fence on it.

**THE FENCE IS A FILE, NOT PROSE.** The cut of record is
**`ace-house-data/house-wide-fence.json`**, sha256
**`a1a4c8b04151e9b187d33f76c3c37b3b10073e70185916966325689d81e8aecb`** (661 B, read by this lane
2026-09-06T00:1xZ). **The freeze asserts that sha by read-back before the first exclusion is
written**, and the fence report echoes it (`fence_spec_sha256`) beside the tag file's own sha. Prose
below reproduces the file for readability; **where the two ever disagree, the JSON wins.**

| field | value |
|---|---|
| `source` | `raw_30s.tsv` (§2.5) |
| `licences` | `by` · `by-sa` · `cc0` *(zero CC0 exist in MTG-Jamendo — the term is registered for the archive.org rung)* |
| `in_tags` | **`house` · `deephouse` · `techhouse`** — tech house is now read from **its own tag**, not inferred |
| `out_tags` (29) | `acid · acidhouse · acidjazz · breakbeat · dancehall · drumnbass · dubstep · ebm · edm · electrohouse · electropunk · ethnicrock · eurodance · hard · hardstyle · hiphop · houseelectro · minimaltechno · progressivehouse · progressivemetal · psytrance · rap · rave · reggae · rock · singersongwriter · technohouse · trance · trancetechno` |
| `title_regex` | `\b(acid\|hard ?house\|hardstyle\|hard)\b`, case-insensitive |
| `ruling` | **D-20260905-91** |

**Three properties of FENCE v2, registered:**

1. **The IN rule widened and the OUT list grew — both in the same ruling.** `techhouse` adds **7**
   tracks that carry no `house`/`deephouse` tag (the class v2 had to exclude as E3-b; **E3-b is now
   closed**), taking the IN-set from 567 to **574**. The OUT list gained fourteen terms, of which the
   **house hybrids** (`houseelectro` 28 · `progressivehouse` 16 · `electrohouse` 9 · `technohouse` 6 ·
   `rave` 2 · `minimaltechno` 4) are the substantive cut: **65 tracks that ARE house-tagged are
   fenced out as hybrids.** That is the operator's ear ruling on adjacency, and the article says so
   rather than presenting the fence as a neutral filter.
2. **No substring rule is needed any more.** `acid` and `acidhouse` are both named explicitly.
   Verified on the IN-set: the only acid-family genre tags present are `acid` and `acidhouse`, and
   **both are covered by `out_tags`** — so the fence is exactly the JSON, with no implicit clause.
3. **The block-list still wins over the IN list, by construction.** A track tagged both `techhouse`
   and `trance` goes out. Measured: `house ∧ techno` (the old inferred cross-tab) counts **81** in the
   fenced pool, and `techhouse`-tagged counts **33** — both reported descriptively, neither is the IN
   mechanism.

**The title rule matches WHOLE WORDS, never bare substrings** — a bare substring would catch
*Richard*, *Hardware*, *Chardonnay*. It fires on **two** titles in the IN-set: `track_1165635`
*"DJ Dr@fT - Hard mix"* (the one net-new exclusion — no genre clause catches it) and `track_1196247`
*"Fireball [hardstyle]"* (already removed by its tags). ⚠ For the archive.org rung a bare `\bhard\b`
is over-broad on ordinary titles ("Hard Times"); **A5-HOUSE narrows it to
`\b(acid|hardstyle)\b|\bhard\s*house\b` for that rung only.**

**archive.org rung:** subjects `"house"`, `"deep house"`, `"tech house"` are probed as sources;
`"acid house"` subjects and the same `out_tags` where an item's subjects carry them are excluded.

**Every excluded track is named in the intake doc, never silently dropped** — D-20260905-84's own
closing clause, carried forward.

### 2.3.2 Measured impact of FENCE v2

Computed independently by this lane over `raw_30s.tsv` ∩ `audio_licenses.txt`, 2026-09-06T00:1xZ, and
**reproduced to the row by the intake lane's rebuild** (`ace-house-data/house-wide/fence-report.json`,
`"applied": true`, `"excluded": 141`, `fence_spec_sha256` matching the sha above):

| excluded by | tracks |
|---|---:|
| `trance` | 46 |
| `houseelectro` | 28 |
| `progressivehouse` | 16 |
| `edm` | 13 |
| `drumnbass` | 10 |
| `eurodance` · `dubstep` · `electrohouse` | 9 each |
| `acidhouse` | 7 |
| `technohouse` | 6 |
| `minimaltechno` | 4 |
| `hiphop` · `dancehall` | 3 each |
| `rave` · `progressivemetal` · `breakbeat` | 2 each |
| `acid` · `singersongwriter` · `ebm` · `rock` · `trancetechno` · `reggae` · `ethnicrock` · `hard` · `hardstyle` · `rap` · `electropunk` · `psytrance` | 1 each |
| title match (`DJ Dr@fT - Hard mix`, net-new) | 1 |
| **distinct tracks excluded** | **141** |

*(The column sums to more than 141 because a track may carry several blocked tags.)*
**IN-set 574 → POOL 433. The fence costs 141 tracks = 24.6 % and 11.31 h**, and `trance` plus the
house hybrids are three quarters of it.

**The eight acid tracks, named** (all eight would have trained under the pre-correction fence; all
eight are absent from the rebuilt manifest, verified by `grep -c` → 0 each):

| track_id | title | artist | tag |
|---|---|---|---|
| `track_0134387` | Digmar | Bsl & Bass | `genre---acid` |
| `track_0647580` | money- | PBMatrics | `genre---acidhouse` |
| `track_0661498` | Mr. BuG - The Day of Liberty (Original Mix) | Mr. BuG | `genre---acidhouse` |
| `track_1209893` | 20 Cymric ( House Mix ) | Hasenchat | `genre---acidhouse` |
| `track_1218127` | 19 Metek ( Guitar Mix ) | Hasenchat | `genre---acidhouse` |
| `track_1268139` | 11 Paradise ( Tropic House Mix ) | Hasenchat | `genre---acidhouse` |
| `track_1295802` | Housewife Bass | Hasenchat | `genre---acidhouse` |
| `track_1341177` | 10.Penetration | J.O.R.B.I | `genre---acidhouse` |

**⚠ What the fence does NOT do.** It removes tracks whose *published tags* say another genre. It does
not listen. A house-tagged track that is in fact a trance record with no trance tag stays in; a
genuinely house record tagged `trance` by its uploader goes out. **The fence is a metadata operation
on a folksonomy**, with the same limits the mnml write-up gave the archive.org subject tag, and the
article says so.

⚠ **One id fix owed downstream:** `ace-house-data/house-wide/fence-report.json` records
`"ruling": "D-20260905-89"`. The ruling of record is **D-20260905-91**; `-88`/`-89` were minted twice
on 2026-09-06 by two sessions (the estate's known ledger-hygiene hazard). The intake lane's next write
corrects the string; the JSON's sha is unaffected because the id lives in the report, not the spec.

### 2.4 The exclusion classes, fixed in advance

| # | class | rule |
|---|---|---|
| E1 | **licence** | not CC0 / BY / BY-SA in the source's own record, or the record cannot be read first-hand. **Includes Licence Art Libre** (§2.2) as sub-class `E1-lal` |
| E2 | **paperwork trap** | licence field and licence body disagree; PD-mark or PD-declaration on a modern release (D-20260831-01(b)) |
| E3 | **style fence** | FENCE v2 exactly as `house-wide-fence.json` defines it (§2.3.1), sha-asserted — **every exclusion named** |
| ~~E3-b~~ | **CLOSED by D-20260905-91** | the 7 `techhouse`-only tracks are now **IN**, not excluded; the class is retired and named here so a reader of v2 knows why it vanished |
| E4 | **not a track** | duration ≥ **20 min** (a DJ set — `MINIMAL-TECHNO-INTAKE:180`: *"Training on it would teach an adapter to imitate mixing, not composition"*) or < **30 s** |
| E5 | **duplicate / near-duplicate** | same audio bytes (sha256) as an accepted track; **or** the same normalised title+artist across two releases; **or** a cross-split acoustic near-duplicate (§3.1(7)). Earliest release at the best bandwidth wins; the loser is named |
| E6 | **AI-generated** | Udio / Suno / "AI" in the item title, description or subject (archive.org arm) |
| E7 | **damaged / telephone-rate source** | the file fails to decode, or its container rate proves a telephone-rate re-encode. **Bandwidth is stored as metadata for every accepted file and is NEVER a threshold** (lesson 3). Every E7 exclusion names the measured number |
| E8 | **catalogue the uploader could not license** | archive.org rung only. The minimal-techno survey measured this at ~51 % of a naive CC0 harvest; it has its own class so the archive rung cannot smuggle it in under E2 |
| **E9** | **`relicensed-since-2019`** (D-20260905-92) | the live Jamendo API reports a licence **off the CC0/BY/BY-SA rung** where the 2019 dataset record reported an open one. **Measured: 26 in the FENCE v2 cut** (30 across the void 486). Each exclusion names its 2019 licence, its licence today, and the API evidence row. **Applied again to any of the 105 unreadable-today tracks found relicensed before the freeze.** ⚠ This class is a *consent* exclusion, not a legal one — see §2.2 |

**No other exclusion may be applied.** A track dropped for any reason not in this table is a
deviation and is reported as one.

### 2.5 The pinned metadata inputs — and the build that must be voided

| file | bytes | rows | sha256 | pool | genre tags in pool | acid hits |
|---|---:|---:|---|---:|---:|---:|
| **`raw_30s.tsv`** ✅ **REGISTERED (tags + fence + captions)** | 8,399,247 | 55,701 | `4673e71953852a2e6c15ece1db8784cc59c6f1f62914e3850b741e36e01fe784` | **567** | **85** | **8** |
| `raw_30s_cleantags_50artists.tsv` ❌ (= the `autotagging.tsv` symlink) | 7,807,534 | 55,609 | `a30655f45f4a7b4f9dba2d6b51d78733be33687eae3e8b9795e2234d54ef4e56` | 570 | 52 | **0** |
| `autotagging_genre.tsv` ❌ (genre projection only) | 5,710,640 | 55,215 | `2b59cf0ba1c447da88858f7f51bdd8b15f791e65330b1710918324543680a998` | 570 | — | 0 |

Also pinned: `raw.meta.tsv` (7,848,074 B, 56,640 lines, sha
`bb1efa2876536cbe1a8b67db5dda15249ca144f0cff69e481b638803cbdc9aca`) for track/artist/album names and
Jamendo URLs; MTG repo commit **`cafd8e20c265ed84f1e61f1c875327971f43a62f`**; per-track published
sha256 from `metadata/mtg/download/raw_30s_audio_sha256_tracks.txt`.
⚠ **`genre.txt` in that directory is 14 bytes of the literal text `404: Not Found`** (sha
`d5558cd4…`, a failed fetch). It is not a vocabulary file and nothing may read it.

**Why `raw_30s.tsv` and not the merged file.** The cleantags file's tag-cleaning step **deletes the
`acid` and `acidhouse` tags entirely** (measured: its whole-dataset vocabulary is 195 tags and
contains only `acidjazz`; `raw_30s.tsv`'s is 692 and contains `acid`, `acidhouse`, `acidrock`,
`acidjazz`). **On the merged file the operator's ruling removes zero tracks.** The intake lane's
counter-argument — that the merge recovers `housemusic → house` and yields 570 rather than 567 — is
recorded here and **declined**: a fence that depends on which of two files a lane happened to open is
not a fence. The recovery is handled explicitly instead, by FENCE v2's IN rule (§2.3.1), with the
measured new-track counts (`techhouse` +7 · `houseelectro` +15 · `progressivehouse` +11 ·
`electrohouse` +5 · `housemusic` +3 · `dancehouse` +3 · `technohouse` +1; `acidhouse` +20 stays OUT).

*(Correction owed to v1, self-caught: v1 said `raw_30s.tsv` carries "the 195-tag vocabulary". Measured,
`raw_30s.tsv` carries **692** dataset-wide tags and the cleantags file carries **195**. The reason to
register `raw_30s.tsv` is the acid tags, not the vocabulary size.)*

**⚠ REGISTERED — THE 2026-09-05T17:18Z BUILD IS VOID.**
`ace-house-data/house-wide/manifest.jsonl` (486 rows), `fence-report.json` (84 excluded),
`style-excluded.jsonl`, `acid-excluded.jsonl` (**0 bytes**) and `CREDITS.md` as they stood at
2026-09-05T17:18Z were built against the cleantags file. **All eight tracks in §2.3's table are
present in that manifest** (verified: each `track_id` greps to exactly 1 hit). **They are not the
frozen corpus and no downstream step may read them.** The freeze rebuilds from `raw_30s.tsv`, sha
asserted by read-back before the first exclusion is written. **The rebuild's receipt is
`acid-excluded.jsonl` containing exactly the eight `track_id`s above — an empty file is a stop
condition, not a pass.**

### 2.6 The corpus under FENCE v2 — measured by three independent computations

Computed by this lane 2026-09-06T00:1xZ over `raw_30s.tsv` ∩ `audio_licenses.txt` (both shas in §2.5)
under `house-wide-fence.json` (sha in §2.3.1), **before** E4–E8 (which need the audio):

| quantity | measured |
|---|---:|
| tracks tagged `house` (open licence) | 533 |
| tracks tagged `deephouse` (open licence) | 89 |
| tracks tagged `techhouse` (open licence) | 44 |
| — of which carry no `house`/`deephouse` tag (**new under FENCE v2**) | **7** |
| **IN-SET, open licence, before the fence** | **574** |
| style-fenced out (§2.3.2) | **141** (24.6 %, 11.31 h) |
| **POOL AFTER THE FENCE** | **433** |
| **E9 `relicensed-since-2019`** (D-20260905-92, §2.2) | **−26** of the 30 (4 were already fenced) |
| **POOL AFTER FENCE + E9** | **407** ⟦the freeze fills the final figure⟧ |
| — still-unreadable today (HTTP 429), kept under the frozen 2019 licence | **105** of the 124 |
| licence mix | **BY-SA 289 · BY 144 · CC0 0** |
| distinct artists | **96** |
| total audio | **36.56 h** raw / **27.34 h** at the 240 s cap (mean capped duration **227.3 s**) |
| duration distribution | median **290.7 s** · min **30.1 s** · max **905.2 s** |
| `techhouse`-tagged in the fenced pool (descriptive) | **33** |
| `house ∧ techno` in the fenced pool (the old inferred cross-tab, descriptive) | **81** |
| largest artist | `artist_487628` "Oilboy's Aftersun", **47** tracks (**10.9 %**), all CC BY 3.0 |
| top-5 artist share | 31.2 % |
| artists with exactly one track | 37 |
| tag vocabulary, IN-set before the fence | genre **85** · instrument **38** · mood **73** |

**THREE INDEPENDENT COMPUTATIONS AGREE ON 433.** This lane's own pass over the pinned files; the
orchestrator's expected N relayed with D-20260905-91 (*"433 tracks / 36.6 h / 96 artists"*); and the
intake lane's **rebuilt** `ace-house-data/house-wide/manifest.jsonl` — **433 rows**, sha256
`a9abcd6a8140d508fb56bd761c437f47b65444901ce46bd859efb779e966df3d`, beside a 141-row
`style-excluded.jsonl` and a 574-row `manifest-union.jsonl`, with `fence-report.json` echoing the
fence spec's sha. **The v2-era 486-row build is void (§2.5) and all eight acid tracks are absent from
the rebuild** (`grep -c` → 0 each).

**These are still PROJECTIONS of the frozen corpus.** E4–E8 fire only once the audio exists, and E9
can still grow if any of the 105 unreadable tracks resolves off the rung before the freeze, so the
frozen N can only fall from **407**; it rises only if A5-HOUSE admits the archive rung.
*(The orchestrator's relayed expectation was ≈ 403; measured it is **407**, because 4 of the 30
relicensed tracks were already removed by FENCE v2 and cannot be subtracted twice.)* **The freeze records the
actual numbers; this table is what was known before it**, and the difference between the two is
itself reported.

**⚠ Corpus sizes in flight in this directory: 433 (this file and the rebuilt manifest — the number of
record), 476 (this file's own v2, pre-FENCE-v2), 486 (the voided build), 625 (the runbook's planning
figure).** The freeze's first act is to publish one number and correct the others by name.

### 2.7 THE ACQUISITION ROUTE, REGISTERED (because the route changes the corpus's identity)

**The MTG tar route is registered as MEASURED-INFEASIBLE for this window**, not abandoned silently:
the manifest touches all 100 tars = **544.93 GB**; measured mirror throughput **0.665 MB/s** from the archive box,
one stream (315 MB in 473 s) = **228 h (9.5 days)**. MTG shards by the last two digits of the track
id, which is arbitrary with respect to genre, so **no subset of the tars can be pulled instead**. The
audio is wanted by 2026-09-06T18:00Z — about 18 hours. **228 h ≠ 18 h.**

**RESOLVED, and the route is REGISTERED: the Jamendo API.** the operator's client id landed
2026-09-06 ~00:1xZ; `intake/fetch_via_api.py` reads it **from an environment variable, never argv**;
honest UA (`strata2signal-research/1.0 (private research; contact via strata2signal.com)`), one
stream, ~3 req/s. **The fetch is gated on a five-file MTG-digest check that runs FIRST**
(`ace-house-data/house-wide/api-digest-check.json`) — five tracks are fetched through the API and
their bytes hashed against MTG's published per-track digest before the bulk pull is allowed to start.

**THE PROVENANCE CHAIN, registered as the digest match itself.** For every API-fetched file the freeze
records MTG's `published_sha256`, the fetched bytes' `local_sha256`, and the **verdict**:

- **match** → the chain is complete: MTG's dataset record and the Jamendo delivery are the same bytes,
  so the corpus keeps MTG's provenance *and* gains a first-hand fetch receipt.
  `source_file.integrity_verified_at` is set, and the provenance line reads *"Jamendo API on ⟦date⟧,
  bytes verified against the MTG-Jamendo published digest"*.
- **mismatch** → the file is **kept only with its mismatch recorded**: `integrity_verified_at` stays
  NULL, `published_sha256` is marked **non-verifying** for that file, and the provenance line drops the
  MTG half. **The per-file verdict is a first-class column, never a corpus-level assumption**, and the
  freeze publishes the match rate.
- **If the five-file check fails outright, the bulk fetch does not start** and the orchestrator is
  told; a lane does not relax the check.

Three registered consequences of the route, written before the bulk fetch:

1. **The provenance line changes** from *"MTG-Jamendo raw_30s tar NN"* to *"Jamendo API on ⟦date⟧"*,
   per track, in `manifest.jsonl` and `PROVENANCE.md` — **qualified per file by the digest verdict
   above**, never by a blanket sentence.
2. **E7 is re-based and §9.2's P-A reasoning is amended in the same stroke.** The delivery format is
   no longer assumed to be 320 kbps MP3. The measured bandwidth ceiling is recorded per file as
   metadata (never a threshold), and **the corpus's codec/rate census is published in the freeze**.
   P-A's stated confidence rests on "one host, one delivery format" — that half of the sentence is
   replaced by the measured census (§9.2).
3. **The Jamendo API's terms of use are a LICENCE SURFACE, distinct from the track's CC licence.**
   They are read first-hand, their URL and `text_sha256` recorded **as a `licence` row like any other
   licence evidence** (§11.1 row 1), and the reading stated in the article. **If they cannot be read
   first-hand before the bulk fetch, the fetch does not start** — the rule §2.2 applies to a track's
   licence applies to the channel that delivers it. This is the one licence surface v1 did not touch
   at all, and it is now a row, not a note.

**If neither route delivers by the freeze deadline, the registered response is to reduce the corpus,
never to relax the rung:** arm 1 freezes on whatever subset arrived, the frozen N replaces §2.6's
projection, the epoch rule (§5.2) re-reads off the frozen N, and the shortfall is stated in the
article.

---

## §3 — THE HELD-OUT SPLIT

### 3.1 The rule (registered)

**~20 % of the frozen corpus is held out, stratified BY ARTIST.** This escalates D-20260831-03's
by-release stratification one level: on this corpus the leak is artist-shaped (one artist's tracks
share a production chain, a mastering pass, often one session), and 37 of the 96 artists contribute
exactly one track. *(Measured and worth stating: **0 albums span more than one `artist_id`** in this
pool, so artist stratification subsumes release stratification here rather than replacing it.)*

1. **No artist straddles the boundary** — an artist's tracks are all-in or all-out. *(The one place an
   intra-artist split occurs is inside arm 3's own corpus, §3.3, and it is registered there.)*
2. **Target: 20.0 % of the frozen corpus's tracks, accepted band [18 %, 23 %].** If the split on the
   **frozen** pool lands outside the band, the registered repair escalates in one fixed order:
   **(i)** continue the artist order past the stopping point, adding the next artist that fits under
   the band top; **(ii)** if none fits, remove the last-added artist and resume; **(iii)** if the band
   is still missed, the run **STOPS** and an amendment naming a new target is filed **before any
   preprocessing**. **Changing the target is never an in-run repair.**
3. **THE RULE IS S3 — whole artists, smallest catalogue first, DETERMINISTIC, NO RNG.** The intake
   lane's `intake/SPLIT-NOTE.md` computed three candidates on the FENCE v2 cut and this lane adopts
   its recommendation:

   ```
   size[a] = |tracks of artist a|                        # over the FROZEN manifest
   order   = sorted(artists, key=lambda a: (size[a], a)) # smallest catalogue first, tie by artist_id
   hold, cnt = [], 0
   for a in order:
       if cnt >= 0.20 * N: break                         # STOP AT THE TARGET
       hold.append(a); cnt += size[a]                    # whole artists only
   # tracks within an artist ordered by track_id; no RNG, no seed, no second pass
   ```

   **Why S3 and not the other two.** On the 433-track cut **all three candidates hold out the same 87
   tracks (20.1 %)**, so S3's properties are **free**: **0 straddling artists** (S1 straddles five —
   the leak D-20260831-03 exists to prevent, and for a *style* adapter it would make the evaluation
   partly a test of artists the model trained on), **59 distinct unseen artists in the holdout**
   (S2 gives 3, with 54 % of its holdout one artist), and **every large catalogue stays in training**
   (S2 loses the top three entirely, 87 of 433 tracks). S3 also leaves training the most material.
   **S1 — the rule the orchestrator first sketched — is computed and available** in
   `ace-house-data/house-wide/split-proposal.json` if it is preferred; adopting S3 is this lane's
   call under "adopt or amend", and the fault-check below is the amendment.

   **Re-measured by this lane on the pool AFTER E9** (407 tracks, 90 artists): S3 holds out
   **82 tracks / 20.15 % / 58 artists**, **0 straddlers**, **top-5 artists all in training**,
   `N_train` **325**. In band.

   **⚠ TWO FAULTS FOUND AND REGISTERED RATHER THAN LEFT IMPLICIT.**
   **(a) The holdout is composed of small-catalogue artists BY CONSTRUCTION.** Smallest-first means
   the held-out artists are systematically unrepresentative of the corpus's catalogue-size
   distribution, so **every holdout-derived statistic — the style-match centroid (§7.5.2) and
   A2-HOUSE's negative control — is computed on small-catalogue artists only**, and each is reported
   with that sentence attached. It is the right trade for a generalisation question and the wrong one
   to leave unstated.
   **(b) S3 CONFLICTS WITH ⧖ H-1 OPTION (a).** S3 puts `artist_487628` — the largest catalogue —
   **fully in training**, because smallest-first reaches it last. ⧖ H-1(a) forces those 47 tracks into
   the holdout, which would make one artist ~54 % of the holdout: **S3 would degenerate into S2, the
   candidate the split note rejects.** **The two rulings cannot both hold as written.** This lane's
   recommendation, offered to the seal: **take S3 and rule ⧖ H-1 as (b)** — arm 3's nesting inside
   arm 1 is then named honestly (§3.3) rather than bought at the cost of the holdout's diversity.
   If ⧖ H-1(a) is preferred instead, **S3 runs on the corpus MINUS `artist_487628`** and the holdout
   is *47 + S3's fill*, with the 54 % concentration stated wherever a holdout figure appears.
   **Whichever is ruled, it is ruled before the freeze — the two interact and neither may be settled
   by whichever script runs first.**

   *(Seed 42 is no longer used for arm 1's split — S3 has no RNG. It remains fixed for arm 3's
   intra-artist by-track split, §3.3.)*
   **One thing no split can fix, and the write-up says it out loud:** with 37 single-track artists and
   a median of 2 tracks per artist, **the artist axis is a weak stratifier on this corpus** — whatever
   rule is chosen, the training set is dominated by ten catalogues. That is a property of the
   open-licence house pool, not of the split.
4. **The split script is named and lives in one place:** `ace-house-data/house-wide/split_rule.py`
   (the mnml pattern: *"a split rule that exists twice is a split rule that will disagree with
   itself"*). The freeze script and any dry run import the same module; its sha256 enters the freeze.
5. **Held-out files are never preprocessed.** The preprocessor discovers its work from
   `dataset.json`'s `audio_path` entries, never by scanning the audio directory. **Asserted by
   read-back:** the tensor stem count equals the training track count exactly, with zero held-out and
   zero excluded stems.
6. **`split.json` records:** the rule verbatim (S3), the target,
   the actual, the per-artist assignment with album ids, the tier/licence census on both sides, and
   **the caption census separately for the training and held-out sides** (§4.4).
7. **The cross-split near-duplicate scan, registered.** Artist stratification does not close the leak
   of *the same work under two `artist_id`s* (a remix, a differently-credited collaboration, a
   re-upload; two mp3 encodes of one recording are not byte-identical, so E5's sha clause misses it).
   Measured on the fenced pool: **1** normalised title under >1 artist_id, **39** titles containing
   remix/rmx/edit/mix, **0** albums spanning >1 artist_id. After the split and **before any
   preprocessing**, every held-out track's A1-pinned CLAP embedding — already computed for §9.2's
   P-A — is compared to every training track's. **Any (holdout, training) pair below the 1st
   percentile of the training set's own pairwise distribution is named in `split.json`, listened to,
   and if it is the same recording the holdout copy moves to the training side or both are excluded
   under E5, with the decision recorded.** The threshold, the percentile it came from and the dataset
   hash are recorded. **Absent this scan the split is an *artist* split, not a *work* split, and the
   file says so.**

### 3.2 ONE SHARED HOLDOUT ACROSS ALL ARMS, stated directionally

**Registered:** for every arm X, no track in arm X's own holdout is in arm X's training set, is
rendered against, selects a checkpoint, or tunes a caption. Across arms the rule is: **no arm's
training set contains a track that another arm holds out for the purpose that arm's holdout serves.**

This is registered now because the alternative is the correction the coherence bench had to file after
the fact (`PREREG-COHERENCE.md` **Amendment A-C3**: two training sets registered as disjoint and
**measured to share 21 of 24 tracks**).

**Under ⧖ H-1 option (a) it resolves as follows, registered here rather than derived later:**

- arm 1's holdout = the 47 `artist_487628` tracks + the walk's fill to ~20 % of the frozen corpus;
- **arm 3 carves its own holdout from inside those 47** (§3.3), and arm 3's training side is the
  remainder;
- therefore **arm 1's holdout CONTAINS arm 3's training set.** That is admissible — arm 1 never trains
  on it, renders against it, or selects from it — with two consequences registered now: **(i)** arm
  1's style-match centroid (§7.5.2) is ~49 % composed of arm 3's training material, which is why
  §7.5.2's *"reported twice, with and without that artist"* is **mandatory, not optional**; and
  **(ii)** the sentence *"arm 1 and arm 3 trained on disjoint sets"* is written as **"arm 3's training
  set was held out of arm 1"**, never as *"the two corpora are independent"*.

*(v1 composed §3.2's blanket rule with §3.3(a) and left arm 3 with an empty training set. This is the
fix.)*

### 3.3 The arm-3 artist — recomputed on the FENCE v2 pool

⧖ **H-1 — see §15.** v1 gave three mutually inconsistent costings for option (a); v2 corrected them on
the 476-track pool; **FENCE v2 and then E9 moved the artist vector twice more, and the split rule
itself changed to S3.** Recomputed here on the pool **after fence + E9 = 407 tracks / 90 artists**,
under S3 (§3.1(3)) — and note that **S3 and option (a) conflict** (§3.1(3) fault (b)):

| option | arm 1 holdout under S3 | **arm 1 N_train** | recipe (projected) | arm 3 | what it costs |
|---|---|---:|---|---|---|
| **(b) THIS LANE'S REC after S3** — the artist stays whole in arm 1's training side | **82 tracks, 58 artists, largest ≈ 3 (3 %)** — 20.15 %, in band | **325** | 82 steps/epoch · 5 epochs · **410** steps · effective warmup **41** | arm 3 ⊂ arm 1 by ~37 tracks | reproduces the A-C3 nesting, **named in advance**: every arm-1-vs-arm-3 sentence carries *"the same ~37 tracks with and without ~288 others"* |
| (a) the artist is held out of arm 1 entirely | **47 + S3's fill; ~54 % of the holdout is one artist** | ⟦derived at freeze⟧ | ⟦derived at freeze⟧ | arm 3 carves its own holdout inside those 47 | arm 1 trains on **none** of the largest catalogue, and **S3 degenerates into S2** — the candidate the split note rejects; every holdout-derived statistic reported twice, with and without that artist; **P-A's number moves** (§9.2) |

**⚠ The recommendation FLIPPED between v2 and v3, and the reason is on the record.** v2 recommended
(a), because on the 476-track pool the two options cost the same `N_train` and (a) bought a disjoint
arm-1/arm-3 comparison for free. **Under S3 it is no longer free:** (a) hands 54 % of the holdout to
one artist and destroys the 58-unseen-artist property that is S3's whole reason for existing. **A
disjoint comparison is worth less than a holdout that can answer "does this generalise to artists it
has never heard".** v1's *"loses 47 of 476 (9.9 %)"*, *"343 / 86 / 430 / 43 / 22.9 min"* and
*"8.4 % … 41 %"* remain struck, and v2's *"both options give 380"* is superseded.

**The intra-artist split unit, registered — because "by album" is INFEASIBLE here.** Measured on the
FENCE v2 pool (all 47 tracks survive the fence): `artist_487628` has 47 tracks in exactly **two**
albums — `album_156668` (39) and `album_157794` (8).
The only by-album partitions are 17.02 % or 82.98 %, and the band is [18 %, 23 %]. **REGISTERED: where
an arm's corpus is a single artist, the holdout is drawn BY TRACK** —
`numpy.random.default_rng(42).permutation` over track ids sorted ascending, taking tracks until the
count first reaches ⌈0.20 · N⌉. For N = 47 this is **10 held out / 37 trained (21.3 %, in band)**.
Every track's album id is recorded in `split.json`. **The production-chain leak this admits is named
rather than denied**: within one artist's two albums a by-track holdout does not separate production
chains, so arm 3's holdout is a weaker instrument than arm 1's, and it is used for nothing but
A2-HOUSE's negative control (§3.4).

### 3.4 What the holdout is for, and what it is not

The holdout feeds exactly three things:

1. the **style-match** side-reading (§7.5.2);
2. the **memorisation screen's NEGATIVE CONTROL** (§12, A2-HOUSE). ⚠ v1 said the holdout feeds *"the
   memorisation screen's corpus side"*, which is meaningless — the model never saw the holdout. **The
   screen's positive target is the TRAINING set** (the distribution the threshold comes from); the
   holdout supplies the matched *"music the adapter never saw"* distribution a similarity is read
   against;
3. the **cross-split near-duplicate scan** (§3.1(7)).

**It is never rendered against, never used to select a checkpoint, never used to tune a caption, and
never used to select another arm's corpus** (§13.1). The trainer reports no holdout loss on this
recipe; if a future version does, §6 switches to it by amendment.

---

## §4 — THE CAPTION RULE

### 4.1 Why this section exists

`MATERIALS.md` §3.7: the mnml corpus trained on **placeholder captions** — `"minimal techno, " +
<title cleaned>` — where *"nobody listened to these tracks and wrote a description"*, 15 % of captions
began with a surviving track number, and `bpm`, `genre`, `keyscale`, `timesignature` were empty on all
159. D-20260827-P43 (the approved-caption regime) *"was never applied"*. **This train applies a
documented caption regime.** It is not P43's letter — *"Fable drafts, the operator approves each line"* does
not scale to ~325 tracks — it is P43's principle: **the caption is derived from evidence about the
track, by a fixed rule written down before the first caption is rendered.** ⧖ **H-2 — see §15.**

### 4.2 The template (registered)

> **`<head>, <other genre tags>, <instrument tags>, <mood tags>`**

Rendered from the track's own tags in `raw_30s.tsv` (§2.5), by these rules and no others:

1. **`<head>`** = `deep house` if the track carries `genre---deephouse`, else `house`.
2. **`<other genre tags>`** = every `genre---*` tag except `house` and `deephouse`, de-camelised
   (§4.3), sorted **alphabetically by the raw tag string**, **capped at 3**.
3. **`<instrument tags>`** = every `instrument---*` tag, de-camelised, alphabetical, **capped at 3**.
4. **`<mood tags>`** = every `mood/theme---*` tag, de-camelised, alphabetical, **capped at 2**.
5. Terms joined with `", "`. Empty families contribute nothing (no empty commas).
6. **No title. No artist. No album. No bpm. No key.** Titles are not descriptions — the mnml corpus's
   leading track numbers are the receipt — and neither bpm nor key exists in the Jamendo metadata. A
   librosa pass could supply bpm; **it is not run for arm 1** and is owed amendment A3-HOUSE, because
   adding it after some captions exist would make the corpus caption-inhomogeneous.
7. **Deterministic:** alphabetical sort on the raw tag string, fixed caps, fixed family order. Two
   runs over the same manifest produce byte-identical captions, asserted by comparing the rendered
   captions file's sha256 across a re-run.
8. **The trigger word is NOT in the caption text.** It is applied by the preprocessor from
   `metadata.custom_tag` with `tag_position = prepend` (§4.6).

### 4.3 De-camelisation

MTG tags are lowercase compounds (`drummachine`, `electricguitar`, `easylistening`, `triphop`,
`acousticguitar`, `deephouse`). The renderer expands them through **one explicit lookup table**,
written to `ace-house-data/house-wide/tag_words.json` and **sha-pinned into the freeze**. The table
covers every distinct tag present in the fenced pool; **a tag absent from the table is a HARD ERROR,
never a silent pass-through**, so the vocabulary cannot drift between manifest and captions. The table
is built from the tag strings alone; **no tag is invented, renamed or merged — only spaced.**

### 4.4 What the template produces — measured before it is used

Rendered by this lane over the **433** FENCE v2 tracks (§2.6), 2026-09-06T00:1xZ:

| quantity | measured |
|---|---:|
| distinct captions | **175** of 433 |
| captions used exactly once | 126 |
| modal caption | `house, club, dance, disco, happy, summer` — **39 tracks** (runner-up `house, electronic`, 31) |
| mean terms per caption | **4.13** |
| **tracks with ≥ 1 instrument tag** | **135 (31.2 %)** |
| **tracks with ≥ 1 mood tag** | **155 (35.8 %)** |
| **GENRE-ONLY captions (no instrument, no mood)** | **198 (45.7 %)** |
| distinct tags available in the fenced pool | genre **50** · instrument **34** · mood **53** |

*(v2 measured 195 / 139 / 4.24 / 161 / 172 / 211 on the pre-FENCE-v2 pool of 476. FENCE v2 removed 43
more tracks, and the genre-only share **rose** from 44.3 % to 45.7 % — the hybrid tags it fenced out
were themselves caption terms, so the surviving captions are marginally thinner, not richer. That is
the honest direction and it is recorded rather than smoothed.)*

**⚠ THE CAPTION-COVERAGE CONFOUND, registered as a first-class fact about this train.** A tag-derived
regime is only as rich as the tags, and **on this pool the tags are sparse**: two thirds of the corpus
carries no instrument word, nearly two thirds no mood word, and **45.7 % of captions are genre terms
and nothing else**. The regime is a real improvement on `mnml0`'s `"minimal techno, {title}"` — every
term is a published claim about the track rather than a filename — but it is **not** a per-track
description, and **the corpus is caption-inhomogeneous by construction.**

**THE TEMPLATE DEGRADES HONESTLY. NO TAG IS EVER INVENTED.** A track with no instrument tag gets no
instrument word; a track with no mood tag gets no mood word; a track with only its head tag gets a
one-term caption. **The renderer may not substitute a genre-typical instrument, may not infer a mood
from a genre, may not copy a sibling track's tags, and may not fall back to the title.**

**⚠ THESE ARE POOL FIGURES, and the H-1 ruling changes them.** `split.json` records the same census
separately for the training and held-out sides, and **the article quotes the TRAINING-SET figures,
since those are what the adapter saw.** Measured: the modal caption (39 tracks, 8.2 % of the pool) is
**one album by one artist — `album_156668` of `artist_487628`, the arm-3 artist** — so the
caption-repetition confound and the arm-3 corpus are the same tracks. Under option (a) that whole
cluster leaves arm 1's training side and the modal caption becomes `house, electronic` at 31.

**The honest phrase, registered so it cannot be improved later:** *"captions derived from each track's
own published tags by a fixed template, which for 46 % of the corpus means genre words alone"*.

*(Measurement note, since smaller figures were relayed to this lane: **135 of 433** tracks carry at
least one instrument tag. "~110" is the count of `instrument---synthesizer` alone; "~31" is the number
of distinct mood tags in the pre-fence pool under the unregistered cleantags file. Both are real
numbers about different things. The relayed point stands and is stronger than stated: **most captions
are genre-only.**)*

### 4.5 The approval surface

The intake lane's `INTAKE-JAMENDO-HOUSE.md` renders 20 examples; **it was built against the voided
cleantags build (§2.5) and its caption figures therefore disagree with §4.4 by construction.** The
template of record is §4.2, this lane's, and the intake lane renders **against it** after the rebuild
or files a delta. Twelve specimens rendered by this lane from the pool, for shape (shown with raw tag
strings so the de-camelisation still owed is visible):

```
house, dance, electronic, techno
house, electronic
house, easylistening, electronic, lounge
house, electronic, jazz, minimal, melodic
house, electronic, minimal, triphop, melodic
house, electronic, minimal, bass, computer, drummachine, game
deep house, triphop, acousticguitar
house, club, dance, disco, happy, summer
house, world
house, ambient, electronic
deep house, techno, bass, deep
house, club, techhouse, tribal, happy, summer
```

### 4.6 The trigger word, `genre_ratio`, and the two preprocessor defects

- **Trigger word = the run slug**: `house-wide` (arm 1), `house-core`, `house-artist`. Applied by the
  preprocessor from `dataset.json.metadata.custom_tag`, `tag_position = "prepend"`. It appears in no
  caption string in `dataset.json`.
- **⚠ THE TRIGGER IS NOT A NEUTRAL SLUG ON THIS CORPUS.** `house-wide` tokenises to include the genre
  word **house**, so prepending it at render time adds a genre term to every prompt — **new
  information on P01–P06** (the six techno prompts, which contain no house word) and redundant on
  P07–P10. This is a **first-order confound of the 2AFC itself**, not merely of the training, and it
  is materially worse than mnml's case (`mnml-shakedown` contains no genre word). It is kept — rather
  than renamed to an opaque token — only because the recipe must stay comparable to `mnml0`. **The
  cost of keeping it is block T (§7.3), which is registered, and the caveat that travels with every
  published tally (§10.1).**
- **`genre_ratio = 0`**, `genre` / `keyscale` / `timesignature` empty, `bpm` null, as on mnml.
  ⚠ **`genre_ratio` IS AN AUTO-CAPTION REPLACER** (`preprocess.py:215-223`): at `genre_ratio > 0` that
  fraction of samples **discards the caption and trains on the bare `genre` string**, and the run
  looks perfectly normal in the log. **`genre_ratio: 0` is mandatory and is asserted by reading
  `dataset.json` back, never assumed.**
- **There is NO auto-captioner on this path — there is nothing to disable.** The caption is read
  verbatim from the manifest and the trigger prepended. What exists instead are **two silent caption
  defects the freeze script must gate:**
  - the recorded and the **encoded** caption have **different fallbacks** — `preprocess.py:261`
    records `caption = sm.get("caption", af.stem)` (the **filename stem**) while
    `preprocess_prompt.py:41` encodes `meta.get("caption", "")` (the **empty string**). **A sample
    with no caption records one thing and trains on another.**
  - **The freeze script asserts a non-empty caption on every entry before preprocessing starts**, and
    asserts that the sha256 of the captions column extracted from `dataset.json` equals the sha256 of
    the renderer's output for the training rows. A mismatch aborts before training.
- `lyrics = "[Instrumental]"`, `is_instrumental = true` on every sample.

---

## §5 — THE RECIPE

### 5.1 The launch line

The `mnml0` launch line (`MATERIALS.md` §1.7) **verbatim, with exactly the four changes marked**:

```bash
CUDA_VISIBLE_DEVICES=(GPU UUID withheld) setsid nohup \
  ACE-Step-1.5/.venv/bin/python ACE-Step-1.5/train.py --plain --yes fixed \
    --model-variant turbo --base-model turbo --device cuda:0 --precision bf16 --num-devices 1 \
    --adapter-type lora --rank 64 --alpha 128 --dropout 0.1 \
    --target-modules q_proj k_proj v_proj o_proj --attention-type both \
    --batch-size 1 --gradient-accumulation 4 --lr 1e-4 --scheduler-type cosine \
    --warmup-steps 100 --gradient-checkpointing --optimizer-type adamw \
    --shift 3.0 --num-inference-steps 8 --cfg-ratio 0.15 --epochs ⟦EPOCHS⟧ --save-every 1 --seed 42
```

| # | change | from | to | why |
|---|---|---|---|---|
| C1 | `--epochs` | 10 | **5** for arm 1 (§5.2) | lesson 2: epochs scale down as the corpus scales up |
| C2 | `--save-every` | 5 | **1** | lesson 1 + the mnml `save_every` miss: epoch 9 was the run's best (0.6334) and **was never written to disk**; the shipped adapter was 2.84 % worse than the run's best, and the best no longer exists |
| C3 | `CUDA_VISIBLE_DEVICES` | the 96 GB workstation-class card's UUID | **`(GPU UUID withheld)`, the training box CARD B at 250 W, pinned in §5.4 — not a placeholder** | the box moved, and **D-20260905-94** pins sustained work to the 250 W card |
| C4 | the run slug / paths | `mnml-shakedown` | `house-wide` | the corpus moved |

**Everything else is byte-identical**: turbo base · bf16 · rank 64 / alpha 128 / dropout 0.1 · targets
`q_proj k_proj v_proj o_proj` · bias none · lr 1e-4 cosine · batch 1 / grad-accum 4 · warmup requested
100 · weight decay 0.01 · max grad norm 1 · **seed 42** · cfg-ratio 0.15 · shift 3.0 · 8 inference
steps · grad-checkpointing on · AdamW.

**Max sample duration 240 s** (`duration_policy = flat_cap`, `max_duration_s = 240.0`) —
**D-20260905-86**.

### 5.2 The epoch rule, stated as a rule so arms 2–3 cannot move it

**`steps_per_epoch = ceil(N_train / 4)`** (batch 1 × grad-accum 4) — verified against mnml:
`ceil(159/4) = 40`, and its log records 40.

| N_train | epochs | precedent |
|---|---:|---|
| N < 100 | 10 | Chopin 19, Bach 63, Sousa 84, fm-control 24 all ran 10 |
| 100 ≤ N < 300 | **10 for a size-matched replication of `mnml0`** (arm 2), else 8 | mnml ran 10 at N = 159, flat from epoch 6 |
| **N ≥ 300** | **5** | the brief's rule for a ~600-track corpus |

with a **floor: `epochs × steps_per_epoch ≥ 300`**; if the table's value misses the floor, epochs rises
to the smallest value that meets it. **The floor is SUSPENDED for arm 3** (§13.2). The chosen value and
the rule row are recorded in the run manifest.

**Arm 1's arithmetic. The binding values are `⟦to be filled at freeze⟧`; the projections beside them
are the §3.1(3) dry run on the FENCE v2 pool of 433 at seed 42.** E4–E8 have not fired (they need the
audio), so the frozen `N_train` can only fall from these.

| quantity | **binding** | projected (S3, ⧖ H-1 (b)) |
|---|---|---:|
| corpus after FENCE v2 | ⟦filled at freeze⟧ | 433 |
| after E9 `relicensed-since-2019` | ⟦filled at freeze⟧ | **407** |
| N_holdout (S3) | **⟦filled at freeze⟧** | 82 (20.15 %), 58 artists |
| **N_train** | **⟦filled at freeze⟧** | **325** |
| steps/epoch = ceil(N_train / 4) | ⟦derived at freeze⟧ | **82** |
| epochs (§5.2's rule, N ≥ 300) | **5** | 5 |
| total optimiser steps | ⟦derived at freeze⟧ | **410** |
| effective warmup = total // 10 | ⟦derived at freeze⟧ | **41** |

*(Under ⧖ H-1 (a) every row below the corpus line is re-derived at the freeze; §3.3 explains why this
lane no longer recommends it. **E9 can still grow** if any of the 105 unreadable tracks resolves off
the rung before the freeze, which is a second reason `N_train` is a `⟦filled at freeze⟧` and not a
number.)*

**The freeze fills every `⟦to be filled at freeze⟧` from the frozen manifest, and the seal records
them.** No step runs on a projected number.

### 5.3 THE WARMUP TRAP — record the EFFECTIVE number, never the requested one

`acestep/training_v2/optim.py:143-151`, at the pinned checkout:

```python
# Clamp warmup to avoid exceeding total
warmup_steps = min(warmup_steps, max(1, total_steps // 10))
```

**Every run in the previous arc got exactly 10 % of its own step budget, and all three of the launch
line, the config echo and the substrate recorded the requested 100.** Arm 1 requests 100 and receives
`total_steps // 10` — projected **47** at 475 steps.

**Registered:** the run manifest and `train_run` carry **both** `warmup_steps` (the requested 100) and
**`warmup_steps_effective`** — a column that **does not exist today** and is owed as A4-HOUSE gap 4
(§11.3). **Every published warmup figure is the effective one**, confirmed from the TensorBoard
`train/lr` series (the step at which `lr` peaks at 1e-4), not from the config echo.

### 5.4 The box, the card — PINNED — and the pinned stack

**Box: the training box.** Measured by this lane 2026-09-05T23:1xZ: `/` 295 G total, 126 G used, **157 G
available**; RAM 30 G total, **10 G available with the seats up**; 2 × RTX 3090 24 GB, driver
**595.84**.

**THE CARD IS PINNED HERE, FOR ALL FOUR ARMS — CARD B, AT 250 W (D-20260905-94):**
`CUDA_VISIBLE_DEVICES=(GPU UUID withheld)` (nvidia index **0**, roster label
`3090-b` / "card B"), then `--device cuda:0` — a UUID pin makes that card the only visible device, so
it is index 0 inside the process either way.

| index | uuid | label | **power cap** | driver | role |
|---|---|---|---:|---|---|
| **0** | **`(GPU UUID withheld)`** | **`3090-b` "card B"** | **250.00 W** | 595.84 | **THE TRAIN CARD, all four arms** |
| 1 | `GPU-46890836-d8f7-e868-1977-c1ce28db0d7a` | `3090-a` "card A" | 280.00 W | 595.84 | inference seats (the P77 80 % posture) |

**THE 250 W CAP IS A REGISTERED INSTRUMENT PROPERTY, NOT AN ACCIDENT.** the operator, D-20260905-94:
*"whatever card we use, should be at 250w … let's be sure to power limit to 250w for sustained
workloads, as a practice (on the 3090s), and make note of that"* — **sustained** work (training,
multi-hour benches, batch renders) runs at **250 W**; **inference seats** may sit at 280 W. So:

- **`power_limit_w = 250.00`** and `driver_version = '595.84'` ride the run manifest and `train_run`,
  and **every published s/step for this programme carries "250 W" in its config vector** (§5.5).
- **Throttle reason `0x4` (SW power cap) during the train is EXPECTED, not a fault.** Bach measured
  exactly that on this card (248.93 W against the 250 W cap). A run that never touches its cap on a
  sustained load is the surprising outcome, and either reading is recorded rather than explained away.
- **This supersedes v2's card-A pin**, which was chosen for the *higher* cap on the reasoning that a
  power-limited card is a compromised instrument. D-20260905-94 reverses the premise: **the cap is the
  house instrument**, and matching it across arms matters more than maximising it. The flip is
  recorded here rather than quietly applied.
- **The estate's timing anchor already comes from this card** — the 1.512 s/sample figure of §5.6 is a
  the training box measurement at the 240 s cap, and Bach's own run was card B at 250 W, so §5.6's projection
  needs no re-basing for the flip.
- **A card change is a registered deviation** with its own dated note, and **no s/step from one card is
  published beside an s/step from the other without both power limits named.**

**⚠ Card B's co-tenant is stopped for the window.** Measured 2026-09-06T00:2xZ, card B carried three
compute processes — 17,444 MiB (an ollama seat), 3,634 MiB (**the print lab's ComfyUI on `:PORT-A`**)
and 354 MiB. **The print-lab session stops `:PORT-A` for the train window before any GPU work starts**
(D-20260905-94), so **card B has no co-tenant during the train** — unlike v2's card-A pin, which
would have trained beside a live renderer. A lane never stops it; the print-lab session does, and the
receipt is card B's process list showing only the trainer.

- **The seats are stopped by the operator's own paste** (sudo is password-only). Until they are, **no GPU
  work starts.** A lane never stops, restarts or evicts a seat, and never touches
  `printlab-worker.service` or the ComfyUI processes on `:PORT-A`/`:PORT-B`.
  ⚠ **Stopping the seats buys back ~1.2 GB of RAM, not 18** — the ollama runners hold most of their
  weight in VRAM, and the print lab's ComfyUI is the box's large RAM tenant. **The RAM budget is
  measured after the stop, not assumed**, and §9.2's P-A bench does **not** run before the stop.
- **VRAM:** peak train ≈ **5.7 GiB** (trainer allocator) / **6.7 GiB** (card delta) at bs1 +
  grad-checkpointing — measured on the 96 GB workstation-class card under an unchanged recipe. With the seats stopped **and
  `:PORT-A` stopped**, card B is empty: ~23.5 GiB free against a 6.7 GiB peak is a **~3.5× margin**,
  and it is a margin on an *empty* card rather than a shared one. **Both readings are published with the instrument that produced each**
  (the honest range is 5.7–6.7 GiB), and only one is `is_authoritative` (§11.2).
- **Disk:** arm 1's budget is **~13 GB** (audio ~7.5 GB + tensors ~3.4 GB + ~2.2 GB adapters and five
  epoch checkpoints). ⚠ That takes the training box to ~144–145 G free, **below the lab plan's own registered
  ≥ 150 G floor** (`PLAN-ACE-LORA-THE TRAINING BOX-2026-08-27.md:439-441`). **Registered: `/bin/df -h /` on
  the training box is a receipt before the pull, before preprocessing and after the train**, and if free space
  would fall below 120 G the run stops and the orchestrator is told rather than a lane deleting
  anything.
- **RAM:** the preprocess ceiling on a ~325-track corpus is **unmeasured on this box**. The preprocess
  runs under `systemd-run --user --unit house-wide-preprocess` (never a terminal scope — the oomd law)
  with a RAM sampler beside it, and the measured peak is a first-class number in the run manifest.
- **Pinned venv:** `music/ACE-Step-1.5/.venv`, against
  `music/docs/trainer-venv-freeze-2026-08-29.txt` (present, verified). **A diff between the
  live venv and that freeze is a FINDING, recorded before the train, not after.**
- **The pinned stack, carried here rather than by pointer** (each is a NOT NULL column in
  `train_run`): Python **3.12.14** · torch **2.10.0+cu128** · CUDA **12.8** · PEFT **0.18.1** ·
  precision **bf16** · attention backend **`sdpa`** as logged (the flag passed is `both`) · optimiser
  **AdamW** (bitsandbytes absent; `--optimizer-type adamw` is what was asked, so the "not installed"
  line is a no-op) · driver **595.84** · **power limit 250.00 W** (D-20260905-94) · box **the training box** ·
  card **B** · attended **true**.
- **⚠ TRAINER PROVENANCE — v1 had this INVERTED, and so does `MATERIALS.md:490`.** Measured on
  the training box: `music/ACE-Step-1.5` has `origin = https://github.com/ACE-Step/ACE-Step-1.5.git`; there
  is **no `.gitmodules`** and **no `acestep/training_v2/.git`**; and
  `14c0211d5a0653b0f63e27686f4c3f151b4d8629` is **that repository's HEAD on `origin/main`** — PR
  #1287, *"Promote the complete/lego skip-LM workaround to a default (interim)"*, author
  `gurubusvoyage`, author date **2026-08-16T04:32:26Z**. So:
  **`trainer_commit_sha = 14c0211d…` pins the ACE-Step-1.5 CHECKOUT IN WHICH Side-Step v2.0.0 IS
  VENDORED** (at `acestep/training_v2/`, a plain directory) — the only reproducible pin the estate
  has. **Side-Step's own upstream commit (`github.com/koda-dernet/Side-Step`) is NOT recorded anywhere
  on this estate**, and `14c0211d` does not exist in that repository. Recovering it is owed amendment
  **A7-HOUSE**. **A correction is owed to `MATERIALS.md:490` and `recon/sleeve-rows.md §3.1 HAZARD 4`,
  which state the inverse.**
- **Trainer licence:** Side-Step is **CC BY-NC-SA 4.0** inside MIT ACE-Step. The estate's reading
  (D-20260827-P47) is that **the CODE is encumbered and adapters/outputs are not**; the clarification
  email was sent 2026-08-31 and **P47 is still open**. This is **research use**. The reading governs
  until answered, and **the article says so rather than being caught omitting it.**
- **Base model:** `acestep-v15-turbo`, present at `music/checkpoints/`. It is named **only
  as a string; no hash and no commit exists anywhere on the estate** — the run manifest records the
  checkpoint directory's own file shas, so this is the first arc that can prove which weights it
  trained against.

### 5.5 What every reported number must carry

Inherited verbatim from `PREREG-ACE-LORA-FIRST-TRAIN-2026-08-27.md` §10. Any `s/step` or peak-VRAM
figure carries its **full config vector** — card + driver + **power limit** · torch/CUDA build ·
trainer commit · **FA2 vs SDPA as actually logged** · gradient-checkpointing · batch size · grad-accum
· **measured sample duration** · rank · alpha · **the optimiser actually used** · the epochs the
seconds were averaged over · **the prereg sha** — or it is not a measurement.

**And the counting rule is named beside the number** (`MATERIALS.md` §1.5): an s/step from the epoch
lines, from the wall banner and from the wrapper are three different numbers. **Exactly one is
authoritative per (subject, metric)**, and the substrate enforces it (§11.2).

### 5.6 What the train should cost — and the 240 s cap as a corpus property

**Per-sample step cost scales near-linearly with seconds of audio.** The measured the training box anchor at
the cap is **1.512 s/sample** (Chopin r64 on the training box at 240.0 s mean):

```
epoch_seconds ≈ N_train × 1.512 s          s/step = 4 × s/sample
```

| reading | arithmetic (at the projected `N_train` = 325) | result |
|---|---|---|
| at the full cap (1.512 s/sample) | 325 × 1.512 = 491.4 s/epoch; × 5 | **~41.0 min**, 6.05 s/step |
| scaled to this pool's mean capped duration (~227 s) | 1.512 × 227/240 = 1.430 s/sample → 464.8 s/epoch; × 5 | **~38.7 min**, 5.72 s/step |

**REGISTERED: the projected train is 38–41 minutes at the projected N**, recomputed at the freeze from
the actual `N_train`, and **both arithmetics are published with their counting rules**. ⚠ v1 projected ~25 min from a **3.19 s/step** figure derived from **Bach**, whose
samples are short; that figure does not apply to a corpus that mostly hits the cap, and it is struck.

**The 240 s cap as a corpus property (D-20260905-86).** Arm 1 keeps the mnml recipe's cap for
comparability and for the measured VRAM ceiling on a 24 GB card. **The consequence is stated as a
property of the corpus, not hidden in a config line: a majority of the corpus is truncated at 240 s**
— measured on the FENCE v2 pool, median duration **290.7 s**, so more than half of every long track's
runtime past four minutes is never seen by the trainer. The intake doc's figure for the voided
486-track build was 334 of 486; **the freeze publishes the count for the frozen 433-track corpus.** Full-length
conditioning is a later route's question, not this arm's.

---

## §6 — THE SHIPPED-CHECKPOINT RULE

**The shipped adapter is the checkpoint with the best epoch-mean TRAINING loss — never the last.**
With `--save-every 1` every epoch is on disk, so the best epoch is always selectable.

- If the trainer reports a **holdout** loss, that becomes the selection basis and the switch is
  recorded. It does not on this recipe.
- The selection is made **by the recorded number, not by ear**, and **before** any blind trial is
  rendered. *(The first prereg's §9 alternative — pick by ear from previews — is not used: previews are
  not rendered for these arms, and picking the winner after seeing blind results would be p-hacking
  with extra steps.)*
- **`checkpoint.selection_basis` states which basis was used**; with `--save-every 1` the qualifier
  *"among saved"* becomes vacuous, which is the point of C2.
- **Losses across corpora are not comparable** — different data has different intrinsic difficulty.
  Only the loss **shape** is a fair comparison, and that caveat travels with every cross-arm loss
  figure (`MATERIALS.md` §1.3).
- **"Best of k" is optimistic in k**: arm 1 selects over **5** candidates, arm 3 over 10. Any
  cross-arm loss statement names its k.
- Every epoch checkpoint is kept. The shipped adapter is **immediately** rsynced to
  `music/adapters/_backup/house-wide/` — an adapter that has produced anything is precious
  (D-20260831-07), and mnml's was the first ever backed up.

---

## §7 — THE INSTRUMENT

### 7.1 The listener, the trial, and what is inherited

Inherited from `PREREG-ACE-LORA-FIRST-TRAIN-2026-08-27.md` §1–§5: blind pairwise forced choice,
**the operator's ear**, order randomised per trial, condition hidden, **no "no preference" option**,
loudness-matched clips, presented on the gated review shelf and nowhere else (and only on a fresh P45
go, §2.2).

**The listener is not the unit of replication — the trial is.** Only **distinct** trials count.

**⚠ THE HARNESS DOES NOT EXIST YET.** §1 of the first prereg describes a fork of `build_console3.py`
with a `loudnorm` pass, per-trial order randomisation and sentinel injection.
`STAGE0-READINESS-2026-08-29.md:423-428` records: *"Neither exists yet."* What exists is Round 4's
blind **sheet** (12 shuffled pairs with a sealed key), which has no sentinels and no forced-choice
tally. **Building the harness is owed work, not existing work**, and it is on arm 1's critical path.

### 7.2 The stimulus set — the Round-4 prompts, verbatim

The **twelve Round-4 prompts** (`PREREG-ROUND4.md` §3, ledger row 26) are reused **verbatim**:

| id | style | bpm pin | caption text (verbatim, base arm) |
|---|---|---:|---|
| P01 | minimal techno | 128 | minimal techno, hypnotic rolling groove, analog drum machine, deep sub bass, sparse percussion, late night |
| P02 | dub techno | 122 | dub techno, deep chord stabs drenched in delay, soft muffled kick, tape hiss, slow underwater swing |
| P03 | Detroit techno | 132 | detroit techno, soaring string pads, crisp 909 drums, warm bassline, futuristic and soulful |
| P04 | melodic techno | 124 | melodic techno, driving arpeggiated synth, big reverb, emotive chord progression, steady four on the floor |
| P05 | hard techno | 145 | hard techno, distorted rumbling kick, industrial percussion, relentless, dark warehouse |
| P06 | acid techno | 130 | acid techno, squelching 303 bassline, resonant filter sweeps, tight drum machine, raw and hypnotic |
| P07 | deep house | 122 | deep house, warm rhodes chords, shuffled hi-hats, smooth sub bass, soulful and laid back |
| P08 | tech house | 126 | tech house, chunky rolling bassline, tight clap, minimal percussion fills, groovy and punchy |
| P09 | disco house | 124 | disco house, filtered disco loop, live strings and brass stabs, funky bass guitar, joyful |
| P10 | progressive house | 128 | progressive house, long atmospheric build, plucked synth melody, sidechained pads, euphoric drop |
| P11 | electro breaks | 130 | electro breakbeat, syncopated broken drums, robotic bass synth, vocoder stabs, retro futuristic |
| P12 | uplifting trance | 138 | uplifting trance, supersaw lead melody, huge breakdown, pumping kick, euphoric festival energy |

**The adapter arm's prompt, registered** (v1 left this to the render lane): `house-wide, ` + the
caption text above, byte-for-byte, exactly as Round 4 prepended `<trigger>, ` (`PREREG-ROUND4.md` §4).
The base arm receives the caption text as-is. **Every base/adapter difference measured in this
programme is therefore "adapter weights **+ trigger token**", never "adapter alone"** —
`PREREG-COHERENCE.md` §6.2's wording — and **block T (§7.3) is what separates the two.**

**⚠ P06 is "acid techno" and stays.** D-20260905-84 fences the **corpus**, not the prompt set. P06 now
sits on the far side of a deliberate corpus boundary, which makes it *more* informative. The article
says so rather than quietly dropping a prompt after a ruling.

**⚠ H4-HOUSE cannot be read as v1 registered it.** v1 predicted the largest house-adapter effect on
P07–P10. **The trigger confound predicts the opposite** — the largest lexical gain on P01–P06, where
"house" is new information, and the smallest on P07–P10, where the prompt already says house. The two
mechanisms push in opposite directions. **H4-HOUSE is registered as UNINTERPRETABLE without block T**,
and is reported as two group medians with no test and with both mechanisms named.

### 7.3 The blocks and the threshold

**Seeds:** `4000 + i` (Round 4's own seed for prompt `i`) and `5000 + i` (new). Fixed here.
Replacement draw on a void: `6000 + i`, also fixed here (§7.4).

| block | contrast | pairs | reported as |
|---|---|---:|---|
| **A — PRIMARY, THE GATE** | base (dose 0) vs `house-wide` @ **1.0** | 12 prompts × 2 seeds = **24** | **clears at ≥ 18** — see the clustering correction |
| B — descriptive | base vs `house-wide` @ **0.5** | **24** | **proportion + 95 % Wilson CI. No threshold, no α, no p-value, no "clears".** |
| pooled — descriptive | A ∪ B | 48 | **proportion + 95 % Wilson CI only**, carrying the sentence *"these 48 include block A's own 24 trials and share its base renders; the pooled figure is not independent confirmation of block A."* |
| **T — TRIGGER-ONLY CONTROL / the harness's first null** | base vs **base + the string `house-wide, ` prepended**, no adapter loaded | **12** (seed 4000+i) | see below |

**⚠ THE CLUSTERING CORRECTION — v1's α was optimistic and this is the fix.** Block A's 24 trials are
**12 prompts × 2 seeds = 12 clusters of 2**. The first prereg's rule licenses *counting* a second seed
(it is a distinct stimulus, not a replay), **but "distinct" is not "independent", and the binomial null
assumes independence.** Measured by beta-binomial simulation (300,000 draws, mean 0.5, intra-prompt
correlation ρ), at k ≥ 17:

| ρ | true P(k ≥ 17 \| H₀) | v1's registered α |
|---:|---:|---:|
| 0.0 | 0.0320 | 0.0320 |
| 0.1 | 0.0390 | 0.0320 |
| 0.3 | **0.0536** | 0.0320 |
| 0.5 | **0.0669** | 0.0320 |
| 0.7 | **0.0795** | 0.0320 |

At ρ ≥ 0.3 — an ordinary prompt effect — **the gate would run above the estate's own α ≤ 0.05 rule
while its registration said 0.0320.** Power is essentially unaffected (0.565 → 0.559 at ρ = 0.5), so
clustering costs α and buys nothing.

**REGISTERED: block A clears at ≥ 18 of 24**, robust to ρ ≤ 0.5 (measured 0.0113 independent · 0.0237
at ρ = 0.3 · 0.0322 at ρ = 0.5), and **the power is stated honestly at 0.389 at a true p = 0.70**, not
0.565. **k ≥ 17 with a 0.0320 label is not available.**

**⧖ H-3 IS RULED: the clustered gate stands as registered — 24 trials, `k ≥ 18`, power stated
honestly. No new prompts.** The alternative (twelve fresh house-family prompts giving 24 independent
trials at `k ≥ 17`, α 0.0320, power 0.565 — the same correction the first prereg made to its own first
draft) was offered and **declined by the orchestrator**; **A8-HOUSE is therefore CLOSED, not-taken**,
and this paragraph is the record that the cheaper-power option was chosen knowingly rather than
missed. **Every published block-A sentence carries `k ≥ 18` and power 0.389, never 0.565.**

**BLOCK T, registered as an arm** (the trigger confound of §4.6 and the missing null, answered by one
block): twelve renders of the twelve prompts at seed 4000+i, **base model, no adapter**, with
`house-wide, ` prepended exactly as the adapter arm prepends it — same session, same pins, one clip per
process. It feeds two readings: **(i)** the Audiobox PQ and the CLAP-to-house-centroid distance of a
trigger-only render against the plain base render at the same seed, so *"the token moved it"* and *"the
weights moved it"* are separable; and **(ii) if scored by the ear, `base` vs `base + trigger` is the
cleanest null block this harness will ever have** — twelve pairs in which no adapter exists, so a
systematic preference is an instrument artefact by construction.

Reproduce every cell with the first prereg's own code:

```python
from math import comb
def tail(n, k, p=0.5):
    return sum(comb(n, i) * p**i * (1-p)**(n-i) for i in range(k, n+1))
def crit(n, alpha=0.05):
    return next(k for k in range(n//2, n+1) if tail(n, k) <= alpha)
```

### 7.4 Clips, sentinels, presentation, failures, and the stop conditions

- **Clips: the whole 30 s render**, at Round 4's pins reused verbatim: `acestep-v15-turbo` ·
  **8 inference steps** · **shift 1.0** · `guidance_scale 1.0` · `lyrics [Instrumental]` ·
  `keyscale A minor` · `timesignature 4` · 48 kHz · **one clip per process** (Round 3's law:
  `unload_lora` does not restore the base decoder bit-exactly) **plus a determinism repeat**
  (D-20260903-04).
  **⚠ REGISTERED DEVIATION FROM THE FIRST PREREG.** Its §1 pins 25 s clips at shift 3.0; Round 4
  rendered **30 s at shift 1.0** (measured in `music/out/mnml-round4/round-4/records.json`:
  `"shift": 1.0, "guidance_scale": 1.0, "duration": 30.0`). **Cross-article comparability wins**; the
  deviation is registered in advance with its reason.
  **⚠ "Byte-comparable across articles" is MEASURED, not assumed.** Round 4 rendered on **the archive box**
  (a 96 GB workstation-class card); the house arms render on **the training box** (RTX 3090, sm_86), and fixed-seed diffusion is
  not guaranteed bit-identical across architectures. **Before block A opens, P01 is re-rendered at seed
  4001 on the training box under Round 4's pins and its sha256 compared to the archive box's base render.** The result —
  match or mismatch — is recorded in the run manifest, and **if it is a mismatch the phrase
  "byte-comparable across articles" is struck from every downstream document.**
- **Loudness: every presented clip is normalised to −16 LUFS integrated, true peak ≤ −1 dBTP** (ffmpeg
  `loudnorm`), measured on the delivered bytes. Not optional. The renders are already peak-normalised
  at render time (`enable_normalization: true, normalization_db: -1.0`); the LUFS pass applies to the
  **presented** clip and its measured LUFS/TP ride the records.
- **Sentinels: exactly 12, ALL TWELVE PRESENTED IN SITTING 1 alongside block A**, so the gate's only
  scoring block is self-contained. **Sitting 1 = 24 scoring trials + 12 sentinels = 36 presentations.**
  Accept **2–10 of 12**; P(accept | honest) = **0.9937**, P(void | honest) = **0.0063**. Sitting 2 =
  block B's 24 with **no sentinel block**, a further reason block B carries no threshold. *(v1's 6 + 6
  split left the band undefined whenever the operator completed block A only — the realistic case. If
  the orchestrator prefers 6 + 6, the registered band for a 6-sentinel block is **1–5 of 6**,
  P(void | honest) = 0.0312; the 2–4 band is never used, because at P(void) = 0.219 it fails an honest
  block one time in five and pays for the retry in α.)*
- **Presentation and blinding:** the within-pair order is sealed to a key file that **does not travel
  with the clips** (Round 4's Amendment A4: `_records/` rides every rsync). Blind clips are byte-copied
  to neutral names so the `src=` attribute leaks nothing. **No tally, running count or per-trial
  feedback is shown to the listener until every sitting is complete**; the harness reveals nothing and
  the orchestrator reports nothing between sittings. **Block order is fixed (A then B) and is therefore
  confounded with sitting order and fatigue** — any A-vs-B comparison names that.
- **The void rule:** a voided block is discarded and replaced by the **registered replacement draw** —
  the same prompts at seeds **6000 + i**, fixed here, under the same pins. *(v1 inherited "fresh
  stimulus draws" from a prereg with headroom; this stimulus set is exhaustively fixed, so without a
  registered replacement the re-run would be either a replay or a post-hoc seed choice.)* The block is
  re-run **at most once**; a second void ends the arm as **INCONCLUSIVE**.
- **Failed renders, registered.** Every clip passes a sanity check before it enters a pair: non-silent
  (integrated LUFS measurable and above −40 LUFS), full expected duration, decodes. A failing clip is
  re-rendered **once** in a fresh process at the same seed and the event recorded. If a prompt still
  fails its pair is dropped, **n falls, and the threshold is recomputed mechanically from the same rule
  (smallest k with exact one-sided α ≤ 0.05), never held at its original value**:

  | n | clears at ≥ | exact α | power @0.70 |
  |---:|---:|---:|---:|
  | 24 | 17 | 0.0320 | 0.565 |
  | 23 | 16 | 0.0466 | 0.618 |
  | 22 | 16 | 0.0262 | 0.494 |
  | 21 | 15 | 0.0392 | 0.551 |
  | 20 | 15 | 0.0207 | 0.416 |
  | 19 | 14 | 0.0318 | 0.474 |
  | 18 | 13 | 0.0481 | 0.534 |

  *(This is the independent-trial reference; under the clustered threshold the same recomputation runs
  one step stricter.)* Below n = 18 the arm is **INCONCLUSIVE**, not tested.
- **⚠ THE STOP CONDITION THIS PROGRAMME ACTUALLY NEEDS.** If the operator does not complete block A —
  the mnml verdict was two described pairs, not a scored block — **the arm is INCONCLUSIVE BY THE
  GATE**, and the only publishable sentence is the described listen, quoted, with the number of pairs
  actually heard. **A partial block is never reported as a tally, never rounded up to a verdict, and
  never compared to the threshold.**
- **⚠ THE NULL-INSTRUMENT RUN: NEVER RUN, AT ANY CLIP LENGTH — and this prereg does NOT inherit the
  first prereg's §8 stop condition.** Receipt: `STAGE0-READINESS-2026-08-29.md:423-428` — *"Neither
  exists yet"* — and no null-run artefact exists under `music/out/` or
  `estate/bench/ace-mnml-2026-09/`. The first prereg's §8 registered a null block at 25 s as a
  precondition for Rung 2 and it was never scored. **REGISTERED, in advance: if block A opens without a
  measured null floor, the consequence is named rather than softened —** *this harness has never been
  shown to return ≈ 50 % with no adapter in the loop, so a clearing tally cannot be separated from an
  instrument that prefers the second clip* — **and that sentence travels with every block-A result in
  this programme, in the results paragraph and not in a footnote.** Declining an inherited stop
  condition is a **deviation from row 24's sealed prereg** and is filed there as its own numbered
  amendment **in the same stroke as this seal**. *(v1 said the null "was measured at 25 s" and "has not
  been re-measured at 30 s". Both were false, in the direction that flattered the instrument. Struck.)*
  **A6-HOUSE — running block T as the null before block A's first sitting — is the only way to retire
  the caveat, and it costs 12 presentations, not 30.**

### 7.5 Objective side-readings — descriptive, never verdicts

1. **Floor check — the one hard automatic fail, and it is BINDING here.** Audiobox-Aesthetics
   **PQ ≥ (base-arm PQ − 0.3)**, mean over the arm, both arms scored by **one A1-pinned instrument in
   one session** on the training box. A1 is filed and verified intact, so unlike the first train this criterion
   is binding. **Never rank on the PC axis.** Licence: `audiobox-aesthetics` **CC-BY-4.0** — clean,
   publishable beside the result, credited in the article's thanks section.
2. **Style-match — descriptive, and useless without its control.** Cosine similarity between each
   generation and the **centroid of the arm's held-out tracks**, reported **only** beside a negative
   control (the same similarity against three unrelated corpora). Under ⧖ H-1 option (a) this figure is
   **reported twice, with and without the arm-3 artist's tracks in the centroid** (§3.2).
3. **Tempo / key stability — descriptive.** `|rendered BPM − requested BPM|` as a percentage, with
   **octave errors (2× / ½×) counted separately and never folded into a mean**; key agreement as a raw
   count. ⚠ Key pins are **unverified instruments** on this estate (lesson 8).
4. **EXCLUDED: FAD / KAD.** Positive bias halving per doubling of N; values at different N are not
   comparable, and these arms differ in N by design. Per-song FAD for **outlier hunting only**,
   reported as a list of flagged clips, never a score.
5. **MuQ-Eval: run it, label it, do not ship it** — CC-BY-NC-4.0 backbone, internal only, blocked from
   any public claim without a P47-class ruling.
6. **CLAP-laion-music** (§8): code **CC0-1.0** as read from its bundled LICENSE (its setuptools
   classifier says Apache-2.0 — both readings recorded, both permissive), weights **cc0-1.0**. Clean,
   and credited in the article's thanks section.

### 7.6 WHAT "ARM 1 CLEARS" MEANS — all four, or it did not clear

*(v1 named a gate, a binding automatic fail, a sentinel band and a memorisation criterion and never
conjoined them, so nothing forbade the sentence "arm 1 cleared" on a run where block A hit threshold
and the PQ floor failed. The parent prereg's Rung 2 was explicit; this restores it.)*

Arm 1 clears iff **all** of:

- **(a)** block A: the adapter arm wins **≥ 18 of 24** distinct trials (§7.3);
- **(b)** the sentinel block accepts, **2–10 of 12** (§7.4);
- **(c)** the floor check passes — Audiobox PQ ≥ base − 0.3, one A1-pinned instrument, one session
  across both arms (**binding**, §7.5.1);
- **(d)** the memorisation check passes against A2-HOUSE's frozen numeric threshold with its listened
  confirmation (**descriptive if A2-HOUSE is unfiled**, §12).

Provenance (§11.1's rows 1–10) is a **precondition of the run**, not a clause of the verdict.
**A rung rejected by its own gate gets no threshold table and no consolation ladder — it gets a
write-up saying it did not clear.**

---

## §8 — THE COHERENCE BENCH, RE-RUN UNDER THE PINNED INSTRUMENT

**Amendment A1 of `PREREG-COHERENCE.md` pins this instrument, and it is reused, not rebuilt.** Same
CLAP-laion-music checkpoint (`music_audioset_epoch_15_esc_90.14.pt`, sha `fae3e9c0…`), same
CPython 3.12.14 / torch 2.8.0+cpu freeze (`freeze-A1.txt` sha `258a10ee…`), same
`CLAP_Module(enable_fusion=False, amodel='HTSAT-base')` with the checkpoint passed explicitly as
`ckpt=`. **STEP 0 aborts if A1's receipt — `shape (1, 512), L2 norm 1.0000` — is not reproduced.**
All verified present on the training box.

**Crop and loudness policy, seeds, the duplicate-pair rule and the estimator are inherited verbatim**
from `PREREG-COHERENCE.md` §4–§5: three 10 s windows at 25 / 50 / 75 % of the source's true `ffprobe`
duration, mono 48 kHz, −16 LUFS / −1 dBTP, 16-bit PCM; a track's embedding is the L2-normalised mean of
its three crops; `D_pair` is the headline; equal-N draws `default_rng(20260903)`, bootstrap
`default_rng(20260904)` over **distinct ids only**, permutation `default_rng(20260905)`, 10,000
permutations.

**MEASURED, NEVER GATING** (D-20260831-17).

### 8.1 Equal N — and every hypothesis names its N

`PREREG-COHERENCE.md` fixed **N = 19** as the smallest training set across five corpora. The house
comparison's smallest training set will be **arm 3's** (37, §3.3). **Registered: the house bench reports
at BOTH `N = 19` (comparable to the five mnml-arc corpora) and at `N = N_min(house)`.** **The N = 19
axis is PRIMARY for every hypothesis that names one**, so no hypothesis is decided on an axis chosen
after its numbers exist.

### 8.2 The registered hypotheses, written before any embedding

- **H1-HOUSE:** `D_pair(house-wide training set) > D_pair(house-artist training set)`, **N = 19
  primary, N_min(house) secondary**. **Decision rule, inherited exactly:** **primary —
  non-overlapping 95 % CIs** (`PREREG-COHERENCE.md` RATIFY-5's ruled rule); **secondary — one-sided
  permutation p < 0.05**. Both reported, and **if they disagree the disagreement is the finding**.
  *(v1 conjoined the two with AND — a stricter instrument presented as inheritance; corrected toward
  the inherited rule.)* **Predicted: yes. Confidence: high** — the mnml arc measured 0.4489 vs 0.2378
  on the analogous pair, and the house pool spans 96 artists against one. **Under ⧖ H-1 option (a)
  the two training sets are DISJOINT by construction** — the comparison the mnml bench could not make
  (its A-C3 measured 21 of 24 shared tracks).
- **H1b-HOUSE (a manipulation check):** `D_pair(house-core) < D_pair(house-wide)`, **N = 19 primary,
  N_min(house) secondary**. **⚠ `house-core` is a SUBSET of `house-wide`'s training set by
  construction** — 159 of arm 1's ~325 — so this is not two corpora but *"the nearest 159 with and
  without the other ~221"*. **It is the A-C3 nesting, registered in advance this time rather than
  discovered after the numbers.** It is further guaranteed by the selection rule: arm 2 is chosen for
  proximity to a centroid **in the same space the bench measures**. **A confirmation says the prune
  ran; only a NON-confirmation is informative, and it would indicate a bug.**
- **H3-HOUSE / H3b-HOUSE:** for each base/adapter pair at the same caption and seed, is the adapter's
  render closer to its own training corpus's centroid? **Predicted: uncertain** — the mnml arc's
  best-powered arm returned 5/12 and 6/12. Exact one-sided sign test, **n = 24 per arm**, clears at
  **k ≥ 17** (α = 0.0320); **power 0.358 / 0.565 / 0.766 / 0.911 at a true 0.65 / 0.70 / 0.75 / 0.80**;
  minimum attainable one-sided p = 2⁻²⁴. Against the mnml arc's Set B (n = 12) this is the estate's
  best-powered coherence arm — **and its 24 trials are 12 prompts × 2 seeds and are therefore
  prompt-clustered, so §7.3's clustered type-I table rides this test too.**
- **H5-HOUSE (descriptive):** `d(·, C_house-wide)` is non-increasing across `base → 0.5 → 1.0`. A
  non-monotone majority publishes in the coherence prereg's own words: *"the dial moves the audio but
  not along the corpus axis"*.
- **H4-HOUSE (exploratory, no test):** see §7.2 — **uninterpretable without block T**, reported as two
  group medians with both mechanisms named.
- **The cross-centroid control** (`PREREG-COHERENCE.md` §6.4) applies to every house render.

### 8.3 Boxes, archives, and what the bench must NOT re-cut

**One box note, corrected.** The coherence bench of 2026-09-03 **ran on the training box** — this programme's own
train and eval box (its §10.1 receipt lists GPU UUIDs `(GPU UUID withheld)` and `GPU-46890836-…`, identical
to §5.4's). The mnml-arc crops travelled there then, and their embeddings are archived at
`music/out/coherence-bench/` (`embeddings.npz` sha `f9e968ce…`, `crops-archive-box.csv`,
`crops-training-box.csv`, `out/metric1-corpus-spread.csv` sha `2287ed0c…`). **No cross-box transfer and no
fresh cross-box crop-equivalence check is needed for any cross-arc comparison, and RE-CUTTING THE MNML
CROPS IS FORBIDDEN** — it re-opens the one thing that makes 0.4489 comparable. *(v1 said the mnml
corpora live on the archive box and crops must travel; struck.)*

### 8.4 What the coherence bench cannot say

Inherited verbatim from `PREREG-COHERENCE.md` §9: CLAP distance is **not musical quality**; spread is
**not disorder**; **no causal claim**; **no generalisation** to genres, models or embedders; **not a
memorisation check**; **not an equivalence test** — a null is *"we did not detect a difference at this
N with this instrument"*, never *"the corpora are the same"*.

---

## §9 — THE OPERATOR'S PREDICTION, REGISTERED BEFORE ANY NUMBER EXISTS

### 9.1 The words

the operator, relayed to this lane **2026-09-05 ~23:4xZ**, before any house track had been preprocessed,
verbatim:

> *"i feel like since house has a more consistent structure, with a larger training set here, it could
> turn out better, but honestly, nobody knows haha"*

Registered as a **prediction**, not a hypothesis the programme was designed around, and written down so
that whichever way it lands, it lands **on the record made before the numbers**. The operator's own
hedge — *"nobody knows"* — is part of the registration. *(The exact utterance time is the
orchestrator's to confirm at the seal; this lane records the time it received the words.)*

### 9.2 P-A — the corpus reading

**The claim.** The `house-wide` **training set**'s mean pairwise CLAP cosine distance `D_pair` lands
**below** the minimal-techno training set's, measured on the same instrument at the same N.

**The comparator is READ, not recomputed.** mnml's equal-N=19 `D_pair` = **0.448852**, draw sd
**0.039577**, 95 % bootstrap CI **[0.365211, 0.523948]**, read from
`music/out/coherence-bench/out/metric1-corpus-spread.csv` (sha `2287ed0c…`), row
`primary,mnml`. *(That CI is the 5th and 196th order statistic of 200 draws — granular, not smooth.)*

**P-A's DECISION RULE, registered** (v1 had none, and its three outcomes overlapped — a point
comparison and an interval rule cannot partition anything):

- **Primary (the ruled rule):** P-A **holds** iff the house training set's equal-N=19 `D_pair` 95 %
  bootstrap CI lies **entirely below** [0.365211, 0.523948]. P-A **fails** iff it lies entirely
  **above**. Otherwise the result is **NOT DETECTED** — *"the two corpora are not measurably different
  in spread at this N with this instrument"*, never an equivalence.
- **Secondary (registered, not a substitute):** a two-sample permutation test between the two
  track-embedding sets at equal N = 19, 10,000 permutations, `default_rng(20260905)`, one-sided for
  "house < mnml". Both reported; **if they disagree, the disagreement is the finding.**
- **The three outcomes are exhaustive and mutually exclusive by construction. No fourth sentence
  exists.** Point estimates are reported **beside** the rule, never as the rule.

**STEP 0′ — the reproduction gate.** Before any house crop is cut, the house bench re-derives mnml's row
from the archived `embeddings.npz` (sha `f9e968ce…`) + `embeddings-index.csv` (sha `dd8e4712…`),
**consuming `default_rng(20260903)` / `(20260904)` in the same `CORPUS_ORDER` position mnml occupied
(fifth of five — `run_bench.py:116`)**, and **aborts if it does not reproduce 0.448852 /
[0.365211, 0.523948] to six decimals.** The house corpus draws as a **fresh stream at position 1**
(registered here, not chosen later), and the bench **also** reports the house CI under mnml's
fifth-position stream as a sensitivity, so the stream cannot be the thing that decides the rule.

**WHEN: BEFORE THE TRAIN, AFTER THE SEATS STOP.** The bench is CPU-only (`torch 2.8.0+cpu`, no CUDA
runtime linked — it cannot allocate on a card) and needs only the frozen audio, so **P-A is measured
between the corpus freeze and the first training step** and is **reportable as a PRE-TRAIN FACT**.
⚠ It does **not** run before the seats stop: the training box has ~10 GB RAM available with them up and is
already into swap, and a CPU CLAP pass over ~433 tracks is a RAM tenant, not a free rider.

**P-A is reported for THREE sets, all registered here, because the ⧖ H-1 ruling moves the number:**
(i) the frozen arm-1 **training set** as the H-1 ruling leaves it — **the headline**; (ii) the full
frozen **pool**; (iii) the training set **with `artist_487628` re-included**. Under option (a) the
corpus's single tightest cluster (39 tracks sharing one caption and one album) leaves the training set,
which **raises** `D_pair` — so the ruling's effect on the number is visible rather than baked in.

**Predicted: YES. Confidence: moderate, not high.** Reasoning stated in advance: the house pool spans
96 artists against the mnml corpus's dozens, which argues the other way; what argues *for* is that
house is one genre family with a narrower production convention, while the mnml corpus was an
**archive.org folksonomy tag** spanning twenty years of netlabel culture and three licence tiers.

**Two confounds registered with their directions, because P-A's own stated mechanism is one of them:**

- **The delivery chain.** The mnml corpus spanned four codecs and four sample rates; the house pool is
  one host — **and because §2.7's API route is now the registered route, the "one delivery format" half
  of that sentence is replaced by the freeze's measured codec/rate census, whatever it says.** Codec diversity is a delivery property, not a musical one, and
  **CLAP is sensitive to it: resampling to 48 kHz does not remove a codec's lowpass.** So P-A, if it
  holds, may be measuring *"one codec vs four"*. **Registered sensitivity arm S-BAND:** the per-file
  measured bandwidth ceiling is reported per corpus as a distribution, and house `D_pair` is recomputed
  on crops after a common lowpass at **the mnml corpus's own median ceiling**, so a codec-matched
  reading exists beside the primary.
- **Duration.** The crop policy samples a fixed 30 s per track. The house pool's median duration is
  **288.0 s** against the mnml-arc corpora's 133–240 s, so house tracks are sampled at a *smaller
  fraction* of their length — more sampling noise per embedding, which **inflates** house `D_pair`.
  That is a bias **against** P-A (the safe direction), registered rather than left to be found. Both
  duration distributions are published beside the `D_pair` figures, and a registered sensitivity arm
  recomputes house `D_pair` on the subset of house tracks inside the mnml corpus's own duration range.

### 9.3 P-B — the ear reading

**The claim.** The operator's blind 2AFC prefers the `house-wide` adapter at dose 1.0 over base more
often than `mnml0` did.

**⚠ THE HONEST FORM, and why it is not a direct comparison.** `mnml0` **has no scored block.** Its
record is *described listens*: the operator ruled base better on `Basement Loop 7`, and on the
caption-shaped pair said the two were *"similar"* then *"very different"* with *"weird rhythms"* added
by the adapter (D-20260903-03, verbatim). **A described listen and a scored block are different
instruments, and a tally may never be compared to a description as though both were counts.**

| part | form | threshold |
|---|---|---|
| **P-B1 — the registered test** | block A (§7.3): base vs `house-wide` @ 1.0, 24 trials, blind, loudness-matched, order-randomised | **clears at ≥ 18** — the clustered threshold, ruled final under ⧖ H-3 |
| **P-B2 — the descriptive comparison** | `mnml0`'s described listens quoted verbatim beside `house-wide`'s tally | **no threshold, no test, no p-value** — the two instruments named and the incomparability stated in the same sentence |

### 9.4 The sentences each outcome may support

| outcome | the sentence it licenses, and the one it does not |
|---|---|
| **P-A holds** | *"Measured before the adapter existed, the house training set sits closer together in CLAP space than the minimal-techno training set did at the same sample size (⟦x⟧, 95 % CI ⟦…⟧, against 0.448852 [0.365211, 0.523948], equal N = 19, one pinned CPU instrument). **The two corpora also differ in delivery chain and in track length, and CLAP is sensitive to both; the measured bandwidth-ceiling and duration distributions of both corpora are published beside this number so the reader can see how much of the gap could be the codec.**"* **Not:** "house is a more coherent genre." |
| **P-A fails** | *"The operator's intuition that house would be the more consistent corpus is not supported by this instrument."* **This is a real result and it publishes**, before the ear's verdict is known — which is what makes it worth registering. |
| **P-A not detected** | *"not measurably different at this N with this instrument"* — never "the corpora are the same". |
| **P-B1 clears** | §10.1's verbatim sentence, and nothing more. **Not** "house trained better than minimal techno" (§1.1's six-way confound). |
| **P-B1 misses** | *"No large effect detected"* — never "no effect", and never "the operator's prediction was wrong". At n = 24, k ≥ 18, a true 0.70 effect is missed **61 %** of the time. |
| **block A not completed** | **INCONCLUSIVE by the gate** (§7.4). The prediction is neither confirmed nor refuted. |
| **P-A holds but P-B1 misses** | the most interesting outcome: *"the corpus was measurably more coherent and the ear still did not prefer the adapter"* — coherence is not sufficient, which sharpens rather than settles the question. |
| **P-A fails but P-B1 clears** | the self-refutation clause of §10.3(6) fires: **the metric failed, not the adapter**, and that demotion publishes beside the result. |

### 9.5 THE CAVEAT THE ARTICLE MUST CARRY: what "structure" can and cannot reach

the operator's reasoning rests on **structure** — house being more consistently *arranged*. The adapter cannot
learn arrangement, and saying so is a fact about the recipe, not a hedge.

**The LoRA targets `q_proj k_proj v_proj o_proj` only** (§5.1, rank 64 / alpha 128, dropout 0.1, bias
none) — the four attention projections, and **no MLP, no embedding, no output head**. What a rank-64
adapter on those projections can move is **local statistics**: timbre, texture, the production
signature, the drum palette, the spectral fingerprint of one mastering convention. What it cannot
install is **long-range musical form** — a sixteen-bar build, a drop where the drop belongs, an
arrangement.

> *A more consistent genre may help this adapter — but only by making the **production signature** more
> consistent, not by teaching it the **arrangement**. "House has a more consistent structure" reaches
> this recipe as a texture claim, not a form claim.*

This is also why the coherence instrument and the recipe agree on their axis: **CLAP embeddings are
timbre- and texture-dominated**, which is precisely the axis a q/k/v/o LoRA moves. That agreement is a
convenience of the design and **also a limit** — both instruments are blind to arrangement, so
**neither can confirm nor refute the structural half of the operator's intuition.** The article states
that plainly rather than letting a coherence number stand in for a claim about form.

---

## §10 — THE SENTENCES A PASS MAY AND MAY NOT SUPPORT, WRITTEN IN ADVANCE

### 10.1 The only sentence a passing block A licenses, verbatim

> *"the operator preferred the `house-wide` arm in ⟦k⟧ of 24 blind, loudness-matched, order-randomised paired
> trials (95 % Wilson CI ⟦lo⟧–⟦hi⟧), on the twelve prompts frozen for Round 4 and reused verbatim, at
> two seeds each, **the adapter arm's prompt prefixed with the trigger string `house-wide, ` that the
> base arm did not carry**, scored against a pre-registration sealed 2026-09-0⟦d⟧. **The harness's null
> has never been measured.**"*

Never *"the adapter is better."* With one listener you cannot separate a real effect from one person's
idiosyncrasy — and for a personal style adapter that is arguably the point, which is why the claim is
scoped to the listener by name rather than generalised.

### 10.2 The non-claim, computed in advance

At n = 24 with k ≥ 18, a true 0.70 effect has power **0.389** and a true 0.65 effect far less: a real,
moderate improvement **will be missed most of the time**.

**A result below the threshold is *"no large effect detected."* It is NEVER *"no effect."*** A block
that was not completed is **INCONCLUSIVE**, not a null.

### 10.3 What no house result may claim

1. **Nothing about captions.** Arm 1 changes genre, source, size, caption regime, box and epochs at
   once (§1.1).
2. **Nothing about "more data is better".** Arm 1 vs `mnml0` is ~325 house tracks against 159 techno
   tracks — two corpora, two genres, two intake pipelines, and `mnml0` has no scored block. **Arm 1 vs
   arm 2 is the size comparison this programme registers**, interpretable only once both have run, and
   even then the epoch difference is a named non-matched variable (§13.1).
3. **Nothing about the genre.** "House" here is two Jamendo tags on one dataset snapshot under two
   licence terms, minus a block-list. **It is not the genre.**
4. **Nothing about models or embedders.** One text-to-music model, one adapter recipe, one embedding
   space.
5. **No causal claim from two under-powered instruments agreeing.**
6. **The self-refutation clause:** if an adapter wins the blind block while **losing** on the automatic
   scores, **the metric failed, not the adapter** — the automatic scores are demoted to diagnostic for
   this programme, and the demotion publishes beside the result.
7. **A rung rejected by its own gate gets no threshold table and no consolation ladder.**
8. **Nothing that separates the adapter from its trigger token** without block T (§4.6, §7.3).

---

## §11 — THE SUBSTRATE CONTRACT

Per D-20260831-04/06/07, **train #6 records intake items + licence evidence + files/hashes + dataset
freeze + split + pinned stack + train config/steps/losses + the adapter, end to end.** Table names are
from `estate/research-substrate/migrations/0001_v0.sql`; the pattern is `ingest/ingest_mnml0.py` +
`mnml0.sql`. **Extend it; do not fork it.** DSN via `estate/research-substrate/research-psql.sh`
(the research database on the records host :PORT, the private network only); **no passwords in argv**.

### 11.1 Rows that MUST exist BEFORE the first training step

| # | table | what it must hold |
|---|---|---|
| 1 | `licence` | one row per distinct licence URL, `url_verbatim` exactly as the source wrote it, `requires_attribution` / `share_alike`, `text_sha256` + `text_read_at` where the deed was read first-hand — **including the Jamendo API terms if §2.7's route is taken** |
| 2 | `source_item` | one row per upstream record, with `evidence_url`, `evidence_fetched_at`, `evidence_sha256`, **`user_agent_sent`**, and (gap 6) `excluded_before_fetch` + reason + note for metadata-time exclusions |
| 3 | `source_file` | one row per **fetched** audio file: `local_sha256`, `bytes`, `published_sha256` where known and **marked non-verifying under the API route** |
| 4 | `corpus` | slug `house-wide`, `acquired_at`, `acquired_on_box`, `intake_receipt_sha256` |
| 5 | `corpus_member` | one row per **fetched** file with `status` and, for every exclusion, `exclusion_reason` + `exclusion_note` |
| 6 | `freeze_point` tier `corpus` | all NOT NULLs: `tier`, `corpus_id`, `host`, `root_path`, `manifest_sha256`, `file_count`, `byte_total`, `frozen_at`, `durability` — plus `record_manifest_sha256` (gap 7) |
| 7 | `freeze_point` tier `dataset` | same NOT NULLs, `parent_freeze_id` → the corpus freeze |
| 8 | `split_policy` | the §3 rule verbatim, `holdout_fraction_target` 0.200, actual counts, `caption_source`, `caption_template`, `caption_rule_verbatim` (gap 8), `duration_policy = flat_cap`, `max_duration_s = 240.0`, **`genre_ratio = 0`**, `custom_tag = 'house-wide'`, `tag_position = 'prepend'` |
| 9 | `split_assignment` | one row per split unit with side and track count |
| 10 | `freeze_point` tier `tensor` | the tensor freeze, `parent_freeze_id` → the dataset freeze |

**No training step starts until rows 1–10 exist and verify.** That is the gate D-20260831-04 named.

### 11.2 Rows that MUST exist AFTER the train

`train_run` — every NOT NULL sourced in §5.4: `box`, `gpu_uuid` (never an index), `gpu_model`,
`driver_version` **595.84**, `power_limit_w` **250.00** (D-20260905-94), `attended`, `seed`, `trainer`,
`trainer_commit_sha`, `python_version`, `torch_version`, `cuda_version`, `peft_version`,
`adapter_type`, `target_modules`, `batch_size`, `grad_accum`, `lr`, `epochs`, `n_samples`,
`steps_per_epoch`, `total_steps`, `peak_vram_gib`, `warmup_steps` (requested) and
`warmup_steps_effective` (gap 4) · `epoch_metric` (one row per epoch, `loss_kind = 'epoch_mean'`, 6 dp)
· `checkpoint` (**five under `--save-every 1`**, `selection_basis` on the shipped one) · `adapter`
(sha256, bytes, `licence_posture = 'share_alike_encumbered'`, `origin = 'train'`) · `freeze_point` tier
`adapter_artifact`, `durability = 'precious'` · `measurement` · `decision_link` (this prereg,
D-20260831-01/03/04, **D-20260905-84**, **D-20260905-86**, P43, P45, P47) · `render` +
`render_adapter` for every clip · **`egress_grant` + `egress_event`** for anything that reaches the
shelf (§2.2) · `replica` for the the archive box adapter backup.

⚠ **The `one_authoritative_measurement` partial unique index bites twice, and the authoritative row is
named in advance:** **(i)** peak VRAM has two readings (allocator 5.7 GiB, card delta 6.7 GiB) — **the
allocator reading is authoritative**, the card delta rides as `is_authoritative = false` with its
counting rule; **(ii)** `D_pair` has two N axes — **N = 19 is authoritative**, `N_min(house)` rides as
false. Same for s/step: **the epoch-lines reading is authoritative**, the banner and wrapper readings
ride as false with their rules.

### 11.3 ⚠ EIGHT SCHEMA GAPS THAT BLOCK THE INGEST — owed as migration `0002_house` before the freeze

| # | gap | line | what breaks | additive fix |
|---|---|---|---|---|
| 1 | `split_strategy` has no `by_artist_stratified` | `:174` | §3's split cannot be recorded truthfully | add the value |
| 2 | `split_unit_kind` has no `artist` | `:178` | `split_assignment.unit_kind` cannot name what the walk walked | add the value |
| 3 | `caption_source` is `('placeholder','authored')` | `:175` | §4's captions are neither | add `derived_from_source_tags` |
| 4 | **`train_run` has `warmup_steps` only** | `:257` | **§5.3's both-numbers rule is unrecordable; the substrate would log the requested 100 for the sixth run running** | add `warmup_steps_effective int`; `warmup_steps` becomes the requested value and the comment says so |
| 5 | **`exclusion_reason` has no style-fence, too-short or decode-failure value** | `:108-111` | **91 style-fence exclusions would collapse to `'other'`, defeating D-20260905-84's naming clause** | add `style_fence`, `under_30s`, `decode_failure`, `lal_licence`, `out_of_scope_in_rule` |
| 6 | **metadata-time exclusions cannot be rowed** — `source_file.local_sha256`/`bytes` are NOT NULL | `:87-88`, `:125-134` | **E1/E2/E3/E6/E8 tracks are never fetched, so they can have no `corpus_member` row** | **registered choice:** `corpus_member` records only exclusions of **fetched** files (E4/E5/E7). Metadata-time exclusions are rowed on `source_item` with `excluded_before_fetch boolean NOT NULL DEFAULT false` + `exclusion_reason` + `exclusion_note`, and **the freeze's verify SQL asserts that count equals the intake doc's named-exclusion count**, so the two cannot drift |
| 7 | **`freeze_point.manifest_sha256` means the sha of `MANIFEST.sha256`, not of `manifest.jsonl`** | `:161` | the house freeze row would hold a different artifact from mnml0's in the same column | **registered choice:** that column keeps its defined meaning; the sha of `manifest.jsonl` lands in a new `freeze_point.record_manifest_sha256 char(64)`, and §2.1(3) is worded so the two are never confused |
| 8 | `split_policy` has `caption_template` but no place for the rule prose | `:188` | §4.2's rule cannot be stored verbatim | add `caption_rule_verbatim text` |

**All eight are additive** — enum values and nullable columns break nothing already stored. **A4-HOUSE
covers all eight and must land before the dataset-freeze ingest.**

---

## §12 — OWED AMENDMENTS, EACH WITH THE STEP IT MUST PRECEDE

| # | what it fixes | must be filed BEFORE | if unfiled |
|---|---|---|---|
| **A1-HOUSE** | *(not owed — inherited)* the eval instrument pin; A1 of row 24 is FILED and verified intact | — | — |
| **A2-HOUSE** | **the memorisation threshold as a literal number**: the **TRAINING-set** pairwise CLAP similarity distribution on the frozen dataset hash, published whole, threshold = its **95th percentile**, with the **holdout as the matched negative control**; **k = 20**, fixed here; the render set is block A's 24 adapter-arm clips; the top-20 (render, training-track) pairs by cosine are listened to in the same harness, question *"is this the same tune?"* | **the first training step of arm 1** | the memorisation criterion is **DESCRIPTIVE**: reported with its distribution, never counted as a pass |
| **A3-HOUSE** | *(conditional)* **bpm in the captions** from a local librosa pass | **the first caption render** | not run; captions carry no bpm |
| **A4-HOUSE** | **migration `0002_house`** — the eight gaps of §11.3 | **the dataset-freeze ingest** | the split, caption and exclusion rows cannot be recorded truthfully; the ingest is blocked, not fudged |
| **A5-HOUSE** | *(conditional)* **the archive.org rung** — which licence rung, how many tracks, class E8's application, and the narrowed title rule for that rung | **the corpus freeze** | arm 1 is Jamendo-only and says so |
| **A6-HOUSE** | **block T scored as the null-instrument block** before block A's first sitting | **block A's first sitting** | block A opens with the "never measured" caveat of §7.4 travelling with every result |
| **A7-HOUSE** | **Side-Step's own upstream commit sha**, from `ACE-Step-1.5/docs/sidestep/` and `requirements-sidestep.txt` | any published claim naming a Side-Step version | `trainer_commit_sha` pins the ACE-Step-1.5 checkout only, and the article says exactly that |
| ~~**A8-HOUSE**~~ | **CLOSED NOT-TAKEN** by the ⧖ H-3 ruling — twelve new prompts were offered and declined | — | block A runs at 12 × 2 with the clustered threshold **k ≥ 18**, power **0.389**, stated in every published sentence |

**Two amendments are owed against OTHER files in the same stroke as this seal:** the declination of row
24's §8 null-run stop condition (§7.4), filed as a numbered amendment there; and the correction to
`MATERIALS.md:490` / `recon/sleeve-rows.md §3.1 HAZARD 4` on the trainer commit (§5.4).

---

## §13 — WHAT ARMS 2 AND 3 INHERIT (registered now so their trains cannot move the goalposts)

Everything above binds arms 2 and 3 unless this section changes it: the shared-holdout rule (§3.2), the
caption template (§4), the shipped-checkpoint rule (§6), the instrument (§7), the coherence bench (§8),
the non-claims (§10), the substrate contract (§11).

### 13.1 ARM 2 — `house-core`, coherence at matched size

- **The pool** is arm 1's frozen corpus, **training side only**.
- **The pruning instrument is the A1-pinned CLAP embedder** — the same one that measures coherence, so
  **the circularity is registered**: arm 2 is selected in the space it is later measured in
  (H1b-HOUSE, §8.2).
- **The seed set is the operator's, picked by ear from arm 1's TRAINING SIDE ONLY.** The holdout is
  never played to the operator for this purpose — a holdout track that shapes the seed centroid is a
  holdout track doing selection. The number of seed tracks, their ids and the date the operator picked them
  are recorded before the prune runs. **A second cost is registered: the operator hears corpus audio
  during this step, so for arm 2 the memorisation screen's listened confirmation is performed by an ear
  that has heard part of the corpus. That limit travels with arm 2's memorisation result.**
- **The prune:** each candidate's cosine distance to the **centroid of the seed set's embeddings**
  (crops per §8's policy); ascending; nearest taken until the training-set size is reached; ties by
  `track_id` ascending. **No re-ranking, no manual additions, no second pass.**
- **THE SIZE MATCH IS AT THE TRAINING-SET LEVEL: `N_train = 159`**, matching `mnml0`'s **159 training
  tracks** — not its 208-track corpus (`PREREG-COHERENCE.md` §2.5 is the receipt for why that
  distinction is load-bearing).
- **The recipe:** `mnml0`'s exactly — **10 epochs**, `--save-every 1`, 40 steps/epoch, 400 total steps,
  effective warmup 40. **Arm 2 vs `mnml0` is recipe-identical and only the corpus moves.**
  **⚠ Arm 2 vs arm 1 is NOT recipe-matched** (10 epochs vs 5) — a named non-matched variable that
  travels with every arm-1-vs-arm-2 statement.
- **What arm 2 can claim:** at a training-set size matched to `mnml0`'s 159 and an identical recipe,
  whether the operator's blind ear prefers `house-core` **over the base model** at the registered
  threshold — a within-arm statement, exactly as arm 1's.
  **What it cannot claim:** anything comparing that tally to `mnml0`, **which has no scored block**
  (§9.3). A comparison to `mnml0` requires `mnml0` to be scored in the same harness on the same prompts
  and seeds — a separate registered block, not an inference. **Nor** anything about corpus size,
  **nor** anything derived from the fact that the prune worked in CLAP space. *(v1's claim — "beats the
  wide techno corpus on the operator's ear" — was a sentence this same file forbade. Struck.)*

### 13.2 ARM 3 — `house-artist`, one artist at scale

- **The artist-pick rule, fixed here:** *the artist with the most tracks in arm 1's frozen corpus
  (after the §2.3 fence and §2.4 exclusions), by `artist_id`; ties broken by total capped duration,
  then `artist_id` ascending.* Measured today it selects **`artist_487628` — "Oilboy's Aftersun",
  47 tracks, 4.76 h, all CC BY 3.0, every track house-tagged, all 47 surviving the fence.** The rule,
  not the name, is registered.
- **⚠ A CORRECTION OWED TO CONTEXT.md.** It describes arm 3 as *"the one-artist control's shape at 3×
  its size"*. Measured: `fm-control` is a **30-track corpus / 24 training tracks**; this artist has
  **47 tracks → 37 training tracks** under §3.3's by-track split. That is **1.57× the corpus and
  1.54× the training set — not 3×.** Every downstream doc carries the measured multiple.
- **⚠ Arm 3's caption regime is DEGENERATE, and is registered as such before it trains.**
  `artist_487628`'s 47 tracks carry exactly **two** distinct captions: `house, club, dance, disco,
  happy, summer` ×39 (`album_156668`) and `house, club, techhouse, tribal, happy, summer` ×8
  (`album_157794`). **A caption-conditioned adapter on two captions is effectively unconditional.** No
  arm-1-vs-arm-3 sentence may attribute a difference to corpus breadth without naming that **arm 1 saw
  195 captions and arm 3 saw 2**, on top of size and epochs.
- **The recipe:** N_train = 37 → `ceil(37/4) = 10` steps/epoch. The §5.2 table gives 10 epochs → 100
  total steps, **which misses the 300-step floor**. **REGISTERED: the floor is SUSPENDED for arm 3 and
  arm 3 matches `fm-control`'s recipe — 10 epochs, 100 steps** — because a control's value is in being
  recipe-identical to what it controls (`fm-control` ran 60 steps). The suspension is recorded here,
  not decided later.
- **Under ⧖ H-1 option (a)** arm 3's training set was **held out of arm 1** (§3.2's exact wording),
  which makes H1-HOUSE the clean comparison the mnml arc could not make.
- **What arm 3 can claim:** whether one artist at 1.54× `fm-control`'s training size produces an
  adapter the ear prefers over base, on the same twelve prompts. **What it cannot:** anything about
  "one artist beats many" without arm 1 having run its own block A on the same prompts and seeds.

### 13.3 ARM 4 — the baseline

Not a train: **the base model, unmodified**, and the **base arm of every trial in every block** — the
same prompts × seeds at dose 0, rendered once per process, reused byte-for-byte **within this
programme** wherever seed and pins match (Round 3's precedent: one fixed origin per adapter). The
implementation **keys on `output_sha256`, not `clip_id`** — clip ids collide. *(Cross-article byte reuse
from Round 4 is measured, not assumed — §7.4.)*

---

## §14 — THE LEDGER ROWS OWED, IN THE SAME STROKE AS THE SEAL

`PREREG-LEDGER-OF-LEDGERS.md` LAW 1: *opening a new prereg location = adding its row here in the same
stroke.* The file's last row is **25** (verified). **Two rows are owed** (§0.5). This lane did not edit
the ledger.

**Proposed row 26 — Round 4, the location this file inherits from:**

> `| 26 | estate/bench/ace-mnml-2026-09/PREREG-ROUND4.md (body) + round4-blind-key.json + music/out/mnml-round4/ (runs) | the laptop (repo; the body) + the archive box (the renders) | **ROUND 4 — THE PROMPT SPREAD** (D-20260903-04) — twelve adjacent-style captions × four arms (base · mnml0 @0.5 · mnml0 @1.0 · the one-artist control @1.0), one seed per prompt (4001–4012), 30 s, turbo@8, one clip per process + a determinism repeat; amendments A1–A4 filed before the first render. **Body NOT sha-sealed**; the pins are receipted from music/out/mnml-round4/round-4/records.json (49 clips, shift 1.0 / guidance_scale 1.0 / duration 30.0 / 8 steps / keyscale A minor). Rowed 2026-09-0⟦d⟧ because PREREG-HOUSE-ARMS.md (row 27) reuses its twelve prompts, seeds and render pins VERBATIM and a rule-2 hunt must be able to find them. |`

**Proposed row 27 — this file:**

> `| 27 | estate/bench/ace-house-2026-09/PREREG-HOUSE-ARMS.md (body) + estate/bench/ace-house-2026-09/ (lane reports, panel, runs) | the laptop (repo; the body) + **the training box** (train + eval host, **card B `(GPU UUID withheld)` at 250 W**, D-20260905-94) | **THE HOUSE ADAPTER PROGRAMME, arms 1–4** — the wide house corpus (~407 open-licence tracks (433 fenced, minus the D-20260905-92 `relicensed-since-2019` class), BY/BY-SA, house ∪ deep house ∪ tech house, style-fenced per FENCE v2 (D-20260905-91, sha-pinned JSON) after the D-20260905-88 correction, 240 s cap per D-20260905-86), ~20 % holdout stratified BY ARTIST by the deterministic S3 rule (whole artists, smallest catalogue first, no RNG — 0 straddlers, 58 unseen artists) with ONE shared holdout across all arms and a cross-split near-duplicate scan, captions derived from each track's own Jamendo tags by a fixed sha-pinned template (the P43 gap the mnml train never closed) with 46 % genre-only, the mnml recipe verbatim except epochs 5 and --save-every 1, shipped checkpoint by best epoch-mean loss, the blind 2AFC gate at 24 prompt-clustered trials clearing at ≥ 18 (clustered α ≤ 0.032, power 0.389 @0.70 — the twelve-fresh-prompt alternative offered and DECLINED, D-20260905-91's breath) on the twelve Round-4 prompts REUSED VERBATIM at two seeds, 12 sentinels accepting 2–10, a trigger-only control block T that doubles as the harness's first null (the null-instrument run has NEVER been scored — declared, not hidden), the audio acquired by the Jamendo API route (client id from the operator, a five-file MTG-digest gate, a per-file digest verdict as the provenance chain, the API terms rowed as a licence), plus the coherence bench re-run under row 24's Amendment A1 instrument. MEASURED NEVER GATING per D-20260831-17. The operator's pre-train prediction (P-A/P-B) registered before any number existed. Arms 2 (coherent core, N_train = 159) and 3 (one artist at scale, N_train = 37) registered here BEFORE arm 1 trains. sha256:⧖ at seal. A rule-2 hunt reads this row AND rows 24, 25 and 26 — the eval instrument pin lives in 24, the coherence instrument in 25, the twelve prompts and render pins in 26. |`

---

## §15 — WHAT REMAINS TO RULE BEFORE THE SEAL

**Five of v2's questions are RULED and folded, and two remain.** Since v2 the orchestrator also ruled
**D-20260905-92** (tracks relicensed off the open rung do not train — exclusion class **E9**, §2.2 and
§2.4) and adopted the intake lane's **S3** split candidate (§3.1(3)), both folded here.

**Three of v2's five are RULED and folded** (their records live in the sections they govern, not
here): **⧖ H-6** → D-20260905-88 rows the source-file error and **D-20260905-91 is FENCE v2**, pinned
by sha at §2.3.1 and measured at §2.3.2 / §2.6; **⧖ H-4** → the Jamendo API route is registered with a
five-file MTG-digest gate and a per-file digest verdict as the provenance chain (§2.7); **⧖ H-3** →
the clustered gate stands, `k ≥ 18`, power 0.389, **no new prompts**, A8-HOUSE closed not-taken
(§7.3, §12).

**Two remained at v3; both are RULED at the seal (2026-09-06T00:32Z): ⧖ H-1 → option (b), D-20260905-95; ⧖ H-2 → a named P43 variant, D-20260905-96. A5-HOUSE → not taken for arm 1 (Jamendo-only), D-20260905-97. The table below is kept as the record of the question.**

| id | the question | this lane's recommendation | cost of the other choice |
|---|---|---|---|
| **⧖ H-1** | **Where does arm 3's artist go in arm 1's split?** (§3.3) — **and it now COLLIDES with the split rule**: S3 puts that artist wholly in training, option (a) forces it wholly into the holdout | **THE RECOMMENDATION FLIPPED IN v3 to (b)** — keep the artist whole in arm 1's training side, name arm 3's nesting honestly. Under S3, option (a) is no longer free: it hands **~54 % of the holdout to one artist** and destroys the **58-unseen-artist** property that is S3's reason for existing, degenerating S3 into the S2 candidate the split note rejects. A disjoint arm-1/arm-3 comparison is worth less than a holdout that can answer *"does this generalise to artists it has never heard"* | (a) keeps the disjoint comparison the mnml arc could not make, at the cost above, and requires S3 to run on the corpus minus that artist. Either way the ruling **moves P-A's headline number** (§9.2) and fixes `N_train`, so it must be made **before the freeze and before the coherence bench** — the two rulings interact and neither may be settled by whichever script runs first |
| **⧖ H-2** | **Does the §4 template regime satisfy D-20260827-P43**, or does it need its own DECISIONS row? | rule it a **named P43 variant** in the ledger — *"authored from the source's own tags by a fixed template, operator-approved as a template rather than line by line"* — with §4.5's rendered examples as the approval surface | leaving it unruled means the article must say the approved-caption regime was **again** not applied — the exact sentence this train exists to stop having to write |

**⚠ ONE LEDGER-HYGIENE ITEM THE SEAL MUST CARRY.** `D-20260905-88` and `D-20260905-89` were each
**minted twice on 2026-09-06 by two sessions** — the music/ace fence-correction row and a
research-hub row share `-88`; a research-hub ⧖ holds `-89`. The fence's ruling of record is
**D-20260905-91**, and `ace-house-data/house-wide/fence-report.json` still records
`"ruling": "D-20260905-89"` (§2.3.2's closing note). The estate's own rule from D-20260829-23 applies:
**read the tail max before minting**, and renumbering existing rows is refused. This file cites -88
(music/ace) and -91 throughout.

*(Ruled by this lane unless the orchestrator objects: **arm 3's step floor is suspended** (§13.2);
**LAL tracks are excluded** pending a rung ruling (§2.2); **the archive.org rung is decided as
A5-HOUSE before the freeze**, never after, since a post-freeze addition is a new freeze.)*

**Ten operator-blocking steps exist across this programme; four were written down nowhere before this
file, and two of those are now closed:** (1) ~~the Jamendo API client id~~ **— landed** (§2.7);
(2) the seat-stop paste **and the print lab's `:PORT-A` stop** (D-20260905-94); (3) ~~twelve new prompts~~ **— declined, ⧖ H-3**; (4) arm 2's seed-set pick by
ear; (5) the P45 go for the review shelf; (6) block A sitting 1; (7) block B sitting 2; (8) the
memorisation listen (A2-HOUSE); (9) the seat restore; (10) the two ⧖ rulings above. **The seat-down
window is unbounded in this file and must not be: the 24/7 law (D-20260905-50) puts rulesage, the beat
lab, amble and the estate first, and the training box's seats are part of that estate.** The runbook's restore
paste closes the window, and the window's expected length is stated in the orchestrator's dispatch,
not left open.

---

## §16 — CHANGE LOG

| version | when (UTC) | what changed |
|---|---|---|
| **v1** | 2026-09-05 ~23:3xZ | first draft. Folded during drafting: D-20260905-84 as amended (the full genre block-list + title rule), the caption-coverage confound, and §9's operator prediction. |
| **v2** | 2026-09-05 ~23:5xZ | **panel-hardened.** Two fresh Opus critics (`panel/PANEL-method.md`, `panel/PANEL-laws-ops.md`) returned **18 BLOCKING, 39 IMPORTANT, 13 NICE**. Every BLOCKING and IMPORTANT is folded; the folds are listed below. |
| **v4 — SEALED** | 2026-09-06T00:32Z | **the seal.** ⧖ H-1 ruled (b) (D-20260905-95); ⧖ H-2 ruled a named P43 variant with §4.5 as the approval surface, shown to the operator before the first caption render (D-20260905-96); A5-HOUSE ruled not taken — arm 1 is Jamendo-only and says so (D-20260905-97). No other text changed between v3 and the seal; the §0.4 line is filled with the sha computed while it read its placeholder. |
| **v3** | 2026-09-06 ~00:2xZ | **orchestrator-ruled.** Three of v2's five seal questions are answered and folded (§15 now carries two). ⧖ H-6 → **D-20260905-88** rows the source-file error and **D-20260905-91 is FENCE v2**, now a **sha-pinned JSON** rather than prose (§2.3.1), with its impact measured by three independent computations that agree on **433** (§2.3.2, §2.6); `techhouse` is IN, so **class E3-b is closed**; the OUT list gained the house hybrids, which cost **65 house-tagged tracks** and are named as the operator's adjacency ruling, not a neutral filter. ⧖ H-4 → the **Jamendo API route is registered** with the operator's client id landed, a **five-file MTG-digest gate before the bulk fetch**, a **per-file digest verdict as the provenance chain**, and the API's terms as a **licence row** (§2.7). ⧖ H-3 → **the clustered gate stands: 24 trials, `k ≥ 18`, power 0.389, no new prompts; A8-HOUSE is CLOSED not-taken** (§7.3, §12). Every downstream number is recomputed on the FENCE v2 pool — the caption census (§4.4: 175 distinct, **45.7 % genre-only**, up from 44.3 %), the split dry run (§3.1), the ⧖ H-1 table (§3.3: **the two options no longer tie — (a) now costs 8 training tracks**), the recipe (§5.2, now `⟦to be filled at freeze⟧` with both projections beside it) and the train time (§5.6: **40–44 min**). The `-88`/`-89` id collision is named in §15. |

**What v2 changed, by finding.**

*METHOD lens.* **B1/B2/B3** — the shared-holdout rule restated directionally so arm 3 is not left with
an empty training set; all three of v1's option-(a) arithmetics struck and replaced with the measured
one (both options give `N_train` 380); the by-album intra-artist split shown **infeasible** (two albums,
39 + 8) and replaced with a by-track split (37 / 10). **B4** — P-A given a decision rule (CI-based,
three exhaustive outcomes) where v1 had a bare point comparison and three overlapping outcomes. **B5** —
the trigger `house-wide` shown to contain the genre word *house*, registered as a first-order confound
of the 2AFC, and **block T added** as its control. **B6** — the null-instrument run shown **never to
have run at any clip length** and the harness shown not to exist; v1's two sentences saying otherwise
struck; the §8 inheritance explicitly declined with an amendment owed against row 24. **B7** — the
clustering correction: threshold raised to **k ≥ 18** with power stated at 0.389, and the 24-prompt fix
registered as A8-HOUSE. **B8** — arm 2's headline claim, which the file's own §9.3 forbade, rewritten as
a within-arm statement. **B9** — subsection numbering fixed throughout. **I1–I24** — the walk stated as
code; the band-miss remedy made non-circular; blocks B and pooled stripped of thresholds; all 12
sentinels moved into sitting 1; a registered replacement draw (seeds 6000+i); §7.6's four-part "clears"
conjunction restored; P-A's RNG stream position and the STEP 0′ reproduction gate registered; §8.3's box
note corrected (the bench ran on the training box; re-cutting the mnml crops forbidden); the duration and
delivery-chain confounds registered with their directions; P-A reported for three sets because H-1 moves
it; §4.4 marked a POOL census with the modal caption identified as one album by the arm-3 artist;
cross-article byte comparability made measured not assumed; the adapter arm's prompt registered; arm 2's
seed set restricted to the training side; E5 widened plus the cross-split near-duplicate scan; the
tech-house cell corrected (88, not 91, and the fence costs 17 % of it); the audio-product assertion
added; H1b framed honestly as the A-C3 nesting; a failed-render rule with its threshold table; blinding
between sittings; H3-HOUSE given a power table; the memorisation screen's target corrected to the
training set with k = 20; H1-HOUSE's rule corrected toward the inherited one.

*LAWS + OPERATIONS lens.* **B1** — the 2026-09-05T17:18Z build **voided**, with the rebuild's receipt
specified. **B2** — the ruling's own figures shown to be the wrong file's and the operator's
tag-vocabulary approval shown to have been given over the wrong list → ⧖ H-6 and a correction row owed
against D-20260905-84. **B3** — `genre---techhouse` shown to exist (44 open tracks, 7 outside the IN
rule) → class E3-b and ⧖ H-6. **B4** — the trainer commit provenance **inverted** in v1 and in
`MATERIALS.md`; corrected, with A7-HOUSE owed. **B5** — the null-run claim (shared with METHOD B6).
**B6** — the audio cannot arrive by the tar route (228 h vs 18 h) → **§2.7, the acquisition route**, with
its three registered consequences. **B7** — `PREREG-ROUND4.md` has no ledger row → **two rows owed**,
this file becomes **27**. **B8** — five more schema gaps found (warmup, exclusion values, metadata-time
exclusions, the manifest-sha meaning, the rule-prose column) → §11.3 now lists **eight**. **B9** — the
card **pinned** (v2 pinned card A at 280 W; **D-20260905-94 later flipped it to card B at 250 W** — see the v3 note below) with the two cards shown not to be one instrument.
**I1–I15** — LAL named and excluded; P45 and the egress ladder restored; the RAM budget corrected
(stopping the seats buys ~1.2 GB, not 18) and P-A moved to after the stop; the ≥150 G disk floor named
with a stop condition; class E8 added for the archive rung; the three-corpus-size divergence named; ten
operator-blocking steps enumerated; the `one_authoritative_measurement` index handled for both VRAM
readings and both N axes; the seal-verification procedure made reproducible and the explicit-path commit
law named; the title rule corrected to two matches; **D-20260905-50 named with the seat-down window
called out as unbounded**; the instrument licences (Audiobox CC-BY-4.0, CLAP CC0-1.0) stated.

*Self-caught by this lane between v1 and the panel:* the s/step projection corrected from ~25 min to
**45–48 min** using the measured the training box 1.512 s/sample anchor at the 240 s cap; the two preprocessor
caption defects (`genre_ratio` as an auto-caption replacer; the recorded-vs-encoded caption fallback
mismatch) added as freeze-script gates; and **v1's claim that `raw_30s.tsv` carries "the 195-tag
vocabulary" corrected** — measured, `raw_30s.tsv` carries **692** dataset-wide tags and the cleantags
file carries **195**; the reason to register `raw_30s.tsv` is the acid tags, not the vocabulary size,
and §2.5 now says so.

**NICE findings deferred, by name:** METHOD **N1** (the archive-rung title rule's over-breadth — folded
partially into §2.3 rule 2 and A5-HOUSE; the rest deferred), **N3** (best-of-k not equalised across arms
— the one-sentence rule is folded into §6; the fuller treatment deferred), **N4** (the bootstrap CI's
order-statistic granularity — folded as one clause in §9.2), **N5** (a programme-level claim inventory
table — **deferred, and it is the best of the deferred set**), **N6** (pin numpy for `split_rule.py` —
folded into §3.1(3)), **N7** (the future-dated stamps — fixed in §0.2). LAWS **N1–N6** deferred as filed
in `panel/PANEL-laws-ops.md`.

**Two further rulings folded into v3 after the first three.** **D-20260905-92** — *"Drop the 30, keep
the rest"*: tracks the live Jamendo API now reports off the CC0/BY/BY-SA rung leave the corpus as
exclusion class **E9 `relicensed-since-2019`**, with the API evidence beside each
(`api-licence-audit.json`, 486 rows; `OPTION-B-VERDICT.md` Finding 3). **Measured: 26 of the 30 are in
the FENCE v2 cut**, so the pool is **407**, not the relayed ≈ 403 — the other 4 were already fenced on
style and cannot be subtracted twice. The 105 still-unreadable-today tracks stay in under their frozen
2019 licence, with the same rule applied to any found relicensed before the freeze. **§2.2 states it
as a licence-surface finding for the article**: an open-licence dataset is a *snapshot* of consent,
the estate's rung is deliberately stricter than the law, and nobody who reuses a 2019 research corpus
is told when its authors change their minds. And **the split rule is now S3** (§3.1(3)) — whole
artists, smallest catalogue first, **deterministic with no RNG**, adopted from the intake lane's
`SPLIT-NOTE.md` because on this cut it is **free**: 0 straddlers, 58–59 unseen artists in the holdout,
every large catalogue left in training. Two faults are registered rather than left implicit — the
holdout is small-catalogue-artists **by construction**, and **S3 collides with ⧖ H-1 option (a)**,
which is why v3's H-1 recommendation **flipped to (b)**.

**What v3 changed, beyond the rulings.** Three things were recomputed rather than carried forward,
and each moved in a direction worth naming: **(i)** the caption regime got *thinner*, not richer —
FENCE v2's hybrid tags were themselves caption terms, so genre-only rose from 44.3 % to **45.7 %**;
**(ii)** ⧖ H-1's two options **stopped tying** — on 476 tracks the artist walk backfilled and both gave
`N_train` 380, but on 433 tracks with 96 artists option (a) now costs **8 training tracks** as well as
composition, which is new information for the ruling; **(iii)** the corpus lost **24.6 %** to the
fence rather than v2's 16.05 %, and the article should say that the operator's adjacency ear, not the
licence rung, is what made this corpus small.

**A fifth ruling landed while v3 was being written and is folded: D-20260905-94, the 3090 power
practice.** *"whatever card we use, should be at 250w … for sustained workloads, as a practice"* —
**the train card flips from A to B** (`(GPU UUID withheld)`, index 0, already capped at **250 W**, Bach's
card), for all four arms. §5.4 now records the cap as a **registered instrument property**, with three
consequences: every published s/step carries "250 W"; **throttle `0x4` at the cap is expected, not a
fault**; and the flip **reverses v2's own reasoning** (v2 picked card A *because* its cap was higher,
treating a power-limited card as a compromised instrument — D-94 rules the cap *is* the house
instrument). It also improves the co-tenancy picture rather than worsening it: **the print lab's
ComfyUI on `:PORT-A` sits on card B and is stopped for the window**, so the train runs on an empty
card, where v2's card-A pin would have trained beside a live renderer. §5.6 needs no re-basing — the
1.512 s/sample anchor is already a card-B-at-250 W measurement.

**And one number to watch at the seal:** `N_train` is a **`⟦filled at freeze⟧`**, not a projection
dressed as a fact. Its current best estimate is **325** (407 after fence + E9, minus S3's 82-track
holdout), it fell from v2's 380 through two rulings and a split-rule change, and **E9 can still grow**
if any of the 105 unreadable tracks resolves off the rung before the freeze.

*End of v3. Nothing in this file has been run, and nothing may run until it is sealed.*


---

## AMENDMENT A-H1 — filed 2026-09-06T01:03Z, before the freeze (additive; nothing above this line changed)

**What this amends, for a reader who scrolled straight here.** The sealed body above (v4, sha
`182e3361…`) pins the FENCE v2 spec at §2.3.1 as sha `a1a4c8b0…`. **That value is stale.** The
prereg lane read `ace-house-data/house-wide-fence.json` while its `ruling` field still said
`D-20260905-89`; the orchestrator then corrected the field to `D-20260905-91` (the id collision of §15)
and the file's digest moved. Verified on disk 2026-09-06T01:03Z: the ruling JSON (661 B) is
**`088e25e57fe25d26f4d755b8915e13b5c34e320d902f365f64a905feaf10a30d`**, and `fence-report.json`
records the same value as `fence_spec_sha256`. **The sha of record for the fence spec is
`088e25e5…30d`.** The file's CONTENT is unchanged apart from that one field; §2.3.1's reproduction
of the rules stands.

Four further clarifications, each a fact discovered after the seal by the substrate-0002 lane:

1. **`intake/fence-spec.json` (1,270 B) is the intake lane's DERIVED spec** (the ruling JSON plus its
   measured counts), not a second ruling; where the two disagree the ruling JSON wins. The freeze
   records both shas and names their roles.
2. **§2.7's digest verdict will read `match` for every file, not `mismatch`:** the registered
   acquisition route is the ranged tar walk from the MTG mirror (option C), which verifies each file
   against MTG's published per-track sha256 before writing it; the API route (option B) failed its
   five-file gate (0/5, re-encoded 161–203 kbps) and was rejected under §2.7's own clause. The API was
   used ONLY for the licence census (metadata reads); a snapshot of Jamendo's API terms page, fetched
   with the honest UA and sha-pinned, is filed in the freeze dir as the licence evidence §2.2 owes for
   that use.
3. **The corpus of record at the freeze is the FINAL manifest: 416 tracks** (574 − 141 fence − 17
   relicensed; census complete 574/574). §2.6's 407 was a projection on a partial census and is
   superseded by the freeze's own arithmetic; every `⟦filled at freeze⟧` derives from the 416-track
   manifest.
4. **Owed artifacts named by the body and not yet existing** — `split_rule.py` (§3.1(3)) and
   `tag_words.json` (§4.3) — are written by the train lane at step 1 and sha-pinned in the freeze;
   the substrate migration `0002_house` (A4-HOUSE) is APPLIED (research-substrate, 13 gaps closed
   incl. the E9 enum value, the per-file digest columns, the artist key and `corpus_input`), so the
   freeze ingest is unblocked. `egress_grant` (§11.2) remains a gap to close before anything reaches
   the shelf.

*Filed by the orchestrator (Fable). Verify the seal: remove this amendment block, restore §0.4's line
to its placeholder, sha256sum → `182e3361…`.*


---

## AMENDMENT A6-HOUSE — filed 2026-09-06T11:19Z, before block A's first sitting (additive)

**What this amends, for a reader who scrolled straight here.** §12 owes A6-HOUSE: *block T scored as
the null-instrument block before block A's first sitting*. Block T is rendered (12 clips, trigger
string only, NO adapter loaded, 2026-09-06 10:33–10:59Z, receipts in MATERIALS.md) and its listening
copies are two-pass loudness-matched with the rest (85/85 in tolerance after the single-pass defect
was found and fixed). **Filed now, before any sitting:**

1. **The operator's FIRST sitting is block T**, twelve forced-choice pairs, base vs trigger-only,
   order randomised, condition hidden, no adapter in the loop. It is scored as the null-instrument
   block registered by §7.3: the harness is expected to return a count consistent with p = 0.5
   (7..17 of 24 under the inherited rule scaled to 12 pairs = **3..9 of 12**). A count outside
   that band is a HARNESS finding (the trigger word, the presentation, or the listener), reported
   before block A and carried beside every block-A sentence; it does not by itself void block A.
2. **Block A (base vs adapter at 1.0, 24 pairs) follows in the SAME sitting or a later one**, blind
   between blocks per §7.4; block B (0.5) after. The listen room presents block T first by
   construction (the page order), and the sealed blind key (`round-house-blind-key.json`, outside
   `_records/`) covers all three blocks.
3. With this amendment filed, the caveat *"the harness's null has never been measured"* in §10.1's
   licensed sentence is **retired for arm 1 once block T is scored**, and replaced by block T's
   measured count, whatever it is. Until scored, the caveat stands verbatim.

*A2-HOUSE was NOT filed before its step (the first training step, 09:52:02Z); per §0.5 the
memorisation criterion §7.6(d) is DESCRIPTIVE for arm 1 and the screen is reported as such. Nothing
is back-dated. Filed by the orchestrator (Fable).*
