feat(reachability-lab): song-mode holdout filtering boundary (ADR-0032 impl) - #168
Conversation
Isolated offline Reachability Lab (ADR-0032 / ADR-0010 isolation precedent): the holdout-filtering boundary over a bound LoadedCorpus, before corpus_material. Excluded from the workspace; no holdout policy in production CLI/cockpit. Types + a todo!() prepare_corpus_for_mode, driven by 13 failing tests: - mode distinctions: NoCorpus -> None; LeakyDiagnostic -> Some(all); the two are distinct experiments; - fail-closed refusals propagate the existing SongHoldoutRefusal set — uncurated, unidentified (no sha256), manifest disagreement, inconsistent sha256->SongId — plus MissingTargetSongId; - single-authority binding refuses provenance mismatch (the stale-manifest leak), a loaded record absent from the manifest, and a duplicate loaded id; - exclusion + zero leakage: a curated corpus excludes every source representation of the target song, and the material equals what the keeper alone produces across references, rhythm templates, and gesture — with the excluded song's gesture proven not to survive; - filtering is deterministic. Song mode only; file/fragment modes and measurement axes are separate slices. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012T7SRMiXmZe5v1imtrKMPi
Implement prepare_corpus_for_mode over a single-authority LoadedCorpus: - NoCorpus -> Ok(None); LeakyDiagnostic -> Ok(Some(corpus_material(all))); - HoldoutTargetSong -> check_binding -> song_holdout_preflight -> require target song_id -> exclude every LoadedChunk carrying it -> compile the survivors. Provenance exclusion is primary and precedes material construction. - check_binding enforces the single-authority invariant (ChunkId maps to one agreeing manifest chunk; no duplicate loaded id), closing the stale-manifest leak with typed BindingRefusals. 13/13 tests green; clippy (all=deny, pedantic=warn) and rustfmt clean. README documents the song-only scope and the isolation posture. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012T7SRMiXmZe5v1imtrKMPi
📝 WalkthroughWalkthroughAdds an isolated, non-publishable ChangesReachability Lab holdout boundary
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant prepare_corpus_for_mode
participant check_binding
participant song_holdout_preflight
participant corpus_material
Caller->>prepare_corpus_for_mode: Submit LoadedCorpus and target
prepare_corpus_for_mode->>check_binding: Validate manifest and loaded chunks
check_binding-->>prepare_corpus_for_mode: Return binding result
prepare_corpus_for_mode->>song_holdout_preflight: Validate song-mode sources
song_holdout_preflight-->>prepare_corpus_for_mode: Return preflight result
prepare_corpus_for_mode->>corpus_material: Compile filtered survivor chunks
corpus_material-->>Caller: Return CorpusMaterial or HoldoutError
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5b4f9d0a96
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@reachability-lab/src/lib.rs`:
- Around line 131-152: Update check_binding to detect duplicate ChunkId values
while constructing by_id from corpus.manifest.chunks, recording the appropriate
binding refusal instead of silently overwriting entries. Preserve the existing
loaded-duplicate and provenance checks, and ensure duplicate manifest IDs cause
validation to fail rather than selecting one manifest entry.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 4bebd189-c918-4981-afc7-724e0eb43566
⛔ Files ignored due to path filters (1)
reachability-lab/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (4)
Cargo.tomlreachability-lab/Cargo.tomlreachability-lab/README.mdreachability-lab/src/lib.rs
Second RED→GREEN pair closing two ADR-0032 contract gaps. Tests-only; the crate now fails to compile (the referenced HoldoutError::TargetSongAbsent and BindingRefusal::DuplicateManifest variants land in GREEN). Target must actually be held out: - a target song no loaded chunk carries must refuse (not return the whole corpus as a "successful" holdout); - a target present in the manifest but only via a skipped/unloaded record must refuse (an import failure must not silently become the holdout); - a successful holdout must have excluded at least one chunk. Single authority — full metadata, no ambiguous manifest: - a duplicate ChunkId in manifest.chunks must refuse; - matching song_id/sha256 but differing bar_range must refuse; - matching source identity but differing gesture metadata must refuse. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012T7SRMiXmZe5v1imtrKMPi
Close the two contract gaps: 1. A holdout that excludes nothing now refuses. HoldoutTargetSong partitions the loaded records by the target song_id and typed-refuses (HoldoutError::TargetSongAbsent) when zero loaded chunks carry it — so a nonexistent target, or a target whose only source failed to load (skipped), can no longer be relabelled a valid holdout. 2. check_binding now enforces the single-authority invariant properly: duplicate ChunkIds in manifest.chunks are collected as BindingRefusal::DuplicateManifest (not silently overwritten), and a loaded record must match its manifest entry on the COMPLETE ChunkMeta (PartialEq) — bar_range, track_index, gesture, and every other material-defining field, not just song_id + sha256. 19/19 tests green; clippy (all=deny, pedantic=warn) and rustfmt clean. README error semantics updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012T7SRMiXmZe5v1imtrKMPi
REQUEST CHANGES addressed — second RED→GREEN pair (head
|
What
The ADR-0032 implementation slice (authorized after #167): the holdout-filtering boundary over a bound
LoadedCorpus, in a new isolatedreachability-lab/crate. Two RED→GREEN pairs. Song mode only.Excluded from the workspace (ADR-0010/0032 isolation) — production build, CI,
--workspaceclippy, CLI, and cockpit acquire no holdout policy.Boundary
NoCorpus→Ok(None)(genuinely corpus-free);LeakyDiagnostic→Ok(Some(_))(deliberately unfiltered, named);HoldoutTargetSong→ bind → preflight → require targetsong_id→ partition & refuse if nothing is excluded → compile survivors.check_bindingmaps every loaded record byChunkIdto one manifest chunk whose completeChunkMetamatches (not justsong_id/sha256), collects duplicate manifest ids, and rejects duplicate loaded ids — closing the stale-manifest leak with typedBindingRefusals.TargetSongAbsent) rather than returning the corpus unchanged. Every failure is a typedHoldoutError, never a silent pick.Tests (RED → GREEN, 19)
NoCorpusNone vsLeakyDiagnosticSome(all); distinct);SongHoldoutRefusalset (uncurated, unidentified/no-sha256, manifest disagreement, inconsistent-sha256) +MissingTargetSongId;bar_range, differinggestureunder matching source identity);Verification
cargo test -p …reachability-lab→ 19/19 green;clippy --all-targets(all=deny, pedantic=warn) andrustfmtclean. Isolated crate → not in CI (ADR-0010 precedent) — verified locally under nix.Out of scope
File/fragment modes (separate slices), measurement/eligibility/projection axes, curation, production wiring, generation/scoring changes.
🤖 Generated with Claude Code
https://claude.ai/code/session_012T7SRMiXmZe5v1imtrKMPi