Skip to content

fix(miner): cover worktree-allocator worktree_slots in the right-to-be-forgotten purge#8498

Closed
tryeverything24 wants to merge 2 commits into
JSONbored:mainfrom
tryeverything24:fix-worktree-allocator-8320
Closed

fix(miner): cover worktree-allocator worktree_slots in the right-to-be-forgotten purge#8498
tryeverything24 wants to merge 2 commits into
JSONbored:mainfrom
tryeverything24:fix-worktree-allocator-8320

Conversation

@tryeverything24

Copy link
Copy Markdown
Contributor

What

packages/loopover-miner/lib/worktree-allocator.ts's worktree_slots table carries a repo_full_name column but was absent from purge-cli.ts's right-to-be-forgotten sweep — the same recurring gap class already fixed for other stores in #7091, #6599, and #8009. This wires worktree-allocator into the purge so loopover-miner purge --repo <owner/repo> covers it like every other repo-scoped store.

worktree_slots is a fixed pool of pre-allocated slot rows (slot_index is the primary key; every slot 0..maxConcurrency-1 always exists), not an append-only ledger, so the generic DELETE-based purgeStoreByRepo is the wrong shape — deleting a slot row would shrink the pool and break the ensureSlots/selectFreeSlot invariant. Following governor-state.ts's precedent for a store needing custom purge logic, the purge lives on the store object.

Changes

  • worktree-allocator.ts: add purgeByRepo(repoFullName): number to the WorktreeAllocator type and openWorktreeAllocator's implementation. It uses a hand-written UPDATE (mirroring release()/reclaimOrphanedAllocations()'s own SET ... = NULL statement) that clears the repo only from status = 'free' rows, and never deletes a row and never touches an active slot — an active slot's repo_full_name reflects a live, in-flight attempt's real worktree checkout on disk, and force-clearing it would desync the allocator from that checkout. Both the real UPDATE and the read-only dry-run counter share one match condition (status = 'free' AND repo_full_name = ?) verbatim so they can never diverge. A code comment states explicitly that this purge is expected to affect 0 rows on the overwhelming majority of real calls, by design (every normal release/reclaim path already blanks these fields on free); it is a defensive backstop for a row predating this fix or stranded by an unexpected crash path. Also exports countPurgeableWorktreeSlotsByRepo for the dry-run count path.
  • purge-cli.ts: register worktree-allocator in REAL_PURGE_TARGETS with no spec/specs field (its purge logic lives on the store object), carrying its own status-aware countByRepo counter — exactly mirroring how governor-state's entry carries specs for its own non-uniform case. --dry-run's row-count path counts only status = 'free' AND repo_full_name = ? rows, matching the real purge's match condition exactly so an active-slot row is never reported as purgeable.

Tests

Full branch coverage added in test/unit/miner-worktree-allocator.test.ts and test/unit/miner-purge-cli.test.ts:

  1. A free slot seeded directly with a stale non-null repo_full_name (bypassing the normal acquire/release path) — purged and counted (returns 1).
  2. An active slot for the target repo — left completely untouched, not counted.
  3. No matching rows at all — returns 0.
  4. --dry-run reports the same count the real purge would remove, for both the free-stale-row and active-row cases (dry-run count matches the real purge exactly).

The fixed pool stays intact in every case (no slot row is ever deleted). npm run test:ci stays green.

Closes #8320

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.77%. Comparing base (04d38b6) to head (d53a4b2).
⚠️ Report is 27 commits behind head on main.

Files with missing lines Patch % Lines
packages/loopover-miner/lib/worktree-allocator.ts 0.00% 6 Missing ⚠️
packages/loopover-miner/lib/purge-cli.ts 0.00% 3 Missing ⚠️

