@sun-asterisk/sungen 3.2.34 → 3.3.0-alpha.1

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 (866) hide show
  1. package/dist/basis/anchor-grammar.d.ts +32 -0
  2. package/dist/basis/anchor-grammar.d.ts.map +1 -0
  3. package/dist/basis/anchor-grammar.js +82 -0
  4. package/dist/basis/anchor-grammar.js.map +1 -0
  5. package/dist/basis/anchor-hash.d.ts +6 -0
  6. package/dist/basis/anchor-hash.d.ts.map +1 -0
  7. package/dist/basis/anchor-hash.js +28 -0
  8. package/dist/basis/anchor-hash.js.map +1 -0
  9. package/dist/basis/bm51-tables.d.ts +20 -0
  10. package/dist/basis/bm51-tables.d.ts.map +1 -0
  11. package/dist/basis/bm51-tables.js +71 -0
  12. package/dist/basis/bm51-tables.js.map +1 -0
  13. package/dist/basis/extract-spec-anchors.d.ts +39 -0
  14. package/dist/basis/extract-spec-anchors.d.ts.map +1 -0
  15. package/dist/basis/extract-spec-anchors.js +81 -0
  16. package/dist/basis/extract-spec-anchors.js.map +1 -0
  17. package/dist/basis/migration-sentinel.d.ts +47 -0
  18. package/dist/basis/migration-sentinel.d.ts.map +1 -0
  19. package/dist/basis/migration-sentinel.js +219 -0
  20. package/dist/basis/migration-sentinel.js.map +1 -0
  21. package/dist/basis/spec-frontmatter.d.ts +18 -0
  22. package/dist/basis/spec-frontmatter.d.ts.map +1 -0
  23. package/dist/basis/spec-frontmatter.js +55 -0
  24. package/dist/basis/spec-frontmatter.js.map +1 -0
  25. package/dist/basis/spec-sections.d.ts +18 -0
  26. package/dist/basis/spec-sections.d.ts.map +1 -0
  27. package/dist/basis/spec-sections.js +27 -0
  28. package/dist/basis/spec-sections.js.map +1 -0
  29. package/dist/basis/test-basis-schema.d.ts +28 -0
  30. package/dist/basis/test-basis-schema.d.ts.map +1 -0
  31. package/dist/basis/test-basis-schema.js +141 -0
  32. package/dist/basis/test-basis-schema.js.map +1 -0
  33. package/dist/capabilities/registry.d.ts +15 -0
  34. package/dist/capabilities/registry.d.ts.map +1 -1
  35. package/dist/capabilities/registry.js.map +1 -1
  36. package/dist/cli/commands/audit.d.ts.map +1 -1
  37. package/dist/cli/commands/audit.js +9 -4
  38. package/dist/cli/commands/audit.js.map +1 -1
  39. package/dist/cli/commands/capability.d.ts.map +1 -1
  40. package/dist/cli/commands/capability.js +6 -2
  41. package/dist/cli/commands/capability.js.map +1 -1
  42. package/dist/cli/commands/contract-derive-command.d.ts +10 -0
  43. package/dist/cli/commands/contract-derive-command.d.ts.map +1 -0
  44. package/dist/cli/commands/contract-derive-command.js +99 -0
  45. package/dist/cli/commands/contract-derive-command.js.map +1 -0
  46. package/dist/cli/commands/contract.d.ts +17 -0
  47. package/dist/cli/commands/contract.d.ts.map +1 -0
  48. package/dist/cli/commands/contract.js +162 -0
  49. package/dist/cli/commands/contract.js.map +1 -0
  50. package/dist/cli/commands/defect.d.ts +7 -0
  51. package/dist/cli/commands/defect.d.ts.map +1 -0
  52. package/dist/cli/commands/defect.js +68 -0
  53. package/dist/cli/commands/defect.js.map +1 -0
  54. package/dist/cli/commands/delivery.d.ts.map +1 -1
  55. package/dist/cli/commands/delivery.js +87 -10
  56. package/dist/cli/commands/delivery.js.map +1 -1
  57. package/dist/cli/commands/generate.d.ts.map +1 -1
  58. package/dist/cli/commands/generate.js +3 -1
  59. package/dist/cli/commands/generate.js.map +1 -1
  60. package/dist/cli/commands/journey.d.ts.map +1 -1
  61. package/dist/cli/commands/journey.js +41 -13
  62. package/dist/cli/commands/journey.js.map +1 -1
  63. package/dist/cli/commands/next.d.ts +8 -0
  64. package/dist/cli/commands/next.d.ts.map +1 -1
  65. package/dist/cli/commands/next.js +64 -6
  66. package/dist/cli/commands/next.js.map +1 -1
  67. package/dist/cli/commands/triage.d.ts +7 -0
  68. package/dist/cli/commands/triage.d.ts.map +1 -0
  69. package/dist/cli/commands/triage.js +98 -0
  70. package/dist/cli/commands/triage.js.map +1 -0
  71. package/dist/cli/commands/update.d.ts +11 -0
  72. package/dist/cli/commands/update.d.ts.map +1 -1
  73. package/dist/cli/commands/update.js +31 -6
  74. package/dist/cli/commands/update.js.map +1 -1
  75. package/dist/cli/index.js +24 -33
  76. package/dist/cli/index.js.map +1 -1
  77. package/dist/contract/approve-contract.d.ts +31 -0
  78. package/dist/contract/approve-contract.d.ts.map +1 -0
  79. package/dist/contract/approve-contract.js +87 -0
  80. package/dist/contract/approve-contract.js.map +1 -0
  81. package/dist/contract/assertion-matcher-vocabulary.d.ts +24 -0
  82. package/dist/contract/assertion-matcher-vocabulary.d.ts.map +1 -0
  83. package/dist/contract/assertion-matcher-vocabulary.js +100 -0
  84. package/dist/contract/assertion-matcher-vocabulary.js.map +1 -0
  85. package/dist/contract/build-contract-verdict.d.ts +32 -0
  86. package/dist/contract/build-contract-verdict.d.ts.map +1 -0
  87. package/dist/contract/build-contract-verdict.js +123 -0
  88. package/dist/contract/build-contract-verdict.js.map +1 -0
  89. package/dist/contract/build-trace-conformance.d.ts +18 -0
  90. package/dist/contract/build-trace-conformance.d.ts.map +1 -0
  91. package/dist/contract/build-trace-conformance.js +153 -0
  92. package/dist/contract/build-trace-conformance.js.map +1 -0
  93. package/dist/contract/classify-contract-change.d.ts +23 -0
  94. package/dist/contract/classify-contract-change.d.ts.map +1 -0
  95. package/dist/contract/classify-contract-change.js +98 -0
  96. package/dist/contract/classify-contract-change.js.map +1 -0
  97. package/dist/contract/classify-contract-unit.d.ts +18 -0
  98. package/dist/contract/classify-contract-unit.d.ts.map +1 -0
  99. package/dist/contract/classify-contract-unit.js +49 -0
  100. package/dist/contract/classify-contract-unit.js.map +1 -0
  101. package/dist/contract/classify-trace-conformance.d.ts +32 -0
  102. package/dist/contract/classify-trace-conformance.d.ts.map +1 -0
  103. package/dist/contract/classify-trace-conformance.js +117 -0
  104. package/dist/contract/classify-trace-conformance.js.map +1 -0
  105. package/dist/contract/contract-git.d.ts +24 -0
  106. package/dist/contract/contract-git.d.ts.map +1 -0
  107. package/dist/contract/contract-git.js +144 -0
  108. package/dist/contract/contract-git.js.map +1 -0
  109. package/dist/contract/contract-hash.d.ts +7 -0
  110. package/dist/contract/contract-hash.d.ts.map +1 -0
  111. package/dist/contract/contract-hash.js +38 -0
  112. package/dist/contract/contract-hash.js.map +1 -0
  113. package/dist/contract/contract-report-file.d.ts +4 -0
  114. package/dist/contract/contract-report-file.d.ts.map +1 -0
  115. package/dist/contract/contract-report-file.js +60 -0
  116. package/dist/contract/contract-report-file.js.map +1 -0
  117. package/dist/contract/contract-schema.d.ts +71 -0
  118. package/dist/contract/contract-schema.d.ts.map +1 -0
  119. package/dist/contract/contract-schema.js +102 -0
  120. package/dist/contract/contract-schema.js.map +1 -0
  121. package/dist/contract/contract-units.d.ts +12 -0
  122. package/dist/contract/contract-units.d.ts.map +1 -0
  123. package/dist/contract/contract-units.js +96 -0
  124. package/dist/contract/contract-units.js.map +1 -0
  125. package/dist/contract/contracts-lock-file.d.ts +24 -0
  126. package/dist/contract/contracts-lock-file.d.ts.map +1 -0
  127. package/dist/contract/contracts-lock-file.js +140 -0
  128. package/dist/contract/contracts-lock-file.js.map +1 -0
  129. package/dist/contract/data-normalize.d.ts +10 -0
  130. package/dist/contract/data-normalize.d.ts.map +1 -0
  131. package/dist/contract/data-normalize.js +110 -0
  132. package/dist/contract/data-normalize.js.map +1 -0
  133. package/dist/contract/derive-free-feature.d.ts +30 -0
  134. package/dist/contract/derive-free-feature.d.ts.map +1 -0
  135. package/dist/contract/derive-free-feature.js +145 -0
  136. package/dist/contract/derive-free-feature.js.map +1 -0
  137. package/dist/contract/field-semantic-redaction.d.ts +21 -0
  138. package/dist/contract/field-semantic-redaction.d.ts.map +1 -0
  139. package/dist/contract/field-semantic-redaction.js +118 -0
  140. package/dist/contract/field-semantic-redaction.js.map +1 -0
  141. package/dist/contract/free-feature-blocks.d.ts +10 -0
  142. package/dist/contract/free-feature-blocks.d.ts.map +1 -0
  143. package/dist/contract/free-feature-blocks.js +94 -0
  144. package/dist/contract/free-feature-blocks.js.map +1 -0
  145. package/dist/contract/lock-secret-guard.d.ts +22 -0
  146. package/dist/contract/lock-secret-guard.d.ts.map +1 -0
  147. package/dist/contract/lock-secret-guard.js +134 -0
  148. package/dist/contract/lock-secret-guard.js.map +1 -0
  149. package/dist/contract/lock-vs-git-head.d.ts +26 -0
  150. package/dist/contract/lock-vs-git-head.d.ts.map +1 -0
  151. package/dist/contract/lock-vs-git-head.js +28 -0
  152. package/dist/contract/lock-vs-git-head.js.map +1 -0
  153. package/dist/contract/normalize-contract-step.d.ts +21 -0
  154. package/dist/contract/normalize-contract-step.d.ts.map +1 -0
  155. package/dist/contract/normalize-contract-step.js +70 -0
  156. package/dist/contract/normalize-contract-step.js.map +1 -0
  157. package/dist/contract/normalize-feature-steps.d.ts +7 -0
  158. package/dist/contract/normalize-feature-steps.d.ts.map +1 -0
  159. package/dist/contract/normalize-feature-steps.js +127 -0
  160. package/dist/contract/normalize-feature-steps.js.map +1 -0
  161. package/dist/contract/oracle-strength.d.ts +12 -0
  162. package/dist/contract/oracle-strength.d.ts.map +1 -0
  163. package/dist/contract/oracle-strength.js +88 -0
  164. package/dist/contract/oracle-strength.js.map +1 -0
  165. package/dist/contract/project-contract-blockers.d.ts +10 -0
  166. package/dist/contract/project-contract-blockers.d.ts.map +1 -0
  167. package/dist/contract/project-contract-blockers.js +73 -0
  168. package/dist/contract/project-contract-blockers.js.map +1 -0
  169. package/dist/contract/record-contract-approval.d.ts +21 -0
  170. package/dist/contract/record-contract-approval.d.ts.map +1 -0
  171. package/dist/contract/record-contract-approval.js +98 -0
  172. package/dist/contract/record-contract-approval.js.map +1 -0
  173. package/dist/contract/render-free-gherkin.d.ts +40 -0
  174. package/dist/contract/render-free-gherkin.d.ts.map +1 -0
  175. package/dist/contract/render-free-gherkin.js +141 -0
  176. package/dist/contract/render-free-gherkin.js.map +1 -0
  177. package/dist/contract/render-trace-sentence.d.ts +20 -0
  178. package/dist/contract/render-trace-sentence.d.ts.map +1 -0
  179. package/dist/contract/render-trace-sentence.js +109 -0
  180. package/dist/contract/render-trace-sentence.js.map +1 -0
  181. package/dist/contract/render-trace-target.d.ts +14 -0
  182. package/dist/contract/render-trace-target.d.ts.map +1 -0
  183. package/dist/contract/render-trace-target.js +70 -0
  184. package/dist/contract/render-trace-target.js.map +1 -0
  185. package/dist/contract/resolve-unit-trace-identities.d.ts +8 -0
  186. package/dist/contract/resolve-unit-trace-identities.d.ts.map +1 -0
  187. package/dist/contract/resolve-unit-trace-identities.js +78 -0
  188. package/dist/contract/resolve-unit-trace-identities.js.map +1 -0
  189. package/dist/contract/trace/collect-trace-evidence.d.ts +33 -0
  190. package/dist/contract/trace/collect-trace-evidence.d.ts.map +1 -0
  191. package/dist/contract/trace/collect-trace-evidence.js +161 -0
  192. package/dist/contract/trace/collect-trace-evidence.js.map +1 -0
  193. package/dist/contract/trace/identity-cache.d.ts +19 -0
  194. package/dist/contract/trace/identity-cache.d.ts.map +1 -0
  195. package/dist/contract/trace/identity-cache.js +104 -0
  196. package/dist/contract/trace/identity-cache.js.map +1 -0
  197. package/dist/contract/trace/select-final-attempt.d.ts +27 -0
  198. package/dist/contract/trace/select-final-attempt.d.ts.map +1 -0
  199. package/dist/contract/trace/select-final-attempt.js +116 -0
  200. package/dist/contract/trace/select-final-attempt.js.map +1 -0
  201. package/dist/contract/trace/snapshot-html-renderer.d.ts +31 -0
  202. package/dist/contract/trace/snapshot-html-renderer.d.ts.map +1 -0
  203. package/dist/contract/trace/snapshot-html-renderer.js +172 -0
  204. package/dist/contract/trace/snapshot-html-renderer.js.map +1 -0
  205. package/dist/contract/trace/snapshot-resolver.d.ts +21 -0
  206. package/dist/contract/trace/snapshot-resolver.d.ts.map +1 -0
  207. package/dist/contract/trace/snapshot-resolver.js +65 -0
  208. package/dist/contract/trace/snapshot-resolver.js.map +1 -0
  209. package/dist/contract/trace/snapshot-store.d.ts +66 -0
  210. package/dist/contract/trace/snapshot-store.d.ts.map +1 -0
  211. package/dist/contract/trace/snapshot-store.js +173 -0
  212. package/dist/contract/trace/snapshot-store.js.map +1 -0
  213. package/dist/contract/trace/target-identity.d.ts +74 -0
  214. package/dist/contract/trace/target-identity.d.ts.map +1 -0
  215. package/dist/contract/trace/target-identity.js +68 -0
  216. package/dist/contract/trace/target-identity.js.map +1 -0
  217. package/dist/contract/trace/test-step-join.d.ts +65 -0
  218. package/dist/contract/trace/test-step-join.d.ts.map +1 -0
  219. package/dist/contract/trace/test-step-join.js +80 -0
  220. package/dist/contract/trace/test-step-join.js.map +1 -0
  221. package/dist/contract/trace/trace-binding.d.ts +21 -0
  222. package/dist/contract/trace/trace-binding.d.ts.map +1 -0
  223. package/dist/contract/trace/trace-binding.js +88 -0
  224. package/dist/contract/trace/trace-binding.js.map +1 -0
  225. package/dist/contract/trace/trace-file-reader.d.ts +35 -0
  226. package/dist/contract/trace/trace-file-reader.d.ts.map +1 -0
  227. package/dist/contract/trace/trace-file-reader.js +155 -0
  228. package/dist/contract/trace/trace-file-reader.js.map +1 -0
  229. package/dist/contract/trace/trace-fingerprint.d.ts +22 -0
  230. package/dist/contract/trace/trace-fingerprint.d.ts.map +1 -0
  231. package/dist/contract/trace/trace-fingerprint.js +96 -0
  232. package/dist/contract/trace/trace-fingerprint.js.map +1 -0
  233. package/dist/contract/trace/trace-identity-resolution.d.ts +26 -0
  234. package/dist/contract/trace/trace-identity-resolution.d.ts.map +1 -0
  235. package/dist/contract/trace/trace-identity-resolution.js +84 -0
  236. package/dist/contract/trace/trace-identity-resolution.js.map +1 -0
  237. package/dist/contract/trace/trace-run-record.d.ts +27 -0
  238. package/dist/contract/trace/trace-run-record.d.ts.map +1 -0
  239. package/dist/contract/trace/trace-run-record.js +115 -0
  240. package/dist/contract/trace/trace-run-record.js.map +1 -0
  241. package/dist/contract/trace/trace-steps.d.ts +19 -0
  242. package/dist/contract/trace/trace-steps.d.ts.map +1 -0
  243. package/dist/contract/trace/trace-steps.js +79 -0
  244. package/dist/contract/trace/trace-steps.js.map +1 -0
  245. package/dist/contract/trace/trace-zip-limits.d.ts +41 -0
  246. package/dist/contract/trace/trace-zip-limits.d.ts.map +1 -0
  247. package/dist/contract/trace/trace-zip-limits.js +48 -0
  248. package/dist/contract/trace/trace-zip-limits.js.map +1 -0
  249. package/dist/contract/trace/trace-zip-reader.d.ts +10 -0
  250. package/dist/contract/trace/trace-zip-reader.d.ts.map +1 -0
  251. package/dist/contract/trace/trace-zip-reader.js +186 -0
  252. package/dist/contract/trace/trace-zip-reader.js.map +1 -0
  253. package/dist/contract/verify-approval-decisions.d.ts +5 -0
  254. package/dist/contract/verify-approval-decisions.d.ts.map +1 -0
  255. package/dist/contract/verify-approval-decisions.js +104 -0
  256. package/dist/contract/verify-approval-decisions.js.map +1 -0
  257. package/dist/decisions/append-decision.d.ts +12 -0
  258. package/dist/decisions/append-decision.d.ts.map +1 -0
  259. package/dist/decisions/append-decision.js +73 -0
  260. package/dist/decisions/append-decision.js.map +1 -0
  261. package/dist/decisions/confirmed-decision-commands.d.ts +30 -0
  262. package/dist/decisions/confirmed-decision-commands.d.ts.map +1 -0
  263. package/dist/decisions/confirmed-decision-commands.js +172 -0
  264. package/dist/decisions/confirmed-decision-commands.js.map +1 -0
  265. package/dist/decisions/decision-file.d.ts +31 -0
  266. package/dist/decisions/decision-file.d.ts.map +1 -0
  267. package/dist/decisions/decision-file.js +139 -0
  268. package/dist/decisions/decision-file.js.map +1 -0
  269. package/dist/decisions/decision-identity.d.ts +12 -0
  270. package/dist/decisions/decision-identity.d.ts.map +1 -0
  271. package/dist/decisions/decision-identity.js +78 -0
  272. package/dist/decisions/decision-identity.js.map +1 -0
  273. package/dist/decisions/decision-integrity-check.d.ts +12 -0
  274. package/dist/decisions/decision-integrity-check.d.ts.map +1 -0
  275. package/dist/decisions/decision-integrity-check.js +102 -0
  276. package/dist/decisions/decision-integrity-check.js.map +1 -0
  277. package/dist/decisions/decision-schema.d.ts +42 -0
  278. package/dist/decisions/decision-schema.d.ts.map +1 -0
  279. package/dist/decisions/decision-schema.js +75 -0
  280. package/dist/decisions/decision-schema.js.map +1 -0
  281. package/dist/decisions/decision-source.d.ts +2 -0
  282. package/dist/decisions/decision-source.d.ts.map +1 -0
  283. package/dist/decisions/decision-source.js +18 -0
  284. package/dist/decisions/decision-source.js.map +1 -0
  285. package/dist/decisions/exclusive-file-create.d.ts +3 -0
  286. package/dist/decisions/exclusive-file-create.d.ts.map +1 -0
  287. package/dist/decisions/exclusive-file-create.js +84 -0
  288. package/dist/decisions/exclusive-file-create.js.map +1 -0
  289. package/dist/decisions/git-head-trust.d.ts +7 -0
  290. package/dist/decisions/git-head-trust.d.ts.map +1 -0
  291. package/dist/decisions/git-head-trust.js +76 -0
  292. package/dist/decisions/git-head-trust.js.map +1 -0
  293. package/dist/decisions/human-confirmation.d.ts +33 -0
  294. package/dist/decisions/human-confirmation.d.ts.map +1 -0
  295. package/dist/decisions/human-confirmation.js +155 -0
  296. package/dist/decisions/human-confirmation.js.map +1 -0
  297. package/dist/decisions/legacy-waiver-migration.d.ts +31 -0
  298. package/dist/decisions/legacy-waiver-migration.d.ts.map +1 -0
  299. package/dist/decisions/legacy-waiver-migration.js +170 -0
  300. package/dist/decisions/legacy-waiver-migration.js.map +1 -0
  301. package/dist/decisions/read-decisions.d.ts +19 -0
  302. package/dist/decisions/read-decisions.d.ts.map +1 -0
  303. package/dist/decisions/read-decisions.js +90 -0
  304. package/dist/decisions/read-decisions.js.map +1 -0
  305. package/dist/decisions/viewpoint-baseline-adapter.d.ts +7 -0
  306. package/dist/decisions/viewpoint-baseline-adapter.d.ts.map +1 -0
  307. package/dist/decisions/viewpoint-baseline-adapter.js +109 -0
  308. package/dist/decisions/viewpoint-baseline-adapter.js.map +1 -0
  309. package/dist/decisions/waiver-decisions.d.ts +24 -0
  310. package/dist/decisions/waiver-decisions.d.ts.map +1 -0
  311. package/dist/decisions/waiver-decisions.js +46 -0
  312. package/dist/decisions/waiver-decisions.js.map +1 -0
  313. package/dist/exporters/csv-exporter.d.ts +4 -0
  314. package/dist/exporters/csv-exporter.d.ts.map +1 -1
  315. package/dist/exporters/csv-exporter.js +1 -1
  316. package/dist/exporters/csv-exporter.js.map +1 -1
  317. package/dist/exporters/feature-parser.d.ts +8 -0
  318. package/dist/exporters/feature-parser.d.ts.map +1 -1
  319. package/dist/exporters/feature-parser.js +12 -0
  320. package/dist/exporters/feature-parser.js.map +1 -1
  321. package/dist/exporters/matrix/build.d.ts +3 -0
  322. package/dist/exporters/matrix/build.d.ts.map +1 -1
  323. package/dist/exporters/matrix/build.js +59 -19
  324. package/dist/exporters/matrix/build.js.map +1 -1
  325. package/dist/exporters/matrix/carry-manual-results.d.ts +19 -0
  326. package/dist/exporters/matrix/carry-manual-results.d.ts.map +1 -1
  327. package/dist/exporters/matrix/carry-manual-results.js +76 -6
  328. package/dist/exporters/matrix/carry-manual-results.js.map +1 -1
  329. package/dist/exporters/matrix/export.d.ts +8 -2
  330. package/dist/exporters/matrix/export.d.ts.map +1 -1
  331. package/dist/exporters/matrix/export.js +16 -3
  332. package/dist/exporters/matrix/export.js.map +1 -1
  333. package/dist/exporters/matrix/gates.d.ts +6 -1
  334. package/dist/exporters/matrix/gates.d.ts.map +1 -1
  335. package/dist/exporters/matrix/gates.js +57 -128
  336. package/dist/exporters/matrix/gates.js.map +1 -1
  337. package/dist/exporters/matrix/render-csv.d.ts.map +1 -1
  338. package/dist/exporters/matrix/render-csv.js +4 -1
  339. package/dist/exporters/matrix/render-csv.js.map +1 -1
  340. package/dist/exporters/matrix/render-gate-overrides-sheet.d.ts +13 -0
  341. package/dist/exporters/matrix/render-gate-overrides-sheet.d.ts.map +1 -0
  342. package/dist/exporters/matrix/render-gate-overrides-sheet.js +44 -0
  343. package/dist/exporters/matrix/render-gate-overrides-sheet.js.map +1 -0
  344. package/dist/exporters/matrix/render-xlsx.d.ts +1 -0
  345. package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
  346. package/dist/exporters/matrix/render-xlsx.js +6 -0
  347. package/dist/exporters/matrix/render-xlsx.js.map +1 -1
  348. package/dist/exporters/matrix/types.d.ts +9 -1
  349. package/dist/exporters/matrix/types.d.ts.map +1 -1
  350. package/dist/exporters/matrix/types.js.map +1 -1
  351. package/dist/exporters/playwright-report-parser.d.ts.map +1 -1
  352. package/dist/exporters/playwright-report-parser.js +1 -0
  353. package/dist/exporters/playwright-report-parser.js.map +1 -1
  354. package/dist/exporters/scenario-merger.d.ts.map +1 -1
  355. package/dist/exporters/scenario-merger.js +2 -0
  356. package/dist/exporters/scenario-merger.js.map +1 -1
  357. package/dist/exporters/types.d.ts +5 -0
  358. package/dist/exporters/types.d.ts.map +1 -1
  359. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  360. package/dist/generators/test-generator/code-generator.js +13 -0
  361. package/dist/generators/test-generator/code-generator.js.map +1 -1
  362. package/dist/graph/evaluate-graph.d.ts +21 -0
  363. package/dist/graph/evaluate-graph.d.ts.map +1 -0
  364. package/dist/graph/evaluate-graph.js +49 -0
  365. package/dist/graph/evaluate-graph.js.map +1 -0
  366. package/dist/graph/locate-finding.d.ts +20 -0
  367. package/dist/graph/locate-finding.d.ts.map +1 -0
  368. package/dist/graph/locate-finding.js +137 -0
  369. package/dist/graph/locate-finding.js.map +1 -0
  370. package/dist/graph/node-decl.d.ts +59 -0
  371. package/dist/graph/node-decl.d.ts.map +1 -0
  372. package/dist/graph/node-decl.js +8 -0
  373. package/dist/graph/node-decl.js.map +1 -0
  374. package/dist/graph/nodes/core-node-catalog.d.ts +7 -0
  375. package/dist/graph/nodes/core-node-catalog.d.ts.map +1 -0
  376. package/dist/graph/nodes/core-node-catalog.js +13 -0
  377. package/dist/graph/nodes/core-node-catalog.js.map +1 -0
  378. package/dist/graph/nodes/test-case-contract-nodes.d.ts +19 -0
  379. package/dist/graph/nodes/test-case-contract-nodes.d.ts.map +1 -0
  380. package/dist/graph/nodes/test-case-contract-nodes.js +56 -0
  381. package/dist/graph/nodes/test-case-contract-nodes.js.map +1 -0
  382. package/dist/graph/nodes/test-case-nodes.d.ts +26 -0
  383. package/dist/graph/nodes/test-case-nodes.d.ts.map +1 -0
  384. package/dist/graph/nodes/test-case-nodes.js +66 -0
  385. package/dist/graph/nodes/test-case-nodes.js.map +1 -0
  386. package/dist/graph/nodes/unit-audit-nodes.d.ts +18 -0
  387. package/dist/graph/nodes/unit-audit-nodes.d.ts.map +1 -0
  388. package/dist/graph/nodes/unit-audit-nodes.js +95 -0
  389. package/dist/graph/nodes/unit-audit-nodes.js.map +1 -0
  390. package/dist/graph/nodes/unit-contract-node.d.ts +20 -0
  391. package/dist/graph/nodes/unit-contract-node.d.ts.map +1 -0
  392. package/dist/graph/nodes/unit-contract-node.js +81 -0
  393. package/dist/graph/nodes/unit-contract-node.js.map +1 -0
  394. package/dist/graph/nodes/unit-design-nodes.d.ts +14 -0
  395. package/dist/graph/nodes/unit-design-nodes.d.ts.map +1 -0
  396. package/dist/graph/nodes/unit-design-nodes.js +90 -0
  397. package/dist/graph/nodes/unit-design-nodes.js.map +1 -0
  398. package/dist/graph/nodes/unit-execution-nodes.d.ts +16 -0
  399. package/dist/graph/nodes/unit-execution-nodes.d.ts.map +1 -0
  400. package/dist/graph/nodes/unit-execution-nodes.js +79 -0
  401. package/dist/graph/nodes/unit-execution-nodes.js.map +1 -0
  402. package/dist/graph/test-case-identity.d.ts +13 -0
  403. package/dist/graph/test-case-identity.d.ts.map +1 -0
  404. package/dist/graph/test-case-identity.js +106 -0
  405. package/dist/graph/test-case-identity.js.map +1 -0
  406. package/dist/graph/test-case-results.d.ts +11 -0
  407. package/dist/graph/test-case-results.d.ts.map +1 -0
  408. package/dist/graph/test-case-results.js +137 -0
  409. package/dist/graph/test-case-results.js.map +1 -0
  410. package/dist/graph/test-case-satisfied.d.ts +25 -0
  411. package/dist/graph/test-case-satisfied.d.ts.map +1 -0
  412. package/dist/graph/test-case-satisfied.js +51 -0
  413. package/dist/graph/test-case-satisfied.js.map +1 -0
  414. package/dist/graph/test-case-state-shape.d.ts +67 -0
  415. package/dist/graph/test-case-state-shape.d.ts.map +1 -0
  416. package/dist/graph/test-case-state-shape.js +3 -0
  417. package/dist/graph/test-case-state-shape.js.map +1 -0
  418. package/dist/graph/test-case-states.d.ts +9 -0
  419. package/dist/graph/test-case-states.d.ts.map +1 -0
  420. package/dist/graph/test-case-states.js +116 -0
  421. package/dist/graph/test-case-states.js.map +1 -0
  422. package/dist/graph/unit-artifact-probes.d.ts +19 -0
  423. package/dist/graph/unit-artifact-probes.d.ts.map +1 -0
  424. package/dist/graph/unit-artifact-probes.js +133 -0
  425. package/dist/graph/unit-artifact-probes.js.map +1 -0
  426. package/dist/graph/unit-state-facts.d.ts +43 -0
  427. package/dist/graph/unit-state-facts.d.ts.map +1 -0
  428. package/dist/graph/unit-state-facts.js +87 -0
  429. package/dist/graph/unit-state-facts.js.map +1 -0
  430. package/dist/harness/audit.d.ts +11 -0
  431. package/dist/harness/audit.d.ts.map +1 -1
  432. package/dist/harness/audit.js +34 -9
  433. package/dist/harness/audit.js.map +1 -1
  434. package/dist/harness/catalog/gate-rules.yaml +647 -0
  435. package/dist/harness/counted-assertions.d.ts +2 -0
  436. package/dist/harness/counted-assertions.d.ts.map +1 -0
  437. package/dist/harness/counted-assertions.js +38 -0
  438. package/dist/harness/counted-assertions.js.map +1 -0
  439. package/dist/harness/defect-draft.d.ts +14 -0
  440. package/dist/harness/defect-draft.d.ts.map +1 -0
  441. package/dist/harness/defect-draft.js +143 -0
  442. package/dist/harness/defect-draft.js.map +1 -0
  443. package/dist/harness/defects.d.ts +24 -0
  444. package/dist/harness/defects.d.ts.map +1 -0
  445. package/dist/harness/defects.js +118 -0
  446. package/dist/harness/defects.js.map +1 -0
  447. package/dist/harness/gates/audit-gate-terms.d.ts +41 -0
  448. package/dist/harness/gates/audit-gate-terms.d.ts.map +1 -0
  449. package/dist/harness/gates/audit-gate-terms.js +72 -0
  450. package/dist/harness/gates/audit-gate-terms.js.map +1 -0
  451. package/dist/harness/gates/audit-gate-verdict.d.ts +31 -0
  452. package/dist/harness/gates/audit-gate-verdict.d.ts.map +1 -0
  453. package/dist/harness/gates/audit-gate-verdict.js +101 -0
  454. package/dist/harness/gates/audit-gate-verdict.js.map +1 -0
  455. package/dist/harness/gates/audit-input-hash.d.ts +4 -0
  456. package/dist/harness/gates/audit-input-hash.d.ts.map +1 -0
  457. package/dist/harness/gates/audit-input-hash.js +96 -0
  458. package/dist/harness/gates/audit-input-hash.js.map +1 -0
  459. package/dist/harness/gates/audit-report-verification.d.ts +32 -0
  460. package/dist/harness/gates/audit-report-verification.d.ts.map +1 -0
  461. package/dist/harness/gates/audit-report-verification.js +207 -0
  462. package/dist/harness/gates/audit-report-verification.js.map +1 -0
  463. package/dist/harness/gates/decisions-hash.d.ts +13 -0
  464. package/dist/harness/gates/decisions-hash.d.ts.map +1 -0
  465. package/dist/harness/gates/decisions-hash.js +72 -0
  466. package/dist/harness/gates/decisions-hash.js.map +1 -0
  467. package/dist/harness/gates/delivery-checklist.d.ts +21 -0
  468. package/dist/harness/gates/delivery-checklist.d.ts.map +1 -0
  469. package/dist/harness/gates/delivery-checklist.js +128 -0
  470. package/dist/harness/gates/delivery-checklist.js.map +1 -0
  471. package/dist/harness/gates/delivery-decision-gate.d.ts +29 -0
  472. package/dist/harness/gates/delivery-decision-gate.d.ts.map +1 -0
  473. package/dist/harness/gates/delivery-decision-gate.js +91 -0
  474. package/dist/harness/gates/delivery-decision-gate.js.map +1 -0
  475. package/dist/harness/gates/delivery-decision-step.d.ts +16 -0
  476. package/dist/harness/gates/delivery-decision-step.d.ts.map +1 -0
  477. package/dist/harness/gates/delivery-decision-step.js +71 -0
  478. package/dist/harness/gates/delivery-decision-step.js.map +1 -0
  479. package/dist/harness/gates/gate-override-report.d.ts +59 -0
  480. package/dist/harness/gates/gate-override-report.d.ts.map +1 -0
  481. package/dist/harness/gates/gate-override-report.js +86 -0
  482. package/dist/harness/gates/gate-override-report.js.map +1 -0
  483. package/dist/harness/gates/gate-override-scope.d.ts +18 -0
  484. package/dist/harness/gates/gate-override-scope.d.ts.map +1 -0
  485. package/dist/harness/gates/gate-override-scope.js +98 -0
  486. package/dist/harness/gates/gate-override-scope.js.map +1 -0
  487. package/dist/harness/gates/gate-override-validation.d.ts +25 -0
  488. package/dist/harness/gates/gate-override-validation.d.ts.map +1 -0
  489. package/dist/harness/gates/gate-override-validation.js +81 -0
  490. package/dist/harness/gates/gate-override-validation.js.map +1 -0
  491. package/dist/harness/gates/gate-rule-catalog.d.ts +24 -0
  492. package/dist/harness/gates/gate-rule-catalog.d.ts.map +1 -0
  493. package/dist/harness/gates/gate-rule-catalog.js +112 -0
  494. package/dist/harness/gates/gate-rule-catalog.js.map +1 -0
  495. package/dist/harness/gates/gate-terms.d.ts +33 -0
  496. package/dist/harness/gates/gate-terms.d.ts.map +1 -0
  497. package/dist/harness/gates/gate-terms.js +41 -0
  498. package/dist/harness/gates/gate-terms.js.map +1 -0
  499. package/dist/harness/gates/in-run-decision-check.d.ts +21 -0
  500. package/dist/harness/gates/in-run-decision-check.d.ts.map +1 -0
  501. package/dist/harness/gates/in-run-decision-check.js +138 -0
  502. package/dist/harness/gates/in-run-decision-check.js.map +1 -0
  503. package/dist/harness/gates/journey-gate-inputs.d.ts +37 -0
  504. package/dist/harness/gates/journey-gate-inputs.d.ts.map +1 -0
  505. package/dist/harness/gates/journey-gate-inputs.js +81 -0
  506. package/dist/harness/gates/journey-gate-inputs.js.map +1 -0
  507. package/dist/harness/gates/migrated-waiver-review.d.ts +6 -0
  508. package/dist/harness/gates/migrated-waiver-review.d.ts.map +1 -0
  509. package/dist/harness/gates/migrated-waiver-review.js +116 -0
  510. package/dist/harness/gates/migrated-waiver-review.js.map +1 -0
  511. package/dist/harness/gates/resolve-rule.d.ts +59 -0
  512. package/dist/harness/gates/resolve-rule.d.ts.map +1 -0
  513. package/dist/harness/gates/resolve-rule.js +41 -0
  514. package/dist/harness/gates/resolve-rule.js.map +1 -0
  515. package/dist/harness/gates/unit-gate-overrides.d.ts +25 -0
  516. package/dist/harness/gates/unit-gate-overrides.d.ts.map +1 -0
  517. package/dist/harness/gates/unit-gate-overrides.js +122 -0
  518. package/dist/harness/gates/unit-gate-overrides.js.map +1 -0
  519. package/dist/harness/journey.d.ts +24 -1
  520. package/dist/harness/journey.d.ts.map +1 -1
  521. package/dist/harness/journey.js +114 -23
  522. package/dist/harness/journey.js.map +1 -1
  523. package/dist/harness/manifest.d.ts +12 -0
  524. package/dist/harness/manifest.d.ts.map +1 -1
  525. package/dist/harness/manifest.js +73 -45
  526. package/dist/harness/manifest.js.map +1 -1
  527. package/dist/harness/next-step.d.ts +37 -6
  528. package/dist/harness/next-step.d.ts.map +1 -1
  529. package/dist/harness/next-step.js +34 -174
  530. package/dist/harness/next-step.js.map +1 -1
  531. package/dist/harness/parse.d.ts +25 -0
  532. package/dist/harness/parse.d.ts.map +1 -1
  533. package/dist/harness/parse.js +38 -13
  534. package/dist/harness/parse.js.map +1 -1
  535. package/dist/harness/script-check.d.ts.map +1 -1
  536. package/dist/harness/script-check.js +29 -6
  537. package/dist/harness/script-check.js.map +1 -1
  538. package/dist/harness/sensors.d.ts +14 -3
  539. package/dist/harness/sensors.d.ts.map +1 -1
  540. package/dist/harness/sensors.js +64 -44
  541. package/dist/harness/sensors.js.map +1 -1
  542. package/dist/harness/triage-signals.d.ts +20 -0
  543. package/dist/harness/triage-signals.d.ts.map +1 -0
  544. package/dist/harness/triage-signals.js +30 -0
  545. package/dist/harness/triage-signals.js.map +1 -0
  546. package/dist/harness/triage-unit.d.ts +23 -0
  547. package/dist/harness/triage-unit.d.ts.map +1 -0
  548. package/dist/harness/triage-unit.js +142 -0
  549. package/dist/harness/triage-unit.js.map +1 -0
  550. package/dist/harness/triage.d.ts +28 -0
  551. package/dist/harness/triage.d.ts.map +1 -0
  552. package/dist/harness/triage.js +99 -0
  553. package/dist/harness/triage.js.map +1 -0
  554. package/dist/harness/viewpoint-ledger.d.ts.map +1 -1
  555. package/dist/harness/viewpoint-ledger.js +2 -1
  556. package/dist/harness/viewpoint-ledger.js.map +1 -1
  557. package/dist/hooks/bash-write-targets.d.ts +15 -0
  558. package/dist/hooks/bash-write-targets.d.ts.map +1 -0
  559. package/dist/hooks/bash-write-targets.js +173 -0
  560. package/dist/hooks/bash-write-targets.js.map +1 -0
  561. package/dist/hooks/claude-hook-entry.d.ts +11 -0
  562. package/dist/hooks/claude-hook-entry.d.ts.map +1 -0
  563. package/dist/hooks/claude-hook-entry.js +137 -0
  564. package/dist/hooks/claude-hook-entry.js.map +1 -0
  565. package/dist/hooks/claude-transcript-turn.d.ts +11 -0
  566. package/dist/hooks/claude-transcript-turn.d.ts.map +1 -0
  567. package/dist/hooks/claude-transcript-turn.js +143 -0
  568. package/dist/hooks/claude-transcript-turn.js.map +1 -0
  569. package/dist/hooks/guard-delivery-contract-rule.d.ts +10 -0
  570. package/dist/hooks/guard-delivery-contract-rule.d.ts.map +1 -0
  571. package/dist/hooks/guard-delivery-contract-rule.js +152 -0
  572. package/dist/hooks/guard-delivery-contract-rule.js.map +1 -0
  573. package/dist/hooks/guard-protected-paths.d.ts +9 -0
  574. package/dist/hooks/guard-protected-paths.d.ts.map +1 -0
  575. package/dist/hooks/guard-protected-paths.js +106 -0
  576. package/dist/hooks/guard-protected-paths.js.map +1 -0
  577. package/dist/hooks/guard-rules.d.ts +37 -0
  578. package/dist/hooks/guard-rules.d.ts.map +1 -0
  579. package/dist/hooks/guard-rules.js +61 -0
  580. package/dist/hooks/guard-rules.js.map +1 -0
  581. package/dist/hooks/guard-tty-spoof-rule.d.ts +15 -0
  582. package/dist/hooks/guard-tty-spoof-rule.d.ts.map +1 -0
  583. package/dist/hooks/guard-tty-spoof-rule.js +21 -0
  584. package/dist/hooks/guard-tty-spoof-rule.js.map +1 -0
  585. package/dist/hooks/hand-back-core.d.ts +37 -0
  586. package/dist/hooks/hand-back-core.d.ts.map +1 -0
  587. package/dist/hooks/hand-back-core.js +115 -0
  588. package/dist/hooks/hand-back-core.js.map +1 -0
  589. package/dist/hooks/hook-cli-command.d.ts +9 -0
  590. package/dist/hooks/hook-cli-command.d.ts.map +1 -0
  591. package/dist/hooks/hook-cli-command.js +46 -0
  592. package/dist/hooks/hook-cli-command.js.map +1 -0
  593. package/dist/hooks/hook-registry.d.ts +10 -0
  594. package/dist/hooks/hook-registry.d.ts.map +1 -0
  595. package/dist/hooks/hook-registry.js +24 -0
  596. package/dist/hooks/hook-registry.js.map +1 -0
  597. package/dist/hooks/hook-result-contract.d.ts +50 -0
  598. package/dist/hooks/hook-result-contract.d.ts.map +1 -0
  599. package/dist/hooks/hook-result-contract.js +80 -0
  600. package/dist/hooks/hook-result-contract.js.map +1 -0
  601. package/dist/hooks/hook-toggles.d.ts +10 -0
  602. package/dist/hooks/hook-toggles.d.ts.map +1 -0
  603. package/dist/hooks/hook-toggles.js +107 -0
  604. package/dist/hooks/hook-toggles.js.map +1 -0
  605. package/dist/hooks/pre-tool-guard-hook.d.ts +10 -0
  606. package/dist/hooks/pre-tool-guard-hook.d.ts.map +1 -0
  607. package/dist/hooks/pre-tool-guard-hook.js +105 -0
  608. package/dist/hooks/pre-tool-guard-hook.js.map +1 -0
  609. package/dist/hooks/session-start-unit-state-hook.d.ts +13 -0
  610. package/dist/hooks/session-start-unit-state-hook.d.ts.map +1 -0
  611. package/dist/hooks/session-start-unit-state-hook.js +55 -0
  612. package/dist/hooks/session-start-unit-state-hook.js.map +1 -0
  613. package/dist/hooks/stop-next-step-hook.d.ts +16 -0
  614. package/dist/hooks/stop-next-step-hook.d.ts.map +1 -0
  615. package/dist/hooks/stop-next-step-hook.js +42 -0
  616. package/dist/hooks/stop-next-step-hook.js.map +1 -0
  617. package/dist/hooks/sungen-project-root.d.ts +19 -0
  618. package/dist/hooks/sungen-project-root.d.ts.map +1 -0
  619. package/dist/hooks/sungen-project-root.js +130 -0
  620. package/dist/hooks/sungen-project-root.js.map +1 -0
  621. package/dist/orchestrator/ai-skills/command-partial-includes.d.ts +15 -0
  622. package/dist/orchestrator/ai-skills/command-partial-includes.d.ts.map +1 -0
  623. package/dist/orchestrator/ai-skills/command-partial-includes.js +106 -0
  624. package/dist/orchestrator/ai-skills/command-partial-includes.js.map +1 -0
  625. package/dist/orchestrator/ai-skills/commands.d.ts +5 -1
  626. package/dist/orchestrator/ai-skills/commands.d.ts.map +1 -1
  627. package/dist/orchestrator/ai-skills/commands.js +16 -6
  628. package/dist/orchestrator/ai-skills/commands.js.map +1 -1
  629. package/dist/orchestrator/ai-skills/golden-skills.test.js +29 -0
  630. package/dist/orchestrator/ai-skills/golden-skills.test.js.map +1 -1
  631. package/dist/orchestrator/claude-hooks-install.d.ts +27 -0
  632. package/dist/orchestrator/claude-hooks-install.d.ts.map +1 -0
  633. package/dist/orchestrator/claude-hooks-install.js +203 -0
  634. package/dist/orchestrator/claude-hooks-install.js.map +1 -0
  635. package/dist/orchestrator/lockstep-version.d.ts +15 -5
  636. package/dist/orchestrator/lockstep-version.d.ts.map +1 -1
  637. package/dist/orchestrator/lockstep-version.js +30 -17
  638. package/dist/orchestrator/lockstep-version.js.map +1 -1
  639. package/dist/orchestrator/project-initializer.d.ts +6 -0
  640. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  641. package/dist/orchestrator/project-initializer.js +23 -0
  642. package/dist/orchestrator/project-initializer.js.map +1 -1
  643. package/dist/orchestrator/screen-manager.d.ts.map +1 -1
  644. package/dist/orchestrator/screen-manager.js +4 -2
  645. package/dist/orchestrator/screen-manager.js.map +1 -1
  646. package/dist/orchestrator/templates/ai-src/commands/add-api.md +2 -0
  647. package/dist/orchestrator/templates/ai-src/commands/add-flow.md +2 -0
  648. package/dist/orchestrator/templates/ai-src/commands/add-screen.md +2 -0
  649. package/dist/orchestrator/templates/ai-src/commands/create-data-test.md +1 -0
  650. package/dist/orchestrator/templates/ai-src/commands/create-test.md +14 -16
  651. package/dist/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
  652. package/dist/orchestrator/templates/ai-src/commands/delivery.md +2 -0
  653. package/dist/orchestrator/templates/ai-src/commands/design.md +2 -0
  654. package/dist/orchestrator/templates/ai-src/commands/feedback.md +2 -0
  655. package/dist/orchestrator/templates/ai-src/commands/locale.md +2 -0
  656. package/dist/orchestrator/templates/ai-src/commands/review.md +2 -0
  657. package/dist/orchestrator/templates/ai-src/commands/run-test.md +14 -10
  658. package/dist/orchestrator/templates/ai-src/config/claude.md +20 -7
  659. package/dist/orchestrator/templates/ai-src/config/copilot.md +20 -7
  660. package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.claude.md +20 -0
  661. package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.codex.md +20 -0
  662. package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.copilot.md +20 -0
  663. package/dist/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +1 -1
  664. package/dist/orchestrator/templates/ai-src/skills/sungen-capture-mobile/SKILL.md +3 -3
  665. package/dist/orchestrator/templates/ai-src/skills/sungen-data-factory/SKILL.md +9 -0
  666. package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +2 -0
  667. package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +1 -1
  668. package/dist/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +2 -0
  669. package/dist/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
  670. package/dist/utils/safe-yaml-parse.d.ts +8 -0
  671. package/dist/utils/safe-yaml-parse.d.ts.map +1 -0
  672. package/dist/utils/safe-yaml-parse.js +51 -0
  673. package/dist/utils/safe-yaml-parse.js.map +1 -0
  674. package/package.json +3 -3
  675. package/src/basis/anchor-grammar.ts +83 -0
  676. package/src/basis/anchor-hash.ts +27 -0
  677. package/src/basis/bm51-tables.ts +65 -0
  678. package/src/basis/extract-spec-anchors.ts +95 -0
  679. package/src/basis/migration-sentinel.ts +175 -0
  680. package/src/basis/spec-frontmatter.ts +68 -0
  681. package/src/basis/spec-sections.ts +35 -0
  682. package/src/basis/test-basis-schema.ts +81 -0
  683. package/src/capabilities/registry.ts +16 -0
  684. package/src/cli/commands/audit.ts +9 -4
  685. package/src/cli/commands/capability.ts +4 -2
  686. package/src/cli/commands/contract-derive-command.ts +60 -0
  687. package/src/cli/commands/contract.ts +130 -0
  688. package/src/cli/commands/defect.ts +49 -0
  689. package/src/cli/commands/delivery.ts +85 -13
  690. package/src/cli/commands/generate.ts +3 -1
  691. package/src/cli/commands/journey.ts +39 -14
  692. package/src/cli/commands/next.ts +60 -8
  693. package/src/cli/commands/triage.ts +57 -0
  694. package/src/cli/commands/update.ts +35 -8
  695. package/src/cli/index.ts +24 -30
  696. package/src/contract/approve-contract.ts +94 -0
  697. package/src/contract/assertion-matcher-vocabulary.ts +93 -0
  698. package/src/contract/build-contract-verdict.ts +108 -0
  699. package/src/contract/build-trace-conformance.ts +100 -0
  700. package/src/contract/classify-contract-change.ts +92 -0
  701. package/src/contract/classify-contract-unit.ts +47 -0
  702. package/src/contract/classify-trace-conformance.ts +116 -0
  703. package/src/contract/contract-git.ts +106 -0
  704. package/src/contract/contract-hash.ts +34 -0
  705. package/src/contract/contract-report-file.ts +25 -0
  706. package/src/contract/contract-schema.ts +137 -0
  707. package/src/contract/contract-units.ts +52 -0
  708. package/src/contract/contracts-lock-file.ts +97 -0
  709. package/src/contract/data-normalize.ts +66 -0
  710. package/src/contract/derive-free-feature.ts +110 -0
  711. package/src/contract/field-semantic-redaction.ts +80 -0
  712. package/src/contract/free-feature-blocks.ts +56 -0
  713. package/src/contract/lock-secret-guard.ts +95 -0
  714. package/src/contract/lock-vs-git-head.ts +38 -0
  715. package/src/contract/normalize-contract-step.ts +74 -0
  716. package/src/contract/normalize-feature-steps.ts +93 -0
  717. package/src/contract/oracle-strength.ts +80 -0
  718. package/src/contract/project-contract-blockers.ts +36 -0
  719. package/src/contract/record-contract-approval.ts +70 -0
  720. package/src/contract/render-free-gherkin.ts +113 -0
  721. package/src/contract/render-trace-sentence.ts +98 -0
  722. package/src/contract/render-trace-target.ts +68 -0
  723. package/src/contract/resolve-unit-trace-identities.ts +35 -0
  724. package/src/contract/trace/collect-trace-evidence.ts +109 -0
  725. package/src/contract/trace/identity-cache.ts +61 -0
  726. package/src/contract/trace/select-final-attempt.ts +70 -0
  727. package/src/contract/trace/snapshot-html-renderer.ts +136 -0
  728. package/src/contract/trace/snapshot-resolver.ts +66 -0
  729. package/src/contract/trace/snapshot-store.ts +151 -0
  730. package/src/contract/trace/target-identity.ts +104 -0
  731. package/src/contract/trace/test-step-join.ts +103 -0
  732. package/src/contract/trace/trace-binding.ts +56 -0
  733. package/src/contract/trace/trace-file-reader.ts +123 -0
  734. package/src/contract/trace/trace-fingerprint.ts +68 -0
  735. package/src/contract/trace/trace-identity-resolution.ts +74 -0
  736. package/src/contract/trace/trace-run-record.ts +74 -0
  737. package/src/contract/trace/trace-steps.ts +88 -0
  738. package/src/contract/trace/trace-zip-limits.ts +73 -0
  739. package/src/contract/trace/trace-zip-reader.ts +127 -0
  740. package/src/contract/verify-approval-decisions.ts +60 -0
  741. package/src/decisions/append-decision.ts +35 -0
  742. package/src/decisions/confirmed-decision-commands.ts +128 -0
  743. package/src/decisions/decision-file.ts +93 -0
  744. package/src/decisions/decision-identity.ts +73 -0
  745. package/src/decisions/decision-integrity-check.ts +61 -0
  746. package/src/decisions/decision-schema.ts +76 -0
  747. package/src/decisions/decision-source.ts +14 -0
  748. package/src/decisions/exclusive-file-create.ts +42 -0
  749. package/src/decisions/git-head-trust.ts +32 -0
  750. package/src/decisions/human-confirmation.ts +114 -0
  751. package/src/decisions/legacy-waiver-migration.ts +135 -0
  752. package/src/decisions/read-decisions.ts +61 -0
  753. package/src/decisions/viewpoint-baseline-adapter.ts +74 -0
  754. package/src/decisions/waiver-decisions.ts +56 -0
  755. package/src/exporters/csv-exporter.ts +5 -1
  756. package/src/exporters/feature-parser.ts +12 -0
  757. package/src/exporters/matrix/build.ts +62 -18
  758. package/src/exporters/matrix/carry-manual-results.ts +70 -7
  759. package/src/exporters/matrix/export.ts +17 -2
  760. package/src/exporters/matrix/gates.ts +62 -129
  761. package/src/exporters/matrix/render-csv.ts +4 -1
  762. package/src/exporters/matrix/render-gate-overrides-sheet.ts +50 -0
  763. package/src/exporters/matrix/render-xlsx.ts +6 -0
  764. package/src/exporters/matrix/types.ts +9 -1
  765. package/src/exporters/playwright-report-parser.ts +1 -0
  766. package/src/exporters/scenario-merger.ts +2 -1
  767. package/src/exporters/types.ts +5 -0
  768. package/src/generators/test-generator/code-generator.ts +13 -0
  769. package/src/graph/evaluate-graph.ts +62 -0
  770. package/src/graph/locate-finding.ts +93 -0
  771. package/src/graph/node-decl.ts +65 -0
  772. package/src/graph/nodes/core-node-catalog.ts +15 -0
  773. package/src/graph/nodes/test-case-contract-nodes.ts +69 -0
  774. package/src/graph/nodes/test-case-nodes.ts +68 -0
  775. package/src/graph/nodes/unit-audit-nodes.ts +95 -0
  776. package/src/graph/nodes/unit-contract-node.ts +82 -0
  777. package/src/graph/nodes/unit-design-nodes.ts +88 -0
  778. package/src/graph/nodes/unit-execution-nodes.ts +77 -0
  779. package/src/graph/test-case-identity.ts +75 -0
  780. package/src/graph/test-case-results.ts +90 -0
  781. package/src/graph/test-case-satisfied.ts +55 -0
  782. package/src/graph/test-case-state-shape.ts +62 -0
  783. package/src/graph/test-case-states.ts +84 -0
  784. package/src/graph/unit-artifact-probes.ts +77 -0
  785. package/src/graph/unit-state-facts.ts +112 -0
  786. package/src/harness/audit.ts +46 -11
  787. package/src/harness/catalog/gate-rules.yaml +647 -0
  788. package/src/harness/counted-assertions.ts +33 -0
  789. package/src/harness/defect-draft.ts +115 -0
  790. package/src/harness/defects.ts +94 -0
  791. package/src/harness/gates/audit-gate-terms.ts +80 -0
  792. package/src/harness/gates/audit-gate-verdict.ts +78 -0
  793. package/src/harness/gates/audit-input-hash.ts +55 -0
  794. package/src/harness/gates/audit-report-verification.ts +173 -0
  795. package/src/harness/gates/decisions-hash.ts +42 -0
  796. package/src/harness/gates/delivery-checklist.ts +120 -0
  797. package/src/harness/gates/delivery-decision-gate.ts +111 -0
  798. package/src/harness/gates/delivery-decision-step.ts +73 -0
  799. package/src/harness/gates/gate-override-report.ts +114 -0
  800. package/src/harness/gates/gate-override-scope.ts +66 -0
  801. package/src/harness/gates/gate-override-validation.ts +75 -0
  802. package/src/harness/gates/gate-rule-catalog.ts +82 -0
  803. package/src/harness/gates/gate-terms.ts +59 -0
  804. package/src/harness/gates/in-run-decision-check.ts +99 -0
  805. package/src/harness/gates/journey-gate-inputs.ts +89 -0
  806. package/src/harness/gates/migrated-waiver-review.ts +68 -0
  807. package/src/harness/gates/resolve-rule.ts +94 -0
  808. package/src/harness/gates/unit-gate-overrides.ts +99 -0
  809. package/src/harness/journey.ts +122 -27
  810. package/src/harness/manifest.ts +69 -45
  811. package/src/harness/next-step.ts +60 -170
  812. package/src/harness/parse.ts +40 -13
  813. package/src/harness/script-check.ts +27 -6
  814. package/src/harness/sensors.ts +73 -47
  815. package/src/harness/triage-signals.ts +46 -0
  816. package/src/harness/triage-unit.ts +113 -0
  817. package/src/harness/triage.ts +127 -0
  818. package/src/harness/viewpoint-ledger.ts +2 -2
  819. package/src/hooks/bash-write-targets.ts +109 -0
  820. package/src/hooks/claude-hook-entry.ts +85 -0
  821. package/src/hooks/claude-transcript-turn.ts +96 -0
  822. package/src/hooks/guard-delivery-contract-rule.ts +110 -0
  823. package/src/hooks/guard-protected-paths.ts +70 -0
  824. package/src/hooks/guard-rules.ts +98 -0
  825. package/src/hooks/guard-tty-spoof-rule.ts +31 -0
  826. package/src/hooks/hand-back-core.ts +106 -0
  827. package/src/hooks/hook-cli-command.ts +17 -0
  828. package/src/hooks/hook-registry.ts +24 -0
  829. package/src/hooks/hook-result-contract.ts +114 -0
  830. package/src/hooks/hook-toggles.ts +66 -0
  831. package/src/hooks/pre-tool-guard-hook.ts +67 -0
  832. package/src/hooks/session-start-unit-state-hook.ts +54 -0
  833. package/src/hooks/stop-next-step-hook.ts +37 -0
  834. package/src/hooks/sungen-project-root.ts +80 -0
  835. package/src/orchestrator/ai-skills/command-partial-includes.ts +72 -0
  836. package/src/orchestrator/ai-skills/commands.ts +22 -8
  837. package/src/orchestrator/ai-skills/golden-skills.test.ts +23 -0
  838. package/src/orchestrator/claude-hooks-install.ts +168 -0
  839. package/src/orchestrator/lockstep-version.ts +28 -15
  840. package/src/orchestrator/project-initializer.ts +21 -0
  841. package/src/orchestrator/screen-manager.ts +3 -1
  842. package/src/orchestrator/templates/ai-src/commands/add-api.md +2 -0
  843. package/src/orchestrator/templates/ai-src/commands/add-flow.md +2 -0
  844. package/src/orchestrator/templates/ai-src/commands/add-screen.md +2 -0
  845. package/src/orchestrator/templates/ai-src/commands/create-data-test.md +1 -0
  846. package/src/orchestrator/templates/ai-src/commands/create-test.md +14 -16
  847. package/src/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
  848. package/src/orchestrator/templates/ai-src/commands/delivery.md +2 -0
  849. package/src/orchestrator/templates/ai-src/commands/design.md +2 -0
  850. package/src/orchestrator/templates/ai-src/commands/feedback.md +2 -0
  851. package/src/orchestrator/templates/ai-src/commands/locale.md +2 -0
  852. package/src/orchestrator/templates/ai-src/commands/review.md +2 -0
  853. package/src/orchestrator/templates/ai-src/commands/run-test.md +14 -10
  854. package/src/orchestrator/templates/ai-src/config/claude.md +20 -7
  855. package/src/orchestrator/templates/ai-src/config/copilot.md +20 -7
  856. package/src/orchestrator/templates/ai-src/partials/hand-back-rule.claude.md +20 -0
  857. package/src/orchestrator/templates/ai-src/partials/hand-back-rule.codex.md +20 -0
  858. package/src/orchestrator/templates/ai-src/partials/hand-back-rule.copilot.md +20 -0
  859. package/src/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +1 -1
  860. package/src/orchestrator/templates/ai-src/skills/sungen-capture-mobile/SKILL.md +3 -3
  861. package/src/orchestrator/templates/ai-src/skills/sungen-data-factory/SKILL.md +9 -0
  862. package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +2 -0
  863. package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +1 -1
  864. package/src/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +2 -0
  865. package/src/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
  866. package/src/utils/safe-yaml-parse.ts +44 -0
