autodocs-engine 0.5.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 (240) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +185 -0
  3. package/dist/analysis-builder.d.ts +13 -0
  4. package/dist/analysis-builder.js +268 -0
  5. package/dist/analysis-builder.js.map +1 -0
  6. package/dist/anti-pattern-detector.d.ts +9 -0
  7. package/dist/anti-pattern-detector.js +58 -0
  8. package/dist/anti-pattern-detector.js.map +1 -0
  9. package/dist/architecture-detector.d.ts +7 -0
  10. package/dist/architecture-detector.js +212 -0
  11. package/dist/architecture-detector.js.map +1 -0
  12. package/dist/ast-parser.d.ts +5 -0
  13. package/dist/ast-parser.js +635 -0
  14. package/dist/ast-parser.js.map +1 -0
  15. package/dist/benchmark/code-generator.d.ts +20 -0
  16. package/dist/benchmark/code-generator.js +206 -0
  17. package/dist/benchmark/code-generator.js.map +1 -0
  18. package/dist/benchmark/pr-miner.d.ts +61 -0
  19. package/dist/benchmark/pr-miner.js +304 -0
  20. package/dist/benchmark/pr-miner.js.map +1 -0
  21. package/dist/benchmark/pr-runner.d.ts +58 -0
  22. package/dist/benchmark/pr-runner.js +346 -0
  23. package/dist/benchmark/pr-runner.js.map +1 -0
  24. package/dist/benchmark/pr-scorer.d.ts +48 -0
  25. package/dist/benchmark/pr-scorer.js +222 -0
  26. package/dist/benchmark/pr-scorer.js.map +1 -0
  27. package/dist/benchmark/pr-task-gen.d.ts +16 -0
  28. package/dist/benchmark/pr-task-gen.js +129 -0
  29. package/dist/benchmark/pr-task-gen.js.map +1 -0
  30. package/dist/benchmark/report.d.ts +9 -0
  31. package/dist/benchmark/report.js +131 -0
  32. package/dist/benchmark/report.js.map +1 -0
  33. package/dist/benchmark/runner.d.ts +6 -0
  34. package/dist/benchmark/runner.js +183 -0
  35. package/dist/benchmark/runner.js.map +1 -0
  36. package/dist/benchmark/scorer.d.ts +6 -0
  37. package/dist/benchmark/scorer.js +549 -0
  38. package/dist/benchmark/scorer.js.map +1 -0
  39. package/dist/benchmark/shuffler.d.ts +5 -0
  40. package/dist/benchmark/shuffler.js +70 -0
  41. package/dist/benchmark/shuffler.js.map +1 -0
  42. package/dist/benchmark/statistics.d.ts +36 -0
  43. package/dist/benchmark/statistics.js +159 -0
  44. package/dist/benchmark/statistics.js.map +1 -0
  45. package/dist/benchmark/task-generator.d.ts +20 -0
  46. package/dist/benchmark/task-generator.js +388 -0
  47. package/dist/benchmark/task-generator.js.map +1 -0
  48. package/dist/benchmark/types.d.ts +111 -0
  49. package/dist/benchmark/types.js +3 -0
  50. package/dist/benchmark/types.js.map +1 -0
  51. package/dist/bin/autodocs-engine.d.ts +2 -0
  52. package/dist/bin/autodocs-engine.js +296 -0
  53. package/dist/bin/autodocs-engine.js.map +1 -0
  54. package/dist/bin/benchmark.d.ts +14 -0
  55. package/dist/bin/benchmark.js +172 -0
  56. package/dist/bin/benchmark.js.map +1 -0
  57. package/dist/bin/check.d.ts +13 -0
  58. package/dist/bin/check.js +79 -0
  59. package/dist/bin/check.js.map +1 -0
  60. package/dist/bin/init.d.ts +11 -0
  61. package/dist/bin/init.js +268 -0
  62. package/dist/bin/init.js.map +1 -0
  63. package/dist/bin/serve.d.ts +4 -0
  64. package/dist/bin/serve.js +29 -0
  65. package/dist/bin/serve.js.map +1 -0
  66. package/dist/budget-validator.d.ts +22 -0
  67. package/dist/budget-validator.js +119 -0
  68. package/dist/budget-validator.js.map +1 -0
  69. package/dist/command-extractor.d.ts +10 -0
  70. package/dist/command-extractor.js +276 -0
  71. package/dist/command-extractor.js.map +1 -0
  72. package/dist/config-analyzer.d.ts +5 -0
  73. package/dist/config-analyzer.js +364 -0
  74. package/dist/config-analyzer.js.map +1 -0
  75. package/dist/config.d.ts +33 -0
  76. package/dist/config.js +172 -0
  77. package/dist/config.js.map +1 -0
  78. package/dist/contribution-patterns.d.ts +6 -0
  79. package/dist/contribution-patterns.js +263 -0
  80. package/dist/contribution-patterns.js.map +1 -0
  81. package/dist/convention-extractor.d.ts +17 -0
  82. package/dist/convention-extractor.js +90 -0
  83. package/dist/convention-extractor.js.map +1 -0
  84. package/dist/cross-package.d.ts +5 -0
  85. package/dist/cross-package.js +71 -0
  86. package/dist/cross-package.js.map +1 -0
  87. package/dist/dependency-analyzer.d.ts +5 -0
  88. package/dist/dependency-analyzer.js +233 -0
  89. package/dist/dependency-analyzer.js.map +1 -0
  90. package/dist/detectors/build-tool.d.ts +2 -0
  91. package/dist/detectors/build-tool.js +67 -0
  92. package/dist/detectors/build-tool.js.map +1 -0
  93. package/dist/detectors/component-patterns.d.ts +2 -0
  94. package/dist/detectors/component-patterns.js +49 -0
  95. package/dist/detectors/component-patterns.js.map +1 -0
  96. package/dist/detectors/data-fetching.d.ts +2 -0
  97. package/dist/detectors/data-fetching.js +127 -0
  98. package/dist/detectors/data-fetching.js.map +1 -0
  99. package/dist/detectors/database.d.ts +2 -0
  100. package/dist/detectors/database.js +54 -0
  101. package/dist/detectors/database.js.map +1 -0
  102. package/dist/detectors/error-handling.d.ts +2 -0
  103. package/dist/detectors/error-handling.js +47 -0
  104. package/dist/detectors/error-handling.js.map +1 -0
  105. package/dist/detectors/export-patterns.d.ts +2 -0
  106. package/dist/detectors/export-patterns.js +64 -0
  107. package/dist/detectors/export-patterns.js.map +1 -0
  108. package/dist/detectors/file-naming.d.ts +2 -0
  109. package/dist/detectors/file-naming.js +74 -0
  110. package/dist/detectors/file-naming.js.map +1 -0
  111. package/dist/detectors/graphql-patterns.d.ts +2 -0
  112. package/dist/detectors/graphql-patterns.js +47 -0
  113. package/dist/detectors/graphql-patterns.js.map +1 -0
  114. package/dist/detectors/hook-patterns.d.ts +2 -0
  115. package/dist/detectors/hook-patterns.js +105 -0
  116. package/dist/detectors/hook-patterns.js.map +1 -0
  117. package/dist/detectors/import-patterns.d.ts +2 -0
  118. package/dist/detectors/import-patterns.js +88 -0
  119. package/dist/detectors/import-patterns.js.map +1 -0
  120. package/dist/detectors/telemetry-patterns.d.ts +2 -0
  121. package/dist/detectors/telemetry-patterns.js +42 -0
  122. package/dist/detectors/telemetry-patterns.js.map +1 -0
  123. package/dist/detectors/test-framework-ecosystem.d.ts +2 -0
  124. package/dist/detectors/test-framework-ecosystem.js +95 -0
  125. package/dist/detectors/test-framework-ecosystem.js.map +1 -0
  126. package/dist/detectors/test-patterns.d.ts +2 -0
  127. package/dist/detectors/test-patterns.js +60 -0
  128. package/dist/detectors/test-patterns.js.map +1 -0
  129. package/dist/detectors/web-framework.d.ts +2 -0
  130. package/dist/detectors/web-framework.js +51 -0
  131. package/dist/detectors/web-framework.js.map +1 -0
  132. package/dist/deterministic-formatter.d.ts +54 -0
  133. package/dist/deterministic-formatter.js +922 -0
  134. package/dist/deterministic-formatter.js.map +1 -0
  135. package/dist/diff-analyzer.d.ts +7 -0
  136. package/dist/diff-analyzer.js +126 -0
  137. package/dist/diff-analyzer.js.map +1 -0
  138. package/dist/example-extractor.d.ts +6 -0
  139. package/dist/example-extractor.js +115 -0
  140. package/dist/example-extractor.js.map +1 -0
  141. package/dist/existing-docs.d.ts +36 -0
  142. package/dist/existing-docs.js +257 -0
  143. package/dist/existing-docs.js.map +1 -0
  144. package/dist/file-discovery.d.ts +6 -0
  145. package/dist/file-discovery.js +154 -0
  146. package/dist/file-discovery.js.map +1 -0
  147. package/dist/git-history.d.ts +41 -0
  148. package/dist/git-history.js +401 -0
  149. package/dist/git-history.js.map +1 -0
  150. package/dist/impact-classifier.d.ts +22 -0
  151. package/dist/impact-classifier.js +87 -0
  152. package/dist/impact-classifier.js.map +1 -0
  153. package/dist/impact-radius.d.ts +23 -0
  154. package/dist/impact-radius.js +130 -0
  155. package/dist/impact-radius.js.map +1 -0
  156. package/dist/import-chain.d.ts +12 -0
  157. package/dist/import-chain.js +93 -0
  158. package/dist/import-chain.js.map +1 -0
  159. package/dist/index.d.ts +40 -0
  160. package/dist/index.js +72 -0
  161. package/dist/index.js.map +1 -0
  162. package/dist/inferability.d.ts +16 -0
  163. package/dist/inferability.js +142 -0
  164. package/dist/inferability.js.map +1 -0
  165. package/dist/llm/adapter.d.ts +33 -0
  166. package/dist/llm/adapter.js +202 -0
  167. package/dist/llm/adapter.js.map +1 -0
  168. package/dist/llm/client.d.ts +5 -0
  169. package/dist/llm/client.js +68 -0
  170. package/dist/llm/client.js.map +1 -0
  171. package/dist/llm/hierarchical.d.ts +23 -0
  172. package/dist/llm/hierarchical.js +126 -0
  173. package/dist/llm/hierarchical.js.map +1 -0
  174. package/dist/llm/serializer.d.ts +19 -0
  175. package/dist/llm/serializer.js +363 -0
  176. package/dist/llm/serializer.js.map +1 -0
  177. package/dist/llm/template-selector.d.ts +7 -0
  178. package/dist/llm/template-selector.js +21 -0
  179. package/dist/llm/template-selector.js.map +1 -0
  180. package/dist/llm-adapter.d.ts +2 -0
  181. package/dist/llm-adapter.js +5 -0
  182. package/dist/llm-adapter.js.map +1 -0
  183. package/dist/mcp/cache.d.ts +30 -0
  184. package/dist/mcp/cache.js +112 -0
  185. package/dist/mcp/cache.js.map +1 -0
  186. package/dist/mcp/errors.d.ts +21 -0
  187. package/dist/mcp/errors.js +27 -0
  188. package/dist/mcp/errors.js.map +1 -0
  189. package/dist/mcp/queries.d.ts +27 -0
  190. package/dist/mcp/queries.js +121 -0
  191. package/dist/mcp/queries.js.map +1 -0
  192. package/dist/mcp/server.d.ts +14 -0
  193. package/dist/mcp/server.js +131 -0
  194. package/dist/mcp/server.js.map +1 -0
  195. package/dist/mcp/tools.d.ts +39 -0
  196. package/dist/mcp/tools.js +249 -0
  197. package/dist/mcp/tools.js.map +1 -0
  198. package/dist/mermaid-generator.d.ts +6 -0
  199. package/dist/mermaid-generator.js +59 -0
  200. package/dist/mermaid-generator.js.map +1 -0
  201. package/dist/meta-tool-detector.d.ts +23 -0
  202. package/dist/meta-tool-detector.js +177 -0
  203. package/dist/meta-tool-detector.js.map +1 -0
  204. package/dist/output-validator.d.ts +6 -0
  205. package/dist/output-validator.js +471 -0
  206. package/dist/output-validator.js.map +1 -0
  207. package/dist/pattern-fingerprinter.d.ts +7 -0
  208. package/dist/pattern-fingerprinter.js +241 -0
  209. package/dist/pattern-fingerprinter.js.map +1 -0
  210. package/dist/pipeline.d.ts +5 -0
  211. package/dist/pipeline.js +374 -0
  212. package/dist/pipeline.js.map +1 -0
  213. package/dist/plugin-loader.d.ts +19 -0
  214. package/dist/plugin-loader.js +124 -0
  215. package/dist/plugin-loader.js.map +1 -0
  216. package/dist/role-inferrer.d.ts +5 -0
  217. package/dist/role-inferrer.js +159 -0
  218. package/dist/role-inferrer.js.map +1 -0
  219. package/dist/symbol-graph.d.ts +11 -0
  220. package/dist/symbol-graph.js +613 -0
  221. package/dist/symbol-graph.js.map +1 -0
  222. package/dist/templates/agents-md.d.ts +20 -0
  223. package/dist/templates/agents-md.js +346 -0
  224. package/dist/templates/agents-md.js.map +1 -0
  225. package/dist/templates/claude-md.d.ts +4 -0
  226. package/dist/templates/claude-md.js +23 -0
  227. package/dist/templates/claude-md.js.map +1 -0
  228. package/dist/templates/cursorrules.d.ts +4 -0
  229. package/dist/templates/cursorrules.js +18 -0
  230. package/dist/templates/cursorrules.js.map +1 -0
  231. package/dist/tier-classifier.d.ts +7 -0
  232. package/dist/tier-classifier.js +32 -0
  233. package/dist/tier-classifier.js.map +1 -0
  234. package/dist/types.d.ts +428 -0
  235. package/dist/types.js +42 -0
  236. package/dist/types.js.map +1 -0
  237. package/dist/workflow-rules.d.ts +18 -0
  238. package/dist/workflow-rules.js +131 -0
  239. package/dist/workflow-rules.js.map +1 -0
  240. package/package.json +62 -0
