- hasCycles(): uses graphology-dag.hasCycle() as fast boolean check - findCycles(): SCC pre-check + custom 3-color DFS for cycle path extraction - topologicalOrder(): graphology-dag.topologicalSort + CircularDependencyError on cycle - dependencies/dependents: inNeighbors/outNeighbors with TaskNotFoundError - taskCount(): graph.order, getTask(): node attributes or undefined - 45 unit tests covering all acceptance criteria
3.1 KiB
3.1 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level | |
|---|---|---|---|---|---|---|---|---|
| graph/queries | Implement TaskGraph query methods (hasCycles, findCycles, topologicalOrder, dependencies, dependents, taskCount, getTask) | completed |
|
moderate | medium | component | implementation |
Description
Implement query methods in src/graph/queries.ts and integrate on TaskGraph. The findCycles implementation requires a custom 3-color DFS since graphology-components only gives SCCs, not cycle paths.
Per errors-validation.md:
hasCycles()returns boolean (usesgraphology-dagorgraphology-componentsfor fast check)findCycles()returnsstring[][]— each inner array is an ordered cycle pathtopologicalOrder()throwsCircularDependencyErrorwithcyclespopulated when graph is cyclic (per ADR-003)
Acceptance Criteria
hasCycles(): boolean— usesgraphology-dag.hasCycle()orgraphology-componentsSCC check as fast pre-checkfindCycles(): string[][]:- Uses
stronglyConnectedComponents()as pre-check: if zero multi-node SCCs and no self-loops, skip DFS - Custom 3-color DFS (WHITE/GREY/BLACK) to extract cycle paths
- Returns one representative cycle per back edge, not exhaustive enumeration
- Each inner array is an ordered node sequence where last node has edge back to first
- Uses
topologicalOrder(): string[]:- Uses
graphology-dag.topologicalSort()for the actual sort - Throws
CircularDependencyError(withcyclesfromfindCycles()) when graph is cyclic - Returns
string[]of task IDs in prerequisite→dependent order
- Uses
dependencies(taskId: string): string[]— returns prerequisite task IDs (inNeighbors). ThrowsTaskNotFoundErrorif ID doesn't exist.dependents(taskId: string): string[]— returns dependent task IDs (outNeighbors). ThrowsTaskNotFoundErrorif ID doesn't exist.taskCount(): number— returns number of nodesgetTask(taskId: string): TaskGraphNodeAttributes | undefined— returns node attributes or undefined- Unit tests: cycle detection on known cyclic/acyclic graphs, topologicalOrder on DAG, topologicalOrder throws on cyclic graph, dependency/dependent queries
References
- docs/architecture/api-surface.md — query methods
- docs/architecture/errors-validation.md — cycle handling, CircularDependencyError
- docs/architecture/cost-benefit.md — findCycles algorithm description
- docs/architecture/decisions/003-topo-order-throws-on-cycle.md — ADR-003
Notes
findCycles uses a custom 3-color DFS (WHITE/GREY/BLACK) as specified — graphology-components only gives SCCs, not cycle paths. The DFS traces the recursion stack on back edges to extract ordered cycle paths.
Summary
Implemented all 7 query methods in src/graph/queries.ts as free functions operating on the inner graphology graph, and integrated them as instance methods on TaskGraph.
- Created:
src/graph/queries.ts,test/queries.test.ts - Modified:
src/graph/construction.ts(added query method imports and 7 instance methods) - Tests: 45, all passing (full suite: 302 passing)