Ψ-W2-T2 remediation: atomic temp+rename collapse write, honest unknown-channel fallback, [verify — DAW] markers, corrected+filed bake-collapse deferral, observable collapse message, quiet-NaN test

This commit is contained in:
2026-08-01 22:08:39 -04:00
parent 4fa3c1dd15
commit 8b191e3379
12 changed files with 151 additions and 31 deletions
+4 -3
View File
@@ -19,8 +19,9 @@ Per-module detail — what each file owns, its invariants — lives in the twent
paths anywhere in the index.
- **Material:** must handle full-mix/stem bounces, chops/one-shots, and
single-cycle/wavetable grabs equally. That means exact sample-accurate bounds,
explicit tail control, channel-count preservation, and loop/zero-crossing
handling all matter from day one.
explicit tail control, correct channel handling (the exact-bounds channel rule
under Precision invariants), and loop/zero-crossing handling all matter from day
one.
## One-time submodule setup
@@ -206,7 +207,7 @@ Plan-style docs live under `docs/`:
- **Null test:** a dry offline capture of a range, re-inserted at its source position, nulls to silence against the source — the tool's trust anchor. Ship as a verification action. (Verification action cut per `docs/product/provenance.md` — manual verification only.)
- **Bit-identical repeats:** identical offline capture requests produce identical files.
- **Non-destructive:** capture never mutates source items or tracks; the realtime backend's temp track is created and removed cleanly, and source routing is restored.
- **Exact bounds:** no rounding of the requested range; no added silence unless a tail is explicitly requested; **no lossy channel fold** — summing or averaging differing channels is forbidden. The one permitted collapse is lossless: a new capture whose channels are bit-identical per frame (float bit patterns, never an epsilon) lands as a 1-channel file, with `Sample::channelCount` and the file's `fmt` written together so the two can never disagree. Frame count, sample rate and bit depth are untouched by it. Never retroactive — existing entries and files are never rewritten — and ingest is excluded, because an imported file is the user's bytes, not our capture. The superseded wording ("channel count preserved") was already untrue in the other direction: a mono source renders at `RENDER_CHANNELS = 2`.
- **Exact bounds:** no rounding of the requested range; no added silence unless a tail is explicitly requested; **no lossy channel fold** — summing or averaging differing channels is forbidden. The one permitted collapse is lossless: a new capture whose channels are bit-identical per frame (float bit patterns, never an epsilon) lands as a 1-channel file, with `Sample::channelCount` and the file's `fmt` written together so the two can never disagree. Frame count, sample rate and bit depth are untouched by it. Never retroactive — existing entries and files are never rewritten — and ingest is excluded, because an imported file is the user's bytes, not our capture. The superseded wording ("channel count preserved") was already untrue in the other direction: a mono source renders at `RENDER_CHANNELS = 2`. `[verify — DAW]` "lossless" here is a file-bytes property; whether REAPER sums a 1-channel item on a stereo track at the same unity gain as a dual-mono 2-channel item (pan law, mono spread) — the null test's actual playback-chain property — is unconfirmed.
- **Relative paths only** in the persisted `BankIndex`.
- **Capture FX scope:** two scopes only — item = item/take FX only; track = item FX + the selected track's own track FX. There is no master scope (to capture the master, render a track instead). For both scopes, the out-of-scope chain (ancestors + master track, plus the item's own track for item scope) has its FX, gain, and pan/width/pan-law/mode neutralized to unity — the master track is bypassed as out-of-scope chain, not captured as a scope. Range (time selection or razor) is orthogonal.