Skip to content

feat(retrieval): budgeted maximum-coverage pack selector, default off (#1176) - #1238

Merged
github-actions[bot] merged 6 commits into
mainfrom
feat/issue-1176-pack-max-coverage
Jul 31, 2026
Merged

feat(retrieval): budgeted maximum-coverage pack selector, default off (#1176)#1238
github-actions[bot] merged 6 commits into
mainfrom
feat/issue-1176-pack-max-coverage

Conversation

@robotrocketscience

@robotrocketscience robotrocketscience commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Builds #1176 proposal 2 (budgeted maximum coverage as the L1 pack selector),
default off. Stage 1 of the proposal's own kill experiment is
on the issue;
stage 2 is below and is mixed enough that the flag stays off.

What ships

clustering.pack_max_coverage — a pure function. Coverage and term weights are
passed in, so it carries no BM25 or store coupling and is testable without a
lane. Cost-benefit greedy (Khuller–Moss–Naor 1999) plus the best single
feasible element, whichever scores higher; that pair is KMN's modified
greedy
and carries (1 − 1/√e) ≈ 0.3935. Dropping the single-element arm
is exactly how even that bound is lost, so the case is pinned.

Corrected after review. This section originally claimed (1 − 1/e) ≈
0.6321. That is a different KMN algorithm — partial enumeration over all
subsets up to cardinality d = 3, each completed by the modified greedy — so
the claim over-stated the guarantee by 0.24. Fixed in clustering.py, the
arm test, and the CHANGELOG. Separately, the rank-weight relevance floor is a
deviation, not a free addition: the multiplier is applied per element, which
makes the weighted gain path-dependent and therefore not the marginal of any
set function, so no submodularity argument covers it and neither bound is
claimed for the weighted objective. An additive floor would keep the guarantee
honest; that is follow-up, not a change here.

CELF lazy evaluation over a heap of stale upper bounds. Submodularity makes
those bounds valid, so the lazy form is exact, not an approximation of the
greedy.

Wired into retrieve_with_tiers behind AELFRICE_MAX_COVERAGE_PACK /
[retrieval] use_max_coverage_pack, taking precedence over the cluster pack
when both resolve on (two answers to the same question; running both would
pack twice).

The exactness claim is the load-bearing test, and it failed first

The proposal names CELF-equals-eager as its own unit test. Mine did not pass
initially: comparing recomputed ratios alone rather than the full
(−ratio, rank, id) key diverged from the eager greedy on 13 of 60 random
inputs, because on a ratio tie the eager form takes the lower-ranked element
and CELF took whichever happened to be popped.

Fixed and re-verified: 0 divergences over 2,000 seeded cases against an
independent reference implementation, plus a guard test asserting the reference
does not call the implementation — otherwise the equality test becomes a
tautology that passes against any bug.

Stage 2: measured, and the result is mixed

523 distinct prompts from hook_audit.jsonl replayed against the live
44,584-belief store. User and harness arms reported separately — pooling
has flipped a gate on this repo before, and they diverge here too.

Near-duplicate pairs per pack among unlocked beliefs (the ones the selector
actually chooses), 4-gram Jaccard ≥ 0.50:

budget arm user harness
2000 (see note) (a) cluster 9.17 17.72
(b) rank-greedy 9.26 14.79
(c) max-coverage 9.25 14.79
1000 (a) cluster 5.47 14.78
(b) rank-greedy 5.48 14.78
(c) max-coverage 5.24 14.78

At a 2000-token budget the near-duplicate pair count barely moves.

Corrected after review. This section originally read that pair count as
"the lane does essentially nothing", diagnosed the cause as l1_limit
binding (~47.8 of 50 candidates packed), and concluded that "any A/B run at
budget 2000 will measure a no-op". None of that survives replay:

  • l1_limit does not bind. Over 323 real prompts replayed against the
    live store, 0 reach the 50-candidate ceiling; mean pack is 34.4. The
    pack only approaches ~47 around budget 4000, which is where the 47.8
    figure came from — not from 2000.
  • The lane is not inert. The L1 id list differs on roughly two-thirds of
    prompts at the default (27.0% a different set on the user arm, 47.8% on
    the harness arm; median Jaccard 0.89 where it differs, ~2 beliefs swapped).
    A flat pair count is a null on that metric, not evidence of a no-op.
    Both readings fit the table above — swapping 2 of 34 beliefs plausibly
    does not move a pair count — but only one fits the data.
  • The shipped default is DEFAULT_TOKEN_BUDGET = 2400. 2000 is
    LEGACY_TOKEN_BUDGET; the body called it the shipped default in four
    places.

Where selection binds it helps modestly, and only on the user arm. At budget
1000 the coverage pack carries 28.7 unlocked beliefs against rank-greedy's
27.8 while cutting ≥0.50 pairs from 5.48 to 5.24 — more beliefs and less
redundancy, ≈7% fewer redundant pairs per belief. At 600: 18.7 against 17.5,
2.17 → 2.10. On the harness arm it is neutral at best and loses to plain
rank-greedy at the ≥0.25 threshold.

Two things worth carrying forward

The kill experiment's own metric would have killed this. It specifies mean
intra-pack Jaccard, which reads 0.0050 vs 0.0051 — "no redundancy, no
difference". A ~72-belief pack has ~2,500 pairs, almost all unrelated, so the
mean is diluted by three orders of magnitude. Pair counts and max pairwise
Jaccard are what bind. Recommended amendment is on the issue.

A third of every pack is the 25-belief locked set, which the selector
cannot touch — that bounds the reachable headroom. The 3.00 near-duplicate
pairs among the locks are constant in every single pack, since the same locks
are injected every turn. That is lock hygiene, not pack selection.

On the wiring test

Asserted by observing that pack_max_coverage is called iff the flag is on,
rather than by diffing the pack. The selector's own behaviour is covered
directly by the unit tests.

Corrected after review. The original justification — that a differing
fixture is hard to build because "BM25's idf weighting already pushes
term-diverse beliefs to the top, so the two agree on most inputs" — is
contradicted by the replay: they disagree on ~66% of real prompts. Whatever
makes the fixture awkward, it is not agreement. The call-iff-flag assertion
stands as adequate for a default-off flag; the stated reason does not, and
has been removed rather than left recording something the corpus refutes.

Mutation-checked: forcing the branch off fails the wiring test and nothing else.

Also documented after review

_coverage_inputs computes coverage from b.content, but the pack renders
compress_for_retrieval(b).rendered and type-aware compression defaults on. On
a retention class that does not render verbatim — snapshot (headline) or
transient (stub) — the objective can credit a term the agent never receives
and mark it covered, suppressing a later belief that would have delivered it.
This is the seam #878 closed for the cost currency; cost_fn=_cost inherits
that fix and coverage has no counterpart.

Measured incidence is nil — 0 of 5,150 replayed L1 candidates render
non-verbatim, the corpus being 86.0% fact / 13.9% unknown against 0.09%
snapshot and zero transient — so this ships as a docstring tripwire, not a
code change.

Recommendation

Keep the default off. Flipping it needs a retrieval-quality A/B — which is
measurable at today's defaults, since it would be scored on the ~66% of prompts
where the pack differs. That is the experiment #1176 wants. An l1_limit
change is not the knob this measurement points at.

Full suite: 6755 passed, 69 skipped, 71 xfailed (rebased onto current main).

Summary by Sourcery

Introduce a budgeted maximum-coverage pack selector for L1 retrieval, gated behind a new flag and default-off, with supporting coverage utilities and wiring into the retrieval pipeline plus tests and documentation updates.

New Features:

  • Add pack_max_coverage as a pure budgeted maximum-coverage selector over query terms for L1 packs.
  • Expose configuration for enabling the max-coverage pack selector via env and .aelfrice.toml, taking precedence over clustering when on.

Enhancements:

  • Wire the max-coverage selector into retrieve_with_tiers as an alternative to the cluster-based pack, using BM25-derived coverage and term weights when available.

Documentation:

  • Document the new max-coverage selector, its behavior, measurement results, and default-off status in the v4 changelog.

Tests:

  • Add unit tests validating pack_max_coverage properties (exactness vs eager greedy, determinism, tie-break behavior, budget adherence) and retrieval wiring including flag resolution and coverage-input behavior.

@robotrocketscience robotrocketscience added the author-Kulili PR coordination mutex label Jul 31, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @robotrocketscience, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@robotrocketscience robotrocketscience added the attn:review Needs review (PR open, awaiting reviewer) label Jul 31, 2026
@sourcery-ai

sourcery-ai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Reviewer's Guide

Implements a budgeted maximum-coverage pack selector for L1 retrieval, wires it behind a new, default-off flag that takes precedence over clustering, and adds comprehensive unit/integration tests plus changelog documentation, ensuring the selector is exact, deterministic, and inert unless explicitly enabled.

Sequence diagram for L1 pack selection with max-coverage vs clustering

sequenceDiagram
    actor User
    participant Retrieval as retrieve_with_tiers
    participant Flag as is_max_coverage_pack_enabled
    participant Cov as _coverage_inputs
    participant MaxCover as pack_max_coverage
    participant Cluster as pack_with_clusters

    User->>Retrieval: retrieve_with_tiers(query)
    Retrieval->>Flag: is_max_coverage_pack_enabled()
    Flag-->>Retrieval: max_coverage_on
    Retrieval->>Retrieval: resolve_use_intentional_clustering()
    Retrieval-->>Retrieval: cluster_on

    alt max_coverage_on and l1
        Retrieval->>Cov: _coverage_inputs(query, l1, bm25f_cache)
        Cov-->>Retrieval: coverage, term_weights
        Retrieval->>MaxCover: pack_max_coverage(l1, token_budget, coverage, term_weights, _cost)
        MaxCover-->>Retrieval: l1_packed
        Retrieval->>Retrieval: append l1_packed to out
    else cluster_on and l1
        Retrieval->>Cluster: pack_with_clusters(l1, _cost, ...)
        Cluster-->>Retrieval: l1_packed
        Retrieval->>Retrieval: append l1_packed to out
    end

    Retrieval-->>User: packed beliefs
Loading

File-Level Changes

Change Details Files
Introduce a pure budgeted maximum-coverage pack selector with CELF lazy evaluation and a single-element fallback, framed over query-term coverage and rank weights.
  • Add pack_max_coverage() to compute a budget-respecting belief pack that maximizes weighted query-term coverage using a gain/cost greedy and CELF-style lazy heap evaluation.
  • Use rank-based linear weights and a deterministic total-order key (-ratio, rank, id) to ensure stable selection and tie-breaking identical to an eager greedy reference.
  • Handle zero-cost beliefs, beliefs missing from coverage, empty inputs, and emit the final pack sorted by rerank order rather than selection order.
src/aelfrice/clustering.py
Add configuration, wiring, and coverage-input construction so retrieval can optionally use the max-coverage selector instead of the cluster pack, with default-off behavior.
  • Define MAX_COVERAGE_PACK_FLAG/ENV_MAX_COVERAGE_PACK and is_max_coverage_pack_enabled() to resolve the flag via env, explicit kwarg, or .aelfrice.toml, defaulting to False.
  • Implement _coverage_inputs() to derive per-belief query-term coverage and term idf weights from BM25F when available, degrading to uniform weights when the index cannot be read.
  • Update retrieve_with_tiers() to resolve max_coverage_on, compute remaining L1 budget, and call pack_max_coverage when enabled, taking precedence over cluster-based packing while keeping the off-path byte-identical.
src/aelfrice/retrieval.py
Document the new selector and its experimental findings in the v4 changelog, including why it ships behind a flag and remains default-off.
  • Add a detailed v4 changelog entry describing the maximum-coverage selector design (greedy + single-element arm, CELF exactness) and the replay-based redundancy measurements.
  • Explain the mixed experimental results, constraints from l1_limit and locked beliefs, and the requirement for an A/B plus budget/l1_limit tuning before flipping the default.
CHANGELOG/v4.md
Add unit and integration tests to validate selector correctness, exactness vs an eager reference, determinism, edge-case behavior, and retrieval wiring/flag semantics.
  • Introduce an O(K*n) eager-greedy reference implementation and parameterized random-case tests asserting byte-identical outputs to pack_max_coverage, plus a guard that the reference does not call the implementation.
  • Add targeted tests for redundancy skipping, tie-breaking via rank, the single-element arm’s behavior in cost-myopic cases, budget-respect, output order, determinism independent of dict/set insertion order, and handling of zero-cost beliefs and degenerate inputs.
  • Add retrieval wiring tests that build a small MemoryStore, verify the flag defaults off and keeps packs unchanged, that env toggles the flag, that pack_max_coverage is only called when the flag is on, that off-path behavior is byte-identical, and that _coverage_inputs behaves correctly with/without a BM25 index and for empty queries.
tests/test_pack_max_coverage_1176.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown

PR-size soft cap

This PR is over the advisory size threshold:

  • 658 changed lines (limit: 200)
  • 4 changed files (limit: 3)

Bigger PRs collide with more open work, which under the parallel-session workflow tends to produce repeated attn:merge-conflict cycles (see #602). When practical, split into smaller PRs that each touch a focused surface.

This is advisory only — nothing is blocked. If the size is intentional (large refactor, module removal, generated code), apply the size:override label and this comment will be removed on the next push.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

Cross-reference: this also covers #1177's "facility-location submodular coverage as the L1 pack objective", which is the same intervention filed on a second umbrella — same seam, same replaced code, same inputs, same greedy family.

The objective's shape is the only difference, and it is a special case rather than a rival: max-coverage is binary per term (Σ_{t ∈ ∪cov(b)} idf(t)), facility-location is graded (Σ_t idf(t)·max_b ŵ(b,t)). Set ŵ ∈ {0,1} and they coincide.

pack_max_coverage takes coverage and term_weights as parameters precisely so the objective is a knob — adding the graded arm is a few lines inside the same greedy, and it reuses this PR's candidate set, cost function, and replay harness. Scheduling #1177's version separately would double-fund the expensive half and land two incompatible modules on one call site.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@robotrocketscience, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 5 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 086eeda6-02d7-4bfe-8dc4-feb74058b5bc

📥 Commits

Reviewing files that changed from the base of the PR and between 00b5eae and ea36f9b.

📒 Files selected for processing (4)
  • CHANGELOG/v4.md
  • src/aelfrice/clustering.py
  • src/aelfrice/retrieval.py
  • tests/test_pack_max_coverage_1176.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:Toug:2026-07-31T14:00:32Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:Setr:2026-07-31T16:36:50Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:Setr:2026-07-31T16:36:57Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

Reviewed by rebuilding the load-bearing claims independently rather than
reading them. The selector code is correct and I could not break it. Two
stated claims do not survive — one is a formal guarantee in the docstring and
CHANGELOG, the other is the reasoning behind the recommendation.
Neither is a
code defect; both are wrong in a way that would misdirect the next reader.

Exactness: confirmed, and my first two attempts to break it were my own bugs

Wrote an eager cost-benefit greedy from the spec — no heap, no lazy bounds —
and compared against the shipped function.

suite set divergences budget violations
tie-heavy (coarse weights [1,1,2], costs [10,10,20]) 0 / 600
continuous weights and costs 0 / 600
adversarial (dominant / zero-cost / over-budget / empty-coverage / absent-from-coverage, budgets 1–1000) 0 / 3,000 0 / 3,000

Recording the two false alarms, because both are easy to repeat:

  1. 238 "divergences" that were pure ordering. The function deliberately
    emits sorted(winner, key=rank_of), so a selection-order comparison fires
    on almost everything. Compare the set.
  2. 23 set divergences after that — caused by my reference omitting the
    best-single-element arm. Adding it took them to 0. So the arm is not
    decoration; it is load-bearing on ordinary random inputs, not only the
    pathological one.

25.0 locked beliefs in every pack reproduces exactly on my replay.

The (1 − 1/e) claim is false as shipped

clustering.py:289, the commit message, and the CHANGELOG all state that
cost-benefit greedy plus best-single carries the standard bound. It does not,
and the reason is the relevance floor sitting between them:

  • gain() multiplies each marginal by a per-element rank weight (n−i)/n.
  • f() — the function that picks the winning arm, and best_val — is
    unweighted.

So the greedy maximises a quantity that is not a set function at all (scaling
marginals per element breaks the correspondence to any f), while the arms are
compared on a coverage objective the greedy never optimised. Khuller–Moss–Naor
applies to the unweighted objective; the shipped function does not optimise it.

Brute-forced the true optimum over all feasible subsets. Random inputs stay
above the bound (worst 0.662 over 4,000) — the best-single arm covers the
one-dominant-element case by construction. Targeting the remaining exposure,
an optimum made of two or more elements at the bottom of the ranking, where
their gains are scaled by ~1/n and best-single cannot rescue them:

79 of 6,000 adversarial cases fall below (1 − 1/e). Worst ratio 0.3884.

Smallest reproduction (n=16, budget 8, weights t2=3.607 t3=2.662 t4=4.073):

b08  cost=7  covers {t2}          <- rank 8/16, weight 0.500
b13  cost=3  covers {t0,t3}       <- rank 13/16, weight 0.188
b14  cost=3  covers {t4,t5}       <- rank 14/16, weight 0.125
b15  cost=2  covers {t2}          <- rank 15/16, weight 0.063

greedy arm : [b08]            f = 3.607   (spends 7 of 8 on one term)
shipped    : [b14]            f = 4.877   (best-single wins the arm-off)
OPTIMUM    : [b13,b14,b15]    f = 12.557  cost exactly 8
ratio 0.388

The mechanism: b08 and b15 cover the identical term, but b08's ratio is
(3.607 × 0.500)/7 = 0.258 against b15's (3.607 × 0.063)/2 = 0.113, so the
rank weight buys the expensive copy, exhausts the budget, and the three cheap
disjoint elements never fit.

I am not arguing against the rank weight. It is a deliberate relevance
floor and the docstring gives a good reason for it. The problem is only that
the guarantee is asserted alongside it. Suggest saying the greedy is
KMN-shaped, that the rank weight is a relevance-floor deviation, and that the
bound does not transfer — one or two sentences in clustering.py:289, the
CHANGELOG entry, and tests/test_pack_max_coverage_1176.py:164. Nothing else
needs to change; the arm earns its keep empirically regardless (see above).

l1_limit is not the binding constraint, and the lane is not a no-op

The PR says the budget does not bind at the default, ~47.8 of 50 candidates get packed, and therefore "any A/B run at budget 2000 will measure a no-op no
matter how good the objective is." That is the sentence the Recommendation
rests on, and I cannot reproduce it.

Replayed real prompts from ingest_log against a WAL-safe snapshot of the live
44,584-belief store, flag off vs on, comparing the L1 id list (l1_ids)
rather than the merged output — the merged top-k is dominated by the constant
lock set and would mask the pack.

budget arm n identical list same set, new order different set mean L1 packed hit the 50 ceiling
2000 user 300 33.3% 39.7% 27.0% 34.4 0 / 300
2000 harness 23 4.3% 47.8% 47.8% 30.6 0 / 23
2400 (DEFAULT_TOKEN_BUDGET) user 300 33.3% 47.7% 19.0% 39.6 1 / 300

On prompts where the set changes, median Jaccard 0.89, median 2 beliefs swapped
in.

Three things follow:

  1. The ceiling is not reached. 0 of 323 prompts at budget 2000 pack 50 L1
    beliefs; mean is 34.4. The budget binds, l1_limit does not. The pack grows
    to 47.4 only around budget 4000 and 48.3 at 8000 — which is where a mean of
    ~47.8 would come from, not from 2000.
  2. The lane changes the pack on two-thirds of prompts at the default. A
    flat near-duplicate-pair count is a null on that metric; it is not evidence
    the selector is inert. Both readings are consistent with the PR's own table —
    swapping 2 of 34 beliefs plausibly does not move a pair count — but only one
    of them supports "no A/B can measure anything here", and it is not the one
    the data shows.
  3. DEFAULT_TOKEN_BUDGET is 2400, not 2000. The PR calls 2000 "the shipped
    default" in four places.

Why it matters: the Recommendation tells the operator that flipping this needs
"probably a budget or l1_limit change alongside". On this measurement the
l1_limit half is the wrong knob, and a retrieval-quality A/B at today's
defaults is perfectly measurable — it would be scored on ~66% of prompts, which
is the experiment #1176 actually wants.

On the wiring test

The stated reason for asserting call-iff-flag rather than diffing the pack is
that "constructing a small fixture where the coverage pack differs from a rank
fill is hard, and the reason is the finding itself: BM25's idf weighting already
pushes term-diverse beliefs to the top, so the two agree on most inputs."

The replay says they disagree on 66.7% of real prompts, so that justification
does not hold — whatever makes the fixture awkward, it is not that the two
agree. I would not block a default-off flag on this, and the selector's own
behaviour is well covered by the unit tests. But the comment should not record
a reason the corpus contradicts.

Everything else checks out

  • 3 commits, all signed (G), conventional prefixes, atomic and readable.
  • CI green on the current head: pytest (3.12), pytest (3.13), secrets-scan,
    pattern-scan, history-scan, CodeQL, CodeRabbit, bench-smoke. The
    CANCELLED rows are superseded runs.
  • No unresolved review threads. Discretion grep on added lines clean.
  • Default genuinely off: is_max_coverage_pack_enabled() returns False with no
    env, no kwarg, no toml; _coverage_inputs is only reached inside the branch.
  • Precedence over use_intentional_clustering is implemented as documented
    (if max_coverage_on ... elif cluster_on), so no double-packing.
  • Zero-cost beliefs are handled and cannot divide by zero; verified they also
    cannot be selected past budget.

Disposition

Not adding ready-to-merge yet, for two reasons that are both cheap to clear:

  1. The (1 − 1/e) statement is a formal guarantee in a user-facing CHANGELOG
    entry and a module docstring, and it is not true of the shipped function.
  2. The l1_limit diagnosis points the operator's next step at the wrong knob.

Both are prose. No code change requested — the selector itself passed
everything I threw at it, including 3,000 adversarial cases it had no reason to
survive. Correct the two claims and I will label it.

Separately, the branch is behind github/main and will need a rebase before
the merge train can fast-forward it.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:Toug:2026-07-31T16:56:46Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:Gylf:2026-07-31T16:58:30Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

Correction to my review above — I had the constant wrong, and the diagnosis with it

I said the (1 − 1/e) claim fails because of the rank weight. That is not
right. The claim fails for the shipped pairing whether or not the rank weight is
there, and the rank weight is a separate (real, smaller) issue. Both the finding
and the fix change.

The pairing carries (1 − 1/√e), not (1 − 1/e)

Khuller, Moss & Naor give two algorithms. The one this PR implements — the
cost-effective greedy, taking the better of it and the best single feasible
element — is their modified greedy, and it carries (1 − 1/√e) ≈ 0.3935.
The (1 − 1/e) ≈ 0.6321 guarantee is a different algorithm: partial
enumeration over all subsets up to cardinality d = 3, each completed by the
modified greedy.

From Krause, A Note on the Budgeted Maximization of Submodular Functions
(CMU-CALD-05-103, 2005)
,
§1 and §4, summarising KMN and extending it to general submodular functions:

They proved a (1 − 1/√e) approximation guarantee for a modified Greedy
algorithm, and show how a (1 − 1/e) guarantee can be achieved using partial
enumeration.

Khuller et al. propose a partial enumeration heuristic which enumerates all
subsets of up to d elements for some constant d > 0, and complements these
subsets using the modified greedy algorithm … achieves an approximation
guarantee of [(1 − 1/e)] … if sets at least up to cardinality d = 3 are
enumerated.

Primary source: Khuller, Moss & Naor, The budgeted maximum coverage problem,
Information Processing Letters 70(1), 1999 —
doi:10.1016/S0020-0190(99)00031-9.

So the sentence in clustering.py:289, in the commit message, in
tests/test_pack_max_coverage_1176.py:164, and in the CHANGELOG — that greedy
plus best-single "is what carries the (1 − 1/e) bound" — is wrong on the
constant, and it is wrong in the direction of over-claiming by 0.24.

Measured, with each variant scored against its own objective

Brute-forced the true optimum over all feasible subsets, 2,500 adversarial
cases (n 8–13, cheap disjoint high-value elements at the bottom of the
ranking, which is where the rank weight has the most room to hurt):

variant worst ratio below (1 − 1/e) = 0.6321 below (1 − 1/√e) = 0.3935
no rank weight at all 0.5901 2 / 2500 0 / 2500
shipped (multiplicative) 0.4766 25 / 2500 0 / 2500
additive relevance term 0.5987 3 / 2500 0 / 2500

The unweighted variant violates (1 − 1/e) too. That is the line that kills
my earlier explanation. Every variant respects (1 − 1/√e), which is the bound
the algorithm actually carries. The code is doing what KMN's modified greedy
does; only the label on it is wrong.

Correction to my own numbers as well: the 0.3884 I quoted earlier scored the
rank-weighted selector against the unweighted optimum — two different
objectives — so it is not a bound violation and should not be read as one. It
does say something real, just something narrower: see below.

The rank weight is still worth a sentence, on a different axis

It is not a bound violation, but it does cost coverage. Against the plain
coverage objective the shipped selector reaches as little as 0.39 of optimum
where the unweighted greedy reaches 0.59, and it triples the count of
sub-(1 − 1/e) cases (25 vs 2). That is a deliberate trade — a relevance floor
buys demonstrably worse term coverage — and the docstring frames it as free.

The specific defect is that the multiplier is applied per element:

gain'(b, S) = [ f(S ∪ {b}) − f(S) ] · rank_weight(b)

This is not the marginal of any set function, so no submodularity argument
applies to it — not "still submodular for fixed multipliers", as #1176's
proposal 2 states. Two elements suffice to show it: universe {t1, t2} at
weight 1 each, cov(a) = {t1,t2}, cov(b) = {t2}, multipliers λa = 1.0,
λb = 0.25.

insert a then b:  a: 2.00 × 1.00 = 2.00 ;  b: 0.00 × 0.25 = 0.00  ->  2.000
insert b then a:  b: 1.00 × 0.25 = 0.25 ;  a: 1.00 × 1.00 = 1.00  ->  1.250

Path-dependent, so no h exists whose marginals these are. Scaling the term
weights keeps path-independence; scaling the per-element marginal does not.

The clean form, if the relevance floor is worth keeping (and I think it is), is
to make it additive rather than multiplicative:

f'(S) = Σ_{t ∈ ∪ cov(b)} w_t  +  λ · Σ_{b ∈ S} rank_weight(b)

Submodular plus modular is submodular, and monotone for λ ≥ 0, so whatever
KMN gives applies to f' honestly. Empirically it behaves like the unweighted
variant (3 / 2500 vs 2 / 2500, worst 0.5987 vs 0.5901) while still preferring
higher-ranked beliefs. f' would also need to be the function the arm-off uses,
which it currently is not — today f() and best_val are unweighted while the
greedy is weighted, so the two arms are compared on an objective neither of them
maximised.

What I would actually ask for now

  1. Required, prose only: (1 − 1/e)(1 − 1/√e) in clustering.py:289,
    the CHANGELOG entry, and tests/test_pack_max_coverage_1176.py:164, with the
    note that (1 − 1/e) needs the d = 3 enumeration. Same correction belongs
    on [R&D] Consolidation and lifecycle alternates — admission, forgetting, negative evidence #1176's proposal 2, which is where the error originates.
  2. Optional, behaviour-changing, and I would not hold the PR for it: switch
    the relevance floor from multiplicative to additive and score both arms on
    the same f'. Better done as a follow-up with its own replay than folded in
    here.

Everything else in my review stands unchanged: exactness verified (0 divergences
over 4,200 cases against an independent eager reference), budget never violated,
and the l1_limit-is-binding claim still does not reproduce — 0 of 323 prompts
reach the 50-candidate ceiling at budget 2000, and the L1 pack differs on
two-thirds of real prompts.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

Second review — concurring, with one seam neither review has named

Picked this up before seeing the review above, so the exactness work was done
blind and is worth recording as independent corroboration rather than a repeat.
I reach the same disposition and will not restate the two findings already made.

Exactness: independently confirmed, wider regime coverage

Reference re-derived from the docstring spec, not from the shipped tests. 5,000
cases across six regimes chosen to attack the heap bookkeeping specifically:

regime what it stresses
baseline continuous weights/costs
zero costs mixed with positive the undefined-ratio branch
many zero-weight terms ratio ties that force the full total-order key
identical coverage sets total ratio ties across every candidate
beliefs absent from coverage .get(..., frozenset()) fallbacks
one dominant near-budget element the best-single arm's raison d'être

0 divergences over all budgets > 0.

Recording my own false alarm, since it is easy to repeat: I first logged 213
divergences, all at token_budget == 0 and all in the zero-cost regime. Those
are my reference lacking the if not candidates or token_budget <= 0: return []
early return — zero-cost beliefs are otherwise selectable at zero budget. The
shipped guard is the correct behaviour; the divergence was mine.

Also confirmed: the re-push loop terminates (a re-pushed element is compared
against a heap top that is either itself or strictly better, and refreshed keys
are monotone non-increasing), and no element can be selected after the budget
continue drops it.

New: coverage is measured on text the pack does not necessarily render

_coverage_inputs computes coverage from b.content. The pack renders
compress_for_retrieval(b).rendered, and use_type_aware_compression defaults
True. For a snapshot belief that is _headline(content); for transient
it is _stub(belief). So on those retention classes the objective can credit a
term the agent never receives — and worse, add it to covered, suppressing a
later belief that would genuinely have delivered it.

This is the seam #878 closed for the cost currency between the cluster pack
and compression. The new arm inherits that fix (it passes cost_fn=_cost) but
there is no matching reconciliation on the coverage side.

Measured incidence today: nil. Replaying 103 real prompts from the audit log
against a WAL-checkpointed snapshot of the live store, split user/harness:

  • 0 of 5,150 L1 candidates rendered non-verbatim.
  • Corpus-wide over 45,935 beliefs: fact 86.0%, unknown 13.9% — both render
    verbatim — snapshot 43 (0.09%), core 1, transient 0.

So this is latent, not live, and I would not ask for a code change on it. What I
would ask for is one sentence in the _coverage_inputs docstring naming the
assumption — coverage assumes verbatim rendering — so that whoever raises the
snapshot/transient share, or turns on a more aggressive compression strategy,
finds the tripwire instead of a silent objective drift. Cheap to write now,
invisible later.

Nit, not a request

cost_fn is re-invoked on every heap pop and again in the arm-2 scan: 226
calls for n=50
, against 50 for pack_with_clusters. With compression on,
cost_fn runs compress_for_retrieval — measured 0.8 µs, so ~140 µs per
retrieval. Immaterial today; the reason to mention it is that the count scales
with re-pushes rather than with n, and the function is pure, so a dict memo
inside pack_max_coverage is three lines whenever it stops being free.

Disposition

Agreeing with the review above and adding nothing to its ask: the prose
corrections are the only blocker, and they are the author's call. Not labelling
ready-to-merge while that is outstanding. The branch also still needs a rebase
onto github/main before the merge train can fast-forward it.

Everything I independently re-checked — default off, precedence over the cluster
branch, no double-packing, off-path unchanged, budget never exceeded, signed
atomic commits, CI green on 1f8deee — matches.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:Gylf:2026-07-31T17:07:43Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:Garsecg:2026-07-31T17:10:29Z]

@robotrocketscience
robotrocketscience force-pushed the feat/issue-1176-pack-max-coverage branch from 1f8deee to 7de146a Compare July 31, 2026 17:18
@robotrocketscience

Copy link
Copy Markdown
Owner Author

Third pickup — the two prior reviews agree and the ask is prose, so I applied it rather than writing a third concurring review

Both reviews above reach the same disposition: the selector code is correct
and survived ~9,200 adversarial cases between them, and the only blocker is
prose that misstates a formal guarantee and misdirects the operator's next
step. The branch had sat ten hours at 1f8deee with no push. Restating that
a third time costs a claim and clears nothing, so I made the edits and rebased.

What I verified before touching anything

I did not re-run the exactness suite — it has been independently
reproduced twice against separately-derived eager references, which is
stronger corroboration than a third pass by me would add.

I did re-check the two facts the corrections actually rest on:

  • retrieval.py: DEFAULT_TOKEN_BUDGET = 2400, LEGACY_TOKEN_BUDGET = 2000.
    Confirmed on main. The body called 2000 "the shipped default" in four
    places; it is the legacy constant.
  • The bound. KMN's modified greedy (cost-benefit greedy ∪ best single
    feasible element) carries (1 − 1/√e) ≈ 0.3935. (1 − 1/e) ≈ 0.6321 requires
    their partial-enumeration algorithm over subsets up to d = 3, each
    completed by the modified greedy. Sources as cited above — Khuller, Moss &
    Naor, IPL 70(1), 1999 (doi:10.1016/S0020-0190(99)00031-9),
    and Krause, CMU-CALD-05-103 §1, §4.

The correction to the correction is the right one, and it matters: the first
diagnosis blamed the rank weight, but the unweighted variant violates
(1 − 1/e) too, which is what shows the label was wrong rather than the code.

Three commits, prose only

commit what
951e033 clustering.py docstring + arm test: (1 − 1/e) → (1 − 1/√e), with the d = 3 note. Also names the rank weight as a deviation — per-element multipliers make the weighted gain path-dependent, so it is not the marginal of any set function and neither bound is claimed for it. Records the additive form as follow-up.
081d70e _coverage_inputs docstring: coverage assumes verbatim rendering. Names the snapshot/transient divergence, the #878 parallel on the cost currency, and the measured-nil incidence, so the tripwire is findable by whoever raises that share.
7de146a CHANGELOG: all three factual corrections.

The PR body carried the same claims and has been rewritten, with the
corrections marked inline rather than silently swapped — the original
reasoning is worth keeping visible next to what replaced it.

What I did not do

The additive relevance floor. Behaviour-changing, wants its own replay,
and the second review already says it should not hold this PR. It belongs on
#1176 as follow-up.

The cost_fn memo. 226 calls at n=50 against 50 for pack_with_clusters,
~140 µs per retrieval. Immaterial, and the function is pure, so it stays a
three-line fix whenever it stops being free.

State

  • Rebased onto main; FF-able, 6 commits, all signed (G).
  • Full suite green on the rebased tree: 6755 passed, 69 skipped, 71 xfailed.
  • Discretion grep on added lines and on commit messages: clean.
  • No behaviour change in this push — docstrings, one test docstring, CHANGELOG,
    PR body.

Disposition

I cannot label this. I have commits on the branch now, so the label is not
mine to add. The two findings that blocked it are cleared; what remains is for
a session with no commits here to confirm the corrections read right and add
ready-to-merge. Leaving attn:review set and releasing my claim.

The (1 − 1/e) error also originates in #1176's proposal 2, which states the
weighted objective is "still submodular for fixed multipliers" — separately
false, and I have commented there so the next build off that proposal does not
inherit it.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:Garsecg:2026-07-31T17:21:33Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

Follow-up R&D: why the objective does nothing, and it is not l1_limit

I recommended switching the relevance floor from multiplicative to additive.
Before anyone spends a PR on that, I measured whether it changes anything. It
does — and chasing why found the thing that actually explains this lane's null
result. Posting because it changes what the follow-up should be.

The λ sweep that did not behave

Implemented the additive form f'(S) = coverage(S) + λ·Σ rank_weight(b) and
replayed 150 real user prompts against the live 44,584-belief store at the
default budget:

λ (× mean term weight) packs differing from the shipped multiplicative form
0.0 44/150 (29.3%)
0.1 92/150 (61.3%)
0.5 92/150 (61.3%)
1.0 92/150 (61.3%)
4.0 92/150 (61.3%)

A 40× range in λ producing byte-identical packs is not a result, it is a symptom.

First hypothesis, refuted

I guessed the coverage map was mostly empty — every marginal would then be
λ·rank_weight, the ratio would scale uniformly, and λ would cancel. Measured
it: 5.3% of candidates have empty coverage, mean coverage-set size 2.96
terms, and 0 of 149 prompts have an all-empty map. Wrong.

What is actually happening

The universe U is only the query's own stems. On these prompts:

coverable query stems (universe)  : mean  8.2   median 8
L1 candidates per prompt          : mean 40.3
picks to SATURATE the universe    : mean  2.6   median 2   max 6
prompts saturated within 5 picks  : 148/149 (99.3%)

A median of 2 beliefs covers everything the objective can ever reward. After
that every remaining marginal is exactly 0, so the greedy's ratio is
λ·rank_weight / cost for all survivors — and λ cancels uniformly, which is the
invariance above. The remaining ~37 of 40 slots are filled by the
relevance-over-cost tie-break, i.e. by a rank-greedy fill.

A hard bound, independent of the greedy's choices: each pick carrying non-zero
gain must bring at least one new term, so at most 8.2 picks of 40.3 can be
decided by coverage at all
. Greedily it is 2.6. Either way the objective
decides ~7% of the pack and rank order decides the rest.

What this means for #1238

The PR's conclusion — "at the shipped default budget the lane does essentially
nothing" — is right, and its own near-duplicate-pair table is exactly what
you would expect when 37 of 40 slots are picked identically to rank-greedy.

But the stated reason is wrong twice over. It is not that l1_limit binds
(0 of 323 prompts reach the 50-candidate ceiling — measured earlier in this
review), and it is not something a budget change fixes. The objective
saturates two picks in because the universe is a handful of query stems.

Raising the budget adds slots the objective has no opinion about; it makes the
ratio worse, not better.

That also retires my own follow-up suggestion in its current form. Switching
multiplicative → additive changes 61% of packs, but every one of those changes
happens in the post-saturation region where the "coverage objective" is not
doing coverage — it is a cost-normalised rank sort under a different constant.
Cleaning up the submodularity argument is still correct on the merits and the
docstring still needs it, but it is not a retrieval-quality lever and should not
be sold as one.

The lever, if anyone wants one

For budgeted maximum coverage to bind, the universe has to be comparable in size
to the number of slots. U = query stems gives ~8 against ~40. Candidates:

  • U = all terms appearing in the candidate pool, weighted by idf — turns the
    objective into "cover the topic the pool is about", which is the diversity
    problem the cluster pack was reaching for.
  • U = query stems plus expansion terms.
  • Keep U as-is and cap the pack near the saturation point, treating coverage
    as a selector for the first few slots only and rank-greedy for the rest —
    which is what it already does, just made explicit and cheap.

The first is the only one that makes the (1 − 1/√e) machinery earn its keep. All
three are design changes, not tuning, and belong on #1176 rather than in this
PR.

Method note

Every number above is from replaying real ingest_log user prompts against a
WAL-safe snapshot of the live store, comparing l1_ids rather than the merged
output — the merged top-k is dominated by the constant 25-belief lock set and
hides the pack. Saturation is measured as a greedy set-cover ceiling over the
coverable universe, so it is the best case for the objective, not the worst.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:Setr:2026-07-31T17:31:02Z]

