/**
 * Linear Task Sync Adapter
 *
 * Implements the TaskSyncAdapter interface for Linear issue operations.
 * Maps between Stoneforge ExternalTask/ExternalTaskInput and Linear's
 * GraphQL API using the LinearApiClient.
 *
 * Key design points:
 * - Caches workflow states per team (fetched on first use)
 * - Builds bidirectional lookup maps: stateTypeToStateId and stateIdToType
 * - Refreshes state cache when a stateId lookup fails
 * - Uses native Linear priority (0-4) instead of label-based priority
 * - Maps status via workflow state TYPE, not state name
 */
import type { Timestamp } from '@stoneforge/core';
import type { TaskSyncAdapter, ExternalTask, ExternalTaskInput, TaskFieldMapConfig } from '@stoneforge/core';
import type { LinearApiClient } from './linear-api.js';
import type { LinearStateType } from './linear-field-map.js';
/**
 * TaskSyncAdapter implementation for Linear.
 *
 * Provides bidirectional sync between Stoneforge tasks and Linear issues.
 * Uses workflow state caching for efficient status mapping and handles
 * Linear's native priority field directly (no label convention needed).
 *
 * @example
 * ```typescript
 * const client = new LinearApiClient({ apiKey: 'lin_api_...' });
 * const adapter = new LinearTaskAdapter(client);
 *
 * // Fetch a single issue
 * const issue = await adapter.getIssue('ENG', 'uuid-here');
 *
 * // List recent changes
 * const issues = await adapter.listIssuesSince('ENG', '2024-01-01T00:00:00Z');
 * ```
 */
export declare class LinearTaskAdapter implements TaskSyncAdapter {
    private readonly api;
    /** Cached workflow states keyed by team ID */
    private stateCacheByTeam;
    /** Cached team lookups keyed by team key (e.g., "ENG") */
    private teamByKey;
    /** Cached label name→ID lookup (workspace-level) */
    private labelsByName;
    /** Whether labels have been fetched from the API */
    private labelsCached;
    constructor(api: LinearApiClient);
    /**
     * Fetch a single Linear issue by external ID (UUID) and convert to ExternalTask.
     *
     * @param project - Team key (e.g., "ENG")
     * @param externalId - Linear issue UUID
     * @returns ExternalTask or null if not found
     */
    getIssue(project: string, externalId: string): Promise<ExternalTask | null>;
    /**
     * List Linear issues updated since a given timestamp.
     *
     * @param project - Team key (e.g., "ENG")
     * @param since - ISO 8601 timestamp
     * @returns Array of ExternalTask
     */
    listIssuesSince(project: string, since: Timestamp): Promise<ExternalTask[]>;
    /**
     * Create a new issue in Linear.
     *
     * Resolves the team key to a team ID, maps ExternalTaskInput fields to
     * Linear mutation input (title, description, priority, stateId), and
     * calls the API to create the issue.
     *
     * @param project - Team key (e.g., "ENG")
     * @param issue - ExternalTaskInput with the fields to set
     * @returns The created ExternalTask
     */
    createIssue(project: string, issue: ExternalTaskInput): Promise<ExternalTask>;
    /**
     * Update an existing issue in Linear.
     *
     * Maps partial ExternalTaskInput to Linear mutation input and calls
     * the API to update the issue.
     *
     * @param project - Team key (e.g., "ENG")
     * @param externalId - Linear issue UUID
     * @param updates - Partial ExternalTaskInput with fields to update
     * @returns The updated ExternalTask
     */
    updateIssue(project: string, externalId: string, updates: Partial<ExternalTaskInput>): Promise<ExternalTask>;
    /**
     * Returns the Linear-specific TaskFieldMapConfig.
     */
    getFieldMapConfig(): TaskFieldMapConfig;
    /**
     * Converts a Linear issue API response to the normalized ExternalTask format.
     *
     * Injects a synthetic sf:status:* label based on the workflow state type.
     * This allows the generic field mapping system (stateToStatus) to extract
     * granular statuses without the sync engine needing Linear-specific logic.
     */
    private linearIssueToExternalTask;
    /**
     * Builds a CreateIssueInput from an ExternalTaskInput.
     */
    private buildCreateInput;
    /**
     * Builds an UpdateIssueInput from a partial ExternalTaskInput.
     */
    private buildUpdateInput;
    /**
     * Resolves a team key (e.g., "ENG") to a LinearTeam object.
     * Caches the team lookup.
     */
    private resolveTeam;
    /**
     * Gets or creates the workflow state cache for a team.
     * Fetches workflow states from the API on first use.
     */
    private getStateCache;
    /**
     * Fetches workflow states from the API and rebuilds the cache.
     */
    private refreshStateCache;
    /**
     * Resolves a Linear workflow state type to a state ID.
     * Uses the cached states, refreshing if the type is not found.
     */
    private resolveStateId;
    /**
     * Resolves a Linear state ID to a workflow state type.
     * Uses the cached states, refreshing if the ID is not found.
     */
    resolveStateType(teamId: string, stateId: string): Promise<LinearStateType | undefined>;
    /**
     * Filters input labels to only those that should be synced as Linear labels.
     *
     * All label types are now synced to Linear for lossless round-tripping:
     * - sf:priority:* labels (synced alongside native priority for round-tripping)
     * - sf:status:* labels (synced alongside native workflow states for round-tripping)
     * - "blocked" label (synced as a Linear label)
     * - sf:type:* labels (task type — Linear has no native type concept)
     * - User tags (non-prefixed labels)
     *
     * This method exists as an extension point for future label filtering needs.
     */
    private filterSyncableLabels;
    /**
     * Resolves a label name to a Linear label ID.
     * Uses the label cache, fetching from the API on first call.
     * Creates the label if it doesn't exist.
     *
     * @param labelName - The label name to resolve
     * @param teamId - Team ID to associate with a newly created label
     * @returns The label ID, or undefined if resolution fails
     */
    private resolveLabelId;
    /**
     * Resolves all syncable labels from an ExternalTaskInput to Linear label IDs.
     * All labels (including sf:priority:* and sf:status:*) are synced to Linear
     * for lossless round-tripping alongside native fields.
     *
     * @param teamId - Team ID for label creation
     * @param labels - Input labels from ExternalTaskInput
     * @returns Array of resolved Linear label IDs
     */
    private resolveInputLabelIds;
    /**
     * Computes the new labelIds for an issue update by comparing the desired
     * labels against the current issue's labels on Linear.
     *
     * Handles all label types:
     * - "blocked" label (added/removed based on blocked status)
     * - sf:type:* labels (task type synced as Linear labels)
     * - sf:priority:* labels (synced alongside native priority for lossless round-tripping)
     * - sf:status:* labels (synced alongside native workflow states for lossless round-tripping)
     * - User tags (synced as Linear labels)
     *
     * Returns undefined if no label change is needed (avoids unnecessary writes).
     *
     * @param teamId - Team ID (for label creation if needed)
     * @param externalId - Issue UUID to fetch current labels from
     * @param desiredLabels - The full set of desired labels from ExternalTaskInput
     * @returns New labelIds array, or undefined if no change needed
     */
    private computeLabelIds;
    /**
     * Fetches all workspace labels and populates the label cache.
     */
    private refreshLabelCache;
}
//# sourceMappingURL=linear-task-adapter.d.ts.map