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

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 (889) 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/discover.d.ts +4 -0
  34. package/dist/capabilities/discover.d.ts.map +1 -1
  35. package/dist/capabilities/discover.js +16 -2
  36. package/dist/capabilities/discover.js.map +1 -1
  37. package/dist/capabilities/registry.d.ts +15 -0
  38. package/dist/capabilities/registry.d.ts.map +1 -1
  39. package/dist/capabilities/registry.js.map +1 -1
  40. package/dist/cli/commands/audit.d.ts.map +1 -1
  41. package/dist/cli/commands/audit.js +10 -5
  42. package/dist/cli/commands/audit.js.map +1 -1
  43. package/dist/cli/commands/capability.d.ts.map +1 -1
  44. package/dist/cli/commands/capability.js +6 -2
  45. package/dist/cli/commands/capability.js.map +1 -1
  46. package/dist/cli/commands/contract-derive-command.d.ts +11 -0
  47. package/dist/cli/commands/contract-derive-command.d.ts.map +1 -0
  48. package/dist/cli/commands/contract-derive-command.js +99 -0
  49. package/dist/cli/commands/contract-derive-command.js.map +1 -0
  50. package/dist/cli/commands/contract.d.ts +17 -0
  51. package/dist/cli/commands/contract.d.ts.map +1 -0
  52. package/dist/cli/commands/contract.js +162 -0
  53. package/dist/cli/commands/contract.js.map +1 -0
  54. package/dist/cli/commands/defect.d.ts +7 -0
  55. package/dist/cli/commands/defect.d.ts.map +1 -0
  56. package/dist/cli/commands/defect.js +68 -0
  57. package/dist/cli/commands/defect.js.map +1 -0
  58. package/dist/cli/commands/delivery.d.ts.map +1 -1
  59. package/dist/cli/commands/delivery.js +96 -12
  60. package/dist/cli/commands/delivery.js.map +1 -1
  61. package/dist/cli/commands/generate.d.ts.map +1 -1
  62. package/dist/cli/commands/generate.js +3 -1
  63. package/dist/cli/commands/generate.js.map +1 -1
  64. package/dist/cli/commands/journey.d.ts.map +1 -1
  65. package/dist/cli/commands/journey.js +43 -15
  66. package/dist/cli/commands/journey.js.map +1 -1
  67. package/dist/cli/commands/next.d.ts +8 -0
  68. package/dist/cli/commands/next.d.ts.map +1 -1
  69. package/dist/cli/commands/next.js +68 -8
  70. package/dist/cli/commands/next.js.map +1 -1
  71. package/dist/cli/commands/triage.d.ts +7 -0
  72. package/dist/cli/commands/triage.d.ts.map +1 -0
  73. package/dist/cli/commands/triage.js +98 -0
  74. package/dist/cli/commands/triage.js.map +1 -0
  75. package/dist/cli/commands/update.d.ts +11 -0
  76. package/dist/cli/commands/update.d.ts.map +1 -1
  77. package/dist/cli/commands/update.js +31 -6
  78. package/dist/cli/commands/update.js.map +1 -1
  79. package/dist/cli/index.js +24 -33
  80. package/dist/cli/index.js.map +1 -1
  81. package/dist/cli/project-sungen-invocation.d.ts +7 -0
  82. package/dist/cli/project-sungen-invocation.d.ts.map +1 -0
  83. package/dist/cli/project-sungen-invocation.js +76 -0
  84. package/dist/cli/project-sungen-invocation.js.map +1 -0
  85. package/dist/contract/approve-contract.d.ts +31 -0
  86. package/dist/contract/approve-contract.d.ts.map +1 -0
  87. package/dist/contract/approve-contract.js +87 -0
  88. package/dist/contract/approve-contract.js.map +1 -0
  89. package/dist/contract/assertion-matcher-vocabulary.d.ts +24 -0
  90. package/dist/contract/assertion-matcher-vocabulary.d.ts.map +1 -0
  91. package/dist/contract/assertion-matcher-vocabulary.js +100 -0
  92. package/dist/contract/assertion-matcher-vocabulary.js.map +1 -0
  93. package/dist/contract/build-contract-verdict.d.ts +32 -0
  94. package/dist/contract/build-contract-verdict.d.ts.map +1 -0
  95. package/dist/contract/build-contract-verdict.js +123 -0
  96. package/dist/contract/build-contract-verdict.js.map +1 -0
  97. package/dist/contract/build-trace-conformance.d.ts +18 -0
  98. package/dist/contract/build-trace-conformance.d.ts.map +1 -0
  99. package/dist/contract/build-trace-conformance.js +153 -0
  100. package/dist/contract/build-trace-conformance.js.map +1 -0
  101. package/dist/contract/classify-contract-change.d.ts +23 -0
  102. package/dist/contract/classify-contract-change.d.ts.map +1 -0
  103. package/dist/contract/classify-contract-change.js +98 -0
  104. package/dist/contract/classify-contract-change.js.map +1 -0
  105. package/dist/contract/classify-contract-unit.d.ts +18 -0
  106. package/dist/contract/classify-contract-unit.d.ts.map +1 -0
  107. package/dist/contract/classify-contract-unit.js +49 -0
  108. package/dist/contract/classify-contract-unit.js.map +1 -0
  109. package/dist/contract/classify-trace-conformance.d.ts +32 -0
  110. package/dist/contract/classify-trace-conformance.d.ts.map +1 -0
  111. package/dist/contract/classify-trace-conformance.js +117 -0
  112. package/dist/contract/classify-trace-conformance.js.map +1 -0
  113. package/dist/contract/contract-git.d.ts +24 -0
  114. package/dist/contract/contract-git.d.ts.map +1 -0
  115. package/dist/contract/contract-git.js +144 -0
  116. package/dist/contract/contract-git.js.map +1 -0
  117. package/dist/contract/contract-hash.d.ts +7 -0
  118. package/dist/contract/contract-hash.d.ts.map +1 -0
  119. package/dist/contract/contract-hash.js +38 -0
  120. package/dist/contract/contract-hash.js.map +1 -0
  121. package/dist/contract/contract-report-file.d.ts +4 -0
  122. package/dist/contract/contract-report-file.d.ts.map +1 -0
  123. package/dist/contract/contract-report-file.js +60 -0
  124. package/dist/contract/contract-report-file.js.map +1 -0
  125. package/dist/contract/contract-schema.d.ts +71 -0
  126. package/dist/contract/contract-schema.d.ts.map +1 -0
  127. package/dist/contract/contract-schema.js +102 -0
  128. package/dist/contract/contract-schema.js.map +1 -0
  129. package/dist/contract/contract-units.d.ts +12 -0
  130. package/dist/contract/contract-units.d.ts.map +1 -0
  131. package/dist/contract/contract-units.js +96 -0
  132. package/dist/contract/contract-units.js.map +1 -0
  133. package/dist/contract/contracts-lock-file.d.ts +24 -0
  134. package/dist/contract/contracts-lock-file.d.ts.map +1 -0
  135. package/dist/contract/contracts-lock-file.js +140 -0
  136. package/dist/contract/contracts-lock-file.js.map +1 -0
  137. package/dist/contract/data-normalize.d.ts +10 -0
  138. package/dist/contract/data-normalize.d.ts.map +1 -0
  139. package/dist/contract/data-normalize.js +110 -0
  140. package/dist/contract/data-normalize.js.map +1 -0
  141. package/dist/contract/derive-free-feature.d.ts +38 -0
  142. package/dist/contract/derive-free-feature.d.ts.map +1 -0
  143. package/dist/contract/derive-free-feature.js +154 -0
  144. package/dist/contract/derive-free-feature.js.map +1 -0
  145. package/dist/contract/field-semantic-redaction.d.ts +21 -0
  146. package/dist/contract/field-semantic-redaction.d.ts.map +1 -0
  147. package/dist/contract/field-semantic-redaction.js +118 -0
  148. package/dist/contract/field-semantic-redaction.js.map +1 -0
  149. package/dist/contract/free-feature-blocks.d.ts +10 -0
  150. package/dist/contract/free-feature-blocks.d.ts.map +1 -0
  151. package/dist/contract/free-feature-blocks.js +94 -0
  152. package/dist/contract/free-feature-blocks.js.map +1 -0
  153. package/dist/contract/lock-secret-guard.d.ts +22 -0
  154. package/dist/contract/lock-secret-guard.d.ts.map +1 -0
  155. package/dist/contract/lock-secret-guard.js +134 -0
  156. package/dist/contract/lock-secret-guard.js.map +1 -0
  157. package/dist/contract/lock-vs-git-head.d.ts +26 -0
  158. package/dist/contract/lock-vs-git-head.d.ts.map +1 -0
  159. package/dist/contract/lock-vs-git-head.js +28 -0
  160. package/dist/contract/lock-vs-git-head.js.map +1 -0
  161. package/dist/contract/normalize-contract-step.d.ts +21 -0
  162. package/dist/contract/normalize-contract-step.d.ts.map +1 -0
  163. package/dist/contract/normalize-contract-step.js +70 -0
  164. package/dist/contract/normalize-contract-step.js.map +1 -0
  165. package/dist/contract/normalize-feature-steps.d.ts +7 -0
  166. package/dist/contract/normalize-feature-steps.d.ts.map +1 -0
  167. package/dist/contract/normalize-feature-steps.js +127 -0
  168. package/dist/contract/normalize-feature-steps.js.map +1 -0
  169. package/dist/contract/oracle-strength.d.ts +12 -0
  170. package/dist/contract/oracle-strength.d.ts.map +1 -0
  171. package/dist/contract/oracle-strength.js +88 -0
  172. package/dist/contract/oracle-strength.js.map +1 -0
  173. package/dist/contract/project-contract-blockers.d.ts +10 -0
  174. package/dist/contract/project-contract-blockers.d.ts.map +1 -0
  175. package/dist/contract/project-contract-blockers.js +73 -0
  176. package/dist/contract/project-contract-blockers.js.map +1 -0
  177. package/dist/contract/record-contract-approval.d.ts +21 -0
  178. package/dist/contract/record-contract-approval.d.ts.map +1 -0
  179. package/dist/contract/record-contract-approval.js +98 -0
  180. package/dist/contract/record-contract-approval.js.map +1 -0
  181. package/dist/contract/render-free-gherkin.d.ts +40 -0
  182. package/dist/contract/render-free-gherkin.d.ts.map +1 -0
  183. package/dist/contract/render-free-gherkin.js +141 -0
  184. package/dist/contract/render-free-gherkin.js.map +1 -0
  185. package/dist/contract/render-trace-sentence.d.ts +20 -0
  186. package/dist/contract/render-trace-sentence.d.ts.map +1 -0
  187. package/dist/contract/render-trace-sentence.js +109 -0
  188. package/dist/contract/render-trace-sentence.js.map +1 -0
  189. package/dist/contract/render-trace-target.d.ts +14 -0
  190. package/dist/contract/render-trace-target.d.ts.map +1 -0
  191. package/dist/contract/render-trace-target.js +70 -0
  192. package/dist/contract/render-trace-target.js.map +1 -0
  193. package/dist/contract/resolve-unit-trace-identities.d.ts +8 -0
  194. package/dist/contract/resolve-unit-trace-identities.d.ts.map +1 -0
  195. package/dist/contract/resolve-unit-trace-identities.js +78 -0
  196. package/dist/contract/resolve-unit-trace-identities.js.map +1 -0
  197. package/dist/contract/trace/collect-trace-evidence.d.ts +33 -0
  198. package/dist/contract/trace/collect-trace-evidence.d.ts.map +1 -0
  199. package/dist/contract/trace/collect-trace-evidence.js +161 -0
  200. package/dist/contract/trace/collect-trace-evidence.js.map +1 -0
  201. package/dist/contract/trace/identity-cache.d.ts +19 -0
  202. package/dist/contract/trace/identity-cache.d.ts.map +1 -0
  203. package/dist/contract/trace/identity-cache.js +104 -0
  204. package/dist/contract/trace/identity-cache.js.map +1 -0
  205. package/dist/contract/trace/select-final-attempt.d.ts +27 -0
  206. package/dist/contract/trace/select-final-attempt.d.ts.map +1 -0
  207. package/dist/contract/trace/select-final-attempt.js +116 -0
  208. package/dist/contract/trace/select-final-attempt.js.map +1 -0
  209. package/dist/contract/trace/snapshot-html-renderer.d.ts +31 -0
  210. package/dist/contract/trace/snapshot-html-renderer.d.ts.map +1 -0
  211. package/dist/contract/trace/snapshot-html-renderer.js +172 -0
  212. package/dist/contract/trace/snapshot-html-renderer.js.map +1 -0
  213. package/dist/contract/trace/snapshot-resolver.d.ts +21 -0
  214. package/dist/contract/trace/snapshot-resolver.d.ts.map +1 -0
  215. package/dist/contract/trace/snapshot-resolver.js +65 -0
  216. package/dist/contract/trace/snapshot-resolver.js.map +1 -0
  217. package/dist/contract/trace/snapshot-store.d.ts +66 -0
  218. package/dist/contract/trace/snapshot-store.d.ts.map +1 -0
  219. package/dist/contract/trace/snapshot-store.js +173 -0
  220. package/dist/contract/trace/snapshot-store.js.map +1 -0
  221. package/dist/contract/trace/target-identity.d.ts +74 -0
  222. package/dist/contract/trace/target-identity.d.ts.map +1 -0
  223. package/dist/contract/trace/target-identity.js +68 -0
  224. package/dist/contract/trace/target-identity.js.map +1 -0
  225. package/dist/contract/trace/test-step-join.d.ts +65 -0
  226. package/dist/contract/trace/test-step-join.d.ts.map +1 -0
  227. package/dist/contract/trace/test-step-join.js +80 -0
  228. package/dist/contract/trace/test-step-join.js.map +1 -0
  229. package/dist/contract/trace/trace-binding.d.ts +21 -0
  230. package/dist/contract/trace/trace-binding.d.ts.map +1 -0
  231. package/dist/contract/trace/trace-binding.js +88 -0
  232. package/dist/contract/trace/trace-binding.js.map +1 -0
  233. package/dist/contract/trace/trace-file-reader.d.ts +41 -0
  234. package/dist/contract/trace/trace-file-reader.d.ts.map +1 -0
  235. package/dist/contract/trace/trace-file-reader.js +161 -0
  236. package/dist/contract/trace/trace-file-reader.js.map +1 -0
  237. package/dist/contract/trace/trace-fingerprint.d.ts +22 -0
  238. package/dist/contract/trace/trace-fingerprint.d.ts.map +1 -0
  239. package/dist/contract/trace/trace-fingerprint.js +96 -0
  240. package/dist/contract/trace/trace-fingerprint.js.map +1 -0
  241. package/dist/contract/trace/trace-identity-resolution.d.ts +26 -0
  242. package/dist/contract/trace/trace-identity-resolution.d.ts.map +1 -0
  243. package/dist/contract/trace/trace-identity-resolution.js +84 -0
  244. package/dist/contract/trace/trace-identity-resolution.js.map +1 -0
  245. package/dist/contract/trace/trace-run-record.d.ts +30 -0
  246. package/dist/contract/trace/trace-run-record.d.ts.map +1 -0
  247. package/dist/contract/trace/trace-run-record.js +121 -0
  248. package/dist/contract/trace/trace-run-record.js.map +1 -0
  249. package/dist/contract/trace/trace-steps.d.ts +19 -0
  250. package/dist/contract/trace/trace-steps.d.ts.map +1 -0
  251. package/dist/contract/trace/trace-steps.js +79 -0
  252. package/dist/contract/trace/trace-steps.js.map +1 -0
  253. package/dist/contract/trace/trace-zip-limits.d.ts +45 -0
  254. package/dist/contract/trace/trace-zip-limits.d.ts.map +1 -0
  255. package/dist/contract/trace/trace-zip-limits.js +52 -0
  256. package/dist/contract/trace/trace-zip-limits.js.map +1 -0
  257. package/dist/contract/trace/trace-zip-reader.d.ts +10 -0
  258. package/dist/contract/trace/trace-zip-reader.d.ts.map +1 -0
  259. package/dist/contract/trace/trace-zip-reader.js +186 -0
  260. package/dist/contract/trace/trace-zip-reader.js.map +1 -0
  261. package/dist/contract/verify-approval-decisions.d.ts +5 -0
  262. package/dist/contract/verify-approval-decisions.d.ts.map +1 -0
  263. package/dist/contract/verify-approval-decisions.js +104 -0
  264. package/dist/contract/verify-approval-decisions.js.map +1 -0
  265. package/dist/decisions/append-decision.d.ts +12 -0
  266. package/dist/decisions/append-decision.d.ts.map +1 -0
  267. package/dist/decisions/append-decision.js +73 -0
  268. package/dist/decisions/append-decision.js.map +1 -0
  269. package/dist/decisions/confirmed-decision-commands.d.ts +41 -0
  270. package/dist/decisions/confirmed-decision-commands.d.ts.map +1 -0
  271. package/dist/decisions/confirmed-decision-commands.js +190 -0
  272. package/dist/decisions/confirmed-decision-commands.js.map +1 -0
  273. package/dist/decisions/decision-file.d.ts +31 -0
  274. package/dist/decisions/decision-file.d.ts.map +1 -0
  275. package/dist/decisions/decision-file.js +139 -0
  276. package/dist/decisions/decision-file.js.map +1 -0
  277. package/dist/decisions/decision-identity.d.ts +12 -0
  278. package/dist/decisions/decision-identity.d.ts.map +1 -0
  279. package/dist/decisions/decision-identity.js +78 -0
  280. package/dist/decisions/decision-identity.js.map +1 -0
  281. package/dist/decisions/decision-integrity-check.d.ts +12 -0
  282. package/dist/decisions/decision-integrity-check.d.ts.map +1 -0
  283. package/dist/decisions/decision-integrity-check.js +102 -0
  284. package/dist/decisions/decision-integrity-check.js.map +1 -0
  285. package/dist/decisions/decision-schema.d.ts +42 -0
  286. package/dist/decisions/decision-schema.d.ts.map +1 -0
  287. package/dist/decisions/decision-schema.js +75 -0
  288. package/dist/decisions/decision-schema.js.map +1 -0
  289. package/dist/decisions/decision-source.d.ts +2 -0
  290. package/dist/decisions/decision-source.d.ts.map +1 -0
  291. package/dist/decisions/decision-source.js +18 -0
  292. package/dist/decisions/decision-source.js.map +1 -0
  293. package/dist/decisions/exclusive-file-create.d.ts +3 -0
  294. package/dist/decisions/exclusive-file-create.d.ts.map +1 -0
  295. package/dist/decisions/exclusive-file-create.js +84 -0
  296. package/dist/decisions/exclusive-file-create.js.map +1 -0
  297. package/dist/decisions/git-head-trust.d.ts +7 -0
  298. package/dist/decisions/git-head-trust.d.ts.map +1 -0
  299. package/dist/decisions/git-head-trust.js +76 -0
  300. package/dist/decisions/git-head-trust.js.map +1 -0
  301. package/dist/decisions/human-confirmation.d.ts +35 -0
  302. package/dist/decisions/human-confirmation.d.ts.map +1 -0
  303. package/dist/decisions/human-confirmation.js +161 -0
  304. package/dist/decisions/human-confirmation.js.map +1 -0
  305. package/dist/decisions/legacy-waiver-migration.d.ts +31 -0
  306. package/dist/decisions/legacy-waiver-migration.d.ts.map +1 -0
  307. package/dist/decisions/legacy-waiver-migration.js +170 -0
  308. package/dist/decisions/legacy-waiver-migration.js.map +1 -0
  309. package/dist/decisions/read-decisions.d.ts +19 -0
  310. package/dist/decisions/read-decisions.d.ts.map +1 -0
  311. package/dist/decisions/read-decisions.js +90 -0
  312. package/dist/decisions/read-decisions.js.map +1 -0
  313. package/dist/decisions/viewpoint-baseline-adapter.d.ts +7 -0
  314. package/dist/decisions/viewpoint-baseline-adapter.d.ts.map +1 -0
  315. package/dist/decisions/viewpoint-baseline-adapter.js +109 -0
  316. package/dist/decisions/viewpoint-baseline-adapter.js.map +1 -0
  317. package/dist/decisions/waiver-decisions.d.ts +24 -0
  318. package/dist/decisions/waiver-decisions.d.ts.map +1 -0
  319. package/dist/decisions/waiver-decisions.js +46 -0
  320. package/dist/decisions/waiver-decisions.js.map +1 -0
  321. package/dist/exporters/csv-exporter.d.ts +4 -0
  322. package/dist/exporters/csv-exporter.d.ts.map +1 -1
  323. package/dist/exporters/csv-exporter.js +1 -1
  324. package/dist/exporters/csv-exporter.js.map +1 -1
  325. package/dist/exporters/feature-parser.d.ts +8 -0
  326. package/dist/exporters/feature-parser.d.ts.map +1 -1
  327. package/dist/exporters/feature-parser.js +12 -0
  328. package/dist/exporters/feature-parser.js.map +1 -1
  329. package/dist/exporters/matrix/build.d.ts +3 -0
  330. package/dist/exporters/matrix/build.d.ts.map +1 -1
  331. package/dist/exporters/matrix/build.js +59 -19
  332. package/dist/exporters/matrix/build.js.map +1 -1
  333. package/dist/exporters/matrix/carry-manual-results.d.ts +19 -0
  334. package/dist/exporters/matrix/carry-manual-results.d.ts.map +1 -1
  335. package/dist/exporters/matrix/carry-manual-results.js +76 -6
  336. package/dist/exporters/matrix/carry-manual-results.js.map +1 -1
  337. package/dist/exporters/matrix/export.d.ts +8 -2
  338. package/dist/exporters/matrix/export.d.ts.map +1 -1
  339. package/dist/exporters/matrix/export.js +16 -3
  340. package/dist/exporters/matrix/export.js.map +1 -1
  341. package/dist/exporters/matrix/gates.d.ts +6 -1
  342. package/dist/exporters/matrix/gates.d.ts.map +1 -1
  343. package/dist/exporters/matrix/gates.js +57 -128
  344. package/dist/exporters/matrix/gates.js.map +1 -1
  345. package/dist/exporters/matrix/render-csv.d.ts.map +1 -1
  346. package/dist/exporters/matrix/render-csv.js +4 -1
  347. package/dist/exporters/matrix/render-csv.js.map +1 -1
  348. package/dist/exporters/matrix/render-gate-overrides-sheet.d.ts +13 -0
  349. package/dist/exporters/matrix/render-gate-overrides-sheet.d.ts.map +1 -0
  350. package/dist/exporters/matrix/render-gate-overrides-sheet.js +44 -0
  351. package/dist/exporters/matrix/render-gate-overrides-sheet.js.map +1 -0
  352. package/dist/exporters/matrix/render-xlsx.d.ts +1 -0
  353. package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
  354. package/dist/exporters/matrix/render-xlsx.js +6 -0
  355. package/dist/exporters/matrix/render-xlsx.js.map +1 -1
  356. package/dist/exporters/matrix/types.d.ts +9 -1
  357. package/dist/exporters/matrix/types.d.ts.map +1 -1
  358. package/dist/exporters/matrix/types.js.map +1 -1
  359. package/dist/exporters/matrix/xlsx-cells.js +1 -1
  360. package/dist/exporters/matrix/xlsx-cells.js.map +1 -1
  361. package/dist/exporters/playwright-report-parser.d.ts.map +1 -1
  362. package/dist/exporters/playwright-report-parser.js +1 -0
  363. package/dist/exporters/playwright-report-parser.js.map +1 -1
  364. package/dist/exporters/scenario-merger.d.ts.map +1 -1
  365. package/dist/exporters/scenario-merger.js +2 -0
  366. package/dist/exporters/scenario-merger.js.map +1 -1
  367. package/dist/exporters/types.d.ts +5 -0
  368. package/dist/exporters/types.d.ts.map +1 -1
  369. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  370. package/dist/generators/test-generator/code-generator.js +13 -0
  371. package/dist/generators/test-generator/code-generator.js.map +1 -1
  372. package/dist/graph/evaluate-graph.d.ts +23 -0
  373. package/dist/graph/evaluate-graph.d.ts.map +1 -0
  374. package/dist/graph/evaluate-graph.js +52 -0
  375. package/dist/graph/evaluate-graph.js.map +1 -0
  376. package/dist/graph/locate-finding.d.ts +20 -0
  377. package/dist/graph/locate-finding.d.ts.map +1 -0
  378. package/dist/graph/locate-finding.js +137 -0
  379. package/dist/graph/locate-finding.js.map +1 -0
  380. package/dist/graph/node-decl.d.ts +66 -0
  381. package/dist/graph/node-decl.d.ts.map +1 -0
  382. package/dist/graph/node-decl.js +8 -0
  383. package/dist/graph/node-decl.js.map +1 -0
  384. package/dist/graph/nodes/core-node-catalog.d.ts +7 -0
  385. package/dist/graph/nodes/core-node-catalog.d.ts.map +1 -0
  386. package/dist/graph/nodes/core-node-catalog.js +13 -0
  387. package/dist/graph/nodes/core-node-catalog.js.map +1 -0
  388. package/dist/graph/nodes/test-case-contract-nodes.d.ts +21 -0
  389. package/dist/graph/nodes/test-case-contract-nodes.d.ts.map +1 -0
  390. package/dist/graph/nodes/test-case-contract-nodes.js +59 -0
  391. package/dist/graph/nodes/test-case-contract-nodes.js.map +1 -0
  392. package/dist/graph/nodes/test-case-nodes.d.ts +26 -0
  393. package/dist/graph/nodes/test-case-nodes.d.ts.map +1 -0
  394. package/dist/graph/nodes/test-case-nodes.js +66 -0
  395. package/dist/graph/nodes/test-case-nodes.js.map +1 -0
  396. package/dist/graph/nodes/unit-audit-nodes.d.ts +18 -0
  397. package/dist/graph/nodes/unit-audit-nodes.d.ts.map +1 -0
  398. package/dist/graph/nodes/unit-audit-nodes.js +95 -0
  399. package/dist/graph/nodes/unit-audit-nodes.js.map +1 -0
  400. package/dist/graph/nodes/unit-contract-node.d.ts +21 -0
  401. package/dist/graph/nodes/unit-contract-node.d.ts.map +1 -0
  402. package/dist/graph/nodes/unit-contract-node.js +88 -0
  403. package/dist/graph/nodes/unit-contract-node.js.map +1 -0
  404. package/dist/graph/nodes/unit-design-nodes.d.ts +14 -0
  405. package/dist/graph/nodes/unit-design-nodes.d.ts.map +1 -0
  406. package/dist/graph/nodes/unit-design-nodes.js +91 -0
  407. package/dist/graph/nodes/unit-design-nodes.js.map +1 -0
  408. package/dist/graph/nodes/unit-execution-nodes.d.ts +16 -0
  409. package/dist/graph/nodes/unit-execution-nodes.d.ts.map +1 -0
  410. package/dist/graph/nodes/unit-execution-nodes.js +79 -0
  411. package/dist/graph/nodes/unit-execution-nodes.js.map +1 -0
  412. package/dist/graph/test-case-identity.d.ts +13 -0
  413. package/dist/graph/test-case-identity.d.ts.map +1 -0
  414. package/dist/graph/test-case-identity.js +106 -0
  415. package/dist/graph/test-case-identity.js.map +1 -0
  416. package/dist/graph/test-case-results.d.ts +11 -0
  417. package/dist/graph/test-case-results.d.ts.map +1 -0
  418. package/dist/graph/test-case-results.js +137 -0
  419. package/dist/graph/test-case-results.js.map +1 -0
  420. package/dist/graph/test-case-satisfied.d.ts +25 -0
  421. package/dist/graph/test-case-satisfied.d.ts.map +1 -0
  422. package/dist/graph/test-case-satisfied.js +51 -0
  423. package/dist/graph/test-case-satisfied.js.map +1 -0
  424. package/dist/graph/test-case-state-shape.d.ts +67 -0
  425. package/dist/graph/test-case-state-shape.d.ts.map +1 -0
  426. package/dist/graph/test-case-state-shape.js +3 -0
  427. package/dist/graph/test-case-state-shape.js.map +1 -0
  428. package/dist/graph/test-case-states.d.ts +9 -0
  429. package/dist/graph/test-case-states.d.ts.map +1 -0
  430. package/dist/graph/test-case-states.js +116 -0
  431. package/dist/graph/test-case-states.js.map +1 -0
  432. package/dist/graph/unit-artifact-probes.d.ts +19 -0
  433. package/dist/graph/unit-artifact-probes.d.ts.map +1 -0
  434. package/dist/graph/unit-artifact-probes.js +133 -0
  435. package/dist/graph/unit-artifact-probes.js.map +1 -0
  436. package/dist/graph/unit-state-facts.d.ts +43 -0
  437. package/dist/graph/unit-state-facts.d.ts.map +1 -0
  438. package/dist/graph/unit-state-facts.js +87 -0
  439. package/dist/graph/unit-state-facts.js.map +1 -0
  440. package/dist/harness/audit.d.ts +11 -0
  441. package/dist/harness/audit.d.ts.map +1 -1
  442. package/dist/harness/audit.js +34 -9
  443. package/dist/harness/audit.js.map +1 -1
  444. package/dist/harness/catalog/gate-rules.yaml +647 -0
  445. package/dist/harness/counted-assertions.d.ts +2 -0
  446. package/dist/harness/counted-assertions.d.ts.map +1 -0
  447. package/dist/harness/counted-assertions.js +38 -0
  448. package/dist/harness/counted-assertions.js.map +1 -0
  449. package/dist/harness/defect-draft.d.ts +14 -0
  450. package/dist/harness/defect-draft.d.ts.map +1 -0
  451. package/dist/harness/defect-draft.js +143 -0
  452. package/dist/harness/defect-draft.js.map +1 -0
  453. package/dist/harness/defects.d.ts +24 -0
  454. package/dist/harness/defects.d.ts.map +1 -0
  455. package/dist/harness/defects.js +118 -0
  456. package/dist/harness/defects.js.map +1 -0
  457. package/dist/harness/gates/audit-gate-terms.d.ts +41 -0
  458. package/dist/harness/gates/audit-gate-terms.d.ts.map +1 -0
  459. package/dist/harness/gates/audit-gate-terms.js +72 -0
  460. package/dist/harness/gates/audit-gate-terms.js.map +1 -0
  461. package/dist/harness/gates/audit-gate-verdict.d.ts +31 -0
  462. package/dist/harness/gates/audit-gate-verdict.d.ts.map +1 -0
  463. package/dist/harness/gates/audit-gate-verdict.js +101 -0
  464. package/dist/harness/gates/audit-gate-verdict.js.map +1 -0
  465. package/dist/harness/gates/audit-input-hash.d.ts +4 -0
  466. package/dist/harness/gates/audit-input-hash.d.ts.map +1 -0
  467. package/dist/harness/gates/audit-input-hash.js +96 -0
  468. package/dist/harness/gates/audit-input-hash.js.map +1 -0
  469. package/dist/harness/gates/audit-report-verification.d.ts +41 -0
  470. package/dist/harness/gates/audit-report-verification.d.ts.map +1 -0
  471. package/dist/harness/gates/audit-report-verification.js +236 -0
  472. package/dist/harness/gates/audit-report-verification.js.map +1 -0
  473. package/dist/harness/gates/decisions-hash.d.ts +13 -0
  474. package/dist/harness/gates/decisions-hash.d.ts.map +1 -0
  475. package/dist/harness/gates/decisions-hash.js +72 -0
  476. package/dist/harness/gates/decisions-hash.js.map +1 -0
  477. package/dist/harness/gates/delivery-checklist.d.ts +21 -0
  478. package/dist/harness/gates/delivery-checklist.d.ts.map +1 -0
  479. package/dist/harness/gates/delivery-checklist.js +128 -0
  480. package/dist/harness/gates/delivery-checklist.js.map +1 -0
  481. package/dist/harness/gates/delivery-decision-gate.d.ts +33 -0
  482. package/dist/harness/gates/delivery-decision-gate.d.ts.map +1 -0
  483. package/dist/harness/gates/delivery-decision-gate.js +116 -0
  484. package/dist/harness/gates/delivery-decision-gate.js.map +1 -0
  485. package/dist/harness/gates/delivery-decision-step.d.ts +19 -0
  486. package/dist/harness/gates/delivery-decision-step.d.ts.map +1 -0
  487. package/dist/harness/gates/delivery-decision-step.js +86 -0
  488. package/dist/harness/gates/delivery-decision-step.js.map +1 -0
  489. package/dist/harness/gates/gate-override-report.d.ts +59 -0
  490. package/dist/harness/gates/gate-override-report.d.ts.map +1 -0
  491. package/dist/harness/gates/gate-override-report.js +86 -0
  492. package/dist/harness/gates/gate-override-report.js.map +1 -0
  493. package/dist/harness/gates/gate-override-scope.d.ts +18 -0
  494. package/dist/harness/gates/gate-override-scope.d.ts.map +1 -0
  495. package/dist/harness/gates/gate-override-scope.js +98 -0
  496. package/dist/harness/gates/gate-override-scope.js.map +1 -0
  497. package/dist/harness/gates/gate-override-validation.d.ts +25 -0
  498. package/dist/harness/gates/gate-override-validation.d.ts.map +1 -0
  499. package/dist/harness/gates/gate-override-validation.js +81 -0
  500. package/dist/harness/gates/gate-override-validation.js.map +1 -0
  501. package/dist/harness/gates/gate-rule-catalog.d.ts +24 -0
  502. package/dist/harness/gates/gate-rule-catalog.d.ts.map +1 -0
  503. package/dist/harness/gates/gate-rule-catalog.js +112 -0
  504. package/dist/harness/gates/gate-rule-catalog.js.map +1 -0
  505. package/dist/harness/gates/gate-terms.d.ts +33 -0
  506. package/dist/harness/gates/gate-terms.d.ts.map +1 -0
  507. package/dist/harness/gates/gate-terms.js +41 -0
  508. package/dist/harness/gates/gate-terms.js.map +1 -0
  509. package/dist/harness/gates/in-run-decision-check.d.ts +21 -0
  510. package/dist/harness/gates/in-run-decision-check.d.ts.map +1 -0
  511. package/dist/harness/gates/in-run-decision-check.js +138 -0
  512. package/dist/harness/gates/in-run-decision-check.js.map +1 -0
  513. package/dist/harness/gates/journey-gate-inputs.d.ts +37 -0
  514. package/dist/harness/gates/journey-gate-inputs.d.ts.map +1 -0
  515. package/dist/harness/gates/journey-gate-inputs.js +81 -0
  516. package/dist/harness/gates/journey-gate-inputs.js.map +1 -0
  517. package/dist/harness/gates/migrated-waiver-review.d.ts +6 -0
  518. package/dist/harness/gates/migrated-waiver-review.d.ts.map +1 -0
  519. package/dist/harness/gates/migrated-waiver-review.js +116 -0
  520. package/dist/harness/gates/migrated-waiver-review.js.map +1 -0
  521. package/dist/harness/gates/resolve-rule.d.ts +59 -0
  522. package/dist/harness/gates/resolve-rule.d.ts.map +1 -0
  523. package/dist/harness/gates/resolve-rule.js +41 -0
  524. package/dist/harness/gates/resolve-rule.js.map +1 -0
  525. package/dist/harness/gates/unit-gate-overrides.d.ts +25 -0
  526. package/dist/harness/gates/unit-gate-overrides.d.ts.map +1 -0
  527. package/dist/harness/gates/unit-gate-overrides.js +122 -0
  528. package/dist/harness/gates/unit-gate-overrides.js.map +1 -0
  529. package/dist/harness/journey.d.ts +43 -1
  530. package/dist/harness/journey.d.ts.map +1 -1
  531. package/dist/harness/journey.js +207 -33
  532. package/dist/harness/journey.js.map +1 -1
  533. package/dist/harness/manifest.d.ts +12 -0
  534. package/dist/harness/manifest.d.ts.map +1 -1
  535. package/dist/harness/manifest.js +73 -45
  536. package/dist/harness/manifest.js.map +1 -1
  537. package/dist/harness/next-step.d.ts +37 -6
  538. package/dist/harness/next-step.d.ts.map +1 -1
  539. package/dist/harness/next-step.js +34 -174
  540. package/dist/harness/next-step.js.map +1 -1
  541. package/dist/harness/parse.d.ts +25 -0
  542. package/dist/harness/parse.d.ts.map +1 -1
  543. package/dist/harness/parse.js +38 -13
  544. package/dist/harness/parse.js.map +1 -1
  545. package/dist/harness/provenance.d.ts +29 -0
  546. package/dist/harness/provenance.d.ts.map +1 -1
  547. package/dist/harness/provenance.js +109 -9
  548. package/dist/harness/provenance.js.map +1 -1
  549. package/dist/harness/script-check.d.ts.map +1 -1
  550. package/dist/harness/script-check.js +29 -6
  551. package/dist/harness/script-check.js.map +1 -1
  552. package/dist/harness/sensors.d.ts +14 -3
  553. package/dist/harness/sensors.d.ts.map +1 -1
  554. package/dist/harness/sensors.js +64 -44
  555. package/dist/harness/sensors.js.map +1 -1
  556. package/dist/harness/triage-signals.d.ts +20 -0
  557. package/dist/harness/triage-signals.d.ts.map +1 -0
  558. package/dist/harness/triage-signals.js +30 -0
  559. package/dist/harness/triage-signals.js.map +1 -0
  560. package/dist/harness/triage-unit.d.ts +23 -0
  561. package/dist/harness/triage-unit.d.ts.map +1 -0
  562. package/dist/harness/triage-unit.js +142 -0
  563. package/dist/harness/triage-unit.js.map +1 -0
  564. package/dist/harness/triage.d.ts +28 -0
  565. package/dist/harness/triage.d.ts.map +1 -0
  566. package/dist/harness/triage.js +99 -0
  567. package/dist/harness/triage.js.map +1 -0
  568. package/dist/harness/viewpoint-ledger.d.ts.map +1 -1
  569. package/dist/harness/viewpoint-ledger.js +2 -1
  570. package/dist/harness/viewpoint-ledger.js.map +1 -1
  571. package/dist/hooks/bash-write-targets.d.ts +15 -0
  572. package/dist/hooks/bash-write-targets.d.ts.map +1 -0
  573. package/dist/hooks/bash-write-targets.js +173 -0
  574. package/dist/hooks/bash-write-targets.js.map +1 -0
  575. package/dist/hooks/claude-hook-entry.d.ts +11 -0
  576. package/dist/hooks/claude-hook-entry.d.ts.map +1 -0
  577. package/dist/hooks/claude-hook-entry.js +137 -0
  578. package/dist/hooks/claude-hook-entry.js.map +1 -0
  579. package/dist/hooks/claude-transcript-turn.d.ts +11 -0
  580. package/dist/hooks/claude-transcript-turn.d.ts.map +1 -0
  581. package/dist/hooks/claude-transcript-turn.js +143 -0
  582. package/dist/hooks/claude-transcript-turn.js.map +1 -0
  583. package/dist/hooks/guard-delivery-contract-rule.d.ts +10 -0
  584. package/dist/hooks/guard-delivery-contract-rule.d.ts.map +1 -0
  585. package/dist/hooks/guard-delivery-contract-rule.js +152 -0
  586. package/dist/hooks/guard-delivery-contract-rule.js.map +1 -0
  587. package/dist/hooks/guard-protected-paths.d.ts +9 -0
  588. package/dist/hooks/guard-protected-paths.d.ts.map +1 -0
  589. package/dist/hooks/guard-protected-paths.js +107 -0
  590. package/dist/hooks/guard-protected-paths.js.map +1 -0
  591. package/dist/hooks/guard-rules.d.ts +37 -0
  592. package/dist/hooks/guard-rules.d.ts.map +1 -0
  593. package/dist/hooks/guard-rules.js +61 -0
  594. package/dist/hooks/guard-rules.js.map +1 -0
  595. package/dist/hooks/guard-tty-spoof-rule.d.ts +15 -0
  596. package/dist/hooks/guard-tty-spoof-rule.d.ts.map +1 -0
  597. package/dist/hooks/guard-tty-spoof-rule.js +21 -0
  598. package/dist/hooks/guard-tty-spoof-rule.js.map +1 -0
  599. package/dist/hooks/hand-back-core.d.ts +39 -0
  600. package/dist/hooks/hand-back-core.d.ts.map +1 -0
  601. package/dist/hooks/hand-back-core.js +122 -0
  602. package/dist/hooks/hand-back-core.js.map +1 -0
  603. package/dist/hooks/hook-cli-command.d.ts +9 -0
  604. package/dist/hooks/hook-cli-command.d.ts.map +1 -0
  605. package/dist/hooks/hook-cli-command.js +46 -0
  606. package/dist/hooks/hook-cli-command.js.map +1 -0
  607. package/dist/hooks/hook-registry.d.ts +10 -0
  608. package/dist/hooks/hook-registry.d.ts.map +1 -0
  609. package/dist/hooks/hook-registry.js +24 -0
  610. package/dist/hooks/hook-registry.js.map +1 -0
  611. package/dist/hooks/hook-result-contract.d.ts +50 -0
  612. package/dist/hooks/hook-result-contract.d.ts.map +1 -0
  613. package/dist/hooks/hook-result-contract.js +80 -0
  614. package/dist/hooks/hook-result-contract.js.map +1 -0
  615. package/dist/hooks/hook-toggles.d.ts +10 -0
  616. package/dist/hooks/hook-toggles.d.ts.map +1 -0
  617. package/dist/hooks/hook-toggles.js +107 -0
  618. package/dist/hooks/hook-toggles.js.map +1 -0
  619. package/dist/hooks/pre-tool-guard-hook.d.ts +10 -0
  620. package/dist/hooks/pre-tool-guard-hook.d.ts.map +1 -0
  621. package/dist/hooks/pre-tool-guard-hook.js +105 -0
  622. package/dist/hooks/pre-tool-guard-hook.js.map +1 -0
  623. package/dist/hooks/session-start-unit-state-hook.d.ts +13 -0
  624. package/dist/hooks/session-start-unit-state-hook.d.ts.map +1 -0
  625. package/dist/hooks/session-start-unit-state-hook.js +57 -0
  626. package/dist/hooks/session-start-unit-state-hook.js.map +1 -0
  627. package/dist/hooks/stop-next-step-hook.d.ts +16 -0
  628. package/dist/hooks/stop-next-step-hook.d.ts.map +1 -0
  629. package/dist/hooks/stop-next-step-hook.js +42 -0
  630. package/dist/hooks/stop-next-step-hook.js.map +1 -0
  631. package/dist/hooks/sungen-project-root.d.ts +19 -0
  632. package/dist/hooks/sungen-project-root.d.ts.map +1 -0
  633. package/dist/hooks/sungen-project-root.js +130 -0
  634. package/dist/hooks/sungen-project-root.js.map +1 -0
  635. package/dist/orchestrator/ai-skills/command-partial-includes.d.ts +15 -0
  636. package/dist/orchestrator/ai-skills/command-partial-includes.d.ts.map +1 -0
  637. package/dist/orchestrator/ai-skills/command-partial-includes.js +106 -0
  638. package/dist/orchestrator/ai-skills/command-partial-includes.js.map +1 -0
  639. package/dist/orchestrator/ai-skills/commands.d.ts +5 -1
  640. package/dist/orchestrator/ai-skills/commands.d.ts.map +1 -1
  641. package/dist/orchestrator/ai-skills/commands.js +16 -6
  642. package/dist/orchestrator/ai-skills/commands.js.map +1 -1
  643. package/dist/orchestrator/ai-skills/golden-skills.test.js +29 -0
  644. package/dist/orchestrator/ai-skills/golden-skills.test.js.map +1 -1
  645. package/dist/orchestrator/assets-drift.d.ts +5 -0
  646. package/dist/orchestrator/assets-drift.d.ts.map +1 -1
  647. package/dist/orchestrator/assets-drift.js +12 -3
  648. package/dist/orchestrator/assets-drift.js.map +1 -1
  649. package/dist/orchestrator/claude-hooks-install.d.ts +27 -0
  650. package/dist/orchestrator/claude-hooks-install.d.ts.map +1 -0
  651. package/dist/orchestrator/claude-hooks-install.js +203 -0
  652. package/dist/orchestrator/claude-hooks-install.js.map +1 -0
  653. package/dist/orchestrator/lockstep-version.d.ts +15 -5
  654. package/dist/orchestrator/lockstep-version.d.ts.map +1 -1
  655. package/dist/orchestrator/lockstep-version.js +30 -17
  656. package/dist/orchestrator/lockstep-version.js.map +1 -1
  657. package/dist/orchestrator/project-initializer.d.ts +6 -0
  658. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  659. package/dist/orchestrator/project-initializer.js +24 -0
  660. package/dist/orchestrator/project-initializer.js.map +1 -1
  661. package/dist/orchestrator/screen-manager.d.ts.map +1 -1
  662. package/dist/orchestrator/screen-manager.js +4 -2
  663. package/dist/orchestrator/screen-manager.js.map +1 -1
  664. package/dist/orchestrator/templates/ai-src/commands/add-api.md +2 -0
  665. package/dist/orchestrator/templates/ai-src/commands/add-flow.md +2 -0
  666. package/dist/orchestrator/templates/ai-src/commands/add-screen.md +2 -0
  667. package/dist/orchestrator/templates/ai-src/commands/create-data-test.md +1 -0
  668. package/dist/orchestrator/templates/ai-src/commands/create-test.md +14 -16
  669. package/dist/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
  670. package/dist/orchestrator/templates/ai-src/commands/delivery.md +2 -0
  671. package/dist/orchestrator/templates/ai-src/commands/design.md +2 -0
  672. package/dist/orchestrator/templates/ai-src/commands/feedback.md +2 -0
  673. package/dist/orchestrator/templates/ai-src/commands/locale.md +2 -0
  674. package/dist/orchestrator/templates/ai-src/commands/review.md +2 -0
  675. package/dist/orchestrator/templates/ai-src/commands/run-test.md +14 -10
  676. package/dist/orchestrator/templates/ai-src/config/claude.md +20 -7
  677. package/dist/orchestrator/templates/ai-src/config/copilot.md +20 -7
  678. package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.claude.md +20 -0
  679. package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.codex.md +20 -0
  680. package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.copilot.md +20 -0
  681. package/dist/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +1 -1
  682. package/dist/orchestrator/templates/ai-src/skills/sungen-capture-mobile/SKILL.md +3 -3
  683. package/dist/orchestrator/templates/ai-src/skills/sungen-data-factory/SKILL.md +9 -0
  684. package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +2 -0
  685. package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +1 -1
  686. package/dist/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +2 -0
  687. package/dist/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
  688. package/dist/utils/safe-yaml-parse.d.ts +8 -0
  689. package/dist/utils/safe-yaml-parse.d.ts.map +1 -0
  690. package/dist/utils/safe-yaml-parse.js +51 -0
  691. package/dist/utils/safe-yaml-parse.js.map +1 -0
  692. package/package.json +3 -3
  693. package/src/basis/anchor-grammar.ts +83 -0
  694. package/src/basis/anchor-hash.ts +27 -0
  695. package/src/basis/bm51-tables.ts +65 -0
  696. package/src/basis/extract-spec-anchors.ts +95 -0
  697. package/src/basis/migration-sentinel.ts +175 -0
  698. package/src/basis/spec-frontmatter.ts +68 -0
  699. package/src/basis/spec-sections.ts +35 -0
  700. package/src/basis/test-basis-schema.ts +81 -0
  701. package/src/capabilities/discover.ts +15 -2
  702. package/src/capabilities/registry.ts +16 -0
  703. package/src/cli/commands/audit.ts +10 -5
  704. package/src/cli/commands/capability.ts +4 -2
  705. package/src/cli/commands/contract-derive-command.ts +61 -0
  706. package/src/cli/commands/contract.ts +130 -0
  707. package/src/cli/commands/defect.ts +49 -0
  708. package/src/cli/commands/delivery.ts +92 -15
  709. package/src/cli/commands/generate.ts +3 -1
  710. package/src/cli/commands/journey.ts +41 -16
  711. package/src/cli/commands/next.ts +64 -10
  712. package/src/cli/commands/triage.ts +57 -0
  713. package/src/cli/commands/update.ts +35 -8
  714. package/src/cli/index.ts +24 -30
  715. package/src/cli/project-sungen-invocation.ts +39 -0
  716. package/src/contract/approve-contract.ts +94 -0
  717. package/src/contract/assertion-matcher-vocabulary.ts +93 -0
  718. package/src/contract/build-contract-verdict.ts +108 -0
  719. package/src/contract/build-trace-conformance.ts +100 -0
  720. package/src/contract/classify-contract-change.ts +92 -0
  721. package/src/contract/classify-contract-unit.ts +47 -0
  722. package/src/contract/classify-trace-conformance.ts +116 -0
  723. package/src/contract/contract-git.ts +106 -0
  724. package/src/contract/contract-hash.ts +34 -0
  725. package/src/contract/contract-report-file.ts +25 -0
  726. package/src/contract/contract-schema.ts +137 -0
  727. package/src/contract/contract-units.ts +52 -0
  728. package/src/contract/contracts-lock-file.ts +97 -0
  729. package/src/contract/data-normalize.ts +66 -0
  730. package/src/contract/derive-free-feature.ts +120 -0
  731. package/src/contract/field-semantic-redaction.ts +80 -0
  732. package/src/contract/free-feature-blocks.ts +56 -0
  733. package/src/contract/lock-secret-guard.ts +95 -0
  734. package/src/contract/lock-vs-git-head.ts +38 -0
  735. package/src/contract/normalize-contract-step.ts +74 -0
  736. package/src/contract/normalize-feature-steps.ts +93 -0
  737. package/src/contract/oracle-strength.ts +80 -0
  738. package/src/contract/project-contract-blockers.ts +36 -0
  739. package/src/contract/record-contract-approval.ts +70 -0
  740. package/src/contract/render-free-gherkin.ts +113 -0
  741. package/src/contract/render-trace-sentence.ts +98 -0
  742. package/src/contract/render-trace-target.ts +68 -0
  743. package/src/contract/resolve-unit-trace-identities.ts +35 -0
  744. package/src/contract/trace/collect-trace-evidence.ts +109 -0
  745. package/src/contract/trace/identity-cache.ts +61 -0
  746. package/src/contract/trace/select-final-attempt.ts +70 -0
  747. package/src/contract/trace/snapshot-html-renderer.ts +136 -0
  748. package/src/contract/trace/snapshot-resolver.ts +66 -0
  749. package/src/contract/trace/snapshot-store.ts +151 -0
  750. package/src/contract/trace/target-identity.ts +104 -0
  751. package/src/contract/trace/test-step-join.ts +104 -0
  752. package/src/contract/trace/trace-binding.ts +56 -0
  753. package/src/contract/trace/trace-file-reader.ts +133 -0
  754. package/src/contract/trace/trace-fingerprint.ts +68 -0
  755. package/src/contract/trace/trace-identity-resolution.ts +74 -0
  756. package/src/contract/trace/trace-run-record.ts +80 -0
  757. package/src/contract/trace/trace-steps.ts +88 -0
  758. package/src/contract/trace/trace-zip-limits.ts +77 -0
  759. package/src/contract/trace/trace-zip-reader.ts +127 -0
  760. package/src/contract/verify-approval-decisions.ts +60 -0
  761. package/src/decisions/append-decision.ts +35 -0
  762. package/src/decisions/confirmed-decision-commands.ts +149 -0
  763. package/src/decisions/decision-file.ts +93 -0
  764. package/src/decisions/decision-identity.ts +73 -0
  765. package/src/decisions/decision-integrity-check.ts +61 -0
  766. package/src/decisions/decision-schema.ts +76 -0
  767. package/src/decisions/decision-source.ts +14 -0
  768. package/src/decisions/exclusive-file-create.ts +42 -0
  769. package/src/decisions/git-head-trust.ts +32 -0
  770. package/src/decisions/human-confirmation.ts +119 -0
  771. package/src/decisions/legacy-waiver-migration.ts +135 -0
  772. package/src/decisions/read-decisions.ts +61 -0
  773. package/src/decisions/viewpoint-baseline-adapter.ts +74 -0
  774. package/src/decisions/waiver-decisions.ts +56 -0
  775. package/src/exporters/csv-exporter.ts +5 -1
  776. package/src/exporters/feature-parser.ts +12 -0
  777. package/src/exporters/matrix/build.ts +62 -18
  778. package/src/exporters/matrix/carry-manual-results.ts +70 -7
  779. package/src/exporters/matrix/export.ts +17 -2
  780. package/src/exporters/matrix/gates.ts +62 -129
  781. package/src/exporters/matrix/render-csv.ts +4 -1
  782. package/src/exporters/matrix/render-gate-overrides-sheet.ts +50 -0
  783. package/src/exporters/matrix/render-xlsx.ts +6 -0
  784. package/src/exporters/matrix/types.ts +9 -1
  785. package/src/exporters/matrix/xlsx-cells.ts +1 -1
  786. package/src/exporters/playwright-report-parser.ts +1 -0
  787. package/src/exporters/scenario-merger.ts +2 -1
  788. package/src/exporters/types.ts +5 -0
  789. package/src/generators/test-generator/code-generator.ts +13 -0
  790. package/src/graph/evaluate-graph.ts +66 -0
  791. package/src/graph/locate-finding.ts +93 -0
  792. package/src/graph/node-decl.ts +72 -0
  793. package/src/graph/nodes/core-node-catalog.ts +15 -0
  794. package/src/graph/nodes/test-case-contract-nodes.ts +74 -0
  795. package/src/graph/nodes/test-case-nodes.ts +68 -0
  796. package/src/graph/nodes/unit-audit-nodes.ts +95 -0
  797. package/src/graph/nodes/unit-contract-node.ts +89 -0
  798. package/src/graph/nodes/unit-design-nodes.ts +89 -0
  799. package/src/graph/nodes/unit-execution-nodes.ts +77 -0
  800. package/src/graph/test-case-identity.ts +75 -0
  801. package/src/graph/test-case-results.ts +90 -0
  802. package/src/graph/test-case-satisfied.ts +55 -0
  803. package/src/graph/test-case-state-shape.ts +62 -0
  804. package/src/graph/test-case-states.ts +84 -0
  805. package/src/graph/unit-artifact-probes.ts +77 -0
  806. package/src/graph/unit-state-facts.ts +112 -0
  807. package/src/harness/audit.ts +46 -11
  808. package/src/harness/catalog/gate-rules.yaml +647 -0
  809. package/src/harness/counted-assertions.ts +33 -0
  810. package/src/harness/defect-draft.ts +115 -0
  811. package/src/harness/defects.ts +94 -0
  812. package/src/harness/gates/audit-gate-terms.ts +80 -0
  813. package/src/harness/gates/audit-gate-verdict.ts +78 -0
  814. package/src/harness/gates/audit-input-hash.ts +55 -0
  815. package/src/harness/gates/audit-report-verification.ts +201 -0
  816. package/src/harness/gates/decisions-hash.ts +42 -0
  817. package/src/harness/gates/delivery-checklist.ts +120 -0
  818. package/src/harness/gates/delivery-decision-gate.ts +139 -0
  819. package/src/harness/gates/delivery-decision-step.ts +89 -0
  820. package/src/harness/gates/gate-override-report.ts +114 -0
  821. package/src/harness/gates/gate-override-scope.ts +66 -0
  822. package/src/harness/gates/gate-override-validation.ts +75 -0
  823. package/src/harness/gates/gate-rule-catalog.ts +82 -0
  824. package/src/harness/gates/gate-terms.ts +59 -0
  825. package/src/harness/gates/in-run-decision-check.ts +99 -0
  826. package/src/harness/gates/journey-gate-inputs.ts +89 -0
  827. package/src/harness/gates/migrated-waiver-review.ts +68 -0
  828. package/src/harness/gates/resolve-rule.ts +94 -0
  829. package/src/harness/gates/unit-gate-overrides.ts +99 -0
  830. package/src/harness/journey.ts +215 -38
  831. package/src/harness/manifest.ts +69 -45
  832. package/src/harness/next-step.ts +60 -170
  833. package/src/harness/parse.ts +40 -13
  834. package/src/harness/provenance.ts +99 -11
  835. package/src/harness/script-check.ts +27 -6
  836. package/src/harness/sensors.ts +73 -47
  837. package/src/harness/triage-signals.ts +46 -0
  838. package/src/harness/triage-unit.ts +113 -0
  839. package/src/harness/triage.ts +127 -0
  840. package/src/harness/viewpoint-ledger.ts +2 -2
  841. package/src/hooks/bash-write-targets.ts +109 -0
  842. package/src/hooks/claude-hook-entry.ts +85 -0
  843. package/src/hooks/claude-transcript-turn.ts +96 -0
  844. package/src/hooks/guard-delivery-contract-rule.ts +110 -0
  845. package/src/hooks/guard-protected-paths.ts +71 -0
  846. package/src/hooks/guard-rules.ts +98 -0
  847. package/src/hooks/guard-tty-spoof-rule.ts +31 -0
  848. package/src/hooks/hand-back-core.ts +112 -0
  849. package/src/hooks/hook-cli-command.ts +17 -0
  850. package/src/hooks/hook-registry.ts +24 -0
  851. package/src/hooks/hook-result-contract.ts +114 -0
  852. package/src/hooks/hook-toggles.ts +66 -0
  853. package/src/hooks/pre-tool-guard-hook.ts +67 -0
  854. package/src/hooks/session-start-unit-state-hook.ts +56 -0
  855. package/src/hooks/stop-next-step-hook.ts +37 -0
  856. package/src/hooks/sungen-project-root.ts +80 -0
  857. package/src/orchestrator/ai-skills/command-partial-includes.ts +72 -0
  858. package/src/orchestrator/ai-skills/commands.ts +22 -8
  859. package/src/orchestrator/ai-skills/golden-skills.test.ts +23 -0
  860. package/src/orchestrator/assets-drift.ts +12 -5
  861. package/src/orchestrator/claude-hooks-install.ts +168 -0
  862. package/src/orchestrator/lockstep-version.ts +28 -15
  863. package/src/orchestrator/project-initializer.ts +22 -0
  864. package/src/orchestrator/screen-manager.ts +3 -1
  865. package/src/orchestrator/templates/ai-src/commands/add-api.md +2 -0
  866. package/src/orchestrator/templates/ai-src/commands/add-flow.md +2 -0
  867. package/src/orchestrator/templates/ai-src/commands/add-screen.md +2 -0
  868. package/src/orchestrator/templates/ai-src/commands/create-data-test.md +1 -0
  869. package/src/orchestrator/templates/ai-src/commands/create-test.md +14 -16
  870. package/src/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
  871. package/src/orchestrator/templates/ai-src/commands/delivery.md +2 -0
  872. package/src/orchestrator/templates/ai-src/commands/design.md +2 -0
  873. package/src/orchestrator/templates/ai-src/commands/feedback.md +2 -0
  874. package/src/orchestrator/templates/ai-src/commands/locale.md +2 -0
  875. package/src/orchestrator/templates/ai-src/commands/review.md +2 -0
  876. package/src/orchestrator/templates/ai-src/commands/run-test.md +14 -10
  877. package/src/orchestrator/templates/ai-src/config/claude.md +20 -7
  878. package/src/orchestrator/templates/ai-src/config/copilot.md +20 -7
  879. package/src/orchestrator/templates/ai-src/partials/hand-back-rule.claude.md +20 -0
  880. package/src/orchestrator/templates/ai-src/partials/hand-back-rule.codex.md +20 -0
  881. package/src/orchestrator/templates/ai-src/partials/hand-back-rule.copilot.md +20 -0
  882. package/src/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +1 -1
  883. package/src/orchestrator/templates/ai-src/skills/sungen-capture-mobile/SKILL.md +3 -3
  884. package/src/orchestrator/templates/ai-src/skills/sungen-data-factory/SKILL.md +9 -0
  885. package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +2 -0
  886. package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +1 -1
  887. package/src/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +2 -0
  888. package/src/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
  889. package/src/utils/safe-yaml-parse.ts +44 -0
