fix(consume): a withheld concept carries the rule that actually decided it

The quota filters the WHOLE candidate list, so every over-quota candidate
came back `source_quota_exceeded` -- including the ones the RANK had
already put outside k, which the quota only reached because it ran first.

`_fates_without_quota` asks the same cut what would have become of each
candidate with no quota, and the drop keeps THAT rule; only a candidate the
quota-off cut would have delivered is named as the quota's. The packer is
lifted into `_pack` and used by both, so the quota-off fate is decided by
the code the run itself uses and never by a second implementation.

The retrieval gate's row 3 goes 2 of 5 RED to 5 of 5 GREEN. Row 7 is
unchanged at 12 of 14; M01 and M02 lose their row-3 credit, which was the
lying label moving and not the ranking. Suite: 2288 passed, 0 failed; no
committed payload moves a byte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-20 08:24:26 +02:00
commit f81683ea54
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
2 changed files with 141 additions and 46 deletions

View file

@ -1873,6 +1873,77 @@ def knapsack(items: Sequence[tuple[float, int]], *, capacity: int) -> tuple[int,
return max(best, key=lambda entry: entry[0])[1]
def _pack(
shortlist: Sequence[tuple["Concept", float, dict[str, object], int]],
*,
limit: int,
reserve_top_rank: bool,
) -> tuple[list[dict[str, object]], list[str], tuple[str, int] | None]:
"""The budget step, alone: a shortlist in fused-rank order to delivered
excerpts, the ids the budget dropped, and the reservation that was made.
Lifted out of :func:`cut` so the quota-off fate of a dropped candidate is
decided by the SAME packer the run itself uses.
"""
# The DP POOL is sorted by `concept_id`, so which of two equal-value subsets
# wins is a property of the input set rather than of the order the ranker
# happened to emit. The OUTPUT is not: excerpts come back in fused-rank
# order, because the rank is what a hit@k measurement reads, and an id-sorted
# list would silently turn "position in the payload" into a different number
# from "position in the ranking".
pool = sorted(shortlist, key=lambda entry: entry[0].concept_id)
reserved: tuple[str, int] | None = None
room = limit
if reserve_top_rank and shortlist:
# `shortlist` is in fused-rank order, so its first entry IS the
# top-ranked candidate -- not the heaviest, and not the first by id.
top = shortlist[0]
reserved = (top[0].concept_id, top[3])
room = limit - top[3]
pool = [entry for entry in pool if entry[0] is not top[0]]
capacity = room // WEIGHT_BUCKET
packed = {
id(pool[index][0])
for index in knapsack(
tuple((score, -(-weight // WEIGHT_BUCKET)) for _, score, _, weight in pool),
capacity=capacity,
)
}
if reserved is not None:
packed.add(id(shortlist[0][0]))
delivered: list[dict[str, object]] = []
over_budget: list[str] = []
for concept, _, excerpt, _ in shortlist:
if id(concept) in packed:
delivered.append({**excerpt, "rank": len(delivered) + 1})
else:
over_budget.append(concept.concept_id)
return delivered, over_budget, reserved
def _fates_without_quota(
candidates: Sequence[tuple["Concept", float, dict[str, object], int]],
*,
k: int,
limit: int,
reserve_top_rank: bool,
) -> dict[str, str]:
"""What would have become of each candidate had the quota not run.
A candidate the quota-off cut would have DELIVERED is the only one the
quota can honestly claim: it is the place the quota took. Everything else
keeps the rule the quota-off cut gives it, because that is what actually
decided it.
"""
fates = {concept.concept_id: "below_k" for concept, _, _, _ in candidates[k:]}
delivered, over_budget, _ = _pack(
candidates[:k], limit=limit, reserve_top_rank=reserve_top_rank
)
fates.update({concept_id: "over_budget_after_knapsack" for concept_id in over_budget})
fates.update({str(entry["concept_id"]): "source_quota_exceeded" for entry in delivered})
return fates
def cut(
ranked: Sequence[tuple[Concept, float, int]],
*,
@ -1957,8 +2028,21 @@ def cut(
# to the quota being off.
for index in over[: max(k - sum(keep), 0)]:
keep[index] = True
# THE RULE A DROP CARRIES IS TRUE OF THAT DROP. The quota filters the
# WHOLE candidate list rather than the top k, so an over-quota
# candidate the RANK had already put outside k used to come back
# `source_quota_exceeded` -- the quota only reached it because it ran
# first. Measured on 25 real misses 2026-09-17: 13 were named by the
# quota and decided by the rank.
#
# The truth is the SAME cut without the quota, computed from the SAME
# candidate list by the SAME packer -- never a second implementation
# of the rule, which would be two rules with one name.
fates = _fates_without_quota(
candidates, k=k, limit=limit, reserve_top_rank=reserve_top_rank
)
withheld.extend(
(candidates[index][0].concept_id, "source_quota_exceeded")
(candidates[index][0].concept_id, fates[candidates[index][0].concept_id])
for index in range(len(candidates))
if not keep[index]
)
@ -1966,38 +2050,10 @@ def cut(
for concept, _, _, _ in candidates[k:]:
withheld.append((concept.concept_id, "below_k"))
shortlist = candidates[:k]
# The DP POOL is sorted by `concept_id`, so which of two equal-value subsets
# wins is a property of the input set rather than of the order the ranker
# happened to emit. The OUTPUT is not: excerpts come back in fused-rank
# order, because the rank is what a hit@k measurement reads, and an id-sorted
# list would silently turn "position in the payload" into a different number
# from "position in the ranking".
pool = sorted(shortlist, key=lambda entry: entry[0].concept_id)
reserved: tuple[str, int] | None = None
room = limit
if reserve_top_rank and shortlist:
# `shortlist` is in fused-rank order, so its first entry IS the
# top-ranked candidate -- not the heaviest, and not the first by id.
top = shortlist[0]
reserved = (top[0].concept_id, top[3])
room = limit - top[3]
pool = [entry for entry in pool if entry[0] is not top[0]]
capacity = room // WEIGHT_BUCKET
packed = {
id(pool[index][0])
for index in knapsack(
tuple((score, -(-weight // WEIGHT_BUCKET)) for _, score, _, weight in pool),
capacity=capacity,
)
}
if reserved is not None:
packed.add(id(shortlist[0][0]))
delivered: list[dict[str, object]] = []
for concept, _, excerpt, _ in shortlist:
if id(concept) in packed:
delivered.append({**excerpt, "rank": len(delivered) + 1})
else:
withheld.append((concept.concept_id, "over_budget_after_knapsack"))
delivered, over_budget, reserved = _pack(
shortlist, limit=limit, reserve_top_rank=reserve_top_rank
)
withheld.extend((concept_id, "over_budget_after_knapsack") for concept_id in over_budget)
withheld.sort()
return tuple(delivered), tuple(withheld), reserved