Skip to content

feat(dig-node): tier-0 knapsack selector + sub-budget + hysteresis - #152

Merged
MichaelTaylor3d merged 2 commits into
mainfrom
feat/tier0-knapsack-selector
Aug 2, 2026
Merged

feat(dig-node): tier-0 knapsack selector + sub-budget + hysteresis#152
MichaelTaylor3d merged 2 commits into
mainfrom
feat/tier0-knapsack-selector

Conversation

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor

Closes DIG-Network/dig_ecosystem#1988 — child 3/7 of the tiered relevance-cache epic (dig_ecosystem#1934). Builds on child 1 (relevance() / should_displace(), merged 9fff0cdc).

What changed

New pure module crates/dig-node-core/src/tier0_selector.rs (pub mod tier0_selector; in lib.rs) — the tier-0 selection brain, no I/O:

  • Candidate { size_bytes, relevance } + select_within_budget(...) — 0/1 knapsack via greedy value-density (value ÷ size), O(n log n) (WHY-commented: near-optimal on a GiB-scale budget, DP is wasteful there). size_bytes == 0 handled defensively (no divide-by-zero).
  • tier0_budget_bytes(cache_cap) — the tier-0 sub-budget = a FRACTION of the whole cache cap (TIER0_BUDGET_FRACTION = 10%, overridable), never the whole cap, so eager precache can't starve demand-driven tiers. The selected set's total size never exceeds it.
  • should_displace_tier0(...) — thin wrapper over child 1's should_displace with DEFAULT_HYSTERESIS_MARGIN = 0.05, so a marginally-better candidate doesn't displace an incumbent (churn control).

Also fixes the two cosmetic comment-accuracy nits deferred from child 1 in relevance.rs (attacker-gameable-only sum wording; hi128 / u128::MAX) — comment text only, no behaviour change (relevance's 11 unit tests unchanged/green).

Scope is only the pure selector — no DHT sampling (child 2), no prefetch loop (child 4), no live-cache wiring.

How verified

  • cargo fmt --all -- --check → clean; cargo clippy -p dig-node-core --all-targets --all-features -- -D warnings → exit 0; cargo build -p dig-node-core → green.
  • cargo test -p dig-node-core --lib tier0_selector5/5 (greedy-optimal subset, budget fraction, budget-never-exceeded, zero-size no-divide, hysteresis margin). relevance 11/11 unchanged.
  • Coverage (cargo llvm-cov -p dig-node-core --lib): tier0_selector.rs100%; crate total 86.34% lines — above the 80% floor.

Note: 9 peer::tests::* / dual_stack_bind_* / pool-status tests fail in the CI sandbox used for local dev because it can't bind sockets — they are pre-existing and unrelated (reproduced one in isolation; none touch relevance/tier0_selector). Real CI runners bind sockets, so they run normally here.

Version

dig-node-core 0.27.0 → 0.28.0 (MINOR — new export); root [workspace.package].version 0.76.0 → 0.77.0 (the version-increment gate reads the root); Cargo.lock regenerated. SPEC.md §7.10b adds the normative selector/budget/hysteresis contract.


Generated by Claude Code

Add tier0_selector: a pure, deterministic module that picks which
speculative-precache candidates are worth keeping under a small
sub-budget of DIG_NODE_CACHE_CAP, reusing relevance()/RelevanceValue/
should_displace from the child-1 relevance module rather than
reimplementing scoring or hysteresis.
- Candidate{size_bytes, relevance} + select_within_budget: O(n log n)
greedy by value-density (relevance/size), never exceeding the given
budget. Deliberately greedy, not DP: at GiB-scale budgets a DP table
is disproportionate, and greedy under-fills by at most one
candidate's size.
- tier0_budget_bytes: TIER0_BUDGET_FRACTION (0.10) of the whole cache
cap, pure arithmetic over a caller-supplied cap (no I/O in this
module).
- should_displace_tier0: thin named wrapper over should_displace with
the selector's own DEFAULT_HYSTERESIS_MARGIN, so a marginally-better
candidate cannot displace an incumbent and thrash fetch/evict/refetch.
Also fixes two comment-accuracy nits left over from child #1 in
relevance.rs: the xor-weight-dominance comment now states it exceeds
only the ATTACKER-GAMEABLE secondaries (scarcity+demand+recency=0.85),
excluding the operator-controlled pin/pin_adjacent bonuses; the
proximity-map comment now says `hi128 / u128::MAX` to match what the
code actually divides by. No behaviour change.
Bumps: crates/dig-node-core 0.27.0 -> 0.28.0 (MINOR, new export) and
the root workspace [workspace.package].version (the released dig-node
binary) 0.76.0 -> 0.77.0 (MINOR), with Cargo.lock regenerated to match.
Co-Authored-By: Claude <noreply@anthropic.com>
Add SPEC.md §7.10b normativley describing tier0_selector's contract
(the 10% sub-budget, greedy-by-density selection, and the hysteresis
reuse of should_displace) alongside §7.10a's relevance model. Also
applies the rustfmt ordering rustfmt itself wants for the new
`pub mod tier0_selector;` declaration in lib.rs.
Co-Authored-By: Claude <noreply@anthropic.com>
@MichaelTaylor3d
MichaelTaylor3d merged commit a7af1b5 into mainAug 2, 2026
15 checks passed
@MichaelTaylor3d
MichaelTaylor3d deleted the feat/tier0-knapsack-selector branch August 2, 2026 21:28
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@MichaelTaylor3d@claude