openlore 2.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 (634) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +268 -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 +143 -0
  6. package/dist/api/analyze.js.map +1 -0
  7. package/dist/api/audit.d.ts +10 -0
  8. package/dist/api/audit.d.ts.map +1 -0
  9. package/dist/api/audit.js +117 -0
  10. package/dist/api/audit.js.map +1 -0
  11. package/dist/api/decisions.d.ts +55 -0
  12. package/dist/api/decisions.d.ts.map +1 -0
  13. package/dist/api/decisions.js +157 -0
  14. package/dist/api/decisions.js.map +1 -0
  15. package/dist/api/drift.d.ts +21 -0
  16. package/dist/api/drift.d.ts.map +1 -0
  17. package/dist/api/drift.js +152 -0
  18. package/dist/api/drift.js.map +1 -0
  19. package/dist/api/generate.d.ts +18 -0
  20. package/dist/api/generate.d.ts.map +1 -0
  21. package/dist/api/generate.js +259 -0
  22. package/dist/api/generate.js.map +1 -0
  23. package/dist/api/index.d.ts +41 -0
  24. package/dist/api/index.d.ts.map +1 -0
  25. package/dist/api/index.js +34 -0
  26. package/dist/api/index.js.map +1 -0
  27. package/dist/api/init.d.ts +18 -0
  28. package/dist/api/init.d.ts.map +1 -0
  29. package/dist/api/init.js +83 -0
  30. package/dist/api/init.js.map +1 -0
  31. package/dist/api/run.d.ts +19 -0
  32. package/dist/api/run.d.ts.map +1 -0
  33. package/dist/api/run.js +312 -0
  34. package/dist/api/run.js.map +1 -0
  35. package/dist/api/specs.d.ts +49 -0
  36. package/dist/api/specs.d.ts.map +1 -0
  37. package/dist/api/specs.js +137 -0
  38. package/dist/api/specs.js.map +1 -0
  39. package/dist/api/types.d.ts +201 -0
  40. package/dist/api/types.d.ts.map +1 -0
  41. package/dist/api/types.js +9 -0
  42. package/dist/api/types.js.map +1 -0
  43. package/dist/api/verify.d.ts +20 -0
  44. package/dist/api/verify.d.ts.map +1 -0
  45. package/dist/api/verify.js +117 -0
  46. package/dist/api/verify.js.map +1 -0
  47. package/dist/cli/commands/analyze.d.ts +30 -0
  48. package/dist/cli/commands/analyze.d.ts.map +1 -0
  49. package/dist/cli/commands/analyze.js +683 -0
  50. package/dist/cli/commands/analyze.js.map +1 -0
  51. package/dist/cli/commands/audit.d.ts +9 -0
  52. package/dist/cli/commands/audit.d.ts.map +1 -0
  53. package/dist/cli/commands/audit.js +98 -0
  54. package/dist/cli/commands/audit.js.map +1 -0
  55. package/dist/cli/commands/decisions.d.ts +16 -0
  56. package/dist/cli/commands/decisions.d.ts.map +1 -0
  57. package/dist/cli/commands/decisions.js +864 -0
  58. package/dist/cli/commands/decisions.js.map +1 -0
  59. package/dist/cli/commands/digest.d.ts +9 -0
  60. package/dist/cli/commands/digest.d.ts.map +1 -0
  61. package/dist/cli/commands/digest.js +61 -0
  62. package/dist/cli/commands/digest.js.map +1 -0
  63. package/dist/cli/commands/doctor.d.ts +9 -0
  64. package/dist/cli/commands/doctor.d.ts.map +1 -0
  65. package/dist/cli/commands/doctor.js +398 -0
  66. package/dist/cli/commands/doctor.js.map +1 -0
  67. package/dist/cli/commands/drift.d.ts +9 -0
  68. package/dist/cli/commands/drift.d.ts.map +1 -0
  69. package/dist/cli/commands/drift.js +550 -0
  70. package/dist/cli/commands/drift.js.map +1 -0
  71. package/dist/cli/commands/generate.d.ts +9 -0
  72. package/dist/cli/commands/generate.d.ts.map +1 -0
  73. package/dist/cli/commands/generate.js +565 -0
  74. package/dist/cli/commands/generate.js.map +1 -0
  75. package/dist/cli/commands/init.d.ts +9 -0
  76. package/dist/cli/commands/init.d.ts.map +1 -0
  77. package/dist/cli/commands/init.js +173 -0
  78. package/dist/cli/commands/init.js.map +1 -0
  79. package/dist/cli/commands/mcp.d.ts +2235 -0
  80. package/dist/cli/commands/mcp.d.ts.map +1 -0
  81. package/dist/cli/commands/mcp.js +1384 -0
  82. package/dist/cli/commands/mcp.js.map +1 -0
  83. package/dist/cli/commands/refresh-stories.d.ts +10 -0
  84. package/dist/cli/commands/refresh-stories.d.ts.map +1 -0
  85. package/dist/cli/commands/refresh-stories.js +314 -0
  86. package/dist/cli/commands/refresh-stories.js.map +1 -0
  87. package/dist/cli/commands/run.d.ts +9 -0
  88. package/dist/cli/commands/run.d.ts.map +1 -0
  89. package/dist/cli/commands/run.js +459 -0
  90. package/dist/cli/commands/run.js.map +1 -0
  91. package/dist/cli/commands/setup.d.ts +19 -0
  92. package/dist/cli/commands/setup.d.ts.map +1 -0
  93. package/dist/cli/commands/setup.js +355 -0
  94. package/dist/cli/commands/setup.js.map +1 -0
  95. package/dist/cli/commands/test.d.ts +22 -0
  96. package/dist/cli/commands/test.d.ts.map +1 -0
  97. package/dist/cli/commands/test.js +180 -0
  98. package/dist/cli/commands/test.js.map +1 -0
  99. package/dist/cli/commands/verify.d.ts +9 -0
  100. package/dist/cli/commands/verify.d.ts.map +1 -0
  101. package/dist/cli/commands/verify.js +383 -0
  102. package/dist/cli/commands/verify.js.map +1 -0
  103. package/dist/cli/commands/view.d.ts +13 -0
  104. package/dist/cli/commands/view.d.ts.map +1 -0
  105. package/dist/cli/commands/view.js +547 -0
  106. package/dist/cli/commands/view.js.map +1 -0
  107. package/dist/cli/index.d.ts +9 -0
  108. package/dist/cli/index.d.ts.map +1 -0
  109. package/dist/cli/index.js +118 -0
  110. package/dist/cli/index.js.map +1 -0
  111. package/dist/cli/tui-approval.d.ts +11 -0
  112. package/dist/cli/tui-approval.d.ts.map +1 -0
  113. package/dist/cli/tui-approval.js +129 -0
  114. package/dist/cli/tui-approval.js.map +1 -0
  115. package/dist/constants.d.ts +314 -0
  116. package/dist/constants.d.ts.map +1 -0
  117. package/dist/constants.js +382 -0
  118. package/dist/constants.js.map +1 -0
  119. package/dist/core/analyzer/ai-config-generator.d.ts +54 -0
  120. package/dist/core/analyzer/ai-config-generator.d.ts.map +1 -0
  121. package/dist/core/analyzer/ai-config-generator.js +98 -0
  122. package/dist/core/analyzer/ai-config-generator.js.map +1 -0
  123. package/dist/core/analyzer/architecture-writer.d.ts +67 -0
  124. package/dist/core/analyzer/architecture-writer.d.ts.map +1 -0
  125. package/dist/core/analyzer/architecture-writer.js +209 -0
  126. package/dist/core/analyzer/architecture-writer.js.map +1 -0
  127. package/dist/core/analyzer/artifact-generator.d.ts +261 -0
  128. package/dist/core/analyzer/artifact-generator.d.ts.map +1 -0
  129. package/dist/core/analyzer/artifact-generator.js +909 -0
  130. package/dist/core/analyzer/artifact-generator.js.map +1 -0
  131. package/dist/core/analyzer/ast-chunker.d.ts +24 -0
  132. package/dist/core/analyzer/ast-chunker.d.ts.map +1 -0
  133. package/dist/core/analyzer/ast-chunker.js +198 -0
  134. package/dist/core/analyzer/ast-chunker.js.map +1 -0
  135. package/dist/core/analyzer/call-graph.d.ts +162 -0
  136. package/dist/core/analyzer/call-graph.d.ts.map +1 -0
  137. package/dist/core/analyzer/call-graph.js +2040 -0
  138. package/dist/core/analyzer/call-graph.js.map +1 -0
  139. package/dist/core/analyzer/code-shaper.d.ts +33 -0
  140. package/dist/core/analyzer/code-shaper.d.ts.map +1 -0
  141. package/dist/core/analyzer/code-shaper.js +154 -0
  142. package/dist/core/analyzer/code-shaper.js.map +1 -0
  143. package/dist/core/analyzer/codebase-digest.d.ts +40 -0
  144. package/dist/core/analyzer/codebase-digest.d.ts.map +1 -0
  145. package/dist/core/analyzer/codebase-digest.js +195 -0
  146. package/dist/core/analyzer/codebase-digest.js.map +1 -0
  147. package/dist/core/analyzer/cpp-header-resolver.d.ts +30 -0
  148. package/dist/core/analyzer/cpp-header-resolver.d.ts.map +1 -0
  149. package/dist/core/analyzer/cpp-header-resolver.js +71 -0
  150. package/dist/core/analyzer/cpp-header-resolver.js.map +1 -0
  151. package/dist/core/analyzer/dependency-graph.d.ts +230 -0
  152. package/dist/core/analyzer/dependency-graph.d.ts.map +1 -0
  153. package/dist/core/analyzer/dependency-graph.js +752 -0
  154. package/dist/core/analyzer/dependency-graph.js.map +1 -0
  155. package/dist/core/analyzer/duplicate-detector.d.ts +52 -0
  156. package/dist/core/analyzer/duplicate-detector.d.ts.map +1 -0
  157. package/dist/core/analyzer/duplicate-detector.js +289 -0
  158. package/dist/core/analyzer/duplicate-detector.js.map +1 -0
  159. package/dist/core/analyzer/embedding-service.d.ts +56 -0
  160. package/dist/core/analyzer/embedding-service.d.ts.map +1 -0
  161. package/dist/core/analyzer/embedding-service.js +118 -0
  162. package/dist/core/analyzer/embedding-service.js.map +1 -0
  163. package/dist/core/analyzer/env-extractor.d.ts +33 -0
  164. package/dist/core/analyzer/env-extractor.d.ts.map +1 -0
  165. package/dist/core/analyzer/env-extractor.js +196 -0
  166. package/dist/core/analyzer/env-extractor.js.map +1 -0
  167. package/dist/core/analyzer/external-packages.d.ts +20 -0
  168. package/dist/core/analyzer/external-packages.d.ts.map +1 -0
  169. package/dist/core/analyzer/external-packages.js +175 -0
  170. package/dist/core/analyzer/external-packages.js.map +1 -0
  171. package/dist/core/analyzer/file-walker.d.ts +78 -0
  172. package/dist/core/analyzer/file-walker.d.ts.map +1 -0
  173. package/dist/core/analyzer/file-walker.js +532 -0
  174. package/dist/core/analyzer/file-walker.js.map +1 -0
  175. package/dist/core/analyzer/function-registry-trie.d.ts +21 -0
  176. package/dist/core/analyzer/function-registry-trie.d.ts.map +1 -0
  177. package/dist/core/analyzer/function-registry-trie.js +39 -0
  178. package/dist/core/analyzer/function-registry-trie.js.map +1 -0
  179. package/dist/core/analyzer/http-route-parser.d.ts +152 -0
  180. package/dist/core/analyzer/http-route-parser.d.ts.map +1 -0
  181. package/dist/core/analyzer/http-route-parser.js +971 -0
  182. package/dist/core/analyzer/http-route-parser.js.map +1 -0
  183. package/dist/core/analyzer/import-parser.d.ts +100 -0
  184. package/dist/core/analyzer/import-parser.d.ts.map +1 -0
  185. package/dist/core/analyzer/import-parser.js +952 -0
  186. package/dist/core/analyzer/import-parser.js.map +1 -0
  187. package/dist/core/analyzer/import-resolver-bridge.d.ts +25 -0
  188. package/dist/core/analyzer/import-resolver-bridge.d.ts.map +1 -0
  189. package/dist/core/analyzer/import-resolver-bridge.js +99 -0
  190. package/dist/core/analyzer/import-resolver-bridge.js.map +1 -0
  191. package/dist/core/analyzer/index.d.ts +10 -0
  192. package/dist/core/analyzer/index.d.ts.map +1 -0
  193. package/dist/core/analyzer/index.js +10 -0
  194. package/dist/core/analyzer/index.js.map +1 -0
  195. package/dist/core/analyzer/middleware-extractor.d.ts +29 -0
  196. package/dist/core/analyzer/middleware-extractor.d.ts.map +1 -0
  197. package/dist/core/analyzer/middleware-extractor.js +195 -0
  198. package/dist/core/analyzer/middleware-extractor.js.map +1 -0
  199. package/dist/core/analyzer/refactor-analyzer.d.ts +83 -0
  200. package/dist/core/analyzer/refactor-analyzer.d.ts.map +1 -0
  201. package/dist/core/analyzer/refactor-analyzer.js +351 -0
  202. package/dist/core/analyzer/refactor-analyzer.js.map +1 -0
  203. package/dist/core/analyzer/repository-mapper.d.ts +150 -0
  204. package/dist/core/analyzer/repository-mapper.d.ts.map +1 -0
  205. package/dist/core/analyzer/repository-mapper.js +740 -0
  206. package/dist/core/analyzer/repository-mapper.js.map +1 -0
  207. package/dist/core/analyzer/schema-extractor.d.ts +41 -0
  208. package/dist/core/analyzer/schema-extractor.d.ts.map +1 -0
  209. package/dist/core/analyzer/schema-extractor.js +229 -0
  210. package/dist/core/analyzer/schema-extractor.js.map +1 -0
  211. package/dist/core/analyzer/signature-extractor.d.ts +31 -0
  212. package/dist/core/analyzer/signature-extractor.d.ts.map +1 -0
  213. package/dist/core/analyzer/signature-extractor.js +675 -0
  214. package/dist/core/analyzer/signature-extractor.js.map +1 -0
  215. package/dist/core/analyzer/significance-scorer.d.ts +79 -0
  216. package/dist/core/analyzer/significance-scorer.d.ts.map +1 -0
  217. package/dist/core/analyzer/significance-scorer.js +407 -0
  218. package/dist/core/analyzer/significance-scorer.js.map +1 -0
  219. package/dist/core/analyzer/spec-snapshot-generator.d.ts +17 -0
  220. package/dist/core/analyzer/spec-snapshot-generator.d.ts.map +1 -0
  221. package/dist/core/analyzer/spec-snapshot-generator.js +201 -0
  222. package/dist/core/analyzer/spec-snapshot-generator.js.map +1 -0
  223. package/dist/core/analyzer/spec-vector-index.d.ts +68 -0
  224. package/dist/core/analyzer/spec-vector-index.d.ts.map +1 -0
  225. package/dist/core/analyzer/spec-vector-index.js +340 -0
  226. package/dist/core/analyzer/spec-vector-index.js.map +1 -0
  227. package/dist/core/analyzer/subgraph-extractor.d.ts +51 -0
  228. package/dist/core/analyzer/subgraph-extractor.d.ts.map +1 -0
  229. package/dist/core/analyzer/subgraph-extractor.js +147 -0
  230. package/dist/core/analyzer/subgraph-extractor.js.map +1 -0
  231. package/dist/core/analyzer/type-inference-engine.d.ts +23 -0
  232. package/dist/core/analyzer/type-inference-engine.d.ts.map +1 -0
  233. package/dist/core/analyzer/type-inference-engine.js +130 -0
  234. package/dist/core/analyzer/type-inference-engine.js.map +1 -0
  235. package/dist/core/analyzer/ui-component-extractor.d.ts +43 -0
  236. package/dist/core/analyzer/ui-component-extractor.d.ts.map +1 -0
  237. package/dist/core/analyzer/ui-component-extractor.js +245 -0
  238. package/dist/core/analyzer/ui-component-extractor.js.map +1 -0
  239. package/dist/core/analyzer/unified-search.d.ts +116 -0
  240. package/dist/core/analyzer/unified-search.d.ts.map +1 -0
  241. package/dist/core/analyzer/unified-search.js +231 -0
  242. package/dist/core/analyzer/unified-search.js.map +1 -0
  243. package/dist/core/analyzer/vector-index.d.ts +92 -0
  244. package/dist/core/analyzer/vector-index.d.ts.map +1 -0
  245. package/dist/core/analyzer/vector-index.js +451 -0
  246. package/dist/core/analyzer/vector-index.js.map +1 -0
  247. package/dist/core/decisions/consolidator.d.ts +14 -0
  248. package/dist/core/decisions/consolidator.d.ts.map +1 -0
  249. package/dist/core/decisions/consolidator.js +169 -0
  250. package/dist/core/decisions/consolidator.js.map +1 -0
  251. package/dist/core/decisions/extractor.d.ts +26 -0
  252. package/dist/core/decisions/extractor.d.ts.map +1 -0
  253. package/dist/core/decisions/extractor.js +156 -0
  254. package/dist/core/decisions/extractor.js.map +1 -0
  255. package/dist/core/decisions/index.d.ts +19 -0
  256. package/dist/core/decisions/index.d.ts.map +1 -0
  257. package/dist/core/decisions/index.js +16 -0
  258. package/dist/core/decisions/index.js.map +1 -0
  259. package/dist/core/decisions/store.d.ts +36 -0
  260. package/dist/core/decisions/store.d.ts.map +1 -0
  261. package/dist/core/decisions/store.js +109 -0
  262. package/dist/core/decisions/store.js.map +1 -0
  263. package/dist/core/decisions/syncer.d.ts +27 -0
  264. package/dist/core/decisions/syncer.d.ts.map +1 -0
  265. package/dist/core/decisions/syncer.js +214 -0
  266. package/dist/core/decisions/syncer.js.map +1 -0
  267. package/dist/core/decisions/verifier.d.ts +20 -0
  268. package/dist/core/decisions/verifier.d.ts.map +1 -0
  269. package/dist/core/decisions/verifier.js +115 -0
  270. package/dist/core/decisions/verifier.js.map +1 -0
  271. package/dist/core/digest/digest-generator.d.ts +29 -0
  272. package/dist/core/digest/digest-generator.d.ts.map +1 -0
  273. package/dist/core/digest/digest-generator.js +181 -0
  274. package/dist/core/digest/digest-generator.js.map +1 -0
  275. package/dist/core/drift/drift-detector.d.ts +102 -0
  276. package/dist/core/drift/drift-detector.d.ts.map +1 -0
  277. package/dist/core/drift/drift-detector.js +598 -0
  278. package/dist/core/drift/drift-detector.js.map +1 -0
  279. package/dist/core/drift/git-diff.d.ts +60 -0
  280. package/dist/core/drift/git-diff.d.ts.map +1 -0
  281. package/dist/core/drift/git-diff.js +383 -0
  282. package/dist/core/drift/git-diff.js.map +1 -0
  283. package/dist/core/drift/index.d.ts +12 -0
  284. package/dist/core/drift/index.d.ts.map +1 -0
  285. package/dist/core/drift/index.js +9 -0
  286. package/dist/core/drift/index.js.map +1 -0
  287. package/dist/core/drift/spec-mapper.d.ts +73 -0
  288. package/dist/core/drift/spec-mapper.d.ts.map +1 -0
  289. package/dist/core/drift/spec-mapper.js +353 -0
  290. package/dist/core/drift/spec-mapper.js.map +1 -0
  291. package/dist/core/drift/test-suggester.d.ts +18 -0
  292. package/dist/core/drift/test-suggester.d.ts.map +1 -0
  293. package/dist/core/drift/test-suggester.js +107 -0
  294. package/dist/core/drift/test-suggester.js.map +1 -0
  295. package/dist/core/generator/adr-generator.d.ts +32 -0
  296. package/dist/core/generator/adr-generator.d.ts.map +1 -0
  297. package/dist/core/generator/adr-generator.js +192 -0
  298. package/dist/core/generator/adr-generator.js.map +1 -0
  299. package/dist/core/generator/index.d.ts +9 -0
  300. package/dist/core/generator/index.d.ts.map +1 -0
  301. package/dist/core/generator/index.js +12 -0
  302. package/dist/core/generator/index.js.map +1 -0
  303. package/dist/core/generator/mapping-generator.d.ts +54 -0
  304. package/dist/core/generator/mapping-generator.d.ts.map +1 -0
  305. package/dist/core/generator/mapping-generator.js +240 -0
  306. package/dist/core/generator/mapping-generator.js.map +1 -0
  307. package/dist/core/generator/openspec-compat.d.ts +160 -0
  308. package/dist/core/generator/openspec-compat.d.ts.map +1 -0
  309. package/dist/core/generator/openspec-compat.js +524 -0
  310. package/dist/core/generator/openspec-compat.js.map +1 -0
  311. package/dist/core/generator/openspec-format-generator.d.ts +131 -0
  312. package/dist/core/generator/openspec-format-generator.d.ts.map +1 -0
  313. package/dist/core/generator/openspec-format-generator.js +963 -0
  314. package/dist/core/generator/openspec-format-generator.js.map +1 -0
  315. package/dist/core/generator/openspec-writer.d.ts +130 -0
  316. package/dist/core/generator/openspec-writer.d.ts.map +1 -0
  317. package/dist/core/generator/openspec-writer.js +404 -0
  318. package/dist/core/generator/openspec-writer.js.map +1 -0
  319. package/dist/core/generator/prompts.d.ts +35 -0
  320. package/dist/core/generator/prompts.d.ts.map +1 -0
  321. package/dist/core/generator/prompts.js +212 -0
  322. package/dist/core/generator/prompts.js.map +1 -0
  323. package/dist/core/generator/rag-manifest-generator.d.ts +37 -0
  324. package/dist/core/generator/rag-manifest-generator.d.ts.map +1 -0
  325. package/dist/core/generator/rag-manifest-generator.js +134 -0
  326. package/dist/core/generator/rag-manifest-generator.js.map +1 -0
  327. package/dist/core/generator/schemas.d.ts +365 -0
  328. package/dist/core/generator/schemas.d.ts.map +1 -0
  329. package/dist/core/generator/schemas.js +190 -0
  330. package/dist/core/generator/schemas.js.map +1 -0
  331. package/dist/core/generator/spec-pipeline.d.ts +123 -0
  332. package/dist/core/generator/spec-pipeline.d.ts.map +1 -0
  333. package/dist/core/generator/spec-pipeline.js +699 -0
  334. package/dist/core/generator/spec-pipeline.js.map +1 -0
  335. package/dist/core/generator/stages/stage1-survey.d.ts +19 -0
  336. package/dist/core/generator/stages/stage1-survey.d.ts.map +1 -0
  337. package/dist/core/generator/stages/stage1-survey.js +171 -0
  338. package/dist/core/generator/stages/stage1-survey.js.map +1 -0
  339. package/dist/core/generator/stages/stage2-entities.d.ts +11 -0
  340. package/dist/core/generator/stages/stage2-entities.d.ts.map +1 -0
  341. package/dist/core/generator/stages/stage2-entities.js +74 -0
  342. package/dist/core/generator/stages/stage2-entities.js.map +1 -0
  343. package/dist/core/generator/stages/stage3-services.d.ts +11 -0
  344. package/dist/core/generator/stages/stage3-services.d.ts.map +1 -0
  345. package/dist/core/generator/stages/stage3-services.js +85 -0
  346. package/dist/core/generator/stages/stage3-services.js.map +1 -0
  347. package/dist/core/generator/stages/stage4-api.d.ts +11 -0
  348. package/dist/core/generator/stages/stage4-api.d.ts.map +1 -0
  349. package/dist/core/generator/stages/stage4-api.js +72 -0
  350. package/dist/core/generator/stages/stage4-api.js.map +1 -0
  351. package/dist/core/generator/stages/stage5-architecture.d.ts +11 -0
  352. package/dist/core/generator/stages/stage5-architecture.d.ts.map +1 -0
  353. package/dist/core/generator/stages/stage5-architecture.js +75 -0
  354. package/dist/core/generator/stages/stage5-architecture.js.map +1 -0
  355. package/dist/core/generator/stages/stage6-adr.d.ts +8 -0
  356. package/dist/core/generator/stages/stage6-adr.d.ts.map +1 -0
  357. package/dist/core/generator/stages/stage6-adr.js +47 -0
  358. package/dist/core/generator/stages/stage6-adr.js.map +1 -0
  359. package/dist/core/services/chat-agent.d.ts +50 -0
  360. package/dist/core/services/chat-agent.d.ts.map +1 -0
  361. package/dist/core/services/chat-agent.js +369 -0
  362. package/dist/core/services/chat-agent.js.map +1 -0
  363. package/dist/core/services/chat-tools.d.ts +32 -0
  364. package/dist/core/services/chat-tools.d.ts.map +1 -0
  365. package/dist/core/services/chat-tools.js +494 -0
  366. package/dist/core/services/chat-tools.js.map +1 -0
  367. package/dist/core/services/config-manager.d.ts +61 -0
  368. package/dist/core/services/config-manager.d.ts.map +1 -0
  369. package/dist/core/services/config-manager.js +149 -0
  370. package/dist/core/services/config-manager.js.map +1 -0
  371. package/dist/core/services/edge-store.d.ts +57 -0
  372. package/dist/core/services/edge-store.d.ts.map +1 -0
  373. package/dist/core/services/edge-store.js +419 -0
  374. package/dist/core/services/edge-store.js.map +1 -0
  375. package/dist/core/services/gitignore-manager.d.ts +29 -0
  376. package/dist/core/services/gitignore-manager.d.ts.map +1 -0
  377. package/dist/core/services/gitignore-manager.js +95 -0
  378. package/dist/core/services/gitignore-manager.js.map +1 -0
  379. package/dist/core/services/index.d.ts +8 -0
  380. package/dist/core/services/index.d.ts.map +1 -0
  381. package/dist/core/services/index.js +8 -0
  382. package/dist/core/services/index.js.map +1 -0
  383. package/dist/core/services/llm-service.d.ts +379 -0
  384. package/dist/core/services/llm-service.d.ts.map +1 -0
  385. package/dist/core/services/llm-service.js +1553 -0
  386. package/dist/core/services/llm-service.js.map +1 -0
  387. package/dist/core/services/mcp-handlers/analysis.d.ts +127 -0
  388. package/dist/core/services/mcp-handlers/analysis.d.ts.map +1 -0
  389. package/dist/core/services/mcp-handlers/analysis.js +1185 -0
  390. package/dist/core/services/mcp-handlers/analysis.js.map +1 -0
  391. package/dist/core/services/mcp-handlers/change.d.ts +14 -0
  392. package/dist/core/services/mcp-handlers/change.d.ts.map +1 -0
  393. package/dist/core/services/mcp-handlers/change.js +416 -0
  394. package/dist/core/services/mcp-handlers/change.js.map +1 -0
  395. package/dist/core/services/mcp-handlers/decisions.d.ts +16 -0
  396. package/dist/core/services/mcp-handlers/decisions.d.ts.map +1 -0
  397. package/dist/core/services/mcp-handlers/decisions.js +239 -0
  398. package/dist/core/services/mcp-handlers/decisions.js.map +1 -0
  399. package/dist/core/services/mcp-handlers/graph.d.ts +94 -0
  400. package/dist/core/services/mcp-handlers/graph.d.ts.map +1 -0
  401. package/dist/core/services/mcp-handlers/graph.js +693 -0
  402. package/dist/core/services/mcp-handlers/graph.js.map +1 -0
  403. package/dist/core/services/mcp-handlers/orient.d.ts +17 -0
  404. package/dist/core/services/mcp-handlers/orient.d.ts.map +1 -0
  405. package/dist/core/services/mcp-handlers/orient.js +357 -0
  406. package/dist/core/services/mcp-handlers/orient.js.map +1 -0
  407. package/dist/core/services/mcp-handlers/semantic.d.ts +66 -0
  408. package/dist/core/services/mcp-handlers/semantic.d.ts.map +1 -0
  409. package/dist/core/services/mcp-handlers/semantic.js +432 -0
  410. package/dist/core/services/mcp-handlers/semantic.js.map +1 -0
  411. package/dist/core/services/mcp-handlers/utils.d.ts +85 -0
  412. package/dist/core/services/mcp-handlers/utils.d.ts.map +1 -0
  413. package/dist/core/services/mcp-handlers/utils.js +262 -0
  414. package/dist/core/services/mcp-handlers/utils.js.map +1 -0
  415. package/dist/core/services/mcp-watcher.d.ts +41 -0
  416. package/dist/core/services/mcp-watcher.d.ts.map +1 -0
  417. package/dist/core/services/mcp-watcher.js +254 -0
  418. package/dist/core/services/mcp-watcher.js.map +1 -0
  419. package/dist/core/services/project-detector.d.ts +32 -0
  420. package/dist/core/services/project-detector.d.ts.map +1 -0
  421. package/dist/core/services/project-detector.js +100 -0
  422. package/dist/core/services/project-detector.js.map +1 -0
  423. package/dist/core/test-generator/coverage-analyzer.d.ts +27 -0
  424. package/dist/core/test-generator/coverage-analyzer.d.ts.map +1 -0
  425. package/dist/core/test-generator/coverage-analyzer.js +285 -0
  426. package/dist/core/test-generator/coverage-analyzer.js.map +1 -0
  427. package/dist/core/test-generator/framework-detector.d.ts +17 -0
  428. package/dist/core/test-generator/framework-detector.d.ts.map +1 -0
  429. package/dist/core/test-generator/framework-detector.js +65 -0
  430. package/dist/core/test-generator/framework-detector.js.map +1 -0
  431. package/dist/core/test-generator/index.d.ts +14 -0
  432. package/dist/core/test-generator/index.d.ts.map +1 -0
  433. package/dist/core/test-generator/index.js +11 -0
  434. package/dist/core/test-generator/index.js.map +1 -0
  435. package/dist/core/test-generator/renderers/catch2.d.ts +8 -0
  436. package/dist/core/test-generator/renderers/catch2.d.ts.map +1 -0
  437. package/dist/core/test-generator/renderers/catch2.js +47 -0
  438. package/dist/core/test-generator/renderers/catch2.js.map +1 -0
  439. package/dist/core/test-generator/renderers/gtest.d.ts +8 -0
  440. package/dist/core/test-generator/renderers/gtest.d.ts.map +1 -0
  441. package/dist/core/test-generator/renderers/gtest.js +45 -0
  442. package/dist/core/test-generator/renderers/gtest.js.map +1 -0
  443. package/dist/core/test-generator/renderers/index.d.ts +20 -0
  444. package/dist/core/test-generator/renderers/index.d.ts.map +1 -0
  445. package/dist/core/test-generator/renderers/index.js +35 -0
  446. package/dist/core/test-generator/renderers/index.js.map +1 -0
  447. package/dist/core/test-generator/renderers/playwright.d.ts +8 -0
  448. package/dist/core/test-generator/renderers/playwright.d.ts.map +1 -0
  449. package/dist/core/test-generator/renderers/playwright.js +44 -0
  450. package/dist/core/test-generator/renderers/playwright.js.map +1 -0
  451. package/dist/core/test-generator/renderers/pytest.d.ts +8 -0
  452. package/dist/core/test-generator/renderers/pytest.d.ts.map +1 -0
  453. package/dist/core/test-generator/renderers/pytest.js +44 -0
  454. package/dist/core/test-generator/renderers/pytest.js.map +1 -0
  455. package/dist/core/test-generator/renderers/shared.d.ts +21 -0
  456. package/dist/core/test-generator/renderers/shared.d.ts.map +1 -0
  457. package/dist/core/test-generator/renderers/shared.js +56 -0
  458. package/dist/core/test-generator/renderers/shared.js.map +1 -0
  459. package/dist/core/test-generator/renderers/vitest.d.ts +8 -0
  460. package/dist/core/test-generator/renderers/vitest.d.ts.map +1 -0
  461. package/dist/core/test-generator/renderers/vitest.js +52 -0
  462. package/dist/core/test-generator/renderers/vitest.js.map +1 -0
  463. package/dist/core/test-generator/scenario-parser.d.ts +33 -0
  464. package/dist/core/test-generator/scenario-parser.d.ts.map +1 -0
  465. package/dist/core/test-generator/scenario-parser.js +244 -0
  466. package/dist/core/test-generator/scenario-parser.js.map +1 -0
  467. package/dist/core/test-generator/test-generator.d.ts +30 -0
  468. package/dist/core/test-generator/test-generator.d.ts.map +1 -0
  469. package/dist/core/test-generator/test-generator.js +174 -0
  470. package/dist/core/test-generator/test-generator.js.map +1 -0
  471. package/dist/core/test-generator/test-writer.d.ts +25 -0
  472. package/dist/core/test-generator/test-writer.d.ts.map +1 -0
  473. package/dist/core/test-generator/test-writer.js +128 -0
  474. package/dist/core/test-generator/test-writer.js.map +1 -0
  475. package/dist/core/test-generator/then-matchers.d.ts +35 -0
  476. package/dist/core/test-generator/then-matchers.d.ts.map +1 -0
  477. package/dist/core/test-generator/then-matchers.js +211 -0
  478. package/dist/core/test-generator/then-matchers.js.map +1 -0
  479. package/dist/core/verifier/index.d.ts +5 -0
  480. package/dist/core/verifier/index.d.ts.map +1 -0
  481. package/dist/core/verifier/index.js +5 -0
  482. package/dist/core/verifier/index.js.map +1 -0
  483. package/dist/core/verifier/verification-engine.d.ts +293 -0
  484. package/dist/core/verifier/verification-engine.d.ts.map +1 -0
  485. package/dist/core/verifier/verification-engine.js +919 -0
  486. package/dist/core/verifier/verification-engine.js.map +1 -0
  487. package/dist/types/index.d.ts +368 -0
  488. package/dist/types/index.d.ts.map +1 -0
  489. package/dist/types/index.js +5 -0
  490. package/dist/types/index.js.map +1 -0
  491. package/dist/types/pipeline.d.ts +167 -0
  492. package/dist/types/pipeline.d.ts.map +1 -0
  493. package/dist/types/pipeline.js +5 -0
  494. package/dist/types/pipeline.js.map +1 -0
  495. package/dist/types/test-generator.d.ts +103 -0
  496. package/dist/types/test-generator.d.ts.map +1 -0
  497. package/dist/types/test-generator.js +17 -0
  498. package/dist/types/test-generator.js.map +1 -0
  499. package/dist/utils/command-helpers.d.ts +68 -0
  500. package/dist/utils/command-helpers.d.ts.map +1 -0
  501. package/dist/utils/command-helpers.js +150 -0
  502. package/dist/utils/command-helpers.js.map +1 -0
  503. package/dist/utils/errors.d.ts +51 -0
  504. package/dist/utils/errors.d.ts.map +1 -0
  505. package/dist/utils/errors.js +129 -0
  506. package/dist/utils/errors.js.map +1 -0
  507. package/dist/utils/logger.d.ts +149 -0
  508. package/dist/utils/logger.d.ts.map +1 -0
  509. package/dist/utils/logger.js +342 -0
  510. package/dist/utils/logger.js.map +1 -0
  511. package/dist/utils/misc.d.ts +10 -0
  512. package/dist/utils/misc.d.ts.map +1 -0
  513. package/dist/utils/misc.js +21 -0
  514. package/dist/utils/misc.js.map +1 -0
  515. package/dist/utils/progress.d.ts +142 -0
  516. package/dist/utils/progress.d.ts.map +1 -0
  517. package/dist/utils/progress.js +283 -0
  518. package/dist/utils/progress.js.map +1 -0
  519. package/dist/utils/prompts.d.ts +53 -0
  520. package/dist/utils/prompts.d.ts.map +1 -0
  521. package/dist/utils/prompts.js +199 -0
  522. package/dist/utils/prompts.js.map +1 -0
  523. package/dist/utils/shutdown.d.ts +89 -0
  524. package/dist/utils/shutdown.d.ts.map +1 -0
  525. package/dist/utils/shutdown.js +238 -0
  526. package/dist/utils/shutdown.js.map +1 -0
  527. package/examples/bmad/README.md +113 -0
  528. package/examples/bmad/agents/architect.md +226 -0
  529. package/examples/bmad/agents/dev-brownfield.md +69 -0
  530. package/examples/bmad/setup/architect.customize.yaml +14 -0
  531. package/examples/bmad/tasks/implement-story.md +254 -0
  532. package/examples/bmad/tasks/onboarding.md +169 -0
  533. package/examples/bmad/tasks/refactor.md +178 -0
  534. package/examples/bmad/tasks/sprint-planning.md +168 -0
  535. package/examples/bmad/templates/story.md +108 -0
  536. package/examples/cline-workflows/openlore-analyze-codebase.md +101 -0
  537. package/examples/cline-workflows/openlore-check-spec-drift.md +102 -0
  538. package/examples/cline-workflows/openlore-execute-refactor.md +212 -0
  539. package/examples/cline-workflows/openlore-implement-feature.md +266 -0
  540. package/examples/cline-workflows/openlore-plan-refactor.md +279 -0
  541. package/examples/cline-workflows/openlore-refactor-codebase.md +16 -0
  542. package/examples/cline-workflows/openlore-write-tests.md +177 -0
  543. package/examples/drift-demo/openspec/config.yaml +14 -0
  544. package/examples/drift-demo/openspec/specs/architecture/spec.md +30 -0
  545. package/examples/drift-demo/openspec/specs/auth/spec.md +71 -0
  546. package/examples/drift-demo/openspec/specs/database/spec.md +33 -0
  547. package/examples/drift-demo/openspec/specs/overview/spec.md +20 -0
  548. package/examples/drift-demo/openspec/specs/projects/spec.md +55 -0
  549. package/examples/drift-demo/openspec/specs/tasks/spec.md +78 -0
  550. package/examples/drift-demo/package.json +21 -0
  551. package/examples/drift-demo/src/auth/auth-middleware.ts +30 -0
  552. package/examples/drift-demo/src/auth/auth-routes.ts +29 -0
  553. package/examples/drift-demo/src/auth/auth-service.ts +45 -0
  554. package/examples/drift-demo/src/database/connection.ts +27 -0
  555. package/examples/drift-demo/src/index.ts +16 -0
  556. package/examples/drift-demo/src/projects/project-model.ts +15 -0
  557. package/examples/drift-demo/src/projects/project-service.ts +34 -0
  558. package/examples/drift-demo/src/tasks/task-model.ts +37 -0
  559. package/examples/drift-demo/src/tasks/task-routes.ts +53 -0
  560. package/examples/drift-demo/src/tasks/task-service.ts +60 -0
  561. package/examples/drift-demo/src/utils/validation.ts +11 -0
  562. package/examples/drift-demo/tests/auth.test.ts +4 -0
  563. package/examples/drift-demo/tests/tasks.test.ts +4 -0
  564. package/examples/drift-demo/tsconfig.json +10 -0
  565. package/examples/drift-test/run-drift-test.sh +1087 -0
  566. package/examples/gsd/README.md +119 -0
  567. package/examples/gsd/commands/gsd/openlore-drift.md +111 -0
  568. package/examples/gsd/commands/gsd/openlore-orient.md +191 -0
  569. package/examples/mistral-vibe/README.md +101 -0
  570. package/examples/mistral-vibe/antipatterns-template.md +18 -0
  571. package/examples/mistral-vibe/skills/openlore-analyze-codebase/SKILL.md +124 -0
  572. package/examples/mistral-vibe/skills/openlore-brainstorm/SKILL.md +379 -0
  573. package/examples/mistral-vibe/skills/openlore-debug/SKILL.md +330 -0
  574. package/examples/mistral-vibe/skills/openlore-execute-refactor/SKILL.md +291 -0
  575. package/examples/mistral-vibe/skills/openlore-generate/SKILL.md +245 -0
  576. package/examples/mistral-vibe/skills/openlore-implement-story/SKILL.md +326 -0
  577. package/examples/mistral-vibe/skills/openlore-plan-refactor/SKILL.md +365 -0
  578. package/examples/mistral-vibe/skills/openlore-review-changes/SKILL.md +128 -0
  579. package/examples/mistral-vibe/skills/openlore-write-tests/SKILL.md +261 -0
  580. package/examples/opencode/agent-guard.ts +170 -0
  581. package/examples/opencode/plugins/anti-laziness.ts +202 -0
  582. package/examples/opencode/plugins/lib/openlore-context-injector-helpers.ts +116 -0
  583. package/examples/opencode/plugins/lib/openlore-decision-extractor-helpers.ts +65 -0
  584. package/examples/opencode/plugins/openlore-context-injector.test.ts +211 -0
  585. package/examples/opencode/plugins/openlore-context-injector.ts +165 -0
  586. package/examples/opencode/plugins/openlore-decision-extractor.test.ts +131 -0
  587. package/examples/opencode/plugins/openlore-decision-extractor.ts +322 -0
  588. package/examples/opencode/plugins/openlore-enforcer.ts +227 -0
  589. package/examples/opencode/prompts/sisyphus-sdd.md +150 -0
  590. package/examples/opencode-skills/openlore-analyze-codebase/SKILL.md +101 -0
  591. package/examples/opencode-skills/openlore-brainstorm/SKILL.md +354 -0
  592. package/examples/opencode-skills/openlore-debug/SKILL.md +291 -0
  593. package/examples/opencode-skills/openlore-execute-refactor/SKILL.md +241 -0
  594. package/examples/opencode-skills/openlore-generate/SKILL.md +236 -0
  595. package/examples/opencode-skills/openlore-implement-story/SKILL.md +251 -0
  596. package/examples/opencode-skills/openlore-plan-refactor/SKILL.md +298 -0
  597. package/examples/opencode-skills/openlore-review-changes/SKILL.md +134 -0
  598. package/examples/opencode-skills/openlore-write-tests/SKILL.md +230 -0
  599. package/examples/openspec-analysis/README.md +59 -0
  600. package/examples/openspec-analysis/SUMMARY.md +72 -0
  601. package/examples/openspec-analysis/config.json +16 -0
  602. package/examples/openspec-analysis/dependencies.mermaid +35 -0
  603. package/examples/openspec-analysis/dependency-graph.json +12116 -0
  604. package/examples/openspec-analysis/llm-context.json +119 -0
  605. package/examples/openspec-analysis/repo-structure.json +871 -0
  606. package/examples/openspec-cli/README.md +67 -0
  607. package/examples/openspec-cli/openspec/config.yaml +26 -0
  608. package/examples/openspec-cli/openspec/specs/architecture/spec.md +178 -0
  609. package/examples/openspec-cli/openspec/specs/artifact-graph/spec.md +143 -0
  610. package/examples/openspec-cli/openspec/specs/cli/spec.md +138 -0
  611. package/examples/openspec-cli/openspec/specs/overview/spec.md +60 -0
  612. package/examples/openspec-cli/openspec/specs/parsing/spec.md +123 -0
  613. package/examples/openspec-cli/openspec/specs/validation/spec.md +108 -0
  614. package/examples/spec-kit/README.md +104 -0
  615. package/examples/spec-kit/commands/drift.md +87 -0
  616. package/examples/spec-kit/commands/orient.md +138 -0
  617. package/examples/spec-kit/extension.yml +54 -0
  618. package/package.json +125 -0
  619. package/src/viewer/InteractiveGraphViewer.jsx +1600 -0
  620. package/src/viewer/app/index.html +17 -0
  621. package/src/viewer/app/main.jsx +13 -0
  622. package/src/viewer/components/ArchitectureView.jsx +177 -0
  623. package/src/viewer/components/ChatPanel.jsx +450 -0
  624. package/src/viewer/components/ClassGraph.jsx +782 -0
  625. package/src/viewer/components/ClusterGraph.jsx +469 -0
  626. package/src/viewer/components/FilterBar.jsx +179 -0
  627. package/src/viewer/components/FlatGraph.jsx +282 -0
  628. package/src/viewer/components/MicroComponents.jsx +85 -0
  629. package/src/viewer/hooks/usePanZoom.js +79 -0
  630. package/src/viewer/utils/constants.js +64 -0
  631. package/src/viewer/utils/graph-helpers.js +303 -0
  632. package/src/viewer/utils/graph-helpers.test.ts +39 -0
  633. package/src/viewer/utils/themes.js +206 -0
  634. package/stubs/tree-sitter-cli-stub/package.json +6 -0
