// Standalone tests for reasampler::sample_usage — no REAPER, no framework.
// The pS-usage seam: instances publish held captures; the extension folds live
// instances' holds into the prune's `referenced` set. Tested hard here because this is
// the prune-protection guarantee — a SAFETY property: every failure, ambiguity, or
// uncertainty must FAIL-SAFE toward PROTECT (over-protection acceptable;
// under-protection = deleting a maybe-used file is a data-loss bug).
//
// Covers: wire round-trip (nonce + unioned flag, empty / adversarial bytes),
// malformed -> nullopt, the publish plan's branches (fresh / clean replace + skip /
// sibling union with the sticky poison flag / cross-track re-mint / undecodable remint),
// the SAME-TRACK SIBLING repro (the review's 🔴#1 — byte-identical wire convergence
// must never let one sibling clean-replace the other's still-held paths, including one
// write later via the poison flag), the liveness fold (live, dead-track, empty-guid
// fallback, de-dup), the ZERO-IDENTIFIED protect-all net (🔴#2 — an identity-matcher
// failure must protect everything, not nothing), the UNREADABLE-record abort
// (foldUsageRecords.abortPrune — prune halts, deletes nothing), the UNDECODABLE-EXISTING
// REMINT (corrupt key left in place — prune-side abort keeps firing while sibling holds
// unprotected), the ABORT→PROTECT-ALL belt-and-braces (foldUsageRecords.heldPaths is
// the full protect-all set even when abortPrune is set), the TRUNCATED-WALK→PROTECT-ALL
// proof (FX walk misses a nested instance → anyLive=false → usageHeldPaths protects
// every record — the pure side of the depth-cap + depth-exhaustion-is-container fix),
// the pure identity matcher (UID hex / module filename base / display name, beta
// over-protect), and the composed pruneOrphans exclusion proof.

#include "../src/core/wire/sample_usage.h"

#include <cstdio>
#include <optional>
#include <string>
#include <unordered_set>
#include <vector>

#include "../src/core/reclaim/prune_reconcile.h"  // mergeReferenced + pruneOrphans (composed proof)

using namespace reasampler;
using namespace reasampler::reclaim;
using namespace reasampler::wire;

static int g_fail = 0;
#define CHECK(cond) do { if(!(cond)) { \
    std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0)

namespace {

UsageRecord makeRecord(const std::string& trackGuid, const std::string& nonce,
                       std::vector<UsageHold> holds, bool unioned = false) {
    UsageRecord r;
    r.trackGuid = trackGuid;
    r.ownerNonce = nonce;
    r.unioned = unioned;
    r.holds = std::move(holds);
    return r;
}

// One enumerated key's read result. Keys are synthesized per index because the fold
// only uses them to name an offender; a nullopt record is the unreadable case.
DecodedUsage decodedOf(const std::string& key, std::optional<UsageRecord> rec) {
    return DecodedUsage{key, std::move(rec)};
}

bool holdsContainPath(const std::vector<UsageHold>& holds, const std::string& path) {
    for (const UsageHold& h : holds)
        if (h.relativePath == path) return true;
    return false;
}

}  // namespace

// --- wire round-trip ----------------------------------------------------------

static void testRoundTrip() {
    const UsageRecord rec = makeRecord(
        "{12345678-1234-1234-1234-1234567890AB}", "aabbccdd00112233",
        {UsageHold{"cap-1700-kick", "reasampler_bank/kick.wav"},
         UsageHold{"cap-1701-snare", "reasampler_bank/snare.wav"}},
        /*unioned=*/true);
    const std::string wire = encodeUsageRecord(rec);
    auto back = decodeUsageRecord(wire);
    CHECK(back.has_value());
    CHECK(*back == rec);
    CHECK(back->unioned);
    CHECK(encodeUsageRecord(*back) == wire);  // deterministic re-encode
}

static void testRoundTripEmptyHoldsAndEmptyGuid() {
    // An empty-holds record is LEGAL (an instance releasing everything it held), and an
    // empty trackGuid is legal (no track context at publish -> any-instance fallback).
    const UsageRecord rec = makeRecord("", "", {});
    auto back = decodeUsageRecord(encodeUsageRecord(rec));
    CHECK(back.has_value());
    CHECK(back->trackGuid.empty());
    CHECK(back->ownerNonce.empty());
    CHECK(!back->unioned);
    CHECK(back->holds.empty());
}

