/**
 * Increment Archiver - Smart archiving system for completed increments
 *
 * Keeps the increments folder clean by archiving old/completed increments
 * while preserving active work and maintaining full history.
 */
import { Logger } from '../../utils/logger.js';
export interface ArchiveOptions {
    keepLast?: number;
    strictLast?: number;
    olderThanDays?: number;
    archiveCompleted?: boolean;
    preserveActive?: boolean;
    dryRun?: boolean;
    increments?: string[];
    pattern?: string;
}
export interface ArchiveResult {
    archived: string[];
    skipped: string[];
    errors: string[];
    totalSize: number;
}
export declare class IncrementArchiver {
    private logger;
    private config;
    private rootDir;
    private incrementsDir;
    private archiveDir;
    private abandonedDir;
    constructor(rootDir: string, options?: {
        logger?: Logger;
    });
    /**
     * Archive increments based on options
     *
     * CRITICAL FIX (2025-11-26): --keep-last N now means "exactly N increments remain"
     *
     * Previous bug: External sync protection would ADD exceptions on top of keepLast,
     * resulting in more than N increments remaining. Now we use a "greedy archive"
     * algorithm that archives from oldest until exactly N remain.
     *
     * Algorithm:
     * 1. Sort all increments by number (oldest first)
     * 2. Calculate how many need to remain: keepLast (or apply other filters)
     * 3. Walk from oldest, archiving each eligible increment
     * 4. Protected increments (external sync, active) count toward the "remaining" quota
     * 5. Stop when exactly keepLast increments remain
     */
    archive(options?: ArchiveOptions): Promise<ArchiveResult>;
    /**
     * Archive specific increments by ID
     */
    private archiveSpecificIncrements;
    /**
     * Archive increments matching a pattern
     */
    private archiveByPattern;
    /**
     * Archive increments older than N days
     */
    private archiveByAge;
    /**
     * Archive with --keep-last N semantics
     *
     * v0.30.0 CRITICAL FIX: "keep last 5" means "keep the 5 HIGHEST-NUMBERED increments"
     * v0.33.0 CRITICAL FIX: External increments (E suffix) are SEPARATE from internal!
     *
     * Previous bug: Counted only active increments. If 5 active with gaps (0072, 0085-0088),
     * nothing would archive because 5 <= 5.
     *
     * v0.33.0 bug fix: parseInt("0118E") → 118, losing E suffix! This caused 0118E
     * to be treated as same number as 0118, potentially archiving the wrong one.
     *
     * NEW Algorithm:
     * 1. Get ALL increment KEYS (number + E suffix) to find the global "last N"
     * 2. Extract key using extractIncrementKey() which preserves E suffix
     * 3. Calculate which keys should remain: the N highest by number (E variants separate)
     * 4. Archive any active increment NOT in that list
     * 5. Protected increments (external sync) are SKIPPED but logged as needing attention
     */
    private archiveWithKeepLast;
    /**
     * Extract increment key from increment name
     *
     * Preserves the E suffix for external increments!
     * - "0118-my-feature" → "0118"
     * - "0118E-external-issue" → "0118E"
     *
     * CRITICAL (v0.33.0): This is NOT the same as parseInt()!
     * parseInt("0118E") → 118 (WRONG - loses E)
     * extractIncrementKey("0118E-name") → "0118E" (CORRECT)
     */
    private extractIncrementKey;
    /**
     * STRICT archive: Keep exactly last N increments, ignoring ALL protections
     *
     * This mode:
     * - Ignores external sync status (GitHub issues, JIRA tickets, ADO work items)
     * - Ignores active/paused status
     * - Ignores uncommitted changes
     * - Archives EVERYTHING except the last N by increment number
     *
     * Use when you want a clean folder with exactly N increments, no exceptions.
     */
    private archiveStrictLast;
    /**
     * Try to archive a single increment, handling all checks
     * Returns { archived: boolean, error: boolean }
     */
    private tryArchiveIncrement;
    /**
     * Get all increment directories (excluding _archive and _abandoned)
     */
    private getIncrements;
    /**
     * Determine if an increment should be archived
     */
    private shouldArchive;
    /**
     * Archive a single increment
     *
     * CRITICAL FIX (2025-12-07): Sync to living docs BEFORE moving to archive!
     *
     * Previous bug: Living docs were only reorganized (moved) after archive, but
     * content was never synced. If feature folder didn't exist, nothing got archived.
     *
     * Flow now:
     * 1. SYNC: Create/update living docs from spec.md (while increment is active)
     * 2. MOVE: Move increment to _archive/
     * 3. ARCHIVE: Move feature folder to _archive/ (if all increments archived)
     */
    private archiveIncrement;
    /**
     * Sync increment to living docs BEFORE archiving
     *
     * CRITICAL: This must happen while the increment is still in the active folder!
     * LivingDocsSync.syncIncrement() checks for active folder location and skips
     * if increment is already archived.
     *
     * This ensures:
     * - Feature folder exists in living docs
     * - FEATURE.md has latest content
     * - User story files are created/updated
     * - Tasks are synced to living docs
     */
    private syncToLivingDocsBeforeArchive;
    /**
     * Get metadata for an increment
     */
    private getMetadata;
    /**
     * Check if increment has uncommitted changes
     */
    private hasUncommittedChanges;
    /**
     * Update references after archiving
     */
    private updateReferences;
    /**
     * Update references after restoring (mirror of archiving behavior)
     *
     * When an increment is restored from archive, check if its linked feature
     * is also in the archive. If so, restore the feature to maintain consistency
     * between increments and living docs.
     */
    private updateReferencesOnRestore;
    /**
     * Calculate total size of archived increments
     */
    private calculateSize;
    /**
     * Get directory size recursively
     */
    private getDirectorySize;
    /**
     * Restore an increment from archive
     */
    restore(increment: string): Promise<void>;
    /**
     * List archived increments
     */
    listArchived(): Promise<string[]>;
    /**
     * Get feature ID for an increment (explicit or inferred)
     *
     * Priority:
     * 1. Explicit linkage (feature_id or epic in frontmatter)
     * 2. Auto-inferred from increment number (0041 → FS-041)
     */
    private getFeatureIdForIncrement;
    /**
     * Infer feature ID from increment number
     *
     * Examples:
     * - "0041-living-docs-test-fixes" → "FS-041"
     * - "0123-my-feature" → "FS-123"
     * - "0111E-external-issue" → "FS-111E" (external increment → external feature)
     * - "temp-experiment" → null (no number)
     *
     * CRITICAL (v0.33.0): External increments (with E suffix like 0111E-...)
     * MUST map to external features (FS-111E), not internal ones (FS-111).
     */
    private inferFeatureIdFromIncrement;
    /**
     * Get archive statistics
     */
    getStats(): Promise<{
        active: number;
        archived: number;
        abandoned: number;
        totalSize: number;
        oldestActive: string | null;
        newestArchived: string | null;
    }>;
}
//# sourceMappingURL=increment-archiver.d.ts.map