@@ -0,0 +1,241 @@
1
+ // src/pattern-fingerprinter.ts — W2-2: Pattern Fingerprinting (W5-B3: Simplified)
2
+ // For the top N exports (by import count), analyze the function body AST to
3
+ // extract concrete patterns: actual parameter names, return value keys, internal calls.
4
+ // W5-B3: Removed abstract shapes (error pattern, async pattern, complexity).
5
+ // Produces 1-line summaries per export with concrete details.
6
+ import { readFileSync } from "node:fs";
7
+ import { resolve, extname } from "node:path";
8
+ import ts from "typescript";
9
+ /**
10
+ * Fingerprint the top N public API exports by analyzing their function bodies.
11
+ * Returns fingerprints for exports where the source file can be parsed and
12
+ * the function body can be found.
13
+ */
14
+ export function fingerprintTopExports(publicAPI, packageDir, topN = 5, warnings = []) {
15
+ // Select top N non-type exports by import count
16
+ const candidates = publicAPI
17
+ .filter((e) => !e.isTypeOnly && e.kind !== "type" && e.kind !== "interface" && e.kind !== "enum")
18
+ .sort((a, b) => (b.importCount ?? 0) - (a.importCount ?? 0))
19
+ .slice(0, topN);
20
+ if (candidates.length === 0)
21
+ return [];
22
+ // Group by source file to parse each file once
23
+ const byFile = new Map();
24
+ for (const entry of candidates) {
25
+ const file = entry.sourceFile;
26
+ if (!byFile.has(file))
27
+ byFile.set(file, []);
28
+ byFile.get(file).push(entry);
29
+ }
30
+ const fingerprints = [];
31
+ for (const [relFile, entries] of byFile) {
32
+ const absPath = resolve(packageDir, relFile);
33
+ let content;
34
+ try {
35
+ content = readFileSync(absPath, "utf-8");
36
+ }
37
+ catch {
38
+ continue;
39
+ }
40
+ const ext = extname(absPath).toLowerCase();
41
+ const scriptKind = ext === ".tsx" ? ts.ScriptKind.TSX :
42
+ ext === ".jsx" ? ts.ScriptKind.JSX :
43
+ ext === ".js" ? ts.ScriptKind.JS :
44
+ ts.ScriptKind.TS;
45
+ const sourceFile = ts.createSourceFile(absPath, content, ts.ScriptTarget.Latest, true, scriptKind);
46
+ for (const entry of entries) {
47
+ try {
48
+ const fp = fingerprintExport(sourceFile, entry, relFile);
49
+ if (fp)
50
+ fingerprints.push(fp);
51
+ }
52
+ catch (err) {
53
+ warnings.push({
54
+ level: "info",
55
+ module: "pattern-fingerprinter",
56
+ message: `Could not fingerprint ${entry.name}: ${err instanceof Error ? err.message : String(err)}`,
57
+ });
58
+ }
59
+ }
60
+ }
61
+ return fingerprints;
62
+ }
63
+ /**
64
+ * Analyze a single exported function/hook/component to produce a PatternFingerprint.
65
+ * W5-B3: Simplified — only extracts params, return shape, internal calls.
66
+ */
67
+ function fingerprintExport(sourceFile, entry, relFile) {
68
+ const funcInfo = findExportedFunction(sourceFile, entry.name);
69
+ if (!funcInfo)
70
+ return null;
71
+ const { params, body, returnType } = funcInfo;
72
+ const parameterShape = analyzeParameterShape(params);
73
+ const returnShape = returnType
74
+ ? returnType.getText()
75
+ : analyzeReturnShape(body);
76
+ const internalCalls = extractInternalCalls(body);
77
+ const summary = composeSummary(entry, parameterShape, returnShape, internalCalls);
78
+ return {
79
+ exportName: entry.name,
80
+ sourceFile: relFile,
81
+ parameterShape,
82
+ returnShape,
83
+ internalCalls,
84
+ // W5-B3: Deprecated fields kept for backward compatibility, set to defaults
85
+ errorPattern: "none",
86
+ asyncPattern: "sync",
87
+ complexity: "simple",
88
+ summary,
89
+ };
90
+ }
91
+ function findExportedFunction(sourceFile, name) {
92
+ for (const stmt of sourceFile.statements) {
93
+ if (!ts.canHaveModifiers(stmt))
94
+ continue;
95
+ const modifiers = ts.getModifiers(stmt);
96
+ const hasExport = modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);
97
+ if (!hasExport)
98
+ continue;
99
+ // export function foo(...)
100
+ if (ts.isFunctionDeclaration(stmt) && stmt.name?.text === name && stmt.body) {
101
+ return {
102
+ params: stmt.parameters,
103
+ body: stmt.body,
104
+ returnType: stmt.type,
105
+ };
106
+ }
107
+ // export const foo = (...) => ...
108
+ if (ts.isVariableStatement(stmt)) {
109
+ for (const decl of stmt.declarationList.declarations) {
110
+ if (!ts.isIdentifier(decl.name) || decl.name.text !== name)
111
+ continue;
112
+ if (!decl.initializer)
113
+ continue;
114
+ let func;
115
+ if (ts.isArrowFunction(decl.initializer)) {
116
+ func = decl.initializer;
117
+ }
118
+ else if (ts.isFunctionExpression(decl.initializer)) {
119
+ func = decl.initializer;
120
+ }
121
+ else if (ts.isCallExpression(decl.initializer)) {
122
+ // React.memo(() => ...) or similar wrapper
123
+ const arg = decl.initializer.arguments[0];
124
+ if (arg && (ts.isArrowFunction(arg) || ts.isFunctionExpression(arg))) {
125
+ func = arg;
126
+ }
127
+ }
128
+ if (func) {
129
+ return {
130
+ params: func.parameters,
131
+ body: func.body,
132
+ returnType: func.type,
133
+ };
134
+ }
135
+ }
136
+ }
137
+ }
138
+ return null;
139
+ }
140
+ // ---- Parameter Shape Analysis ----
141
+ function analyzeParameterShape(params) {
142
+ if (params.length === 0)
143
+ return "no params";
144
+ if (params.length === 1) {
145
+ const param = params[0];
146
+ // Destructured object: ({ foo, bar })
147
+ if (ts.isObjectBindingPattern(param.name)) {
148
+ const props = param.name.elements.map((e) => e.name.getText());
149
+ return `{ ${props.join(", ")} }`;
150
+ }
151
+ // Object type annotation
152
+ if (param.type && ts.isTypeLiteralNode(param.type)) {
153
+ const props = param.type.members
154
+ .filter(ts.isPropertySignature)
155
+ .map((m) => m.name?.getText() ?? "?");
156
+ return `{ ${props.join(", ")} }`;
157
+ }
158
+ // Type reference (e.g., Options, Config)
159
+ if (param.type && ts.isTypeReferenceNode(param.type)) {
160
+ return `${param.name.getText()}: ${param.type.getText()}`;
161
+ }
162
+ return `${param.name.getText()}: ${param.type?.getText() ?? "unknown"}`;
163
+ }
164
+ return `(${params.map((p) => p.name.getText()).join(", ")})`;
165
+ }
166
+ // ---- Return Shape Analysis ----
167
+ function analyzeReturnShape(body) {
168
+ const returnExprs = [];
169
+ function walk(node) {
170
+ if (ts.isReturnStatement(node) && node.expression) {
171
+ // Object literal return
172
+ if (ts.isObjectLiteralExpression(node.expression)) {
173
+ const props = node.expression.properties
174
+ .map((p) => {
175
+ if (ts.isPropertyAssignment(p) || ts.isShorthandPropertyAssignment(p)) {
176
+ return p.name?.getText() ?? "?";
177
+ }
178
+ if (ts.isSpreadAssignment(p))
179
+ return "...spread";
180
+ return "?";
181
+ });
182
+ returnExprs.push(`{ ${props.join(", ")} }`);
183
+ return;
184
+ }
185
+ // JSX return
186
+ if (ts.isJsxElement(node.expression) || ts.isJsxSelfClosingElement(node.expression) || ts.isJsxFragment(node.expression)) {
187
+ returnExprs.push("JSX.Element");
188
+ return;
189
+ }
190
+ // Parenthesized JSX
191
+ if (ts.isParenthesizedExpression(node.expression)) {
192
+ const inner = node.expression.expression;
193
+ if (ts.isJsxElement(inner) || ts.isJsxSelfClosingElement(inner) || ts.isJsxFragment(inner)) {
194
+ returnExprs.push("JSX.Element");
195
+ return;
196
+ }
197
+ }
198
+ returnExprs.push("value");
199
+ }
200
+ ts.forEachChild(node, walk);
201
+ }
202
+ walk(body);
203
+ if (returnExprs.length === 0)
204
+ return "void";
205
+ const unique = [...new Set(returnExprs)];
206
+ return unique[0];
207
+ }
208
+ // ---- Internal Calls ----
209
+ function extractInternalCalls(body) {
210
+ const calls = new Set();
211
+ function walk(node) {
212
+ if (ts.isCallExpression(node)) {
213
+ if (ts.isIdentifier(node.expression)) {
214
+ calls.add(node.expression.text);
215
+ }
216
+ else if (ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.name)) {
217
+ const name = node.expression.name.text;
218
+ const obj = node.expression.expression;
219
+ if (ts.isIdentifier(obj)) {
220
+ calls.add(`${obj.text}.${name}`);
221
+ }
222
+ }
223
+ }
224
+ ts.forEachChild(node, walk);
225
+ }
226
+ walk(body);
227
+ return [...calls].slice(0, 15);
228
+ }
229
+ // ---- Summary Composition ----
230
+ function composeSummary(entry, parameterShape, returnShape, internalCalls) {
231
+ const kind = entry.kind === "hook" ? "Custom hook" :
232
+ entry.kind === "component" ? "React component" :
233
+ entry.kind === "function" ? "Function" : "Export";
234
+ const paramPart = parameterShape === "no params" ? "" : ` accepting ${parameterShape}`;
235
+ const callPart = internalCalls.length > 0
236
+ ? `, uses ${internalCalls.slice(0, 4).join(", ")}`
237
+ : "";
238
+ const returnPart = returnShape !== "void" ? `, returns ${returnShape}` : "";
239
+ return `${kind}${paramPart}${callPart}${returnPart}`;
240
+ }
241
+ //# sourceMappingURL=pattern-fingerprinter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern-fingerprinter.js","sourceRoot":"","sources":["../src/pattern-fingerprinter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { ResolvedConfig, StructuredAnalysis } from "./types.js";
2
+ /**
3
+ * Run the full analysis pipeline for all packages.
4
+ */
5
+ export declare function runPipeline(config: ResolvedConfig): Promise<StructuredAnalysis>;
@@ -0,0 +1,374 @@
1
+ // src/pipeline.ts — Pipeline Orchestrator
2
+ // Errata applied: E-31 (publicAPI before Architecture Detector), E-39 (warnings to all modules)
3
+ import { readFileSync } from "node:fs";
4
+ import { basename, join } from "node:path";
5
+ import { discoverFiles } from "./file-discovery.js";
6
+ import { parseFile } from "./ast-parser.js";
7
+ import { buildSymbolGraph } from "./symbol-graph.js";
8
+ import { classifyTiers } from "./tier-classifier.js";
9
+ import { extractConventions } from "./convention-extractor.js";
10
+ import { extractCommands, scanWorkspaceCommands } from "./command-extractor.js";
11
+ import { detectArchitecture } from "./architecture-detector.js";
12
+ import { buildPublicAPI, buildPackageAnalysis, buildStructuredAnalysis } from "./analysis-builder.js";
13
+ import { analyzeCrossPackage } from "./cross-package.js";
14
+ import { inferRole } from "./role-inferrer.js";
15
+ import { deriveAntiPatterns } from "./anti-pattern-detector.js";
16
+ import { detectContributionPatterns } from "./contribution-patterns.js";
17
+ import { classifyImpacts } from "./impact-classifier.js";
18
+ import { analyzeConfig } from "./config-analyzer.js";
19
+ import { generateWorkflowRules } from "./workflow-rules.js";
20
+ import { fingerprintTopExports } from "./pattern-fingerprinter.js";
21
+ import { analyzeDependencies } from "./dependency-analyzer.js";
22
+ import { detectExistingDocs } from "./existing-docs.js";
23
+ import { extractExamples } from "./example-extractor.js";
24
+ import { generateDependencyDiagram } from "./mermaid-generator.js";
25
+ import { detectMetaTool } from "./meta-tool-detector.js";
26
+ import { computeImportChain, generateImportChainRules } from "./import-chain.js";
27
+ import { mineGitHistory, generateCoChangeRules } from "./git-history.js";
28
+ /** Verbose logger — writes to stderr only when verbose is enabled. */
29
+ function vlog(verbose, msg) {
30
+ if (verbose)
31
+ process.stderr.write(`[INFO] ${msg}\n`);
32
+ }
33
+ /**
34
+ * Run the full analysis pipeline for all packages.
35
+ */
36
+ export async function runPipeline(config) {
37
+ const warnings = [];
38
+ const startTime = performance.now();
39
+ const packageAnalyses = [];
40
+ const verbose = config.verbose;
41
+ // Git history mining — run once at repo level, distribute to packages
42
+ const gitHistoryMap = mineGitHistory(config.rootDir ?? config.packages[0], config.packages, warnings);
43
+ if (gitHistoryMap) {
44
+ vlog(verbose, `Git history: mined for ${gitHistoryMap.size} package(s)`);
45
+ }
46
+ for (const pkgPath of config.packages) {
47
+ try {
48
+ const analysis = analyzePackage(pkgPath, config, warnings);
49
+ // Attach pre-computed git history for this package
50
+ const pkgGitHistory = gitHistoryMap?.get(pkgPath);
51
+ if (pkgGitHistory) {
52
+ analysis.gitHistory = pkgGitHistory;
53
+ vlog(verbose, ` Git co-change: ${pkgGitHistory.coChangeEdges.length} edges (${pkgGitHistory.totalCommitsAnalyzed} commits analyzed)`);
54
+ }
55
+ packageAnalyses.push(analysis);
56
+ }
57
+ catch (err) {
58
+ const msg = err instanceof Error ? err.message : String(err);
59
+ warnings.push({
60
+ level: "error",
61
+ module: "pipeline",
62
+ message: `Failed to analyze ${pkgPath}: ${msg}`,
63
+ });
64
+ }
65
+ }
66
+ // Cross-package analysis (if >1 package)
67
+ let crossPackage;
68
+ let workspaceCommands = [];
69
+ let rootCommands;
70
+ if (packageAnalyses.length > 1) {
71
+ vlog(verbose, `Running cross-package analysis for ${packageAnalyses.length} packages...`);
72
+ rootCommands = config.rootDir
73
+ ? extractCommands(config.rootDir, undefined, warnings)
74
+ : undefined;
75
+ crossPackage = analyzeCrossPackage(packageAnalyses, rootCommands);
76
+ if (crossPackage) {
77
+ vlog(verbose, ` Dependency edges: ${crossPackage.dependencyGraph.length}`);
78
+ vlog(verbose, ` Shared conventions: ${crossPackage.sharedConventions.length}`);
79
+ vlog(verbose, ` Divergent conventions: ${crossPackage.divergentConventions.length}`);
80
+ }
81
+ // W5-C3: Generate Mermaid dependency diagram
82
+ if (crossPackage && crossPackage.dependencyGraph.length > 0) {
83
+ const mermaidDiagram = generateDependencyDiagram(packageAnalyses, crossPackage.dependencyGraph);
84
+ if (mermaidDiagram) {
85
+ crossPackage.mermaidDiagram = mermaidDiagram;
86
+ vlog(verbose, ` Mermaid diagram: ${crossPackage.dependencyGraph.length} edges rendered`);
87
+ }
88
+ }
89
+ // W3-1: Workspace-wide command scanning (multi-package only)
90
+ if (config.rootDir) {
91
+ const analyzedPkgNames = new Set(packageAnalyses.map((p) => p.name));
92
+ workspaceCommands = scanWorkspaceCommands(config.rootDir, warnings, analyzedPkgNames);
93
+ if (workspaceCommands.length > 0) {
94
+ vlog(verbose, ` Workspace commands: ${workspaceCommands.length} operational commands found`);
95
+ if (crossPackage) {
96
+ crossPackage.workspaceCommands = workspaceCommands;
97
+ }
98
+ }
99
+ }
100
+ }
101
+ // Workflow rule generation — runs for ALL analyses (single and multi-package)
102
+ const firstConfig = packageAnalyses.find((p) => p.configAnalysis)?.configAnalysis;
103
+ const workflowRules = generateWorkflowRules({
104
+ workspaceCommands,
105
+ rootCommands,
106
+ packageCommands: packageAnalyses.map((p) => ({
107
+ packageName: p.name,
108
+ commands: p.commands,
109
+ })),
110
+ configAnalysis: firstConfig,
111
+ allDependencyInsights: packageAnalyses
112
+ .map((p) => p.dependencyInsights)
113
+ .filter((d) => d != null),
114
+ allConventions: packageAnalyses.flatMap((p) => p.conventions),
115
+ });
116
+ // Add import-chain rules (from file-to-file coupling analysis)
117
+ const allImportChainEdges = packageAnalyses.flatMap((p) => p.importChain ?? []);
118
+ const importChainRules = generateImportChainRules(allImportChainEdges);
119
+ if (importChainRules.length > 0) {
120
+ vlog(verbose, `Import chain rules: ${importChainRules.length} high-coupling rules generated`);
121
+ workflowRules.push(...importChainRules);
122
+ }
123
+ // Add co-change rules from git history (structured dedup against import-chain)
124
+ const importChainCoveredFiles = new Set(allImportChainEdges.map((e) => e.source));
125
+ const coChangeRules = generateCoChangeRules(packageAnalyses.flatMap((p) => p.gitHistory?.coChangeEdges ?? []), importChainCoveredFiles);
126
+ if (coChangeRules.length > 0) {
127
+ vlog(verbose, `Co-change rules: ${coChangeRules.length} rules from git history`);
128
+ workflowRules.push(...coChangeRules);
129
+ }
130
+ if (workflowRules.length > 0) {
131
+ vlog(verbose, `Workflow rules: ${workflowRules.length} total rules generated`);
132
+ // For single-package, create a minimal crossPackage to hold the rules
133
+ if (!crossPackage) {
134
+ crossPackage = {
135
+ dependencyGraph: [],
136
+ sharedConventions: [],
137
+ divergentConventions: [],
138
+ sharedAntiPatterns: [],
139
+ workflowRules,
140
+ };
141
+ }
142
+ else {
143
+ crossPackage.workflowRules = workflowRules;
144
+ }
145
+ }
146
+ const totalMs = Math.round(performance.now() - startTime);
147
+ vlog(verbose, `Total analysis time: ${totalMs}ms`);
148
+ return buildStructuredAnalysis(packageAnalyses, crossPackage, config, warnings, startTime);
149
+ }
150
+ function analyzePackage(pkgPath, config, warnings) {
151
+ const verbose = config.verbose;
152
+ const pkgStart = performance.now();
153
+ vlog(verbose, `Analyzing ${basename(pkgPath)}...`);
154
+ // Step 1: File Discovery (E-39: pass warnings)
155
+ const files = discoverFiles(pkgPath, config.exclude, warnings);
156
+ // Step 2: AST Parser (E-39: pass warnings)
157
+ const parsed = files
158
+ .map((f) => {
159
+ try {
160
+ return parseFile(f, pkgPath, warnings);
161
+ }
162
+ catch (err) {
163
+ const msg = err instanceof Error ? err.message : String(err);
164
+ warnings.push({
165
+ level: "warn",
166
+ module: "ast-parser",
167
+ message: msg,
168
+ file: f,
169
+ });
170
+ return null;
171
+ }
172
+ })
173
+ .filter(Boolean);
174
+ // Step 3: Symbol Graph Builder (E-39: pass warnings)
175
+ const symbolGraph = buildSymbolGraph(parsed, pkgPath, warnings);
176
+ // Compute file-to-file import coupling before symbolGraph is discarded
177
+ const importChain = computeImportChain(symbolGraph, pkgPath, warnings);
178
+ if (importChain.length > 0) {
179
+ vlog(verbose, ` Import chain: ${importChain.length} high-coupling file pairs`);
180
+ }
181
+ // Step 4: Tier Classifier
182
+ const tiers = classifyTiers(parsed, symbolGraph, symbolGraph.barrelFile);
183
+ // Verbose: tier counts
184
+ if (verbose) {
185
+ let t1 = 0, t2 = 0, t3 = 0;
186
+ for (const [, info] of tiers) {
187
+ if (info.tier === 1)
188
+ t1++;
189
+ else if (info.tier === 2)
190
+ t2++;
191
+ else
192
+ t3++;
193
+ }
194
+ vlog(verbose, ` Files discovered: ${parsed.length} (${t1} T1, ${t2} T2, ${t3} T3)`);
195
+ }
196
+ // E-31: Compute publicAPI BEFORE Architecture Detector
197
+ const publicAPI = buildPublicAPI(symbolGraph, parsed, config.maxPublicAPIEntries, warnings);
198
+ vlog(verbose, ` Public API: ${publicAPI.length} exports`);
199
+ // Steps 5-7: Run analysis modules (E-39: pass warnings)
200
+ // Improvement 1 & 2: Config and dependency analysis needed before convention extraction
201
+ // (moved up so detectors can use context)
202
+ const configAnalysis = analyzeConfig(pkgPath, config.rootDir, warnings);
203
+ vlog(verbose, ` Config: build=${configAnalysis.buildTool?.name ?? "none"}, linter=${configAnalysis.linter?.name ?? "none"}, formatter=${configAnalysis.formatter?.name ?? "none"}`);
204
+ // Collect all imported module specifiers from source files for import-verified framework detection
205
+ // Excludes type-only imports — they don't indicate runtime framework usage
206
+ const allImportedModules = new Set();
207
+ for (const pf of parsed) {
208
+ for (const imp of pf.imports) {
209
+ if (imp.isTypeOnly)
210
+ continue;
211
+ const spec = imp.moduleSpecifier;
212
+ if (spec.startsWith(".") || spec.startsWith("/"))
213
+ continue;
214
+ const parts = spec.split("/");
215
+ const basePkg = spec.startsWith("@") ? parts.slice(0, 2).join("/") : parts[0];
216
+ allImportedModules.add(basePkg);
217
+ }
218
+ }
219
+ const dependencyInsights = analyzeDependencies(pkgPath, config.rootDir, warnings, allImportedModules);
220
+ vlog(verbose, ` Dependencies: ${dependencyInsights.frameworks.length} frameworks, runtime=${dependencyInsights.runtime.map((r) => r.name).join("+") || "node"}`);
221
+ // Meta-tool detection (before conventions — informs format-time reclassification)
222
+ let pkgJsonRaw = null;
223
+ try {
224
+ pkgJsonRaw = JSON.parse(readFileSync(join(pkgPath, "package.json"), "utf-8"));
225
+ }
226
+ catch { /* no package.json */ }
227
+ const metaToolResult = (!config.noMetaTool && pkgJsonRaw)
228
+ ? detectMetaTool({
229
+ parsedFiles: parsed,
230
+ tiers,
231
+ dependencies: (pkgJsonRaw.dependencies ?? {}),
232
+ devDependencies: (pkgJsonRaw.devDependencies ?? {}),
233
+ peerDeps: (pkgJsonRaw.peerDependencies ?? {}),
234
+ threshold: config.metaToolThreshold,
235
+ }, warnings)
236
+ : { isMetaTool: false, signal: "none", supportedFamilies: [], coreFamilies: [] };
237
+ if (metaToolResult.isMetaTool) {
238
+ vlog(verbose, ` Meta-tool: ${metaToolResult.signal} (${metaToolResult.supportedFamilies.length} families, core: ${metaToolResult.coreFamilies.join(", ") || "none"})`);
239
+ }
240
+ // Read root devDeps for test framework fallback in monorepos
241
+ let rootDevDeps;
242
+ if (config.rootDir) {
243
+ try {
244
+ const rootPkg = JSON.parse(readFileSync(join(config.rootDir, "package.json"), "utf-8"));
245
+ rootDevDeps = rootPkg.devDependencies;
246
+ }
247
+ catch {
248
+ // skip
249
+ }
250
+ }
251
+ // W2-3: Pass dependency and config context to convention detectors
252
+ const conventions = extractConventions(parsed, tiers, config.conventions.disable, warnings, { dependencies: dependencyInsights, config: configAnalysis, rootDevDeps });
253
+ vlog(verbose, ` Conventions: ${conventions.length} detected`);
254
+ // Improvement 4: Existing docs detection
255
+ const existingDocs = detectExistingDocs(pkgPath, warnings);
256
+ if (existingDocs.hasAgentsMd || existingDocs.hasClaudeMd) {
257
+ vlog(verbose, ` Existing docs: ${existingDocs.hasAgentsMd ? "AGENTS.md" : ""}${existingDocs.hasClaudeMd ? " CLAUDE.md" : ""}`);
258
+ }
259
+ const commands = extractCommands(pkgPath, config.rootDir, warnings);
260
+ // Improvement 1 integration: Override commands with build tool info (turbo, nx)
261
+ if (configAnalysis.buildTool && configAnalysis.buildTool.name !== "none") {
262
+ adjustCommandsForBuildTool(commands, configAnalysis.buildTool, warnings);
263
+ }
264
+ const cmdList = [
265
+ commands.build && "build",
266
+ commands.test && "test",
267
+ commands.lint && "lint",
268
+ commands.start && "start",
269
+ ].filter(Boolean);
270
+ vlog(verbose, ` Commands: ${commands.packageManager} (${cmdList.join(", ") || "none"})`);
271
+ const architecture = detectArchitecture(parsed, pkgPath, publicAPI, symbolGraph.barrelFile, warnings);
272
+ // Enhancement 1: Role inference
273
+ const partialAnalysis = buildPackageAnalysis(pkgPath, config.rootDir, parsed, symbolGraph, tiers, conventions, commands, architecture, publicAPI, warnings);
274
+ const role = inferRole(partialAnalysis);
275
+ if (metaToolResult.isMetaTool) {
276
+ role.summary += ` — integrates with ${metaToolResult.supportedFamilies.length} framework ecosystems`;
277
+ }
278
+ vlog(verbose, ` Role: ${role.summary}`);
279
+ // Enhancement 3: Anti-pattern derivation
280
+ const antiPatterns = deriveAntiPatterns(conventions);
281
+ vlog(verbose, ` Anti-patterns: ${antiPatterns.length} derived`);
282
+ // Enhancement 4: Contribution patterns
283
+ const contributionPatterns = detectContributionPatterns(parsed, publicAPI, tiers, architecture.directories, symbolGraph.barrelFile);
284
+ vlog(verbose, ` Contribution patterns: ${contributionPatterns.length} detected`);
285
+ // Impact classification
286
+ const classified = classifyImpacts(conventions, antiPatterns);
287
+ vlog(verbose, ` Impact: ${classified.conventions.filter((c) => c.impact === "high").length} high, ${classified.conventions.filter((c) => c.impact === "medium").length} medium, ${classified.conventions.filter((c) => c.impact === "low").length} low`);
288
+ // Improvement 3: Call graph logging
289
+ if (symbolGraph.callGraph.length > 0) {
290
+ vlog(verbose, ` Call graph: ${symbolGraph.callGraph.length} edges`);
291
+ }
292
+ // W2-2: Pattern fingerprinting for top exports
293
+ const patternFingerprints = fingerprintTopExports(publicAPI, pkgPath, 5, warnings);
294
+ if (patternFingerprints.length > 0) {
295
+ vlog(verbose, ` Pattern fingerprints: ${patternFingerprints.length} exports analyzed`);
296
+ }
297
+ // W5-C1: Extract usage examples from test files
298
+ const examples = extractExamples(publicAPI, parsed, pkgPath, 10, warnings);
299
+ if (examples.length > 0) {
300
+ vlog(verbose, ` Usage examples: ${examples.length} extracted from test files`);
301
+ }
302
+ const pkgMs = Math.round(performance.now() - pkgStart);
303
+ vlog(verbose, ` Analysis time: ${pkgMs}ms`);
304
+ return {
305
+ ...partialAnalysis,
306
+ conventions: classified.conventions,
307
+ role,
308
+ antiPatterns: classified.antiPatterns,
309
+ contributionPatterns,
310
+ configAnalysis,
311
+ dependencyInsights,
312
+ existingDocs,
313
+ callGraph: symbolGraph.callGraph.length > 0 ? symbolGraph.callGraph : undefined,
314
+ importChain: importChain.length > 0 ? importChain : undefined,
315
+ patternFingerprints: patternFingerprints.length > 0 ? patternFingerprints : undefined,
316
+ examples: examples.length > 0 ? examples : undefined,
317
+ isMetaTool: metaToolResult.isMetaTool || undefined,
318
+ metaToolInfo: metaToolResult.isMetaTool ? {
319
+ signal: metaToolResult.signal,
320
+ supportedFamilies: metaToolResult.supportedFamilies,
321
+ coreFamilies: metaToolResult.coreFamilies,
322
+ } : undefined,
323
+ };
324
+ }
325
+ /**
326
+ * Improvement 1: Adjust commands based on detected build tool (turbo, nx).
327
+ * If turbo.json defines tasks like "build", "test", "lint", "dev",
328
+ * use "turbo run <task>" instead of "<pm> run <script>".
329
+ */
330
+ function adjustCommandsForBuildTool(commands, buildTool, _warnings) {
331
+ if (buildTool.name !== "turbo" && buildTool.name !== "nx")
332
+ return;
333
+ const prefix = buildTool.name === "turbo" ? "turbo run" : "nx run";
334
+ const taskSet = new Set(buildTool.taskNames);
335
+ const mapping = {
336
+ build: "build",
337
+ test: "test",
338
+ lint: "lint",
339
+ dev: "start",
340
+ start: "start",
341
+ };
342
+ for (const [taskName, cmdField] of Object.entries(mapping)) {
343
+ if (!taskSet.has(taskName))
344
+ continue;
345
+ const existing = commands[cmdField];
346
+ if (existing) {
347
+ // Keep the existing as a variant, use turbo as primary
348
+ const turboCmd = `${prefix} ${taskName}`;
349
+ if (existing.run !== turboCmd) {
350
+ if (!existing.variants)
351
+ existing.variants = [];
352
+ existing.variants.push({ name: "package-level", run: existing.run });
353
+ existing.run = turboCmd;
354
+ existing.source = `${buildTool.configFile} tasks.${taskName}`;
355
+ }
356
+ }
357
+ else {
358
+ // Create new command from turbo task
359
+ const newCmd = {
360
+ run: `${prefix} ${taskName}`,
361
+ source: `${buildTool.configFile} tasks.${taskName}`,
362
+ };
363
+ if (cmdField === "build")
364
+ commands.build = newCmd;
365
+ else if (cmdField === "test")
366
+ commands.test = newCmd;
367
+ else if (cmdField === "lint")
368
+ commands.lint = newCmd;
369
+ else if (cmdField === "start")
370
+ commands.start = newCmd;
371
+ }
372
+ }
373
+ }
374
+ //# sourceMappingURL=pipeline.js.map