@ttsc/graph 0.16.4 → 0.16.6

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 (115) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +24 -53
  3. package/lib/TtscGraphApplication.js +59 -0
  4. package/lib/TtscGraphApplication.js.map +1 -0
  5. package/lib/index.js +31 -108
  6. package/lib/index.js.map +1 -1
  7. package/lib/model/TtscGraphMemory.js +185 -0
  8. package/lib/model/TtscGraphMemory.js.map +1 -0
  9. package/lib/model/loadGraph.js +418 -0
  10. package/lib/model/loadGraph.js.map +1 -0
  11. package/lib/reduce.js +101 -0
  12. package/lib/reduce.js.map +1 -0
  13. package/lib/resolveGraphBinary.js +42 -0
  14. package/lib/resolveGraphBinary.js.map +1 -0
  15. package/lib/server/accessAliases.js +53 -0
  16. package/lib/server/accessAliases.js.map +1 -0
  17. package/lib/server/createServer.js +1726 -0
  18. package/lib/server/createServer.js.map +1 -0
  19. package/lib/server/instructions.js +80 -0
  20. package/lib/server/instructions.js.map +1 -0
  21. package/lib/server/resolveHandle.js +25 -0
  22. package/lib/server/resolveHandle.js.map +1 -0
  23. package/lib/server/runDetails.js +413 -0
  24. package/lib/server/runDetails.js.map +1 -0
  25. package/lib/server/runEntrypoints.js +211 -0
  26. package/lib/server/runEntrypoints.js.map +1 -0
  27. package/lib/server/runLookup.js +234 -0
  28. package/lib/server/runLookup.js.map +1 -0
  29. package/lib/server/runOverview.js +160 -0
  30. package/lib/server/runOverview.js.map +1 -0
  31. package/lib/server/runTrace.js +314 -0
  32. package/lib/server/runTrace.js.map +1 -0
  33. package/lib/server/startServer.js +21 -0
  34. package/lib/server/startServer.js.map +1 -0
  35. package/lib/structures/ITtscGraphApplication.js +3 -0
  36. package/lib/structures/ITtscGraphApplication.js.map +1 -0
  37. package/lib/structures/ITtscGraphDecorator.js +3 -0
  38. package/lib/structures/ITtscGraphDecorator.js.map +1 -0
  39. package/lib/structures/ITtscGraphDetails.js +3 -0
  40. package/lib/structures/ITtscGraphDetails.js.map +1 -0
  41. package/lib/structures/ITtscGraphDiagnostic.js +3 -0
  42. package/lib/structures/ITtscGraphDiagnostic.js.map +1 -0
  43. package/lib/structures/ITtscGraphDump.js +3 -0
  44. package/lib/structures/ITtscGraphDump.js.map +1 -0
  45. package/lib/structures/ITtscGraphEdge.js +3 -0
  46. package/lib/structures/ITtscGraphEdge.js.map +1 -0
  47. package/lib/structures/ITtscGraphEntrypoints.js +3 -0
  48. package/lib/structures/ITtscGraphEntrypoints.js.map +1 -0
  49. package/lib/structures/ITtscGraphEscape.js +3 -0
  50. package/lib/structures/ITtscGraphEscape.js.map +1 -0
  51. package/lib/structures/ITtscGraphEvidence.js +3 -0
  52. package/lib/structures/ITtscGraphEvidence.js.map +1 -0
  53. package/lib/structures/ITtscGraphLookup.js +3 -0
  54. package/lib/structures/ITtscGraphLookup.js.map +1 -0
  55. package/lib/structures/ITtscGraphNode.js +3 -0
  56. package/lib/structures/ITtscGraphNode.js.map +1 -0
  57. package/lib/structures/ITtscGraphOverview.js +3 -0
  58. package/lib/structures/ITtscGraphOverview.js.map +1 -0
  59. package/lib/structures/ITtscGraphTrace.js +3 -0
  60. package/lib/structures/ITtscGraphTrace.js.map +1 -0
  61. package/lib/structures/TtscGraphEdgeKind.js +3 -0
  62. package/lib/structures/TtscGraphEdgeKind.js.map +1 -0
  63. package/lib/structures/TtscGraphNodeKind.js +3 -0
  64. package/lib/structures/TtscGraphNodeKind.js.map +1 -0
  65. package/lib/structures/TtscGraphNodeModifier.js +3 -0
  66. package/lib/structures/TtscGraphNodeModifier.js.map +1 -0
  67. package/lib/structures/index.js +38 -0
  68. package/lib/structures/index.js.map +1 -0
  69. package/lib/view.js +140 -0
  70. package/lib/view.js.map +1 -0
  71. package/lib/viewer/index.html +123 -0
  72. package/lib/viewer/viewer.js +4610 -0
  73. package/package.json +17 -4
  74. package/src/TtscGraphApplication.ts +64 -0
  75. package/src/index.ts +40 -126
  76. package/src/model/TtscGraphMemory.ts +204 -0
  77. package/src/model/loadGraph.ts +85 -0
  78. package/src/reduce.ts +165 -0
  79. package/src/resolveGraphBinary.ts +40 -0
  80. package/src/server/accessAliases.ts +55 -0
  81. package/src/server/createServer.ts +101 -0
  82. package/src/server/instructions.ts +76 -0
  83. package/src/server/resolveHandle.ts +34 -0
  84. package/src/server/runDetails.ts +469 -0
  85. package/src/server/runEntrypoints.ts +256 -0
  86. package/src/server/runLookup.ts +257 -0
  87. package/src/server/runOverview.ts +166 -0
  88. package/src/server/runTrace.ts +359 -0
  89. package/src/server/startServer.ts +25 -0
  90. package/src/structures/ITtscGraphApplication.ts +116 -0
  91. package/src/structures/ITtscGraphDecorator.ts +31 -0
  92. package/src/structures/ITtscGraphDetails.ts +134 -0
  93. package/src/structures/ITtscGraphDiagnostic.ts +34 -0
  94. package/src/structures/ITtscGraphDump.ts +35 -0
  95. package/src/structures/ITtscGraphEdge.ts +24 -0
  96. package/src/structures/ITtscGraphEntrypoints.ts +118 -0
  97. package/src/structures/ITtscGraphEscape.ts +39 -0
  98. package/src/structures/ITtscGraphEvidence.ts +26 -0
  99. package/src/structures/ITtscGraphLookup.ts +61 -0
  100. package/src/structures/ITtscGraphNode.ts +70 -0
  101. package/src/structures/ITtscGraphOverview.ts +87 -0
  102. package/src/structures/ITtscGraphTrace.ts +140 -0
  103. package/src/structures/TtscGraphEdgeKind.ts +23 -0
  104. package/src/structures/TtscGraphNodeKind.ts +26 -0
  105. package/src/structures/TtscGraphNodeModifier.ts +19 -0
  106. package/src/structures/index.ts +22 -0
  107. package/src/view.ts +155 -0
  108. package/src/viewer/index.html +123 -0
  109. package/src/viewer/main.ts +209 -0
  110. package/lib/bin.d.ts +0 -2
  111. package/lib/diagnostics.d.ts +0 -23
  112. package/lib/diagnostics.js +0 -84
  113. package/lib/diagnostics.js.map +0 -1
  114. package/lib/index.d.ts +0 -29
  115. package/src/diagnostics.ts +0 -93
