@ttsc/graph 0.16.6 → 0.16.8

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 (59) hide show
  1. package/README.md +45 -25
  2. package/lib/TtscGraphApplication.js +39 -16
  3. package/lib/TtscGraphApplication.js.map +1 -1
  4. package/lib/model/TtscGraphMemory.js +43 -4
  5. package/lib/model/TtscGraphMemory.js.map +1 -1
  6. package/lib/model/loadGraph.js +74 -90
  7. package/lib/model/loadGraph.js.map +1 -1
  8. package/lib/reduce.js +34 -3
  9. package/lib/reduce.js.map +1 -1
  10. package/lib/server/createServer.js +650 -247
  11. package/lib/server/createServer.js.map +1 -1
  12. package/lib/server/pathPolicy.js +35 -0
  13. package/lib/server/pathPolicy.js.map +1 -0
  14. package/lib/server/resultGuide.js +16 -0
  15. package/lib/server/resultGuide.js.map +1 -0
  16. package/lib/server/runDetails.js +71 -10
  17. package/lib/server/runDetails.js.map +1 -1
  18. package/lib/server/runEntrypoints.js +3 -4
  19. package/lib/server/runEntrypoints.js.map +1 -1
  20. package/lib/server/runLookup.js +21 -9
  21. package/lib/server/runLookup.js.map +1 -1
  22. package/lib/server/runOverview.js +13 -6
  23. package/lib/server/runOverview.js.map +1 -1
  24. package/lib/server/runTour.js +737 -0
  25. package/lib/server/runTour.js.map +1 -0
  26. package/lib/server/runTrace.js +108 -22
  27. package/lib/server/runTrace.js.map +1 -1
  28. package/lib/structures/ITtscGraphNext.js +3 -0
  29. package/lib/structures/ITtscGraphNext.js.map +1 -0
  30. package/lib/structures/ITtscGraphTour.js +3 -0
  31. package/lib/structures/ITtscGraphTour.js.map +1 -0
  32. package/lib/structures/index.js +2 -0
  33. package/lib/structures/index.js.map +1 -1
  34. package/package.json +3 -8
  35. package/src/TtscGraphApplication.ts +49 -16
  36. package/src/model/TtscGraphMemory.ts +46 -4
  37. package/src/reduce.ts +37 -5
  38. package/src/server/createServer.ts +7 -2
  39. package/src/server/pathPolicy.ts +43 -0
  40. package/src/server/resultGuide.ts +20 -0
  41. package/src/server/runDetails.ts +90 -6
  42. package/src/server/runEntrypoints.ts +9 -4
  43. package/src/server/runLookup.ts +33 -6
  44. package/src/server/runOverview.ts +24 -8
  45. package/src/server/runTour.ts +881 -0
  46. package/src/server/runTrace.ts +151 -23
  47. package/src/structures/ITtscGraphApplication.ts +126 -57
  48. package/src/structures/ITtscGraphDetails.ts +74 -11
  49. package/src/structures/ITtscGraphEntrypoints.ts +46 -15
  50. package/src/structures/ITtscGraphEscape.ts +19 -9
  51. package/src/structures/ITtscGraphLookup.ts +36 -15
  52. package/src/structures/ITtscGraphNext.ts +23 -0
  53. package/src/structures/ITtscGraphOverview.ts +20 -5
  54. package/src/structures/ITtscGraphTour.ts +150 -0
  55. package/src/structures/ITtscGraphTrace.ts +58 -21
  56. package/src/structures/index.ts +2 -0
  57. package/lib/server/instructions.js +0 -80
  58. package/lib/server/instructions.js.map +0 -1
  59. package/src/server/instructions.ts +0 -76
@@ -1,18 +1,22 @@
1
1
  import { TtscGraphMemory } from "../model/TtscGraphMemory";
2
+ import { ITtscGraphEdge } from "../structures/ITtscGraphEdge";
2
3
  import { ITtscGraphEvidence } from "../structures/ITtscGraphEvidence";
3
4
  import { ITtscGraphNode } from "../structures/ITtscGraphNode";
4
5
  import { ITtscGraphTrace } from "../structures/ITtscGraphTrace";
5
6
  import { accessAliasesFor } from "./accessAliases";
