@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,82 @@
1
+ /**
2
+ * The Test Contract as a QA DECISION in `sungen next` (DOS-14.4, phase 06 residual) — built from the
3
+ * verdict `sungen contract check` and the delivery guard rebuild (buildContractVerdict), so the three
4
+ * never disagree. Always `decide`: an agent presents it and never approves its own edit.
5
+ *
6
+ * unit.contract-approve (rank 105, after the audit gate, before the first run)
7
+ * error the verdict could not be built → check it on a terminal
8
+ * uncommitted by kind: tampered → re-approve or restore · untracked → commit after review ·
9
+ * edited → review and commit, or `git checkout --` the lock · unverified → commit the
10
+ * decision (approving again cannot fix a commit, and offering it would loop)
11
+ * hard a check got weaker / changed target / was lost → restore it, or QA approves
12
+ * review changed, not weaker → QA re-approves (review blocks delivery)
13
+ * unit.contract-proposed (rank 137, after every blocking unit step — it never preempts one)
14
+ * proposed never approved → QA approves (proposed scenarios never block)
15
+ * A free / impl:code scenario only its TRACE cannot prove — unproven, inconclusive, opaque — is not a
16
+ * unit decision: the case nodes say what proves it (test-case-contract-nodes.ts, phase 09).
17
+ */
18
+ import { ALL_KINDS, StepCore, UnitNodeDecl, unitKindDir } from '../node-decl';
19
+ import type { UnitState } from '../../harness/next-step';
20
+
21
+ const HUMAN_ONLY = 'A QA decision on a terminal: an agent presents it and never approves its own edit';
22
+ const approveCmd = (s: UnitState): string => `sungen contract approve --screen ${s.unit}`;
23
+
24
+ function uncommittedStep(s: UnitState): StepCore {
25
+ const c = s.contract!;
26
+ const lock = `qa/${unitKindDir(s.kind)}/${s.unit}/contracts.lock.yaml`;
27
+ const n = c.uncommitted;
28
+ switch (c.uncommittedKind) {
29
+ case 'tampered':
30
+ return { kind: 'decide', command: approveCmd(s), because: `${n} lock entr(ies) no longer match their steps (edited by hand) — re-approve with \`${approveCmd(s)}\` on a terminal, or restore the lock from git` };
31
+ case 'untracked':
32
+ return { kind: 'decide', command: `commit ${lock} and its contract-approval decision after review`, because: `the lock has never been committed — ${n} entr(ies) are not in git HEAD (contract.lock-uncommitted); commit it after review` };
33
+ case 'unverified':
34
+ return { kind: 'decide', command: `commit the contract-approval decision behind ${lock} after review`, because: `${n} lock entr(ies) are not vouched for by a committed contract-approval decision (contract.lock-uncommitted) — commit the decision after review, or re-approve with \`${approveCmd(s)}\` on a terminal` };
35
+ default:
36
+ return { kind: 'decide', command: `review and commit ${lock}, or restore it: git checkout -- ${lock}`, because: `${n} lock entr(ies) differ from the lock in git HEAD (contract.lock-uncommitted) — review and commit the lock, or restore it with \`git checkout -- ${lock}\`; approving again cannot fix that` };
37
+ }
38
+ }
39
+
40
+ function contractStep(s: UnitState): StepCore {
41
+ const c = s.contract!;
42
+ if (c.error) {
43
+ return { kind: 'decide', command: `sungen contract check --screen ${s.unit}`, because: `the contract verdict could not be built (${c.error}) — check it on a terminal; until it builds, the delivery guard asks instead of passing` };
44
+ }
45
+ if (c.uncommitted > 0) return uncommittedStep(s);
46
+ if (c.hard > 0) {
47
+ return { kind: 'decide', command: approveCmd(s), because: `${c.hard} scenario(s) break the approved contract (${c.headline}) — restore the approved checks in the .feature, or, if the change is intended, a QA approves it on a terminal. An agent presents this and never approves its own edit` };
48
+ }
49
+ return { kind: 'decide', command: approveCmd(s), because: `${c.review} approved scenario(s) changed since QA approved them (changed, not weaker) — review blocks \`sungen delivery\` until QA re-approves. ${HUMAN_ONLY}` };
50
+ }
51
+
52
+ const CONTRACT_RULES = ['contract.hash-changed', 'contract.oracle-weakened', 'contract.target-changed', 'contract.assertion-lost', 'contract.lock-uncommitted'];
53
+ /** The verdict is a pass and it was built: nothing blocks, nothing to repair. */
54
+ const verdictClean = (s: UnitState): boolean => !s.contract!.error && s.contract!.verdict === 'pass';
55
+ /** Nothing for a QA to decide at unit level: built, committed, nothing approved got weaker or changed. */
56
+ const nothingToDecide = (s: UnitState): boolean => {
57
+ const c = s.contract!;
58
+ return !c.error && c.uncommitted === 0 && c.hard === 0 && c.review === 0 && (c.verdict === 'pass' || (c.unproven ?? 0) + (c.traceReview ?? 0) > 0);
59
+ };
60
+
61
+ export const UNIT_CONTRACT_NODES: readonly UnitNodeDecl[] = [
62
+ {
63
+ id: 'unit.contract-approve', title: 'Resolve the Test Contract', actor: 'human', granularity: 'unit',
64
+ appliesTo: ALL_KINDS, requires: ['unit.gate-fail'], blocking: false, rank: 105, gates: CONTRACT_RULES,
65
+ produces: ['contracts.lock.yaml', 'decisions/<id>.yaml'],
66
+ active: (s) => Boolean(s.contract),
67
+ satisfied: nothingToDecide,
68
+ step: contractStep,
69
+ },
70
+ {
71
+ id: 'unit.contract-proposed', title: 'Approve the Test Contract', actor: 'human', granularity: 'unit',
72
+ appliesTo: ALL_KINDS, requires: ['unit.run'], blocking: false, rank: 137, gates: [],
73
+ produces: ['contracts.lock.yaml', 'decisions/<id>.yaml'],
74
+ active: (s) => Boolean(s.contract) && verdictClean(s),
75
+ satisfied: (s) => s.contract!.proposed === 0,
76
+ step: (s) => ({
77
+ kind: 'decide',
78
+ command: approveCmd(s),
79
+ because: `${s.contract!.proposed} scenario(s) have no approved contract yet — approving locks the checks QA reviewed, so a later edit that weakens one (a healer's included) fails \`sungen contract check\`. ${HUMAN_ONLY}; proposed scenarios do not block`,
80
+ }),
81
+ },
82
+ ];
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Design-stage unit nodes — rows 1–6 of the OES-10.2 parity table, in the order and with the exact
3
+ * words `deriveSteps` used (frozen in tests/graph/fixtures/legacy-derive-steps.ts).
4
+ *
5
+ * 1 unit.no-source no spec and no viewpoint → blocked; cuts BEFORE even `sungen update`
6
+ * 2 unit.assets-drift AI assets from another build → `sungen update` (first, it voids the rest)
7
+ * 3 unit.viewpoint-missing no test-viewpoint.md → blocked, does not cut
8
+ * 4 unit.flow-contract a flow without flow-contract.yaml → blocked, cuts
9
+ * 5 unit.no-scenarios zero scenarios → create-test, cuts
10
+ * 6 unit.flow-inventory a flow contract without `flows:` → add it, re-audit
11
+ */
12
+ import { ALL_KINDS, UnitNodeDecl, unitKindDir } from '../node-decl';
13
+
14
+ const design = (unit: string): string => `/sungen:create-test ${unit}`;
15
+
16
+ export const UNIT_DESIGN_NODES: readonly UnitNodeDecl[] = [
17
+ {
18
+ id: 'unit.no-source', title: 'Write a source to generate from', actor: 'human', granularity: 'unit',
19
+ appliesTo: ALL_KINDS, requires: [], blocking: true, rank: 10, gates: [], produces: ['requirements/spec.md'],
20
+ active: () => true,
21
+ satisfied: (s) => s.hasSpec || s.hasViewpoint,
22
+ step: (s) => ({
23
+ kind: 'blocked',
24
+ command: `write qa/${unitKindDir(s.kind)}/${s.unit}/requirements/spec.md`,
25
+ because: 'the unit has neither a spec nor a test-viewpoint, so there is nothing to generate FROM — generation without a source invents behaviour',
26
+ }),
27
+ },
28
+ {
29
+ // Stale AI assets come FIRST: a HARD RULE added to `create-test` reaches nobody until `sungen update`
30
+ // runs, and upgrading the package alone does not refresh them (#620).
31
+ id: 'unit.assets-drift', title: 'Refresh the AI commands and skills', actor: 'ai', granularity: 'unit',
32
+ appliesTo: ALL_KINDS, requires: ['unit.no-source'], blocking: false, rank: 20, gates: [], produces: ['.claude/', '.github/', '.agents/'],
33
+ active: () => true,
34
+ satisfied: (s) => !s.assetsDrift,
35
+ step: (s) => ({
36
+ kind: 'do',
37
+ command: 'sungen update',
38
+ because: `this project's AI commands/skills were written by sungen ${s.assetsDrift!.recordedVersion} and you are running ${s.assetsDrift!.runningVersion} — upgrading the package does NOT refresh them, so any rule added since ${s.assetsDrift!.recordedVersion} is not in effect for the next run`,
39
+ }),
40
+ },
41
+ {
42
+ // The yardstick `atomicLedger` and `traceability` are measured against; it can go missing from a
43
+ // unit that already HAS a spec, which unit.no-source never sees.
44
+ id: 'unit.viewpoint-missing', title: 'Restore the test viewpoint', actor: 'human', granularity: 'unit',
45
+ appliesTo: ALL_KINDS, requires: ['unit.no-source'], blocking: false, rank: 30, gates: [], produces: ['requirements/test-viewpoint.md'],
46
+ active: () => true,
47
+ satisfied: (s) => s.hasViewpoint,
48
+ step: (s) => ({
49
+ kind: 'blocked',
50
+ command: s.kind === 'flow'
51
+ ? `sungen add-flow --flow ${s.unit} --path <start-url> # repairs the missing scaffold; never overwrites`
52
+ : `write qa/screens/${s.unit}/requirements/test-viewpoint.md`,
53
+ because: 'requirements/test-viewpoint.md is missing — it is the yardstick `atomicLedger` and `traceability` are measured against, and four sensors read it, so the audit reports VIEWPOINT-MISSING and those axes are excluded. A flow contract does not substitute: it declares the use case, the viewpoint declares the claims',
54
+ }),
55
+ },
56
+ {
57
+ id: 'unit.flow-contract', title: 'Author the flow contract', actor: 'human', granularity: 'unit',
58
+ appliesTo: ['flow'], requires: ['unit.no-source'], blocking: true, rank: 40, gates: [], produces: ['requirements/flow-contract.yaml'],
59
+ active: () => true,
60
+ satisfied: (s) => s.hasContract,
61
+ step: (s) => ({
62
+ kind: 'blocked',
63
+ command: `author requirements/flow-contract.yaml, then ${design(s.unit)}`,
64
+ because: 'a flow with no contract is scored as a generic screen against page-type themes a journey cannot have (FLOW-CONTRACT-MISSING)',
65
+ }),
66
+ },
67
+ {
68
+ id: 'unit.no-scenarios', title: 'Generate the scenarios', actor: 'ai', granularity: 'unit',
69
+ appliesTo: ALL_KINDS, requires: ['unit.no-source', 'unit.flow-contract'], blocking: true, rank: 50,
70
+ gates: ['journey.phase-create'], produces: ['features/<unit>.feature'],
71
+ active: () => true,
72
+ satisfied: (s) => s.scenarioCount !== 0,
73
+ step: (s) => ({ kind: 'do', command: design(s.unit), because: 'no scenarios exist yet' }),
74
+ },
75
+ {
76
+ // Without the inventory, coverage is per PHASE, and a phase counts as covered once one scenario
77
+ // carries it — so the number cannot show a missing flow.
78
+ id: 'unit.flow-inventory', title: 'Declare the flow inventory', actor: 'ai', granularity: 'unit',
79
+ appliesTo: ['flow'], requires: ['unit.no-scenarios'], blocking: false, rank: 60, gates: [], produces: ['requirements/flow-contract.yaml'],
80
+ active: () => true,
81
+ satisfied: (s) => s.hasFlowInventory,
82
+ step: (s) => ({
83
+ kind: 'do',
84
+ command: `add \`flows:\` to requirements/flow-contract.yaml, then sungen audit --screen ${s.unit}`,
85
+ because: 'without the inventory, coverage is measured per PHASE — and a phase counts as covered as soon as one scenario carries it, so the number cannot tell you a flow is missing',
86
+ }),
87
+ },
88
+ ];
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Execution-stage unit nodes — rows 11–15 (+13b from phase 01) of the OES-10.2 parity table, with the
3
+ * exact words of the frozen oracle.
4
+ *
5
+ * 11 unit.selectors non-api, no selectors or a placeholder file → run-test, cuts
6
+ * 12 unit.compile not compiled → `sungen generate`, cuts
7
+ * 13 unit.run never run → run-test, cuts
8
+ * 13b unit.triage results with failures → `sungen triage`, before delivery, does not cut —
9
+ * with test-case states it keeps only the reds no case accounts for; tc.triage
10
+ * takes the rest (phase 05)
11
+ * 14 unit.deliver no deliverable → delivery
12
+ * 15 unit.extend always → optional create-test (the end of the path)
13
+ */
14
+ import { ALL_KINDS, UnitNodeDecl } from '../node-decl';
15
+ import { attributedReds, unattributedReds } from './test-case-nodes';
16
+
17
+ const TRIAGE_TAIL = 'classify each (known defect, test defect, environment, product candidate) before exporting or extending: an unexplained red in the deliverable is a finding nobody has judged';
18
+
19
+ export const UNIT_EXECUTION_NODES: readonly UnitNodeDecl[] = [
20
+ {
21
+ // A scaffolded selector file exists but resolves nothing; treating it as done makes a run look further along.
22
+ id: 'unit.selectors', title: 'Generate selectors from the live page', actor: 'ai', granularity: 'unit',
23
+ appliesTo: ['screen', 'flow'], requires: ['unit.gate-fail'], blocking: true, rank: 110, gates: [], produces: ['selectors/<unit>.yaml'],
24
+ active: () => true,
25
+ satisfied: (s) => s.hasSelectors && !s.selectorsArePlaceholder,
26
+ step: (s) => ({
27
+ kind: 'do',
28
+ command: `/sungen:run-test ${s.unit}`,
29
+ because: s.hasSelectors
30
+ ? 'the selector file is still a placeholder, so nothing resolves against a live page'
31
+ : 'no selectors exist yet — run-test generates them from the live page, compiles and auto-fixes',
32
+ }),
33
+ },
34
+ {
35
+ id: 'unit.compile', title: 'Compile the suite', actor: 'deterministic', granularity: 'unit',
36
+ appliesTo: ALL_KINDS, requires: ['unit.gate-fail', 'unit.selectors'], blocking: true, rank: 120, gates: [], produces: ['specs/generated/<unit>/'],
37
+ active: () => true,
38
+ satisfied: (s) => s.compiled,
39
+ step: (s) => ({ kind: 'do', command: `sungen generate --${s.kind === 'flow' ? 'flow' : 'screen'} ${s.unit}`, because: 'the suite has not been compiled to a spec yet' }),
40
+ },
41
+ {
42
+ id: 'unit.run', title: 'Run the compiled suite', actor: 'ai', granularity: 'unit',
43
+ appliesTo: ALL_KINDS, requires: ['unit.compile'], blocking: true, rank: 130, gates: ['journey.phase-run'], produces: ['specs/generated/<unit>/<unit>-test-result.json'],
44
+ active: () => true,
45
+ satisfied: (s) => s.hasResults,
46
+ step: (s) => ({ kind: 'do', command: `/sungen:run-test ${s.unit}`, because: 'the compiled spec has never been run, so every case is Pending' }),
47
+ },
48
+ {
49
+ // Reds are classified before they are exported or built on; the steps after it still follow.
50
+ id: 'unit.triage', title: 'Classify the failed scenarios', actor: 'deterministic', granularity: 'unit',
51
+ appliesTo: ALL_KINDS, requires: ['unit.run'], blocking: false, rank: 135, gates: [], produces: ['.sungen/triage/<unit>.json'],
52
+ active: () => true,
53
+ satisfied: (s) => !(unattributedReds(s) > 0),
54
+ step: (s) => ({
55
+ kind: 'do',
56
+ command: `sungen triage --${s.kind === 'api' ? 'api' : 'screen'} ${s.unit}`,
57
+ because: attributedReds(s) > 0
58
+ ? `${unattributedReds(s)} failed result(s) in the latest run match no test case of the .feature (a renamed scenario, an @cases row or a title the .feature does not show) — ${TRIAGE_TAIL}`
59
+ : `${s.failedCount} scenario(s) failed in the latest run — ${TRIAGE_TAIL}`,
60
+ }),
61
+ },
62
+ {
63
+ id: 'unit.deliver', title: 'Export the deliverable', actor: 'ai', granularity: 'unit',
64
+ appliesTo: ALL_KINDS, requires: ['unit.run'], blocking: false, rank: 140, gates: ['journey.phase-deliver', 'decision.in-run'],
65
+ produces: ['qa/deliverables/<unit>-testcases.xlsx'],
66
+ active: () => true,
67
+ satisfied: (s) => s.hasDeliverable,
68
+ step: (s) => ({ kind: 'do', command: `/sungen:delivery ${s.unit}`, because: 'results exist but have not been exported to the Test Case & Coverage Matrix' }),
69
+ },
70
+ {
71
+ id: 'unit.extend', title: 'Extend coverage', actor: 'ai', granularity: 'unit',
72
+ appliesTo: ALL_KINDS, requires: ['unit.run'], blocking: false, rank: 150, gates: [], produces: ['features/<unit>.feature'],
73
+ active: () => true,
74
+ satisfied: () => false,
75
+ step: (s) => ({ kind: 'optional', command: `/sungen:create-test ${s.unit}`, because: 'extend coverage — the next tier, or the flows the inventory still lists as pending' }),
76
+ },
77
+ ];
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Which test cases a unit holds, read off its `.feature` files (DOS-11.1): one per runnable scenario
3
+ * — `@steps` bases, hooks and the scaffold sample are not test cases (as in delivery).
4
+ *
5
+ * id the scenario's VP-id (the exporters' format-tolerant SCENARIO_ID); without one,
6
+ * `T-<hash8>` of file + title, flagged `unstableId` (a rename changes it)
7
+ * lines the scenario block, its tag lines included, up to the line before the next block
8
+ * mocked verified against a declared mock (`@mock` / `@network`, or a mock step) — Pass (Mocked)
9
+ */
10
+ import { createHash } from 'crypto';
11
+ import * as fs from 'fs';
12
+ import * as path from 'path';
13
+ import { isHookScenario, isSampleScaffoldScenario, isStepsBaseScenario, parseFeatureMetadata, splitVpAndName } from '../exporters/feature-parser';
14
+ import { featureFilesFor } from '../harness/unit-paths';
15
+
16
+ export interface FeatureCase {
17
+ id: string;
18
+ unstableId?: true;
19
+ title: string;
20
+ absFile: string;
21
+ /** The feature's basename — result files are named after it. */
22
+ featureBase: string;
23
+ lines: [number, number];
24
+ tags: string[];
25
+ mocked: boolean;
26
+ }
27
+
28
+ const SCENARIO_LINE = /^\s*Scenario(?: Outline)?:\s*(.*?)\s*$/;
29
+ const ENDS_BLOCK = /^\s*(?:Rule|Background):/;
30
+ /** Blank lines and the next block's section marker are not part of a scenario. */
31
+ const TRAILER = /^\s*(?:#\s*-{2,}\s*Section:.*)?$/i;
32
+ /** Literal twin of the mock grammar (exporters/matrix/build.ts detectMocked), without loading drivers. */
33
+ const MOCK_TAGS = ['@mock', '@network'];
34
+ const MOCK_STEP = /\[[^\]]+\]\s+mock\s+(?:is\s+active|called\s+(?:\{\{[^}]+\}\}|\d+)\s+times?)\b/i;
35
+
36
+ /** 1-based [first, last] line of every Scenario block, in file order. */
37
+ function scenarioBlocks(lines: string[]): Array<{ title: string; range: [number, number] }> {
38
+ const starts: Array<{ title: string; first: number; at: number }> = [];
39
+ lines.forEach((line, i) => {
40
+ const m = line.match(SCENARIO_LINE);
41
+ if (!m) return;
42
+ let first = i;
43
+ while (first > 0 && /^\s*@/.test(lines[first - 1])) first--;
44
+ starts.push({ title: m[1], first, at: i });
45
+ });
46
+ return starts.map((b, k) => {
47
+ let end = k + 1 < starts.length ? starts[k + 1].first : lines.length; // exclusive
48
+ for (let j = b.at + 1; j < end; j++) if (ENDS_BLOCK.test(lines[j])) { end = j; break; }
49
+ while (end - 1 > b.at && TRAILER.test(lines[end - 1])) end--;
50
+ return { title: b.title, range: [b.first + 1, end] as [number, number] };
51
+ });
52
+ }
53
+
54
+ export function featureCases(unitDir: string, unit: string): FeatureCase[] {
55
+ const out: FeatureCase[] = [];
56
+ for (const absFile of featureFilesFor(unitDir, unit).filter((f) => fs.existsSync(f))) {
57
+ const meta = parseFeatureMetadata(absFile);
58
+ const blocks = scenarioBlocks(fs.readFileSync(absFile, 'utf8').split(/\r?\n/));
59
+ const used = new Set<number>();
60
+ for (const sc of meta.scenarios) {
61
+ const at = blocks.findIndex((b, i) => !used.has(i) && b.title === sc.name);
62
+ if (at >= 0) used.add(at);
63
+ if (isStepsBaseScenario(sc) || isHookScenario(sc) || isSampleScaffoldScenario(sc)) continue;
64
+ const vpId = splitVpAndName(sc.name).vpId;
65
+ const rel = path.basename(absFile);
66
+ const id = vpId ?? `T-${createHash('sha1').update(`${rel}\n${sc.name}`).digest('hex').slice(0, 8)}`;
67
+ out.push({
68
+ id, ...(vpId ? {} : { unstableId: true as const }), title: sc.name, absFile, featureBase: path.basename(absFile, '.feature'),
69
+ lines: at >= 0 ? blocks[at].range : [1, 1], tags: sc.tags,
70
+ mocked: sc.tags.some((t) => MOCK_TAGS.some((m) => t === m || t.startsWith(`${m}:`))) || sc.orderedSteps.some((s) => MOCK_STEP.test(s.text)),
71
+ });
72
+ }
73
+ }
74
+ return out;
75
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * What has happened to each test case: its result, whether that result still describes the
3
+ * scenario, and the triage verdict on it — all read off files that already exist (DOS-11.1).
4
+ *
5
+ * result final attempt across every result file of its feature (`<base>-test-result[.<os>][.<env>].json`)
6
+ * and every `@cases` row (`<title> — <label>`): any red → failed; else any pass → passed
7
+ * stale the run manifest (`sungen changed`) selects the scenario: its steps/tags, a selector or a
8
+ * test-data key it uses, or a project input changed since the recorded run
9
+ * triage the rows of `.sungen/triage/<unit>.json` for the case, only when that triage is not
10
+ * older than the case's result files (a re-run voids it)
11
+ */
12
+ import * as fs from 'fs';
13
+ import * as path from 'path';
14
+ import { loadPlaywrightReport } from '../exporters/playwright-report-parser';
15
+ import type { PlaywrightResult } from '../exporters/types';
16
+ import { buildRunManifest, readRunManifest, selectChanged } from '../harness/run-manifest';
17
+ import { readTriageReport } from '../harness/triage-unit';
18
+ import type { TriageClass } from '../harness/triage';
19
+ import type { FeatureCase } from './test-case-identity';
20
+ import type { TestCaseResult, TestCaseState } from './test-case-state-shape';
21
+ import { generatedDirs, RESULT_FILE } from './unit-artifact-probes';
22
+
23
+ const RED = new Set<PlaywrightResult['status']>(['failed', 'timedOut', 'interrupted']);
24
+ /** The class a case shows when its rows disagree: what needs a human first. */
25
+ const TRIAGE_PRECEDENCE: TriageClass[] = ['product-candidate', 'unclassified', 'test-defect', 'environment', 'known-defect', 'blocked-capability', 'flaky'];
26
+
27
+ export interface CaseOutcome { result: TestCaseResult; failedResults: number; resultFiles: string[]; stale?: string; triage?: TestCaseState['triage'] }
28
+
29
+ const ownsTitle = (key: string, title: string): boolean => key === title || key.endsWith(` > ${title}`)
30
+ || key.startsWith(`${title} — `) || key.includes(` > ${title} — `);
31
+ const rowOwns = (scenario: string, title: string): boolean => scenario === title || scenario.startsWith(`${title} — `);
32
+ const mtime = (f: string): number => { try { return fs.statSync(f).mtimeMs; } catch { return 0; } };
33
+
34
+ /** Every result file of each feature, with its parsed report (read once per file). */
35
+ function resultsByFeature(projectRoot: string, unit: string, unitId: string): Map<string, Array<{ file: string; report: Map<string, PlaywrightResult> }>> {
36
+ const dirs = [...new Set([...generatedDirs(projectRoot, unit), path.join(projectRoot, 'specs', 'generated', unitId)])];
37
+ const out = new Map<string, Array<{ file: string; report: Map<string, PlaywrightResult> }>>();
38
+ for (const d of dirs) {
39
+ let names: string[] = [];
40
+ try { names = fs.readdirSync(d).filter((f) => RESULT_FILE.test(f)).sort(); } catch { continue; }
41
+ for (const name of names) {
42
+ const report = loadPlaywrightReport(path.join(d, name));
43
+ if (!report) continue; // unreadable = unknown, never red
44
+ const base = name.replace(RESULT_FILE, '');
45
+ out.set(base, [...(out.get(base) ?? []), { file: path.join(d, name), report }]);
46
+ }
47
+ }
48
+ return out;
49
+ }
50
+
51
+ /** Scenarios `sungen changed` would re-run. No baseline, or one that cannot be read, claims nothing. */
52
+ function staleReasons(projectRoot: string, unitDir: string, unit: string): Record<string, string> {
53
+ const before = readRunManifest(projectRoot, unit);
54
+ if (!before || typeof before.scenarios !== 'object' || !before.selectorKeys || !before.dataKeys) return {};
55
+ try { return selectChanged(before, buildRunManifest(projectRoot, unitDir, unit)).reasons; } catch { return {}; }
56
+ }
57
+
58
+ /** The triage rows, shape-checked: the report is a file anyone can edit. */
59
+ function triageRows(projectRoot: string, unitId: string): { at: number; rows: Array<{ scenario: string; class: TriageClass; ruleId: string }> } {
60
+ const report = readTriageReport(projectRoot, unitId);
61
+ const rows = Array.isArray(report?.rows)
62
+ ? report!.rows.filter((r) => r && typeof r.scenario === 'string' && TRIAGE_PRECEDENCE.includes(r.class)) : [];
63
+ return { at: report && typeof report.generatedAt === 'string' ? Date.parse(report.generatedAt) : NaN, rows };
64
+ }
65
+
66
+ export function caseOutcomes(projectRoot: string, unitDir: string, unit: string, unitId: string, cases: FeatureCase[]): CaseOutcome[] {
67
+ const byFeature = resultsByFeature(projectRoot, unit, unitId);
68
+ const stale = staleReasons(projectRoot, unitDir, unit);
69
+ const triage = triageRows(projectRoot, unitId);
70
+ return cases.map((c) => {
71
+ const statuses: PlaywrightResult['status'][] = [];
72
+ const files: string[] = [];
73
+ for (const { file, report } of byFeature.get(c.featureBase) ?? []) {
74
+ const mine = [...report.entries()].filter(([key]) => ownsTitle(key, c.title)).map(([, r]) => r.status);
75
+ if (mine.length) { statuses.push(...mine); files.push(file); }
76
+ }
77
+ const result: TestCaseResult = statuses.some((s) => RED.has(s)) ? 'failed'
78
+ : statuses.includes('passed') ? 'passed' : statuses.includes('skipped') ? 'skipped' : 'never-run';
79
+ const out: CaseOutcome = {
80
+ result, failedResults: statuses.filter((st) => RED.has(st)).length,
81
+ resultFiles: files.map((f) => path.relative(projectRoot, f).split(path.sep).join('/')),
82
+ };
83
+ if (result !== 'never-run' && stale[c.title]) out.stale = stale[c.title];
84
+ const current = !Number.isNaN(triage.at) && files.every((f) => mtime(f) <= triage.at);
85
+ const rows = current ? triage.rows.filter((r) => rowOwns(r.scenario, c.title)) : [];
86
+ const worst = TRIAGE_PRECEDENCE.find((cls) => rows.some((r) => r.class === cls));
87
+ if (worst) out.triage = { class: worst, ruleId: rows.find((r) => r.class === worst)!.ruleId };
88
+ return out;
89
+ });
90
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * When a test case generates work, and which (DOS-11.2).
3
+ *
4
+ * exempt — satisfied, no work: `@manual` (a human executes it), `@requires:<cap>` (waits on a
5
+ * capability the QA has not enabled), `@known-defect` (a recorded product defect),
6
+ * `@deferred:flow` (owned and automated by its flow — the contract excludes it too),
7
+ * triage `blocked-capability`. Any other `@deferred:*` is NOT exempt.
8
+ * trigger — what the case needs otherwise, first match wins:
9
+ * never run → run · result older than the scenario (run manifest) → rerun-stale ·
10
+ * red with no current triage, or left `unclassified` by it → triage (a classification
11
+ * is still owed) · triaged product-candidate → a QA decision
12
+ * A pass — Pass (Mocked) included — needs nothing. A red triaged test-defect / environment has been
13
+ * judged; the triage report and the deliverable carry it (no P0 node — a P1 follow-up).
14
+ */
15
+ import type { TestCaseState } from './test-case-state-shape';
16
+
17
+ export type TestCaseExemption = 'manual' | 'requires' | 'known-defect' | 'deferred' | 'blocked-capability';
18
+ export type TestCaseNeed = 'run' | 'rerun-stale' | 'triage' | 'product-candidate';
19
+
20
+ const tagged = (tc: TestCaseState, tag: string): boolean => tc.tags.some((t) => t === tag || t.startsWith(`${tag}:`));
21
+
22
+ /** Why the case is satisfied regardless of its result, or null when it is not exempt. */
23
+ export function exemptionOf(tc: TestCaseState): TestCaseExemption | null {
24
+ if (tagged(tc, '@manual')) return 'manual';
25
+ if (tc.tags.some((t) => t.startsWith('@requires:'))) return 'requires';
26
+ if (tagged(tc, '@known-defect')) return 'known-defect';
27
+ if (tc.tags.some((t) => /^@deferred:flow$/i.test(t))) return 'deferred';
28
+ if (tc.triage?.class === 'blocked-capability') return 'blocked-capability';
29
+ return null;
30
+ }
31
+
32
+ /** What the case would need if it were not exempt. */
33
+ export function triggerOf(tc: TestCaseState): TestCaseNeed | null {
34
+ if (tc.result === 'never-run') return 'run';
35
+ if (tc.stale) return 'rerun-stale';
36
+ if (tc.result === 'failed') {
37
+ if (!tc.triage || tc.triage.class === 'unclassified') return 'triage';
38
+ if (tc.triage.class === 'product-candidate') return 'product-candidate';
39
+ }
40
+ return null;
41
+ }
42
+
43
+ export function testCaseNeed(tc: TestCaseState): TestCaseNeed | null {
44
+ return exemptionOf(tc) ? null : triggerOf(tc);
45
+ }
46
+
47
+ /** One word for `--case`: why the case asks for nothing, or what it needs. */
48
+ export function testCaseStatusLabel(tc: TestCaseState): string {
49
+ const exempt = exemptionOf(tc);
50
+ if (exempt) return `satisfied (${exempt})`;
51
+ const need = triggerOf(tc);
52
+ if (need) return `needs ${need}`;
53
+ if (tc.result === 'passed') return tc.mocked ? 'satisfied (Pass (Mocked))' : 'satisfied (passed)';
54
+ return tc.triage ? `satisfied (triaged ${tc.triage.class})` : `satisfied (${tc.result})`;
55
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The shape of one test case's state (DOS-11.1) — facts read off files that already exist, never a
3
+ * stored record. `testCaseStates()` (test-case-states.ts) builds it; `test-case-satisfied.ts` decides
4
+ * whether it generates work; the test-case nodes turn the unsatisfied ones into steps.
5
+ */
6
+ import type { ScenarioClass } from '../contract/contract-schema';
7
+ import type { TriageClass } from '../harness/triage';
8
+
9
+ /** DOS-12.1 confidence labels: EXTRACTED 0.9–1.0 · INFERRED 0.5–0.89 · AMBIGUOUS < 0.5. */
10
+ export type ConfidenceLabel = 'EXTRACTED' | 'INFERRED' | 'AMBIGUOUS';
11
+
12
+ /** An audit finding pinned to the scenario it names, in the shared trace vocabulary (DOS-12.1). */
13
+ export interface LocatedFinding {
14
+ code: string;
15
+ text: string;
16
+ /** `repo@SHA:path#Lx-Ly` — SHA is `worktree` when git is absent or the file differs from HEAD. */
17
+ citation: string;
18
+ confidence: { label: ConfidenceLabel; score: number };
19
+ }
20
+
21
+ export type TestCaseResult = 'passed' | 'failed' | 'skipped' | 'never-run';
22
+
23
+ /** The case in the contract verdict `sungen contract check` rebuilds (DOS-14.4–14.6) — attached on read. */
24
+ export interface TestCaseContract {
25
+ class: ScenarioClass;
26
+ /** Its first finding, as the check prints it. */
27
+ detail?: string;
28
+ /** A trace step acts on a target whose identity is only `low` — `contract check --trace` can resolve it. */
29
+ lowIdentity?: true;
30
+ /** Its lock entry is not what QA approved and committed (contract.lock-uncommitted). */
31
+ uncommitted?: true;
32
+ }
33
+
34
+ export interface TestCaseState {
35
+ /** The scenario's VP-id; `T-<hash8>` of file + title when it carries none (`unstableId`). */
36
+ id: string;
37
+ unstableId?: true;
38
+ title: string;
39
+ /** Project-relative, `/`-separated path of the `.feature`. */
40
+ file: string;
41
+ /** 1-based first and last line of the scenario block (its tags included). */
42
+ lines: [number, number];
43
+ /** Feature and scenario tags. */
44
+ tags: string[];
45
+ /** Final-attempt outcome across every result file and variant: any red is `failed`. */
46
+ result: TestCaseResult;
47
+ /** Red final attempts this case accounts for — one per result file, variant and `@cases` row. */
48
+ failedResults?: number;
49
+ /** Verified against a declared mock — a pass is Pass (Mocked), not Pass (Real). */
50
+ mocked: boolean;
51
+ /** Result files that carry this case, project-relative. */
52
+ resultFiles: string[];
53
+ /** Set when the scenario changed after the run that produced its result (run manifest). */
54
+ stale?: string;
55
+ /** The current `sungen triage` row for a red case — absent when triage has not judged this result. */
56
+ triage?: { class: TriageClass; ruleId: string };
57
+ /** Spec anchors the case was generated from (manifest), and whether they moved since. */
58
+ anchors: Array<{ anchor: string; change: 'keep' | 'regenerate' | 'retire' | 'unknown' }>;
59
+ findings: LocatedFinding[];
60
+ /** Its class in the rebuilt contract verdict; absent outside the contract (@manual, no scenario id) or unread. */
61
+ contract?: TestCaseContract;
62
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * `testCaseStates(projectRoot, unit)` — the state of every test case of a unit, a PURE function of
3
+ * files that already exist, evaluated whenever it is read (DOS-11.1, red-team #9): no state file, no
4
+ * facet registry, nothing written. A step interrupted yesterday is recomputed today, not remembered.
5
+ *
6
+ * identity .feature test-case-identity.ts
7
+ * outcome results · run manifest · triage test-case-results.ts
8
+ * anchors .sungen/manifest/<unit>.json — the spec anchors each scenario came from, and their drift
9
+ * findings the audit's findings, located on the case they name (locate-finding.ts, DOS-12.1)
10
+ *
11
+ * The audit's findings are taken only from a report that counts (verifyAuditReport): a stale or
12
+ * untrusted report locates nothing. A caller that already verified the report passes its findings.
13
+ */
14
+ import * as fs from 'fs';
15
+ import * as path from 'path';
16
+ import { resolveUnitCandidates } from '../cli/resolve-unit';
17
+ import { auditCounts, verifyAuditReport } from '../harness/gates/audit-report-verification';
18
+ import { diffManifest, Manifest } from '../harness/manifest';
19
+ import { reportSlug } from '../harness/unit-paths';
20
+ import { gitCitationContext, locateFindings } from './locate-finding';
21
+ import { caseOutcomes } from './test-case-results';
22
+ import { featureCases } from './test-case-identity';
23
+ import type { TestCaseState } from './test-case-state-shape';
24
+
25
+ export interface TestCaseStateOptions {
26
+ /** The unit's directory, when the caller has resolved it already. */
27
+ unitDir?: string;
28
+ /** The findings of an audit report the caller verified; read through verifyAuditReport otherwise. */
29
+ auditFindings?: string[];
30
+ }
31
+
32
+ type Anchor = TestCaseState['anchors'][number];
33
+
34
+ /** scenario title → its anchors, with the change `diffManifest` reports (unknown when it cannot say). */
35
+ function anchorsByScenario(projectRoot: string, unitDir: string, unit: string): Map<string, Anchor[]> {
36
+ const out = new Map<string, Anchor[]>();
37
+ let manifest: Manifest;
38
+ try {
39
+ manifest = JSON.parse(fs.readFileSync(path.join(projectRoot, '.sungen', 'manifest', `${reportSlug(unit)}.json`), 'utf8'));
40
+ } catch { return out; }
41
+ if (!manifest || !Array.isArray(manifest.entries)) return out;
42
+ let changes: Map<string, Anchor['change']> = new Map();
43
+ try {
44
+ changes = new Map(diffManifest(unitDir, unit, manifest).scenarios.map((s) => [`${s.scenario}\n${s.section}`, s.change]));
45
+ } catch { /* a pending migration or an unreadable spec — the drift is unknown */ }
46
+ for (const e of manifest.entries) {
47
+ if (!e || typeof e.scenario !== 'string' || typeof e.section !== 'string') continue;
48
+ out.set(e.scenario, [...(out.get(e.scenario) ?? []), { anchor: e.section, change: changes.get(`${e.scenario}\n${e.section}`) ?? 'unknown' }]);
49
+ }
50
+ return out;
51
+ }
52
+
53
+ function verifiedFindings(projectRoot: string, unit: string): string[] {
54
+ const v = verifyAuditReport(projectRoot, unit);
55
+ const findings = auditCounts(v) ? v.report?.findings : undefined;
56
+ return Array.isArray(findings) ? findings.filter((f): f is string => typeof f === 'string') : [];
57
+ }
58
+
59
+ export function testCaseStates(projectRoot: string, unit: string, opts: TestCaseStateOptions = {}): TestCaseState[] {
60
+ const found = resolveUnitCandidates(unit, projectRoot);
61
+ const unitDir = opts.unitDir ?? (found.length === 1 ? found[0].dir : undefined);
62
+ if (!unitDir || !fs.existsSync(unitDir)) return [];
63
+ const unitId = found.find((f) => f.dir === unitDir)?.unitId ?? unit;
64
+ const cases = featureCases(unitDir, unit);
65
+ if (!cases.length) return [];
66
+ const outcomes = caseOutcomes(projectRoot, unitDir, unit, unitId, cases);
67
+ const anchors = anchorsByScenario(projectRoot, unitDir, unit);
68
+ const findings = opts.auditFindings ?? verifiedFindings(projectRoot, unit);
69
+ const located = findings.length
70
+ ? locateFindings(findings, cases, gitCitationContext(projectRoot, [...new Set(cases.map((c) => c.absFile))]))
71
+ : new Map();
72
+ return cases.map((c, i) => ({
73
+ id: c.id,
74
+ ...(c.unstableId ? { unstableId: true as const } : {}),
75
+ title: c.title,
76
+ file: path.relative(projectRoot, c.absFile).split(path.sep).join('/'),
77
+ lines: c.lines,
78
+ tags: c.tags,
79
+ mocked: c.mocked,
80
+ ...outcomes[i],
81
+ anchors: anchors.get(c.title) ?? [],
82
+ findings: located.get(i) ?? [],
83
+ }));
84
+ }