@@ -0,0 +1,699 @@
1
+ /**
2
+ * Spec Generation Pipeline
3
+ *
4
+ * Orchestrates the multi-step LLM process to generate accurate specifications
5
+ * in OpenSpec format from code analysis.
6
+ */
7
+ import { readFile, writeFile, mkdir, stat } from 'node:fs/promises';
8
+ import { join, resolve } from 'node:path';
9
+ import logger from '../../utils/logger.js';
10
+ import { SKELETON_EXCERPT_MAX_CHARS, SKELETON_STANDALONE_MAX_CHARS, STAGE_CHUNK_MAX_CHARS } from '../../constants.js';
11
+ import { buildGraphPromptSection, getFileGodFunctions, extractSubgraph } from '../analyzer/subgraph-extractor.js';
12
+ import { getSkeletonContent, detectLanguage, isSkeletonWorthIncluding } from '../analyzer/code-shaper.js';
13
+ import { isTestFile } from '../analyzer/artifact-generator.js';
14
+ import { runStage1 } from './stages/stage1-survey.js';
15
+ import { runStage2 } from './stages/stage2-entities.js';
16
+ import { runStage3 } from './stages/stage3-services.js';
17
+ import { runStage4 } from './stages/stage4-api.js';
18
+ import { runStage5 } from './stages/stage5-architecture.js';
19
+ import { runStage6 } from './stages/stage6-adr.js';
20
+ import { PROMPTS } from './prompts.js';
21
+ import { SUBSPEC_SCHEMA } from './schemas.js';
22
+ // ============================================================================
23
+ // SPEC GENERATION PIPELINE
24
+ // ============================================================================
25
+ /**
26
+ * Spec Generation Pipeline
27
+ */
28
+ export class SpecGenerationPipeline {
29
+ llm;
30
+ options;
31
+ progress;
32
+ semanticSearch;
33
+ /** Set at the start of run() and used by stage methods for graph-based prompts */
34
+ currentLLMContext;
35
+ /** Set at the start of run() and used by schemasFor() / routesFor() */
36
+ currentRepoStructure;
37
+ constructor(llm, options) {
38
+ this.llm = llm;
39
+ this.progress = options.progress;
40
+ this.semanticSearch = options.semanticSearch;
41
+ this.options = {
42
+ outputDir: options.outputDir,
43
+ skipStages: options.skipStages ?? [],
44
+ resumeFrom: options.resumeFrom ?? '',
45
+ force: options.force ?? false,
46
+ maxRetries: options.maxRetries ?? 2,
47
+ rootPath: options.rootPath ?? '',
48
+ saveIntermediate: options.saveIntermediate ?? true,
49
+ generateADRs: options.generateADRs ?? false,
50
+ chunkMaxChars: options.chunkMaxChars ?? STAGE_CHUNK_MAX_CHARS,
51
+ };
52
+ }
53
+ /**
54
+ * Run the complete pipeline
55
+ */
56
+ async run(repoStructure, llmContext, depGraph, refactorReport) {
57
+ this.currentLLMContext = llmContext;
58
+ this.currentRepoStructure = repoStructure;
59
+ const startTime = Date.now();
60
+ let totalTokens = 0;
61
+ const completedStages = [];
62
+ const skippedStages = [];
63
+ // Ensure output directory exists
64
+ if (this.options.saveIntermediate) {
65
+ await mkdir(this.options.outputDir, { recursive: true });
66
+ }
67
+ const totalStages = this.options.generateADRs ? 6 : 5;
68
+ let stageNum = 0;
69
+ const startStage = (name, label) => {
70
+ stageNum++;
71
+ if (this.progress) {
72
+ this.progress.updateGeneration({ stage: stageNum, totalStages, stageName: label });
73
+ }
74
+ else {
75
+ logger.analysis(`Running Stage ${stageNum}: ${label}`);
76
+ }
77
+ };
78
+ // Helper to execute a pipeline stage with consistent error handling
79
+ const executeStage = async (name, label, runner, fallback, normalize, onSuccess) => {
80
+ if (!this.shouldRunStage(name)) {
81
+ skippedStages.push(name);
82
+ const saved = await this.loadStageResult(name);
83
+ if (saved?.success && saved.data) {
84
+ logger.analysis(`Resume: loaded ${name} from disk`);
85
+ let data = saved.data;
86
+ if (normalize)
87
+ data = normalize(data);
88
+ if (onSuccess)
89
+ onSuccess(data);
90
+ return data;
91
+ }
92
+ return fallback();
93
+ }
94
+ // Auto-resume: if a cached result exists on disk and --force is not set, skip the LLM call
95
+ if (!this.options.force) {
96
+ const cached = await this.loadStageResult(name);
97
+ if (cached?.success && cached.data) {
98
+ logger.analysis(`Auto-resume: ${name} already complete, loading from disk`);
99
+ skippedStages.push(name);
100
+ let data = cached.data;
101
+ if (normalize)
102
+ data = normalize(data);
103
+ if (onSuccess)
104
+ onSuccess(data);
105
+ return data;
106
+ }
107
+ }
108
+ startStage(name, label);
109
+ const result = await runner();
110
+ if (result.success && result.data) {
111
+ let data = result.data;
112
+ if (normalize)
113
+ data = normalize(data);
114
+ totalTokens += result.tokens;
115
+ completedStages.push(name);
116
+ if (onSuccess)
117
+ onSuccess(data);
118
+ return data;
119
+ }
120
+ else {
121
+ const errorMsg = result.error ?? 'Unknown error';
122
+ this.progress?.stop();
123
+ logger.warning(`${label} failed: ${errorMsg}`);
124
+ if (name === 'survey' && /Unauthorized|401|403/i.test(errorMsg)) {
125
+ throw new Error(`API authentication failed: ${errorMsg}. Check your API key`);
126
+ }
127
+ return await fallback();
128
+ }
129
+ };
130
+ // Stage 1: Project Survey
131
+ const survey = await executeStage('survey', 'Project Survey', async () => runStage1(this.llm, this.options, this.saveResult.bind(this), repoStructure, llmContext), () => this.getDefaultSurvey(repoStructure), data => ({
132
+ ...data,
133
+ frameworks: data.frameworks ?? [],
134
+ suggestedDomains: data.suggestedDomains ?? [],
135
+ schemaFiles: data.schemaFiles ?? [],
136
+ serviceFiles: data.serviceFiles ?? [],
137
+ apiFiles: data.apiFiles ?? [],
138
+ }));
139
+ // Stage 2: Entity Extraction
140
+ let entities = [];
141
+ const schemaFiles = await this.resolveFiles(llmContext, survey.schemaFiles ?? [], await this.getSchemaFiles(llmContext));
142
+ if (schemaFiles.length > 0) {
143
+ entities = await executeStage('entities', 'Entity Extraction', async () => runStage2(this, survey, schemaFiles, (i, total, file) => {
144
+ this.progress?.updateGeneration({ stage: stageNum, totalStages, stageName: `Entity Extraction ${i}/${total}: ${file}` });
145
+ }), () => []);
146
+ }
147
+ else {
148
+ logger.warning('No schema files found, skipping entity extraction');
149
+ skippedStages.push('entities');
150
+ }
151
+ // Stage 3: Service Analysis
152
+ let services = [];
153
+ const serviceFiles = await this.resolveFiles(llmContext, survey.serviceFiles ?? [], await this.getServiceFiles(llmContext));
154
+ if (serviceFiles.length > 0) {
155
+ services = await executeStage('services', 'Service Analysis', async () => runStage3(this, survey, entities, serviceFiles, (i, total, file) => {
156
+ this.progress?.updateGeneration({ stage: stageNum, totalStages, stageName: `Service Analysis ${i}/${total}: ${file}` });
157
+ }), () => []);
158
+ }
159
+ else {
160
+ logger.warning('No service files found, skipping service analysis');
161
+ skippedStages.push('services');
162
+ }
163
+ // Stage 4: API Extraction
164
+ let endpoints = [];
165
+ const apiFiles = await this.resolveFiles(llmContext, survey.apiFiles ?? [], await this.getApiFiles(llmContext));
166
+ if (apiFiles.length > 0) {
167
+ endpoints = await executeStage('api', 'API Extraction', async () => runStage4(this, apiFiles, (i, total, file) => {
168
+ this.progress?.updateGeneration({ stage: stageNum, totalStages, stageName: `API Extraction ${i}/${total}: ${file}` });
169
+ }), () => []);
170
+ }
171
+ else {
172
+ logger.warning('No API files found, skipping API extraction');
173
+ skippedStages.push('api');
174
+ }
175
+ // Stage 5: Architecture Synthesis
176
+ const architecture = await executeStage('architecture', 'Architecture Synthesis', async () => runStage5(this, survey, entities, services, endpoints, depGraph, llmContext.callGraph, refactorReport), () => this.getDefaultArchitecture(survey), data => ({
177
+ ...data,
178
+ layerMap: data.layerMap ?? [],
179
+ integrations: data.integrations ?? [],
180
+ keyDecisions: data.keyDecisions ?? [],
181
+ }));
182
+ // Stage 6: ADR Enrichment (optional)
183
+ let adrs = [];
184
+ if (this.options.generateADRs && this.shouldRunStage('adr')) {
185
+ if (architecture.keyDecisions.length > 0) {
186
+ adrs = await executeStage('adr', 'ADR Enrichment', async () => runStage6(this, architecture), () => []);
187
+ }
188
+ else {
189
+ logger.warning('No key decisions found, skipping ADR enrichment');
190
+ skippedStages.push('adr');
191
+ }
192
+ }
193
+ const duration = Date.now() - startTime;
194
+ const costTracking = this.llm.getCostTracking();
195
+ const pipelineResult = {
196
+ survey,
197
+ entities,
198
+ services,
199
+ endpoints,
200
+ architecture,
201
+ adrs: adrs.length > 0 ? adrs : undefined,
202
+ metadata: {
203
+ totalTokens,
204
+ estimatedCost: costTracking.estimatedCost,
205
+ duration,
206
+ completedStages,
207
+ skippedStages,
208
+ },
209
+ };
210
+ // Save final result
211
+ if (this.options.saveIntermediate) {
212
+ await this.saveResult('pipeline-result', pipelineResult);
213
+ }
214
+ logger.success(`Pipeline completed in ${(duration / 1000).toFixed(1)}s, ${totalTokens} tokens used`);
215
+ return pipelineResult;
216
+ }
217
+ /**
218
+ * Check if a stage should run
219
+ */
220
+ shouldRunStage(stage) {
221
+ if (this.options.skipStages.includes(stage)) {
222
+ return false;
223
+ }
224
+ if (this.options.resumeFrom) {
225
+ const stages = ['survey', 'entities', 'services', 'api', 'architecture', 'adr'];
226
+ const resumeIndex = stages.indexOf(this.options.resumeFrom);
227
+ const currentIndex = stages.indexOf(stage);
228
+ return currentIndex >= resumeIndex;
229
+ }
230
+ return true;
231
+ }
232
+ /**
233
+ * Split file content into chunks, breaking only on blank lines (function/class boundaries).
234
+ * A chunk is emitted when its size exceeds maxChars and a blank line is encountered.
235
+ * overlapLines trailing lines from the previous chunk are prepended to the next one,
236
+ * preserving context (e.g. class declaration visible when processing its methods).
237
+ */
238
+ chunkContent(content, maxChars, overlapLines = 10) {
239
+ if (content.length <= maxChars)
240
+ return [content];
241
+ const lines = content.split('\n');
242
+ const chunks = [];
243
+ let currentLines = [];
244
+ let currentSize = 0;
245
+ for (const line of lines) {
246
+ currentLines.push(line);
247
+ currentSize += line.length + 1;
248
+ // Break only at blank lines once the threshold is reached
249
+ if (currentSize >= maxChars && line.trim() === '') {
250
+ const chunk = currentLines.join('\n').trim();
251
+ if (chunk.length > 0)
252
+ chunks.push(chunk);
253
+ // Carry over the last N lines as overlap for the next chunk
254
+ const overlap = currentLines.slice(-overlapLines);
255
+ currentLines = [...overlap];
256
+ currentSize = overlap.reduce((s, l) => s + l.length + 1, 0);
257
+ }
258
+ }
259
+ const remaining = currentLines.join('\n').trim();
260
+ if (remaining.length > 0)
261
+ chunks.push(remaining);
262
+ return chunks;
263
+ }
264
+ /**
265
+ * For a large file, try to build a graph-based prompt section.
266
+ * Returns null when the file is small enough for raw chunking and has no graph data.
267
+ *
268
+ * Priority:
269
+ * 1. Graph section (god functions) + optional skeleton supplement — richest representation
270
+ * 2. Standalone skeleton for large files without god functions — avoids [PARTIAL SPEC]
271
+ * 3. null → caller falls back to raw AST chunking
272
+ *
273
+ * The skeleton fallback fires when content would be split (> STAGE_CHUNK_MAX_CHARS) and
274
+ * the skeleton achieves ≥ 20% size reduction AND fits within SKELETON_STANDALONE_MAX_CHARS.
275
+ */
276
+ graphPromptFor(filePath, content) {
277
+ const ctx = this.currentLLMContext;
278
+ // ── Path 1: graph section exists (file has god functions) ──────────────
279
+ if (ctx?.callGraph) {
280
+ const graphSection = buildGraphPromptSection(ctx.callGraph, ctx.signatures, filePath);
281
+ if (graphSection) {
282
+ if (!content)
283
+ return graphSection;
284
+ const language = detectLanguage(filePath);
285
+ const skeleton = getSkeletonContent(content, language);
286
+ if (isSkeletonWorthIncluding(content, skeleton)) {
287
+ // Cap skeleton to avoid overwhelming the prompt
288
+ const skeletonExcerpt = skeleton.length > SKELETON_EXCERPT_MAX_CHARS
289
+ ? skeleton.slice(0, SKELETON_EXCERPT_MAX_CHARS) + '\n... [skeleton truncated]'
290
+ : skeleton;
291
+ return `${graphSection}\n\nFunction skeleton (logs/comments stripped):\n${skeletonExcerpt}`;
292
+ }
293
+ return graphSection;
294
+ }
295
+ }
296
+ // ── Path 2: skeleton fallback for large files without god functions ─────
297
+ // Avoids splitting files into multiple chunks (and the resulting [PARTIAL SPEC] marker)
298
+ // when the skeleton alone is a complete, noise-free representation.
299
+ if (content && content.length > this.options.chunkMaxChars) {
300
+ const language = detectLanguage(filePath);
301
+ const skeleton = getSkeletonContent(content, language);
302
+ if (isSkeletonWorthIncluding(content, skeleton) && skeleton.length <= SKELETON_STANDALONE_MAX_CHARS) {
303
+ return `Function skeleton (logs/comments stripped):\n${skeleton}`;
304
+ }
305
+ }
306
+ return null;
307
+ }
308
+ signaturesFor(filePath) {
309
+ const sigs = this.currentLLMContext?.signatures;
310
+ if (!sigs)
311
+ return null;
312
+ const fileMap = sigs.find(s => s.path === filePath);
313
+ if (!fileMap || fileMap.entries.length === 0)
314
+ return null;
315
+ return fileMap.entries
316
+ .map(e => `- ${e.signature}${e.docstring ? ` — ${e.docstring}` : ''}`)
317
+ .join('\n');
318
+ }
319
+ schemasFor(filePath) {
320
+ const schemas = this.currentRepoStructure?.schemas;
321
+ if (!schemas || schemas.length === 0)
322
+ return null;
323
+ const fileSchemas = schemas.filter(s => s.file === filePath);
324
+ if (fileSchemas.length === 0)
325
+ return null;
326
+ return fileSchemas.map(s => {
327
+ const fields = s.fields
328
+ .map(f => `${f.name} (${f.type}${f.nullable ? '' : ', required'})`)
329
+ .join(', ');
330
+ return `- ${s.name} [${s.orm}]: ${fields}`;
331
+ }).join('\n');
332
+ }
333
+ routesFor(filePath) {
334
+ const routes = this.currentRepoStructure?.routeInventory?.routes;
335
+ if (!routes || routes.length === 0)
336
+ return null;
337
+ const fileRoutes = routes.filter(r => r.file === filePath);
338
+ if (fileRoutes.length === 0)
339
+ return null;
340
+ return fileRoutes.map(r => `- ${r.method} ${r.path}${r.handler ? ` → ${r.handler}` : ''}`).join('\n');
341
+ }
342
+ /**
343
+ * Generate sub-specifications for the direct callees of god functions in a file.
344
+ * Makes a single batched LLM call covering all callees at once.
345
+ * Returns [] when no graph data or no god functions are found.
346
+ */
347
+ async generateSubSpecs(filePath, parentName, parentPurpose) {
348
+ const callGraph = this.currentLLMContext?.callGraph;
349
+ if (!callGraph)
350
+ return [];
351
+ const godFunctions = getFileGodFunctions(callGraph, filePath);
352
+ if (godFunctions.length === 0)
353
+ return [];
354
+ // Collect unique direct callees across all god functions in this file
355
+ const seenCallees = new Set();
356
+ const calleeInfos = [];
357
+ for (const godFn of godFunctions) {
358
+ const sub = extractSubgraph(callGraph, godFn);
359
+ const directCallees = [...new Set(sub.edges.filter(([from]) => from === godFn.name).map(([, to]) => to))];
360
+ for (const calleeName of directCallees) {
361
+ if (seenCallees.has(calleeName))
362
+ continue;
363
+ seenCallees.add(calleeName);
364
+ const sigEntry = this.currentLLMContext?.signatures
365
+ ?.flatMap(s => s.entries)
366
+ .find(e => e.name === calleeName);
367
+ const subcallees = [...new Set(sub.edges.filter(([from]) => from === calleeName).map(([, to]) => to))];
368
+ calleeInfos.push({
369
+ name: calleeName,
370
+ signature: sigEntry?.signature,
371
+ docstring: sigEntry?.docstring,
372
+ subcallees,
373
+ });
374
+ }
375
+ }
376
+ if (calleeInfos.length === 0)
377
+ return [];
378
+ try {
379
+ const result = await this.llm.completeJSON({
380
+ systemPrompt: PROMPTS.stage3_subspec_system,
381
+ userPrompt: PROMPTS.stage3_subspec(parentName, parentPurpose, calleeInfos),
382
+ temperature: 0.3,
383
+ maxTokens: 4000,
384
+ }, SUBSPEC_SCHEMA);
385
+ if (Array.isArray(result)) {
386
+ // Ensure callee field is set — LLM sometimes names it differently
387
+ for (const sub of result) {
388
+ if (!sub.callee) {
389
+ const matched = calleeInfos.find(c => c.name === sub.name ||
390
+ c.name.toLowerCase().includes((sub.name ?? '').toLowerCase()));
391
+ sub.callee = matched?.name ?? sub.name;
392
+ }
393
+ sub.operations = sub.operations ?? [];
394
+ }
395
+ return result;
396
+ }
397
+ }
398
+ catch (error) {
399
+ logger.warning(`Sub-specs: failed for ${parentName}: ${error.message}`);
400
+ }
401
+ return [];
402
+ }
403
+ /**
404
+ * Generation retrieval strategy: semantic-first → depth-N graph expansion.
405
+ *
406
+ * 1. Semantic search identifies seed files relevant to the query.
407
+ * 2. BFS graph expansion up to `depth` hops adds callee files so indirect
408
+ * implementations are not missed. Score decays by λ^hop (λ=0.6) — used
409
+ * only for logging; all resolved files are passed to the LLM stage.
410
+ */
411
+ async semanticFiles(query, context, limit = 15, depth = 2) {
412
+ if (!this.semanticSearch)
413
+ return [];
414
+ try {
415
+ const results = await this.semanticSearch(query, limit);
416
+ const seen = new Set();
417
+ const files = [];
418
+ const resolveFile = async (fp) => {
419
+ if (seen.has(fp) || isTestFile(fp))
420
+ return;
421
+ seen.add(fp);
422
+ const deep = context.phase2_deep.files.find(f => f.path === fp);
423
+ if (deep?.content) {
424
+ files.push({ path: fp, content: deep.content });
425
+ }
426
+ else if (this.options.rootPath) {
427
+ try {
428
+ const content = await readFile(resolve(this.options.rootPath, fp), 'utf-8');
429
+ if (content.trim())
430
+ files.push({ path: fp, content });
431
+ }
432
+ catch { /* file not readable, skip */ }
433
+ }
434
+ };
435
+ // Step 1: resolve semantic seed files
436
+ for (const r of results)
437
+ await resolveFile(r.record.filePath);
438
+ const seedCount = files.length;
439
+ // Step 2: depth-N BFS callee expansion (RIG-21)
440
+ const cg = context.callGraph;
441
+ if (cg && seedCount > 0) {
442
+ const calleeMap = new Map();
443
+ for (const e of cg.edges) {
444
+ if (!e.calleeId)
445
+ continue;
446
+ const list = calleeMap.get(e.callerId) ?? [];
447
+ list.push(e.calleeId);
448
+ calleeMap.set(e.callerId, list);
449
+ }
450
+ const nodeFile = new Map(cg.nodes.map(n => [n.id, n.filePath]));
451
+ const seedPaths = new Set(seen);
452
+ let frontier = cg.nodes.filter(n => seedPaths.has(n.filePath)).map(n => n.id);
453
+ for (let hop = 1; hop <= depth && frontier.length > 0; hop++) {
454
+ const beforeHop = files.length;
455
+ const nextFrontier = [];
456
+ for (const nodeId of frontier) {
457
+ for (const calleeId of calleeMap.get(nodeId) ?? []) {
458
+ const calleePath = nodeFile.get(calleeId);
459
+ if (calleePath && !seen.has(calleePath)) {
460
+ await resolveFile(calleePath);
461
+ nextFrontier.push(calleeId);
462
+ }
463
+ }
464
+ }
465
+ const hopAdded = files.length - beforeHop;
466
+ if (hopAdded > 0)
467
+ logger.analysis(`Graph expansion depth ${hop}: +${hopAdded} files`);
468
+ frontier = nextFrontier;
469
+ }
470
+ }
471
+ return files;
472
+ }
473
+ catch (err) {
474
+ logger.warning(`Semantic file selection failed (${query}): ${err.message}`);
475
+ return [];
476
+ }
477
+ }
478
+ /** Name-based heuristic fallback for schema/entity/type files. */
479
+ heuristicSchemaFiles(context) {
480
+ return context.phase2_deep.files
481
+ .filter(f => {
482
+ const name = f.path.toLowerCase();
483
+ return (name.includes('model') ||
484
+ name.includes('schema') ||
485
+ name.includes('entity') ||
486
+ name.includes('types') ||
487
+ name.includes('interface'));
488
+ })
489
+ .map(f => ({ path: f.path, content: f.content ?? '' }))
490
+ .filter(f => f.content.length > 0);
491
+ }
492
+ /** Name-based heuristic fallback for service/business-logic files. */
493
+ heuristicServiceFiles(context) {
494
+ return context.phase2_deep.files
495
+ .filter(f => {
496
+ const name = f.path.toLowerCase();
497
+ return (name.includes('service') ||
498
+ name.includes('manager') ||
499
+ name.includes('handler') ||
500
+ name.includes('controller') ||
501
+ name.includes('use-case') ||
502
+ name.includes('usecase'));
503
+ })
504
+ .map(f => ({ path: f.path, content: f.content ?? '' }))
505
+ .filter(f => f.content.length > 0);
506
+ }
507
+ /** Name-based heuristic fallback for API/route files. */
508
+ heuristicApiFiles(context) {
509
+ return context.phase2_deep.files
510
+ .filter(f => {
511
+ const name = f.path.toLowerCase();
512
+ return (name.includes('route') ||
513
+ name.includes('api') ||
514
+ name.includes('endpoint') ||
515
+ name.includes('controller') ||
516
+ name.includes('rest'));
517
+ })
518
+ .map(f => ({ path: f.path, content: f.content ?? '' }))
519
+ .filter(f => f.content.length > 0);
520
+ }
521
+ /**
522
+ * Get schema files — semantic-first, name-heuristic fallback.
523
+ */
524
+ async getSchemaFiles(context) {
525
+ const semantic = await this.semanticFiles('data model entity schema type interface database structure', context);
526
+ if (semantic.length > 0) {
527
+ logger.analysis(`Schema files: ${semantic.length} via semantic search`);
528
+ return semantic;
529
+ }
530
+ const fallback = this.heuristicSchemaFiles(context);
531
+ if (this.semanticSearch && fallback.length > 0) {
532
+ logger.warning('Schema semantic search returned no results, falling back to name heuristics');
533
+ }
534
+ return fallback;
535
+ }
536
+ /**
537
+ * Get service files — semantic-first, name-heuristic fallback.
538
+ */
539
+ async getServiceFiles(context) {
540
+ const semantic = await this.semanticFiles('service business logic manager handler use case orchestration', context);
541
+ if (semantic.length > 0) {
542
+ logger.analysis(`Service files: ${semantic.length} via semantic search`);
543
+ return semantic;
544
+ }
545
+ const fallback = this.heuristicServiceFiles(context);
546
+ if (this.semanticSearch && fallback.length > 0) {
547
+ logger.warning('Service semantic search returned no results, falling back to name heuristics');
548
+ }
549
+ return fallback;
550
+ }
551
+ /**
552
+ * Get API files — semantic-first, name-heuristic fallback.
553
+ */
554
+ async getApiFiles(context) {
555
+ const semantic = await this.semanticFiles('API route endpoint REST controller HTTP request response', context);
556
+ if (semantic.length > 0) {
557
+ logger.analysis(`API files: ${semantic.length} via semantic search`);
558
+ return semantic;
559
+ }
560
+ const fallback = this.heuristicApiFiles(context);
561
+ if (this.semanticSearch && fallback.length > 0) {
562
+ logger.warning('API semantic search returned no results, falling back to name heuristics');
563
+ }
564
+ return fallback;
565
+ }
566
+ /**
567
+ * Resolve file paths identified by Stage 1 LLM to actual file content.
568
+ * First looks in phase2_deep (already in memory); if not found and rootPath is set,
569
+ * reads the file from disk so that files outside the top-20 scored set can still
570
+ * be analyzed in later stages.
571
+ * Falls back to the provided heuristic list if no paths resolve.
572
+ */
573
+ async resolveFiles(context, llmPaths, fallback) {
574
+ // Guard: never pass test files to the LLM stages regardless of what Stage 1 suggested
575
+ const safePaths = llmPaths.filter(p => !isTestFile(p));
576
+ if (safePaths.length === 0) {
577
+ return fallback.filter(f => !isTestFile(f.path));
578
+ }
579
+ llmPaths = safePaths;
580
+ const allFiles = context.phase2_deep.files;
581
+ const resolved = [];
582
+ for (const p of llmPaths) {
583
+ // 1. Look in phase2_deep (already loaded in memory)
584
+ const found = allFiles.find(f => f.path === p || f.path.endsWith('/' + p) || p.endsWith('/' + f.path));
585
+ if (found?.content) {
586
+ resolved.push({ path: found.path, content: found.content });
587
+ continue;
588
+ }
589
+ // 2. Read from disk when rootPath is configured (covers files outside phase2_deep)
590
+ if (this.options.rootPath) {
591
+ try {
592
+ const absPath = resolve(this.options.rootPath, p);
593
+ // Prevent path traversal outside the project root
594
+ if (!absPath.startsWith(resolve(this.options.rootPath)))
595
+ continue;
596
+ const content = await readFile(absPath, 'utf-8');
597
+ resolved.push({ path: p, content });
598
+ }
599
+ catch {
600
+ // file not found or unreadable — skip
601
+ }
602
+ }
603
+ }
604
+ return resolved.length > 0 ? resolved : fallback;
605
+ }
606
+ /**
607
+ * Get default survey when stage is skipped
608
+ */
609
+ getDefaultSurvey(repoStructure) {
610
+ return {
611
+ projectCategory: 'other',
612
+ primaryLanguage: repoStructure.projectType,
613
+ frameworks: repoStructure.frameworks,
614
+ architecturePattern: repoStructure.architecture.pattern,
615
+ domainSummary: `A ${repoStructure.projectType} project`,
616
+ suggestedDomains: repoStructure.domains.map(d => d.name),
617
+ confidence: 0.5,
618
+ schemaFiles: [],
619
+ serviceFiles: [],
620
+ apiFiles: [],
621
+ };
622
+ }
623
+ /**
624
+ * Get default architecture when stage is skipped
625
+ */
626
+ getDefaultArchitecture(survey) {
627
+ return {
628
+ systemPurpose: survey.domainSummary,
629
+ architectureStyle: survey.architecturePattern,
630
+ layerMap: [],
631
+ dataFlow: 'Unknown',
632
+ integrations: [],
633
+ securityModel: 'Unknown',
634
+ keyDecisions: [],
635
+ };
636
+ }
637
+ /**
638
+ * Save intermediate result
639
+ */
640
+ async saveResult(name, data) {
641
+ const filepath = join(this.options.outputDir, `${name}.json`);
642
+ await writeFile(filepath, JSON.stringify(data, null, 2));
643
+ logger.debug(`Saved ${name} to ${filepath}`);
644
+ }
645
+ /**
646
+ * Map short stage name to the filename used by saveResult.
647
+ */
648
+ stageFileName(stage) {
649
+ const map = {
650
+ survey: 'stage1-survey',
651
+ entities: 'stage2-entities',
652
+ services: 'stage3-services',
653
+ api: 'stage4-api',
654
+ architecture: 'stage5-architecture',
655
+ adr: 'stage6-adr-enrichment',
656
+ };
657
+ return map[stage] ?? `stage-${stage}`;
658
+ }
659
+ /**
660
+ * Load previous stage result (for resume)
661
+ */
662
+ async loadStageResult(stage) {
663
+ try {
664
+ const filepath = join(this.options.outputDir, `${this.stageFileName(stage)}.json`);
665
+ // Invalidate cache if analysis (llm-context.json) is newer than the stage file.
666
+ // This ensures that running `openlore analyze` followed by `openlore generate`
667
+ // always re-runs the pipeline rather than serving stale LLM results.
668
+ if (this.options.rootPath) {
669
+ const analysisFile = join(this.options.rootPath, '.openlore', 'analysis', 'llm-context.json');
670
+ try {
671
+ const [stageStat, analysisStat] = await Promise.all([stat(filepath), stat(analysisFile)]);
672
+ if (analysisStat.mtimeMs > stageStat.mtimeMs) {
673
+ logger.analysis(`Auto-resume: ${stage} cache is older than analysis — will re-run`);
674
+ return null;
675
+ }
676
+ }
677
+ catch {
678
+ // Either file missing — fall through to normal load/null
679
+ }
680
+ }
681
+ const content = await readFile(filepath, 'utf-8');
682
+ return JSON.parse(content);
683
+ }
684
+ catch {
685
+ return null;
686
+ }
687
+ }
688
+ }
689
+ // ============================================================================
690
+ // CONVENIENCE FUNCTIONS
691
+ // ============================================================================
692
+ /**
693
+ * Run the spec generation pipeline
694
+ */
695
+ export async function runSpecGenerationPipeline(llm, repoStructure, llmContext, options, depGraph, refactorReport) {
696
+ const pipeline = new SpecGenerationPipeline(llm, options);
697
+ return pipeline.run(repoStructure, llmContext, depGraph, refactorReport);
698
+ }
699
+ //# sourceMappingURL=spec-pipeline.js.map