/**
 * V3 Data Service — Automatic V3 entity creation via EventBus hooks
 *
 * Subscribes to existing backend events and automatically creates/updates
 * V3 entities (WorkItem, Request, Mission). This service is fire-and-forget:
 * errors are logged but never block the main flow.
 *
 * Design principle: Orchestrator has zero knowledge of V3 concepts.
 * V3 data is produced as a side effect of normal operations.
 *
 * Events consumed:
 * - task:delegated  -> creates WorkItem in TaskPool
 * - task:completed  -> updates WorkItem status to 'done'
 * - task:failed     -> updates WorkItem status to 'failed'
 * - goal:set        -> creates Mission with conservative policy
 * - message:user_work -> creates Request
 *
 * @module services/v3/v3-data.service
 */
import { EventEmitter } from 'events';
import { type IntentCategory, type IntentLevel } from '../../types/v2/request.types.js';
/**
 * Minimum content length for a user message to create a Request.
 * P2-1: Relaxed from 5 → 2 to stop dropping legitimate short commands
 * like "fix", "help", "go", "OK". Only truly empty or single-char
 * messages (e.g., ".", "k") are filtered out.
 */
export declare const MIN_REQUEST_CONTENT_LENGTH = 2;
/**
 * Grace period (in ms) before an open Request with no WorkItems is
 * auto-closed as dangling. P2-1: Added to prevent premature closure —
 * the orchestrator may need time to process the request and delegate.
 * Default: 5 minutes.
 */
export declare const DANGLING_REQUEST_GRACE_MS: number;
/**
 * Payload emitted when a task is delegated to an agent.
 */
export interface TaskDelegatedEvent {
    taskId: string;
    title: string;
    description?: string;
    assignedTo: string;
    priority?: string;
    projectPath: string;
    milestone?: string;
    requestId?: string;
    timestamp: string;
}
/**
 * Payload emitted when a task is completed.
 */
export interface TaskCompletedEvent {
    type: string;
    taskId?: string;
    sessionName: string;
    previousValue?: string;
    newValue: string;
    changedField?: string;
    timestamp: string;
}
/**
 * Payload emitted when a goal is set.
 */
export interface GoalSetEvent {
    goal: string;
    projectPath: string;
    setBy: string;
    timestamp: string;
}
/**
 * Payload emitted when a task is blocked.
 */
export interface TaskBlockedEvent {
    taskId?: string;
    sessionName: string;
    reason?: string;
    timestamp: string;
}
/**
 * Payload emitted when a user message is ready for processing.
 */
export interface UserWorkMessageEvent {
    messageId: string;
    conversationId: string;
    content: string;
    source: string;
    timestamp: string;
}
/**
 * V3DataService automatically creates V3 data entities by subscribing to
 * backend EventBus events. It wraps every handler in try-catch to ensure
 * failures never impact the main workflow.
 *
 * @example
 * ```typescript
 * const v3Data = new V3DataService(eventBus, '/path/to/project');
 * // That's it — events are now being listened to.
 * ```
 */