static void testRoundTripAdversarialBytes() {
    // Ids/paths carrying the wire's own metacharacters must survive whole (the whole
    // point of length-prefixing): ':' delimiters, digits, the magic tag itself.
    const UsageRecord rec = makeRecord(
        "12:34:guid-with-colons", "1:0",
        {UsageHold{"rsusage1-lookalike", "path with spaces/and:colons/7:x.wav"}});
    auto back = decodeUsageRecord(encodeUsageRecord(rec));
    CHECK(back.has_value());
    CHECK(*back == rec);
}

static void testDecodeMalformed() {
    CHECK(!decodeUsageRecord("").has_value());
    CHECK(!decodeUsageRecord("garbage").has_value());
    CHECK(!decodeUsageRecord("rsusage1").has_value());          // truncated after magic
    CHECK(!decodeUsageRecord("rsusage2" "0:0:1:01:0").has_value());  // wrong magic
    // A non-"0"/"1" unioned field is corruption -> reject whole. Hand-built wire:
    // magic + trackGuid "" + nonce "" + unioned "2" + count 0.
    CHECK(!decodeUsageRecord("rsusage1" "0:" "0:" "1:2" "1:0").has_value());
    // Truncated mid-holds: claims 2 holds, carries 1. The count field for one hold is
    // the "1:1" that FOLLOWS the unioned field "1:0" (nonce chosen digit-free so the
    // needle is unambiguous).
    UsageRecord one = makeRecord("{G}", "nonce", {UsageHold{"a", "p.wav"}});
    std::string wire = encodeUsageRecord(one);
    const std::string needle = "1:0" "1:1";  // unioned=0 then count=1
    const std::size_t pos = wire.find(needle);
    CHECK(pos != std::string::npos);
    wire[pos + 5] = '2';  // count "1:1" -> "1:2"
    CHECK(!decodeUsageRecord(wire).has_value());
    // Trailing garbage after a complete record -> reject whole.
    CHECK(!decodeUsageRecord(encodeUsageRecord(one) + "x").has_value());
}

// --- publish plan --------------------------------------------------------------

static void testPlanFreshKey() {
    const UsageRecord mine = makeRecord("{T1}", "NA", {UsageHold{"a", "p.wav"}});
    const UsagePublishPlan plan = planUsagePublish(std::nullopt, mine);
    CHECK(!plan.remint);
    CHECK(!plan.skipWrite);
    auto back = decodeUsageRecord(plan.wire);
    CHECK(back.has_value());
    CHECK(back->ownerNonce == "NA");
    CHECK(!back->unioned);  // sole known writer -> un-poisoned
}

static void testPlanCleanReplaceAndSkip() {
    // The key holds this incarnation's own un-poisoned write (nonce match, !unioned):
    // the sole-writer path. Clean replace; released holds drop.
    const UsageRecord prev = makeRecord("{T1}", "NA", {UsageHold{"a", "pa.wav"},
                                                       UsageHold{"b", "pb.wav"}});
    const std::string prevWire = encodeUsageRecord(prev);
    const UsageRecord mine = makeRecord("{T1}", "NA", {UsageHold{"a", "pa.wav"}});
    const UsagePublishPlan plan = planUsagePublish(prevWire, mine);
    CHECK(!plan.remint);
    CHECK(!plan.skipWrite);
    auto back = decodeUsageRecord(plan.wire);
    CHECK(back.has_value());
    CHECK(back->holds.size() == 1);  // 'b' genuinely released — NOT unioned back in
    CHECK(!back->unioned);

    // Unchanged play-set -> byte-identical write -> skip (idle reload tick).
    const UsagePublishPlan idle = planUsagePublish(prevWire, prev);
    CHECK(idle.skipWrite);
    CHECK(!idle.remint);
}