@@ -0,0 +1,115 @@
1
+ /**
2
+ * `sungen defect draft` — turn each `product-candidate` row of a unit's last triage into a record
3
+ * `qa/defects/DEF-NNN-<slug>.md` (see defects.ts for the link checks). Deterministic: Steps come
4
+ * from the scenario's Gherkin with test-data resolved, Expected/Actual from the assertion, and the
5
+ * severity is PROPOSED by rule until QA confirms it. Never overwrites a file, and never drafts a
6
+ * scenario an existing record already names.
7
+ */
8
+ import * as fs from 'fs';
9
+ import * as path from 'path';
10
+ import { stringify as toYaml } from 'yaml';
11
+ import type { ResolvedUnit } from '../cli/resolve-unit';
12
+ import { redactSecrets } from '../exporters/api-testcase-formatter';
13
+ import { getEnvironment } from '../exporters/run-environment';
14
+ import { parseFeatureMetadata } from '../exporters/feature-parser';
15
+ import { mergeFeatureAndSpec, MergedScenario } from '../exporters/scenario-merger';
16
+ import { maskCredentialValue } from '../exporters/sensitive-key';
17
+ import { parseSpecFile } from '../exporters/spec-parser';
18
+ import { loadTestData, substituteTestDataVars } from '../exporters/test-data-resolver';
19
+ import { readCapabilities } from './capability';
20
+ import { defectsDir, nextDefectId, readDefects } from './defects';
21
+ import type { TriageRow } from './triage';
22
+ import { readTriageReport, unitSecrets } from './triage-unit';
23
+
24
+ export interface DraftResult {
25
+ /** `sungen triage` has not run for this unit. */
26
+ missingTriage?: boolean;
27
+ written: string[];
28
+ skipped: Array<{ scenario: string; id: string }>;
29
+ }
30
+
31
+ /** Blocking actions: a @high scenario that fails on one of these is `major`, otherwise `minor`. */
32
+ const BLOCKING = /\b(?:submit|save|apply|log ?in|sign ?in|sign ?up|register|checkout|pay|confirm|send|navigate|redirect)\b/i;
33
+
34
+ const slug = (s: string): string =>
35
+ s.replace(/^\s*(?:VP|FL)-[A-Z0-9-]+\s+/i, '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 50).replace(/-$/, '');
36
+
37
+ interface UnitScenario { merged: MergedScenario; testData: Record<string, string>; secrets: string[] }
38
+
39
+ /** Scenario title → its merged Gherkin, test-data (credentials masked) and secret values. */
40
+ function unitScenarios(cwd: string, unit: ResolvedUnit): Map<string, UnitScenario> {
41
+ const out = new Map<string, UnitScenario>();
42
+ const featuresDir = path.join(unit.dir, 'features');
43
+ if (!fs.existsSync(featuresDir)) return out;
44
+ for (const f of fs.readdirSync(featuresDir).filter((x) => x.endsWith('.feature'))) {
45
+ const base = f.replace(/\.feature$/, '');
46
+ const spec = parseSpecFile(path.join(cwd, 'specs', 'generated', unit.unitId, `${base}.spec.ts`));
47
+ const dataFile = path.join(unit.dir, 'test-data', `${base}.yaml`);
48
+ const raw = fs.existsSync(dataFile) ? loadTestData(dataFile) : {};
49
+ const testData = Object.fromEntries(Object.entries(raw).map(([k, v]) => [k, maskCredentialValue(k, String(v))]));
50
+ const secrets = unitSecrets(raw, cwd);
51
+ for (const m of mergeFeatureAndSpec(parseFeatureMetadata(path.join(featuresDir, f)), spec)) {
52
+ out.set(m.feature.name, { merged: m, testData, secrets });
53
+ }
54
+ }
55
+ return out;
56
+ }
57
+
58
+ function render(cwd: string, unit: ResolvedUnit, id: string, row: TriageRow, sc: UnitScenario | undefined): string {
59
+ const tags = sc?.merged.feature.tags ?? [];
60
+ const resolve = (t: string): string => (sc ? substituteTestDataVars(t, sc.testData) : t);
61
+ const steps = (sc?.merged.resolvedSteps ?? []).map((s) => resolve(s.text));
62
+ const thens = (sc?.merged.resolvedExpected ?? []).map((s) => resolve(s.text));
63
+ const high = tags.some((t) => t === '@high' || t === '@critical');
64
+ const severity = high && BLOCKING.test([row.scenario, ...steps].join(' ')) ? 'major' : 'minor';
65
+ const specFile = path.join(unit.dir, 'requirements', 'spec.md');
66
+ const env = getEnvironment(cwd);
67
+ const front = {
68
+ id, title: row.scenario, severity, severity_source: 'proposed', status: 'open',
69
+ units: [unit.unitId], scenarios: [row.scenario], claims: row.ids, legacy: row.legacy,
70
+ spec: fs.existsSync(specFile) ? path.relative(cwd, specFile) : '',
71
+ found: {
72
+ date: new Date().toISOString().slice(0, 10),
73
+ env: process.env.SUNGEN_ENV || 'default',
74
+ base_url: env.baseURL,
75
+ platform: row.variant || readCapabilities(cwd).platform || 'web',
76
+ },
77
+ tracker: '',
78
+ };
79
+ const body = [
80
+ '---', toYaml(front).trimEnd(), '---', '',
81
+ `# ${id}: ${row.scenario}`, '',
82
+ '## Summary', '', '(to fill: what is wrong, where, and who it affects)', '',
83
+ '## Steps to reproduce', '', ...(steps.length ? steps.map((s, i) => `${i + 1}. ${s}`) : ['(scenario steps not found — see the feature)']), '',
84
+ '## Expected', '', ...thens.map((t) => `- ${t}`), ...(row.expected ? [`- Asserted value: ${row.expected}`] : []), '',
85
+ '## Actual', '', `- ${row.received ? `Received: ${row.received}` : row.evidence}`, '',
86
+ '## Evidence', '', `- Error: ${row.evidence}`, ...(row.tracePath ? [`- Trace: ${row.tracePath}`] : []), '',
87
+ '## Notes', '', `- Triage: ${row.class} (${row.ruleId})${row.variant ? ` on ${row.variant}` : ''}`, '',
88
+ ].join('\n');
89
+ return redactSecrets(body, sc?.secrets ?? []);
90
+ }
91
+
92
+ export function draftDefects(cwd: string, unit: ResolvedUnit, opts: { scenario?: string } = {}): DraftResult {
93
+ const triage = readTriageReport(cwd, unit.unitId);
94
+ if (!triage) return { missingTriage: true, written: [], skipped: [] };
95
+ const recorded = new Map<string, string>();
96
+ for (const r of readDefects(cwd)) if (r.units.includes(unit.unitId)) for (const s of r.scenarios) recorded.set(s, r.id);
97
+
98
+ const wanted = triage.rows.filter((r) => r.class === 'product-candidate'
99
+ && (!opts.scenario || r.scenario.includes(opts.scenario) || r.ids.includes(opts.scenario)));
100
+ const scenarios = unitScenarios(cwd, unit);
101
+ const result: DraftResult = { written: [], skipped: [] };
102
+ const seen = new Set<string>();
103
+ for (const row of wanted) {
104
+ if (seen.has(row.scenario)) continue; // one record per scenario, even across OS variants
105
+ seen.add(row.scenario);
106
+ const existing = recorded.get(row.scenario);
107
+ if (existing) { result.skipped.push({ scenario: row.scenario, id: existing }); continue; }
108
+ const id = nextDefectId(cwd);
109
+ const file = path.join(defectsDir(cwd), `${id}-${slug(row.scenario) || 'defect'}.md`);
110
+ fs.mkdirSync(path.dirname(file), { recursive: true });
111
+ fs.writeFileSync(file, render(cwd, unit, id, row, scenarios.get(row.scenario)), { encoding: 'utf-8', flag: 'wx' });
112
+ result.written.push(path.relative(cwd, file));
113
+ }
114
+ return result;
115
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Defect records — `qa/defects/DEF-NNN-<slug>.md`, one project-wide folder. A scenario points at a
3
+ * record with `@known-defect:DEF-NNN`; the record points back at units, scenarios, claims and legacy
4
+ * TCs in its frontmatter. This module reads the records and checks both directions of that link.
5
+ * Drafting a record from a triage row lives in defect-draft.ts.
6
+ */
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+ import { parse as parseYaml } from 'yaml';
10
+
11
+ export const DEFECT_STATUSES = ['open', 'fixed', 'verified', 'closed', 'wont-fix'] as const;
12
+ export type DefectStatus = typeof DEFECT_STATUSES[number];
13
+
14
+ export interface DefectRecord {
15
+ id: string;
16
+ title: string;
17
+ severity: string;
18
+ status: string;
19
+ units: string[];
20
+ scenarios: string[];
21
+ /** Project-relative path of the record file. */
22
+ file: string;
23
+ }
24
+
25
+ const DEF_FILE = /^(DEF-(\d+))-.*\.md$/;
26
+ const KNOWN_DEFECT_TAG = /@known-defect:(DEF-\d+)\b/g;
27
+
28
+ export function defectsDir(cwd: string): string {
29
+ return path.join(cwd, 'qa', 'defects');
30
+ }
31
+
32
+ function defectFiles(cwd: string): string[] {
33
+ const dir = defectsDir(cwd);
34
+ return fs.existsSync(dir) ? fs.readdirSync(dir).filter((f) => DEF_FILE.test(f)).sort() : [];
35
+ }
36
+
37
+ /** The next free id: one above the highest number on disk, zero-padded to 3. */
38
+ export function nextDefectId(cwd: string): string {
39
+ const max = defectFiles(cwd).reduce((m, f) => Math.max(m, Number(f.match(DEF_FILE)![2])), 0);
40
+ return `DEF-${String(max + 1).padStart(3, '0')}`;
41
+ }
42
+
43
+ const list = (v: unknown): string[] => (Array.isArray(v) ? v.map(String) : []);
44
+
45
+ /** Every record whose frontmatter parses; a malformed file is skipped, never thrown on. */
46
+ export function readDefects(cwd: string): DefectRecord[] {
47
+ const out: DefectRecord[] = [];
48
+ for (const f of defectFiles(cwd)) {
49
+ const file = path.join(defectsDir(cwd), f);
50
+ try {
51
+ const fm = parseYaml(fs.readFileSync(file, 'utf-8').split(/^---\s*$/m)[1] ?? '') as Record<string, unknown> | null;
52
+ if (!fm || typeof fm !== 'object') continue;
53
+ out.push({
54
+ id: String(fm.id ?? f.match(DEF_FILE)![1]),
55
+ title: String(fm.title ?? ''),
56
+ severity: String(fm.severity ?? ''),
57
+ status: String(fm.status ?? ''),
58
+ units: list(fm.units),
59
+ scenarios: list(fm.scenarios),
60
+ file: path.relative(cwd, file),
61
+ });
62
+ } catch {
63
+ // unreadable frontmatter: not a record we can reason about
64
+ }
65
+ }
66
+ return out;
67
+ }
68
+
69
+ /**
70
+ * Advisory audit findings for one unit (never scored):
71
+ * DEFECT-REF-MISSING a `@known-defect:DEF-NNN` tag with no record file.
72
+ * DEFECT-ORPHAN (info) an OPEN record of this unit names a scenario the unit no longer has.
73
+ */
74
+ export function defectLinkFindings(cwd: string, unitId: string, featureText: string, scenarioNames: string[]): string[] {
75
+ const records = readDefects(cwd);
76
+ const findings: string[] = [];
77
+ const known = new Set(records.map((r) => r.id));
78
+ const tagged = new Set([...featureText.matchAll(KNOWN_DEFECT_TAG)].map((m) => m[1]));
79
+ for (const id of tagged) {
80
+ if (!known.has(id)) {
81
+ findings.push(`DEFECT-REF-MISSING: \`@known-defect:${id}\` has no record in qa/defects/ — draft it with \`sungen defect draft --screen ${unitId}\`, or correct the id.`);
82
+ }
83
+ }
84
+ const names = new Set(scenarioNames);
85
+ for (const r of records) {
86
+ if (r.status !== 'open' || !r.units.includes(unitId)) continue;
87
+ for (const s of r.scenarios) {
88
+ if (!names.has(s)) {
89
+ findings.push(`DEFECT-ORPHAN (info): ${r.id} is open and names scenario "${s}", which ${unitId} no longer has — update the record's scenarios, or close it.`);
90
+ }
91
+ }
92
+ }
93
+ return findings;
94
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The audit's gateStatus conjunction, in ONE place (OES-11.2): `runAudit` evaluates it to set
3
+ * gateStatus, and `verifyAuditReport` re-evaluates it from the report's own fields to catch a stored
4
+ * PASS the report cannot reproduce (a hand-flipped gateStatus + exitCode — tester finding m1).
5
+ *
6
+ * Each term names its catalog rule; `resolveRule` decides whether a violated one blocks. The decision
7
+ * layer adds three hard terms: a rejected override, a decision file that does not verify (id / hash).
8
+ * Re-evaluating catches casual tampering only: a forger who also rewrites every finding, gap and
9
+ * verdict in the report is out of scope here, as for inputsHash (anti-staleness, not anti-forgery).
10
+ */
11
+ import { evaluateGateTerms, GateTerm } from './gate-terms';
12
+ import { trackGateRules } from './resolve-rule';
13
+ import { UnitGateOverrides } from './unit-gate-overrides';
14
+
15
+ /** The report fields the conjunction reads — present in every report runAudit writes. */
16
+ export interface AuditTermSources {
17
+ gate: { gaps: unknown[] };
18
+ depth: { verdict: string };
19
+ claim: { verdict: string };
20
+ spec: { verdict: string };
21
+ taxonomyMismatch: boolean;
22
+ gateSensorError: boolean;
23
+ reusedScenarioIds: unknown[];
24
+ }
25
+
26
+ export function auditGateTerms(r: AuditTermSources): GateTerm[] {
27
+ return [
28
+ { rule: 'audit.viewpoint-coverage', holds: r.gate.gaps.length === 0 },
29
+ { rule: 'audit.assertion-depth', holds: r.depth.verdict !== 'fail' },
30
+ { rule: 'audit.claim-proof', holds: r.claim.verdict !== 'fail' },
31
+ { rule: 'audit.spec-coverage', holds: r.spec.verdict !== 'fail' },
32
+ { rule: 'audit.taxonomy-mismatch', holds: !r.taxonomyMismatch },
33
+ // An 'error' finding from a capability gate sensor (api, db, …) — the driver's own verdict.
34
+ { rule: 'audit.gate-sensor-error', holds: !r.gateSensorError },
35
+ // #694 — a reused id reaches the deliverable as two rows under one testcase id.
36
+ { rule: 'audit.scenario-id-reuse', holds: r.reusedScenarioIds.length === 0 },
37
+ ];
38
+ }
39
+
40
+ export function decisionTerms(o: UnitGateOverrides): GateTerm[] {
41
+ return [
42
+ { rule: 'gate.override-rejected', holds: o.rejected.length === 0 },
43
+ { rule: 'decision.id-reuse', holds: !o.problems.some((p) => p.code === 'id-mismatch') },
44
+ { rule: 'decision.mutated', holds: !o.problems.some((p) => p.code !== 'id-mismatch') },
45
+ ];
46
+ }
47
+
48
+ /** The gateStatus a report's own terms produce under the unit's overrides — what the audit computed. */
49
+ export function recomputeAuditGateStatus(sources: AuditTermSources, overrides: UnitGateOverrides): 'PASS' | 'FAIL' {
50
+ const outcome = evaluateGateTerms([...auditGateTerms(sources), ...decisionTerms(overrides)], trackGateRules(overrides.context));
51
+ return outcome.pass ? 'PASS' : 'FAIL';
52
+ }
53
+
54
+ const isObj = (v: unknown): v is Record<string, unknown> => !!v && typeof v === 'object' && !Array.isArray(v);
55
+
56
+ /**
57
+ * The term sources of a parsed audit.json. `strict` (a current report): every field must be there with
58
+ * its type, else null. Not strict (a legacy report, written before some fields): a missing field reads
59
+ * as "holds", so only a stored PASS that a present field contradicts can be caught.
60
+ */
61
+ export function termSourcesOf(r: Record<string, unknown>, strict: boolean): AuditTermSources | null {
62
+ const verdict = (k: string): string | null | undefined => {
63
+ const v = r[k];
64
+ if (!isObj(v)) return strict ? null : undefined;
65
+ return typeof v.verdict === 'string' ? v.verdict : strict ? null : undefined;
66
+ };
67
+ const gaps = isObj(r.gate) && Array.isArray(r.gate.gaps) ? r.gate.gaps : strict ? null : [];
68
+ const depth = verdict('depth');
69
+ const claim = verdict('claim');
70
+ const spec = verdict('spec');
71
+ const flag = (k: string): boolean | null => (typeof r[k] === 'boolean' ? r[k] as boolean : strict ? null : false);
72
+ const taxonomyMismatch = flag('taxonomyMismatch');
73
+ const gateSensorError = flag('gateSensorError');
74
+ const reused = Array.isArray(r.reusedScenarioIds) ? r.reusedScenarioIds : strict ? null : [];
75
+ if ([gaps, depth, claim, spec, taxonomyMismatch, gateSensorError, reused].some((x) => x === null)) return null;
76
+ return {
77
+ gate: { gaps: gaps as unknown[] }, depth: { verdict: depth ?? 'pass' }, claim: { verdict: claim ?? 'pass' }, spec: { verdict: spec ?? 'pass' },
78
+ taxonomyMismatch: taxonomyMismatch as boolean, gateSensorError: gateSensorError as boolean, reusedScenarioIds: reused as unknown[],
79
+ };
80
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * The audit's side of the gate registry (OES-11.2/11.4): load the unit's gate overrides, hand the
3
+ * tracked rules to the sensors, evaluate the gateStatus conjunction, and produce the fields the
4
+ * report records so readers can verify it (takumi T3):
5
+ *
6
+ * gateOverrides[] every override touching the unit, applied / ineffective / rejected
7
+ * decisionsHash the overrides it was judged under (stale when they change)
8
+ * inputsHash .feature + spec + viewpoint + decisionsHash
9
+ * exitCode 0 on PASS, 2 on FAIL — what `sungen audit` exits with
10
+ *
11
+ * The decision layer adds three hard terms: a rejected override (gate.override-rejected) and a
12
+ * decision file in the unit's reach that does not verify (decision.id-reuse / decision.mutated).
13
+ * With no decision at all none of this changes an outcome.
14
+ */
15
+ import * as path from 'path';
16
+ import { projectRootFromScreenDir } from '../intent';
17
+ import { auditInputsHash } from './audit-input-hash';
18
+ import { evaluateGateTerms, ruleVerdict, SensorVerdict } from './gate-terms';
19
+ import { auditGateTerms, AuditTermSources, decisionTerms } from './audit-gate-terms';
20
+ import { GateOverrideReport, gateOverrideReports } from './gate-override-report';
21
+ import { GateRules, TrackedGateRules, trackGateRules } from './resolve-rule';
22
+ import { loadUnitGateOverrides, unitScopeOfDir, UnitGateOverrides } from './unit-gate-overrides';
23
+
24
+ export const AUDIT_EXIT_CODE = { PASS: 0, FAIL: 2 } as const;
25
+
26
+ export interface AuditGateContext {
27
+ projectRoot: string;
28
+ overrides: UnitGateOverrides;
29
+ rules: TrackedGateRules;
30
+ }
31
+
32
+ export function auditGateContext(unitDir: string): AuditGateContext {
33
+ const projectRoot = projectRootFromScreenDir(unitDir);
34
+ const overrides = loadUnitGateOverrides(projectRoot, unitScopeOfDir(projectRoot, unitDir));
35
+ return { projectRoot, overrides, rules: trackGateRules(overrides.context) };
36
+ }
37
+
38
+ /** A depth verdict a capability computed with the catalog alone, re-levelled for this unit's rules. */
39
+ export function relevelProvidedDepth<T extends { verdict: SensorVerdict }>(depth: T, rules: GateRules): T {
40
+ if (depth.verdict !== 'fail') return depth;
41
+ const verdict = ruleVerdict(rules, 'audit.assertion-depth', true, false);
42
+ return verdict === 'fail' ? depth : { ...depth, verdict };
43
+ }
44
+
45
+ /** Findings for the decision layer — empty when the unit has no override and no bad decision file. */
46
+ export function decisionFindings(ctx: AuditGateContext): string[] {
47
+ const o = ctx.overrides;
48
+ const rel = (p: string): string => path.relative(ctx.projectRoot, p).split(path.sep).join('/');
49
+ return [
50
+ ...o.rejected.map((r) => `GATE-OVERRIDE-REJECTED (gate.override-rejected): ${r.decisionId} in ${r.path} cannot apply — ${r.reason}. Record a valid override that supersedes it.`),
51
+ ...o.ineffective.map((r) => `GATE-OVERRIDE-INEFFECTIVE: ${r.decisionId} (${r.rule ?? '?'}) in ${r.path} relaxes nothing — ${r.reason}. Record it with \`sungen journey --decide gate-override\` on a terminal.`),
52
+ ...o.problems.map((p) => `${p.code === 'id-mismatch' ? 'DECISION-ID-REUSED (decision.id-reuse)' : 'DECISION-UNVERIFIABLE (decision.mutated)'}: ${rel(p.path)} — ${p.message}. Restore it from git; change a decision by recording a superseding one.`),
53
+ ...o.inForce.map((x) => `GATE-OVERRIDDEN: ${x.rule} is ${x.severity} for ${x.scope} (catalog level lowered by ${x.decisionId}, recorded by ${x.by}) — ${x.reason}`),
54
+ // Review H1: it counts here so its author sees the effect; release refuses it until reviewed.
55
+ ...o.inForce.filter((x) => x.committed === false).map((x) => `GATE-OVERRIDE-UNCOMMITTED: ${x.decisionId} (${x.rule}) is not in git HEAD — it counts in this audit, but \`sungen gate --phase deliver\` and \`sungen delivery\` refuse it (decision.in-run) until it is committed through review.`),
56
+ ];
57
+ }
58
+
59
+ export interface AuditGateVerdict {
60
+ gateStatus: 'PASS' | 'FAIL';
61
+ gateOverrides: GateOverrideReport[];
62
+ decisionsHash: string;
63
+ inputsHash: string;
64
+ exitCode: number;
65
+ }
66
+
67
+ /** Evaluate the gateStatus conjunction (audit-gate-terms.ts, shared with the reader) and the verifiable fields. */
68
+ export function auditGateVerdict(ctx: AuditGateContext, sources: AuditTermSources, unitDir: string, unitName: string): AuditGateVerdict {
69
+ const outcome = evaluateGateTerms([...auditGateTerms(sources), ...decisionTerms(ctx.overrides)], ctx.rules);
70
+ const gateStatus = outcome.pass ? 'PASS' : 'FAIL';
71
+ return {
72
+ gateStatus,
73
+ gateOverrides: gateOverrideReports(ctx.overrides, ctx.rules.triggered()),
74
+ decisionsHash: ctx.overrides.decisionsHash,
75
+ inputsHash: auditInputsHash(unitDir, unitName, ctx.overrides.decisionsHash),
76
+ exitCode: AUDIT_EXIT_CODE[gateStatus],
77
+ };
78
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * `inputsHash` of an audit (OES-11.4, takumi T3): the hash of what the audit judged plus the
3
+ * `decisionsHash` it was judged under. A reader recomputes it; any difference means the report no
4
+ * longer describes the unit, so it counts as never audited.
5
+ *
6
+ * It is ANTI-STALENESS, NOT ANTI-FORGERY: anyone who can write audit.json can also compute this hash
7
+ * (the function is public). It catches a report that outlived its inputs; verdicts built by code and
8
+ * the git-HEAD checks on decisions are what stand against a forger.
9
+ *
10
+ * Inputs — every file whose change can move a verdict:
11
+ * the unit's .feature files · requirements/spec.md · requirements/test-viewpoint.md ·
12
+ * requirements/flow-contract.yaml · requirements/spec_figma.md · requirements/ui-inventory.md ·
13
+ * requirements/ui/* · qa/context.md (intent focus → thresholds) · qa/capabilities.yaml (platform,
14
+ * enabled drivers → gate sensors)
15
+ * Not yet (phase 05 follow-ups): qa/defects/ and the sibling flows credited to a screen.
16
+ */
17
+ import { createHash } from 'crypto';
18
+ import * as fs from 'fs';
19
+ import * as path from 'path';
20
+ import { canonicalJson } from '../../decisions/decision-identity';
21
+ import { projectRootFromScreenDir } from '../intent';
22
+ import { featureFilesFor } from '../unit-paths';
23
+
24
+ const sha256 = (s: string | Buffer): string => createHash('sha256').update(s).digest('hex');
25
+
26
+ function fileSha(file: string): string | null {
27
+ try { return sha256(fs.readFileSync(file)); } catch { return null; }
28
+ }
29
+
30
+ function filesIn(dir: string): string[] {
31
+ try {
32
+ return fs.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => path.join(dir, e.name)).sort();
33
+ } catch { return []; }
34
+ }
35
+
36
+ /** The audit's input files that exist, in a stable order. */
37
+ export function auditInputFiles(unitDir: string, unitName: string): string[] {
38
+ const req = path.join(unitDir, 'requirements');
39
+ const qa = path.join(projectRootFromScreenDir(unitDir), 'qa');
40
+ const candidates = [
41
+ ...featureFilesFor(unitDir, unitName),
42
+ ...['spec.md', 'test-viewpoint.md', 'flow-contract.yaml', 'spec_figma.md', 'ui-inventory.md'].map((f) => path.join(req, f)),
43
+ ...filesIn(path.join(req, 'ui')),
44
+ path.join(qa, 'context.md'),
45
+ path.join(qa, 'capabilities.yaml'),
46
+ ];
47
+ return candidates.filter((f) => fs.existsSync(f));
48
+ }
49
+
50
+ export function auditInputsHash(unitDir: string, unitName: string, decisionsHash: string): string {
51
+ const root = projectRootFromScreenDir(unitDir);
52
+ const inputs = auditInputFiles(unitDir, unitName)
53
+ .map((f) => ({ file: path.relative(root, f).split(path.sep).join('/'), sha: fileSha(f) }));
54
+ return sha256(canonicalJson({ schema: 2, inputs, decisionsHash }));
55
+ }
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Reading `audit.json` back without trusting it (takumi T3, DOS-14.0, OES-11.4). The report is an
3
+ * OUTPUT of `sungen audit`; every reader (journey/gate, delivery, and `next` via this module) checks:
4
+ *
5
+ * schema a JSON object; only the keys the audit writes; known keys have their type
6
+ * status `gateStatus` is PASS|FAIL and agrees with the integer `exitCode` (0 | 2)
7
+ * inputs `inputsHash` equals the hash of today's inputs + decisions (audit-input-hash.ts)
8
+ * decisions `decisionsHash` equals today's — otherwise the audit is stale: re-audit
9
+ * rules `provenance.catalogHash` and `provenance.rulesHash` are the running sungen's — other
10
+ * catalogs or another AUDIT_RULES_VERSION scored it (a 3.2 PASS can be a 3.3 FAIL on the
11
+ * same files): stale, re-audit. Missing → stale (fail closed). The package VERSION
12
+ * alone is not a reason: a newer sungen with the same rules gives the same verdict (W4)
13
+ * verdict gateStatus re-evaluated from the report's own terms (audit-gate-terms.ts) under the
14
+ * overrides in force — a flipped gateStatus + exitCode is `verdict-mismatch` (tester m1)
15
+ * Anything else counts as NEVER AUDITED, not as clean; only an explicit `gateStatus: PASS` passes.
16
+ * These checks are anti-STALENESS and anti-casual-tamper, NOT anti-forgery: a writer of audit.json can
17
+ * recompute the hashes, and one who rewrites every finding, gap and verdict is out of scope here.
18
+ *
19
+ * Legacy (DOS-11.4, #933): a report written before these fields existed carries none of exitCode /
20
+ * inputsHash / decisionsHash / gateOverrides, so nothing in it can vouch for today's inputs. It reads
21
+ * STALE — one `sungen audit` records a current one. (It used to count while no input file was newer:
22
+ * a fresh checkout gives every file the checkout's mtime, so that proved nothing and an old PASS was
23
+ * trusted.) A legacy report claiming a PASS its own fields contradict is invalid. A report carrying
24
+ * SOME of the fields is malformed.
25
+ */
26
+ import * as fs from 'fs';
27
+ import * as path from 'path';
28
+ import { resolveUnitCandidates } from '../../cli/resolve-unit';
29
+ import { reportSlug } from '../unit-paths';
30
+ import { getProvenance } from '../provenance';
31
+ import { auditInputsHash } from './audit-input-hash';
32
+ import { AUDIT_EXIT_CODE } from './audit-gate-verdict';
33
+ import { recomputeAuditGateStatus, termSourcesOf } from './audit-gate-terms';
34
+ import { EMPTY_DECISIONS_HASH } from './decisions-hash';
35
+ import { loadUnitGateOverrides, unitScopeOfDir, UnitGateOverrides } from './unit-gate-overrides';
36
+
37
+ export type AuditState = 'absent' | 'verified' | 'stale' | 'invalid';
38
+ export type AuditProblemCode = 'unreadable' | 'unknown-key' | 'bad-type' | 'partial-fields' | 'status-exit-mismatch'
39
+ | 'unit-unresolved' | 'decisions-changed' | 'inputs-changed' | 'rules-changed' | 'legacy-with-overrides' | 'legacy-unverified' | 'verdict-mismatch';
40
+
41
+ export interface AuditVerification {
42
+ state: AuditState;
43
+ problems: Array<{ code: AuditProblemCode; message: string }>;
44
+ /** Caveats on a report that counts. */
45
+ notes: string[];
46
+ /** The parsed report — only when it counts (verified). */
47
+ report: Record<string, unknown> | null;
48
+ path: string;
49
+ /** Today's decisionsHash for the unit (what a fresh audit would record). */
50
+ currentDecisionsHash: string;
51
+ }
52
+
53
+ /** A string field of the report's provenance, or null when it does not say. */
54
+ function provenanceField(r: Record<string, unknown>, key: 'sungenVersion' | 'catalogHash' | 'rulesHash'): string | null {
55
+ const v = r.provenance && typeof r.provenance === 'object' ? (r.provenance as Record<string, unknown>)[key] : undefined;
56
+ return typeof v === 'string' && v ? v : null;
57
+ }
58
+ const writtenBy = (r: Record<string, unknown>): string | null => provenanceField(r, 'sungenVersion');
59
+
60
+ export interface RulesStamp { catalogHash: string | null; rulesHash: string | null }
61
+ /** What getProvenance writes when it could not read a catalog — never a match, on either side. */
62
+ const UNKNOWN = 'unknown';
63
+
64
+ /**
65
+ * Why the rules a report was scored by (`was`) cannot be taken as this sungen's (`now`), or null when
66
+ * they are the same KNOWN rules. Missing or `unknown` on either side is a problem (fail closed):
67
+ * unknown == unknown proves nothing.
68
+ */
69
+ export function rulesProblem(was: RulesStamp, now: RulesStamp): string | null {
70
+ if (!was.catalogHash || !was.rulesHash) return 'it does not say which rules scored it (no provenance.catalogHash / rulesHash)';
71
+ if ([was.catalogHash, was.rulesHash].includes(UNKNOWN)) return 'the rules that scored it are unknown (provenance says "unknown")';
72
+ if (!now.catalogHash || !now.rulesHash || [now.catalogHash, now.rulesHash].includes(UNKNOWN)) return 'this sungen cannot read its own rules (catalog or rules hash unknown), so it trusts no report';
73
+ if (was.catalogHash === now.catalogHash && was.rulesHash === now.rulesHash) return null;
74
+ return `scored by other rules (catalog ${was.catalogHash} · rules ${was.rulesHash}) than this sungen's (catalog ${now.catalogHash} · rules ${now.rulesHash})`;
75
+ }
76
+
77
+ /** Why a current-format report was judged by other rules than this sungen's, or null when the same. */
78
+ function otherRules(r: Record<string, unknown>): string | null {
79
+ return rulesProblem({ catalogHash: provenanceField(r, 'catalogHash'), rulesHash: provenanceField(r, 'rulesHash') }, getProvenance());
80
+ }
81
+
82
+ type JsonKind = 'string' | 'number' | 'boolean' | 'object' | 'array';
83
+ const OBJ = 'object' as const;
84
+ /** Every top-level key `runAudit` writes (tests/gates/audit-report-trust.run.ts keeps this in step). */
85
+ export const AUDIT_REPORT_KEYS: Record<string, JsonKind> = {
86
+ screen: 'string', scenarioCount: 'number', gate: OBJ, depth: OBJ, claim: OBJ, taxonomy: OBJ, balance: OBJ,
87
+ duplicates: OBJ, trace: OBJ, taxonomyMismatch: 'boolean', reusedScenarioIds: 'array', downstream: OBJ,
88
+ manualOracle: OBJ, automatableManual: OBJ, flowDepth: OBJ, oracle: OBJ, ledger: OBJ, viewpointBaseline: OBJ,
89
+ flowQuality: OBJ, flowInventory: OBJ, uiInventory: OBJ, calibration: OBJ, score: OBJ, gateStatus: 'string',
90
+ findings: 'array', intent: OBJ, provenance: OBJ, spec: OBJ,
91
+ gateOverrides: 'array', decisionsHash: 'string', inputsHash: 'string', exitCode: 'number', gateSensorError: 'boolean',
92
+ };
93
+ const P0_KEYS = ['exitCode', 'inputsHash', 'decisionsHash', 'gateOverrides', 'gateSensorError'];
94
+ const HASH_RE = /^[0-9a-f]{64}$/;
95
+
96
+ const kindOf = (v: unknown): JsonKind | 'null' => (v === null ? 'null' : Array.isArray(v) ? 'array' : typeof v as JsonKind);
97
+
98
+ /** Structural problems of a parsed report, independent of the unit's current inputs. */
99
+ function schemaProblems(r: Record<string, unknown>): AuditVerification['problems'] {
100
+ const out: AuditVerification['problems'] = [];
101
+ for (const [k, v] of Object.entries(r)) {
102
+ const want = AUDIT_REPORT_KEYS[k];
103
+ if (!want) out.push({ code: 'unknown-key', message: `unknown key "${k}" — the audit never writes it` });
104
+ else if (kindOf(v) !== want) out.push({ code: 'bad-type', message: `"${k}" must be ${want}, got ${kindOf(v)}` });
105
+ }
106
+ if (r.gateStatus !== 'PASS' && r.gateStatus !== 'FAIL') out.push({ code: 'bad-type', message: 'gateStatus must be PASS or FAIL' });
107
+ if (Array.isArray(r.findings) && !r.findings.every((f) => typeof f === 'string')) out.push({ code: 'bad-type', message: 'findings must be strings' });
108
+ const present = P0_KEYS.filter((k) => k in r);
109
+ if (present.length > 0 && present.length < P0_KEYS.length) {
110
+ out.push({ code: 'partial-fields', message: `carries ${present.join(', ')} but not ${P0_KEYS.filter((k) => !(k in r)).join(', ')}` });
111
+ }
112
+ if (present.length === P0_KEYS.length) {
113
+ if (!Number.isInteger(r.exitCode)) out.push({ code: 'bad-type', message: 'exitCode must be an integer' });
114
+ else if (r.gateStatus === 'PASS' || r.gateStatus === 'FAIL') {
115
+ if (r.exitCode !== AUDIT_EXIT_CODE[r.gateStatus]) out.push({ code: 'status-exit-mismatch', message: `gateStatus ${r.gateStatus} with exitCode ${r.exitCode} — a ${r.gateStatus} audit exits ${AUDIT_EXIT_CODE[r.gateStatus]}` });
116
+ }
117
+ for (const k of ['inputsHash', 'decisionsHash']) if (typeof r[k] !== 'string' || !HASH_RE.test(r[k] as string)) out.push({ code: 'bad-type', message: `${k} must be 64 hex characters` });
118
+ if (Array.isArray(r.gateOverrides) && !r.gateOverrides.every((g) => kindOf(g) === 'object')) out.push({ code: 'bad-type', message: 'gateOverrides must be objects' });
119
+ }
120
+ return out;
121
+ }
122
+
123
+ export function auditReportPath(projectRoot: string, unit: string): string {
124
+ return path.join(projectRoot, '.sungen', 'reports', `${reportSlug(unit)}-audit.json`);
125
+ }
126
+
127
+ /** Today's decisionsHash for a unit name — what `next` compares an audit with (phase 05). */
128
+ export function currentDecisionsHash(projectRoot: string, unit: string): string {
129
+ const found = resolveUnitCandidates(unit, projectRoot);
130
+ const scope = found.length === 1 ? unitScopeOfDir(projectRoot, found[0].dir) : null;
131
+ return loadUnitGateOverrides(projectRoot, scope).decisionsHash;
132
+ }
133
+
134
+ export function verifyAuditReport(projectRoot: string, unit: string): AuditVerification {
135
+ const file = auditReportPath(projectRoot, unit);
136
+ const found = resolveUnitCandidates(unit, projectRoot);
137
+ const unitDir = found.length === 1 ? found[0].dir : null;
138
+ const overrides = loadUnitGateOverrides(projectRoot, unitDir ? unitScopeOfDir(projectRoot, unitDir) : null);
139
+ const current = overrides.decisionsHash;
140
+ const result = (state: AuditState, problems: AuditVerification['problems'], report: Record<string, unknown> | null = null, notes: string[] = []): AuditVerification =>
141
+ ({ state, problems, notes, report, path: file, currentDecisionsHash: current });
142
+
143
+ if (!fs.existsSync(file)) return result('absent', []);
144
+ let parsed: unknown;
145
+ try { parsed = JSON.parse(fs.readFileSync(file, 'utf8').replace(/^/, '')); } catch (err) {
146
+ return result('invalid', [{ code: 'unreadable', message: err instanceof Error ? err.message : String(err) }]);
147
+ }
148
+ if (kindOf(parsed) !== 'object') return result('invalid', [{ code: 'unreadable', message: 'not a JSON object' }]);
149
+ const r = parsed as Record<string, unknown>;
150
+ const schema = schemaProblems(r);
151
+ if (schema.length) return result('invalid', schema);
152
+
153
+ if (!P0_KEYS.some((k) => k in r)) {
154
+ // A legacy report predates gateSensorError, so only a stored PASS its own fields contradict is caught.
155
+ const sources = termSourcesOf(r, false);
156
+ if (r.gateStatus === 'PASS' && sources && recomputeAuditGateStatus(sources, overrides) === 'FAIL') return result('invalid', [verdictMismatch(r)]);
157
+ const by = `written by ${writtenBy(r) ? `sungen ${writtenBy(r)}` : 'an earlier sungen'}`;
158
+ if (current !== EMPTY_DECISIONS_HASH) {
159
+ return result('stale', [{ code: 'legacy-with-overrides', message: `${by} (no decisionsHash) and a gate-override now applies to this unit` }]);
160
+ }
161
+ return result('stale', [{ code: 'legacy-unverified', message: `${by}, before inputsHash existed — its inputs cannot be verified` }]);
162
+ }
163
+ const stale: AuditVerification['problems'] = [];
164
+ const rules = otherRules(r);
165
+ if (rules) stale.push({ code: 'rules-changed', message: `${writtenBy(r) ? `written by sungen ${writtenBy(r)}, ` : ''}${rules}` });
166
+ if (r.decisionsHash !== current) stale.push({ code: 'decisions-changed', message: 'the gate-override decisions changed since this audit' });
167
+ if (!unitDir) return result('invalid', [{ code: 'unit-unresolved', message: `"${unit}" does not name exactly one unit, so the audit's inputs cannot be checked` }]);
168
+ if (r.inputsHash !== auditInputsHash(unitDir, unit, r.decisionsHash as string)) {
169
+ stale.push({ code: 'inputs-changed', message: 'an input the audit judged (.feature, spec, viewpoint, context, design) changed since this audit' });
170
+ }
171
+ if (stale.length) return result('stale', stale);
172
+ const tampered = verdictProblem(r, overrides);
173
+ return tampered ? result('invalid', [tampered]) : result('verified', [], r);
174
+ }
175
+
176
+ const verdictMismatch = (r: Record<string, unknown>): AuditVerification['problems'][number] => ({
177
+ code: 'verdict-mismatch',
178
+ message: `verdict mismatch — gateStatus ${String(r.gateStatus)} is not what the report's own findings produce under today's overrides (edited by hand)`,
179
+ });
180
+
181
+ /** A current report re-evaluated from its own terms (audit-gate-terms.ts): missing terms or another verdict = not trusted. */
182
+ function verdictProblem(r: Record<string, unknown>, overrides: UnitGateOverrides): AuditVerification['problems'][number] | null {
183
+ const sources = termSourcesOf(r, true);
184
+ if (!sources) return { code: 'bad-type', message: 'the gate terms (gate.gaps, depth/claim/spec verdicts, taxonomyMismatch, gateSensorError, reusedScenarioIds) are incomplete' };
185
+ return recomputeAuditGateStatus(sources, overrides) === r.gateStatus ? null : verdictMismatch(r);
186
+ }
187
+
188
+ /** Whether the report may be used at all: only a verified one. */
189
+ export const auditCounts = (v: AuditVerification): boolean => v.state === 'verified';
190
+
191
+ /** Only an explicit `gateStatus: PASS` on a report that counts passes; a score never does. */
192
+ export const auditPassed = (v: AuditVerification): boolean => auditCounts(v) && v.report?.gateStatus === 'PASS';
193
+
194
+ /** One line saying why the report does not count, for a needs-you item or a blocker. */
195
+ export function auditNotCountedReason(v: AuditVerification, unit: string): string {
196
+ const why = v.problems.map((p) => p.message).join('; ');
197
+ const rerun = `re-run \`sungen audit --screen ${unit}\``;
198
+ if (v.state === 'stale') return `Audit report is stale (${why}) — ${rerun}.`;
199
+ if (v.state === 'invalid') return `Audit report is not trusted (${why}) — treated as never audited; ${rerun}.`;
200
+ return `No audit report yet — ${rerun}.`;
201
+ }