Fix sampler budget overflow

The `allocateBudget` function in the proportional sampler can allocate more files than the budget allows. When the budget is smaller than the number of non-empty depth buckets, the first-pass floor allocation exceeds the budget and `remaining` goes negative. The function's contract says "budget" and it should mean budget. Source: Learn Session 7, finding `fix-deep-tier-sampling-C2`.

verdict PASSscore 8 / 8findings 4 (0 risk · 1 debt · 3 obs)duration 23mrejection cycles 0shipped May 21, 2026surface cli

Pipeline timeline

Intent to proven code in 23m across Think, Plan, Build, and Verify.

Think
2m
Plan
2m
Build
4m
Verify
3m

Assertion ledger

8 claims, each independently verified.

IDSaysMatcher
A001The sampler never returns more files than the budget allowsverifiedok
A002A budget of 2 with three depth levels returns at most 2 filesverifiedok
A003Shallow files get priority when the budget is too small for all depth levelsverifiedok
A004A budget of 1 with three depth levels returns exactly 1 fileverifiedok
A005Existing sampler tests still pass after the fixverifiedok
A006Proportional allocation across roots still works after the fixverifiedok
A007Depth stratification still works after the fixverifiedok
A008Budget cap is still enforced after the fixverifiedok

Findings 4 total

obsclosed
A001 says field ('never returns more than budget') doesn't match its matcher (not_equals 0 — just checks non-empty). Budget enforcement is actually verified by A002.
debtpackages/cli/src/engine/sampling/proportionalSampler.tsscope
Root-level allocation in sampleFilesProportional lines 140-143 has the same floor-1-without-remaining-guard pattern. Protected by final trim at line 172 but still wastes glob work.
obspackages/cli/tests/engine/sampling/proportional-sampler.test.tsclosed
Budget=1 test (A004) verifies count but not that the returned file is shallow. Iteration order guarantees shallow, but the test doesn't assert it.
obsclosed
Proof chain finding fix-deep-tier-sampling-C2 (allocateBudget can exceed budget) is directly resolved by the remaining > 0 guard at line 81.

Integrity seal

scopesha256:6d9f92a912b10...
contractsha256:f1cafedbb95a3...
plansha256:b633237eeb707...
specsha256:32d33b7841c3a...
build-reportsha256:5ca7accddd826...
build-datasha256:94bdbdc3b2226...
verify-reportsha256:0af5ce7fd3e71...
verify-datasha256:b3dead10d8f3e...
audit cmd$ ana proof audit fix-sampler-budget-overflow   → all hashes match