@specship/specship-win32-arm64 0.25.0 → 0.29.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 (305) 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 +8 -10
  15. package/lib/dist/activation/steering.d.ts.map +1 -1
  16. package/lib/dist/activation/steering.js +21 -6
  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 +799 -81
  27. package/lib/dist/bin/specship.js.map +1 -1
  28. package/lib/dist/commands/specship/learn.md +22 -0
  29. package/lib/dist/commands/specship/spec.md +19 -1
  30. package/lib/dist/db/sqlite-adapter.d.ts +7 -5
  31. package/lib/dist/db/sqlite-adapter.d.ts.map +1 -1
  32. package/lib/dist/db/sqlite-adapter.js +11 -9
  33. package/lib/dist/db/sqlite-adapter.js.map +1 -1
  34. package/lib/dist/design-md/check.d.ts +51 -0
  35. package/lib/dist/design-md/check.d.ts.map +1 -0
  36. package/lib/dist/design-md/check.js +335 -0
  37. package/lib/dist/design-md/check.js.map +1 -0
  38. package/lib/dist/design-md/css.d.ts +40 -0
  39. package/lib/dist/design-md/css.d.ts.map +1 -0
  40. package/lib/dist/design-md/css.js +224 -0
  41. package/lib/dist/design-md/css.js.map +1 -0
  42. package/lib/dist/design-md/extract.d.ts +84 -0
  43. package/lib/dist/design-md/extract.d.ts.map +1 -0
  44. package/lib/dist/design-md/extract.js +595 -0
  45. package/lib/dist/design-md/extract.js.map +1 -0
  46. package/lib/dist/design-md/maintain.d.ts +45 -0
  47. package/lib/dist/design-md/maintain.d.ts.map +1 -0
  48. package/lib/dist/design-md/maintain.js +127 -0
  49. package/lib/dist/design-md/maintain.js.map +1 -0
  50. package/lib/dist/design-md/render.d.ts +28 -0
  51. package/lib/dist/design-md/render.d.ts.map +1 -0
  52. package/lib/dist/design-md/render.js +178 -0
  53. package/lib/dist/design-md/render.js.map +1 -0
  54. package/lib/dist/design-md/upkeep.d.ts +48 -0
  55. package/lib/dist/design-md/upkeep.d.ts.map +1 -0
  56. package/lib/dist/design-md/upkeep.js +169 -0
  57. package/lib/dist/design-md/upkeep.js.map +1 -0
  58. package/lib/dist/design-md/verify.d.ts +65 -0
  59. package/lib/dist/design-md/verify.d.ts.map +1 -0
  60. package/lib/dist/design-md/verify.js +311 -0
  61. package/lib/dist/design-md/verify.js.map +1 -0
  62. package/lib/dist/enforce/changed-files.d.ts +11 -0
  63. package/lib/dist/enforce/changed-files.d.ts.map +1 -1
  64. package/lib/dist/enforce/changed-files.js +42 -0
  65. package/lib/dist/enforce/changed-files.js.map +1 -1
  66. package/lib/dist/enforce/enforce.d.ts +25 -1
  67. package/lib/dist/enforce/enforce.d.ts.map +1 -1
  68. package/lib/dist/enforce/enforce.js +58 -3
  69. package/lib/dist/enforce/enforce.js.map +1 -1
  70. package/lib/dist/enforce/mutation.d.ts +46 -0
  71. package/lib/dist/enforce/mutation.d.ts.map +1 -0
  72. package/lib/dist/enforce/mutation.js +104 -0
  73. package/lib/dist/enforce/mutation.js.map +1 -0
  74. package/lib/dist/enforce/suppressions.d.ts +33 -0
  75. package/lib/dist/enforce/suppressions.d.ts.map +1 -0
  76. package/lib/dist/enforce/suppressions.js +159 -0
  77. package/lib/dist/enforce/suppressions.js.map +1 -0
  78. package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -1
  79. package/lib/dist/extraction/specs/markdown-spec-extractor.js +16 -2
  80. package/lib/dist/extraction/specs/markdown-spec-extractor.js.map +1 -1
  81. package/lib/dist/graph/spec-coverage.d.ts +57 -1
  82. package/lib/dist/graph/spec-coverage.d.ts.map +1 -1
  83. package/lib/dist/graph/spec-coverage.js +129 -5
  84. package/lib/dist/graph/spec-coverage.js.map +1 -1
  85. package/lib/dist/health/smoke-check.js +2 -2
  86. package/lib/dist/health/smoke-check.js.map +1 -1
  87. package/lib/dist/index.d.ts +8 -3
  88. package/lib/dist/index.d.ts.map +1 -1
  89. package/lib/dist/index.js +65 -9
  90. package/lib/dist/index.js.map +1 -1
  91. package/lib/dist/installer/gemini-commands.d.ts +107 -0
  92. package/lib/dist/installer/gemini-commands.d.ts.map +1 -0
  93. package/lib/dist/installer/gemini-commands.js +271 -0
  94. package/lib/dist/installer/gemini-commands.js.map +1 -0
  95. package/lib/dist/installer/index.d.ts +23 -1
  96. package/lib/dist/installer/index.d.ts.map +1 -1
  97. package/lib/dist/installer/index.js +22 -3
  98. package/lib/dist/installer/index.js.map +1 -1
  99. package/lib/dist/installer/install-defaults.d.ts +19 -0
  100. package/lib/dist/installer/install-defaults.d.ts.map +1 -1
  101. package/lib/dist/installer/install-defaults.js +28 -0
  102. package/lib/dist/installer/install-defaults.js.map +1 -1
  103. package/lib/dist/installer/instructions-template.d.ts +22 -0
  104. package/lib/dist/installer/instructions-template.d.ts.map +1 -1
  105. package/lib/dist/installer/instructions-template.js +37 -1
  106. package/lib/dist/installer/instructions-template.js.map +1 -1
  107. package/lib/dist/installer/targets/claude.d.ts +5 -1
  108. package/lib/dist/installer/targets/claude.d.ts.map +1 -1
  109. package/lib/dist/installer/targets/claude.js +15 -27
  110. package/lib/dist/installer/targets/claude.js.map +1 -1
  111. package/lib/dist/installer/targets/gemini.d.ts +85 -12
  112. package/lib/dist/installer/targets/gemini.d.ts.map +1 -1
  113. package/lib/dist/installer/targets/gemini.js +527 -30
  114. package/lib/dist/installer/targets/gemini.js.map +1 -1
  115. package/lib/dist/installer/targets/shared.d.ts +13 -0
  116. package/lib/dist/installer/targets/shared.d.ts.map +1 -1
  117. package/lib/dist/installer/targets/shared.js +18 -0
  118. package/lib/dist/installer/targets/shared.js.map +1 -1
  119. package/lib/dist/installer/targets/types.d.ts +12 -0
  120. package/lib/dist/installer/targets/types.d.ts.map +1 -1
  121. package/lib/dist/jira/auto-publish.d.ts +71 -4
  122. package/lib/dist/jira/auto-publish.d.ts.map +1 -1
  123. package/lib/dist/jira/auto-publish.js +186 -17
  124. package/lib/dist/jira/auto-publish.js.map +1 -1
  125. package/lib/dist/jira/reconcile.d.ts +24 -1
  126. package/lib/dist/jira/reconcile.d.ts.map +1 -1
  127. package/lib/dist/jira/reconcile.js +46 -2
  128. package/lib/dist/jira/reconcile.js.map +1 -1
  129. package/lib/dist/jira/repo-config.d.ts +9 -0
  130. package/lib/dist/jira/repo-config.d.ts.map +1 -1
  131. package/lib/dist/jira/repo-config.js +11 -0
  132. package/lib/dist/jira/repo-config.js.map +1 -1
  133. package/lib/dist/jira/types.d.ts +7 -0
  134. package/lib/dist/jira/types.d.ts.map +1 -1
  135. package/lib/dist/jira/types.js.map +1 -1
  136. package/lib/dist/knowledge/enforce.d.ts +75 -0
  137. package/lib/dist/knowledge/enforce.d.ts.map +1 -0
  138. package/lib/dist/knowledge/enforce.js +250 -0
  139. package/lib/dist/knowledge/enforce.js.map +1 -0
  140. package/lib/dist/knowledge/facts.d.ts +33 -0
  141. package/lib/dist/knowledge/facts.d.ts.map +1 -0
  142. package/lib/dist/knowledge/facts.js +117 -0
  143. package/lib/dist/knowledge/facts.js.map +1 -0
  144. package/lib/dist/knowledge/proposals.d.ts +88 -0
  145. package/lib/dist/knowledge/proposals.d.ts.map +1 -0
  146. package/lib/dist/knowledge/proposals.js +360 -0
  147. package/lib/dist/knowledge/proposals.js.map +1 -0
  148. package/lib/dist/knowledge/stale.d.ts +64 -0
  149. package/lib/dist/knowledge/stale.d.ts.map +1 -0
  150. package/lib/dist/knowledge/stale.js +174 -0
  151. package/lib/dist/knowledge/stale.js.map +1 -0
  152. package/lib/dist/mcp/gemini-session.d.ts +50 -0
  153. package/lib/dist/mcp/gemini-session.d.ts.map +1 -0
  154. package/lib/dist/mcp/gemini-session.js +159 -0
  155. package/lib/dist/mcp/gemini-session.js.map +1 -0
  156. package/lib/dist/mcp/jira-tools.d.ts.map +1 -1
  157. package/lib/dist/mcp/jira-tools.js +25 -0
  158. package/lib/dist/mcp/jira-tools.js.map +1 -1
  159. package/lib/dist/mcp/model-context.d.ts +22 -9
  160. package/lib/dist/mcp/model-context.d.ts.map +1 -1
  161. package/lib/dist/mcp/model-context.js +35 -13
  162. package/lib/dist/mcp/model-context.js.map +1 -1
  163. package/lib/dist/mcp/proxy.js +1 -1
  164. package/lib/dist/mcp/proxy.js.map +1 -1
  165. package/lib/dist/mcp/server-instructions.d.ts +16 -15
  166. package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
  167. package/lib/dist/mcp/server-instructions.js +67 -1
  168. package/lib/dist/mcp/server-instructions.js.map +1 -1
  169. package/lib/dist/mcp/session.js +1 -1
  170. package/lib/dist/mcp/session.js.map +1 -1
  171. package/lib/dist/mcp/spec-tools.d.ts +9 -1
  172. package/lib/dist/mcp/spec-tools.d.ts.map +1 -1
  173. package/lib/dist/mcp/spec-tools.js +69 -21
  174. package/lib/dist/mcp/spec-tools.js.map +1 -1
  175. package/lib/dist/mcp/tools.d.ts +37 -1
  176. package/lib/dist/mcp/tools.d.ts.map +1 -1
  177. package/lib/dist/mcp/tools.js +120 -9
  178. package/lib/dist/mcp/tools.js.map +1 -1
  179. package/lib/dist/pulse/pulse.d.ts +93 -0
  180. package/lib/dist/pulse/pulse.d.ts.map +1 -0
  181. package/lib/dist/pulse/pulse.js +401 -0
  182. package/lib/dist/pulse/pulse.js.map +1 -0
  183. package/lib/dist/reflect/apply.d.ts.map +1 -1
  184. package/lib/dist/reflect/apply.js +38 -3
  185. package/lib/dist/reflect/apply.js.map +1 -1
  186. package/lib/dist/reflect/auto-sweep.d.ts +26 -0
  187. package/lib/dist/reflect/auto-sweep.d.ts.map +1 -0
  188. package/lib/dist/reflect/auto-sweep.js +90 -0
  189. package/lib/dist/reflect/auto-sweep.js.map +1 -0
  190. package/lib/dist/reflect/cli.d.ts +62 -0
  191. package/lib/dist/reflect/cli.d.ts.map +1 -0
  192. package/lib/dist/reflect/cli.js +163 -0
  193. package/lib/dist/reflect/cli.js.map +1 -0
  194. package/lib/dist/reflect/miner.d.ts.map +1 -1
  195. package/lib/dist/reflect/miner.js +119 -0
  196. package/lib/dist/reflect/miner.js.map +1 -1
  197. package/lib/dist/reflect/sweep.d.ts +1 -0
  198. package/lib/dist/reflect/sweep.d.ts.map +1 -1
  199. package/lib/dist/reflect/sweep.js +62 -13
  200. package/lib/dist/reflect/sweep.js.map +1 -1
  201. package/lib/dist/reflect/targets.d.ts +2 -0
  202. package/lib/dist/reflect/targets.d.ts.map +1 -1
  203. package/lib/dist/reflect/targets.js +33 -0
  204. package/lib/dist/reflect/targets.js.map +1 -1
  205. package/lib/dist/reflect/types.d.ts +19 -2
  206. package/lib/dist/reflect/types.d.ts.map +1 -1
  207. package/lib/dist/resolution/test-title-links.d.ts.map +1 -1
  208. package/lib/dist/resolution/test-title-links.js +3 -14
  209. package/lib/dist/resolution/test-title-links.js.map +1 -1
  210. package/lib/dist/server/routes/claude.js +15 -7
  211. package/lib/dist/server/routes/knowledge.js +118 -0
  212. package/lib/dist/server/server.js +2 -0
  213. package/lib/dist/skills/design-md/SKILL.md +172 -0
  214. package/lib/dist/skills/design-md/references/authored-sections.md +90 -0
  215. package/lib/dist/skills/design-md/references/sources.md +71 -0
  216. package/lib/dist/spec-lint/lint.d.ts +1 -1
  217. package/lib/dist/spec-lint/lint.d.ts.map +1 -1
  218. package/lib/dist/spec-lint/lint.js +63 -2
  219. package/lib/dist/spec-lint/lint.js.map +1 -1
  220. package/lib/dist/spec-quality/criterion-ids.d.ts +13 -0
  221. package/lib/dist/spec-quality/criterion-ids.d.ts.map +1 -0
  222. package/lib/dist/spec-quality/criterion-ids.js +38 -0
  223. package/lib/dist/spec-quality/criterion-ids.js.map +1 -0
  224. package/lib/dist/spec-quality/evidence-kind.d.ts +54 -0
  225. package/lib/dist/spec-quality/evidence-kind.d.ts.map +1 -0
  226. package/lib/dist/spec-quality/evidence-kind.js +183 -0
  227. package/lib/dist/spec-quality/evidence-kind.js.map +1 -0
  228. package/lib/dist/spec-quality/link-persist.d.ts +65 -0
  229. package/lib/dist/spec-quality/link-persist.d.ts.map +1 -0
  230. package/lib/dist/spec-quality/link-persist.js +249 -0
  231. package/lib/dist/spec-quality/link-persist.js.map +1 -0
  232. package/lib/dist/spec-quality/plan-scope.d.ts +38 -0
  233. package/lib/dist/spec-quality/plan-scope.d.ts.map +1 -0
  234. package/lib/dist/spec-quality/plan-scope.js +129 -0
  235. package/lib/dist/spec-quality/plan-scope.js.map +1 -0
  236. package/lib/dist/spec-quality/postcheck.d.ts +91 -0
  237. package/lib/dist/spec-quality/postcheck.d.ts.map +1 -0
  238. package/lib/dist/spec-quality/postcheck.js +421 -0
  239. package/lib/dist/spec-quality/postcheck.js.map +1 -0
  240. package/lib/dist/spec-quality/readiness.d.ts +72 -0
  241. package/lib/dist/spec-quality/readiness.d.ts.map +1 -0
  242. package/lib/dist/spec-quality/readiness.js +226 -0
  243. package/lib/dist/spec-quality/readiness.js.map +1 -0
  244. package/lib/dist/workflows/agents/claude.d.ts +16 -0
  245. package/lib/dist/workflows/agents/claude.d.ts.map +1 -0
  246. package/lib/dist/workflows/agents/claude.js +82 -0
  247. package/lib/dist/workflows/agents/claude.js.map +1 -0
  248. package/lib/dist/workflows/agents/gemini.d.ts +21 -0
  249. package/lib/dist/workflows/agents/gemini.d.ts.map +1 -0
  250. package/lib/dist/workflows/agents/gemini.js +124 -0
  251. package/lib/dist/workflows/agents/gemini.js.map +1 -0
  252. package/lib/dist/workflows/agents/index.d.ts +28 -0
  253. package/lib/dist/workflows/agents/index.d.ts.map +1 -0
  254. package/lib/dist/workflows/agents/index.js +104 -0
  255. package/lib/dist/workflows/agents/index.js.map +1 -0
  256. package/lib/dist/workflows/agents/types.d.ts +55 -0
  257. package/lib/dist/workflows/agents/types.d.ts.map +1 -0
  258. package/lib/dist/workflows/agents/types.js +46 -0
  259. package/lib/dist/workflows/agents/types.js.map +1 -0
  260. package/lib/dist/workflows/batch.d.ts +63 -0
  261. package/lib/dist/workflows/batch.d.ts.map +1 -0
  262. package/lib/dist/workflows/batch.js +151 -0
  263. package/lib/dist/workflows/batch.js.map +1 -0
  264. package/lib/dist/workflows/defaults/claude-design-implement.yaml +37 -9
  265. package/lib/dist/workflows/defaults/spec-author.yaml +11 -9
  266. package/lib/dist/workflows/defaults/spec-implement-mixed.yaml +21 -436
  267. package/lib/dist/workflows/defaults/spec-implement.yaml +481 -46
  268. package/lib/dist/workflows/discovery.d.ts +13 -0
  269. package/lib/dist/workflows/discovery.d.ts.map +1 -1
  270. package/lib/dist/workflows/discovery.js +79 -17
  271. package/lib/dist/workflows/discovery.js.map +1 -1
  272. package/lib/dist/workflows/executor.d.ts +18 -0
  273. package/lib/dist/workflows/executor.d.ts.map +1 -1
  274. package/lib/dist/workflows/executor.js +130 -33
  275. package/lib/dist/workflows/executor.js.map +1 -1
  276. package/lib/dist/workflows/gc.d.ts +50 -0
  277. package/lib/dist/workflows/gc.d.ts.map +1 -0
  278. package/lib/dist/workflows/gc.js +120 -0
  279. package/lib/dist/workflows/gc.js.map +1 -0
  280. package/lib/dist/workflows/merge-queue.d.ts +64 -0
  281. package/lib/dist/workflows/merge-queue.d.ts.map +1 -0
  282. package/lib/dist/workflows/merge-queue.js +162 -0
  283. package/lib/dist/workflows/merge-queue.js.map +1 -0
  284. package/lib/dist/workflows/runners/approval.d.ts +1 -1
  285. package/lib/dist/workflows/runners/approval.d.ts.map +1 -1
  286. package/lib/dist/workflows/runners/approval.js +11 -2
  287. package/lib/dist/workflows/runners/approval.js.map +1 -1
  288. package/lib/dist/workflows/runners/bash.d.ts +15 -0
  289. package/lib/dist/workflows/runners/bash.d.ts.map +1 -1
  290. package/lib/dist/workflows/runners/bash.js +50 -1
  291. package/lib/dist/workflows/runners/bash.js.map +1 -1
  292. package/lib/dist/workflows/runners/prompt.d.ts +16 -41
  293. package/lib/dist/workflows/runners/prompt.d.ts.map +1 -1
  294. package/lib/dist/workflows/runners/prompt.js +55 -120
  295. package/lib/dist/workflows/runners/prompt.js.map +1 -1
  296. package/lib/dist/workflows/runners/types.d.ts +12 -0
  297. package/lib/dist/workflows/runners/types.d.ts.map +1 -1
  298. package/lib/dist/workflows/schemas/workflow.d.ts +17 -0
  299. package/lib/dist/workflows/schemas/workflow.d.ts.map +1 -1
  300. package/lib/dist/workflows/schemas/workflow.js +27 -0
  301. package/lib/dist/workflows/schemas/workflow.js.map +1 -1
  302. package/lib/node_modules/.package-lock.json +1 -1
  303. package/lib/package.json +2 -2
  304. package/package.json +5 -3
  305. package/node.exe +0 -4
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Headless-agent registry and selection (REQ-AGENTADAPT-005/006).
3
+ *
4
+ * The agent is resolved once at run start — `--agent`, then
5
+ * `SPECSHIP_WORKFLOW_AGENT`, then `workflow.agent` in specship.config.json,
6
+ * then the coding agent that launched the command, then Claude Code — and is
7
+ * stored on the run so approve / revise / resume use the same one.
8
+ */
9
+ import type { HeadlessAgent, HeadlessAgentConfig } from './types';
10
+ export type { HeadlessAgent, HeadlessAgentConfig, HeadlessInvocation, StreamParseState } from './types';
11
+ export declare const DEFAULT_WORKFLOW_AGENT: string;
12
+ /** Run-metadata key the chosen agent is stored under. */
13
+ export declare const RUN_AGENT_KEY = "agent";
14
+ export declare function knownWorkflowAgents(): string[];
15
+ export declare function getHeadlessAgent(id: string): HeadlessAgent | undefined;
16
+ export declare class UnknownWorkflowAgentError extends Error {
17
+ constructor(name: string, source: string);
18
+ }
19
+ export interface ResolveAgentOptions {
20
+ flag?: string;
21
+ env?: NodeJS.ProcessEnv;
22
+ projectRoot: string;
23
+ }
24
+ /** The agent id for a new run, or throws UnknownWorkflowAgentError (REQ-AGENTADAPT-006.A4). */
25
+ export declare function resolveWorkflowAgent(opts: ResolveAgentOptions): string;
26
+ /** `workflow.agents.<id>` settings (model tier mapping), {} when unset. */
27
+ export declare function workflowAgentConfig(projectRoot: string, id: string): HeadlessAgentConfig;
28
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/workflows/agents/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAElE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGxG,eAAO,MAAM,sBAAsB,QAAyB,CAAC;AAC7D,yDAAyD;AACzD,eAAO,MAAM,aAAa,UAAU,CAAC;AAErC,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEtE;AAED,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAIzC;AAgBD,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,+FAA+F;AAC/F,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAgBtE;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,mBAAmB,CAGxF"}
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ /**
3
+ * Headless-agent registry and selection (REQ-AGENTADAPT-005/006).
4
+ *
5
+ * The agent is resolved once at run start — `--agent`, then
6
+ * `SPECSHIP_WORKFLOW_AGENT`, then `workflow.agent` in specship.config.json,
7
+ * then the coding agent that launched the command, then Claude Code — and is
8
+ * stored on the run so approve / revise / resume use the same one.
9
+ */
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
23
+ }) : function(o, v) {
24
+ o["default"] = v;
25
+ });
26
+ var __importStar = (this && this.__importStar) || (function () {
27
+ var ownKeys = function(o) {
28
+ ownKeys = Object.getOwnPropertyNames || function (o) {
29
+ var ar = [];
30
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
+ return ar;
32
+ };
33
+ return ownKeys(o);
34
+ };
35
+ return function (mod) {
36
+ if (mod && mod.__esModule) return mod;
37
+ var result = {};
38
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
+ __setModuleDefault(result, mod);
40
+ return result;
41
+ };
42
+ })();
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.UnknownWorkflowAgentError = exports.RUN_AGENT_KEY = exports.DEFAULT_WORKFLOW_AGENT = void 0;
45
+ exports.knownWorkflowAgents = knownWorkflowAgents;
46
+ exports.getHeadlessAgent = getHeadlessAgent;
47
+ exports.resolveWorkflowAgent = resolveWorkflowAgent;
48
+ exports.workflowAgentConfig = workflowAgentConfig;
49
+ const fs = __importStar(require("fs"));
50
+ const path = __importStar(require("path"));
51
+ const claude_1 = require("./claude");
52
+ const gemini_1 = require("./gemini");
53
+ const AGENTS = [claude_1.claudeHeadlessAgent, gemini_1.geminiHeadlessAgent];
54
+ exports.DEFAULT_WORKFLOW_AGENT = claude_1.claudeHeadlessAgent.id;
55
+ /** Run-metadata key the chosen agent is stored under. */
56
+ exports.RUN_AGENT_KEY = 'agent';
57
+ function knownWorkflowAgents() {
58
+ return AGENTS.map((a) => a.id);
59
+ }
60
+ function getHeadlessAgent(id) {
61
+ return AGENTS.find((a) => a.id === id);
62
+ }
63
+ class UnknownWorkflowAgentError extends Error {
64
+ constructor(name, source) {
65
+ super(`Unknown workflow agent "${name}" (from ${source}). Known agents: ${knownWorkflowAgents().join(', ')}`);
66
+ this.name = 'UnknownWorkflowAgentError';
67
+ }
68
+ }
69
+ exports.UnknownWorkflowAgentError = UnknownWorkflowAgentError;
70
+ function readWorkflowConfig(projectRoot) {
71
+ try {
72
+ const cfg = JSON.parse(fs.readFileSync(path.join(projectRoot, 'specship.config.json'), 'utf8'));
73
+ return (cfg && typeof cfg.workflow === 'object' && cfg.workflow) || {};
74
+ }
75
+ catch {
76
+ return {};
77
+ }
78
+ }
79
+ /** The agent id for a new run, or throws UnknownWorkflowAgentError (REQ-AGENTADAPT-006.A4). */
80
+ function resolveWorkflowAgent(opts) {
81
+ const env = opts.env ?? process.env;
82
+ const cfg = readWorkflowConfig(opts.projectRoot);
83
+ const explicit = [
84
+ [opts.flag, '--agent'],
85
+ [env.SPECSHIP_WORKFLOW_AGENT, 'SPECSHIP_WORKFLOW_AGENT'],
86
+ [cfg.agent, 'workflow.agent in specship.config.json'],
87
+ ];
88
+ for (const [value, source] of explicit) {
89
+ if (typeof value !== 'string' || !value.trim())
90
+ continue;
91
+ const id = value.trim().toLowerCase();
92
+ if (!getHeadlessAgent(id))
93
+ throw new UnknownWorkflowAgentError(value, source);
94
+ return id;
95
+ }
96
+ const launcher = AGENTS.find((a) => a.id !== exports.DEFAULT_WORKFLOW_AGENT && a.launchedFrom(env));
97
+ return launcher?.id ?? exports.DEFAULT_WORKFLOW_AGENT;
98
+ }
99
+ /** `workflow.agents.<id>` settings (model tier mapping), {} when unset. */
100
+ function workflowAgentConfig(projectRoot, id) {
101
+ const entry = readWorkflowConfig(projectRoot).agents?.[id];
102
+ return entry && typeof entry === 'object' ? entry : {};
103
+ }
104
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/workflows/agents/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Headless-agent adapters for workflow prompt steps (AGENTADAPT-DOC,
3
+ * REQ-AGENTADAPT-005). One adapter per coding agent owns that host's binary,
4
+ * argument translation and output parsing; the prompt runner stays
5
+ * host-neutral and gets the same step result whichever host ran it.
6
+ */
7
+ import type { PromptNode } from '../schemas/workflow';
8
+ import type { WorkflowEventType } from '../../types';
9
+ /** Accumulated state while parsing an agent's streamed output. */
10
+ export interface StreamParseState {
11
+ /** True once at least one line parsed as a known stream event. */
12
+ sawStream: boolean;
13
+ /** Final result text from a terminal result event, if the host sends one. */
14
+ resultText: string | null;
15
+ /** Concatenated assistant text (the result when there's no result text). */
16
+ assistantText: string;
17
+ costUsd?: number;
18
+ durationMs?: number;
19
+ model?: string;
20
+ /** Set when the host's own terminal event reports failure. */
21
+ failure?: string;
22
+ }
23
+ export declare function newStreamState(): StreamParseState;
24
+ export type EmitFn = (type: WorkflowEventType, data?: Record<string, unknown>) => void;
25
+ /** What to spawn for one step. */
26
+ export interface HeadlessInvocation {
27
+ bin: string;
28
+ args: string[];
29
+ /** Written to the child's stdin, then closed. */
30
+ stdin: string;
31
+ }
32
+ /** Per-agent settings from `workflow.agents.<id>` in specship.config.json. */
33
+ export interface HeadlessAgentConfig {
34
+ /** Model tier alias (`haiku`, `sonnet`, `opus`) → this host's model id. */
35
+ models?: Record<string, string>;
36
+ }
37
+ export interface HeadlessAgent {
38
+ /** The name `--agent` / `SPECSHIP_WORKFLOW_AGENT` / `workflow.agent` use. */
39
+ readonly id: string;
40
+ /** True when `env` shows the command was launched from inside this host. */
41
+ launchedFrom(env: NodeJS.ProcessEnv): boolean;
42
+ /**
43
+ * Translate a step. Returns `{ error }` — never a partial invocation — when
44
+ * the step uses something this host cannot honour (REQ-AGENTADAPT-007.A4).
45
+ */
46
+ build(node: PromptNode, config: HeadlessAgentConfig, env: NodeJS.ProcessEnv): HeadlessInvocation | {
47
+ error: string;
48
+ };
49
+ /** Parse one output line, emitting live events and folding into `state`. */
50
+ handleLine(line: string, emit: EmitFn, state: StreamParseState): void;
51
+ }
52
+ /** A short, single-line summary of a tool's input for the `tool_called` event. */
53
+ export declare function summarizeToolInput(input: unknown): string;
54
+ export declare function parseJsonLine(line: string): Record<string, unknown> | null;
55
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/workflows/agents/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,kEAAkE;AAClE,MAAM,WAAW,gBAAgB;IAC/B,kEAAkE;IAClE,SAAS,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,4EAA4E;IAC5E,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,cAAc,IAAI,gBAAgB,CAEjD;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AAEvF,kCAAkC;AAClC,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,8EAA8E;AAC9E,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC;IAC9C;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,mBAAmB,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,kBAAkB,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACrH,4EAA4E;IAC5E,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACvE;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAezD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAS1E"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ /**
3
+ * Headless-agent adapters for workflow prompt steps (AGENTADAPT-DOC,
4
+ * REQ-AGENTADAPT-005). One adapter per coding agent owns that host's binary,
5
+ * argument translation and output parsing; the prompt runner stays
6
+ * host-neutral and gets the same step result whichever host ran it.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.newStreamState = newStreamState;
10
+ exports.summarizeToolInput = summarizeToolInput;
11
+ exports.parseJsonLine = parseJsonLine;
12
+ function newStreamState() {
13
+ return { sawStream: false, resultText: null, assistantText: '' };
14
+ }
15
+ /** A short, single-line summary of a tool's input for the `tool_called` event. */
16
+ function summarizeToolInput(input) {
17
+ if (input == null)
18
+ return '';
19
+ let s;
20
+ if (typeof input === 'string') {
21
+ s = input;
22
+ }
23
+ else if (typeof input === 'object') {
24
+ const o = input;
25
+ const pick = o.file_path ?? o.path ?? o.command ?? o.pattern ?? o.query ?? o.url ?? o.prompt;
26
+ s = typeof pick === 'string' ? pick : JSON.stringify(o);
27
+ }
28
+ else {
29
+ s = String(input);
30
+ }
31
+ s = s.replace(/\s+/g, ' ').trim();
32
+ return s.length > 140 ? `${s.slice(0, 140)}…` : s;
33
+ }
34
+ function parseJsonLine(line) {
35
+ const trimmed = line.trim();
36
+ if (!trimmed)
37
+ return null;
38
+ try {
39
+ const ev = JSON.parse(trimmed);
40
+ return ev && typeof ev === 'object' && !Array.isArray(ev) ? ev : null;
41
+ }
42
+ catch {
43
+ return null; // not JSON — ignore (hosts may print plain diagnostics)
44
+ }
45
+ }
46
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/workflows/agents/types.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAoBH,wCAEC;AAiCD,gDAeC;AAED,sCASC;AA7DD,SAAgB,cAAc;IAC5B,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC;AACnE,CAAC;AAgCD,kFAAkF;AAClF,SAAgB,kBAAkB,CAAC,KAAc;IAC/C,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC7B,IAAI,CAAS,CAAC;IACd,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,CAAC,GAAG,KAAK,CAAC;IACZ,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,KAAgC,CAAC;QAC3C,MAAM,IAAI,GACR,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC;QAClF,CAAC,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC;SAAM,CAAC;QACN,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IACD,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAClC,OAAO,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,SAAgB,aAAa,CAAC,IAAY;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/B,OAAO,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,EAA8B,CAAC,CAAC,CAAC,IAAI,CAAC;IACrG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,wDAAwD;IACvE,CAAC;AACH,CAAC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * REQ-THRU-001 — parallel batch runs.
3
+ *
4
+ * `specship workflow run-batch <workflow> --specs <ID,…>` starts one run per
5
+ * requirement, each in its own worktree. Requirements whose `implementations:`
6
+ * files overlap never run concurrently: the later one is placed in a later
7
+ * wave and waits for the earlier wave to finish. No wave holds more runs than
8
+ * the concurrency limit.
9
+ */
10
+ export declare const DEFAULT_BATCH_CONCURRENCY = 3;
11
+ export interface BatchSpec {
12
+ id: string;
13
+ implementationFiles: string[];
14
+ }
15
+ /** Statuses after which a run is finished (no longer holding its files). */
16
+ export declare const TERMINAL_RUN_STATUSES: Set<string>;
17
+ /**
18
+ * Plan the waves. Specs are visited in input order; each goes into the
19
+ * earliest wave that (a) comes after every wave holding a spec it shares an
20
+ * implementation file with, and (b) still has room under `concurrency`.
21
+ */
22
+ export declare function planBatch(specs: BatchSpec[], concurrency: number): string[][];
23
+ /**
24
+ * Implementation files of a requirement, read from its spec file's
25
+ * `implementations:` block (`path:Symbol` bullets → `path`). Null when the
26
+ * requirement is not found under specs/.
27
+ */
28
+ export declare function implementationFilesFor(projectRoot: string, requirementId: string): string[] | null;
29
+ export interface BatchRunResult {
30
+ specId: string;
31
+ runId: string;
32
+ status: string;
33
+ wave: number;
34
+ }
35
+ export interface RunBatchOptions {
36
+ projectRoot: string;
37
+ specIds: string[];
38
+ concurrency?: number;
39
+ /** Start one run for a requirement; resolves once the run is started/settled. */
40
+ startRun: (specId: string) => Promise<{
41
+ runId: string;
42
+ status: string;
43
+ }>;
44
+ /**
45
+ * Wait until a started run is finished. Default: the run is finished when
46
+ * `startRun` resolves. The CLI waits for a terminal status so a run paused
47
+ * at an approval still holds its files.
48
+ */
49
+ waitForRun?: (runId: string, status: string) => Promise<string>;
50
+ /** Resolve a requirement's implementation files (default: its spec file). */
51
+ resolveFiles?: (specId: string) => string[] | null;
52
+ /** Called with the full plan before any run starts. */
53
+ onPlan?: (waves: string[][]) => void;
54
+ /** Called as each run is started. */
55
+ onRunStarted?: (run: BatchRunResult) => void;
56
+ }
57
+ export interface RunBatchResult {
58
+ waves: string[][];
59
+ runs: BatchRunResult[];
60
+ }
61
+ /** Start the runs wave by wave; a wave finishes before the next one starts. */
62
+ export declare function runBatch(opts: RunBatchOptions): Promise<RunBatchResult>;
63
+ //# sourceMappingURL=batch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../src/workflows/batch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,4EAA4E;AAC5E,eAAO,MAAM,qBAAqB,aAA4D,CAAC;AAE/F;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CA+B7E;AAMD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAalG;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzE;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChE,6EAA6E;IAC7E,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,EAAE,GAAG,IAAI,CAAC;IACnD,uDAAuD;IACvD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,IAAI,CAAC;IACrC,qCAAqC;IACrC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;IAClB,IAAI,EAAE,cAAc,EAAE,CAAC;CACxB;AAED,+EAA+E;AAC/E,wBAAsB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA8B7E"}
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ /**
3
+ * REQ-THRU-001 — parallel batch runs.
4
+ *
5
+ * `specship workflow run-batch <workflow> --specs <ID,…>` starts one run per
6
+ * requirement, each in its own worktree. Requirements whose `implementations:`
7
+ * files overlap never run concurrently: the later one is placed in a later
8
+ * wave and waits for the earlier wave to finish. No wave holds more runs than
9
+ * the concurrency limit.
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.TERMINAL_RUN_STATUSES = exports.DEFAULT_BATCH_CONCURRENCY = void 0;
46
+ exports.planBatch = planBatch;
47
+ exports.implementationFilesFor = implementationFilesFor;
48
+ exports.runBatch = runBatch;
49
+ const fs = __importStar(require("fs"));
50
+ const postcheck_1 = require("../spec-quality/postcheck");
51
+ exports.DEFAULT_BATCH_CONCURRENCY = 3;
52
+ /** Statuses after which a run is finished (no longer holding its files). */
53
+ exports.TERMINAL_RUN_STATUSES = new Set(['completed', 'failed', 'cancelled', 'rejected']);
54
+ /**
55
+ * Plan the waves. Specs are visited in input order; each goes into the
56
+ * earliest wave that (a) comes after every wave holding a spec it shares an
57
+ * implementation file with, and (b) still has room under `concurrency`.
58
+ */
59
+ function planBatch(specs, concurrency) {
60
+ const limit = Math.max(1, Math.floor(concurrency) || 1);
61
+ const waves = [];
62
+ const waveOf = new Map();
63
+ const filesOf = new Map();
64
+ for (let i = 0; i < specs.length; i++) {
65
+ const spec = specs[i];
66
+ if (waveOf.has(spec.id))
67
+ continue; // duplicate id — schedule once
68
+ const files = new Set(spec.implementationFiles.map(normalizeFile));
69
+ let minWave = 0;
70
+ for (let j = 0; j < i; j++) {
71
+ const earlier = specs[j];
72
+ const w = waveOf.get(earlier.id);
73
+ if (w === undefined)
74
+ continue;
75
+ const ef = filesOf.get(earlier.id);
76
+ for (const f of files) {
77
+ if (ef.has(f)) {
78
+ minWave = Math.max(minWave, w + 1);
79
+ break;
80
+ }
81
+ }
82
+ }
83
+ let wave = minWave;
84
+ while (waves[wave] && waves[wave].length >= limit)
85
+ wave++;
86
+ while (waves.length <= wave)
87
+ waves.push([]);
88
+ waves[wave].push(spec.id);
89
+ waveOf.set(spec.id, wave);
90
+ filesOf.set(spec.id, files);
91
+ }
92
+ return waves.filter((w) => w.length > 0);
93
+ }
94
+ function normalizeFile(f) {
95
+ return f.trim().replace(/\\/g, '/').replace(/^\.\//, '');
96
+ }
97
+ /**
98
+ * Implementation files of a requirement, read from its spec file's
99
+ * `implementations:` block (`path:Symbol` bullets → `path`). Null when the
100
+ * requirement is not found under specs/.
101
+ */
102
+ function implementationFilesFor(projectRoot, requirementId) {
103
+ const specFile = (0, postcheck_1.findSpecFile)(projectRoot, requirementId);
104
+ if (!specFile)
105
+ return null;
106
+ const block = (0, postcheck_1.requirementBlock)(fs.readFileSync(specFile, 'utf8'), requirementId);
107
+ if (block === null)
108
+ return null;
109
+ const files = new Set();
110
+ for (const bullet of (0, postcheck_1.linkBullets)(block, 'implementations')) {
111
+ const target = bullet.replace(/^`|`$/g, '').trim();
112
+ const colon = target.indexOf(':');
113
+ const file = normalizeFile(colon > 0 ? target.slice(0, colon) : target);
114
+ if (file)
115
+ files.add(file);
116
+ }
117
+ return [...files];
118
+ }
119
+ /** Start the runs wave by wave; a wave finishes before the next one starts. */
120
+ async function runBatch(opts) {
121
+ const resolve = opts.resolveFiles ?? ((id) => implementationFilesFor(opts.projectRoot, id));
122
+ const specs = [];
123
+ const missing = [];
124
+ for (const id of opts.specIds) {
125
+ const files = resolve(id);
126
+ if (files === null)
127
+ missing.push(id);
128
+ else
129
+ specs.push({ id, implementationFiles: files });
130
+ }
131
+ if (missing.length > 0) {
132
+ throw new Error(`Requirement(s) not found under specs/: ${missing.join(', ')}`);
133
+ }
134
+ const waves = planBatch(specs, opts.concurrency ?? exports.DEFAULT_BATCH_CONCURRENCY);
135
+ opts.onPlan?.(waves);
136
+ const runs = [];
137
+ for (let w = 0; w < waves.length; w++) {
138
+ const wave = waves[w];
139
+ const settled = await Promise.all(wave.map(async (specId) => {
140
+ const started = await opts.startRun(specId);
141
+ const run = { specId, runId: started.runId, status: started.status, wave: w };
142
+ opts.onRunStarted?.(run);
143
+ if (opts.waitForRun)
144
+ run.status = await opts.waitForRun(started.runId, started.status);
145
+ return run;
146
+ }));
147
+ runs.push(...settled);
148
+ }
149
+ return { waves, runs };
150
+ }
151
+ //# sourceMappingURL=batch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/workflows/batch.ts"],"names":[],"mappings":"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"}
@@ -53,7 +53,9 @@ systemPromptAppend: |
53
53
 
54
54
  The fidelity principle: never paraphrase or summarise design content
55
55
  when capturing it. The snapshot HTML and tokens.css are the
56
- zero-loss reference layer; the spec captures contract only (behaviour,
56
+ zero-loss reference layer, and design.md states every value from them
57
+ verbatim in a fixed layout (written by `specship design extract`, never
58
+ transcribed by hand); the spec captures contract only (behaviour,
57
59
  accessibility, responsive, interaction states, data shape).
58
60
 
59
61
  There are two import shapes — exactly one source input is non-empty:
@@ -73,6 +75,7 @@ nodes:
73
75
  allowed_tools:
74
76
  - Read
75
77
  - Write
78
+ - Edit
76
79
  - Bash
77
80
  - mcp__specship__specship_explore
78
81
  - mcp__specship__specship_search
@@ -160,7 +163,29 @@ nodes:
160
163
 
161
164
  ── BOTH BRANCHES ──
162
165
 
163
- 4. Extract CSS custom properties + literal token-like values
166
+ 4. Write the pixel-exact design reference (DESIGNMD-DOC). The values
167
+ come from the extractor, never from you:
168
+
169
+ specship design extract specs/$INPUT.SLUG/snapshot.html \
170
+ --out specs/$INPUT.SLUG/design.md --title "$INPUT.FILE_LABEL"
171
+
172
+ (If design.md already exists from an earlier import, use
173
+ `--update specs/$INPUT.SLUG/design.md` instead of `--out`.)
174
+ If the generated block reports a "Missing linked stylesheet",
175
+ copy that file next to the snapshot and re-run with `--update`.
176
+ Then fill design.md's authored sections — Screens & layout,
177
+ Components & states, Interactions & motion, Responsive behaviour,
178
+ Assets — following the design-md skill
179
+ (~/.claude/skills/design-md/SKILL.md and its
180
+ references/authored-sections.md): every value copied verbatim
181
+ from the generated block with its selector, every styled state
182
+ listed, no approximate wording. Run
183
+
184
+ specship design check specs/$INPUT.SLUG/design.md
185
+
186
+ and fix findings until it passes.
187
+
188
+ 5. Extract CSS custom properties + literal token-like values
164
189
  (colors, spacing, font sizes, radii, transitions) from the
165
190
  snapshot to `specs/$INPUT.SLUG/tokens.css`. Use
166
191
  `specship_explore` first to find the project's existing token
@@ -175,6 +200,7 @@ nodes:
175
200
  - Any visible interaction or state cues in the CSS (`:hover`,
176
201
  `:focus`, `:disabled`, `[aria-*]` selectors) the spec
177
202
  author should be aware of.
203
+ - Whether `specship design check` passes on design.md.
178
204
  - For Branch A: note that source.md carries the verbatim decision
179
205
  record — the draft step should mine it for stated behaviour.
180
206
 
@@ -196,6 +222,7 @@ nodes:
196
222
  - specs/$INPUT.SLUG/snapshot.html (visual + structural source)
197
223
  - specs/$INPUT.SLUG/tokens.css (design tokens)
198
224
  - specs/$INPUT.SLUG/source.md (audit record)
225
+ - specs/$INPUT.SLUG/design.md (pixel-exact design reference)
199
226
 
200
227
  Spec scope: $INPUT.FILE_LABEL component(s).
201
228
  Optional inputs: owner=$INPUT.OWNER priority=$INPUT.PRIORITY
@@ -236,6 +263,7 @@ nodes:
236
263
  source: specs/<SLUG>/source.md
237
264
  snapshot: specs/<SLUG>/snapshot.html
238
265
  tokens: specs/<SLUG>/tokens.css
266
+ design: specs/<SLUG>/design.md
239
267
  ---
240
268
  ```
241
269
 
@@ -257,18 +285,17 @@ nodes:
257
285
  $draft_spec.output
258
286
  capture_response: true
259
287
  on_reject:
288
+ # The reviewer's rejection reason is appended automatically.
260
289
  prompt: |
261
- The draft was rejected with this feedback. Revise the spec
290
+ The draft was rejected (feedback follows). Revise the spec
262
291
  per the feedback; keep ALL existing REQ IDs stable so any
263
292
  downstream tracking survives the rewrite.
264
293
 
265
- Feedback:
266
- $gap_review.output
267
-
268
294
  Current draft:
269
295
  $draft_spec.output
270
296
 
271
297
  Output the revised draft.
298
+ revises: draft_spec
272
299
  max_attempts: 3
273
300
 
274
301
  - id: write_spec
@@ -323,14 +350,15 @@ nodes:
323
350
  1. The path of the spec file: `specs/$INPUT.SLUG.md`.
324
351
  2. The full list of REQ IDs the spec defines, one per line.
325
352
  3. The reference files the implementation phase should read:
353
+ - specs/$INPUT.SLUG/design.md (read first: every value verbatim)
326
354
  - specs/$INPUT.SLUG/snapshot.html
327
355
  - specs/$INPUT.SLUG/tokens.css
328
356
  - specs/$INPUT.SLUG/source.md
329
357
  4. The exact next command:
330
358
  /specship:spec implement <first REQ ID>
331
- 5. A one-line reminder that the implementation step should
332
- load the snapshot for visual fidelity — the spec covers
333
- contract only.
359
+ 5. A one-line reminder that the implementation step builds the UI
360
+ from design.md (values verbatim) — the spec covers contract
361
+ only.
334
362
 
335
363
  Keep the message ≤200 words. The user is about to switch from
336
364
  this workflow to the implement workflow; this is the bridge.
@@ -111,13 +111,15 @@ nodes:
111
111
  [the agent fills these in based on the draft above]
112
112
  capture_response: true
113
113
  on_reject:
114
+ # The reviewer's rejection reason is appended automatically.
114
115
  prompt: |
115
- The draft was rejected with this feedback. Revise the draft to
116
+ The draft was rejected (feedback follows). Revise the draft to
116
117
  address it. Keep all existing IDs stable so any pre-existing links
117
- survive.
118
+ survive. Output the full revised draft.
118
119
 
119
- Feedback:
120
- $gap_review.output
120
+ Current draft:
121
+ $draft.output
122
+ revises: draft
121
123
  max_attempts: 3
122
124
 
123
125
  - id: incorporate
@@ -177,15 +179,15 @@ nodes:
177
179
  $incorporate.output
178
180
  capture_response: true
179
181
  on_reject:
182
+ # The reviewer's rejection reason is appended automatically.
180
183
  prompt: |
181
- Final approval was rejected. Revise the draft per the feedback,
182
- re-run the quality review pass, and produce a new draft.
183
-
184
- Feedback:
185
- $finalize.output
184
+ Final approval was rejected (feedback follows). Revise the draft
185
+ per the feedback, re-run the quality review pass, and output the
186
+ full revised draft.
186
187
 
187
188
  Current draft:
188
189
  $incorporate.output
190
+ revises: incorporate
189
191
  max_attempts: 2
190
192
 
191
193
  - id: write_file