@@ -0,0 +1,130 @@
1
+ /**
2
+ * `sungen contract approve | check` — the Test Contract (DOS-14, phase 06a).
3
+ *
4
+ * approve --screen <u> [--scenario <id>] [--reason <text>]
5
+ * a human types a confirmation on a TTY; writes contracts.lock.yaml + a contract-approval
6
+ * decision. No TTY → refused with the exact command (exit 1).
7
+ * check --screen <u> [--trace] [--json]
8
+ * rebuilds the verdict from .feature + lock + git HEAD + recorded traces (never from a report),
9
+ * writes .sungen/reports/<slug>-contract.json as output (secret-scanned first). Exit 2 on a hard
10
+ * finding, 0 on pass or review, 1 on an error (unknown unit, untrusted lock, unparseable feature).
11
+ * `--trace` first asks driver-ui (a real browser) for the target identities of free / impl:code
12
+ * traces; without it the cached answers are used (DOS-14.5, 14.6).
13
+ * derive --screen <u> [--grep <re>] → contract-derive-command.ts (DOS-14.8)
14
+ */
15
+ import { Command } from 'commander';
16
+ import * as fs from 'fs';
17
+ import * as path from 'path';
18
+ import { approveContract } from '../../contract/approve-contract';
19
+ import { buildContractVerdict, ContractVerdict } from '../../contract/build-contract-verdict';
20
+ import { contractReportPath, writeContractReport } from '../../contract/contract-report-file';
21
+ import { HARD_CLASSES, REVIEW_CLASSES } from '../../contract/contract-schema';
22
+ import { processIO } from '../../decisions/human-confirmation';
23
+ import { resolveContractUnit } from '../../contract/contract-units';
24
+ import { secretScanHits } from '../../contract/field-semantic-redaction';
25
+ import { resolveUnitTraceIdentities } from '../../contract/resolve-unit-trace-identities';
26
+ import { registerDeriveCommand } from './contract-derive-command';
27
+
28
+ const MARK: Record<string, string> = {
29
+ match: '✓', strengthened: '↑', proposed: '+', 'hash-changed': '⚖', 'oracle-weakened': '✗', 'target-changed': '✗', 'assertion-lost': '✗',
30
+ opaque: '◐', nondeterministic: '≈', inconclusive: '?', unproven: '✗',
31
+ };
32
+ /** `contract check` judges traces with a generous deadline (the guard path keeps ~3 s). */
33
+ const CHECK_TRACE_BUDGET_MS = 120_000;
34
+ const UNPROVEN_HINT = " → free / impl:code tests need trace: 'on' and the sungen run-record reporter, then a fresh run (see `sungen contract derive`).";
35
+
36
+ function printVerdict(v: ContractVerdict, reportFile: string): void {
37
+ const L = console.log;
38
+ const head = v.verdict === 'pass' ? '✓ PASS' : v.verdict === 'review'
39
+ ? '⚖ REVIEW — changed, not weaker. Exit 0 here, but review blocks `sungen delivery` until QA re-approves' : '✗ FAIL';
40
+ L('');
41
+ L(`━━━ Contract check: ${v.unit} — Gherkin vs the approved lock ━━━`);
42
+ L('');
43
+ L(` verdict: ${head}`);
44
+ const matched = v.scenarios.filter((s) => s.class === 'match').length;
45
+ for (const s of v.scenarios.filter((x) => x.class !== 'match')) {
46
+ L(` ${MARK[s.class] ?? '?'} ${s.id} ${s.class}${s.class === 'proposed' ? ' (no approved entry — does not block)' : ''}`);
47
+ for (const f of s.findings) L(` ${f.rule ? `[${f.rule}] ` : ''}${f.step ? `step ${f.step}: ` : ''}${f.detail}`);
48
+ if (s.trace?.hashes.length) L(` trace: ${[...new Set(s.trace.hashes)].join(', ')} (${s.trace.runs.length} run(s))`);
49
+ if (s.class === 'unproven') L(UNPROVEN_HINT);
50
+ }
51
+ if (matched) L(` ✓ ${matched} scenario(s) match the approved contract`);
52
+ const issue = (u: ContractVerdict['uncommitted'][number]): string =>
53
+ u.change === 'tampered' || u.change === 'unverified' ? `lock entry ${u.change}: ${u.detail}` : `lock entry ${u.change} and not committed`;
54
+ for (const u of v.uncommitted.slice(0, 10)) L(` ✗ ${u.id} ${issue(u)} [contract.lock-uncommitted]`);
55
+ if (v.uncommitted.length > 10) L(` ✗ … and ${v.uncommitted.length - 10} more lock entries that are not what QA approved and committed`);
56
+ for (const w of v.warnings) L(` ⚠ ${w}`);
57
+ L('');
58
+ // Only missing / refused traces: re-approving cannot help, a fresh traced run can.
59
+ const blocking = v.scenarios.filter((s) => HARD_CLASSES.has(s.class) || REVIEW_CLASSES.has(s.class));
60
+ const onlyUnproven = blocking.length > 0 && blocking.every((s) => s.class === 'unproven');
61
+ if (v.verdict === 'fail') {
62
+ L(v.uncommitted.length
63
+ ? ' → Commit the approval (lock + decision) through review, or restore the lock from git (`git checkout -- <lock>`).'
64
+ : onlyUnproven ? " → Re-run the free / impl:code tests with trace: 'on', then check again."
65
+ : ' → Restore the approved checks in the .feature — or, if the change is intended, QA approves it on a terminal:');
66
+ }
67
+ if (v.verdict !== 'pass' && !v.uncommitted.length && !onlyUnproven) L(` sungen contract approve --screen ${v.unit}`);
68
+ L(` Report: ${path.relative(process.cwd(), reportFile)}`);
69
+ L('');
70
+ }
71
+
72
+ function unitOrThrow(name: string | undefined): { name: string; dir: string } {
73
+ if (!name) throw new Error('Provide --screen <name>');
74
+ return resolveContractUnit(process.cwd(), name);
75
+ }
76
+
77
+ export function registerContractCommand(program: Command): void {
78
+ const contract = program
79
+ .command('contract')
80
+ .description('Test Contract (DOS-14): the Gherkin QA approved is the contract — lock it (TTY) and check the .feature was not weakened');
81
+
82
+ contract
83
+ .command('approve')
84
+ .description('Lock the current Gherkin as the approved contract — a human types a confirmation on a TTY')
85
+ .option('-s, --screen <name>', 'Screen / flow / api unit name')
86
+ .option('--scenario <id>', 'Approve one scenario only (its ID, e.g. VP-LOGIN-001)')
87
+ .option('--reason <text>', 'Why (recorded in the contract-approval decision)')
88
+ .action(async (options) => {
89
+ try {
90
+ const unit = unitOrThrow(options.screen);
91
+ const r = await approveContract({ projectRoot: process.cwd(), unit: unit.name, scenario: options.scenario, reason: options.reason, io: processIO() });
92
+ if (r.status === 'nothing-to-approve') { console.log(`\n= Nothing to approve: every chosen scenario of ${unit.name} already matches its approved lock entry.\n`); return; }
93
+ console.log(`\n✓ Approved ${r.approved.length} scenario(s)${r.removed.length ? `, removed ${r.removed.length}` : ''} → ${path.relative(process.cwd(), r.lockPath)} (decision ${r.decisionId})`);
94
+ console.log(' Commit the lock and the decision through review: until they are in git HEAD, `sungen contract check` reports contract.lock-uncommitted.\n');
95
+ } catch (error) {
96
+ console.error('Error:', error instanceof Error ? error.message : error);
97
+ process.exit(1);
98
+ }
99
+ });
100
+
101
+ contract
102
+ .command('check')
103
+ .description('Compare the .feature with the approved lock on the strength ladder, and the lock with git HEAD')
104
+ .option('-s, --screen <name>', 'Screen / flow / api unit name')
105
+ .option('--trace', 'Resolve free / impl:code trace target identities with @sungen/driver-ui (a real browser) first')
106
+ .option('--json', 'Output the verdict as JSON')
107
+ .action(async (options) => {
108
+ let unit: { name: string; dir: string } | undefined;
109
+ try {
110
+ unit = unitOrThrow(options.screen);
111
+ const notes = options.trace ? await resolveUnitTraceIdentities(process.cwd(), unit) : [];
112
+ // The CLI may take its time; the guard (contractBlockers) keeps the ~3 s default.
113
+ const verdict = buildContractVerdict(process.cwd(), unit, { traceBudgetMs: CHECK_TRACE_BUDGET_MS });
114
+ verdict.warnings.push(...notes);
115
+ const hits = secretScanHits(JSON.stringify(verdict, null, 2), `${unit.name}-contract.json`);
116
+ if (hits.length) throw new Error(`Refused to write the contract report — likely secret(s): ${hits.map((h) => `${h.where} ${h.reason}`).join('; ')}`);
117
+ const file = writeContractReport(process.cwd(), verdict);
118
+ if (options.json) console.log(JSON.stringify(verdict, null, 2));
119
+ else printVerdict(verdict, file);
120
+ process.exit(verdict.exitCode);
121
+ } catch (error) {
122
+ // Unreadable = not run (DOS-14.0): an earlier report must not outlive the inputs it judged.
123
+ if (unit) fs.rmSync(contractReportPath(process.cwd(), unit.name), { force: true });
124
+ console.error('Error:', error instanceof Error ? error.message : error);
125
+ process.exit(1);
126
+ }
127
+ });
128
+
129
+ registerDeriveCommand(contract);
130
+ }
@@ -0,0 +1,49 @@
1
+ import { Command } from 'commander';
2
+ import { resolveUnit } from '../resolve-unit';
3
+ import { draftDefects } from '../../harness/defect-draft';
4
+ import { readDefects } from '../../harness/defects';
5
+
6
+ /**
7
+ * `sungen defect draft|list` — defect records under qa/defects/ (see harness/defects.ts).
8
+ * `draft` writes one record per product-candidate row of the unit's last `sungen triage`.
9
+ */
10
+ export function registerDefectCommand(program: Command): void {
11
+ const defect = program.command('defect').description('Draft and list defect records (qa/defects/DEF-NNN-*.md) from red scenarios');
12
+
13
+ defect
14
+ .command('draft')
15
+ .description('Draft a defect record for each product-candidate row of the last `sungen triage`')
16
+ .option('-s, --screen <name>', 'Screen or flow name')
17
+ .option('--api <name>', 'API-first area or api flow (qa/api/<name>)')
18
+ .option('--scenario <title|id>', 'Only the scenario whose title contains this text, or that carries this VP id')
19
+ .option('--json', 'Output raw JSON')
20
+ .action((o: { screen?: string; api?: string; scenario?: string; json?: boolean }) => {
21
+ try {
22
+ const name = o.screen || o.api;
23
+ if (!name) throw new Error('Provide --screen <name> (or --api <area>)');
24
+ const unit = resolveUnit(name, process.cwd());
25
+ if (!unit) throw new Error(`Not found: qa/screens/${name}, qa/flows/${name}, or qa/api/${name}`);
26
+ const r = draftDefects(process.cwd(), unit, { scenario: o.scenario });
27
+ if (o.json) { console.log(JSON.stringify(r, null, 2)); return; }
28
+ if (r.missingTriage) { console.log(`\n ${name}: no triage yet — run \`sungen triage --screen ${name}\` after the tests.\n`); return; }
29
+ for (const f of r.written) console.log(` ✎ ${f}`);
30
+ for (const s of r.skipped) console.log(` ○ already recorded as ${s.id}: ${s.scenario}`);
31
+ if (!r.written.length && !r.skipped.length) console.log(` ✓ ${name}: no product-candidate rows to draft.`);
32
+ } catch (error) {
33
+ console.error('Error:', error instanceof Error ? error.message : error);
34
+ process.exitCode = 1;
35
+ }
36
+ });
37
+
38
+ defect
39
+ .command('list')
40
+ .description('List defect records (id, severity, status, units, scenario count)')
41
+ .option('--status <status>', 'Only records with this status (open, fixed, verified, closed, wont-fix)')
42
+ .option('--json', 'Output raw JSON')
43
+ .action((o: { status?: string; json?: boolean }) => {
44
+ const rows = readDefects(process.cwd()).filter((r) => !o.status || r.status === o.status);
45
+ if (o.json) { console.log(JSON.stringify(rows, null, 2)); return; }
46
+ if (!rows.length) { console.log(' (no defect records)'); return; }
47
+ for (const r of rows) console.log(` ${r.id} ${r.severity.padEnd(8)} ${r.status.padEnd(9)} ${r.units.join(',')} ${r.scenarios.length} scenario(s) ${r.title}`);
48
+ });
49
+ }
@@ -7,7 +7,7 @@ import { Command } from 'commander';
7
7
  import * as path from 'path';
