@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
@@ -13,23 +13,58 @@ nodes:
13
13
  output_type: test_results
14
14
  timeout: 600000
15
15
  bash: |
16
+ # Same VERIFY_RESULT contract as spec-implement / spec-fix
17
+ # (REQ-REVINT-006, REQ-VSTATE-005): the marker is what the routing node
18
+ # reads. This node used to emit no marker at all and `exit 0` when it
19
+ # found no runner — a no-runner repo read as a clean verification pass.
16
20
  if [ -f package.json ]; then
17
21
  # Run against a built tree so a missing dist/ can't false-fail the
18
22
  # verify leg (WF-REJECT-DOC, REQ-WFREJ-005).
19
- npm run build --if-present
20
- npm test
23
+ if ! npm run build --if-present; then echo "VERIFY_RESULT=build-failed"; exit 1; fi
24
+ if npm test; then echo "VERIFY_RESULT=ran-and-passed"; else echo "VERIFY_RESULT=ran-and-failed"; exit 1; fi
21
25
  elif [ -f Cargo.toml ]; then
22
- cargo test
26
+ if ! cargo build; then echo "VERIFY_RESULT=build-failed"; exit 1; fi
27
+ if cargo test; then echo "VERIFY_RESULT=ran-and-passed"; else echo "VERIFY_RESULT=ran-and-failed"; exit 1; fi
23
28
  elif [ -f pyproject.toml ] || [ -f requirements.txt ]; then
24
- python -m pytest
29
+ if ! python -c 'import pytest' 2>/dev/null; then echo "VERIFY_RESULT=env-failed"; exit 1; fi
30
+ if python -m pytest; then echo "VERIFY_RESULT=ran-and-passed"; else echo "VERIFY_RESULT=ran-and-failed"; exit 1; fi
25
31
  else
26
- echo "no recognised test framework; skipping" >&2
27
- exit 0
32
+ echo "no recognised test framework; tests did NOT run" >&2
33
+ echo "VERIFY_RESULT=skipped"
28
34
  fi
29
35
 
36
+ - id: route_verify
37
+ kind: bash
38
+ depends_on: [run_tests]
39
+ output_type: verify_route
40
+ bash: |
41
+ # Deterministic routing (REQ-VSTATE-005.A1): code decides what the
42
+ # summarize node may do with link state.
43
+ VERIFY_OUT=$run_tests.output
44
+ MARKER=$(printf '%s' "$VERIFY_OUT" | grep -oE 'VERIFY_RESULT=[a-z-]+' | tail -n 1 | cut -d= -f2)
45
+ [ -n "$MARKER" ] || MARKER=missing
46
+ echo "VERIFY_RESULT=$MARKER"
47
+ case "$MARKER" in
48
+ ran-and-passed)
49
+ echo "LINK_ACTION=verify-evidenced" ;;
50
+ ran-and-failed)
51
+ echo "LINK_ACTION=verify-fail" ;;
52
+ skipped)
53
+ echo "LINK_ACTION=no-verify" ;;
54
+ env-failed)
55
+ echo "HALT_CAUSE=environment setup failed — nothing is known about the tests"
56
+ exit 1 ;;
57
+ build-failed)
58
+ echo "HALT_CAUSE=build failed — nothing is known about the tests"
59
+ exit 1 ;;
60
+ *)
61
+ echo "HALT_CAUSE=no VERIFY_RESULT marker found in the test output — an unknown result is never a pass"
62
+ exit 1 ;;
63
+ esac
64
+
30
65
  - id: summarize
31
66
  kind: prompt
32
- depends_on: [run_tests]
67
+ depends_on: [route_verify]
33
68
  output_type: link_summary
34
69
  trigger_rule: all_done
35
70
  allowed_tools:
@@ -41,12 +76,23 @@ nodes:
41
76
 
42
77
  $run_tests.output
43
78
 
79
+ Routing decision (computed in code — act on it, do not re-derive it
80
+ from the log above):
81
+
82
+ $route_verify.output
83
+
44
84
  Promotion is EVIDENCE-BASED (VERIFY-EVID-DOC): a spec may only become