export declare class V3DataService {
    private readonly eventBus;
    private readonly logger;
    private readonly storageService;
    private readonly projectPath;
    private readonly missionsDir;
    /**
     * Creates and initializes the V3DataService.
     *
     * Subscribes to EventBus domain events. (Legacy ProjectTask file watcher
     * was retired with the V3↔.md bridge deprecation per
     * `specs/2026-05-06-projecttask-md-deprecation.md`.)
     *
     * @param eventBus - The EventEmitter that publishes domain events
     * @param projectPath - Absolute path to the project root
     */
    constructor(eventBus: EventEmitter, projectPath: string);
    /**
     * Finds the WorkItem matching a task event using a two-tier strategy:
     * 1. Match by projectTaskId (most precise)
     * 2. Fall back to sessionName + status (running first, then queued)
     *
     * If the matched WorkItem is 'queued', it is transitioned to 'running'
     * since completeItem/failItem require 'running' status.
     *
     * @param taskId - The project task ID (may be undefined)
     * @param sessionName - The agent session name
     * @param logContext - Context string for debug logging
     * @returns The matched WorkItem (with status fix applied), or null
     */
    private findMatchingWorkItem;
    /**
     * Handles task:delegated — creates a WorkItem in the TaskPool.
     *
     * @param event - Task delegation event payload
     */
    private onTaskDelegated;
    /**
     * Handles task:completed — updates the matching WorkItem to 'done'.
     *
     * Uses a two-tier matching strategy:
     * 1. Match by projectTaskId (most precise — correlates to the .crewly/tasks/ file ID)
     * 2. Fall back to sessionName + status (running or queued, since WorkItems
     *    created via delegation start as 'queued' and may never be claimed)
     *
     * @param event - Task completion event payload
     */
    private onTaskCompleted;
    /**
     * Handles task:failed — first failure triggers `failItem`, then we
     * decide retry-vs-escalate based on the WI's own `retryCount` budget.
     *
     * Two-stage flow:
     *   1. Always flip running → failed via taskPool.failItem (records the
     *      error, releases the claim). This is the ground truth state.
     *   2. If `retryCount < maxRetries` → requeueAfterFailure (failed →
     *      queued, retryCount++). The original target keeps the WI.
     *   3. Otherwise → leave it in failed AND escalate to ORC so it can
     *      surface the failure to the user and ask for a new plan.
     *
     * Cascade-to-parent-Request happens ONLY on the terminal path
     * (exhausted retries). A retry-eligible WI doesn't cascade, since
     * the Request might still complete on the next attempt.
     *
     * Steve 2026-05-22: prior to this fix the system treated every
     * `task:failed` as terminal — retryCount/maxRetries were dead fields,
     * Mission/Request would cascade-fail on a single transient failure,
     * and the user only learned about it by digging in the Work Items
     * UI. New behaviour: retry up to `maxRetries`, then escalate.
     *
     * @param event - Task failure event payload
     */
    private onTaskFailed;
    /**
     * Handles goal:set — creates a Mission with conservative policy.
     *
     * @param event - Goal set event payload
     */
    private onGoalSet;
    /**
     * Handles message:user_work — creates a Request from a user message.
     *
     * @param event - User work message event payload
     */
    private onUserWorkMessage;
    /**
     * Handles task:blocked — updates the matching WorkItem to 'blocked'.
     *
     * Uses the same two-tier matching strategy as onTaskCompleted.
     *
     * @param event - Task blocked event payload
     */
    private onTaskBlocked;
    /**
     * Recomputes Request.status from the aggregate state of its child WorkItems.
     *
     * Rules:
     * - All WorkItems done → Request = done
     * - Any WorkItem running → Request = running
     * - All WorkItems queued → no change (work delegated but not started)
     * - Any WorkItem blocked, none running → Request = blocked
     * - All WorkItems failed/cancelled → Request = cancelled
     * - Some done + some queued (no running) → Request = running
     *
     * @param requestId - The parent Request ID (may be undefined for unlinked WorkItems)
     */
    private cascadeRequestStatus;
    /**
     * Decomposes a mission objective into V3 WorkItems.
     *
     * Per `specs/2026-05-06-task-management-v1-deprecation.md`, the legacy
     * `.crewly/tasks/delegated/open/*.md` filesystem write has been removed —
     * V3 task-pool is the sole source of truth for delegated work. Each
     * planned sub-task lands as a queued WorkItem with the long-form brief
     * carried in `briefMarkdown` (the same content that previously lived in
     * the .md body).
     *
     * @param missionId - The parent mission ID (stored on each WI and in the
     *                    brief's Context section)
     * @param objective - The mission objective text
     * @param projectPath - Reserved for future use (e.g. resolving relative
     *                     skill paths in the brief). Currently unused but
     *                     kept in the signature so existing callers don't
     *                     have to be updated in lockstep.
     * @returns Array of created WorkItem IDs in plan order
     */
    static decomposeMissionToTasks(missionId: string, objective: string, _projectPath: string): Promise<string[]>;
    /**
     * Lists all missions from disk.
     *
     * @returns Array of Mission objects
     */
    private listMissions;
    /**
     * Stops listening to events. Used for cleanup/testing.
     */
    dispose(): void;
}
/**
 * Checks if a message is non-actionable (confirmation, chit-chat, greeting).
 * These messages should not create Requests or WorkItems.
 *
 * @param content - The user message text (trimmed)
 * @returns True if the message is non-actionable
 */