// The review's 🔴#1 repro. Two same-track FX copies share a key and converge on
// byte-identical hold sets; the OLD wire-equality discriminator let sibling A
// clean-replace over B's still-held path. With the in-wire per-lifetime nonce +
// sticky unioned poison, every same-track collision unions and NO write of A's can
// ever drop B's holds — including A's SECOND write after it re-owns the key.
static void testSiblingCollisionNeverDropsHolds() {
    // A (lifetime nonce NA) publishes {pa}.
    const UsageRecord aFirst = makeRecord("{T1}", "NA", {UsageHold{"a", "pa.wav"}});
    const UsagePublishPlan planA1 = planUsagePublish(std::nullopt, aFirst);
    CHECK(!planA1.remint && !planA1.skipWrite);

    // B (lifetime nonce NB, same track, SAME hold set — the byte-identical
    // convergence) publishes {pa}: foreign nonce, same track -> UNION, and the
    // false->true poison flip is WRITTEN (never skipped), marking the key multi-writer.
    const UsageRecord bSame = makeRecord("{T1}", "NB", {UsageHold{"a", "pa.wav"}});
    const UsagePublishPlan planB = planUsagePublish(planA1.wire, bSame);
    CHECK(!planB.remint);
    CHECK(!planB.skipWrite);  // the poison flip must land in ext-state
    auto bBack = decodeUsageRecord(planB.wire);
    CHECK(bBack.has_value());
    CHECK(bBack->unioned);
    CHECK(holdsContainPath(bBack->holds, "pa.wav"));

    // A changes its selection to {pc} (releases pa from ITS play-set — but B still
    // plays pa). Foreign nonce (NB) -> union: pa is RETAINED. Pre-fix this was the
    // clean-replace that dropped B's hold -> prune could delete B's playing file.
    const UsageRecord aSecond = makeRecord("{T1}", "NA", {UsageHold{"c", "pc.wav"}});
    const UsagePublishPlan planA2 = planUsagePublish(planB.wire, aSecond);
    CHECK(!planA2.remint);
    auto a2Back = decodeUsageRecord(planA2.wire);
    CHECK(a2Back.has_value());
    CHECK(holdsContainPath(a2Back->holds, "pa.wav"));  // B's hold survives A's write
    CHECK(holdsContainPath(a2Back->holds, "pc.wav"));
    CHECK(a2Back->unioned);

    // A writes AGAIN (selection {pd}) — now the key carries A's OWN nonce (NA). A bare
    // nonce discriminator would clean-replace here and drop pa one step late; the
    // sticky unioned poison forces union forever. pa STILL survives.
    const UsageRecord aThird = makeRecord("{T1}", "NA", {UsageHold{"d", "pd.wav"}});
    const UsagePublishPlan planA3 = planUsagePublish(planA2.wire, aThird);
    CHECK(!planA3.remint);
    auto a3Back = decodeUsageRecord(planA3.wire);
    CHECK(a3Back.has_value());
    CHECK(holdsContainPath(a3Back->holds, "pa.wav"));  // the poison-flag guarantee
    CHECK(a3Back->unioned);
}

static void testPlanUnionSkipOnlyWhenAlreadyPoisoned() {
    // Union over an ALREADY-unioned record that adds no holds -> skip (the write would
    // flip only the nonce — redundant churn; the protection is already in place).
    const UsageRecord poisoned = makeRecord("{T1}", "NA", {UsageHold{"a", "pa.wav"}},
                                            /*unioned=*/true);
    const UsageRecord mineSubset = makeRecord("{T1}", "NB", {UsageHold{"a", "pa.wav"}});
    const UsagePublishPlan plan =
        planUsagePublish(encodeUsageRecord(poisoned), mineSubset);
    CHECK(!plan.remint);
    CHECK(plan.skipWrite);
    // But a union that ADDS a hold must write even when already poisoned.
    const UsageRecord mineNew = makeRecord("{T1}", "NB", {UsageHold{"b", "pb.wav"}});
    const UsagePublishPlan plan2 =
        planUsagePublish(encodeUsageRecord(poisoned), mineNew);
    CHECK(!plan2.skipWrite);
    auto back = decodeUsageRecord(plan2.wire);
    CHECK(back.has_value());
    CHECK(back->holds.size() == 2);
    CHECK(back->unioned);
}

