/**
 * Feature ID Collision Detection Utility
 *
 * CRITICAL (2025-11-26): Prevents FS-XXX vs FS-XXXE collisions
 *
 * Problem: Internal feature IDs (FS-001) were generated without checking
 * if external features (FS-001E) existed with the same numeric index.
 *
 * Solution: Before generating any internal feature ID, check if either
 * FS-XXX or FS-XXXE exists. If collision detected, increment to next available.
 *
 * Usage:
 * ```typescript
 * // Instead of: const featureId = `FS-${num.toString().padStart(3, '0')}`;
 * // Use:
 * const num = await findNextAvailableInternalId(incrementNum, specsPath, projectId);
 * const featureId = `FS-${num.toString().padStart(3, '0')}`;
 * ```
 */
import { Logger } from './logger.js';
/**
 * Options for collision detection
 */
export interface CollisionCheckOptions {
    /** Logger instance for warnings */
    logger?: Logger;
    /** Maximum iterations to prevent infinite loops (default: 1000) */
    maxIterations?: number;
}
/**
 * Find the next available internal feature ID number that doesn't collide
 * with existing internal OR external features.
 *
 * CRITICAL: This function prevents FS-001 vs FS-001E collision by checking
 * if either variant exists before returning a number.
 *
 * CRITICAL FIX (2025-12-04): Now supports hierarchical project paths!
 * - Handles paths like "acme/backend-services" (2-level ADO structure)
 * - Scans _orphans folder for US-XXX files that may reference FS-IDs
 *
 * @param baseNumber - Starting number (typically from increment ID)
 * @param specsPath - Path to specs directory (e.g., .specweave/docs/internal/specs)
 * @param projectPath - Project path for multi-project mode (e.g., "my-project" or "acme/backend")
 * @param options - Optional configuration
 * @returns Next available number that doesn't conflict with existing features
 *
 * @example
 * ```typescript
 * // Increment 0001 would normally generate FS-001
 * // But if FS-001E exists, this returns 2 (for FS-002)
 * const num = await findNextAvailableInternalId(1, specsPath, 'my-project');
 *
 * // Works with hierarchical paths (ADO 2-level structure)
 * const num = await findNextAvailableInternalId(1, specsPath, 'acme-corp/backend-services');
 * ```
 */
export declare function findNextAvailableInternalId(baseNumber: number, specsPath: string, projectPath: string, options?: CollisionCheckOptions): Promise<number>;
/**
 * Synchronous version of findNextAvailableInternalId
 *
 * CRITICAL FIX (2025-12-04): Updated to match async version with:
 * - Support for hierarchical project paths (e.g., "acme/backend")
 * - _orphans folder scanning
 *
 * Use this in synchronous contexts where async isn't available.
 */
export declare function findNextAvailableInternalIdSync(baseNumber: number, specsPath: string, projectPath: string, options?: CollisionCheckOptions): number;
/**
 * Check if a specific numeric index has a collision (either FS-XXX or FS-XXXE exists)
 *
 * CRITICAL FIX (2025-12-04): Now supports hierarchical paths, _orphans and _archive folders
 *
 * @param number - Numeric index to check
 * @param specsPath - Path to specs directory
 * @param projectPath - Project path (may be hierarchical like "acme/backend")
 * @returns Object indicating which variants exist
 */
export declare function checkFeatureIdCollision(number: number, specsPath: string, projectPath: string): {
    internalExists: boolean;
    externalExists: boolean;
    archiveExists: boolean;
    orphanHasId: boolean;
    hasCollision: boolean;
};
/**
 * Find the next available user story ID number that doesn't collide
 * with existing internal OR external user stories.
 *
 * CRITICAL (2025-12-04): Prevents US-001 vs US-001E collision
 * - Scans all FS-XXX folders for us-*.md files
 * - Scans _orphans folder for us-*.md files
 * - Returns the max ID + 1 to avoid collision
 *
 * @param projectSpecsPath - Path to project's specs folder
 * @param options - Optional configuration
 * @returns Next available US-ID number
 *
 * @example
 * ```typescript
 * // If US-001E, US-002E exist in the project, returns 3
 * const nextId = findNextAvailableUSId('/path/to/specs/my-project');
 * ```
 */
