@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
@@ -16,9 +16,17 @@
16
16
  */
17
17
  import * as fs from 'fs';
18
18
  import * as path from 'path';
19
- import { reportSlug, featureFilesFor } from './unit-paths';
20
- import { readTextFile } from './read-text';
19
+ import { reportSlug } from './unit-paths';
21
20
  import { checkAssetsDrift } from '../orchestrator/assets-drift';
21
+ import type { HeadSnapshot } from '../contract/contract-git';
22
+ import { evaluateGraph, EvaluateOptions } from '../graph/evaluate-graph';
23
+ import { CORE_NODES } from '../graph/nodes/core-node-catalog';
24
+ import type { TestCaseState } from '../graph/test-case-state-shape';
25
+ import { testCaseStates } from '../graph/test-case-states';
26
+ import {
27
+ countFailedResults, countScenarios, hasDeliverableFor, hasResolvedSelector, isCompiled, readIfExists, unitResultFiles,
28
+ } from '../graph/unit-artifact-probes';
29
+ import { AuditNotCounted, ContractFacts, ContractSummary, readContractFacts, readTrustedAudit } from '../graph/unit-state-facts';
22
30
 
23
31
  export interface NextStep {
24
32
  /** The command to run, as the operator would type it. */
@@ -33,6 +41,13 @@ export interface NextStep {
33
41
  * in the same session (#660).
34
42
  */
35
43
  kind: 'do' | 'blocked' | 'optional' | 'decide';
44
+ /** The graph node that produced the step (OES-10.1). `--json` detail; the text never shows it. */
45
+ nodeId?: string;
46
+ granularity?: 'unit' | 'test-case';
47
+ /** The one test case the step is about (`sungen next <unit> --case <id>`). */
48
+ testCase?: string;
49
+ /** Catalog rule ids (gate-rules.yaml) the step answers to. */
50
+ gates?: string[];
36
51
  }
37
52
 
38
53
  export interface UnitState {
@@ -47,6 +62,13 @@ export interface UnitState {
47
62
  selectorsArePlaceholder: boolean;
48
63
  compiled: boolean;
49
64
  hasResults: boolean;
65
+ /**
66
+ * Scenarios whose FINAL attempt failed (failed · timedOut · interrupted) across the unit's result
67
+ * files — a retried pass is not a failure. Any failure puts `sungen triage` in the path: with only
68
+ * "optional" left after a deliverable, a red run read as done and its reds reached the export
69
+ * unclassified. Absent when the state was not read from disk.
70
+ */
71
+ failedCount?: number;
50
72
  hasDeliverable: boolean;
51
73
  audit?: {
52
74
  overall: number;
@@ -61,69 +83,42 @@ export interface UnitState {
61
83
  * warning is one grey stderr line at the top of every command (#620).
62
84
  */
63
85
  assetsDrift?: { recordedVersion: string; runningVersion: string };
86
+ /** An audit report exists but does not count (stale, untrusted) — gate and delivery block on it too. */
87
+ auditNotCounted?: AuditNotCounted;
88
+ /** The rebuilt Test Contract verdict (DOS-14.4); absent when not read from disk or no scenario exists. */
89
+ contract?: ContractSummary;
90
+ /** Per-test-case state (DOS-11.1); absent when not read from disk or unreadable. */
91
+ testCases?: TestCaseState[];
64
92
  steps: NextStep[];
65
93
  }
66
94
 
67
- const exists = (p: string): boolean => fs.existsSync(p);
68
-
69
- function readJson(p: string): Record<string, unknown> | null {
70
- try {
71
- return JSON.parse(readTextFile(p)) as Record<string, unknown>;
72
- } catch {
73
- return null; // absent or unreadable — treated as "not run"
74
- }
95
+ export interface ReadUnitStateOptions {
96
+ /** git HEAD read once for many units (`sungen next` with no unit). */
97
+ gitSnapshot?: HeadSnapshot;
75
98
  }
76
99
 
77
- function countScenarios(unitDir: string, unit: string): number {
78
- let n = 0;
79
- for (const f of featureFilesFor(unitDir, unit)) {
80
- const text = fs.existsSync(f) ? readTextFile(f) : '';
81
- n += (text.match(/^\s*Scenario(?: Outline)?:/gm) ?? []).length;
82
- }
83
- return n;
84
- }
100
+ const exists = (p: string): boolean => fs.existsSync(p);
85
101
 
86
102
  /**
87
- * Everything the resolver needs, read from disk. `unitId` is the catalog id
88
- * (`<screen>` · `flows/<f>` · `api/<a>`); `unitDir` is its directory.
103
+ * Everything the resolver needs, read from disk. `unit` is the catalog id
104
+ * (`<screen>` · `flows/<f>` · `api/<a>`); `unitDir` is its directory. The audit report is read
105
+ * through verifyAuditReport, as `sungen gate` and `sungen delivery` read it: a stale or untrusted
106
+ * report counts as never audited (OES-11.4) and is named in `auditNotCounted`.
89
107
  */
90
108
  export function readUnitState(
91
- projectRoot: string, unitDir: string, unit: string, kind: UnitState['kind'],
109
+ projectRoot: string, unitDir: string, unit: string, kind: UnitState['kind'], opts: ReadUnitStateOptions = {},
92
110
  ): UnitState {
93
111
  const req = path.join(unitDir, 'requirements');
94
112
  const slug = reportSlug(unit);
95
- const audit = readJson(path.join(projectRoot, '.sungen', 'reports', `${slug}-audit.json`));
113
+ const { report: audit, notCounted } = readTrustedAudit(projectRoot, unit);
96
114
  const selectorsDir = path.join(unitDir, 'selectors');
97
115
  let selectorFiles: string[] = [];
98
116
  try {
99
117
  selectorFiles = fs.readdirSync(selectorsDir).filter((f) => f.endsWith('.yaml'));
100
118
  } catch { /* api units carry no selectors */ }
101
- // `readTextFile` throws on a missing file, and every path here is legitimately absent at some
102
- // point in a unit's life — the resolver exists to report exactly that, so it must not crash on it.
103
- const read = (p: string): string => (fs.existsSync(p) ? readTextFile(p) : '');
104
- const selectorText = selectorFiles.map((f) => read(path.join(selectorsDir, f))).join('\n');
119
+ const selectorTexts = selectorFiles.map((f) => readIfExists(path.join(selectorsDir, f)));
105
120
  const contractPath = path.join(req, 'flow-contract.yaml');
106
- const contractText = read(contractPath);
107
-
108
- const specDirs = [
109
- path.join(projectRoot, 'specs', 'generated', 'flows', unit),
110
- path.join(projectRoot, 'specs', 'generated', unit),
111
- ];
112
- const compiled = specDirs.some((d) => {
113
- try {
114
- return fs.readdirSync(d).some((f) => f.endsWith('.spec.ts'));
115
- } catch { return false; }
116
- });
117
- const hasResults = specDirs.some((d) => {
118
- try {
119
- return fs.readdirSync(d).some((f) => f.endsWith('-test-result.json'));
120
- } catch { return false; }
121
- });
122
- let hasDeliverable = false;
123
- try {
124
- hasDeliverable = fs.readdirSync(path.join(projectRoot, 'qa', 'deliverables'))
125
- .some((f) => f.startsWith(`${slug}-`));
126
- } catch { /* nothing exported yet */ }
121
+ const resultFiles = unitResultFiles(projectRoot, unit);
127
122
 
128
123
  const score = (audit?.score ?? {}) as { overall?: number };
129
124
  const baseline = (audit?.viewpointBaseline ?? {}) as { status?: string };
@@ -134,14 +129,16 @@ export function readUnitState(
134
129
  hasContract: exists(contractPath),
135
130
  // A contract WITHOUT `flows:` can only be scored per phase, which is a materially weaker
136
131
  // claim — so it is part of the state, not a detail.
137
- hasFlowInventory: /^\s*flows:\s*$/m.test(contractText),
132
+ hasFlowInventory: /^\s*flows:\s*$/m.test(readIfExists(contractPath)),
138
133
  scenarioCount: countScenarios(unitDir, unit),
139
134
  hasSelectors: selectorFiles.length > 0,
140
135
  // A scaffolded selector file exists but resolves nothing; treating it as "done" is what
141
136
  // makes a run look further along than it is.
142
- selectorsArePlaceholder: selectorFiles.length > 0
143
- && (/TODO|PLACEHOLDER|REPLACE ME/i.test(selectorText) || selectorText.trim().length < 40),
144
- compiled, hasResults, hasDeliverable,
137
+ selectorsArePlaceholder: selectorFiles.length > 0 && !selectorTexts.some(hasResolvedSelector),
138
+ compiled: isCompiled(projectRoot, unit),
139
+ hasResults: resultFiles.length > 0,
140
+ failedCount: countFailedResults(resultFiles),
141
+ hasDeliverable: hasDeliverableFor(projectRoot, slug),
145
142
  assetsDrift: (() => {
146
143
  const d = checkAssetsDrift(projectRoot);
147
144
  return d && d.recordedVersion !== d.runningVersion
@@ -156,131 +153,24 @@ export function readUnitState(
156
153
  viewpointBaselineStatus: baseline.status,
157
154
  }
158
155
  : undefined,
156
+ ...(notCounted ? { auditNotCounted: notCounted } : {}),
159
157
  steps: [],
160
158
  };
159
+ let contract: ContractFacts | undefined;
160
+ if (state.scenarioCount > 0) state.contract = (contract = readContractFacts(projectRoot, unit, unitDir, opts.gitSnapshot)).summary;
161
+ try {
162
+ state.testCases = testCaseStates(projectRoot, unit, { unitDir, auditFindings: state.audit?.findings ?? [] })
163
+ .map((tc) => (contract?.cases.has(tc.id) ? { ...tc, contract: contract.cases.get(tc.id) } : tc));
164
+ } catch { /* an unparseable .feature — the unit-level nodes still answer, as before test-case state */ }
161
165
  state.steps = deriveSteps(state);
162
166
  return state;
163
167
  }
164
168
 
165
- /** The finding codes worth naming in a next step — each maps to a specific repair. */
166
- const REPAIRABLE = [
167
- 'FLOW-CONTRACT-MISSING', 'FLOW-INVENTORY-MISSING', 'FLOW-UNCOVERED', 'FLOW-UNDECLARED',
168
- 'FLOW-PHASE-MISFILED', 'FLOW-GUARANTEE-MISSING', 'FLOW-OUTCOME-UNPROVEN', 'CONTINUITY-ONE-SIDED',
169
- 'ORACLE-URL-ONLY',
170
- 'SPEC-RESTATED-UNVERIFIED', 'VIEWPOINT-GESTURE-SUBSTITUTED', 'SPEC-UNCOVERED', 'SPEC-CLAUSE-UNCOVERED',
171
- 'TRIGGER-UNCOVERED', 'PERMISSION-PAIR-MISSING', 'VISIBILITY-PAIR-MISSING',
172
- 'VIEWPOINT-ITEM-MISSING', 'MANUAL-CODE-MISSING', 'MANUAL-AUTOMATABLE', 'DEPTH-DEFERRED',
173
- 'UI-INVENTORY-MISSING', 'UI-INVENTORY-INCOMPLETE', 'UI-ITEM-UNCOVERED',
174
- ];
175
-
176
169
  /**
177
- * The ordered answer. Earliest unmet precondition first, so the list reads as a path rather than
178
- * a menu — and a `blocked` step names what to resolve instead of pretending it can run.
170
+ * The ordered answer — earliest unmet precondition first, so the list reads as a path rather than a
171
+ * menu. Evaluated over the internal node graph (src/graph, OES-10.1): each former if/return branch
172
+ * is one node, and an open blocking node cuts everything after it, exactly as the `return`s did.
179
173
  */
180
- export function deriveSteps(s: UnitState): NextStep[] {
181
- const out: NextStep[] = [];
182
- const design = s.kind === 'api' ? `/sungen:create-test ${s.unit}` : `/sungen:create-test ${s.unit}`;
183
-
184
- if (!s.hasSpec && !s.hasViewpoint) {
185
- out.push({
186
- kind: 'blocked',
187
- command: `write qa/${s.kind === 'screen' ? 'screens' : s.kind === 'flow' ? 'flows' : 'api'}/${s.unit}/requirements/spec.md`,
188
- because: 'the unit has neither a spec nor a test-viewpoint, so there is nothing to generate FROM — generation without a source invents behaviour',
189
- });
190
- return out;
191
- }
192
- // Stale AI assets come FIRST, because they invalidate the advice below: a HARD RULE added to
193
- // `create-test` reaches nobody until `sungen update` runs, so the run that follows will repeat
194
- // whatever the old instructions said. Upgrading the package alone does not refresh them, and the
195
- // existing warning is one grey stderr line among a command's whole output (#620).
196
- if (s.assetsDrift) {
197
- out.push({
198
- kind: 'do',
199
- command: 'sungen update',
200
- because: `this project's AI commands/skills were written by sungen ${s.assetsDrift.recordedVersion} and you are running ${s.assetsDrift.runningVersion} — upgrading the package does NOT refresh them, so any rule added since ${s.assetsDrift.recordedVersion} is not in effect for the next run`,
201
- });
202
- }
203
- // The yardstick. `atomicLedger` and `traceability` are measured against test-viewpoint.md and
204
- // four sensors read it, so its absence is not cosmetic — and it can go missing from a unit that
205
- // already HAS a spec (a run deleted it), which the "no source at all" branch above never sees.
206
- if (!s.hasViewpoint) {
207
- out.push({
208
- kind: 'blocked',
209
- command: s.kind === 'flow'
210
- ? `sungen add-flow --flow ${s.unit} --path <start-url> # repairs the missing scaffold; never overwrites`
211
- : `write qa/screens/${s.unit}/requirements/test-viewpoint.md`,
212
- because: 'requirements/test-viewpoint.md is missing — it is the yardstick `atomicLedger` and `traceability` are measured against, and four sensors read it, so the audit reports VIEWPOINT-MISSING and those axes are excluded. A flow contract does not substitute: it declares the use case, the viewpoint declares the claims',
213
- });
214
- }
215
- if (s.kind === 'flow' && !s.hasContract) {
216
- out.push({
217
- kind: 'blocked',
218
- command: `author requirements/flow-contract.yaml, then ${design}`,
219
- because: 'a flow with no contract is scored as a generic screen against page-type themes a journey cannot have (FLOW-CONTRACT-MISSING)',
220
- });
221
- return out;
222
- }
223
- if (s.scenarioCount === 0) {
224
- out.push({ kind: 'do', command: design, because: 'no scenarios exist yet' });
225
- return out;
226
- }
227
- if (s.kind === 'flow' && !s.hasFlowInventory) {
228
- out.push({
229
- kind: 'do',
230
- command: `add \`flows:\` to requirements/flow-contract.yaml, then sungen audit --screen ${s.unit}`,
231
- because: 'without the inventory, coverage is measured per PHASE — and a phase counts as covered as soon as one scenario carries it, so the number cannot tell you a flow is missing',
232
- });
233
- }
234
- if (!s.audit) {
235
- out.push({ kind: 'do', command: `sungen audit --screen ${s.unit}`, because: 'the suite has never been measured' });
236
- return out;
237
- }
238
- if (s.audit.viewpointBaselineStatus === 'changed') {
239
- out.push({
240
- kind: 'decide',
241
- command: `sungen audit --screen ${s.unit} --accept-viewpoint`,
242
- because: 'test-viewpoint.md changed since the accepted baseline, so the ledger and traceability axes are not evidence until a QA confirms the new declaration. A decision, not a step: an agent presents it and does not run it — accepting the yardstick you just wrote makes both axes read 100% by construction',
243
- });
244
- }
245
- const repair = s.audit.findings
246
- .map((f) => f.split(':')[0].trim())
247
- .filter((code) => REPAIRABLE.includes(code));
248
- if (repair.length > 0) {
249
- out.push({
250
- kind: 'do',
251
- command: `repair, then sungen audit --screen ${s.unit}`,
252
- because: `${repair.length} finding(s) name a specific repair: ${[...new Set(repair)].slice(0, 4).join(', ')}`,
253
- });
254
- }
255
- if (s.audit.gateStatus === 'FAIL') {
256
- out.push({
257
- kind: 'blocked',
258
- command: `repair the gate, then sungen audit --screen ${s.unit}`,
259
- because: `the viewpoint gate is FAIL at ${s.audit.overall}/10 — running tests against a design that fails its own gate measures the wrong thing`,
260
- });
261
- return out;
262
- }
263
- if (s.kind !== 'api' && (!s.hasSelectors || s.selectorsArePlaceholder)) {
264
- out.push({
265
- kind: 'do',
266
- command: `/sungen:run-test ${s.unit}`,
267
- because: s.hasSelectors
268
- ? 'the selector file is still a placeholder, so nothing resolves against a live page'
269
- : 'no selectors exist yet — run-test generates them from the live page, compiles and auto-fixes',
270
- });
271
- return out;
272
- }
273
- if (!s.compiled) {
274
- out.push({ kind: 'do', command: `sungen generate --${s.kind === 'flow' ? 'flow' : 'screen'} ${s.unit}`, because: 'the suite has not been compiled to a spec yet' });
275
- return out;
276
- }
277
- if (!s.hasResults) {
278
- out.push({ kind: 'do', command: `/sungen:run-test ${s.unit}`, because: 'the compiled spec has never been run, so every case is Pending' });
279
- return out;
280
- }
281
- if (!s.hasDeliverable) {
282
- out.push({ kind: 'do', command: `/sungen:delivery ${s.unit}`, because: 'results exist but have not been exported to the Test Case & Coverage Matrix' });
283
- }
284
- out.push({ kind: 'optional', command: `/sungen:create-test ${s.unit}`, because: 'extend coverage — the next tier, or the flows the inventory still lists as pending' });
285
- return out;
174
+ export function deriveSteps(s: UnitState, opts: EvaluateOptions = {}): NextStep[] {
175
+ return evaluateGraph(CORE_NODES, s, s.testCases, opts);
286
176
  }
@@ -79,6 +79,7 @@ export interface ScenarioInfo {
79
79
  deferredToFlow?: boolean; // @deferred:flow — owned by a flow, not automated on this screen (H6)
80
80
  ownedByFlow?: string; // @owned-by:<flow> — the flow that owns this deferred scenario (H6)
81
81
  featureManual?: boolean; // its Feature is tagged @manual — codegen skips the whole file (#835)
82
+ handWritten?: boolean; // @free / @impl:code — counted, never compiled (isHandWritten, DOS-14.8)
82
83
  /** Ordered steps with their resolved bucket (And/But inherit) — flow handoff analysis (#569). */
83
84
  /** `arg` = the step's data table, normalised (#817) — absent when the step has none. */
84
85
  steps?: Array<{ bucket: 'given' | 'when' | 'then'; text: string; arg?: string }>;
@@ -285,6 +286,25 @@ function withBackground(sc: ParsedScenario, background?: ParsedScenario): Parsed
285
286
  return { ...sc, steps: [...bg, ...((sc.steps as ParsedStep[]) || [])] } as ParsedScenario;
286
287
  }
287
288
 
289
+ /**
290
+ * The `VP-<CATEGORY>-<n>` / `FL-<PHASE>-<n>` code in a scenario title, and its category — the ONE
291
+ * reading of it; the manifest kept an older copy of this regex and recorded no code for
292
+ * VP-I18N-001, VP-LIST-DISPLAY-01, VP-AF02-01 or any FL- id (#889).
293
+ *
294
+ * Category is everything between `VP-` and the final `-<sequence>` — INCLUDING hyphens, so
295
+ * compound categories (VP-LIST-DISPLAY-01, VP-ADD-TO-CART-03, VP-PRODUCT-DISCOVERY-02) parse,
296
+ * not just single-word ones. A single-word category (VP-CART-001) still works. (H1)
297
+ * Flows use journey-phase ids (FL-HP-001 / FL-ER-002) — the VP- anchor rejected them, so every
298
+ * flow scenario had NO category and the whole suite bucketed `other` (taxonomy=0%, #569).
299
+ * Segments may carry digits: the use-case framework numbers its flows (VP-AF02-01,
300
+ * VP-EF11-01 — one id per Alternate/Exception Flow), and `[A-Z]+` also silently truncated
301
+ * VP-I18N-001 to no category at all (the `18` broke the class mid-segment).
302
+ */
303
+ export function vpCodeOf(title: string): { vpCode?: string; category?: string } {
304
+ const m = title.match(/\b(?:VP|FL)-([A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*)-\d+/i);
305
+ return m ? { vpCode: m[0].toUpperCase(), category: m[1].toUpperCase() } : {};
306
+ }
307
+
288
308
  function classifyScenario(sc: ParsedScenario): ScenarioInfo {
289
309
  const tags = sc.tags || [];
290
310
  const deferredToFlow = tags.includes('@deferred:flow');
@@ -310,17 +330,7 @@ function classifyScenario(sc: ParsedScenario): ScenarioInfo {
310
330
  let priority: Priority = 'unknown';
311
331
  for (const t of tags) if (PRIORITY_TAGS[t]) priority = PRIORITY_TAGS[t];
312
332
 
313
- // Category is everything between `VP-` and the final `-<sequence>` — INCLUDING hyphens, so
314
- // compound categories (VP-LIST-DISPLAY-01, VP-ADD-TO-CART-03, VP-PRODUCT-DISCOVERY-02) parse,
315
- // not just single-word ones. A single-word category (VP-CART-001) still works. (H1)
316
- // Flows use journey-phase ids (FL-HP-001 / FL-ER-002) — the VP- anchor rejected them, so every
317
- // flow scenario had NO category and the whole suite bucketed `other` (taxonomy=0%, #569).
318
- // Segments may carry digits: the use-case framework numbers its flows (VP-AF02-01,
319
- // VP-EF11-01 — one id per Alternate/Exception Flow), and `[A-Z]+` also silently truncated
320
- // VP-I18N-001 to no category at all (the `18` broke the class mid-segment).
321
- const codeMatch = sc.name.match(/\b(?:VP|FL)-([A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*)-\d+/i);
322
- const vpCode = codeMatch ? codeMatch[0].toUpperCase() : undefined;
323
- const category = codeMatch ? codeMatch[1].toUpperCase() : undefined;
333
+ const { vpCode, category } = vpCodeOf(sc.name);
324
334
  // Project-scheme ID: the leading token of the title (VP0-001 / MS-HP-001 / VP-LIST-001).
325
335
  const leadMatch = sc.name.match(/^\s*([A-Za-z][A-Za-z0-9.-]*)/);
326
336
  const vpId = leadMatch && isIdLike(leadMatch[1]) ? leadMatch[1].toUpperCase() : undefined;
@@ -395,9 +405,26 @@ export function loadScenarios(featurePath: string): ScenarioInfo[] {
395
405
  const feature = parser.parseFeatureFile(featurePath);
396
406
  // Kept apart from `manual` so the audit's accounting is unchanged; only `select` reads it.
397
407
  const featureManual = (feature.tags || []).some((t: string) => /^@manual\b/i.test(t)) || undefined;
408
+ // A derived `@proposed` scenario (sungen contract derive, DOS-14.8) is not counted until QA approves it;
409
+ // an approved `@free` / `@impl:code` one IS counted, but never compiled (`handWritten`).
410
+ const tagsOf = (s: { tags?: string[] }): string[] => [...(feature.tags || []), ...(s.tags || [])];
398
411
  return (feature.scenarios || [])
399
- .filter((s) => !s.stepsName && !s.hookType) // skip @steps/@hook blocks
400
- .map((s) => ({ ...classifyScenario(withBackground(s, feature.background)), sourceFile: featurePath, featureManual }));
412
+ .filter((s) => !s.stepsName && !s.hookType && !tagsOf(s).some((t) => PROPOSED_TAG.test(t))) // skip @steps/@hook blocks and unapproved proposals
413
+ .map((s) => ({
414
+ ...classifyScenario(withBackground(s, feature.background)), sourceFile: featurePath, featureManual,
415
+ handWritten: isHandWritten(tagsOf(s), featurePath) || undefined,
416
+ }));
417
+ }
418
+
419
+ const PROPOSED_TAG = /^@proposed$/i;
420
+
421
+ /**
422
+ * Is a scenario implemented by HAND-WRITTEN code rather than compiled (DOS-14.2, 14.8)? `@free`,
423
+ * `@impl:code`, a derived `@proposed`, or anything in a derived `*.free.feature`. The one predicate
424
+ * codegen (never compiles these), script-check (never expects a compiled twin) and the harness share.
425
+ */
426
+ export function isHandWritten(tags: readonly string[], featureFile?: string): boolean {
427
+ return (!!featureFile && featureFile.endsWith('.free.feature')) || tags.some((t) => /^@(?:free|impl:code|proposed)$/i.test(t));
401
428
  }
402
429
 
403
430
  /**
@@ -1,22 +1,110 @@
1
1
  /**
2
- * Provenance stamp for deterministic reports (score-determinism D1).
2
+ * Provenance stamp for deterministic reports (score-determinism D1), and the RULES the audit's
3
+ * verdict was judged by (#933, owner decision W4).
3
4
  *
4
- * The audit score is a pure function of the project files + the bundled catalog.
5
- * Stamping the sungen version + a catalog hash into the report lets two users who
6
- * get different scores see IMMEDIATELY whether the cause is a version/catalog
7
- * mismatch (the main residual source of cross-user variance) rather than a real
8
- * difference in their test design.
5
+ * The audit score is a pure function of the project files + the bundled catalogs + the scoring
6
+ * code. Stamping them into the report lets two users who get different scores see IMMEDIATELY
7
+ * whether the cause is a rules mismatch rather than a real difference in their test design — and
8
+ * lets `verifyAuditReport` tell a report judged by today's rules from one judged by other rules:
9
+ *
10
+ * sungenVersion which package wrote it — informational: a newer sungen with the same rules
11
+ * gives the same verdict, so the version alone never makes a report stale
12
+ * catalogHash sha256(universal-viewpoints.yaml), first 12 hex — the viewpoint catalog
13
+ * rulesHash sha256(AUDIT_RULES_VERSION + every catalog file under harness/catalog/ + each
14
+ * bundled driver's sources/catalogs), first 12 hex — everything the verdict
15
+ * depends on that is not the project's own files. No package VERSION is hashed:
16
+ * packages are lockstep-versioned, so a release would stale every report
9
17
  */
10
18
  import * as fs from 'fs';
11
19
  import * as path from 'path';
12
20
  import * as crypto from 'crypto';
13
21
 
22
+ /**
23
+ * The version of the audit's SCORING CODE. Bump it (by one) in the same change whenever what
24
+ * `runAudit` computes for the same project can change: a sensor, a threshold, a gate term
25
+ * (audit-gate-terms.ts), the score model or weights, a finding that feeds the verdict, or the
26
+ * audit sensor of a bundled driver. Every report scored before the bump then reads stale and asks
27
+ * for one `sungen audit`. Catalog edits (harness/catalog/*.yaml) and bundled-driver changes (their
28
+ * sources and catalogs are hashed) need no bump.
29
+ * A release that changes none of these keeps every report trusted across the upgrade.
30
+ * Enforced by tests/audit/run.ts: its rules lock (tests/audit/audit-rules.lock.json) fails when the
31
+ * fixtures' audit output changes under an unchanged rules hash. After the bump, re-record it:
32
+ * npx tsx tests/audit/run.ts --record-rules-lock
33
+ */
34
+ export const AUDIT_RULES_VERSION = 1;
35
+
14
36
  export interface Provenance {
15
37
  sungenVersion: string;
16
38
  catalogHash: string; // sha256(universal-viewpoints.yaml), first 12 hex — the catalog that drives the score
39
+ rulesHash: string; // sha256(AUDIT_RULES_VERSION + harness/catalog/*.yaml + bundled drivers), first 12 hex — the verdict's rules
40
+ }
41
+
42
+ /** A bundled driver as an input of the rules: its package dir, or null when it is not installed. */
43
+ export interface DriverRulesInput { name: string; version?: string; dir: string | null }
44
+
45
+ /** What is not a driver's rule: dependencies, build output, tests, docs, editor and lock files. */
46
+ const SKIP_DIR = new Set(['node_modules', 'dist', 'tests', 'test', 'coverage']);
47
+ const SKIP_FILE = /^(?:\.|package(?:-lock)?\.json$|tsconfig.*\.json$|.*\.(?:md|tsbuildinfo)$)/;
48
+
49
+ function driverFiles(root: string, rel = ''): string[] {
50
+ const out: string[] = [];
51
+ for (const e of fs.readdirSync(path.join(root, rel), { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name, 'en'))) {
52
+ if (e.name.startsWith('.')) continue;
53
+ const r = rel ? `${rel}/${e.name}` : e.name;
54
+ if (e.isDirectory()) { if (!SKIP_DIR.has(e.name)) out.push(...driverFiles(root, r)); }
55
+ else if (e.isFile() && !SKIP_FILE.test(e.name)) out.push(r);
56
+ }
57
+ return out;
58
+ }
59
+
60
+ /** The package root above a driver's resolved entry file (the dir whose package.json names it). */
61
+ function packageRootOf(entry: string, name: string): string | null {
62
+ let dir = path.dirname(entry);
63
+ for (let i = 0; i < 8; i++) {
64
+ try { if (JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'))?.name === name) return dir; } catch { /* keep walking */ }
65
+ const parent = path.dirname(dir);
66
+ if (parent === dir) break;
67
+ dir = parent;
68
+ }
69
+ return null;
17
70
  }
18
71
 
72
+ /** Each bundled driver as discovery would load it (project anchor, then core's), or `absent`. */
73
+ export function bundledDriverRulesInputs(): DriverRulesInput[] {
74
+ // Lazy: discovery pulls the capability registry, which nothing else here needs.
75
+ const { bundledDriverNames, resolveDriverCopy } = require('../capabilities/discover') as typeof import('../capabilities/discover');
76
+ return bundledDriverNames().map((name) => {
77
+ const copy = resolveDriverCopy(name);
78
+ const dir = copy ? packageRootOf(copy.resolved, name) : null;
79
+ return { name, version: copy?.version, dir };
80
+ });
81
+ }
82
+
83
+ const CATALOG_DIR = path.join(__dirname, 'catalog');
84
+ const sha12 = (s: string | Buffer): string => crypto.createHash('sha256').update(s).digest('hex').slice(0, 12);
85
+
86
+ /**
87
+ * The rules hash: the scoring version, every *.yaml of the catalog dir (by name), and each bundled
88
+ * driver — every source / catalog file of its package (by relative path; build output, tests and
89
+ * dependencies excluded), or a stable `absent` marker when it is not installed. A driver's version is
90
+ * deliberately left out: releases bump every package in lockstep, and only content changes the rules.
91
+ */
92
+ export function rulesHashOf(rulesVersion: number, catalogDir: string = CATALOG_DIR, drivers: DriverRulesInput[] = bundledDriverRulesInputs()): string {
93
+ const files = fs.readdirSync(catalogDir).filter((f) => f.endsWith('.yaml')).sort();
94
+ const h = crypto.createHash('sha256').update(`audit-rules:${rulesVersion}\n`);
95
+ for (const f of files) h.update(`${f}\n`).update(fs.readFileSync(path.join(catalogDir, f))).update('\n');
96
+ for (const d of [...drivers].sort((a, b) => a.name.localeCompare(b.name, 'en'))) {
97
+ h.update(`driver:${d.name}\n`);
98
+ if (!d.dir) { h.update('absent\n'); continue; }
99
+ for (const f of driverFiles(d.dir)) h.update(`${f}\n`).update(fs.readFileSync(path.join(d.dir, f))).update('\n');
100
+ }
101
+ return h.digest('hex').slice(0, 12);
102
+ }
103
+
104
+ let cached: Provenance | null = null;
105
+
19
106
  export function getProvenance(): Provenance {
107
+ if (cached) return cached;
20
108
  let sungenVersion = 'unknown';
21
109
  try {
22
110
  const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'package.json'), 'utf-8'));
@@ -24,10 +112,10 @@ export function getProvenance(): Provenance {
24
112
  } catch { /* version stays 'unknown' */ }
25
113
 
26
114
  let catalogHash = 'unknown';
27
- try {
28
- const cat = fs.readFileSync(path.join(__dirname, 'catalog', 'universal-viewpoints.yaml'), 'utf-8');
29
- catalogHash = crypto.createHash('sha256').update(cat).digest('hex').slice(0, 12);
30
- } catch { /* hash stays 'unknown' */ }
115
+ try { catalogHash = sha12(fs.readFileSync(path.join(CATALOG_DIR, 'universal-viewpoints.yaml'), 'utf-8')); } catch { /* hash stays 'unknown' */ }
116
+ let rulesHash = 'unknown';
117
+ try { rulesHash = rulesHashOf(AUDIT_RULES_VERSION); } catch { /* hash stays 'unknown' */ }
31
118
 
32
- return { sungenVersion, catalogHash };
119
+ cached = { sungenVersion, catalogHash, rulesHash };
120
+ return cached;
33
121
  }
@@ -18,6 +18,8 @@ import * as os from 'os';
18
18
  import { loadUnitScenarios, ScenarioInfo } from './parse';
19
19
  import { featureFilesFor } from './unit-paths';
20
20
  import { readTextFile } from './read-text';
21
+ import { CATALOG_GATE_RULES } from './gates/resolve-rule';
22
+ import { evaluateGateTerms } from './gates/gate-terms';
21
23
 
22
24
  export interface ScriptCheckResult {
23
25
  screen: string;
@@ -107,6 +109,12 @@ const ASSERTION_STEP_COMMENT = /^\s*\/\/\s*Assert\b/;
107
109
  // but as a bare substring it would also exempt a genuinely hollow step whose test-data or step
108
110
  // text happened to contain it.
109
111
  const NOOP_STEP_MARKER = /^\s*\/\/\s*App launched via wdio capabilities/;
112
+ // The same kind of step on the web adapter, where the explanation IS the step comment: the
113
+ // step-mapper compiles `Given User is on [Edit] dialog` (and its exit) to `// Enter dialog scope:
114
+ // Edit` and no code, because it only re-roots the steps after it — the next assertion runs as
115
+ // `page.getByRole('dialog', …).getByRole(…)`. A field unit reported 13 BYPASS, every one of them
116
+ // this comment, and exited 2 on a correct suite (#881). Anchored to the whole marker line.
117
+ const SCOPE_STEP_MARKER = /^\s*\/\/\s*(?:Enter|Exit) dialog scope(?::\s*.*)?$/;
110
118
 
111
119
  /** A spec comment line reduced to its text, for comparison against a compiler step comment. */
112
120
  const commentText = (line: string): string => line.trim().replace(/^\/\/\s?/, '').trim();
@@ -241,7 +249,7 @@ export function analyzeFaithfulness(
241
249
  const hasCode = region.some((l) => !isComment(l) && CODE_LINE.test(l));
242
250
  // A documented no-op emits its explanation INTO the step's region, so read the region
243
251
  // (not just the marker line) for it — see NOOP_STEP_MARKER.
244
- if (hasCode || region.some((l) => NOOP_STEP_MARKER.test(l))) continue;
252
+ if (hasCode || region.some((l) => NOOP_STEP_MARKER.test(l)) || SCOPE_STEP_MARKER.test(body[markers[s]])) continue;
245
253
  if (tailAmbiguous && s === markers.length - 1) continue;
246
254
  hollowSteps.push({ test: title, step: body[markers[s]].trim().slice(0, 70) });
247
255
  }
@@ -334,7 +342,8 @@ function findSpecs(dir: string, name: string, kind: UnitKind): string[] {
334
342
  export async function runScriptCheck(screenDir: string, screenName: string, kind: UnitKind): Promise<ScriptCheckResult> {
335
343
  const featureFiles = featureFilesFor(screenDir, screenName);
336
344
  const scenarios = loadUnitScenarios(screenDir, screenName);
337
- const automated = scenarios.filter((s) => !s.manual);
345
+ // Hand-written (@free / @impl:code) scenarios are proven by their traces, not compiled — no twin expected.
346
+ const automated = scenarios.filter((s) => !s.manual && !s.handWritten);
338
347
  const manual = scenarios.filter((s) => s.manual);
339
348
 
340
349
  const committedSpecs = findSpecs(path.join(process.cwd(), 'specs', 'generated'), screenName, kind);
@@ -382,9 +391,10 @@ export async function runScriptCheck(screenDir: string, screenName: string, kind
382
391
  // failed regenerate degrades check C to its heuristic instead of crashing it.
383
392
  let stepTrace: Map<string, string[]> | undefined;
384
393
  if (committedSpec) {
394
+ let tmp: string | undefined;
385
395
  try {
386
396
  const { CodeGenerator } = require('../generators/test-generator/code-generator');
387
- const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'sungen-scriptcheck-'));
397
+ tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'sungen-scriptcheck-'));
388
398
  const qaSourceDir = path.join(process.cwd(), 'qa', kind === 'flow' ? 'flows' : kind === 'api' ? 'api' : 'screens');
389
399
  // api units derive their unit id (api/<area>) from the feature path — like `generate --api`;
390
400
  // screen/flow pass screenName + flowMode explicitly (unchanged → byte-identical regenerate).
@@ -422,9 +432,11 @@ export async function runScriptCheck(screenDir: string, screenName: string, kind
422
432
  if (drift === 'drift') {
423
433
  findings.push('DRIFT: committed spec differs from a fresh regenerate → spec was hand-edited or the .feature changed without `sungen generate`. The test code no longer reflects the Gherkin.');
424
434
  }
425
- fs.rmSync(tmp, { recursive: true, force: true });
426
435
  } catch (e) {
427
436
  findings.push(`Drift check skipped (regenerate failed): ${e instanceof Error ? e.message : e}`);
437
+ } finally {
438
+ // Removed on every path: a throwing regenerate used to leave one sungen-scriptcheck-* dir per call.
439
+ if (tmp) fs.rmSync(tmp, { recursive: true, force: true });
428
440
  }
429
441
  }
430
442
 
@@ -440,7 +452,16 @@ export async function runScriptCheck(screenDir: string, screenName: string, kind
440
452
  }
441
453
  const bypass = assertionlessTests.length > 0 || hollowSteps.length > 0;
442
454
 
443
- const ok = !!committedSpec && countMatch && missingInSpec.length === 0 && extraInSpec.length === 0 && drift === 'in-sync' && !bypass;
455
+ // Every term is a hard rule (the #387 drift family): no gate-override can lower one, so the
456
+ // catalog alone decides (OES-11.3).
457
+ const faithful = evaluateGateTerms([
458
+ { rule: 'script.no-spec', holds: !!committedSpec },
459
+ { rule: 'script.count-mismatch', holds: countMatch },
460
+ { rule: 'script.missing-in-spec', holds: missingInSpec.length === 0 },
461
+ { rule: 'script.extra-in-spec', holds: extraInSpec.length === 0 },
462
+ { rule: 'script.drift', holds: drift === 'in-sync' },
463
+ { rule: 'script.bypass', holds: !bypass },
464
+ ], CATALOG_GATE_RULES);
444
465
 
445
466
  return {
446
467
  screen: screenName,
@@ -456,7 +477,7 @@ export async function runScriptCheck(screenDir: string, screenName: string, kind
456
477
  assertionlessTests,
457
478
  hollowSteps,
458
479
  bypass,
459
- status: ok ? 'OK' : 'FAIL',
480
+ status: faithful.pass ? 'OK' : 'FAIL',
460
481
  findings,
461
482
  };
462
483
  }