@specship/specship-win32-arm64 0.24.0 → 0.28.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 (341) hide show
  1. package/bin/specship.cmd +31 -1
  2. package/lib/dist/activation/cheatsheet.d.ts +17 -1
  3. package/lib/dist/activation/cheatsheet.d.ts.map +1 -1
  4. package/lib/dist/activation/cheatsheet.js +47 -3
  5. package/lib/dist/activation/cheatsheet.js.map +1 -1
  6. package/lib/dist/activation/hook-output.d.ts +80 -0
  7. package/lib/dist/activation/hook-output.d.ts.map +1 -0
  8. package/lib/dist/activation/hook-output.js +103 -0
  9. package/lib/dist/activation/hook-output.js.map +1 -0
  10. package/lib/dist/activation/search-intercept.d.ts +60 -29
  11. package/lib/dist/activation/search-intercept.d.ts.map +1 -1
  12. package/lib/dist/activation/search-intercept.js +159 -55
  13. package/lib/dist/activation/search-intercept.js.map +1 -1
  14. package/lib/dist/activation/steering.d.ts +11 -13
  15. package/lib/dist/activation/steering.d.ts.map +1 -1
  16. package/lib/dist/activation/steering.js +25 -10
  17. package/lib/dist/activation/steering.js.map +1 -1
  18. package/lib/dist/behaviour/behaviour-surface.d.ts +47 -0
  19. package/lib/dist/behaviour/behaviour-surface.d.ts.map +1 -1
  20. package/lib/dist/behaviour/behaviour-surface.js +108 -2
  21. package/lib/dist/behaviour/behaviour-surface.js.map +1 -1
  22. package/lib/dist/bin/node-version-check.d.ts +22 -7
  23. package/lib/dist/bin/node-version-check.d.ts.map +1 -1
  24. package/lib/dist/bin/node-version-check.js +39 -9
  25. package/lib/dist/bin/node-version-check.js.map +1 -1
  26. package/lib/dist/bin/specship.js +989 -116
  27. package/lib/dist/bin/specship.js.map +1 -1
  28. package/lib/dist/commands/specship/learn.md +27 -3
  29. package/lib/dist/commands/specship/spec.md +85 -15
  30. package/lib/dist/db/spec-queries.d.ts +73 -3
  31. package/lib/dist/db/spec-queries.d.ts.map +1 -1
  32. package/lib/dist/db/spec-queries.js +139 -5
  33. package/lib/dist/db/spec-queries.js.map +1 -1
  34. package/lib/dist/db/sqlite-adapter.d.ts +7 -5
  35. package/lib/dist/db/sqlite-adapter.d.ts.map +1 -1
  36. package/lib/dist/db/sqlite-adapter.js +11 -9
  37. package/lib/dist/db/sqlite-adapter.js.map +1 -1
  38. package/lib/dist/enforce/changed-files.d.ts +39 -0
  39. package/lib/dist/enforce/changed-files.d.ts.map +1 -0
  40. package/lib/dist/enforce/changed-files.js +114 -0
  41. package/lib/dist/enforce/changed-files.js.map +1 -0
  42. package/lib/dist/enforce/enforce.d.ts +53 -2
  43. package/lib/dist/enforce/enforce.d.ts.map +1 -1
  44. package/lib/dist/enforce/enforce.js +95 -8
  45. package/lib/dist/enforce/enforce.js.map +1 -1
  46. package/lib/dist/enforce/mutation.d.ts +46 -0
  47. package/lib/dist/enforce/mutation.d.ts.map +1 -0
  48. package/lib/dist/enforce/mutation.js +104 -0
  49. package/lib/dist/enforce/mutation.js.map +1 -0
  50. package/lib/dist/enforce/suppressions.d.ts +33 -0
  51. package/lib/dist/enforce/suppressions.d.ts.map +1 -0
  52. package/lib/dist/enforce/suppressions.js +159 -0
  53. package/lib/dist/enforce/suppressions.js.map +1 -0
  54. package/lib/dist/extraction/grammars.d.ts +10 -0
  55. package/lib/dist/extraction/grammars.d.ts.map +1 -1
  56. package/lib/dist/extraction/grammars.js +32 -3
  57. package/lib/dist/extraction/grammars.js.map +1 -1
  58. package/lib/dist/extraction/index.d.ts +7 -0
  59. package/lib/dist/extraction/index.d.ts.map +1 -1
  60. package/lib/dist/extraction/index.js.map +1 -1
  61. package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts +7 -0
  62. package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -1
  63. package/lib/dist/extraction/specs/markdown-spec-extractor.js +97 -10
  64. package/lib/dist/extraction/specs/markdown-spec-extractor.js.map +1 -1
  65. package/lib/dist/extraction/wasm/tree-sitter-pascal.wasm.gz +0 -0
  66. package/lib/dist/extraction/wasm/tree-sitter-scala.wasm.gz +0 -0
  67. package/lib/dist/graph/spec-coverage.d.ts +142 -0
  68. package/lib/dist/graph/spec-coverage.d.ts.map +1 -0
  69. package/lib/dist/graph/spec-coverage.js +276 -0
  70. package/lib/dist/graph/spec-coverage.js.map +1 -0
  71. package/lib/dist/health/smoke-check.js +2 -2
  72. package/lib/dist/health/smoke-check.js.map +1 -1
  73. package/lib/dist/index.d.ts +75 -7
  74. package/lib/dist/index.d.ts.map +1 -1
  75. package/lib/dist/index.js +191 -23
  76. package/lib/dist/index.js.map +1 -1
  77. package/lib/dist/installer/gemini-commands.d.ts +107 -0
  78. package/lib/dist/installer/gemini-commands.d.ts.map +1 -0
  79. package/lib/dist/installer/gemini-commands.js +264 -0
  80. package/lib/dist/installer/gemini-commands.js.map +1 -0
  81. package/lib/dist/installer/index.d.ts +55 -8
  82. package/lib/dist/installer/index.d.ts.map +1 -1
  83. package/lib/dist/installer/index.js +72 -53
  84. package/lib/dist/installer/index.js.map +1 -1
  85. package/lib/dist/installer/init-offer.d.ts +14 -9
  86. package/lib/dist/installer/init-offer.d.ts.map +1 -1
  87. package/lib/dist/installer/init-offer.js +13 -9
  88. package/lib/dist/installer/init-offer.js.map +1 -1
  89. package/lib/dist/installer/install-defaults.d.ts +81 -0
  90. package/lib/dist/installer/install-defaults.d.ts.map +1 -0
  91. package/lib/dist/installer/install-defaults.js +95 -0
  92. package/lib/dist/installer/install-defaults.js.map +1 -0
  93. package/lib/dist/installer/instructions-template.d.ts +22 -0
  94. package/lib/dist/installer/instructions-template.d.ts.map +1 -1
  95. package/lib/dist/installer/instructions-template.js +37 -1
  96. package/lib/dist/installer/instructions-template.js.map +1 -1
  97. package/lib/dist/installer/targets/claude.d.ts +18 -0
  98. package/lib/dist/installer/targets/claude.d.ts.map +1 -1
  99. package/lib/dist/installer/targets/claude.js +70 -23
  100. package/lib/dist/installer/targets/claude.js.map +1 -1
  101. package/lib/dist/installer/targets/gemini.d.ts +85 -12
  102. package/lib/dist/installer/targets/gemini.d.ts.map +1 -1
  103. package/lib/dist/installer/targets/gemini.js +527 -30
  104. package/lib/dist/installer/targets/gemini.js.map +1 -1
  105. package/lib/dist/installer/targets/shared.d.ts +13 -0
  106. package/lib/dist/installer/targets/shared.d.ts.map +1 -1
  107. package/lib/dist/installer/targets/shared.js +22 -4
  108. package/lib/dist/installer/targets/shared.js.map +1 -1
  109. package/lib/dist/installer/targets/types.d.ts +12 -0
  110. package/lib/dist/installer/targets/types.d.ts.map +1 -1
  111. package/lib/dist/jira/auto-publish.d.ts +71 -4
  112. package/lib/dist/jira/auto-publish.d.ts.map +1 -1
  113. package/lib/dist/jira/auto-publish.js +186 -17
  114. package/lib/dist/jira/auto-publish.js.map +1 -1
  115. package/lib/dist/jira/reconcile.d.ts +24 -1
  116. package/lib/dist/jira/reconcile.d.ts.map +1 -1
  117. package/lib/dist/jira/reconcile.js +46 -2
  118. package/lib/dist/jira/reconcile.js.map +1 -1
  119. package/lib/dist/jira/repo-config.d.ts +9 -0
  120. package/lib/dist/jira/repo-config.d.ts.map +1 -1
  121. package/lib/dist/jira/repo-config.js +11 -0
  122. package/lib/dist/jira/repo-config.js.map +1 -1
  123. package/lib/dist/jira/types.d.ts +7 -0
  124. package/lib/dist/jira/types.d.ts.map +1 -1
  125. package/lib/dist/jira/types.js.map +1 -1
  126. package/lib/dist/knowledge/enforce.d.ts +75 -0
  127. package/lib/dist/knowledge/enforce.d.ts.map +1 -0
  128. package/lib/dist/knowledge/enforce.js +250 -0
  129. package/lib/dist/knowledge/enforce.js.map +1 -0
  130. package/lib/dist/knowledge/facts.d.ts +33 -0
  131. package/lib/dist/knowledge/facts.d.ts.map +1 -0
  132. package/lib/dist/knowledge/facts.js +117 -0
  133. package/lib/dist/knowledge/facts.js.map +1 -0
  134. package/lib/dist/knowledge/proposals.d.ts +88 -0
  135. package/lib/dist/knowledge/proposals.d.ts.map +1 -0
  136. package/lib/dist/knowledge/proposals.js +360 -0
  137. package/lib/dist/knowledge/proposals.js.map +1 -0
  138. package/lib/dist/knowledge/stale.d.ts +64 -0
  139. package/lib/dist/knowledge/stale.d.ts.map +1 -0
  140. package/lib/dist/knowledge/stale.js +174 -0
  141. package/lib/dist/knowledge/stale.js.map +1 -0
  142. package/lib/dist/mcp/fitness-tool.d.ts +5 -6
  143. package/lib/dist/mcp/fitness-tool.d.ts.map +1 -1
  144. package/lib/dist/mcp/fitness-tool.js +0 -16
  145. package/lib/dist/mcp/fitness-tool.js.map +1 -1
  146. package/lib/dist/mcp/gemini-session.d.ts +50 -0
  147. package/lib/dist/mcp/gemini-session.d.ts.map +1 -0
  148. package/lib/dist/mcp/gemini-session.js +159 -0
  149. package/lib/dist/mcp/gemini-session.js.map +1 -0
  150. package/lib/dist/mcp/health-tool.d.ts +26 -0
  151. package/lib/dist/mcp/health-tool.d.ts.map +1 -0
  152. package/lib/dist/mcp/health-tool.js +50 -0
  153. package/lib/dist/mcp/health-tool.js.map +1 -0
  154. package/lib/dist/mcp/jira-tools.d.ts.map +1 -1
  155. package/lib/dist/mcp/jira-tools.js +25 -0
  156. package/lib/dist/mcp/jira-tools.js.map +1 -1
  157. package/lib/dist/mcp/maintainability-tool.d.ts +5 -7
  158. package/lib/dist/mcp/maintainability-tool.d.ts.map +1 -1
  159. package/lib/dist/mcp/maintainability-tool.js +0 -16
  160. package/lib/dist/mcp/maintainability-tool.js.map +1 -1
  161. package/lib/dist/mcp/model-context.d.ts +31 -7
  162. package/lib/dist/mcp/model-context.d.ts.map +1 -1
  163. package/lib/dist/mcp/model-context.js +70 -21
  164. package/lib/dist/mcp/model-context.js.map +1 -1
  165. package/lib/dist/mcp/proxy.d.ts.map +1 -1
  166. package/lib/dist/mcp/proxy.js +5 -2
  167. package/lib/dist/mcp/proxy.js.map +1 -1
  168. package/lib/dist/mcp/server-instructions.d.ts +16 -15
  169. package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
  170. package/lib/dist/mcp/server-instructions.js +72 -5
  171. package/lib/dist/mcp/server-instructions.js.map +1 -1
  172. package/lib/dist/mcp/session.js +1 -1
  173. package/lib/dist/mcp/session.js.map +1 -1
  174. package/lib/dist/mcp/spec-tools.d.ts +9 -1
  175. package/lib/dist/mcp/spec-tools.d.ts.map +1 -1
  176. package/lib/dist/mcp/spec-tools.js +282 -49
  177. package/lib/dist/mcp/spec-tools.js.map +1 -1
  178. package/lib/dist/mcp/tools.d.ts +49 -9
  179. package/lib/dist/mcp/tools.d.ts.map +1 -1
  180. package/lib/dist/mcp/tools.js +210 -58
  181. package/lib/dist/mcp/tools.js.map +1 -1
  182. package/lib/dist/pulse/pulse.d.ts +93 -0
  183. package/lib/dist/pulse/pulse.d.ts.map +1 -0
  184. package/lib/dist/pulse/pulse.js +401 -0
  185. package/lib/dist/pulse/pulse.js.map +1 -0
  186. package/lib/dist/reflect/apply.d.ts.map +1 -1
  187. package/lib/dist/reflect/apply.js +38 -3
  188. package/lib/dist/reflect/apply.js.map +1 -1
  189. package/lib/dist/reflect/auto-sweep.d.ts +26 -0
  190. package/lib/dist/reflect/auto-sweep.d.ts.map +1 -0
  191. package/lib/dist/reflect/auto-sweep.js +90 -0
  192. package/lib/dist/reflect/auto-sweep.js.map +1 -0
  193. package/lib/dist/reflect/cli.d.ts +62 -0
  194. package/lib/dist/reflect/cli.d.ts.map +1 -0
  195. package/lib/dist/reflect/cli.js +163 -0
  196. package/lib/dist/reflect/cli.js.map +1 -0
  197. package/lib/dist/reflect/miner.d.ts.map +1 -1
  198. package/lib/dist/reflect/miner.js +119 -0
  199. package/lib/dist/reflect/miner.js.map +1 -1
  200. package/lib/dist/reflect/sweep.d.ts +1 -0
  201. package/lib/dist/reflect/sweep.d.ts.map +1 -1
  202. package/lib/dist/reflect/sweep.js +62 -13
  203. package/lib/dist/reflect/sweep.js.map +1 -1
  204. package/lib/dist/reflect/targets.d.ts +2 -0
  205. package/lib/dist/reflect/targets.d.ts.map +1 -1
  206. package/lib/dist/reflect/targets.js +33 -0
  207. package/lib/dist/reflect/targets.js.map +1 -1
  208. package/lib/dist/reflect/types.d.ts +19 -2
  209. package/lib/dist/reflect/types.d.ts.map +1 -1
  210. package/lib/dist/resolution/spec-link-resolver.d.ts +44 -2
  211. package/lib/dist/resolution/spec-link-resolver.d.ts.map +1 -1
  212. package/lib/dist/resolution/spec-link-resolver.js +132 -0
  213. package/lib/dist/resolution/spec-link-resolver.js.map +1 -1
  214. package/lib/dist/resolution/test-title-links.d.ts +62 -0
  215. package/lib/dist/resolution/test-title-links.d.ts.map +1 -0
  216. package/lib/dist/resolution/test-title-links.js +97 -0
  217. package/lib/dist/resolution/test-title-links.js.map +1 -0
  218. package/lib/dist/search/query-parser.d.ts.map +1 -1
  219. package/lib/dist/search/query-parser.js +6 -1
  220. package/lib/dist/search/query-parser.js.map +1 -1
  221. package/lib/dist/server/project-registry.js +1 -1
  222. package/lib/dist/server/routes/claude.js +24 -43
  223. package/lib/dist/server/routes/graph.js +53 -7
  224. package/lib/dist/server/routes/knowledge.js +118 -0
  225. package/lib/dist/server/routes/mcp.js +4 -3
  226. package/lib/dist/server/routes/projects.js +4 -4
  227. package/lib/dist/server/routes/spec.js +49 -7
  228. package/lib/dist/server/server.js +31 -17
  229. package/lib/dist/skills/spec-author/SKILL.md +164 -0
  230. package/lib/dist/skills/spec-author/references/format.md +210 -0
  231. package/lib/dist/skills/spec-author/references/gap-questions.md +152 -0
  232. package/lib/dist/skills/spec-author/references/quality-rubric.md +125 -0
  233. package/lib/dist/skills/spec-author/references/review-checklist.md +175 -0
  234. package/lib/dist/spec-lint/lint.d.ts +82 -0
  235. package/lib/dist/spec-lint/lint.d.ts.map +1 -0
  236. package/lib/dist/spec-lint/lint.js +491 -0
  237. package/lib/dist/spec-lint/lint.js.map +1 -0
  238. package/lib/dist/spec-quality/criterion-ids.d.ts +13 -0
  239. package/lib/dist/spec-quality/criterion-ids.d.ts.map +1 -0
  240. package/lib/dist/spec-quality/criterion-ids.js +38 -0
  241. package/lib/dist/spec-quality/criterion-ids.js.map +1 -0
  242. package/lib/dist/spec-quality/evidence-kind.d.ts +54 -0
  243. package/lib/dist/spec-quality/evidence-kind.d.ts.map +1 -0
  244. package/lib/dist/spec-quality/evidence-kind.js +183 -0
  245. package/lib/dist/spec-quality/evidence-kind.js.map +1 -0
  246. package/lib/dist/spec-quality/link-persist.d.ts +65 -0
  247. package/lib/dist/spec-quality/link-persist.d.ts.map +1 -0
  248. package/lib/dist/spec-quality/link-persist.js +249 -0
  249. package/lib/dist/spec-quality/link-persist.js.map +1 -0
  250. package/lib/dist/spec-quality/plan-scope.d.ts +38 -0
  251. package/lib/dist/spec-quality/plan-scope.d.ts.map +1 -0
  252. package/lib/dist/spec-quality/plan-scope.js +129 -0
  253. package/lib/dist/spec-quality/plan-scope.js.map +1 -0
  254. package/lib/dist/spec-quality/postcheck.d.ts +85 -0
  255. package/lib/dist/spec-quality/postcheck.d.ts.map +1 -0
  256. package/lib/dist/spec-quality/postcheck.js +390 -0
  257. package/lib/dist/spec-quality/postcheck.js.map +1 -0
  258. package/lib/dist/spec-quality/readiness.d.ts +72 -0
  259. package/lib/dist/spec-quality/readiness.d.ts.map +1 -0
  260. package/lib/dist/spec-quality/readiness.js +226 -0
  261. package/lib/dist/spec-quality/readiness.js.map +1 -0
  262. package/lib/dist/statusline/index.js.map +1 -1
  263. package/lib/dist/statusline/render.d.ts +1 -1
  264. package/lib/dist/statusline/render.d.ts.map +1 -1
  265. package/lib/dist/statusline/render.js +3 -1
  266. package/lib/dist/statusline/render.js.map +1 -1
  267. package/lib/dist/ui/assets/index-BzuUWUAE.js +50 -0
  268. package/lib/dist/ui/index.html +1 -1
  269. package/lib/dist/verify/report-ingest.d.ts +88 -0
  270. package/lib/dist/verify/report-ingest.d.ts.map +1 -0
  271. package/lib/dist/verify/report-ingest.js +269 -0
  272. package/lib/dist/verify/report-ingest.js.map +1 -0
  273. package/lib/dist/workflows/agents/claude.d.ts +16 -0
  274. package/lib/dist/workflows/agents/claude.d.ts.map +1 -0
  275. package/lib/dist/workflows/agents/claude.js +82 -0
  276. package/lib/dist/workflows/agents/claude.js.map +1 -0
  277. package/lib/dist/workflows/agents/gemini.d.ts +21 -0
  278. package/lib/dist/workflows/agents/gemini.d.ts.map +1 -0
  279. package/lib/dist/workflows/agents/gemini.js +124 -0
  280. package/lib/dist/workflows/agents/gemini.js.map +1 -0
  281. package/lib/dist/workflows/agents/index.d.ts +28 -0
  282. package/lib/dist/workflows/agents/index.d.ts.map +1 -0
  283. package/lib/dist/workflows/agents/index.js +104 -0
  284. package/lib/dist/workflows/agents/index.js.map +1 -0
  285. package/lib/dist/workflows/agents/types.d.ts +55 -0
  286. package/lib/dist/workflows/agents/types.d.ts.map +1 -0
  287. package/lib/dist/workflows/agents/types.js +46 -0
  288. package/lib/dist/workflows/agents/types.js.map +1 -0
  289. package/lib/dist/workflows/batch.d.ts +63 -0
  290. package/lib/dist/workflows/batch.d.ts.map +1 -0
  291. package/lib/dist/workflows/batch.js +151 -0
  292. package/lib/dist/workflows/batch.js.map +1 -0
  293. package/lib/dist/workflows/defaults/claude-design-implement.yaml +3 -4
  294. package/lib/dist/workflows/defaults/spec-author.yaml +11 -9
  295. package/lib/dist/workflows/defaults/spec-fix.yaml +103 -12
  296. package/lib/dist/workflows/defaults/spec-implement-mixed.yaml +21 -193
  297. package/lib/dist/workflows/defaults/spec-implement.yaml +701 -41
  298. package/lib/dist/workflows/defaults/spec-verify.yaml +60 -9
  299. package/lib/dist/workflows/discovery.d.ts +13 -0
  300. package/lib/dist/workflows/discovery.d.ts.map +1 -1
  301. package/lib/dist/workflows/discovery.js +79 -17
  302. package/lib/dist/workflows/discovery.js.map +1 -1
  303. package/lib/dist/workflows/executor.d.ts +18 -0
  304. package/lib/dist/workflows/executor.d.ts.map +1 -1
  305. package/lib/dist/workflows/executor.js +130 -33
  306. package/lib/dist/workflows/executor.js.map +1 -1
  307. package/lib/dist/workflows/gc.d.ts +50 -0
  308. package/lib/dist/workflows/gc.d.ts.map +1 -0
  309. package/lib/dist/workflows/gc.js +120 -0
  310. package/lib/dist/workflows/gc.js.map +1 -0
  311. package/lib/dist/workflows/merge-queue.d.ts +64 -0
  312. package/lib/dist/workflows/merge-queue.d.ts.map +1 -0
  313. package/lib/dist/workflows/merge-queue.js +162 -0
  314. package/lib/dist/workflows/merge-queue.js.map +1 -0
  315. package/lib/dist/workflows/runners/approval.d.ts +1 -1
  316. package/lib/dist/workflows/runners/approval.d.ts.map +1 -1
  317. package/lib/dist/workflows/runners/approval.js +11 -2
  318. package/lib/dist/workflows/runners/approval.js.map +1 -1
  319. package/lib/dist/workflows/runners/bash.d.ts +15 -0
  320. package/lib/dist/workflows/runners/bash.d.ts.map +1 -1
  321. package/lib/dist/workflows/runners/bash.js +50 -1
  322. package/lib/dist/workflows/runners/bash.js.map +1 -1
  323. package/lib/dist/workflows/runners/prompt.d.ts +16 -41
  324. package/lib/dist/workflows/runners/prompt.d.ts.map +1 -1
  325. package/lib/dist/workflows/runners/prompt.js +55 -120
  326. package/lib/dist/workflows/runners/prompt.js.map +1 -1
  327. package/lib/dist/workflows/runners/types.d.ts +12 -0
  328. package/lib/dist/workflows/runners/types.d.ts.map +1 -1
  329. package/lib/dist/workflows/schemas/workflow.d.ts +17 -0
  330. package/lib/dist/workflows/schemas/workflow.d.ts.map +1 -1
  331. package/lib/dist/workflows/schemas/workflow.js +27 -0
  332. package/lib/dist/workflows/schemas/workflow.js.map +1 -1
  333. package/lib/node_modules/.package-lock.json +1 -1
  334. package/lib/package.json +8 -4
  335. package/package.json +5 -3
  336. package/lib/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  337. package/lib/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
  338. package/lib/dist/server/ingest/impact-query.js +0 -343
  339. package/lib/dist/server/routes/events.js +0 -152
  340. package/lib/dist/ui/assets/index-CjjaftDw.js +0 -50
  341. package/node.exe +0 -4