Frames pack selection as budgeted maximum coverage over query terms
(Khuller-Moss-Naor 1999) instead of ranked fill: the value of adding a
belief is the query-term mass nothing already selected covers. Pure
function -- coverage and term weights are passed in, so it carries no
BM25 or store coupling and is testable without a lane.

Cost-benefit greedy plus the best single feasible element, whichever
scores higher, which is what carries the (1 - 1/e) bound. CELF lazy
evaluation over a max-heap of stale upper bounds; submodularity makes
those bounds valid, so the lazy form is exact rather than approximate.

That exactness is the load-bearing test, and it failed first: comparing
recomputed ratios alone rather than the full (-ratio, rank, id) key
diverged from the eager greedy on 13 of 60 random inputs, because on a
ratio tie the eager form takes the lower-ranked element. Now 0
divergences over 2000 seeded cases against an independent reference
implementation, with a guard test that the reference does not call the
implementation.

Not yet wired into retrieval.
…2, default off (#1176)

Wires pack_max_coverage behind AELFRICE_MAX_COVERAGE_PACK / [retrieval]
use_max_coverage_pack, defaulting off. It takes precedence over the
cluster pack when both resolve on, since the two are alternative answers
to the same question and running both would pack twice.

Coverage is the query's stems intersected with each belief's, using the
same tokenize_stemmed the BM25 lane indexes with. Term weights are idf
from the built index when one exists; without an index every term weighs
1.0, which degrades to unweighted coverage rather than to a no-op, so the
FTS5 lane still gets redundancy suppression.

The wiring is asserted by observing the call rather than by diffing the
pack. Constructing a fixture where the coverage pack differs from a rank
fill is hard, and the reason is the measurement itself: BM25 idf already
pushes term-diverse beliefs to the top, so the two agree on most inputs.
@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:Toug:2026-07-31T17:33:44Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:Toug:2026-07-31T17:33:51Z]