static void testPlanEmptyNonceNeverClaimsOwnership() {
    // A record written with an empty nonce (defensive: publisher failed to mint) can
    // never be claimed via empty==empty — the same-track path must UNION, not replace.
    const UsageRecord theirs = makeRecord("{T1}", "", {UsageHold{"a", "pa.wav"}});
    const UsageRecord mine = makeRecord("{T1}", "", {UsageHold{"b", "pb.wav"}});
    const UsagePublishPlan plan = planUsagePublish(encodeUsageRecord(theirs), mine);
    CHECK(!plan.remint);
    auto back = decodeUsageRecord(plan.wire);
    CHECK(back.has_value());
    CHECK(holdsContainPath(back->holds, "pa.wav"));  // never dropped
    CHECK(back->unioned);
}

static void testPlanCrossTrackRemint() {
    // The key holds a foreign record from ANOTHER track: this state was cloned there
    // (FX copy / track duplication) — take a fresh identity, leave theirs untouched.
    const UsageRecord theirs = makeRecord("{T1}", "NA", {UsageHold{"a", "pa.wav"}});
    const UsageRecord mine = makeRecord("{T2}", "NB", {UsageHold{"a", "pa.wav"}});
    const UsagePublishPlan plan = planUsagePublish(encodeUsageRecord(theirs), mine);
    CHECK(plan.remint);
    auto back = decodeUsageRecord(plan.wire);
    CHECK(back.has_value());
    CHECK(!back->unioned);  // written under the NEW key — fresh, un-poisoned
}

static void testPlanOwnRecordAfterTrackMove() {
    // My own un-poisoned record, but the instance moved tracks THIS lifetime (nonce
    // matches, track differs): still mine — clean replace with the new track guid, NOT
    // a remint (the key stays stable; no record proliferation on a track move).
    const UsageRecord prev = makeRecord("{T1}", "NA", {UsageHold{"a", "pa.wav"}});
    const UsageRecord mine = makeRecord("{T2}", "NA", {UsageHold{"a", "pa.wav"}});
    const UsagePublishPlan plan = planUsagePublish(encodeUsageRecord(prev), mine);
    CHECK(!plan.remint);
    auto back = decodeUsageRecord(plan.wire);
    CHECK(back.has_value());
    CHECK(back->trackGuid == "{T2}");
}

static void testPlanUndecodableExistingRemints() {
    // An undecodable existing value under MY key must REMINT (not overwrite). Overwriting
    // would clear the prune-side abort while a same-key sibling B's holds are unprotected
    // until B republishes. Leaving the corrupt key in place keeps the prune-side abort
    // (foldUsageRecords.abortPrune) firing so no delete-ward window opens.
    const UsageRecord mine = makeRecord("{T1}", "NA", {UsageHold{"a", "pa.wav"}});
    const UsagePublishPlan plan = planUsagePublish(std::string("corrupt"), mine);
    CHECK(plan.remint);         // fresh key — leave the corrupt key untouched
    CHECK(!plan.skipWrite);
    // wire carries mine (to be written under the NEW key by the caller)
    auto back = decodeUsageRecord(plan.wire);
    CHECK(back.has_value());
    CHECK(back->holds.size() == 1);
    CHECK(!back->unioned);  // fresh key, sole writer — un-poisoned
}

// --- liveness fold ---------------------------------------------------------------

static void testHeldPathsLiveness() {
    const std::vector<UsageRecord> records = {
        makeRecord("{LIVE}", "N1", {UsageHold{"a", "pa.wav"}}),
        makeRecord("{DEAD}", "N2", {UsageHold{"b", "pb.wav"}}),  // deleted track
        makeRecord("", "N3", {UsageHold{"c", "pc.wav"}}),        // no track context
    };
    const std::unordered_set<std::string> live = {"{LIVE}"};

    // Live-track record counts; dead-track record is EXCLUDED (stale-record cleanup —
    // possible ONLY because at least one instance was positively identified, so the
    // matcher demonstrably works in this project); empty-guid record counts while ANY
    // instance lives (fail-safe fallback).
    const std::vector<std::string> withAny = usageHeldPaths(records, live, true);
    CHECK(withAny.size() == 2);
    CHECK(withAny[0] == "pa.wav");
    CHECK(withAny[1] == "pc.wav");
}

