@specship/specship-win32-arm64 0.24.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/bin/specship.cmd +31 -1
  2. package/lib/dist/activation/cheatsheet.d.ts +17 -1
  3. package/lib/dist/activation/cheatsheet.d.ts.map +1 -1
  4. package/lib/dist/activation/cheatsheet.js +47 -3
  5. package/lib/dist/activation/cheatsheet.js.map +1 -1
  6. package/lib/dist/activation/hook-output.d.ts +80 -0
  7. package/lib/dist/activation/hook-output.d.ts.map +1 -0
  8. package/lib/dist/activation/hook-output.js +103 -0
  9. package/lib/dist/activation/hook-output.js.map +1 -0
  10. package/lib/dist/activation/search-intercept.d.ts +60 -29
  11. package/lib/dist/activation/search-intercept.d.ts.map +1 -1
  12. package/lib/dist/activation/search-intercept.js +159 -55
  13. package/lib/dist/activation/search-intercept.js.map +1 -1
  14. package/lib/dist/activation/steering.d.ts +11 -13
  15. package/lib/dist/activation/steering.d.ts.map +1 -1
  16. package/lib/dist/activation/steering.js +25 -10
  17. package/lib/dist/activation/steering.js.map +1 -1
  18. package/lib/dist/behaviour/behaviour-surface.d.ts +47 -0
  19. package/lib/dist/behaviour/behaviour-surface.d.ts.map +1 -1
  20. package/lib/dist/behaviour/behaviour-surface.js +108 -2
  21. package/lib/dist/behaviour/behaviour-surface.js.map +1 -1
  22. package/lib/dist/bin/node-version-check.d.ts +22 -7
  23. package/lib/dist/bin/node-version-check.d.ts.map +1 -1
  24. package/lib/dist/bin/node-version-check.js +39 -9
  25. package/lib/dist/bin/node-version-check.js.map +1 -1
  26. package/lib/dist/bin/specship.js +989 -116
  27. package/lib/dist/bin/specship.js.map +1 -1
  28. package/lib/dist/commands/specship/learn.md +27 -3
  29. package/lib/dist/commands/specship/spec.md +85 -15
  30. package/lib/dist/db/spec-queries.d.ts +73 -3
  31. package/lib/dist/db/spec-queries.d.ts.map +1 -1
  32. package/lib/dist/db/spec-queries.js +139 -5
  33. package/lib/dist/db/spec-queries.js.map +1 -1
  34. package/lib/dist/db/sqlite-adapter.d.ts +7 -5
  35. package/lib/dist/db/sqlite-adapter.d.ts.map +1 -1
  36. package/lib/dist/db/sqlite-adapter.js +11 -9
  37. package/lib/dist/db/sqlite-adapter.js.map +1 -1
  38. package/lib/dist/enforce/changed-files.d.ts +39 -0
  39. package/lib/dist/enforce/changed-files.d.ts.map +1 -0
  40. package/lib/dist/enforce/changed-files.js +114 -0
  41. package/lib/dist/enforce/changed-files.js.map +1 -0
  42. package/lib/dist/enforce/enforce.d.ts +53 -2
  43. package/lib/dist/enforce/enforce.d.ts.map +1 -1
  44. package/lib/dist/enforce/enforce.js +95 -8
  45. package/lib/dist/enforce/enforce.js.map +1 -1
  46. package/lib/dist/enforce/mutation.d.ts +46 -0
  47. package/lib/dist/enforce/mutation.d.ts.map +1 -0
  48. package/lib/dist/enforce/mutation.js +104 -0
  49. package/lib/dist/enforce/mutation.js.map +1 -0
  50. package/lib/dist/enforce/suppressions.d.ts +33 -0
  51. package/lib/dist/enforce/suppressions.d.ts.map +1 -0
  52. package/lib/dist/enforce/suppressions.js +159 -0
  53. package/lib/dist/enforce/suppressions.js.map +1 -0
  54. package/lib/dist/extraction/grammars.d.ts +10 -0
  55. package/lib/dist/extraction/grammars.d.ts.map +1 -1
  56. package/lib/dist/extraction/grammars.js +32 -3
  57. package/lib/dist/extraction/grammars.js.map +1 -1
  58. package/lib/dist/extraction/index.d.ts +7 -0
  59. package/lib/dist/extraction/index.d.ts.map +1 -1
  60. package/lib/dist/extraction/index.js.map +1 -1
  61. package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts +7 -0
  62. package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -1
  63. package/lib/dist/extraction/specs/markdown-spec-extractor.js +97 -10
  64. package/lib/dist/extraction/specs/markdown-spec-extractor.js.map +1 -1
  65. package/lib/dist/extraction/wasm/tree-sitter-pascal.wasm.gz +0 -0
  66. package/lib/dist/extraction/wasm/tree-sitter-scala.wasm.gz +0 -0
  67. package/lib/dist/graph/spec-coverage.d.ts +142 -0
  68. package/lib/dist/graph/spec-coverage.d.ts.map +1 -0
  69. package/lib/dist/graph/spec-coverage.js +276 -0
  70. package/lib/dist/graph/spec-coverage.js.map +1 -0
  71. package/lib/dist/health/smoke-check.js +2 -2
  72. package/lib/dist/health/smoke-check.js.map +1 -1
  73. package/lib/dist/index.d.ts +75 -7
  74. package/lib/dist/index.d.ts.map +1 -1
  75. package/lib/dist/index.js +191 -23
  76. package/lib/dist/index.js.map +1 -1
  77. package/lib/dist/installer/gemini-commands.d.ts +107 -0
  78. package/lib/dist/installer/gemini-commands.d.ts.map +1 -0
  79. package/lib/dist/installer/gemini-commands.js +264 -0
  80. package/lib/dist/installer/gemini-commands.js.map +1 -0
  81. package/lib/dist/installer/index.d.ts +55 -8
  82. package/lib/dist/installer/index.d.ts.map +1 -1
  83. package/lib/dist/installer/index.js +72 -53
  84. package/lib/dist/installer/index.js.map +1 -1
  85. package/lib/dist/installer/init-offer.d.ts +14 -9
  86. package/lib/dist/installer/init-offer.d.ts.map +1 -1
  87. package/lib/dist/installer/init-offer.js +13 -9
  88. package/lib/dist/installer/init-offer.js.map +1 -1
  89. package/lib/dist/installer/install-defaults.d.ts +81 -0
  90. package/lib/dist/installer/install-defaults.d.ts.map +1 -0
  91. package/lib/dist/installer/install-defaults.js +95 -0
  92. package/lib/dist/installer/install-defaults.js.map +1 -0
  93. package/lib/dist/installer/instructions-template.d.ts +22 -0
  94. package/lib/dist/installer/instructions-template.d.ts.map +1 -1
  95. package/lib/dist/installer/instructions-template.js +37 -1
  96. package/lib/dist/installer/instructions-template.js.map +1 -1
  97. package/lib/dist/installer/targets/claude.d.ts +18 -0
  98. package/lib/dist/installer/targets/claude.d.ts.map +1 -1
  99. package/lib/dist/installer/targets/claude.js +70 -23
  100. package/lib/dist/installer/targets/claude.js.map +1 -1
  101. package/lib/dist/installer/targets/gemini.d.ts +85 -12
  102. package/lib/dist/installer/targets/gemini.d.ts.map +1 -1
  103. package/lib/dist/installer/targets/gemini.js +527 -30
  104. package/lib/dist/installer/targets/gemini.js.map +1 -1
  105. package/lib/dist/installer/targets/shared.d.ts +13 -0
  106. package/lib/dist/installer/targets/shared.d.ts.map +1 -1
  107. package/lib/dist/installer/targets/shared.js +22 -4
  108. package/lib/dist/installer/targets/shared.js.map +1 -1
  109. package/lib/dist/installer/targets/types.d.ts +12 -0
  110. package/lib/dist/installer/targets/types.d.ts.map +1 -1
  111. package/lib/dist/jira/auto-publish.d.ts +71 -4
  112. package/lib/dist/jira/auto-publish.d.ts.map +1 -1
  113. package/lib/dist/jira/auto-publish.js +186 -17
  114. package/lib/dist/jira/auto-publish.js.map +1 -1
  115. package/lib/dist/jira/reconcile.d.ts +24 -1
  116. package/lib/dist/jira/reconcile.d.ts.map +1 -1
  117. package/lib/dist/jira/reconcile.js +46 -2
  118. package/lib/dist/jira/reconcile.js.map +1 -1
  119. package/lib/dist/jira/repo-config.d.ts +9 -0
  120. package/lib/dist/jira/repo-config.d.ts.map +1 -1
  121. package/lib/dist/jira/repo-config.js +11 -0
  122. package/lib/dist/jira/repo-config.js.map +1 -1
  123. package/lib/dist/jira/types.d.ts +7 -0
  124. package/lib/dist/jira/types.d.ts.map +1 -1
  125. package/lib/dist/jira/types.js.map +1 -1
  126. package/lib/dist/knowledge/enforce.d.ts +75 -0
  127. package/lib/dist/knowledge/enforce.d.ts.map +1 -0
  128. package/lib/dist/knowledge/enforce.js +250 -0
  129. package/lib/dist/knowledge/enforce.js.map +1 -0
  130. package/lib/dist/knowledge/facts.d.ts +33 -0
  131. package/lib/dist/knowledge/facts.d.ts.map +1 -0
  132. package/lib/dist/knowledge/facts.js +117 -0
  133. package/lib/dist/knowledge/facts.js.map +1 -0
  134. package/lib/dist/knowledge/proposals.d.ts +88 -0
  135. package/lib/dist/knowledge/proposals.d.ts.map +1 -0
  136. package/lib/dist/knowledge/proposals.js +360 -0
  137. package/lib/dist/knowledge/proposals.js.map +1 -0
  138. package/lib/dist/knowledge/stale.d.ts +64 -0
  139. package/lib/dist/knowledge/stale.d.ts.map +1 -0
  140. package/lib/dist/knowledge/stale.js +174 -0
  141. package/lib/dist/knowledge/stale.js.map +1 -0
  142. package/lib/dist/mcp/fitness-tool.d.ts +5 -6
  143. package/lib/dist/mcp/fitness-tool.d.ts.map +1 -1
  144. package/lib/dist/mcp/fitness-tool.js +0 -16
  145. package/lib/dist/mcp/fitness-tool.js.map +1 -1
  146. package/lib/dist/mcp/gemini-session.d.ts +50 -0
  147. package/lib/dist/mcp/gemini-session.d.ts.map +1 -0
  148. package/lib/dist/mcp/gemini-session.js +159 -0
  149. package/lib/dist/mcp/gemini-session.js.map +1 -0
  150. package/lib/dist/mcp/health-tool.d.ts +26 -0
  151. package/lib/dist/mcp/health-tool.d.ts.map +1 -0
  152. package/lib/dist/mcp/health-tool.js +50 -0
  153. package/lib/dist/mcp/health-tool.js.map +1 -0
  154. package/lib/dist/mcp/jira-tools.d.ts.map +1 -1
  155. package/lib/dist/mcp/jira-tools.js +25 -0
  156. package/lib/dist/mcp/jira-tools.js.map +1 -1
  157. package/lib/dist/mcp/maintainability-tool.d.ts +5 -7
  158. package/lib/dist/mcp/maintainability-tool.d.ts.map +1 -1
  159. package/lib/dist/mcp/maintainability-tool.js +0 -16
  160. package/lib/dist/mcp/maintainability-tool.js.map +1 -1
  161. package/lib/dist/mcp/model-context.d.ts +31 -7
  162. package/lib/dist/mcp/model-context.d.ts.map +1 -1
  163. package/lib/dist/mcp/model-context.js +70 -21
  164. package/lib/dist/mcp/model-context.js.map +1 -1
  165. package/lib/dist/mcp/proxy.d.ts.map +1 -1
  166. package/lib/dist/mcp/proxy.js +5 -2
  167. package/lib/dist/mcp/proxy.js.map +1 -1
  168. package/lib/dist/mcp/server-instructions.d.ts +16 -15
  169. package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
  170. package/lib/dist/mcp/server-instructions.js +72 -5
  171. package/lib/dist/mcp/server-instructions.js.map +1 -1
  172. package/lib/dist/mcp/session.js +1 -1
  173. package/lib/dist/mcp/session.js.map +1 -1
  174. package/lib/dist/mcp/spec-tools.d.ts +9 -1
  175. package/lib/dist/mcp/spec-tools.d.ts.map +1 -1
  176. package/lib/dist/mcp/spec-tools.js +282 -49
  177. package/lib/dist/mcp/spec-tools.js.map +1 -1
  178. package/lib/dist/mcp/tools.d.ts +49 -9
  179. package/lib/dist/mcp/tools.d.ts.map +1 -1
  180. package/lib/dist/mcp/tools.js +210 -58
  181. package/lib/dist/mcp/tools.js.map +1 -1
  182. package/lib/dist/pulse/pulse.d.ts +93 -0
  183. package/lib/dist/pulse/pulse.d.ts.map +1 -0
  184. package/lib/dist/pulse/pulse.js +401 -0
  185. package/lib/dist/pulse/pulse.js.map +1 -0
  186. package/lib/dist/reflect/apply.d.ts.map +1 -1
  187. package/lib/dist/reflect/apply.js +38 -3
  188. package/lib/dist/reflect/apply.js.map +1 -1
  189. package/lib/dist/reflect/auto-sweep.d.ts +26 -0
  190. package/lib/dist/reflect/auto-sweep.d.ts.map +1 -0
  191. package/lib/dist/reflect/auto-sweep.js +90 -0
  192. package/lib/dist/reflect/auto-sweep.js.map +1 -0
  193. package/lib/dist/reflect/cli.d.ts +62 -0
  194. package/lib/dist/reflect/cli.d.ts.map +1 -0
  195. package/lib/dist/reflect/cli.js +163 -0
  196. package/lib/dist/reflect/cli.js.map +1 -0
  197. package/lib/dist/reflect/miner.d.ts.map +1 -1
  198. package/lib/dist/reflect/miner.js +119 -0
  199. package/lib/dist/reflect/miner.js.map +1 -1
  200. package/lib/dist/reflect/sweep.d.ts +1 -0
  201. package/lib/dist/reflect/sweep.d.ts.map +1 -1
  202. package/lib/dist/reflect/sweep.js +62 -13
  203. package/lib/dist/reflect/sweep.js.map +1 -1
  204. package/lib/dist/reflect/targets.d.ts +2 -0
  205. package/lib/dist/reflect/targets.d.ts.map +1 -1
  206. package/lib/dist/reflect/targets.js +33 -0
  207. package/lib/dist/reflect/targets.js.map +1 -1
  208. package/lib/dist/reflect/types.d.ts +19 -2
  209. package/lib/dist/reflect/types.d.ts.map +1 -1
  210. package/lib/dist/resolution/spec-link-resolver.d.ts +44 -2
  211. package/lib/dist/resolution/spec-link-resolver.d.ts.map +1 -1
  212. package/lib/dist/resolution/spec-link-resolver.js +132 -0
  213. package/lib/dist/resolution/spec-link-resolver.js.map +1 -1
  214. package/lib/dist/resolution/test-title-links.d.ts +62 -0
  215. package/lib/dist/resolution/test-title-links.d.ts.map +1 -0
  216. package/lib/dist/resolution/test-title-links.js +97 -0
  217. package/lib/dist/resolution/test-title-links.js.map +1 -0
  218. package/lib/dist/search/query-parser.d.ts.map +1 -1
  219. package/lib/dist/search/query-parser.js +6 -1
  220. package/lib/dist/search/query-parser.js.map +1 -1
  221. package/lib/dist/server/project-registry.js +1 -1
  222. package/lib/dist/server/routes/claude.js +24 -43
  223. package/lib/dist/server/routes/graph.js +53 -7
  224. package/lib/dist/server/routes/knowledge.js +118 -0
  225. package/lib/dist/server/routes/mcp.js +4 -3
  226. package/lib/dist/server/routes/projects.js +4 -4
  227. package/lib/dist/server/routes/spec.js +49 -7
  228. package/lib/dist/server/server.js +31 -17
  229. package/lib/dist/skills/spec-author/SKILL.md +164 -0
  230. package/lib/dist/skills/spec-author/references/format.md +210 -0
  231. package/lib/dist/skills/spec-author/references/gap-questions.md +152 -0
  232. package/lib/dist/skills/spec-author/references/quality-rubric.md +125 -0
  233. package/lib/dist/skills/spec-author/references/review-checklist.md +175 -0
  234. package/lib/dist/spec-lint/lint.d.ts +82 -0
  235. package/lib/dist/spec-lint/lint.d.ts.map +1 -0
  236. package/lib/dist/spec-lint/lint.js +491 -0
  237. package/lib/dist/spec-lint/lint.js.map +1 -0
  238. package/lib/dist/spec-quality/criterion-ids.d.ts +13 -0
  239. package/lib/dist/spec-quality/criterion-ids.d.ts.map +1 -0
  240. package/lib/dist/spec-quality/criterion-ids.js +38 -0
  241. package/lib/dist/spec-quality/criterion-ids.js.map +1 -0
  242. package/lib/dist/spec-quality/evidence-kind.d.ts +54 -0
  243. package/lib/dist/spec-quality/evidence-kind.d.ts.map +1 -0
  244. package/lib/dist/spec-quality/evidence-kind.js +183 -0
  245. package/lib/dist/spec-quality/evidence-kind.js.map +1 -0
  246. package/lib/dist/spec-quality/link-persist.d.ts +65 -0
  247. package/lib/dist/spec-quality/link-persist.d.ts.map +1 -0
  248. package/lib/dist/spec-quality/link-persist.js +249 -0
  249. package/lib/dist/spec-quality/link-persist.js.map +1 -0
  250. package/lib/dist/spec-quality/plan-scope.d.ts +38 -0
  251. package/lib/dist/spec-quality/plan-scope.d.ts.map +1 -0
  252. package/lib/dist/spec-quality/plan-scope.js +129 -0
  253. package/lib/dist/spec-quality/plan-scope.js.map +1 -0
  254. package/lib/dist/spec-quality/postcheck.d.ts +85 -0
  255. package/lib/dist/spec-quality/postcheck.d.ts.map +1 -0
  256. package/lib/dist/spec-quality/postcheck.js +390 -0
  257. package/lib/dist/spec-quality/postcheck.js.map +1 -0
  258. package/lib/dist/spec-quality/readiness.d.ts +72 -0
  259. package/lib/dist/spec-quality/readiness.d.ts.map +1 -0
  260. package/lib/dist/spec-quality/readiness.js +226 -0
  261. package/lib/dist/spec-quality/readiness.js.map +1 -0
  262. package/lib/dist/statusline/index.js.map +1 -1
  263. package/lib/dist/statusline/render.d.ts +1 -1
  264. package/lib/dist/statusline/render.d.ts.map +1 -1
  265. package/lib/dist/statusline/render.js +3 -1
  266. package/lib/dist/statusline/render.js.map +1 -1
  267. package/lib/dist/ui/assets/index-BzuUWUAE.js +50 -0
  268. package/lib/dist/ui/index.html +1 -1
  269. package/lib/dist/verify/report-ingest.d.ts +88 -0
  270. package/lib/dist/verify/report-ingest.d.ts.map +1 -0
  271. package/lib/dist/verify/report-ingest.js +269 -0
  272. package/lib/dist/verify/report-ingest.js.map +1 -0
  273. package/lib/dist/workflows/agents/claude.d.ts +16 -0
  274. package/lib/dist/workflows/agents/claude.d.ts.map +1 -0
  275. package/lib/dist/workflows/agents/claude.js +82 -0
  276. package/lib/dist/workflows/agents/claude.js.map +1 -0
  277. package/lib/dist/workflows/agents/gemini.d.ts +21 -0
  278. package/lib/dist/workflows/agents/gemini.d.ts.map +1 -0
  279. package/lib/dist/workflows/agents/gemini.js +124 -0
  280. package/lib/dist/workflows/agents/gemini.js.map +1 -0
  281. package/lib/dist/workflows/agents/index.d.ts +28 -0
  282. package/lib/dist/workflows/agents/index.d.ts.map +1 -0
  283. package/lib/dist/workflows/agents/index.js +104 -0
  284. package/lib/dist/workflows/agents/index.js.map +1 -0
  285. package/lib/dist/workflows/agents/types.d.ts +55 -0
  286. package/lib/dist/workflows/agents/types.d.ts.map +1 -0
  287. package/lib/dist/workflows/agents/types.js +46 -0
  288. package/lib/dist/workflows/agents/types.js.map +1 -0
  289. package/lib/dist/workflows/batch.d.ts +63 -0
  290. package/lib/dist/workflows/batch.d.ts.map +1 -0
  291. package/lib/dist/workflows/batch.js +151 -0
  292. package/lib/dist/workflows/batch.js.map +1 -0
  293. package/lib/dist/workflows/defaults/claude-design-implement.yaml +3 -4
  294. package/lib/dist/workflows/defaults/spec-author.yaml +11 -9
  295. package/lib/dist/workflows/defaults/spec-fix.yaml +103 -12
  296. package/lib/dist/workflows/defaults/spec-implement-mixed.yaml +21 -193
  297. package/lib/dist/workflows/defaults/spec-implement.yaml +701 -41
  298. package/lib/dist/workflows/defaults/spec-verify.yaml +60 -9
  299. package/lib/dist/workflows/discovery.d.ts +13 -0
  300. package/lib/dist/workflows/discovery.d.ts.map +1 -1
  301. package/lib/dist/workflows/discovery.js +79 -17
  302. package/lib/dist/workflows/discovery.js.map +1 -1
  303. package/lib/dist/workflows/executor.d.ts +18 -0
  304. package/lib/dist/workflows/executor.d.ts.map +1 -1
  305. package/lib/dist/workflows/executor.js +130 -33
  306. package/lib/dist/workflows/executor.js.map +1 -1
  307. package/lib/dist/workflows/gc.d.ts +50 -0
  308. package/lib/dist/workflows/gc.d.ts.map +1 -0
  309. package/lib/dist/workflows/gc.js +120 -0
  310. package/lib/dist/workflows/gc.js.map +1 -0
  311. package/lib/dist/workflows/merge-queue.d.ts +64 -0
  312. package/lib/dist/workflows/merge-queue.d.ts.map +1 -0
  313. package/lib/dist/workflows/merge-queue.js +162 -0
  314. package/lib/dist/workflows/merge-queue.js.map +1 -0
  315. package/lib/dist/workflows/runners/approval.d.ts +1 -1
  316. package/lib/dist/workflows/runners/approval.d.ts.map +1 -1
  317. package/lib/dist/workflows/runners/approval.js +11 -2
  318. package/lib/dist/workflows/runners/approval.js.map +1 -1
  319. package/lib/dist/workflows/runners/bash.d.ts +15 -0
  320. package/lib/dist/workflows/runners/bash.d.ts.map +1 -1
  321. package/lib/dist/workflows/runners/bash.js +50 -1
  322. package/lib/dist/workflows/runners/bash.js.map +1 -1
  323. package/lib/dist/workflows/runners/prompt.d.ts +16 -41
  324. package/lib/dist/workflows/runners/prompt.d.ts.map +1 -1
  325. package/lib/dist/workflows/runners/prompt.js +55 -120
  326. package/lib/dist/workflows/runners/prompt.js.map +1 -1
  327. package/lib/dist/workflows/runners/types.d.ts +12 -0
  328. package/lib/dist/workflows/runners/types.d.ts.map +1 -1
  329. package/lib/dist/workflows/schemas/workflow.d.ts +17 -0
  330. package/lib/dist/workflows/schemas/workflow.d.ts.map +1 -1
  331. package/lib/dist/workflows/schemas/workflow.js +27 -0
  332. package/lib/dist/workflows/schemas/workflow.js.map +1 -1
  333. package/lib/node_modules/.package-lock.json +1 -1
  334. package/lib/package.json +8 -4
  335. package/package.json +5 -3
  336. package/lib/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  337. package/lib/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
  338. package/lib/dist/server/ingest/impact-query.js +0 -343
  339. package/lib/dist/server/routes/events.js +0 -152
  340. package/lib/dist/ui/assets/index-CjjaftDw.js +0 -50
  341. package/node.exe +0 -4
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Evidence kinds (PIPETRUST-DOC, REQ-PIPETRUST-001 / REQ-PIPETRUST-002).
3
+ *
4
+ * Coverage used to count "a test" without asking what kind. Every acceptance
5
+ * criterion now resolves to exactly one REQUIRED kind of evidence, and every
6
+ * test file classifies to the kind it actually PROVIDES — both
7
+ * deterministically, so coverage can compare the two.
8
+ *
9
+ * - required: an inline `(evidence: <kind>)` tag wins; otherwise derived from
10
+ * the criterion's shape (invariant phrasing → property) and the
11
+ * requirement's direct links (UI → e2e, route → contract), else unit.
12
+ * - present: read from the test file alone — library imports and path
13
+ * segments. Never throws; anything unreadable is `unit`.
14
+ */
15
+ export type EvidenceKind = 'unit' | 'property' | 'e2e' | 'contract';
16
+ /** The four kinds, in the order reports list them. */
17
+ export declare const EVIDENCE_KINDS: readonly EvidenceKind[];
18
+ /**
19
+ * Read an inline `(evidence: <kind>)` tag from an acceptance bullet
20
+ * (REQ-PIPETRUST-001.A1). No tag → `{}`; a known kind → `{ kind }`; an
21
+ * unknown kind → `{ invalid: <what was written> }` (a lint error, A3).
22
+ */
23
+ export declare function parseDeclaredEvidenceKind(text: string): {
24
+ kind?: EvidenceKind;
25
+ invalid?: string;
26
+ };
27
+ export interface EvidenceKindContext {
28
+ /** The requirement is directly linked (implements) to UI code. */
29
+ linksUi?: boolean;
30
+ /** The requirement is directly linked (implements) to a `route` node. */
31
+ linksRoute?: boolean;
32
+ }
33
+ /**
34
+ * The single evidence kind a criterion requires (REQ-PIPETRUST-001.A1/.A2).
35
+ * Precedence: declared tag → invariant phrasing (property) → UI link (e2e) →
36
+ * route link (contract) → unit. An invalid declared kind falls through to the
37
+ * derived kind — the lint reports it; resolution never fails.
38
+ */
39
+ export declare function requiredEvidenceKind(criterionText: string, ctx?: EvidenceKindContext): EvidenceKind;
40
+ /**
41
+ * Remove block comments, `//` line comments and `#` line comments (Python /
42
+ * shell test files). Deliberately simple: a `//` inside a string literal also
43
+ * ends the line's code, which can only make classification more conservative.
44
+ */
45
+ export declare function stripComments(source: string): string;
46
+ /**
47
+ * Classify a test file by the kind of evidence it provides
48
+ * (REQ-PIPETRUST-002.A1). Source signals are checked before path signals, and
49
+ * property before e2e before contract. `source` is read from `filePath` when
50
+ * omitted; a missing or unreadable file classifies as `unit` (A2) — this
51
+ * function never throws.
52
+ */
53
+ export declare function classifyTestEvidence(filePath: string, source?: string): EvidenceKind;
54
+ //# sourceMappingURL=evidence-kind.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence-kind.d.ts","sourceRoot":"","sources":["../../src/spec-quality/evidence-kind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,UAAU,GAAG,KAAK,GAAG,UAAU,CAAC;AAEpE,sDAAsD;AACtD,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAA4C,CAAC;AAkB/F;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,YAAY,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAMjG;AAED,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yEAAyE;IACzE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,GAAE,mBAAwB,GAAG,YAAY,CAOvG;AA2BD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMpD;AASD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAyBpF"}
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ /**
3
+ * Evidence kinds (PIPETRUST-DOC, REQ-PIPETRUST-001 / REQ-PIPETRUST-002).
4
+ *
5
+ * Coverage used to count "a test" without asking what kind. Every acceptance
6
+ * criterion now resolves to exactly one REQUIRED kind of evidence, and every
7
+ * test file classifies to the kind it actually PROVIDES — both
8
+ * deterministically, so coverage can compare the two.
9
+ *
10
+ * - required: an inline `(evidence: <kind>)` tag wins; otherwise derived from
11
+ * the criterion's shape (invariant phrasing → property) and the
12
+ * requirement's direct links (UI → e2e, route → contract), else unit.
13
+ * - present: read from the test file alone — library imports and path
14
+ * segments. Never throws; anything unreadable is `unit`.
15
+ */
16
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ var desc = Object.getOwnPropertyDescriptor(m, k);
19
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
20
+ desc = { enumerable: true, get: function() { return m[k]; } };
21
+ }
22
+ Object.defineProperty(o, k2, desc);
23
+ }) : (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ o[k2] = m[k];
26
+ }));
27
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
28
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
29
+ }) : function(o, v) {
30
+ o["default"] = v;
31
+ });
32
+ var __importStar = (this && this.__importStar) || (function () {
33
+ var ownKeys = function(o) {
34
+ ownKeys = Object.getOwnPropertyNames || function (o) {
35
+ var ar = [];
36
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
37
+ return ar;
38
+ };
39
+ return ownKeys(o);
40
+ };
41
+ return function (mod) {
42
+ if (mod && mod.__esModule) return mod;
43
+ var result = {};
44
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
45
+ __setModuleDefault(result, mod);
46
+ return result;
47
+ };
48
+ })();
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.EVIDENCE_KINDS = void 0;
51
+ exports.parseDeclaredEvidenceKind = parseDeclaredEvidenceKind;
52
+ exports.requiredEvidenceKind = requiredEvidenceKind;
53
+ exports.stripComments = stripComments;
54
+ exports.classifyTestEvidence = classifyTestEvidence;
55
+ const fs = __importStar(require("fs"));
56
+ const behaviour_surface_1 = require("../behaviour/behaviour-surface");
57
+ /** The four kinds, in the order reports list them. */
58
+ exports.EVIDENCE_KINDS = ['unit', 'property', 'e2e', 'contract'];
59
+ /** `(evidence: <kind>)` — case-insensitive; the kind is any non-`)` run. */
60
+ const EVIDENCE_TAG = /\(\s*evidence\s*:\s*([^)]*?)\s*\)/i;
61
+ /**
62
+ * Drop inline code spans and fenced blocks first: a spec that DOCUMENTS the
63
+ * tag syntax writes `` `(evidence: <kind>)` `` in backticks and is not itself
64
+ * declaring a kind (same convention as the lint's `[needs review]` scan).
65
+ */
66
+ function stripCode(text) {
67
+ return text.replace(/```[\s\S]*?```/g, ' ').replace(/`[^`]*`/g, ' ');
68
+ }
69
+ function isEvidenceKind(s) {
70
+ return exports.EVIDENCE_KINDS.includes(s);
71
+ }
72
+ /**
73
+ * Read an inline `(evidence: <kind>)` tag from an acceptance bullet
74
+ * (REQ-PIPETRUST-001.A1). No tag → `{}`; a known kind → `{ kind }`; an
75
+ * unknown kind → `{ invalid: <what was written> }` (a lint error, A3).
76
+ */
77
+ function parseDeclaredEvidenceKind(text) {
78
+ const m = stripCode(text ?? '').match(EVIDENCE_TAG);
79
+ if (!m)
80
+ return {};
81
+ const raw = (m[1] ?? '').trim();
82
+ const norm = raw.toLowerCase();
83
+ return isEvidenceKind(norm) ? { kind: norm } : { invalid: raw };
84
+ }
85
+ /**
86
+ * The single evidence kind a criterion requires (REQ-PIPETRUST-001.A1/.A2).
87
+ * Precedence: declared tag → invariant phrasing (property) → UI link (e2e) →
88
+ * route link (contract) → unit. An invalid declared kind falls through to the
89
+ * derived kind — the lint reports it; resolution never fails.
90
+ */
91
+ function requiredEvidenceKind(criterionText, ctx = {}) {
92
+ const declared = parseDeclaredEvidenceKind(criterionText).kind;
93
+ if (declared)
94
+ return declared;
95
+ if ((0, behaviour_surface_1.classifyCriterionShape)(criterionText ?? '') === 'invariant')
96
+ return 'property';
97
+ if (ctx.linksUi)
98
+ return 'e2e';
99
+ if (ctx.linksRoute)
100
+ return 'contract';
101
+ return 'unit';
102
+ }
103
+ /** Property-testing library use: fast-check, Hypothesis, jqwik, proptest, QuickCheck. */
104
+ const PROPERTY_SOURCE = [
105
+ /['"]fast-check['"]/,
106
+ /\bfc\.(assert|property|asyncProperty)\s*\(/,
107
+ /@given\s*\(/,
108
+ /\bfrom\s+hypothesis\b|\bimport\s+hypothesis\b/,
109
+ /\bnet\.jqwik\b|@Property\b/,
110
+ /\bproptest!?\b/,
111
+ /\bquickcheck\b/i,
112
+ ];
113
+ /** Browser e2e frameworks. */
114
+ const E2E_SOURCE = [/['"]@playwright\/test['"]/, /['"]cypress['"]/, /\bcy\.(visit|get|request)\s*\(/];
115
+ /** Contract / API-schema testing tools. */
116
+ const CONTRACT_SOURCE = [
117
+ // Case-sensitive: the package and CLI are lowercase in real use, and an
118
+ // upper-case identifier (a constant named SCHEMATHESIS) is not a use.
119
+ /\bschemathesis\b/,
120
+ /@pact-foundation\//,
121
+ /\b(from|import)\s+pact\b/,
122
+ /\bnew\s+Pact(V\d)?\s*\(/,
123
+ /\bau\.com\.dius\.pact\b/,
124
+ ];
125
+ /**
126
+ * Remove block comments, `//` line comments and `#` line comments (Python /
127
+ * shell test files). Deliberately simple: a `//` inside a string literal also
128
+ * ends the line's code, which can only make classification more conservative.
129
+ */
130
+ function stripComments(source) {
131
+ return source
132
+ .replace(/\/\*[\s\S]*?\*\//g, '')
133
+ .split('\n')
134
+ .map((line) => line.replace(/(^|\s)\/\/.*$/, '$1').replace(/^\s*#(?!!).*$/, ''))
135
+ .join('\n');
136
+ }
137
+ function pathSegments(filePath) {
138
+ return filePath
139
+ .replace(/\\/g, '/')
140
+ .split('/')
141
+ .map((s) => s.toLowerCase());
142
+ }
143
+ /**
144
+ * Classify a test file by the kind of evidence it provides
145
+ * (REQ-PIPETRUST-002.A1). Source signals are checked before path signals, and
146
+ * property before e2e before contract. `source` is read from `filePath` when
147
+ * omitted; a missing or unreadable file classifies as `unit` (A2) — this
148
+ * function never throws.
149
+ */
150
+ function classifyTestEvidence(filePath, source) {
151
+ let text = source;
152
+ if (text === undefined) {
153
+ try {
154
+ text = fs.readFileSync(filePath, 'utf-8');
155
+ }
156
+ catch {
157
+ text = '';
158
+ }
159
+ }
160
+ // A tool named in prose (a doc comment explaining the classifier, say) is
161
+ // not a use of it — match against code with comments removed.
162
+ text = stripComments(text);
163
+ try {
164
+ if (PROPERTY_SOURCE.some((re) => re.test(text)))
165
+ return 'property';
166
+ if (E2E_SOURCE.some((re) => re.test(text)))
167
+ return 'e2e';
168
+ if (CONTRACT_SOURCE.some((re) => re.test(text)))
169
+ return 'contract';
170
+ const segs = pathSegments(filePath ?? '');
171
+ const dirs = segs.slice(0, -1);
172
+ const base = segs[segs.length - 1] ?? '';
173
+ if (dirs.includes('e2e') || /(^|[.\-_])e2e([.\-_]|$)/.test(base))
174
+ return 'e2e';
175
+ if (dirs.includes('contract') || dirs.includes('contracts'))
176
+ return 'contract';
177
+ }
178
+ catch {
179
+ // fall through — classification is advisory, never fatal
180
+ }
181
+ return 'unit';
182
+ }
183
+ //# sourceMappingURL=evidence-kind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence-kind.js","sourceRoot":"","sources":["../../src/spec-quality/evidence-kind.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Durable link assertions (THROUGHPUT-DOC, REQ-THRU-005).
3
+ *
4
+ * A link asserted through the link-assert tool lands as a DB row, and a DB row
5
+ * alone vanishes on a full reindex. This module writes the same link into the
6
+ * requirement's `implementations:` (kind `implements`) or `verifies:` (kind
7
+ * `tests`) block in its spec file, so the parser re-asserts it on every index.
8
+ *
9
+ * Rules:
10
+ * - an acceptance-criterion id (`REQ-X.A1`) persists into its parent
11
+ * requirement's block — link blocks live under the requirement, never in
12
+ * the Acceptance section;
13
+ * - one bullet per target; a missing block is created right before the
14
+ * requirement's `## Acceptance` heading (or at the end of its prose);
15
+ * - idempotent — re-persisting a listed target leaves the file
16
+ * byte-identical;
17
+ * - a target with no symbol, or a symbol not defined in its file, is refused
18
+ * and the spec file is never touched.
19
+ */
20
+ export type PersistLinkKind = 'implements' | 'tests';
21
+ export interface PersistLinkOptions {
22
+ projectRoot: string;
23
+ /** Requirement id (`REQ-X`) or acceptance-criterion id (`REQ-X.A1`). */
24
+ specId: string;
25
+ kind: PersistLinkKind;
26
+ /** Project-relative path of the code/test file. */
27
+ filePath: string;
28
+ /** Symbol (qualified name or named test function) defined in `filePath`. */
29
+ symbol: string;
30
+ /**
31
+ * Spec file to edit (project-relative or absolute). Default: the file under
32
+ * `specs/` declaring the requirement's id marker.
33
+ */
34
+ specSourcePath?: string;
35
+ /**
36
+ * The caller already resolved `filePath:symbol` against the code graph —
37
+ * skip the textual definition check (it is a fallback for callers without
38
+ * a graph, and can miss syntax the extractor understands).
39
+ */
40
+ symbolResolved?: boolean;
41
+ }
42
+ export interface PersistLinkResult {
43
+ status: 'persisted' | 'unchanged' | 'refused';
44
+ /** Project-relative spec file path, when one was located. */
45
+ specFile?: string;
46
+ /** The requirement whose block was (or would have been) edited. */
47
+ requirementId: string;
48
+ /** Human-readable outcome / refusal reason. */
49
+ detail: string;
50
+ }
51
+ /** `REQ-X.A1` → `REQ-X`; a requirement id is returned unchanged. */
52
+ export declare function parentRequirementId(specId: string): string;
53
+ /**
54
+ * Textual "is `symbol` defined in this source" check, in the style of the
55
+ * postcheck verifies-coverage check, widened to qualified names
56
+ * (`Class.method` → both the container and the member must be declared) and
57
+ * class members / type declarations.
58
+ */
59
+ export declare function symbolDefinedInSource(source: string, symbol: string): boolean;
60
+ /**
61
+ * Persist an asserted link into the spec file. Never throws — failures and
62
+ * refusals come back as `status: 'refused'` with the reason.
63
+ */
64
+ export declare function persistLinkToSpecFile(opts: PersistLinkOptions): PersistLinkResult;
65
+ //# sourceMappingURL=link-persist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-persist.d.ts","sourceRoot":"","sources":["../../src/spec-quality/link-persist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,OAAO,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,eAAe,CAAC;IACtB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,SAAS,CAAC;IAC9C,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,aAAa,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;CAChB;AAMD,oEAAoE;AACpE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1D;AAMD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAkB7E;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,kBAAkB,GAAG,iBAAiB,CA+IjF"}
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+ /**
3
+ * Durable link assertions (THROUGHPUT-DOC, REQ-THRU-005).
4
+ *
5
+ * A link asserted through the link-assert tool lands as a DB row, and a DB row
6
+ * alone vanishes on a full reindex. This module writes the same link into the
7
+ * requirement's `implementations:` (kind `implements`) or `verifies:` (kind
8
+ * `tests`) block in its spec file, so the parser re-asserts it on every index.
9
+ *
10
+ * Rules:
11
+ * - an acceptance-criterion id (`REQ-X.A1`) persists into its parent
12
+ * requirement's block — link blocks live under the requirement, never in
13
+ * the Acceptance section;
14
+ * - one bullet per target; a missing block is created right before the
15
+ * requirement's `## Acceptance` heading (or at the end of its prose);
16
+ * - idempotent — re-persisting a listed target leaves the file
17
+ * byte-identical;
18
+ * - a target with no symbol, or a symbol not defined in its file, is refused
19
+ * and the spec file is never touched.
20
+ */
21
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ var desc = Object.getOwnPropertyDescriptor(m, k);
24
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
25
+ desc = { enumerable: true, get: function() { return m[k]; } };
26
+ }
27
+ Object.defineProperty(o, k2, desc);
28
+ }) : (function(o, m, k, k2) {
29
+ if (k2 === undefined) k2 = k;
30
+ o[k2] = m[k];
31
+ }));
32
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
33
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
34
+ }) : function(o, v) {
35
+ o["default"] = v;
36
+ });
37
+ var __importStar = (this && this.__importStar) || (function () {
38
+ var ownKeys = function(o) {
39
+ ownKeys = Object.getOwnPropertyNames || function (o) {
40
+ var ar = [];
41
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
42
+ return ar;
43
+ };
44
+ return ownKeys(o);
45
+ };
46
+ return function (mod) {
47
+ if (mod && mod.__esModule) return mod;
48
+ var result = {};
49
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
50
+ __setModuleDefault(result, mod);
51
+ return result;
52
+ };
53
+ })();
54
+ Object.defineProperty(exports, "__esModule", { value: true });
55
+ exports.parentRequirementId = parentRequirementId;
56
+ exports.symbolDefinedInSource = symbolDefinedInSource;
57
+ exports.persistLinkToSpecFile = persistLinkToSpecFile;
58
+ const fs = __importStar(require("fs"));
59
+ const path = __importStar(require("path"));
60
+ const postcheck_1 = require("./postcheck");
61
+ const ID_MARKER = /^\s*<!--\s*id:\s*([A-Za-z0-9._-]+)\s*-->\s*$/;
62
+ const ACCEPTANCE_HEADING = /^#{1,6}\s+Acceptance\b/i;
63
+ const BULLET = /^\s+[-*]\s+\S/;
64
+ /** `REQ-X.A1` → `REQ-X`; a requirement id is returned unchanged. */
65
+ function parentRequirementId(specId) {
66
+ return specId.replace(/\.A\d+$/, '');
67
+ }
68
+ function escapeRe(s) {
69
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
70
+ }
71
+ /**
72
+ * Textual "is `symbol` defined in this source" check, in the style of the
73
+ * postcheck verifies-coverage check, widened to qualified names
74
+ * (`Class.method` → both the container and the member must be declared) and
75
+ * class members / type declarations.
76
+ */
77
+ function symbolDefinedInSource(source, symbol) {
78
+ const parts = symbol.split(/\.|::|#/).filter(Boolean);
79
+ if (parts.length === 0)
80
+ return false;
81
+ return parts.every((part, i) => {
82
+ const s = escapeRe(part);
83
+ const decl = new RegExp(`\\b(function\\*?|const|let|var|class|interface|type|enum|struct|trait|def|fn|func)\\s+${s}\\b` +
84
+ `|\\b${s}\\s*[:=]\\s*(async\\s+)?(function|\\()`);
85
+ if (decl.test(source))
86
+ return true;
87
+ if (i === 0 && parts.length > 1)
88
+ return false;
89
+ // Class member: ` async name(` / ` public static name<T>(`.
90
+ const member = new RegExp(`^\\s*(?:(?:public|private|protected|static|async|readonly|override|get|set)\\s+)*\\*?${s}\\s*(?:<[^>]*>)?\\s*\\(`, 'm');
91
+ return member.test(source);
92
+ });
93
+ }
94
+ /**
95
+ * Persist an asserted link into the spec file. Never throws — failures and
96
+ * refusals come back as `status: 'refused'` with the reason.
97
+ */
98
+ function persistLinkToSpecFile(opts) {
99
+ const requirementId = parentRequirementId(opts.specId);
100
+ const refuse = (detail, specFile) => ({
101
+ status: 'refused',
102
+ requirementId,
103
+ detail,
104
+ ...(specFile ? { specFile } : {}),
105
+ });
106
+ const symbol = (opts.symbol ?? '').trim();
107
+ const filePath = (opts.filePath ?? '').trim().replace(/\\/g, '/');
108
+ if (!symbol)
109
+ return refuse('target has no symbol — a link needs a `path:Symbol` target');
110
+ if (!filePath)
111
+ return refuse('target has no file path');
112
+ if (opts.kind !== 'implements' && opts.kind !== 'tests') {
113
+ return refuse(`kind "${String(opts.kind)}" has no spec-file block`);
114
+ }
115
+ const root = path.resolve(opts.projectRoot);
116
+ const inRoot = (abs) => {
117
+ const rel = path.relative(root, abs);
118
+ return !rel.startsWith('..') && !path.isAbsolute(rel);
119
+ };
120
+ try {
121
+ // 1. The target must be a resolvable `path:Symbol`.
122
+ if (!opts.symbolResolved) {
123
+ const targetAbs = path.resolve(root, filePath);
124
+ if (!inRoot(targetAbs))
125
+ return refuse(`${filePath} resolves outside the project root`);
126
+ let code;
127
+ try {
128
+ code = fs.readFileSync(targetAbs, 'utf8');
129
+ }
130
+ catch {
131
+ return refuse(`${filePath} does not exist`);
132
+ }
133
+ if (!symbolDefinedInSource(code, symbol)) {
134
+ return refuse(`${symbol} is not defined in ${filePath}`);
135
+ }
136
+ }
137
+ // 2. Locate the spec file and the requirement's block.
138
+ const specAbs = opts.specSourcePath
139
+ ? path.resolve(root, opts.specSourcePath)
140
+ : (0, postcheck_1.findSpecFile)(root, requirementId);
141
+ if (!specAbs)
142
+ return refuse(`no spec file under specs/ declares ${requirementId}`);
143
+ if (!inRoot(specAbs))
144
+ return refuse(`spec file resolves outside the project root`);
145
+ const specFile = path.relative(root, specAbs).replace(/\\/g, '/');
146
+ const source = fs.readFileSync(specAbs, 'utf8');
147
+ const block = (0, postcheck_1.requirementBlock)(source, requirementId);
148
+ if (block === null)
149
+ return refuse(`marker <!-- id: ${requirementId} --> not found`, specFile);
150
+ const blockName = opts.kind === 'tests' ? 'verifies' : 'implementations';
151
+ const target = `${filePath}:${symbol}`;
152
+ if ((0, postcheck_1.linkBullets)(block, blockName).includes(target)) {
153
+ return {
154
+ status: 'unchanged',
155
+ requirementId,
156
+ specFile,
157
+ detail: `${blockName}: already lists ${target}`,
158
+ };
159
+ }
160
+ // 3. Line-level edit inside the requirement's region.
161
+ const eol = source.includes('\r\n') ? '\r\n' : '\n';
162
+ const lines = source.split(/\r?\n/);
163
+ let start = -1;
164
+ let end = lines.length;
165
+ for (let i = 0; i < lines.length; i++) {
166
+ const m = (lines[i] ?? '').match(ID_MARKER);
167
+ if (!m)
168
+ continue;
169
+ if (start === -1) {
170
+ if (m[1] === requirementId)
171
+ start = i;
172
+ }
173
+ else if (!m[1].startsWith(`${requirementId}.`)) {
174
+ end = i;
175
+ break;
176
+ }
177
+ }
178
+ if (start === -1)
179
+ return refuse(`marker <!-- id: ${requirementId} --> not found`, specFile);
180
+ const bullet = ` - ${target}`;
181
+ const header = new RegExp(`^${blockName}:\\s*$`);
182
+ let headerIdx = -1;
183
+ for (let i = start + 1; i < end; i++) {
184
+ if (header.test(lines[i] ?? '')) {
185
+ headerIdx = i;
186
+ break;
187
+ }
188
+ }
189
+ if (headerIdx !== -1) {
190
+ let last = headerIdx;
191
+ for (let i = headerIdx + 1; i < end; i++) {
192
+ const line = lines[i] ?? '';
193
+ if (BULLET.test(line)) {
194
+ last = i;
195
+ continue;
196
+ }
197
+ if (line.trim() === '')
198
+ continue;
199
+ break;
200
+ }
201
+ lines.splice(last + 1, 0, bullet);
202
+ }
203
+ else {
204
+ // Prose ends at `## Acceptance`, else at the first criterion marker,
205
+ // else at the end of the region.
206
+ let proseEnd = end;
207
+ for (let i = start + 1; i < end; i++) {
208
+ const line = lines[i] ?? '';
209
+ const m = line.match(ID_MARKER);
210
+ if (ACCEPTANCE_HEADING.test(line) || (m && m[1].startsWith(`${requirementId}.`))) {
211
+ proseEnd = i;
212
+ break;
213
+ }
214
+ }
215
+ // An `implementations:` block goes before an existing `verifies:` one.
216
+ if (blockName === 'implementations') {
217
+ for (let i = start + 1; i < proseEnd; i++) {
218
+ if (/^verifies:\s*$/.test(lines[i] ?? '')) {
219
+ proseEnd = i;
220
+ break;
221
+ }
222
+ }
223
+ }
224
+ let insertAt = proseEnd;
225
+ while (insertAt > start + 1 && (lines[insertAt - 1] ?? '').trim() === '')
226
+ insertAt--;
227
+ const inserted = ['', `${blockName}:`, bullet];
228
+ if (insertAt < lines.length)
229
+ inserted.push('');
230
+ // Collapse the blank line(s) we trimmed past so spacing stays single.
231
+ let removeBlanks = 0;
232
+ while (insertAt + removeBlanks < proseEnd && (lines[insertAt + removeBlanks] ?? '').trim() === '') {
233
+ removeBlanks++;
234
+ }
235
+ lines.splice(insertAt, removeBlanks, ...inserted);
236
+ }
237
+ fs.writeFileSync(specAbs, lines.join(eol), 'utf8');
238
+ return {
239
+ status: 'persisted',
240
+ requirementId,
241
+ specFile,
242
+ detail: `${blockName}: entry ${target} written to ${specFile}`,
243
+ };
244
+ }
245
+ catch (err) {
246
+ return refuse(err instanceof Error ? err.message : String(err));
247
+ }
248
+ }
249
+ //# sourceMappingURL=link-persist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-persist.js","sourceRoot":"","sources":["../../src/spec-quality/link-persist.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Small-plan auto-approval (THROUGHPUT-DOC, REQ-THRU-003).
3
+ *
4
+ * A plan may skip the human plan gate ONLY when the project opted in
5
+ * (`workflow.autoApproveSmallPlans: true` in specship.config.json), every
6
+ * source file it names is already one of the requirement's
7
+ * `implementations:` files, and the requirement has at most
8
+ * `workflow.smallPlanMaxCriteria` (default 3) acceptance criteria. Test files,
9
+ * the requirement's own spec file and CHANGELOG.md never count against the
10
+ * scope — a good plan always names them. The final review is never skipped.
11
+ *
12
+ * Deterministic and file-based, so it runs inside a workflow worktree. The
13
+ * AUTO_APPROVE=yes|no marker is the contract the approval step reads.
14
+ */
15
+ export declare const DEFAULT_SMALL_PLAN_MAX_CRITERIA = 3;
16
+ export interface PlanScopeInput {
17
+ planText: string;
18
+ /** Files named by the requirement's `implementations:` bullets. */
19
+ implementationFiles: string[];
20
+ criteriaCount: number;
21
+ optIn: boolean;
22
+ maxCriteria?: number;
23
+ /** The requirement's spec file (project-relative), always in scope. */
24
+ specFile?: string;
25
+ }
26
+ export interface PlanScopeResult {
27
+ autoApprove: boolean;
28
+ reasons: string[];
29
+ /** Source files the plan names that are outside the requirement's implementations. */
30
+ outOfScope: string[];
31
+ }
32
+ /** Project-relative file paths a plan names (deduplicated, in order). */
33
+ export declare function filesNamedInPlan(planText: string): string[];
34
+ export declare function assessPlanScope(input: PlanScopeInput): PlanScopeResult;
35
+ /** File-based loader: reads the requirement block and the project's opt-in. */
36
+ export declare function assessPlanScopeFromFile(projectRoot: string, requirementId: string, planText: string): PlanScopeResult;
37
+ export declare function formatPlanScope(result: PlanScopeResult): string;
38
+ //# sourceMappingURL=plan-scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-scope.d.ts","sourceRoot":"","sources":["../../src/spec-quality/plan-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sFAAsF;IACtF,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAOD,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAS3D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CAmBtE;AAgBD,+EAA+E;AAC/E,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAmBrH;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAE/D"}