45
85
  "verified" when a test linked to it as evidence passed. Evidence links
46
- have kind='tests' and come from a `verifies:` block in the spec or an
47
- `@verifies REQ-X` comment on the test. A green suite alone proves
86
+ have kind='tests' and come from a `verifies:` block in the spec, an
87
+ `@verifies REQ-X` comment on the test, or a spec id inside an `it()`
88
+ title in a test file (REQ-VSTATE-002). A green suite alone proves
48
89
  nothing about a spec with no linked tests — never blanket-promote.
49
90
 
91
+ - LINK_ACTION=verify-evidenced → proceed with steps 1–4 below.
92
+ - LINK_ACTION=verify-fail → only demote (step 3). Promote nothing.
93
+ - LINK_ACTION=no-verify → no test ran. Mutate no link state at all;
94
+ report that verification was skipped and stop.
95
+
50
96
  1. Call specship_drifted to see any drifted/broken/orphaned links.
51
97
  2. For each 'implemented' link whose spec HAS test-evidence links:
52
98
  if all of that spec's evidence tests passed in the output above,
@@ -61,5 +107,10 @@ nodes:
61
107
  "unevidenced" in your summary so the author can add `verifies:`
62
108
  blocks (REQ-VEVID-003).
63
109
 
110
+ For a fully deterministic alternative to steps 2–3, run
111
+ `specship verify --report <vitest-json>` (REQ-VSTATE-004): it maps
112
+ reported test cases to `tests` links by file + title and moves the
113
+ state itself, with the run recorded as evidence.
114
+
64
115
  Output: a short summary — how many links moved to verified, how many
65
116
  to broken, which specs are unevidenced, and which are still drifted.
@@ -43,4 +43,17 @@ export declare function discoverWorkflows(projectRoot: string): WorkflowLoadResu
43
43
  * Returns null if no workflow with that name exists in any scope.
44
44
  */
45
45
  export declare function loadWorkflowByName(projectRoot: string, name: string): WorkflowWithSource | null;
46
+ /**
47
+ * Resolve `extends: <workflow>` + `node_overrides` (THROUGHPUT-DOC,
48
+ * REQ-THRU-004): the result is the base workflow's raw definition with the
49
+ * extending file's top-level fields on top and each named node's fields
50
+ * shallow-merged from `node_overrides`. One source for shared nodes — a
51
+ * variant like spec-implement-mixed only states what differs. Chains resolve
52
+ * recursively; a cycle, an unknown base, or an override naming no base node
53
+ * is an error.
54
+ */
55
+ export declare function resolveExtends(raw: Record<string, unknown>, getBase: (name: string) => Record<string, unknown> | undefined, seen?: Set<string>): {
56
+ value?: Record<string, unknown>;
57
+ errors: ValidationError[];
58
+ };
46
59
  //# sourceMappingURL=discovery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/workflows/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,OAAO,EACL,kBAAkB,EAElB,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAG5B,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE7D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,yDAAyD;IACzD,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAChC,uCAAuC;IACvC,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,CAoCzE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,kBAAkB,GAAG,IAAI,CAG3B"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/workflows/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,OAAO,EACL,kBAAkB,EAElB,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAG5B,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE7D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,yDAAyD;IACzD,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAChC,uCAAuC;IACvC,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,CA4CzE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,kBAAkB,GAAG,IAAI,CAG3B;AAuFD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC9D,IAAI,GAAE,GAAG,CAAC,MAAM,CAAa,GAC5B;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CAiChE"}
