import { type GitRunner } from './project.js';
/**
 * The maintenance sweep (#298): a background job that walks the registered repos,
 * finds the commits each repo has grown since its last maintenance review, and runs
 * the maintainability loop on them. Per-repo review state is a small local file
 * (`.the-framework/maintenance.json`, gitignored) recording the last-reviewed commit,
 * so a sweep only ever acts on new work. The capacity gate is the existing budget cap
 * (`--max-cost`). #298's "check the limit" half is reachable after all — the agent
 * reports the account's quota per turn (#517) and on demand (#521) — but this sweep
 * does not gate on it yet; that is #519's consumption limits.
 */
/** The per-repo review-state filename under `.the-framework/`. */
export declare const MAINTENANCE_FILE = "maintenance.json";
/** What a repo's last maintenance review recorded. */
export interface MaintenanceState {
    /** The HEAD commit the maintenance loop last reviewed (a full SHA). */
    reviewedSha?: string;
    /** ISO timestamp of that review. */
    reviewedAt?: string;
    /**
     * ISO timestamp of the last automatic codebase-wide sweep (#882). Deliberately separate
     * from {@link MaintenanceState.reviewedAt}: that one tracks how far the commit-delta sweep
     * (#298) has read, and this one paces a whole-codebase pass that ignores commits entirely.
     * Sharing a key would make either feature silently reset the other's schedule.
     */
    sweptAt?: string;
}
/**
 * How long a repo is left alone between automatic codebase-wide sweeps (#882).
 *
 * A week, and deliberately not configurable: per #879 the answer to "should this have a
 * setting?" is no unless a setting earns itself. The sweep only queues follow-up entries and
 * only runs on an idle machine under its quota boundary, so the cost of it being a little too
 * eager is a backlog entry, not a bill.
 */
export declare const DEFAULT_MAINTENANCE_INTERVAL_MS: number;
/**
 * Whether a repo is due an automatic sweep: never swept, or swept longer ago than the interval.
 *
 * A never-swept repo is due immediately, which is the case #882 exists for. The commit-delta
 * sweep (#298) treats a first-seen repo the opposite way, baselining it at HEAD so its whole
 * pre-existing history is never reviewed, and that is precisely the gap this closes.
 *
 * An unparseable timestamp counts as due: a repo whose state file was hand-edited into nonsense
 * should get swept, not fall silently out of the schedule forever.
 */
export declare function maintenanceDue(state: MaintenanceState, now: number, intervalMs?: number): boolean;
/** Minimal fs seam so the state IO is unit-testable without touching disk. */
export interface MaintenanceFs {
    read(path: string): Promise<string>;
    write(path: string, contents: string): Promise<void>;
    mkdir(path: string): Promise<void>;
}
/** The review-state file path for a repo. */
export declare function maintenanceStatePath(cwd: string): string;
/** Read a repo's review state. Forgiving: a missing/unreadable/malformed file yields `{}`. */
export declare function readMaintenanceState(cwd: string, fs?: MaintenanceFs): Promise<MaintenanceState>;
/** Record a repo's review state, creating `.the-framework/` as needed. */
export declare function writeMaintenanceState(cwd: string, state: MaintenanceState, fs?: MaintenanceFs): Promise<void>;
/**
 * Record part of a repo's state, leaving the keys not mentioned alone.
 *
 * Load-bearing since #882: {@link writeMaintenanceState} replaces the file wholesale, and two
 * features now write it. The commit-delta sweep (#298) writes `reviewedSha`/`reviewedAt` and the
 * automatic sweep writes `sweptAt`, so a wholesale write from either one would silently reset the
 * other's schedule.
 */
export declare function mergeMaintenanceState(cwd: string, patch: MaintenanceState, fs?: MaintenanceFs): Promise<void>;
/** What the sweep decided for one repo. */
export type MaintenanceAction = 'baseline' | 'review' | 'skip' | 'error';
/** A repo's assessed maintenance status. */
export interface RepoReview {
    /** Registry id, when assessed from the registry. */
    id?: string;
    /** Absolute repo path. */
    path: string;
    /** Current HEAD SHA, when resolvable. */
    headSha?: string;
    /** The last-reviewed SHA, when the repo has been reviewed before. */
    reviewedSha?: string;
    /** Commits in `reviewedSha..HEAD` (0 for a first-seen or up-to-date repo). */
    newCommits: number;
    /** What to do: baseline a first-seen repo, review new commits, skip an up-to-date one, or an error. */
    action: MaintenanceAction;
    /** Context for an `error` or an unusual `review` (e.g. rewritten history). */
    note?: string;
}
/**
 * Assess one repo: resolve HEAD, read its review state, and count the commits since
 * the last review. A never-reviewed repo is `baseline` (we record HEAD without
 * reviewing history retroactively); an unchanged repo is `skip`; new commits are
 * `review`. A non-repo / missing git is `error` (skipped, never throws). A reviewed
 * SHA git no longer knows (rebased away) falls back to `review`.
 */
export declare function assessRepo(path: string, git?: GitRunner, fs?: MaintenanceFs): Promise<RepoReview>;
/** Assess every registered repo, tagging each review with its registry id. */
export declare function planMaintenanceSweep(repos: readonly {
    id?: string;
    path: string;
}[], git?: GitRunner, fs?: MaintenanceFs): Promise<RepoReview[]>;
/** The tally a sweep returns. */
export interface SweepSummary {
    reviewed: number;
    baselined: number;
    skipped: number;
    failed: number;
    /** Repos not reached because `maxRepos` was hit. */
    pending: number;
}
/** Injected effects for {@link maintainSweep}, so the orchestration is testable off disk/process. */
export interface SweepDeps {
    /** Run the maintenance loop on a repo; resolves true on success. */
    agent(review: RepoReview): Promise<boolean>;
    /** Persist a repo's review state (called after a baseline or a successful review). */
    record(path: string, state: MaintenanceState): Promise<void>;
    /** Progress line. */
    log(message: string): void;
    /** ISO timestamp for a recorded review (injected so runs are deterministic in tests). */
    now(): string;
    /** Stop after reviewing this many repos in one sweep (baselines/skips don't count). */
    maxRepos?: number;
}
/**
 * Orchestrate a sweep over pre-assessed reviews: baseline first-seen repos (record
 * HEAD, no run), skip up-to-date ones, and run the maintenance loop on the rest —
 * recording the reviewed SHA only when the agent succeeds, so a failure is retried next
 * sweep. Honors `maxRepos`; the remainder is reported as `pending`.
 */
export declare function maintainSweep(reviews: readonly RepoReview[], deps: SweepDeps): Promise<SweepSummary>;
/** Short SHA for logs. */
export declare function short(sha: string | undefined): string;
//# sourceMappingURL=maintenance.d.ts.map