@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
@@ -8,7 +8,7 @@
8
8
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" />
9
9
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png" />
10
10
  <link rel="apple-touch-icon" sizes="180x180" href="/favicon-180.png" />
11
- <script type="module" crossorigin src="/assets/index-CjjaftDw.js"></script>
11
+ <script type="module" crossorigin src="/assets/index-BzuUWUAE.js"></script>
12
12
  <link rel="stylesheet" crossorigin href="/assets/index-ezwX2EfG.css">
13
13
  </head>
14
14
  <body>
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Test-report ingestion (REQ-VSTATE-004).
3
+ *
4
+ * `verified` used to mean "an LLM read a test log and said it passed". This
5
+ * module replaces that with a deterministic mapping: parse a real test report,
6
+ * match each reported case to the `tests` links that claim it, and move those
7
+ * links — passed → `verified`, failed → `broken` — recording the run itself as
8
+ * the evidence.
9
+ *
10
+ * Parsing is total before any write happens, so a malformed report exits with a
11
+ * parse error having changed no state (A4).
12
+ */
13
+ import type { SpecLink } from '../types';
14
+ import type { SpecQueries } from '../db/spec-queries';
15
+ /** Thrown for an unreadable / unparseable / shapeless report (REQ-VSTATE-004.A4). */
16
+ export declare class TestReportParseError extends Error {
17
+ constructor(message: string);
18
+ }
19
+ /** One test case as reported by the runner. */
20
+ export interface ReportedTestCase {
21
+ /** Project-relative POSIX path of the test file. */
22
+ file: string;
23
+ /** The `it()` title, without ancestor describe titles. */
24
+ title: string;
25
+ /** Ancestors + title joined, as the runner reported it. */
26
+ fullName: string;
27
+ status: 'passed' | 'failed' | 'skipped';
28
+ failureMessage?: string;
29
+ }
30
+ /** What one link's state move was, for reporting. */
31
+ export interface LinkOutcome {
32
+ linkId: number;
33
+ specId: string;
34
+ file: string;
35
+ /** The matched test titles the verdict rests on. */
36
+ titles: string[];
37
+ from: SpecLink['state'];
38
+ to: SpecLink['state'];
39
+ }
40
+ export interface VerifyReportResult {
41
+ runId: string;
42
+ reportPath: string;
43
+ /** Total cases read out of the report. */
44
+ cases: number;
45
+ promoted: LinkOutcome[];
46
+ demoted: LinkOutcome[];
47
+ /** Links matched whose state didn't move (already there, or only skips). */
48
+ unchanged: number;
49
+ /** Reported cases that matched no `tests` link at all (A3). */
50
+ unmatched: number;
51
+ /** A bounded sample of the unmatched cases, for the operator (A3). */
52
+ unmatchedSample: string[];
53
+ }
54
+ /**
55
+ * Parse a vitest / jest JSON report (`vitest run --reporter=json`).
56
+ *
57
+ * Shape: `{ testResults: [{ name, assertionResults: [{ title, fullName,
58
+ * ancestorTitles, status, failureMessages }] }] }`. Anything else — invalid
59
+ * JSON, a non-object, a missing/!array `testResults` — is a parse error rather
60
+ * than an empty result, so a report written by a crashed runner can never read
61
+ * as "nothing to verify" (A4).
62
+ */
63
+ export declare function parseVitestJsonReport(raw: string, projectRoot: string): ReportedTestCase[];
64
+ /**
65
+ * Does `testCase` prove `link`? Matching is by FILE first — a link's evidence
66
+ * must live in the file it points at — then by title, in descending precision:
67
+ *
68
+ * 1. the link's recorded `metadata.testTitles` (written by the test-title pass,
69
+ * REQ-VSTATE-002) contains the case's title or full name;
70
+ * 2. the case's full name mentions the link's spec id (the `(REQ-X.A1)` title
71
+ * convention, for links that predate the recorded titles);
72
+ * 3. the case's full name mentions the link's target symbol (a `verifies:`
73
+ * block naming a hoisted test function).
74
+ */
75
+ export declare function caseMatchesLink(testCase: ReportedTestCase, link: SpecLink): boolean;
76
+ /**
77
+ * Read a report and apply it to the DB (REQ-VSTATE-004).
78
+ *
79
+ * Per matched link: any failed case → `broken`; otherwise at least one passed
80
+ * case → `verified`; only-skipped → left alone (a skipped test proves nothing
81
+ * either way). The verification record persisted on the link carries the run id,
82
+ * the report path, the ISO timestamp and the exact test names the verdict rests
83
+ * on, so `verified` is auditable back to a specific run.
84
+ */
85
+ export declare function ingestTestReport(sq: SpecQueries, projectRoot: string, reportPath: string, options?: {
86
+ runId?: string;
87
+ }): VerifyReportResult;
88
+ //# sourceMappingURL=report-ingest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-ingest.d.ts","sourceRoot":"","sources":["../../src/verify/report-ingest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,qFAAqF;AACrF,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED,+CAA+C;AAC/C,MAAM,WAAW,gBAAgB;IAC/B,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qDAAqD;AACrD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxB,EAAE,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAyBD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAiE1F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAkBnF;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,WAAW,EACf,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,kBAAkB,CAqFpB"}
@@ -0,0 +1,269 @@
1
+ "use strict";
2
+ /**
3
+ * Test-report ingestion (REQ-VSTATE-004).
4
+ *
5
+ * `verified` used to mean "an LLM read a test log and said it passed". This
6
+ * module replaces that with a deterministic mapping: parse a real test report,
7
+ * match each reported case to the `tests` links that claim it, and move those
8
+ * links — passed → `verified`, failed → `broken` — recording the run itself as
9
+ * the evidence.
10
+ *
11
+ * Parsing is total before any write happens, so a malformed report exits with a
12
+ * parse error having changed no state (A4).
13
+ */
14
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ var desc = Object.getOwnPropertyDescriptor(m, k);
17
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
18
+ desc = { enumerable: true, get: function() { return m[k]; } };
19
+ }
20
+ Object.defineProperty(o, k2, desc);
21
+ }) : (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ o[k2] = m[k];
24
+ }));
25
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
26
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
27
+ }) : function(o, v) {
28
+ o["default"] = v;
29
+ });
30
+ var __importStar = (this && this.__importStar) || (function () {
31
+ var ownKeys = function(o) {
32
+ ownKeys = Object.getOwnPropertyNames || function (o) {
33
+ var ar = [];
34
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
35
+ return ar;
36
+ };
37
+ return ownKeys(o);
38
+ };
39
+ return function (mod) {
40
+ if (mod && mod.__esModule) return mod;
41
+ var result = {};
42
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
43
+ __setModuleDefault(result, mod);
44
+ return result;
45
+ };
46
+ })();
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.TestReportParseError = void 0;
49
+ exports.parseVitestJsonReport = parseVitestJsonReport;
50
+ exports.caseMatchesLink = caseMatchesLink;
51
+ exports.ingestTestReport = ingestTestReport;
52
+ const fs = __importStar(require("fs"));
53
+ const path = __importStar(require("path"));
54
+ /** Thrown for an unreadable / unparseable / shapeless report (REQ-VSTATE-004.A4). */
55
+ class TestReportParseError extends Error {
56
+ constructor(message) {
57
+ super(message);
58
+ this.name = 'TestReportParseError';
59
+ }
60
+ }
61
+ exports.TestReportParseError = TestReportParseError;
62
+ /** Normalize an absolute or relative path to a project-relative POSIX path. */
63
+ function toProjectRelative(projectRoot, filePath) {
64
+ const normalized = filePath.replace(/\\/g, '/');
65
+ const abs = path.isAbsolute(normalized)
66
+ ? normalized
67
+ : path.resolve(projectRoot, normalized);
68
+ const rel = path.relative(projectRoot, abs).replace(/\\/g, '/');
69
+ return rel.startsWith('..') ? normalized.replace(/^\.\//, '') : rel;
70
+ }
71
+ /**
72
+ * Parse a vitest / jest JSON report (`vitest run --reporter=json`).
73
+ *
74
+ * Shape: `{ testResults: [{ name, assertionResults: [{ title, fullName,
75
+ * ancestorTitles, status, failureMessages }] }] }`. Anything else — invalid
76
+ * JSON, a non-object, a missing/!array `testResults` — is a parse error rather
77
+ * than an empty result, so a report written by a crashed runner can never read
78
+ * as "nothing to verify" (A4).
79
+ */
80
+ function parseVitestJsonReport(raw, projectRoot) {
81
+ const trimmed = raw.trim();
82
+ if (trimmed.length === 0) {
83
+ throw new TestReportParseError('report file is empty');
84
+ }
85
+ let parsed;
86
+ try {
87
+ parsed = JSON.parse(trimmed);
88
+ }
89
+ catch (err) {
90
+ throw new TestReportParseError(`report is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
91
+ }
92
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
93
+ throw new TestReportParseError('report is not a JSON object');
94
+ }
95
+ const results = parsed.testResults;
96
+ if (!Array.isArray(results)) {
97
+ throw new TestReportParseError('report has no `testResults` array — expected `vitest run --reporter=json` output');
98
+ }
99
+ const cases = [];
100
+ for (const entry of results) {
101
+ if (typeof entry !== 'object' || entry === null)
102
+ continue;
103
+ const fileResult = entry;
104
+ const name = typeof fileResult.name === 'string' ? fileResult.name : '';
105
+ if (!name)
106
+ continue;
107
+ const file = toProjectRelative(projectRoot, name);
108
+ const assertions = Array.isArray(fileResult.assertionResults)
109
+ ? fileResult.assertionResults
110
+ : [];
111
+ for (const a of assertions) {
112
+ if (typeof a !== 'object' || a === null)
113
+ continue;
114
+ const ar = a;
115
+ const title = typeof ar.title === 'string' ? ar.title : '';
116
+ if (!title)
117
+ continue;
118
+ const ancestors = Array.isArray(ar.ancestorTitles)
119
+ ? ar.ancestorTitles.filter((t) => typeof t === 'string')
120
+ : [];
121
+ const fullName = typeof ar.fullName === 'string' && ar.fullName.length > 0
122
+ ? ar.fullName
123
+ : [...ancestors, title].join(' > ');
124
+ const rawStatus = typeof ar.status === 'string' ? ar.status : 'skipped';
125
+ const status = rawStatus === 'passed'
126
+ ? 'passed'
127
+ : rawStatus === 'failed'
128
+ ? 'failed'
129
+ : 'skipped';
130
+ const failures = Array.isArray(ar.failureMessages)
131
+ ? ar.failureMessages.filter((m) => typeof m === 'string')
132
+ : [];
133
+ cases.push({
134
+ file,
135
+ title,
136
+ fullName,
137
+ status,
138
+ failureMessage: failures[0],
139
+ });
140
+ }
141
+ }
142
+ return cases;
143
+ }
144
+ /**
145
+ * Does `testCase` prove `link`? Matching is by FILE first — a link's evidence
146
+ * must live in the file it points at — then by title, in descending precision:
147
+ *
148
+ * 1. the link's recorded `metadata.testTitles` (written by the test-title pass,
149
+ * REQ-VSTATE-002) contains the case's title or full name;
150
+ * 2. the case's full name mentions the link's spec id (the `(REQ-X.A1)` title
151
+ * convention, for links that predate the recorded titles);
152
+ * 3. the case's full name mentions the link's target symbol (a `verifies:`
153
+ * block naming a hoisted test function).
154
+ */
155
+ function caseMatchesLink(testCase, link) {
156
+ const linkFile = link.targetFilePath.replace(/\\/g, '/');
157
+ if (linkFile !== testCase.file)
158
+ return false;
159
+ const recorded = link.metadata?.testTitles;
160
+ if (Array.isArray(recorded)) {
161
+ for (const t of recorded) {
162
+ if (typeof t !== 'string')
163
+ continue;
164
+ if (t === testCase.title || t === testCase.fullName)
165
+ return true;
166
+ }
167
+ }
168
+ if (testCase.fullName.includes(link.specId))
169
+ return true;
170
+ // A file-targeted link (the test-title pass) has no symbol to match on — its
171
+ // qualified name IS the path, whose extension would match almost any title.
172
+ if (link.targetNodeKind === 'file')
173
+ return false;
174
+ const symbol = link.targetQualifiedName.split('.').pop() ?? '';
175
+ if (symbol.length >= 3 && testCase.fullName.includes(symbol))
176
+ return true;
177
+ return false;
178
+ }
179
+ /**
180
+ * Read a report and apply it to the DB (REQ-VSTATE-004).
181
+ *
182
+ * Per matched link: any failed case → `broken`; otherwise at least one passed
183
+ * case → `verified`; only-skipped → left alone (a skipped test proves nothing
184
+ * either way). The verification record persisted on the link carries the run id,
185
+ * the report path, the ISO timestamp and the exact test names the verdict rests
186
+ * on, so `verified` is auditable back to a specific run.
187
+ */
188
+ function ingestTestReport(sq, projectRoot, reportPath, options = {}) {
189
+ let raw;
190
+ try {
191
+ raw = fs.readFileSync(path.resolve(projectRoot, reportPath), 'utf-8');
192
+ }
193
+ catch (err) {
194
+ throw new TestReportParseError(`cannot read report ${reportPath}: ${err instanceof Error ? err.message : String(err)}`);
195
+ }
196
+ // Parse EVERYTHING before the first write (A4).
197
+ const cases = parseVitestJsonReport(raw, projectRoot);
198
+ const runId = options.runId ?? `run-${Date.now()}`;
199
+ const verifiedAt = new Date().toISOString();
200
+ const testsLinks = sq.getAllLinks().filter((l) => l.kind === 'tests');
201
+ // Bucket the cases per link, and track which cases matched something.
202
+ const perLink = new Map();
203
+ const matchedCases = new Set();
204
+ for (const link of testsLinks) {
205
+ for (const c of cases) {
206
+ if (!caseMatchesLink(c, link))
207
+ continue;
208
+ const bucket = perLink.get(link.id) ?? { link, cases: [] };
209
+ bucket.cases.push(c);
210
+ perLink.set(link.id, bucket);
211
+ matchedCases.add(c);
212
+ }
213
+ }
214
+ const promoted = [];
215
+ const demoted = [];
216
+ let unchanged = 0;
217
+ for (const { link, cases: linkCases } of perLink.values()) {
218
+ const failed = linkCases.filter((c) => c.status === 'failed');
219
+ const passed = linkCases.filter((c) => c.status === 'passed');
220
+ if (failed.length === 0 && passed.length === 0) {
221
+ unchanged++;
222
+ continue;
223
+ }
224
+ const pass = failed.length === 0;
225
+ const relevant = pass ? passed : failed;
226
+ const titles = relevant.map((c) => c.fullName);
227
+ const now = Date.now();
228
+ const metadata = {
229
+ ...(link.metadata ?? {}),
230
+ verification: {
231
+ result: pass ? 'pass' : 'fail',
232
+ verifiedAt,
233
+ reason: pass
234
+ ? `${passed.length} test(s) passed in ${path.basename(reportPath)}`
235
+ : (failed[0]?.failureMessage?.split('\n')[0] ??
236
+ `${failed.length} test(s) failed in ${path.basename(reportPath)}`),
237
+ evidence: relevant.map((c) => `${c.file}:${c.fullName}`),
238
+ run: { id: runId, report: reportPath, source: 'vitest-json', ranAt: verifiedAt },
239
+ },
240
+ };
241
+ const to = pass ? 'verified' : 'broken';
242
+ sq.updateSpecLinkState(link.id, to, null, now);
243
+ sq.updateSpecLinkMetadata(link.id, metadata, now);
244
+ const outcome = {
245
+ linkId: link.id,
246
+ specId: link.specId,
247
+ file: link.targetFilePath,
248
+ titles,
249
+ from: link.state,
250
+ to,
251
+ };
252
+ if (pass)
253
+ promoted.push(outcome);
254
+ else
255
+ demoted.push(outcome);
256
+ }
257
+ const unmatchedCases = cases.filter((c) => !matchedCases.has(c));
258
+ return {
259
+ runId,
260
+ reportPath,
261
+ cases: cases.length,
262
+ promoted,
263
+ demoted,
264
+ unchanged,
265
+ unmatched: unmatchedCases.length,
266
+ unmatchedSample: unmatchedCases.slice(0, 10).map((c) => `${c.file}:${c.fullName}`),
267
+ };
268
+ }
269
+ //# sourceMappingURL=report-ingest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-ingest.js","sourceRoot":"","sources":["../../src/verify/report-ingest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Claude Code headless adapter (REQ-AGENTADAPT-005): `claude --print` with
3
+ * stream-json output. The argument list is exactly what the prompt runner
4
+ * built before adapters existed (REQ-AGENTADAPT-005.A1).
5
+ */
6
+ import type { PromptNode } from '../schemas/workflow';
7
+ import { EmitFn, HeadlessAgent, StreamParseState } from './types';
8
+ export declare function buildClaudeArgs(node: PromptNode): string[];
9
+ /**
10
+ * Parse one stream-json line, emit any activity events, and fold the result
11
+ * into `state`. Pure aside from the `emit` callback. Unknown / non-JSON lines
12
+ * are ignored. Extended-thinking blocks are intentionally NOT emitted.
13
+ */
14
+ export declare function handleClaudeStreamLine(line: string, emit: EmitFn, state: StreamParseState): void;
15
+ export declare const claudeHeadlessAgent: HeadlessAgent;
16
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/workflows/agents/claude.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAsB,gBAAgB,EAAqC,MAAM,SAAS,CAAC;AAEzH,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,EAAE,CAkB1D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CA4BhG;AAED,eAAO,MAAM,mBAAmB,EAAE,aAQjC,CAAC"}
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ /**
3
+ * Claude Code headless adapter (REQ-AGENTADAPT-005): `claude --print` with
4
+ * stream-json output. The argument list is exactly what the prompt runner
5
+ * built before adapters existed (REQ-AGENTADAPT-005.A1).
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.claudeHeadlessAgent = void 0;
9
+ exports.buildClaudeArgs = buildClaudeArgs;
10
+ exports.handleClaudeStreamLine = handleClaudeStreamLine;
11
+ const types_1 = require("./types");
12
+ function buildClaudeArgs(node) {
13
+ const args = [];
14
+ args.push('--print');
15
+ // Stream the agent's activity as JSONL so we can surface tool calls and
16
+ // messages live. `--print` + `--output-format stream-json` requires
17
+ // `--verbose` (the CLI rejects the combination otherwise).
18
+ args.push('--output-format', 'stream-json', '--verbose');
19
+ if (node.model)
20
+ args.push('--model', node.model);
21
+ if (node.allowed_tools && node.allowed_tools.length > 0) {
22
+ args.push('--allowed-tools', node.allowed_tools.join(','));
23
+ }
24
+ if (node.denied_tools && node.denied_tools.length > 0) {
25
+ args.push('--disallowed-tools', node.denied_tools.join(','));
26
+ }
27
+ if (node.systemPromptAppend) {
28
+ args.push('--append-system-prompt', node.systemPromptAppend);
29
+ }
30
+ return args;
31
+ }
32
+ /**
33
+ * Parse one stream-json line, emit any activity events, and fold the result
34
+ * into `state`. Pure aside from the `emit` callback. Unknown / non-JSON lines
35
+ * are ignored. Extended-thinking blocks are intentionally NOT emitted.
36
+ */
37
+ function handleClaudeStreamLine(line, emit, state) {
38
+ const e = (0, types_1.parseJsonLine)(line);
39
+ if (!e)
40
+ return;
41
+ if (e.type === 'assistant' && e.message && typeof e.message === 'object') {
42
+ state.sawStream = true;
43
+ const content = e.message.content;
44
+ if (Array.isArray(content)) {
45
+ for (const raw of content) {
46
+ const b = raw;
47
+ if (b?.type === 'tool_use') {
48
+ emit('tool_called', { name: b.name, input: (0, types_1.summarizeToolInput)(b.input) });
49
+ }
50
+ else if (b?.type === 'text' && typeof b.text === 'string' && b.text.trim()) {
51
+ state.assistantText += (state.assistantText ? '\n' : '') + b.text;
52
+ emit('agent_message', { text: b.text });
53
+ }
54
+ // 'thinking' blocks: deliberately skipped.
55
+ }
56
+ }
57
+ }
58
+ else if (e.type === 'result') {
59
+ state.sawStream = true;
60
+ if (typeof e.result === 'string')
61
+ state.resultText = e.result;
62
+ if (typeof e.total_cost_usd === 'number')
63
+ state.costUsd = e.total_cost_usd;
64
+ if (typeof e.duration_ms === 'number')
65
+ state.durationMs = e.duration_ms;
66
+ }
67
+ else if (e.type === 'system') {
68
+ state.sawStream = true; // init/system frame — confirms we're on the stream path
69
+ if (typeof e.model === 'string' && e.model)
70
+ state.model = e.model;
71
+ }
72
+ }
73
+ exports.claudeHeadlessAgent = {
74
+ id: 'claude',
75
+ // Claude Code sets CLAUDECODE=1 in the environment of the commands it runs.
76
+ launchedFrom: (env) => env.CLAUDECODE === '1',
77
+ build(node, _config, env) {
78
+ return { bin: env.SPECSHIP_CLAUDE_BIN ?? 'claude', args: buildClaudeArgs(node), stdin: node.prompt };
79
+ },
80
+ handleLine: handleClaudeStreamLine,
81
+ };
82
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/workflows/agents/claude.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Gemini CLI headless adapter (REQ-AGENTADAPT-007), against the installed
3
+ * 0.28.0 source (DOM-SPECSHIP-008): piped stdin runs Gemini headless, and in
4
+ * that mode every approval-needing tool not in `--allowed-tools` is removed,
5
+ * so each step's tools are translated to Gemini's names. There is no deny or
6
+ * append-system-prompt flag: `denied_tools` is refused, and the appended
7
+ * system prompt leads the stdin prompt.
8
+ */
9
+ import { EmitFn, HeadlessAgent, StreamParseState } from './types';
10
+ /** Translate a step's allowed tools, or name the first one with no Gemini equivalent. */
11
+ export declare function translateGeminiTools(tools: string[]): {
12
+ tools: string[];
13
+ } | {
14
+ error: string;
15
+ };
16
+ /** The Gemini model for a step: a mapped tier alias, a Gemini id as-is, else none (Gemini's default). */
17
+ export declare function geminiModelFor(model: string | undefined, models: Record<string, string> | undefined): string | undefined;
18
+ /** Parse one Gemini stream-json event (init / message / tool_use / error / result). */
19
+ export declare function handleGeminiStreamLine(line: string, emit: EmitFn, state: StreamParseState): void;
20
+ export declare const geminiHeadlessAgent: HeadlessAgent;
21
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../../src/workflows/agents/gemini.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,aAAa,EAAsB,gBAAgB,EAAqC,MAAM,SAAS,CAAC;AAiBzH,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAa7F;AAED,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAIxH;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAmChG;AAED,eAAO,MAAM,mBAAmB,EAAE,aAsBjC,CAAC"}
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ /**
3
+ * Gemini CLI headless adapter (REQ-AGENTADAPT-007), against the installed
4
+ * 0.28.0 source (DOM-SPECSHIP-008): piped stdin runs Gemini headless, and in
5
+ * that mode every approval-needing tool not in `--allowed-tools` is removed,
6
+ * so each step's tools are translated to Gemini's names. There is no deny or
7
+ * append-system-prompt flag: `denied_tools` is refused, and the appended
8
+ * system prompt leads the stdin prompt.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.geminiHeadlessAgent = void 0;
12
+ exports.translateGeminiTools = translateGeminiTools;
13
+ exports.geminiModelFor = geminiModelFor;
14
+ exports.handleGeminiStreamLine = handleGeminiStreamLine;
15
+ const types_1 = require("./types");
16
+ /** Claude-form built-in tool names → Gemini CLI 0.28 tool names. */
17
+ const BUILTIN_TOOLS = {
18
+ Read: 'read_file',
19
+ Write: 'write_file',
20
+ Edit: 'replace',
21
+ MultiEdit: 'replace',
22
+ Bash: 'run_shell_command',
23
+ Glob: 'glob',
24
+ Grep: 'grep_search',
25
+ LS: 'list_directory',
26
+ WebFetch: 'web_fetch',
27
+ WebSearch: 'google_web_search',
28
+ };
29
+ const MODEL_TIERS = new Set(['haiku', 'sonnet', 'opus']);
30
+ /** Translate a step's allowed tools, or name the first one with no Gemini equivalent. */
31
+ function translateGeminiTools(tools) {
32
+ const out = [];
33
+ for (const tool of tools) {
34
+ let mapped;
35
+ const mcp = tool.match(/^mcp__([A-Za-z0-9_-]+?)__(.+)$/);
36
+ const shell = tool.match(/^Bash\((.+?)(?::\*)?\)$/);
37
+ if (mcp)
38
+ mapped = `${mcp[1]}__${mcp[2]}`;
39
+ else if (shell)
40
+ mapped = `run_shell_command(${shell[1].trim()})`;
41
+ else
42
+ mapped = BUILTIN_TOOLS[tool];
43
+ if (!mapped)
44
+ return { error: `allowed tool "${tool}" has no Gemini CLI equivalent` };
45
+ if (!out.includes(mapped))
46
+ out.push(mapped);
47
+ }
48
+ return { tools: out };
49
+ }
50
+ /** The Gemini model for a step: a mapped tier alias, a Gemini id as-is, else none (Gemini's default). */
51
+ function geminiModelFor(model, models) {
52
+ if (!model)
53
+ return undefined;
54
+ if (MODEL_TIERS.has(model))
55
+ return models?.[model];
56
+ return /^gemini/i.test(model) ? model : undefined; // a Claude id is never passed to Gemini
57
+ }
58
+ /** Parse one Gemini stream-json event (init / message / tool_use / error / result). */
59
+ function handleGeminiStreamLine(line, emit, state) {
60
+ const e = (0, types_1.parseJsonLine)(line);
61
+ if (!e)
62
+ return;
63
+ switch (e.type) {
64
+ case 'init':
65
+ state.sawStream = true;
66
+ if (typeof e.model === 'string' && e.model)
67
+ state.model = e.model;
68
+ break;
69
+ case 'message':
70
+ state.sawStream = true;
71
+ if (e.role === 'assistant' && typeof e.content === 'string' && e.content) {
72
+ // Deltas are fragments of one turn; whole messages are separate turns.
73
+ state.assistantText += e.delta === true || !state.assistantText ? e.content : `\n${e.content}`;
74
+ emit('agent_message', { text: e.content });
75
+ }
76
+ break;
77
+ case 'tool_use':
78
+ state.sawStream = true;
79
+ emit('tool_called', { name: e.tool_name, input: (0, types_1.summarizeToolInput)(e.parameters) });
80
+ break;
81
+ case 'result': {
82
+ state.sawStream = true;
83
+ const stats = e.stats;
84
+ if (stats && typeof stats.duration_ms === 'number')
85
+ state.durationMs = stats.duration_ms;
86
+ if (e.status === 'error') {
87
+ const err = e.error;
88
+ state.failure = typeof err?.message === 'string' ? err.message : 'Gemini CLI reported an error result';
89
+ }
90
+ break;
91
+ }
92
+ case 'error':
93
+ state.sawStream = true;
94
+ if (e.severity === 'error' && typeof e.message === 'string')
95
+ state.failure = e.message;
96
+ break;
97
+ }
98
+ }
99
+ exports.geminiHeadlessAgent = {
100
+ id: 'gemini',
101
+ // Gemini CLI sets GEMINI_CLI=1 for the shell commands it runs.
102
+ launchedFrom: (env) => env.GEMINI_CLI === '1',
103
+ build(node, config, env) {
104
+ if (node.denied_tools && node.denied_tools.length > 0) {
105
+ return { error: `denied_tools (${node.denied_tools.join(', ')}) cannot be enforced on Gemini CLI — it has no deny flag` };
106
+ }
107
+ const args = ['--output-format', 'stream-json'];
108
+ const model = geminiModelFor(node.model, config.models);
109
+ if (model)
110
+ args.push('--model', model);
111
+ if (node.allowed_tools && node.allowed_tools.length > 0) {
112
+ const t = translateGeminiTools(node.allowed_tools);
113
+ if ('error' in t)
114
+ return t;
115
+ args.push('--allowed-tools', ...t.tools);
116
+ }
117
+ const stdin = node.systemPromptAppend
118
+ ? `${node.systemPromptAppend.trimEnd()}\n\n---\n\n${node.prompt}`
119
+ : node.prompt;
120
+ return { bin: env.SPECSHIP_GEMINI_BIN ?? 'gemini', args, stdin };
121
+ },
122
+ handleLine: handleGeminiStreamLine,
123
+ };
124
+ //# sourceMappingURL=gemini.js.map