❌ Your patch check has failed because the patch coverage (0.00%) is below the target coverage (99.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@             Coverage Diff             @@
##             main    #8498       +/-   ##
===========================================
+ Coverage   59.40%   88.77%   +29.37%     
===========================================
  Files         791       99      -692     
  Lines       79335    22912    -56423     
  Branches    23965     3930    -20035     
===========================================
- Hits        47131    20341    -26790     
+ Misses      28743     2393    -26350     
+ Partials     3461      178     -3283     
Flag Coverage Δ
shard-1 0.00% <0.00%> (?)
shard-2 0.00% <0.00%> (-47.31%) ⬇️
shard-3 0.00% <0.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
packages/loopover-miner/lib/purge-cli.ts 0.00% <0.00%> (ø)
packages/loopover-miner/lib/worktree-allocator.ts 0.00% <0.00%> (-74.79%) ⬇️

... and 692 files with indirect coverage changes

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 24, 2026
@loopover-orb

loopover-orb Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Caution

🛑 LoopOver review result - fixes required

Review updated: 2026-07-24 16:59:21 UTC

5 files · 1 AI reviewer · no blockers · CI failing · unstable

🛑 Suggested Action - Fix Blockers

Review summary
This PR wires worktree-allocator's fixed-pool worktree_slots table into the purge CLI's right-to-be-forgotten sweep, correctly recognizing that the generic DELETE-based purgeStoreByRepo would break the pool invariant and instead adding a custom UPDATE that only clears repo_full_name from free (never active) slots. The shared PURGEABLE_FREE_SLOT_MATCH constant between the real UPDATE and the dry-run counter is a solid design choice that prevents drift, and the regression tests directly verify an active slot is untouched while a stale free slot is cleared. The codecov/patch failures (0.00% diff hit) look spurious given the extensive test additions in this diff across three test files exercising the new purgeByRepo/countPurgeableWorktreeSlotsByRepo paths.

Nits — 4 non-blocking
  • worktree-allocator.ts:270's `PURGEABLE_FREE_SLOT_MATCH` constant embeds the issue number only in a comment, not the code, which is fine, but the file is now ~403 lines and growing dense with purge-specific logic mixed into the core allocator — consider whether purge logic could live in a separate module if it grows further.
  • purge-cli.ts's PurgeTarget type now has three optional fields (spec/specs/countByRepo) with an implicit 'exactly one is set' invariant enforced only by comments and a non-null assertion (`target.spec!`); a discriminated union would let the type system enforce this instead of relying on doc comments.
  • Consider a small type-level refinement in purge-cli.ts (e.g. `{ spec: LedgerPurgeSpec } | { specs: LedgerPurgeSpec[] } | { countByRepo: ... }`) to remove the `target.spec!` non-null assertion at purge-cli.ts and make the 'exactly one' invariant compiler-checked rather than comment-documented.
  • The codecov/patch failure reporting 0.00% hit despite substantial new tests in miner-worktree-allocator.test.ts and miner-purge-cli.test.ts is worth a quick sanity check on the coverage tool config rather than treating it as a real gap, since the diff shows direct assertions against purgeByRepo and countPurgeableWorktreeSlotsByRepo.

CI checks failing

  • codecov/patch — 0.00% of diff hit (target 99.00%)

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #8320
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 84 registered-repo PR(s), 38 merged, 4 issue(s).
Contributor context ✅ Confirmed Gittensor contributor tryeverything24; Gittensor profile; 84 PR(s), 4 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: moderate
Linked issue satisfaction

Addressed
The diff adds purgeByRepo to WorktreeAllocator using a hand-written UPDATE restricted to status='free' rows, registers worktree-allocator in REAL_PURGE_TARGETS via a countByRepo field mirroring governor-state's non-uniform spec precedent, and makes dry-run share the exact same match condition, with tests covering stale-free-row purge, active-row exclusion, zero-match, and dry-run/real-purge parity

Review context
  • Author: tryeverything24
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 84 PR(s), 4 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Keep the PR focused and include validation evidence before maintainer review.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb

loopover-orb Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

LoopOver is closing this pull request on the maintainer's behalf (CI is failing (codecov/patch)). This is an automated maintenance action — to pursue this change, please open a new pull request with the issues resolved. Closed PRs may be analyzed later to improve review accuracy, but they are not automatically reopened or re-reviewed.

@loopover-orb loopover-orb Bot closed this Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(miner): worktree-allocator.ts's worktree_slots (has repo_full_name) is absent from purge-cli.ts's right-to-be-forgotten sweep

1 participant