@selvakumaresra/specship 0.1.3 → 0.3.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 (694) hide show
  1. package/README.md +2 -2
  2. package/commands/ss-design-implement.md +79 -0
  3. package/commands/{cg-drifted.md → ss-drifted.md} +2 -2
  4. package/commands/{cg-fix.md → ss-fix.md} +1 -1
  5. package/commands/{cg-implement.md → ss-implement.md} +1 -1
  6. package/commands/ss-spec-author.md +43 -0
  7. package/commands/ss-spec-review.md +48 -0
  8. package/dist/bin/node-version-check.d.ts +37 -0
  9. package/dist/bin/node-version-check.d.ts.map +1 -0
  10. package/dist/bin/node-version-check.js +79 -0
  11. package/dist/bin/node-version-check.js.map +1 -0
  12. package/dist/bin/specship.d.ts +25 -0
  13. package/dist/bin/specship.d.ts.map +1 -0
  14. package/dist/bin/specship.js +2019 -0
  15. package/dist/bin/specship.js.map +1 -0
  16. package/dist/bin/uninstall.d.ts +13 -0
  17. package/dist/bin/uninstall.d.ts.map +1 -0
  18. package/dist/bin/uninstall.js +35 -0
  19. package/dist/bin/uninstall.js.map +1 -0
  20. package/dist/context/formatter.d.ts +30 -0
  21. package/dist/context/formatter.d.ts.map +1 -0
  22. package/dist/context/formatter.js +263 -0
  23. package/dist/context/formatter.js.map +1 -0
  24. package/dist/context/index.d.ts +119 -0
  25. package/dist/context/index.d.ts.map +1 -0
  26. package/dist/context/index.js +1289 -0
  27. package/dist/context/index.js.map +1 -0
  28. package/dist/context/markers.d.ts +19 -0
  29. package/dist/context/markers.d.ts.map +1 -0
  30. package/dist/context/markers.js +22 -0
  31. package/dist/context/markers.js.map +1 -0
  32. package/dist/db/index.d.ts +103 -0
  33. package/dist/db/index.d.ts.map +1 -0
  34. package/dist/db/index.js +279 -0
  35. package/dist/db/index.js.map +1 -0
  36. package/dist/db/migrations.d.ts +44 -0
  37. package/dist/db/migrations.d.ts.map +1 -0
  38. package/dist/db/migrations.js +462 -0
  39. package/dist/db/migrations.js.map +1 -0
  40. package/dist/db/queries.d.ts +357 -0
  41. package/dist/db/queries.d.ts.map +1 -0
  42. package/dist/db/queries.js +1504 -0
  43. package/dist/db/queries.js.map +1 -0
  44. package/dist/db/schema.sql +419 -0
  45. package/dist/db/spec-queries.d.ts +101 -0
  46. package/dist/db/spec-queries.d.ts.map +1 -0
  47. package/dist/db/spec-queries.js +675 -0
  48. package/dist/db/spec-queries.js.map +1 -0
  49. package/dist/db/sqlite-adapter.d.ts +65 -0
  50. package/dist/db/sqlite-adapter.d.ts.map +1 -0
  51. package/dist/db/sqlite-adapter.js +214 -0
  52. package/dist/db/sqlite-adapter.js.map +1 -0
  53. package/dist/directory.d.ts +67 -0
  54. package/dist/directory.d.ts.map +1 -0
  55. package/dist/directory.js +267 -0
  56. package/dist/directory.js.map +1 -0
  57. package/dist/errors.d.ts +136 -0
  58. package/dist/errors.d.ts.map +1 -0
  59. package/dist/errors.js +219 -0
  60. package/dist/errors.js.map +1 -0
  61. package/dist/extraction/dfm-extractor.d.ts +31 -0
  62. package/dist/extraction/dfm-extractor.d.ts.map +1 -0
  63. package/dist/extraction/dfm-extractor.js +151 -0
  64. package/dist/extraction/dfm-extractor.js.map +1 -0
  65. package/dist/extraction/generated-detection.d.ts +30 -0
  66. package/dist/extraction/generated-detection.d.ts.map +1 -0
  67. package/dist/extraction/generated-detection.js +80 -0
  68. package/dist/extraction/generated-detection.js.map +1 -0
  69. package/dist/extraction/grammars.d.ts +100 -0
  70. package/dist/extraction/grammars.d.ts.map +1 -0
  71. package/dist/extraction/grammars.js +426 -0
  72. package/dist/extraction/grammars.js.map +1 -0
  73. package/dist/extraction/index.d.ts +138 -0
  74. package/dist/extraction/index.d.ts.map +1 -0
  75. package/dist/extraction/index.js +1394 -0
  76. package/dist/extraction/index.js.map +1 -0
  77. package/dist/extraction/languages/c-cpp.d.ts +4 -0
  78. package/dist/extraction/languages/c-cpp.d.ts.map +1 -0
  79. package/dist/extraction/languages/c-cpp.js +171 -0
  80. package/dist/extraction/languages/c-cpp.js.map +1 -0
  81. package/dist/extraction/languages/csharp.d.ts +3 -0
  82. package/dist/extraction/languages/csharp.d.ts.map +1 -0
  83. package/dist/extraction/languages/csharp.js +73 -0
  84. package/dist/extraction/languages/csharp.js.map +1 -0
  85. package/dist/extraction/languages/dart.d.ts +3 -0
  86. package/dist/extraction/languages/dart.d.ts.map +1 -0
  87. package/dist/extraction/languages/dart.js +192 -0
  88. package/dist/extraction/languages/dart.js.map +1 -0
  89. package/dist/extraction/languages/go.d.ts +3 -0
  90. package/dist/extraction/languages/go.d.ts.map +1 -0
  91. package/dist/extraction/languages/go.js +74 -0
  92. package/dist/extraction/languages/go.js.map +1 -0
  93. package/dist/extraction/languages/index.d.ts +10 -0
  94. package/dist/extraction/languages/index.d.ts.map +1 -0
  95. package/dist/extraction/languages/index.js +51 -0
  96. package/dist/extraction/languages/index.js.map +1 -0
  97. package/dist/extraction/languages/java.d.ts +3 -0
  98. package/dist/extraction/languages/java.d.ts.map +1 -0
  99. package/dist/extraction/languages/java.js +70 -0
  100. package/dist/extraction/languages/java.js.map +1 -0
  101. package/dist/extraction/languages/javascript.d.ts +3 -0
  102. package/dist/extraction/languages/javascript.d.ts.map +1 -0
  103. package/dist/extraction/languages/javascript.js +90 -0
  104. package/dist/extraction/languages/javascript.js.map +1 -0
  105. package/dist/extraction/languages/kotlin.d.ts +3 -0
  106. package/dist/extraction/languages/kotlin.d.ts.map +1 -0
  107. package/dist/extraction/languages/kotlin.js +259 -0
  108. package/dist/extraction/languages/kotlin.js.map +1 -0
  109. package/dist/extraction/languages/lua.d.ts +3 -0
  110. package/dist/extraction/languages/lua.d.ts.map +1 -0
  111. package/dist/extraction/languages/lua.js +150 -0
  112. package/dist/extraction/languages/lua.js.map +1 -0
  113. package/dist/extraction/languages/luau.d.ts +3 -0
  114. package/dist/extraction/languages/luau.d.ts.map +1 -0
  115. package/dist/extraction/languages/luau.js +37 -0
  116. package/dist/extraction/languages/luau.js.map +1 -0
  117. package/dist/extraction/languages/objc.d.ts +3 -0
  118. package/dist/extraction/languages/objc.d.ts.map +1 -0
  119. package/dist/extraction/languages/objc.js +133 -0
  120. package/dist/extraction/languages/objc.js.map +1 -0
  121. package/dist/extraction/languages/pascal.d.ts +3 -0
  122. package/dist/extraction/languages/pascal.d.ts.map +1 -0
  123. package/dist/extraction/languages/pascal.js +66 -0
  124. package/dist/extraction/languages/pascal.js.map +1 -0
  125. package/dist/extraction/languages/php.d.ts +3 -0
  126. package/dist/extraction/languages/php.d.ts.map +1 -0
  127. package/dist/extraction/languages/php.js +107 -0
  128. package/dist/extraction/languages/php.js.map +1 -0
  129. package/dist/extraction/languages/python.d.ts +3 -0
  130. package/dist/extraction/languages/python.d.ts.map +1 -0
  131. package/dist/extraction/languages/python.js +56 -0
  132. package/dist/extraction/languages/python.js.map +1 -0
  133. package/dist/extraction/languages/ruby.d.ts +3 -0
  134. package/dist/extraction/languages/ruby.d.ts.map +1 -0
  135. package/dist/extraction/languages/ruby.js +114 -0
  136. package/dist/extraction/languages/ruby.js.map +1 -0
  137. package/dist/extraction/languages/rust.d.ts +3 -0
  138. package/dist/extraction/languages/rust.d.ts.map +1 -0
  139. package/dist/extraction/languages/rust.js +109 -0
  140. package/dist/extraction/languages/rust.js.map +1 -0
  141. package/dist/extraction/languages/scala.d.ts +3 -0
  142. package/dist/extraction/languages/scala.d.ts.map +1 -0
  143. package/dist/extraction/languages/scala.js +139 -0
  144. package/dist/extraction/languages/scala.js.map +1 -0
  145. package/dist/extraction/languages/swift.d.ts +3 -0
  146. package/dist/extraction/languages/swift.d.ts.map +1 -0
  147. package/dist/extraction/languages/swift.js +91 -0
  148. package/dist/extraction/languages/swift.js.map +1 -0
  149. package/dist/extraction/languages/typescript.d.ts +3 -0
  150. package/dist/extraction/languages/typescript.d.ts.map +1 -0
  151. package/dist/extraction/languages/typescript.js +129 -0
  152. package/dist/extraction/languages/typescript.js.map +1 -0
  153. package/dist/extraction/liquid-extractor.d.ts +52 -0
  154. package/dist/extraction/liquid-extractor.d.ts.map +1 -0
  155. package/dist/extraction/liquid-extractor.js +313 -0
  156. package/dist/extraction/liquid-extractor.js.map +1 -0
  157. package/dist/extraction/mybatis-extractor.d.ts +48 -0
  158. package/dist/extraction/mybatis-extractor.d.ts.map +1 -0
  159. package/dist/extraction/mybatis-extractor.js +198 -0
  160. package/dist/extraction/mybatis-extractor.js.map +1 -0
  161. package/dist/extraction/parse-worker.d.ts +8 -0
  162. package/dist/extraction/parse-worker.d.ts.map +1 -0
  163. package/dist/extraction/parse-worker.js +94 -0
  164. package/dist/extraction/parse-worker.js.map +1 -0
  165. package/dist/extraction/specs/markdown-spec-extractor.d.ts +59 -0
  166. package/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -0
  167. package/dist/extraction/specs/markdown-spec-extractor.js +327 -0
  168. package/dist/extraction/specs/markdown-spec-extractor.js.map +1 -0
  169. package/dist/extraction/specs/types.d.ts +39 -0
  170. package/dist/extraction/specs/types.d.ts.map +1 -0
  171. package/dist/extraction/specs/types.js +8 -0
  172. package/dist/extraction/specs/types.js.map +1 -0
  173. package/dist/extraction/svelte-extractor.d.ts +56 -0
  174. package/dist/extraction/svelte-extractor.d.ts.map +1 -0
  175. package/dist/extraction/svelte-extractor.js +272 -0
  176. package/dist/extraction/svelte-extractor.js.map +1 -0
  177. package/dist/extraction/tree-sitter-helpers.d.ts +28 -0
  178. package/dist/extraction/tree-sitter-helpers.d.ts.map +1 -0
  179. package/dist/extraction/tree-sitter-helpers.js +103 -0
  180. package/dist/extraction/tree-sitter-helpers.js.map +1 -0
  181. package/dist/extraction/tree-sitter-types.d.ts +193 -0
  182. package/dist/extraction/tree-sitter-types.d.ts.map +1 -0
  183. package/dist/extraction/tree-sitter-types.js +10 -0
  184. package/dist/extraction/tree-sitter-types.js.map +1 -0
  185. package/dist/extraction/tree-sitter.d.ts +317 -0
  186. package/dist/extraction/tree-sitter.d.ts.map +1 -0
  187. package/dist/extraction/tree-sitter.js +3092 -0
  188. package/dist/extraction/tree-sitter.js.map +1 -0
  189. package/dist/extraction/vue-extractor.d.ts +51 -0
  190. package/dist/extraction/vue-extractor.d.ts.map +1 -0
  191. package/dist/extraction/vue-extractor.js +251 -0
  192. package/dist/extraction/vue-extractor.js.map +1 -0
  193. package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
  194. package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
  195. package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  196. package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
  197. package/dist/extraction/wasm-runtime-flags.d.ts +38 -0
  198. package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -0
  199. package/dist/extraction/wasm-runtime-flags.js +106 -0
  200. package/dist/extraction/wasm-runtime-flags.js.map +1 -0
  201. package/dist/graph/index.d.ts +8 -0
  202. package/dist/graph/index.d.ts.map +1 -0
  203. package/dist/graph/index.js +13 -0
  204. package/dist/graph/index.js.map +1 -0
  205. package/dist/graph/queries.d.ts +106 -0
  206. package/dist/graph/queries.d.ts.map +1 -0
  207. package/dist/graph/queries.js +366 -0
  208. package/dist/graph/queries.js.map +1 -0
  209. package/dist/graph/traversal.d.ts +127 -0
  210. package/dist/graph/traversal.d.ts.map +1 -0
  211. package/dist/graph/traversal.js +531 -0
  212. package/dist/graph/traversal.js.map +1 -0
  213. package/dist/index.d.ts +551 -0
  214. package/dist/index.d.ts.map +1 -0
  215. package/dist/index.js +1165 -0
  216. package/dist/index.js.map +1 -0
  217. package/dist/installer/config-writer.d.ts +28 -0
  218. package/dist/installer/config-writer.d.ts.map +1 -0
  219. package/dist/installer/config-writer.js +91 -0
  220. package/dist/installer/config-writer.js.map +1 -0
  221. package/dist/installer/index.d.ts +87 -0
  222. package/dist/installer/index.d.ts.map +1 -0
  223. package/dist/installer/index.js +415 -0
  224. package/dist/installer/index.js.map +1 -0
  225. package/dist/installer/instructions-template.d.ts +18 -0
  226. package/dist/installer/instructions-template.d.ts.map +1 -0
  227. package/dist/installer/instructions-template.js +21 -0
  228. package/dist/installer/instructions-template.js.map +1 -0
  229. package/dist/installer/targets/claude.d.ts +98 -0
  230. package/dist/installer/targets/claude.d.ts.map +1 -0
  231. package/dist/installer/targets/claude.js +639 -0
  232. package/dist/installer/targets/claude.js.map +1 -0
  233. package/dist/installer/targets/registry.d.ts +19 -0
  234. package/dist/installer/targets/registry.d.ts.map +1 -0
  235. package/dist/installer/targets/registry.js +31 -0
  236. package/dist/installer/targets/registry.js.map +1 -0
  237. package/dist/installer/targets/shared.d.ts +62 -0
  238. package/dist/installer/targets/shared.d.ts.map +1 -0
  239. package/dist/installer/targets/shared.js +207 -0
  240. package/dist/installer/targets/shared.js.map +1 -0
  241. package/dist/installer/targets/types.d.ts +76 -0
  242. package/dist/installer/targets/types.d.ts.map +1 -0
  243. package/dist/installer/targets/types.js +12 -0
  244. package/dist/installer/targets/types.js.map +1 -0
  245. package/dist/isolation/worktree.d.ts +65 -0
  246. package/dist/isolation/worktree.d.ts.map +1 -0
  247. package/dist/isolation/worktree.js +231 -0
  248. package/dist/isolation/worktree.js.map +1 -0
  249. package/dist/mcp/daemon-paths.d.ts +46 -0
  250. package/dist/mcp/daemon-paths.d.ts.map +1 -0
  251. package/dist/mcp/daemon-paths.js +125 -0
  252. package/dist/mcp/daemon-paths.js.map +1 -0
  253. package/dist/mcp/daemon.d.ts +161 -0
  254. package/dist/mcp/daemon.d.ts.map +1 -0
  255. package/dist/mcp/daemon.js +403 -0
  256. package/dist/mcp/daemon.js.map +1 -0
  257. package/dist/mcp/engine.d.ts +105 -0
  258. package/dist/mcp/engine.d.ts.map +1 -0
  259. package/dist/mcp/engine.js +270 -0
  260. package/dist/mcp/engine.js.map +1 -0
  261. package/dist/mcp/index.d.ts +112 -0
  262. package/dist/mcp/index.d.ts.map +1 -0
  263. package/dist/mcp/index.js +477 -0
  264. package/dist/mcp/index.js.map +1 -0
  265. package/dist/mcp/proxy.d.ts +81 -0
  266. package/dist/mcp/proxy.d.ts.map +1 -0
  267. package/dist/mcp/proxy.js +510 -0
  268. package/dist/mcp/proxy.js.map +1 -0
  269. package/dist/mcp/server-instructions.d.ts +18 -0
  270. package/dist/mcp/server-instructions.d.ts.map +1 -0
  271. package/dist/mcp/server-instructions.js +77 -0
  272. package/dist/mcp/server-instructions.js.map +1 -0
  273. package/dist/mcp/session.d.ts +77 -0
  274. package/dist/mcp/session.d.ts.map +1 -0
  275. package/dist/mcp/session.js +294 -0
  276. package/dist/mcp/session.js.map +1 -0
  277. package/dist/mcp/spec-tools.d.ts +39 -0
  278. package/dist/mcp/spec-tools.d.ts.map +1 -0
  279. package/dist/mcp/spec-tools.js +326 -0
  280. package/dist/mcp/spec-tools.js.map +1 -0
  281. package/dist/mcp/tools.d.ts +404 -0
  282. package/dist/mcp/tools.d.ts.map +1 -0
  283. package/dist/mcp/tools.js +3066 -0
  284. package/dist/mcp/tools.js.map +1 -0
  285. package/dist/mcp/transport.d.ts +188 -0
  286. package/dist/mcp/transport.d.ts.map +1 -0
  287. package/dist/mcp/transport.js +343 -0
  288. package/dist/mcp/transport.js.map +1 -0
  289. package/dist/mcp/version.d.ts +19 -0
  290. package/dist/mcp/version.d.ts.map +1 -0
  291. package/dist/mcp/version.js +71 -0
  292. package/dist/mcp/version.js.map +1 -0
  293. package/dist/resolution/callback-synthesizer.d.ts +10 -0
  294. package/dist/resolution/callback-synthesizer.d.ts.map +1 -0
  295. package/dist/resolution/callback-synthesizer.js +1300 -0
  296. package/dist/resolution/callback-synthesizer.js.map +1 -0
  297. package/dist/resolution/frameworks/cargo-workspace.d.ts +18 -0
  298. package/dist/resolution/frameworks/cargo-workspace.d.ts.map +1 -0
  299. package/dist/resolution/frameworks/cargo-workspace.js +225 -0
  300. package/dist/resolution/frameworks/cargo-workspace.js.map +1 -0
  301. package/dist/resolution/frameworks/csharp.d.ts +8 -0
  302. package/dist/resolution/frameworks/csharp.d.ts.map +1 -0
  303. package/dist/resolution/frameworks/csharp.js +241 -0
  304. package/dist/resolution/frameworks/csharp.js.map +1 -0
  305. package/dist/resolution/frameworks/drupal.d.ts +51 -0
  306. package/dist/resolution/frameworks/drupal.d.ts.map +1 -0
  307. package/dist/resolution/frameworks/drupal.js +367 -0
  308. package/dist/resolution/frameworks/drupal.js.map +1 -0
  309. package/dist/resolution/frameworks/expo-modules.d.ts +3 -0
  310. package/dist/resolution/frameworks/expo-modules.d.ts.map +1 -0
  311. package/dist/resolution/frameworks/expo-modules.js +143 -0
  312. package/dist/resolution/frameworks/expo-modules.js.map +1 -0
  313. package/dist/resolution/frameworks/express.d.ts +8 -0
  314. package/dist/resolution/frameworks/express.d.ts.map +1 -0
  315. package/dist/resolution/frameworks/express.js +308 -0
  316. package/dist/resolution/frameworks/express.js.map +1 -0
  317. package/dist/resolution/frameworks/fabric.d.ts +3 -0
  318. package/dist/resolution/frameworks/fabric.d.ts.map +1 -0
  319. package/dist/resolution/frameworks/fabric.js +354 -0
  320. package/dist/resolution/frameworks/fabric.js.map +1 -0
  321. package/dist/resolution/frameworks/go.d.ts +8 -0
  322. package/dist/resolution/frameworks/go.d.ts.map +1 -0
  323. package/dist/resolution/frameworks/go.js +161 -0
  324. package/dist/resolution/frameworks/go.js.map +1 -0
  325. package/dist/resolution/frameworks/index.d.ts +48 -0
  326. package/dist/resolution/frameworks/index.d.ts.map +1 -0
  327. package/dist/resolution/frameworks/index.js +161 -0
  328. package/dist/resolution/frameworks/index.js.map +1 -0
  329. package/dist/resolution/frameworks/java.d.ts +8 -0
  330. package/dist/resolution/frameworks/java.d.ts.map +1 -0
  331. package/dist/resolution/frameworks/java.js +504 -0
  332. package/dist/resolution/frameworks/java.js.map +1 -0
  333. package/dist/resolution/frameworks/laravel.d.ts +13 -0
  334. package/dist/resolution/frameworks/laravel.d.ts.map +1 -0
  335. package/dist/resolution/frameworks/laravel.js +257 -0
  336. package/dist/resolution/frameworks/laravel.js.map +1 -0
  337. package/dist/resolution/frameworks/nestjs.d.ts +26 -0
  338. package/dist/resolution/frameworks/nestjs.d.ts.map +1 -0
  339. package/dist/resolution/frameworks/nestjs.js +698 -0
  340. package/dist/resolution/frameworks/nestjs.js.map +1 -0
  341. package/dist/resolution/frameworks/play.d.ts +19 -0
  342. package/dist/resolution/frameworks/play.d.ts.map +1 -0
  343. package/dist/resolution/frameworks/play.js +111 -0
  344. package/dist/resolution/frameworks/play.js.map +1 -0
  345. package/dist/resolution/frameworks/python.d.ts +10 -0
  346. package/dist/resolution/frameworks/python.d.ts.map +1 -0
  347. package/dist/resolution/frameworks/python.js +396 -0
  348. package/dist/resolution/frameworks/python.js.map +1 -0
  349. package/dist/resolution/frameworks/react-native.d.ts +3 -0
  350. package/dist/resolution/frameworks/react-native.d.ts.map +1 -0
  351. package/dist/resolution/frameworks/react-native.js +360 -0
  352. package/dist/resolution/frameworks/react-native.js.map +1 -0
  353. package/dist/resolution/frameworks/react.d.ts +8 -0
  354. package/dist/resolution/frameworks/react.d.ts.map +1 -0
  355. package/dist/resolution/frameworks/react.js +365 -0
  356. package/dist/resolution/frameworks/react.js.map +1 -0
  357. package/dist/resolution/frameworks/ruby.d.ts +8 -0
  358. package/dist/resolution/frameworks/ruby.d.ts.map +1 -0
  359. package/dist/resolution/frameworks/ruby.js +302 -0
  360. package/dist/resolution/frameworks/ruby.js.map +1 -0
  361. package/dist/resolution/frameworks/rust.d.ts +8 -0
  362. package/dist/resolution/frameworks/rust.d.ts.map +1 -0
  363. package/dist/resolution/frameworks/rust.js +304 -0
  364. package/dist/resolution/frameworks/rust.js.map +1 -0
  365. package/dist/resolution/frameworks/svelte.d.ts +9 -0
  366. package/dist/resolution/frameworks/svelte.d.ts.map +1 -0
  367. package/dist/resolution/frameworks/svelte.js +249 -0
  368. package/dist/resolution/frameworks/svelte.js.map +1 -0
  369. package/dist/resolution/frameworks/swift-objc.d.ts +37 -0
  370. package/dist/resolution/frameworks/swift-objc.d.ts.map +1 -0
  371. package/dist/resolution/frameworks/swift-objc.js +252 -0
  372. package/dist/resolution/frameworks/swift-objc.js.map +1 -0
  373. package/dist/resolution/frameworks/swift.d.ts +10 -0
  374. package/dist/resolution/frameworks/swift.d.ts.map +1 -0
  375. package/dist/resolution/frameworks/swift.js +400 -0
  376. package/dist/resolution/frameworks/swift.js.map +1 -0
  377. package/dist/resolution/frameworks/vue.d.ts +9 -0
  378. package/dist/resolution/frameworks/vue.d.ts.map +1 -0
  379. package/dist/resolution/frameworks/vue.js +306 -0
  380. package/dist/resolution/frameworks/vue.js.map +1 -0
  381. package/dist/resolution/go-module.d.ts +26 -0
  382. package/dist/resolution/go-module.d.ts.map +1 -0
  383. package/dist/resolution/go-module.js +78 -0
  384. package/dist/resolution/go-module.js.map +1 -0
  385. package/dist/resolution/import-resolver.d.ts +68 -0
  386. package/dist/resolution/import-resolver.d.ts.map +1 -0
  387. package/dist/resolution/import-resolver.js +1275 -0
  388. package/dist/resolution/import-resolver.js.map +1 -0
  389. package/dist/resolution/index.d.ts +117 -0
  390. package/dist/resolution/index.d.ts.map +1 -0
  391. package/dist/resolution/index.js +895 -0
  392. package/dist/resolution/index.js.map +1 -0
  393. package/dist/resolution/lru-cache.d.ts +24 -0
  394. package/dist/resolution/lru-cache.d.ts.map +1 -0
  395. package/dist/resolution/lru-cache.js +62 -0
  396. package/dist/resolution/lru-cache.js.map +1 -0
  397. package/dist/resolution/name-matcher.d.ts +32 -0
  398. package/dist/resolution/name-matcher.d.ts.map +1 -0
  399. package/dist/resolution/name-matcher.js +596 -0
  400. package/dist/resolution/name-matcher.js.map +1 -0
  401. package/dist/resolution/path-aliases.d.ts +68 -0
  402. package/dist/resolution/path-aliases.d.ts.map +1 -0
  403. package/dist/resolution/path-aliases.js +238 -0
  404. package/dist/resolution/path-aliases.js.map +1 -0
  405. package/dist/resolution/spec-link-resolver.d.ts +103 -0
  406. package/dist/resolution/spec-link-resolver.d.ts.map +1 -0
  407. package/dist/resolution/spec-link-resolver.js +259 -0
  408. package/dist/resolution/spec-link-resolver.js.map +1 -0
  409. package/dist/resolution/strip-comments.d.ts +27 -0
  410. package/dist/resolution/strip-comments.d.ts.map +1 -0
  411. package/dist/resolution/strip-comments.js +441 -0
  412. package/dist/resolution/strip-comments.js.map +1 -0
  413. package/dist/resolution/swift-objc-bridge.d.ts +134 -0
  414. package/dist/resolution/swift-objc-bridge.d.ts.map +1 -0
  415. package/dist/resolution/swift-objc-bridge.js +256 -0
  416. package/dist/resolution/swift-objc-bridge.js.map +1 -0
  417. package/dist/resolution/types.d.ts +216 -0
  418. package/dist/resolution/types.d.ts.map +1 -0
  419. package/dist/resolution/types.js +8 -0
  420. package/dist/resolution/types.js.map +1 -0
  421. package/dist/resolution/workspace-packages.d.ts +48 -0
  422. package/dist/resolution/workspace-packages.d.ts.map +1 -0
  423. package/dist/resolution/workspace-packages.js +208 -0
  424. package/dist/resolution/workspace-packages.js.map +1 -0
  425. package/dist/search/query-parser.d.ts +57 -0
  426. package/dist/search/query-parser.d.ts.map +1 -0
  427. package/dist/search/query-parser.js +177 -0
  428. package/dist/search/query-parser.js.map +1 -0
  429. package/dist/search/query-utils.d.ts +71 -0
  430. package/dist/search/query-utils.d.ts.map +1 -0
  431. package/dist/search/query-utils.js +380 -0
  432. package/dist/search/query-utils.js.map +1 -0
  433. package/dist/server/cli.js +152 -0
  434. package/dist/server/index.js +12 -0
  435. package/dist/server/ingest/index.js +18 -0
  436. package/dist/server/ingest/ingestor.js +506 -0
  437. package/dist/server/ingest/parser.js +104 -0
  438. package/dist/server/ingest/pricing.js +78 -0
  439. package/dist/server/ingest/types.js +9 -0
  440. package/dist/server/ingest/watcher.js +77 -0
  441. package/dist/server/package.json +3 -0
  442. package/dist/server/project-registry.js +101 -0
  443. package/dist/server/routes/claude.js +868 -0
  444. package/dist/server/routes/graph.js +211 -0
  445. package/dist/server/routes/memory.js +272 -0
  446. package/dist/server/routes/projects.js +197 -0
  447. package/dist/server/routes/spec.js +265 -0
  448. package/dist/server/routes/status.js +112 -0
  449. package/dist/server/routes/workflow.js +212 -0
  450. package/dist/server/server.js +206 -0
  451. package/dist/server/static-handler.js +87 -0
  452. package/dist/sync/git-hooks.d.ts +45 -0
  453. package/dist/sync/git-hooks.d.ts.map +1 -0
  454. package/dist/sync/git-hooks.js +225 -0
  455. package/dist/sync/git-hooks.js.map +1 -0
  456. package/dist/sync/index.d.ts +19 -0
  457. package/dist/sync/index.d.ts.map +1 -0
  458. package/dist/sync/index.js +35 -0
  459. package/dist/sync/index.js.map +1 -0
  460. package/dist/sync/watch-policy.d.ts +48 -0
  461. package/dist/sync/watch-policy.d.ts.map +1 -0
  462. package/dist/sync/watch-policy.js +124 -0
  463. package/dist/sync/watch-policy.js.map +1 -0
  464. package/dist/sync/watcher.d.ts +283 -0
  465. package/dist/sync/watcher.d.ts.map +1 -0
  466. package/dist/sync/watcher.js +606 -0
  467. package/dist/sync/watcher.js.map +1 -0
  468. package/dist/sync/worktree.d.ts +54 -0
  469. package/dist/sync/worktree.d.ts.map +1 -0
  470. package/dist/sync/worktree.js +137 -0
  471. package/dist/sync/worktree.js.map +1 -0
  472. package/dist/types.d.ts +623 -0
  473. package/dist/types.d.ts.map +1 -0
  474. package/dist/types.js +108 -0
  475. package/dist/types.js.map +1 -0
  476. package/dist/ui/glyphs.d.ts +42 -0
  477. package/dist/ui/glyphs.d.ts.map +1 -0
  478. package/dist/ui/glyphs.js +78 -0
  479. package/dist/ui/glyphs.js.map +1 -0
  480. package/dist/ui/shimmer-progress.d.ts +11 -0
  481. package/dist/ui/shimmer-progress.d.ts.map +1 -0
  482. package/dist/ui/shimmer-progress.js +90 -0
  483. package/dist/ui/shimmer-progress.js.map +1 -0
  484. package/dist/ui/shimmer-worker.d.ts +2 -0
  485. package/dist/ui/shimmer-worker.d.ts.map +1 -0
  486. package/dist/ui/shimmer-worker.js +118 -0
  487. package/dist/ui/shimmer-worker.js.map +1 -0
  488. package/dist/ui/types.d.ts +17 -0
  489. package/dist/ui/types.d.ts.map +1 -0
  490. package/dist/ui/types.js +3 -0
  491. package/dist/ui/types.js.map +1 -0
  492. package/dist/utils.d.ts +205 -0
  493. package/dist/utils.d.ts.map +1 -0
  494. package/dist/utils.js +549 -0
  495. package/dist/utils.js.map +1 -0
  496. package/dist/web/chunk-2AJCHB7P.js +1 -0
  497. package/dist/web/chunk-2CPLUFCH.js +2 -0
  498. package/dist/web/chunk-2DHIGIOI.js +1 -0
  499. package/dist/web/chunk-2GBEK2GM.js +1 -0
  500. package/dist/web/chunk-2I7L37NS.js +1 -0
  501. package/dist/web/chunk-2NAWAJB5.js +1 -0
  502. package/dist/web/chunk-2OJBIPE4.js +1 -0
  503. package/dist/web/chunk-2OKMB4KX.js +2 -0
  504. package/dist/web/chunk-3E2WB6D5.js +1 -0
  505. package/dist/web/chunk-3EBFYSCH.js +2 -0
  506. package/dist/web/chunk-3QCQ4BXS.js +1 -0
  507. package/dist/web/chunk-3SEJX2BK.js +1 -0
  508. package/dist/web/chunk-42XVAQ6I.js +1 -0
  509. package/dist/web/chunk-4IMMPEYM.js +1 -0
  510. package/dist/web/chunk-4N5DWG46.js +1 -0
  511. package/dist/web/chunk-4TJQJPCZ.js +1 -0
  512. package/dist/web/chunk-4WZIHTPC.js +1 -0
  513. package/dist/web/chunk-4YVSYOSD.js +1 -0
  514. package/dist/web/chunk-5BQIOYKW.js +1 -0
  515. package/dist/web/chunk-5HGWHUJA.js +1 -0
  516. package/dist/web/chunk-5Y244R4G.js +1 -0
  517. package/dist/web/chunk-6RRDPT5Z.js +1 -0
  518. package/dist/web/chunk-6VKB2ZWM.js +1 -0
  519. package/dist/web/chunk-7DMFVTU4.js +1 -0
  520. package/dist/web/chunk-7RNS77UP.js +1 -0
  521. package/dist/web/chunk-7SMPKVEP.js +1 -0
  522. package/dist/web/chunk-AZJVTPLU.js +1 -0
  523. package/dist/web/chunk-BCZM5AXU.js +1 -0
  524. package/dist/web/chunk-BLBRMCN2.js +1 -0
  525. package/dist/web/chunk-BMIAXD2V.js +2 -0
  526. package/dist/web/chunk-BPECIDVO.js +1 -0
  527. package/dist/web/chunk-BUXWEHIY.js +1 -0
  528. package/dist/web/chunk-BYZFQSM6.js +1 -0
  529. package/dist/web/chunk-DA6SNNAF.js +1 -0
  530. package/dist/web/chunk-DLQPZWSI.css +1 -0
  531. package/dist/web/chunk-DTRN7FZR.js +1 -0
  532. package/dist/web/chunk-DYRFLPJA.js +1 -0
  533. package/dist/web/chunk-E3J3CXR5.js +1 -0
  534. package/dist/web/chunk-E44X4RH2.js +1 -0
  535. package/dist/web/chunk-E73OX2P7.js +1 -0
  536. package/dist/web/chunk-EAXRKDLV.js +1 -0
  537. package/dist/web/chunk-EBKKDHYI.js +1 -0
  538. package/dist/web/chunk-EE7V7Q5P.js +1 -0
  539. package/dist/web/chunk-EKY2FUHU.js +1 -0
  540. package/dist/web/chunk-EMGMOEVR.js +1 -0
  541. package/dist/web/chunk-EP6XOPXH.js +1 -0
  542. package/dist/web/chunk-ESGDLJOJ.js +1 -0
  543. package/dist/web/chunk-ETJG7NCY.js +1 -0
  544. package/dist/web/chunk-EUUEFEDI.js +1 -0
  545. package/dist/web/chunk-FGNZDHTL.js +11 -0
  546. package/dist/web/chunk-FIJW2UNJ.js +1 -0
  547. package/dist/web/chunk-FMV5PXRC.js +5 -0
  548. package/dist/web/chunk-G7VZT5KB.js +3 -0
  549. package/dist/web/chunk-GRZYXPSO.js +7 -0
  550. package/dist/web/chunk-GYGPS3AN.js +1 -0
  551. package/dist/web/chunk-H7AF7YS4.js +1 -0
  552. package/dist/web/chunk-HDZDQILN.js +1 -0
  553. package/dist/web/chunk-HMK6UO6N.js +1 -0
  554. package/dist/web/chunk-HZA6NEAB.js +1 -0
  555. package/dist/web/chunk-IHEE5NYJ.js +1 -0
  556. package/dist/web/chunk-ISNEBICW.js +1 -0
  557. package/dist/web/chunk-J2GZVLHH.js +1 -0
  558. package/dist/web/chunk-JFYVCXK3.js +1 -0
  559. package/dist/web/chunk-JN6W7HCN.js +17 -0
  560. package/dist/web/chunk-JT7P3DEK.js +6 -0
  561. package/dist/web/chunk-JTFXTIPE.js +903 -0
  562. package/dist/web/chunk-L37MTFSG.js +3 -0
  563. package/dist/web/chunk-LB6JPLX2.js +1 -0
  564. package/dist/web/chunk-LNSVDHCI.js +1 -0
  565. package/dist/web/chunk-LV4G6QFG.js +2 -0
  566. package/dist/web/chunk-LVGIY3SO.js +1 -0
  567. package/dist/web/chunk-LXLHIHEN.js +1 -0
  568. package/dist/web/chunk-MC4DFIHG.js +1 -0
  569. package/dist/web/chunk-MVOMVPYB.js +1 -0
  570. package/dist/web/chunk-N6SS4G6S.js +1 -0
  571. package/dist/web/chunk-NTBJG6SJ.js +1 -0
  572. package/dist/web/chunk-NUDB3Q2Y.js +3 -0
  573. package/dist/web/chunk-OXEF5E3E.js +1 -0
  574. package/dist/web/chunk-PDN6QYGJ.js +4 -0
  575. package/dist/web/chunk-PGGJPDJG.js +1 -0
  576. package/dist/web/chunk-PUYSJNJR.js +1 -0
  577. package/dist/web/chunk-Q2RVFS45.js +1 -0
  578. package/dist/web/chunk-Q7L6LLAK.js +1 -0
  579. package/dist/web/chunk-QCMKJIWY.js +1 -0
  580. package/dist/web/chunk-QH6CF3M3.js +1 -0
  581. package/dist/web/chunk-QQ5LD7PI.js +1 -0
  582. package/dist/web/chunk-QR6L3KAC.js +1 -0
  583. package/dist/web/chunk-R2DLK4HO.js +1 -0
  584. package/dist/web/chunk-R5W2MDZN.js +1 -0
  585. package/dist/web/chunk-RAAMPHPJ.js +1 -0
  586. package/dist/web/chunk-RD6TVPOT.js +1 -0
  587. package/dist/web/chunk-RKY4EJYJ.js +1 -0
  588. package/dist/web/chunk-RONYWVY7.js +1 -0
  589. package/dist/web/chunk-RXKXYF2C.js +1 -0
  590. package/dist/web/chunk-SBWU7JFC.js +1 -0
  591. package/dist/web/chunk-SEXBRGYK.js +1 -0
  592. package/dist/web/chunk-SHPTC4RL.js +1 -0
  593. package/dist/web/chunk-SUZYBYDW.js +1 -0
  594. package/dist/web/chunk-SWKJRNYY.js +1 -0
  595. package/dist/web/chunk-T66XVKGB.js +1 -0
  596. package/dist/web/chunk-T7AZ65JP.js +1 -0
  597. package/dist/web/chunk-TCZDVOHD.js +1 -0
  598. package/dist/web/chunk-TPTITA3V.js +1 -0
  599. package/dist/web/chunk-TR335633.js +1 -0
  600. package/dist/web/chunk-TWXZK6XM.js +1 -0
  601. package/dist/web/chunk-UR5KDXPX.js +1 -0
  602. package/dist/web/chunk-UR6O2GEH.js +1 -0
  603. package/dist/web/chunk-UTNMGWTP.js +1 -0
  604. package/dist/web/chunk-UYC52MBC.js +1 -0
  605. package/dist/web/chunk-VECWMHJP.js +1 -0
  606. package/dist/web/chunk-VUACT35R.js +3 -0
  607. package/dist/web/chunk-VZI7H4SZ.js +1 -0
  608. package/dist/web/chunk-WAI2JMZP.js +1 -0
  609. package/dist/web/chunk-WB6YHOD4.js +1 -0
  610. package/dist/web/chunk-WBT64AWV.js +1 -0
  611. package/dist/web/chunk-WDU3WICG.js +1 -0
  612. package/dist/web/chunk-WFXJIXZE.js +4 -0
  613. package/dist/web/chunk-WTGYRH3Z.js +298 -0
  614. package/dist/web/chunk-WXTCVDTP.js +1 -0
  615. package/dist/web/chunk-X2HTISHL.js +1 -0
  616. package/dist/web/chunk-XCDHWLVH.js +1 -0
  617. package/dist/web/chunk-Y3H6FFUZ.js +1 -0
  618. package/dist/web/chunk-Y4F5ULGJ.js +1 -0
  619. package/dist/web/chunk-YAWCRPHV.js +1 -0
  620. package/dist/web/chunk-YEGKAAEE.js +1 -0
  621. package/dist/web/chunk-YM2KU57F.js +1 -0
  622. package/dist/web/chunk-YRERBP6T.js +1 -0
  623. package/dist/web/chunk-ZLV4VCDG.js +3 -0
  624. package/dist/web/chunk-ZTVI5KFF.js +1 -0
  625. package/dist/web/favicon-16.png +0 -0
  626. package/dist/web/favicon-180.png +0 -0
  627. package/dist/web/favicon-32.png +0 -0
  628. package/dist/web/favicon-512.png +0 -0
  629. package/dist/web/favicon-small.svg +15 -0
  630. package/dist/web/favicon.ico +0 -0
  631. package/dist/web/favicon.svg +20 -0
  632. package/dist/web/index.html +145 -0
  633. package/dist/web/main-ESADRXN2.css +1 -0
  634. package/dist/web/main-WVI3YTDU.js +1 -0
  635. package/dist/web/media/codicon-LN6W7LCM.ttf +0 -0
  636. package/dist/web/styles-KSOPUVDA.css +1 -0
  637. package/dist/workflows/condition-evaluator.d.ts +75 -0
  638. package/dist/workflows/condition-evaluator.d.ts.map +1 -0
  639. package/dist/workflows/condition-evaluator.js +282 -0
  640. package/dist/workflows/condition-evaluator.js.map +1 -0
  641. package/dist/workflows/defaults/claude-design-implement.yaml +247 -0
  642. package/dist/workflows/defaults/index.d.ts +26 -0
  643. package/dist/workflows/defaults/index.d.ts.map +1 -0
  644. package/dist/workflows/defaults/index.js +94 -0
  645. package/dist/workflows/defaults/index.js.map +1 -0
  646. package/dist/workflows/defaults/spec-author.yaml +214 -0
  647. package/dist/workflows/defaults/spec-fix.yaml +110 -0
  648. package/dist/workflows/defaults/spec-implement.yaml +150 -0
  649. package/dist/workflows/defaults/spec-relink.yaml +81 -0
  650. package/dist/workflows/defaults/spec-verify.yaml +51 -0
  651. package/dist/workflows/discovery.d.ts +46 -0
  652. package/dist/workflows/discovery.d.ts.map +1 -0
  653. package/dist/workflows/discovery.js +193 -0
  654. package/dist/workflows/discovery.js.map +1 -0
  655. package/dist/workflows/executor.d.ts +83 -0
  656. package/dist/workflows/executor.d.ts.map +1 -0
  657. package/dist/workflows/executor.js +624 -0
  658. package/dist/workflows/executor.js.map +1 -0
  659. package/dist/workflows/runners/approval.d.ts +18 -0
  660. package/dist/workflows/runners/approval.d.ts.map +1 -0
  661. package/dist/workflows/runners/approval.js +34 -0
  662. package/dist/workflows/runners/approval.js.map +1 -0
  663. package/dist/workflows/runners/bash.d.ts +13 -0
  664. package/dist/workflows/runners/bash.d.ts.map +1 -0
  665. package/dist/workflows/runners/bash.js +143 -0
  666. package/dist/workflows/runners/bash.js.map +1 -0
  667. package/dist/workflows/runners/cancel.d.ts +10 -0
  668. package/dist/workflows/runners/cancel.d.ts.map +1 -0
  669. package/dist/workflows/runners/cancel.js +19 -0
  670. package/dist/workflows/runners/cancel.js.map +1 -0
  671. package/dist/workflows/runners/prompt.d.ts +28 -0
  672. package/dist/workflows/runners/prompt.d.ts.map +1 -0
  673. package/dist/workflows/runners/prompt.js +212 -0
  674. package/dist/workflows/runners/prompt.js.map +1 -0
  675. package/dist/workflows/runners/script.d.ts +17 -0
  676. package/dist/workflows/runners/script.d.ts.map +1 -0
  677. package/dist/workflows/runners/script.js +155 -0
  678. package/dist/workflows/runners/script.js.map +1 -0
  679. package/dist/workflows/runners/types.d.ts +51 -0
  680. package/dist/workflows/runners/types.d.ts.map +1 -0
  681. package/dist/workflows/runners/types.js +13 -0
  682. package/dist/workflows/runners/types.js.map +1 -0
  683. package/dist/workflows/schemas/workflow.d.ts +166 -0
  684. package/dist/workflows/schemas/workflow.d.ts.map +1 -0
  685. package/dist/workflows/schemas/workflow.js +437 -0
  686. package/dist/workflows/schemas/workflow.js.map +1 -0
  687. package/package.json +1 -1
  688. package/scripts/offline-install.sh +19 -6
  689. /package/commands/{cg-explore.md → ss-explore.md} +0 -0
  690. /package/commands/{cg-impact.md → ss-impact.md} +0 -0
  691. /package/commands/{cg-relink.md → ss-relink.md} +0 -0
  692. /package/commands/{cg-spec.md → ss-spec.md} +0 -0
  693. /package/commands/{cg-sync.md → ss-sync.md} +0 -0
  694. /package/commands/{cg-trace.md → ss-trace.md} +0 -0
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Spec layer routes — list / fetch / link assert / link verify / drift queue.
3
+ * Plus the v0.2 write endpoints: PUT /api/spec/:id and POST /api/specs,
4
+ * which let the dashboard's Monaco editor save spec edits back to disk.
5
+ *
6
+ * Every route is project-scoped via `?project=<slug>` (falls back to the
7
+ * boot-time primary). Returns 409 / `no_project` when neither is selectable.
8
+ */
9
+ import * as fs from 'node:fs';
10
+ import * as path from 'node:path';
11
+ /**
12
+ * Resolve a project-relative path to an absolute path under the project
13
+ * root, refusing anything that escapes the root (path-traversal guard).
14
+ * Returns null when the resolved path is outside the project — caller
15
+ * surfaces 400 in that case.
16
+ */
17
+ function safeProjectPath(projectRoot, relPath) {
18
+ // Strip leading slashes so absolute paths in user input don't blow past
19
+ // path.resolve's "drop earlier components" behavior.
20
+ const cleaned = relPath.replace(/^[/\\]+/, '');
21
+ const abs = path.resolve(projectRoot, cleaned);
22
+ const rootResolved = path.resolve(projectRoot);
23
+ const rel = path.relative(rootResolved, abs);
24
+ if (rel.startsWith('..') || path.isAbsolute(rel))
25
+ return null;
26
+ return abs;
27
+ }
28
+ /**
29
+ * Atomic file write: tmp + rename. Mirrors `atomicWriteFileSync` in
30
+ * `src/installer/targets/shared.ts` — kept local here to avoid the
31
+ * @selvakumaresra/specship deep-import dance for a 10-line helper.
32
+ */
33
+ function atomicWriteFile(targetPath, content) {
34
+ const dir = path.dirname(targetPath);
35
+ fs.mkdirSync(dir, { recursive: true });
36
+ const tmp = `${targetPath}.tmp.${process.pid}.${Date.now()}`;
37
+ fs.writeFileSync(tmp, content, 'utf-8');
38
+ fs.renameSync(tmp, targetPath);
39
+ }
40
+ async function resolveCg(app, req, reply) {
41
+ const cg = await app.activeCg(req);
42
+ if (!cg) {
43
+ reply.code(409).send({ error: 'no project selected', code: 'no_project' });
44
+ return null;
45
+ }
46
+ return cg;
47
+ }
48
+ export async function registerSpecRoutes(app) {
49
+ app.get('/api/specs', async (req, reply) => {
50
+ const cg = await resolveCg(app, req, reply);
51
+ if (!cg)
52
+ return;
53
+ const docs = cg.getSpecQueries().getAllSpecs();
54
+ return { specs: docs };
55
+ });
56
+ app.get('/api/spec/:id', async (req, reply) => {
57
+ const cg = await resolveCg(app, req, reply);
58
+ if (!cg)
59
+ return;
60
+ const sq = cg.getSpecQueries();
61
+ const spec = sq.getSpecById(req.params.id);
62
+ if (!spec)
63
+ return reply.code(404).send({ error: 'spec not found' });
64
+ const parent = spec.parentId ? sq.getSpecById(spec.parentId) : null;
65
+ const children = sq.getSpecsByParent(spec.id);
66
+ const siblings = parent ? sq.getSpecsByParent(parent.id).filter((s) => s.id !== spec.id) : [];
67
+ const links = sq.getLinksBySpec(spec.id);
68
+ // Read the raw source file so the dashboard's Monaco editor can edit
69
+ // the whole document, not just the DB-parsed body fragment for this
70
+ // requirement. The `spec.body` field stores per-section content; the
71
+ // editor needs the file.
72
+ let source = null;
73
+ try {
74
+ const projectRoot = cg.getProjectRoot();
75
+ const absPath = safeProjectPath(projectRoot, spec.sourcePath);
76
+ if (absPath && fs.existsSync(absPath)) {
77
+ source = fs.readFileSync(absPath, 'utf-8');
78
+ }
79
+ }
80
+ catch {
81
+ // File missing or unreadable — return null so the UI can show a
82
+ // "source not available" hint without failing the whole fetch.
83
+ }
84
+ return { spec, parent, siblings, children, links, source };
85
+ });
86
+ app.get('/api/drift', async (req, reply) => {
87
+ const cg = await resolveCg(app, req, reply);
88
+ if (!cg)
89
+ return;
90
+ const sq = cg.getSpecQueries();
91
+ const validStates = [
92
+ 'drafted', 'implementing', 'implemented', 'verified',
93
+ 'drifted', 'broken', 'orphaned',
94
+ ];
95
+ const requested = (req.query.state ?? 'drifted,broken,orphaned')
96
+ .split(',')
97
+ .map((s) => s.trim())
98
+ .filter((s) => validStates.includes(s));
99
+ const limit = Math.min(parseInt(req.query.limit ?? '100', 10) || 100, 500);
100
+ const links = sq.getLinksByState(requested).slice(0, limit);
101
+ const out = links.map((l) => {
102
+ const spec = sq.getSpecById(l.specId);
103
+ return { ...l, specTitle: spec?.title ?? null };
104
+ });
105
+ return { links: out };
106
+ });
107
+ app.post('/api/spec/link-assert', async (req, reply) => {
108
+ const cg = await resolveCg(app, req, reply);
109
+ if (!cg)
110
+ return;
111
+ const body = req.body;
112
+ if (!body?.spec_id || !body.target_file_path || !body.target_qualified_name) {
113
+ return reply.code(400).send({ error: 'spec_id, target_file_path, target_qualified_name required' });
114
+ }
115
+ const sq = cg.getSpecQueries();
116
+ const spec = sq.getSpecById(body.spec_id);
117
+ if (!spec)
118
+ return reply.code(404).send({ error: 'spec not found' });
119
+ const now = Date.now();
120
+ const id = sq.upsertSpecLink({
121
+ specId: body.spec_id,
122
+ targetFilePath: body.target_file_path,
123
+ targetQualifiedName: body.target_qualified_name,
124
+ targetNodeKind: body.target_node_kind ?? 'function',
125
+ resolvedNodeId: undefined,
126
+ kind: body.kind ?? 'implements',
127
+ state: 'implemented',
128
+ driftAxis: null,
129
+ specHashAtLink: spec.contentHash,
130
+ nodeSigAtLink: undefined,
131
+ provenance: 'agent-asserted',
132
+ confidence: 1.0,
133
+ createdAt: now,
134
+ updatedAt: now,
135
+ });
136
+ cg.getSpecLinkResolver().resolveLinksForFiles([body.target_file_path]);
137
+ return { id, ok: true };
138
+ });
139
+ app.post('/api/spec/link-verify', async (req, reply) => {
140
+ const cg = await resolveCg(app, req, reply);
141
+ if (!cg)
142
+ return;
143
+ const body = req.body;
144
+ if (typeof body?.link_id !== 'number' || (body.result !== 'pass' && body.result !== 'fail')) {
145
+ return reply.code(400).send({ error: 'link_id (number) and result ("pass"|"fail") required' });
146
+ }
147
+ const sq = cg.getSpecQueries();
148
+ const link = sq.getLinkById(body.link_id);
149
+ if (!link)
150
+ return reply.code(404).send({ error: 'link not found' });
151
+ sq.updateSpecLinkState(body.link_id, body.result === 'pass' ? 'verified' : 'broken', null);
152
+ return { ok: true, state: body.result === 'pass' ? 'verified' : 'broken' };
153
+ });
154
+ /**
155
+ * PUT /api/spec/:id — overwrite the spec file backing this spec.
156
+ *
157
+ * Resolves the source file path from the existing spec row, validates it's
158
+ * under the project root (path-traversal guard), atomically writes the new
159
+ * content, then re-syncs the project so the indexer picks up the change.
160
+ * Returns the freshly re-parsed spec node. Used by the dashboard's Monaco
161
+ * editor.
162
+ */
163
+ app.put('/api/spec/:id', async (req, reply) => {
164
+ const cg = await resolveCg(app, req, reply);
165
+ if (!cg)
166
+ return;
167
+ const sq = cg.getSpecQueries();
168
+ const spec = sq.getSpecById(req.params.id);
169
+ if (!spec)
170
+ return reply.code(404).send({ error: 'spec not found' });
171
+ const body = req.body;
172
+ if (typeof body?.content !== 'string') {
173
+ return reply.code(400).send({ error: 'content (string) required' });
174
+ }
175
+ const projectRoot = cg.getProjectRoot();
176
+ const absPath = safeProjectPath(projectRoot, spec.sourcePath);
177
+ if (!absPath) {
178
+ return reply.code(400).send({
179
+ error: 'spec.sourcePath resolves outside project root',
180
+ code: 'path_traversal',
181
+ });
182
+ }
183
+ try {
184
+ atomicWriteFile(absPath, body.content);
185
+ }
186
+ catch (e) {
187
+ return reply.code(500).send({
188
+ error: 'failed to write spec file',
189
+ detail: e instanceof Error ? e.message : String(e),
190
+ });
191
+ }
192
+ // Re-index so the freshly-edited spec replaces the old graph nodes.
193
+ // The Markdown extractor will rebuild the doc + REQs + acceptance
194
+ // children, and the link resolver re-runs against the new content
195
+ // hash so drift states transition correctly.
196
+ try {
197
+ await cg.sync();
198
+ }
199
+ catch (e) {
200
+ // Sync errors don't roll back the write — the file is on disk and
201
+ // the next sync will pick it up. Surface so the UI can show a
202
+ // "saved but not yet indexed" hint.
203
+ const updated = sq.getSpecById(req.params.id);
204
+ return {
205
+ ok: true,
206
+ spec: updated ?? spec,
207
+ syncError: e instanceof Error ? e.message : String(e),
208
+ };
209
+ }
210
+ const updated = sq.getSpecById(req.params.id);
211
+ return { ok: true, spec: updated ?? spec };
212
+ });
213
+ /**
214
+ * POST /api/specs — create a new spec file under the project's specs/
215
+ * directory.
216
+ *
217
+ * `filePath` is project-relative (e.g. `specs/billing.md`). 409 if the
218
+ * file already exists. Used by the dashboard's Draft-with-Claude flow
219
+ * for the optional "finalize via dashboard" path.
220
+ */
221
+ app.post('/api/specs', async (req, reply) => {
222
+ const cg = await resolveCg(app, req, reply);
223
+ if (!cg)
224
+ return;
225
+ const body = req.body;
226
+ if (typeof body?.filePath !== 'string' || typeof body?.content !== 'string') {
227
+ return reply.code(400).send({ error: 'filePath and content (strings) required' });
228
+ }
229
+ const projectRoot = cg.getProjectRoot();
230
+ const absPath = safeProjectPath(projectRoot, body.filePath);
231
+ if (!absPath) {
232
+ return reply.code(400).send({
233
+ error: 'filePath resolves outside project root',
234
+ code: 'path_traversal',
235
+ });
236
+ }
237
+ if (fs.existsSync(absPath)) {
238
+ return reply.code(409).send({
239
+ error: 'file already exists',
240
+ code: 'file_exists',
241
+ filePath: body.filePath,
242
+ });
243
+ }
244
+ try {
245
+ atomicWriteFile(absPath, body.content);
246
+ }
247
+ catch (e) {
248
+ return reply.code(500).send({
249
+ error: 'failed to write spec file',
250
+ detail: e instanceof Error ? e.message : String(e),
251
+ });
252
+ }
253
+ try {
254
+ await cg.sync();
255
+ }
256
+ catch (e) {
257
+ return {
258
+ ok: true,
259
+ filePath: body.filePath,
260
+ syncError: e instanceof Error ? e.message : String(e),
261
+ };
262
+ }
263
+ return { ok: true, filePath: body.filePath };
264
+ });
265
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * GET /api/status — backend, journal mode, node/edge counts, drift count,
3
+ * last index time. Drives the UI's persistent status strip.
4
+ *
5
+ * POST /api/refresh — force-sync the SpecShip index AND trigger an
6
+ * immediate Claude Code transcript re-ingest. Wired to the global
7
+ * refresh button in the dashboard's status strip so users can pull
8
+ * Sessions / Heatmap / Costs / Memory current without waiting on the
9
+ * watcher's debounce.
10
+ *
11
+ * Project-scoped: accepts `?project=<slug>` and serves the matching
12
+ * SpecShip instance from the registry. When no project is selectable
13
+ * (no `?project=`, no primary), returns a 409 with `code: 'no_project'`
14
+ * so the UI can show the picker without blowing up.
15
+ */
16
+ export async function registerStatusRoutes(app) {
17
+ app.get('/api/status', async (req, reply) => {
18
+ const cg = await app.activeCg(req);
19
+ if (!cg) {
20
+ return reply.code(409).send({ error: 'no project selected', code: 'no_project' });
21
+ }
22
+ const stats = cg.getStats();
23
+ const lastIndexed = cg.getLastIndexedAt();
24
+ const drift = cg
25
+ .getSpecQueries()
26
+ .getLinksByState(['drifted', 'broken', 'orphaned']).length;
27
+ return {
28
+ projectPath: cg.getProjectRoot ? cg.getProjectRoot() : '',
29
+ backend: cg.getBackend(),
30
+ journalMode: cg.getJournalMode(),
31
+ nodeCount: stats.nodeCount,
32
+ edgeCount: stats.edgeCount,
33
+ fileCount: stats.fileCount,
34
+ drift,
35
+ lastIndexed: lastIndexed != null ? new Date(lastIndexed).toISOString() : null,
36
+ nodesByKind: stats.nodesByKind,
37
+ filesByLanguage: stats.filesByLanguage,
38
+ dbSizeBytes: stats.dbSizeBytes,
39
+ };
40
+ });
41
+ /**
42
+ * Force a synchronous re-sync of the project's SpecShip index AND a
43
+ * fresh Claude Code transcript ingest pass. The status strip's
44
+ * refresh button calls this so users can pull every project-scoped
45
+ * surface (Sessions, Heatmap, Costs, Memory, Drift, Graph) to
46
+ * current without waiting on the JSONL watcher's debounce window or
47
+ * the next file-watcher tick.
48
+ *
49
+ * Returns the same shape as GET /api/status (so the UI can update
50
+ * its strip and `lastIndexed` label in one round-trip) plus the
51
+ * ingest stats for surfaces interested in "how many new sessions
52
+ * landed."
53
+ *
54
+ * Both steps run sequentially. Errors in either are surfaced under
55
+ * `syncError` / `ingestError` so a transient ingest hiccup doesn't
56
+ * mask a successful index sync (or vice versa) — and the UI can
57
+ * decide whether to retry or surface the failure.
58
+ */
59
+ app.post('/api/refresh', async (req, reply) => {
60
+ const cg = await app.activeCg(req);
61
+ if (!cg) {
62
+ return reply.code(409).send({ error: 'no project selected', code: 'no_project' });
63
+ }
64
+ let syncError = null;
65
+ let ingestError = null;
66
+ let ingestStats = null;
67
+ // 1. Re-index the project. Picks up code AND specs/ changes the
68
+ // auto-sync hook may not have caught yet.
69
+ try {
70
+ await cg.sync();
71
+ }
72
+ catch (e) {
73
+ syncError = e instanceof Error ? e.message : String(e);
74
+ }
75
+ // 2. Re-ingest Claude Code transcripts. Skipped silently when the
76
+ // server was booted with `--no-ingest` (app.watcher == null).
77
+ if (app.watcher) {
78
+ try {
79
+ ingestStats = await app.watcher.ingestNow();
80
+ }
81
+ catch (e) {
82
+ ingestError = e instanceof Error ? e.message : String(e);
83
+ }
84
+ }
85
+ // 3. Echo the new status so the UI updates its strip + lastIndexed
86
+ // label without a separate GET.
87
+ const stats = cg.getStats();
88
+ const lastIndexed = cg.getLastIndexedAt();
89
+ const drift = cg
90
+ .getSpecQueries()
91
+ .getLinksByState(['drifted', 'broken', 'orphaned']).length;
92
+ return {
93
+ ok: syncError === null && ingestError === null,
94
+ syncError,
95
+ ingestError,
96
+ ingestStats,
97
+ status: {
98
+ projectPath: cg.getProjectRoot ? cg.getProjectRoot() : '',
99
+ backend: cg.getBackend(),
100
+ journalMode: cg.getJournalMode(),
101
+ nodeCount: stats.nodeCount,
102
+ edgeCount: stats.edgeCount,
103
+ fileCount: stats.fileCount,
104
+ drift,
105
+ lastIndexed: lastIndexed != null ? new Date(lastIndexed).toISOString() : null,
106
+ nodesByKind: stats.nodesByKind,
107
+ filesByLanguage: stats.filesByLanguage,
108
+ dbSizeBytes: stats.dbSizeBytes,
109
+ },
110
+ };
111
+ });
112
+ }
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Workflow routes — discover / run / resume / cancel / approve / reject /
3
+ * runs list / run detail + SSE event stream.
4
+ *
5
+ * All project-scoped via `?project=<slug>` (falls back to primary). Each
6
+ * handler resolves the active SpecShip instance from the registry and
7
+ * constructs the WorktreeProvider + WorkflowExecutor on demand against
8
+ * that instance's queries. Construction is cheap (both classes just stash
9
+ * references), and pinning a single executor across all projects would
10
+ * tie the entire surface to whichever instance loaded first.
11
+ *
12
+ * The SSE endpoint streams workflow_events as they're appended to the DB
13
+ * (polling 500ms). For v1 polling the same SQLite the executor writes to is
14
+ * faster + more reliable than wiring an in-process event bus across packages.
15
+ */
16
+ import path from 'node:path';
17
+ import { existsSync } from 'node:fs';
18
+ import { fileURLToPath, pathToFileURL } from 'node:url';
19
+ async function resolveCg(app, req, reply) {
20
+ const cg = await app.activeCg(req);
21
+ if (!cg) {
22
+ reply.code(409).send({ error: 'no project selected', code: 'no_project' });
23
+ return null;
24
+ }
25
+ return cg;
26
+ }
27
+ export async function registerWorkflowRoutes(app) {
28
+ // Lazy import — keeps the server bootable even if the workflow engine
29
+ // is disabled in the current build profile.
30
+ //
31
+ // Two delivery shapes (same pattern as loadSpecShip() in ../server.ts):
32
+ // 1. **Bundled** — `dist/server/routes/workflow.js` sits two levels under
33
+ // `dist/`, so the core workflow modules live at `../../workflows/*.js`
34
+ // and `../../isolation/*.js`. We try this relative path first because
35
+ // the bundled tarball stages the specship core without a resolvable
36
+ // `@selvakumaresra/specship` package on Node's module graph (offline
37
+ // installs hit this — see scripts/offline-install.sh).
38
+ // 2. **Workspace / dev** — the `file:../..` workspace dep resolves the
39
+ // named import via Node's normal package resolution.
40
+ let discovery;
41
+ let executorMod;
42
+ let worktreeMod;
43
+ const here = path.dirname(fileURLToPath(import.meta.url));
44
+ const bundledDiscovery = path.resolve(here, '..', '..', 'workflows', 'discovery.js');
45
+ if (existsSync(bundledDiscovery)) {
46
+ discovery = await import(pathToFileURL(bundledDiscovery).href);
47
+ executorMod = await import(pathToFileURL(path.resolve(here, '..', '..', 'workflows', 'executor.js')).href);
48
+ worktreeMod = await import(pathToFileURL(path.resolve(here, '..', '..', 'isolation', 'worktree.js')).href);
49
+ }
50
+ else {
51
+ discovery = await import('@selvakumaresra/specship/dist/workflows/discovery.js');
52
+ executorMod = await import('@selvakumaresra/specship/dist/workflows/executor.js');
53
+ worktreeMod = await import('@selvakumaresra/specship/dist/isolation/worktree.js');
54
+ }
55
+ const { discoverWorkflows, loadWorkflowByName } = discovery;
56
+ const { WorkflowExecutor } = executorMod;
57
+ const { WorktreeProvider } = worktreeMod;
58
+ const executorCache = new WeakMap();
59
+ /** Build (or fetch cached) executor + worktree provider for a project. */
60
+ function executorFor(cg) {
61
+ const sq = cg.getSpecQueries();
62
+ const cached = executorCache.get(sq);
63
+ if (cached)
64
+ return { sq, executor: cached.executor, projectRoot: cached.projectRoot };
65
+ const projectRoot = cg.getProjectRoot ? cg.getProjectRoot() : process.cwd();
66
+ const worktrees = new WorktreeProvider(sq);
67
+ const executor = new WorkflowExecutor(sq, worktrees);
68
+ executorCache.set(sq, { executor, projectRoot });
69
+ return { sq, executor, projectRoot };
70
+ }
71
+ app.get('/api/workflows', async (req, reply) => {
72
+ const cg = await resolveCg(app, req, reply);
73
+ if (!cg)
74
+ return;
75
+ const { projectRoot } = executorFor(cg);
76
+ return discoverWorkflows(projectRoot);
77
+ });
78
+ app.post('/api/workflows/runs', async (req, reply) => {
79
+ const cg = await resolveCg(app, req, reply);
80
+ if (!cg)
81
+ return;
82
+ const { executor, projectRoot } = executorFor(cg);
83
+ const body = req.body;
84
+ if (!body?.workflowName)
85
+ return reply.code(400).send({ error: 'workflowName required' });
86
+ const loaded = loadWorkflowByName(projectRoot, body.workflowName);
87
+ if (!loaded)
88
+ return reply.code(404).send({ error: 'workflow not found' });
89
+ const startPromise = executor.start(loaded.workflow, {
90
+ projectRoot,
91
+ inputs: body.inputs,
92
+ variables: body.variables,
93
+ });
94
+ const result = await Promise.race([
95
+ startPromise,
96
+ new Promise((resolve) => setTimeout(() => resolve({ run: { id: 'pending', status: 'starting' } }), 50)),
97
+ ]);
98
+ startPromise.catch(() => { });
99
+ return { runId: result.run.id, status: result.run.status };
100
+ });
101
+ app.get('/api/workflows/runs', async (req, reply) => {
102
+ const cg = await resolveCg(app, req, reply);
103
+ if (!cg)
104
+ return;
105
+ const { sq } = executorFor(cg);
106
+ const limit = Math.min(parseInt(req.query.limit ?? '50', 10) || 50, 500);
107
+ return { runs: sq.getAllWorkflowRuns(limit) };
108
+ });
109
+ app.get('/api/workflows/runs/:id', async (req, reply) => {
110
+ const cg = await resolveCg(app, req, reply);
111
+ if (!cg)
112
+ return;
113
+ const { sq } = executorFor(cg);
114
+ const run = sq.getWorkflowRunById(req.params.id);
115
+ if (!run)
116
+ return reply.code(404).send({ error: 'run not found' });
117
+ const events = sq.getEventsByRun(req.params.id, 500);
118
+ return { run, events };
119
+ });
120
+ /**
121
+ * SSE event stream. Polls the events table every 500ms for any events
122
+ * newer than the last id sent. Closes when the run hits a terminal state.
123
+ */
124
+ app.get('/api/workflows/runs/:id/events', async (req, reply) => {
125
+ const cg = await resolveCg(app, req, reply);
126
+ if (!cg)
127
+ return;
128
+ const { sq } = executorFor(cg);
129
+ const runId = req.params.id;
130
+ let lastId = parseInt(req.query.since ?? '0', 10) || 0;
131
+ reply.raw.setHeader('Content-Type', 'text/event-stream');
132
+ reply.raw.setHeader('Cache-Control', 'no-cache');
133
+ reply.raw.setHeader('Connection', 'keep-alive');
134
+ reply.raw.flushHeaders();
135
+ let closed = false;
136
+ req.raw.on('close', () => { closed = true; });
137
+ const tick = async () => {
138
+ if (closed)
139
+ return;
140
+ const events = sq.getEventsByRun(runId, 1000);
141
+ const fresh = events.filter((e) => e.id > lastId);
142
+ for (const e of fresh) {
143
+ reply.raw.write(`id: ${e.id}\n`);
144
+ reply.raw.write(`event: ${e.eventType}\n`);
145
+ reply.raw.write(`data: ${JSON.stringify(e)}\n\n`);
146
+ lastId = e.id;
147
+ }
148
+ const run = sq.getWorkflowRunById(runId);
149
+ if (!run || ['completed', 'failed', 'cancelled'].includes(run.status)) {
150
+ reply.raw.write(`event: done\ndata: ${JSON.stringify({ status: run?.status })}\n\n`);
151
+ reply.raw.end();
152
+ return;
153
+ }
154
+ setTimeout(() => { void tick(); }, 500);
155
+ };
156
+ void tick();
157
+ });
158
+ app.post('/api/workflows/runs/:id/approve', async (req, reply) => {
159
+ const cg = await resolveCg(app, req, reply);
160
+ if (!cg)
161
+ return;
162
+ const { executor } = executorFor(cg);
163
+ try {
164
+ executor.approve(req.params.id, req.body?.comment);
165
+ return { ok: true };
166
+ }
167
+ catch (err) {
168
+ return reply.code(400).send({ error: err instanceof Error ? err.message : String(err) });
169
+ }
170
+ });
171
+ app.post('/api/workflows/runs/:id/reject', async (req, reply) => {
172
+ const cg = await resolveCg(app, req, reply);
173
+ if (!cg)
174
+ return;
175
+ const { executor } = executorFor(cg);
176
+ try {
177
+ executor.reject(req.params.id, req.body?.reason);
178
+ return { ok: true };
179
+ }
180
+ catch (err) {
181
+ return reply.code(400).send({ error: err instanceof Error ? err.message : String(err) });
182
+ }
183
+ });
184
+ app.post('/api/workflows/runs/:id/cancel', async (req, reply) => {
185
+ const cg = await resolveCg(app, req, reply);
186
+ if (!cg)
187
+ return;
188
+ const { executor } = executorFor(cg);
189
+ try {
190
+ executor.cancel(req.params.id, req.body?.reason);
191
+ return { ok: true };
192
+ }
193
+ catch (err) {
194
+ return reply.code(400).send({ error: err instanceof Error ? err.message : String(err) });
195
+ }
196
+ });
197
+ app.post('/api/workflows/runs/:id/resume', async (req, reply) => {
198
+ const cg = await resolveCg(app, req, reply);
199
+ if (!cg)
200
+ return;
201
+ const { sq, executor, projectRoot } = executorFor(cg);
202
+ const run = sq.getWorkflowRunById(req.params.id);
203
+ if (!run)
204
+ return reply.code(404).send({ error: 'run not found' });
205
+ const loaded = loadWorkflowByName(projectRoot, run.workflowName);
206
+ if (!loaded)
207
+ return reply.code(404).send({ error: 'workflow definition missing' });
208
+ const promise = executor.resume(loaded.workflow, req.params.id, { projectRoot });
209
+ promise.catch(() => { });
210
+ return { ok: true };
211
+ });
212
+ }