@specship/specship-win32-arm64 0.25.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 (274) 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 +762 -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 +12 -0
  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/enforce/changed-files.d.ts +11 -0
  35. package/lib/dist/enforce/changed-files.d.ts.map +1 -1
  36. package/lib/dist/enforce/changed-files.js +42 -0
  37. package/lib/dist/enforce/changed-files.js.map +1 -1
  38. package/lib/dist/enforce/enforce.d.ts +25 -1
  39. package/lib/dist/enforce/enforce.d.ts.map +1 -1
  40. package/lib/dist/enforce/enforce.js +58 -3
  41. package/lib/dist/enforce/enforce.js.map +1 -1
  42. package/lib/dist/enforce/mutation.d.ts +46 -0
  43. package/lib/dist/enforce/mutation.d.ts.map +1 -0
  44. package/lib/dist/enforce/mutation.js +104 -0
  45. package/lib/dist/enforce/mutation.js.map +1 -0
  46. package/lib/dist/enforce/suppressions.d.ts +33 -0
  47. package/lib/dist/enforce/suppressions.d.ts.map +1 -0
  48. package/lib/dist/enforce/suppressions.js +159 -0
  49. package/lib/dist/enforce/suppressions.js.map +1 -0
  50. package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -1
  51. package/lib/dist/extraction/specs/markdown-spec-extractor.js +16 -2
  52. package/lib/dist/extraction/specs/markdown-spec-extractor.js.map +1 -1
  53. package/lib/dist/graph/spec-coverage.d.ts +57 -1
  54. package/lib/dist/graph/spec-coverage.d.ts.map +1 -1
  55. package/lib/dist/graph/spec-coverage.js +129 -5
  56. package/lib/dist/graph/spec-coverage.js.map +1 -1
  57. package/lib/dist/health/smoke-check.js +2 -2
  58. package/lib/dist/health/smoke-check.js.map +1 -1
  59. package/lib/dist/index.d.ts +8 -3
  60. package/lib/dist/index.d.ts.map +1 -1
  61. package/lib/dist/index.js +65 -9
  62. package/lib/dist/index.js.map +1 -1
  63. package/lib/dist/installer/gemini-commands.d.ts +107 -0
  64. package/lib/dist/installer/gemini-commands.d.ts.map +1 -0
  65. package/lib/dist/installer/gemini-commands.js +264 -0
  66. package/lib/dist/installer/gemini-commands.js.map +1 -0
  67. package/lib/dist/installer/index.d.ts +23 -1
  68. package/lib/dist/installer/index.d.ts.map +1 -1
  69. package/lib/dist/installer/index.js +22 -3
  70. package/lib/dist/installer/index.js.map +1 -1
  71. package/lib/dist/installer/install-defaults.d.ts +19 -0
  72. package/lib/dist/installer/install-defaults.d.ts.map +1 -1
  73. package/lib/dist/installer/install-defaults.js +28 -0
  74. package/lib/dist/installer/install-defaults.js.map +1 -1
  75. package/lib/dist/installer/instructions-template.d.ts +22 -0
  76. package/lib/dist/installer/instructions-template.d.ts.map +1 -1
  77. package/lib/dist/installer/instructions-template.js +37 -1
  78. package/lib/dist/installer/instructions-template.js.map +1 -1
  79. package/lib/dist/installer/targets/claude.d.ts +4 -0
  80. package/lib/dist/installer/targets/claude.d.ts.map +1 -1
  81. package/lib/dist/installer/targets/claude.js +8 -25
  82. package/lib/dist/installer/targets/claude.js.map +1 -1
  83. package/lib/dist/installer/targets/gemini.d.ts +85 -12
  84. package/lib/dist/installer/targets/gemini.d.ts.map +1 -1
  85. package/lib/dist/installer/targets/gemini.js +527 -30
  86. package/lib/dist/installer/targets/gemini.js.map +1 -1
  87. package/lib/dist/installer/targets/shared.d.ts +13 -0
  88. package/lib/dist/installer/targets/shared.d.ts.map +1 -1
  89. package/lib/dist/installer/targets/shared.js +18 -0
  90. package/lib/dist/installer/targets/shared.js.map +1 -1
  91. package/lib/dist/installer/targets/types.d.ts +12 -0
  92. package/lib/dist/installer/targets/types.d.ts.map +1 -1
  93. package/lib/dist/jira/auto-publish.d.ts +71 -4
  94. package/lib/dist/jira/auto-publish.d.ts.map +1 -1
  95. package/lib/dist/jira/auto-publish.js +186 -17
  96. package/lib/dist/jira/auto-publish.js.map +1 -1
  97. package/lib/dist/jira/reconcile.d.ts +24 -1
  98. package/lib/dist/jira/reconcile.d.ts.map +1 -1
  99. package/lib/dist/jira/reconcile.js +46 -2
  100. package/lib/dist/jira/reconcile.js.map +1 -1
  101. package/lib/dist/jira/repo-config.d.ts +9 -0
  102. package/lib/dist/jira/repo-config.d.ts.map +1 -1
  103. package/lib/dist/jira/repo-config.js +11 -0
  104. package/lib/dist/jira/repo-config.js.map +1 -1
  105. package/lib/dist/jira/types.d.ts +7 -0
  106. package/lib/dist/jira/types.d.ts.map +1 -1
  107. package/lib/dist/jira/types.js.map +1 -1
  108. package/lib/dist/knowledge/enforce.d.ts +75 -0
  109. package/lib/dist/knowledge/enforce.d.ts.map +1 -0
  110. package/lib/dist/knowledge/enforce.js +250 -0
  111. package/lib/dist/knowledge/enforce.js.map +1 -0
  112. package/lib/dist/knowledge/facts.d.ts +33 -0
  113. package/lib/dist/knowledge/facts.d.ts.map +1 -0
  114. package/lib/dist/knowledge/facts.js +117 -0
  115. package/lib/dist/knowledge/facts.js.map +1 -0
  116. package/lib/dist/knowledge/proposals.d.ts +88 -0
  117. package/lib/dist/knowledge/proposals.d.ts.map +1 -0
  118. package/lib/dist/knowledge/proposals.js +360 -0
  119. package/lib/dist/knowledge/proposals.js.map +1 -0
  120. package/lib/dist/knowledge/stale.d.ts +64 -0
  121. package/lib/dist/knowledge/stale.d.ts.map +1 -0
  122. package/lib/dist/knowledge/stale.js +174 -0
  123. package/lib/dist/knowledge/stale.js.map +1 -0
  124. package/lib/dist/mcp/gemini-session.d.ts +50 -0
  125. package/lib/dist/mcp/gemini-session.d.ts.map +1 -0
  126. package/lib/dist/mcp/gemini-session.js +159 -0
  127. package/lib/dist/mcp/gemini-session.js.map +1 -0
  128. package/lib/dist/mcp/jira-tools.d.ts.map +1 -1
  129. package/lib/dist/mcp/jira-tools.js +25 -0
  130. package/lib/dist/mcp/jira-tools.js.map +1 -1
  131. package/lib/dist/mcp/model-context.d.ts +22 -9
  132. package/lib/dist/mcp/model-context.d.ts.map +1 -1
  133. package/lib/dist/mcp/model-context.js +35 -13
  134. package/lib/dist/mcp/model-context.js.map +1 -1
  135. package/lib/dist/mcp/proxy.js +1 -1
  136. package/lib/dist/mcp/proxy.js.map +1 -1
  137. package/lib/dist/mcp/server-instructions.d.ts +16 -15
  138. package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
  139. package/lib/dist/mcp/server-instructions.js +67 -1
  140. package/lib/dist/mcp/server-instructions.js.map +1 -1
  141. package/lib/dist/mcp/session.js +1 -1
  142. package/lib/dist/mcp/session.js.map +1 -1
  143. package/lib/dist/mcp/spec-tools.d.ts +9 -1
  144. package/lib/dist/mcp/spec-tools.d.ts.map +1 -1
  145. package/lib/dist/mcp/spec-tools.js +69 -21
  146. package/lib/dist/mcp/spec-tools.js.map +1 -1
  147. package/lib/dist/mcp/tools.d.ts +37 -1
  148. package/lib/dist/mcp/tools.d.ts.map +1 -1
  149. package/lib/dist/mcp/tools.js +120 -9
  150. package/lib/dist/mcp/tools.js.map +1 -1
  151. package/lib/dist/pulse/pulse.d.ts +93 -0
  152. package/lib/dist/pulse/pulse.d.ts.map +1 -0
  153. package/lib/dist/pulse/pulse.js +401 -0
  154. package/lib/dist/pulse/pulse.js.map +1 -0
  155. package/lib/dist/reflect/apply.d.ts.map +1 -1
  156. package/lib/dist/reflect/apply.js +38 -3
  157. package/lib/dist/reflect/apply.js.map +1 -1
  158. package/lib/dist/reflect/auto-sweep.d.ts +26 -0
  159. package/lib/dist/reflect/auto-sweep.d.ts.map +1 -0
  160. package/lib/dist/reflect/auto-sweep.js +90 -0
  161. package/lib/dist/reflect/auto-sweep.js.map +1 -0
  162. package/lib/dist/reflect/cli.d.ts +62 -0
  163. package/lib/dist/reflect/cli.d.ts.map +1 -0
  164. package/lib/dist/reflect/cli.js +163 -0
  165. package/lib/dist/reflect/cli.js.map +1 -0
  166. package/lib/dist/reflect/miner.d.ts.map +1 -1
  167. package/lib/dist/reflect/miner.js +119 -0
  168. package/lib/dist/reflect/miner.js.map +1 -1
  169. package/lib/dist/reflect/sweep.d.ts +1 -0
  170. package/lib/dist/reflect/sweep.d.ts.map +1 -1
  171. package/lib/dist/reflect/sweep.js +62 -13
  172. package/lib/dist/reflect/sweep.js.map +1 -1
  173. package/lib/dist/reflect/targets.d.ts +2 -0
  174. package/lib/dist/reflect/targets.d.ts.map +1 -1
  175. package/lib/dist/reflect/targets.js +33 -0
  176. package/lib/dist/reflect/targets.js.map +1 -1
  177. package/lib/dist/reflect/types.d.ts +19 -2
  178. package/lib/dist/reflect/types.d.ts.map +1 -1
  179. package/lib/dist/resolution/test-title-links.d.ts.map +1 -1
  180. package/lib/dist/resolution/test-title-links.js +3 -14
  181. package/lib/dist/resolution/test-title-links.js.map +1 -1
  182. package/lib/dist/server/routes/claude.js +15 -7
  183. package/lib/dist/server/routes/knowledge.js +118 -0
  184. package/lib/dist/server/server.js +2 -0
  185. package/lib/dist/spec-lint/lint.d.ts +1 -1
  186. package/lib/dist/spec-lint/lint.d.ts.map +1 -1
  187. package/lib/dist/spec-lint/lint.js +63 -2
  188. package/lib/dist/spec-lint/lint.js.map +1 -1
  189. package/lib/dist/spec-quality/criterion-ids.d.ts +13 -0
  190. package/lib/dist/spec-quality/criterion-ids.d.ts.map +1 -0
  191. package/lib/dist/spec-quality/criterion-ids.js +38 -0
  192. package/lib/dist/spec-quality/criterion-ids.js.map +1 -0
  193. package/lib/dist/spec-quality/evidence-kind.d.ts +54 -0
  194. package/lib/dist/spec-quality/evidence-kind.d.ts.map +1 -0
  195. package/lib/dist/spec-quality/evidence-kind.js +183 -0
  196. package/lib/dist/spec-quality/evidence-kind.js.map +1 -0
  197. package/lib/dist/spec-quality/link-persist.d.ts +65 -0
  198. package/lib/dist/spec-quality/link-persist.d.ts.map +1 -0
  199. package/lib/dist/spec-quality/link-persist.js +249 -0
  200. package/lib/dist/spec-quality/link-persist.js.map +1 -0
  201. package/lib/dist/spec-quality/plan-scope.d.ts +38 -0
  202. package/lib/dist/spec-quality/plan-scope.d.ts.map +1 -0
  203. package/lib/dist/spec-quality/plan-scope.js +129 -0
  204. package/lib/dist/spec-quality/plan-scope.js.map +1 -0
  205. package/lib/dist/spec-quality/postcheck.d.ts +85 -0
  206. package/lib/dist/spec-quality/postcheck.d.ts.map +1 -0
  207. package/lib/dist/spec-quality/postcheck.js +390 -0
  208. package/lib/dist/spec-quality/postcheck.js.map +1 -0
  209. package/lib/dist/spec-quality/readiness.d.ts +72 -0
  210. package/lib/dist/spec-quality/readiness.d.ts.map +1 -0
  211. package/lib/dist/spec-quality/readiness.js +226 -0
  212. package/lib/dist/spec-quality/readiness.js.map +1 -0
  213. package/lib/dist/workflows/agents/claude.d.ts +16 -0
  214. package/lib/dist/workflows/agents/claude.d.ts.map +1 -0
  215. package/lib/dist/workflows/agents/claude.js +82 -0
  216. package/lib/dist/workflows/agents/claude.js.map +1 -0
  217. package/lib/dist/workflows/agents/gemini.d.ts +21 -0
  218. package/lib/dist/workflows/agents/gemini.d.ts.map +1 -0
  219. package/lib/dist/workflows/agents/gemini.js +124 -0
  220. package/lib/dist/workflows/agents/gemini.js.map +1 -0
  221. package/lib/dist/workflows/agents/index.d.ts +28 -0
  222. package/lib/dist/workflows/agents/index.d.ts.map +1 -0
  223. package/lib/dist/workflows/agents/index.js +104 -0
  224. package/lib/dist/workflows/agents/index.js.map +1 -0
  225. package/lib/dist/workflows/agents/types.d.ts +55 -0
  226. package/lib/dist/workflows/agents/types.d.ts.map +1 -0
  227. package/lib/dist/workflows/agents/types.js +46 -0
  228. package/lib/dist/workflows/agents/types.js.map +1 -0
  229. package/lib/dist/workflows/batch.d.ts +63 -0
  230. package/lib/dist/workflows/batch.d.ts.map +1 -0
  231. package/lib/dist/workflows/batch.js +151 -0
  232. package/lib/dist/workflows/batch.js.map +1 -0
  233. package/lib/dist/workflows/defaults/claude-design-implement.yaml +3 -4
  234. package/lib/dist/workflows/defaults/spec-author.yaml +11 -9
  235. package/lib/dist/workflows/defaults/spec-implement-mixed.yaml +21 -436
  236. package/lib/dist/workflows/defaults/spec-implement.yaml +465 -46
  237. package/lib/dist/workflows/discovery.d.ts +13 -0
  238. package/lib/dist/workflows/discovery.d.ts.map +1 -1
  239. package/lib/dist/workflows/discovery.js +79 -17
  240. package/lib/dist/workflows/discovery.js.map +1 -1
  241. package/lib/dist/workflows/executor.d.ts +18 -0
  242. package/lib/dist/workflows/executor.d.ts.map +1 -1
  243. package/lib/dist/workflows/executor.js +130 -33
  244. package/lib/dist/workflows/executor.js.map +1 -1
  245. package/lib/dist/workflows/gc.d.ts +50 -0
  246. package/lib/dist/workflows/gc.d.ts.map +1 -0
  247. package/lib/dist/workflows/gc.js +120 -0
  248. package/lib/dist/workflows/gc.js.map +1 -0
  249. package/lib/dist/workflows/merge-queue.d.ts +64 -0
  250. package/lib/dist/workflows/merge-queue.d.ts.map +1 -0
  251. package/lib/dist/workflows/merge-queue.js +162 -0
  252. package/lib/dist/workflows/merge-queue.js.map +1 -0
  253. package/lib/dist/workflows/runners/approval.d.ts +1 -1
  254. package/lib/dist/workflows/runners/approval.d.ts.map +1 -1
  255. package/lib/dist/workflows/runners/approval.js +11 -2
  256. package/lib/dist/workflows/runners/approval.js.map +1 -1
  257. package/lib/dist/workflows/runners/bash.d.ts +15 -0
  258. package/lib/dist/workflows/runners/bash.d.ts.map +1 -1
  259. package/lib/dist/workflows/runners/bash.js +50 -1
  260. package/lib/dist/workflows/runners/bash.js.map +1 -1
  261. package/lib/dist/workflows/runners/prompt.d.ts +16 -41
  262. package/lib/dist/workflows/runners/prompt.d.ts.map +1 -1
  263. package/lib/dist/workflows/runners/prompt.js +55 -120
  264. package/lib/dist/workflows/runners/prompt.js.map +1 -1
  265. package/lib/dist/workflows/runners/types.d.ts +12 -0
  266. package/lib/dist/workflows/runners/types.d.ts.map +1 -1
  267. package/lib/dist/workflows/schemas/workflow.d.ts +17 -0
  268. package/lib/dist/workflows/schemas/workflow.d.ts.map +1 -1
  269. package/lib/dist/workflows/schemas/workflow.js +27 -0
  270. package/lib/dist/workflows/schemas/workflow.js.map +1 -1
  271. package/lib/node_modules/.package-lock.json +1 -1
  272. package/lib/package.json +2 -2
  273. package/package.json +5 -3
  274. package/node.exe +0 -4
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ /**
3
+ * Spec readiness gate (PIPETRUST-DOC, REQ-PIPETRUST-004).
4
+ *
5
+ * Implement must not start on a spec that cannot be implemented to a
6
+ * verifiable result. A requirement is READY when its spec file lints without
7
+ * errors, it has at least one acceptance criterion, and no criterion still
8
+ * carries a `[needs review]` marker. A ready requirement also yields an
9
+ * EVIDENCE PLAN — one line per criterion with the evidence kind it requires
10
+ * (REQ-PIPETRUST-001) and a suggested named test function — which the
11
+ * implement workflows hand to their plan and implement steps so "untested"
12
+ * can never be planned in.
13
+ *
14
+ * Pure core (`assessReadiness`) over plain inputs, plus a thin loader
15
+ * (`assessReadinessFromIndex`) that reads them from a SpecShip index.
16
+ */
17
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ var desc = Object.getOwnPropertyDescriptor(m, k);
20
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
+ desc = { enumerable: true, get: function() { return m[k]; } };
22
+ }
23
+ Object.defineProperty(o, k2, desc);
24
+ }) : (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ o[k2] = m[k];
27
+ }));
28
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
30
+ }) : function(o, v) {
31
+ o["default"] = v;
32
+ });
33
+ var __importStar = (this && this.__importStar) || (function () {
34
+ var ownKeys = function(o) {
35
+ ownKeys = Object.getOwnPropertyNames || function (o) {
36
+ var ar = [];
37
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
38
+ return ar;
39
+ };
40
+ return ownKeys(o);
41
+ };
42
+ return function (mod) {
43
+ if (mod && mod.__esModule) return mod;
44
+ var result = {};
45
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
46
+ __setModuleDefault(result, mod);
47
+ return result;
48
+ };
49
+ })();
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.suggestedTestName = suggestedTestName;
52
+ exports.assessReadiness = assessReadiness;
53
+ exports.formatEvidencePlan = formatEvidencePlan;
54
+ exports.assessReadinessFromIndex = assessReadinessFromIndex;
55
+ exports.criteriaFromBlock = criteriaFromBlock;
56
+ exports.assessReadinessFromFile = assessReadinessFromFile;
57
+ const fs = __importStar(require("fs"));
58
+ const path = __importStar(require("path"));
59
+ const lint_1 = require("../spec-lint/lint");
60
+ const evidence_kind_1 = require("./evidence-kind");
61
+ const postcheck_1 = require("./postcheck");
62
+ /** UI source files — same rule the behaviour surface uses for Playwright targets. */
63
+ const UI_FILE = /\.(tsx|jsx|vue|svelte|astro)$/i;
64
+ const NEEDS_REVIEW = /\[needs review/i;
65
+ /** Criterion bullet text as stored by the extractor (title, falling back to body). */
66
+ function criterionText(c) {
67
+ return (c.title && c.title.trim()) || (c.body ?? '').trim();
68
+ }
69
+ /**
70
+ * Deterministic test-function name for a criterion id:
71
+ * `REQ-PIPETRUST-004.A1` → `reqPipetrust004A1`. Authors are expected to rename
72
+ * it to describe the behaviour; it exists so the plan names a real symbol.
73
+ */
74
+ function suggestedTestName(criterionId) {
75
+ const parts = criterionId.split(/[^A-Za-z0-9]+/).filter(Boolean);
76
+ return parts
77
+ .map((p, i) => {
78
+ const lower = p.toLowerCase();
79
+ return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
80
+ })
81
+ .join('');
82
+ }
83
+ function assessReadiness(input) {
84
+ const { requirementId, requirement, criteria, implementsLinks, lintFindings } = input;
85
+ const reasons = [];
86
+ if (!requirement) {
87
+ return { requirementId, ready: false, reasons: [`no spec with id ${requirementId}`], plan: [] };
88
+ }
89
+ const lintErrors = lintFindings.filter((f) => f.severity === 'error');
90
+ for (const f of lintErrors) {
91
+ reasons.push(`lint error ${f.code}${f.line ? ` (line ${f.line})` : ''}: ${f.message}`);
92
+ }
93
+ if (criteria.length === 0) {
94
+ reasons.push(`${requirementId} has no acceptance criteria`);
95
+ }
96
+ for (const c of criteria) {
97
+ if (NEEDS_REVIEW.test(criterionText(c)) || NEEDS_REVIEW.test(c.body ?? '')) {
98
+ reasons.push(`${c.id} still carries [needs review]`);
99
+ }
100
+ }
101
+ const linksUi = implementsLinks.some((l) => UI_FILE.test(l.targetFilePath));
102
+ const linksRoute = implementsLinks.some((l) => l.targetNodeKind === 'route');
103
+ const plan = criteria.map((c) => ({
104
+ criterionId: c.id,
105
+ text: criterionText(c),
106
+ kind: (0, evidence_kind_1.requiredEvidenceKind)(criterionText(c), { linksUi, linksRoute }),
107
+ testName: suggestedTestName(c.id),
108
+ }));
109
+ return { requirementId, ready: reasons.length === 0, reasons, plan };
110
+ }
111
+ /** Human / prompt-facing rendering. The READY marker is the machine contract. */
112
+ function formatEvidencePlan(result) {
113
+ const lines = [];
114
+ if (result.ready) {
115
+ lines.push(`READY=yes ${result.requirementId}`);
116
+ lines.push('Evidence plan (criterion → required evidence kind → suggested test function):');
117
+ for (const p of result.plan) {
118
+ lines.push(`- ${p.criterionId} → ${p.kind} → ${p.testName} — ${p.text}`);
119
+ }
120
+ lines.push('Write each test as a NAMED function passed to it(), put the criterion id in the it() title, ' +
121
+ 'and list it under the requirement\'s `verifies:` block.');
122
+ }
123
+ else {
124
+ lines.push(`READY=no ${result.requirementId}`);
125
+ for (const r of result.reasons)
126
+ lines.push(`- ${r}`);
127
+ }
128
+ return lines.join('\n');
129
+ }
130
+ /** Load the inputs for `assessReadiness` from an index and the spec file on disk. */
131
+ function assessReadinessFromIndex(sq, projectRoot, requirementId) {
132
+ const requirement = sq.getSpecById(requirementId);
133
+ if (!requirement) {
134
+ return assessReadiness({ requirementId, requirement: null, criteria: [], implementsLinks: [], lintFindings: [] });
135
+ }
136
+ const criteria = sq.getSpecsByParent(requirementId).filter((s) => s.kind === 'acceptance');
137
+ const implementsLinks = [requirementId, ...criteria.map((c) => c.id)]
138
+ .flatMap((id) => sq.getLinksBySpec(id))
139
+ .filter((l) => l.kind === 'implements');
140
+ let lintFindings = [];
141
+ const abs = path.isAbsolute(requirement.sourcePath)
142
+ ? requirement.sourcePath
143
+ : path.join(projectRoot, requirement.sourcePath);
144
+ try {
145
+ lintFindings = (0, lint_1.lintSpecSource)(requirement.sourcePath, fs.readFileSync(abs, 'utf-8'));
146
+ }
147
+ catch (err) {
148
+ lintFindings = [
149
+ {
150
+ code: 'lint_unreadable_file',
151
+ severity: 'error',
152
+ filePath: requirement.sourcePath,
153
+ message: `Could not read: ${err instanceof Error ? err.message : String(err)}`,
154
+ },
155
+ ];
156
+ }
157
+ // Only findings about THIS requirement (or file-level ones) gate it — a
158
+ // sibling requirement's lint error must not block an unrelated implement.
159
+ const ownIds = new Set([requirementId, ...criteria.map((c) => c.id)]);
160
+ lintFindings = lintFindings.filter((f) => !f.specId || ownIds.has(f.specId));
161
+ return assessReadiness({ requirementId, requirement, criteria, implementsLinks, lintFindings });
162
+ }
163
+ const ID_MARKER = /^<!--\s*id:\s*([A-Za-z0-9._-]+)\s*-->\s*$/;
164
+ /** Acceptance bullets (id → text) read straight from a requirement block. */
165
+ function criteriaFromBlock(block, requirementId) {
166
+ const lines = block.split(/\r?\n/);
167
+ const out = [];
168
+ for (let i = 0; i < lines.length; i++) {
169
+ const m = (lines[i] ?? '').match(ID_MARKER);
170
+ if (!m || !m[1].startsWith(`${requirementId}.A`))
171
+ continue;
172
+ const text = [];
173
+ for (let j = i + 1; j < lines.length; j++) {
174
+ const line = lines[j] ?? '';
175
+ if (ID_MARKER.test(line) || /^#{1,6}\s/.test(line) || (line.trim() === '' && text.length > 0))
176
+ break;
177
+ if (line.trim() === '')
178
+ continue;
179
+ text.push(line.replace(/^\s*-\s+/, '').trim());
180
+ }
181
+ out.push({ id: m[1], text: text.join(' ') });
182
+ }
183
+ return out;
184
+ }
185
+ /**
186
+ * File-based readiness: works without a SpecShip index (a workflow worktree
187
+ * has none — and a CLI with no project index must never walk up to $HOME).
188
+ * UI linkage comes from the `implementations:` bullets' file extensions;
189
+ * route linkage needs the index, so it is only known when `routeTargets`
190
+ * is supplied by an index-backed caller.
191
+ */
192
+ function assessReadinessFromFile(projectRoot, requirementId, routeTargets = new Set()) {
193
+ const specFile = (0, postcheck_1.findSpecFile)(projectRoot, requirementId);
194
+ const source = specFile ? fs.readFileSync(specFile, 'utf-8') : null;
195
+ const block = source ? (0, postcheck_1.requirementBlock)(source, requirementId) : null;
196
+ if (!specFile || !source || !block) {
197
+ return assessReadiness({ requirementId, requirement: null, criteria: [], implementsLinks: [], lintFindings: [] });
198
+ }
199
+ const rel = path.relative(projectRoot, specFile);
200
+ const now = Date.now();
201
+ const asSpec = (id, title, kind) => ({
202
+ id, kind, title, body: title, format: 'markdown', sourcePath: rel, contentHash: '', createdAt: now, updatedAt: now,
203
+ });
204
+ const criteria = criteriaFromBlock(block, requirementId).map((c) => asSpec(c.id, c.text, 'acceptance'));
205
+ const implementsLinks = (0, postcheck_1.linkBullets)(block, 'implementations').map((b) => {
206
+ const idx = b.lastIndexOf(':');
207
+ const file = idx > 0 ? b.slice(0, idx) : b;
208
+ const symbol = idx > 0 ? b.slice(idx + 1) : '';
209
+ return {
210
+ targetFilePath: file,
211
+ targetQualifiedName: symbol,
212
+ targetNodeKind: routeTargets.has(`${file}:${symbol}`) ? 'route' : 'function',
213
+ kind: 'implements',
214
+ };
215
+ });
216
+ const ownIds = new Set([requirementId, ...criteria.map((c) => c.id)]);
217
+ const lintFindings = (0, lint_1.lintSpecSource)(rel, source).filter((f) => !f.specId || ownIds.has(f.specId));
218
+ return assessReadiness({
219
+ requirementId,
220
+ requirement: asSpec(requirementId, requirementId, 'requirement'),
221
+ criteria,
222
+ implementsLinks,
223
+ lintFindings,
224
+ });
225
+ }
226
+ //# sourceMappingURL=readiness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readiness.js","sourceRoot":"","sources":["../../src/spec-quality/readiness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Claude Code headless adapter (REQ-AGENTADAPT-005): `claude --print` with
3
+ * stream-json output. The argument list is exactly what the prompt runner
4
+ * built before adapters existed (REQ-AGENTADAPT-005.A1).
5
+ */
6
+ import type { PromptNode } from '../schemas/workflow';
7
+ import { EmitFn, HeadlessAgent, StreamParseState } from './types';
8
+ export declare function buildClaudeArgs(node: PromptNode): string[];
9
+ /**
10
+ * Parse one stream-json line, emit any activity events, and fold the result
11
+ * into `state`. Pure aside from the `emit` callback. Unknown / non-JSON lines
12
+ * are ignored. Extended-thinking blocks are intentionally NOT emitted.
13
+ */
14
+ export declare function handleClaudeStreamLine(line: string, emit: EmitFn, state: StreamParseState): void;
15
+ export declare const claudeHeadlessAgent: HeadlessAgent;
16
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/workflows/agents/claude.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAsB,gBAAgB,EAAqC,MAAM,SAAS,CAAC;AAEzH,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,EAAE,CAkB1D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CA4BhG;AAED,eAAO,MAAM,mBAAmB,EAAE,aAQjC,CAAC"}
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ /**
3
+ * Claude Code headless adapter (REQ-AGENTADAPT-005): `claude --print` with
4
+ * stream-json output. The argument list is exactly what the prompt runner
5
+ * built before adapters existed (REQ-AGENTADAPT-005.A1).
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.claudeHeadlessAgent = void 0;
9
+ exports.buildClaudeArgs = buildClaudeArgs;
10
+ exports.handleClaudeStreamLine = handleClaudeStreamLine;
11
+ const types_1 = require("./types");
12
+ function buildClaudeArgs(node) {
13
+ const args = [];
14
+ args.push('--print');
15
+ // Stream the agent's activity as JSONL so we can surface tool calls and
16
+ // messages live. `--print` + `--output-format stream-json` requires
17
+ // `--verbose` (the CLI rejects the combination otherwise).
18
+ args.push('--output-format', 'stream-json', '--verbose');
19
+ if (node.model)
20
+ args.push('--model', node.model);
21
+ if (node.allowed_tools && node.allowed_tools.length > 0) {
22
+ args.push('--allowed-tools', node.allowed_tools.join(','));
23
+ }
24
+ if (node.denied_tools && node.denied_tools.length > 0) {
25
+ args.push('--disallowed-tools', node.denied_tools.join(','));
26
+ }
27
+ if (node.systemPromptAppend) {
28
+ args.push('--append-system-prompt', node.systemPromptAppend);
29
+ }
30
+ return args;
31
+ }
32
+ /**
33
+ * Parse one stream-json line, emit any activity events, and fold the result
34
+ * into `state`. Pure aside from the `emit` callback. Unknown / non-JSON lines
35
+ * are ignored. Extended-thinking blocks are intentionally NOT emitted.
36
+ */
37
+ function handleClaudeStreamLine(line, emit, state) {
38
+ const e = (0, types_1.parseJsonLine)(line);
39
+ if (!e)
40
+ return;
41
+ if (e.type === 'assistant' && e.message && typeof e.message === 'object') {
42
+ state.sawStream = true;
43
+ const content = e.message.content;
44
+ if (Array.isArray(content)) {
45
+ for (const raw of content) {
46
+ const b = raw;
47
+ if (b?.type === 'tool_use') {
48
+ emit('tool_called', { name: b.name, input: (0, types_1.summarizeToolInput)(b.input) });
49
+ }
50
+ else if (b?.type === 'text' && typeof b.text === 'string' && b.text.trim()) {
51
+ state.assistantText += (state.assistantText ? '\n' : '') + b.text;
52
+ emit('agent_message', { text: b.text });
53
+ }
54
+ // 'thinking' blocks: deliberately skipped.
55
+ }
56
+ }
57
+ }
58
+ else if (e.type === 'result') {
59
+ state.sawStream = true;
60
+ if (typeof e.result === 'string')
61
+ state.resultText = e.result;
62
+ if (typeof e.total_cost_usd === 'number')
63
+ state.costUsd = e.total_cost_usd;
64
+ if (typeof e.duration_ms === 'number')
65
+ state.durationMs = e.duration_ms;
66
+ }
67
+ else if (e.type === 'system') {
68
+ state.sawStream = true; // init/system frame — confirms we're on the stream path
69
+ if (typeof e.model === 'string' && e.model)
70
+ state.model = e.model;
71
+ }
72
+ }
73
+ exports.claudeHeadlessAgent = {
74
+ id: 'claude',
75
+ // Claude Code sets CLAUDECODE=1 in the environment of the commands it runs.
76
+ launchedFrom: (env) => env.CLAUDECODE === '1',
77
+ build(node, _config, env) {
78
+ return { bin: env.SPECSHIP_CLAUDE_BIN ?? 'claude', args: buildClaudeArgs(node), stdin: node.prompt };
79
+ },
80
+ handleLine: handleClaudeStreamLine,
81
+ };
82
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/workflows/agents/claude.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Gemini CLI headless adapter (REQ-AGENTADAPT-007), against the installed
3
+ * 0.28.0 source (DOM-SPECSHIP-008): piped stdin runs Gemini headless, and in
4
+ * that mode every approval-needing tool not in `--allowed-tools` is removed,
5
+ * so each step's tools are translated to Gemini's names. There is no deny or
6
+ * append-system-prompt flag: `denied_tools` is refused, and the appended
7
+ * system prompt leads the stdin prompt.
8
+ */
9
+ import { EmitFn, HeadlessAgent, StreamParseState } from './types';
10
+ /** Translate a step's allowed tools, or name the first one with no Gemini equivalent. */
11
+ export declare function translateGeminiTools(tools: string[]): {
12
+ tools: string[];
13
+ } | {
14
+ error: string;
15
+ };
16
+ /** The Gemini model for a step: a mapped tier alias, a Gemini id as-is, else none (Gemini's default). */
17
+ export declare function geminiModelFor(model: string | undefined, models: Record<string, string> | undefined): string | undefined;
18
+ /** Parse one Gemini stream-json event (init / message / tool_use / error / result). */
19
+ export declare function handleGeminiStreamLine(line: string, emit: EmitFn, state: StreamParseState): void;
20
+ export declare const geminiHeadlessAgent: HeadlessAgent;
21
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../../src/workflows/agents/gemini.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,aAAa,EAAsB,gBAAgB,EAAqC,MAAM,SAAS,CAAC;AAiBzH,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAa7F;AAED,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAIxH;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAmChG;AAED,eAAO,MAAM,mBAAmB,EAAE,aAsBjC,CAAC"}
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ /**
3
+ * Gemini CLI headless adapter (REQ-AGENTADAPT-007), against the installed
4
+ * 0.28.0 source (DOM-SPECSHIP-008): piped stdin runs Gemini headless, and in
5
+ * that mode every approval-needing tool not in `--allowed-tools` is removed,
6
+ * so each step's tools are translated to Gemini's names. There is no deny or
7
+ * append-system-prompt flag: `denied_tools` is refused, and the appended
8
+ * system prompt leads the stdin prompt.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.geminiHeadlessAgent = void 0;
12
+ exports.translateGeminiTools = translateGeminiTools;
13
+ exports.geminiModelFor = geminiModelFor;
14
+ exports.handleGeminiStreamLine = handleGeminiStreamLine;
15
+ const types_1 = require("./types");
16
+ /** Claude-form built-in tool names → Gemini CLI 0.28 tool names. */
17
+ const BUILTIN_TOOLS = {
18
+ Read: 'read_file',
19
+ Write: 'write_file',
20
+ Edit: 'replace',
21
+ MultiEdit: 'replace',
22
+ Bash: 'run_shell_command',
23
+ Glob: 'glob',
24
+ Grep: 'grep_search',
25
+ LS: 'list_directory',
26
+ WebFetch: 'web_fetch',
27
+ WebSearch: 'google_web_search',
28
+ };
29
+ const MODEL_TIERS = new Set(['haiku', 'sonnet', 'opus']);
30
+ /** Translate a step's allowed tools, or name the first one with no Gemini equivalent. */
31
+ function translateGeminiTools(tools) {
32
+ const out = [];
33
+ for (const tool of tools) {
34
+ let mapped;
35
+ const mcp = tool.match(/^mcp__([A-Za-z0-9_-]+?)__(.+)$/);
36
+ const shell = tool.match(/^Bash\((.+?)(?::\*)?\)$/);
37
+ if (mcp)
38
+ mapped = `${mcp[1]}__${mcp[2]}`;
39
+ else if (shell)
40
+ mapped = `run_shell_command(${shell[1].trim()})`;
41
+ else
42
+ mapped = BUILTIN_TOOLS[tool];
43
+ if (!mapped)
44
+ return { error: `allowed tool "${tool}" has no Gemini CLI equivalent` };
45
+ if (!out.includes(mapped))
46
+ out.push(mapped);
47
+ }
48
+ return { tools: out };
49
+ }
50
+ /** The Gemini model for a step: a mapped tier alias, a Gemini id as-is, else none (Gemini's default). */
51
+ function geminiModelFor(model, models) {
52
+ if (!model)
53
+ return undefined;
54
+ if (MODEL_TIERS.has(model))
55
+ return models?.[model];
56
+ return /^gemini/i.test(model) ? model : undefined; // a Claude id is never passed to Gemini
57
+ }
58
+ /** Parse one Gemini stream-json event (init / message / tool_use / error / result). */
59
+ function handleGeminiStreamLine(line, emit, state) {
60
+ const e = (0, types_1.parseJsonLine)(line);
61
+ if (!e)
62
+ return;
63
+ switch (e.type) {
64
+ case 'init':
65
+ state.sawStream = true;
66
+ if (typeof e.model === 'string' && e.model)
67
+ state.model = e.model;
68
+ break;
69
+ case 'message':
70
+ state.sawStream = true;
71
+ if (e.role === 'assistant' && typeof e.content === 'string' && e.content) {
72
+ // Deltas are fragments of one turn; whole messages are separate turns.
73
+ state.assistantText += e.delta === true || !state.assistantText ? e.content : `\n${e.content}`;
74
+ emit('agent_message', { text: e.content });
75
+ }
76
+ break;
77
+ case 'tool_use':
78
+ state.sawStream = true;
79
+ emit('tool_called', { name: e.tool_name, input: (0, types_1.summarizeToolInput)(e.parameters) });
80
+ break;
81
+ case 'result': {
82
+ state.sawStream = true;
83
+ const stats = e.stats;
84
+ if (stats && typeof stats.duration_ms === 'number')
85
+ state.durationMs = stats.duration_ms;
86
+ if (e.status === 'error') {
87
+ const err = e.error;
88
+ state.failure = typeof err?.message === 'string' ? err.message : 'Gemini CLI reported an error result';
89
+ }
90
+ break;
91
+ }
92
+ case 'error':
93
+ state.sawStream = true;
94
+ if (e.severity === 'error' && typeof e.message === 'string')
95
+ state.failure = e.message;
96
+ break;
97
+ }
98
+ }
99
+ exports.geminiHeadlessAgent = {
100
+ id: 'gemini',
101
+ // Gemini CLI sets GEMINI_CLI=1 for the shell commands it runs.
102
+ launchedFrom: (env) => env.GEMINI_CLI === '1',
103
+ build(node, config, env) {
104
+ if (node.denied_tools && node.denied_tools.length > 0) {
105
+ return { error: `denied_tools (${node.denied_tools.join(', ')}) cannot be enforced on Gemini CLI — it has no deny flag` };
106
+ }
107
+ const args = ['--output-format', 'stream-json'];
108
+ const model = geminiModelFor(node.model, config.models);
109
+ if (model)
110
+ args.push('--model', model);
111
+ if (node.allowed_tools && node.allowed_tools.length > 0) {
112
+ const t = translateGeminiTools(node.allowed_tools);
113
+ if ('error' in t)
114
+ return t;
115
+ args.push('--allowed-tools', ...t.tools);
116
+ }
117
+ const stdin = node.systemPromptAppend
118
+ ? `${node.systemPromptAppend.trimEnd()}\n\n---\n\n${node.prompt}`
119
+ : node.prompt;
120
+ return { bin: env.SPECSHIP_GEMINI_BIN ?? 'gemini', args, stdin };
121
+ },
122
+ handleLine: handleGeminiStreamLine,
123
+ };
124
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../../src/workflows/agents/gemini.ts"],"names":[],"mappings":"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"}
@@ -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