8
8
  import * as fs from 'fs';
9
9
  import { parse as parseYaml } from 'yaml';
10
- import { parseFeatureMetadata } from '../../exporters/feature-parser';
10
+ import { isHookScenario, parseFeatureMetadata } from '../../exporters/feature-parser';
11
11
  import { parseSpecFile } from '../../exporters/spec-parser';
12
12
  import { loadTestData } from '../../exporters/test-data-resolver';
13
13
  import { loadSelectorKeyMap } from '../../exporters/selector-key-resolver';
@@ -20,7 +20,7 @@ import {
20
20
  renderCsv,
21
21
  writeCsv,
22
22
  } from '../../exporters/csv-exporter';
23
- import { renderXlsxMultiSheet, writeXlsx, buildApiDetailRows, addApiDetailSheet } from '../../exporters/xlsx-exporter';
23
+ import { renderXlsxMultiSheet, writeXlsx, buildApiDetailRows, addApiDetailSheet, deliverableXlsxPath } from '../../exporters/xlsx-exporter';
24
24
  import { loadApiCatalog } from '../../exporters/api-catalog-loader';
25
25
  import { resolveApiEnvironment } from '../../exporters/api-environment';
26
26
  import { getEnvironment, platformOfResultFile, RunEnvironment } from '../../exporters/run-environment';
