Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions reachability-lab/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
# that must never enter the production build, CI, `--workspace` clippy, or add
# holdout policy to the CLI/cockpit. Mirrors the ADR-0010 isolation precedent.
#
# Scope of this crate right now (ADR-0032 first slice): song-mode holdout only —
# a fail-closed, single-authority boundary over a bound LoadedCorpus. File and
# fragment modes, and any measurement axes, are separate later slices.
# Scope of this crate (ADR-0032): song-mode and source-file-mode holdout — a
# fail-closed, single-authority boundary over a bound LoadedCorpus. Fragment mode
# and any measurement axes are separate later slices.

[package]
name = "griff-reachability-lab"
Expand Down
27 changes: 18 additions & 9 deletions reachability-lab/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ novelty references, and gesture stats. So a holdout decision can only be made

## Scope (ADR-0032 first slice)

**Song mode only**, fail-closed, over a single-authority `LoadedCorpus`:
**Song and source-file modes**, fail-closed, over a single-authority
`LoadedCorpus`:

```rust
prepare_corpus_for_mode(corpus: LoadedCorpus, mode: CorpusMode, target: &TargetIdentity)
Expand All @@ -25,8 +26,15 @@ prepare_corpus_for_mode(corpus: LoadedCorpus, mode: CorpusMode, target: &TargetI
- **`NoCorpus`** → `Ok(None)` — a genuinely corpus-free run.
- **`LeakyDiagnostic`** → `Ok(Some(_))` — a corpus supplied deliberately
**unfiltered**, named so it can never be mistaken for a holdout.
- **`HoldoutTargetSong`** → bind → preflight → require target `song_id` →
- **`HoldoutTargetSong`** → bind → song preflight → require target `song_id` →
exclude every representation of that song → compile the survivors.
- **`HoldoutTargetSourceFile`** → bind → source-file preflight → require target
`source_sha256` → exclude every chunk cut from that file (by exact `sha256`,
regardless of `bar_range` or track) → compile the survivors. Source-file mode
needs **only** complete hash identity — it does **not** run the song preflight
and does **not** require `song_id`, so a hash-identified but song-uncurated
corpus is a valid file-mode experiment. Its preflight rejects any participating
chunk without `sha256` (no basename fallback).

`LoadedCorpus { manifest, loaded, skipped }` is **one authority**: every loaded
record maps by `ChunkId` to exactly one manifest chunk whose **full** `ChunkMeta`
Expand All @@ -35,20 +43,21 @@ manifest or the loaded set — otherwise the preflight would validate one datase
while the filter executes another (the stale-manifest leak).

A holdout that would exclude nothing is a **refusal**, not a silent success: if
the target `song_id` is carried by no *loaded* chunk — including when its only
source failed to load and sits in `skipped` — the run typed-refuses
(`TargetSongAbsent`) rather than returning the corpus unchanged. Every binding
violation, missing/absent target, and `song_holdout_preflight` refusal is
**typed** (`HoldoutError` / `BindingRefusal`), never a silent pick.
the target is carried by no *loaded* chunk — including when its only source
failed to load and sits in `skipped` — the run typed-refuses (`TargetSongAbsent`
/ `TargetSourceAbsent`) rather than returning the corpus unchanged. Every binding
violation, missing/absent target, and preflight refusal is **typed**
(`HoldoutError` / `BindingRefusal` / `SourceHoldoutRefusal`), never a silent pick.

The zero-leakage guarantee is proven by asserting the held-out material equals
what the keeper alone produces across **all** channels — references, rhythm
templates, and gesture.

## Not in this crate

- File and fragment modes (their `bar_range == None` whole-source overlap
semantics get their own slice).
- Fragment mode (its range-overlap semantics — including the dangerous rule that
`bar_range == None` overlaps every range in the same source — get their own
slice, built over this source-file identity path).
- Any measurement / eligibility / projection axis.
- Curation, production wiring, generation or scoring changes.

Expand Down
Loading
Loading