import type { TaskFilter, TaskGraph, TaskNode, TaskProgress, TaskSort } from '../types/task-graph.js'; export interface TaskStore { saveGraph(graph: TaskGraph): Promise; loadGraph(id: string): Promise; listGraphs(): Promise<{ id: string; title: string; updatedAt: number; }[]>; deleteGraph(id: string): Promise; } export interface TaskTrackerOptions { store: TaskStore; /** * Called when an in-the-background persistence (`saveGraph`) rejects. * The synchronous TaskTracker methods (addNode/addEdge/updateNodeStatus) * fire-and-forget their writes; without this, a failing store silently * loses graph mutations. Defaults to a console.warn. */ onPersistError?: ((err: unknown) => void) | undefined; } export interface TaskTransition { from: TaskNode['status']; to: TaskNode['status']; timestamp: number; reason?: string | undefined; } /** A change notification emitted to `TaskTracker.subscribe` listeners. */ export interface TaskTrackerChange { type: 'node_added' | 'node_updated' | 'status_changed' | 'node_removed'; nodeId: string; /** For `node_removed` this is the node as it was just before deletion. */ node: TaskNode; transition?: TaskTransition | undefined; } export type TaskTrackerListener = (change: TaskTrackerChange) => void; export declare class TaskTracker { private readonly opts; private graph; private transitions; private listeners; private static readonly MAX_TRANSITIONS; constructor(opts: TaskTrackerOptions); /** * Subscribe to live task mutations (add / update / status change). Returns an * unsubscribe fn. This is the hook the board projector uses to stream a live * snapshot — the tracker was previously fire-and-forget with no observability. */ subscribe(listener: TaskTrackerListener): () => void; private notifyChange; /** * Attach an existing graph (used by PhaseOrchestrator to associate a tracker * with a phase's pre-built task graph without re-creating it). */ setGraph(graph: TaskGraph): void; createGraph(specId: string, title: string): Promise; loadGraph(id: string): Promise; addNode(node: Omit): TaskNode; addEdge(from: string, to: string, type?: TaskGraph['edges'][0]['type']): void; /** * Declare that `taskId` depends on `depId` (a `depends_on` edge `depId → taskId`), * guarding against self-loops, duplicates, missing nodes, and cycles. Returns * true if the dependency now holds (added or already present), false if it was * rejected (would create a cycle / unknown node). This is the safe entry point * for wiring agent-declared `dependsOn` references into the graph. */ addDependency(depId: string, taskId: string): boolean; /** True when `taskId` transitively depends on `targetId` (follows depends_on blockers). */ private dependsOnTransitively; /** * Merge `patch` into a node's `metadata` (used for per-task model/provider/ * fallback assignment and the cancel marker). Persists + notifies as a node * update. No-op if the node is missing. */ patchMetadata(id: string, patch: Record): void; /** * Remove a node and every edge touching it. Intended for deleting a task that * has not started yet — callers must gate on status (do not remove a running * task). Dependents simply lose this blocker (re-evaluated by `canStart`). * Returns true if a node was removed. */ removeNode(id: string): boolean; updateNodeStatus(id: string, status: TaskNode['status'], reason?: string): void; updateNode(id: string, patch: Partial>): void; getNode(id: string): TaskNode | undefined; getAllNodes(filter?: TaskFilter, sort?: TaskSort): TaskNode[]; getChildren(parentId: string): TaskNode[]; getDependents(taskId: string): string[]; getBlockers(taskId: string): string[]; canStart(taskId: string): boolean; getProgress(): TaskProgress; getTransitions(_taskId?: string): TaskTransition[]; private unblockDependents; private checkAndBlockIfNeeded; /** * Fire-and-forget persistence with attached error handler. * Synchronous mutators (addNode/addEdge/updateNodeStatus) use this to * avoid forcing an async cascade through every caller; if the store * is missing or throwing, the error is surfaced via onPersistError. */ private persist; } //# sourceMappingURL=task-tracker.d.ts.map