@@ -38,9 +38,14 @@ import {
38
38
  hasReview,
39
39
  } from '../../exporters/matrix/export';
40
40
  import { MatrixFinding } from '../../exporters/matrix/types';
41
- import { ManualCarryReport } from '../../exporters/matrix/carry-manual-results';
41
+ import { applyManualCarry, ManualCarryReport, PriorManualResults, readPriorManualResults } from '../../exporters/matrix/carry-manual-results';
42
42
  import { formatTestOutcome, resultTotals } from '../../exporters/matrix/result-totals';
43
43
  import { readCapabilities } from '../../harness/capability';
44
+ import { processIO } from '../../decisions/human-confirmation';
45
+ import { DeliveryDecisionGate } from '../../harness/gates/delivery-decision-gate';
46
+ import { runDeliveryDecisionStep } from '../../harness/gates/delivery-decision-step';
47
+ import { deliverableGateOverrides, InRunAcceptance } from '../../harness/gates/gate-override-report';
48
+ import { ChecklistUnit, renderChecklist, unitChecklist } from '../../harness/gates/delivery-checklist';
44
49
 
45
50
  const COLOR = {
46
51
  reset: '\x1b[0m',
@@ -85,6 +90,12 @@ export interface DeliveryTarget {
85
90
  isFlow: boolean;
86
91
  }
87
92
 
93
+ /** The command that regenerates a target's unit — flag by kind, the unit (not feature) name. */
94
+ function generateCommandFor(target: DeliveryTarget): string {
95
+ const flag = target.kind === 'flow' ? '--flow' : target.kind === 'api' ? '--api' : '--screen';
96
+ return `sungen generate ${flag} ${target.screen}`;
97
+ }
98
+
88
99
  function makeTarget(screen: string, featureBaseName: string, kind: UnitKind): DeliveryTarget {
89
100
  return { screen, featureBaseName, name: featureBaseName, kind, isFlow: kind === 'flow' };
90
101
  }
@@ -464,6 +475,7 @@ async function exportTarget(
464
475
  if (isMobileProject(cwd)) removeBaseDeliverables(cwd, target.featureBaseName);
465
476
  const rows = buildTestCaseRows({
466
477
  screen: label,
478
+ generateCommand: generateCommandFor(target),
467
479
  featureName: feature.featureName,
468
480
  // OS-precise env column: a mobile dual-id Path resolves to just the
469
481
  // android package / ios bundle id for SUNGEN_ENV=android|ios.
@@ -522,6 +534,7 @@ async function exportTarget(
522
534
  for (const variant of osVariants) {
523
535
  const variantRows = buildTestCaseRows({
524
536
  screen: label,
537
+ generateCommand: generateCommandFor(target),
525
538
  featureName: feature.featureName,
526
539
  featurePath: resolvePlatformAppId(featurePath, variant.locale), // OS-precise app id
527
540
  merged,
@@ -574,6 +587,7 @@ async function exportTarget(
574
587
  const variantResults = variant.resultsPath ? loadPlaywrightReport(variant.resultsPath) : null;
575
588
  const variantRows = buildTestCaseRows({
576
589
  screen: label,
590
+ generateCommand: generateCommandFor(target),
577
591
  featureName: feature.featureName,
578
592
  // No-op for web (URL Path); for a mobile fall-through (a no-suffix result
579
593
  // json) this collapses the dual-id to the android package so the combined
@@ -651,7 +665,7 @@ export function matrixPathsFor(cwd: string, target: DeliveryTarget): MatrixTarge
651
665
  }
652
666
 
653
667
  function printFindings(findings: MatrixFinding[]): void {
654
- const icon = { error: `${COLOR.red}✗`, review: `${COLOR.yellow}⚠`, warning: `${COLOR.gray}·` } as const;
668
+ const icon = { error: `${COLOR.red}✗`, review: `${COLOR.yellow}⚠`, warning: `${COLOR.gray}·`, info: `${COLOR.gray}i` } as const;
655
669
  for (const f of findings) {
656
670
  log(` ${icon[f.severity]} [Gate ${f.gate}]${COLOR.reset} ${f.ref ? `${f.ref}: ` : ''}${f.message}`);
657
671
  }
@@ -676,18 +690,22 @@ async function exportMatrixTarget(
676
690
  target: DeliveryTarget,
677
691
  opts: { check?: boolean; preview?: boolean; format?: MatrixFormat },
678
692
  env: EnvironmentInfo,
693
+ decisions?: DeliveryDecisionGate,
679
694
  ): Promise<MatrixRunSummary | 'skipped' | null> {
680
695
  const paths = matrixPathsFor(cwd, target);
681
696
  paths.runEnv = matrixRunEnv(cwd, target, env, paths);
697
+ paths.gateRules = decisions?.rulesFor(qaDir(cwd, target)); // the unit's gate-overrides apply to its matrix gates
682
698
 
683
699
  // A feature whose scenarios are ALL @exploration probes has nothing to deliver —
684
700
  // skip it quietly (no map required) instead of demanding a reviewed grouping for
685
701
  // probes that are, by contract, outside the official suite.
686
702
  {
687
703
  const featureMeta = parseFeatureMetadata(paths.featureFile);
688
- const deliverable = featureMeta.scenarios.filter((s) => !s.tags.some((t) => /^@exploration\b/i.test(t)));
689
- if (featureMeta.scenarios.length > 0 && deliverable.length === 0) {
690
- log(`${COLOR.gray}${paths.label}: nothing to deliver — all ${featureMeta.scenarios.length} scenario(s) are @exploration probes (outside the official suite).${COLOR.reset}`);
704
+ // Hooks are setup/teardown, never test cases — they neither need nor make a deliverable (#880).
705
+ const scenarios = featureMeta.scenarios.filter((s) => !isHookScenario(s));
706
+ const deliverable = scenarios.filter((s) => !s.tags.some((t) => /^@exploration\b/i.test(t)));
707
+ if (scenarios.length > 0 && deliverable.length === 0) {
708
+ log(`${COLOR.gray}${paths.label}: nothing to deliver — all ${scenarios.length} scenario(s) are @exploration probes (outside the official suite).${COLOR.reset}`);
691
709
  return 'skipped';
692
710
  }
693
711
  }
@@ -707,6 +725,18 @@ async function exportMatrixTarget(
707
725
  return null;
708
726
  }
709
727
 
728
+ // The tester's recorded Manual results are part of the outcome: read them BEFORE anything is
729
+ // counted, so this line, the workbook's totals and the summary table all agree (#891). A file
730
+ // that cannot be read is reported where it matters — when it would be overwritten.
731
+ const format = opts.format ?? 'xlsx';
732
+ let prior: PriorManualResults | null = null;
733
+ let priorError: Error | null = null;
734
+ try { prior = await readPriorManualResults(deliverableXlsxPath(cwd, paths.unit)); }
735
+ // A CSV-only export overwrites no workbook, so an unreadable one only means "nothing to carry".
736
+ catch (e) { if (format !== 'csv') priorError = e as Error; }
737
+ applyManualCarry(model, prior);
738
+ model.gateOverrides = deliverableGateOverrides(decisions?.overridesFor(qaDir(cwd, target)) ?? [], hasReview(model.findings), decisions?.acceptedInRun);
739
+
710
740
  log(`${COLOR.bold}${paths.label}${COLOR.reset} — ${model.manifest.itemCount} delivery item(s), ${model.manifest.variantCount} coverage variant(s), review: ${model.manifest.approvalState} (design), test outcome: ${formatTestOutcome(resultTotals(model.items))}`);
711
741
  {
712
742
  const mocked = model.items.flatMap((it) => it.variants.filter((v) => v.mocked));
@@ -741,7 +771,8 @@ async function exportMatrixTarget(
741
771
 
742
772
  let deliverables: Awaited<ReturnType<typeof writeMatrixDeliverables>>;
743
773
  try {
744
- deliverables = await writeMatrixDeliverables(paths, model, opts.format ?? 'xlsx');
774
+ if (priorError) throw priorError;
775
+ deliverables = await writeMatrixDeliverables(paths, model, format, prior);
745
776
  } catch (e) {
746
777
  // The existing workbook could not be read, so writing would destroy its Manual results.
747
778
  log(` ${COLOR.red}not written:${COLOR.reset} ${(e as Error).message}`);
@@ -869,6 +900,19 @@ function printSummaryTable(summaries: ScreenSummary[]): void {
869
900
  }
870
901
  }
871
902
 
903
+ /** T6: one checklist block per delivered unit, each box from what its command says now (delivery-checklist.ts). */
904
+ async function printDeliveryChecklist(cwd: string, targets: DeliveryTarget[], accepted?: InRunAcceptance): Promise<void> {
905
+ const units = new Map<string, ChecklistUnit>();
906
+ for (const t of targets) {
907
+ const dir = qaDir(cwd, t);
908
+ if (!units.has(dir)) units.set(dir, { label: t.isFlow ? `flow/${t.screen}` : t.screen, unitName: t.screen, unitDir: dir, kind: t.kind, resultsPath: resolveResultsPath(cwd, t) });
909
+ }
910
+ const rows: Array<{ label: string; boxes: Awaited<ReturnType<typeof unitChecklist>> }> = [];
911
+ for (const u of units.values()) rows.push({ label: u.label, boxes: await unitChecklist(cwd, u, accepted) });
912
+ log('');
913
+ for (const line of renderChecklist(rows)) log(line);
914
+ }
915
+
872
916
  // ----------------------------------------------------------------------------
873
917
  // Command registration
874
918
  // ----------------------------------------------------------------------------
@@ -887,10 +931,11 @@ export function registerDeliveryCommand(program: Command): void {
887
931
  .option('--approve [ids]', 'Approve proposed groups (all, or a comma-separated id list) + stamp fingerprints')
888
932
  .option('--preview', 'Render the matrix despite review-required findings (DRAFT watermark)')
889
933
  .option('--format <format>', 'Matrix output format: xlsx (default) | csv | both', 'xlsx')
934
+ .option('--accept-in-run', 'Deliver despite gate-overrides/waivers/approvals recorded during the run (decision.in-run) — a human confirms on a terminal')
890
935
  .action(async (names: string[], options: {
891
936
  skipPreflight?: boolean; continueOnMissing?: boolean; env?: string;
892
937
  legacy?: boolean; full?: boolean; check?: boolean; approve?: boolean | string; preview?: boolean;
893
- format?: string;
938
+ format?: string; acceptInRun?: boolean;
894
939
  }) => {
895
940
  try {
896
941
  // Same effect as running with SUNGEN_ENV=<env> — result-file resolution,
@@ -967,6 +1012,30 @@ export function registerDeliveryCommand(program: Command): void {
967
1012
  .reduce<SecretScanResult>((a, r) => ({ hits: [...a.hits, ...r.hits], unscanned: [...a.unscanned, ...r.unscanned] }), { hits: [], unscanned: [] });
968
1013
  for (const line of formatSecretScan(secretScan)) log(line);
969
1014
 
1015
+ // OES-11.3–11.5: decisions that do not verify, rejected overrides, a stale audit and in-run
1016
+ // decisions stop the delivery before anything is written (approval only stamps the map).
1017
+ let decisions: DeliveryDecisionGate | undefined;
1018
+ // --approve only stamps a matrix map. With --legacy / --full it would skip this gate and
1019
+ // fall through to the export, so the combination is refused before anything is written.
1020
+ if (options.approve !== undefined && (options.legacy || options.full)) {
1021
+ console.error(`${COLOR.red}--approve applies to the matrix deliverable only${COLOR.reset} — it cannot be combined with --legacy / --full`);
1022
+ process.exit(1);
1023
+ }
1024
+ if (options.approve === undefined) {
1025
+ const gate = await runDeliveryDecisionStep({
1026
+ projectRoot: cwd, acceptInRun: !!options.acceptInRun, io: processIO(), log,
1027
+ // --preview / --check soften only the matrix export; --legacy has no draft mode, so it always needs one.
1028
+ requireTrustedAudit: !!(options.legacy || options.full) || (!options.preview && !options.check),
1029
+ refs: toExport.map((t) => ({ label: t.isFlow ? `flow/${t.featureBaseName}` : t.featureBaseName, unitName: t.screen, unitDir: qaDir(cwd, t), resultsPath: resolveResultsPath(cwd, t) })),
1030
+ argv: ['sungen', 'delivery', ...(names ?? []), ...(options.env ? ['--env', options.env] : []), ...(options.legacy || options.full ? ['--legacy'] : [])],
1031
+ });
1032
+ if (!gate) {
1033
+ await printDeliveryChecklist(cwd, toExport);
1034
+ process.exit(1);
1035
+ }
1036
+ decisions = gate;
1037
+ }
1038
+
970
1039
  // 3. Export
971
1040
  const legacy = options.legacy || options.full;
972
1041
  if (!legacy) {
@@ -981,9 +1050,9 @@ export function registerDeliveryCommand(program: Command): void {
981
1050
  // Same contract as the export path: an all-@exploration feature has no
982
1051
  // deliverable variants, so there is no map to approve — skip, not an error.
983
1052
  {
984
- const featureMeta = parseFeatureMetadata(paths.featureFile);
985
- if (featureMeta.scenarios.length > 0
986
- && featureMeta.scenarios.every((s) => s.tags.some((t) => /^@exploration\b/i.test(t)))) {
1053
+ const scenarios = parseFeatureMetadata(paths.featureFile).scenarios.filter((s) => !isHookScenario(s));
1054
+ if (scenarios.length > 0
1055
+ && scenarios.every((s) => s.tags.some((t) => /^@exploration\b/i.test(t)))) {
987
1056
  log(`${COLOR.gray}${paths.label}: nothing to approve — all scenario(s) are @exploration probes.${COLOR.reset}`);
988
1057
  continue;
989
1058
  }
@@ -1012,13 +1081,15 @@ export function registerDeliveryCommand(program: Command): void {
1012
1081
  for (const target of toExport) {
1013
1082
  const s = await exportMatrixTarget(cwd, target, {
1014
1083
  check: options.check, preview: options.preview, format: format as MatrixFormat,
1015
- }, env);
1084
+ }, env, decisions);
1016
1085
  if (s === 'skipped') continue; // all-@exploration feature — neither exported nor a failure
1017
1086
  if (s) matrixSummaries.push(s);
1018
1087
  else notExported.push(target.isFlow ? `flow/${target.featureBaseName}` : target.featureBaseName);
1019
1088
  }
1020
1089
  if (matrixSummaries.length > 0 && !options.check) printMatrixSummaryTable(matrixSummaries);
1090
+ for (const line of decisions?.summaryLines() ?? []) log(line);
1021
1091
  printSkipSummary(skipped, notExported);
1092
+ await printDeliveryChecklist(cwd, toExport, decisions?.acceptedInRun);
1022
1093
  // A named target that produced nothing is a failure. A sweep is a failure
1023
1094
  // only when it produced nothing at all — units still waiting for a map or
1024
1095
  // an approval are the normal state of a live project. Preflight skips are
@@ -1041,6 +1112,7 @@ export function registerDeliveryCommand(program: Command): void {
1041
1112
  // 4. Summary
1042
1113
  printSummaryTable(summaries);
1043
1114
  printSkipSummary(skipped, []);
1115
+ await printDeliveryChecklist(cwd, toExport, decisions?.acceptedInRun);
1044
1116
  // Same rule as the matrix path: every attempted target in an explicit scope
1045
1117
  // must have produced a file; a sweep only fails when nothing was written.
1046
1118
  if (explicitScope ? summaries.length < toExport.length : summaries.length === 0) process.exit(1);
@@ -7,6 +7,7 @@ import { scanTestDataSecrets, formatSecretScan, type SecretScanResult } from '..
7
7
  import { capabilityRegistry } from '../../capabilities/registry';
8
8
  import { discoverAndRegisterCapabilities } from '../../capabilities/discover';
9
9
  import { readCapabilities, writeCapabilities, driverMeta, loadDriverCatalog } from '../../harness/capability';
10
+ import { isHandWritten } from '../../harness/parse';
10
11
 
11
12
  /**
12
13
  * Find .feature files recursively in a directory
@@ -20,7 +21,8 @@ function findFeatureFiles(dir: string): string[] {
20
21
  const fullPath = path.join(dir, entry.name);
21
22
  if (entry.isDirectory()) {
22
23
  files.push(...findFeatureFiles(fullPath));
23
- } else if (entry.isFile() && entry.name.endsWith('.feature')) {
24
+ } else if (entry.isFile() && entry.name.endsWith('.feature') && !isHandWritten([], fullPath)) {
25
+ // A derived `*.free.feature` is a contract for hand-written tests — never compiled (DOS-14.8).
24
26
  files.push(fullPath);
25
27
  }
26
28
  }
@@ -1,10 +1,12 @@
1
1
  import { Command } from 'commander';
2
2
  import * as path from 'path';
3
- import * as fs from 'fs';
4
- import { runJourney, waive, signoff, renderJourneyBoard, rollupJourney, renderRollupBoard } from '../../harness/journey';
3
+ import { runJourney, signoff, renderJourneyBoard, rollupJourney, renderRollupBoard, writeJourneyFileBestEffort } from '../../harness/journey';
5
4
  import { reportSlug } from '../../harness/unit-paths';
6
5
  import { findUnitDir } from '../resolve-unit';
6
+ import { answerPendingMigration, decideWithConfirmation, DECIDE_KINDS, waiveWithConfirmation } from '../../decisions/confirmed-decision-commands';
7
+ import { processIO } from '../../decisions/human-confirmation';
7
8
 
9
+ const collect = (value: string, previous: string[]): string[] => [...previous, value];
8
10
 
9
11
  export function registerJourneyCommand(program: Command): void {
10
12
  program
@@ -12,22 +14,41 @@ export function registerJourneyCommand(program: Command): void {
12
14
  .description('Durable "you are here" board (#381): obligations + what-to-review + next, synthesised read-only from the audit report + ledger already on disk.')
13
15
  .option('-s, --screen <name>', 'Screen / flow / api unit name')
14
16
  .option('--all', 'Roll up every unit (screens + flows + api) into one board — the serial review surface for multi-unit fan-out')
15
- .option('--waive <obligation>', 'Waive an obligation (e.g. OB-coverage) — requires --reason')
16
- .option('--reason <text>', 'The reason a waived obligation is acceptable (mandatory with --waive)')
17
+ .option('--waive <obligation>', 'Waive an obligation (e.g. OB-coverage) — requires --reason; a human types a confirmation on a TTY')
18
+ .option('--reason <text>', 'Why: mandatory with --waive and --decide')
19
+ .option('--decide <kind>', `Record a decision (${DECIDE_KINDS.join(' | ')}) in qa/decisions/, or the unit's with --screen — a human types a confirmation on a TTY`)
20
+ .option('--text <text>', 'What was decided (with --decide)')
21
+ .option('--anchor <id>', 'Spec anchor the decision is about, e.g. SPEC-AUTH-001#A-2 (repeatable, with --decide)', collect, [])
22
+ .option('--payload <json>', 'Kind-specific fields as a JSON object, e.g. a gate-override\'s {"rule","severity","scope"} (with --decide)')
23
+ .option('--visibility <v>', 'internal (default, never exported) | client (with --decide)')
24
+ .option('--supersedes <id>', 'The decision this one replaces — the old entry is never edited (with --decide)')
17
25
  .option('--signoff', 'Sign off the review queue — the single human gate (allowed only when every other obligation is satisfied/waived)')
18
26
  .option('--by <name>', 'Who is signing off (recorded with --signoff)')
19
27
  .option('--json', 'Output the raw JSON report')
20
- .action((options) => {
28
+ .action(async (options) => {
29
+ const io = processIO();
21
30
  try {
31
+ if (options.decide) {
32
+ if (options.screen && !findUnitDir(options.screen)) throw new Error(`Not found: qa/screens/${options.screen}, qa/flows/${options.screen}, or qa/api/${options.screen}`);
33
+ const r = await decideWithConfirmation({
34
+ projectRoot: process.cwd(), unit: options.screen, kind: options.decide, text: options.text, reason: options.reason,
35
+ anchors: options.anchor, payload: options.payload, visibility: options.visibility, supersedes: options.supersedes, io,
36
+ });
37
+ if (options.json) { console.log(JSON.stringify({ status: r.status, path: path.relative(process.cwd(), r.path), entry: r.entry }, null, 2)); return; }
38
+ console.log(`\n${r.status === 'created' ? '✓ Recorded' : '= Already recorded'} ${r.entry.id} → ${path.relative(process.cwd(), r.path)}`);
39
+ console.log(' Commit it through review: a decision not yet in git HEAD is flagged at delivery (decision.in-run).\n');
40
+ return;
41
+ }
42
+
22
43
  if (options.all) {
23
44
  const rows = rollupJourney(process.cwd());
24
45
  const board = renderRollupBoard(rows);
25
46
  const outDir = path.join(process.cwd(), '.sungen', 'journey');
26
- fs.mkdirSync(outDir, { recursive: true });
27
- fs.writeFileSync(path.join(outDir, '_rollup.json'), JSON.stringify(rows, null, 2), 'utf-8');
28
- fs.writeFileSync(path.join(outDir, '_rollup.board.md'), board, 'utf-8');
47
+ // Derived files: a read-only checkout still gets the board (DOS-13.3).
48
+ writeJourneyFileBestEffort(path.join(outDir, '_rollup.json'), JSON.stringify(rows, null, 2));
49
+ const written = writeJourneyFileBestEffort(path.join(outDir, '_rollup.board.md'), board);
29
50
  if (options.json) console.log(JSON.stringify(rows, null, 2));
30
- else { console.log(''); console.log(board); console.log(` Board: ${path.relative(process.cwd(), path.join(outDir, '_rollup.board.md'))}`); console.log(''); }
51
+ else { console.log(''); console.log(board); console.log(` Board: ${written ? path.relative(process.cwd(), written) : '(not written — read-only checkout)'}`); console.log(''); }
31
52
  return;
32
53
  }
33
54
 
@@ -35,25 +56,29 @@ export function registerJourneyCommand(program: Command): void {
35
56
  if (!name) throw new Error('Provide --screen <name> (or --all for the roll-up)');
36
57
  if (!findUnitDir(name)) throw new Error(`Not found: qa/screens/${name}, qa/flows/${name}, or qa/api/${name}`);
37
58
 
59
+ // A migration killed half-way (T6): a human answers REVERT or KEEP before anything else runs.
60
+ const restored = await answerPendingMigration(process.cwd(), name, io);
61
+ if (restored) io.output.write(` Interrupted migration resolved${restored.length ? ` — restored ${restored.length} file(s)` : ' — kept the new files'}.\n`);
62
+
38
63
  const report = options.waive
39
- ? waive(process.cwd(), name, options.waive, options.reason || '')
64
+ ? await waiveWithConfirmation({ projectRoot: process.cwd(), unit: name, obligation: options.waive, reason: options.reason || '', io })
40
65
  : options.signoff
41
66
  ? signoff(process.cwd(), name, options.by)
42
67
  : runJourney(process.cwd(), name);
43
68
 
44
69
  const outDir = path.join(process.cwd(), '.sungen', 'journey');
45
- fs.mkdirSync(outDir, { recursive: true });
46
70
  const slug = reportSlug(name);
47
- fs.writeFileSync(path.join(outDir, `${slug}.json`), JSON.stringify(report, null, 2), 'utf-8');
71
+ // Derived files: a read-only checkout still gets the board (DOS-13.3).
72
+ writeJourneyFileBestEffort(path.join(outDir, `${slug}.json`), JSON.stringify(report, null, 2));
48
73
  const board = renderJourneyBoard(report);
49
- fs.writeFileSync(path.join(outDir, `${slug}.board.md`), board, 'utf-8');
74
+ const written = writeJourneyFileBestEffort(path.join(outDir, `${slug}.board.md`), board);
50
75
 
51
76
  if (options.json) {
52
77
  console.log(JSON.stringify(report, null, 2));
53
78
  } else {
54
79
  console.log('');
55
80
  console.log(board);
56
- console.log(` Board: ${path.relative(process.cwd(), path.join(outDir, `${slug}.board.md`))}`);
81
+ console.log(` Board: ${written ? path.relative(process.cwd(), written) : '(not written — read-only checkout)'}`);
57
82
  console.log('');
58
83
  }
59
84
  } catch (error) {