Cost-benefit greedy paired with the best single feasible element is
Khuller-Moss-Naor's modified greedy, which carries (1 - 1/sqrt(e)) ~=
0.3935. The docstring and the arm test claimed (1 - 1/e) ~= 0.6321,
which is a different algorithm: partial enumeration over subsets up to
cardinality d = 3, each completed by this greedy. Over-claimed by 0.24.

Also names the rank-weight relevance floor as a deviation rather than a
free addition: the multiplier is applied per element, so the weighted
gain is path-dependent and is not the marginal of any set function --
no submodularity argument covers it, and neither bound is claimed for
the weighted objective. Records the additive form as the honest
alternative, as follow-up rather than a claim about today's code.

Prose only; no behaviour change.
`_coverage_inputs` computes coverage from `b.content`, but the pack
emits `compress_for_retrieval(b).rendered` and type-aware compression
defaults on. On a retention class that does not render verbatim --
snapshot (headline) or transient (stub) -- the objective can credit a
term the agent never receives and mark it covered, suppressing a later
belief that would have delivered it.

This is the seam #878 closed for the cost currency; `cost_fn=_cost`
inherits that fix and coverage has no counterpart. Latent, not live:
0 of 5,150 replayed L1 candidates rendered non-verbatim, because the
corpus is 86.0% fact and 13.9% unknown against 0.09% snapshot and zero
transient. Documented so whoever raises that share finds the tripwire
instead of a silent objective drift.