// The review's 🔴#2 repro: records exist but ZERO instances were identified live
// (either every instance was genuinely deleted, or — indistinguishable — the identity
// matcher failed on every FX). The old fold dropped every record -> all held captures
// became prunable. The fail-safe net protects ALL records' paths instead.
static void testZeroIdentifiedProtectsAll() {
    const std::vector<UsageRecord> records = {
        makeRecord("{T1}", "N1", {UsageHold{"a", "pa.wav"}}),
        makeRecord("{T2}", "N2", {UsageHold{"b", "pb.wav"}}),
        makeRecord("", "N3", {UsageHold{"c", "pc.wav"}}),
    };
    const std::vector<std::string> all =
        usageHeldPaths(records, std::unordered_set<std::string>{}, false);
    CHECK(all.size() == 3);  // EVERY path protected — never zero
    CHECK(all[0] == "pa.wav");
    CHECK(all[1] == "pb.wav");
    CHECK(all[2] == "pc.wav");

    // No records at all -> nothing to protect (the common no-instances case).
    CHECK(usageHeldPaths({}, std::unordered_set<std::string>{}, false).empty());
}

static void testHeldPathsDedupAndEmptyPathSkip() {
    const std::vector<UsageRecord> records = {
        makeRecord("{T}", "N1", {UsageHold{"a", "shared.wav"}, UsageHold{"x", ""}}),
        makeRecord("{T}", "N2", {UsageHold{"b", "shared.wav"}, UsageHold{"c", "own.wav"}}),
    };
    const std::unordered_set<std::string> live = {"{T}"};
    const std::vector<std::string> paths = usageHeldPaths(records, live, true);
    CHECK(paths.size() == 2);  // shared.wav de-duped across records; empty path skipped
    CHECK(paths[0] == "shared.wav");
    CHECK(paths[1] == "own.wav");
}

// A take-FX-hosted instance: the shell attributes it to the ITEM'S OWNING TRACK (the
// same guid the VST-side getReaperParent(1) publishes), so at the pure layer its record
// folds exactly like a track-FX one. This is the pure half of the take-FX guarantee;
// the enumeration itself (TakeFX_* walk, fx_ident + original_name) is shell code.
static void testTakeFxAttributedRecordIsProtected() {
    const std::vector<UsageRecord> records = {
        makeRecord("{ITEM-TRACK}", "N1", {UsageHold{"a", "take-held.wav"}}),
    };
    const std::unordered_set<std::string> live = {"{ITEM-TRACK}"};  // set via item scan
    const std::vector<std::string> paths = usageHeldPaths(records, live, true);
    CHECK(paths.size() == 1);
    CHECK(paths[0] == "take-held.wav");
}

// --- the unreadable-record abort (foldUsageRecords) --------------------------------
// A present-but-unreadable/undecodable rsusage_* record must ABORT the prune (halt,
// delete nothing) — silently reduced protection is the delete direction.

