@rengler33/prov 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/README.md +314 -0
  2. package/dist/cli.d.ts +26 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +381 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/agent.d.ts +107 -0
  7. package/dist/commands/agent.d.ts.map +1 -0
  8. package/dist/commands/agent.js +197 -0
  9. package/dist/commands/agent.js.map +1 -0
  10. package/dist/commands/agent.test.d.ts +5 -0
  11. package/dist/commands/agent.test.d.ts.map +1 -0
  12. package/dist/commands/agent.test.js +199 -0
  13. package/dist/commands/agent.test.js.map +1 -0
  14. package/dist/commands/constraint.d.ts +100 -0
  15. package/dist/commands/constraint.d.ts.map +1 -0
  16. package/dist/commands/constraint.js +763 -0
  17. package/dist/commands/constraint.js.map +1 -0
  18. package/dist/commands/constraint.test.d.ts +9 -0
  19. package/dist/commands/constraint.test.d.ts.map +1 -0
  20. package/dist/commands/constraint.test.js +470 -0
  21. package/dist/commands/constraint.test.js.map +1 -0
  22. package/dist/commands/graph.d.ts +99 -0
  23. package/dist/commands/graph.d.ts.map +1 -0
  24. package/dist/commands/graph.js +552 -0
  25. package/dist/commands/graph.js.map +1 -0
  26. package/dist/commands/graph.test.d.ts +2 -0
  27. package/dist/commands/graph.test.d.ts.map +1 -0
  28. package/dist/commands/graph.test.js +258 -0
  29. package/dist/commands/graph.test.js.map +1 -0
  30. package/dist/commands/impact.d.ts +83 -0
  31. package/dist/commands/impact.d.ts.map +1 -0
  32. package/dist/commands/impact.js +319 -0
  33. package/dist/commands/impact.js.map +1 -0
  34. package/dist/commands/impact.test.d.ts +2 -0
  35. package/dist/commands/impact.test.d.ts.map +1 -0
  36. package/dist/commands/impact.test.js +234 -0
  37. package/dist/commands/impact.test.js.map +1 -0
  38. package/dist/commands/init.d.ts +45 -0
  39. package/dist/commands/init.d.ts.map +1 -0
  40. package/dist/commands/init.js +94 -0
  41. package/dist/commands/init.js.map +1 -0
  42. package/dist/commands/init.test.d.ts +7 -0
  43. package/dist/commands/init.test.d.ts.map +1 -0
  44. package/dist/commands/init.test.js +174 -0
  45. package/dist/commands/init.test.js.map +1 -0
  46. package/dist/commands/integration.test.d.ts +10 -0
  47. package/dist/commands/integration.test.d.ts.map +1 -0
  48. package/dist/commands/integration.test.js +456 -0
  49. package/dist/commands/integration.test.js.map +1 -0
  50. package/dist/commands/mcp.d.ts +21 -0
  51. package/dist/commands/mcp.d.ts.map +1 -0
  52. package/dist/commands/mcp.js +616 -0
  53. package/dist/commands/mcp.js.map +1 -0
  54. package/dist/commands/mcp.test.d.ts +7 -0
  55. package/dist/commands/mcp.test.d.ts.map +1 -0
  56. package/dist/commands/mcp.test.js +132 -0
  57. package/dist/commands/mcp.test.js.map +1 -0
  58. package/dist/commands/plan.d.ts +218 -0
  59. package/dist/commands/plan.d.ts.map +1 -0
  60. package/dist/commands/plan.js +1307 -0
  61. package/dist/commands/plan.js.map +1 -0
  62. package/dist/commands/plan.test.d.ts +9 -0
  63. package/dist/commands/plan.test.d.ts.map +1 -0
  64. package/dist/commands/plan.test.js +569 -0
  65. package/dist/commands/plan.test.js.map +1 -0
  66. package/dist/commands/spec.d.ts +94 -0
  67. package/dist/commands/spec.d.ts.map +1 -0
  68. package/dist/commands/spec.js +635 -0
  69. package/dist/commands/spec.js.map +1 -0
  70. package/dist/commands/spec.test.d.ts +9 -0
  71. package/dist/commands/spec.test.d.ts.map +1 -0
  72. package/dist/commands/spec.test.js +407 -0
  73. package/dist/commands/spec.test.js.map +1 -0
  74. package/dist/commands/trace.d.ts +157 -0
  75. package/dist/commands/trace.d.ts.map +1 -0
  76. package/dist/commands/trace.js +847 -0
  77. package/dist/commands/trace.js.map +1 -0
  78. package/dist/commands/trace.test.d.ts +9 -0
  79. package/dist/commands/trace.test.d.ts.map +1 -0
  80. package/dist/commands/trace.test.js +524 -0
  81. package/dist/commands/trace.test.js.map +1 -0
  82. package/dist/graph.d.ts +204 -0
  83. package/dist/graph.d.ts.map +1 -0
  84. package/dist/graph.js +496 -0
  85. package/dist/graph.js.map +1 -0
  86. package/dist/graph.test.d.ts +2 -0
  87. package/dist/graph.test.d.ts.map +1 -0
  88. package/dist/graph.test.js +382 -0
  89. package/dist/graph.test.js.map +1 -0
  90. package/dist/hash.d.ts +72 -0
  91. package/dist/hash.d.ts.map +1 -0
  92. package/dist/hash.js +137 -0
  93. package/dist/hash.js.map +1 -0
  94. package/dist/hash.test.d.ts +2 -0
  95. package/dist/hash.test.d.ts.map +1 -0
  96. package/dist/hash.test.js +227 -0
  97. package/dist/hash.test.js.map +1 -0
  98. package/dist/index.d.ts +18 -0
  99. package/dist/index.d.ts.map +1 -0
  100. package/dist/index.js +64 -0
  101. package/dist/index.js.map +1 -0
  102. package/dist/index.test.d.ts +2 -0
  103. package/dist/index.test.d.ts.map +1 -0
  104. package/dist/index.test.js +11 -0
  105. package/dist/index.test.js.map +1 -0
  106. package/dist/output.d.ts +84 -0
  107. package/dist/output.d.ts.map +1 -0
  108. package/dist/output.js +175 -0
  109. package/dist/output.js.map +1 -0
  110. package/dist/output.test.d.ts +7 -0
  111. package/dist/output.test.d.ts.map +1 -0
  112. package/dist/output.test.js +146 -0
  113. package/dist/output.test.js.map +1 -0
  114. package/dist/staleness.d.ts +162 -0
  115. package/dist/staleness.d.ts.map +1 -0
  116. package/dist/staleness.js +309 -0
  117. package/dist/staleness.js.map +1 -0
  118. package/dist/staleness.test.d.ts +2 -0
  119. package/dist/staleness.test.d.ts.map +1 -0
  120. package/dist/staleness.test.js +448 -0
  121. package/dist/staleness.test.js.map +1 -0
  122. package/dist/storage.d.ts +267 -0
  123. package/dist/storage.d.ts.map +1 -0
  124. package/dist/storage.js +623 -0
  125. package/dist/storage.js.map +1 -0
  126. package/dist/storage.test.d.ts +5 -0
  127. package/dist/storage.test.d.ts.map +1 -0
  128. package/dist/storage.test.js +434 -0
  129. package/dist/storage.test.js.map +1 -0
  130. package/dist/types.d.ts +270 -0
  131. package/dist/types.d.ts.map +1 -0
  132. package/dist/types.js +12 -0
  133. package/dist/types.js.map +1 -0
  134. package/dist/types.test.d.ts +2 -0
  135. package/dist/types.test.d.ts.map +1 -0
  136. package/dist/types.test.js +232 -0
  137. package/dist/types.test.js.map +1 -0
  138. package/dist/watcher.d.ts +139 -0
  139. package/dist/watcher.d.ts.map +1 -0
  140. package/dist/watcher.js +406 -0
  141. package/dist/watcher.js.map +1 -0
  142. package/dist/watcher.test.d.ts +5 -0
  143. package/dist/watcher.test.d.ts.map +1 -0
  144. package/dist/watcher.test.js +327 -0
  145. package/dist/watcher.test.js.map +1 -0
  146. package/package.json +53 -0
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Intent Graph implementation.
3
+ *
4
+ * The intent graph is a directed acyclic graph (DAG) that connects
5
+ * specifications to implementations via plans and traces.
6
+ *
7
+ * @see spec:intent-graph:v1
8
+ */
9
+ import type { EntityId, NodeType, EdgeType, GraphNode, GraphEdge, Hash, Spec, Requirement, Constraint, Invariant, Plan, Decision, Step, Trace } from './types.js';
10
+ /**
11
+ * Entity data that can be stored in a graph node.
12
+ */
13
+ export type EntityData = Spec | Requirement | Constraint | Invariant | Plan | Decision | Step | Trace;
14
+ /**
15
+ * Options for graph traversal.
16
+ */
17
+ export interface TraversalOptions {
18
+ /** Maximum depth to traverse (default: unlimited) */
19
+ readonly maxDepth?: number;
20
+ /** Edge types to follow (default: all) */
21
+ readonly edgeTypes?: readonly EdgeType[];
22
+ /** Include the starting node in results */
23
+ readonly includeStart?: boolean;
24
+ }
25
+ /**
26
+ * Result of validation check.
27
+ */
28
+ export interface ValidationResult {
29
+ readonly valid: boolean;
30
+ readonly errors: readonly string[];
31
+ readonly warnings: readonly string[];
32
+ }
33
+ /**
34
+ * Intent Graph - the central data structure for provenance tracking.
35
+ *
36
+ * @see req:graph:structure
37
+ */
38
+ export declare class IntentGraph {
39
+ private readonly nodes;
40
+ private readonly edges;
41
+ private readonly outgoingEdges;
42
+ private readonly incomingEdges;
43
+ /**
44
+ * Create a new empty intent graph.
45
+ */
46
+ constructor();
47
+ /**
48
+ * Get the number of nodes in the graph.
49
+ */
50
+ get nodeCount(): number;
51
+ /**
52
+ * Get the number of edges in the graph.
53
+ */
54
+ get edgeCount(): number;
55
+ /**
56
+ * Add a node to the graph.
57
+ *
58
+ * @param id - Entity ID
59
+ * @param type - Node type
60
+ * @param data - Entity data
61
+ * @param hash - Optional pre-computed hash
62
+ */
63
+ addNode(id: EntityId, type: NodeType, data: EntityData, hash?: Hash): GraphNode;
64
+ /**
65
+ * Get a node by ID.
66
+ */
67
+ getNode(id: EntityId): GraphNode | undefined;
68
+ /**
69
+ * Check if a node exists.
70
+ */
71
+ hasNode(id: EntityId): boolean;
72
+ /**
73
+ * Remove a node and all its edges.
74
+ */
75
+ removeNode(id: EntityId): boolean;
76
+ /**
77
+ * Get all nodes of a specific type.
78
+ */
79
+ getNodesByType(type: NodeType): GraphNode[];
80
+ /**
81
+ * Get all nodes as an array.
82
+ */
83
+ getAllNodes(): GraphNode[];
84
+ /**
85
+ * Add an edge to the graph.
86
+ *
87
+ * @param from - Source node ID
88
+ * @param to - Target node ID
89
+ * @param type - Edge type
90
+ * @returns true if edge was added, false if it already exists
91
+ */
92
+ addEdge(from: EntityId, to: EntityId, type: EdgeType): boolean;
93
+ /**
94
+ * Remove an edge from the graph.
95
+ */
96
+ removeEdge(from: EntityId, to: EntityId, type: EdgeType): boolean;
97
+ /**
98
+ * Get edges going out from a node.
99
+ */
100
+ getOutgoingEdges(id: EntityId, type?: EdgeType): GraphEdge[];
101
+ /**
102
+ * Get edges coming into a node.
103
+ */
104
+ getIncomingEdges(id: EntityId, type?: EdgeType): GraphEdge[];
105
+ /**
106
+ * Get all edges.
107
+ */
108
+ getAllEdges(): GraphEdge[];
109
+ /**
110
+ * Traverse forward from a node (follow outgoing edges).
111
+ *
112
+ * @see req:graph:traversal-forward
113
+ */
114
+ traverseForward(startId: EntityId, options?: TraversalOptions): EntityId[];
115
+ /**
116
+ * Traverse backward from a node (follow incoming edges).
117
+ *
118
+ * @see req:graph:traversal-backward
119
+ */
120
+ traverseBackward(startId: EntityId, options?: TraversalOptions): EntityId[];
121
+ /**
122
+ * Internal traversal implementation using BFS.
123
+ */
124
+ private traverse;
125
+ /**
126
+ * Get all nodes reachable from a given node (forward).
127
+ *
128
+ * @see req:graph:subgraph-extraction
129
+ */
130
+ getReachableFrom(id: EntityId): EntityId[];
131
+ /**
132
+ * Get all nodes that can reach a given node (backward).
133
+ *
134
+ * @see req:graph:subgraph-extraction
135
+ */
136
+ getReachableTo(id: EntityId): EntityId[];
137
+ /**
138
+ * Get the neighborhood of a node (nodes it can reach + nodes that can reach it).
139
+ *
140
+ * @see req:graph:subgraph-extraction
141
+ */
142
+ getNeighborhood(id: EntityId): EntityId[];
143
+ /**
144
+ * Find all nodes impacted by a change to the given node.
145
+ *
146
+ * @see req:graph:impact-analysis
147
+ */
148
+ getImpact(id: EntityId): EntityId[];
149
+ /**
150
+ * Find orphan requirements (no step traces to them).
151
+ *
152
+ * @see req:graph:orphan-detection
153
+ */
154
+ getOrphanRequirements(): EntityId[];
155
+ /**
156
+ * Find orphan artifacts (no step implements them).
157
+ *
158
+ * @see req:graph:orphan-detection
159
+ */
160
+ getOrphanArtifacts(): EntityId[];
161
+ /**
162
+ * Check if the graph is a valid DAG (no cycles).
163
+ *
164
+ * @see req:graph:structure
165
+ */
166
+ isDAG(): boolean;
167
+ /**
168
+ * Validate graph consistency.
169
+ *
170
+ * @see req:graph:consistency
171
+ */
172
+ validate(): ValidationResult;
173
+ /**
174
+ * Export graph to a plain object for serialization.
175
+ */
176
+ toJSON(): {
177
+ nodes: GraphNode[];
178
+ edges: GraphEdge[];
179
+ };
180
+ /**
181
+ * Create a graph from a plain object.
182
+ */
183
+ static fromJSON(data: {
184
+ nodes: GraphNode[];
185
+ edges: GraphEdge[];
186
+ }): IntentGraph;
187
+ }
188
+ /**
189
+ * Add a Spec and its Requirements to the graph.
190
+ */
191
+ export declare function addSpecToGraph(graph: IntentGraph, spec: Spec): void;
192
+ /**
193
+ * Add a Constraint and its Invariants to the graph.
194
+ */
195
+ export declare function addConstraintToGraph(graph: IntentGraph, constraint: Constraint): void;
196
+ /**
197
+ * Add a Plan and its Decisions/Steps to the graph.
198
+ */
199
+ export declare function addPlanToGraph(graph: IntentGraph, plan: Plan): void;
200
+ /**
201
+ * Add a Trace to the graph (linking artifact to step).
202
+ */
203
+ export declare function addTraceToGraph(graph: IntentGraph, trace: Trace): void;
204
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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"}
package/dist/graph.js ADDED
@@ -0,0 +1,496 @@
1
+ /**
2
+ * Intent Graph implementation.
3
+ *
4
+ * The intent graph is a directed acyclic graph (DAG) that connects
5
+ * specifications to implementations via plans and traces.
6
+ *
7
+ * @see spec:intent-graph:v1
8
+ */
9
+ import { computeHash } from './hash.js';
10
+ /**
11
+ * Intent Graph - the central data structure for provenance tracking.
12
+ *
13
+ * @see req:graph:structure
14
+ */
15
+ export class IntentGraph {
16
+ nodes = new Map();
17
+ edges = [];
18
+ outgoingEdges = new Map();
19
+ incomingEdges = new Map();
20
+ /**
21
+ * Create a new empty intent graph.
22
+ */
23
+ constructor() { }
24
+ /**
25
+ * Get the number of nodes in the graph.
26
+ */
27
+ get nodeCount() {
28
+ return this.nodes.size;
29
+ }
30
+ /**
31
+ * Get the number of edges in the graph.
32
+ */
33
+ get edgeCount() {
34
+ return this.edges.length;
35
+ }
36
+ // ============================================================================
37
+ // Node Operations
38
+ // ============================================================================
39
+ /**
40
+ * Add a node to the graph.
41
+ *
42
+ * @param id - Entity ID
43
+ * @param type - Node type
44
+ * @param data - Entity data
45
+ * @param hash - Optional pre-computed hash
46
+ */
47
+ addNode(id, type, data, hash) {
48
+ const node = {
49
+ id,
50
+ type,
51
+ data,
52
+ hash: hash ?? computeHash(data),
53
+ };
54
+ this.nodes.set(id, node);
55
+ return node;
56
+ }
57
+ /**
58
+ * Get a node by ID.
59
+ */
60
+ getNode(id) {
61
+ return this.nodes.get(id);
62
+ }
63
+ /**
64
+ * Check if a node exists.
65
+ */
66
+ hasNode(id) {
67
+ return this.nodes.has(id);
68
+ }
69
+ /**
70
+ * Remove a node and all its edges.
71
+ */
72
+ removeNode(id) {
73
+ if (!this.nodes.has(id)) {
74
+ return false;
75
+ }
76
+ // Remove all edges connected to this node
77
+ const outgoing = this.outgoingEdges.get(id) ?? [];
78
+ const incoming = this.incomingEdges.get(id) ?? [];
79
+ for (const edge of [...outgoing, ...incoming]) {
80
+ this.removeEdge(edge.from, edge.to, edge.type);
81
+ }
82
+ this.nodes.delete(id);
83
+ this.outgoingEdges.delete(id);
84
+ this.incomingEdges.delete(id);
85
+ return true;
86
+ }
87
+ /**
88
+ * Get all nodes of a specific type.
89
+ */
90
+ getNodesByType(type) {
91
+ const result = [];
92
+ for (const node of this.nodes.values()) {
93
+ if (node.type === type) {
94
+ result.push(node);
95
+ }
96
+ }
97
+ return result;
98
+ }
99
+ /**
100
+ * Get all nodes as an array.
101
+ */
102
+ getAllNodes() {
103
+ return Array.from(this.nodes.values());
104
+ }
105
+ // ============================================================================
106
+ // Edge Operations
107
+ // ============================================================================
108
+ /**
109
+ * Add an edge to the graph.
110
+ *
111
+ * @param from - Source node ID
112
+ * @param to - Target node ID
113
+ * @param type - Edge type
114
+ * @returns true if edge was added, false if it already exists
115
+ */
116
+ addEdge(from, to, type) {
117
+ // Check for duplicate
118
+ const existing = this.edges.find((e) => e.from === from && e.to === to && e.type === type);
119
+ if (existing !== undefined) {
120
+ return false;
121
+ }
122
+ const edge = { from, to, type };
123
+ this.edges.push(edge);
124
+ // Update adjacency lists
125
+ if (!this.outgoingEdges.has(from)) {
126
+ this.outgoingEdges.set(from, []);
127
+ }
128
+ this.outgoingEdges.get(from)?.push(edge);
129
+ if (!this.incomingEdges.has(to)) {
130
+ this.incomingEdges.set(to, []);
131
+ }
132
+ this.incomingEdges.get(to)?.push(edge);
133
+ return true;
134
+ }
135
+ /**
136
+ * Remove an edge from the graph.
137
+ */
138
+ removeEdge(from, to, type) {
139
+ const index = this.edges.findIndex((e) => e.from === from && e.to === to && e.type === type);
140
+ if (index === -1) {
141
+ return false;
142
+ }
143
+ this.edges.splice(index, 1);
144
+ // Update adjacency lists
145
+ const outgoing = this.outgoingEdges.get(from);
146
+ if (outgoing !== undefined) {
147
+ const outIndex = outgoing.findIndex((e) => e.to === to && e.type === type);
148
+ if (outIndex !== -1) {
149
+ outgoing.splice(outIndex, 1);
150
+ }
151
+ }
152
+ const incoming = this.incomingEdges.get(to);
153
+ if (incoming !== undefined) {
154
+ const inIndex = incoming.findIndex((e) => e.from === from && e.type === type);
155
+ if (inIndex !== -1) {
156
+ incoming.splice(inIndex, 1);
157
+ }
158
+ }
159
+ return true;
160
+ }
161
+ /**
162
+ * Get edges going out from a node.
163
+ */
164
+ getOutgoingEdges(id, type) {
165
+ const edges = this.outgoingEdges.get(id) ?? [];
166
+ if (type === undefined) {
167
+ return [...edges];
168
+ }
169
+ return edges.filter((e) => e.type === type);
170
+ }
171
+ /**
172
+ * Get edges coming into a node.
173
+ */
174
+ getIncomingEdges(id, type) {
175
+ const edges = this.incomingEdges.get(id) ?? [];
176
+ if (type === undefined) {
177
+ return [...edges];
178
+ }
179
+ return edges.filter((e) => e.type === type);
180
+ }
181
+ /**
182
+ * Get all edges.
183
+ */
184
+ getAllEdges() {
185
+ return [...this.edges];
186
+ }
187
+ // ============================================================================
188
+ // Traversal Operations
189
+ // ============================================================================
190
+ /**
191
+ * Traverse forward from a node (follow outgoing edges).
192
+ *
193
+ * @see req:graph:traversal-forward
194
+ */
195
+ traverseForward(startId, options = {}) {
196
+ return this.traverse(startId, 'forward', options);
197
+ }
198
+ /**
199
+ * Traverse backward from a node (follow incoming edges).
200
+ *
201
+ * @see req:graph:traversal-backward
202
+ */
203
+ traverseBackward(startId, options = {}) {
204
+ return this.traverse(startId, 'backward', options);
205
+ }
206
+ /**
207
+ * Internal traversal implementation using BFS.
208
+ */
209
+ traverse(startId, direction, options) {
210
+ const { maxDepth, edgeTypes, includeStart = false } = options;
211
+ const visited = new Set();
212
+ const result = [];
213
+ const queue = [
214
+ { id: startId, depth: 0 },
215
+ ];
216
+ while (queue.length > 0) {
217
+ const current = queue.shift();
218
+ if (current === undefined)
219
+ break;
220
+ const { id, depth } = current;
221
+ if (visited.has(id))
222
+ continue;
223
+ visited.add(id);
224
+ // Add to result (skip start if not included)
225
+ if (id !== startId || includeStart) {
226
+ result.push(id);
227
+ }
228
+ // Check depth limit
229
+ if (maxDepth !== undefined && depth >= maxDepth)
230
+ continue;
231
+ // Get edges based on direction
232
+ const edges = direction === 'forward'
233
+ ? this.getOutgoingEdges(id)
234
+ : this.getIncomingEdges(id);
235
+ // Follow edges
236
+ for (const edge of edges) {
237
+ // Filter by edge type if specified
238
+ if (edgeTypes !== undefined && !edgeTypes.includes(edge.type)) {
239
+ continue;
240
+ }
241
+ const nextId = direction === 'forward' ? edge.to : edge.from;
242
+ if (!visited.has(nextId)) {
243
+ queue.push({ id: nextId, depth: depth + 1 });
244
+ }
245
+ }
246
+ }
247
+ return result;
248
+ }
249
+ /**
250
+ * Get all nodes reachable from a given node (forward).
251
+ *
252
+ * @see req:graph:subgraph-extraction
253
+ */
254
+ getReachableFrom(id) {
255
+ return this.traverseForward(id, { includeStart: false });
256
+ }
257
+ /**
258
+ * Get all nodes that can reach a given node (backward).
259
+ *
260
+ * @see req:graph:subgraph-extraction
261
+ */
262
+ getReachableTo(id) {
263
+ return this.traverseBackward(id, { includeStart: false });
264
+ }
265
+ /**
266
+ * Get the neighborhood of a node (nodes it can reach + nodes that can reach it).
267
+ *
268
+ * @see req:graph:subgraph-extraction
269
+ */
270
+ getNeighborhood(id) {
271
+ const forward = new Set(this.getReachableFrom(id));
272
+ const backward = new Set(this.getReachableTo(id));
273
+ return [...new Set([...forward, ...backward])];
274
+ }
275
+ // ============================================================================
276
+ // Impact Analysis
277
+ // ============================================================================
278
+ /**
279
+ * Find all nodes impacted by a change to the given node.
280
+ *
281
+ * @see req:graph:impact-analysis
282
+ */
283
+ getImpact(id) {
284
+ return this.traverseForward(id, { includeStart: false });
285
+ }
286
+ // ============================================================================
287
+ // Orphan Detection
288
+ // ============================================================================
289
+ /**
290
+ * Find orphan requirements (no step traces to them).
291
+ *
292
+ * @see req:graph:orphan-detection
293
+ */
294
+ getOrphanRequirements() {
295
+ const orphans = [];
296
+ for (const node of this.getNodesByType('requirement')) {
297
+ const incoming = this.getIncomingEdges(node.id, 'traces_to');
298
+ if (incoming.length === 0) {
299
+ orphans.push(node.id);
300
+ }
301
+ }
302
+ return orphans;
303
+ }
304
+ /**
305
+ * Find orphan artifacts (no step implements them).
306
+ *
307
+ * @see req:graph:orphan-detection
308
+ */
309
+ getOrphanArtifacts() {
310
+ const orphans = [];
311
+ for (const node of this.getNodesByType('artifact')) {
312
+ const incoming = this.getIncomingEdges(node.id, 'implements');
313
+ if (incoming.length === 0) {
314
+ orphans.push(node.id);
315
+ }
316
+ }
317
+ return orphans;
318
+ }
319
+ // ============================================================================
320
+ // Validation
321
+ // ============================================================================
322
+ /**
323
+ * Check if the graph is a valid DAG (no cycles).
324
+ *
325
+ * @see req:graph:structure
326
+ */
327
+ isDAG() {
328
+ const visited = new Set();
329
+ const recursionStack = new Set();
330
+ const hasCycle = (id) => {
331
+ visited.add(id);
332
+ recursionStack.add(id);
333
+ const edges = this.getOutgoingEdges(id);
334
+ for (const edge of edges) {
335
+ if (!visited.has(edge.to)) {
336
+ if (hasCycle(edge.to)) {
337
+ return true;
338
+ }
339
+ }
340
+ else if (recursionStack.has(edge.to)) {
341
+ return true;
342
+ }
343
+ }
344
+ recursionStack.delete(id);
345
+ return false;
346
+ };
347
+ for (const id of this.nodes.keys()) {
348
+ if (!visited.has(id)) {
349
+ if (hasCycle(id)) {
350
+ return false;
351
+ }
352
+ }
353
+ }
354
+ return true;
355
+ }
356
+ /**
357
+ * Validate graph consistency.
358
+ *
359
+ * @see req:graph:consistency
360
+ */
361
+ validate() {
362
+ const errors = [];
363
+ const warnings = [];
364
+ // Check for cycles
365
+ if (!this.isDAG()) {
366
+ errors.push('Graph contains cycles');
367
+ }
368
+ // Check that all edge endpoints exist
369
+ for (const edge of this.edges) {
370
+ if (!this.nodes.has(edge.from)) {
371
+ errors.push(`Edge references non-existent source node: ${edge.from}`);
372
+ }
373
+ if (!this.nodes.has(edge.to)) {
374
+ errors.push(`Edge references non-existent target node: ${edge.to}`);
375
+ }
376
+ }
377
+ // Check for orphan requirements
378
+ const orphanReqs = this.getOrphanRequirements();
379
+ for (const id of orphanReqs) {
380
+ warnings.push(`Orphan requirement (no implementation): ${id}`);
381
+ }
382
+ // Check for orphan artifacts
383
+ const orphanArtifacts = this.getOrphanArtifacts();
384
+ for (const id of orphanArtifacts) {
385
+ warnings.push(`Orphan artifact (no implementing step): ${id}`);
386
+ }
387
+ return {
388
+ valid: errors.length === 0,
389
+ errors,
390
+ warnings,
391
+ };
392
+ }
393
+ // ============================================================================
394
+ // Serialization
395
+ // ============================================================================
396
+ /**
397
+ * Export graph to a plain object for serialization.
398
+ */
399
+ toJSON() {
400
+ return {
401
+ nodes: this.getAllNodes(),
402
+ edges: this.getAllEdges(),
403
+ };
404
+ }
405
+ /**
406
+ * Create a graph from a plain object.
407
+ */
408
+ static fromJSON(data) {
409
+ const graph = new IntentGraph();
410
+ for (const node of data.nodes) {
411
+ graph.nodes.set(node.id, node);
412
+ }
413
+ for (const edge of data.edges) {
414
+ graph.addEdge(edge.from, edge.to, edge.type);
415
+ }
416
+ return graph;
417
+ }
418
+ }
419
+ // ============================================================================
420
+ // Graph Building Helpers
421
+ // ============================================================================
422
+ /**
423
+ * Add a Spec and its Requirements to the graph.
424
+ */
425
+ export function addSpecToGraph(graph, spec) {
426
+ // Add spec node
427
+ graph.addNode(spec.id, 'spec', spec, spec.hash);
428
+ // Add requirement nodes and edges
429
+ for (const req of spec.requirements) {
430
+ graph.addNode(req.id, 'requirement', req);
431
+ graph.addEdge(spec.id, req.id, 'contains');
432
+ // Add dependency edges
433
+ if (req.dependencies !== undefined) {
434
+ for (const depId of req.dependencies) {
435
+ graph.addEdge(req.id, depId, 'depends_on');
436
+ }
437
+ }
438
+ }
439
+ }
440
+ /**
441
+ * Add a Constraint and its Invariants to the graph.
442
+ */
443
+ export function addConstraintToGraph(graph, constraint) {
444
+ // Add constraint node
445
+ graph.addNode(constraint.id, 'constraint', constraint, constraint.hash);
446
+ // Add invariant nodes and edges
447
+ for (const inv of constraint.invariants) {
448
+ graph.addNode(inv.id, 'invariant', inv);
449
+ graph.addEdge(constraint.id, inv.id, 'contains');
450
+ }
451
+ }
452
+ /**
453
+ * Add a Plan and its Decisions/Steps to the graph.
454
+ */
455
+ export function addPlanToGraph(graph, plan) {
456
+ // Add plan node
457
+ graph.addNode(plan.id, 'plan', plan, plan.hash);
458
+ // Add derives_from edges to sources
459
+ for (const source of plan.sources) {
460
+ graph.addEdge(plan.id, source.id, 'derives_from');
461
+ }
462
+ // Add decision nodes and edges
463
+ for (const decision of plan.decisions) {
464
+ graph.addNode(decision.id, 'decision', decision);
465
+ graph.addEdge(plan.id, decision.id, 'contains');
466
+ // Add traces_to edges
467
+ for (const targetId of decision.tracesTo) {
468
+ graph.addEdge(decision.id, targetId, 'traces_to');
469
+ }
470
+ }
471
+ // Add step nodes and edges
472
+ for (const step of plan.steps) {
473
+ graph.addNode(step.id, 'step', step);
474
+ graph.addEdge(plan.id, step.id, 'contains');
475
+ // Add traces_to edges
476
+ for (const targetId of step.tracesTo) {
477
+ graph.addEdge(step.id, targetId, 'traces_to');
478
+ }
479
+ // Add dependency edges
480
+ if (step.dependencies !== undefined) {
481
+ for (const depId of step.dependencies) {
482
+ graph.addEdge(step.id, depId, 'depends_on');
483
+ }
484
+ }
485
+ }
486
+ }
487
+ /**
488
+ * Add a Trace to the graph (linking artifact to step).
489
+ */
490
+ export function addTraceToGraph(graph, trace) {
491
+ // Add trace as artifact node
492
+ graph.addNode(trace.id, 'artifact', trace);
493
+ // Add implements edge from step to artifact
494
+ graph.addEdge(trace.step, trace.id, 'implements');
495
+ }
496
+ //# sourceMappingURL=graph.js.map