import type { FileOperationResult } from "../core/config.js";
import type { ICopyStrategy, StrategyContext } from "./strategy.interface.js";
/**
 * Implements tagged merge strategy for JSON files with comment-based section control
 * @remarks
 * Supports three tag behaviors:
 * - `//lisa-force-*`: Lisa replaces entire section, project changes ignored (for governance)
 * - `//lisa-defaults-*`: Lisa provides values, project can override (for sensible defaults)
 * - `//lisa-merge-*`: For arrays - combine Lisa's + project's items deduplicated (for shared lists)
 *
 * Tag format: `//lisa-<behavior>-<category>` with matching `//end-lisa-<behavior>-<category>`
 *
 * Order preservation: JSON key ordering is maintained throughout the merge process,
 * ensuring deterministic output and minimal diff noise when configs change.
 */
export declare class TaggedMergeStrategy implements ICopyStrategy {
    readonly name: "tagged-merge";
    /**
     * Produce the exact tagged-merge result without filesystem access.
     * @param source - Lisa tagged template object
     * @param destination - Existing host object
     * @returns Merged object preserving host-owned sections
     */
    mergeJson(source: Record<string, unknown>, destination: Record<string, unknown>): Record<string, unknown>;
    /**
     * Regex pattern for parsing opening tags
     * @remarks Captures behavior (force|defaults|merge) and category name for routing to appropriate merge logic
     */
    private readonly tagPattern;
    /**
     * Apply tagged merge strategy to a JSON file
     * @param sourcePath - Absolute path to Lisa template JSON file with tags
     * @param destPath - Absolute path to project JSON file to merge into
     * @param relativePath - Project-relative path for logging
     * @param context - Strategy context with config and backup functions
     * @returns Operation result indicating copied, skipped, or merged action
     * @throws JsonMergeError if source or destination JSON cannot be parsed
     * @remarks
     * When destination doesn't exist, copies source directly. When destination exists,
     * performs tagged merge preserving project customizations outside tagged sections.
     */
    apply(sourcePath: string, destPath: string, relativePath: string, context: StrategyContext): Promise<FileOperationResult>;
    /**
     * Merge source and destination JSON using tagged sections
     * @param source - Lisa template JSON containing tag markers and governed content
     * @param dest - Project JSON with potential customizations to preserve
     * @returns Merged JSON with tagged sections applied according to their behavior types
     * @remarks
     * Processing supports tags at any nesting level. For each tagged section (whether at
     * top level or nested in an object), applies its behavior rules. Order of processing:
     * 1) Process all tagged sections from source recursively, applying their behaviors
     * 2) Add unprocessed content from destination (preserves project customizations)
     * 3) Add any remaining unprocessed tags from source
     * This ensures governance while preserving project-specific additions outside tagged regions.
     */
    private mergeWithTags;
    /**
     * Process an object that might contain nested tags
     * @param key - The key of the object to process
     * @param source - Source object containing the nested object
     * @param dest - Destination object containing potential counterpart
     * @param result - Result object being built
     * @param processed - Set of processed keys
     */
    private processNestedTaggedObject;
    /**
     * Check if a value is a plain object (not array, null, or primitive)
     * @param value - Value to check
     * @returns True if value is a plain object
     */
    private isPlainObject;
    /**
     * Check if an object contains any nested tags
     * @param obj - Object to check
     * @returns True if object has opening tags as properties
     */
    private hasNestedTags;
    /**
     * Get the destination object for a key, or empty object if not found
     * @param dest - Destination object
     * @param key - Key to look for
     * @returns Destination object or empty object
     */
    private getDestinationObject;
    /**
     * Merge an object that may contain nested tags
     * @param source - Source object potentially containing tags
     * @param dest - Destination object to merge with
     * @returns Merged object with tags applied appropriately
     */
    private mergeObjectWithNestedTags;
    /**
     * Preserve project customizations by adding untagged destination content to result
     * @param result - Result object being built
     * @param dest - Project JSON containing potential customizations
     * @param processed - Keys already processed via tagged sections (to avoid duplicates)
     * @param processedTags - Tag keys already processed (to avoid duplicates)
     * @remarks
     * This is the key step that preserves project freedom: any content outside tagged
     * regions is copied from the project's file unchanged, allowing custom scripts,
     * dependencies, or configs that Lisa doesn't govern.
     */
    private addUnprocessedContent;
    /**
     * Add any remaining tag keys from source that weren't part of complete tag pairs
     * @param result - Result object being built
     * @param source - Lisa template JSON
     * @param processedTags - Tag keys already processed as part of complete sections
     * @param processed - Content keys already processed
     * @remarks
     * Handles edge case of orphaned tags (e.g., opening tag without closing tag)
     * by preserving them in output rather than silently dropping them.
     */
    private addUnprocessedTags;
    /**
     * Process a single tagged section, routing to appropriate behavior handler
     * @param key - Opening tag key (e.g., `//lisa-force-scripts`)
     * @param source - Lisa template JSON
     * @param dest - Project JSON
     * @param sourceTags - Map of all parsed tag sections from source
     * @param result - Result object being built
     * @param processed - Set tracking processed content keys
     * @param processedTags - Set tracking processed tag keys
     * @remarks
     * Routes to applyForceSection, applyDefaultsSection, or applyMergeSection
     * based on the behavior extracted from the tag. All keys within the section
     * (including opening/closing tags) are marked as processed to prevent
     * duplicate handling in subsequent steps.
     */
    private processTaggedSection;
    /**
     * Parse JSON object to extract all tagged sections with their boundaries
     * @param obj - JSON object to parse for tag markers
     * @returns Map of opening tag keys to section info (behavior, category, content keys, close key)
     * @remarks
     * Relies on JSON key ordering being preserved (standard in modern JS engines).
     * Skips sections without matching closing tags to handle malformed input gracefully.
     */
    private parseTaggedSections;
    /**
     * Apply force behavior: Lisa's section replaces project's entirely
     * @param result - Result object being built
     * @param source - Lisa template containing the authoritative values
     * @param section - Section info with content keys to copy
     * @remarks
     * Use force for governance-critical configs that projects must not override,
     * such as CI/CD scripts, required linting commands, or mandatory dev dependencies.
     * Project changes within force-tagged sections are discarded during merge.
     */
    private applyForceSection;
    /**
     * Apply defaults behavior: project's values take precedence if they exist
     * @param result - Result object being built
     * @param source - Lisa template with default values
     * @param dest - Project JSON with potential overrides
     * @param section - Section info from source
     * @param category - Tag category name for looking up destination section
     * @remarks
     * Use defaults for sensible starting values that projects may legitimately need
     * to customize, such as engine versions or optional configurations. If project
     * has the same tagged section, its content is used; otherwise Lisa's defaults apply.
     */
    private applyDefaultsSection;
    /**
     * Add defaults section content, preferring project's version if it has content
     * @param result - Result object being built
     * @param source - Lisa template with fallback values
     * @param dest - Project JSON with potential overrides
     * @param section - Section info from source
     * @param category - Tag category name
     */
    private addDefaultsContent;
    /**
     * Locate and extract the matching tagged section from destination JSON
     * @param dest - Project JSON to search for matching tags
     * @param section - Source section info containing behavior type
     * @param category - Tag category name to match
     * @returns Extracted section info if found, undefined if project lacks the section
     */
    private findAndExtractDestinationSection;
    /**
     * Copy content keys from source template to result
     * @param result - Result object being built
     * @param source - Lisa template containing values to copy
     * @param contentKeys - Keys to copy from source
     */
    private addSourceContent;
    /**
     * Apply merge behavior: combine arrays from source and dest without duplicates
     * @param result - Result object being built
     * @param source - Lisa template with base array items
     * @param dest - Project JSON with additional array items
     * @param section - Section info with content keys
     * @param category - Tag category name
     * @remarks
     * Use merge for shared lists where both Lisa and projects contribute items,
     * such as trustedDependencies. Lisa's items come first, then project's unique
     * additions. Deduplication uses JSON.stringify for value equality comparison.
     */
    private applyMergeSection;
    /**
     * Combine two arrays, removing duplicates while preserving order
     * @param sourceArray - Lisa template array (items added first)
     * @param destArray - Project array (unique items added after)
     * @returns Combined array with source items first, then project's unique additions
     * @remarks
     * Uses JSON.stringify for value equality, so objects/arrays with same content
     * are considered duplicates. This allows deduplicating complex items like
     * package names with version specifiers.
     */
    private deduplicateArrays;
    /**
     * Test if a key is an opening tag (matches `//lisa-<behavior>-<category>` format)
     * @param key - JSON key to test
     * @returns True if key matches the opening tag pattern
     */
    private isOpeningTag;
    /**
     * Test if a key is any tag-like comment key (starts with `//`)
     * @param key - JSON key to test
     * @returns True if key is a JSON comment (convention used for documentation/tags)
     */
    private isTagKey;
    /**
     * Find opening tag key for a given behavior and category in an object
     * @param obj - Object to search for the tag
     * @param behavior - Tag behavior type (force, defaults, merge)
     * @param category - Tag category name
     * @returns Tag key string if found, undefined if object lacks this tag
     */
    private findSectionStart;
    /**
     * Extract section boundaries and content keys between opening and closing tags
     * @param obj - Object containing the tagged section
     * @param startKey - Opening tag key that marks section start
     * @param behavior - Tag behavior type (for constructing close key)
     * @param category - Tag category name (for constructing close key)
     * @returns Complete section info including content keys between tags
     */
    private extractSectionContent;
    /**
     * Extract keys between opening and closing tag indices
     * @param startIndex - Index of opening tag in keys array
     * @param closeIndex - Index of closing tag in keys array
     * @param keys - Ordered array of all keys in the object
     * @returns Array of content keys between the tags, empty if indices invalid
     */
    private extractContentKeysFromRange;
}
//# sourceMappingURL=tagged-merge.d.ts.map