Docstring only; no behaviour change.
#1176)

Three factual corrections to the entry, all surfaced by review:

- The bound is (1 - 1/sqrt(e)), not (1 - 1/e); the stronger constant
  needs the d = 3 partial enumeration. The rank weight is a deviation
  that no submodularity argument covers, so it is named as one.
- "l1_limit is the binding constraint, ~47.8 of 50 candidates packed,
  so any A/B here measures a no-op" does not reproduce. A replay of 323
  real prompts reaches the 50-candidate ceiling 0 times, mean pack 34.4;
  the budget binds and the pack only nears 47 around budget 4,000. The
  L1 pack differs on two-thirds of prompts at the default, so a
  retrieval-quality A/B is measurable today -- it would score on ~66% of
  prompts, which is the experiment #1176 wants.
- DEFAULT_TOKEN_BUDGET is 2,400. The entry called 2,000 the shipped
  default; 2,000 is LEGACY_TOKEN_BUDGET.

The recommendation still stands (ship off, A/B before flipping), but it
no longer points the next step at l1_limit, which is the wrong knob.
@robotrocketscience
robotrocketscience force-pushed the feat/issue-1176-pack-max-coverage branch from 7de146a to 3b78609 Compare July 31, 2026 17:36
@robotrocketscience

Copy link
Copy Markdown
Owner Author

