/** * `kanban-audit.ts` — Pure, dependency-free Kanban Cleaner audit for the TUI. * * Mirrors the WebUI's `packages/webui/src/lib/kanban-cleaner.ts` but * lives in the TUI package so we don't have to thread `@wrongstack/webui` * (which depends on React) into a server-side TUI pipeline. * * The two implementations must produce the same verdicts for the same board. * That claim used to be a comment; it is now enforced by * `packages/cli/tests/kanban-cleaner-parity.test.ts`, which runs a shared * corpus through both and compares the `taskId:code:severity` triples. Only * three differences are deliberate, and all three are API shape rather than * verdict: this file also accepts `liveAgentIdentities`, returns eight extra * summary fields the WebUI's `KanbanCleanerAlert` fills from queue health, and * exports `summarizeAuditHeadline` / `topAuditIssues` for the panel badge. * Messages may differ; codes and severities may not. * * The output of `auditKanbanBoard()` feeds the TUI panel header badge so * users see Cleaner warnings inline — mirroring the WebUI's * `KanbanCleanerAlert` component, but inline-pinned to the project root. */ import type { KanbanBoard } from '@wrongstack/kanban'; export type KanbanAuditSeverity = 'error' | 'warning'; /** * The audit vocabulary, as a runtime value so the parity test can compare the * two implementations' code sets instead of trusting that both type unions * were edited together. */ export declare const ALL_AUDIT_CODES: readonly ['abandoned-running-task', 'board-oversized', 'missing-assignee', 'missing-description', 'missing-due-date', 'missing-labels', 'missing-subtasks', 'missing-success-criteria', 'skipped-lifecycle-state', 'stale-review', 'stale-running-task']; export type KanbanAuditIssueCode = (typeof ALL_AUDIT_CODES)[number]; export interface KanbanAuditIssue { id: string; taskId: string; taskTitle: string; code: KanbanAuditIssueCode; severity: KanbanAuditSeverity; message: string; } export interface KanbanAuditSummary { /** Wall-clock time the audit ran (ISO-8601). Used by the renderer to * label the report and by tests to pin the audit's age. */ generatedAt: string; /** IDs of every board this summary aggregated across. */ boardIds: readonly string[]; /** Aggregate severity counters. */ counts: Readonly>; /** Detail buckets surfaced by the WebUI Cleaner `KanbanCleanerAlert`. * Each entry lists the tasks that triggered the signal. */ dependencyBlocked: { count: number; tasks: ReadonlyArray<{ board: { title: string; }; task: { title: string; }; }>; }; staleAssignments: { count: number; tasks: ReadonlyArray<{ board: { title: string; }; task: { title: string; }; }>; }; failedRetryable: { count: number; tasks: ReadonlyArray<{ board: { title: string; }; task: { title: string; }; }>; }; heartbeatDue: { count: number; tasks: ReadonlyArray<{ board: { title: string; }; task: { title: string; }; }>; }; /** Activity stamps for last dispatch / last recovery. */ lastDispatchedAt: string | undefined; lastStaleRecoveredAt: string | undefined; /** All issues raised by the audit, sorted error-first. */ issues: readonly KanbanAuditIssue[]; /** Distinct task IDs across `issues`. */ affectedTaskCount: number; } export interface KanbanAuditOptions { /** Explicit time input keeps the audit pure, deterministic, and unit-testable. */ now: number | Date; /** IDs or names of agents currently reported as running by the WebUI fleet roster. */ liveAgentIdentities?: ReadonlySet | readonly string[] | undefined; /** Enable only when the shared Kanban task contract exposes a due date. */ requireDueDate?: boolean | undefined; /** Used when the board has no review-age policy. */ defaultReviewStaleAfterMs?: number | undefined; } export declare function auditKanbanBoard(board: KanbanBoard, options: KanbanAuditOptions): KanbanAuditSummary; /** * Short headline string used by the panel header badge. Returns null when * the summary is empty so callers can hide the badge entirely instead of * rendering a noisy "0 warnings" chip. */ export declare function summarizeAuditHeadline(summary: KanbanAuditSummary): string | null; /** * Top-N issues, biased toward `error` severity first. The TUI panel * surfaces these inline; the full list is still available via * `summary.issues` for tooling. * * We sort defensively (rather than rely on `auditKanbanBoard`'s in-place * order) so callers that hand us a manually-built summary — for example * a test fixture, or a future caller that aggregates issues from * multiple boards — still get the error-first ordering. */ export declare function topAuditIssues(summary: KanbanAuditSummary, limit?: number): readonly KanbanAuditIssue[]; //# sourceMappingURL=kanban-audit.d.ts.map