/**
 * Epic ID Allocator - Intelligent Epic ID allocation with chronological placement
 *
 * Allocates EP-XXX IDs for external work items (ADO Capabilities, Strategic Themes)
 * based on creation date, attempting chronological insertion while preventing collisions.
 *
 * CRITICAL: Epics are stored PER-PROJECT in {project}/_epics/ folders,
 * NOT at the root level. Each project has its own epic namespace.
 *
 * Features:
 * - Per-project epic storage: {project}/_epics/EP-XXX/
 * - Chronological ID allocation based on work item creation date
 * - Gap filling (insert EP-011E between EP-010 and EP-020)
 * - Append mode fallback (max ID + 1)
 * - Collision detection (checks both EP-XXX and EP-XXXE)
 * - Archive-aware (scans both active and archived epics)
 *
 * @module living-docs/epic-id-allocator
 * @version 0.30.3
 */
import { type ExternalItemMetadata } from '../core/types/origin-metadata.js';
import type { ExternalContainerContext } from '../core/types/increment-metadata.js';
import { Logger } from '../utils/logger.js';
/**
 * Epic metadata extracted from living docs
 */
export interface EpicMetadata {
    /** Epic ID (e.g., "EP-042", "EP-042E") */
    id: string;
    /** Epic creation timestamp (ISO 8601) */
    createdAt: string;
    /** Origin (internal | external) */
    origin: 'internal' | 'external';
    /** External ID if external origin */
    externalId?: string;
    /** Path to epic folder */
    path: string;
}
/**
 * External work item to be allocated an EP-ID (Capability, Strategic Theme, etc.)
 */
export interface ExternalEpicItem {
    /** External ID (e.g., "ADO-123", "JIRA-THEME-456") */
    externalId: string;
    /** Epic title */
    title: string;
    /** Creation timestamp (ISO 8601) */
    createdAt: string;
    /** External URL */
    externalUrl: string;
    /** Original work item type (Capability, Strategic Theme, etc.) */
    workItemType?: string;
}
/**
 * Epic ID allocation result
 */
export interface EpicAllocationResult {
    /** Allocated EP-ID (e.g., "EP-042E") */
    id: string;
    /** Allocation strategy used */
    strategy: 'chronological-insert' | 'append' | 'first';
    /** Reason for allocation decision */
    reason: string;
    /** Numeric ID value */
    number: number;
}
/**
 * Epic ID Allocator Options
 */
export interface EpicIdAllocatorOptions {
    /** Enable global collision detection across ALL projects (umbrella mode) */
    globalCollisionDetection?: boolean;
    /**
     * External container context for 2-level directory structure
     */
    externalContainer?: ExternalContainerContext;
    /** Logger instance (defaults to consoleLogger) */
    logger?: Logger;
}
/**
 * Epic ID Allocator
 *
 * Intelligently allocates Epic IDs with chronological placement.
 *
 * CRITICAL: Epics are stored PER-PROJECT in {project}/_epics/ folders.
 * Structure: specs/{projectId}/_epics/EP-XXX/EPIC.md
 *
 * In umbrella/multi-repo setups, enable globalCollisionDetection
 * to prevent ID collisions like EP-001 in one repo and EP-001E in another.
 */
export declare class EpicIdAllocator {
    private projectRoot;
    private specsPath;
    private projectId;
    private epicsPath;
    private existingEpics;
    private scanned;
    private globalCollisionDetection;
    private externalContainer;
    private logger;
    /**
     * Create an Epic ID Allocator for a specific project
     *
     * @param projectRoot - Root directory of the SpecWeave project
     * @param projectId - Project ID (e.g., "acme", "parent"). Required for per-project epics.
     * @param options - Optional configuration
     */
    constructor(projectRoot: string, projectId: string, options?: EpicIdAllocatorOptions);
    /**
     * Get base directory for epics, handling both 1-level and 2-level structures
     *
     * Mirrors FSIdAllocator.getBaseDirectory() for consistency:
     * - 2-level (JIRA): specs/JIRA-{containerId}/{projectId}/
     * - 2-level (ADO): specs/{containerId}/{projectId}/ (no ADO- prefix)
     * - 1-level (GitHub): specs/{projectId}/
     *
     * IMPORTANT: For 2-level structure, epics ALWAYS go in the inner folder (board/area level),
     * even when containerDirName == projectId (e.g., specs/my-project/my-project/).
     * This is correct because the outer folder is PROJECT level, inner is BOARD level.
     */
    private getBaseDirectory;
    /**
     * Get the project ID this allocator is configured for
     */
    getProjectId(): string;
    /**
     * Get the epics path for this project
     */
    getEpicsPath(): string;
    /**
     * Scan existing EP-IDs (both active and archived)
     *
     * CRITICAL: Archives are scanned to prevent ID reuse
     *
     * Structure (per-project):
     * - {project}/_epics/EP-XXX/
     * - {project}/_epics/_archive/EP-XXX/
     */
    scanExistingIds(): Promise<void>;
    /**
     * Scan directory for EP-XXX folders
     */
    private scanDirectory;
    /**
     * Parse epic metadata from EPIC.md frontmatter
     */
    private parseEpicMetadata;
    /**
     * Allocate EP-ID for external work item with chronological placement
     *
     * Algorithm:
     * 1. Sort existing IDs by creation date
     * 2. Find chronological insertion point based on work item creation date
     * 3. Check for ID gaps between consecutive epics
     * 4. If gap exists, allocate next ID in gap (e.g., EP-011E between EP-010 and EP-020)
     * 5. If no gap, append to end (max ID + 1 with E suffix)
     *
     * CRITICAL: Unified numeric sequence - EP-XXX and EP-XXXE never share same index
     *
     * @param workItem - External epic item to allocate ID for
     * @returns Allocation result with ID and strategy
     */
    allocateId(workItem: ExternalEpicItem): Promise<EpicAllocationResult>;
    /**
     * Track a newly allocated ID to prevent duplicates in the same session
     */
    private trackAllocatedId;
    /**
     * Check if ID has collision (exact match or variant)
     */
    hasCollision(id: string): boolean;
    /**
     * Get maximum numeric ID value (ignoring E suffix)
     */
    getMaxId(): number;
    /**
     * Extract numeric part from EP-ID
     */
    private extractNumber;
    /**
     * Find which epic ID is using a numeric index
     */
    private findCollidingId;
    /**
     * Get all existing epic IDs (sorted by creation date)
     */
    getExistingEpics(): EpicMetadata[];
    /**
     * Get allocation statistics
     */
    getStats(): {
        total: number;
        active: number;
        archived: number;
        internal: number;
        external: number;
        maxId: number;
    };
    /**
     * Create epic folder with EPIC.md and metadata
     *
     * Structure (per-project):
     * - {project}/_epics/EP-XXX/EPIC.md
     *
     * @param epId - Epic ID (e.g., "EP-042E")
     * @param workItem - External epic item metadata
     * @param metadata - External item metadata for origin tracking
     * @returns Path to created epic folder
     */
    createEpicFolder(epId: string, workItem: ExternalEpicItem, metadata: ExternalItemMetadata): Promise<string>;
}
//# sourceMappingURL=epic-id-allocator.d.ts.map