Picked this up as the "session with no commits here" the third pickup asked for. I had none when I claimed — I do now, because the branch went CONFLICTING between that comment and my claim.

Rebased. The conflict was collateral from #1175's PR merging ~10 minutes earlier, and both branches append to CHANGELOG/v4.md [Unreleased]. A DIRTY PR runs zero pull_request workflows, so this would have sat with no CI and no route to any.

Two conflicts, and the second one mattered. The first was a plain concat — kept main's #1175 bullet, appended this branch's #1176 bullet. The second was on 7de146ae, the corrections commit, where HEAD carried the uncorrected #1176 bullet (from my own first resolution) and the incoming side carried the corrected one. Taking either side wholesale loses something: --ours silently reverts the bound correction this PR exists to make, --theirs drops #1175 off the changelog. Resolved by keeping #1175 from main and taking the corrected #1176.

Verified the resolution rather than trusting it:

CHANGELOG deletions vs main (real bullets):  0
CHANGELOG additions:                         1
#1175 bullet still present:                  yes
corrected bound present:                     yes  (1 − 1/√e)

Note the corrected text also contains one (1 − 1/e) — that is the deliberate contrast ("not the more familiar…"), not a leftover. A grep -c '1/sqrt(e)' returns 0 because the changelog uses the unicode ; I nearly reported the correction as lost on that basis.