@@ -0,0 +1,359 @@
1
+ import { TtscGraphMemory } from "../model/TtscGraphMemory";
2
+ import { ITtscGraphEvidence } from "../structures/ITtscGraphEvidence";
3
+ import { ITtscGraphNode } from "../structures/ITtscGraphNode";
4
+ import { ITtscGraphTrace } from "../structures/ITtscGraphTrace";
5
+ import { accessAliasesFor } from "./accessAliases";
6
+ import { resolveGraphHandle } from "./resolveHandle";
7
+ import { edgeEvidenceOf, edgeEvidenceTextOf, signatureOf } from "./runDetails";
8
+
9
+ const DEFAULT_DEPTH = 2;
10
+ const DEFAULT_MAX_NODES = 6;
11
+ const MAX_OPEN_DEPTH = 2;
12
+ const MAX_OPEN_NODES = 8;
13
+ const MAX_HOPS_PER_NODE = 1;
14
+ const MAX_STEPS = 6;
15
+ const MAX_NEXT_HANDLES = 2;
16
+
17
+ /**
18
+ * Breadth-first trace along the dependency graph. Structural
19
+ * (contains/exports/imports) edges are excluded so the path is real call/type
20
+ * flow; forward walks callees, reverse and impact walk callers. Impact
21
+ * additionally tags each reached node's role so the blast radius on the public
22
+ * surface is legible.
23
+ */
24
+ export function runTrace(
25
+ graph: TtscGraphMemory,
26
+ props: ITtscGraphTrace.IRequest,
27
+ ): ITtscGraphTrace {
28
+ const direction = props.direction ?? "forward";
29
+ const focus = props.focus ?? "all";
30
+ const maxDepth = bound(props.maxDepth, DEFAULT_DEPTH, 1, MAX_OPEN_DEPTH);
31
+ const maxNodes = bound(props.maxNodes, DEFAULT_MAX_NODES, 1, MAX_OPEN_NODES);
32
+ const maxHops = maxNodes * MAX_HOPS_PER_NODE;
33
+ const reverse = direction === "reverse" || direction === "impact";
34
+ // Only an impact trace tags reached nodes with their public-surface role; for
35
+ // forward/reverse the role is noise.
36
+ const withRoles = direction === "impact";
37
+
38
+ const start = resolveGraphHandle(graph, props.from);
39
+ if (start.candidates) {
40
+ return {
41
+ type: "trace",
42
+ direction,
43
+ hops: [],
44
+ reached: [],
45
+ truncated: false,
46
+ candidates: start.candidates.map((n) => summary(graph, n)),
47
+ };
48
+ }
49
+ if (start.node === undefined) {
50
+ return {
51
+ type: "trace",
52
+ direction,
53
+ hops: [],
54
+ reached: [],
55
+ truncated: false,
56
+ };
57
+ }
58
+
59
+ // Path mode: with `to`, return the dependency path from `from` to `to`, the
60
+ // one-call answer for "how does A reach B", instead of an open-ended trace.
61
+ if (props.to !== undefined && props.to !== "") {
62
+ const base = {
63
+ type: "trace" as const,
64
+ direction: "path",
65
+ hops: [],
66
+ reached: [],
67
+ truncated: false,
68
+ };
69
+ const target = resolveGraphHandle(graph, props.to);
70
+ if (target.candidates) {
71
+ return {
72
+ ...base,
73
+ start: summary(graph, start.node),
74
+ candidates: target.candidates.map((n) => summary(graph, n)),
75
+ };
76
+ }
77
+ if (target.node === undefined) {
78
+ return { ...base, start: summary(graph, start.node) };
79
+ }
80
+ const found = findPath(
81
+ graph,
82
+ start.node.id,
83
+ target.node.id,
84
+ bound(props.maxDepth, 12, 1, 12),
85
+ focus,
86
+ );
87
+ const path = found?.path ?? [];
88
+ const hops = found?.hops ?? [];
89
+ return {
90
+ ...base,
91
+ start: summary(graph, start.node),
92
+ target: summary(graph, target.node),
93
+ hops,
94
+ path: path.map((node, i) => summary(graph, node, i, false, true)),
95
+ steps: traceSteps(graph, hops),
96
+ next: nextFromPath(path),
97
+ };
98
+ }
99
+
100
+ const hops: ITtscGraphTrace.IHop[] = [];
101
+ const reached = new Map<string, ITtscGraphTrace.INode>();
102
+ const visited = new Set<string>([start.node.id]);
103
+ let queue: Array<{ id: string; depth: number }> = [
104
+ { id: start.node.id, depth: 0 },
105
+ ];
106
+ let truncated = false;
107
+
108
+ while (queue.length > 0) {
109
+ const next: Array<{ id: string; depth: number }> = [];
110
+ for (const { id, depth } of queue) {
111
+ if (depth >= maxDepth) {
112
+ truncated = true;
113
+ continue;
114
+ }
115
+ const edges = reverse ? graph.incoming(id) : graph.outgoing(id);
116
+ for (const edge of edges) {
117
+ if (!traversable(edge.kind, focus)) continue;
118
+ const otherId = reverse ? edge.from : edge.to;
119
+ const other = graph.node(otherId);
120
+ if (other === undefined || other.kind === "file") continue;
121
+ const hop: ITtscGraphTrace.IHop = {
122
+ from: edge.from,
123
+ to: edge.to,
124
+ kind: edge.kind,
125
+ depth: depth + 1,
126
+ };
127
+ const evidence = edgeEvidenceOf(edge);
128
+ if (evidence !== undefined) hop.evidence = evidence;
129
+ const aliases = accessAliasesFor(
130
+ graph.node(edge.to),
131
+ edgeEvidenceTextOf(edge),
132
+ );
133
+ if (aliases !== undefined) hop.aliases = aliases;
134
+ // A back-edge to the start or an already-reached node: record the hop;
135
+ // its endpoints are already represented.
136
+ if (visited.has(otherId)) {
137
+ if (hops.length >= maxHops) truncated = true;
138
+ else hops.push(hop);
139
+ continue;
140
+ }
141
+ // A new node past the cap is left unrepresented, so drop its hop too:
142
+ // every hop's endpoints stay resolvable in `reached`/`start`.
143
+ if (reached.size >= maxNodes) {
144
+ truncated = true;
145
+ continue;
146
+ }
147
+ if (hops.length >= maxHops) {
148
+ truncated = true;
149
+ continue;
150
+ }
151
+ visited.add(otherId);
152
+ reached.set(otherId, summary(graph, other, depth + 1, withRoles));
153
+ next.push({ id: otherId, depth: depth + 1 });
154
+ hops.push(hop);
155
+ }
156
+ }
157
+ queue = next;
158
+ }
159
+
160
+ return {
161
+ type: "trace",
162
+ start: summary(graph, start.node),
163
+ direction,
164
+ hops,
165
+ reached: [...reached.values()],
166
+ steps: traceSteps(graph, hops),
167
+ next: {
168
+ details: [start.node.id, ...reached.keys()].slice(0, MAX_NEXT_HANDLES),
169
+ traceFrom: [...reached.keys()].slice(0, MAX_NEXT_HANDLES),
170
+ },
171
+ truncated,
172
+ };
173
+ }
174
+
175
+ function nextFromPath(path: ITtscGraphNode[]): ITtscGraphTrace.INext {
176
+ return {
177
+ details: path.map((node) => node.id),
178
+ traceFrom: path.length > 0 ? [path[path.length - 1]!.id] : [],
179
+ };
180
+ }
181
+
182
+ function traceSteps(
183
+ graph: TtscGraphMemory,
184
+ hops: ITtscGraphTrace.IHop[],
185
+ ): string[] {
186
+ return hops.slice(0, MAX_STEPS).map((hop) => {
187
+ const from = graph.node(hop.from);
188
+ const to = graph.node(hop.to);
189
+ const lhs = from?.qualifiedName ?? from?.name ?? hop.from;
190
+ const rhs = to?.qualifiedName ?? to?.name ?? hop.to;
191
+ const evidence =
192
+ hop.evidence === undefined
193
+ ? ""
194
+ : ` at ${hop.evidence.file}:${hop.evidence.startLine}`;
195
+ const aliases =
196
+ hop.aliases === undefined ? "" : ` aliases ${hop.aliases.join(", ")}`;
197
+ return `${lhs} -[${hop.kind}${evidence}${aliases}]-> ${rhs}`;
198
+ });
199
+ }
200
+
201
+ /**
202
+ * The shortest dependency path from `startId` to `targetId` over real (non-
203
+ * structural) forward edges, breadth-first, or null when `targetId` is not
204
+ * reachable within maxDepth. Returns the nodes in order and the hops between.
205
+ */
206
+ function findPath(
207
+ graph: TtscGraphMemory,
208
+ startId: string,
209
+ targetId: string,
210
+ maxDepth: number,
211
+ focus: ITtscGraphTrace.IRequest["focus"],
212
+ ): { path: ITtscGraphNode[]; hops: ITtscGraphTrace.IHop[] } | null {
213
+ const startNode = graph.node(startId);
214
+ if (startNode === undefined) return null;
215
+ if (startId === targetId) return { path: [startNode], hops: [] };
216
+ const parent = new Map<
217
+ string,
218
+ {
219
+ via: string;
220
+ kind: string;
221
+ evidence?: ITtscGraphEvidence;
222
+ evidenceText?: string;
223
+ }
224
+ >();
225
+ const visited = new Set<string>([startId]);
226
+ let queue: Array<{ id: string; depth: number }> = [{ id: startId, depth: 0 }];
227
+ while (queue.length > 0) {
228
+ const next: Array<{ id: string; depth: number }> = [];
229
+ for (const { id, depth } of queue) {
230
+ if (depth >= maxDepth) continue;
231
+ for (const edge of graph.outgoing(id)) {
232
+ if (!traversable(edge.kind, focus)) continue;
233
+ const otherId = edge.to;
234
+ if (visited.has(otherId)) continue;
235
+ const other = graph.node(otherId);
236
+ if (other === undefined || other.kind === "file") continue;
237
+ visited.add(otherId);
238
+ const evidence = edgeEvidenceOf(edge);
239
+ parent.set(otherId, {
240
+ via: id,
241
+ kind: edge.kind,
242
+ evidence,
243
+ evidenceText: edgeEvidenceTextOf(edge),
244
+ });
245
+ if (otherId === targetId) {
246
+ const ids: string[] = [otherId];
247
+ let cur = otherId;
248
+ while (cur !== startId) {
249
+ const p = parent.get(cur);
250
+ if (p === undefined) break;
251
+ ids.unshift(p.via);
252
+ cur = p.via;
253
+ }
254
+ const path: ITtscGraphNode[] = [];
255
+ for (const nid of ids) {
256
+ const n = graph.node(nid);
257
+ if (n !== undefined) path.push(n);
258
+ }
259
+ const hops: ITtscGraphTrace.IHop[] = [];
260
+ for (let i = 1; i < path.length; i++) {
261
+ const node = path[i]!;
262
+ const parentEdge = parent.get(node.id);
263
+ const hop: ITtscGraphTrace.IHop = {
264
+ from: path[i - 1]!.id,
265
+ to: node.id,
266
+ kind: parentEdge?.kind ?? "calls",
267
+ depth: i,
268
+ };
269
+ if (parentEdge?.evidence !== undefined)
270
+ hop.evidence = parentEdge.evidence;
271
+ const aliases = accessAliasesFor(node, parentEdge?.evidenceText);
272
+ if (aliases !== undefined) hop.aliases = aliases;
273
+ hops.push(hop);
274
+ }
275
+ return { path, hops };
276
+ }
277
+ next.push({ id: otherId, depth: depth + 1 });
278
+ }
279
+ }
280
+ queue = next;
281
+ }
282
+ return null;
283
+ }
284
+
285
+ /**
286
+ * Summarize a node for a trace result. With `withRoles`, tag the public-surface
287
+ * roles (exported / test) an impact trace reports; other directions omit them.
288
+ */
289
+ function summary(
290
+ graph: TtscGraphMemory,
291
+ node: ITtscGraphNode,
292
+ depth?: number,
293
+ withRoles = false,
294
+ withSignature = false,
295
+ ): ITtscGraphTrace.INode {
296
+ const out: ITtscGraphTrace.INode = {
297
+ id: node.id,
298
+ name: node.qualifiedName ?? node.name,
299
+ kind: node.kind,
300
+ file: node.file,
301
+ };
302
+ if (depth !== undefined) out.depth = depth;
303
+ if (withSignature) {
304
+ const sig = signatureOf(graph.project, node);
305
+ if (sig !== undefined) out.signature = sig;
306
+ }
307
+ if (withRoles) {
308
+ const roles: string[] = [];
309
+ if (node.exported) roles.push("exported");
310
+ if (isTestFile(node.file)) roles.push("test");
311
+ if (roles.length > 0) out.roles = roles;
312
+ }
313
+ return out;
314
+ }
315
+
316
+ /** An edge the trace should follow: a real dependency, not a structural edge. */
317
+ function traversable(
318
+ kind: string,
319
+ focus: ITtscGraphTrace.IRequest["focus"],
320
+ ): boolean {
321
+ if (kind === "contains" || kind === "exports" || kind === "imports") {
322
+ return false;
323
+ }
324
+ if (focus === "execution") {
325
+ return (
326
+ kind === "calls" ||
327
+ kind === "instantiates" ||
328
+ kind === "accesses" ||
329
+ kind === "renders"
330
+ );
331
+ }
332
+ if (focus === "types") {
333
+ return (
334
+ kind === "type_ref" ||
335
+ kind === "extends" ||
336
+ kind === "implements" ||
337
+ kind === "overrides" ||
338
+ kind === "decorates"
339
+ );
340
+ }
341
+ return true;
342
+ }
343
+
344
+ function isTestFile(file: string): boolean {
345
+ return (
346
+ /(^|\/)(test|tests|__tests__|spec)\//.test(file) ||
347
+ /\.(test|spec)\.[cm]?tsx?$/.test(file)
348
+ );
349
+ }
350
+
351
+ function bound(
352
+ value: number | undefined,
353
+ fallback: number,
354
+ min: number,
355
+ max: number,
356
+ ): number {
357
+ const n = value === undefined || !Number.isFinite(value) ? fallback : value;
358
+ return Math.max(min, Math.min(max, Math.floor(n)));
359
+ }
@@ -0,0 +1,25 @@
1
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
+
3
+ import { TtscGraphMemory } from "../model/TtscGraphMemory";
4
+ import { loadGraph } from "../model/loadGraph";
5
+ import { createServer } from "./createServer";
6
+
7
+ /**
8
+ * Serve the graph tools over MCP on stdio. The server answers the MCP handshake
9
+ * immediately and builds the resident graph on the first tool call, so a large
10
+ * project cannot make the client give up before tools are advertised.
11
+ */
12
+ export async function startServer(options: {
13
+ cwd?: string;
14
+ tsconfig?: string;
15
+ /** Server version reported in the MCP handshake. */
16
+ version: string;
17
+ }): Promise<void> {
18
+ let graph: TtscGraphMemory | undefined;
19
+ const server = createServer(() => {
20
+ graph ??= loadGraph({ cwd: options.cwd, tsconfig: options.tsconfig });
21
+ return graph;
22
+ }, options.version);
23
+ const transport = new StdioServerTransport();
24
+ await server.connect(transport);
25
+ }
@@ -0,0 +1,116 @@
1
+ import { ITtscGraphDetails } from "./ITtscGraphDetails";
2
+ import { ITtscGraphEntrypoints } from "./ITtscGraphEntrypoints";
3
+ import { ITtscGraphEscape } from "./ITtscGraphEscape";
4
+ import { ITtscGraphLookup } from "./ITtscGraphLookup";
5
+ import { ITtscGraphOverview } from "./ITtscGraphOverview";
6
+ import { ITtscGraphTrace } from "./ITtscGraphTrace";
7
+
8
+ /**
9
+ * The MCP tool surface of `@ttsc/graph`, as a typed application.
10
+ *
11
+ * The single method is the single MCP tool. Its parameter object becomes the
12
+ * JSON schema once `typia.llm.controller` reflects this interface.
13
+ * `TtscGraphApplication` implements it over the resident graph.
14
+ */
15
+ export interface ITtscGraphApplication {
16
+ /**
17
+ * Query the TypeScript project graph for code evidence.
18
+ *
19
+ * Use this before answering TypeScript codebase questions. It returns
20
+ * checker-resolved symbols, dependency paths, edge evidence ranges, and
21
+ * sourceSpan anchors from the resident graph, avoiding assumptions, shell
22
+ * search, or file reads when graph evidence is enough.
23
+ *
24
+ * Fill properties in order: question, graphNeed, draft, review, request.
25
+ * Write `draft.reason` before `draft.type`, then choose `entrypoints`,
26
+ * `lookup`, `trace`, `details`, `overview`, or `escape`.
27
+ *
28
+ * Most answers should need 1-3 calls; four is the hard stop for one answer.
29
+ * Keep slices small, prefer defaults, and stop once file/symbol/range
30
+ * evidence is enough.
31
+ *
32
+ * @param props The reasoning and selected graph request
33
+ * @returns One `result` union member matching the selected request type
34
+ */
35
+ query(props: ITtscGraphApplication.IProps): ITtscGraphApplication.IResult;
36
+ }
37
+
38
+ export namespace ITtscGraphApplication {
39
+ /** Think, review, then submit exactly one graph request. */
40
+ export interface IProps {
41
+ /**
42
+ * User's TypeScript code question.
43
+ *
44
+ * Restate the codebase question being answered. Keep this about TypeScript
45
+ * source, symbols, call flow, type flow, or architecture. If the user is
46
+ * asking about scripts, config, generated output, or documentation instead,
47
+ * say that boundary here.
48
+ */
49
+ question: string;
50
+
51
+ /**
52
+ * Why the resident graph is the next evidence source.
53
+ *
54
+ * State what graph evidence is needed and why assumptions or broad shell
55
+ * search are not the next step for this call. Name the smallest evidence
56
+ * that would let the agent stop. If graph is not actually the right source,
57
+ * say that and use `escape`.
58
+ */
59
+ graphNeed: string;
60
+
61
+ /**
62
+ * First request-type decision before arguments are filled.
63
+ *
64
+ * Explain why one operation class is smaller than the alternatives, then
65
+ * name it in `draft.type`. This is only the draft; the final arguments are
66
+ * in `request` after `review`.
67
+ */
68
+ draft: IRequestDraft;
69
+
70
+ /**
71
+ * Critical review of the draft request.
72
+ *
73
+ * Check whether the draft avoids overfetch, non-graph fallback, broad
74
+ * reads, and unnecessary neighbor expansion. If this would be a fourth
75
+ * broad lookup, trace, or details call, prefer answering from evidence in
76
+ * hand or choose `escape`. Do not spend graph calls only to hunt for tests.
77
+ * If the draft is wrong, choose the corrected type in `request`.
78
+ */
79
+ review: string;
80
+
81
+ /** The graph operation chosen from the reasoning above, or a no-op escape. */
82
+ request:
83
+ | ITtscGraphEntrypoints.IRequest
84
+ | ITtscGraphLookup.IRequest
85
+ | ITtscGraphTrace.IRequest
86
+ | ITtscGraphDetails.IRequest
87
+ | ITtscGraphOverview.IRequest
88
+ | ITtscGraphEscape.IRequest;
89
+ }
90
+
91
+ /** First-pass operation choice before final request arguments. */
92
+ export interface IRequestDraft {
93
+ /** Why this operation type is the smallest useful next step. */
94
+ reason: string;
95
+
96
+ /** Draft discriminator for the intended graph operation. */
97
+ type:
98
+ | ITtscGraphEntrypoints.IRequest["type"]
99
+ | ITtscGraphLookup.IRequest["type"]
100
+ | ITtscGraphTrace.IRequest["type"]
101
+ | ITtscGraphDetails.IRequest["type"]
102
+ | ITtscGraphOverview.IRequest["type"]
103
+ | ITtscGraphEscape.IRequest["type"];
104
+ }
105
+
106
+ /** The selected request's output. `result.type` mirrors `request.type`. */
107
+ export interface IResult {
108
+ result:
109
+ | ITtscGraphEntrypoints
110
+ | ITtscGraphLookup
111
+ | ITtscGraphTrace
112
+ | ITtscGraphDetails
113
+ | ITtscGraphOverview
114
+ | ITtscGraphEscape;
115
+ }
116
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * A decorator as written on a declaration, carried on the decorated
3
+ * {@link ITtscGraphNode}'s `decorators`.
4
+ *
5
+ * The graph reports the decorator faithfully rather than interpreting any
6
+ * framework's convention: the `name` is the decorator as written (`Controller`,
7
+ * `Get`, `TypedRoute.Get`, ...), and statically resolvable literal arguments
8
+ * are preserved so a consumer can apply its own meaning without re-parsing
9
+ * source.
10
+ */
11
+ export interface ITtscGraphDecorator {
12
+ /**
13
+ * The decorator name as written, qualified through its access path:
14
+ * `Controller`, `Get`, `TypedRoute.Get`, `MessagePattern`.
15
+ */
16
+ name: string;
17
+
18
+ /** The literal call arguments, in source order. Empty for a bare decorator. */
19
+ arguments: ITtscGraphDecorator.IArgument[];
20
+ }
21
+ export namespace ITtscGraphDecorator {
22
+ /**
23
+ * One argument of an {@link ITtscGraphDecorator}. `literal` is set only when
24
+ * the argument is a string, number, or boolean literal the producer could
25
+ * resolve statically, so a consumer can use it without evaluating code.
26
+ */
27
+ export interface IArgument {
28
+ /** The statically-resolved literal value, when the argument is a literal. */
29
+ literal?: string | number | boolean;
30
+ }
31
+ }
@@ -0,0 +1,134 @@
1
+ import { ITtscGraphDecorator } from "./ITtscGraphDecorator";
2
+ import { ITtscGraphEvidence } from "./ITtscGraphEvidence";
3
+
4
+ /**
5
+ * The resolved symbol details returned for a set of handles.
6
+ *
7
+ * The default payload is source-free: signatures, member outlines, and direct
8
+ * graph summaries with sourceSpan anchors.
9
+ */
10
+ export interface ITtscGraphDetails {
11
+ /** Discriminator for selected symbol inspection. */
12
+ type: "details";
13
+
14
+ nodes: ITtscGraphDetails.INode[];
15
+
16
+ /** Handles that resolved to no node, or that were ambiguous. */
17
+ unknown: string[];
18
+ }
19
+ export namespace ITtscGraphDetails {
20
+ /** Which handles to inspect, and how much of each to return. */
21
+ export interface IRequest {
22
+ /** Discriminator for selected symbol inspection. */
23
+ type: "details";
24
+
25
+ /**
26
+ * Node ids from another tool, or dotted symbol handles such as
27
+ * `OrderService.create`. Pass the few handles you need for source-free
28
+ * details; use `trace` when you need a path instead of widening this call.
29
+ */
30
+ handles: string[];
31
+
32
+ /**
33
+ * Also list each node's direct dependencies and dependents (the symbols it
34
+ * uses and the symbols that use it). The list is capped; raise
35
+ * `neighborLimit` only when the first slice is not enough.
36
+ *
37
+ * @default false
38
+ */
39
+ neighbors?: boolean;
40
+
41
+ /**
42
+ * Maximum dependencies and dependents to return per side when
43
+ * `neighbors:true`.
44
+ *
45
+ * @default 2
46
+ */
47
+ neighborLimit?: number;
48
+
49
+ /**
50
+ * Maximum owned members to return for a container or object literal. Raise
51
+ * only when the first outline is truncated.
52
+ *
53
+ * @default 6
54
+ */
55
+ memberLimit?: number;
56
+
57
+ /**
58
+ * Maximum direct execution and type references to return per group. Raise
59
+ * only when the first dependency slice is not enough.
60
+ *
61
+ * @default 1
62
+ */
63
+ dependencyLimit?: number;
64
+ }
65
+
66
+ /** One inspected node: its declared shape and graph coordinates. */
67
+ export interface INode {
68
+ id: string;
69
+ name: string;
70
+ kind: string;
71
+ file: string;
72
+ /** 1-based declaration line, when known. */
73
+ line?: number;
74
+ /** The declaration signature: its first line(s) up to the body. */
75
+ signature?: string;
76
+ /** Decorators written on this declaration, when any. */
77
+ decorators?: ITtscGraphDecorator[];
78
+ /** Assigned implementation span, when source comes from one. */
79
+ implementation?: ITtscGraphEvidence;
80
+ /** Direct execution dependencies in source order, with edge evidence. */
81
+ calls?: IReference[];
82
+ /** Direct type dependencies in source order, with edge evidence. */
83
+ types?: IReference[];
84
+ /** String literal values from the signature. */
85
+ literals?: string[];
86
+ /**
87
+ * For a container or object-literal variable: the owned symbol or top-level
88
+ * property outline a consumer reaches for, without bodies.
89
+ */
90
+ members?: IMember[];
91
+ /** The declaration or implementation file and line range, when known. */
92
+ sourceSpan?: Pick<ITtscGraphEvidence, "file" | "startLine" | "endLine">;
93
+ /** Symbols this node uses (outgoing dependency edges). */
94
+ dependsOn?: IReference[];
95
+ /** Symbols that use this node (incoming dependency edges). */
96
+ dependedOnBy?: IReference[];
97
+ }
98
+
99
+ /** One member of a container node, with its signature but not its body. */
100
+ export interface IMember {
101
+ name: string;
102
+ kind: string;
103
+ /** 1-based declaration line, when known. */
104
+ line?: number;
105
+ /** The member's declaration signature. */
106
+ signature?: string;
107
+ /** Decorators written on this member, when any. */
108
+ decorators?: ITtscGraphDecorator[];
109
+ }
110
+
111
+ /** A dependency neighbor of an inspected node and the edge that links them. */
112
+ export interface IReference {
113
+ id: string;
114
+ name: string;
115
+ kind: string;
116
+ file: string;
117
+ /** 1-based declaration line, when known. */
118
+ line?: number;
119
+ /** The edge kind connecting the two (`calls`, `type_ref`, ...). */
120
+ relation: string;
121
+ /**
122
+ * Source span for the expression that produced this relationship. It lets
123
+ * an agent see why the edge exists without opening the file.
124
+ */
125
+ evidence?: ITtscGraphEvidence;
126
+ /**
127
+ * Stable access-path aliases derived from edge evidence. For example, an
128
+ * edge to `Owner.member` through `obj.slot.member` may expose
129
+ * `Owner.slot.member` so answers can preserve both the resolved symbol and
130
+ * the source access path.
131
+ */
132
+ aliases?: string[];
133
+ }
134
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * A compiler or plugin diagnostic, fused onto the graph so an edit-triage query
3
+ * can name the owning symbol of an error.
4
+ *
5
+ * The TypeScript semantic pass contributes numeric-coded `tsc` diagnostics;
6
+ * `@ttsc/lint` rules and transform plugins (typia, nestia, …) contribute
7
+ * `plugin`/`lint` findings whose `code` is a string. `node` is set when the
8
+ * finding's position was attributed to a graph node.
9
+ */
10
+ export interface ITtscGraphDiagnostic {
11
+ /** Project-relative path of the file the diagnostic is reported in. */
12
+ file: string;
13
+
14
+ /** 1-based line of the diagnostic. */
15
+ line: number;
16
+
17
+ /** 1-based column of the diagnostic, when known. */
18
+ column?: number;
19
+
20
+ /** Numeric `tsc` code, or string rule id for a lint/plugin finding. */
21
+ code: number | string;
22
+
23
+ /** The human-readable diagnostic message. */
24
+ message: string;
25
+
26
+ /** Severity, when the producer distinguishes it. */
27
+ severity?: "error" | "warning" | "info" | "hint";
28
+
29
+ /** Which lane produced the diagnostic. */
30
+ origin?: "tsc" | "plugin" | "lint";
31
+
32
+ /** Node id the diagnostic was fused onto, when resolved. */
33
+ node?: string;
34
+ }