7
+ import { isExternalNode, isTestPath } from "./pathPolicy";
6
8
  import { resolveGraphHandle } from "./resolveHandle";
9
+ import { resultGuide, resultNext } from "./resultGuide";
7
10
  import { edgeEvidenceOf, edgeEvidenceTextOf, signatureOf } from "./runDetails";
8
11
 
9
12
  const DEFAULT_DEPTH = 2;
10
13
  const DEFAULT_MAX_NODES = 6;
11
14
  const MAX_OPEN_DEPTH = 2;
12
15
  const MAX_OPEN_NODES = 8;
13
- const MAX_HOPS_PER_NODE = 1;
16
+ const MAX_IMPACT_DEPTH = 4;
17
+ const MAX_IMPACT_NODES = 16;
18
+ const MAX_HOPS_PER_NODE = 2;
14
19
  const MAX_STEPS = 6;
15
- const MAX_NEXT_HANDLES = 2;
16
20
 
17
21
  /**
18
22
  * Breadth-first trace along the dependency graph. Structural
@@ -27,10 +31,22 @@ export function runTrace(
27
31
  ): ITtscGraphTrace {
28
32
  const direction = props.direction ?? "forward";
29
33
  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);
34
+ const impact = direction === "impact";
35
+ const maxDepth = bound(
36
+ props.maxDepth,
37
+ DEFAULT_DEPTH,
38
+ 1,
39
+ impact ? MAX_IMPACT_DEPTH : MAX_OPEN_DEPTH,
40
+ );
41
+ const maxNodes = bound(
42
+ props.maxNodes,
43
+ DEFAULT_MAX_NODES,
44
+ 1,
45
+ impact ? MAX_IMPACT_NODES : MAX_OPEN_NODES,
46
+ );
32
47
  const maxHops = maxNodes * MAX_HOPS_PER_NODE;
33
48
  const reverse = direction === "reverse" || direction === "impact";
49
+ const includeExternal = props.includeExternal === true;
34
50
  // Only an impact trace tags reached nodes with their public-surface role; for
35
51
  // forward/reverse the role is noise.
36
52
  const withRoles = direction === "impact";
@@ -43,6 +59,13 @@ export function runTrace(
43
59
  hops: [],
44
60
  reached: [],
45
61
  truncated: false,
62
+ next: resultNext(
63
+ "clarify",
64
+ "The start handle is ambiguous; choose one returned candidate.",
65
+ ),
66
+ guide: resultGuide(
67
+ "Disambiguate with the returned candidates, or ask the user for the intended symbol.",
68
+ ),
46
69
  candidates: start.candidates.map((n) => summary(graph, n)),
47
70
  };
48
71
  }
@@ -53,6 +76,13 @@ export function runTrace(
53
76
  hops: [],
54
77
  reached: [],
55
78
  truncated: false,
79
+ next: resultNext(
80
+ "clarify",
81
+ "The start handle did not resolve in the compiler graph.",
82
+ ),
83
+ guide: resultGuide(
84
+ "The start symbol was not resolved; answer that the graph has no trace from this handle.",
85
+ ),
56
86
  };
57
87
  }
58
88
 
@@ -65,6 +95,13 @@ export function runTrace(
65
95
  hops: [],
66
96
  reached: [],
67
97
  truncated: false,
98
+ next: resultNext(
99
+ "answer",
100
+ "The path result is the structural flow answer; cite path nodes and evidence ranges.",
101
+ ),
102
+ guide: resultGuide(
103
+ "Use the returned path, hops, and evidence ranges as the flow answer.",
104
+ ),
68
105
  };
69
106
  const target = resolveGraphHandle(graph, props.to);
70
107
  if (target.candidates) {
@@ -83,6 +120,7 @@ export function runTrace(
83
120
  target.node.id,
84
121
  bound(props.maxDepth, 12, 1, 12),
85
122
  focus,
123
+ includeExternal,
86
124
  );
87
125
  const path = found?.path ?? [];
88
126
  const hops = found?.hops ?? [];
@@ -93,7 +131,6 @@ export function runTrace(
93
131
  hops,
94
132
  path: path.map((node, i) => summary(graph, node, i, false, true)),
95
133
  steps: traceSteps(graph, hops),
96
- next: nextFromPath(path),
97
134
  };
98
135
  }
99
136
 
@@ -112,12 +149,18 @@ export function runTrace(
112
149
  truncated = true;
113
150
  continue;
114
151
  }
115
- const edges = reverse ? graph.incoming(id) : graph.outgoing(id);
152
+ const edges = orderedEdges(
153
+ graph,
154
+ reverse ? graph.incoming(id) : graph.outgoing(id),
155
+ direction,
156
+ reverse,
157
+ );
116
158
  for (const edge of edges) {
117
159
  if (!traversable(edge.kind, focus)) continue;
118
160
  const otherId = reverse ? edge.from : edge.to;
119
161
  const other = graph.node(otherId);
120
162
  if (other === undefined || other.kind === "file") continue;
163
+ if (!includeExternal && isExternalNode(other)) continue;
121
164
  const hop: ITtscGraphTrace.IHop = {
122
165
  from: edge.from,
123
166
  to: edge.to,
@@ -164,21 +207,17 @@ export function runTrace(
164
207
  hops,
165
208
  reached: [...reached.values()],
166
209
  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
- },
210
+ next: resultNext(
211
+ "answer",
212
+ "Steps, hops, reached nodes, and evidence ranges are the flow answer surface.",
213
+ ),
214
+ guide: resultGuide(
215
+ "Use steps, hops, reached nodes, and evidence ranges as the flow answer or reading-list anchor.",
216
+ ),
171
217
  truncated,
172
218
  };
173
219
  }
174
220
 
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
221
  function traceSteps(
183
222
  graph: TtscGraphMemory,
184
223
  hops: ITtscGraphTrace.IHop[],
@@ -209,6 +248,7 @@ function findPath(
209
248
  targetId: string,
210
249
  maxDepth: number,
211
250
  focus: ITtscGraphTrace.IRequest["focus"],
251
+ includeExternal: boolean,
212
252
  ): { path: ITtscGraphNode[]; hops: ITtscGraphTrace.IHop[] } | null {
213
253
  const startNode = graph.node(startId);
214
254
  if (startNode === undefined) return null;
@@ -234,6 +274,7 @@ function findPath(
234
274
  if (visited.has(otherId)) continue;
235
275
  const other = graph.node(otherId);
236
276
  if (other === undefined || other.kind === "file") continue;
277
+ if (!includeExternal && isExternalNode(other)) continue;
237
278
  visited.add(otherId);
238
279
  const evidence = edgeEvidenceOf(edge);
239
280
  parent.set(otherId, {
@@ -282,6 +323,59 @@ function findPath(
282
323
  return null;
283
324
  }
284
325
 
326
+ function orderedEdges(
327
+ graph: TtscGraphMemory,
328
+ edges: readonly ITtscGraphEdge[],
329
+ direction: string,
330
+ reverse: boolean,
331
+ ): readonly ITtscGraphEdge[] {
332
+ if (direction !== "impact")
333
+ return [...edges].sort(
334
+ (a, b) =>
335
+ edgeKindRank(a.kind) - edgeKindRank(b.kind) ||
336
+ traceEndpointRank(graph, reverse ? a.from : a.to) -
337
+ traceEndpointRank(graph, reverse ? b.from : b.to) ||
338
+ evidenceRank(a) - evidenceRank(b),
339
+ );
340
+ return [...edges].sort(
341
+ (a, b) =>
342
+ impactEndpointRank(graph, reverse ? a.from : a.to) -
343
+ impactEndpointRank(graph, reverse ? b.from : b.to) ||
344
+ edgeKindRank(a.kind) - edgeKindRank(b.kind) ||
345
+ evidenceRank(a) - evidenceRank(b),
346
+ );
347
+ }
348
+
349
+ function impactEndpointRank(graph: TtscGraphMemory, id: string): number {
350
+ const node = graph.node(id);
351
+ if (node === undefined) return 9;
352
+ if (isTestPath(node.file)) return 0;
353
+ if (node.exported) return 1;
354
+ if (node.external || node.ignored) return 4;
355
+ return 2;
356
+ }
357
+
358
+ function traceEndpointRank(graph: TtscGraphMemory, id: string): number {
359
+ const node = graph.node(id);
360
+ if (node === undefined) return 9;
361
+ if (isTestPath(node.file)) return 6;
362
+ switch (node.kind) {
363
+ case "function":
364
+ case "method":
365
+ case "class":
366
+ return 0;
367
+ case "variable":
368
+ return 1;
369
+ case "property":
370
+ return 2;
371
+ case "interface":
372
+ case "type":
373
+ return 4;
374
+ default:
375
+ return 3;
376
+ }
377
+ }
378
+
285
379
  /**
286
380
  * Summarize a node for a trace result. With `withRoles`, tag the public-surface
287
381
  * roles (exported / test) an impact trace reports; other directions omit them.
@@ -299,6 +393,16 @@ function summary(
299
393
  kind: node.kind,
300
394
  file: node.file,
301
395
  };
396
+ if (node.evidence?.startLine !== undefined)
397
+ out.line = node.evidence.startLine;
398
+ const span = node.implementation ?? node.evidence;
399
+ if (span !== undefined) {
400
+ out.sourceSpan = {
401
+ file: span.file,
402
+ startLine: span.startLine,
403
+ ...(span.endLine !== undefined ? { endLine: span.endLine } : {}),
404
+ };
405
+ }
302
406
  if (depth !== undefined) out.depth = depth;
303
407
  if (withSignature) {
304
408
  const sig = signatureOf(graph.project, node);
@@ -307,7 +411,7 @@ function summary(
307
411
  if (withRoles) {
308
412
  const roles: string[] = [];
309
413
  if (node.exported) roles.push("exported");
310
- if (isTestFile(node.file)) roles.push("test");
414
+ if (isTestPath(node.file)) roles.push("test");
311
415
  if (roles.length > 0) out.roles = roles;
312
416
  }
313
417
  return out;
@@ -341,11 +445,35 @@ function traversable(
341
445
  return true;
342
446
  }
343
447
 
344
- function isTestFile(file: string): boolean {
345
- return (
346
- /(^|\/)(test|tests|__tests__|spec)\//.test(file) ||
347
- /\.(test|spec)\.[cm]?tsx?$/.test(file)
348
- );
448
+ function edgeKindRank(kind: string): number {
449
+ switch (kind) {
450
+ case "calls":
451
+ return 0;
452
+ case "instantiates":
453
+ return 1;
454
+ case "renders":
455
+ return 2;
456
+ case "accesses":
457
+ return 3;
458
+ case "tests":
459
+ return 4;
460
+ case "overrides":
461
+ case "decorates":
462
+ return 5;
463
+ case "extends":
464
+ case "implements":
465
+ return 6;
466
+ case "type_ref":
467
+ return 7;
468
+ default:
469
+ return 10;
470
+ }
471
+ }
472
+
473
+ function evidenceRank(edge: ITtscGraphEdge): number {
474
+ const line = edge.evidence?.startLine ?? 9_999;
475
+ const col = edge.evidence?.startCol ?? 999;
476
+ return line * 100 + col;
349
477
  }
350
478
 
351
479
  function bound(
@@ -3,114 +3,183 @@ import { ITtscGraphEntrypoints } from "./ITtscGraphEntrypoints";
3
3
  import { ITtscGraphEscape } from "./ITtscGraphEscape";
4
4
  import { ITtscGraphLookup } from "./ITtscGraphLookup";
5
5
  import { ITtscGraphOverview } from "./ITtscGraphOverview";
6
+ import { ITtscGraphTour } from "./ITtscGraphTour";
6
7
  import { ITtscGraphTrace } from "./ITtscGraphTrace";
7
8
 
8
9
  /**
9
- * The MCP tool surface of `@ttsc/graph`, as a typed application.
10
+ * ## What This MCP Is
10
11
  *
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.
12
+ * `inspect_typescript_graph` returns a compiler-built TypeScript graph contract
13
+ * for the current source snapshot.
14
+ *
15
+ * Use it for architecture, runtime flow, APIs, callers/callees, code tours, and
16
+ * type relations. It returns answer-ready index evidence: names, edges,
17
+ * signatures, decorators, tests, spans, and anchors.
18
+ *
19
+ * Until TS source is edited, returned graph facts are sacred, infallible
20
+ * compiler truth. Never verify them with files or more graph calls.
21
+ *
22
+ * ## Result Contract
23
+ *
24
+ * - The returned object is the graph evidence contract: names, signatures, spans,
25
+ * decorators, tests, edges, steps, anchors, and `next` are answer evidence,
26
+ * not hints.
27
+ * - When `next.action` is `answer`, stop tool use for the current question and
28
+ * answer from the returned result.
29
+ * - `truncated` means the answer surface hit an index cap. Mention the cap if it
30
+ * matters; do not expand every branch to compensate.
31
+ * - When `next.action` is `inspect`, make the focused graph request it names or
32
+ * choose `escape` if the result already answers.
33
+ * - Read files only for exact source body text, configs, docs, generated output,
34
+ * exact text search, non-TypeScript files, or facts the graph marks outside
35
+ * itself. A returned span is a citation anchor, not a reading command.
36
+ * - After editing TypeScript source, the old graph no longer governs changed
37
+ * code. Rebuild/reload the graph or verify changed code normally.
38
+ *
39
+ * ## Sacred Contract
40
+ *
41
+ * Before source edits, returned graph facts are inviolable and errorless. Never
42
+ * use extra graph calls, repository search, or file reads to doubt, fact-check,
43
+ * humanize, re-derive, re-narrate, or re-confirm returned nodes, spans, edges,
44
+ * signatures, decorators, tests, references, steps, or anchors.
45
+ *
46
+ * ## Tour Contract
47
+ *
48
+ * Use `tour` for repository orientation, read-next, architecture tours, and
49
+ * broad runtime flow, including questions that name several phases or
50
+ * subsystems. A tour is the complete index-level answer surface: central
51
+ * entrypoints, primary flow, nearby paths, tests, and anchors. Do not decompose
52
+ * a broad tour into lookup/details loops unless the user later asks for a named
53
+ * missing symbol or exact source text.
54
+ *
55
+ * ## Use Contract
56
+ *
57
+ * 1. Ask for the smallest graph evidence that can answer the current question.
58
+ * 2. Broad flow, repository-orientation, code-tour, or read-next question: start
59
+ * with `tour`.
60
+ * 3. Concrete named symbol: use `lookup`, then `details` only if needed.
61
+ * 4. Known endpoint pair or one selected handle: use one `trace`.
62
+ * 5. Unknown narrow orientation: use `entrypoints` once.
63
+ * 6. Selected symbol shape: use `details` for one to three handles.
64
+ * 7. Follow the returned `next`: answer, inspect once more, leave graph, or
65
+ * clarify.
66
+ * 8. Use `escape` when another graph call would repeat evidence or the remaining
67
+ * evidence is outside the TypeScript graph.
68
+ *
69
+ * Most TypeScript structure answers need one or two graph calls.
70
+ *
71
+ * ## Request Fields
72
+ *
73
+ * Fill the visible checklist, then exactly one request.
74
+ *
75
+ * - `question`: restate the code question being considered.
76
+ * - `draft`: initial request type and why it seems smallest.
77
+ * - `review`: correct a wrong, broad, stale, or duplicate draft. If graph facts
78
+ * already answer, if prior `next.action` was `answer`, or if the next
79
+ * evidence is outside the indexed TypeScript graph, say so here and make
80
+ * `request.type` be `escape`. If a broad flow draft is not `tour`, correct it
81
+ * here.
82
+ * - `request`: final request after review.
83
+ *
84
+ * ## How to answer from graph evidence
85
+ *
86
+ * - Use returned node names, signatures, edges, references, evidence, and
87
+ * `sourceSpan` ranges directly.
88
+ * - Explain the central path first, then mention important branches.
89
+ * - For tests, impact, or reading lists, returned nodes and ranges are the answer
90
+ * evidence, not search keywords.
91
+ * - A returned range is a sacred citation anchor, not permission to open the
92
+ * file.
14
93
  */