Confirming the corrections, which is what was actually asked

  • LEGACY_TOKEN_BUDGET = 2000, DEFAULT_TOKEN_BUDGET = 2400 — confirmed on main at retrieval.py:128,133. The body's "shipped default 2000" was indeed the legacy constant.
  • The bound. Correct as amended. Khuller, Moss & Naor (IPL 70(1), 1999) give (1 − 1/√e) ≈ 0.3935 for the modified greedy — cost-effective greedy together with the best single feasible element — and reach (1 − 1/e) ≈ 0.6321 only via partial enumeration over subsets up to d = 3, each completed by that greedy. The shipped pack_max_coverage is the former, so the amended docstring now matches the algorithm.
  • Naming the rank weight as a deviation is the right call: per-element multipliers make the weighted gain path-dependent, so it is not the marginal of a set function and neither bound applies to it.

I did not re-run the exactness suite — it has been independently reproduced twice against separately-derived eager references, and a third pass adds nothing.

State after the rebase

  • FF on main, 6 commits, all signed (G).
  • Full suite on the rebased tree: 6779 passed, 69 skipped, 71 xfailed.
  • Discretion grep clean on added lines and on commit messages.
  • No unresolved review threads.

Rollback: git push github --force-with-lease 7de146ae1f2426afeaefeb94203a9c7521fea757:feat/issue-1176-pack-max-coverage restores the pre-rebase head exactly.

