spec-gen-cli 1.0.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 (303) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1078 -0
  3. package/dist/api/analyze.d.ts +17 -0
  4. package/dist/api/analyze.d.ts.map +1 -0
  5. package/dist/api/analyze.js +109 -0
  6. package/dist/api/analyze.js.map +1 -0
  7. package/dist/api/drift.d.ts +21 -0
  8. package/dist/api/drift.d.ts.map +1 -0
  9. package/dist/api/drift.js +145 -0
  10. package/dist/api/drift.js.map +1 -0
  11. package/dist/api/generate.d.ts +18 -0
  12. package/dist/api/generate.d.ts.map +1 -0
  13. package/dist/api/generate.js +251 -0
  14. package/dist/api/generate.js.map +1 -0
  15. package/dist/api/index.d.ts +39 -0
  16. package/dist/api/index.d.ts.map +1 -0
  17. package/dist/api/index.js +32 -0
  18. package/dist/api/index.js.map +1 -0
  19. package/dist/api/init.d.ts +18 -0
  20. package/dist/api/init.d.ts.map +1 -0
  21. package/dist/api/init.js +82 -0
  22. package/dist/api/init.js.map +1 -0
  23. package/dist/api/run.d.ts +19 -0
  24. package/dist/api/run.d.ts.map +1 -0
  25. package/dist/api/run.js +291 -0
  26. package/dist/api/run.js.map +1 -0
  27. package/dist/api/specs.d.ts +49 -0
  28. package/dist/api/specs.d.ts.map +1 -0
  29. package/dist/api/specs.js +136 -0
  30. package/dist/api/specs.js.map +1 -0
  31. package/dist/api/types.d.ts +176 -0
  32. package/dist/api/types.d.ts.map +1 -0
  33. package/dist/api/types.js +9 -0
  34. package/dist/api/types.js.map +1 -0
  35. package/dist/api/verify.d.ts +20 -0
  36. package/dist/api/verify.d.ts.map +1 -0
  37. package/dist/api/verify.js +117 -0
  38. package/dist/api/verify.js.map +1 -0
  39. package/dist/cli/commands/analyze.d.ts +27 -0
  40. package/dist/cli/commands/analyze.d.ts.map +1 -0
  41. package/dist/cli/commands/analyze.js +485 -0
  42. package/dist/cli/commands/analyze.js.map +1 -0
  43. package/dist/cli/commands/drift.d.ts +9 -0
  44. package/dist/cli/commands/drift.d.ts.map +1 -0
  45. package/dist/cli/commands/drift.js +540 -0
  46. package/dist/cli/commands/drift.js.map +1 -0
  47. package/dist/cli/commands/generate.d.ts +9 -0
  48. package/dist/cli/commands/generate.d.ts.map +1 -0
  49. package/dist/cli/commands/generate.js +633 -0
  50. package/dist/cli/commands/generate.js.map +1 -0
  51. package/dist/cli/commands/init.d.ts +9 -0
  52. package/dist/cli/commands/init.d.ts.map +1 -0
  53. package/dist/cli/commands/init.js +171 -0
  54. package/dist/cli/commands/init.js.map +1 -0
  55. package/dist/cli/commands/mcp.d.ts +638 -0
  56. package/dist/cli/commands/mcp.d.ts.map +1 -0
  57. package/dist/cli/commands/mcp.js +574 -0
  58. package/dist/cli/commands/mcp.js.map +1 -0
  59. package/dist/cli/commands/run.d.ts +24 -0
  60. package/dist/cli/commands/run.d.ts.map +1 -0
  61. package/dist/cli/commands/run.js +546 -0
  62. package/dist/cli/commands/run.js.map +1 -0
  63. package/dist/cli/commands/verify.d.ts +9 -0
  64. package/dist/cli/commands/verify.d.ts.map +1 -0
  65. package/dist/cli/commands/verify.js +417 -0
  66. package/dist/cli/commands/verify.js.map +1 -0
  67. package/dist/cli/commands/view.d.ts +9 -0
  68. package/dist/cli/commands/view.d.ts.map +1 -0
  69. package/dist/cli/commands/view.js +511 -0
  70. package/dist/cli/commands/view.js.map +1 -0
  71. package/dist/cli/index.d.ts +9 -0
  72. package/dist/cli/index.d.ts.map +1 -0
  73. package/dist/cli/index.js +83 -0
  74. package/dist/cli/index.js.map +1 -0
  75. package/dist/core/analyzer/architecture-writer.d.ts +67 -0
  76. package/dist/core/analyzer/architecture-writer.d.ts.map +1 -0
  77. package/dist/core/analyzer/architecture-writer.js +209 -0
  78. package/dist/core/analyzer/architecture-writer.js.map +1 -0
  79. package/dist/core/analyzer/artifact-generator.d.ts +222 -0
  80. package/dist/core/analyzer/artifact-generator.d.ts.map +1 -0
  81. package/dist/core/analyzer/artifact-generator.js +726 -0
  82. package/dist/core/analyzer/artifact-generator.js.map +1 -0
  83. package/dist/core/analyzer/call-graph.d.ts +83 -0
  84. package/dist/core/analyzer/call-graph.d.ts.map +1 -0
  85. package/dist/core/analyzer/call-graph.js +827 -0
  86. package/dist/core/analyzer/call-graph.js.map +1 -0
  87. package/dist/core/analyzer/code-shaper.d.ts +33 -0
  88. package/dist/core/analyzer/code-shaper.d.ts.map +1 -0
  89. package/dist/core/analyzer/code-shaper.js +149 -0
  90. package/dist/core/analyzer/code-shaper.js.map +1 -0
  91. package/dist/core/analyzer/dependency-graph.d.ts +179 -0
  92. package/dist/core/analyzer/dependency-graph.d.ts.map +1 -0
  93. package/dist/core/analyzer/dependency-graph.js +574 -0
  94. package/dist/core/analyzer/dependency-graph.js.map +1 -0
  95. package/dist/core/analyzer/duplicate-detector.d.ts +52 -0
  96. package/dist/core/analyzer/duplicate-detector.d.ts.map +1 -0
  97. package/dist/core/analyzer/duplicate-detector.js +279 -0
  98. package/dist/core/analyzer/duplicate-detector.js.map +1 -0
  99. package/dist/core/analyzer/embedding-service.d.ts +50 -0
  100. package/dist/core/analyzer/embedding-service.d.ts.map +1 -0
  101. package/dist/core/analyzer/embedding-service.js +104 -0
  102. package/dist/core/analyzer/embedding-service.js.map +1 -0
  103. package/dist/core/analyzer/file-walker.d.ts +78 -0
  104. package/dist/core/analyzer/file-walker.d.ts.map +1 -0
  105. package/dist/core/analyzer/file-walker.js +531 -0
  106. package/dist/core/analyzer/file-walker.js.map +1 -0
  107. package/dist/core/analyzer/import-parser.d.ts +91 -0
  108. package/dist/core/analyzer/import-parser.d.ts.map +1 -0
  109. package/dist/core/analyzer/import-parser.js +720 -0
  110. package/dist/core/analyzer/import-parser.js.map +1 -0
  111. package/dist/core/analyzer/index.d.ts +10 -0
  112. package/dist/core/analyzer/index.d.ts.map +1 -0
  113. package/dist/core/analyzer/index.js +10 -0
  114. package/dist/core/analyzer/index.js.map +1 -0
  115. package/dist/core/analyzer/refactor-analyzer.d.ts +80 -0
  116. package/dist/core/analyzer/refactor-analyzer.d.ts.map +1 -0
  117. package/dist/core/analyzer/refactor-analyzer.js +339 -0
  118. package/dist/core/analyzer/refactor-analyzer.js.map +1 -0
  119. package/dist/core/analyzer/repository-mapper.d.ts +150 -0
  120. package/dist/core/analyzer/repository-mapper.d.ts.map +1 -0
  121. package/dist/core/analyzer/repository-mapper.js +731 -0
  122. package/dist/core/analyzer/repository-mapper.js.map +1 -0
  123. package/dist/core/analyzer/signature-extractor.d.ts +31 -0
  124. package/dist/core/analyzer/signature-extractor.d.ts.map +1 -0
  125. package/dist/core/analyzer/signature-extractor.js +387 -0
  126. package/dist/core/analyzer/signature-extractor.js.map +1 -0
  127. package/dist/core/analyzer/significance-scorer.d.ts +79 -0
  128. package/dist/core/analyzer/significance-scorer.d.ts.map +1 -0
  129. package/dist/core/analyzer/significance-scorer.js +407 -0
  130. package/dist/core/analyzer/significance-scorer.js.map +1 -0
  131. package/dist/core/analyzer/subgraph-extractor.d.ts +43 -0
  132. package/dist/core/analyzer/subgraph-extractor.d.ts.map +1 -0
  133. package/dist/core/analyzer/subgraph-extractor.js +129 -0
  134. package/dist/core/analyzer/subgraph-extractor.js.map +1 -0
  135. package/dist/core/analyzer/vector-index.d.ts +63 -0
  136. package/dist/core/analyzer/vector-index.d.ts.map +1 -0
  137. package/dist/core/analyzer/vector-index.js +169 -0
  138. package/dist/core/analyzer/vector-index.js.map +1 -0
  139. package/dist/core/drift/drift-detector.d.ts +102 -0
  140. package/dist/core/drift/drift-detector.d.ts.map +1 -0
  141. package/dist/core/drift/drift-detector.js +597 -0
  142. package/dist/core/drift/drift-detector.js.map +1 -0
  143. package/dist/core/drift/git-diff.d.ts +55 -0
  144. package/dist/core/drift/git-diff.d.ts.map +1 -0
  145. package/dist/core/drift/git-diff.js +356 -0
  146. package/dist/core/drift/git-diff.js.map +1 -0
  147. package/dist/core/drift/index.d.ts +12 -0
  148. package/dist/core/drift/index.d.ts.map +1 -0
  149. package/dist/core/drift/index.js +9 -0
  150. package/dist/core/drift/index.js.map +1 -0
  151. package/dist/core/drift/spec-mapper.d.ts +73 -0
  152. package/dist/core/drift/spec-mapper.d.ts.map +1 -0
  153. package/dist/core/drift/spec-mapper.js +353 -0
  154. package/dist/core/drift/spec-mapper.js.map +1 -0
  155. package/dist/core/generator/adr-generator.d.ts +32 -0
  156. package/dist/core/generator/adr-generator.d.ts.map +1 -0
  157. package/dist/core/generator/adr-generator.js +192 -0
  158. package/dist/core/generator/adr-generator.js.map +1 -0
  159. package/dist/core/generator/index.d.ts +9 -0
  160. package/dist/core/generator/index.d.ts.map +1 -0
  161. package/dist/core/generator/index.js +12 -0
  162. package/dist/core/generator/index.js.map +1 -0
  163. package/dist/core/generator/mapping-generator.d.ts +54 -0
  164. package/dist/core/generator/mapping-generator.d.ts.map +1 -0
  165. package/dist/core/generator/mapping-generator.js +239 -0
  166. package/dist/core/generator/mapping-generator.js.map +1 -0
  167. package/dist/core/generator/openspec-compat.d.ts +160 -0
  168. package/dist/core/generator/openspec-compat.d.ts.map +1 -0
  169. package/dist/core/generator/openspec-compat.js +523 -0
  170. package/dist/core/generator/openspec-compat.js.map +1 -0
  171. package/dist/core/generator/openspec-format-generator.d.ts +111 -0
  172. package/dist/core/generator/openspec-format-generator.d.ts.map +1 -0
  173. package/dist/core/generator/openspec-format-generator.js +817 -0
  174. package/dist/core/generator/openspec-format-generator.js.map +1 -0
  175. package/dist/core/generator/openspec-writer.d.ts +131 -0
  176. package/dist/core/generator/openspec-writer.d.ts.map +1 -0
  177. package/dist/core/generator/openspec-writer.js +379 -0
  178. package/dist/core/generator/openspec-writer.js.map +1 -0
  179. package/dist/core/generator/prompts.d.ts +35 -0
  180. package/dist/core/generator/prompts.d.ts.map +1 -0
  181. package/dist/core/generator/prompts.js +212 -0
  182. package/dist/core/generator/prompts.js.map +1 -0
  183. package/dist/core/generator/spec-pipeline.d.ts +94 -0
  184. package/dist/core/generator/spec-pipeline.d.ts.map +1 -0
  185. package/dist/core/generator/spec-pipeline.js +474 -0
  186. package/dist/core/generator/spec-pipeline.js.map +1 -0
  187. package/dist/core/generator/stages/stage1-survey.d.ts +19 -0
  188. package/dist/core/generator/stages/stage1-survey.d.ts.map +1 -0
  189. package/dist/core/generator/stages/stage1-survey.js +105 -0
  190. package/dist/core/generator/stages/stage1-survey.js.map +1 -0
  191. package/dist/core/generator/stages/stage2-entities.d.ts +11 -0
  192. package/dist/core/generator/stages/stage2-entities.d.ts.map +1 -0
  193. package/dist/core/generator/stages/stage2-entities.js +67 -0
  194. package/dist/core/generator/stages/stage2-entities.js.map +1 -0
  195. package/dist/core/generator/stages/stage3-services.d.ts +11 -0
  196. package/dist/core/generator/stages/stage3-services.d.ts.map +1 -0
  197. package/dist/core/generator/stages/stage3-services.js +75 -0
  198. package/dist/core/generator/stages/stage3-services.js.map +1 -0
  199. package/dist/core/generator/stages/stage4-api.d.ts +11 -0
  200. package/dist/core/generator/stages/stage4-api.d.ts.map +1 -0
  201. package/dist/core/generator/stages/stage4-api.js +65 -0
  202. package/dist/core/generator/stages/stage4-api.js.map +1 -0
  203. package/dist/core/generator/stages/stage5-architecture.d.ts +10 -0
  204. package/dist/core/generator/stages/stage5-architecture.d.ts.map +1 -0
  205. package/dist/core/generator/stages/stage5-architecture.js +62 -0
  206. package/dist/core/generator/stages/stage5-architecture.js.map +1 -0
  207. package/dist/core/generator/stages/stage6-adr.d.ts +8 -0
  208. package/dist/core/generator/stages/stage6-adr.d.ts.map +1 -0
  209. package/dist/core/generator/stages/stage6-adr.js +41 -0
  210. package/dist/core/generator/stages/stage6-adr.js.map +1 -0
  211. package/dist/core/services/chat-agent.d.ts +45 -0
  212. package/dist/core/services/chat-agent.d.ts.map +1 -0
  213. package/dist/core/services/chat-agent.js +310 -0
  214. package/dist/core/services/chat-agent.js.map +1 -0
  215. package/dist/core/services/chat-tools.d.ts +32 -0
  216. package/dist/core/services/chat-tools.d.ts.map +1 -0
  217. package/dist/core/services/chat-tools.js +270 -0
  218. package/dist/core/services/chat-tools.js.map +1 -0
  219. package/dist/core/services/config-manager.d.ts +61 -0
  220. package/dist/core/services/config-manager.d.ts.map +1 -0
  221. package/dist/core/services/config-manager.js +143 -0
  222. package/dist/core/services/config-manager.js.map +1 -0
  223. package/dist/core/services/gitignore-manager.d.ts +29 -0
  224. package/dist/core/services/gitignore-manager.d.ts.map +1 -0
  225. package/dist/core/services/gitignore-manager.js +106 -0
  226. package/dist/core/services/gitignore-manager.js.map +1 -0
  227. package/dist/core/services/index.d.ts +8 -0
  228. package/dist/core/services/index.d.ts.map +1 -0
  229. package/dist/core/services/index.js +8 -0
  230. package/dist/core/services/index.js.map +1 -0
  231. package/dist/core/services/llm-service.d.ts +336 -0
  232. package/dist/core/services/llm-service.d.ts.map +1 -0
  233. package/dist/core/services/llm-service.js +1155 -0
  234. package/dist/core/services/llm-service.js.map +1 -0
  235. package/dist/core/services/mcp-handlers/analysis.d.ts +42 -0
  236. package/dist/core/services/mcp-handlers/analysis.d.ts.map +1 -0
  237. package/dist/core/services/mcp-handlers/analysis.js +300 -0
  238. package/dist/core/services/mcp-handlers/analysis.js.map +1 -0
  239. package/dist/core/services/mcp-handlers/graph.d.ts +65 -0
  240. package/dist/core/services/mcp-handlers/graph.d.ts.map +1 -0
  241. package/dist/core/services/mcp-handlers/graph.js +509 -0
  242. package/dist/core/services/mcp-handlers/graph.js.map +1 -0
  243. package/dist/core/services/mcp-handlers/semantic.d.ts +38 -0
  244. package/dist/core/services/mcp-handlers/semantic.d.ts.map +1 -0
  245. package/dist/core/services/mcp-handlers/semantic.js +172 -0
  246. package/dist/core/services/mcp-handlers/semantic.js.map +1 -0
  247. package/dist/core/services/mcp-handlers/utils.d.ts +21 -0
  248. package/dist/core/services/mcp-handlers/utils.d.ts.map +1 -0
  249. package/dist/core/services/mcp-handlers/utils.js +62 -0
  250. package/dist/core/services/mcp-handlers/utils.js.map +1 -0
  251. package/dist/core/services/project-detector.d.ts +32 -0
  252. package/dist/core/services/project-detector.d.ts.map +1 -0
  253. package/dist/core/services/project-detector.js +111 -0
  254. package/dist/core/services/project-detector.js.map +1 -0
  255. package/dist/core/verifier/index.d.ts +5 -0
  256. package/dist/core/verifier/index.d.ts.map +1 -0
  257. package/dist/core/verifier/index.js +5 -0
  258. package/dist/core/verifier/index.js.map +1 -0
  259. package/dist/core/verifier/verification-engine.d.ts +226 -0
  260. package/dist/core/verifier/verification-engine.d.ts.map +1 -0
  261. package/dist/core/verifier/verification-engine.js +681 -0
  262. package/dist/core/verifier/verification-engine.js.map +1 -0
  263. package/dist/types/index.d.ts +252 -0
  264. package/dist/types/index.d.ts.map +1 -0
  265. package/dist/types/index.js +5 -0
  266. package/dist/types/index.js.map +1 -0
  267. package/dist/types/pipeline.d.ts +148 -0
  268. package/dist/types/pipeline.d.ts.map +1 -0
  269. package/dist/types/pipeline.js +5 -0
  270. package/dist/types/pipeline.js.map +1 -0
  271. package/dist/utils/errors.d.ts +51 -0
  272. package/dist/utils/errors.d.ts.map +1 -0
  273. package/dist/utils/errors.js +128 -0
  274. package/dist/utils/errors.js.map +1 -0
  275. package/dist/utils/logger.d.ts +149 -0
  276. package/dist/utils/logger.d.ts.map +1 -0
  277. package/dist/utils/logger.js +331 -0
  278. package/dist/utils/logger.js.map +1 -0
  279. package/dist/utils/progress.d.ts +142 -0
  280. package/dist/utils/progress.d.ts.map +1 -0
  281. package/dist/utils/progress.js +280 -0
  282. package/dist/utils/progress.js.map +1 -0
  283. package/dist/utils/prompts.d.ts +53 -0
  284. package/dist/utils/prompts.d.ts.map +1 -0
  285. package/dist/utils/prompts.js +199 -0
  286. package/dist/utils/prompts.js.map +1 -0
  287. package/dist/utils/shutdown.d.ts +89 -0
  288. package/dist/utils/shutdown.d.ts.map +1 -0
  289. package/dist/utils/shutdown.js +237 -0
  290. package/dist/utils/shutdown.js.map +1 -0
  291. package/package.json +114 -0
  292. package/src/viewer/InteractiveGraphViewer.jsx +1486 -0
  293. package/src/viewer/app/index.html +17 -0
  294. package/src/viewer/app/main.jsx +13 -0
  295. package/src/viewer/components/ArchitectureView.jsx +177 -0
  296. package/src/viewer/components/ChatPanel.jsx +448 -0
  297. package/src/viewer/components/ClusterGraph.jsx +441 -0
  298. package/src/viewer/components/FilterBar.jsx +179 -0
  299. package/src/viewer/components/FlatGraph.jsx +275 -0
  300. package/src/viewer/components/MicroComponents.jsx +83 -0
  301. package/src/viewer/hooks/usePanZoom.js +79 -0
  302. package/src/viewer/utils/constants.js +47 -0
  303. package/src/viewer/utils/graph-helpers.js +291 -0