export declare function isNonActionableMessage(content: string): boolean;
/**
 * Auto-classify request intent from message content.
 * Runs synchronously — no AI call, just keyword matching.
 *
 * Bug A v0 (2026-05-06): delegates to the canonical
 * `classifyIntentLevel` + `classifyIntentCategory` from
 * `backend/src/types/intent-task.types.ts` (which read from the
 * code-of-record rules at
 * `backend/src/services/intent-task/intent-classifier.rules.ts`).
 *
 * Why delegation rather than maintaining a parallel rule-set: prior to
 * this PR, the two classifyIntent paths drifted. The Mission-side classifier
 * had ~40 patterns + length floor; the Request-side classifier had ~7 patterns
 * with no length floor. This caused classification skew across surfaces.
 *
 * The local pre-filter `isNonActionableMessage` is preserved because it's
 * scoped to v3-data.service callers (Request creation flow) and short-
 * circuits L0 for chit-chat without invoking the heavier classifier.
 *
 * @param content - The user message text
 * @returns Object with intentCategory and intentLevel
 */
export declare function classifyIntent(content: string): {
    intentCategory: IntentCategory;
    intentLevel: IntentLevel;
};
/**
 * Planned task structure used during mission decomposition.
 */
export interface PlannedTask {
    /** Short task title */
    title: string;
    /** Detailed task description */
    description: string;
    /** Measurable acceptance criteria */
    acceptanceCriteria: string[];
    /** Task priority */
    priority: 'high' | 'medium' | 'low';
    /**
     * Titles of other planned tasks this one depends on. The fan-out caller
     * (request-decompose subscriber, mission executor) is expected to map
     * these titles to the resolved WorkItem IDs and write them into
     * `WorkItem.dependsOn` before queueing.
     *
     * **Why titles, not indices.** Titles survive plan() reordering and
     * make the dependency intent self-documenting in the plan output.
     *
     * **Sequential plans.** A planner that wants strict A→B→C ordering
     * sets `B.dependsOnTitles = [A.title]` and `C.dependsOnTitles = [B.title]`.
     * Without this, all three tasks queue concurrently and a worker can
     * claim Review before Execute is done — observed in the 2026-05-08
     * dogfood, where Sam claimed Review while Plan/Execute were still
     * blocked.
     */
    dependsOnTitles?: string[];
}
/**
 * Determines whether an objective is complex enough for multi-step decomposition.
 * Complexity heuristics: word count, presence of conjunctions/lists, multiple
 * action verbs, or explicit multi-step indicators.
 *
 * @param objective - The objective text
 * @returns True if the objective warrants multiple tasks
 */
export declare function isComplexObjective(objective: string): boolean;
/**
 * Decomposes a mission objective into actionable tasks using keyword matching.
 *
 * P0-1 fix: Uses intelligent decomposition instead of always producing 3 tasks.
 * - Simple/direct objectives → 1 task
 * - Complex/multi-step objectives → 2-3 tasks
 *
 * Recognises three broad categories:
 * - **Build** (create/implement/build/add/feature) → single task or design+implement+test
 * - **Fix** (fix/debug/resolve/repair/patch) → single task or investigate+fix+verify
 * - **Default** (anything else) → single task or plan+execute+review
 *
 * @param objective - The mission objective text
 * @returns Array of PlannedTask objects (1-3 items)
 */
export declare function planTasksFromObjective(objective: string): PlannedTask[];
/**
 * Generates a summarized title for a Request instead of copying raw content.
 *
 * For short messages (under 60 chars), uses the content directly with an
 * intent prefix. For longer messages, extracts the first sentence or clause
 * and prepends the intent prefix.
 *
 * @param content - The trimmed user message
 * @param intentCategory - The classified intent category
 * @returns A concise, informative title (max 80 chars)
 */
export declare function generateRequestTitle(content: string, intentCategory: IntentCategory): string;
//# sourceMappingURL=v3-data.service.d.ts.map