@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,130 @@
1
+ /**
2
+ * Which Bash segments only READ, so they may name a protected path freely (bash-protected-mention).
3
+ *
4
+ * An allowlist, fail-closed (#968): a command is read-only only in the forms listed here. It drops
5
+ * back to "the guard cannot tell" when
6
+ * - the command word has a `/` outside the system bin dirs (`./cat`, `/tmp/evil/jq`),
7
+ * - a word holds `$`, `{`, `*`, `?` or `[` (`$'--output'`, `${…}`, `--{output=…,stat}`, a `q*` glob can
8
+ * hide an option name or a path),
9
+ * - an option runs a program or writes a file, also abbreviated where the tool accepts that
10
+ * (`rg --pre`, `git diff --output` / `--outp`, ugrep's `grep --filter` / `--save-config` / `--pager`
11
+ * / `--config`, `sort -o` / `--o…` / `--c…`),
12
+ * - git has any global option before its subcommand except `--no-pager` / `-P` / `--no-optional-locks`
13
+ * (`-c`, `--config-env`, `--exec-path`, `-C`, `--git-dir`… can point it at another program),
14
+ * - its output is piped into anything that is not a read-only command or filter (`| xargs rm`, `| sh`).
15
+ * And the whole LINE loses the exemption (lineKeepsReadOnlyExemption) when it uses command
16
+ * substitution or changes shell state that a later command obeys: any `NAME=value`, `export`,
17
+ * `declare`, `typeset`, `set`, `setopt`, `shopt`, `alias`, `unalias`, `hash`, `unset`, `read`,
18
+ * `enable`, `builtin`, `trap`, `source` / `.`, `eval`, or a function definition.
19
+ * `git grep` is not read-only at all: `-O` runs a program, also inside a flag cluster (`-nOrm`) and
20
+ * as an abbreviation (`--open=`). `node -e|-p` counts only when its script can do nothing but read
21
+ * (isReadOnlyNodeEval).
22
+ *
23
+ * Accepted floor, not closed here: `sungen` is listed read-only (it writes approval records only
24
+ * through its own human gates); a path built at runtime (`$VAR` away from a protected name), a
25
+ * symlink, or a script that writes without naming the path is out of reach; a bare directory
26
+ * (`rm -rf qa/decisions`, `cd qa && rm -rf decisions/`) is not a protected-path mention (#970);
27
+ * `git -C <dir> …` is not followed; a same-line `D=qa/decisions; … $D` is not tracked; pathless
28
+ * destructive git (`clean -fdx`, `stash`, `reset --hard`, `checkout .`, `apply`, `am`) is not seen;
29
+ * and a quoting trick the tokenizer reads differently from the shell can turn a deny into an ask.
30
+ * The backstop is release-time decision integrity: the git HEAD comparison and the in-run rule.
31
+ */
32
+ import * as path from 'path';
33
+ import type { BashSegment } from './bash-write-targets';
34
+
35
+ const READ_ONLY = new Set(['cat', 'ls', 'head', 'tail', 'grep', 'rg', 'wc', 'diff', 'stat', 'jq', 'sungen', 'sungen.js']);
36
+ const GIT_READ_ONLY = new Set(['diff', 'log', 'show', 'status', 'check-ignore', 'ls-files', 'ls-tree', 'blame', 'rev-parse', 'cat-file']);
37
+ /** The only git global options allowed before a read-only subcommand. */
38
+ const GIT_SAFE_GLOBALS = new Set(['--no-pager', '-P', '--no-optional-locks']);
39
+ /** Filters that write only to stdout — safe as a pipe sink, in the forms isPipeFilter allows. */
40
+ const FILTERS = new Set(['sort', 'uniq', 'cut', 'tr']);
41
+
42
+ /** A command word with a `/` counts only from these dirs: `./cat` or `/tmp/evil/jq` is not `cat` / `jq`. */
43
+ const SYSTEM_BIN = new Set(['/usr/bin', '/bin', '/usr/local/bin', '/opt/homebrew/bin']);
44
+ /** Characters that let the shell build a word the guard cannot read: expansions, braces, globs. */
45
+ const OPAQUE_WORD = /[$*?[{]/;
46
+
47
+ /** Is `word` the long option `--<one of names>`, or an abbreviation of one at least `min` chars long? */
48
+ const longOpt = (names: string[], min: number) => (word: string): boolean => {
49
+ const m = /^--([^=]+)/.exec(word);
50
+ return !!m && names.some((n) => n === m[1] || (m[1].length >= min && n.startsWith(m[1])));
51
+ };
52
+ /** Options that make an otherwise read-only command run a program or write a file. */
53
+ const UNSAFE_OPT: Record<string, (word: string) => boolean> = {
54
+ rg: (w) => /^--(?:pre|hostname-bin)(?:=|$)/.test(w),
55
+ git: longOpt(['output', 'ext-diff', 'textconv'], 2),
56
+ // `grep` may be ugrep: --filter runs programs, --save-config writes, --pager / --view run one, --config / ---FILE load those
57
+ grep: (w) => w.startsWith('---') || longOpt(['filter', 'save-config', 'pager', 'view', 'config'], 3)(w),
58
+ };
59
+ const trustedWords = (seg: BashSegment): boolean =>
60
+ !seg.assigns.length && !seg.words.some((w) => OPAQUE_WORD.test(w))
61
+ && (!seg.cmdPath.includes('/') || SYSTEM_BIN.has(path.posix.dirname(seg.cmdPath)));
62
+
63
+ /** `$(…)`, backticks, `<(…)`, `>(…)`: a command's output becomes another command's words. */
64
+ const SUBSTITUTION = /\$\(|`|[<>]\(/;
65
+ /** Commands that change shell state a later command on the line obeys. */
66
+ const SHELL_STATE = new Set([
67
+ 'export', 'declare', 'typeset', 'local', 'readonly', 'set', 'setopt', 'shopt', 'alias', 'unalias', 'hash', 'unset',
68
+ 'read', 'enable', 'builtin', 'trap', 'source', '.', 'eval', 'function',
69
+ ]);
70
+ /** `name() {` / `name() (` — a function definition (`function name` is caught by SHELL_STATE). */
71
+ const FUNCTION_DEF = /(?:^|[\s;&|])[\w.:-]+\s*\(\s*\)\s*[{(]/;
72
+
73
+ /** May any read-only segment of this line keep its exemption? */
74
+ export function lineKeepsReadOnlyExemption(command: string, segs: BashSegment[]): boolean {
75
+ return !SUBSTITUTION.test(command) && !FUNCTION_DEF.test(command)
76
+ && !segs.some((s) => s.assigns.length || SHELL_STATE.has(s.cmd));
77
+ }
78
+
79
+ /** `node -e` / `node -p` whose script can only read: no write/exec API, no computed access, no escapes. */
80
+ const NODE_EVAL_FLAGS = new Set(['-e', '-p', '--eval', '--print']);
81
+ const NODE_UNSAFE = new RegExp([
82
+ '[`\\[\\\\]', // template literals, computed property access, string escapes
83
+ 'flag', // `readFileSync(p, { flag: 'w' })` truncates p
84
+ 'write', 'append', '\\brm', 'unlink', 'rename', 'copy', '\\bcp', 'mkd', 'truncate', 'stream', 'open', 'link',
85
+ 'chmod', 'chown', 'utime', 'exec', 'spawn', 'fork', 'child', 'eval', 'function', 'import', 'constructor',
86
+ 'proto', 'reflect', 'proxy', 'global', 'process', 'module', 'object', 'concat', '\\bvm\\b', 'worker', 'binding',
87
+ ].join('|'), 'i');
88
+ const SAFE_REQUIRE = /\brequire\(\s*(['"])(?:(?:node:)?(?:fs|path)|[./][^'"]*\.json)\1\s*\)/g;
89
+
90
+ export function isReadOnlyNodeEval(args: string[]): boolean {
91
+ if (args.length !== 2 || !NODE_EVAL_FLAGS.has(args[0])) return false;
92
+ const script = args[1];
93
+ return !NODE_UNSAFE.test(script) && !/\brequire\b/.test(script.replace(SAFE_REQUIRE, ''));
94
+ }
95
+
96
+ /** `git [--no-pager|-P|--no-optional-locks]… <read-only subcommand> …` — anchored, no other global option. */
97
+ function isReadOnlyGit(words: string[]): boolean {
98
+ let k = 0;
99
+ while (GIT_SAFE_GLOBALS.has(words[k])) k++;
100
+ return GIT_READ_ONLY.has(words[k] ?? '');
101
+ }
102
+
103
+ /** Does this segment only read? (`words` holds its arguments and redirection targets.) */
104
+ export function isReadOnlySegment(seg: BashSegment): boolean {
105
+ if (!seg.cmd || !trustedWords(seg)) return false;
106
+ const unsafe = UNSAFE_OPT[seg.cmd];
107
+ if (unsafe && seg.words.some(unsafe)) return false;
108
+ if (seg.cmd === 'git') return isReadOnlyGit(seg.words);
109
+ if (seg.cmd === 'node') return isReadOnlyNodeEval(seg.words);
110
+ return READ_ONLY.has(seg.cmd);
111
+ }
112
+
113
+ /** A pipe sink that cannot act on what it reads: a read-only command, or a stdout-only filter. */
114
+ function isPipeFilter(seg: BashSegment): boolean {
115
+ if (isReadOnlySegment(seg)) return true;
116
+ if (!FILTERS.has(seg.cmd) || !trustedWords(seg)) return false;
117
+ // `sort -o out` / `--compress-program=…` (any `--o…` / `--c…` abbreviation) write or run; `uniq in out` writes its second operand.
118
+ if (seg.cmd === 'sort') return !seg.words.some((w) => /^(?:-[^-]*o|--[oc])/.test(w));
119
+ if (seg.cmd === 'uniq') return seg.words.every((w) => w.startsWith('-'));
120
+ return true; // cut, tr: operands are inputs or character sets
121
+ }
122
+
123
+ /** Does everything downstream of segment `i` in its pipeline only read / filter? */
124
+ export function pipelineStaysReadOnly(segs: BashSegment[], i: number): boolean {
125
+ for (let j = i; segs[j]?.pipesTo; j++) {
126
+ const next = segs[j + 1];
127
+ if (!next || !isPipeFilter(next)) return false;
128
+ }
129
+ return true;
130
+ }
@@ -0,0 +1,195 @@
1
+ /**
2
+ * The files a Bash command line WRITES through the three forms the pre-tool guard covers (P0.1):
3
+ * output redirection (`>`, `>>`, `>|`, `&>`, `2>`, `>&file`, zsh `>!`…), `tee`, in-place `sed -i`, and
4
+ * `git … --output <file>` (also abbreviated, `--outp=`) (#968).
5
+ *
6
+ * A floor, not a shell interpreter: quotes, escapes, `$'…'` ANSI-C strings, backslash-newline
7
+ * continuations, `;`/`&&`/`||`/`|` and `cd` / `pushd` (with their options; an operand it cannot resolve
8
+ * marks the directory unknown) are understood; anything else that can write a file (`cp`, a script, `python -c`) is out of scope by
9
+ * design. The command string is untrusted — it is only tokenized here, never executed.
10
+ */
11
+ import * as path from 'path';
12
+
13
+ type Tok = { kind: 'word'; value: string } | { kind: 'sep'; pipe?: boolean } | { kind: 'redir'; writes: boolean; dup?: boolean };
14
+
15
+ /** Commands that run another command: the real one is the next word. */
16
+ const WRAPPERS = new Set(['sudo', 'env', 'command', 'nohup', 'time', 'exec', 'nice']);
17
+ const ASSIGNMENT = /^[A-Za-z_]\w*=/;
18
+ const ANSI_C: Record<string, string> = {
19
+ a: '\x07', b: '\b', e: '\x1b', E: '\x1b', f: '\f', n: '\n', r: '\r', t: '\t', v: '\v', '\\': '\\', "'": "'", '"': '"', '?': '?',
20
+ };
21
+
22
+ /** Decode a bash `$'…'` body starting at `j` (just past `$'`); returns the text and the index past the closing `'`. */
23
+ function ansiC(cmd: string, j: number): [string, number] {
24
+ let out = '';
25
+ while (j < cmd.length && cmd[j] !== "'") {
26
+ if (cmd[j] !== '\\' || j + 1 >= cmd.length) { out += cmd[j++]; continue; }
27
+ const e = cmd[j + 1];
28
+ j += 2;
29
+ if (e in ANSI_C) out += ANSI_C[e];
30
+ else if (/[0-7]/.test(e)) {
31
+ let m = e;
32
+ while (m.length < 3 && /[0-7]/.test(cmd[j] ?? '')) m += cmd[j++];
33
+ out += String.fromCharCode(parseInt(m, 8) & 0xff);
34
+ } else if (e === 'x' || e === 'u' || e === 'U') {
35
+ const max = e === 'x' ? 2 : e === 'u' ? 4 : 8;
36
+ let h = '';
37
+ while (h.length < max && /[0-9a-fA-F]/.test(cmd[j] ?? '')) h += cmd[j++];
38
+ const cp = parseInt(h, 16);
39
+ out += !h ? `\\${e}` : cp <= 0x10ffff ? String.fromCodePoint(cp) : '\ufffd'; // never throw: a throw fails open
40
+ } else if (e === 'c' && j < cmd.length) out += String.fromCharCode(cmd.charCodeAt(j++) & 31);
41
+ else out += `\\${e}`;
42
+ }
43
+ return [out, j + 1];
44
+ }
45
+
46
+ function tokenize(cmd: string): Tok[] {
47
+ const toks: Tok[] = [];
48
+ let word = '';
49
+ let inWord = false;
50
+ const flush = (): void => { if (inWord) toks.push({ kind: 'word', value: word }); word = ''; inWord = false; };
51
+ for (let i = 0; i < cmd.length;) {
52
+ const ch = cmd[i];
53
+ if (ch === '$' && cmd[i + 1] === "'") {
54
+ const [text, next] = ansiC(cmd, i + 2);
55
+ word += text; inWord = true; i = next;
56
+ } else if (ch === '$' && cmd[i + 1] === '"') {
57
+ i++; // `$"…"` (locale translation) reads as `"…"`
58
+ } else if (ch === "'") {
59
+ const end = cmd.indexOf("'", i + 1);
60
+ word += cmd.slice(i + 1, end < 0 ? cmd.length : end); inWord = true; i = end < 0 ? cmd.length : end + 1;
61
+ } else if (ch === '"') {
62
+ let j = i + 1;
63
+ for (; j < cmd.length && cmd[j] !== '"'; j++) {
64
+ if (cmd[j] === '\\' && cmd[j + 1] === '\n') { j++; continue; } // line continuation
65
+ if (cmd[j] === '\\' && j + 1 < cmd.length) j++;
66
+ word += cmd[j];
67
+ }
68
+ inWord = true; i = j + 1;
69
+ } else if (ch === '\\' && cmd[i + 1] === '\n') {
70
+ i += 2; // line continuation: removed entirely
71
+ } else if (ch === '\\' && i + 1 < cmd.length) {
72
+ word += cmd[i + 1]; inWord = true; i += 2;
73
+ } else if (ch === ' ' || ch === '\t') {
74
+ flush(); i++;
75
+ } else if ('\n;|()'.includes(ch) || (ch === '&' && cmd[i + 1] !== '>')) {
76
+ const doubled = (ch === '|' || ch === '&') && cmd[i + 1] === ch;
77
+ flush(); toks.push({ kind: 'sep', pipe: ch === '|' && !doubled }); i += doubled ? 2 : 1;
78
+ } else if (ch === '>' || (ch === '&' && cmd[i + 1] === '>')) {
79
+ if (ch === '>' && inWord && /^\d+$/.test(word)) { word = ''; inWord = false; } else flush(); // `2>`: an fd, not a word
80
+ i += ch === '&' ? 2 : 1;
81
+ if (cmd[i] === '>') i++; // `>>`, `&>>`
82
+ const dup = cmd[i] === '&'; // `>&x`, `>>&x`: an fd dup only when x is an fd
83
+ if (dup) i++;
84
+ if (cmd[i] === '|' || cmd[i] === '!') i++; // clobber: `>|`, `>!`, `>>!`, `&>!`, `>&|`, `>&!`
85
+ toks.push({ kind: 'redir', writes: true, dup });
86
+ } else if (ch === '<') {
87
+ flush(); i++;
88
+ while (cmd[i] === '<') i++;
89
+ toks.push({ kind: 'redir', writes: false });
90
+ } else {
91
+ word += ch; inWord = true; i++;
92
+ }
93
+ }
94
+ flush();
95
+ return toks;
96
+ }
97
+
98
+ const isInPlaceFlag = (a: string): boolean => a === '--in-place' || a.startsWith('--in-place=') || /^-[a-zA-Z]*i/.test(a);
99
+
100
+ /** One simple command of a Bash line (`a | b && c` is three). */
101
+ export interface BashSegment {
102
+ /** The command name (basename, after env assignments and wrappers like `sudo`), or ''. */
103
+ cmd: string;
104
+ /** The command word as written (`./cat`, `/usr/bin/grep`, `cat`). */
105
+ cmdPath: string;
106
+ /** Its arguments, and every redirection target, as written. */
107
+ words: string[];
108
+ /** The directory it runs in — a preceding `cd` in the same line is followed. */
109
+ dir: string;
110
+ /** Absolute paths it writes via redirection, `tee`, `sed -i` or `git … --output`. */
111
+ writes: string[];
112
+ /** False once a `cd` / `pushd` / `popd` on the line went somewhere the guard cannot resolve. */
113
+ dirKnown: boolean;
114
+ /** It writes a relative path while `dirKnown` is false — the guard cannot tell where. */
115
+ writesInUnknownDir: boolean;
116
+ /** Leading `NAME=value` assignments (a lone `X=…` is a segment too, with cmd ''). */
117
+ assigns: string[];
118
+ /** Its stdout feeds the next segment through `|`. */
119
+ pipesTo: boolean;
120
+ }
121
+
122
+ /** `git diff|log|show … --output=<file>` / `--output <file>` writes that file (git takes `--outp` for `--output`). */
123
+ function gitOutputTargets(args: string[]): string[] {
124
+ const out: string[] = [];
125
+ args.forEach((a, k) => {
126
+ const m = /^--([\w-]+)(=([\s\S]*))?$/.exec(a);
127
+ if (!m || m[1].length < 2 || !'output'.startsWith(m[1])) return;
128
+ if (m[2] !== undefined) out.push(m[3]);
129
+ else if (args[k + 1]) out.push(args[k + 1]);
130
+ });
131
+ return out.filter((t) => t && t !== '/dev/null' && t !== '-');
132
+ }
133
+
134
+ /** The operand of `cd` / `pushd` after its options (`-L -P -e -@`, pushd `-n`, `--`), or null when there is not exactly one. */
135
+ function cdOperand(args: string[]): string | null {
136
+ let k = 0;
137
+ while (k < args.length && /^-[LPe@n]+$/.test(args[k])) k++;
138
+ if (args[k] === '--') k++;
139
+ return args.length - k === 1 ? args[k] : null;
140
+ }
141
+
142
+ export function bashSegments(command: string, cwd: string): BashSegment[] {
143
+ const out: BashSegment[] = [];
144
+ const toks = tokenize(command);
145
+ let dir = cwd;
146
+ let dirKnown = true;
147
+ let seg: string[] = [];
148
+ let redirected: string[] = [];
149
+ let rawWrites: string[] = [];
150
+ const endSegment = (pipesTo = false): void => {
151
+ let k = 0;
152
+ while (k < seg.length && (ASSIGNMENT.test(seg[k]) || WRAPPERS.has(seg[k]))) k++;
153
+ const assigns = seg.slice(0, k).filter((w) => ASSIGNMENT.test(w));
154
+ const cmdPath = seg[k] ?? '';
155
+ const cmd = path.basename(cmdPath);
156
+ const args = seg.slice(k + 1).filter((a) => a !== '');
157
+ if (cmd === 'tee') rawWrites.push(...args.filter((a) => !a.startsWith('-')));
158
+ else if ((cmd === 'sed' || cmd === 'gsed') && args.some(isInPlaceFlag)) rawWrites.push(...args.filter((a) => !a.startsWith('-')));
159
+ else if (cmd === 'git') rawWrites.push(...gitOutputTargets(args));
160
+ const writes = rawWrites.map((a) => path.resolve(dir, a));
161
+ const writesInUnknownDir = !dirKnown && rawWrites.some((a) => !path.isAbsolute(a));
162
+ if (cmd || redirected.length || assigns.length) {
163
+ out.push({ cmd, cmdPath, words: [...args, ...redirected], dir, dirKnown, writes, writesInUnknownDir, assigns, pipesTo });
164
+ }
165
+ if (cmd === 'cd' || cmd === 'pushd' || cmd === 'popd') {
166
+ const target = cmd === 'popd' ? null : cdOperand(args);
167
+ if (target && !/[$~`]/.test(target) && target !== '-' && !/^[+-]\d+$/.test(target)) {
168
+ dir = path.resolve(dir, target);
169
+ dirKnown = dirKnown || path.isAbsolute(target);
170
+ } else dirKnown = false; // `cd`, `cd ~`, `cd $D`, `cd -`, `popd`: somewhere the guard cannot resolve
171
+ }
172
+ seg = []; redirected = []; rawWrites = [];
173
+ };
174
+ for (let t = 0; t < toks.length; t++) {
175
+ const tok = toks[t];
176
+ if (tok.kind === 'sep') { endSegment(tok.pipe === true); continue; }
177
+ if (tok.kind === 'redir') {
178
+ const target = toks[t + 1];
179
+ if (target?.kind !== 'word') continue;
180
+ t++;
181
+ redirected.push(target.value);
182
+ const fd = tok.dup && /^(?:\d+-?|-)$/.test(target.value); // `2>&1`, `>&2`, `2>&-`
183
+ if (tok.writes && !fd && target.value && target.value !== '/dev/null' && target.value !== '-') rawWrites.push(target.value);
184
+ continue;
185
+ }
186
+ seg.push(tok.value);
187
+ }
188
+ endSegment();
189
+ return out;
190
+ }
191
+
192
+ /** Absolute paths the command writes via redirection, `tee`, `sed -i` or `git --output`, resolved against `cwd`. */
193
+ export function bashWriteTargets(command: string, cwd: string): string[] {
194
+ return bashSegments(command, cwd).flatMap((s) => s.writes);
195
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Claude Code → sungen hook bridge (P0.1). Three ways in, one behaviour:
3
+ *
4
+ * node dist/hooks/claude-hook-entry.js <hook> executed directly (`require.main` branch)
5
+ * .claude/hooks/sungen-hook.cjs <hook> the project launcher `require`s this, calls main
6
+ * sungen hook <hook> the hidden CLI command (debugging, dev checkouts)
7
+ *
8
+ * Reads the event JSON on stdin, runs the hook through `runHook` (toggles + fail-open), and prints
9
+ * the Claude Code JSON on stdout. Exit code is ALWAYS 0 and anything unexpected prints `{}`: a hook
10
+ * error must never block or derail a session. The payload is untrusted — it is parsed as JSON and
11
+ * read field by field, never executed.
12
+ */
13
+ import * as path from 'path';
14
+ import { ClaudeHookEvent, HookContext, HookInput, runHook, runHookOnUnreadableInput, toClaudeStdout } from './hook-result-contract';
15
+ import { loadHook } from './hook-registry';
16
+ import { hooksKilled } from './hook-toggles';
17
+
18
+ /**
19
+ * Payloads above this are not parsed. Not a free pass either: a hook declares what an unreadable
20
+ * payload means (`onUnreadableInput`) — the guard asks, the advisory hooks stay quiet.
21
+ */
22
+ const MAX_PAYLOAD_BYTES = 5 * 1024 * 1024;
23
+ /** A hook whose stdin never closes still answers (as a no-op) well inside its timeout. */
24
+ const STDIN_TIMEOUT_MS = 2000;
25
+
26
+ export function parsePayload(raw: string): HookInput {
27
+ try {
28
+ const v: unknown = JSON.parse(raw);
29
+ return v && typeof v === 'object' && !Array.isArray(v) ? (v as HookInput) : {};
30
+ } catch { return {}; }
31
+ }
32
+
33
+ export function contextFor(input: HookInput, env: Record<string, string | undefined>): HookContext {
34
+ const cwd = typeof input.cwd === 'string' && path.isAbsolute(input.cwd) ? input.cwd : env.CLAUDE_PROJECT_DIR || process.cwd();
35
+ return { env, cwd };
36
+ }
37
+
38
+ /**
39
+ * What to print for this hook and raw payload — pure apart from the hook's own reads. `oversize`
40
+ * means the payload was too large to read at all.
41
+ */
42
+ export function dispatch(hookName: string, raw: string, env: Record<string, string | undefined>, oversize = false): string {
43
+ if (hooksKilled(env)) return '{}';
44
+ const hook = loadHook(hookName);
45
+ if (!hook) return '{}';
46
+ if (oversize) return toClaudeStdout(hook.meta.events[0], runHookOnUnreadableInput(hook, contextFor({}, env)));
47
+ const input = parsePayload(raw);
48
+ const event = typeof input.hook_event_name === 'string' ? input.hook_event_name : hook.meta.events[0];
49
+ if (!hook.meta.events.includes(event as ClaudeHookEvent)) return '{}';
50
+ return toClaudeStdout(event, runHook(hook, input, contextFor(input, env)));
51
+ }
52
+
53
+ function readStdin(): Promise<{ raw: string; oversize: boolean }> {
54
+ return new Promise((resolve) => {
55
+ if (process.stdin.isTTY) { resolve({ raw: '', oversize: false }); return; }
56
+ let size = 0;
57
+ const chunks: Buffer[] = [];
58
+ const done = (raw: string, oversize = false): void => {
59
+ clearTimeout(timer); process.stdin.removeAllListeners(); process.stdin.destroy(); resolve({ raw, oversize });
60
+ };
61
+ const timer = setTimeout(() => done(''), STDIN_TIMEOUT_MS);
62
+ process.stdin.on('data', (c: Buffer) => {
63
+ size += c.length;
64
+ if (size > MAX_PAYLOAD_BYTES) done('', true); else chunks.push(c);
65
+ });
66
+ process.stdin.on('end', () => done(Buffer.concat(chunks).toString('utf8')));
67
+ process.stdin.on('error', () => done(''));
68
+ });
69
+ }
70
+
71
+ /** Run one hook end to end. Resolves once stdout has flushed; never rejects. */
72
+ export async function main(hookName: string = process.argv[2] ?? ''): Promise<void> {
73
+ let out = '{}';
74
+ try {
75
+ const { raw, oversize } = await readStdin();
76
+ out = dispatch(hookName, raw, process.env, oversize);
77
+ } catch { out = '{}'; }
78
+ await new Promise<void>((resolve) => process.stdout.write(`${out}\n`, () => resolve()));
79
+ process.exitCode = 0;
80
+ }
81
+
82
+ if (require.main === module) {
83
+ // Exit explicitly once flushed: a stray handle must not keep a hook alive into its timeout.
84
+ void main().then(() => process.exit(0), () => process.exit(0));
85
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * What happened in the turn that just ended, read from the tail of Claude Code's transcript.
3
+ *
4
+ * The Stop hook must not nag every turn of every conversation in a sungen project — only a turn
5
+ * that ran sungen work and then ended without handing back. The transcript (JSONL) answers both:
6
+ * walk back from its end to the human prompt that opened the turn, noting sungen activity and any
7
+ * AskUserQuestion that came after it.
8
+ *
9
+ * The transcript is untrusted data: each line is JSON-parsed and inspected as strings. Nothing in
10
+ * it is ever executed.
11
+ */
12
+ import * as fs from 'fs';
13
+ import * as path from 'path';
14
+
15
+ export interface TurnSummary {
16
+ /** The turn ran sungen: a `/sungen:` prompt, a Bash call running `sungen`, a sungen skill. */
17
+ sungenActivity: boolean;
18
+ /** An AskUserQuestion came AFTER the last sungen activity — the turn already handed back. */
19
+ askedAfter: boolean;
20
+ /** The last unit a sungen call named (`--screen x`, `/sungen:create-test x`). */
21
+ lastUnit?: string;
22
+ }
23
+
24
+ /** Enough for any realistic turn; a transcript can be many MB and the hook has a time budget. */
25
+ const TAIL_BYTES = 512 * 1024;
26
+ const SUNGEN_BASH = /(?:^|[\s;&|(])(?:\S*\/)?sungen(?:\.js)?\s+[a-z]/;
27
+ const UNIT_FLAG = /--(?:screen|flow|area|api)[= ]([\w.-]+(?:\/[\w.-]+)?)/g;
28
+ /** `/sungen:<cmd>` typed, or as Claude Code records it; the unit argument is optional. */
29
+ const SLASH = /\/sungen:[a-z-]+(?:(?:<\/command-name>[\s\S]*?<command-args>|[ \t]+)([\w.-]+))?/;
30
+
31
+ type Block = { type?: unknown; name?: unknown; input?: unknown; text?: unknown };
32
+ type Entry = { type?: unknown; isMeta?: unknown; message?: { role?: unknown; content?: unknown } };
33
+
34
+ function readTail(file: string): string[] {
35
+ const fd = fs.openSync(file, 'r');
36
+ try {
37
+ const size = fs.fstatSync(fd).size;
38
+ const start = Math.max(0, size - TAIL_BYTES);
39
+ const buf = Buffer.alloc(size - start);
40
+ // Only the bytes actually read: a transcript truncated between fstat and read must not leave
41
+ // zero-filled garbage at the end of the buffer.
42
+ const read = fs.readSync(fd, buf, 0, buf.length, start);
43
+ const lines = buf.subarray(0, read).toString('utf8').split('\n');
44
+ return start > 0 ? lines.slice(1) : lines; // the first line of a cut tail is partial
45
+ } finally { fs.closeSync(fd); }
46
+ }
47
+
48
+ const lastUnitIn = (s: string): string | undefined => [...s.matchAll(UNIT_FLAG)].pop()?.[1];
49
+
50
+ /** The human prompt's text, or null when this user entry is a tool result or injected meta. */
51
+ function promptText(e: Entry): string | null {
52
+ if (e.type !== 'user' || e.isMeta === true || e.message?.role !== 'user') return null;
53
+ const c = e.message.content;
54
+ if (typeof c === 'string') return c;
55
+ if (!Array.isArray(c)) return null;
56
+ const text = (c as Block[]).filter((b) => b?.type === 'text' && typeof b.text === 'string').map((b) => b.text as string);
57
+ return text.length ? text.join('\n') : null;
58
+ }
59
+
60
+ /** Summarize the last turn, or null when the transcript cannot be read (callers fail open). */
61
+ export function summarizeTurn(transcriptPath: unknown): TurnSummary | null {
62
+ if (typeof transcriptPath !== 'string' || !path.isAbsolute(transcriptPath)) return null;
63
+ let lines: string[];
64
+ try { lines = readTail(transcriptPath); } catch { return null; }
65
+
66
+ const turn: TurnSummary = { sungenActivity: false, askedAfter: false };
67
+ // Walking backwards, the first unit seen is the most recently named one.
68
+ const sawSungen = (unit?: string): void => {
69
+ turn.lastUnit ??= unit;
70
+ turn.sungenActivity = true;
71
+ };
72
+ for (let i = lines.length - 1; i >= 0; i--) {
73
+ let e: Entry;
74
+ try { e = JSON.parse(lines[i]) as Entry; } catch { continue; }
75
+ if (!e || typeof e !== 'object') continue;
76
+ const prompt = promptText(e);
77
+ if (prompt !== null) {
78
+ const m = prompt.match(SLASH);
79
+ if (m) sawSungen(m[1]);
80
+ break; // the turn starts here
81
+ }
82
+ if (e.type !== 'assistant' || !Array.isArray(e.message?.content)) continue;
83
+ const blocks = e.message!.content as Block[];
84
+ for (let j = blocks.length - 1; j >= 0; j--) {
85
+ const b = blocks[j];
86
+ if (b?.type !== 'tool_use' || !b.input || typeof b.input !== 'object') continue;
87
+ const input = b.input as Record<string, unknown>;
88
+ if (b.name === 'AskUserQuestion') { if (!turn.sungenActivity) turn.askedAfter = true; continue; }
89
+ const cmd = typeof input.command === 'string' ? input.command : '';
90
+ if (b.name === 'Bash' && SUNGEN_BASH.test(cmd)) sawSungen(lastUnitIn(cmd));
91
+ else if (b.name === 'SlashCommand' && cmd.includes('/sungen:')) sawSungen(cmd.match(SLASH)?.[1]);
92
+ else if (b.name === 'Skill' && typeof input.skill === 'string' && input.skill.startsWith('sungen')) sawSungen();
93
+ }
94
+ }
95
+ return turn;
96
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Guard rule `delivery-contract-verdict` (phase 06, OES-12.3, DOS-14.4, takumi T4): Claude Code may
3
+ * not run `sungen delivery` while a delivered unit's Test Contract verdict is not `pass`.
4
+ *
5
+ * - the verdict is REBUILT from .feature + lock + git HEAD (buildContractVerdict); the report file
6
+ * is never read, so a hand-edited "pass" there is ignored
7
+ * - which units: those `delivery` itself would deliver (contract-units.ts) — every candidate of an
8
+ * ambiguous name, api flows included; bare `delivery`, a runner (`npx`, `pnpm dlx`, `tsx`, `node`…)
9
+ * whose sungen cannot be named, or a `bash -c` / `eval` wrapper → every unit
10
+ * - recognized: `sungen`, `sungen.js`, `@scope/sungen@1.2.3`, `sungen@latest`; `delivery --check`
11
+ * (writes nothing) is allowed; a unit with no lock in the tree or in HEAD is skipped
12
+ * - git runs with a ≈3 s timeout (the hook's own budget is 5 s); git failing while a lock exists,
13
+ * or any other read error, → `ask` (onError), never a silent pass
14
+ * - the command is only tokenized, never executed; unit names are matched against directories
15
+ *
16
+ * The contract module loads only when a command mentions both `sungen` (or a runner) and `delivery`,
17
+ * so every other Edit/Write/Bash call pays nothing for this rule.
18
+ */
19
+ import * as path from 'path';
20
+ import type { HookResult } from './hook-result-contract';
21
+ import { bashSegments } from './bash-write-targets';
22
+ import type { GuardRule } from './guard-rules';
23
+ import { findSungenRoot } from './sungen-project-root';
24
+
25
+ const SUNGEN = /^sungen(?:\.js)?(?:@[^/]*)?$/;
26
+ const RUNNERS = new Set(['npx', 'pnpm', 'yarn', 'bunx', 'bun', 'npm', 'tsx', 'ts-node', 'node', 'deno']);
27
+ /** delivery options that take a value (commander would consume the next word). */
28
+ const VALUE_OPTS = new Set(['--env', '--format', '--approve']);
29
+ const READ_ONLY_OPTS = new Set(['--check', '--help', '-h']);
30
+ const WRAPPED = /\b(?:bash|sh|zsh|dash|eval|xargs)\b/;
31
+ const MENTION = /\bsungen\b[^\n]*\bdelivery\b/;
32
+ const GUARD_GIT_TIMEOUT_MS = 3_000;
33
+
34
+ interface Invocation { dir: string; names: string[] }
35
+
36
+ function namesAfter(args: string[]): string[] {
37
+ const names: string[] = [];
38
+ for (let i = 0; i < args.length; i++) {
39
+ if (VALUE_OPTS.has(args[i])) { i++; continue; }
40
+ if (!args[i].startsWith('-')) names.push(args[i]);
41
+ }
42
+ return names;
43
+ }
44
+
45
+ /**
46
+ * Where `delivery` sits as sungen's subcommand, or -1. Only options, and a word that may be an
47
+ * option's value (`--env staging`), may precede it — so `sungen --env x delivery` is caught while
48
+ * `sungen add --screen delivery` (a unit named delivery) is not a delivery call.
49
+ */
50
+ function deliverySubcommandAt(rest: string[]): number {
51
+ for (let i = 0; i < rest.length; i++) {
52
+ if (rest[i] === 'delivery') return i;
53
+ if (rest[i].startsWith('-')) continue;
54
+ const prev = rest[i - 1];
55
+ if (prev && prev.startsWith('--') && !prev.includes('=')) continue;
56
+ return -1;
57
+ }
58
+ return -1;
59
+ }
60
+
61
+ /** Every `sungen delivery …` the command line would run, with the unit names it passes ([] = every unit). */
62
+ export function deliveryInvocations(command: string, cwd: string): Invocation[] {
63
+ const out: Invocation[] = [];
64
+ for (const seg of bashSegments(command, cwd)) {
65
+ const words = [seg.cmd, ...seg.words];
66
+ const at = words.findIndex((w) => SUNGEN.test(path.basename(w)));
67
+ if (at >= 0) {
68
+ const rest = words.slice(at + 1);
69
+ const sub = deliverySubcommandAt(rest);
70
+ if (sub < 0) continue;
71
+ const args = rest.slice(sub + 1);
72
+ if (!args.some((a) => READ_ONLY_OPTS.has(a))) out.push({ dir: seg.dir, names: namesAfter(args) });
73
+ } else if (RUNNERS.has(seg.cmd) && seg.words.includes('delivery') && !seg.words.some((a) => READ_ONLY_OPTS.has(a))) {
74
+ out.push({ dir: seg.dir, names: [] }); // `tsx src/cli/index.ts delivery`, `node dist/cli/index.js delivery`
75
+ }
76
+ }
77
+ if (!out.length && MENTION.test(command) && WRAPPED.test(command)) out.push({ dir: cwd, names: [] });
78
+ return out;
79
+ }
80
+
81
+ function denyFor(blockers: Array<{ unit: string; verdict: string; headline: string }>): HookResult {
82
+ const lines = blockers.slice(0, 5).map((b) => `\`${b.unit}\` is ${b.verdict}: ${b.headline} — see \`sungen contract check --screen ${b.unit}\``);
83
+ return {
84
+ status: 'deny',
85
+ denyReason: `sungen: delivery is blocked — the Test Contract does not pass.\n${lines.join('\n')}${blockers.length > 5 ? `\n(+${blockers.length - 5} more)` : ''}\n`
86
+ + 'Restore the approved checks in the .feature, or ask QA to approve the change themselves on a terminal (`sungen contract approve --screen <unit>`). '
87
+ + 'Do not edit the lock or the report.',
88
+ };
89
+ }
90
+
91
+ export const deliveryContractVerdict: GuardRule = {
92
+ id: 'delivery-contract-verdict',
93
+ onError: 'ask',
94
+ check(call) {
95
+ const cmd = call.tool === 'Bash' ? call.bashCommand : undefined;
96
+ if (!cmd || !cmd.includes('delivery')) return null;
97
+ const invocations = deliveryInvocations(cmd, call.cwd);
98
+ if (!invocations.length) return null;
99
+ const units = require('../contract/contract-units') as typeof import('../contract/contract-units');
100
+ const { contractBlockers } = require('../contract/project-contract-blockers') as typeof import('../contract/project-contract-blockers');
101
+ const blockers: Array<{ unit: string; verdict: string; headline: string }> = [];
102
+ for (const inv of invocations) {
103
+ const root = findSungenRoot(inv.dir);
104
+ if (!root) continue;
105
+ const targets = inv.names.length ? inv.names.flatMap((n) => units.deliveryUnitsNamed(root, n)) : units.allContractUnits(root);
106
+ blockers.push(...contractBlockers(root, targets, { gitTimeoutMs: GUARD_GIT_TIMEOUT_MS }));
107
+ }
108
+ return blockers.length ? denyFor(blockers) : null;
109
+ },
110
+ };