static void testUnreadableRecordAbortsPrune() {
    std::vector<DecodedUsage> decoded;
    decoded.push_back(decodedOf("rsusage_1", makeRecord("{T1}", "N1", {UsageHold{"a", "pa.wav"}})));
    decoded.push_back(decodedOf("rsusage_BAD", std::nullopt));  // one unreadable among readable
    const UsageFoldResult fold =
        foldUsageRecords(decoded, std::unordered_set<std::string>{"{T1}"}, true);
    CHECK(fold.abortPrune);
    // The offender is named so the action can tell the operator which key to recover.
    CHECK(fold.offendingKeys.size() == 1);
    CHECK(fold.offendingKeys[0] == "rsusage_BAD");
    // Attribution is exactly what an unreadable record destroys — no record may be
    // reported as counted while one is unreadable.
    CHECK(fold.counted.empty());

    // All readable -> no abort, normal liveness fold, and the live record is attributed.
    std::vector<DecodedUsage> ok;
    ok.push_back(decodedOf("rsusage_1", makeRecord("{T1}", "N1", {UsageHold{"a", "pa.wav"}})));
    const UsageFoldResult okFold =
        foldUsageRecords(ok, std::unordered_set<std::string>{"{T1}"}, true);
    CHECK(!okFold.abortPrune);
    CHECK(okFold.offendingKeys.empty());
    CHECK(okFold.heldPaths.size() == 1);
    CHECK(okFold.heldPaths[0] == "pa.wav");
    CHECK(okFold.counted.size() == 1);
    CHECK(okFold.counted[0].key == "rsusage_1");

    // Empty input (no records enumerated) -> empty, no abort.
    const UsageFoldResult empty =
        foldUsageRecords({}, std::unordered_set<std::string>{}, false);
    CHECK(!empty.abortPrune);
    CHECK(empty.heldPaths.empty());
    CHECK(empty.counted.empty());

    // Readable records + zero identified -> the protect-all net applies through the
    // fold too (belt and braces with the abort), and every record counts.
    std::vector<DecodedUsage> unmatched;
    unmatched.push_back(decodedOf("rsusage_9", makeRecord("{T9}", "N1", {UsageHold{"a", "pa.wav"}})));
    const UsageFoldResult net =
        foldUsageRecords(unmatched, std::unordered_set<std::string>{}, false);
    CHECK(!net.abortPrune);
    CHECK(net.heldPaths.size() == 1);
    CHECK(net.counted.size() == 1);
}

// A dead-track record must be excluded from `counted` as well as from heldPaths —
// attribution and protection must name the same records or the two consumers drift.
static void testCountedMirrorsHeldPaths() {
    std::vector<DecodedUsage> decoded;
    decoded.push_back(decodedOf("rsusage_LIVE", makeRecord("{LIVE}", "N1", {UsageHold{"a", "pa.wav"}})));
    decoded.push_back(decodedOf("rsusage_DEAD", makeRecord("{DEAD}", "N2", {UsageHold{"b", "pb.wav"}})));
    const UsageFoldResult fold =
        foldUsageRecords(decoded, std::unordered_set<std::string>{"{LIVE}"}, true);
    CHECK(fold.heldPaths.size() == 1);
    CHECK(fold.heldPaths[0] == "pa.wav");
    CHECK(fold.counted.size() == 1);
    CHECK(fold.counted[0].key == "rsusage_LIVE");
}

// --- abort returns the protect-all set (belt-and-braces) ---------------------------
// foldUsageRecords must return heldPaths = EVERY readable record's paths when
// abortPrune is set, so a future caller that forgets to check the flag before using
// heldPaths still gets maximum protection rather than an empty set (which would be
// delete-ward).
static void testAbortFoldReturnsProtectAllSet() {
    // Two readable records + one unreadable (nullopt) in between.
    std::vector<DecodedUsage> decoded;
    decoded.push_back(decodedOf("rsusage_1", makeRecord("{T1}", "N1", {UsageHold{"a", "pa.wav"}})));
    decoded.push_back(decodedOf("rsusage_BAD", std::nullopt));  // triggers abort
    decoded.push_back(decodedOf("rsusage_2", makeRecord("{T2}", "N2", {UsageHold{"b", "pb.wav"}})));

    // Live: only {T1} — so without protect-all, T2's path would be excluded.
    const UsageFoldResult fold =
        foldUsageRecords(decoded, std::unordered_set<std::string>{"{T1}"}, true);
    CHECK(fold.abortPrune);
    // heldPaths must contain BOTH paths (protect-all over all readable records),
    // not just {T1}'s path.
    CHECK(fold.heldPaths.size() == 2);
    bool hasPA = false, hasPB = false;
    for (const std::string& p : fold.heldPaths) {
        if (p == "pa.wav") hasPA = true;
        if (p == "pb.wav") hasPB = true;
    }
    CHECK(hasPA);
    CHECK(hasPB);

    // All nullopt (every key unreadable): abort + empty heldPaths (nothing readable).
    std::vector<DecodedUsage> allNull;
    allNull.push_back(decodedOf("rsusage_BAD", std::nullopt));
    const UsageFoldResult allNullFold =
        foldUsageRecords(allNull, std::unordered_set<std::string>{}, false);
    CHECK(allNullFold.abortPrune);
    CHECK(allNullFold.heldPaths.empty());  // no readable records to protect
}

