@mrclrchtr/supi-code-intelligence 0.1.0

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 +212 -0
  2. package/node_modules/@mrclrchtr/supi-core/README.md +90 -0
  3. package/node_modules/@mrclrchtr/supi-core/package.json +30 -0
  4. package/node_modules/@mrclrchtr/supi-core/src/config-settings.ts +76 -0
  5. package/node_modules/@mrclrchtr/supi-core/src/config.ts +186 -0
  6. package/node_modules/@mrclrchtr/supi-core/src/context-messages.ts +119 -0
  7. package/node_modules/@mrclrchtr/supi-core/src/context-provider-registry.ts +36 -0
  8. package/node_modules/@mrclrchtr/supi-core/src/context-tag.ts +31 -0
  9. package/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +255 -0
  10. package/node_modules/@mrclrchtr/supi-core/src/index.ts +83 -0
  11. package/node_modules/@mrclrchtr/supi-core/src/project-roots.ts +170 -0
  12. package/node_modules/@mrclrchtr/supi-core/src/registry-utils.ts +54 -0
  13. package/node_modules/@mrclrchtr/supi-core/src/session-utils.ts +29 -0
  14. package/node_modules/@mrclrchtr/supi-core/src/settings-command.ts +15 -0
  15. package/node_modules/@mrclrchtr/supi-core/src/settings-registry.ts +41 -0
  16. package/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +226 -0
  17. package/node_modules/@mrclrchtr/supi-core/src/terminal.ts +60 -0
  18. package/node_modules/@mrclrchtr/supi-lsp/README.md +112 -0
  19. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +90 -0
  20. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +30 -0
  21. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config-settings.ts +76 -0
  22. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config.ts +186 -0
  23. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/context-messages.ts +119 -0
  24. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/context-provider-registry.ts +36 -0
  25. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/context-tag.ts +31 -0
  26. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +255 -0
  27. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/index.ts +83 -0
  28. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/project-roots.ts +170 -0
  29. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/registry-utils.ts +54 -0
  30. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/session-utils.ts +29 -0
  31. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings-command.ts +15 -0
  32. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings-registry.ts +41 -0
  33. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +226 -0
  34. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/terminal.ts +60 -0
  35. package/node_modules/@mrclrchtr/supi-lsp/package.json +45 -0
  36. package/node_modules/@mrclrchtr/supi-lsp/src/capabilities.ts +62 -0
  37. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-refresh.ts +229 -0
  38. package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +545 -0
  39. package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +192 -0
  40. package/node_modules/@mrclrchtr/supi-lsp/src/config.ts +143 -0
  41. package/node_modules/@mrclrchtr/supi-lsp/src/defaults.json +82 -0
  42. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostic-augmentation.ts +82 -0
  43. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostic-display.ts +68 -0
  44. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostic-summary.ts +73 -0
  45. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostics.ts +98 -0
  46. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/stale-diagnostics.ts +47 -0
  47. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/suppression-diagnostics.ts +58 -0
  48. package/node_modules/@mrclrchtr/supi-lsp/src/format.ts +359 -0
  49. package/node_modules/@mrclrchtr/supi-lsp/src/guidance.ts +163 -0
  50. package/node_modules/@mrclrchtr/supi-lsp/src/index.ts +17 -0
  51. package/node_modules/@mrclrchtr/supi-lsp/src/lsp-state.ts +82 -0
  52. package/node_modules/@mrclrchtr/supi-lsp/src/lsp.ts +470 -0
  53. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-client-state.ts +34 -0
  54. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +139 -0
  55. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-helpers.ts +39 -0
  56. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-project-info.ts +46 -0
  57. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-types.ts +39 -0
  58. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +83 -0
  59. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-symbol.ts +18 -0
  60. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +550 -0
  61. package/node_modules/@mrclrchtr/supi-lsp/src/overrides.ts +173 -0
  62. package/node_modules/@mrclrchtr/supi-lsp/src/pattern-matcher.ts +197 -0
  63. package/node_modules/@mrclrchtr/supi-lsp/src/renderer.ts +120 -0
  64. package/node_modules/@mrclrchtr/supi-lsp/src/scanner.ts +153 -0
  65. package/node_modules/@mrclrchtr/supi-lsp/src/search-fallback.ts +98 -0
  66. package/node_modules/@mrclrchtr/supi-lsp/src/service-registry.ts +153 -0
  67. package/node_modules/@mrclrchtr/supi-lsp/src/settings-registration.ts +292 -0
  68. package/node_modules/@mrclrchtr/supi-lsp/src/summary.ts +153 -0
  69. package/node_modules/@mrclrchtr/supi-lsp/src/tool-actions.ts +430 -0
  70. package/node_modules/@mrclrchtr/supi-lsp/src/tree-persist.ts +48 -0
  71. package/node_modules/@mrclrchtr/supi-lsp/src/tsconfig-scope.ts +156 -0
  72. package/node_modules/@mrclrchtr/supi-lsp/src/types.ts +409 -0
  73. package/node_modules/@mrclrchtr/supi-lsp/src/ui.ts +358 -0
  74. package/node_modules/@mrclrchtr/supi-lsp/src/utils.ts +122 -0
  75. package/node_modules/@mrclrchtr/supi-lsp/src/workspace-sentinels.ts +114 -0
  76. package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +97 -0
  77. package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +67 -0
  78. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/.gitkeep +0 -0
  79. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/bash/tree-sitter-bash.wasm +0 -0
  80. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/bash/tree-sitter-bash.wasm.json +7 -0
  81. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/c/tree-sitter-c.wasm +0 -0
  82. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/c/tree-sitter-c.wasm.json +7 -0
  83. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/cpp/tree-sitter-cpp.wasm +0 -0
  84. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/cpp/tree-sitter-cpp.wasm.json +7 -0
  85. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/go/tree-sitter-go.wasm +0 -0
  86. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/go/tree-sitter-go.wasm.json +7 -0
  87. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/html/tree-sitter-html.wasm +0 -0
  88. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/html/tree-sitter-html.wasm.json +7 -0
  89. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/java/tree-sitter-java.wasm +0 -0
  90. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/java/tree-sitter-java.wasm.json +7 -0
  91. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/javascript/tree-sitter-javascript.wasm +0 -0
  92. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/javascript/tree-sitter-javascript.wasm.json +7 -0
  93. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/kotlin/tree-sitter-kotlin.wasm +0 -0
  94. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/kotlin/tree-sitter-kotlin.wasm.json +12 -0
  95. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/python/tree-sitter-python.wasm +0 -0
  96. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/python/tree-sitter-python.wasm.json +7 -0
  97. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/r/tree-sitter-r.wasm +0 -0
  98. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/r/tree-sitter-r.wasm.json +7 -0
  99. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/ruby/tree-sitter-ruby.wasm +0 -0
  100. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/ruby/tree-sitter-ruby.wasm.json +7 -0
  101. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/rust/tree-sitter-rust.wasm +0 -0
  102. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/rust/tree-sitter-rust.wasm.json +7 -0
  103. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/sql/tree-sitter-sql.wasm +0 -0
  104. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/sql/tree-sitter-sql.wasm.json +19 -0
  105. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/tsx/tree-sitter-tsx.wasm +0 -0
  106. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/tsx/tree-sitter-tsx.wasm.json +7 -0
  107. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/typescript/tree-sitter-typescript.wasm +0 -0
  108. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/typescript/tree-sitter-typescript.wasm.json +7 -0
  109. package/node_modules/@mrclrchtr/supi-tree-sitter/scripts/generate-kotlin-wasm.mjs +126 -0
  110. package/node_modules/@mrclrchtr/supi-tree-sitter/scripts/generate-sql-wasm.mjs +144 -0
  111. package/node_modules/@mrclrchtr/supi-tree-sitter/scripts/vendor-wasm.mjs +151 -0
  112. package/node_modules/@mrclrchtr/supi-tree-sitter/src/callees.ts +343 -0
  113. package/node_modules/@mrclrchtr/supi-tree-sitter/src/coordinates.ts +108 -0
  114. package/node_modules/@mrclrchtr/supi-tree-sitter/src/exports.ts +315 -0
  115. package/node_modules/@mrclrchtr/supi-tree-sitter/src/formatting.ts +104 -0
  116. package/node_modules/@mrclrchtr/supi-tree-sitter/src/imports.ts +42 -0
  117. package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +16 -0
  118. package/node_modules/@mrclrchtr/supi-tree-sitter/src/language.ts +116 -0
  119. package/node_modules/@mrclrchtr/supi-tree-sitter/src/node-at.ts +96 -0
  120. package/node_modules/@mrclrchtr/supi-tree-sitter/src/outline.ts +287 -0
  121. package/node_modules/@mrclrchtr/supi-tree-sitter/src/runtime.ts +237 -0
  122. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session.ts +112 -0
  123. package/node_modules/@mrclrchtr/supi-tree-sitter/src/structure.ts +7 -0
  124. package/node_modules/@mrclrchtr/supi-tree-sitter/src/syntax-node.ts +13 -0
  125. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tree-sitter.ts +306 -0
  126. package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +146 -0
  127. package/package.json +47 -0
  128. package/src/actions/affected-action.ts +310 -0
  129. package/src/actions/brief-action.ts +242 -0
  130. package/src/actions/callees-action.ts +134 -0
  131. package/src/actions/callers-action.ts +215 -0
  132. package/src/actions/implementations-action.ts +190 -0
  133. package/src/actions/index-action.ts +187 -0
  134. package/src/actions/pattern-action.ts +232 -0
  135. package/src/architecture.ts +367 -0
  136. package/src/brief-focused.ts +383 -0
  137. package/src/brief.ts +228 -0
  138. package/src/code-intelligence.ts +122 -0
  139. package/src/git-context.ts +65 -0
  140. package/src/guidance.ts +39 -0
  141. package/src/index.ts +28 -0
  142. package/src/resolve-target.ts +104 -0
  143. package/src/search-helpers.ts +283 -0
  144. package/src/target-resolution.ts +368 -0
  145. package/src/tool-actions.ts +109 -0
  146. package/src/types.ts +57 -0
