@sun-asterisk/sungen 3.2.35 → 3.3.0-alpha.10

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 (969) 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/case-triage-hint.d.ts +14 -0
  41. package/dist/cli/case-triage-hint.d.ts.map +1 -0
  42. package/dist/cli/case-triage-hint.js +23 -0
  43. package/dist/cli/case-triage-hint.js.map +1 -0
  44. package/dist/cli/commands/audit.js +1 -1
  45. package/dist/cli/commands/audit.js.map +1 -1
  46. package/dist/cli/commands/capability.js +1 -1
  47. package/dist/cli/commands/capability.js.map +1 -1
  48. package/dist/cli/commands/contract-derive-command.d.ts +12 -0
  49. package/dist/cli/commands/contract-derive-command.d.ts.map +1 -0
  50. package/dist/cli/commands/contract-derive-command.js +113 -0
  51. package/dist/cli/commands/contract-derive-command.js.map +1 -0
  52. package/dist/cli/commands/contract.d.ts +20 -0
  53. package/dist/cli/commands/contract.d.ts.map +1 -0
  54. package/dist/cli/commands/contract.js +195 -0
  55. package/dist/cli/commands/contract.js.map +1 -0
  56. package/dist/cli/commands/delivery.d.ts.map +1 -1
  57. package/dist/cli/commands/delivery.js +109 -19
  58. package/dist/cli/commands/delivery.js.map +1 -1
  59. package/dist/cli/commands/gate.d.ts.map +1 -1
  60. package/dist/cli/commands/gate.js +2 -1
  61. package/dist/cli/commands/gate.js.map +1 -1
  62. package/dist/cli/commands/generate.d.ts.map +1 -1
  63. package/dist/cli/commands/generate.js +17 -3
  64. package/dist/cli/commands/generate.js.map +1 -1
  65. package/dist/cli/commands/journey.d.ts.map +1 -1
  66. package/dist/cli/commands/journey.js +47 -17
  67. package/dist/cli/commands/journey.js.map +1 -1
  68. package/dist/cli/commands/next.d.ts +13 -0
  69. package/dist/cli/commands/next.d.ts.map +1 -1
  70. package/dist/cli/commands/next.js +98 -9
  71. package/dist/cli/commands/next.js.map +1 -1
  72. package/dist/cli/commands/triage.d.ts +2 -1
  73. package/dist/cli/commands/triage.d.ts.map +1 -1
  74. package/dist/cli/commands/triage.js +45 -3
  75. package/dist/cli/commands/triage.js.map +1 -1
  76. package/dist/cli/commands/update.d.ts +11 -0
  77. package/dist/cli/commands/update.d.ts.map +1 -1
  78. package/dist/cli/commands/update.js +37 -8
  79. package/dist/cli/commands/update.js.map +1 -1
  80. package/dist/cli/index.js +24 -33
  81. package/dist/cli/index.js.map +1 -1
  82. package/dist/cli/json-error-on-exit.d.ts +34 -0
  83. package/dist/cli/json-error-on-exit.d.ts.map +1 -0
  84. package/dist/cli/json-error-on-exit.js +63 -0
  85. package/dist/cli/json-error-on-exit.js.map +1 -0
  86. package/dist/cli/project-sungen-invocation.d.ts +13 -0
  87. package/dist/cli/project-sungen-invocation.d.ts.map +1 -0
  88. package/dist/cli/project-sungen-invocation.js +95 -0
  89. package/dist/cli/project-sungen-invocation.js.map +1 -0
  90. package/dist/cli/run-command-hints.d.ts +9 -0
  91. package/dist/cli/run-command-hints.d.ts.map +1 -0
  92. package/dist/cli/run-command-hints.js +84 -0
  93. package/dist/cli/run-command-hints.js.map +1 -0
  94. package/dist/cli/waiting-for-you-block.d.ts +18 -0
  95. package/dist/cli/waiting-for-you-block.d.ts.map +1 -0
  96. package/dist/cli/waiting-for-you-block.js +22 -0
  97. package/dist/cli/waiting-for-you-block.js.map +1 -0
  98. package/dist/contract/accept-opaque-steps.d.ts +3 -0
  99. package/dist/contract/accept-opaque-steps.d.ts.map +1 -0
  100. package/dist/contract/accept-opaque-steps.js +114 -0
  101. package/dist/contract/accept-opaque-steps.js.map +1 -0
  102. package/dist/contract/approve-contract.d.ts +38 -0
  103. package/dist/contract/approve-contract.d.ts.map +1 -0
  104. package/dist/contract/approve-contract.js +93 -0
  105. package/dist/contract/approve-contract.js.map +1 -0
  106. package/dist/contract/assertion-matcher-vocabulary.d.ts +24 -0
  107. package/dist/contract/assertion-matcher-vocabulary.d.ts.map +1 -0
  108. package/dist/contract/assertion-matcher-vocabulary.js +100 -0
  109. package/dist/contract/assertion-matcher-vocabulary.js.map +1 -0
  110. package/dist/contract/build-contract-verdict.d.ts +32 -0
  111. package/dist/contract/build-contract-verdict.d.ts.map +1 -0
  112. package/dist/contract/build-contract-verdict.js +123 -0
  113. package/dist/contract/build-contract-verdict.js.map +1 -0
  114. package/dist/contract/build-trace-conformance.d.ts +22 -0
  115. package/dist/contract/build-trace-conformance.d.ts.map +1 -0
  116. package/dist/contract/build-trace-conformance.js +151 -0
  117. package/dist/contract/build-trace-conformance.js.map +1 -0
  118. package/dist/contract/classify-contract-change.d.ts +24 -0
  119. package/dist/contract/classify-contract-change.d.ts.map +1 -0
  120. package/dist/contract/classify-contract-change.js +98 -0
  121. package/dist/contract/classify-contract-change.js.map +1 -0
  122. package/dist/contract/classify-contract-unit.d.ts +18 -0
  123. package/dist/contract/classify-contract-unit.d.ts.map +1 -0
  124. package/dist/contract/classify-contract-unit.js +49 -0
  125. package/dist/contract/classify-contract-unit.js.map +1 -0
  126. package/dist/contract/classify-trace-conformance.d.ts +47 -0
  127. package/dist/contract/classify-trace-conformance.d.ts.map +1 -0
  128. package/dist/contract/classify-trace-conformance.js +164 -0
  129. package/dist/contract/classify-trace-conformance.js.map +1 -0
  130. package/dist/contract/contract-git.d.ts +24 -0
  131. package/dist/contract/contract-git.d.ts.map +1 -0
  132. package/dist/contract/contract-git.js +144 -0
  133. package/dist/contract/contract-git.js.map +1 -0
  134. package/dist/contract/contract-hash.d.ts +7 -0
  135. package/dist/contract/contract-hash.d.ts.map +1 -0
  136. package/dist/contract/contract-hash.js +38 -0
  137. package/dist/contract/contract-hash.js.map +1 -0
  138. package/dist/contract/contract-report-file.d.ts +4 -0
  139. package/dist/contract/contract-report-file.d.ts.map +1 -0
  140. package/dist/contract/contract-report-file.js +60 -0
  141. package/dist/contract/contract-report-file.js.map +1 -0
  142. package/dist/contract/contract-schema.d.ts +92 -0
  143. package/dist/contract/contract-schema.d.ts.map +1 -0
  144. package/dist/contract/contract-schema.js +124 -0
  145. package/dist/contract/contract-schema.js.map +1 -0
  146. package/dist/contract/contract-units.d.ts +12 -0
  147. package/dist/contract/contract-units.d.ts.map +1 -0
  148. package/dist/contract/contract-units.js +96 -0
  149. package/dist/contract/contract-units.js.map +1 -0
  150. package/dist/contract/contracts-lock-file.d.ts +24 -0
  151. package/dist/contract/contracts-lock-file.d.ts.map +1 -0
  152. package/dist/contract/contracts-lock-file.js +141 -0
  153. package/dist/contract/contracts-lock-file.js.map +1 -0
  154. package/dist/contract/data-normalize.d.ts +10 -0
  155. package/dist/contract/data-normalize.d.ts.map +1 -0
  156. package/dist/contract/data-normalize.js +110 -0
  157. package/dist/contract/data-normalize.js.map +1 -0
  158. package/dist/contract/derive-free-feature.d.ts +49 -0
  159. package/dist/contract/derive-free-feature.d.ts.map +1 -0
  160. package/dist/contract/derive-free-feature.js +183 -0
  161. package/dist/contract/derive-free-feature.js.map +1 -0
  162. package/dist/contract/field-semantic-redaction.d.ts +21 -0
  163. package/dist/contract/field-semantic-redaction.d.ts.map +1 -0
  164. package/dist/contract/field-semantic-redaction.js +118 -0
  165. package/dist/contract/field-semantic-redaction.js.map +1 -0
  166. package/dist/contract/free-feature-blocks.d.ts +10 -0
  167. package/dist/contract/free-feature-blocks.d.ts.map +1 -0
  168. package/dist/contract/free-feature-blocks.js +94 -0
  169. package/dist/contract/free-feature-blocks.js.map +1 -0
  170. package/dist/contract/lock-secret-guard.d.ts +22 -0
  171. package/dist/contract/lock-secret-guard.d.ts.map +1 -0
  172. package/dist/contract/lock-secret-guard.js +134 -0
  173. package/dist/contract/lock-secret-guard.js.map +1 -0
  174. package/dist/contract/lock-vs-git-head.d.ts +26 -0
  175. package/dist/contract/lock-vs-git-head.d.ts.map +1 -0
  176. package/dist/contract/lock-vs-git-head.js +28 -0
  177. package/dist/contract/lock-vs-git-head.js.map +1 -0
  178. package/dist/contract/normalize-contract-step.d.ts +21 -0
  179. package/dist/contract/normalize-contract-step.d.ts.map +1 -0
  180. package/dist/contract/normalize-contract-step.js +70 -0
  181. package/dist/contract/normalize-contract-step.js.map +1 -0
  182. package/dist/contract/normalize-feature-steps.d.ts +7 -0
  183. package/dist/contract/normalize-feature-steps.d.ts.map +1 -0
  184. package/dist/contract/normalize-feature-steps.js +127 -0
  185. package/dist/contract/normalize-feature-steps.js.map +1 -0
  186. package/dist/contract/oracle-strength.d.ts +12 -0
  187. package/dist/contract/oracle-strength.d.ts.map +1 -0
  188. package/dist/contract/oracle-strength.js +88 -0
  189. package/dist/contract/oracle-strength.js.map +1 -0
  190. package/dist/contract/project-contract-blockers.d.ts +10 -0
  191. package/dist/contract/project-contract-blockers.d.ts.map +1 -0
  192. package/dist/contract/project-contract-blockers.js +75 -0
  193. package/dist/contract/project-contract-blockers.js.map +1 -0
  194. package/dist/contract/record-contract-approval.d.ts +36 -0
  195. package/dist/contract/record-contract-approval.d.ts.map +1 -0
  196. package/dist/contract/record-contract-approval.js +126 -0
  197. package/dist/contract/record-contract-approval.js.map +1 -0
  198. package/dist/contract/render-free-gherkin.d.ts +42 -0
  199. package/dist/contract/render-free-gherkin.d.ts.map +1 -0
  200. package/dist/contract/render-free-gherkin.js +147 -0
  201. package/dist/contract/render-free-gherkin.js.map +1 -0
  202. package/dist/contract/render-trace-sentence.d.ts +20 -0
  203. package/dist/contract/render-trace-sentence.d.ts.map +1 -0
  204. package/dist/contract/render-trace-sentence.js +109 -0
  205. package/dist/contract/render-trace-sentence.js.map +1 -0
  206. package/dist/contract/render-trace-target.d.ts +14 -0
  207. package/dist/contract/render-trace-target.d.ts.map +1 -0
  208. package/dist/contract/render-trace-target.js +70 -0
  209. package/dist/contract/render-trace-target.js.map +1 -0
  210. package/dist/contract/resolve-unit-trace-identities.d.ts +20 -0
  211. package/dist/contract/resolve-unit-trace-identities.d.ts.map +1 -0
  212. package/dist/contract/resolve-unit-trace-identities.js +62 -0
  213. package/dist/contract/resolve-unit-trace-identities.js.map +1 -0
  214. package/dist/contract/trace/collect-trace-evidence.d.ts +44 -0
  215. package/dist/contract/trace/collect-trace-evidence.d.ts.map +1 -0
  216. package/dist/contract/trace/collect-trace-evidence.js +219 -0
  217. package/dist/contract/trace/collect-trace-evidence.js.map +1 -0
  218. package/dist/contract/trace/identity-cache.d.ts +19 -0
  219. package/dist/contract/trace/identity-cache.d.ts.map +1 -0
  220. package/dist/contract/trace/identity-cache.js +104 -0
  221. package/dist/contract/trace/identity-cache.js.map +1 -0
  222. package/dist/contract/trace/read-file-once.d.ts +20 -0
  223. package/dist/contract/trace/read-file-once.d.ts.map +1 -0
  224. package/dist/contract/trace/read-file-once.js +135 -0
  225. package/dist/contract/trace/read-file-once.js.map +1 -0
  226. package/dist/contract/trace/scenario-id-claims.d.ts +11 -0
  227. package/dist/contract/trace/scenario-id-claims.d.ts.map +1 -0
  228. package/dist/contract/trace/scenario-id-claims.js +89 -0
  229. package/dist/contract/trace/scenario-id-claims.js.map +1 -0
  230. package/dist/contract/trace/select-final-attempt.d.ts +29 -0
  231. package/dist/contract/trace/select-final-attempt.d.ts.map +1 -0
  232. package/dist/contract/trace/select-final-attempt.js +119 -0
  233. package/dist/contract/trace/select-final-attempt.js.map +1 -0
  234. package/dist/contract/trace/snapshot-html-renderer.d.ts +31 -0
  235. package/dist/contract/trace/snapshot-html-renderer.d.ts.map +1 -0
  236. package/dist/contract/trace/snapshot-html-renderer.js +172 -0
  237. package/dist/contract/trace/snapshot-html-renderer.js.map +1 -0
  238. package/dist/contract/trace/snapshot-resolver.d.ts +21 -0
  239. package/dist/contract/trace/snapshot-resolver.d.ts.map +1 -0
  240. package/dist/contract/trace/snapshot-resolver.js +65 -0
  241. package/dist/contract/trace/snapshot-resolver.js.map +1 -0
  242. package/dist/contract/trace/snapshot-store.d.ts +66 -0
  243. package/dist/contract/trace/snapshot-store.d.ts.map +1 -0
  244. package/dist/contract/trace/snapshot-store.js +173 -0
  245. package/dist/contract/trace/snapshot-store.js.map +1 -0
  246. package/dist/contract/trace/target-identity.d.ts +74 -0
  247. package/dist/contract/trace/target-identity.d.ts.map +1 -0
  248. package/dist/contract/trace/target-identity.js +68 -0
  249. package/dist/contract/trace/target-identity.js.map +1 -0
  250. package/dist/contract/trace/test-step-join.d.ts +65 -0
  251. package/dist/contract/trace/test-step-join.d.ts.map +1 -0
  252. package/dist/contract/trace/test-step-join.js +80 -0
  253. package/dist/contract/trace/test-step-join.js.map +1 -0
  254. package/dist/contract/trace/trace-binding.d.ts +22 -0
  255. package/dist/contract/trace/trace-binding.d.ts.map +1 -0
  256. package/dist/contract/trace/trace-binding.js +91 -0
  257. package/dist/contract/trace/trace-binding.js.map +1 -0
  258. package/dist/contract/trace/trace-file-reader.d.ts +47 -0
  259. package/dist/contract/trace/trace-file-reader.d.ts.map +1 -0
  260. package/dist/contract/trace/trace-file-reader.js +137 -0
  261. package/dist/contract/trace/trace-file-reader.js.map +1 -0
  262. package/dist/contract/trace/trace-fingerprint.d.ts +22 -0
  263. package/dist/contract/trace/trace-fingerprint.d.ts.map +1 -0
  264. package/dist/contract/trace/trace-fingerprint.js +96 -0
  265. package/dist/contract/trace/trace-fingerprint.js.map +1 -0
  266. package/dist/contract/trace/trace-freshness.d.ts +27 -0
  267. package/dist/contract/trace/trace-freshness.d.ts.map +1 -0
  268. package/dist/contract/trace/trace-freshness.js +146 -0
  269. package/dist/contract/trace/trace-freshness.js.map +1 -0
  270. package/dist/contract/trace/trace-identity-resolution.d.ts +28 -0
  271. package/dist/contract/trace/trace-identity-resolution.d.ts.map +1 -0
  272. package/dist/contract/trace/trace-identity-resolution.js +87 -0
  273. package/dist/contract/trace/trace-identity-resolution.js.map +1 -0
  274. package/dist/contract/trace/trace-run-record.d.ts +32 -0
  275. package/dist/contract/trace/trace-run-record.d.ts.map +1 -0
  276. package/dist/contract/trace/trace-run-record.js +135 -0
  277. package/dist/contract/trace/trace-run-record.js.map +1 -0
  278. package/dist/contract/trace/trace-steps.d.ts +19 -0
  279. package/dist/contract/trace/trace-steps.d.ts.map +1 -0
  280. package/dist/contract/trace/trace-steps.js +79 -0
  281. package/dist/contract/trace/trace-steps.js.map +1 -0
  282. package/dist/contract/trace/trace-zip-limits.d.ts +45 -0
  283. package/dist/contract/trace/trace-zip-limits.d.ts.map +1 -0
  284. package/dist/contract/trace/trace-zip-limits.js +52 -0
  285. package/dist/contract/trace/trace-zip-limits.js.map +1 -0
  286. package/dist/contract/trace/trace-zip-reader.d.ts +10 -0
  287. package/dist/contract/trace/trace-zip-reader.d.ts.map +1 -0
  288. package/dist/contract/trace/trace-zip-reader.js +186 -0
  289. package/dist/contract/trace/trace-zip-reader.js.map +1 -0
  290. package/dist/contract/verify-approval-decisions.d.ts +5 -0
  291. package/dist/contract/verify-approval-decisions.d.ts.map +1 -0
  292. package/dist/contract/verify-approval-decisions.js +109 -0
  293. package/dist/contract/verify-approval-decisions.js.map +1 -0
  294. package/dist/decisions/append-decision.d.ts +12 -0
  295. package/dist/decisions/append-decision.d.ts.map +1 -0
  296. package/dist/decisions/append-decision.js +73 -0
  297. package/dist/decisions/append-decision.js.map +1 -0
  298. package/dist/decisions/confirmed-decision-commands.d.ts +41 -0
  299. package/dist/decisions/confirmed-decision-commands.d.ts.map +1 -0
  300. package/dist/decisions/confirmed-decision-commands.js +190 -0
  301. package/dist/decisions/confirmed-decision-commands.js.map +1 -0
  302. package/dist/decisions/decision-file.d.ts +31 -0
  303. package/dist/decisions/decision-file.d.ts.map +1 -0
  304. package/dist/decisions/decision-file.js +139 -0
  305. package/dist/decisions/decision-file.js.map +1 -0
  306. package/dist/decisions/decision-identity.d.ts +12 -0
  307. package/dist/decisions/decision-identity.d.ts.map +1 -0
  308. package/dist/decisions/decision-identity.js +78 -0
  309. package/dist/decisions/decision-identity.js.map +1 -0
  310. package/dist/decisions/decision-integrity-check.d.ts +12 -0
  311. package/dist/decisions/decision-integrity-check.d.ts.map +1 -0
  312. package/dist/decisions/decision-integrity-check.js +102 -0
  313. package/dist/decisions/decision-integrity-check.js.map +1 -0
  314. package/dist/decisions/decision-schema.d.ts +43 -0
  315. package/dist/decisions/decision-schema.d.ts.map +1 -0
  316. package/dist/decisions/decision-schema.js +76 -0
  317. package/dist/decisions/decision-schema.js.map +1 -0
  318. package/dist/decisions/decision-source.d.ts +2 -0
  319. package/dist/decisions/decision-source.d.ts.map +1 -0
  320. package/dist/decisions/decision-source.js +18 -0
  321. package/dist/decisions/decision-source.js.map +1 -0
  322. package/dist/decisions/exclusive-file-create.d.ts +3 -0
  323. package/dist/decisions/exclusive-file-create.d.ts.map +1 -0
  324. package/dist/decisions/exclusive-file-create.js +84 -0
  325. package/dist/decisions/exclusive-file-create.js.map +1 -0
  326. package/dist/decisions/git-head-trust.d.ts +19 -0
  327. package/dist/decisions/git-head-trust.d.ts.map +1 -0
  328. package/dist/decisions/git-head-trust.js +128 -0
  329. package/dist/decisions/git-head-trust.js.map +1 -0
  330. package/dist/decisions/human-confirmation.d.ts +35 -0
  331. package/dist/decisions/human-confirmation.d.ts.map +1 -0
  332. package/dist/decisions/human-confirmation.js +161 -0
  333. package/dist/decisions/human-confirmation.js.map +1 -0
  334. package/dist/decisions/legacy-waiver-migration.d.ts +38 -0
  335. package/dist/decisions/legacy-waiver-migration.d.ts.map +1 -0
  336. package/dist/decisions/legacy-waiver-migration.js +179 -0
  337. package/dist/decisions/legacy-waiver-migration.js.map +1 -0
  338. package/dist/decisions/read-decisions.d.ts +19 -0
  339. package/dist/decisions/read-decisions.d.ts.map +1 -0
  340. package/dist/decisions/read-decisions.js +90 -0
  341. package/dist/decisions/read-decisions.js.map +1 -0
  342. package/dist/decisions/viewpoint-baseline-adapter.d.ts +7 -0
  343. package/dist/decisions/viewpoint-baseline-adapter.d.ts.map +1 -0
  344. package/dist/decisions/viewpoint-baseline-adapter.js +109 -0
  345. package/dist/decisions/viewpoint-baseline-adapter.js.map +1 -0
  346. package/dist/decisions/waiver-decisions.d.ts +24 -0
  347. package/dist/decisions/waiver-decisions.d.ts.map +1 -0
  348. package/dist/decisions/waiver-decisions.js +46 -0
  349. package/dist/decisions/waiver-decisions.js.map +1 -0
  350. package/dist/exporters/csv-exporter.d.ts +11 -2
  351. package/dist/exporters/csv-exporter.d.ts.map +1 -1
  352. package/dist/exporters/csv-exporter.js +8 -4
  353. package/dist/exporters/csv-exporter.js.map +1 -1
  354. package/dist/exporters/matrix/build.d.ts +3 -0
  355. package/dist/exporters/matrix/build.d.ts.map +1 -1
  356. package/dist/exporters/matrix/build.js +10 -9
  357. package/dist/exporters/matrix/build.js.map +1 -1
  358. package/dist/exporters/matrix/export.d.ts +9 -1
  359. package/dist/exporters/matrix/export.d.ts.map +1 -1
  360. package/dist/exporters/matrix/export.js +13 -4
  361. package/dist/exporters/matrix/export.js.map +1 -1
  362. package/dist/exporters/matrix/gates.d.ts +6 -1
  363. package/dist/exporters/matrix/gates.d.ts.map +1 -1
  364. package/dist/exporters/matrix/gates.js +57 -128
  365. package/dist/exporters/matrix/gates.js.map +1 -1
  366. package/dist/exporters/matrix/render-csv.d.ts.map +1 -1
  367. package/dist/exporters/matrix/render-csv.js +3 -0
  368. package/dist/exporters/matrix/render-csv.js.map +1 -1
  369. package/dist/exporters/matrix/render-gate-overrides-sheet.d.ts +13 -0
  370. package/dist/exporters/matrix/render-gate-overrides-sheet.d.ts.map +1 -0
  371. package/dist/exporters/matrix/render-gate-overrides-sheet.js +44 -0
  372. package/dist/exporters/matrix/render-gate-overrides-sheet.js.map +1 -0
  373. package/dist/exporters/matrix/render-xlsx.d.ts +1 -0
  374. package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
  375. package/dist/exporters/matrix/render-xlsx.js +3 -0
  376. package/dist/exporters/matrix/render-xlsx.js.map +1 -1
  377. package/dist/exporters/matrix/types.d.ts +4 -1
  378. package/dist/exporters/matrix/types.d.ts.map +1 -1
  379. package/dist/exporters/matrix/types.js.map +1 -1
  380. package/dist/exporters/matrix/xlsx-cells.js +1 -1
  381. package/dist/exporters/matrix/xlsx-cells.js.map +1 -1
  382. package/dist/exporters/test-data-resolver.d.ts.map +1 -1
  383. package/dist/exporters/test-data-resolver.js +2 -12
  384. package/dist/exporters/test-data-resolver.js.map +1 -1
  385. package/dist/exporters/xlsx-exporter.d.ts +3 -2
  386. package/dist/exporters/xlsx-exporter.d.ts.map +1 -1
  387. package/dist/exporters/xlsx-exporter.js +4 -4
  388. package/dist/exporters/xlsx-exporter.js.map +1 -1
  389. package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
  390. package/dist/generators/gherkin-parser/index.js +0 -1
  391. package/dist/generators/gherkin-parser/index.js.map +1 -1
  392. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/contain-text-assertion.hbs +1 -2
  393. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -13
  394. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -9
  395. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  396. package/dist/generators/test-generator/code-generator.js +18 -4
  397. package/dist/generators/test-generator/code-generator.js.map +1 -1
  398. package/dist/generators/test-generator/diagnostics.d.ts +3 -9
  399. package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
  400. package/dist/generators/test-generator/diagnostics.js +3 -9
  401. package/dist/generators/test-generator/diagnostics.js.map +1 -1
  402. package/dist/generators/test-generator/patterns/types.d.ts +1 -1
  403. package/dist/generators/test-generator/patterns/types.d.ts.map +1 -1
  404. package/dist/generators/test-generator/step-mapper.d.ts +0 -8
  405. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  406. package/dist/generators/test-generator/step-mapper.js +8 -52
  407. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  408. package/dist/generators/test-generator/utils/data-resolver.d.ts +0 -16
  409. package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
  410. package/dist/generators/test-generator/utils/data-resolver.js +0 -59
  411. package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
  412. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  413. package/dist/generators/test-generator/utils/selector-resolver.js +2 -10
  414. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  415. package/dist/graph/board-human-actions.d.ts +5 -0
  416. package/dist/graph/board-human-actions.d.ts.map +1 -0
  417. package/dist/graph/board-human-actions.js +83 -0
  418. package/dist/graph/board-human-actions.js.map +1 -0
  419. package/dist/graph/evaluate-graph.d.ts +41 -0
  420. package/dist/graph/evaluate-graph.d.ts.map +1 -0
  421. package/dist/graph/evaluate-graph.js +77 -0
  422. package/dist/graph/evaluate-graph.js.map +1 -0
  423. package/dist/graph/human-action.d.ts +21 -0
  424. package/dist/graph/human-action.d.ts.map +1 -0
  425. package/dist/graph/human-action.js +3 -0
  426. package/dist/graph/human-action.js.map +1 -0
  427. package/dist/graph/locate-finding.d.ts +20 -0
  428. package/dist/graph/locate-finding.d.ts.map +1 -0
  429. package/dist/graph/locate-finding.js +137 -0
  430. package/dist/graph/locate-finding.js.map +1 -0
  431. package/dist/graph/manual-triage-decisions.d.ts +19 -0
  432. package/dist/graph/manual-triage-decisions.d.ts.map +1 -0
  433. package/dist/graph/manual-triage-decisions.js +53 -0
  434. package/dist/graph/manual-triage-decisions.js.map +1 -0
  435. package/dist/graph/node-decl.d.ts +75 -0
  436. package/dist/graph/node-decl.d.ts.map +1 -0
  437. package/dist/graph/node-decl.js +11 -0
  438. package/dist/graph/node-decl.js.map +1 -0
  439. package/dist/graph/nodes/core-node-catalog.d.ts +7 -0
  440. package/dist/graph/nodes/core-node-catalog.d.ts.map +1 -0
  441. package/dist/graph/nodes/core-node-catalog.js +13 -0
  442. package/dist/graph/nodes/core-node-catalog.js.map +1 -0
  443. package/dist/graph/nodes/test-case-contract-nodes.d.ts +21 -0
  444. package/dist/graph/nodes/test-case-contract-nodes.d.ts.map +1 -0
  445. package/dist/graph/nodes/test-case-contract-nodes.js +72 -0
  446. package/dist/graph/nodes/test-case-contract-nodes.js.map +1 -0
  447. package/dist/graph/nodes/test-case-nodes.d.ts +29 -0
  448. package/dist/graph/nodes/test-case-nodes.d.ts.map +1 -0
  449. package/dist/graph/nodes/test-case-nodes.js +95 -0
  450. package/dist/graph/nodes/test-case-nodes.js.map +1 -0
  451. package/dist/graph/nodes/unit-audit-nodes.d.ts +18 -0
  452. package/dist/graph/nodes/unit-audit-nodes.d.ts.map +1 -0
  453. package/dist/graph/nodes/unit-audit-nodes.js +96 -0
  454. package/dist/graph/nodes/unit-audit-nodes.js.map +1 -0
  455. package/dist/graph/nodes/unit-contract-node.d.ts +21 -0
  456. package/dist/graph/nodes/unit-contract-node.d.ts.map +1 -0
  457. package/dist/graph/nodes/unit-contract-node.js +96 -0
  458. package/dist/graph/nodes/unit-contract-node.js.map +1 -0
  459. package/dist/graph/nodes/unit-design-nodes.d.ts +14 -0
  460. package/dist/graph/nodes/unit-design-nodes.d.ts.map +1 -0
  461. package/dist/graph/nodes/unit-design-nodes.js +91 -0
  462. package/dist/graph/nodes/unit-design-nodes.js.map +1 -0
  463. package/dist/graph/nodes/unit-execution-nodes.d.ts +16 -0
  464. package/dist/graph/nodes/unit-execution-nodes.d.ts.map +1 -0
  465. package/dist/graph/nodes/unit-execution-nodes.js +79 -0
  466. package/dist/graph/nodes/unit-execution-nodes.js.map +1 -0
  467. package/dist/graph/test-case-identity.d.ts +13 -0
  468. package/dist/graph/test-case-identity.d.ts.map +1 -0
  469. package/dist/graph/test-case-identity.js +106 -0
  470. package/dist/graph/test-case-identity.js.map +1 -0
  471. package/dist/graph/test-case-results.d.ts +12 -0
  472. package/dist/graph/test-case-results.d.ts.map +1 -0
  473. package/dist/graph/test-case-results.js +161 -0
  474. package/dist/graph/test-case-results.js.map +1 -0
  475. package/dist/graph/test-case-satisfied.d.ts +26 -0
  476. package/dist/graph/test-case-satisfied.d.ts.map +1 -0
  477. package/dist/graph/test-case-satisfied.js +55 -0
  478. package/dist/graph/test-case-satisfied.js.map +1 -0
  479. package/dist/graph/test-case-state-shape.d.ts +73 -0
  480. package/dist/graph/test-case-state-shape.d.ts.map +1 -0
  481. package/dist/graph/test-case-state-shape.js +3 -0
  482. package/dist/graph/test-case-state-shape.js.map +1 -0
  483. package/dist/graph/test-case-states.d.ts +9 -0
  484. package/dist/graph/test-case-states.d.ts.map +1 -0
  485. package/dist/graph/test-case-states.js +116 -0
  486. package/dist/graph/test-case-states.js.map +1 -0
  487. package/dist/graph/unit-artifact-probes.d.ts +19 -0
  488. package/dist/graph/unit-artifact-probes.d.ts.map +1 -0
  489. package/dist/graph/unit-artifact-probes.js +135 -0
  490. package/dist/graph/unit-artifact-probes.js.map +1 -0
  491. package/dist/graph/unit-results-freshness.d.ts +29 -0
  492. package/dist/graph/unit-results-freshness.d.ts.map +1 -0
  493. package/dist/graph/unit-results-freshness.js +213 -0
  494. package/dist/graph/unit-results-freshness.js.map +1 -0
  495. package/dist/graph/unit-state-facts.d.ts +43 -0
  496. package/dist/graph/unit-state-facts.d.ts.map +1 -0
  497. package/dist/graph/unit-state-facts.js +87 -0
  498. package/dist/graph/unit-state-facts.js.map +1 -0
  499. package/dist/harness/audit.d.ts +14 -2
  500. package/dist/harness/audit.d.ts.map +1 -1
  501. package/dist/harness/audit.js +20 -21
  502. package/dist/harness/audit.js.map +1 -1
  503. package/dist/harness/catalog/gate-rules.yaml +647 -0
  504. package/dist/harness/defect-draft.d.ts.map +1 -1
  505. package/dist/harness/defect-draft.js +12 -2
  506. package/dist/harness/defect-draft.js.map +1 -1
  507. package/dist/harness/defects.d.ts +14 -0
  508. package/dist/harness/defects.d.ts.map +1 -1
  509. package/dist/harness/defects.js +14 -10
  510. package/dist/harness/defects.js.map +1 -1
  511. package/dist/harness/flow-check.d.ts +9 -0
  512. package/dist/harness/flow-check.d.ts.map +1 -1
  513. package/dist/harness/flow-check.js +11 -0
  514. package/dist/harness/flow-check.js.map +1 -1
  515. package/dist/harness/gates/audit-gate-terms.d.ts +41 -0
  516. package/dist/harness/gates/audit-gate-terms.d.ts.map +1 -0
  517. package/dist/harness/gates/audit-gate-terms.js +72 -0
  518. package/dist/harness/gates/audit-gate-terms.js.map +1 -0
  519. package/dist/harness/gates/audit-gate-verdict.d.ts +31 -0
  520. package/dist/harness/gates/audit-gate-verdict.d.ts.map +1 -0
  521. package/dist/harness/gates/audit-gate-verdict.js +102 -0
  522. package/dist/harness/gates/audit-gate-verdict.js.map +1 -0
  523. package/dist/harness/gates/audit-input-hash.d.ts +6 -0
  524. package/dist/harness/gates/audit-input-hash.d.ts.map +1 -0
  525. package/dist/harness/gates/audit-input-hash.js +124 -0
  526. package/dist/harness/gates/audit-input-hash.js.map +1 -0
  527. package/dist/harness/gates/audit-report-verification.d.ts +43 -0
  528. package/dist/harness/gates/audit-report-verification.d.ts.map +1 -0
  529. package/dist/harness/gates/audit-report-verification.js +241 -0
  530. package/dist/harness/gates/audit-report-verification.js.map +1 -0
  531. package/dist/harness/gates/decisions-hash.d.ts +13 -0
  532. package/dist/harness/gates/decisions-hash.d.ts.map +1 -0
  533. package/dist/harness/gates/decisions-hash.js +72 -0
  534. package/dist/harness/gates/decisions-hash.js.map +1 -0
  535. package/dist/harness/gates/delivery-checklist.d.ts +24 -0
  536. package/dist/harness/gates/delivery-checklist.d.ts.map +1 -0
  537. package/dist/harness/gates/delivery-checklist.js +161 -0
  538. package/dist/harness/gates/delivery-checklist.js.map +1 -0
  539. package/dist/harness/gates/delivery-decision-gate.d.ts +33 -0
  540. package/dist/harness/gates/delivery-decision-gate.d.ts.map +1 -0
  541. package/dist/harness/gates/delivery-decision-gate.js +116 -0
  542. package/dist/harness/gates/delivery-decision-gate.js.map +1 -0
  543. package/dist/harness/gates/delivery-decision-step.d.ts +19 -0
  544. package/dist/harness/gates/delivery-decision-step.d.ts.map +1 -0
  545. package/dist/harness/gates/delivery-decision-step.js +86 -0
  546. package/dist/harness/gates/delivery-decision-step.js.map +1 -0
  547. package/dist/harness/gates/gate-override-report.d.ts +59 -0
  548. package/dist/harness/gates/gate-override-report.d.ts.map +1 -0
  549. package/dist/harness/gates/gate-override-report.js +86 -0
  550. package/dist/harness/gates/gate-override-report.js.map +1 -0
  551. package/dist/harness/gates/gate-override-scope.d.ts +18 -0
  552. package/dist/harness/gates/gate-override-scope.d.ts.map +1 -0
  553. package/dist/harness/gates/gate-override-scope.js +98 -0
  554. package/dist/harness/gates/gate-override-scope.js.map +1 -0
  555. package/dist/harness/gates/gate-override-validation.d.ts +25 -0
  556. package/dist/harness/gates/gate-override-validation.d.ts.map +1 -0
  557. package/dist/harness/gates/gate-override-validation.js +81 -0
  558. package/dist/harness/gates/gate-override-validation.js.map +1 -0
  559. package/dist/harness/gates/gate-rule-catalog.d.ts +24 -0
  560. package/dist/harness/gates/gate-rule-catalog.d.ts.map +1 -0
  561. package/dist/harness/gates/gate-rule-catalog.js +112 -0
  562. package/dist/harness/gates/gate-rule-catalog.js.map +1 -0
  563. package/dist/harness/gates/gate-terms.d.ts +33 -0
  564. package/dist/harness/gates/gate-terms.d.ts.map +1 -0
  565. package/dist/harness/gates/gate-terms.js +41 -0
  566. package/dist/harness/gates/gate-terms.js.map +1 -0
  567. package/dist/harness/gates/in-run-decision-check.d.ts +21 -0
  568. package/dist/harness/gates/in-run-decision-check.d.ts.map +1 -0
  569. package/dist/harness/gates/in-run-decision-check.js +166 -0
  570. package/dist/harness/gates/in-run-decision-check.js.map +1 -0
  571. package/dist/harness/gates/journey-gate-inputs.d.ts +37 -0
  572. package/dist/harness/gates/journey-gate-inputs.d.ts.map +1 -0
  573. package/dist/harness/gates/journey-gate-inputs.js +81 -0
  574. package/dist/harness/gates/journey-gate-inputs.js.map +1 -0
  575. package/dist/harness/gates/migrated-waiver-import-bounds.d.ts +13 -0
  576. package/dist/harness/gates/migrated-waiver-import-bounds.d.ts.map +1 -0
  577. package/dist/harness/gates/migrated-waiver-import-bounds.js +141 -0
  578. package/dist/harness/gates/migrated-waiver-import-bounds.js.map +1 -0
  579. package/dist/harness/gates/migrated-waiver-review.d.ts +16 -0
  580. package/dist/harness/gates/migrated-waiver-review.d.ts.map +1 -0
  581. package/dist/harness/gates/migrated-waiver-review.js +114 -0
  582. package/dist/harness/gates/migrated-waiver-review.js.map +1 -0
  583. package/dist/harness/gates/resolve-rule.d.ts +59 -0
  584. package/dist/harness/gates/resolve-rule.d.ts.map +1 -0
  585. package/dist/harness/gates/resolve-rule.js +41 -0
  586. package/dist/harness/gates/resolve-rule.js.map +1 -0
  587. package/dist/harness/gates/unit-gate-overrides.d.ts +25 -0
  588. package/dist/harness/gates/unit-gate-overrides.d.ts.map +1 -0
  589. package/dist/harness/gates/unit-gate-overrides.js +122 -0
  590. package/dist/harness/gates/unit-gate-overrides.js.map +1 -0
  591. package/dist/harness/journey.d.ts +64 -1
  592. package/dist/harness/journey.d.ts.map +1 -1
  593. package/dist/harness/journey.js +258 -34
  594. package/dist/harness/journey.js.map +1 -1
  595. package/dist/harness/manifest.d.ts +12 -0
  596. package/dist/harness/manifest.d.ts.map +1 -1
  597. package/dist/harness/manifest.js +71 -43
  598. package/dist/harness/manifest.js.map +1 -1
  599. package/dist/harness/next-step.d.ts +58 -4
  600. package/dist/harness/next-step.d.ts.map +1 -1
  601. package/dist/harness/next-step.js +55 -204
  602. package/dist/harness/next-step.js.map +1 -1
  603. package/dist/harness/parse.d.ts +7 -0
  604. package/dist/harness/parse.d.ts.map +1 -1
  605. package/dist/harness/parse.js +18 -2
  606. package/dist/harness/parse.js.map +1 -1
  607. package/dist/harness/provenance.d.ts +29 -0
  608. package/dist/harness/provenance.d.ts.map +1 -1
  609. package/dist/harness/provenance.js +109 -9
  610. package/dist/harness/provenance.js.map +1 -1
  611. package/dist/harness/script-check.d.ts.map +1 -1
  612. package/dist/harness/script-check.js +22 -5
  613. package/dist/harness/script-check.js.map +1 -1
  614. package/dist/harness/sensors.d.ts +14 -3
  615. package/dist/harness/sensors.d.ts.map +1 -1
  616. package/dist/harness/sensors.js +41 -38
  617. package/dist/harness/sensors.js.map +1 -1
  618. package/dist/harness/triage-manual-classification.d.ts +32 -0
  619. package/dist/harness/triage-manual-classification.d.ts.map +1 -0
  620. package/dist/harness/triage-manual-classification.js +56 -0
  621. package/dist/harness/triage-manual-classification.js.map +1 -0
  622. package/dist/harness/unit-paths.d.ts +8 -0
  623. package/dist/harness/unit-paths.d.ts.map +1 -1
  624. package/dist/harness/unit-paths.js +23 -1
  625. package/dist/harness/unit-paths.js.map +1 -1
  626. package/dist/hooks/bash-read-only-segment.d.ts +9 -0
  627. package/dist/hooks/bash-read-only-segment.d.ts.map +1 -0
  628. package/dist/hooks/bash-read-only-segment.js +168 -0
  629. package/dist/hooks/bash-read-only-segment.js.map +1 -0
  630. package/dist/hooks/bash-write-targets.d.ts +25 -0
  631. package/dist/hooks/bash-write-targets.d.ts.map +1 -0
  632. package/dist/hooks/bash-write-targets.js +266 -0
  633. package/dist/hooks/bash-write-targets.js.map +1 -0
  634. package/dist/hooks/claude-hook-entry.d.ts +11 -0
  635. package/dist/hooks/claude-hook-entry.d.ts.map +1 -0
  636. package/dist/hooks/claude-hook-entry.js +137 -0
  637. package/dist/hooks/claude-hook-entry.js.map +1 -0
  638. package/dist/hooks/claude-transcript-turn.d.ts +11 -0
  639. package/dist/hooks/claude-transcript-turn.d.ts.map +1 -0
  640. package/dist/hooks/claude-transcript-turn.js +143 -0
  641. package/dist/hooks/claude-transcript-turn.js.map +1 -0
  642. package/dist/hooks/guard-delivery-contract-rule.d.ts +10 -0
  643. package/dist/hooks/guard-delivery-contract-rule.d.ts.map +1 -0
  644. package/dist/hooks/guard-delivery-contract-rule.js +152 -0
  645. package/dist/hooks/guard-delivery-contract-rule.js.map +1 -0
  646. package/dist/hooks/guard-protected-paths.d.ts +13 -0
  647. package/dist/hooks/guard-protected-paths.d.ts.map +1 -0
  648. package/dist/hooks/guard-protected-paths.js +116 -0
  649. package/dist/hooks/guard-protected-paths.js.map +1 -0
  650. package/dist/hooks/guard-rules.d.ts +20 -0
  651. package/dist/hooks/guard-rules.d.ts.map +1 -0
  652. package/dist/hooks/guard-rules.js +130 -0
  653. package/dist/hooks/guard-rules.js.map +1 -0
  654. package/dist/hooks/guard-tty-spoof-rule.d.ts +17 -0
  655. package/dist/hooks/guard-tty-spoof-rule.d.ts.map +1 -0
  656. package/dist/hooks/guard-tty-spoof-rule.js +22 -0
  657. package/dist/hooks/guard-tty-spoof-rule.js.map +1 -0
  658. package/dist/hooks/hand-back-core.d.ts +42 -0
  659. package/dist/hooks/hand-back-core.d.ts.map +1 -0
  660. package/dist/hooks/hand-back-core.js +128 -0
  661. package/dist/hooks/hand-back-core.js.map +1 -0
  662. package/dist/hooks/hook-cli-command.d.ts +9 -0
  663. package/dist/hooks/hook-cli-command.d.ts.map +1 -0
  664. package/dist/hooks/hook-cli-command.js +46 -0
  665. package/dist/hooks/hook-cli-command.js.map +1 -0
  666. package/dist/hooks/hook-registry.d.ts +10 -0
  667. package/dist/hooks/hook-registry.d.ts.map +1 -0
  668. package/dist/hooks/hook-registry.js +24 -0
  669. package/dist/hooks/hook-registry.js.map +1 -0
  670. package/dist/hooks/hook-result-contract.d.ts +50 -0
  671. package/dist/hooks/hook-result-contract.d.ts.map +1 -0
  672. package/dist/hooks/hook-result-contract.js +80 -0
  673. package/dist/hooks/hook-result-contract.js.map +1 -0
  674. package/dist/hooks/hook-toggles.d.ts +10 -0
  675. package/dist/hooks/hook-toggles.d.ts.map +1 -0
  676. package/dist/hooks/hook-toggles.js +107 -0
  677. package/dist/hooks/hook-toggles.js.map +1 -0
  678. package/dist/hooks/pre-tool-guard-hook.d.ts +10 -0
  679. package/dist/hooks/pre-tool-guard-hook.d.ts.map +1 -0
  680. package/dist/hooks/pre-tool-guard-hook.js +105 -0
  681. package/dist/hooks/pre-tool-guard-hook.js.map +1 -0
  682. package/dist/hooks/session-start-unit-state-hook.d.ts +14 -0
  683. package/dist/hooks/session-start-unit-state-hook.d.ts.map +1 -0
  684. package/dist/hooks/session-start-unit-state-hook.js +60 -0
  685. package/dist/hooks/session-start-unit-state-hook.js.map +1 -0
  686. package/dist/hooks/stop-next-step-hook.d.ts +16 -0
  687. package/dist/hooks/stop-next-step-hook.d.ts.map +1 -0
  688. package/dist/hooks/stop-next-step-hook.js +43 -0
  689. package/dist/hooks/stop-next-step-hook.js.map +1 -0
  690. package/dist/hooks/sungen-project-root.d.ts +19 -0
  691. package/dist/hooks/sungen-project-root.d.ts.map +1 -0
  692. package/dist/hooks/sungen-project-root.js +130 -0
  693. package/dist/hooks/sungen-project-root.js.map +1 -0
  694. package/dist/index.d.ts.map +1 -1
  695. package/dist/index.js +1 -2
  696. package/dist/index.js.map +1 -1
  697. package/dist/orchestrator/ai-skills/command-partial-includes.d.ts +15 -0
  698. package/dist/orchestrator/ai-skills/command-partial-includes.d.ts.map +1 -0
  699. package/dist/orchestrator/ai-skills/command-partial-includes.js +106 -0
  700. package/dist/orchestrator/ai-skills/command-partial-includes.js.map +1 -0
  701. package/dist/orchestrator/ai-skills/commands.d.ts +5 -1
  702. package/dist/orchestrator/ai-skills/commands.d.ts.map +1 -1
  703. package/dist/orchestrator/ai-skills/commands.js +11 -3
  704. package/dist/orchestrator/ai-skills/commands.js.map +1 -1
  705. package/dist/orchestrator/assets-drift.d.ts +5 -0
  706. package/dist/orchestrator/assets-drift.d.ts.map +1 -1
  707. package/dist/orchestrator/assets-drift.js +12 -3
  708. package/dist/orchestrator/assets-drift.js.map +1 -1
  709. package/dist/orchestrator/claude-hooks-install.d.ts +27 -0
  710. package/dist/orchestrator/claude-hooks-install.d.ts.map +1 -0
  711. package/dist/orchestrator/claude-hooks-install.js +203 -0
  712. package/dist/orchestrator/claude-hooks-install.js.map +1 -0
  713. package/dist/orchestrator/lockstep-version.d.ts +15 -5
  714. package/dist/orchestrator/lockstep-version.d.ts.map +1 -1
  715. package/dist/orchestrator/lockstep-version.js +30 -17
  716. package/dist/orchestrator/lockstep-version.js.map +1 -1
  717. package/dist/orchestrator/project-initializer.d.ts +6 -0
  718. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  719. package/dist/orchestrator/project-initializer.js +24 -0
  720. package/dist/orchestrator/project-initializer.js.map +1 -1
  721. package/dist/orchestrator/templates/ai-src/commands/add-api.md +2 -0
  722. package/dist/orchestrator/templates/ai-src/commands/add-flow.md +6 -26
  723. package/dist/orchestrator/templates/ai-src/commands/add-screen.md +2 -0
  724. package/dist/orchestrator/templates/ai-src/commands/create-data-test.md +1 -0
  725. package/dist/orchestrator/templates/ai-src/commands/create-test.md +17 -16
  726. package/dist/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
  727. package/dist/orchestrator/templates/ai-src/commands/delivery.md +4 -0
  728. package/dist/orchestrator/templates/ai-src/commands/design.md +2 -0
  729. package/dist/orchestrator/templates/ai-src/commands/feedback.md +2 -0
  730. package/dist/orchestrator/templates/ai-src/commands/locale.md +2 -0
  731. package/dist/orchestrator/templates/ai-src/commands/review.md +4 -0
  732. package/dist/orchestrator/templates/ai-src/commands/run-test.md +6 -8
  733. package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.claude.md +20 -0
  734. package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.codex.md +20 -0
  735. package/dist/orchestrator/templates/ai-src/partials/hand-back-rule.copilot.md +20 -0
  736. package/dist/orchestrator/templates/ai-src/partials/waiting-for-you.claude.md +11 -0
  737. package/dist/orchestrator/templates/ai-src/partials/waiting-for-you.codex.md +11 -0
  738. package/dist/orchestrator/templates/ai-src/partials/waiting-for-you.copilot.md +11 -0
  739. package/dist/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +1 -2
  740. package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +4 -5
  741. package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +8 -24
  742. package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +3 -4
  743. package/dist/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
  744. package/dist/orchestrator/templates/specs-test-data.ts +4 -22
  745. package/dist/utils/safe-yaml-parse.d.ts +8 -0
  746. package/dist/utils/safe-yaml-parse.d.ts.map +1 -0
  747. package/dist/utils/safe-yaml-parse.js +51 -0
  748. package/dist/utils/safe-yaml-parse.js.map +1 -0
  749. package/package.json +3 -3
  750. package/src/basis/anchor-grammar.ts +83 -0
  751. package/src/basis/anchor-hash.ts +27 -0
  752. package/src/basis/bm51-tables.ts +65 -0
  753. package/src/basis/extract-spec-anchors.ts +95 -0
  754. package/src/basis/migration-sentinel.ts +175 -0
  755. package/src/basis/spec-frontmatter.ts +68 -0
  756. package/src/basis/spec-sections.ts +35 -0
  757. package/src/basis/test-basis-schema.ts +81 -0
  758. package/src/capabilities/discover.ts +15 -2
  759. package/src/capabilities/registry.ts +16 -0
  760. package/src/cli/case-triage-hint.ts +31 -0
  761. package/src/cli/commands/audit.ts +1 -1
  762. package/src/cli/commands/capability.ts +1 -1
  763. package/src/cli/commands/contract-derive-command.ts +72 -0
  764. package/src/cli/commands/contract.ts +164 -0
  765. package/src/cli/commands/delivery.ts +106 -19
  766. package/src/cli/commands/gate.ts +2 -1
  767. package/src/cli/commands/generate.ts +16 -3
  768. package/src/cli/commands/journey.ts +45 -18
  769. package/src/cli/commands/next.ts +92 -11
  770. package/src/cli/commands/triage.ts +41 -3
  771. package/src/cli/commands/update.ts +41 -10
  772. package/src/cli/index.ts +24 -30
  773. package/src/cli/json-error-on-exit.ts +72 -0
  774. package/src/cli/project-sungen-invocation.ts +59 -0
  775. package/src/cli/run-command-hints.ts +47 -0
  776. package/src/cli/waiting-for-you-block.ts +27 -0
  777. package/src/contract/accept-opaque-steps.ts +114 -0
  778. package/src/contract/approve-contract.ts +101 -0
  779. package/src/contract/assertion-matcher-vocabulary.ts +93 -0
  780. package/src/contract/build-contract-verdict.ts +108 -0
  781. package/src/contract/build-trace-conformance.ts +103 -0
  782. package/src/contract/classify-contract-change.ts +92 -0
  783. package/src/contract/classify-contract-unit.ts +47 -0
  784. package/src/contract/classify-trace-conformance.ts +170 -0
  785. package/src/contract/contract-git.ts +106 -0
  786. package/src/contract/contract-hash.ts +34 -0
  787. package/src/contract/contract-report-file.ts +25 -0
  788. package/src/contract/contract-schema.ts +166 -0
  789. package/src/contract/contract-units.ts +52 -0
  790. package/src/contract/contracts-lock-file.ts +98 -0
  791. package/src/contract/data-normalize.ts +66 -0
  792. package/src/contract/derive-free-feature.ts +153 -0
  793. package/src/contract/field-semantic-redaction.ts +80 -0
  794. package/src/contract/free-feature-blocks.ts +56 -0
  795. package/src/contract/lock-secret-guard.ts +95 -0
  796. package/src/contract/lock-vs-git-head.ts +38 -0
  797. package/src/contract/normalize-contract-step.ts +74 -0
  798. package/src/contract/normalize-feature-steps.ts +93 -0
  799. package/src/contract/oracle-strength.ts +80 -0
  800. package/src/contract/project-contract-blockers.ts +38 -0
  801. package/src/contract/record-contract-approval.ts +110 -0
  802. package/src/contract/render-free-gherkin.ts +118 -0
  803. package/src/contract/render-trace-sentence.ts +98 -0
  804. package/src/contract/render-trace-target.ts +68 -0
  805. package/src/contract/resolve-unit-trace-identities.ts +58 -0
  806. package/src/contract/trace/collect-trace-evidence.ts +178 -0
  807. package/src/contract/trace/identity-cache.ts +61 -0
  808. package/src/contract/trace/read-file-once.ts +95 -0
  809. package/src/contract/trace/scenario-id-claims.ts +60 -0
  810. package/src/contract/trace/select-final-attempt.ts +77 -0
  811. package/src/contract/trace/snapshot-html-renderer.ts +136 -0
  812. package/src/contract/trace/snapshot-resolver.ts +66 -0
  813. package/src/contract/trace/snapshot-store.ts +151 -0
  814. package/src/contract/trace/target-identity.ts +104 -0
  815. package/src/contract/trace/test-step-join.ts +104 -0
  816. package/src/contract/trace/trace-binding.ts +59 -0
  817. package/src/contract/trace/trace-file-reader.ts +144 -0
  818. package/src/contract/trace/trace-fingerprint.ts +68 -0
  819. package/src/contract/trace/trace-freshness.ts +110 -0
  820. package/src/contract/trace/trace-identity-resolution.ts +77 -0
  821. package/src/contract/trace/trace-run-record.ts +96 -0
  822. package/src/contract/trace/trace-steps.ts +88 -0
  823. package/src/contract/trace/trace-zip-limits.ts +77 -0
  824. package/src/contract/trace/trace-zip-reader.ts +127 -0
  825. package/src/contract/verify-approval-decisions.ts +64 -0
  826. package/src/decisions/append-decision.ts +35 -0
  827. package/src/decisions/confirmed-decision-commands.ts +149 -0
  828. package/src/decisions/decision-file.ts +93 -0
  829. package/src/decisions/decision-identity.ts +73 -0
  830. package/src/decisions/decision-integrity-check.ts +61 -0
  831. package/src/decisions/decision-schema.ts +77 -0
  832. package/src/decisions/decision-source.ts +14 -0
  833. package/src/decisions/exclusive-file-create.ts +42 -0
  834. package/src/decisions/git-head-trust.ts +76 -0
  835. package/src/decisions/human-confirmation.ts +119 -0
  836. package/src/decisions/legacy-waiver-migration.ts +146 -0
  837. package/src/decisions/read-decisions.ts +61 -0
  838. package/src/decisions/viewpoint-baseline-adapter.ts +74 -0
  839. package/src/decisions/waiver-decisions.ts +56 -0
  840. package/src/exporters/csv-exporter.ts +12 -4
  841. package/src/exporters/matrix/build.ts +11 -9
  842. package/src/exporters/matrix/export.ts +16 -4
  843. package/src/exporters/matrix/gates.ts +62 -129
  844. package/src/exporters/matrix/render-csv.ts +3 -0
  845. package/src/exporters/matrix/render-gate-overrides-sheet.ts +50 -0
  846. package/src/exporters/matrix/render-xlsx.ts +3 -0
  847. package/src/exporters/matrix/types.ts +4 -1
  848. package/src/exporters/matrix/xlsx-cells.ts +1 -1
  849. package/src/exporters/test-data-resolver.ts +2 -10
  850. package/src/exporters/xlsx-exporter.ts +5 -4
  851. package/src/generators/gherkin-parser/index.ts +0 -1
  852. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/contain-text-assertion.hbs +1 -2
  853. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -13
  854. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -9
  855. package/src/generators/test-generator/code-generator.ts +17 -4
  856. package/src/generators/test-generator/diagnostics.ts +3 -9
  857. package/src/generators/test-generator/patterns/types.ts +0 -2
  858. package/src/generators/test-generator/step-mapper.ts +9 -56
  859. package/src/generators/test-generator/utils/data-resolver.ts +0 -53
  860. package/src/generators/test-generator/utils/selector-resolver.ts +2 -10
  861. package/src/graph/board-human-actions.ts +80 -0
  862. package/src/graph/evaluate-graph.ts +97 -0
  863. package/src/graph/human-action.ts +33 -0
  864. package/src/graph/locate-finding.ts +93 -0
  865. package/src/graph/manual-triage-decisions.ts +55 -0
  866. package/src/graph/node-decl.ts +83 -0
  867. package/src/graph/nodes/core-node-catalog.ts +15 -0
  868. package/src/graph/nodes/test-case-contract-nodes.ts +90 -0
  869. package/src/graph/nodes/test-case-nodes.ts +100 -0
  870. package/src/graph/nodes/unit-audit-nodes.ts +96 -0
  871. package/src/graph/nodes/unit-contract-node.ts +100 -0
  872. package/src/graph/nodes/unit-design-nodes.ts +89 -0
  873. package/src/graph/nodes/unit-execution-nodes.ts +77 -0
  874. package/src/graph/test-case-identity.ts +75 -0
  875. package/src/graph/test-case-results.ts +111 -0
  876. package/src/graph/test-case-satisfied.ts +58 -0
  877. package/src/graph/test-case-state-shape.ts +67 -0
  878. package/src/graph/test-case-states.ts +84 -0
  879. package/src/graph/unit-artifact-probes.ts +79 -0
  880. package/src/graph/unit-results-freshness.ts +165 -0
  881. package/src/graph/unit-state-facts.ts +112 -0
  882. package/src/harness/audit.ts +31 -18
  883. package/src/harness/catalog/gate-rules.yaml +647 -0
  884. package/src/harness/defect-draft.ts +13 -2
  885. package/src/harness/defects.ts +22 -9
  886. package/src/harness/flow-check.ts +11 -0
  887. package/src/harness/gates/audit-gate-terms.ts +80 -0
  888. package/src/harness/gates/audit-gate-verdict.ts +79 -0
  889. package/src/harness/gates/audit-input-hash.ts +79 -0
  890. package/src/harness/gates/audit-report-verification.ts +206 -0
  891. package/src/harness/gates/decisions-hash.ts +42 -0
  892. package/src/harness/gates/delivery-checklist.ts +152 -0
  893. package/src/harness/gates/delivery-decision-gate.ts +139 -0
  894. package/src/harness/gates/delivery-decision-step.ts +89 -0
  895. package/src/harness/gates/gate-override-report.ts +114 -0
  896. package/src/harness/gates/gate-override-scope.ts +66 -0
  897. package/src/harness/gates/gate-override-validation.ts +75 -0
  898. package/src/harness/gates/gate-rule-catalog.ts +82 -0
  899. package/src/harness/gates/gate-terms.ts +59 -0
  900. package/src/harness/gates/in-run-decision-check.ts +124 -0
  901. package/src/harness/gates/journey-gate-inputs.ts +89 -0
  902. package/src/harness/gates/migrated-waiver-import-bounds.ts +103 -0
  903. package/src/harness/gates/migrated-waiver-review.ts +121 -0
  904. package/src/harness/gates/resolve-rule.ts +94 -0
  905. package/src/harness/gates/unit-gate-overrides.ts +99 -0
  906. package/src/harness/journey.ts +287 -39
  907. package/src/harness/manifest.ts +67 -43
  908. package/src/harness/next-step.ts +91 -193
  909. package/src/harness/parse.ts +20 -2
  910. package/src/harness/provenance.ts +99 -11
  911. package/src/harness/script-check.ts +20 -5
  912. package/src/harness/sensors.ts +47 -40
  913. package/src/harness/triage-manual-classification.ts +76 -0
  914. package/src/harness/unit-paths.ts +19 -0
  915. package/src/hooks/bash-read-only-segment.ts +130 -0
  916. package/src/hooks/bash-write-targets.ts +195 -0
  917. package/src/hooks/claude-hook-entry.ts +85 -0
  918. package/src/hooks/claude-transcript-turn.ts +96 -0
  919. package/src/hooks/guard-delivery-contract-rule.ts +110 -0
  920. package/src/hooks/guard-protected-paths.ts +80 -0
  921. package/src/hooks/guard-rules.ts +117 -0
  922. package/src/hooks/guard-tty-spoof-rule.ts +34 -0
  923. package/src/hooks/hand-back-core.ts +118 -0
  924. package/src/hooks/hook-cli-command.ts +17 -0
  925. package/src/hooks/hook-registry.ts +24 -0
  926. package/src/hooks/hook-result-contract.ts +114 -0
  927. package/src/hooks/hook-toggles.ts +66 -0
  928. package/src/hooks/pre-tool-guard-hook.ts +67 -0
  929. package/src/hooks/session-start-unit-state-hook.ts +59 -0
  930. package/src/hooks/stop-next-step-hook.ts +38 -0
  931. package/src/hooks/sungen-project-root.ts +80 -0
  932. package/src/index.ts +1 -2
  933. package/src/orchestrator/ai-skills/command-partial-includes.ts +72 -0
  934. package/src/orchestrator/ai-skills/commands.ts +17 -5
  935. package/src/orchestrator/assets-drift.ts +12 -5
  936. package/src/orchestrator/claude-hooks-install.ts +168 -0
  937. package/src/orchestrator/lockstep-version.ts +28 -15
  938. package/src/orchestrator/project-initializer.ts +22 -0
  939. package/src/orchestrator/templates/ai-src/commands/add-api.md +2 -0
  940. package/src/orchestrator/templates/ai-src/commands/add-flow.md +6 -26
  941. package/src/orchestrator/templates/ai-src/commands/add-screen.md +2 -0
  942. package/src/orchestrator/templates/ai-src/commands/create-data-test.md +1 -0
  943. package/src/orchestrator/templates/ai-src/commands/create-test.md +17 -16
  944. package/src/orchestrator/templates/ai-src/commands/dashboard.md +2 -0
  945. package/src/orchestrator/templates/ai-src/commands/delivery.md +4 -0
  946. package/src/orchestrator/templates/ai-src/commands/design.md +2 -0
  947. package/src/orchestrator/templates/ai-src/commands/feedback.md +2 -0
  948. package/src/orchestrator/templates/ai-src/commands/locale.md +2 -0
  949. package/src/orchestrator/templates/ai-src/commands/review.md +4 -0
  950. package/src/orchestrator/templates/ai-src/commands/run-test.md +6 -8
  951. package/src/orchestrator/templates/ai-src/partials/hand-back-rule.claude.md +20 -0
  952. package/src/orchestrator/templates/ai-src/partials/hand-back-rule.codex.md +20 -0
  953. package/src/orchestrator/templates/ai-src/partials/hand-back-rule.copilot.md +20 -0
  954. package/src/orchestrator/templates/ai-src/partials/waiting-for-you.claude.md +11 -0
  955. package/src/orchestrator/templates/ai-src/partials/waiting-for-you.codex.md +11 -0
  956. package/src/orchestrator/templates/ai-src/partials/waiting-for-you.copilot.md +11 -0
  957. package/src/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +1 -2
  958. package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +4 -5
  959. package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +8 -24
  960. package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +3 -4
  961. package/src/orchestrator/templates/claude-hooks/sungen-hook.cjs +64 -0
  962. package/src/orchestrator/templates/specs-test-data.ts +4 -22
  963. package/src/utils/safe-yaml-parse.ts +44 -0
  964. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/expanded-assertion.hbs +0 -2
  965. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/date-picker-unsupported.hbs +0 -5
  966. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/expanded-assertion.hbs +0 -12
  967. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/expanded-assertion.hbs +0 -2
  968. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/date-picker-unsupported.hbs +0 -5
  969. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/expanded-assertion.hbs +0 -12
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The "Waiting for you" block (#954) — every pending human-only action of a unit, as ready-to-copy
3
+ * commands with the reason under each. One renderer for the three places that show it: `sungen next`
4
+ * (text) and the Stop / SessionStart hook context. Commands — and those inside a reason (#963) — as the
5
+ * project runs sungen (`npx sungen` with a local install, #939); `--json` keeps `command` canonical in
6
+ * `humanActions` and adds `rendered`. An instruction (a commit through review, a `git checkout --`) is
7
+ * marked `✎ … (by hand, not a command)`, never shown as one to copy.
8
+ */
9
+ import type { HumanAction } from '../graph/human-action';
10
+ import { withProjectInvocation, withProjectInvocationInText } from './project-sungen-invocation';
11
+
12
+ export const WAITING_FOR_YOU_HEAD = '⏳ Waiting for you — a human runs these in their own terminal (in Claude Code: ! <command>); an agent never runs them:';
13
+
14
+ /**
15
+ * The block's lines (indented two spaces), or none when nothing waits for a human and nothing holds the
16
+ * rest. `heldBy`: the title of the blocking step that cut the frontier — the block is not exhaustive then,
17
+ * and says what holds the rest, with that step's command (`heldByCommand`) when given (#966). A held
18
+ * block with no item of its own still says so, rather than vanishing (a QA read "nothing is waiting").
19
+ */
20
+ export function waitingForYouLines(actions: readonly HumanAction[] | undefined, projectRoot: string, heldBy?: string, heldByCommand?: string): string[] {
21
+ const holds = heldBy ? `"${heldBy}" clears${heldByCommand ? ` (the step above: ${withProjectInvocationInText(heldByCommand, projectRoot)})` : ''}` : '';
22
+ if (!actions?.length) return heldBy ? [` ⏳ Waiting for you: nothing yet — more appear once ${holds}.`] : [];
23
+ return [` ${WAITING_FOR_YOU_HEAD}`, ...actions.flatMap((a) => [
24
+ a.instruction ? ` ✎ ${a.command} (by hand, not a command)` : ` ${withProjectInvocation(a.command, projectRoot)}`,
25
+ ` ${withProjectInvocationInText(a.reason, projectRoot)}`,
26
+ ]), ...(heldBy ? [` More appear once ${holds}.`] : [])];
27
+ }
@@ -0,0 +1,114 @@
1
+ /**
2
+ * `sungen contract approve --screen <u> --scenario <id> --accept-opaque` — a QA accepts the reviewed
3
+ * opaque steps of ONE approved free / impl:code scenario (#923). An opaque step (a check on a JS value,
4
+ * an API request, an evaluate) is never compared by code, so without this an approved test that has one
5
+ * stays in review for good: re-approving changes nothing and contract.opaque-step allows no override.
6
+ * In order, like `approve` (approve-contract.ts), so a human never confirms something then refused:
7
+ *
8
+ * 1. the scenario must be approved AS IT READS NOW — its lock entry human-approved, intact, at the
9
+ * current hash, and vouched for by its decision — else: approve it first
10
+ * 2. its verdict is rebuilt (buildContractVerdict, as `contract check`): the opaque steps must be the
11
+ * ONLY thing holding it; anything else (changed, unproven, inconclusive, a `low` identity…) refuses
12
+ * with its own fix. Every opaque step already accepted → nothing to accept, no prompt
13
+ * 3. each opaque step is shown verbatim with its file:line; on a TTY the human types the scenario id
14
+ * and a one-time code — without one: refused with the exact command (an agent never runs this)
15
+ * 4. everything is read AGAIN: if the trace, the feature or the lock moved meanwhile → refused
16
+ * 5. a contract-approval decision records the scenario at its hash WITH the accepted steps (step + sha)
17
+ * and the lock entry points at it (record-contract-approval.ts)
18
+ *
19
+ * The acceptance is bound to each step's sha (opaqueStepSha): a change to an accepted step, or a new
20
+ * approval of the scenario, brings it back to review.
21
+ *
22
+ * Trust boundary: the TTY confirmation guards this command, not the files. A lock entry AND a matching
23
+ * decision forged together and committed through review are trusted like any approval — git review
24
+ * is that boundary, here as for `approve`.
25
+ */
26
+ import { gitUserName } from '../decisions/decision-source';
27
+ import { formatCommand, requireTypedConfirmation } from '../decisions/human-confirmation';
28
+ import type { ApproveInput, ApproveResult } from './approve-contract';
29
+ import { buildContractVerdict } from './build-contract-verdict';
30
+ import { LOW_IDENTITY_FINDING } from './classify-trace-conformance';
31
+ import { canonicalJson } from './contract-hash';
32
+ import { ContractScenario, isHumanApproved, OpaqueStep } from './contract-schema';
33
+ import { resolveContractUnit } from './contract-units';
34
+ import { lockPathFor, ReadLock, readLockFile } from './contracts-lock-file';
35
+ import { loadContractScenarios } from './normalize-feature-steps';
36
+ import { recordOpaqueAcceptance } from './record-contract-approval';
37
+ import { unverifiedApprovals } from './verify-approval-decisions';
38
+
39
+ /** Accepting reads the traces with `contract check`'s generous deadline, never the guard's ~3 s. */
40
+ const ACCEPT_TRACE_BUDGET_MS = 120_000;
41
+ /** Findings that never hold a scenario back may stand beside the opaque steps. */
42
+ const HARMLESS = new Set(['strengthened', 'nondeterministic']);
43
+
44
+ interface Plan { unitDir: string; unit: string; scenario: ContractScenario; lock: ReadLock; decisionId: string; opaque: OpaqueStep[]; fingerprint: string }
45
+
46
+ const isLow = (detail: string): boolean => detail.startsWith(LOW_IDENTITY_FINDING);
47
+
48
+ function plan(i: ApproveInput, id: string): Plan {
49
+ const unit = resolveContractUnit(i.projectRoot, i.unit);
50
+ const lock = readLockFile(lockPathFor(unit.dir));
51
+ const matches = loadContractScenarios(unit.dir, unit.name).filter((s) => s.id === id);
52
+ if (!matches.length) throw new Error(`--scenario ${id} names no scenario of ${i.unit}`);
53
+ if (matches.length > 1) throw new Error(`Refused: scenario id ${id} is used by ${matches.length} scenarios — an acceptance must name exactly one. Give each its own ID.`);
54
+ const sc = matches[0];
55
+ if (sc.implementation === 'compiled') throw new Error(`Refused: ${id} is compiled — only a free / impl:code test has trace steps to accept.`);
56
+ const entry = lock?.scenarios[id];
57
+ if (!lock || !isHumanApproved(entry) || lock.tampered.includes(id) || entry.hash !== sc.hash) {
58
+ throw new Error(`Refused: ${id} is not approved as it reads now — approve it first (\`sungen contract approve --screen ${i.unit} --scenario ${id}\`), re-run it with a trace, then accept its opaque steps.`);
59
+ }
60
+ // The entry an acceptance re-points must be QA's own: its decision (on disk) vouches for it as it is.
61
+ const [unvouched] = unverifiedApprovals(i.projectRoot, unit.dir, { schema: lock.schema, scenarios: { [id]: entry } }, new Set(), { root: i.projectRoot, timeoutMs: 0, blobs: null });
62
+ if (unvouched) throw new Error(`Refused: the lock entry of ${id} is not vouched for by its decision (${unvouched.detail}) — restore the lock from git, or approve the scenario again.`);
63
+
64
+ const v = buildContractVerdict(i.projectRoot, unit, { traceBudgetMs: ACCEPT_TRACE_BUDGET_MS });
65
+ const bad = v.uncommitted.find((u) => u.id === id && (u.change === 'tampered' || u.change === 'unverified'));
66
+ if (bad) throw new Error(`Refused: the lock entry of ${id} is ${bad.change} (${bad.detail}) — restore it from git before accepting anything.`);
67
+ const r = v.scenarios.find((s) => s.id === id);
68
+ const blocking = (r?.findings ?? []).filter((f) => !HARMLESS.has(f.class) && !(f.class === 'opaque' && !isLow(f.detail)));
69
+ if (blocking.length) {
70
+ const fix = blocking.some((f) => isLow(f.detail))
71
+ ? `run \`sungen contract check --screen ${i.unit} --trace\` (a real browser resolves the identity) first`
72
+ : `settle that first — \`sungen contract check --screen ${i.unit}\` names the fix`;
73
+ throw new Error(`Refused: accepting clears only opaque steps, and ${id} is also held by: ${blocking.map((f) => `${f.class}${f.step ? ` (step ${f.step})` : ''} — ${f.detail}`).join('; ')}. ${fix[0].toUpperCase()}${fix.slice(1)}.`);
74
+ }
75
+ const opaque = r?.trace?.opaque ?? [];
76
+ if (!opaque.length) throw new Error(`Refused: the trace of ${id} has no opaque step — nothing to accept (${r?.class ?? 'not judged'}).`);
77
+ return { unitDir: unit.dir, unit: unit.name, scenario: sc, lock, decisionId: entry.decisionId, opaque, fingerprint: canonicalJson({ lock, hash: sc.hash, opaque }) };
78
+ }
79
+
80
+ const describe = (o: OpaqueStep): string =>
81
+ `${o.accepted ? '=' : '◐'} step ${o.step} opaque ${o.kind === 'assert' ? 'check' : 'step'} "${o.verbatim}"${o.where ? ` at ${o.where}` : ''}`
82
+ + `${o.replaces ? ` — replaces approved ${o.replaces}` : ''}${o.accepted ? ' (accepted before)' : ''}`;
83
+
84
+ export async function acceptOpaqueSteps(i: ApproveInput): Promise<ApproveResult> {
85
+ const id = i.scenario;
86
+ if (!id) throw new Error('--accept-opaque needs --scenario <id>: an acceptance names the one scenario whose opaque steps QA reviewed');
87
+ const before = plan(i, id);
88
+ const lockPath = lockPathFor(before.unitDir);
89
+ if (before.opaque.every((o) => o.accepted)) return { status: 'nothing-to-accept', lockPath, approved: [], removed: [] };
90
+
91
+ const pending = before.opaque.filter((o) => !o.accepted);
92
+ await requireTypedConfirmation({
93
+ what: `accept ${pending.length} reviewed opaque step(s) of ${id} (${i.unit}) — steps sungen cannot compare, so they are never checked by code`,
94
+ phrase: id,
95
+ command: formatCommand(['sungen', 'contract', 'approve', '--screen', i.unit, '--scenario', id, '--accept-opaque', ...(i.reason ? ['--reason', i.reason] : [])]),
96
+ summary: [
97
+ ...before.opaque.map(describe),
98
+ `bound to each step as it reads now: a change to it, or a new approval of ${id}, brings it back to review`,
99
+ `${id} stays approved at hash ${before.scenario.hash}; its lock entry moves from decision ${before.decisionId} to the new one`,
100
+ `recorded by: ${gitUserName(i.projectRoot)}`,
101
+ ],
102
+ io: i.io,
103
+ });
104
+
105
+ const after = plan(i, id);
106
+ if (after.fingerprint !== before.fingerprint) {
107
+ throw new Error('Refused: the trace, the feature or the lock changed while you were confirming — nothing was written. Run the command again and review the new summary.');
108
+ }
109
+ const { decisionId } = recordOpaqueAcceptance({
110
+ projectRoot: i.projectRoot, unitDir: after.unitDir, unit: after.unit, scenario: after.scenario, reason: i.reason, lock: after.lock,
111
+ accepted: after.opaque.map((o) => ({ step: o.step, sha: o.sha })),
112
+ });
113
+ return { status: 'accepted', lockPath, decisionId, approved: [id], removed: [], accepted: after.opaque };
114
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * `sungen contract approve --screen <u> [--scenario <id>]` — the human act that locks a contract
3
+ * (DOS-14.4, DOS-13.4, takumi T5). In order, so a human never confirms something then rejected:
4
+ *
5
+ * 1. resolve the unit, read the current scenarios and the lock (an unreadable lock refuses)
6
+ * 2. pick what changes: new, changed or tampered scenarios, and — when approving the whole unit —
7
+ * the entries of scenarios that left the feature; nothing changed → nothing to approve, no prompt
8
+ * 3. refuse a duplicated id or a Scenario Outline, and run the secret guard
9
+ * 4. show each change with its ladder class (a weakening is named before it is confirmed) and
10
+ * require the typed phrase on a TTY — without one: refuse and print the exact command
11
+ * 5. read everything AGAIN: if the feature or the lock moved while the human was reading, what
12
+ * they confirmed is not what would be written — refuse (L5)
13
+ * 6. record the decision and the lock (record-contract-approval.ts)
14
+ *
15
+ * `--accept-opaque` (with `--scenario`) is the other human act of this command: accepting the reviewed
16
+ * opaque trace steps of one approved free / impl:code scenario — accept-opaque-steps.ts (#923).
17
+ */
18
+ import { ConfirmationIO, formatCommand, requireTypedConfirmation } from '../decisions/human-confirmation';
19
+ import { gitUserName } from '../decisions/decision-source';
20
+ import { classifyScenario } from './classify-contract-change';
21
+ import { canonicalJson } from './contract-hash';
22
+ import { acceptOpaqueSteps } from './accept-opaque-steps';
23
+ import { ContractScenario, isHumanApproved, OpaqueStep } from './contract-schema';
24
+ import { resolveContractUnit } from './contract-units';
25
+ import { lockPathFor, ReadLock, readLockFile } from './contracts-lock-file';
26
+ import { dropProposedTags } from './free-feature-blocks';
27
+ import { contractFeatureFiles, loadContractScenarios } from './normalize-feature-steps';
28
+ import { ApprovalWrite, checkApprovalSecrets, recordContractApproval } from './record-contract-approval';
29
+
30
+ export interface ApproveInput { projectRoot: string; unit: string; scenario?: string; reason?: string; io: ConfirmationIO; acceptOpaque?: boolean }
31
+ export interface ApproveResult {
32
+ status: 'approved' | 'nothing-to-approve' | 'accepted' | 'nothing-to-accept';
33
+ lockPath: string;
34
+ decisionId?: string;
35
+ approved: string[];
36
+ removed: string[];
37
+ /** `--accept-opaque`: the scenario's opaque steps, all accepted by the new decision. */
38
+ accepted?: OpaqueStep[];
39
+ }
40
+
41
+ interface Plan { write: ApprovalWrite; lock: ReadLock | null; fingerprint: string }
42
+
43
+ function plan(i: ApproveInput): Plan {
44
+ const unit = resolveContractUnit(i.projectRoot, i.unit);
45
+ const lock = readLockFile(lockPathFor(unit.dir));
46
+ const current = loadContractScenarios(unit.dir, unit.name);
47
+ const ids = new Set(current.map((s) => s.id));
48
+ if (i.scenario && !ids.has(i.scenario) && !lock?.scenarios[i.scenario]) {
49
+ throw new Error(`--scenario ${i.scenario} names no scenario of ${i.unit} (current: ${[...ids].join(', ') || 'none'})`);
50
+ }
51
+ const chosen = current.filter((s) => !i.scenario || s.id === i.scenario);
52
+ const dup = [...new Set(chosen.map((s) => s.id))].find((id) => current.filter((s) => s.id === id).length > 1);
53
+ if (dup) throw new Error(`Refused: scenario id ${dup} is used by ${current.filter((s) => s.id === dup).length} scenarios — a lock entry must name exactly one. Give each its own ID.`);
54
+ const outlines = chosen.filter((s) => s.source.outline).map((s) => s.id);
55
+ if (outlines.length) throw new Error(`Refused: ${outlines.join(', ')} ${outlines.length > 1 ? 'are' : 'is a'} Scenario Outline — the compiler does not support it, so it cannot be locked. Rewrite it as @cases data.`);
56
+ const tampered = new Set(lock?.tampered ?? []);
57
+ const approve = chosen.filter((s) => { const e = lock?.scenarios[s.id]; return !isHumanApproved(e) || e.hash !== s.hash || tampered.has(s.id); });
58
+ const removed = Object.keys(lock?.scenarios ?? {}).filter((id) => !ids.has(id) && (!i.scenario || id === i.scenario));
59
+ const write: ApprovalWrite = { projectRoot: i.projectRoot, unitDir: unit.dir, unit: unit.name, approve, removed, reason: i.reason, lock };
60
+ return { write, lock, fingerprint: canonicalJson({ lock, approve: approve.map((s) => [s.id, s.hash]), removed }) };
61
+ }
62
+
63
+ function describe(sc: ContractScenario, lock: ReadLock | null): string {
64
+ const entry = lock?.scenarios[sc.id];
65
+ if (!isHumanApproved(entry) || lock?.tampered.includes(sc.id)) return `+ ${sc.id} new (${sc.steps.length} steps, ${sc.implementation})`;
66
+ const r = classifyScenario(sc.id, entry, sc);
67
+ return `~ ${sc.id} ${r.class}${r.findings.length ? ` — ${r.findings.map((f) => f.detail).join('; ')}` : ''}`;
68
+ }
69
+
70
+ export async function approveContract(i: ApproveInput): Promise<ApproveResult> {
71
+ if (i.acceptOpaque) return acceptOpaqueSteps(i);
72
+ const before = plan(i);
73
+ const { approve, removed } = before.write;
74
+ const lockPath = lockPathFor(before.write.unitDir);
75
+ if (!approve.length && !removed.length) return { status: 'nothing-to-approve', lockPath, approved: [], removed: [] };
76
+ checkApprovalSecrets(before.write);
77
+
78
+ const unnamed = approve.filter((s) => !s.source.hasId).length;
79
+ await requireTypedConfirmation({
80
+ what: `approve the Test Contract of ${i.unit} (${approve.length} scenario(s)${removed.length ? `, ${removed.length} removed` : ''})`,
81
+ phrase: i.unit,
82
+ command: formatCommand(['sungen', 'contract', 'approve', '--screen', i.unit, ...(i.scenario ? ['--scenario', i.scenario] : []), ...(i.reason ? ['--reason', i.reason] : [])]),
83
+ summary: [
84
+ ...approve.map((s) => describe(s, before.lock)),
85
+ ...removed.map((id) => `- ${id} removed from the feature — its approved checks leave the contract`),
86
+ ...(unnamed ? [`note: ${unnamed} scenario(s) have no ID and are locked by name — renaming one will read as removing it`] : []),
87
+ `recorded by: ${gitUserName(i.projectRoot)}`,
88
+ ],
89
+ io: i.io,
90
+ });
91
+
92
+ const after = plan(i);
93
+ if (after.fingerprint !== before.fingerprint) {
94
+ throw new Error('Refused: the feature or the lock changed while you were confirming — nothing was written. Run the command again and review the new summary.');
95
+ }
96
+ const { decisionId } = recordContractApproval(after.write);
97
+ // A derived `@free @proposed` scenario stops being a proposal once QA locks it (DOS-14.8).
98
+ const approvedIds = new Set(approve.map((s) => s.id));
99
+ for (const f of contractFeatureFiles(after.write.unitDir, after.write.unit)) dropProposedTags(f, approvedIds);
100
+ return { status: 'approved', lockPath, decisionId, approved: approve.map((s) => s.id), removed };
101
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * What an assertion checks — the CLOSED vocabulary of the strength ladder (DOS-14.1, DOS-14.4).
3
+ *
4
+ * Read off the normalized sentence the QA wrote (the documented `see` / `is on` / `expect` forms of
5
+ * sungen-gherkin-syntax), not off the compiler's pattern registry: that registry is assembled from
6
+ * whichever drivers a machine has installed, so a hash built on it would differ between two
7
+ * checkouts of the same `.feature`, and the hook would judge differently from the CLI. A sentence
8
+ * outside the vocabulary is `unknown`, and an unknown check that changed is `review`, never `match`.
9
+ *
10
+ * strength 1 visible · exists (something is there)
11
+ * strength 2 page · state · contains · matches · range · key-matching · child · url-/title-contains|matches
12
+ * strength 3 equals · count · table-data · tab-order · schema · url · title
13
+ * `all:` (every item) adds one. A negation (`not see`, `is not <state>`, `is hidden`) is a flag.
14
+ */
15
+ import type { StateClause } from '../generators/test-generator/patterns/types';
16
+
17
+ export interface AssertShape { matcher: string; negated: boolean }
18
+
19
+ const NEGATION = /\b(?:not|no longer|never|cannot|can't|don't|doesn't|isn't|aren't|shouldn't)\b/;
20
+ const NOT_SEE = /^(?:do not|does not|don't|doesn't|should not|shouldn't|cannot|can't|not|never) see\b/;
21
+ const IS_NOT_STATE = /\bis not (sorted ascending|sorted descending|unchecked|checked|hidden|visible|disabled|enabled|focused|empty|loading|selected)$/;
22
+ const RANGE = /\b(?:at least|at most|more than|less than|greater than|fewer than|between)\b/;
23
+ const PAGE_SUBJECT = /^see (?:the )?(?:current |page )?(url|title)\b(.*)$/;
24
+ /** A state and its complement are one check with a negation: hidden = not visible. */
25
+ const STATE_AS: Partial<Record<StateClause, [string, boolean]>> = {
26
+ visible: ['visible', false], hidden: ['visible', true],
27
+ enabled: ['enabled', false], disabled: ['enabled', true],
28
+ checked: ['checked', false], unchecked: ['checked', true],
29
+ };
30
+
31
+ function comparison(rest: string): string | null {
32
+ if (/\bcontains?\b/.test(rest)) return '-contains';
33
+ if (/\bmatches\b/.test(rest)) return '-matches';
34
+ return /\b(?:is|equals?|with) \{\}|^ ?\{\}$/.test(rest) ? '' : null;
35
+ }
36
+
37
+ function baseMatcher(verb: string, state?: StateClause): string {
38
+ if (/^expect\b/.test(verb)) {
39
+ if (/\bmatches schema\b/.test(verb)) return 'schema';
40
+ if (RANGE.test(verb)) return 'range';
41
+ if (/\bcontains?\b/.test(verb)) return 'contains';
42
+ if (/\bmatches\b/.test(verb)) return 'matches';
43
+ return /\b(?:is|equals?)\b/.test(verb) ? 'equals' : 'unknown';
44
+ }
45
+ if (/\bin (?:local|session) storage\b/.test(verb)) {
46
+ if (/\bkey matching\b/.test(verb)) return 'key-matching';
47
+ if (/\bhas length\b/.test(verb)) return 'count';
48
+ if (/\bis not empty\b/.test(verb)) return 'state:empty';
49
+ return /\b(?:exists?|exist)\b/.test(verb) ? 'exists' : 'unknown';
50
+ }
51
+ if (/^see tab order\b/.test(verb)) return 'tab-order';
52
+ if (/\bmatch data$/.test(verb)) return 'table-data';
53
+ if (!/^(?:see|is on)\b/.test(verb)) return 'unknown';
54
+ const page = verb.match(PAGE_SUBJECT);
55
+ if (page) { const c = comparison(page[2]); return c === null ? 'unknown' : `${page[1]}${c}`; }
56
+ if (state) return STATE_AS[state]?.[0] ?? `state:${state}`;
57
+ if (/^see all \[\] contains? \[\]/.test(verb)) return 'child';
58
+ if (RANGE.test(verb)) return 'range';
59
+ if (/\bmatches \{\}/.test(verb)) return 'matches';
60
+ if (/\b(?:contains?|includes?) \{\}/.test(verb)) return 'contains';
61
+ if (/\b(?:has|have|with) (?:text|value) \{\}|\bwith \{\}/.test(verb)) return 'equals';
62
+ if (/\b(?:has|have) (?:\d+|\{\})(?: [\w-]+)?$/.test(verb)) return 'count';
63
+ if (/^is on \[\] (?:page|screen|dialog)$|^see \[\] page$/.test(verb)) return 'page';
64
+ if (/^see (?:all )?\[\](?: [\w-]+)?$/.test(verb)) return 'visible';
65
+ return 'unknown';
66
+ }
67
+
68
+ /** What an assertion sentence (the normalized `verb`) checks. `state` is the parser's trailing clause. */
69
+ export function assertShapeOf(verb: string, parsedState?: StateClause): AssertShape {
70
+ const v = verb.replace(NOT_SEE, 'see');
71
+ const state = parsedState ?? (v.match(IS_NOT_STATE)?.[1] as StateClause | undefined);
72
+ const base = baseMatcher(v, state);
73
+ const flips = state ? STATE_AS[state]?.[1] === true : false;
74
+ const negated = NEGATION.test(verb) !== flips;
75
+ const all = /^see all\b/.test(v) && base !== 'unknown';
76
+ return { matcher: all ? `all:${base}` : base, negated };
77
+ }
78
+
79
+ const STRENGTH: Record<string, number> = {
80
+ visible: 1, exists: 1,
81
+ page: 2, enabled: 2, checked: 2, contains: 2, matches: 2, range: 2, 'key-matching': 2, child: 2,
82
+ 'url-contains': 2, 'url-matches': 2, 'title-contains': 2, 'title-matches': 2,
83
+ equals: 3, count: 3, 'table-data': 3, 'tab-order': 3, schema: 3, url: 3, title: 3,
84
+ };
85
+
86
+ /** The ordinal strength of a matcher, or null when the ladder cannot judge it. */
87
+ export function matcherStrength(matcher: string | undefined): number | null {
88
+ if (!matcher || matcher === 'unknown') return null;
89
+ const all = matcher.startsWith('all:');
90
+ const base = all ? matcher.slice(4) : matcher;
91
+ const s = base.startsWith('state:') ? 2 : STRENGTH[base];
92
+ return s === undefined ? null : s + (all ? 1 : 0);
93
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * The contract verdict of one unit, BUILT BY CODE from raw inputs every time (DOS-14.0, takumi T3):
3
+ * the `.feature` files, the working lock, the lock and the approval decisions in git HEAD. No report
4
+ * file is read — the `.sungen/reports/<slug>-contract.json` that `contract check` writes is output
5
+ * only, so a hand-edited "pass" there changes nothing. The CLI and the Claude Code guard call this
6
+ * same function, so they cannot disagree.
7
+ *
8
+ * fail oracle-weakened / target-changed / assertion-lost, or any lock-uncommitted issue
9
+ * (added · changed · removed vs HEAD, tampered, unverified), or an APPROVED free /
10
+ * impl:code scenario with no admissible trace (unproven, also past the deadline) exit 2
11
+ * review any hash-changed (changed, not weaker — QA re-approves), opaque (a check no code
12
+ * can compare and QA has not accepted, or a target identity that is only `low`), or inconclusive (an
13
+ * approved free scenario's final attempt did not pass); blocks delivery exit 0
14
+ * pass only match / strengthened / proposed / nondeterministic exit 0
15
+ *
16
+ * free / impl:code scenarios are ALSO held against their recorded traces (DOS-14.6,
17
+ * build-trace-conformance.ts): the worse of the Gherkin class and the trace class wins. A
18
+ * proposed (unapproved) one's trace problems are warnings — it is not locked yet.
19
+ *
20
+ * git failing in a checkout that has .git is not "no git": with a lock present the verdict cannot be
21
+ * built (GitUnavailableError → CLI exit 1, guard `ask`); without one it is only a warning.
22
+ */
23
+ import * as fs from 'fs';
24
+ import * as path from 'path';
25
+ import { canonicalJson, sha256Hex } from './contract-hash';
26
+ import { CLI_GIT_TIMEOUT_MS, GitUnavailableError, HeadSnapshot, headSnapshot, readTextOrNull } from './contract-git';
27
+ import { HARD_CLASSES, REVIEW_CLASSES } from './contract-schema';
28
+ import { ScenarioResult, severityOf } from './classify-contract-change';
29
+ import { traceConformanceForUnit } from './build-trace-conformance';
30
+ import type { TraceOutcome } from './classify-trace-conformance';
31
+ import { classifyUnit } from './classify-contract-unit';
32
+ import { lockPathFor, parseLockText } from './contracts-lock-file';
33
+ import { compareLockWithHead, UncommittedEntry } from './lock-vs-git-head';
34
+ import { contractFeatureFiles, loadContractScenarios } from './normalize-feature-steps';
35
+ import { unverifiedApprovals } from './verify-approval-decisions';
36
+
37
+ export { classifyUnit } from './classify-contract-unit';
38
+
39
+ export interface ContractUnit { name: string; dir: string }
40
+ export type VerdictValue = 'pass' | 'review' | 'fail';
41
+
42
+ export interface ContractVerdict {
43
+ schema: 1;
44
+ unit: string;
45
+ verdict: VerdictValue;
46
+ exitCode: 0 | 2;
47
+ /** sha256 over the inputs the verdict was built from: features, working lock, lock issues. */
48
+ inputsHash: string;
49
+ scenarios: ScenarioResult[];
50
+ /** Every lock entry that is not what QA approved and committed (rule contract.lock-uncommitted). */
51
+ uncommitted: UncommittedEntry[];
52
+ warnings: string[];
53
+ }
54
+
55
+ /**
56
+ * `snapshot` lets a caller checking many units read HEAD once; `gitTimeoutMs` bounds each git call;
57
+ * `traceBudgetMs` bounds the trace part (default ~3 s for the guard; `contract check` passes more).
58
+ */
59
+ export interface VerdictOptions { snapshot?: HeadSnapshot; gitTimeoutMs?: number; traceBudgetMs?: number }
60
+
61
+ /** Fold a free / impl:code scenario's trace outcome into its Gherkin result: the worse class wins. */
62
+ function withTrace(results: ScenarioResult[], outcomes: Map<string, TraceOutcome>): ScenarioResult[] {
63
+ return results.map((r) => {
64
+ const o = outcomes.get(r.id);
65
+ if (!o) return r;
66
+ const cls = severityOf(o.class) > severityOf(r.class) ? o.class : r.class;
67
+ return { ...r, class: cls, findings: [...r.findings, ...o.findings], trace: { hashes: o.hashes, runs: o.runs, ...(o.opaque.length ? { opaque: o.opaque } : {}) } };
68
+ });
69
+ }
70
+
71
+ export function buildContractVerdict(projectRoot: string, unit: ContractUnit, opts: VerdictOptions = {}): ContractVerdict {
72
+ const snap = opts.snapshot ?? headSnapshot(projectRoot, opts.gitTimeoutMs ?? CLI_GIT_TIMEOUT_MS);
73
+ const files = contractFeatureFiles(unit.dir, unit.name);
74
+ const current = loadContractScenarios(unit.dir, unit.name);
75
+ const lockFile = lockPathFor(unit.dir);
76
+ const lockText = readTextOrNull(lockFile);
77
+ if (snap.error && lockText !== null) throw new GitUnavailableError(snap.error);
78
+ const lock = lockText === null ? null : parseLockText(lockText, lockFile);
79
+ const tampered = new Set(lock?.tampered ?? []);
80
+ const gherkin = classifyUnit(lock, current, tampered);
81
+ const traced = traceConformanceForUnit(projectRoot, unit, current, lock, tampered, { budgetMs: opts.traceBudgetMs });
82
+ const results = withTrace(gherkin.results, traced.outcomes);
83
+ const warnings = [...gherkin.warnings, ...traced.warnings];
84
+ const head = compareLockWithHead(projectRoot, lockFile, lockText, lock, snap);
85
+ if (head.status === 'no-git') {
86
+ warnings.push(snap.error
87
+ ? `git failed (${snap.error}); this unit has no lock, so nothing was compared with git HEAD`
88
+ : 'not a git checkout with a commit: the lock was not compared with git HEAD (working tree used)');
89
+ }
90
+ const uncommitted: UncommittedEntry[] = head.status === 'compared' ? [...head.uncommitted] : [];
91
+ for (const id of tampered) {
92
+ if (!uncommitted.some((u) => u.id === id)) uncommitted.push({ id, change: 'tampered', detail: 'its steps no longer hash to its `hash` — edited by hand' });
93
+ }
94
+ uncommitted.push(...unverifiedApprovals(projectRoot, unit.dir, lock, new Set(uncommitted.map((u) => u.id)), snap));
95
+
96
+ const hard = uncommitted.length > 0 || results.some((r) => HARD_CLASSES.has(r.class));
97
+ const verdict: VerdictValue = hard ? 'fail' : results.some((r) => REVIEW_CLASSES.has(r.class)) ? 'review' : 'pass';
98
+ const rel = (f: string): string => path.relative(projectRoot, f).split(path.sep).join('/');
99
+ const inputsHash = sha256Hex(canonicalJson({
100
+ features: files.map((f) => [rel(f), sha256Hex(fs.readFileSync(f, 'utf8'))]),
101
+ lock: lockText === null ? null : sha256Hex(lockText),
102
+ head: head.status,
103
+ uncommitted,
104
+ ...(traced.inputs === null ? {} : { trace: traced.inputs }),
105
+ }));
106
+ const scenarios = results.map((r) => (r.file ? { ...r, file: rel(r.file) } : r));
107
+ return { schema: 1, unit: unit.name, verdict, exitCode: verdict === 'fail' ? 2 : 0, inputsHash, scenarios, uncommitted, warnings };
108
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Trace conformance of one unit, built by code every time (DOS-14.0, 14.6; takumi T3) — the part of
3
+ * the contract verdict that only free / impl:code scenarios have. Synchronous and read-only, so
4
+ * `contract check` and the Claude Code delivery guard (both via buildContractVerdict) agree.
5
+ *
6
+ * platform mobile not supported yet: a warning, nothing judged, exit unaffected
7
+ * no free / impl:code nothing to do (the verdict is byte-identical to the Gherkin-only one)
8
+ * otherwise evidence (run records → reports → final attempts → bound traces) →
9
+ * identities (driver cache or low heuristic) → render → ONE batched
10
+ * fingerprint parse → the ladder
11
+ *
12
+ * Bounded (review H4, M2): a deadline (`budgetMs`; the guard's default is ~3 s) — a scenario not
13
+ * judged in time is `unproven` when approved, a warning while proposed: fail CLOSED. An input that
14
+ * cannot be read while judging (test-data, a trace) makes that scenario unproven with its reason,
15
+ * never a thrown verdict. A trace older than the unit's `.feature` / lock is refused (stale) — judged
16
+ * by their content, so a touch or a fresh clone stales nothing (#967, trace/trace-freshness.ts).
17
+ */
18
+ import { createHash } from 'crypto';
19
+ import * as fs from 'fs';
20
+ import { readCapabilities } from '../harness/capability';
21
+ import { classifyTraceRuns, notJudged, TraceOutcome } from './classify-trace-conformance';
22
+ import { ContractLock, ContractScenario, isHumanApproved, LockEntry } from './contract-schema';
23
+ import { loadTestDataIndex, TestDataIndex } from './data-normalize';
24
+ import { renderTraceSteps, RenderedStep } from './render-free-gherkin';
25
+ import { unitContract } from './trace/trace-freshness';
26
+ import { collectScenarioEvidence, OVER_BUDGET, ScenarioEvidence, TraceRun } from './trace/collect-trace-evidence';
27
+
28
+ export { OVER_BUDGET } from './trace/collect-trace-evidence';
29
+ import { identityCachePath, readIdentityCache } from './trace/identity-cache';
30
+ import { identitiesFor } from './trace/trace-identity-resolution';
31
+ import { fingerprintsOf, TraceFingerprint } from './trace/trace-fingerprint';
32
+ import { traceIntentSteps } from './trace/trace-steps';
33
+
34
+ export interface UnitTraceConformance { outcomes: Map<string, TraceOutcome>; warnings: string[]; inputs: unknown }
35
+
36
+ const sha = (s: string | Buffer): string => createHash('sha256').update(s).digest('hex');
37
+ const why = (e: unknown): string => (e instanceof Error ? e.message : String(e)).split('\n')[0].slice(0, 300);
38
+
39
+ export const MOBILE_NOT_SUPPORTED = 'trace conformance is web-only: free / impl:code scenarios of a mobile project are not supported yet (not judged)';
40
+ /** The Claude Code guard's deadline for the trace part of one unit's verdict (its hook has ~5 s in all). */
41
+ export const GUARD_TRACE_BUDGET_MS = 3_000;
42
+ /** The default deadline (`next`, the guard) — override: SUNGEN_TRACE_VERDICT_BUDGET_MS. */
43
+ export function defaultTraceBudgetMs(env: Record<string, string | undefined> = process.env): number {
44
+ const v = Number(env.SUNGEN_TRACE_VERDICT_BUDGET_MS);
45
+ return Number.isFinite(v) && v > 0 ? v : GUARD_TRACE_BUDGET_MS;
46
+ }
47
+ /** Inside the guard path the override may only SHORTEN the deadline (#926): the hook cannot wait longer. */
48
+ export const guardTraceBudgetMs = (env: Record<string, string | undefined> = process.env): number =>
49
+ Math.min(defaultTraceBudgetMs(env), GUARD_TRACE_BUDGET_MS);
50
+
51
+ export function traceConformanceForUnit(
52
+ projectRoot: string, unit: { name: string; dir: string }, current: ContractScenario[], lock: ContractLock | null,
53
+ untrusted: ReadonlySet<string>, opts: { budgetMs?: number } = {},
54
+ ): UnitTraceConformance {
55
+ const deadline = Date.now() + (opts.budgetMs ?? defaultTraceBudgetMs());
56
+ const traced = [...new Map(current.filter((s) => s.implementation !== 'compiled').map((s) => [s.id, s])).values()];
57
+ if (!traced.length) return { outcomes: new Map(), warnings: [], inputs: null };
58
+ if ((readCapabilities(projectRoot).platform ?? '').toLowerCase() === 'mobile') return { outcomes: new Map(), warnings: [MOBILE_NOT_SUPPORTED], inputs: { platform: 'mobile' } };
59
+
60
+ const approvedEntry = (id: string): LockEntry | undefined => { const e = lock?.scenarios[id]; return isHumanApproved(e) && !untrusted.has(id) ? e : undefined; };
61
+ const outcomes = new Map<string, TraceOutcome>();
62
+ const warnings: string[] = [];
63
+ let evidence: ScenarioEvidence = { runs: new Map(), problems: [], inputs: [] };
64
+ let index: TestDataIndex = { byValue: new Map() };
65
+ let setupError = '';
66
+ try {
67
+ evidence = collectScenarioEvidence(projectRoot, new Set(traced.map((s) => s.id)), unitContract(projectRoot, unit), deadline, new Map(traced.map((s) => [s.id, s.source.name])));
68
+ index = loadTestDataIndex(unit.dir, unit.name);
69
+ } catch (e) { setupError = `trace conformance could not run: ${why(e)}`; }
70
+ const { cache, problem } = readIdentityCache(projectRoot);
71
+ warnings.push(...evidence.problems, ...(problem ? [problem] : []));
72
+
73
+ // 1. render every admissible run (deadline checked per scenario), 2. ONE fingerprint parse, 3. ladder.
74
+ const pending: Array<{ sc: ContractScenario; runs: TraceRun[]; rendered: Map<TraceRun, RenderedStep[]> }> = [];
75
+ for (const sc of traced) {
76
+ if (setupError) { outcomes.set(sc.id, notJudged(sc.id, !!approvedEntry(sc.id), 'unproven', [setupError])); continue; }
77
+ if (Date.now() > deadline) { outcomes.set(sc.id, notJudged(sc.id, !!approvedEntry(sc.id), 'unproven', [OVER_BUDGET])); continue; }
78
+ const runs = evidence.runs.get(sc.id) ?? [];
79
+ const rendered = new Map<TraceRun, RenderedStep[]>();
80
+ try {
81
+ for (const run of runs.filter((r) => r.status === 'admissible' && r.trace)) {
82
+ const steps = traceIntentSteps(run.trace!);
83
+ rendered.set(run, renderTraceSteps(steps, identitiesFor(run.trace!, steps, cache), { index, projectRoot, specFile: run.specFile, secrets: new Set() }));
84
+ }
85
+ pending.push({ sc, runs, rendered });
86
+ } catch (e) { outcomes.set(sc.id, notJudged(sc.id, !!approvedEntry(sc.id), 'unproven', [`trace conformance failed: ${why(e)}`])); }
87
+ }
88
+ const items = pending.flatMap((p) => [...p.rendered.entries()].map(([run, rendered]) => ({ p, run, rendered, implementation: p.sc.implementation })));
89
+ let fps: TraceFingerprint[] = [];
90
+ try { fps = fingerprintsOf(items); } catch (e) {
91
+ for (const p of pending) outcomes.set(p.sc.id, notJudged(p.sc.id, !!approvedEntry(p.sc.id), 'unproven', [`trace conformance failed: ${why(e)}`]));
92
+ }
93
+ if (fps.length === items.length) {
94
+ for (const p of pending) {
95
+ const byRun = new Map(items.map((it, i) => [it, fps[i]] as const).filter(([it]) => it.p === p).map(([it, fp]) => [it.run, fp]));
96
+ outcomes.set(p.sc.id, classifyTraceRuns(p.sc.id, p.sc.implementation, approvedEntry(p.sc.id), p.runs, byRun));
97
+ }
98
+ }
99
+ for (const o of outcomes.values()) warnings.push(...o.warnings);
100
+ const cacheFile = identityCachePath(projectRoot);
101
+ const traceShas = [...evidence.runs.values()].flat().filter((r) => r.trace).map((r) => r.trace!.sha256).sort();
102
+ return { outcomes, warnings, inputs: { runs: evidence.inputs, traces: traceShas, identities: fs.existsSync(cacheFile) ? sha(fs.readFileSync(cacheFile)) : null } };
103
+ }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * One approved lock entry against the scenario as it reads now → its class on the strength ladder
3
+ * (DOS-14.4) and the findings behind it.
4
+ *
5
+ * same hash match
6
+ * assertions, paired in three passes:
7
+ * 1. identical nothing to say
8
+ * 2. same target (ref + scope) compareAsserts against the WORST candidate: weakened · strengthened · review
9
+ * 3. same sentence, other target target-changed
10
+ * left over in the lock assertion-lost left over now strengthened (new check)
11
+ * actions changed · implementation retagged · only reordered hash-changed (review)
12
+ *
13
+ * The scenario's class is its most severe finding. A change that produced no finding at all is
14
+ * still `hash-changed`: equal hashes are the only road to `match`.
15
+ */
16
+ import { sameJson } from './contract-hash';
17
+ import { ContractScenario, ContractStep, FindingClass, LadderClass, LockEntry, OpaqueStep, RULE_OF, ScenarioClass, TraceClass } from './contract-schema';
18
+ import { compareAsserts } from './oracle-strength';
19
+
20
+ export interface ContractFinding { class: FindingClass; rule?: string; detail: string; step?: number }
21
+ /** What a free / impl:code scenario's traces fingerprinted to (DOS-14.6), and their opaque steps (#923) — output only. */
22
+ export interface TraceSummary { hashes: string[]; runs: string[]; opaque?: OpaqueStep[] }
23
+ export interface ScenarioResult { id: string; class: ScenarioClass; findings: ContractFinding[]; file?: string; trace?: TraceSummary }
24
+
25
+ const SEVERITY: Record<ScenarioClass, number> = {
26
+ proposed: 0, match: 0, strengthened: 1, nondeterministic: 1, 'hash-changed': 2, opaque: 2, inconclusive: 2,
27
+ 'target-changed': 3, 'oracle-weakened': 3, 'assertion-lost': 3, unproven: 3,
28
+ };
29
+ export const severityOf = (c: ScenarioClass): number => SEVERITY[c];
30
+
31
+ export const finding = (cls: Exclude<LadderClass, 'match'> | TraceClass, detail: string, step?: number): ContractFinding =>
32
+ ({ class: cls, ...(RULE_OF[cls] ? { rule: RULE_OF[cls] } : {}), detail, ...(step ? { step } : {}) });
33
+
34
+ type Indexed = { step: ContractStep; at: number };
35
+ const asserts = (steps: ContractStep[]): Indexed[] => steps.map((step, i) => ({ step, at: i + 1 })).filter((x) => x.step.kind === 'assert');
36
+ const targetKey = (s: ContractStep): string => s.target ? `${s.target.ref}\u0000${s.target.parent ?? ''}` : `\u0001${s.verb}`;
37
+ const label = (s: ContractStep): string => s.target ? `[${s.target.ref}]${s.target.parent ? ` in ${s.target.parent}` : ''}` : `"${s.verb}"`;
38
+
39
+ function compareAssertions(locked: ContractStep[], current: ContractStep[]): ContractFinding[] {
40
+ const out: ContractFinding[] = [];
41
+ const was = asserts(locked);
42
+ const now = asserts(current);
43
+ const used = new Set<number>();
44
+ const take = (pred: (c: Indexed) => boolean): Indexed | undefined => {
45
+ const hit = now.find((c) => !used.has(c.at) && pred(c));
46
+ if (hit) used.add(hit.at);
47
+ return hit;
48
+ };
49
+ const open: Indexed[] = [];
50
+ for (const l of was) if (!take((c) => sameJson(c.step, l.step))) open.push(l);
51
+ const unpaired: Indexed[] = [];
52
+ for (const l of open) {
53
+ const candidates = now.filter((c) => !used.has(c.at) && targetKey(c.step) === targetKey(l.step));
54
+ if (!candidates.length) { unpaired.push(l); continue; }
55
+ // The WORST replacement is the one judged: picking the kindest let `see [X]` → `is hidden` +
56
+ // `is empty` read as strengthened, the inversion hiding behind a harmless extra check.
57
+ const judged = candidates.map((c) => ({ c, r: compareAsserts(l.step, c.step) }));
58
+ const rank = (k: string): number => (k === 'oracle-weakened' ? 2 : k === 'review' ? 1 : 0);
59
+ const worst = judged.sort((a, b) => rank(b.r.class) - rank(a.r.class))[0];
60
+ used.add(worst.c.at);
61
+ const cls = worst.r.class === 'review' ? 'hash-changed' : worst.r.class;
62
+ out.push(finding(cls, `${label(l.step)}: ${worst.r.detail}`, worst.c.at));
63
+ }
64
+ for (const l of unpaired) {
65
+ const moved = take((c) => c.step.verb === l.step.verb && !!l.step.target && !!c.step.target);
66
+ out.push(moved
67
+ ? finding('target-changed', `the check "${l.step.verb}" moved from ${label(l.step)} to ${label(moved.step)}`, moved.at)
68
+ : finding('assertion-lost', `the approved check ${label(l.step)} "${l.step.verb}" (step ${l.at}) is gone`));
69
+ }
70
+ for (const c of now) if (!used.has(c.at)) out.push(finding('strengthened', `new check ${label(c.step)} "${c.step.verb}"`, c.at));
71
+ return out;
72
+ }
73
+
74
+ export function classifyScenario(id: string, entry: LockEntry, current: ContractScenario | undefined): ScenarioResult {
75
+ if (!current) {
76
+ return { id, class: 'assertion-lost', findings: [finding('assertion-lost', 'the approved scenario is no longer in the feature (removed, its ID changed, or made @manual)')] };
77
+ }
78
+ const base = { id, file: current.source.file };
79
+ if (current.hash === entry.hash) return { ...base, class: 'match', findings: [] };
80
+ const findings = compareAssertions(entry.steps, current.steps);
81
+ if (entry.implementation !== current.implementation) {
82
+ findings.push(finding('hash-changed', `implementation path changed: ${entry.implementation} → ${current.implementation} (retag)`));
83
+ }
84
+ const actionsOf = (steps: ContractStep[]) => steps.filter((s) => s.kind === 'action');
85
+ if (!sameJson(actionsOf(entry.steps), actionsOf(current.steps))) findings.push(finding('hash-changed', 'the actions changed (what the test does before it checks)'));
86
+ if (!findings.length) findings.push(finding('hash-changed', 'the steps changed without a weaker or stronger check (e.g. reordered)'));
87
+ const worst = findings.reduce<ScenarioClass>((acc, f) => {
88
+ const c = f.class as ScenarioClass;
89
+ return severityOf(c) > severityOf(acc) ? c : acc;
90
+ }, 'match');
91
+ return { ...base, class: worst, findings };
92
+ }