// --- truncated enumeration → protect-all -------------------------------------------
// The FX walk may truncate at kMaxContainerDepth, leaving a deeply-nested live instance
// missed. At the PURE layer this is indistinguishable from a genuine identity-matcher
// failure: anyInstanceLive stays false while records exist. The protect-all net in
// usageHeldPaths guarantees this resolves toward PROTECT, never toward delete — the same
// test shape as testZeroIdentifiedProtectsAll, stated here explicitly for the truncation
// failure mode.
static void testTruncatedWalkProtectsAll() {
    // Records from two tracks that host instances; the FX walk (shell side) failed to
    // identify ANY instance (e.g. truncated at depth, or a future matcher gap).
    const std::vector<UsageRecord> records = {
        makeRecord("{TRACK-A}", "N1", {UsageHold{"x", "nested-a.wav"}}),
        makeRecord("{TRACK-B}", "N2", {UsageHold{"y", "nested-b.wav"}}),
    };
    // Shell reported anyLive=false (it couldn't identify any instance — truncated walk).
    const std::vector<std::string> paths =
        usageHeldPaths(records, std::unordered_set<std::string>{}, /*anyInstanceLive=*/false);
    // Both paths must be protected — the protect-all net fires.
    CHECK(paths.size() == 2);
    bool hasA = false, hasB = false;
    for (const std::string& p : paths) {
        if (p == "nested-a.wav") hasA = true;
        if (p == "nested-b.wav") hasB = true;
    }
    CHECK(hasA);
    CHECK(hasB);

    // Belt-and-braces: the same scenario through foldUsageRecords also protects all.
    std::vector<DecodedUsage> decoded;
    for (std::size_t i = 0; i < records.size(); ++i)
        decoded.push_back(decodedOf("rsusage_" + std::to_string(i), records[i]));
    const UsageFoldResult fold =
        foldUsageRecords(decoded, std::unordered_set<std::string>{}, false);
    CHECK(!fold.abortPrune);
    CHECK(fold.heldPaths.size() == 2);
}

// --- the identity matcher ----------------------------------------------------------
// The common-case shapes: REAPER's fx_ident carries the .vst3 MODULE PATH (matched by
// the output-name needle "REASAMPLER_9000" — the display name, space-separated, can
// never match it); original_name carries the display name. UID hex matches when the
// rendering embeds it. All substring, case-insensitive.

static void testIdentityMatcher() {
    const std::string uid = "ABCD1234ABCD1234ABCD1234ABCD1234";
    const std::string name = "REASAMPLER 9000";
    const std::string output = "REASAMPLER_9000";

    // The module-path fx_ident shape: ONLY the output-name needle can catch this (the
    // review's 🔴#2b — the display name alone silently failed the common case).
    const std::string modulePath =
        "C:\\Program Files\\Common Files\\VST3\\reasampler_9000.vst3";
    CHECK(identityMatches(modulePath, uid, name, output));
    CHECK(!identityMatches(modulePath, uid, name, ""));  // display name can't match it

    // The display-name shape (original_name / renamed renderings).
    CHECK(identityMatches("VST3: ReaSampler 9000", uid, name, output));

    // The UID-hex shape (case-insensitive).
    CHECK(identityMatches("vst3<abcd1234abcd1234abcd1234abcd1234>", uid, name, output));

    // Beta over-protect (deliberate): stable needles are substrings of beta renderings
    // — a stable extension protects beta instances' holds too (wider set only).
    CHECK(identityMatches("...\\reasampler_9000_beta.vst3", uid, name, output));
    CHECK(identityMatches("ReaSampler 9000 beta", uid, name, output));

    // Non-matches stay non-matches.
    CHECK(!identityMatches("", uid, name, output));
    CHECK(!identityMatches("ReaComp", uid, name, output));
    CHECK(!identityMatches("some_other_sampler.vst3", uid, name, output));
}

// --- the composed prune-protection proof -----------------------------------------
// The definition-of-done property at the pure layer: a capture held by a live instance
// lands in the referenced union, and pruneOrphans can NEVER emit it — even when the
// bank no longer references it (deleted from the bank while the instance kept its ref)
// and it is owned + present (the exact preconditions under which it WOULD be reclaimed).