15
94
  export interface ITtscGraphApplication {
16
95
  /**
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.
96
+ * Inspect the TypeScript compiler graph contract.
23
97
  *
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`.
98
+ * Use this before repository search when an answer depends on TypeScript
99
+ * symbols, calls, types, decorators, references, ranges, or runtime/source
100
+ * relationships. For repository orientation, read-next, architecture, and
101
+ * broad runtime flow questions, use `tour`.
27
102
  *
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.
103
+ * Returned nodes, edges, signatures, spans, tests, anchors, and `next` are
104
+ * the answer surface. If `next.action` is `answer`, stop tool use and answer
105
+ * from that result. Before source edits, graph facts are sacred, inviolable,
106
+ * complete, and infallible.
31
107
  *
32
- * @param props The reasoning and selected graph request
33
- * @returns One `result` union member matching the selected request type
108
+ * @param props Reasoning plus one graph request
109
+ * @returns Matching `result` union member
34
110
  */
35
- query(props: ITtscGraphApplication.IProps): ITtscGraphApplication.IResult;
111
+ inspect_typescript_graph(
112
+ props: ITtscGraphApplication.IProps,
113
+ ): ITtscGraphApplication.IResult;
36
114
  }
37
115
 
38
116
  export namespace ITtscGraphApplication {
39
- /** Think, review, then submit exactly one graph request. */
117
+ /** Draft, review, then submit exactly one graph request or escape. */
40
118
  export interface IProps {
41
119
  /**
42
120
  * User's TypeScript code question.
43
121
  *
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.
122
+ * Restate the code question being considered. If the next evidence is a
123
+ * script, config, doc, generated output, exact text, non-TypeScript file,
124
+ * or source body text, choose `escape`.
48
125
  */
49
126
  question: string;
50
127
 
51
128
  /**
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.
129
+ * Initial request plan before final arguments are filled.
63
130
  *
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`.
131
+ * Name the intended request type in `type` and why it seems smallest in
132
+ * `reason`. Broad flow, architecture, repository-orientation, and read-next
133
+ * questions should normally draft `tour`; narrow named symbols can draft
134
+ * `lookup`, `trace`, or `details`.
67
135
  */
68
- draft: IRequestDraft;
136
+ draft: IDraft;
69
137
 
70
138
  /**
71
- * Critical review of the draft request.
139
+ * Final self-review before calling.
72
140
  *
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`.
141
+ * Correct a stale, broad, duplicate, or wrong draft here. If broad flow was
142
+ * split into search/detail steps, switch to `tour`. If graph facts already
143
+ * answer, or prior `next.action` was `answer`, make `request.type` be
144
+ * `escape`; do not call graph or read files to re-confirm returned facts.
78
145
  */
79
146
  review: string;
80
147
 
81
- /** The graph operation chosen from the reasoning above, or a no-op escape. */
148
+ /** Final graph operation chosen after review, or a no-op escape. */
82
149
  request:
83
150
  | ITtscGraphEntrypoints.IRequest
84
151
  | ITtscGraphLookup.IRequest
85
152
  | ITtscGraphTrace.IRequest
86
153
  | ITtscGraphDetails.IRequest
87
154
  | ITtscGraphOverview.IRequest
155
+ | ITtscGraphTour.IRequest
88
156
  | ITtscGraphEscape.IRequest;
89
157
  }
90
158
 
91
- /** First-pass operation choice before final request arguments. */
92
- export interface IRequestDraft {
93
- /** Why this operation type is the smallest useful next step. */
159
+ /**
160
+ * First-pass request plan, filled before the final `request` arguments.
161
+ *
162
+ * `reason` comes before `type` so the justification is written before the
163
+ * choice it justifies.
164
+ */
165
+ export interface IDraft {
166
+ /** Why this request type looks like the smallest useful next step. */
94
167
  reason: string;
95
168
 
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"];
169
+ /** The request type being considered, corrected later in `review`. */
170
+ type: IProps["request"]["type"];
104
171
  }
105
172
 
106
173
  /** The selected request's output. `result.type` mirrors `request.type`. */
107
174
  export interface IResult {
175
+ /** Result branch matching the submitted `request.type`. */
108
176
  result:
109
177
  | ITtscGraphEntrypoints
110
178
  | ITtscGraphLookup
111
179
  | ITtscGraphTrace
112
180
  | ITtscGraphDetails
113
181
  | ITtscGraphOverview
182
+ | ITtscGraphTour
114
183
  | ITtscGraphEscape;
115
184
  }
116
185
  }