@specship/specship 0.11.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 (879) hide show
  1. package/.claude-plugin/plugin.json +6 -0
  2. package/LICENSE +21 -0
  3. package/README.md +583 -0
  4. package/agents/specship-explorer.md +29 -0
  5. package/commands/ss-behaviour.md +116 -0
  6. package/commands/ss-check.md +43 -0
  7. package/commands/ss-design-implement.md +84 -0
  8. package/commands/ss-design-loop.md +125 -0
  9. package/commands/ss-explore.md +43 -0
  10. package/commands/ss-spec.md +118 -0
  11. package/dist/activation/starter-prompt.d.ts +57 -0
  12. package/dist/activation/starter-prompt.d.ts.map +1 -0
  13. package/dist/activation/starter-prompt.js +164 -0
  14. package/dist/activation/starter-prompt.js.map +1 -0
  15. package/dist/analytics/specship-impact.d.ts +72 -0
  16. package/dist/analytics/specship-impact.d.ts.map +1 -0
  17. package/dist/analytics/specship-impact.js +216 -0
  18. package/dist/analytics/specship-impact.js.map +1 -0
  19. package/dist/behaviour/behaviour-surface.d.ts +59 -0
  20. package/dist/behaviour/behaviour-surface.d.ts.map +1 -0
  21. package/dist/behaviour/behaviour-surface.js +112 -0
  22. package/dist/behaviour/behaviour-surface.js.map +1 -0
  23. package/dist/bin/node-version-check.d.ts +37 -0
  24. package/dist/bin/node-version-check.d.ts.map +1 -0
  25. package/dist/bin/node-version-check.js +79 -0
  26. package/dist/bin/node-version-check.js.map +1 -0
  27. package/dist/bin/specship.d.ts +25 -0
  28. package/dist/bin/specship.d.ts.map +1 -0
  29. package/dist/bin/specship.js +2823 -0
  30. package/dist/bin/specship.js.map +1 -0
  31. package/dist/bin/uninstall.d.ts +13 -0
  32. package/dist/bin/uninstall.d.ts.map +1 -0
  33. package/dist/bin/uninstall.js +35 -0
  34. package/dist/bin/uninstall.js.map +1 -0
  35. package/dist/context/formatter.d.ts +30 -0
  36. package/dist/context/formatter.d.ts.map +1 -0
  37. package/dist/context/formatter.js +263 -0
  38. package/dist/context/formatter.js.map +1 -0
  39. package/dist/context/index.d.ts +119 -0
  40. package/dist/context/index.d.ts.map +1 -0
  41. package/dist/context/index.js +1289 -0
  42. package/dist/context/index.js.map +1 -0
  43. package/dist/context/markers.d.ts +19 -0
  44. package/dist/context/markers.d.ts.map +1 -0
  45. package/dist/context/markers.js +22 -0
  46. package/dist/context/markers.js.map +1 -0
  47. package/dist/db/index.d.ts +103 -0
  48. package/dist/db/index.d.ts.map +1 -0
  49. package/dist/db/index.js +279 -0
  50. package/dist/db/index.js.map +1 -0
  51. package/dist/db/migrations.d.ts +44 -0
  52. package/dist/db/migrations.d.ts.map +1 -0
  53. package/dist/db/migrations.js +503 -0
  54. package/dist/db/migrations.js.map +1 -0
  55. package/dist/db/queries.d.ts +357 -0
  56. package/dist/db/queries.d.ts.map +1 -0
  57. package/dist/db/queries.js +1504 -0
  58. package/dist/db/queries.js.map +1 -0
  59. package/dist/db/schema.sql +451 -0
  60. package/dist/db/spec-queries.d.ts +130 -0
  61. package/dist/db/spec-queries.d.ts.map +1 -0
  62. package/dist/db/spec-queries.js +738 -0
  63. package/dist/db/spec-queries.js.map +1 -0
  64. package/dist/db/sqlite-adapter.d.ts +65 -0
  65. package/dist/db/sqlite-adapter.d.ts.map +1 -0
  66. package/dist/db/sqlite-adapter.js +214 -0
  67. package/dist/db/sqlite-adapter.js.map +1 -0
  68. package/dist/designer/artifact-store.js +54 -0
  69. package/dist/designer/browser.js +141 -0
  70. package/dist/designer/cdp-ensure.js +60 -0
  71. package/dist/designer/cdp-env.js +18 -0
  72. package/dist/designer/cdp-trace.js +599 -0
  73. package/dist/designer/cross-platform.js +74 -0
  74. package/dist/designer/designer-controller.js +1413 -0
  75. package/dist/designer/file-panel.js +39 -0
  76. package/dist/designer/interstitials.js +97 -0
  77. package/dist/designer/oopif-reader.js +176 -0
  78. package/dist/designer/package-meta.js +18 -0
  79. package/dist/designer/preview-host.js +50 -0
  80. package/dist/designer/repo-root.js +31 -0
  81. package/dist/designer/run-state.js +353 -0
  82. package/dist/designer/session-store.js +59 -0
  83. package/dist/designer/ui-anchors.js +651 -0
  84. package/dist/directory.d.ts +67 -0
  85. package/dist/directory.d.ts.map +1 -0
  86. package/dist/directory.js +267 -0
  87. package/dist/directory.js.map +1 -0
  88. package/dist/enforce/enforce.d.ts +70 -0
  89. package/dist/enforce/enforce.d.ts.map +1 -0
  90. package/dist/enforce/enforce.js +125 -0
  91. package/dist/enforce/enforce.js.map +1 -0
  92. package/dist/errors.d.ts +136 -0
  93. package/dist/errors.d.ts.map +1 -0
  94. package/dist/errors.js +219 -0
  95. package/dist/errors.js.map +1 -0
  96. package/dist/extraction/dfm-extractor.d.ts +31 -0
  97. package/dist/extraction/dfm-extractor.d.ts.map +1 -0
  98. package/dist/extraction/dfm-extractor.js +151 -0
  99. package/dist/extraction/dfm-extractor.js.map +1 -0
  100. package/dist/extraction/generated-detection.d.ts +30 -0
  101. package/dist/extraction/generated-detection.d.ts.map +1 -0
  102. package/dist/extraction/generated-detection.js +80 -0
  103. package/dist/extraction/generated-detection.js.map +1 -0
  104. package/dist/extraction/grammars.d.ts +100 -0
  105. package/dist/extraction/grammars.d.ts.map +1 -0
  106. package/dist/extraction/grammars.js +426 -0
  107. package/dist/extraction/grammars.js.map +1 -0
  108. package/dist/extraction/index.d.ts +138 -0
  109. package/dist/extraction/index.d.ts.map +1 -0
  110. package/dist/extraction/index.js +1394 -0
  111. package/dist/extraction/index.js.map +1 -0
  112. package/dist/extraction/languages/c-cpp.d.ts +4 -0
  113. package/dist/extraction/languages/c-cpp.d.ts.map +1 -0
  114. package/dist/extraction/languages/c-cpp.js +171 -0
  115. package/dist/extraction/languages/c-cpp.js.map +1 -0
  116. package/dist/extraction/languages/csharp.d.ts +3 -0
  117. package/dist/extraction/languages/csharp.d.ts.map +1 -0
  118. package/dist/extraction/languages/csharp.js +73 -0
  119. package/dist/extraction/languages/csharp.js.map +1 -0
  120. package/dist/extraction/languages/dart.d.ts +3 -0
  121. package/dist/extraction/languages/dart.d.ts.map +1 -0
  122. package/dist/extraction/languages/dart.js +192 -0
  123. package/dist/extraction/languages/dart.js.map +1 -0
  124. package/dist/extraction/languages/go.d.ts +3 -0
  125. package/dist/extraction/languages/go.d.ts.map +1 -0
  126. package/dist/extraction/languages/go.js +74 -0
  127. package/dist/extraction/languages/go.js.map +1 -0
  128. package/dist/extraction/languages/index.d.ts +10 -0
  129. package/dist/extraction/languages/index.d.ts.map +1 -0
  130. package/dist/extraction/languages/index.js +51 -0
  131. package/dist/extraction/languages/index.js.map +1 -0
  132. package/dist/extraction/languages/java.d.ts +3 -0
  133. package/dist/extraction/languages/java.d.ts.map +1 -0
  134. package/dist/extraction/languages/java.js +70 -0
  135. package/dist/extraction/languages/java.js.map +1 -0
  136. package/dist/extraction/languages/javascript.d.ts +3 -0
  137. package/dist/extraction/languages/javascript.d.ts.map +1 -0
  138. package/dist/extraction/languages/javascript.js +90 -0
  139. package/dist/extraction/languages/javascript.js.map +1 -0
  140. package/dist/extraction/languages/kotlin.d.ts +3 -0
  141. package/dist/extraction/languages/kotlin.d.ts.map +1 -0
  142. package/dist/extraction/languages/kotlin.js +259 -0
  143. package/dist/extraction/languages/kotlin.js.map +1 -0
  144. package/dist/extraction/languages/lua.d.ts +3 -0
  145. package/dist/extraction/languages/lua.d.ts.map +1 -0
  146. package/dist/extraction/languages/lua.js +150 -0
  147. package/dist/extraction/languages/lua.js.map +1 -0
  148. package/dist/extraction/languages/luau.d.ts +3 -0
  149. package/dist/extraction/languages/luau.d.ts.map +1 -0
  150. package/dist/extraction/languages/luau.js +37 -0
  151. package/dist/extraction/languages/luau.js.map +1 -0
  152. package/dist/extraction/languages/objc.d.ts +3 -0
  153. package/dist/extraction/languages/objc.d.ts.map +1 -0
  154. package/dist/extraction/languages/objc.js +133 -0
  155. package/dist/extraction/languages/objc.js.map +1 -0
  156. package/dist/extraction/languages/pascal.d.ts +3 -0
  157. package/dist/extraction/languages/pascal.d.ts.map +1 -0
  158. package/dist/extraction/languages/pascal.js +66 -0
  159. package/dist/extraction/languages/pascal.js.map +1 -0
  160. package/dist/extraction/languages/php.d.ts +3 -0
  161. package/dist/extraction/languages/php.d.ts.map +1 -0
  162. package/dist/extraction/languages/php.js +107 -0
  163. package/dist/extraction/languages/php.js.map +1 -0
  164. package/dist/extraction/languages/python.d.ts +3 -0
  165. package/dist/extraction/languages/python.d.ts.map +1 -0
  166. package/dist/extraction/languages/python.js +56 -0
  167. package/dist/extraction/languages/python.js.map +1 -0
  168. package/dist/extraction/languages/ruby.d.ts +3 -0
  169. package/dist/extraction/languages/ruby.d.ts.map +1 -0
  170. package/dist/extraction/languages/ruby.js +114 -0
  171. package/dist/extraction/languages/ruby.js.map +1 -0
  172. package/dist/extraction/languages/rust.d.ts +3 -0
  173. package/dist/extraction/languages/rust.d.ts.map +1 -0
  174. package/dist/extraction/languages/rust.js +109 -0
  175. package/dist/extraction/languages/rust.js.map +1 -0
  176. package/dist/extraction/languages/scala.d.ts +3 -0
  177. package/dist/extraction/languages/scala.d.ts.map +1 -0
  178. package/dist/extraction/languages/scala.js +139 -0
  179. package/dist/extraction/languages/scala.js.map +1 -0
  180. package/dist/extraction/languages/swift.d.ts +3 -0
  181. package/dist/extraction/languages/swift.d.ts.map +1 -0
  182. package/dist/extraction/languages/swift.js +91 -0
  183. package/dist/extraction/languages/swift.js.map +1 -0
  184. package/dist/extraction/languages/typescript.d.ts +3 -0
  185. package/dist/extraction/languages/typescript.d.ts.map +1 -0
  186. package/dist/extraction/languages/typescript.js +129 -0
  187. package/dist/extraction/languages/typescript.js.map +1 -0
  188. package/dist/extraction/liquid-extractor.d.ts +52 -0
  189. package/dist/extraction/liquid-extractor.d.ts.map +1 -0
  190. package/dist/extraction/liquid-extractor.js +313 -0
  191. package/dist/extraction/liquid-extractor.js.map +1 -0
  192. package/dist/extraction/mybatis-extractor.d.ts +48 -0
  193. package/dist/extraction/mybatis-extractor.d.ts.map +1 -0
  194. package/dist/extraction/mybatis-extractor.js +198 -0
  195. package/dist/extraction/mybatis-extractor.js.map +1 -0
  196. package/dist/extraction/parse-worker.d.ts +8 -0
  197. package/dist/extraction/parse-worker.d.ts.map +1 -0
  198. package/dist/extraction/parse-worker.js +94 -0
  199. package/dist/extraction/parse-worker.js.map +1 -0
  200. package/dist/extraction/specs/markdown-spec-extractor.d.ts +114 -0
  201. package/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -0
  202. package/dist/extraction/specs/markdown-spec-extractor.js +699 -0
  203. package/dist/extraction/specs/markdown-spec-extractor.js.map +1 -0
  204. package/dist/extraction/specs/types.d.ts +39 -0
  205. package/dist/extraction/specs/types.d.ts.map +1 -0
  206. package/dist/extraction/specs/types.js +8 -0
  207. package/dist/extraction/specs/types.js.map +1 -0
  208. package/dist/extraction/svelte-extractor.d.ts +56 -0
  209. package/dist/extraction/svelte-extractor.d.ts.map +1 -0
  210. package/dist/extraction/svelte-extractor.js +272 -0
  211. package/dist/extraction/svelte-extractor.js.map +1 -0
  212. package/dist/extraction/tree-sitter-helpers.d.ts +28 -0
  213. package/dist/extraction/tree-sitter-helpers.d.ts.map +1 -0
  214. package/dist/extraction/tree-sitter-helpers.js +103 -0
  215. package/dist/extraction/tree-sitter-helpers.js.map +1 -0
  216. package/dist/extraction/tree-sitter-types.d.ts +193 -0
  217. package/dist/extraction/tree-sitter-types.d.ts.map +1 -0
  218. package/dist/extraction/tree-sitter-types.js +10 -0
  219. package/dist/extraction/tree-sitter-types.js.map +1 -0
  220. package/dist/extraction/tree-sitter.d.ts +317 -0
  221. package/dist/extraction/tree-sitter.d.ts.map +1 -0
  222. package/dist/extraction/tree-sitter.js +3092 -0
  223. package/dist/extraction/tree-sitter.js.map +1 -0
  224. package/dist/extraction/vue-extractor.d.ts +51 -0
  225. package/dist/extraction/vue-extractor.d.ts.map +1 -0
  226. package/dist/extraction/vue-extractor.js +251 -0
  227. package/dist/extraction/vue-extractor.js.map +1 -0
  228. package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
  229. package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
  230. package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  231. package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
  232. package/dist/extraction/wasm-runtime-flags.d.ts +38 -0
  233. package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -0
  234. package/dist/extraction/wasm-runtime-flags.js +106 -0
  235. package/dist/extraction/wasm-runtime-flags.js.map +1 -0
  236. package/dist/fitness/fitness.d.ts +75 -0
  237. package/dist/fitness/fitness.d.ts.map +1 -0
  238. package/dist/fitness/fitness.js +204 -0
  239. package/dist/fitness/fitness.js.map +1 -0
  240. package/dist/graph/index.d.ts +8 -0
  241. package/dist/graph/index.d.ts.map +1 -0
  242. package/dist/graph/index.js +13 -0
  243. package/dist/graph/index.js.map +1 -0
  244. package/dist/graph/maintainability.d.ts +115 -0
  245. package/dist/graph/maintainability.d.ts.map +1 -0
  246. package/dist/graph/maintainability.js +299 -0
  247. package/dist/graph/maintainability.js.map +1 -0
  248. package/dist/graph/queries.d.ts +106 -0
  249. package/dist/graph/queries.d.ts.map +1 -0
  250. package/dist/graph/queries.js +366 -0
  251. package/dist/graph/queries.js.map +1 -0
  252. package/dist/graph/traversal.d.ts +127 -0
  253. package/dist/graph/traversal.d.ts.map +1 -0
  254. package/dist/graph/traversal.js +531 -0
  255. package/dist/graph/traversal.js.map +1 -0
  256. package/dist/health/smoke-check.d.ts +85 -0
  257. package/dist/health/smoke-check.d.ts.map +1 -0
  258. package/dist/health/smoke-check.js +246 -0
  259. package/dist/health/smoke-check.js.map +1 -0
  260. package/dist/index.d.ts +674 -0
  261. package/dist/index.d.ts.map +1 -0
  262. package/dist/index.js +1473 -0
  263. package/dist/index.js.map +1 -0
  264. package/dist/installer/config-writer.d.ts +28 -0
  265. package/dist/installer/config-writer.d.ts.map +1 -0
  266. package/dist/installer/config-writer.js +91 -0
  267. package/dist/installer/config-writer.js.map +1 -0
  268. package/dist/installer/index.d.ts +100 -0
  269. package/dist/installer/index.d.ts.map +1 -0
  270. package/dist/installer/index.js +442 -0
  271. package/dist/installer/index.js.map +1 -0
  272. package/dist/installer/init-offer.d.ts +31 -0
  273. package/dist/installer/init-offer.d.ts.map +1 -0
  274. package/dist/installer/init-offer.js +30 -0
  275. package/dist/installer/init-offer.js.map +1 -0
  276. package/dist/installer/instructions-template.d.ts +36 -0
  277. package/dist/installer/instructions-template.d.ts.map +1 -0
  278. package/dist/installer/instructions-template.js +57 -0
  279. package/dist/installer/instructions-template.js.map +1 -0
  280. package/dist/installer/targets/claude.d.ts +146 -0
  281. package/dist/installer/targets/claude.d.ts.map +1 -0
  282. package/dist/installer/targets/claude.js +864 -0
  283. package/dist/installer/targets/claude.js.map +1 -0
  284. package/dist/installer/targets/registry.d.ts +19 -0
  285. package/dist/installer/targets/registry.d.ts.map +1 -0
  286. package/dist/installer/targets/registry.js +31 -0
  287. package/dist/installer/targets/registry.js.map +1 -0
  288. package/dist/installer/targets/shared.d.ts +76 -0
  289. package/dist/installer/targets/shared.d.ts.map +1 -0
  290. package/dist/installer/targets/shared.js +260 -0
  291. package/dist/installer/targets/shared.js.map +1 -0
  292. package/dist/installer/targets/types.d.ts +95 -0
  293. package/dist/installer/targets/types.d.ts.map +1 -0
  294. package/dist/installer/targets/types.js +12 -0
  295. package/dist/installer/targets/types.js.map +1 -0
  296. package/dist/isolation/worktree.d.ts +65 -0
  297. package/dist/isolation/worktree.d.ts.map +1 -0
  298. package/dist/isolation/worktree.js +231 -0
  299. package/dist/isolation/worktree.js.map +1 -0
  300. package/dist/mcp/daemon-paths.d.ts +46 -0
  301. package/dist/mcp/daemon-paths.d.ts.map +1 -0
  302. package/dist/mcp/daemon-paths.js +125 -0
  303. package/dist/mcp/daemon-paths.js.map +1 -0
  304. package/dist/mcp/daemon.d.ts +161 -0
  305. package/dist/mcp/daemon.d.ts.map +1 -0
  306. package/dist/mcp/daemon.js +403 -0
  307. package/dist/mcp/daemon.js.map +1 -0
  308. package/dist/mcp/designer-tools.d.ts +33 -0
  309. package/dist/mcp/designer-tools.d.ts.map +1 -0
  310. package/dist/mcp/designer-tools.js +313 -0
  311. package/dist/mcp/designer-tools.js.map +1 -0
  312. package/dist/mcp/engine.d.ts +105 -0
  313. package/dist/mcp/engine.d.ts.map +1 -0
  314. package/dist/mcp/engine.js +270 -0
  315. package/dist/mcp/engine.js.map +1 -0
  316. package/dist/mcp/fitness-tool.d.ts +12 -0
  317. package/dist/mcp/fitness-tool.d.ts.map +1 -0
  318. package/dist/mcp/fitness-tool.js +46 -0
  319. package/dist/mcp/fitness-tool.js.map +1 -0
  320. package/dist/mcp/index.d.ts +112 -0
  321. package/dist/mcp/index.d.ts.map +1 -0
  322. package/dist/mcp/index.js +477 -0
  323. package/dist/mcp/index.js.map +1 -0
  324. package/dist/mcp/maintainability-tool.d.ts +13 -0
  325. package/dist/mcp/maintainability-tool.d.ts.map +1 -0
  326. package/dist/mcp/maintainability-tool.js +64 -0
  327. package/dist/mcp/maintainability-tool.js.map +1 -0
  328. package/dist/mcp/proxy.d.ts +81 -0
  329. package/dist/mcp/proxy.d.ts.map +1 -0
  330. package/dist/mcp/proxy.js +510 -0
  331. package/dist/mcp/proxy.js.map +1 -0
  332. package/dist/mcp/server-instructions.d.ts +18 -0
  333. package/dist/mcp/server-instructions.d.ts.map +1 -0
  334. package/dist/mcp/server-instructions.js +79 -0
  335. package/dist/mcp/server-instructions.js.map +1 -0
  336. package/dist/mcp/session.d.ts +77 -0
  337. package/dist/mcp/session.d.ts.map +1 -0
  338. package/dist/mcp/session.js +294 -0
  339. package/dist/mcp/session.js.map +1 -0
  340. package/dist/mcp/spec-tools.d.ts +39 -0
  341. package/dist/mcp/spec-tools.d.ts.map +1 -0
  342. package/dist/mcp/spec-tools.js +534 -0
  343. package/dist/mcp/spec-tools.js.map +1 -0
  344. package/dist/mcp/tools.d.ts +417 -0
  345. package/dist/mcp/tools.d.ts.map +1 -0
  346. package/dist/mcp/tools.js +3179 -0
  347. package/dist/mcp/tools.js.map +1 -0
  348. package/dist/mcp/transport.d.ts +188 -0
  349. package/dist/mcp/transport.d.ts.map +1 -0
  350. package/dist/mcp/transport.js +343 -0
  351. package/dist/mcp/transport.js.map +1 -0
  352. package/dist/mcp/version.d.ts +19 -0
  353. package/dist/mcp/version.d.ts.map +1 -0
  354. package/dist/mcp/version.js +71 -0
  355. package/dist/mcp/version.js.map +1 -0
  356. package/dist/reflect/apply.d.ts +31 -0
  357. package/dist/reflect/apply.d.ts.map +1 -0
  358. package/dist/reflect/apply.js +286 -0
  359. package/dist/reflect/apply.js.map +1 -0
  360. package/dist/reflect/hash.d.ts +20 -0
  361. package/dist/reflect/hash.d.ts.map +1 -0
  362. package/dist/reflect/hash.js +36 -0
  363. package/dist/reflect/hash.js.map +1 -0
  364. package/dist/reflect/index.d.ts +16 -0
  365. package/dist/reflect/index.d.ts.map +1 -0
  366. package/dist/reflect/index.js +43 -0
  367. package/dist/reflect/index.js.map +1 -0
  368. package/dist/reflect/miner.d.ts +21 -0
  369. package/dist/reflect/miner.d.ts.map +1 -0
  370. package/dist/reflect/miner.js +463 -0
  371. package/dist/reflect/miner.js.map +1 -0
  372. package/dist/reflect/store.d.ts +31 -0
  373. package/dist/reflect/store.d.ts.map +1 -0
  374. package/dist/reflect/store.js +101 -0
  375. package/dist/reflect/store.js.map +1 -0
  376. package/dist/reflect/sweep.d.ts +26 -0
  377. package/dist/reflect/sweep.d.ts.map +1 -0
  378. package/dist/reflect/sweep.js +42 -0
  379. package/dist/reflect/sweep.js.map +1 -0
  380. package/dist/reflect/targets.d.ts +52 -0
  381. package/dist/reflect/targets.d.ts.map +1 -0
  382. package/dist/reflect/targets.js +192 -0
  383. package/dist/reflect/targets.js.map +1 -0
  384. package/dist/reflect/types.d.ts +96 -0
  385. package/dist/reflect/types.d.ts.map +1 -0
  386. package/dist/reflect/types.js +13 -0
  387. package/dist/reflect/types.js.map +1 -0
  388. package/dist/resolution/brief-link-resolver.d.ts +114 -0
  389. package/dist/resolution/brief-link-resolver.d.ts.map +1 -0
  390. package/dist/resolution/brief-link-resolver.js +261 -0
  391. package/dist/resolution/brief-link-resolver.js.map +1 -0
  392. package/dist/resolution/callback-synthesizer.d.ts +10 -0
  393. package/dist/resolution/callback-synthesizer.d.ts.map +1 -0
  394. package/dist/resolution/callback-synthesizer.js +1300 -0
  395. package/dist/resolution/callback-synthesizer.js.map +1 -0
  396. package/dist/resolution/domain-gap-seed.d.ts +60 -0
  397. package/dist/resolution/domain-gap-seed.d.ts.map +1 -0
  398. package/dist/resolution/domain-gap-seed.js +87 -0
  399. package/dist/resolution/domain-gap-seed.js.map +1 -0
  400. package/dist/resolution/frameworks/cargo-workspace.d.ts +18 -0
  401. package/dist/resolution/frameworks/cargo-workspace.d.ts.map +1 -0
  402. package/dist/resolution/frameworks/cargo-workspace.js +225 -0
  403. package/dist/resolution/frameworks/cargo-workspace.js.map +1 -0
  404. package/dist/resolution/frameworks/csharp.d.ts +8 -0
  405. package/dist/resolution/frameworks/csharp.d.ts.map +1 -0
  406. package/dist/resolution/frameworks/csharp.js +241 -0
  407. package/dist/resolution/frameworks/csharp.js.map +1 -0
  408. package/dist/resolution/frameworks/drupal.d.ts +51 -0
  409. package/dist/resolution/frameworks/drupal.d.ts.map +1 -0
  410. package/dist/resolution/frameworks/drupal.js +367 -0
  411. package/dist/resolution/frameworks/drupal.js.map +1 -0
  412. package/dist/resolution/frameworks/expo-modules.d.ts +3 -0
  413. package/dist/resolution/frameworks/expo-modules.d.ts.map +1 -0
  414. package/dist/resolution/frameworks/expo-modules.js +143 -0
  415. package/dist/resolution/frameworks/expo-modules.js.map +1 -0
  416. package/dist/resolution/frameworks/express.d.ts +8 -0
  417. package/dist/resolution/frameworks/express.d.ts.map +1 -0
  418. package/dist/resolution/frameworks/express.js +308 -0
  419. package/dist/resolution/frameworks/express.js.map +1 -0
  420. package/dist/resolution/frameworks/fabric.d.ts +3 -0
  421. package/dist/resolution/frameworks/fabric.d.ts.map +1 -0
  422. package/dist/resolution/frameworks/fabric.js +354 -0
  423. package/dist/resolution/frameworks/fabric.js.map +1 -0
  424. package/dist/resolution/frameworks/go.d.ts +8 -0
  425. package/dist/resolution/frameworks/go.d.ts.map +1 -0
  426. package/dist/resolution/frameworks/go.js +161 -0
  427. package/dist/resolution/frameworks/go.js.map +1 -0
  428. package/dist/resolution/frameworks/index.d.ts +48 -0
  429. package/dist/resolution/frameworks/index.d.ts.map +1 -0
  430. package/dist/resolution/frameworks/index.js +161 -0
  431. package/dist/resolution/frameworks/index.js.map +1 -0
  432. package/dist/resolution/frameworks/java.d.ts +8 -0
  433. package/dist/resolution/frameworks/java.d.ts.map +1 -0
  434. package/dist/resolution/frameworks/java.js +504 -0
  435. package/dist/resolution/frameworks/java.js.map +1 -0
  436. package/dist/resolution/frameworks/laravel.d.ts +13 -0
  437. package/dist/resolution/frameworks/laravel.d.ts.map +1 -0
  438. package/dist/resolution/frameworks/laravel.js +257 -0
  439. package/dist/resolution/frameworks/laravel.js.map +1 -0
  440. package/dist/resolution/frameworks/nestjs.d.ts +26 -0
  441. package/dist/resolution/frameworks/nestjs.d.ts.map +1 -0
  442. package/dist/resolution/frameworks/nestjs.js +698 -0
  443. package/dist/resolution/frameworks/nestjs.js.map +1 -0
  444. package/dist/resolution/frameworks/play.d.ts +19 -0
  445. package/dist/resolution/frameworks/play.d.ts.map +1 -0
  446. package/dist/resolution/frameworks/play.js +111 -0
  447. package/dist/resolution/frameworks/play.js.map +1 -0
  448. package/dist/resolution/frameworks/python.d.ts +10 -0
  449. package/dist/resolution/frameworks/python.d.ts.map +1 -0
  450. package/dist/resolution/frameworks/python.js +396 -0
  451. package/dist/resolution/frameworks/python.js.map +1 -0
  452. package/dist/resolution/frameworks/react-native.d.ts +3 -0
  453. package/dist/resolution/frameworks/react-native.d.ts.map +1 -0
  454. package/dist/resolution/frameworks/react-native.js +360 -0
  455. package/dist/resolution/frameworks/react-native.js.map +1 -0
  456. package/dist/resolution/frameworks/react.d.ts +8 -0
  457. package/dist/resolution/frameworks/react.d.ts.map +1 -0
  458. package/dist/resolution/frameworks/react.js +365 -0
  459. package/dist/resolution/frameworks/react.js.map +1 -0
  460. package/dist/resolution/frameworks/ruby.d.ts +8 -0
  461. package/dist/resolution/frameworks/ruby.d.ts.map +1 -0
  462. package/dist/resolution/frameworks/ruby.js +302 -0
  463. package/dist/resolution/frameworks/ruby.js.map +1 -0
  464. package/dist/resolution/frameworks/rust.d.ts +8 -0
  465. package/dist/resolution/frameworks/rust.d.ts.map +1 -0
  466. package/dist/resolution/frameworks/rust.js +304 -0
  467. package/dist/resolution/frameworks/rust.js.map +1 -0
  468. package/dist/resolution/frameworks/svelte.d.ts +9 -0
  469. package/dist/resolution/frameworks/svelte.d.ts.map +1 -0
  470. package/dist/resolution/frameworks/svelte.js +249 -0
  471. package/dist/resolution/frameworks/svelte.js.map +1 -0
  472. package/dist/resolution/frameworks/swift-objc.d.ts +37 -0
  473. package/dist/resolution/frameworks/swift-objc.d.ts.map +1 -0
  474. package/dist/resolution/frameworks/swift-objc.js +252 -0
  475. package/dist/resolution/frameworks/swift-objc.js.map +1 -0
  476. package/dist/resolution/frameworks/swift.d.ts +10 -0
  477. package/dist/resolution/frameworks/swift.d.ts.map +1 -0
  478. package/dist/resolution/frameworks/swift.js +400 -0
  479. package/dist/resolution/frameworks/swift.js.map +1 -0
  480. package/dist/resolution/frameworks/vue.d.ts +9 -0
  481. package/dist/resolution/frameworks/vue.d.ts.map +1 -0
  482. package/dist/resolution/frameworks/vue.js +306 -0
  483. package/dist/resolution/frameworks/vue.js.map +1 -0
  484. package/dist/resolution/go-module.d.ts +26 -0
  485. package/dist/resolution/go-module.d.ts.map +1 -0
  486. package/dist/resolution/go-module.js +78 -0
  487. package/dist/resolution/go-module.js.map +1 -0
  488. package/dist/resolution/import-resolver.d.ts +68 -0
  489. package/dist/resolution/import-resolver.d.ts.map +1 -0
  490. package/dist/resolution/import-resolver.js +1275 -0
  491. package/dist/resolution/import-resolver.js.map +1 -0
  492. package/dist/resolution/index.d.ts +117 -0
  493. package/dist/resolution/index.d.ts.map +1 -0
  494. package/dist/resolution/index.js +895 -0
  495. package/dist/resolution/index.js.map +1 -0
  496. package/dist/resolution/lru-cache.d.ts +24 -0
  497. package/dist/resolution/lru-cache.d.ts.map +1 -0
  498. package/dist/resolution/lru-cache.js +62 -0
  499. package/dist/resolution/lru-cache.js.map +1 -0
  500. package/dist/resolution/name-matcher.d.ts +32 -0
  501. package/dist/resolution/name-matcher.d.ts.map +1 -0
  502. package/dist/resolution/name-matcher.js +596 -0
  503. package/dist/resolution/name-matcher.js.map +1 -0
  504. package/dist/resolution/path-aliases.d.ts +68 -0
  505. package/dist/resolution/path-aliases.d.ts.map +1 -0
  506. package/dist/resolution/path-aliases.js +238 -0
  507. package/dist/resolution/path-aliases.js.map +1 -0
  508. package/dist/resolution/spec-link-resolver.d.ts +148 -0
  509. package/dist/resolution/spec-link-resolver.d.ts.map +1 -0
  510. package/dist/resolution/spec-link-resolver.js +337 -0
  511. package/dist/resolution/spec-link-resolver.js.map +1 -0
  512. package/dist/resolution/strip-comments.d.ts +27 -0
  513. package/dist/resolution/strip-comments.d.ts.map +1 -0
  514. package/dist/resolution/strip-comments.js +441 -0
  515. package/dist/resolution/strip-comments.js.map +1 -0
  516. package/dist/resolution/swift-objc-bridge.d.ts +134 -0
  517. package/dist/resolution/swift-objc-bridge.d.ts.map +1 -0
  518. package/dist/resolution/swift-objc-bridge.js +256 -0
  519. package/dist/resolution/swift-objc-bridge.js.map +1 -0
  520. package/dist/resolution/types.d.ts +216 -0
  521. package/dist/resolution/types.d.ts.map +1 -0
  522. package/dist/resolution/types.js +8 -0
  523. package/dist/resolution/types.js.map +1 -0
  524. package/dist/resolution/workspace-packages.d.ts +48 -0
  525. package/dist/resolution/workspace-packages.d.ts.map +1 -0
  526. package/dist/resolution/workspace-packages.js +208 -0
  527. package/dist/resolution/workspace-packages.js.map +1 -0
  528. package/dist/search/query-parser.d.ts +57 -0
  529. package/dist/search/query-parser.d.ts.map +1 -0
  530. package/dist/search/query-parser.js +177 -0
  531. package/dist/search/query-parser.js.map +1 -0
  532. package/dist/search/query-utils.d.ts +71 -0
  533. package/dist/search/query-utils.d.ts.map +1 -0
  534. package/dist/search/query-utils.js +380 -0
  535. package/dist/search/query-utils.js.map +1 -0
  536. package/dist/server/cli.js +152 -0
  537. package/dist/server/index.js +12 -0
  538. package/dist/server/ingest/impact-backfill.js +69 -0
  539. package/dist/server/ingest/impact-query.js +343 -0
  540. package/dist/server/ingest/index.js +19 -0
  541. package/dist/server/ingest/ingestor.js +541 -0
  542. package/dist/server/ingest/parser.js +104 -0
  543. package/dist/server/ingest/pricing.js +78 -0
  544. package/dist/server/ingest/specship-classify.js +153 -0
  545. package/dist/server/ingest/types.js +9 -0
  546. package/dist/server/ingest/watcher.js +77 -0
  547. package/dist/server/package.json +3 -0
  548. package/dist/server/project-registry.js +101 -0
  549. package/dist/server/routes/claude.js +907 -0
  550. package/dist/server/routes/domain.js +0 -0
  551. package/dist/server/routes/events.js +134 -0
  552. package/dist/server/routes/graph.js +248 -0
  553. package/dist/server/routes/maintainability.js +18 -0
  554. package/dist/server/routes/memory.js +272 -0
  555. package/dist/server/routes/projects.js +197 -0
  556. package/dist/server/routes/reflect.js +93 -0
  557. package/dist/server/routes/spec.js +373 -0
  558. package/dist/server/routes/status.js +112 -0
  559. package/dist/server/routes/workflow.js +253 -0
  560. package/dist/server/server.js +238 -0
  561. package/dist/server/static-handler.js +87 -0
  562. package/dist/statusline/active-run.d.ts +16 -0
  563. package/dist/statusline/active-run.d.ts.map +1 -0
  564. package/dist/statusline/active-run.js +73 -0
  565. package/dist/statusline/active-run.js.map +1 -0
  566. package/dist/statusline/cache.d.ts +21 -0
  567. package/dist/statusline/cache.d.ts.map +1 -0
  568. package/dist/statusline/cache.js +34 -0
  569. package/dist/statusline/cache.js.map +1 -0
  570. package/dist/statusline/index.d.ts +24 -0
  571. package/dist/statusline/index.d.ts.map +1 -0
  572. package/dist/statusline/index.js +128 -0
  573. package/dist/statusline/index.js.map +1 -0
  574. package/dist/statusline/paths.d.ts +27 -0
  575. package/dist/statusline/paths.d.ts.map +1 -0
  576. package/dist/statusline/paths.js +101 -0
  577. package/dist/statusline/paths.js.map +1 -0
  578. package/dist/statusline/render.d.ts +25 -0
  579. package/dist/statusline/render.d.ts.map +1 -0
  580. package/dist/statusline/render.js +72 -0
  581. package/dist/statusline/render.js.map +1 -0
  582. package/dist/statusline/session-marker.d.ts +30 -0
  583. package/dist/statusline/session-marker.d.ts.map +1 -0
  584. package/dist/statusline/session-marker.js +71 -0
  585. package/dist/statusline/session-marker.js.map +1 -0
  586. package/dist/statusline/types.d.ts +67 -0
  587. package/dist/statusline/types.d.ts.map +1 -0
  588. package/dist/statusline/types.js +16 -0
  589. package/dist/statusline/types.js.map +1 -0
  590. package/dist/sync/git-hooks.d.ts +45 -0
  591. package/dist/sync/git-hooks.d.ts.map +1 -0
  592. package/dist/sync/git-hooks.js +225 -0
  593. package/dist/sync/git-hooks.js.map +1 -0
  594. package/dist/sync/index.d.ts +19 -0
  595. package/dist/sync/index.d.ts.map +1 -0
  596. package/dist/sync/index.js +35 -0
  597. package/dist/sync/index.js.map +1 -0
  598. package/dist/sync/watch-policy.d.ts +48 -0
  599. package/dist/sync/watch-policy.d.ts.map +1 -0
  600. package/dist/sync/watch-policy.js +124 -0
  601. package/dist/sync/watch-policy.js.map +1 -0
  602. package/dist/sync/watcher.d.ts +283 -0
  603. package/dist/sync/watcher.d.ts.map +1 -0
  604. package/dist/sync/watcher.js +606 -0
  605. package/dist/sync/watcher.js.map +1 -0
  606. package/dist/sync/worktree.d.ts +54 -0
  607. package/dist/sync/worktree.d.ts.map +1 -0
  608. package/dist/sync/worktree.js +137 -0
  609. package/dist/sync/worktree.js.map +1 -0
  610. package/dist/types.d.ts +625 -0
  611. package/dist/types.d.ts.map +1 -0
  612. package/dist/types.js +118 -0
  613. package/dist/types.js.map +1 -0
  614. package/dist/ui/glyphs.d.ts +42 -0
  615. package/dist/ui/glyphs.d.ts.map +1 -0
  616. package/dist/ui/glyphs.js +78 -0
  617. package/dist/ui/glyphs.js.map +1 -0
  618. package/dist/ui/shimmer-progress.d.ts +11 -0
  619. package/dist/ui/shimmer-progress.d.ts.map +1 -0
  620. package/dist/ui/shimmer-progress.js +90 -0
  621. package/dist/ui/shimmer-progress.js.map +1 -0
  622. package/dist/ui/shimmer-worker.d.ts +2 -0
  623. package/dist/ui/shimmer-worker.d.ts.map +1 -0
  624. package/dist/ui/shimmer-worker.js +118 -0
  625. package/dist/ui/shimmer-worker.js.map +1 -0
  626. package/dist/ui/types.d.ts +17 -0
  627. package/dist/ui/types.d.ts.map +1 -0
  628. package/dist/ui/types.js +3 -0
  629. package/dist/ui/types.js.map +1 -0
  630. package/dist/utils.d.ts +205 -0
  631. package/dist/utils.d.ts.map +1 -0
  632. package/dist/utils.js +549 -0
  633. package/dist/utils.js.map +1 -0
  634. package/dist/web/chunk-2AJCHB7P.js +1 -0
  635. package/dist/web/chunk-2CPLUFCH.js +2 -0
  636. package/dist/web/chunk-2I7L37NS.js +1 -0
  637. package/dist/web/chunk-2NAWAJB5.js +1 -0
  638. package/dist/web/chunk-2OJBIPE4.js +1 -0
  639. package/dist/web/chunk-372AYXK6.js +17 -0
  640. package/dist/web/chunk-3E2WB6D5.js +1 -0
  641. package/dist/web/chunk-3EBFYSCH.js +2 -0
  642. package/dist/web/chunk-3QCQ4BXS.js +1 -0
  643. package/dist/web/chunk-42XVAQ6I.js +1 -0
  644. package/dist/web/chunk-4IMMPEYM.js +1 -0
  645. package/dist/web/chunk-4JYHAP7B.js +1 -0
  646. package/dist/web/chunk-4TJQJPCZ.js +1 -0
  647. package/dist/web/chunk-4WZIHTPC.js +1 -0
  648. package/dist/web/chunk-4YVSYOSD.js +1 -0
  649. package/dist/web/chunk-52PO6IMB.js +2 -0
  650. package/dist/web/chunk-54D6RFSW.js +1 -0
  651. package/dist/web/chunk-5BQIOYKW.js +1 -0
  652. package/dist/web/chunk-5HGWHUJA.js +1 -0
  653. package/dist/web/chunk-5XRUOPZE.js +1 -0
  654. package/dist/web/chunk-5Y244R4G.js +1 -0
  655. package/dist/web/chunk-6O7Z3P2M.js +1 -0
  656. package/dist/web/chunk-6QXULGLG.js +1 -0
  657. package/dist/web/chunk-6RRDPT5Z.js +1 -0
  658. package/dist/web/chunk-6VKB2ZWM.js +1 -0
  659. package/dist/web/chunk-7DMFVTU4.js +1 -0
  660. package/dist/web/chunk-7P5CVBJZ.js +1 -0
  661. package/dist/web/chunk-7SMPKVEP.js +1 -0
  662. package/dist/web/chunk-AHLX543M.js +1 -0
  663. package/dist/web/chunk-AMGJBO7D.js +3 -0
  664. package/dist/web/chunk-AZJVTPLU.js +1 -0
  665. package/dist/web/chunk-B3CWIVBW.js +1 -0
  666. package/dist/web/chunk-BLBRMCN2.js +1 -0
  667. package/dist/web/chunk-BMIAXD2V.js +2 -0
  668. package/dist/web/chunk-BPCJLNBS.js +47 -0
  669. package/dist/web/chunk-BRHEUDLY.js +6 -0
  670. package/dist/web/chunk-BUXWEHIY.js +1 -0
  671. package/dist/web/chunk-CD5IZM7Y.js +1 -0
  672. package/dist/web/chunk-DLQPZWSI.css +1 -0
  673. package/dist/web/chunk-DSGNOCKQ.js +1 -0
  674. package/dist/web/chunk-DT5LJYFX.js +1 -0
  675. package/dist/web/chunk-DYRFLPJA.js +1 -0
  676. package/dist/web/chunk-E3J3CXR5.js +1 -0
  677. package/dist/web/chunk-E73OX2P7.js +1 -0
  678. package/dist/web/chunk-EAXRKDLV.js +1 -0
  679. package/dist/web/chunk-EBKKDHYI.js +1 -0
  680. package/dist/web/chunk-EE7V7Q5P.js +1 -0
  681. package/dist/web/chunk-EKY2FUHU.js +1 -0
  682. package/dist/web/chunk-EP6XOPXH.js +1 -0
  683. package/dist/web/chunk-ESGDLJOJ.js +1 -0
  684. package/dist/web/chunk-ETJG7NCY.js +1 -0
  685. package/dist/web/chunk-EUUEFEDI.js +1 -0
  686. package/dist/web/chunk-EX4ZHR4F.js +1 -0
  687. package/dist/web/chunk-F5UNCSXP.js +1 -0
  688. package/dist/web/chunk-FFGJXUHI.js +1 -0
  689. package/dist/web/chunk-FGNZDHTL.js +11 -0
  690. package/dist/web/chunk-FIJW2UNJ.js +1 -0
  691. package/dist/web/chunk-FMV5PXRC.js +5 -0
  692. package/dist/web/chunk-G7VZT5KB.js +3 -0
  693. package/dist/web/chunk-GCOM4JPR.js +2 -0
  694. package/dist/web/chunk-GEIIDO6C.js +1 -0
  695. package/dist/web/chunk-GRZYXPSO.js +7 -0
  696. package/dist/web/chunk-GWBABPZ5.js +1 -0
  697. package/dist/web/chunk-GYGPS3AN.js +1 -0
  698. package/dist/web/chunk-H4GLRD3Q.js +1 -0
  699. package/dist/web/chunk-H5TWEFYX.js +1 -0
  700. package/dist/web/chunk-H7AF7YS4.js +1 -0
  701. package/dist/web/chunk-HCB2N2KH.js +1 -0
  702. package/dist/web/chunk-HDZDQILN.js +1 -0
  703. package/dist/web/chunk-HMK6UO6N.js +1 -0
  704. package/dist/web/chunk-HVVXPI4D.js +1 -0
  705. package/dist/web/chunk-IHEE5NYJ.js +1 -0
  706. package/dist/web/chunk-IPB746BT.js +1 -0
  707. package/dist/web/chunk-ISNEBICW.js +1 -0
  708. package/dist/web/chunk-J2GZVLHH.js +1 -0
  709. package/dist/web/chunk-JTFXTIPE.js +903 -0
  710. package/dist/web/chunk-KHU5M2AL.js +1 -0
  711. package/dist/web/chunk-KW3DHCFV.js +1 -0
  712. package/dist/web/chunk-LB6JPLX2.js +1 -0
  713. package/dist/web/chunk-LBXLFPVN.js +1 -0
  714. package/dist/web/chunk-LGNSHRCE.js +1 -0
  715. package/dist/web/chunk-LNSVDHCI.js +1 -0
  716. package/dist/web/chunk-LVGIY3SO.js +1 -0
  717. package/dist/web/chunk-LXLHIHEN.js +1 -0
  718. package/dist/web/chunk-MFHO2F2U.js +4 -0
  719. package/dist/web/chunk-N5OSSQFZ.js +1 -0
  720. package/dist/web/chunk-N6SS4G6S.js +1 -0
  721. package/dist/web/chunk-NAJYJNHS.js +1 -0
  722. package/dist/web/chunk-NHD66NOI.js +1 -0
  723. package/dist/web/chunk-NNLJ55MY.js +1 -0
  724. package/dist/web/chunk-NTBJG6SJ.js +1 -0
  725. package/dist/web/chunk-NUDB3Q2Y.js +3 -0
  726. package/dist/web/chunk-OM7JVWQQ.js +1 -0
  727. package/dist/web/chunk-OXEF5E3E.js +1 -0
  728. package/dist/web/chunk-PGGJPDJG.js +1 -0
  729. package/dist/web/chunk-PUYSJNJR.js +1 -0
  730. package/dist/web/chunk-Q2RVFS45.js +1 -0
  731. package/dist/web/chunk-Q7L6LLAK.js +1 -0
  732. package/dist/web/chunk-QCMKJIWY.js +1 -0
  733. package/dist/web/chunk-QEQRY4QQ.js +1 -0
  734. package/dist/web/chunk-QH6CF3M3.js +1 -0
  735. package/dist/web/chunk-QQ5LD7PI.js +1 -0
  736. package/dist/web/chunk-QR6L3KAC.js +1 -0
  737. package/dist/web/chunk-QXJS6F3U.js +1 -0
  738. package/dist/web/chunk-R2DLK4HO.js +1 -0
  739. package/dist/web/chunk-RD6TVPOT.js +1 -0
  740. package/dist/web/chunk-RKY4EJYJ.js +1 -0
  741. package/dist/web/chunk-RONYWVY7.js +1 -0
  742. package/dist/web/chunk-RSZZWGGC.js +1 -0
  743. package/dist/web/chunk-RXKXYF2C.js +1 -0
  744. package/dist/web/chunk-SCNDZRN2.js +1 -0
  745. package/dist/web/chunk-SH6UVHQC.js +1 -0
  746. package/dist/web/chunk-SWKJRNYY.js +1 -0
  747. package/dist/web/chunk-T7AZ65JP.js +1 -0
  748. package/dist/web/chunk-TCZDVOHD.js +1 -0
  749. package/dist/web/chunk-TF5TF6IP.js +1 -0
  750. package/dist/web/chunk-TPTITA3V.js +1 -0
  751. package/dist/web/chunk-TR335633.js +1 -0
  752. package/dist/web/chunk-UR5KDXPX.js +1 -0
  753. package/dist/web/chunk-UR6O2GEH.js +1 -0
  754. package/dist/web/chunk-UTNMGWTP.js +1 -0
  755. package/dist/web/chunk-VECWMHJP.js +1 -0
  756. package/dist/web/chunk-VUACT35R.js +3 -0
  757. package/dist/web/chunk-VZI7H4SZ.js +1 -0
  758. package/dist/web/chunk-W22AVG3N.js +1 -0
  759. package/dist/web/chunk-W6NGHRHX.js +1 -0
  760. package/dist/web/chunk-WB6YHOD4.js +1 -0
  761. package/dist/web/chunk-WBT64AWV.js +1 -0
  762. package/dist/web/chunk-WFXJIXZE.js +4 -0
  763. package/dist/web/chunk-WTGYRH3Z.js +298 -0
  764. package/dist/web/chunk-WXTCVDTP.js +1 -0
  765. package/dist/web/chunk-XCDHWLVH.js +1 -0
  766. package/dist/web/chunk-Y3H6FFUZ.js +1 -0
  767. package/dist/web/chunk-Y4F5ULGJ.js +1 -0
  768. package/dist/web/chunk-YEGKAAEE.js +1 -0
  769. package/dist/web/chunk-YM2KU57F.js +1 -0
  770. package/dist/web/chunk-YRERBP6T.js +1 -0
  771. package/dist/web/chunk-ZLV4VCDG.js +3 -0
  772. package/dist/web/chunk-ZQUJMA5K.js +4 -0
  773. package/dist/web/chunk-ZTVI5KFF.js +1 -0
  774. package/dist/web/favicon-16.png +0 -0
  775. package/dist/web/favicon-180.png +0 -0
  776. package/dist/web/favicon-32.png +0 -0
  777. package/dist/web/favicon-512.png +0 -0
  778. package/dist/web/favicon-small.svg +15 -0
  779. package/dist/web/favicon.ico +0 -0
  780. package/dist/web/favicon.svg +20 -0
  781. package/dist/web/icon-192.png +0 -0
  782. package/dist/web/icon-512.png +0 -0
  783. package/dist/web/index.html +146 -0
  784. package/dist/web/main-ESADRXN2.css +1 -0
  785. package/dist/web/main-SQFUMVQA.js +1 -0
  786. package/dist/web/manifest.webmanifest +15 -0
  787. package/dist/web/media/codicon-LN6W7LCM.ttf +0 -0
  788. package/dist/web/styles-KSOPUVDA.css +1 -0
  789. package/dist/web/sw.js +69 -0
  790. package/dist/workflows/condition-evaluator.d.ts +75 -0
  791. package/dist/workflows/condition-evaluator.d.ts.map +1 -0
  792. package/dist/workflows/condition-evaluator.js +282 -0
  793. package/dist/workflows/condition-evaluator.js.map +1 -0
  794. package/dist/workflows/defaults/claude-design-implement.yaml +336 -0
  795. package/dist/workflows/defaults/index.d.ts +26 -0
  796. package/dist/workflows/defaults/index.d.ts.map +1 -0
  797. package/dist/workflows/defaults/index.js +94 -0
  798. package/dist/workflows/defaults/index.js.map +1 -0
  799. package/dist/workflows/defaults/spec-author.yaml +214 -0
  800. package/dist/workflows/defaults/spec-fix.yaml +110 -0
  801. package/dist/workflows/defaults/spec-implement.yaml +150 -0
  802. package/dist/workflows/defaults/spec-relink.yaml +81 -0
  803. package/dist/workflows/defaults/spec-verify.yaml +51 -0
  804. package/dist/workflows/discovery.d.ts +46 -0
  805. package/dist/workflows/discovery.d.ts.map +1 -0
  806. package/dist/workflows/discovery.js +193 -0
  807. package/dist/workflows/discovery.js.map +1 -0
  808. package/dist/workflows/executor.d.ts +98 -0
  809. package/dist/workflows/executor.d.ts.map +1 -0
  810. package/dist/workflows/executor.js +664 -0
  811. package/dist/workflows/executor.js.map +1 -0
  812. package/dist/workflows/runners/approval.d.ts +18 -0
  813. package/dist/workflows/runners/approval.d.ts.map +1 -0
  814. package/dist/workflows/runners/approval.js +34 -0
  815. package/dist/workflows/runners/approval.js.map +1 -0
  816. package/dist/workflows/runners/bash.d.ts +13 -0
  817. package/dist/workflows/runners/bash.d.ts.map +1 -0
  818. package/dist/workflows/runners/bash.js +143 -0
  819. package/dist/workflows/runners/bash.js.map +1 -0
  820. package/dist/workflows/runners/cancel.d.ts +10 -0
  821. package/dist/workflows/runners/cancel.d.ts.map +1 -0
  822. package/dist/workflows/runners/cancel.js +19 -0
  823. package/dist/workflows/runners/cancel.js.map +1 -0
  824. package/dist/workflows/runners/prompt.d.ts +51 -0
  825. package/dist/workflows/runners/prompt.d.ts.map +1 -0
  826. package/dist/workflows/runners/prompt.js +306 -0
  827. package/dist/workflows/runners/prompt.js.map +1 -0
  828. package/dist/workflows/runners/script.d.ts +17 -0
  829. package/dist/workflows/runners/script.d.ts.map +1 -0
  830. package/dist/workflows/runners/script.js +155 -0
  831. package/dist/workflows/runners/script.js.map +1 -0
  832. package/dist/workflows/runners/types.d.ts +57 -0
  833. package/dist/workflows/runners/types.d.ts.map +1 -0
  834. package/dist/workflows/runners/types.js +13 -0
  835. package/dist/workflows/runners/types.js.map +1 -0
  836. package/dist/workflows/schemas/workflow.d.ts +166 -0
  837. package/dist/workflows/schemas/workflow.d.ts.map +1 -0
  838. package/dist/workflows/schemas/workflow.js +437 -0
  839. package/dist/workflows/schemas/workflow.js.map +1 -0
  840. package/hooks/hooks.json +38 -0
  841. package/package.json +78 -0
  842. package/scripts/add-lang/bench.sh +60 -0
  843. package/scripts/add-lang/check-grammar.mjs +75 -0
  844. package/scripts/add-lang/dump-ast.mjs +103 -0
  845. package/scripts/add-lang/verify-extraction.mjs +70 -0
  846. package/scripts/agent-eval/arms-F.sh +21 -0
  847. package/scripts/agent-eval/arms-matrix.sh +37 -0
  848. package/scripts/agent-eval/audit.sh +68 -0
  849. package/scripts/agent-eval/bench-readme.sh +28 -0
  850. package/scripts/agent-eval/bench-why-repo.sh +22 -0
  851. package/scripts/agent-eval/block-read-hook.sh +19 -0
  852. package/scripts/agent-eval/hook-settings.json +15 -0
  853. package/scripts/agent-eval/itrun.sh +120 -0
  854. package/scripts/agent-eval/parse-arms.mjs +116 -0
  855. package/scripts/agent-eval/parse-bench-readme.mjs +84 -0
  856. package/scripts/agent-eval/parse-run.mjs +45 -0
  857. package/scripts/agent-eval/parse-session.mjs +93 -0
  858. package/scripts/agent-eval/probe-context.mjs +21 -0
  859. package/scripts/agent-eval/probe-explore.mjs +40 -0
  860. package/scripts/agent-eval/probe-node.mjs +20 -0
  861. package/scripts/agent-eval/probe-sweep.mjs +119 -0
  862. package/scripts/agent-eval/probe-trace.mjs +20 -0
  863. package/scripts/agent-eval/run-agent.sh +34 -0
  864. package/scripts/agent-eval/run-all.sh +67 -0
  865. package/scripts/agent-eval/run-arms.sh +56 -0
  866. package/scripts/agent-eval/seq-matrix.mjs +137 -0
  867. package/scripts/build-bundle.sh +118 -0
  868. package/scripts/build-server-bundle.mjs +80 -0
  869. package/scripts/build-web-bundle.mjs +66 -0
  870. package/scripts/extract-release-notes.mjs +130 -0
  871. package/scripts/local-install.sh +41 -0
  872. package/scripts/npm-sdk.js +75 -0
  873. package/scripts/npm-shim.js +246 -0
  874. package/scripts/offline-install.ps1 +148 -0
  875. package/scripts/offline-install.sh +149 -0
  876. package/scripts/pack-npm.sh +119 -0
  877. package/scripts/prepare-release.mjs +270 -0
  878. package/scripts/sync-shim-version.mjs +64 -0
  879. package/selectors.json +41 -0