static void testInstanceHoldMakesPathUnprunable() {
    const std::vector<std::string> present = {"held.wav", "orphan.wav"};
    const std::vector<std::string> owned = {"held.wav", "orphan.wav"};
    const std::vector<std::string> bankRefs = {};  // bank does NOT reference either

    // Without instance usage both are orphans (the pre-pS-usage behavior).
    CHECK(pruneOrphans(present, bankRefs, owned).size() == 2);

    // A live instance holds held.wav -> the union protects it; orphan.wav still reclaims.
    const std::vector<UsageRecord> records = {
        makeRecord("{T}", "N1", {UsageHold{"id-held", "held.wav"}})};
    const std::unordered_set<std::string> live = {"{T}"};
    const std::vector<std::string> referenced =
        mergeReferenced(bankRefs, usageHeldPaths(records, live, true));
    const std::vector<std::string> orphans = pruneOrphans(present, referenced, owned);
    CHECK(orphans.size() == 1);
    CHECK(orphans[0] == "orphan.wav");

    // Zero instances identified anywhere -> the protect-all net keeps held.wav
    // un-prunable THROUGH the composed pipeline too (matcher failure must never
    // resolve toward delete; the accepted residual is that leftover records keep
    // protecting until an instance is identified again).
    const std::vector<std::string> refsNoneIdentified = mergeReferenced(
        bankRefs, usageHeldPaths(records, std::unordered_set<std::string>{}, false));
    const std::vector<std::string> orphansNone =
        pruneOrphans(present, refsNoneIdentified, owned);
    CHECK(orphansNone.size() == 1);
    CHECK(orphansNone[0] == "orphan.wav");

    // Stale-record cleanup still works when the matcher is demonstrably alive: another
    // instance is identified on a different track, the record's own track is gone ->
    // the record no longer counts -> held.wav is reclaimable again.
    const std::vector<std::string> refsAfterDelete = mergeReferenced(
        bankRefs,
        usageHeldPaths(records, std::unordered_set<std::string>{"{OTHER}"}, true));
    CHECK(pruneOrphans(present, refsAfterDelete, owned).size() == 2);
}

static void testMergeReferencedOrderAndDedup() {
    const std::vector<std::string> a = {"p1.wav", "p2.wav"};
    const std::vector<std::string> b = {"p2.wav", "p3.wav", "p1.wav"};
    const std::vector<std::string> merged = mergeReferenced(a, b);
    CHECK(merged.size() == 3);
    CHECK(merged[0] == "p1.wav");
    CHECK(merged[1] == "p2.wav");
    CHECK(merged[2] == "p3.wav");
    CHECK(mergeReferenced({}, {}).empty());
}

int main() {
    testRoundTrip();
    testRoundTripEmptyHoldsAndEmptyGuid();
    testRoundTripAdversarialBytes();
    testDecodeMalformed();
    testPlanFreshKey();
    testPlanCleanReplaceAndSkip();
    testSiblingCollisionNeverDropsHolds();
    testPlanUnionSkipOnlyWhenAlreadyPoisoned();
    testPlanEmptyNonceNeverClaimsOwnership();
    testPlanCrossTrackRemint();
    testPlanOwnRecordAfterTrackMove();
    testPlanUndecodableExistingRemints();
    testHeldPathsLiveness();
    testZeroIdentifiedProtectsAll();
    testHeldPathsDedupAndEmptyPathSkip();
    testTakeFxAttributedRecordIsProtected();
    testUnreadableRecordAbortsPrune();
    testCountedMirrorsHeldPaths();
    testAbortFoldReturnsProtectAllSet();
    testTruncatedWalkProtectsAll();
    testIdentityMatcher();

    testInstanceHoldMakesPathUnprunable();
    testMergeReferencedOrderAndDedup();

    if (g_fail == 0) {
        std::printf("sample_usage_tests: all tests passed\n");
        return 0;
    }
    std::printf("sample_usage_tests: %d FAILURES\n", g_fail);
    return 1;
}
