11// `loopover-miner purge` (#5564, #6599): an explicit, operator-invoked right-to-be-forgotten path across the local
22// ledgers. Deletes every row for one repo from the stores that have a real `repoColumn` (claim-ledger,
3- // event-ledger, governor-ledger, prediction-ledger, portfolio-queue, run-state, contribution-profile-cache, and
4- // governor-state's two repo-scoped tables — #7091), via each store's own `purgeByRepo` method (which reuses
3+ // event-ledger, governor-ledger, prediction-ledger, portfolio-queue, run-state, contribution-profile-cache,
4+ // governor-state's two repo-scoped tables — #7091 — plus policy-verdict-cache — #6987 — and ranked-candidates,
5+ // replay-snapshot, and deny-hook-synthesis — #8009), via each store's own `purgeByRepo` method (which reuses
56// `store-maintenance.js`'s shared, identifier-guarded `purgeStoreByRepo`).
67// `attempt-log.js` is deliberately reported as not-purgeable rather than silently skipped or approximated: its
78// payload is a free-form `Record<string, unknown>` with no dedicated repo column, so a precise per-repo match
@@ -30,6 +31,12 @@ import { openGovernorState, resolveGovernorStateDbPath } from "./governor-state.
3031import type { GovernorState } from "./governor-state.js" ;
3132import { initPolicyVerdictCacheStore , resolvePolicyVerdictCacheDbPath } from "./policy-verdict-cache.js" ;
3233import type { PolicyVerdictCacheStore } from "./policy-verdict-cache.js" ;
34+ import { initRankedCandidatesStore , resolveRankedCandidatesDbPath } from "./ranked-candidates.js" ;
35+ import type { RankedCandidatesStore } from "./ranked-candidates.js" ;
36+ import { openReplaySnapshotStore , resolveReplaySnapshotDbPath } from "./replay-snapshot.js" ;
37+ import type { ReplaySnapshotStore } from "./replay-snapshot.js" ;
38+ import { initDenyHookSynthesisStore , resolveDenyHookSynthesisDbPath } from "./deny-hook-synthesis.js" ;
39+ import type { DenyHookSynthesisStore } from "./deny-hook-synthesis.js" ;
3340import { resolveAttemptLogDbPath } from "./attempt-log.js" ;
3441import {
3542 CLAIM_LEDGER_PURGE_SPEC ,
@@ -42,6 +49,9 @@ import {
4249 GOVERNOR_REPUTATION_HISTORY_PURGE_SPEC ,
4350 GOVERNOR_OWN_SUBMISSIONS_PURGE_SPEC ,
4451 POLICY_VERDICT_CACHE_PURGE_SPEC ,
52+ RANKED_CANDIDATES_PURGE_SPEC ,
53+ REPLAY_SNAPSHOT_PURGE_SPEC ,
54+ DENY_HOOK_SYNTHESIS_PURGE_SPEC ,
4555 countStoreByRepo ,
4656 describeError ,
4757} from "./store-maintenance.js" ;
@@ -66,7 +76,10 @@ type PurgeOpenerKey =
6676 | "initRunStateStore"
6777 | "initContributionProfileCache"
6878 | "openGovernorState"
69- | "initPolicyVerdictCacheStore" ;
79+ | "initPolicyVerdictCacheStore"
80+ | "initRankedCandidatesStore"
81+ | "openReplaySnapshotStore"
82+ | "initDenyHookSynthesisStore" ;
7083
7184export type PurgeCliOptions = {
7285 openClaimLedger ?: ( ) => ClaimLedger ;
@@ -78,6 +91,9 @@ export type PurgeCliOptions = {
7891 initContributionProfileCache ?: ( ) => ContributionProfileCache ;
7992 openGovernorState ?: ( ) => GovernorState ;
8093 initPolicyVerdictCacheStore ?: ( ) => PolicyVerdictCacheStore ;
94+ initRankedCandidatesStore ?: ( ) => RankedCandidatesStore ;
95+ openReplaySnapshotStore ?: ( ) => ReplaySnapshotStore ;
96+ initDenyHookSynthesisStore ?: ( ) => DenyHookSynthesisStore ;
8197 resolveDbPaths ?: Record < string , ( ) => string > ;
8298} ;
8399
@@ -102,6 +118,12 @@ const REAL_PURGE_TARGETS: PurgeTarget[] = [
102118 // single handle (never reopening the file), and its dry-run count sums both via `specs` (#7091).
103119 { name : "governor-state" , optionKey : "openGovernorState" , opener : openGovernorState , resolveDbPath : resolveGovernorStateDbPath , specs : [ GOVERNOR_REPUTATION_HISTORY_PURGE_SPEC , GOVERNOR_OWN_SUBMISSIONS_PURGE_SPEC ] } ,
104120 { name : "policy-verdict-cache" , optionKey : "initPolicyVerdictCacheStore" , opener : initPolicyVerdictCacheStore , resolveDbPath : resolvePolicyVerdictCacheDbPath , spec : POLICY_VERDICT_CACHE_PURGE_SPEC } ,
121+ // Three more repo-scoped stores the earlier sweeps missed (#8009). deny-hook-synthesis's dry-run count works
122+ // on both pre- and post-forge-scope files: its live table is `deny_rule_proposals` either way, and the purge
123+ // filters on `repo_full_name` alone (all forge hosts), per its spec's own doc in store-maintenance.js.
124+ { name : "ranked-candidates" , optionKey : "initRankedCandidatesStore" , opener : initRankedCandidatesStore , resolveDbPath : resolveRankedCandidatesDbPath , spec : RANKED_CANDIDATES_PURGE_SPEC } ,
125+ { name : "replay-snapshot" , optionKey : "openReplaySnapshotStore" , opener : openReplaySnapshotStore , resolveDbPath : resolveReplaySnapshotDbPath , spec : REPLAY_SNAPSHOT_PURGE_SPEC } ,
126+ { name : "deny-hook-synthesis" , optionKey : "initDenyHookSynthesisStore" , opener : initDenyHookSynthesisStore , resolveDbPath : resolveDenyHookSynthesisDbPath , spec : DENY_HOOK_SYNTHESIS_PURGE_SPEC } ,
105127] ;
106128
107129export type ParsedPurgeArgs = { json : boolean ; dryRun : boolean ; repoFullName : string } | { error : string } ;
0 commit comments