import { type AmendCandidateReport } from "./amend-candidates.js"; import { type RelationDedupReport } from "./relation-dedup.js"; import type { Archiver } from "./archiver.js"; import type { GraphEngine } from "./graph.js"; import { type StaleItem } from "./staleness.js"; import { type ArchiveCompactionReport } from "./archive-compactor.js"; import type { IBlackboardStore, IDecisionStore } from "../storage/interfaces.js"; import { type EntityScopeRepairReport } from "./entity-scope-repair.js"; export interface StaleProvisional { id: string; summary: string; scope: string; age_days: number; } export interface DanglingWarning { id: string; summary: string; scope: string; age_days: number; } export interface HousekeepingResult { /** Report-only amend candidates (re-scoped field D13 ask 1); write path is twining_amend. */ amend_candidates?: AmendCandidateReport; /** Set when amend_candidates was requested but could not run — never a silent no-op. */ amend_candidates_error?: string; /** Legacy duplicate-relation dedup (wave-2 follow-up); preview unless execute. */ relation_dedup?: RelationDedupReport; /** Set when dedup_relations was requested but could not run — never a silent no-op. */ relation_dedup_error?: string; /** Files-backend index-desync repair (S0-index-desync); preview unless execute. */ index_repair?: { orphans_found: number; orphan_ids: string[]; repaired: number; /** Orphans not salvaged: unparseable, or parseable but not recognizably * a decision matching its filename (execute only; never modified). */ skipped_invalid: number; }; /** Set when repair_index was requested but could not run — never a silent no-op. */ index_repair_error?: string; /** sqlite only, execute only: whether wal_checkpoint(TRUNCATE) ran (S4-7). */ wal_checkpointed?: boolean; archived: { count: number; file: string; kept_open: number; }; deduplicated: { removed: number; }; stale_provisionals: { count: number; items: StaleProvisional[]; }; promoted_provisionals: { count: number; ids: string[]; }; dangling_warnings: { count: number; items: DanglingWarning[]; }; graph_pruned: { removed: number; }; metrics_rotated: { removed: number; }; superseded_backfill: { fixed: number; dangling: number; items: Array<{ id: string; superseded_by: string; }>; }; staleness_review?: { threshold: number; candidates: StaleItem[]; }; merge_sweep?: { initial_record: boolean; enumerated: boolean; current_branches: string[]; deleted_branches: string[]; since: string | null; candidates: Array<{ id: string; kind: "decision" | "blackboard"; summary: string; scope: string; branch: string; commit_sha?: string; recorded_at?: string; }>; }; archive_compaction?: ArchiveCompactionReport; entity_scope_repair?: EntityScopeRepairReport; dry_run: boolean; summary: string; } export declare class HousekeepingEngine { private readonly twiningDir; private readonly blackboardStore; private readonly decisionStore; private readonly archiver; private readonly graphEngine; private readonly projectRoot; private readonly stalenessThreshold; /** Newest-K retention for the opt-in archive pass (config archive.retain_recent). */ private readonly archiveRetain; /** sqlite only: raw handle for the execute-path WAL checkpoint (S4-7). */ private readonly db; constructor(twiningDir: string, blackboardStore: IBlackboardStore, decisionStore: IDecisionStore, archiver: Archiver, graphEngine: GraphEngine | null, projectRoot?: string | null, stalenessThreshold?: number, /** Newest-K retention for the opt-in archive pass (config archive.retain_recent). */ archiveRetain?: number, /** sqlite only: raw handle for the execute-path WAL checkpoint (S4-7). */ db?: import("../storage/sqlite/db.js").SqliteDatabase | null); run(options?: { stale_days?: number; metrics_retention_days?: number; execute?: boolean; promote_provisionals?: boolean; staleness_review?: boolean; merge_sweep?: boolean; /** * Report candidate affected_files for active decisions with empty * lists (scope walk + term overlap). ALWAYS report-only — execute has * no effect; confirm per record with twining_amend. */ amend_candidates?: boolean; /** * Dedup legacy duplicate (source, target, type) graph relations — * survivor is the edge live upserts already merge into (seq-first; the * created-at-oldest on the file backend); properties fold in under * origin precedence. Duplicates with non-unique ids and groups whose * fold fails are skipped and counted in the report. Preview unless * execute is set. */ dedup_relations?: boolean; /** * Files-backend only: detect decision files on disk missing from * decisions/index.json (they are invisible to every index-driven read * path) and, with execute, append salvaged entries to the index. */ repair_index?: boolean; compact_archives?: boolean; /** * Recompute graph entity scopes from their decided_by relations, undoing * the pre-fix last-writer-wins overwrite. Dry-run unless execute is set. */ repair_entity_scopes?: boolean; /** * Set true to run the blackboard archive pass (step 1). OFF BY DEFAULT * since D4: the pass takes no age cutoff, so on `execute: true` it used * to sweep the whole live board as a side effect of any maintenance * call — an agent reaching for the `compact_archives` repair got a * full-board archive it never asked for. When enabled, the sweep * retains the newest `archive.retain_recent` entries (constructor). */ archive?: boolean; }): Promise; } //# sourceMappingURL=housekeeping.d.ts.map