Freeze *.rsbank as binary via .gitattributes; add a truncated additive_forward fixture proving the exact-size proof beats TooNew; enumerate the fixture dir to catch orphaned files; make fixture-size checks fatal instead of just logged; pin fixture version asserts as literals, not build-relative.
Union of two parallel tracks. Both action rows, both menu rows, both link
edges survive; the two package CLAUDE.md files now describe the post-merge
reality rather than either side's pre-merge scope.
Delegates the refuse-gate to ledgerDegraded(), lifts its console message into a
pure testable fold, fixes stale doc line citations and an inaccurate outcome-enum
comment, and splits the rename counter into collision-vs-sanitize.
Clamps insertSuffix's underflow, floors uniqueEntryName's validity guard, suppresses
the redundant overwrite confirm via a picker out-param, adds a PayloadBuffer
high-water mark, and corrects stale CLAUDE.md/CMake claims.
Four collisions answered explicitly: ids reminted, names never overwritten,
content deduped before the write, bank name auto-suffixed. Degraded ledger
refuses before the picker.
Pure planner classifies missing/unreadable/unrepresentable and repairs transport
names; the verb digests, streams and commits atomically over a const session.
Cap readRange's allocation and reject size_t overflow instead of truncating;
re-append .rsbank when the export picker omits it; add cafe coverage for
writeFileExclusive and writeLandedFile; loop write() on EINTR.
Enum comment claimed package-id lookup that no persisted field supports; reworded
to the real distinction. Trimmed CLAUDE.md-duplicated test comments and the header.
Both pickers now ride GetUserFileName (mode 0/1); the "no save picker" premise was false.
Landing uses O_EXCL so the create is the existence check, not a TOCTOU pair.
An additively-tagged newer package that fails to parse now reports TooNew (with
writer semver) instead of unactionable Malformed. Format layer also refuses encoding
a zero-length entry, honoring the shell's appendPayload contract; both test-covered.
Reject NUL/control bytes and Windows-hostile names in entry names, relax
the over-broad ".." substring ban to component-only, close the
trailing-garbage gap on empty manifests, and relocate the package
CMake subdirectory to its ladder home.
Two-integer ladder (formatVersion/minReaderVersion), bare-name-only entries
validated on encode and decode, prefix decode that proves exact file size
without ever reading a payload.
Replace the self-comparing render-window loop with a genuinely discriminating
floor-vs-exact check; correct two stale claims; mark the Auto/Manual floor-parity
premise as unverified; drop the STARTPOS/ENDPOS comment's circular justification.
The millisecond floor lives in the custom-bounds field, not the engine, so
RENDER_BOUNDSFLAG=2 is now the only bounds mode: the two-position type, the
console verdict and the STARTPOS/ENDPOS drift probe all go. capture.cpp 697 -> 622.
Grid-ness of an edge was a proxy for "no floor could explain this count," not
the test itself — equal remainders on both edges cancel under a full floor. Now
checks all three floored models directly and corrects the SHORT/LONG
floor-signature docs.
Verdict can no longer print a false EXACT on an on-grid end, no longer names a
bounds channel a content-derived render never consulted, and the grid-align doc
premise is corrected without implementing it.
Corrects a false comment example, fixes two tests that couldn't detect their
own regressions, adds two more read-back checkpoints around Main_OnCommand so
a drift report self-locates, guards a spurious zero-vs-zero coincidence match,
and softens two sentences that overclaimed cause or defect.
No truncation exists on our side of that boundary, so the read-back is the
only evidence available for whether REAPER kept the window — and it fires on
every tail mode, where only None was ever judged.
The dedup path claimed it directly, so a key could be answered Ok pointing at an entry a failed persist never wrote. Write-back is now guarded and three-valued, and landing one request split out of the scan pass.
SetProjExtState's return covers the whole extname, so it never saw one key. The persist verdict now reaches the report, and a throw mid-write no longer claims the landing left nothing behind.
Splits Ignore into unreadable vs not-a-request and counts every verdict; the report prints only when the pass answered nobody, so its absence proves the action never ran.
The one-frame bound is not provable for a per-edge renderer; the test now shows where it breaks. Refused renders move out of the bank instead of being deleted, so the DAW experiment has something to read.
Rewords Cleared/Unanswered/ForeignRequest to name only observed facts and every live hypothesis instead of picking a winner; adds a guarded answeredOutcome accessor against a future unhandled BakeAnswerKind; folds an unreachable BakeScanKey/Context test state; fixes generation-stamp timing.
A no-answer stays a failure; it now says whether the extension never ran the landing, answered a stale generation, spoke a wire this build cannot read, cleared the request, or refused it.
The tolerance is unchanged and now derived, not assumed: frameCountFor lands in {floor(L), ceil(L)}, so a non-frame-aligned window can never miss by more than a frame. Naming the source is what tells a self-bounding render from a short one.
Corrected the Render-dialog source name the refusal's evidence depends on, added a by-ear content check and a file-size channel proxy, and stopped two comments from overclaiming.
Guards params_payload.cpp's filter-tail seconds and both keyTrack sites against NaN; pins Voice::start's Trigger-span formula against trigger_seam; retires unused shortestDivisionAtLeast.
Loosens the exact-bounds gate against REAPER's edge rounding; deletes the bytes a BoundsMismatch refusal writes, per prune_fs's self-cleanup carve-out.