@@ -0,0 +1,383 @@
1
+ // Focused brief generation — directory and file briefs.
2
+
3
+ import * as fs from "node:fs";
4
+ import * as path from "node:path";
5
+ import type { ArchitectureModel } from "./architecture.ts";
6
+ import { findModuleForPath, getDependencies, getDependents } from "./architecture.ts";
7
+ import { formatGitContext, gatherGitContext } from "./git-context.ts";
8
+ import type { BriefDetails, ConfidenceMode } from "./types.ts";
9
+
10
+ /**
11
+ * Generate a focused brief for a specific path (directory or file).
12
+ */
13
+ export function generateFocusedBrief(
14
+ model: ArchitectureModel,
15
+ focusPath: string,
16
+ ): { content: string; details: BriefDetails } {
17
+ const resolvedPath = path.resolve(focusPath);
18
+
19
+ if (!fs.existsSync(resolvedPath)) {
20
+ return {
21
+ content: `**Error:** Path not found: \`${focusPath}\``,
22
+ details: {
23
+ confidence: "unavailable",
24
+ focusTarget: focusPath,
25
+ startHere: [],
26
+ publicSurfaces: [],
27
+ dependencySummary: null,
28
+ omittedCount: 0,
29
+ nextQueries: [],
30
+ },
31
+ };
32
+ }
33
+
34
+ const stat = fs.statSync(resolvedPath);
35
+
36
+ if (stat.isDirectory()) {
37
+ return generateDirectoryBrief(model, resolvedPath, focusPath);
38
+ }
39
+
40
+ return generateFileBrief(model, resolvedPath, focusPath);
41
+ }
42
+
43
+ function generateDirectoryBrief(
44
+ model: ArchitectureModel,
45
+ resolvedPath: string,
46
+ originalPath: string,
47
+ ): { content: string; details: BriefDetails } {
48
+ const mod = findModuleForPath(model, resolvedPath);
49
+ const lines: string[] = [];
50
+ const confidence: ConfidenceMode = "structural";
51
+ const startHere: Array<{ target: string; reason: string }> = [];
52
+ const publicSurfaces: string[] = [];
53
+ const nextQueries: string[] = [];
54
+
55
+ if (mod && mod.root === resolvedPath) {
56
+ formatModuleBrief({ mod, model, lines, startHere, publicSurfaces, nextQueries, resolvedPath });
57
+ } else {
58
+ formatNonModuleDir({ model, mod, resolvedPath, originalPath, lines });
59
+ }
60
+
61
+ if (nextQueries.length > 0) {
62
+ lines.push("");
63
+ lines.push("## Next");
64
+ for (const q of nextQueries.slice(0, 2)) {
65
+ lines.push(`- ${q}`);
66
+ }
67
+ }
68
+
69
+ const gitCtx = gatherGitContext(model.root);
70
+ if (gitCtx) {
71
+ lines.push(formatGitContext(gitCtx));
72
+ }
73
+
74
+ lines.push("");
75
+
76
+ return {
77
+ content: lines.join("\n"),
78
+ details: {
79
+ confidence,
80
+ focusTarget: originalPath,
81
+ startHere: startHere.slice(0, 3),
82
+ publicSurfaces: publicSurfaces.slice(0, 5),
83
+ dependencySummary: mod ? { moduleCount: 1, edgeCount: mod.internalDeps.length } : null,
84
+ omittedCount: 0,
85
+ nextQueries,
86
+ },
87
+ };
88
+ }
89
+
90
+ interface ModuleBriefContext {
91
+ mod: NonNullable<ReturnType<typeof findModuleForPath>>;
92
+ model: ArchitectureModel;
93
+ lines: string[];
94
+ startHere: Array<{ target: string; reason: string }>;
95
+ publicSurfaces: string[];
96
+ nextQueries: string[];
97
+ resolvedPath: string;
98
+ }
99
+
100
+ function formatModuleBrief(ctx: ModuleBriefContext): void {
101
+ const { mod, model, lines, startHere, publicSurfaces, nextQueries, resolvedPath } = ctx;
102
+ const shortName = mod.name.replace(/^@[^/]+\//, "");
103
+ lines.push(`# Module: ${shortName}`);
104
+ if (mod.description) {
105
+ lines.push("");
106
+ lines.push(mod.description);
107
+ }
108
+ lines.push("");
109
+ lines.push(`- Path: \`${mod.relativePath}\``);
110
+
111
+ if (mod.entrypoints.length > 0) {
112
+ lines.push(`- Entrypoints: ${mod.entrypoints.map((e) => `\`${e}\``).join(", ")}`);
113
+ for (const ep of mod.entrypoints) {
114
+ publicSurfaces.push(`${shortName}: ${ep}`);
115
+ startHere.push({ target: ep, reason: "module entrypoint" });
116
+ }
117
+ }
118
+
119
+ addDependenciesSection(model, mod, lines);
120
+ addDependentsSection(model, mod, lines, nextQueries);
121
+ addSourceFilesSection(resolvedPath, lines);
122
+ }
123
+
124
+ function addDependenciesSection(
125
+ model: ArchitectureModel,
126
+ mod: NonNullable<ReturnType<typeof findModuleForPath>>,
127
+ lines: string[],
128
+ ): void {
129
+ const deps = getDependencies(model, mod.name);
130
+ if (deps.length > 0) {
131
+ lines.push("");
132
+ lines.push("## Dependencies (internal)");
133
+ for (const dep of deps) {
134
+ const depShort = dep.name.replace(/^@[^/]+\//, "");
135
+ lines.push(`- ${depShort} (\`${dep.relativePath}\`)`);
136
+ }
137
+ }
138
+
139
+ if (mod.externalDeps.length > 0) {
140
+ const shown = mod.externalDeps.slice(0, 8);
141
+ lines.push("");
142
+ lines.push("## Dependencies (external)");
143
+ for (const dep of shown) {
144
+ lines.push(`- ${dep}`);
145
+ }
146
+ if (mod.externalDeps.length > 8) {
147
+ lines.push(`- _+${mod.externalDeps.length - 8} more_`);
148
+ }
149
+ }
150
+ }
151
+
152
+ function addDependentsSection(
153
+ model: ArchitectureModel,
154
+ mod: NonNullable<ReturnType<typeof findModuleForPath>>,
155
+ lines: string[],
156
+ nextQueries: string[],
157
+ ): void {
158
+ const dependents = getDependents(model, mod.name);
159
+ if (dependents.length > 0) {
160
+ lines.push("");
161
+ lines.push("## Dependents");
162
+ for (const dep of dependents) {
163
+ const depShort = dep.name.replace(/^@[^/]+\//, "");
164
+ lines.push(`- ${depShort} (\`${dep.relativePath}\`)`);
165
+ }
166
+ nextQueries.push("`code_intel affected` before modifying exports from this module");
167
+ }
168
+
169
+ if (mod.entrypoints.length > 0) {
170
+ const ep = mod.entrypoints[0];
171
+ nextQueries.push(
172
+ `\`code_intel brief\` with \`file: "${mod.relativePath}/${ep.replace(/^\.\//, "")}"\` for entrypoint details`,
173
+ );
174
+ }
175
+ }
176
+
177
+ function addSourceFilesSection(resolvedPath: string, lines: string[]): void {
178
+ const files = listSourceFiles(resolvedPath);
179
+ if (files.length > 0) {
180
+ const shown = files.slice(0, 10);
181
+ lines.push("");
182
+ lines.push("## Source Files");
183
+ for (const f of shown) {
184
+ lines.push(`- \`${f}\``);
185
+ }
186
+ if (files.length > 10) {
187
+ lines.push(`- _+${files.length - 10} more files_`);
188
+ }
189
+ }
190
+ }
191
+
192
+ interface NonModuleDirContext {
193
+ model: ArchitectureModel;
194
+ mod: ReturnType<typeof findModuleForPath>;
195
+ resolvedPath: string;
196
+ originalPath: string;
197
+ lines: string[];
198
+ }
199
+
200
+ function formatNonModuleDir(ctx: NonModuleDirContext): void {
201
+ const { model, mod, resolvedPath, originalPath, lines } = ctx;
202
+ const relPath = path.relative(model.root, resolvedPath);
203
+ lines.push(`# Directory: ${relPath || originalPath}`);
204
+ lines.push("");
205
+
206
+ if (mod) {
207
+ const shortName = mod.name.replace(/^@[^/]+\//, "");
208
+ lines.push(`_Inside module: ${shortName} (\`${mod.relativePath}\`)_`);
209
+ lines.push("");
210
+ }
211
+
212
+ const files = listSourceFiles(resolvedPath);
213
+ if (files.length > 0) {
214
+ const shown = files.slice(0, 10);
215
+ lines.push("## Source Files");
216
+ for (const f of shown) {
217
+ lines.push(`- \`${f}\``);
218
+ }
219
+ if (files.length > 10) {
220
+ lines.push(`- _+${files.length - 10} more files_`);
221
+ }
222
+ } else {
223
+ lines.push("No recognized source files in this directory.");
224
+ }
225
+ }
226
+
227
+ function generateFileBrief(
228
+ model: ArchitectureModel,
229
+ resolvedPath: string,
230
+ originalPath: string,
231
+ ): { content: string; details: BriefDetails } {
232
+ const mod = findModuleForPath(model, resolvedPath);
233
+ const lines: string[] = [];
234
+ const confidence: ConfidenceMode = "structural";
235
+ const publicSurfaces: string[] = [];
236
+ const nextQueries: string[] = [];
237
+
238
+ const fileName = path.basename(resolvedPath);
239
+ const relPath = path.relative(model.root, resolvedPath);
240
+
241
+ lines.push(`# File: ${relPath || fileName}`);
242
+ lines.push("");
243
+
244
+ if (mod) {
245
+ const shortName = mod.name.replace(/^@[^/]+\//, "");
246
+ lines.push(`_Module: ${shortName} (\`${mod.relativePath}\`)_`);
247
+ lines.push("");
248
+
249
+ const isEntrypoint = mod.entrypoints.some((ep) => {
250
+ const epResolved = path.resolve(mod.root, ep);
251
+ return epResolved === resolvedPath;
252
+ });
253
+ if (isEntrypoint) {
254
+ lines.push("**This file is a module entrypoint.**");
255
+ lines.push("");
256
+ publicSurfaces.push(`${shortName} entrypoint`);
257
+ }
258
+ }
259
+
260
+ try {
261
+ const content = fs.readFileSync(resolvedPath, "utf-8");
262
+ const lineCount = content.split("\n").length;
263
+ lines.push(`- Lines: ${lineCount}`);
264
+ lines.push(`- Extension: \`${path.extname(resolvedPath)}\``);
265
+ } catch {
266
+ lines.push("_Could not read file contents._");
267
+ }
268
+
269
+ nextQueries.push(
270
+ `\`code_intel callers\` with \`file: "${relPath}"\` and a line/character for call-site analysis`,
271
+ );
272
+ if (mod) {
273
+ nextQueries.push(
274
+ `\`code_intel brief\` with \`path: "${mod.relativePath}"\` for the containing module overview`,
275
+ );
276
+ }
277
+
278
+ if (nextQueries.length > 0) {
279
+ lines.push("");
280
+ lines.push("## Next");
281
+ for (const q of nextQueries.slice(0, 2)) {
282
+ lines.push(`- ${q}`);
283
+ }
284
+ }
285
+
286
+ const gitCtx = gatherGitContext(model.root);
287
+ if (gitCtx) {
288
+ lines.push(formatGitContext(gitCtx));
289
+ }
290
+
291
+ lines.push("");
292
+
293
+ return {
294
+ content: lines.join("\n"),
295
+ details: {
296
+ confidence,
297
+ focusTarget: originalPath,
298
+ startHere: [],
299
+ publicSurfaces,
300
+ dependencySummary: null,
301
+ omittedCount: 0,
302
+ nextQueries,
303
+ },
304
+ };
305
+ }
306
+
307
+ // ── Helpers ───────────────────────────────────────────────────────────
308
+
309
+ const SOURCE_EXTENSIONS = new Set([
310
+ // JS/TS
311
+ ".ts",
312
+ ".tsx",
313
+ ".js",
314
+ ".jsx",
315
+ ".mts",
316
+ ".cts",
317
+ ".mjs",
318
+ ".cjs",
319
+ // Python
320
+ ".py",
321
+ ".pyi",
322
+ // Rust
323
+ ".rs",
324
+ // Go
325
+ ".go",
326
+ ".mod",
327
+ // C/C++
328
+ ".c",
329
+ ".h",
330
+ ".cpp",
331
+ ".hpp",
332
+ ".cc",
333
+ ".cxx",
334
+ ".hxx",
335
+ ".c++",
336
+ ".h++",
337
+ // Java / Kotlin
338
+ ".java",
339
+ ".kt",
340
+ ".kts",
341
+ // Ruby
342
+ ".rb",
343
+ // Shell
344
+ ".sh",
345
+ ".bash",
346
+ ".zsh",
347
+ // Web
348
+ ".html",
349
+ ".htm",
350
+ ".xhtml",
351
+ ".css",
352
+ ".scss",
353
+ ".less",
354
+ // Data / Config
355
+ ".json",
356
+ ".yaml",
357
+ ".yml",
358
+ ".toml",
359
+ ".md",
360
+ // Other languages
361
+ ".php",
362
+ ".swift",
363
+ ".cs",
364
+ ".r",
365
+ ".sql",
366
+ ]);
367
+
368
+ function listSourceFiles(dir: string): string[] {
369
+ const files: string[] = [];
370
+ try {
371
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
372
+ for (const entry of entries) {
373
+ if (!entry.isFile()) continue;
374
+ if (entry.name.startsWith(".")) continue;
375
+ if (SOURCE_EXTENSIONS.has(path.extname(entry.name))) {
376
+ files.push(entry.name);
377
+ }
378
+ }
379
+ } catch {
380
+ // Directory not readable
381
+ }
382
+ return files.sort((a, b) => a.localeCompare(b));
383
+ }
package/src/brief.ts ADDED
@@ -0,0 +1,228 @@
1
+ // Brief generation — compact overviews and project briefs from the architecture model.
2
+
3
+ import type { ArchitectureModel } from "./architecture.ts";
4
+ import { getDependents } from "./architecture.ts";
5
+ import { formatGitContext, gatherGitContext } from "./git-context.ts";
6
+ import type { BriefDetails, ConfidenceMode } from "./types.ts";
7
+
8
+ // Re-export focused brief generation
9
+ export { generateFocusedBrief } from "./brief-focused.ts";
10
+
11
+ // ── Overview (first-turn injection) ───────────────────────────────────
12
+
13
+ /**
14
+ * Generate a compact architecture overview for first-turn session injection.
15
+ * Targets roughly 500 tokens or less; prefers dense module-edge format.
16
+ */
17
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: overview formatting with module/edge budget logic
18
+ export function generateOverview(model: ArchitectureModel): string | null {
19
+ if (model.modules.length === 0) return null;
20
+
21
+ const lines: string[] = [];
22
+ lines.push("# Project: Code Intelligence Overview");
23
+ lines.push("");
24
+
25
+ if (model.name) {
26
+ lines.push(`**${model.name}**${model.description ? ` — ${model.description}` : ""}`);
27
+ lines.push("");
28
+ }
29
+
30
+ // Dense module-edge format (budget: ~8 modules, ~8 edges)
31
+ const modules = model.modules.slice(0, 8);
32
+ const dependedOn = new Set(model.edges.map((e) => e.to));
33
+
34
+ lines.push("## Modules");
35
+ lines.push("");
36
+
37
+ for (const mod of modules) {
38
+ const isLeaf = !dependedOn.has(mod.name);
39
+ const deps = mod.internalDeps.filter((d) => modules.some((m) => m.name === d));
40
+ const shortName = mod.name.replace(/^@[^/]+\//, "");
41
+
42
+ if (deps.length === 0) {
43
+ lines.push(
44
+ `- **${shortName}**${isLeaf ? " (leaf)" : ""}${mod.description ? ` — ${mod.description}` : ""}`,
45
+ );
46
+ } else {
47
+ const depNames = deps.slice(0, 4).map((d) => d.replace(/^@[^/]+\//, ""));
48
+ const depStr = depNames.join(", ");
49
+ const suffix = deps.length > 4 ? ` +${deps.length - 4} more` : "";
50
+ lines.push(
51
+ `- **${shortName}** → ${depStr}${suffix}${mod.description ? ` — ${mod.description}` : ""}`,
52
+ );
53
+ }
54
+ }
55
+
56
+ if (model.modules.length > 8) {
57
+ lines.push(`- _+${model.modules.length - 8} more modules omitted_`);
58
+ }
59
+
60
+ lines.push("");
61
+
62
+ const gitCtx = gatherGitContext(model.root);
63
+ if (gitCtx) {
64
+ lines.push(formatGitContext(gitCtx));
65
+ }
66
+
67
+ lines.push("_Use `code_intel brief` for deeper context on any module or file._");
68
+
69
+ return lines.join("\n");
70
+ }
71
+
72
+ // ── Full-project brief ────────────────────────────────────────────────
73
+
74
+ /**
75
+ * Generate a full-project brief from the architecture model.
76
+ */
77
+ export function generateProjectBrief(model: ArchitectureModel): {
78
+ content: string;
79
+ details: BriefDetails;
80
+ } {
81
+ const lines: string[] = [];
82
+ const confidence: ConfidenceMode = "structural";
83
+
84
+ lines.push("# Project Brief");
85
+ lines.push("");
86
+
87
+ if (model.name) {
88
+ lines.push(`**${model.name}**${model.description ? ` — ${model.description}` : ""}`);
89
+ lines.push("");
90
+ }
91
+
92
+ const gitCtx = gatherGitContext(model.root);
93
+ if (gitCtx) {
94
+ lines.push(formatGitContext(gitCtx));
95
+ }
96
+
97
+ if (model.modules.length === 0) {
98
+ lines.push(
99
+ "No structured modules detected. This appears to be a minimal or source-only project.",
100
+ );
101
+ return {
102
+ content: lines.join("\n"),
103
+ details: {
104
+ confidence,
105
+ focusTarget: null,
106
+ startHere: [],
107
+ publicSurfaces: [],
108
+ dependencySummary: null,
109
+ omittedCount: 0,
110
+ nextQueries: [],
111
+ },
112
+ };
113
+ }
114
+
115
+ const { startHere, publicSurfaces } = addModuleSections(lines, model);
116
+ addDependencyGraph(lines, model);
117
+
118
+ const topStartHere = startHere.sort((a, b) => b.reason.length - a.reason.length).slice(0, 3);
119
+ addStartHereSection(lines, topStartHere);
120
+
121
+ const nextQueries = buildNextQueries(model, publicSurfaces);
122
+ addNextSection(lines, nextQueries);
123
+
124
+ return {
125
+ content: lines.join("\n"),
126
+ details: {
127
+ confidence,
128
+ focusTarget: null,
129
+ startHere: topStartHere,
130
+ publicSurfaces: publicSurfaces.slice(0, 5),
131
+ dependencySummary: { moduleCount: model.modules.length, edgeCount: model.edges.length },
132
+ omittedCount: 0,
133
+ nextQueries,
134
+ },
135
+ };
136
+ }
137
+
138
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: module section generation with conditional formatting
139
+ function addModuleSections(
140
+ lines: string[],
141
+ model: ArchitectureModel,
142
+ ): { startHere: Array<{ target: string; reason: string }>; publicSurfaces: string[] } {
143
+ lines.push("## Modules");
144
+ lines.push("");
145
+
146
+ const startHere: Array<{ target: string; reason: string }> = [];
147
+ const publicSurfaces: string[] = [];
148
+
149
+ for (const mod of model.modules) {
150
+ const shortName = mod.name.replace(/^@[^/]+\//, "");
151
+ const deps = mod.internalDeps.map((d) => d.replace(/^@[^/]+\//, "")).join(", ");
152
+ const dependents = getDependents(model, mod.name);
153
+ const depCount = dependents.length;
154
+
155
+ lines.push(`### ${shortName}`);
156
+ if (mod.description) lines.push(`${mod.description}`);
157
+ lines.push(`- Path: \`${mod.relativePath}\``);
158
+ if (mod.entrypoints.length > 0) {
159
+ lines.push(`- Entrypoints: ${mod.entrypoints.map((e) => `\`${e}\``).join(", ")}`);
160
+ publicSurfaces.push(`${shortName}: ${mod.entrypoints[0]}`);
161
+ }
162
+ if (deps) lines.push(`- Dependencies: ${deps}`);
163
+ if (depCount > 0) lines.push(`- Dependents: ${depCount} module${depCount > 1 ? "s" : ""}`);
164
+ if (mod.isLeaf) lines.push("- _(leaf — no internal dependents)_");
165
+ lines.push("");
166
+
167
+ if (depCount >= 2) {
168
+ startHere.push({
169
+ target: `${shortName} (${mod.relativePath})`,
170
+ reason: `core dependency used by ${depCount} modules`,
171
+ });
172
+ }
173
+ }
174
+
175
+ return { startHere, publicSurfaces };
176
+ }
177
+
178
+ function addDependencyGraph(lines: string[], model: ArchitectureModel): void {
179
+ if (model.edges.length === 0) return;
180
+ lines.push("## Dependency Graph");
181
+ lines.push("");
182
+ for (const edge of model.edges.slice(0, 15)) {
183
+ const from = edge.from.replace(/^@[^/]+\//, "");
184
+ const to = edge.to.replace(/^@[^/]+\//, "");
185
+ lines.push(`- ${from} → ${to}`);
186
+ }
187
+ if (model.edges.length > 15) {
188
+ lines.push(`- _+${model.edges.length - 15} more edges omitted_`);
189
+ }
190
+ lines.push("");
191
+ }
192
+
193
+ function addStartHereSection(
194
+ lines: string[],
195
+ topStartHere: Array<{ target: string; reason: string }>,
196
+ ): void {
197
+ if (topStartHere.length === 0) return;
198
+ lines.push("## Start Here");
199
+ lines.push("");
200
+ for (const item of topStartHere) {
201
+ lines.push(`- **${item.target}** — ${item.reason}`);
202
+ }
203
+ lines.push("");
204
+ }
205
+
206
+ function buildNextQueries(model: ArchitectureModel, publicSurfaces: string[]): string[] {
207
+ const nextQueries: string[] = [];
208
+ if (model.modules.length > 0) {
209
+ const firstMod = model.modules[0];
210
+ nextQueries.push(
211
+ `\`code_intel brief\` with \`path: "${firstMod.relativePath}"\` for a focused module brief`,
212
+ );
213
+ }
214
+ if (publicSurfaces.length > 0) {
215
+ nextQueries.push("`code_intel affected` before modifying shared exports");
216
+ }
217
+ return nextQueries;
218
+ }
219
+
220
+ function addNextSection(lines: string[], nextQueries: string[]): void {
221
+ if (nextQueries.length === 0) return;
222
+ lines.push("## Next");
223
+ lines.push("");
224
+ for (const q of nextQueries.slice(0, 2)) {
225
+ lines.push(`- ${q}`);
226
+ }
227
+ lines.push("");
228
+ }