@@ -0,0 +1,172 @@
1
+ /**
2
+ * MCP tool handlers for semantic search and feature insertion:
3
+ * search_code, suggest_insertion_points.
4
+ */
5
+ import { join } from 'node:path';
6
+ import { validateDirectory } from './utils.js';
7
+ import { readSpecGenConfig } from '../config-manager.js';
8
+ export function classifyRole(fanIn, fanOut, isHub, isEntryPoint) {
9
+ if (isEntryPoint)
10
+ return 'entry_point';
11
+ if (isHub)
12
+ return 'hub';
13
+ if (fanOut >= 5)
14
+ return 'orchestrator';
15
+ if (fanIn <= 1)
16
+ return 'utility';
17
+ return 'internal';
18
+ }
19
+ export function deriveStrategy(role) {
20
+ switch (role) {
21
+ case 'entry_point': return 'extend_entry_point';
22
+ case 'orchestrator': return 'add_orchestration_step';
23
+ case 'hub': return 'cross_cutting_hook';
24
+ case 'utility': return 'extract_shared_logic';
25
+ default: return 'call_alongside';
26
+ }
27
+ }
28
+ export function buildReason(name, role, strategy, fanIn, fanOut) {
29
+ switch (strategy) {
30
+ case 'extend_entry_point':
31
+ return `${name} is an entry point (no internal callers). Add your feature here or create a sibling entry point that delegates to it.`;
32
+ case 'add_orchestration_step':
33
+ return `${name} orchestrates ${fanOut} downstream calls. Insert your feature as a new step in this pipeline.`;
34
+ case 'cross_cutting_hook':
35
+ return `${name} is called by ${fanIn} functions — adding logic here affects the entire callsite surface.`;
36
+ case 'extract_shared_logic':
37
+ return `${name} is a low-traffic utility. Shared logic for your feature can live here or be extracted alongside it.`;
38
+ default:
39
+ return `${name} is semantically close to your feature and operates in the same domain. Extend or call alongside it.`;
40
+ }
41
+ }
42
+ /** Composite score = (1 - semanticDistance) * 0.6 + structuralBonus * 0.4 */
43
+ export function compositeScore(semanticDistance, role) {
44
+ const semantic = Math.max(0, 1 - semanticDistance);
45
+ const structuralBonus = {
46
+ entry_point: 1.0,
47
+ orchestrator: 0.8,
48
+ hub: 0.6,
49
+ internal: 0.4,
50
+ utility: 0.3,
51
+ };
52
+ return semantic * 0.6 + structuralBonus[role] * 0.4;
53
+ }
54
+ // ============================================================================
55
+ // HANDLERS
56
+ // ============================================================================
57
+ /**
58
+ * Semantic search over the vector index built by "spec-gen analyze --embed".
59
+ */
60
+ export async function handleSearchCode(directory, query, limit = 10, language, minFanIn) {
61
+ const absDir = await validateDirectory(directory);
62
+ const outputDir = join(absDir, '.spec-gen', 'analysis');
63
+ const { VectorIndex } = await import('../../analyzer/vector-index.js');
64
+ const { EmbeddingService } = await import('../../analyzer/embedding-service.js');
65
+ if (!VectorIndex.exists(outputDir)) {
66
+ return {
67
+ error: 'No vector index found. Run "spec-gen analyze --embed" first, ' +
68
+ 'then configure EMBED_BASE_URL and EMBED_MODEL.',
69
+ };
70
+ }
71
+ let embedSvc;
72
+ try {
73
+ embedSvc = EmbeddingService.fromEnv();
74
+ }
75
+ catch {
76
+ const cfg = await readSpecGenConfig(absDir);
77
+ if (!cfg) {
78
+ return { error: 'No embedding configuration found. Set EMBED_BASE_URL and EMBED_MODEL env vars, or add an "embedding" section to .spec-gen/config.json.' };
79
+ }
80
+ const svcFromConfig = EmbeddingService.fromConfig(cfg);
81
+ if (!svcFromConfig) {
82
+ return { error: 'No embedding configuration found. Set EMBED_BASE_URL and EMBED_MODEL env vars, or add an "embedding" section to .spec-gen/config.json.' };
83
+ }
84
+ embedSvc = svcFromConfig;
85
+ }
86
+ limit = Math.max(1, Math.min(limit, 100));
87
+ const results = await VectorIndex.search(outputDir, query, embedSvc, { limit, language, minFanIn });
88
+ return {
89
+ query,
90
+ count: results.length,
91
+ results: results.map(r => ({
92
+ score: r.score,
93
+ name: r.record.name,
94
+ filePath: r.record.filePath,
95
+ className: r.record.className || undefined,
96
+ language: r.record.language,
97
+ signature: r.record.signature || undefined,
98
+ docstring: r.record.docstring || undefined,
99
+ fanIn: r.record.fanIn,
100
+ fanOut: r.record.fanOut,
101
+ isHub: r.record.isHub,
102
+ isEntryPoint: r.record.isEntryPoint,
103
+ })),
104
+ };
105
+ }
106
+ /**
107
+ * Find the best places in the codebase to implement a new feature.
108
+ */
109
+ export async function handleSuggestInsertionPoints(directory, description, limit = 5, language) {
110
+ const absDir = await validateDirectory(directory);
111
+ const outputDir = join(absDir, '.spec-gen', 'analysis');
112
+ const { VectorIndex } = await import('../../analyzer/vector-index.js');
113
+ const { EmbeddingService } = await import('../../analyzer/embedding-service.js');
114
+ if (!VectorIndex.exists(outputDir)) {
115
+ return {
116
+ error: 'No vector index found. Run "spec-gen analyze --embed" first, ' +
117
+ 'then configure EMBED_BASE_URL and EMBED_MODEL.',
118
+ };
119
+ }
120
+ let embedSvc;
121
+ try {
122
+ embedSvc = EmbeddingService.fromEnv();
123
+ }
124
+ catch {
125
+ const cfg = await readSpecGenConfig(absDir);
126
+ if (!cfg) {
127
+ return { error: 'No embedding configuration found. Set EMBED_BASE_URL and EMBED_MODEL env vars, or add an "embedding" section to .spec-gen/config.json.' };
128
+ }
129
+ const svcFromConfig = EmbeddingService.fromConfig(cfg);
130
+ if (!svcFromConfig) {
131
+ return { error: 'No embedding configuration found. Set EMBED_BASE_URL and EMBED_MODEL env vars, or add an "embedding" section to .spec-gen/config.json.' };
132
+ }
133
+ embedSvc = svcFromConfig;
134
+ }
135
+ limit = Math.max(1, Math.min(limit, 20));
136
+ const rawResults = await VectorIndex.search(outputDir, description, embedSvc, { limit: limit * 4, language });
137
+ const candidates = rawResults.map(r => {
138
+ const role = classifyRole(r.record.fanIn, r.record.fanOut, r.record.isHub, r.record.isEntryPoint);
139
+ const strategy = deriveStrategy(role);
140
+ const score = compositeScore(r.score, role);
141
+ return {
142
+ rank: 0,
143
+ score,
144
+ semanticDistance: r.score,
145
+ name: r.record.name,
146
+ filePath: r.record.filePath,
147
+ className: r.record.className || undefined,
148
+ language: r.record.language,
149
+ signature: r.record.signature || undefined,
150
+ docstring: r.record.docstring || undefined,
151
+ role, insertionStrategy: strategy,
152
+ reason: buildReason(r.record.name, role, strategy, r.record.fanIn, r.record.fanOut),
153
+ fanIn: r.record.fanIn, fanOut: r.record.fanOut,
154
+ isHub: r.record.isHub, isEntryPoint: r.record.isEntryPoint,
155
+ };
156
+ });
157
+ candidates.sort((a, b) => b.score - a.score);
158
+ const top = candidates.slice(0, limit).map((c, i) => ({ ...c, rank: i + 1 }));
159
+ return {
160
+ description,
161
+ count: top.length,
162
+ candidates: top,
163
+ nextSteps: top.length > 0
164
+ ? [
165
+ `Run get_function_skeleton on "${top[0].filePath}" to see the internal structure of ${top[0].name}`,
166
+ `Run get_subgraph on "${top[0].name}" to understand its call neighborhood`,
167
+ `After implementing, run check_spec_drift to verify the code matches the spec`,
168
+ ]
169
+ : ['No candidates found. Try a broader description or run "spec-gen analyze --embed" to build the index.'],
170
+ };
171
+ }
172
+ //# sourceMappingURL=semantic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic.js","sourceRoot":"","sources":["../../../../src/core/services/mcp-handlers/semantic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Shared utilities for MCP tool handlers.
3
+ */
4
+ import type { LLMContext } from '../../analyzer/artifact-generator.js';
5
+ /**
6
+ * Resolve and validate a user-supplied directory path.
7
+ *
8
+ * Ensures the path resolves to an existing directory, which prevents path
9
+ * traversal attacks where a client supplies `"../../../../etc"` or a plain
10
+ * file path instead of a project directory.
11
+ */
12
+ export declare function validateDirectory(directory: string): Promise<string>;
13
+ /**
14
+ * Strip common API key and token patterns from an error message before
15
+ * returning it to MCP clients, to prevent secret leakage via error responses.
16
+ */
17
+ export declare function sanitizeMcpError(err: unknown): string;
18
+ export declare function readCachedContext(directory: string): Promise<LLMContext | null>;
19
+ /** Returns true if the cached analysis is present and less than 1 hour old. */
20
+ export declare function isCacheFresh(directory: string): Promise<boolean>;
21
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/core/services/mcp-handlers/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAEvE;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAe1E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAQrD;AAED,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAUrF;AAED,+EAA+E;AAC/E,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOtE"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Shared utilities for MCP tool handlers.
3
+ */
4
+ import { readFile, stat } from 'node:fs/promises';
5
+ import { join, resolve } from 'node:path';
6
+ /**
7
+ * Resolve and validate a user-supplied directory path.
8
+ *
9
+ * Ensures the path resolves to an existing directory, which prevents path
10
+ * traversal attacks where a client supplies `"../../../../etc"` or a plain
11
+ * file path instead of a project directory.
12
+ */
13
+ export async function validateDirectory(directory) {
14
+ if (!directory || typeof directory !== 'string') {
15
+ throw new Error('directory parameter is required and must be a string');
16
+ }
17
+ const absDir = resolve(directory);
18
+ let s;
19
+ try {
20
+ s = await stat(absDir);
21
+ }
22
+ catch {
23
+ throw new Error(`Directory not found: ${absDir}`);
24
+ }
25
+ if (!s.isDirectory()) {
26
+ throw new Error(`Not a directory: ${absDir}`);
27
+ }
28
+ return absDir;
29
+ }
30
+ /**
31
+ * Strip common API key and token patterns from an error message before
32
+ * returning it to MCP clients, to prevent secret leakage via error responses.
33
+ */
34
+ export function sanitizeMcpError(err) {
35
+ const msg = err instanceof Error ? err.message : String(err);
36
+ return msg
37
+ .replace(/sk-ant-[A-Za-z0-9\-_]{10,}/g, '[REDACTED]')
38
+ .replace(/sk-[A-Za-z0-9\-_]{20,}/g, '[REDACTED]')
39
+ .replace(/Bearer\s+\S{10,}/g, 'Bearer [REDACTED]')
40
+ .replace(/Authorization:\s*\S+/gi, 'Authorization: [REDACTED]')
41
+ .replace(/api[_-]?key[=:]\s*\S{8,}/gi, 'api_key=[REDACTED]');
42
+ }
43
+ export async function readCachedContext(directory) {
44
+ try {
45
+ const raw = await readFile(join(directory, '.spec-gen', 'analysis', 'llm-context.json'), 'utf-8');
46
+ return JSON.parse(raw);
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ }
52
+ /** Returns true if the cached analysis is present and less than 1 hour old. */
53
+ export async function isCacheFresh(directory) {
54
+ try {
55
+ const s = await stat(join(directory, '.spec-gen', 'analysis', 'llm-context.json'));
56
+ return Date.now() - s.mtimeMs < 60 * 60 * 1000;
57
+ }
58
+ catch {
59
+ return false;
60
+ }
61
+ }
62
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/core/services/mcp-handlers/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,SAAiB;IACvD,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,IAAI,CAAmC,CAAC;IACxC,IAAI,CAAC;QACH,CAAC,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,wBAAwB,MAAM,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,EAAE,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAY;IAC3C,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,GAAG;SACP,OAAO,CAAC,6BAA6B,EAAE,YAAY,CAAC;SACpD,OAAO,CAAC,yBAAyB,EAAE,YAAY,CAAC;SAChD,OAAO,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;SACjD,OAAO,CAAC,wBAAwB,EAAE,2BAA2B,CAAC;SAC9D,OAAO,CAAC,4BAA4B,EAAE,oBAAoB,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,SAAiB;IACvD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CACxB,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,CAAC,EAC5D,OAAO,CACR,CAAC;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAiB;IAClD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC,CAAC;QACnF,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Project type detection service
3
+ *
4
+ * Detects the project type by checking for language-specific manifest files.
5
+ */
6
+ import type { ProjectType } from '../../types/index.js';
7
+ /**
8
+ * Project detection result
9
+ */
10
+ export interface ProjectDetectionResult {
11
+ projectType: ProjectType;
12
+ manifestFile: string | null;
13
+ hasGit: boolean;
14
+ confidence: 'high' | 'medium' | 'low';
15
+ }
16
+ /**
17
+ * Detect if the directory is a git repository
18
+ */
19
+ export declare function detectGitRepository(rootPath: string): Promise<boolean>;
20
+ /**
21
+ * Detect the project type based on manifest files
22
+ */
23
+ export declare function detectProjectType(rootPath: string): Promise<ProjectDetectionResult>;
24
+ /**
25
+ * Get a human-readable project type name
26
+ */
27
+ export declare function getProjectTypeName(type: ProjectType): string;
28
+ /**
29
+ * Read and parse package.json if it exists
30
+ */
31
+ export declare function readPackageJson(rootPath: string): Promise<Record<string, unknown> | null>;
32
+ //# sourceMappingURL=project-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-detector.d.ts","sourceRoot":"","sources":["../../../src/core/services/project-detector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACvC;AA+BD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAE5E;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA0CzF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAY5D;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAQzC"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Project type detection service
3
+ *
4
+ * Detects the project type by checking for language-specific manifest files.
5
+ */
6
+ import { access, readFile } from 'node:fs/promises';
7
+ import { join } from 'node:path';
8
+ /**
9
+ * Manifest file to project type mapping
10
+ */
11
+ const MANIFEST_MAP = [
12
+ { file: 'package.json', type: 'nodejs', priority: 1 },
13
+ { file: 'pyproject.toml', type: 'python', priority: 1 },
14
+ { file: 'setup.py', type: 'python', priority: 2 },
15
+ { file: 'requirements.txt', type: 'python', priority: 3 },
16
+ { file: 'Cargo.toml', type: 'rust', priority: 1 },
17
+ { file: 'go.mod', type: 'go', priority: 1 },
18
+ { file: 'pom.xml', type: 'java', priority: 1 },
19
+ { file: 'build.gradle', type: 'java', priority: 2 },
20
+ { file: 'build.gradle.kts', type: 'java', priority: 2 },
21
+ { file: 'Gemfile', type: 'ruby', priority: 1 },
22
+ { file: 'composer.json', type: 'php', priority: 1 },
23
+ ];
24
+ /**
25
+ * Check if a file exists
26
+ */
27
+ async function fileExists(filePath) {
28
+ try {
29
+ await access(filePath);
30
+ return true;
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ }
36
+ /**
37
+ * Detect if the directory is a git repository
38
+ */
39
+ export async function detectGitRepository(rootPath) {
40
+ return fileExists(join(rootPath, '.git'));
41
+ }
42
+ /**
43
+ * Detect the project type based on manifest files
44
+ */
45
+ export async function detectProjectType(rootPath) {
46
+ const hasGit = await detectGitRepository(rootPath);
47
+ // Check each manifest file
48
+ const detectedManifests = [];
49
+ for (const manifest of MANIFEST_MAP) {
50
+ if (await fileExists(join(rootPath, manifest.file))) {
51
+ detectedManifests.push(manifest);
52
+ }
53
+ }
54
+ // No manifests found
55
+ if (detectedManifests.length === 0) {
56
+ return {
57
+ projectType: 'unknown',
58
+ manifestFile: null,
59
+ hasGit,
60
+ confidence: 'low',
61
+ };
62
+ }
63
+ // Sort by priority (lower is better) and pick the first
64
+ detectedManifests.sort((a, b) => a.priority - b.priority);
65
+ const primary = detectedManifests[0];
66
+ // Determine confidence based on detection
67
+ let confidence = 'high';
68
+ if (detectedManifests.length > 1) {
69
+ // Multiple project types detected
70
+ const uniqueTypes = new Set(detectedManifests.map((m) => m.type));
71
+ if (uniqueTypes.size > 1) {
72
+ confidence = 'medium';
73
+ }
74
+ }
75
+ return {
76
+ projectType: primary.type,
77
+ manifestFile: primary.file,
78
+ hasGit,
79
+ confidence,
80
+ };
81
+ }
82
+ /**
83
+ * Get a human-readable project type name
84
+ */
85
+ export function getProjectTypeName(type) {
86
+ const names = {
87
+ nodejs: 'Node.js/TypeScript',
88
+ python: 'Python',
89
+ rust: 'Rust',
90
+ go: 'Go',
91
+ java: 'Java',
92
+ ruby: 'Ruby',
93
+ php: 'PHP',
94
+ unknown: 'Unknown',
95
+ };
96
+ return names[type];
97
+ }
98
+ /**
99
+ * Read and parse package.json if it exists
100
+ */
101
+ export async function readPackageJson(rootPath) {
102
+ const packagePath = join(rootPath, 'package.json');
103
+ try {
104
+ const content = await readFile(packagePath, 'utf-8');
105
+ return JSON.parse(content);
106
+ }
107
+ catch {
108
+ return null;
109
+ }
110
+ }
111
+ //# sourceMappingURL=project-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-detector.js","sourceRoot":"","sources":["../../../src/core/services/project-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Verifier module index
3
+ */
4
+ export * from './verification-engine.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/verifier/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,0BAA0B,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Verifier module index
3
+ */
4
+ export * from './verification-engine.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/verifier/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,0BAA0B,CAAC"}