/** * Fuzzy task search with minimal output. * @task T4460 * @epic T4454 */ import type { MinimalTaskRecord, TaskKind, TaskRecord, TaskStatus } from '@cleocode/contracts'; import { type EngineResult } from '../engine-result.js'; import type { NextDirectives } from '../mvi-helpers.js'; import type { DataAccessor } from '../store/data-accessor.js'; /** Minimal task info for search results. */ export interface FindResult { id: string; title: string; status: string; priority: string; type?: string; parentId?: string | null; /** Dependency IDs — essential for agents to determine task readiness. @task T091 */ depends?: string[]; /** Scope size estimate. @task T091 */ size?: string; /** * Bug severity axis — P0|P1|P2|P3, or null/undefined when unset. * Surfaced so the unified urgency surface (T9905) can identify P0/P1 tasks * without a follow-up `cleo show` per row. * @task T9905 */ severity?: string | null; score: number; /** Progressive disclosure directives for follow-up operations. */ _next?: NextDirectives; } /** Options for finding tasks. */ export interface FindTasksOptions { query?: string; id?: string; exact?: boolean; status?: TaskStatus; field?: string; includeArchive?: boolean; limit?: number; offset?: number; /** * Filter by task kind axis. Accepts any valid {@link TaskKind} value. * @task T944 * @task T9072 */ kind?: TaskKind; /** * Unified urgency surface (T9905). * * When `true`, the predicate is * * `priority IN ('critical','high') OR severity IN ('P0','P1')` * * combining the two orthogonal urgency axes (priority + severity) into a * single filter so agents don't have to query each axis separately. * Composes with other filters via AND (e.g. `--urgent --status pending`). * * @task T9905 */ urgent?: boolean; /** * Filter by label — selects tasks whose `labels` array contains this * value. Composes with other filters via AND (e.g. `--label bug --status pending`). * Filter-only mode: passing only `--label` with no `query`/`--id` is valid * and returns every task carrying the label. * * Closes GH#393 — gives `cleo find --label ` parity with the * positional `cleo labels ` surface. * * @task T9904 */ label?: string; /** * Filter by parent task ID — restricts the result set to tasks whose * `parentId` equals this value. Mirrors the `--parent` axis on * `cleo list`. * * When the parent target is a Saga, membership is resolved from canonical * `parentId` containment. `task_relations` rows are soft non-containment * context only and must not drive parent filtering. * * Composes with other filters via AND. Filter-only mode is valid: * `cleo find --parent ` with no query / no --id returns every * task that hangs under the parent. * * @task T10108 * @saga T9862 */ parent?: string; } /** Result of finding tasks. */ export interface FindTasksResult { results: FindResult[]; total: number; query: string; searchType: 'fuzzy' | 'id' | 'exact'; } /** * Predicate for the unified urgency surface (T9905). * * Returns `true` when the task satisfies the disjunctive predicate * * `priority IN ('critical','high') OR severity IN ('P0','P1')` * * Exported for reuse by `coreTaskNext` (scoring boost) and the briefing * computation so the three callers share a single definition of "urgent". * * @task T9905 */ export declare function isUrgentTask(task: { priority?: string | null; severity?: string | null; }): boolean; /** * Calculate fuzzy match score between query and text. * Higher score = better match. 0 = no match. * @task T4460 * * @example * ```ts * // Exact match returns the maximum score (100) * const exact = fuzzyScore('auth', 'auth'); * console.assert(exact === 100, 'exact match → 100'); * * // Substring match returns a high score (80) * const contains = fuzzyScore('auth', 'authentication module'); * console.assert(contains === 80, 'substring match → 80'); * * // No match at all returns 0 * const none = fuzzyScore('xyz', 'authentication'); * console.assert(none === 0, 'no match → 0'); * * // Scores are comparable — substring beats partial character match * const partial = fuzzyScore('athn', 'authentication'); * console.assert(partial < contains, 'partial < full-substring'); * ``` */ export declare function fuzzyScore(query: string, text: string): number; /** * Parse `status:value` / `kind:value` / `priority:value` tokens embedded in * a fuzzy query string and lift them into the filter options. * * Users naturally type `cleo find "status:pending"` expecting it to filter * rather than fuzzy-match against title/description. This helper rewrites * the options so the filter lifts out of the query token and only the * remaining words stay in the free-text search. * * Recognised fields: `status`, `kind`, `priority`, `type`, `id`, `label` (T9904). * Unrecognised `key:value` tokens pass through as-is (treated as fuzzy * text) to preserve user intent. * * @param options - The raw find options supplied by the caller. * @returns A new options object with filters lifted and the fuzzy `query` * reduced to the non-filter tokens, or the same object if nothing * changed. * * @task T1187-followup / v2026.4.114 * @task T9072 * * @example * ```ts * // Inline status token is lifted; remaining text stays as query * const result = extractInlineFilters({ query: 'status:pending auth flow' }); * console.assert(result.status === 'pending', 'status lifted from query'); * console.assert(result.query === 'auth flow', 'remaining text preserved as query'); * * // Kind token lifted similarly * const result2 = extractInlineFilters({ query: 'kind:bug login crash' }); * console.assert(result2.kind === 'bug', 'kind lifted from query'); * console.assert(result2.query === 'login crash', 'remaining text preserved'); * * // No inline tokens — options returned unchanged * const result3 = extractInlineFilters({ query: 'auth module' }); * console.assert(result3.query === 'auth module', 'plain query unchanged'); * console.assert(result3.status === undefined, 'status remains undefined'); * ``` */ export declare function extractInlineFilters(options: FindTasksOptions): FindTasksOptions; /** * Search tasks by fuzzy matching, ID prefix, exact title, or filter-only. * Returns minimal fields only (context-efficient). * * Accepts any of: * - positional `query` for fuzzy title/description search * - `id` prefix * - `status` / `kind` filter (any of these alone is sufficient — no * query required, returns all matches) * - inline `key:value` tokens in `query` (e.g. `status:pending`) * auto-lifted into the corresponding filter * * @task T4460 * @task T1187-followup / v2026.4.114 — filter-only mode + inline key:value parsing */ export declare function findTasks(rawOptions: FindTasksOptions, cwd?: string, accessor?: DataAccessor): Promise; /** * Fuzzy search tasks by title/description/ID, wrapped in EngineResult. * * @param projectRoot - Absolute path to the project root * @param query - Search string to match against title, description, or ID * @param limit - Maximum number of results (defaults to 20) * @param options - Additional search options * @returns EngineResult with matching tasks and total count * * @task T1568 * @epic T1566 */ export declare function taskFind(projectRoot: string, query: string, limit?: number, options?: { id?: string; exact?: boolean; status?: string; includeArchive?: boolean; offset?: number; fields?: string; verbose?: boolean; kind?: string; /** Unified urgency surface — see {@link FindTasksOptions.urgent}. @task T9905 */ urgent?: boolean; /** Filter by label — see {@link FindTasksOptions.label}. @task T9904 */ label?: string; /** Filter by parent task ID — see {@link FindTasksOptions.parent}. @task T10108 */ parent?: string; }): Promise>; //# sourceMappingURL=find.d.ts.map