@@ -1,152 +0,0 @@
1
- /**
2
- * GET /api/events — cross-project alert stream (REQ-PWA-002).
3
- *
4
- * A single SSE stream that watches EVERY initialized project (not just the
5
- * selected one) and emits an event when an alert-worthy transition happens:
6
- * - `approval` — a workflow run entered `paused` (an approval gate)
7
- * - `runDone` — a run entered `completed` or `failed`
8
- * - `drift` — a spec→code link newly entered drifted/broken/orphaned
9
- *
10
- * Polls the same SQLite the executor/resolver write to (mirrors the workflow
11
- * SSE's 500ms-poll approach), diffing against per-connection seen-state so only
12
- * NEW transitions are emitted — never a backlog burst on connect, never a repeat
13
- * for the same transition. The client (NotificationsService) turns these into
14
- * desktop notifications, gated on permission + per-type toggles.
15
- */
16
- import os from 'node:os';
17
- import { writeSseHead } from './sse.js';
18
- import path from 'node:path';
19
- import { enumerate } from './projects.js';
20
- const POLL_MS = 3000;
21
- const KEEPALIVE_MS = 15000;
22
- // Reflection sweep cadence — high-severity-only, roughly daily (REQ-REFLECT-006).
23
- // The persisted reflect_proposals store dedupes across sweeps/connections, so a
24
- // proposal is only ever notified once regardless of how often the sweep runs.
25
- const SWEEP_MS = 24 * 60 * 60 * 1000;
26
- export async function registerEventsRoutes(app) {
27
- const claudeRoot = path.join(os.homedir(), '.claude', 'projects');
28
- app.get('/api/events', async (req, reply) => {
29
- writeSseHead(req, reply);
30
- reply.raw.write(': connected\n\n');
31
- // Per-connection seen-state — emit only NEW transitions.
32
- const lastStatus = new Map(); // `${slug}:${runId}` -> status
33
- const seenDrift = new Set(); // `${slug}:${linkId}`
34
- const lastSweep = new Map(); // slug -> last reflection sweep ms
35
- const lastIndexSig = new Map(); // slug -> lastIndexed signature
36
- let primed = false; // first pass seeds state silently (no burst on connect)
37
- let closed = false;
38
- const send = (ev) => {
39
- if (closed)
40
- return;
41
- try {
42
- reply.raw.write(`data: ${JSON.stringify(ev)}\n\n`);
43
- }
44
- catch { /* peer gone */ }
45
- };
46
- const poll = async () => {
47
- let projects;
48
- try {
49
- projects = await enumerate(claudeRoot);
50
- }
51
- catch {
52
- return;
53
- }
54
- // Bound the sweep to the most-recently-active initialized projects
55
- // (enumerate() sorts by recency): every project here is opened via the
56
- // registry, and an unbounded sweep churns the LRU open/close cycle on
57
- // every poll once slugs resolve to real paths.
58
- projects = projects.filter((p) => p.initialized).slice(0, 10);
59
- for (const p of projects) {
60
- if (closed)
61
- continue;
62
- let cg;
63
- try {
64
- cg = await app.projects.getBySlug(p.slug);
65
- }
66
- catch {
67
- cg = null;
68
- }
69
- if (!cg)
70
- continue;
71
- const sq = cg.getSpecQueries();
72
- // Workflow run transitions.
73
- let runs = [];
74
- try {
75
- runs = sq.getAllWorkflowRuns(50);
76
- }
77
- catch { /* ignore */ }
78
- for (const r of runs) {
79
- const key = `${p.slug}:${r.id}`;
80
- if (lastStatus.get(key) === r.status)
81
- continue;
82
- lastStatus.set(key, r.status);
83
- if (!primed)
84
- continue;
85
- if (r.status === 'paused') {
86
- send({ kind: 'approval', project: p.slug, projectPath: p.path, id: r.id, title: 'Run needs approval', detail: r.workflowName });
87
- }
88
- else if (r.status === 'completed' || r.status === 'failed') {
89
- send({ kind: 'runDone', project: p.slug, projectPath: p.path, id: r.id, title: `Run ${r.status}`, detail: r.workflowName, status: r.status });
90
- }
91
- }
92
- // Index/ingest activity (REQ-DASHUX-004): emit when the project's
93
- // index freshness changes so open pages can refetch instead of
94
- // going stale between manual refreshes.
95
- try {
96
- const sig = String(cg.getLastIndexedAt() ?? '');
97
- if (lastIndexSig.get(p.slug) !== sig) {
98
- lastIndexSig.set(p.slug, sig);
99
- if (primed) {
100
- send({ kind: 'activity', project: p.slug, projectPath: p.path, id: sig, title: 'Index updated' });
101
- }
102
- }
103
- }
104
- catch { /* ignore — activity detection must not break the stream */ }
105
- // Newly-drifted links.
106
- let links = [];
107
- try {
108
- links = sq.getLinksByState(['drifted', 'broken', 'orphaned']);
109
- }
110
- catch { /* ignore */ }
111
- for (const l of links) {
112
- const key = `${p.slug}:${l.id}`;
113
- if (seenDrift.has(key))
114
- continue;
115
- seenDrift.add(key);
116
- if (!primed)
117
- continue;
118
- send({ kind: 'drift', project: p.slug, projectPath: p.path, id: String(l.id), title: 'Drift detected', detail: `${l.specId} → ${l.targetQualifiedName}` });
119
- }
120
- // Reflection sweep — throttled to ~daily. Notifies only on NEW
121
- // high-severity proposals; the persisted store dedupes, so this is NOT
122
- // gated on `primed` (a brand-new finding should alert even on connect,
123
- // while an already-seen one never re-fires regardless of connection).
124
- const now = Date.now();
125
- if (now - (lastSweep.get(p.slug) ?? 0) >= SWEEP_MS) {
126
- lastSweep.set(p.slug, now);
127
- try {
128
- const res = cg.reflectSweep();
129
- for (const prop of res.notify) {
130
- send({ kind: 'reflect', project: p.slug, projectPath: p.path, id: prop.contentHash, title: prop.title, detail: prop.evidence.detail });
131
- }
132
- }
133
- catch { /* ignore — a sweep failure must not break the stream */ }
134
- }
135
- }
136
- primed = true;
137
- };
138
- await poll(); // prime: seed seen-state without emitting
139
- const pollTimer = setInterval(() => { void poll(); }, POLL_MS);
140
- const kaTimer = setInterval(() => { if (!closed) {
141
- try {
142
- reply.raw.write(': ka\n\n');
143
- }
144
- catch { /* noop */ }
145
- } }, KEEPALIVE_MS);
146
- req.raw.on('close', () => {
147
- closed = true;
148
- clearInterval(pollTimer);
149
- clearInterval(kaTimer);
150
- });
151
- });
152
- }