export declare function findNextAvailableUSId(projectSpecsPath: string, options?: CollisionCheckOptions): number;
/**
 * Check if a specific US-ID number is already used
 *
 * @param number - US-ID number to check (e.g., 1 for US-001)
 * @param projectSpecsPath - Path to project's specs folder
 * @returns true if either US-XXX or US-XXXE exists
 */
export declare function isUSIdUsed(number: number, projectSpecsPath: string): boolean;
/**
 * Validate increment number uniqueness
 *
 * CRITICAL (2025-12-04): Prevents duplicate increment numbers like:
 * - 0101-judge-llm-command
 * - 0101-llm-json-extraction-hardening
 *
 * This causes chain shifts in living docs sync because each sync sees
 * the other's FS folder as a "collision".
 *
 * @param incrementNumber - Numeric prefix to validate (e.g., 101 for 0101-xxx)
 * @param incrementsPath - Path to increments folder
 * @returns Object with validation result and existing increment name if duplicate found
 */
export declare function validateIncrementNumberUnique(incrementNumber: number, incrementsPath: string): {
    isUnique: boolean;
    existingIncrement?: string;
};
/**
 * Scan for duplicate increment numbers in the increments folder
 *
 * Returns all increment numbers that appear more than once.
 * Useful for detecting existing duplicates that need cleanup.
 *
 * @param incrementsPath - Path to increments folder
 * @returns Map of increment number to array of full increment names
 */
export declare function findDuplicateIncrementNumbers(incrementsPath: string): Map<number, string[]>;
/**
 * Get all FS-ID numbers used by a project across ALL locations.
 *
 * CRITICAL (v1.0.19): For 2-level structures, a project's features may exist in
 * multiple board/container folders:
 *
 * ```
 * specs/
 * ├── jira-board-1/ec-web-ui/FS-001E/   ← Same project in board 1
 * ├── jira-board-2/ec-web-ui/FS-003/    ← Same project in board 2
 * └── ec-web-ui/FS-005/                 ← 1-level fallback location
 * ```
 *
 * This function scans ALL locations and returns the set of used FS-ID numbers.
 *
 * @param specsPath - Path to .specweave/docs/internal/specs
 * @param projectId - Project ID to search for (e.g., "ec-web-ui")
 * @returns Set of used FS-ID numbers (e.g., Set([1, 3, 5]))
 *
 * @example
 * ```typescript
 * const usedIds = getAllProjectFSIds(specsPath, 'ec-web-ui');
 * // Returns Set([1, 3, 5]) if FS-001E, FS-003, FS-005 exist for this project
 * ```
 *
 * @since 1.0.19
 */
export declare function getAllProjectFSIds(specsPath: string, projectId: string): Set<number>;
/**
 * Find next available FS-ID number for a project across ALL locations.
 *
 * Unlike `findNextAvailableInternalIdSync` which checks a single path,
 * this function scans ALL locations where a project's features might exist
 * (both 1-level and 2-level structures).
 *
 * @param baseNumber - Starting number (typically from increment ID)
 * @param specsPath - Path to .specweave/docs/internal/specs
 * @param projectId - Project ID to check (e.g., "ec-web-ui")
 * @param options - Optional configuration
 * @returns Next available number that doesn't conflict
 *
 * @example
 * ```typescript
 * // Project has FS-001E in board-1, FS-002 in board-2
 * const next = findNextAvailableIdForProject(1, specsPath, 'ec-web-ui');
 * // Returns 3 (skips 1 and 2)
 * ```
 *
 * @since 1.0.19
 */
export declare function findNextAvailableIdForProject(baseNumber: number, specsPath: string, projectId: string, options?: CollisionCheckOptions): number;
//# sourceMappingURL=feature-id-collision.d.ts.map