/** * Multi-session Orchestration, Session Task Graph * * Implements the in-memory cross-session task graph with: * - Global task reference registration and status propagation * - Dependency edge tracking * - Handoff record management * - Subtree traversal for scoped cancellation * - Snapshot serialization for reconnect/resume consistency */ import type { CrossSessionTaskRef, TaskHandoffRecord, CancellationRequest, CancellationResult, SessionTaskGraphSnapshot } from './types.js'; import type { TaskLifecycleState } from '../../runtime/store/domains/tasks.js'; /** * SessionTaskGraph, the central in-memory cross-session task graph. * * All mutations are synchronous and produce no external side effects, * callers are responsible for persisting snapshots via SessionTaskGraphRegistry. * * Invariants: * - Ref keys are unique per (sessionId, taskId) pair. * - Edges reference only registered refs. * - Handoff IDs are globally unique within the graph lifetime. * - The graph is acyclic (cycle detection is performed on `addEdge`). */ export declare class SessionTaskGraph { /** Primary ref store keyed by makeRefKey(sessionId, taskId). */ private readonly _refs; /** Dependency edges: fromKey → Set */ private readonly _deps; /** Reverse edges: toKey → Set (dependents of a given task). */ private readonly _rdeps; /** Handoff records keyed by handoffId. */ private readonly _handoffs; /** All stored edges in insertion order for snapshot serialization. */ private readonly _edgeList; /** * Register a new cross-session task ref or update an existing one. * * If a ref with the same key already exists, only mutable fields * (status, updatedAt, label) are patched, immutable identity fields * (sessionId, taskId, createdAt) are preserved. * * @param ref - The ref to register or update. * @returns The ref as stored (after any patch). */ upsertRef(ref: CrossSessionTaskRef): CrossSessionTaskRef; /** * Retrieve a ref by session + task ID. * * @returns The ref if found, or `undefined`. */ getRef(sessionId: string, taskId: string): CrossSessionTaskRef | undefined; /** * Return all refs owned by a given session. * * @param sessionId - The owning session ID. * @returns Array of refs (may be empty). */ getRefsBySession(sessionId: string): CrossSessionTaskRef[]; /** * Return all currently registered refs. */ getAllRefs(): CrossSessionTaskRef[]; /** * Propagate a status update to a ref. * * Idempotent: updating to the same status is a no-op. * * @param sessionId - Owning session. * @param taskId - Target task. * @param status - New lifecycle status. * @returns `true` if the status changed; `false` if ref not found or no change. */ propagateStatus(sessionId: string, taskId: string, status: TaskLifecycleState): boolean; /** * Add a dependency edge: `from` depends on `to`. * * Both refs must already be registered. Adding a duplicate edge is a no-op. * * @param from - The dependent task. * @param to - The dependency. * @param reason - Optional human-readable reason. * @returns `{ ok: true }` on success, `{ ok: false, error }` on failure. */ addEdge(from: { sessionId: string; taskId: string; }, to: { sessionId: string; taskId: string; }, reason?: string): { ok: boolean; error?: string; }; /** * Returns all direct dependencies of a task (tasks it depends on). * * @param sessionId - Owning session. * @param taskId - Target task. * @returns Array of refs this task depends on. */ getDependencies(sessionId: string, taskId: string): CrossSessionTaskRef[]; /** * Returns all direct dependents of a task (tasks that depend on it). * * @param sessionId - Owning session. * @param taskId - Target task. * @returns Array of refs that depend on this task. */ getDependents(sessionId: string, taskId: string): CrossSessionTaskRef[]; /** * Collect all refs in the transitive dependent subtree of a task * (the task itself plus all tasks that transitively depend on it). * * Used for `subtree` scoped cancellation. * * @param sessionId - Root session. * @param taskId - Root task. * @returns Array of refs in BFS order, root first. */ collectSubtree(sessionId: string, taskId: string): CrossSessionTaskRef[]; /** * Record a task handoff between sessions. * * @param record - The handoff to record. */ recordHandoff(record: TaskHandoffRecord): void; /** * Acknowledge a handoff (mark it as received by the destination session). * * @param handoffId - The handoff to acknowledge. * @returns `true` if found and updated; `false` if not found. */ acknowledgeHandoff(handoffId: string): boolean; /** * Returns all handoff records. */ getHandoffs(): TaskHandoffRecord[]; /** * Returns handoffs targeting or originating from a given session. * * @param sessionId - The session to filter by. */ getHandoffsForSession(sessionId: string): TaskHandoffRecord[]; /** * Apply a scoped cancellation request to the graph. * * Updates the status of all targeted refs to 'cancelled'. This method * only mutates the in-memory graph, the caller is responsible for * propagating the cancellation to the actual task managers. * * @param request - The cancellation request. * @returns Result describing what was cancelled and what was skipped. */ applyCancellation(request: CancellationRequest): CancellationResult; /** * Take a snapshot of the current graph state for persistence or display. * * @returns A `SessionTaskGraphSnapshot` with all refs, edges, and handoffs. */ snapshot(): SessionTaskGraphSnapshot; /** * Hydrate the graph from a persisted snapshot. * * Existing in-memory state is preserved; snapshot entries are upserted. * This allows safe re-hydration on reconnect/resume without data loss. * * @param snap - The snapshot to hydrate from. */ hydrate(snap: SessionTaskGraphSnapshot): void; /** * BFS check: is there any path from `startKey` to `targetKey`? * Used for cycle detection before adding a new edge. */ private _pathExists; /** * Resolve a set of ref keys to their corresponding CrossSessionTaskRef objects. * Skips keys that are no longer present in the map. */ private _refsForKeys; } //# sourceMappingURL=graph.d.ts.map