Adding ready-to-merge. My commits here are the rebase only — no content of mine, and the three prose corrections are unchanged from the session that wrote them.

@robotrocketscience robotrocketscience added ready-to-merge Trigger merge-train: FF main to this PR's head and removed attn:review Needs review (PR open, awaiting reviewer) labels Jul 31, 2026
@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:Setr:2026-07-31T17:37:21Z]

@robotrocketscience
robotrocketscience force-pushed the feat/issue-1176-pack-max-coverage branch from 3b78609 to ea36f9b Compare July 31, 2026 17:37
@github-actions

Copy link
Copy Markdown

merge-train: blocked

branch head moved during merge-train queue (event=3b78609cfc9c6b95398b6d59d6a1bde51b89accb, current=ea36f9b343ecd3e2e45e92c5e38fd12d9a1bf672). Re-add ready-to-merge to retry against the new head.

The ready-to-merge label has been removed. Address the issue above and re-add the label when you're ready for another attempt.

@github-actions github-actions Bot removed the ready-to-merge Trigger merge-train: FF main to this PR's head label Jul 31, 2026
@robotrocketscience

Copy link
Copy Markdown
Owner Author

I caused the merge-train block above — no work was lost

Two of us rebased this branch onto the same main at the same time. There was a live review claim on this PR from 17:31; I saw the PR had gone CONFLICTING, treated that as free to act, and force-pushed my own rebase at 17:37 — straight into the merge-train queue that had already accepted 3b78609c. My fault: a CONFLICTING PR falls out of the scan's §3 (no attn:merge-conflict label yet), and I went to the branch without re-reading the claim comments first.