@@ -50,6 +50,7 @@ var __importStar = (this && this.__importStar) || (function () {
50
50
  Object.defineProperty(exports, "__esModule", { value: true });
51
51
  exports.discoverWorkflows = discoverWorkflows;
52
52
  exports.loadWorkflowByName = loadWorkflowByName;
53
+ exports.resolveExtends = resolveExtends;
53
54
  const fs = __importStar(require("fs"));
54
55
  const path = __importStar(require("path"));
55
56
  const os = __importStar(require("os"));
@@ -65,9 +66,17 @@ const defaults_1 = require("./defaults");
65
66
  function discoverWorkflows(projectRoot) {
66
67
  const byName = new Map();
67
68
  const errors = [];
69
+ // Raw (pre-validation) definitions by name, so `extends:` can resolve
70
+ // against any workflow loaded at the same or a lower-precedence scope.
71
+ const rawByName = new Map();
72
+ for (const entry of defaults_1.bundledDefaults) {
73
+ const raw = parseRaw(entry.yaml);
74
+ if (raw.value && typeof raw.value.name === 'string')
75
+ rawByName.set(raw.value.name, raw.value);
76
+ }
68
77
  // 1. Bundled (lowest precedence)
69
78
  for (const entry of defaults_1.bundledDefaults) {
70
- const result = parseAndValidate(entry.yaml);
79
+ const result = parseAndValidate(entry.yaml, rawByName);
71
80
  if (result.workflow) {
72
81
  byName.set(entry.name, {
73
82
  workflow: result.workflow,
@@ -85,10 +94,10 @@ function discoverWorkflows(projectRoot) {
85
94
  }
86
95
  // 2. Global
87
96
  const globalDir = path.join(os.homedir(), '.specship', 'workflows');
88
- loadFromDir(globalDir, 'global', byName, errors);
97
+ loadFromDir(globalDir, 'global', byName, errors, rawByName);
89
98
  // 3. Project (highest precedence)
90
99
  const projectDir = path.join(projectRoot, '.specship', 'workflows');
91
- loadFromDir(projectDir, 'project', byName, errors);
100
+ loadFromDir(projectDir, 'project', byName, errors, rawByName);
92
101
  return {
93
102
  workflows: [...byName.values()].sort((a, b) => a.workflow.name.localeCompare(b.workflow.name)),
94
103
  errors,
@@ -105,7 +114,7 @@ function loadWorkflowByName(projectRoot, name) {
105
114
  // =============================================================================
106
115
  // internal
107
116
  // =============================================================================
108
- function loadFromDir(dir, scope, byName, errors) {
117
+ function loadFromDir(dir, scope, byName, errors, rawByName = new Map()) {
109
118
  let entries;
110
119
  try {
111
120
  entries = fs.readdirSync(dir, { withFileTypes: true });
@@ -152,8 +161,11 @@ function loadFromDir(dir, scope, byName, errors) {
152
161
  });
153
162
  continue;
154
163
  }
155
- const result = parseAndValidate(source);
164
+ const result = parseAndValidate(source, rawByName);
156
165
  if (result.workflow) {
166
+ const raw = parseRaw(source).value;
167
+ if (raw)
168
+ rawByName.set(result.workflow.name, raw);
157
169
  byName.set(result.workflow.name, {
158
170
  workflow: result.workflow,
159
171
  scope,
@@ -169,22 +181,72 @@ function isYamlFile(name) {
169
181
  const lower = name.toLowerCase();
170
182
  return lower.endsWith('.yaml') || lower.endsWith('.yml');
171
183
  }
172
- function parseAndValidate(source) {
173
- let parsed;
184
+ function parseRaw(source) {
174
185
  try {
175
- parsed = yaml.parse(source);
186
+ const v = yaml.parse(source);
187
+ return v && typeof v === 'object' && !Array.isArray(v) ? { value: v } : { value: undefined };
176
188
  }
177
189
  catch (err) {
178
- return {
179
- errors: [
180
- {
181
- path: '$',
182
- message: `YAML parse error: ${err instanceof Error ? err.message : String(err)}`,
183
- },
184
- ],
185
- };
190
+ return { error: err instanceof Error ? err.message : String(err) };
191
+ }
192
+ }
193
+ /**
194
+ * Resolve `extends: <workflow>` + `node_overrides` (THROUGHPUT-DOC,
195
+ * REQ-THRU-004): the result is the base workflow's raw definition with the
196
+ * extending file's top-level fields on top and each named node's fields
197
+ * shallow-merged from `node_overrides`. One source for shared nodes — a
198
+ * variant like spec-implement-mixed only states what differs. Chains resolve
199
+ * recursively; a cycle, an unknown base, or an override naming no base node
200
+ * is an error.
201
+ */
202
+ function resolveExtends(raw, getBase, seen = new Set()) {
203
+ const baseName = raw.extends;
204
+ if (baseName === undefined)
205
+ return { value: raw, errors: [] };
206
+ if (typeof baseName !== 'string' || baseName.trim() === '') {
207
+ return { errors: [{ path: '$.extends', message: '`extends` must name a workflow' }] };
208
+ }
209
+ if (seen.has(baseName)) {
210
+ return { errors: [{ path: '$.extends', message: `extends cycle through "${baseName}"` }] };
211
+ }
212
+ const baseRaw = getBase(baseName);
213
+ if (!baseRaw) {
214
+ return { errors: [{ path: '$.extends', message: `extends unknown workflow "${baseName}"` }] };
215
+ }
216
+ const base = resolveExtends(baseRaw, getBase, new Set([...seen, baseName]));
217
+ if (!base.value)
218
+ return base;
219
+ const { extends: _e, node_overrides: overridesRaw, ...own } = raw;
220
+ const overrides = overridesRaw && typeof overridesRaw === 'object' && !Array.isArray(overridesRaw)
221
+ ? overridesRaw
222
+ : {};
223
+ const baseNodes = Array.isArray(base.value.nodes) ? base.value.nodes : [];
224
+ const ids = new Set(baseNodes.map((n) => n.id));
225
+ const errors = [];
226
+ for (const id of Object.keys(overrides)) {
227
+ if (!ids.has(id))
228
+ errors.push({ path: `$.node_overrides.${id}`, message: `override names no node "${id}" in "${baseName}"` });
229
+ }
230
+ if (errors.length > 0)
231
+ return { errors };
232
+ const nodes = baseNodes.map((n) => {
233
+ const o = overrides[String(n.id)];
234
+ return o && typeof o === 'object' ? { ...n, ...o, id: n.id } : n;
235
+ });
236
+ return { value: { ...base.value, ...own, nodes }, errors: [] };
237
+ }
238
+ function parseAndValidate(source, rawByName = new Map()) {
239
+ const raw = parseRaw(source);
240
+ if (raw.error !== undefined) {
241
+ return { errors: [{ path: '$', message: `YAML parse error: ${raw.error}` }] };
242
+ }
243
+ if (!raw.value) {
244
+ return { errors: [{ path: '$', message: 'workflow must be a YAML mapping' }] };
186
245
  }
187
- const validation = (0, workflow_1.validateWorkflow)(parsed);
246
+ const resolved = resolveExtends(raw.value, (name) => rawByName.get(name));
247
+ if (!resolved.value)
248
+ return { errors: resolved.errors };
249
+ const validation = (0, workflow_1.validateWorkflow)(resolved.value);
188
250
  if (!validation.ok || !validation.workflow) {
189
251
  return { errors: validation.errors };
190
252
  }
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/workflows/discovery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/workflows/discovery.ts"],"names":[],"mappings":"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"}
@@ -41,6 +41,12 @@ export interface ExecuteOptions {
41
41
  * finalize so a completion hook can recover it (e.g. `{ jira: { issueKey } }`).
42
42
  */
43
43
  runMetadata?: Record<string, unknown>;
44
+ /**
45
+ * The headless agent for prompt steps (`--agent`). When unset it is resolved
46
+ * from SPECSHIP_WORKFLOW_AGENT, `workflow.agent`, then the launching host
47
+ * (REQ-AGENTADAPT-006). Either way it is stored on the run.
48
+ */
49
+ agent?: string;
44
50
  }
45
51
  /**
46
52
  * Invoked once a run settles to `completed` (never paused/failed/cancelled).
@@ -118,6 +124,10 @@ export declare class WorkflowExecutor {
118
124
  * For bash/script nodes we substitute `bash` / `script` (with bash-safe
119
125
  * shell escaping). For approval nodes we substitute `message`.
120
126
  * cancel: substitute `cancel` reason.
127
+ *
128
+ * Prompt nodes also inherit the workflow-level defaults (REQ-AUDFIX-005):
129
+ * `model` applies when the node sets none (node wins); `systemPromptAppend`
130
+ * is the workflow value followed by the node value, joined by a blank line.
121
131
  */
122
132
  private resolveNodeRefs;
123
133
  private makeSubstitutionContext;
@@ -138,4 +148,12 @@ export declare class WorkflowExecutor {
138
148
  * refuses to run a workflow that doesn't form a DAG.
139
149
  */
140
150
  export declare function topoSort(nodes: DagNode[]): string[];
151
+ /**
152
+ * REQ-AUDFIX-004: prepare a `failed` run's metadata for a retrying resume.
153
+ * Failed nodes reset to `pending`, and so does every `skipped` node that is
154
+ * (transitively) downstream of a failed node — it was skipped only because of
155
+ * the failure, so it must be re-evaluated. Completed nodes are untouched, so
156
+ * they are not re-run. Pure — returns a new metadata object.
157
+ */
158
+ export declare function resetFailedNodes(workflow: WorkflowDefinition, metadata: unknown): Record<string, unknown>;
141
159
  //# sourceMappingURL=executor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/workflows/executor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/workflows/executor.ts"],"names":[],"mappings":"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"}
@@ -51,6 +51,7 @@ var __importStar = (this && this.__importStar) || (function () {
51
51
  Object.defineProperty(exports, "__esModule", { value: true });
52
52
  exports.WorkflowExecutor = void 0;
53
53
  exports.topoSort = topoSort;
54
+ exports.resetFailedNodes = resetFailedNodes;
54
55
  const fs = __importStar(require("fs"));
55
56
  const path = __importStar(require("path"));
56
57
  const os = __importStar(require("os"));
@@ -64,6 +65,7 @@ const bash_1 = require("./runners/bash");
64
65
  const script_1 = require("./runners/script");
65
66
  const approval_1 = require("./runners/approval");
66
67
  const cancel_1 = require("./runners/cancel");
68
+ const agents_1 = require("./agents");
67
69
  class WorkflowExecutor {
68
70
  specQueries;
69
71
  worktrees;
@@ -100,6 +102,9 @@ class WorkflowExecutor {
100
102
  async start(workflow, opts) {
101
103
  const runId = opts.runId ?? (0, crypto_1.randomUUID)();
102
104
  const now = Date.now();
105
+ // Resolved before anything is created, so an unknown agent leaves no run
106
+ // behind (REQ-AGENTADAPT-006.A4); stored so resume uses the same one (A3).
107
+ const agent = (0, agents_1.resolveWorkflowAgent)({ flag: opts.agent, projectRoot: opts.projectRoot });
103
108
  // Pre-flight: required capabilities. `specship` is always available
104
109
  // (we're running inside it); `git` and `tests` are checked lazily by
105
110
  // the runner that uses them.
@@ -167,6 +172,7 @@ class WorkflowExecutor {
167
172
  nodeStates: {},
168
173
  completedNodes: [],
169
174
  ...(opts.runMetadata ?? {}),
175
+ [agents_1.RUN_AGENT_KEY]: agent,
170
176
  },
171
177
  };
172
178
  this.specQueries.insertWorkflowRun(run);
@@ -200,6 +206,12 @@ class WorkflowExecutor {
200
206
  lastActivityAt: now,
201
207
  errorMessage: undefined,
202
208
  };
209
+ // Retry-on-resume (REQ-AUDFIX-004): a `failed` run's failed nodes go back
210
+ // to pending, as do nodes skipped downstream of them, so driveExecution
211
+ // re-runs / re-evaluates them. Completed nodes keep their state + output.
212
+ if (existing.status === 'failed') {
213
+ refreshed.metadata = resetFailedNodes(workflow, refreshed.metadata);
214
+ }
203
215
  this.specQueries.updateWorkflowRun(refreshed);
204
216
  this.syncActiveRunMarker(refreshed.status, refreshed.inputs, refreshed.id);
205
217
  this.event(runId, 'run_started', { resumed: true });
@@ -222,34 +234,12 @@ class WorkflowExecutor {
222
234
  this.syncActiveRunMarker('rejected', refreshed.inputs, refreshed.id);
223
235
  throw new Error(msg);
224
236
  }
225
- const outputs = new Map(Object.entries(meta.outputs ?? {}));
226
237
  const reviseId = `${rejection.nodeId}__revise_${rejection.attempts}`;
227
- const rawRevise = {
228
- id: reviseId,
229
- kind: 'prompt',
230
- prompt: `${onReject.prompt}\n\nReviewer feedback (rejection reason):\n` +
231
- `${rejection.reason ?? '(no reason given)'}`,
232
- };
233
- // Resolve $nodeId.output refs in the on_reject prompt against the
234
- // run's accumulated outputs, same as any other node.
235
- const revise = this.resolveNodeRefs(rawRevise, outputs, opts.inputs, opts.variables);
236
- this.event(runId, 'step_started', { stepId: reviseId, kind: 'prompt', revision: true });
237
- const runner = this.runners.get('prompt');
238
- const result = runner
239
- ? await runner.run(revise, {
240
- cwd,
241
- artifactsDir,
242
- logsDir,
243
- runId,
244
- inputs: opts.inputs,
245
- variables: opts.variables,
246
- outputs,
247
- verbose: opts.verbose,
248
- emitEvent: (type, data) => this.event(runId, type, { stepId: reviseId, stepKind: 'prompt', ...data }),
249
- })
250
- : { status: 'failed', error: 'no runner for kind prompt' };
251
- if (result.status !== 'completed') {
252
- const err = result.status === 'failed' ? result.error : `revise step ${result.status}`;
238
+ // Every failure while preparing OR running the revision (an
239
+ // unresolvable $ref, a runner throw, a failed result) parks the run
240
+ // back at `rejected` with the error — never stuck in `running`
241
+ // (REQ-AUDFIX-003.A3).
242
+ const failRevision = (err) => {
253
243
  this.event(runId, 'step_failed', { stepId: reviseId, error: err });
254
244
  this.specQueries.updateWorkflowRun({
255
245
  ...refreshed,
@@ -257,7 +247,43 @@ class WorkflowExecutor {
257
247
  errorMessage: `revision failed: ${err}`,
258
248
  });
259
249
  this.syncActiveRunMarker('rejected', refreshed.inputs, refreshed.id);
260
- throw new Error(`Run ${runId}: on_reject revision failed: ${err}`);
250
+ return new Error(`Run ${runId}: on_reject revision failed: ${err}`);
251
+ };
252
+ const outputs = new Map(Object.entries(meta.outputs ?? {}));
253
+ const rawRevise = {
254
+ id: reviseId,
255
+ kind: 'prompt',
256
+ prompt: `${onReject.prompt}\n\nReviewer feedback (rejection reason):\n` +
257
+ `${rejection.reason ?? '(no reason given)'}`,
258
+ };
259
+ let result;
260
+ try {
261
+ // Resolve $nodeId.output refs in the on_reject prompt against the
262
+ // run's accumulated outputs, same as any other node; workflow-level
263
+ // model/systemPromptAppend apply too (REQ-AUDFIX-005.A2).
264
+ const revise = this.resolveNodeRefs(rawRevise, outputs, opts.inputs, opts.variables, workflow);
265
+ this.event(runId, 'step_started', { stepId: reviseId, kind: 'prompt', revision: true });
266
+ const runner = this.runners.get('prompt');
267
+ result = runner
268
+ ? await runner.run(revise, {
269
+ cwd,
270
+ artifactsDir,
271
+ logsDir,
272
+ runId,
273
+ inputs: opts.inputs,
274
+ variables: opts.variables,
275
+ outputs,
276
+ verbose: opts.verbose,
277
+ agent: runAgent(meta),
278
+ emitEvent: (type, data) => this.event(runId, type, { stepId: reviseId, stepKind: 'prompt', ...data }),
279
+ })
280
+ : { status: 'failed', error: 'no runner for kind prompt' };
281
+ }
282
+ catch (err) {
283
+ throw failRevision(err instanceof Error ? err.message : String(err));
284
+ }
285
+ if (result.status !== 'completed') {
286
+ throw failRevision(result.status === 'failed' ? result.error : `revise step ${result.status}`);
261
287
  }
262
288
  this.event(runId, 'step_completed', {
263
289
  stepId: reviseId,
@@ -266,8 +292,12 @@ class WorkflowExecutor {
266
292
  });
267
293
  await this.writeArtifact(artifactsDir, rawRevise, result.output);
268
294
  // Persist the revise output + clear the pending rejection so the next
269
- // reject starts a fresh attempt count from this one.
295
+ // reject starts a fresh attempt count from this one. With `revises`,
296
+ // the revision also REPLACES the revised node's output so every
297
+ // downstream `$<revises>.output` reads it (REQ-AUDFIX-003.A2).
270
298
  outputs.set(reviseId, result.output);
299
+ if (onReject.revises)
300
+ outputs.set(onReject.revises, result.output);
271
301
  const newMeta = {
272
302
  ...meta,
273
303
  outputs: Object.fromEntries(outputs),
@@ -467,7 +497,7 @@ class WorkflowExecutor {
467
497
  // Run the node. Resolve any $refs in node fields first.
468
498
  let processed;
469
499
  try {
470
- processed = this.resolveNodeRefs(node, outputs, opts.inputs, opts.variables);
500
+ processed = this.resolveNodeRefs(node, outputs, opts.inputs, opts.variables, workflow);
471
501
  }
472
502
  catch (err) {
473
503
  if (err instanceof condition_evaluator_1.OutputRefError) {
@@ -499,6 +529,7 @@ class WorkflowExecutor {
499
529
  variables: opts.variables,
500
530
  outputs,
501
531
  verbose: opts.verbose,
532
+ agent: runAgent(meta),
502
533
  // Stream a step's live activity (agent tool calls / messages) into the
503
534
  // run view (WF-STREAM-DOC). Stamp the step id/kind so the UI can group.
504
535
  emitEvent: (type, data) => this.event(run.id, type, { stepId: nodeId, stepKind: node.kind, ...data }),
@@ -522,6 +553,14 @@ class WorkflowExecutor {
522
553
  }
523
554
  case 'failed': {
524
555
  nodeStates.set(nodeId, 'failed');
556
+ // Keep what the failed step printed as evidence (REQ-PIPETRUST-006.A2):
557
+ // stored in the run's outputs + written as its artifact. The node
558
+ // stays `failed`, so resume still re-runs it (resetFailedNodes is
559
+ // state-driven) and a successful re-run overwrites this output.
560
+ if (result.output) {
561
+ outputs.set(nodeId, result.output);
562
+ await this.writeArtifact(artifactsDir, node, result.output);
563
+ }
525
564
  this.event(run.id, 'step_failed', { stepId: nodeId, error: result.error });
526
565
  await this.finalize(run, workflow, nodeStates, outputs, 'failed', result.error);
527
566
  return { run, nodeStates, outputs };
@@ -595,17 +634,25 @@ class WorkflowExecutor {
595
634
  * For bash/script nodes we substitute `bash` / `script` (with bash-safe
596
635
  * shell escaping). For approval nodes we substitute `message`.
597
636
  * cancel: substitute `cancel` reason.
637
+ *
638
+ * Prompt nodes also inherit the workflow-level defaults (REQ-AUDFIX-005):
639
+ * `model` applies when the node sets none (node wins); `systemPromptAppend`
640
+ * is the workflow value followed by the node value, joined by a blank line.
598
641
  */
599
- resolveNodeRefs(node, outputs, inputs, variables) {
642
+ resolveNodeRefs(node, outputs, inputs, variables, workflow) {
600
643
  const ctx = this.makeSubstitutionContext(outputs, inputs, variables);
601
644
  switch (node.kind) {
602
645
  case 'prompt': {
603
646
  const p = node;
647
+ const model = p.model ?? workflow?.model;
648
+ const appendParts = [workflow?.systemPromptAppend, p.systemPromptAppend].filter((v) => typeof v === 'string' && v.length > 0);
649
+ const systemPromptAppend = appendParts.length > 0 ? appendParts.join('\n\n') : undefined;
604
650
  return {
605
651
  ...p,
652
+ ...(model !== undefined ? { model } : {}),
606
653
  prompt: (0, condition_evaluator_1.substituteRefs)(p.prompt, ctx, { forBash: false, nodeId: p.id }),
607
- systemPromptAppend: p.systemPromptAppend
608
- ? (0, condition_evaluator_1.substituteRefs)(p.systemPromptAppend, ctx, { forBash: false, nodeId: p.id })
654
+ systemPromptAppend: systemPromptAppend
655
+ ? (0, condition_evaluator_1.substituteRefs)(systemPromptAppend, ctx, { forBash: false, nodeId: p.id })
609
656
  : undefined,
610
657
  };
611
658
  }
@@ -699,6 +746,9 @@ class WorkflowExecutor {
699
746
  // reject → resume → re-pause cycles (WF-REJECT-DOC, REQ-WFREJ-003).
700
747
  if (prevMeta.rejection !== undefined)
701
748
  meta.rejection = prevMeta.rejection;
749
+ // The run's agent stays fixed for every later step (REQ-AGENTADAPT-006.A3).
750
+ if (prevMeta[agents_1.RUN_AGENT_KEY] !== undefined)
751
+ meta[agents_1.RUN_AGENT_KEY] = prevMeta[agents_1.RUN_AGENT_KEY];
702
752
  const updated = {
703
753
  ...run,
704
754
  status,
@@ -812,10 +862,57 @@ function topoSort(nodes) {
812
862
  }
813
863
  return out;
814
864
  }
865
+ /**
866
+ * REQ-AUDFIX-004: prepare a `failed` run's metadata for a retrying resume.
867
+ * Failed nodes reset to `pending`, and so does every `skipped` node that is
868
+ * (transitively) downstream of a failed node — it was skipped only because of
869
+ * the failure, so it must be re-evaluated. Completed nodes are untouched, so
870
+ * they are not re-run. Pure — returns a new metadata object.
871
+ */
872
+ function resetFailedNodes(workflow, metadata) {
873
+ const meta = { ...(metadata ?? {}) };
874
+ const states = { ...(meta.nodeStates ?? {}) };
875
+ const failed = Object.keys(states).filter((id) => states[id] === 'failed');
876
+ if (failed.length === 0)
877
+ return meta;
878
+ // Dependents adjacency: id → nodes that depend on it.
879
+ const dependents = new Map();
880
+ for (const n of workflow.nodes) {
881
+ for (const dep of n.depends_on ?? []) {
882
+ const list = dependents.get(dep) ?? [];
883
+ list.push(n.id);
884
+ dependents.set(dep, list);
885
+ }
886
+ }
887
+ const downstream = new Set();
888
+ const queue = [...failed];
889
+ while (queue.length > 0) {
890
+ const id = queue.shift();
891
+ for (const next of dependents.get(id) ?? []) {
892
+ if (!downstream.has(next)) {
893
+ downstream.add(next);
894
+ queue.push(next);
895
+ }
896
+ }
897
+ }
898
+ for (const id of failed)
899
+ states[id] = 'pending';
900
+ for (const id of downstream) {
901
+ if (states[id] === 'skipped')
902
+ states[id] = 'pending';
903
+ }
904
+ meta.nodeStates = states;
905
+ return meta;
906
+ }
815
907
  function sanitizeFilename(s) {
816
908
  return s.replace(/[^a-zA-Z0-9._-]/g, '-').substring(0, 80);
817
909
  }
818
910
  function sleep(ms) {
819
911
  return new Promise((resolve) => setTimeout(resolve, ms));
820
912
  }
913
+ /** The agent stored with a run; undefined for runs created before agents were recorded (→ default). */
914
+ function runAgent(meta) {
915
+ const a = meta[agents_1.RUN_AGENT_KEY];
916
+ return typeof a === 'string' && a ? a : undefined;
917
+ }
821
918
  //# sourceMappingURL=executor.js.map