package/dist/index.js ADDED
@@ -0,0 +1,1473 @@
1
+ "use strict";
2
+ /**
3
+ * SpecShip
4
+ *
5
+ * A local-first code intelligence system that builds a semantic
6
+ * knowledge graph from any codebase.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
42
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.ConfigError = exports.VectorError = exports.SearchError = exports.DatabaseError = exports.ParseError = exports.FileError = exports.SpecShipError = exports.isUiNode = exports.renderBehaviourSurface = exports.computeBehaviourSurface = exports.ENFORCE_CONFIG_FILE = exports.loadEnforceConfig = exports.evaluateEnforcement = exports.FITNESS_CONFIG_FILE = exports.loadFitnessRules = exports.evaluateFitness = exports.highPrecisionClean = exports.LOW_CONFIDENCE_CLASSES = exports.HIGH_PRECISION_CLASSES = exports.CONFIG_FILE_NAME = exports.DEFAULT_EXCLUDE = exports.DEFAULT_THRESHOLDS = exports.resolveExclude = exports.resolveThresholds = exports.computeMaintainability = exports.undoProposal = exports.applyProposal = exports.previewProposal = exports.ReflectStore = exports.reflectSweep = exports.reflectAnalyze = exports.computeDomainGapSeed = exports.findBriefsForSpec = exports.summarizeBriefFunnel = exports.resolveBriefLink = exports.computeSpecFunnel = exports.loadAllGrammars = exports.loadGrammarsForLanguages = exports.initGrammars = exports.getSupportedLanguages = exports.isGrammarLoaded = exports.isLanguageSupported = exports.detectLanguage = exports.SPECSHIP_DIR = exports.findNearestSpecShipRoot = exports.isInitialized = exports.getSpecShipDir = exports.QueryBuilder = exports.DatabaseConnection = exports.getDatabasePath = void 0;
46
+ exports.SpecShip = exports.MCPServer = exports.LockUnavailableError = exports.FileWatcher = exports.MemoryMonitor = exports.throttle = exports.debounce = exports.processInBatches = exports.FileLock = exports.Mutex = exports.defaultLogger = exports.silentLogger = exports.getLogger = exports.setLogger = void 0;
47
+ const path = __importStar(require("path"));
48
+ const db_1 = require("./db");
49
+ const queries_1 = require("./db/queries");
50
+ const directory_1 = require("./directory");
51
+ const statusline_1 = require("./statusline");
52
+ const extraction_1 = require("./extraction");
53
+ const markdown_spec_extractor_1 = require("./extraction/specs/markdown-spec-extractor");
54
+ const resolution_1 = require("./resolution");
55
+ const spec_link_resolver_1 = require("./resolution/spec-link-resolver");
56
+ const brief_link_resolver_1 = require("./resolution/brief-link-resolver");
57
+ const domain_gap_seed_1 = require("./resolution/domain-gap-seed");
58
+ const spec_queries_1 = require("./db/spec-queries");
59
+ const reflect_1 = require("./reflect");
60
+ const os = __importStar(require("os"));
61
+ const fs = __importStar(require("fs"));
62
+ const crypto_1 = require("crypto");
63
+ const graph_1 = require("./graph");
64
+ const maintainability_1 = require("./graph/maintainability");
65
+ const fitness_1 = require("./fitness/fitness");
66
+ const enforce_1 = require("./enforce/enforce");
67
+ const behaviour_surface_1 = require("./behaviour/behaviour-surface");
68
+ const context_1 = require("./context");
69
+ const utils_1 = require("./utils");
70
+ const sync_1 = require("./sync");
71
+ // Re-export types for consumers
72
+ __exportStar(require("./types"), exports);
73
+ // Storage building blocks for embedded/SDK consumers that drive the graph
74
+ // directly (open a DB, run prepared queries) rather than through the SpecShip
75
+ // facade. Exposed from the package entry so they no longer require deep imports
76
+ // into dist/ (issue #354).
77
+ var db_2 = require("./db");
78
+ Object.defineProperty(exports, "getDatabasePath", { enumerable: true, get: function () { return db_2.getDatabasePath; } });
79
+ Object.defineProperty(exports, "DatabaseConnection", { enumerable: true, get: function () { return db_2.DatabaseConnection; } });
80
+ var queries_2 = require("./db/queries");
81
+ Object.defineProperty(exports, "QueryBuilder", { enumerable: true, get: function () { return queries_2.QueryBuilder; } });
82
+ var directory_2 = require("./directory");
83
+ Object.defineProperty(exports, "getSpecShipDir", { enumerable: true, get: function () { return directory_2.getSpecShipDir; } });
84
+ Object.defineProperty(exports, "isInitialized", { enumerable: true, get: function () { return directory_2.isInitialized; } });
85
+ Object.defineProperty(exports, "findNearestSpecShipRoot", { enumerable: true, get: function () { return directory_2.findNearestSpecShipRoot; } });
86
+ Object.defineProperty(exports, "SPECSHIP_DIR", { enumerable: true, get: function () { return directory_2.SPECSHIP_DIR; } });
87
+ var extraction_2 = require("./extraction");
88
+ Object.defineProperty(exports, "detectLanguage", { enumerable: true, get: function () { return extraction_2.detectLanguage; } });
89
+ Object.defineProperty(exports, "isLanguageSupported", { enumerable: true, get: function () { return extraction_2.isLanguageSupported; } });
90
+ Object.defineProperty(exports, "isGrammarLoaded", { enumerable: true, get: function () { return extraction_2.isGrammarLoaded; } });
91
+ Object.defineProperty(exports, "getSupportedLanguages", { enumerable: true, get: function () { return extraction_2.getSupportedLanguages; } });
92
+ Object.defineProperty(exports, "initGrammars", { enumerable: true, get: function () { return extraction_2.initGrammars; } });
93
+ Object.defineProperty(exports, "loadGrammarsForLanguages", { enumerable: true, get: function () { return extraction_2.loadGrammarsForLanguages; } });
94
+ Object.defineProperty(exports, "loadAllGrammars", { enumerable: true, get: function () { return extraction_2.loadAllGrammars; } });
95
+ var brief_link_resolver_2 = require("./resolution/brief-link-resolver");
96
+ Object.defineProperty(exports, "computeSpecFunnel", { enumerable: true, get: function () { return brief_link_resolver_2.computeSpecFunnel; } });
97
+ Object.defineProperty(exports, "resolveBriefLink", { enumerable: true, get: function () { return brief_link_resolver_2.resolveBriefLink; } });
98
+ Object.defineProperty(exports, "summarizeBriefFunnel", { enumerable: true, get: function () { return brief_link_resolver_2.summarizeBriefFunnel; } });
99
+ Object.defineProperty(exports, "findBriefsForSpec", { enumerable: true, get: function () { return brief_link_resolver_2.findBriefsForSpec; } });
100
+ var domain_gap_seed_2 = require("./resolution/domain-gap-seed");
101
+ Object.defineProperty(exports, "computeDomainGapSeed", { enumerable: true, get: function () { return domain_gap_seed_2.computeDomainGapSeed; } });
102
+ // Reflection engine (REFLECT-DOC) — proposals mined from transcripts.
103
+ var reflect_2 = require("./reflect");
104
+ Object.defineProperty(exports, "reflectAnalyze", { enumerable: true, get: function () { return reflect_2.analyze; } });
105
+ Object.defineProperty(exports, "reflectSweep", { enumerable: true, get: function () { return reflect_2.sweep; } });
106
+ Object.defineProperty(exports, "ReflectStore", { enumerable: true, get: function () { return reflect_2.ReflectStore; } });
107
+ Object.defineProperty(exports, "previewProposal", { enumerable: true, get: function () { return reflect_2.previewProposal; } });
108
+ Object.defineProperty(exports, "applyProposal", { enumerable: true, get: function () { return reflect_2.applyProposal; } });
109
+ Object.defineProperty(exports, "undoProposal", { enumerable: true, get: function () { return reflect_2.undoProposal; } });
110
+ // Maintainability harness (MAINT-DOC / REQ-MAINT-001).
111
+ var maintainability_2 = require("./graph/maintainability");
112
+ Object.defineProperty(exports, "computeMaintainability", { enumerable: true, get: function () { return maintainability_2.computeMaintainability; } });
113
+ Object.defineProperty(exports, "resolveThresholds", { enumerable: true, get: function () { return maintainability_2.resolveThresholds; } });
114
+ Object.defineProperty(exports, "resolveExclude", { enumerable: true, get: function () { return maintainability_2.resolveExclude; } });
115
+ Object.defineProperty(exports, "DEFAULT_THRESHOLDS", { enumerable: true, get: function () { return maintainability_2.DEFAULT_THRESHOLDS; } });
116
+ Object.defineProperty(exports, "DEFAULT_EXCLUDE", { enumerable: true, get: function () { return maintainability_2.DEFAULT_EXCLUDE; } });
117
+ Object.defineProperty(exports, "CONFIG_FILE_NAME", { enumerable: true, get: function () { return maintainability_2.CONFIG_FILE_NAME; } });
118
+ Object.defineProperty(exports, "HIGH_PRECISION_CLASSES", { enumerable: true, get: function () { return maintainability_2.HIGH_PRECISION_CLASSES; } });
119
+ Object.defineProperty(exports, "LOW_CONFIDENCE_CLASSES", { enumerable: true, get: function () { return maintainability_2.LOW_CONFIDENCE_CLASSES; } });
120
+ Object.defineProperty(exports, "highPrecisionClean", { enumerable: true, get: function () { return maintainability_2.highPrecisionClean; } });
121
+ // Architecture-fitness harness (FITNESS-DOC / REQ-FITNESS-001…003).
122
+ var fitness_2 = require("./fitness/fitness");
123
+ Object.defineProperty(exports, "evaluateFitness", { enumerable: true, get: function () { return fitness_2.evaluateFitness; } });
124
+ Object.defineProperty(exports, "loadFitnessRules", { enumerable: true, get: function () { return fitness_2.loadFitnessRules; } });
125
+ Object.defineProperty(exports, "FITNESS_CONFIG_FILE", { enumerable: true, get: function () { return fitness_2.FITNESS_CONFIG_FILE; } });
126
+ // Enforcement mode (ENFORCE-DOC / REQ-ENFORCE-001…003).
127
+ var enforce_2 = require("./enforce/enforce");
128
+ Object.defineProperty(exports, "evaluateEnforcement", { enumerable: true, get: function () { return enforce_2.evaluateEnforcement; } });
129
+ Object.defineProperty(exports, "loadEnforceConfig", { enumerable: true, get: function () { return enforce_2.loadEnforceConfig; } });
130
+ Object.defineProperty(exports, "ENFORCE_CONFIG_FILE", { enumerable: true, get: function () { return enforce_2.ENFORCE_CONFIG_FILE; } });
131
+ // Behaviour surface (BEHAVIOUR-DOC / REQ-BEHAVIOUR-001).
132
+ var behaviour_surface_2 = require("./behaviour/behaviour-surface");
133
+ Object.defineProperty(exports, "computeBehaviourSurface", { enumerable: true, get: function () { return behaviour_surface_2.computeBehaviourSurface; } });
134
+ Object.defineProperty(exports, "renderBehaviourSurface", { enumerable: true, get: function () { return behaviour_surface_2.renderBehaviourSurface; } });
135
+ Object.defineProperty(exports, "isUiNode", { enumerable: true, get: function () { return behaviour_surface_2.isUiNode; } });
136
+ var errors_1 = require("./errors");
137
+ Object.defineProperty(exports, "SpecShipError", { enumerable: true, get: function () { return errors_1.SpecShipError; } });
138
+ Object.defineProperty(exports, "FileError", { enumerable: true, get: function () { return errors_1.FileError; } });
139
+ Object.defineProperty(exports, "ParseError", { enumerable: true, get: function () { return errors_1.ParseError; } });
140
+ Object.defineProperty(exports, "DatabaseError", { enumerable: true, get: function () { return errors_1.DatabaseError; } });
141
+ Object.defineProperty(exports, "SearchError", { enumerable: true, get: function () { return errors_1.SearchError; } });
142
+ Object.defineProperty(exports, "VectorError", { enumerable: true, get: function () { return errors_1.VectorError; } });
143
+ Object.defineProperty(exports, "ConfigError", { enumerable: true, get: function () { return errors_1.ConfigError; } });
144
+ Object.defineProperty(exports, "setLogger", { enumerable: true, get: function () { return errors_1.setLogger; } });
145
+ Object.defineProperty(exports, "getLogger", { enumerable: true, get: function () { return errors_1.getLogger; } });
146
+ Object.defineProperty(exports, "silentLogger", { enumerable: true, get: function () { return errors_1.silentLogger; } });
147
+ Object.defineProperty(exports, "defaultLogger", { enumerable: true, get: function () { return errors_1.defaultLogger; } });
148
+ var utils_2 = require("./utils");
149
+ Object.defineProperty(exports, "Mutex", { enumerable: true, get: function () { return utils_2.Mutex; } });
150
+ Object.defineProperty(exports, "FileLock", { enumerable: true, get: function () { return utils_2.FileLock; } });
151
+ Object.defineProperty(exports, "processInBatches", { enumerable: true, get: function () { return utils_2.processInBatches; } });
152
+ Object.defineProperty(exports, "debounce", { enumerable: true, get: function () { return utils_2.debounce; } });
153
+ Object.defineProperty(exports, "throttle", { enumerable: true, get: function () { return utils_2.throttle; } });
154
+ Object.defineProperty(exports, "MemoryMonitor", { enumerable: true, get: function () { return utils_2.MemoryMonitor; } });
155
+ var sync_2 = require("./sync");
156
+ Object.defineProperty(exports, "FileWatcher", { enumerable: true, get: function () { return sync_2.FileWatcher; } });
157
+ Object.defineProperty(exports, "LockUnavailableError", { enumerable: true, get: function () { return sync_2.LockUnavailableError; } });
158
+ var mcp_1 = require("./mcp");
159
+ Object.defineProperty(exports, "MCPServer", { enumerable: true, get: function () { return mcp_1.MCPServer; } });
160
+ /**
161
+ * Main SpecShip class
162
+ *
163
+ * Provides the primary interface for interacting with the code knowledge graph.
164
+ */
165
+ class SpecShip {
166
+ db;
167
+ queries;
168
+ specQueries;
169
+ projectRoot;
170
+ orchestrator;
171
+ resolver;
172
+ specLinkResolver;
173
+ graphManager;
174
+ traverser;
175
+ contextBuilder;
176
+ // Mutex for preventing concurrent indexing operations (in-process)
177
+ indexMutex = new utils_1.Mutex();
178
+ // File lock for preventing concurrent writes across processes (CLI, MCP, git hooks)
179
+ fileLock;
180
+ // File watcher for auto-sync on file changes
181
+ watcher = null;
182
+ constructor(db, queries, projectRoot) {
183
+ this.db = db;
184
+ this.queries = queries;
185
+ this.specQueries = new spec_queries_1.SpecQueries(db.getDb());
186
+ this.projectRoot = projectRoot;
187
+ this.fileLock = new utils_1.FileLock(path.join((0, directory_1.getSpecShipDir)(projectRoot), 'specship.lock'));
188
+ this.orchestrator = new extraction_1.ExtractionOrchestrator(projectRoot, queries);
189
+ this.resolver = (0, resolution_1.createResolver)(projectRoot, queries);
190
+ this.specLinkResolver = new spec_link_resolver_1.SpecLinkResolver(queries, this.specQueries);
191
+ this.graphManager = new graph_1.GraphQueryManager(queries);
192
+ this.traverser = new graph_1.GraphTraverser(queries);
193
+ this.contextBuilder = (0, context_1.createContextBuilder)(projectRoot, queries, this.traverser);
194
+ }
195
+ /** Access to the spec queries (for MCP tools, CLI commands, embedded SDK users). */
196
+ getSpecQueries() {
197
+ return this.specQueries;
198
+ }
199
+ /** Access to the spec link resolver. */
200
+ getSpecLinkResolver() {
201
+ return this.specLinkResolver;
202
+ }
203
+ /**
204
+ * The project-wide spec lifecycle funnel: brainstormed ideas → specs →
205
+ * implemented, with per-document rollups (REQ-FUNNEL-006). Exposed on the
206
+ * instance so the desktop server can serve it without runtime-importing the
207
+ * package (it calls this on the dynamically-loaded SpecShip).
208
+ */
209
+ getSpecFunnel() {
210
+ return (0, brief_link_resolver_1.computeSpecFunnel)(this.specQueries);
211
+ }
212
+ /**
213
+ * The domain gap-seed (REQ-DOMAIN-003): the structural code entities and
214
+ * non-domain specs that no domain fact yet covers, plus a coverage tally.
215
+ * Read-only — computed from live state, writes nothing. Exposed on the
216
+ * instance so the `/ss-spec domain` command and the desktop server can drive it
217
+ * without runtime-importing the package.
218
+ */
219
+ getDomainGapSeed() {
220
+ return (0, domain_gap_seed_1.computeDomainGapSeed)(this.queries, this.specQueries, this.specLinkResolver);
221
+ }
222
+ /**
223
+ * The maintainability harness (REQ-MAINT-001): coupling, size hotspots,
224
+ * dependency cycles, and dead-code candidates, derived from the graph with no
225
+ * additional parse. Read-only and deterministic. Exposed on the instance so
226
+ * the CLI / MCP / desktop server can drive it without runtime-importing the
227
+ * package.
228
+ */
229
+ getMaintainability(thresholds) {
230
+ return (0, maintainability_1.computeMaintainability)(this.queries, (0, maintainability_1.resolveThresholds)(this.projectRoot, thresholds), (0, maintainability_1.resolveExclude)(this.projectRoot));
231
+ }
232
+ /**
233
+ * The architecture-fitness harness (REQ-FITNESS-001/002): evaluate declarative
234
+ * architecture rules (from specship.config.json `fitness.rules`, or an explicit
235
+ * override) against the graph. Read-only, deterministic. Exposed on the
236
+ * instance so the CLI / MCP / server drive it without runtime-importing the
237
+ * package.
238
+ */
239
+ getFitness(rules) {
240
+ return (0, fitness_1.evaluateFitness)(this.queries, rules ?? (0, fitness_1.loadFitnessRules)(this.projectRoot));
241
+ }
242
+ /**
243
+ * Enforcement mode (REQ-ENFORCE-001/002/003): compose drift + fitness +
244
+ * maintainability + the spec→test→verify behaviour chain into one gate. Which
245
+ * checks gate vs advise comes from specship.config.json `enforce` (or an
246
+ * explicit override); with no config every check is advisory and the run
247
+ * passes. The behaviour chain reads `tests`-kind spec-links on each requirement
248
+ * and its acceptance criteria (verified = passing, broken = ran-and-failed).
249
+ */
250
+ getEnforce(config) {
251
+ const cfg = config ?? (0, enforce_1.loadEnforceConfig)(this.projectRoot);
252
+ const sq = this.specQueries;
253
+ const drift = sq.getLinksByState(['drifted', 'broken', 'orphaned']);
254
+ const requirements = sq.getSpecsByKind('requirement').map((req) => {
255
+ const testsLinks = sq.getLinksBySpec(req.id).filter((l) => l.kind === 'tests');
256
+ for (const child of sq.getSpecsByParent(req.id)) {
257
+ if (child.kind === 'acceptance') {
258
+ testsLinks.push(...sq.getLinksBySpec(child.id).filter((l) => l.kind === 'tests'));
259
+ }
260
+ }
261
+ return { id: req.id, title: req.title, testsLinks };
262
+ });
263
+ return (0, enforce_1.evaluateEnforcement)({ drift, fitness: this.getFitness(), maintainability: this.getMaintainability(), requirements }, cfg);
264
+ }
265
+ /**
266
+ * The behaviour surface for a requirement (REQ-BEHAVIOUR-001): its linked code
267
+ * plus the 1-hop route / component / handler neighbourhood, grouped UI vs
268
+ * backend, so the `/ss-behaviour` skill can author end-to-end tests from one
269
+ * call. Lives here as an instance method so the CLI / MCP / server drive it
270
+ * without runtime-importing the package. A requirement (or its acceptance
271
+ * children) supplies the linked nodes; their callers + callees supply the
272
+ * neighbourhood.
273
+ */
274
+ getBehaviourSurface(specId) {
275
+ const sq = this.specQueries;
276
+ const req = sq.getSpecById(specId);
277
+ if (!req) {
278
+ return (0, behaviour_surface_1.computeBehaviourSurface)({
279
+ requirementId: specId,
280
+ requirementExists: false,
281
+ linkedNodes: [],
282
+ neighbourNodes: [],
283
+ });
284
+ }
285
+ // Resolved nodes the requirement + its acceptance children link to.
286
+ const linkIds = new Set();
287
+ const collect = (id) => {
288
+ for (const l of sq.getLinksBySpec(id)) {
289
+ if (l.resolvedNodeId)
290
+ linkIds.add(l.resolvedNodeId);
291
+ }
292
+ };
293
+ collect(req.id);
294
+ for (const child of sq.getSpecsByParent(req.id)) {
295
+ if (child.kind === 'acceptance')
296
+ collect(child.id);
297
+ }
298
+ const linkedNodes = [];
299
+ for (const id of linkIds) {
300
+ const node = this.queries.getNodeById(id);
301
+ if (node)
302
+ linkedNodes.push(node);
303
+ }
304
+ // 1-hop caller/callee neighbourhood of the linked nodes.
305
+ const neighbourById = new Map();
306
+ for (const node of linkedNodes) {
307
+ for (const { node: n } of this.traverser.getCallers(node.id, 1))
308
+ neighbourById.set(n.id, n);
309
+ for (const { node: n } of this.traverser.getCallees(node.id, 1))
310
+ neighbourById.set(n.id, n);
311
+ }
312
+ return (0, behaviour_surface_1.computeBehaviourSurface)({
313
+ requirementId: req.id,
314
+ requirementExists: true,
315
+ linkedNodes,
316
+ neighbourNodes: [...neighbourById.values()],
317
+ });
318
+ }
319
+ // ===========================================================================
320
+ // Reflection engine (REFLECT-DOC)
321
+ //
322
+ // Mines the ingested claude_* transcript tables for recurring, actionable
323
+ // patterns and turns them into durable, human-gated proposals. Exposed as
324
+ // instance methods so the desktop server drives them on the live instance
325
+ // (no runtime package import) and the CLI calls them directly.
326
+ // ===========================================================================
327
+ reflectContext() {
328
+ return { projectRoot: this.projectRoot, homeDir: os.homedir() };
329
+ }
330
+ /** Run a reflection pass, persist the batch, return the open proposals. */
331
+ reflectAnalyze() {
332
+ return (0, reflect_1.analyze)(this.db.getDb(), this.reflectContext());
333
+ }
334
+ /** Run a sweep: analyze + return new high-severity proposals to notify on. */
335
+ reflectSweep() {
336
+ return (0, reflect_1.sweep)(this.db.getDb(), this.reflectContext());
337
+ }
338
+ /** List persisted proposals, optionally filtered by state. */
339
+ reflectList(state) {
340
+ return new reflect_1.ReflectStore(this.db.getDb()).list(state);
341
+ }
342
+ /** Fetch one proposal by its content hash. */
343
+ reflectGet(hash) {
344
+ return new reflect_1.ReflectStore(this.db.getDb()).get(hash);
345
+ }
346
+ /** Non-mutating preview of the change a proposal would make (REQ-REFLECT-003). */
347
+ reflectPreview(hash) {
348
+ const p = this.reflectGet(hash);
349
+ return p ? (0, reflect_1.previewProposal)(p) : null;
350
+ }
351
+ /** Apply a proposal — write idempotently + reversibly, then record state. */
352
+ reflectApply(hash) {
353
+ const p = this.reflectGet(hash);
354
+ if (!p)
355
+ return null;
356
+ const outcome = (0, reflect_1.applyProposal)(p, os.homedir());
357
+ if (outcome === 'applied' || outcome === 'unchanged') {
358
+ new reflect_1.ReflectStore(this.db.getDb()).setState(hash, 'applied');
359
+ }
360
+ return outcome;
361
+ }
362
+ /** Undo a previously applied proposal — remove exactly what apply added. */
363
+ reflectUndo(hash) {
364
+ const p = this.reflectGet(hash);
365
+ if (!p)
366
+ return null;
367
+ const outcome = (0, reflect_1.undoProposal)(p, os.homedir());
368
+ new reflect_1.ReflectStore(this.db.getDb()).setState(hash, 'undone');
369
+ return outcome;
370
+ }
371
+ /** Dismiss a proposal so it does not resurface on later sweeps (REQ-REFLECT-007.A2). */
372
+ reflectDismiss(hash) {
373
+ const p = this.reflectGet(hash);
374
+ if (!p)
375
+ return false;
376
+ new reflect_1.ReflectStore(this.db.getDb()).setState(hash, 'dismissed');
377
+ return true;
378
+ }
379
+ // ===========================================================================
380
+ // Lifecycle Methods
381
+ // ===========================================================================
382
+ /**
383
+ * Initialize a new SpecShip project
384
+ *
385
+ * Creates the .SpecShip directory, database, and configuration.
386
+ *
387
+ * @param projectRoot - Path to the project root directory
388
+ * @param options - Initialization options
389
+ * @returns A new SpecShip instance
390
+ */
391
+ static async init(projectRoot, options = {}) {
392
+ await (0, extraction_1.initGrammars)();
393
+ const resolvedRoot = path.resolve(projectRoot);
394
+ // Check if already initialized
395
+ if ((0, directory_1.isInitialized)(resolvedRoot)) {
396
+ throw new Error(`SpecShip already initialized in ${resolvedRoot}`);
397
+ }
398
+ // Create directory structure
399
+ (0, directory_1.createDirectory)(resolvedRoot);
400
+ // Initialize database
401
+ const dbPath = (0, db_1.getDatabasePath)(resolvedRoot);
402
+ const db = db_1.DatabaseConnection.initialize(dbPath);
403
+ const queries = new queries_1.QueryBuilder(db.getDb());
404
+ const instance = new SpecShip(db, queries, resolvedRoot);
405
+ // Run initial indexing if requested
406
+ if (options.index) {
407
+ await instance.indexAll({ onProgress: options.onProgress });
408
+ }
409
+ return instance;
410
+ }
411
+ /**
412
+ * Initialize synchronously (without indexing)
413
+ */
414
+ static initSync(projectRoot) {
415
+ const resolvedRoot = path.resolve(projectRoot);
416
+ // Check if already initialized
417
+ if ((0, directory_1.isInitialized)(resolvedRoot)) {
418
+ throw new Error(`SpecShip already initialized in ${resolvedRoot}`);
419
+ }
420
+ // Create directory structure
421
+ (0, directory_1.createDirectory)(resolvedRoot);
422
+ // Initialize database
423
+ const dbPath = (0, db_1.getDatabasePath)(resolvedRoot);
424
+ const db = db_1.DatabaseConnection.initialize(dbPath);
425
+ const queries = new queries_1.QueryBuilder(db.getDb());
426
+ return new SpecShip(db, queries, resolvedRoot);
427
+ }
428
+ /**
429
+ * Open an existing SpecShip project
430
+ *
431
+ * @param projectRoot - Path to the project root directory
432
+ * @param options - Open options
433
+ * @returns A SpecShip instance
434
+ */
435
+ static async open(projectRoot, options = {}) {
436
+ await (0, extraction_1.initGrammars)();
437
+ const resolvedRoot = path.resolve(projectRoot);
438
+ // Check if initialized
439
+ if (!(0, directory_1.isInitialized)(resolvedRoot)) {
440
+ throw new Error(`SpecShip not initialized in ${resolvedRoot}. Run init() first.`);
441
+ }
442
+ // Validate directory structure
443
+ const validation = (0, directory_1.validateDirectory)(resolvedRoot);
444
+ if (!validation.valid) {
445
+ throw new Error(`Invalid SpecShip directory: ${validation.errors.join(', ')}`);
446
+ }
447
+ // Open database
448
+ const dbPath = (0, db_1.getDatabasePath)(resolvedRoot);
449
+ const db = db_1.DatabaseConnection.open(dbPath);
450
+ const queries = new queries_1.QueryBuilder(db.getDb());
451
+ const instance = new SpecShip(db, queries, resolvedRoot);
452
+ // Sync if requested
453
+ if (options.sync) {
454
+ await instance.sync();
455
+ }
456
+ return instance;
457
+ }
458
+ /**
459
+ * Open synchronously (without sync)
460
+ */
461
+ static openSync(projectRoot) {
462
+ const resolvedRoot = path.resolve(projectRoot);
463
+ // Check if initialized
464
+ if (!(0, directory_1.isInitialized)(resolvedRoot)) {
465
+ throw new Error(`SpecShip not initialized in ${resolvedRoot}. Run init() first.`);
466
+ }
467
+ // Validate directory structure
468
+ const validation = (0, directory_1.validateDirectory)(resolvedRoot);
469
+ if (!validation.valid) {
470
+ throw new Error(`Invalid SpecShip directory: ${validation.errors.join(', ')}`);
471
+ }
472
+ // Open database
473
+ const dbPath = (0, db_1.getDatabasePath)(resolvedRoot);
474
+ const db = db_1.DatabaseConnection.open(dbPath);
475
+ const queries = new queries_1.QueryBuilder(db.getDb());
476
+ return new SpecShip(db, queries, resolvedRoot);
477
+ }
478
+ /**
479
+ * Check if a directory has been initialized as a SpecShip project
480
+ */
481
+ static isInitialized(projectRoot) {
482
+ return (0, directory_1.isInitialized)(path.resolve(projectRoot));
483
+ }
484
+ /**
485
+ * Close the SpecShip instance and release resources
486
+ */
487
+ close() {
488
+ this.unwatch();
489
+ // Release file lock if held
490
+ this.fileLock.release();
491
+ this.db.close();
492
+ }
493
+ /**
494
+ * Get the project root directory
495
+ */
496
+ getProjectRoot() {
497
+ return this.projectRoot;
498
+ }
499
+ // ===========================================================================
500
+ // Indexing
501
+ // ===========================================================================
502
+ /**
503
+ * Index all files in the project
504
+ *
505
+ * Uses a mutex to prevent concurrent indexing operations.
506
+ */
507
+ async indexAll(options = {}) {
508
+ return this.indexMutex.withLock(async () => {
509
+ try {
510
+ this.fileLock.acquire();
511
+ }
512
+ catch {
513
+ return { success: false, filesIndexed: 0, filesSkipped: 0, filesErrored: 0, nodesCreated: 0, edgesCreated: 0, errors: [{ message: 'Could not acquire file lock - another process may be indexing', severity: 'error' }], durationMs: 0 };
514
+ }
515
+ try {
516
+ const before = this.queries.getNodeAndEdgeCount();
517
+ const result = await this.orchestrator.indexAll(options.onProgress, options.signal, options.verbose);
518
+ // Re-detect frameworks now that the index is populated. The resolver
519
+ // is constructed with createResolver() before any files exist, so
520
+ // framework resolvers whose detect() consults the indexed file list
521
+ // (e.g. UIKit/SwiftUI scanning for imports, swift-objc-bridge looking
522
+ // for both Swift and ObjC files) all return false on that initial pass
523
+ // and silently drop themselves. Re-initializing here gives them a
524
+ // chance to see the actual project before resolution runs.
525
+ if (result.success && result.filesIndexed > 0) {
526
+ this.resolver.initialize();
527
+ // Cross-file finalization (e.g. NestJS RouterModule prefixes). Runs
528
+ // before resolution so updated names show up in subsequent reads.
529
+ this.resolver.runPostExtract();
530
+ }
531
+ // Resolve references to create call/import/extends edges
532
+ if (result.success && result.filesIndexed > 0) {
533
+ // Get count without loading all refs into memory
534
+ const unresolvedCount = this.queries.getUnresolvedReferencesCount();
535
+ options.onProgress?.({
536
+ phase: 'resolving',
537
+ current: 0,
538
+ total: unresolvedCount,
539
+ });
540
+ await this.resolveReferencesBatched((current, total) => {
541
+ options.onProgress?.({
542
+ phase: 'resolving',
543
+ current,
544
+ total,
545
+ });
546
+ });
547
+ }
548
+ // Refresh planner stats + checkpoint the WAL after bulk writes.
549
+ // Cheap and non-blocking; never load-bearing for correctness.
550
+ if (result.success && result.filesIndexed > 0) {
551
+ this.db.runMaintenance();
552
+ }
553
+ // Spec extraction runs after code so spec-declared `implementations:`
554
+ // links can resolve against the freshly-indexed nodes. Code-comment
555
+ // links also get scanned here. Best-effort: a spec parse error never
556
+ // fails the overall index.
557
+ if (result.success) {
558
+ try {
559
+ // Release the lock before re-acquiring inside indexSpecs (mutex
560
+ // is re-entrant via withLock chaining; the file lock isn't).
561
+ this.fileLock.release();
562
+ await this.indexSpecsInternal();
563
+ // Re-acquire so the outer finally can release once.
564
+ this.fileLock.acquire();
565
+ }
566
+ catch (err) {
567
+ // Spec failures are non-fatal in v1. Surface via errors array.
568
+ result.errors.push({
569
+ message: `Spec indexing failed: ${err instanceof Error ? err.message : String(err)}`,
570
+ severity: 'warning',
571
+ });
572
+ }
573
+ }
574
+ // The orchestrator only sees extraction-phase counts; resolution and
575
+ // synthesizer edges (often >50% of the graph on JVM repos) come later.
576
+ // Recompute against the DB so the CLI summary reports the true totals.
577
+ if (result.success && result.filesIndexed > 0) {
578
+ const after = this.queries.getNodeAndEdgeCount();
579
+ result.nodesCreated = after.nodes - before.nodes;
580
+ result.edgesCreated = after.edges - before.edges;
581
+ }
582
+ this.refreshStatuslineCache();
583
+ return result;
584
+ }
585
+ finally {
586
+ this.fileLock.release();
587
+ }
588
+ });
589
+ }
590
+ /**
591
+ * Refresh `.specship/statusline.json` so the `specship statusline` segment
592
+ * has current Tier-A data without ever opening the DB itself
593
+ * (REQ-STATUSLINE-003). Best-effort: a failure here must never break the
594
+ * index/sync operation that triggered it, so the producer swallows its own
595
+ * errors and this wrapper guards the data-gathering too.
596
+ */
597
+ refreshStatuslineCache() {
598
+ try {
599
+ const stats = this.getStats();
600
+ const changes = this.getChangedFiles();
601
+ const drift = this.specQueries.getLinksByState(['drifted', 'broken', 'orphaned']).length;
602
+ (0, statusline_1.writeStatuslineCache)(this.projectRoot, {
603
+ initialized: true,
604
+ pending: {
605
+ added: changes.added.length,
606
+ modified: changes.modified.length,
607
+ removed: changes.removed.length,
608
+ },
609
+ drift,
610
+ backend: this.getBackend(),
611
+ degraded: this.getJournalMode() !== 'wal',
612
+ fileCount: stats.fileCount,
613
+ nodeCount: stats.nodeCount,
614
+ lastIndexed: this.getLastIndexedAt(),
615
+ });
616
+ }
617
+ catch {
618
+ /* best-effort — never let a cache refresh affect indexing */
619
+ }
620
+ }
621
+ /**
622
+ * Internal spec indexing — does NOT take the indexMutex (caller already holds it)
623
+ * and does NOT take the fileLock. Used by indexAll which manages locks itself.
624
+ */
625
+ async indexSpecsInternal() {
626
+ const specRoots = this.defaultSpecRoots();
627
+ if (specRoots.length === 0)
628
+ return;
629
+ const specFiles = [];
630
+ for (const root of specRoots) {
631
+ this.collectSpecFiles(root, specFiles);
632
+ }
633
+ for (const absPath of specFiles) {
634
+ const rel = path.relative(this.projectRoot, absPath);
635
+ let source;
636
+ let stat;
637
+ try {
638
+ source = fs.readFileSync(absPath, 'utf-8');
639
+ stat = fs.statSync(absPath);
640
+ }
641
+ catch {
642
+ continue;
643
+ }
644
+ const hashHex = (0, crypto_1.createHash)('sha256').update(source).digest('hex').substring(0, 32);
645
+ const existing = this.specQueries.getSpecFileByPath(rel);
646
+ if (existing && existing.contentHash === hashHex)
647
+ continue;
648
+ this.specQueries.deleteSpecsByFile(rel);
649
+ const result = new markdown_spec_extractor_1.MarkdownSpecExtractor(rel, source).extract();
650
+ this.specQueries.insertSpecsBatch(result.specs);
651
+ this.specQueries.upsertSpecFile({
652
+ path: rel,
653
+ contentHash: hashHex,
654
+ format: 'markdown',
655
+ size: stat.size,
656
+ modifiedAt: stat.mtimeMs,
657
+ indexedAt: Date.now(),
658
+ specCount: result.specs.length,
659
+ errors: result.errors,
660
+ });
661
+ const specsById = new Map(result.specs.map((s) => [s.id, s]));
662
+ this.specLinkResolver.applyDeclarationCandidates(result.linkCandidates, specsById);
663
+ for (const spec of result.specs) {
664
+ this.specLinkResolver.markSpecDrifted(spec.id, spec.contentHash);
665
+ }
666
+ }
667
+ const allFiles = this.queries.getAllFiles().map((f) => f.path);
668
+ this.specLinkResolver.applyCodeCommentLinks(allFiles);
669
+ this.specLinkResolver.resolveAll();
670
+ }
671
+ /**
672
+ * Index spec files (Markdown only in v1).
673
+ *
674
+ * Default spec roots: `<projectRoot>/specs/` if it exists. Callers can
675
+ * pass explicit roots/files for non-default layouts.
676
+ *
677
+ * Pipeline per file:
678
+ * 1. Hash file content; skip if `spec_files.content_hash` matches.
679
+ * 2. Delete prior specs for this file (cascade-deletes children, links).
680
+ * 3. Run MarkdownSpecExtractor → insert specs + virtual node projections.
681
+ * 4. Apply `spec-declaration` link candidates from `implementations:`.
682
+ * 5. Mark previously-linked specs as drifted (drift_axis='spec') when
683
+ * their content_hash has changed.
684
+ *
685
+ * Returns extraction stats including spec link resolver effects.
686
+ */
687
+ async indexSpecs(roots) {
688
+ const start = Date.now();
689
+ return this.indexMutex.withLock(async () => {
690
+ try {
691
+ this.fileLock.acquire();
692
+ }
693
+ catch {
694
+ return {
695
+ filesProcessed: 0,
696
+ filesSkipped: 0,
697
+ specsExtracted: 0,
698
+ linkCandidates: 0,
699
+ resolverStats: {
700
+ scanned: 0,
701
+ reresolved: 0,
702
+ orphaned: 0,
703
+ driftedCode: 0,
704
+ candidatesApplied: 0,
705
+ commentLinksApplied: 0,
706
+ },
707
+ errors: 0,
708
+ durationMs: Date.now() - start,
709
+ };
710
+ }
711
+ try {
712
+ const specRoots = roots && roots.length > 0 ? roots : this.defaultSpecRoots();
713
+ const specFiles = [];
714
+ for (const root of specRoots) {
715
+ this.collectSpecFiles(root, specFiles);
716
+ }
717
+ let processed = 0;
718
+ let skipped = 0;
719
+ let totalSpecs = 0;
720
+ let totalCandidates = 0;
721
+ let totalErrors = 0;
722
+ const stats = {
723
+ scanned: 0,
724
+ reresolved: 0,
725
+ orphaned: 0,
726
+ driftedCode: 0,
727
+ candidatesApplied: 0,
728
+ commentLinksApplied: 0,
729
+ };
730
+ for (const absPath of specFiles) {
731
+ const rel = path.relative(this.projectRoot, absPath);
732
+ let source;
733
+ let stat;
734
+ try {
735
+ source = fs.readFileSync(absPath, 'utf-8');
736
+ stat = fs.statSync(absPath);
737
+ }
738
+ catch {
739
+ continue;
740
+ }
741
+ const hashHex = (0, crypto_1.createHash)('sha256').update(source).digest('hex').substring(0, 32);
742
+ const existing = this.specQueries.getSpecFileByPath(rel);
743
+ if (existing && existing.contentHash === hashHex) {
744
+ skipped++;
745
+ continue;
746
+ }
747
+ // Replace prior specs for this file. CASCADE removes children +
748
+ // spec_links FK'd on spec_id.
749
+ this.specQueries.deleteSpecsByFile(rel);
750
+ const result = new markdown_spec_extractor_1.MarkdownSpecExtractor(rel, source).extract();
751
+ this.specQueries.insertSpecsBatch(result.specs);
752
+ this.specQueries.upsertSpecFile({
753
+ path: rel,
754
+ contentHash: hashHex,
755
+ format: 'markdown',
756
+ size: stat.size,
757
+ modifiedAt: stat.mtimeMs,
758
+ indexedAt: Date.now(),
759
+ specCount: result.specs.length,
760
+ errors: result.errors,
761
+ });
762
+ // Apply spec-declared `implementations:` link candidates.
763
+ const specsById = new Map(result.specs.map((s) => [s.id, s]));
764
+ this.specLinkResolver.applyDeclarationCandidates(result.linkCandidates, specsById, stats);
765
+ // Spec-side drift: if any prior link's specHashAtLink differs from
766
+ // the new contentHash of its spec, flip the link to drifted(spec).
767
+ for (const spec of result.specs) {
768
+ this.specLinkResolver.markSpecDrifted(spec.id, spec.contentHash);
769
+ }
770
+ processed++;
771
+ totalSpecs += result.specs.length;
772
+ totalCandidates += result.linkCandidates.length;
773
+ totalErrors += result.errors.filter((e) => e.severity === 'error').length;
774
+ }
775
+ // After spec changes settle, also scan code docstrings for
776
+ // `@implements REQ-X` markers. Bounded to the files that already
777
+ // have nodes in the graph (full-graph scan is acceptable here —
778
+ // node count is bounded and the scan is O(N) regex over docstrings).
779
+ const allFiles = this.queries.getAllFiles().map((f) => f.path);
780
+ this.specLinkResolver.applyCodeCommentLinks(allFiles, stats);
781
+ // Re-resolve all links (post-extraction).
782
+ const resolveStats = this.specLinkResolver.resolveAll();
783
+ stats.scanned += resolveStats.scanned;
784
+ stats.reresolved += resolveStats.reresolved;
785
+ stats.orphaned += resolveStats.orphaned;
786
+ stats.driftedCode += resolveStats.driftedCode;
787
+ return {
788
+ filesProcessed: processed,
789
+ filesSkipped: skipped,
790
+ specsExtracted: totalSpecs,
791
+ linkCandidates: totalCandidates,
792
+ resolverStats: stats,
793
+ errors: totalErrors,
794
+ durationMs: Date.now() - start,
795
+ };
796
+ }
797
+ finally {
798
+ this.fileLock.release();
799
+ }
800
+ });
801
+ }
802
+ /**
803
+ * Default spec roots: `<projectRoot>/specs/` if it exists. Future
804
+ * iterations can read from `.specship/config.json`.
805
+ */
806
+ defaultSpecRoots() {
807
+ const candidate = path.join(this.projectRoot, 'specs');
808
+ try {
809
+ const stat = fs.statSync(candidate);
810
+ if (stat.isDirectory())
811
+ return [candidate];
812
+ }
813
+ catch {
814
+ // No specs/ directory — return empty so indexSpecs is a no-op.
815
+ }
816
+ return [];
817
+ }
818
+ /**
819
+ * Recursively collect `.md` files from a directory.
820
+ */
821
+ collectSpecFiles(root, out) {
822
+ let entries;
823
+ try {
824
+ entries = fs.readdirSync(root, { withFileTypes: true });
825
+ }
826
+ catch {
827
+ return;
828
+ }
829
+ for (const entry of entries) {
830
+ const full = path.join(root, entry.name);
831
+ if (entry.isDirectory()) {
832
+ // Skip hidden/system directories
833
+ if (entry.name.startsWith('.') || entry.name === 'node_modules')
834
+ continue;
835
+ this.collectSpecFiles(full, out);
836
+ }
837
+ else if (entry.isFile() && entry.name.toLowerCase().endsWith('.md')) {
838
+ out.push(full);
839
+ }
840
+ }
841
+ }
842
+ /**
843
+ * Index specific files
844
+ *
845
+ * Uses a mutex to prevent concurrent indexing operations.
846
+ */
847
+ async indexFiles(filePaths) {
848
+ return this.indexMutex.withLock(async () => {
849
+ try {
850
+ this.fileLock.acquire();
851
+ }
852
+ catch {
853
+ return { success: false, filesIndexed: 0, filesSkipped: 0, filesErrored: 0, nodesCreated: 0, edgesCreated: 0, errors: [{ message: 'Could not acquire file lock - another process may be indexing', severity: 'error' }], durationMs: 0 };
854
+ }
855
+ try {
856
+ return this.orchestrator.indexFiles(filePaths);
857
+ }
858
+ finally {
859
+ this.fileLock.release();
860
+ }
861
+ });
862
+ }
863
+ /**
864
+ * Sync with current file state (incremental update)
865
+ *
866
+ * Uses a mutex to prevent concurrent indexing operations.
867
+ */
868
+ async sync(options = {}) {
869
+ return this.indexMutex.withLock(async () => {
870
+ try {
871
+ this.fileLock.acquire();
872
+ }
873
+ catch {
874
+ return { filesChecked: 0, filesAdded: 0, filesModified: 0, filesRemoved: 0, nodesUpdated: 0, durationMs: 0 };
875
+ }
876
+ try {
877
+ const result = await this.orchestrator.sync(options.onProgress);
878
+ // Cross-file finalization (e.g. NestJS RouterModule prefixes). Run on
879
+ // every sync that touched files so edits to `app.module.ts` propagate
880
+ // to controllers in unchanged files. The pass is idempotent and cheap
881
+ // (regex over *.module.ts only).
882
+ if (result.filesAdded > 0 || result.filesModified > 0) {
883
+ this.resolver.runPostExtract();
884
+ }
885
+ // Resolve references if files were updated
886
+ if (result.filesAdded > 0 || result.filesModified > 0) {
887
+ if (result.changedFilePaths) {
888
+ // Scope resolution to changed files (git fast path — bounded set)
889
+ const unresolvedRefs = this.queries.getUnresolvedReferencesByFiles(result.changedFilePaths);
890
+ options.onProgress?.({
891
+ phase: 'resolving',
892
+ current: 0,
893
+ total: unresolvedRefs.length,
894
+ });
895
+ this.resolver.resolveAndPersist(unresolvedRefs, (current, total) => {
896
+ options.onProgress?.({
897
+ phase: 'resolving',
898
+ current,
899
+ total,
900
+ });
901
+ });
902
+ }
903
+ else {
904
+ // No git info — use batched resolution to avoid OOM
905
+ const unresolvedCount = this.queries.getUnresolvedReferencesCount();
906
+ options.onProgress?.({
907
+ phase: 'resolving',
908
+ current: 0,
909
+ total: unresolvedCount,
910
+ });
911
+ await this.resolveReferencesBatched((current, total) => {
912
+ options.onProgress?.({
913
+ phase: 'resolving',
914
+ current,
915
+ total,
916
+ });
917
+ });
918
+ }
919
+ }
920
+ // Refresh planner stats + checkpoint the WAL after bulk writes.
921
+ if (result.filesAdded > 0 || result.filesModified > 0 || result.filesRemoved > 0) {
922
+ this.db.runMaintenance();
923
+ }
924
+ this.refreshStatuslineCache();
925
+ return result;
926
+ }
927
+ finally {
928
+ this.fileLock.release();
929
+ }
930
+ });
931
+ }
932
+ /**
933
+ * Check if an indexing operation is currently in progress
934
+ */
935
+ isIndexing() {
936
+ return this.indexMutex.isLocked();
937
+ }
938
+ // ===========================================================================
939
+ // File Watching
940
+ // ===========================================================================
941
+ /**
942
+ * Start watching for file changes and auto-syncing.
943
+ *
944
+ * Uses native OS file events (FSEvents on macOS, inotify on Linux 19+,
945
+ * ReadDirectoryChangesW on Windows) with debouncing to avoid thrashing.
946
+ *
947
+ * @param options - Watch options (debounce delay, callbacks)
948
+ * @returns true if watching started successfully
949
+ */
950
+ watch(options = {}) {
951
+ if (this.watcher?.isActive())
952
+ return true;
953
+ this.watcher = new sync_1.FileWatcher(this.projectRoot, async () => {
954
+ const result = await this.sync();
955
+ // sync() returns this exact zero-shape iff it failed to acquire the
956
+ // file lock (a real empty sync always has filesChecked > 0 because
957
+ // scanDirectory ran). Surface that to the watcher as a typed error
958
+ // so it keeps pendingFiles + reschedules instead of clearing them
959
+ // (#449).
960
+ if (result.filesChecked === 0 && result.durationMs === 0) {
961
+ throw new sync_1.LockUnavailableError();
962
+ }
963
+ const filesChanged = result.filesAdded + result.filesModified + result.filesRemoved;
964
+ return { filesChanged, durationMs: result.durationMs };
965
+ }, options);
966
+ return this.watcher.start();
967
+ }
968
+ /**
969
+ * Stop watching for file changes.
970
+ */
971
+ unwatch() {
972
+ if (this.watcher) {
973
+ this.watcher.stop();
974
+ this.watcher = null;
975
+ }
976
+ }
977
+ /**
978
+ * Check if the file watcher is active.
979
+ */
980
+ isWatching() {
981
+ return this.watcher?.isActive() ?? false;
982
+ }
983
+ /**
984
+ * Files seen by the file watcher since the last successful sync —
985
+ * the per-file "stale" signal MCP tools attach to responses so an agent
986
+ * can fall back to {@link Read} for just the affected file without
987
+ * waiting for a debounced sync to complete (issue #403).
988
+ *
989
+ * Returns an empty list when the watcher isn't active, or no events have
990
+ * arrived. Each entry includes `firstSeenMs` and `lastSeenMs` (wall-clock
991
+ * `Date.now()` values) so callers can render "edited Nms ago", plus an
992
+ * `indexing` flag indicating whether the in-flight sync (if any) will
993
+ * absorb that file.
994
+ */
995
+ getPendingFiles() {
996
+ return this.watcher?.getPendingFiles() ?? [];
997
+ }
998
+ /**
999
+ * Resolves once the file watcher has installed its watch set. Useful for
1000
+ * tests that need a deterministic boundary before asserting on
1001
+ * `getPendingFiles()`. Resolves immediately when no watcher is active.
1002
+ */
1003
+ waitUntilWatcherReady(timeoutMs) {
1004
+ return this.watcher ? this.watcher.waitUntilReady(timeoutMs) : Promise.resolve();
1005
+ }
1006
+ /**
1007
+ * Get files that have changed since last index
1008
+ */
1009
+ getChangedFiles() {
1010
+ return this.orchestrator.getChangedFiles();
1011
+ }
1012
+ /**
1013
+ * Most recent index timestamp (ms since epoch) across all tracked files, or
1014
+ * null when nothing is indexed yet. Lets library consumers check index
1015
+ * freshness without shelling out to `specship status --json`. (#329)
1016
+ */
1017
+ getLastIndexedAt() {
1018
+ return this.queries.getLastIndexedAt();
1019
+ }
1020
+ /**
1021
+ * Extract nodes and edges from source code (without storing)
1022
+ */
1023
+ extractFromSource(filePath, source) {
1024
+ return (0, extraction_1.extractFromSource)(filePath, source);
1025
+ }
1026
+ // ===========================================================================
1027
+ // Reference Resolution
1028
+ // ===========================================================================
1029
+ /**
1030
+ * Resolve unresolved references and create edges
1031
+ *
1032
+ * This method takes unresolved references from extraction and attempts
1033
+ * to resolve them using multiple strategies:
1034
+ * - Framework-specific patterns (React, Express, Laravel)
1035
+ * - Import-based resolution
1036
+ * - Name-based symbol matching
1037
+ */
1038
+ resolveReferences(onProgress) {
1039
+ // Get all unresolved references from the database
1040
+ const unresolvedRefs = this.queries.getUnresolvedReferences();
1041
+ return this.resolver.resolveAndPersist(unresolvedRefs, onProgress);
1042
+ }
1043
+ /**
1044
+ * Resolve references in batches to keep memory bounded on large codebases.
1045
+ * Processes chunks of unresolved refs, persisting results after each batch.
1046
+ */
1047
+ async resolveReferencesBatched(onProgress) {
1048
+ return this.resolver.resolveAndPersistBatched(onProgress);
1049
+ }
1050
+ /**
1051
+ * Get detected frameworks in the project
1052
+ */
1053
+ getDetectedFrameworks() {
1054
+ return this.resolver.getDetectedFrameworks();
1055
+ }
1056
+ /**
1057
+ * Re-initialize the resolver (useful after adding new files)
1058
+ */
1059
+ reinitializeResolver() {
1060
+ this.resolver.initialize();
1061
+ }
1062
+ // ===========================================================================
1063
+ // Graph Statistics
1064
+ // ===========================================================================
1065
+ /**
1066
+ * Get statistics about the knowledge graph
1067
+ */
1068
+ getStats() {
1069
+ const stats = this.queries.getStats();
1070
+ stats.dbSizeBytes = this.db.getSize();
1071
+ return stats;
1072
+ }
1073
+ /**
1074
+ * Active SQLite backend for this project's connection (`node-sqlite` — Node's
1075
+ * built-in real-SQLite module). Surfaced via `specship status` and the
1076
+ * `specship_status` MCP tool alongside the effective journal mode.
1077
+ */
1078
+ getBackend() {
1079
+ return this.db.getBackend();
1080
+ }
1081
+ /**
1082
+ * The journal mode actually in effect ('wal', 'delete', …). 'wal' means
1083
+ * readers never block on a concurrent writer; anything else means they can,
1084
+ * which is the precondition for the "database is locked" failures in issue
1085
+ * #238. Surfaced via `specship status` and the `specship_status` MCP tool.
1086
+ */
1087
+ getJournalMode() {
1088
+ return this.db.getJournalMode();
1089
+ }
1090
+ // ===========================================================================
1091
+ // Node Operations
1092
+ // ===========================================================================
1093
+ /**
1094
+ * Get a node by ID
1095
+ */
1096
+ getNode(id) {
1097
+ return this.queries.getNodeById(id);
1098
+ }
1099
+ /**
1100
+ * Get all nodes in a file
1101
+ */
1102
+ getNodesInFile(filePath) {
1103
+ return this.queries.getNodesByFile(filePath);
1104
+ }
1105
+ /**
1106
+ * Get all nodes of a specific kind
1107
+ */
1108
+ getNodesByKind(kind) {
1109
+ return this.queries.getNodesByKind(kind);
1110
+ }
1111
+ /**
1112
+ * Get ALL nodes with an exact name (direct index lookup, not FTS-ranked/capped).
1113
+ * Used to enumerate every overload of a heavily-overloaded name so the specific
1114
+ * definition the caller wants is never dropped below a search cut.
1115
+ */
1116
+ getNodesByName(name) {
1117
+ return this.queries.getNodesByName(name);
1118
+ }
1119
+ /**
1120
+ * Search nodes by text
1121
+ */
1122
+ searchNodes(query, options) {
1123
+ return this.queries.searchNodes(query, options);
1124
+ }
1125
+ /**
1126
+ * Find the project's "primary route file" — the file with the densest
1127
+ * concentration of framework-emitted `route` nodes (≥3 routes, ≥30%
1128
+ * of all non-test routes). Used to inline the routing config in
1129
+ * `specship_explore` responses on small realworld template repos
1130
+ * (rails-realworld, laravel-realworld, drupal-admintoolbar, …) where
1131
+ * Glob+Read of `routes.rb`/`urls.py`/etc. otherwise beats specship.
1132
+ */
1133
+ getTopRouteFile() {
1134
+ return this.queries.getTopRouteFile();
1135
+ }
1136
+ /**
1137
+ * Build a URL → handler routing manifest from the index. Each entry
1138
+ * pairs a route node (URL + method) with its handler function/method
1139
+ * via the `references` edge that framework resolvers emit. Returns
1140
+ * null when fewer than 3 valid (non-test) routes exist.
1141
+ */
1142
+ getRoutingManifest(limit) {
1143
+ return this.queries.getRoutingManifest(limit);
1144
+ }
1145
+ // ===========================================================================
1146
+ // Edge Operations
1147
+ // ===========================================================================
1148
+ /**
1149
+ * Get outgoing edges from a node
1150
+ */
1151
+ getOutgoingEdges(nodeId) {
1152
+ return this.queries.getOutgoingEdges(nodeId);
1153
+ }
1154
+ /**
1155
+ * Get incoming edges to a node
1156
+ */
1157
+ getIncomingEdges(nodeId) {
1158
+ return this.queries.getIncomingEdges(nodeId);
1159
+ }
1160
+ // ===========================================================================
1161
+ // File Operations
1162
+ // ===========================================================================
1163
+ /**
1164
+ * Get a file record by path
1165
+ */
1166
+ getFile(filePath) {
1167
+ return this.queries.getFileByPath(filePath);
1168
+ }
1169
+ /**
1170
+ * Get all tracked files
1171
+ */
1172
+ getFiles() {
1173
+ return this.queries.getAllFiles();
1174
+ }
1175
+ /**
1176
+ * Estimate the set of files an agent would have needed to Read if it had
1177
+ * NOT used the SpecShip graph to answer a query involving `symbols`.
1178
+ *
1179
+ * For each symbol name in `symbols`, `getNodesByName` is called (exact-match,
1180
+ * no FTS) and the distinct project-relative file paths of the returned nodes
1181
+ * are collected, capped at 5 files per symbol to avoid god-name blowup (a
1182
+ * single overly-common name like `handle` should not pull in the whole repo).
1183
+ * File paths are then deduped across all symbols and each path's byte size is
1184
+ * looked up via `getFile(path)`.
1185
+ *
1186
+ * Returns:
1187
+ * - `files`: array of `{ path: string; size: number }` with project-relative
1188
+ * paths (matching `Node.filePath` / `FileRecord.path`). Callers can dedup
1189
+ * across multiple calls before summing.
1190
+ * - `resolved`: `true` when at least one file was found; `false` is the
1191
+ * safe "we couldn't estimate, claim nothing" sentinel.
1192
+ *
1193
+ * Synchronous — the graph is already open in memory like other query methods.
1194
+ */
1195
+ estimateReadEquivalent(symbols) {
1196
+ // Cap per-symbol file count to prevent a god-name (e.g. "handle") from
1197
+ // pulling in hundreds of files and inflating the estimate.
1198
+ const MAX_FILES_PER_SYMBOL = 5;
1199
+ // Use a Map to dedup file paths across all symbols while preserving size.
1200
+ const fileMap = new Map();
1201
+ for (const sym of symbols) {
1202
+ const nodes = this.getNodesByName(sym);
1203
+ let countForSymbol = 0;
1204
+ for (const node of nodes) {
1205
+ if (countForSymbol >= MAX_FILES_PER_SYMBOL)
1206
+ break;
1207
+ const filePath = node.filePath;
1208
+ if (fileMap.has(filePath)) {
1209
+ // Already known — still counts toward the per-symbol cap.
1210
+ countForSymbol++;
1211
+ continue;
1212
+ }
1213
+ const fileRecord = this.getFile(filePath);
1214
+ if (!fileRecord)
1215
+ continue; // node points to a file not tracked — skip
1216
+ fileMap.set(filePath, fileRecord.size);
1217
+ countForSymbol++;
1218
+ }
1219
+ }
1220
+ const files = Array.from(fileMap.entries()).map(([p, size]) => ({ path: p, size }));
1221
+ return { files, resolved: files.length > 0 };
1222
+ }
1223
+ // ===========================================================================
1224
+ // Graph Query Methods
1225
+ // ===========================================================================
1226
+ /**
1227
+ * Get the context for a node (ancestors, children, references)
1228
+ *
1229
+ * Returns comprehensive context about a node including its containment
1230
+ * hierarchy, children, incoming/outgoing references, type information,
1231
+ * and relevant imports.
1232
+ *
1233
+ * @param nodeId - ID of the focal node
1234
+ * @returns Context object with all related information
1235
+ */
1236
+ getContext(nodeId) {
1237
+ return this.graphManager.getContext(nodeId);
1238
+ }
1239
+ /**
1240
+ * Traverse the graph from a starting node
1241
+ *
1242
+ * Uses breadth-first search by default. Supports filtering by edge types,
1243
+ * node types, and traversal direction.
1244
+ *
1245
+ * @param startId - Starting node ID
1246
+ * @param options - Traversal options
1247
+ * @returns Subgraph containing traversed nodes and edges
1248
+ */
1249
+ traverse(startId, options) {
1250
+ return this.traverser.traverseBFS(startId, options);
1251
+ }
1252
+ /**
1253
+ * Get the call graph for a function
1254
+ *
1255
+ * Returns both callers (functions that call this function) and
1256
+ * callees (functions called by this function) up to the specified depth.
1257
+ *
1258
+ * @param nodeId - ID of the function/method node
1259
+ * @param depth - Maximum depth in each direction (default: 2)
1260
+ * @returns Subgraph containing the call graph
1261
+ */
1262
+ getCallGraph(nodeId, depth = 2) {
1263
+ return this.traverser.getCallGraph(nodeId, depth);
1264
+ }
1265
+ /**
1266
+ * Get the type hierarchy for a class/interface
1267
+ *
1268
+ * Returns both ancestors (types this extends/implements) and
1269
+ * descendants (types that extend/implement this).
1270
+ *
1271
+ * @param nodeId - ID of the class/interface node
1272
+ * @returns Subgraph containing the type hierarchy
1273
+ */
1274
+ getTypeHierarchy(nodeId) {
1275
+ return this.traverser.getTypeHierarchy(nodeId);
1276
+ }
1277
+ /**
1278
+ * Find all usages of a symbol
1279
+ *
1280
+ * Returns all nodes that reference the specified symbol through
1281
+ * any edge type (calls, references, type_of, etc.).
1282
+ *
1283
+ * @param nodeId - ID of the symbol node
1284
+ * @returns Array of nodes and edges that reference this symbol
1285
+ */
1286
+ findUsages(nodeId) {
1287
+ return this.traverser.findUsages(nodeId);
1288
+ }
1289
+ /**
1290
+ * Get callers of a function/method
1291
+ *
1292
+ * @param nodeId - ID of the function/method node
1293
+ * @param maxDepth - Maximum depth to traverse (default: 1)
1294
+ * @returns Array of nodes that call this function
1295
+ */
1296
+ getCallers(nodeId, maxDepth = 1) {
1297
+ return this.traverser.getCallers(nodeId, maxDepth);
1298
+ }
1299
+ /**
1300
+ * Get callees of a function/method
1301
+ *
1302
+ * @param nodeId - ID of the function/method node
1303
+ * @param maxDepth - Maximum depth to traverse (default: 1)
1304
+ * @returns Array of nodes called by this function
1305
+ */
1306
+ getCallees(nodeId, maxDepth = 1) {
1307
+ return this.traverser.getCallees(nodeId, maxDepth);
1308
+ }
1309
+ /**
1310
+ * Calculate the impact radius of a node
1311
+ *
1312
+ * Returns all nodes that could be affected by changes to this node.
1313
+ *
1314
+ * @param nodeId - ID of the node
1315
+ * @param maxDepth - Maximum depth to traverse (default: 3)
1316
+ * @returns Subgraph containing potentially impacted nodes
1317
+ */
1318
+ getImpactRadius(nodeId, maxDepth = 3) {
1319
+ return this.traverser.getImpactRadius(nodeId, maxDepth);
1320
+ }
1321
+ /**
1322
+ * Find the shortest path between two nodes
1323
+ *
1324
+ * @param fromId - Starting node ID
1325
+ * @param toId - Target node ID
1326
+ * @param edgeKinds - Edge types to consider (all if empty)
1327
+ * @returns Array of nodes and edges forming the path, or null if no path exists
1328
+ */
1329
+ findPath(fromId, toId, edgeKinds) {
1330
+ return this.traverser.findPath(fromId, toId, edgeKinds);
1331
+ }
1332
+ /**
1333
+ * Get ancestors of a node in the containment hierarchy
1334
+ *
1335
+ * @param nodeId - ID of the node
1336
+ * @returns Array of ancestor nodes from immediate parent to root
1337
+ */
1338
+ getAncestors(nodeId) {
1339
+ return this.traverser.getAncestors(nodeId);
1340
+ }
1341
+ /**
1342
+ * Get immediate children of a node
1343
+ *
1344
+ * @param nodeId - ID of the node
1345
+ * @returns Array of child nodes
1346
+ */
1347
+ getChildren(nodeId) {
1348
+ return this.traverser.getChildren(nodeId);
1349
+ }
1350
+ /**
1351
+ * Get dependencies of a file
1352
+ *
1353
+ * @param filePath - Path to the file
1354
+ * @returns Array of file paths this file depends on
1355
+ */
1356
+ getFileDependencies(filePath) {
1357
+ return this.graphManager.getFileDependencies(filePath);
1358
+ }
1359
+ /**
1360
+ * Get dependents of a file
1361
+ *
1362
+ * @param filePath - Path to the file
1363
+ * @returns Array of file paths that depend on this file
1364
+ */
1365
+ getFileDependents(filePath) {
1366
+ return this.graphManager.getFileDependents(filePath);
1367
+ }
1368
+ /**
1369
+ * Find circular dependencies in the codebase
1370
+ *
1371
+ * @returns Array of cycles, each cycle is an array of file paths
1372
+ */
1373
+ findCircularDependencies() {
1374
+ return this.graphManager.findCircularDependencies();
1375
+ }
1376
+ /**
1377
+ * Find dead code (unreferenced symbols)
1378
+ *
1379
+ * @param kinds - Node kinds to check (default: functions, methods, classes)
1380
+ * @returns Array of unreferenced nodes
1381
+ */
1382
+ findDeadCode(kinds) {
1383
+ return this.graphManager.findDeadCode(kinds);
1384
+ }
1385
+ /**
1386
+ * Get complexity metrics for a node
1387
+ *
1388
+ * @param nodeId - ID of the node
1389
+ * @returns Object containing various complexity metrics
1390
+ */
1391
+ getNodeMetrics(nodeId) {
1392
+ return this.graphManager.getNodeMetrics(nodeId);
1393
+ }
1394
+ // ===========================================================================
1395
+ // Context Building
1396
+ // ===========================================================================
1397
+ /**
1398
+ * Get the source code for a node
1399
+ *
1400
+ * Reads the file and extracts the code between startLine and endLine.
1401
+ *
1402
+ * @param nodeId - ID of the node
1403
+ * @returns Code string or null if not found
1404
+ */
1405
+ async getCode(nodeId) {
1406
+ return this.contextBuilder.getCode(nodeId);
1407
+ }
1408
+ /**
1409
+ * Find relevant subgraph for a query
1410
+ *
1411
+ * Combines semantic search with graph traversal to find the most
1412
+ * relevant nodes and their relationships for a given query.
1413
+ *
1414
+ * @param query - Natural language query describing the task
1415
+ * @param options - Search and traversal options
1416
+ * @returns Subgraph of relevant nodes and edges
1417
+ */
1418
+ async findRelevantContext(query, options) {
1419
+ return this.contextBuilder.findRelevantContext(query, options);
1420
+ }
1421
+ /**
1422
+ * Build context for a task
1423
+ *
1424
+ * Creates comprehensive context by:
1425
+ * 1. Running FTS search to find entry points
1426
+ * 2. Expanding the graph around entry points
1427
+ * 3. Extracting code blocks for key nodes
1428
+ * 4. Formatting output for Claude
1429
+ *
1430
+ * @param input - Task description (string or {title, description})
1431
+ * @param options - Build options (maxNodes, includeCode, format, etc.)
1432
+ * @returns TaskContext object or formatted string (markdown/JSON)
1433
+ */
1434
+ async buildContext(input, options) {
1435
+ return this.contextBuilder.buildContext(input, options);
1436
+ }
1437
+ // ===========================================================================
1438
+ // Database Management
1439
+ // ===========================================================================
1440
+ /**
1441
+ * Optimize the database (vacuum and analyze)
1442
+ */
1443
+ optimize() {
1444
+ this.db.optimize();
1445
+ }
1446
+ /**
1447
+ * Clear all data from the graph
1448
+ */
1449
+ clear() {
1450
+ this.queries.clear();
1451
+ }
1452
+ /**
1453
+ * Alias for close() for backwards compatibility.
1454
+ * @deprecated Use close() instead
1455
+ */
1456
+ destroy() {
1457
+ this.close();
1458
+ }
1459
+ /**
1460
+ * Completely remove SpecShip from the project.
1461
+ * This closes the database and deletes the .SpecShip directory.
1462
+ *
1463
+ * WARNING: This permanently deletes all SpecShip data for the project.
1464
+ */
1465
+ uninitialize() {
1466
+ this.close();
1467
+ (0, directory_1.removeDirectory)(this.projectRoot);
1468
+ }
1469
+ }
1470
+ exports.SpecShip = SpecShip;
1471
+ // Default export
1472
+ exports.default = SpecShip;
1473
+ //# sourceMappingURL=index.js.map