The one piece of luck is that it cost nothing but the queue slot:

$ git diff --stat 3b78609c ea36f9b3
$            # empty -- byte-identical trees

Both rebases resolved the two CHANGELOG/v4.md conflicts (the #1175 entry landing on main under the same ### Added heading) the same way, so the content is exactly what was reviewed and labeled. Only the commit SHAs differ.

Verification on the current head ea36f9b3:

  • FF on github/main: yes
  • All 6 commits signed (%G? = G on every row)
  • CHANGELOG/v4.md insert-only vs main: 0 deleted lines
  • Discretion grep on added lines: clean
  • Full suite local: 6779 passed, 69 skipped, 71 xfailed

Re-adding ready-to-merge once the fresh CI run finishes. Nothing needed from the other session — and apologies for the wasted cycle.

@github-actions
github-actions Bot merged commit ea36f9b into main Jul 31, 2026
25 checks passed
@github-actions

Copy link
Copy Markdown

merge-train: merged ea36f9bmain via FF push.

@robotrocketscience robotrocketscience added the ready-to-merge Trigger merge-train: FF main to this PR's head label Jul 31, 2026
@github-actions github-actions Bot removed the ready-to-merge Trigger merge-train: FF main to this PR's head label Jul 31, 2026
@github-actions

Copy link
Copy Markdown

merge-train: merged ea36f9bmain via FF push.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author-Kulili PR coordination mutex

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant