@joshuafolkken/kit 1.872.0

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 (1108) hide show
  1. package/.claude/.claude-plugin/plugin.json +11 -0
  2. package/.claude/settings.json +110 -0
  3. package/.claude/skills/dependency-update/SKILL.md +76 -0
  4. package/.claude/skills/epic-commands/SKILL.md +463 -0
  5. package/.claude/skills/verify-ui/SKILL.md +96 -0
  6. package/.claude/skills/workflow-commands/SKILL.md +265 -0
  7. package/.claude/skills/workflow-commands/background-commands.md +130 -0
  8. package/.claude/skills/workflow-commands/backlogrun-child.md +364 -0
  9. package/.claude/skills/workflow-commands/backlogrun-lanes.md +345 -0
  10. package/.claude/skills/workflow-commands/backlogrun-park.md +179 -0
  11. package/.claude/skills/workflow-commands/backlogrun-progress.md +600 -0
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +604 -0
  13. package/.claude/skills/workflow-commands/backlogrun.md +109 -0
  14. package/.claude/skills/workflow-commands/chain-rule.md +98 -0
  15. package/.claude/skills/workflow-commands/delegation.md +52 -0
  16. package/.claude/skills/workflow-commands/followup-reference.md +118 -0
  17. package/.claude/skills/workflow-commands/followup.md +222 -0
  18. package/.claude/skills/workflow-commands/fullrun-steps.md +93 -0
  19. package/.claude/skills/workflow-commands/fullrun.md +82 -0
  20. package/.claude/skills/workflow-commands/halfrun.md +73 -0
  21. package/.claude/skills/workflow-commands/into-target.md +48 -0
  22. package/.claude/skills/workflow-commands/issue-comments.md +109 -0
  23. package/.claude/skills/workflow-commands/issue-fold-existing.md +27 -0
  24. package/.claude/skills/workflow-commands/issue-scout.md +45 -0
  25. package/.claude/skills/workflow-commands/kickoff.md +82 -0
  26. package/.claude/skills/workflow-commands/latest-gate.md +85 -0
  27. package/.claude/skills/workflow-commands/needs-human-review.md +64 -0
  28. package/.claude/skills/workflow-commands/observation-filing.md +349 -0
  29. package/.claude/skills/workflow-commands/pre-gate-cut.md +340 -0
  30. package/.claude/skills/workflow-commands/prerequisite.md +62 -0
  31. package/.claude/skills/workflow-commands/retrospective.md +81 -0
  32. package/.claude/skills/workflow-commands/rule-residency.md +267 -0
  33. package/.claude/skills/workflow-commands/split-assessment.md +130 -0
  34. package/.claude/skills/workflow-commands/target-repository.md +58 -0
  35. package/.claude/skills/workflow-commands/working-tree-hold.md +66 -0
  36. package/.claude-plugin/marketplace.json +15 -0
  37. package/.coderabbit.yaml +50 -0
  38. package/.codex/config.toml +8 -0
  39. package/.codex/hooks.json +71 -0
  40. package/.cursorrules +45 -0
  41. package/.gitattributes +7 -0
  42. package/.github/dependabot.yml +19 -0
  43. package/.github/pull_request_template.md +1 -0
  44. package/.github/release.yml +18 -0
  45. package/.github/workflows/auto-tag.yml +111 -0
  46. package/.github/workflows/ci.yml +681 -0
  47. package/.github/workflows/dependabot-auto-merge.yml +55 -0
  48. package/.github/workflows/production.yml +47 -0
  49. package/.github/workflows/publish.yml +39 -0
  50. package/.github/workflows/sonar-qube.yml +34 -0
  51. package/.mcp.json +8 -0
  52. package/.ncurc.json +3 -0
  53. package/.prettierignore +20 -0
  54. package/.vscode/extensions.json +21 -0
  55. package/.vscode/settings.json +41 -0
  56. package/AGENTS.md +29 -0
  57. package/CLAUDE.md +207 -0
  58. package/CODE_OF_CONDUCT.md +132 -0
  59. package/GEMINI.md +30 -0
  60. package/LICENSE +21 -0
  61. package/README.md +41 -0
  62. package/SECURITY.md +34 -0
  63. package/cspell/index.yaml +177 -0
  64. package/dist/CLAUDE.md +207 -0
  65. package/dist/config-merge/index.d.ts +29 -0
  66. package/dist/config-merge/index.js +459 -0
  67. package/dist/hooks/batch-guard.js +28 -0
  68. package/dist/hooks/chunk-25JL6FMS.js +4970 -0
  69. package/dist/hooks/chunk-2ANGT3XM.js +375 -0
  70. package/dist/hooks/chunk-2EI5GBSW.js +42 -0
  71. package/dist/hooks/chunk-2OT5XE2N.js +5014 -0
  72. package/dist/hooks/chunk-2RUPMGGV.js +137 -0
  73. package/dist/hooks/chunk-2XIGZQMQ.js +3299 -0
  74. package/dist/hooks/chunk-33ELOKEV.js +910 -0
  75. package/dist/hooks/chunk-33YRTKM7.js +230 -0
  76. package/dist/hooks/chunk-36JQU5NN.js +77 -0
  77. package/dist/hooks/chunk-3EJBTWVS.js +1769 -0
  78. package/dist/hooks/chunk-3FK5SFAC.js +432 -0
  79. package/dist/hooks/chunk-3PWPYDD2.js +240 -0
  80. package/dist/hooks/chunk-3TQU7TDH.js +375 -0
  81. package/dist/hooks/chunk-3TVLSFZ6.js +432 -0
  82. package/dist/hooks/chunk-3VXYCB4E.js +77 -0
  83. package/dist/hooks/chunk-44M6JXGV.js +3398 -0
  84. package/dist/hooks/chunk-46EEEHC3.js +240 -0
  85. package/dist/hooks/chunk-4A7UVP2P.js +364 -0
  86. package/dist/hooks/chunk-4LFQEZS4.js +137 -0
  87. package/dist/hooks/chunk-4OCX3V2T.js +469 -0
  88. package/dist/hooks/chunk-4OHA5DE7.js +49 -0
  89. package/dist/hooks/chunk-4PMDW3YD.js +68 -0
  90. package/dist/hooks/chunk-4QHBNAI4.js +68 -0
  91. package/dist/hooks/chunk-4SSB3FEE.js +3273 -0
  92. package/dist/hooks/chunk-5A2WQ2CQ.js +5390 -0
  93. package/dist/hooks/chunk-5EVA2JQB.js +5390 -0
  94. package/dist/hooks/chunk-5P7VF5VE.js +3230 -0
  95. package/dist/hooks/chunk-5QWJGGZP.js +49 -0
  96. package/dist/hooks/chunk-5U5EZYG6.js +77 -0
  97. package/dist/hooks/chunk-5VUUF3ZV.js +240 -0
  98. package/dist/hooks/chunk-5WA7UBT3.js +374 -0
  99. package/dist/hooks/chunk-6EBGRQ3Q.js +301 -0
  100. package/dist/hooks/chunk-6TVHWMD3.js +432 -0
  101. package/dist/hooks/chunk-6V5OPIUU.js +13 -0
  102. package/dist/hooks/chunk-6VAGLEMB.js +68 -0
  103. package/dist/hooks/chunk-75BTXKFJ.js +3424 -0
  104. package/dist/hooks/chunk-75RHN67S.js +137 -0
  105. package/dist/hooks/chunk-76KC3BDD.js +3414 -0
  106. package/dist/hooks/chunk-76SLS7CZ.js +898 -0
  107. package/dist/hooks/chunk-7DHZ4DWT.js +5015 -0
  108. package/dist/hooks/chunk-7INSJDGE.js +458 -0
  109. package/dist/hooks/chunk-7VJ4FTDX.js +268 -0
  110. package/dist/hooks/chunk-7XCYNHQK.js +77 -0
  111. package/dist/hooks/chunk-A5YJ3H7E.js +375 -0
  112. package/dist/hooks/chunk-AAEXXUUL.js +268 -0
  113. package/dist/hooks/chunk-ABVEVV2M.js +432 -0
  114. package/dist/hooks/chunk-ACN3YXFL.js +68 -0
  115. package/dist/hooks/chunk-AD3XE3QZ.js +397 -0
  116. package/dist/hooks/chunk-AENFZPZH.js +230 -0
  117. package/dist/hooks/chunk-AFKRFQ6W.js +68 -0
  118. package/dist/hooks/chunk-AHD5IPWI.js +375 -0
  119. package/dist/hooks/chunk-AMK5JGV7.js +77 -0
  120. package/dist/hooks/chunk-ARN7NCQI.js +425 -0
  121. package/dist/hooks/chunk-AUFY653N.js +3425 -0
  122. package/dist/hooks/chunk-AXQBNFEF.js +375 -0
  123. package/dist/hooks/chunk-AYC7R6U4.js +3316 -0
  124. package/dist/hooks/chunk-AYEA2FJ7.js +5015 -0
  125. package/dist/hooks/chunk-B2LIXYFL.js +77 -0
  126. package/dist/hooks/chunk-B4HPNY2I.js +375 -0
  127. package/dist/hooks/chunk-B4YNCUGB.js +469 -0
  128. package/dist/hooks/chunk-B57S3VWT.js +922 -0
  129. package/dist/hooks/chunk-BINZ3PLI.js +364 -0
  130. package/dist/hooks/chunk-BIWLABFK.js +432 -0
  131. package/dist/hooks/chunk-BODUSXKK.js +410 -0
  132. package/dist/hooks/chunk-BQBAT2YK.js +375 -0
  133. package/dist/hooks/chunk-BUJEBW75.js +391 -0
  134. package/dist/hooks/chunk-BVNWORKA.js +72 -0
  135. package/dist/hooks/chunk-BWI47LQS.js +5205 -0
  136. package/dist/hooks/chunk-C25HRMJX.js +137 -0
  137. package/dist/hooks/chunk-CBFZNC74.js +375 -0
  138. package/dist/hooks/chunk-CECYXS4Y.js +3424 -0
  139. package/dist/hooks/chunk-CELGUP5F.js +49 -0
  140. package/dist/hooks/chunk-CMHANU3F.js +3442 -0
  141. package/dist/hooks/chunk-CMN372LI.js +68 -0
  142. package/dist/hooks/chunk-CPGZLMMK.js +3299 -0
  143. package/dist/hooks/chunk-CTQKXDC7.js +268 -0
  144. package/dist/hooks/chunk-CYAT4RIT.js +68 -0
  145. package/dist/hooks/chunk-CYTWYCH2.js +5014 -0
  146. package/dist/hooks/chunk-CZSOLRBA.js +77 -0
  147. package/dist/hooks/chunk-D2PIDYJR.js +3438 -0
  148. package/dist/hooks/chunk-DE57HI6T.js +137 -0
  149. package/dist/hooks/chunk-DGXDGAPG.js +5306 -0
  150. package/dist/hooks/chunk-DNYRSYQG.js +5014 -0
  151. package/dist/hooks/chunk-DTAXH2A2.js +240 -0
  152. package/dist/hooks/chunk-E2IZUWI5.js +375 -0
  153. package/dist/hooks/chunk-E4L2K2BL.js +397 -0
  154. package/dist/hooks/chunk-E55NKX5F.js +68 -0
  155. package/dist/hooks/chunk-ECXVCCVD.js +3079 -0
  156. package/dist/hooks/chunk-EPHO443D.js +68 -0
  157. package/dist/hooks/chunk-EUFK2BI2.js +375 -0
  158. package/dist/hooks/chunk-EYCD5ZAV.js +137 -0
  159. package/dist/hooks/chunk-F2SDYJU4.js +240 -0
  160. package/dist/hooks/chunk-F4B5D5TF.js +68 -0
  161. package/dist/hooks/chunk-FGEO3NDX.js +432 -0
  162. package/dist/hooks/chunk-FJYI52RE.js +137 -0
  163. package/dist/hooks/chunk-FXAKJKTB.js +18 -0
  164. package/dist/hooks/chunk-FYTZHIY4.js +3085 -0
  165. package/dist/hooks/chunk-G7JL2A5K.js +375 -0
  166. package/dist/hooks/chunk-GA3ITDBW.js +42 -0
  167. package/dist/hooks/chunk-GDR4H4SV.js +469 -0
  168. package/dist/hooks/chunk-GFKDXPSM.js +2855 -0
  169. package/dist/hooks/chunk-GIMRTKFU.js +566 -0
  170. package/dist/hooks/chunk-GOPHRLGO.js +240 -0
  171. package/dist/hooks/chunk-GX4HO7SJ.js +230 -0
  172. package/dist/hooks/chunk-GXKKK23T.js +240 -0
  173. package/dist/hooks/chunk-GZ6FUVIK.js +566 -0
  174. package/dist/hooks/chunk-H5HPY5M5.js +2869 -0
  175. package/dist/hooks/chunk-HCF3OGEE.js +1829 -0
  176. package/dist/hooks/chunk-HDEXAOUM.js +469 -0
  177. package/dist/hooks/chunk-HM2TY3TN.js +469 -0
  178. package/dist/hooks/chunk-HOA7NXA2.js +55 -0
  179. package/dist/hooks/chunk-HOFEWH6H.js +240 -0
  180. package/dist/hooks/chunk-HUUI6S5J.js +2669 -0
  181. package/dist/hooks/chunk-I4D3NVUD.js +469 -0
  182. package/dist/hooks/chunk-I4Q6WAJE.js +68 -0
  183. package/dist/hooks/chunk-IB6N4CR2.js +432 -0
  184. package/dist/hooks/chunk-IFLDYJMD.js +469 -0
  185. package/dist/hooks/chunk-IGU466YD.js +77 -0
  186. package/dist/hooks/chunk-IJCQUHKY.js +375 -0
  187. package/dist/hooks/chunk-IKUMBDJB.js +230 -0
  188. package/dist/hooks/chunk-IM3BDIBJ.js +5005 -0
  189. package/dist/hooks/chunk-IMYMAODK.js +3431 -0
  190. package/dist/hooks/chunk-IN2ZVGXA.js +5005 -0
  191. package/dist/hooks/chunk-ITVJ2MKQ.js +18 -0
  192. package/dist/hooks/chunk-J5RIJYTM.js +2669 -0
  193. package/dist/hooks/chunk-JFLMH4K5.js +3460 -0
  194. package/dist/hooks/chunk-JR25IFML.js +77 -0
  195. package/dist/hooks/chunk-JT5AUXFI.js +432 -0
  196. package/dist/hooks/chunk-JY5YVN6N.js +3234 -0
  197. package/dist/hooks/chunk-K5Q4ETVI.js +391 -0
  198. package/dist/hooks/chunk-K67V2F24.js +137 -0
  199. package/dist/hooks/chunk-KABG6AEW.js +3460 -0
  200. package/dist/hooks/chunk-KATZESEC.js +3273 -0
  201. package/dist/hooks/chunk-KFH4H7W7.js +469 -0
  202. package/dist/hooks/chunk-KMUEI6RX.js +910 -0
  203. package/dist/hooks/chunk-KMV4OY77.js +3438 -0
  204. package/dist/hooks/chunk-KQAZNWEY.js +137 -0
  205. package/dist/hooks/chunk-KZZR6JER.js +5015 -0
  206. package/dist/hooks/chunk-LAR6DREP.js +77 -0
  207. package/dist/hooks/chunk-LNCJWEZD.js +5015 -0
  208. package/dist/hooks/chunk-LRYD2GLM.js +6 -0
  209. package/dist/hooks/chunk-LXBKYHDV.js +77 -0
  210. package/dist/hooks/chunk-LYLKIUNE.js +5024 -0
  211. package/dist/hooks/chunk-LZKCFOVC.js +432 -0
  212. package/dist/hooks/chunk-M4FCIYRI.js +77 -0
  213. package/dist/hooks/chunk-M5M7327Q.js +3425 -0
  214. package/dist/hooks/chunk-MF72MHSX.js +3455 -0
  215. package/dist/hooks/chunk-MK56LKDO.js +397 -0
  216. package/dist/hooks/chunk-N3MJADY7.js +240 -0
  217. package/dist/hooks/chunk-NFQSUDBN.js +458 -0
  218. package/dist/hooks/chunk-NHREKY45.js +137 -0
  219. package/dist/hooks/chunk-NP5TTAAW.js +375 -0
  220. package/dist/hooks/chunk-NQTLTKTJ.js +2993 -0
  221. package/dist/hooks/chunk-NVRCZPBZ.js +391 -0
  222. package/dist/hooks/chunk-O46HMMLJ.js +469 -0
  223. package/dist/hooks/chunk-OFJGH2L4.js +240 -0
  224. package/dist/hooks/chunk-OLFMCZH5.js +240 -0
  225. package/dist/hooks/chunk-OMCZS46I.js +49 -0
  226. package/dist/hooks/chunk-OQZEZW5G.js +469 -0
  227. package/dist/hooks/chunk-P2MDAT2Y.js +1897 -0
  228. package/dist/hooks/chunk-P3M2JJIF.js +68 -0
  229. package/dist/hooks/chunk-PDVHQITQ.js +3453 -0
  230. package/dist/hooks/chunk-PNT2AMDH.js +391 -0
  231. package/dist/hooks/chunk-PR2LVSY6.js +3445 -0
  232. package/dist/hooks/chunk-PRR5R4JK.js +137 -0
  233. package/dist/hooks/chunk-PXT44QVN.js +566 -0
  234. package/dist/hooks/chunk-PZLWJLAP.js +469 -0
  235. package/dist/hooks/chunk-Q2FEAZJ2.js +77 -0
  236. package/dist/hooks/chunk-Q32WETDO.js +3265 -0
  237. package/dist/hooks/chunk-Q45DUBLE.js +3600 -0
  238. package/dist/hooks/chunk-Q7NZSWQ5.js +240 -0
  239. package/dist/hooks/chunk-QH2JNAMK.js +3085 -0
  240. package/dist/hooks/chunk-QNNWYQ2R.js +375 -0
  241. package/dist/hooks/chunk-QPU5H2OS.js +68 -0
  242. package/dist/hooks/chunk-QRAHZ5TO.js +1829 -0
  243. package/dist/hooks/chunk-QUZ5HPIE.js +469 -0
  244. package/dist/hooks/chunk-QVCRG34O.js +2893 -0
  245. package/dist/hooks/chunk-R3MY4E3S.js +1675 -0
  246. package/dist/hooks/chunk-R6TXJJXP.js +77 -0
  247. package/dist/hooks/chunk-REJU6VT7.js +1829 -0
  248. package/dist/hooks/chunk-REQAQLRC.js +2993 -0
  249. package/dist/hooks/chunk-RFCXPAHH.js +391 -0
  250. package/dist/hooks/chunk-RHI6Y22X.js +137 -0
  251. package/dist/hooks/chunk-RKZVOBBS.js +469 -0
  252. package/dist/hooks/chunk-RL57TT2Y.js +566 -0
  253. package/dist/hooks/chunk-RORDOD4S.js +3321 -0
  254. package/dist/hooks/chunk-RZKYW5P2.js +77 -0
  255. package/dist/hooks/chunk-SJPJ6VSI.js +391 -0
  256. package/dist/hooks/chunk-SKSIJQQQ.js +432 -0
  257. package/dist/hooks/chunk-SSQDZKXG.js +268 -0
  258. package/dist/hooks/chunk-SSX23SJ2.js +89 -0
  259. package/dist/hooks/chunk-SYHFKE4C.js +77 -0
  260. package/dist/hooks/chunk-TCGNI2ZY.js +42 -0
  261. package/dist/hooks/chunk-TG3WXJF5.js +137 -0
  262. package/dist/hooks/chunk-TH7IJAY5.js +77 -0
  263. package/dist/hooks/chunk-TLZ27PCY.js +240 -0
  264. package/dist/hooks/chunk-U652FXTN.js +566 -0
  265. package/dist/hooks/chunk-UEK47YUF.js +268 -0
  266. package/dist/hooks/chunk-UIO45H3O.js +432 -0
  267. package/dist/hooks/chunk-UNLZEEVH.js +5005 -0
  268. package/dist/hooks/chunk-UNRVF3SZ.js +432 -0
  269. package/dist/hooks/chunk-USLFAFOI.js +3453 -0
  270. package/dist/hooks/chunk-VAEELMLL.js +442 -0
  271. package/dist/hooks/chunk-VALSWLDQ.js +3453 -0
  272. package/dist/hooks/chunk-VC5JEPNY.js +3398 -0
  273. package/dist/hooks/chunk-VEZVK6C7.js +230 -0
  274. package/dist/hooks/chunk-VK5JKFAR.js +49 -0
  275. package/dist/hooks/chunk-VNF2KP7Z.js +469 -0
  276. package/dist/hooks/chunk-VWWCUMW6.js +2669 -0
  277. package/dist/hooks/chunk-W4JARUQV.js +137 -0
  278. package/dist/hooks/chunk-WCYPBPJC.js +5014 -0
  279. package/dist/hooks/chunk-WEOBMNJG.js +2993 -0
  280. package/dist/hooks/chunk-WKJU3J5Y.js +5390 -0
  281. package/dist/hooks/chunk-WMN4TSVF.js +3299 -0
  282. package/dist/hooks/chunk-WNON54PT.js +3469 -0
  283. package/dist/hooks/chunk-WOVKBPPX.js +137 -0
  284. package/dist/hooks/chunk-WRVFORYJ.js +432 -0
  285. package/dist/hooks/chunk-WUBVYGQZ.js +240 -0
  286. package/dist/hooks/chunk-WWULTUOM.js +68 -0
  287. package/dist/hooks/chunk-WXHKKB45.js +4962 -0
  288. package/dist/hooks/chunk-XAI3YTHJ.js +469 -0
  289. package/dist/hooks/chunk-XFZH6JZJ.js +77 -0
  290. package/dist/hooks/chunk-XGPWX6IA.js +137 -0
  291. package/dist/hooks/chunk-XIXXIVGY.js +566 -0
  292. package/dist/hooks/chunk-XKDOYJGA.js +922 -0
  293. package/dist/hooks/chunk-YALTVBHM.js +432 -0
  294. package/dist/hooks/chunk-YEBEPBFK.js +5014 -0
  295. package/dist/hooks/chunk-YI2BQ3DK.js +3441 -0
  296. package/dist/hooks/chunk-YVNBCFGG.js +1829 -0
  297. package/dist/hooks/chunk-YXBN3RGG.js +432 -0
  298. package/dist/hooks/chunk-Z2OOJSW3.js +3163 -0
  299. package/dist/hooks/chunk-ZA3HVBOY.js +2644 -0
  300. package/dist/hooks/chunk-ZKID46U3.js +137 -0
  301. package/dist/hooks/chunk-ZPMU2JV6.js +49 -0
  302. package/dist/hooks/chunk-ZRKY4W7O.js +432 -0
  303. package/dist/hooks/chunk-ZTMRB7LJ.js +268 -0
  304. package/dist/hooks/chunk-ZVPPBQ3L.js +3413 -0
  305. package/dist/hooks/codex-hook-adapter.js +164 -0
  306. package/dist/hooks/duplicate-read-guard.js +29 -0
  307. package/dist/hooks/format-edited.js +37 -0
  308. package/dist/hooks/investigation-guard.js +31 -0
  309. package/dist/hooks/pretool-guard.js +21 -0
  310. package/dist/hooks/session-lang.js +34 -0
  311. package/dist/hooks/stop-guard.js +1597 -0
  312. package/dist/josh.js +1795 -0
  313. package/dist/managed-marker/index.d.ts +10 -0
  314. package/dist/managed-marker/index.js +32 -0
  315. package/dist/self-sync-guard/index.d.ts +10 -0
  316. package/dist/self-sync-guard/index.js +49 -0
  317. package/dist/version/index.d.ts +93 -0
  318. package/dist/version/index.js +1024 -0
  319. package/env/index.d.ts +7 -0
  320. package/env/index.js +62 -0
  321. package/eslint/base.js +233 -0
  322. package/eslint/checkout-rooted-parser.js +34 -0
  323. package/eslint/config-fingerprint.js +103 -0
  324. package/eslint/rules/code-quality.js +292 -0
  325. package/eslint/rules/english-only-prose.js +135 -0
  326. package/eslint/rules/formatting.js +44 -0
  327. package/eslint/rules/import.js +83 -0
  328. package/eslint/rules/namespace-object-export.js +107 -0
  329. package/eslint/rules/naming-convention.js +109 -0
  330. package/eslint/rules/promise.js +17 -0
  331. package/eslint/rules/sonarjs.js +45 -0
  332. package/eslint/rules/test-filename.js +91 -0
  333. package/eslint/rules/typescript.js +186 -0
  334. package/eslint/rules/unicorn.js +191 -0
  335. package/eslint/vanilla.js +1 -0
  336. package/evals/scenarios/consult-not-execute.json +20 -0
  337. package/evals/scenarios/no-implicit-workflow.json +26 -0
  338. package/evals/scenarios/overrides-both-locations.json +29 -0
  339. package/evals/scenarios/upstream-interrupt.json +23 -0
  340. package/evals/scenarios/workflow-skill-loaded.json +16 -0
  341. package/lefthook/base.yml +131 -0
  342. package/lefthook/vanilla.yml +7 -0
  343. package/package.json +169 -0
  344. package/playwright.config.ts +160 -0
  345. package/pnpm-workspace.yaml +41 -0
  346. package/ports/index.d.ts +17 -0
  347. package/ports/index.js +256 -0
  348. package/prettier/index.d.ts +3 -0
  349. package/prettier/index.js +31 -0
  350. package/prompts/agent-lint-protocol.json +79 -0
  351. package/prompts/agent-rules.md +63 -0
  352. package/prompts/coding-standards.md +382 -0
  353. package/prompts/collaboration-workflow/consultation-vs-execution.md +8 -0
  354. package/prompts/collaboration-workflow/cross-repo-epic.md +54 -0
  355. package/prompts/collaboration-workflow/distributed-docs.md +7 -0
  356. package/prompts/collaboration-workflow/durable-rules.md +24 -0
  357. package/prompts/collaboration-workflow/epic-audit.md +56 -0
  358. package/prompts/collaboration-workflow/epic-bundle.md +109 -0
  359. package/prompts/collaboration-workflow/file-edits.md +124 -0
  360. package/prompts/collaboration-workflow/gh-rest.md +57 -0
  361. package/prompts/collaboration-workflow/issue-citation.md +38 -0
  362. package/prompts/collaboration-workflow/issue-template.md +190 -0
  363. package/prompts/collaboration-workflow/latest-first.md +14 -0
  364. package/prompts/collaboration-workflow/no-clones.md +11 -0
  365. package/prompts/collaboration-workflow/operating-rules.md +123 -0
  366. package/prompts/collaboration-workflow/output-bounds.md +107 -0
  367. package/prompts/collaboration-workflow/overview.md +35 -0
  368. package/prompts/collaboration-workflow/plan-comment.md +85 -0
  369. package/prompts/collaboration-workflow/proposal-request.md +23 -0
  370. package/prompts/collaboration-workflow/report-format.md +206 -0
  371. package/prompts/collaboration-workflow/residency.md +94 -0
  372. package/prompts/collaboration-workflow/rule-delivery.md +146 -0
  373. package/prompts/collaboration-workflow/shell-body.md +82 -0
  374. package/prompts/collaboration-workflow/simplicity-first.md +9 -0
  375. package/prompts/collaboration-workflow/single-source-rules.md +13 -0
  376. package/prompts/collaboration-workflow/turn-batching.md +137 -0
  377. package/prompts/collaboration-workflow/upstream-interrupt.md +51 -0
  378. package/prompts/collaboration-workflow/wip-cap.md +118 -0
  379. package/prompts/collaboration-workflow.md +52 -0
  380. package/prompts/refactoring.md +103 -0
  381. package/prompts/review-rubric.md +338 -0
  382. package/prompts/review.md +217 -0
  383. package/prompts/sonar-hotspot-handling.md +77 -0
  384. package/prompts/testing-guide.md +277 -0
  385. package/scripts/adopt/adopt-logic.ts +107 -0
  386. package/scripts/adopt/adopt-toolkits.ts +181 -0
  387. package/scripts/adopt/adopt.ts +171 -0
  388. package/scripts/agent/agent-argv.ts +140 -0
  389. package/scripts/agent/agent-diagnostics.ts +120 -0
  390. package/scripts/agent/agent-event.ts +173 -0
  391. package/scripts/agent/agent-exit-record.ts +32 -0
  392. package/scripts/agent/agent-launch-environment.ts +71 -0
  393. package/scripts/agent/agent-role-profile.ts +329 -0
  394. package/scripts/agent/api-outage.ts +51 -0
  395. package/scripts/agent/claude-agent-argv.ts +151 -0
  396. package/scripts/agent/claude-result-event.ts +98 -0
  397. package/scripts/agent/codex-agent-argv.ts +94 -0
  398. package/scripts/agent/codex-home-source.ts +11 -0
  399. package/scripts/agent/interactive-ask.ts +91 -0
  400. package/scripts/auto-ok/auto-ok-cli.ts +516 -0
  401. package/scripts/backlog/backlog-arrival.ts +147 -0
  402. package/scripts/backlog/backlog-budget-cli.ts +220 -0
  403. package/scripts/backlog/backlog-budget.ts +284 -0
  404. package/scripts/backlog/backlog-defect-priority.ts +77 -0
  405. package/scripts/backlog/backlog-drive-cli.ts +377 -0
  406. package/scripts/backlog/backlog-drive-finish.ts +23 -0
  407. package/scripts/backlog/backlog-drive-named-offer.ts +81 -0
  408. package/scripts/backlog/backlog-drive-named.ts +101 -0
  409. package/scripts/backlog/backlog-drive-offer-argv.ts +29 -0
  410. package/scripts/backlog/backlog-drive-owner.ts +22 -0
  411. package/scripts/backlog/backlog-drive-restore.ts +67 -0
  412. package/scripts/backlog/backlog-drive.ts +322 -0
  413. package/scripts/backlog/backlog-named.ts +164 -0
  414. package/scripts/backlog/backlog-next.ts +376 -0
  415. package/scripts/backlog/backlog-offer-cli.ts +279 -0
  416. package/scripts/backlog/backlog-offer.ts +93 -0
  417. package/scripts/backlog/backlog-plan-cli.ts +235 -0
  418. package/scripts/backlog/backlog-plan.ts +231 -0
  419. package/scripts/backlog/backlog-pool.ts +322 -0
  420. package/scripts/backlog/backlog-ready.ts +146 -0
  421. package/scripts/backlog/backlog-scope.ts +144 -0
  422. package/scripts/backlog/backlog-stalled-cli.ts +30 -0
  423. package/scripts/backlog/backlog-stalled-detect.ts +143 -0
  424. package/scripts/backlog/backlog-stalled.ts +118 -0
  425. package/scripts/behavior/behavior-assertion.ts +87 -0
  426. package/scripts/behavior/behavior-cli.ts +88 -0
  427. package/scripts/behavior/behavior-rules.ts +128 -0
  428. package/scripts/build/build-bin.ts +36 -0
  429. package/scripts/build/build-claude-md.ts +42 -0
  430. package/scripts/build/build-config-merge.ts +26 -0
  431. package/scripts/build/build-hooks.ts +79 -0
  432. package/scripts/build/build-library.ts +83 -0
  433. package/scripts/build/build-managed-marker.ts +26 -0
  434. package/scripts/build/build-self-sync-guard.ts +26 -0
  435. package/scripts/build/build-version.ts +25 -0
  436. package/scripts/build/local-bin.ts +97 -0
  437. package/scripts/build/shim-shell.ts +25 -0
  438. package/scripts/bytes/bytes-command.ts +181 -0
  439. package/scripts/cases/cases-cli.ts +48 -0
  440. package/scripts/cases/cases-logic.ts +100 -0
  441. package/scripts/claude/skill-meta.ts +37 -0
  442. package/scripts/claude/workflow-destination.ts +13 -0
  443. package/scripts/clone/clone-aggregate.ts +76 -0
  444. package/scripts/clone/clone-fingerprint.ts +96 -0
  445. package/scripts/clone/clone-scan-cli.ts +39 -0
  446. package/scripts/clone/clone-scan.ts +158 -0
  447. package/scripts/config-merge/index.ts +19 -0
  448. package/scripts/config-merge/json-format.ts +128 -0
  449. package/scripts/config-merge/list-patch.ts +61 -0
  450. package/scripts/config-merge/parse-jsonc.ts +14 -0
  451. package/scripts/config-merge/patch-json-key.ts +439 -0
  452. package/scripts/config-merge/patch-json-list.ts +38 -0
  453. package/scripts/config-merge/patch-yaml-list.ts +107 -0
  454. package/scripts/cost-runtime/codex-usage.ts +119 -0
  455. package/scripts/cost-runtime/context-cut-payback.ts +77 -0
  456. package/scripts/cost-runtime/context-cut-threshold.ts +21 -0
  457. package/scripts/cost-runtime/cost-attribute.ts +168 -0
  458. package/scripts/cost-runtime/cost-blocks.ts +149 -0
  459. package/scripts/cost-runtime/cost-cli.ts +318 -0
  460. package/scripts/cost-runtime/cost-corpus.ts +278 -0
  461. package/scripts/cost-runtime/cost-format.ts +32 -0
  462. package/scripts/cost-runtime/cost-pricing.ts +176 -0
  463. package/scripts/cost-runtime/cost-tokens.ts +84 -0
  464. package/scripts/cost-runtime/cost-transcript.ts +531 -0
  465. package/scripts/cost-runtime/cost-usage.ts +287 -0
  466. package/scripts/cost-runtime/cost-verdict.ts +89 -0
  467. package/scripts/cost-runtime/own-session.ts +58 -0
  468. package/scripts/cost-runtime/transcript-cwd.ts +14 -0
  469. package/scripts/delegation/delegation-cli.ts +91 -0
  470. package/scripts/delegation/delegation-policy.ts +178 -0
  471. package/scripts/delegation/duplicate-read-guard.ts +244 -0
  472. package/scripts/delegation/fanout-cli.ts +61 -0
  473. package/scripts/delegation/fanout.ts +95 -0
  474. package/scripts/delegation/investigation-guard.ts +131 -0
  475. package/scripts/delegation/investigation-reads.ts +637 -0
  476. package/scripts/discovery/repo-discovery.ts +166 -0
  477. package/scripts/discovery/repo-map-logic.ts +102 -0
  478. package/scripts/discovery/repo-origin.ts +153 -0
  479. package/scripts/discovery/repo-party-cli.ts +69 -0
  480. package/scripts/discovery/repo-party.ts +46 -0
  481. package/scripts/doctor/doctor-consumer.ts +181 -0
  482. package/scripts/doctor/doctor-io.ts +210 -0
  483. package/scripts/doctor/doctor-logic.ts +122 -0
  484. package/scripts/doctor/doctor-ports.ts +117 -0
  485. package/scripts/doctor/doctor.ts +232 -0
  486. package/scripts/document/backlogrun-parent-read-set.ts +48 -0
  487. package/scripts/document/bash-output-cap.ts +45 -0
  488. package/scripts/document/document-byte-budget.ts +183 -0
  489. package/scripts/document/document-byte-check.ts +131 -0
  490. package/scripts/document/document-reachability.ts +131 -0
  491. package/scripts/document/document-read-cli.ts +82 -0
  492. package/scripts/document/document-scan.ts +108 -0
  493. package/scripts/document/document-section-cli.ts +101 -0
  494. package/scripts/document/document-section.ts +156 -0
  495. package/scripts/document/edit-files-cli.ts +280 -0
  496. package/scripts/document/entry-read-budget.ts +154 -0
  497. package/scripts/document/entry-read-set.ts +471 -0
  498. package/scripts/document/generate-catalog.ts +69 -0
  499. package/scripts/document/lane-child-read-set.ts +88 -0
  500. package/scripts/document/read-files-cli.ts +135 -0
  501. package/scripts/document/read-set-cli.ts +295 -0
  502. package/scripts/document/read-set-point-of-use.ts +89 -0
  503. package/scripts/document/read-set-pricing.ts +52 -0
  504. package/scripts/document/read-set-trim.ts +78 -0
  505. package/scripts/document/retired-phrases.ts +143 -0
  506. package/scripts/document/review-agent-type.ts +46 -0
  507. package/scripts/document/single-source.ts +73 -0
  508. package/scripts/epic/epic-audit-checks.ts +452 -0
  509. package/scripts/epic/epic-audit-cli.ts +374 -0
  510. package/scripts/epic/epic-audit-orphans.ts +142 -0
  511. package/scripts/epic/epic-audit-rationale.ts +191 -0
  512. package/scripts/epic/epic-audit-report.ts +101 -0
  513. package/scripts/epic/epic-audit.ts +240 -0
  514. package/scripts/epic/epic-bundle-cli.ts +472 -0
  515. package/scripts/epic/epic-bundle-evidence.ts +147 -0
  516. package/scripts/epic/epic-bundle-gaps.ts +86 -0
  517. package/scripts/epic/epic-bundle-referenced.ts +195 -0
  518. package/scripts/epic/epic-bundle.ts +309 -0
  519. package/scripts/epic/epic-busy.ts +204 -0
  520. package/scripts/epic/epic-candidate-confirm.ts +279 -0
  521. package/scripts/epic/epic-classify.ts +294 -0
  522. package/scripts/epic/epic-cross-repo.ts +366 -0
  523. package/scripts/epic/epic-fetch.ts +370 -0
  524. package/scripts/epic/epic-graph.ts +279 -0
  525. package/scripts/epic/epic-index.ts +209 -0
  526. package/scripts/epic/epic-issue.ts +172 -0
  527. package/scripts/epic/epic-lane-offer.ts +207 -0
  528. package/scripts/epic/epic-nested.ts +37 -0
  529. package/scripts/epic/epic-next-read.ts +141 -0
  530. package/scripts/epic/epic-next-views.ts +144 -0
  531. package/scripts/epic/epic-next.ts +477 -0
  532. package/scripts/epic/epic-outside-blocker.ts +113 -0
  533. package/scripts/epic/epic-relation-recheck.ts +108 -0
  534. package/scripts/epic/epic-report.ts +200 -0
  535. package/scripts/gate/core-budget.ts +292 -0
  536. package/scripts/gate/gate-log.ts +95 -0
  537. package/scripts/gate/gate-plan.ts +356 -0
  538. package/scripts/gate/gate-report.ts +207 -0
  539. package/scripts/gate/gate-skip.ts +123 -0
  540. package/scripts/gate/gate-tree.ts +49 -0
  541. package/scripts/gate/hook-gate-reuse.ts +130 -0
  542. package/scripts/gate/pre-commit-type-check.ts +187 -0
  543. package/scripts/gate/scoped-green.ts +260 -0
  544. package/scripts/gate/type-check-step.ts +90 -0
  545. package/scripts/gate/verification-gate.ts +531 -0
  546. package/scripts/gh/fix-gh-packages-logic.ts +232 -0
  547. package/scripts/gh/fix-gh-packages.ts +129 -0
  548. package/scripts/gh/gh-cli-token.ts +18 -0
  549. package/scripts/gh/gh-spawn.ts +44 -0
  550. package/scripts/git/animation-helpers.ts +81 -0
  551. package/scripts/git/change-base.ts +26 -0
  552. package/scripts/git/changed-file-scope.ts +209 -0
  553. package/scripts/git/changed-paths.ts +30 -0
  554. package/scripts/git/constants.ts +41 -0
  555. package/scripts/git/git-ai-review-scan.ts +154 -0
  556. package/scripts/git/git-animation.ts +41 -0
  557. package/scripts/git/git-branch.ts +127 -0
  558. package/scripts/git/git-command.ts +587 -0
  559. package/scripts/git/git-commit.ts +27 -0
  560. package/scripts/git/git-common-directory.ts +38 -0
  561. package/scripts/git/git-epic-add-body.ts +365 -0
  562. package/scripts/git/git-epic-add-plan.ts +421 -0
  563. package/scripts/git/git-epic-add.ts +249 -0
  564. package/scripts/git/git-epic-body.ts +150 -0
  565. package/scripts/git/git-epic-chains.ts +411 -0
  566. package/scripts/git/git-epic-close-comment.ts +199 -0
  567. package/scripts/git/git-epic-close.ts +393 -0
  568. package/scripts/git/git-epic-decision.ts +171 -0
  569. package/scripts/git/git-epic-parse.ts +351 -0
  570. package/scripts/git/git-epic-promote.ts +102 -0
  571. package/scripts/git/git-epic-read.ts +73 -0
  572. package/scripts/git/git-epic-reconcile.ts +246 -0
  573. package/scripts/git/git-epic-reference.ts +98 -0
  574. package/scripts/git/git-epic-relations.ts +78 -0
  575. package/scripts/git/git-epic-remove-plan.ts +152 -0
  576. package/scripts/git/git-epic-remove.ts +101 -0
  577. package/scripts/git/git-epic-run.ts +223 -0
  578. package/scripts/git/git-epic-sections.ts +98 -0
  579. package/scripts/git/git-epic-shape.ts +81 -0
  580. package/scripts/git/git-epic-validate.ts +155 -0
  581. package/scripts/git/git-error.ts +78 -0
  582. package/scripts/git/git-execa-error.ts +35 -0
  583. package/scripts/git/git-fixture-workspace.ts +88 -0
  584. package/scripts/git/git-followup-cleanup.ts +88 -0
  585. package/scripts/git/git-followup-flush.ts +63 -0
  586. package/scripts/git/git-followup-label.ts +67 -0
  587. package/scripts/git/git-followup-pending.ts +95 -0
  588. package/scripts/git/git-followup-stages.ts +149 -0
  589. package/scripts/git/git-gh-api-path.ts +118 -0
  590. package/scripts/git/git-gh-check.ts +21 -0
  591. package/scripts/git/git-gh-command.ts +17 -0
  592. package/scripts/git/git-gh-exec.ts +344 -0
  593. package/scripts/git/git-gh-failure.ts +103 -0
  594. package/scripts/git/git-gh-helpers.ts +44 -0
  595. package/scripts/git/git-gh-issue-list.ts +257 -0
  596. package/scripts/git/git-gh-issue-read.ts +457 -0
  597. package/scripts/git/git-gh-issue-rest.ts +238 -0
  598. package/scripts/git/git-gh-issue-write.ts +285 -0
  599. package/scripts/git/git-gh-issue.ts +161 -0
  600. package/scripts/git/git-gh-pr-auto-merge.ts +85 -0
  601. package/scripts/git/git-gh-pr-read.ts +322 -0
  602. package/scripts/git/git-gh-pr-rest.ts +172 -0
  603. package/scripts/git/git-gh-pr-review.ts +103 -0
  604. package/scripts/git/git-gh-pr-rollup.ts +91 -0
  605. package/scripts/git/git-gh-pr-snapshot.ts +138 -0
  606. package/scripts/git/git-gh-pr.ts +219 -0
  607. package/scripts/git/git-gh-reachability.ts +56 -0
  608. package/scripts/git/git-gh-repo.ts +37 -0
  609. package/scripts/git/git-gh-rest-state.ts +14 -0
  610. package/scripts/git/git-issue.ts +168 -0
  611. package/scripts/git/git-location-environment.ts +62 -0
  612. package/scripts/git/git-ls-remote.ts +28 -0
  613. package/scripts/git/git-next-issues.ts +98 -0
  614. package/scripts/git/git-notify.ts +104 -0
  615. package/scripts/git/git-pr-ai-review.ts +180 -0
  616. package/scripts/git/git-pr-checks-eval.ts +265 -0
  617. package/scripts/git/git-pr-checks-parse.ts +153 -0
  618. package/scripts/git/git-pr-checks-watch.ts +184 -0
  619. package/scripts/git/git-pr-checks.ts +387 -0
  620. package/scripts/git/git-pr-coderabbit.ts +129 -0
  621. package/scripts/git/git-pr-confirmation.ts +64 -0
  622. package/scripts/git/git-pr-error.ts +25 -0
  623. package/scripts/git/git-pr-followup-wrapup.ts +225 -0
  624. package/scripts/git/git-pr-followup.ts +436 -0
  625. package/scripts/git/git-pr-managed-config.ts +69 -0
  626. package/scripts/git/git-pr-messages.ts +37 -0
  627. package/scripts/git/git-pr.ts +181 -0
  628. package/scripts/git/git-prompt-display.ts +22 -0
  629. package/scripts/git/git-prompt.ts +207 -0
  630. package/scripts/git/git-push-transport.ts +173 -0
  631. package/scripts/git/git-push.ts +27 -0
  632. package/scripts/git/git-remote-branch.ts +40 -0
  633. package/scripts/git/git-spawn.ts +47 -0
  634. package/scripts/git/git-staging.ts +128 -0
  635. package/scripts/git/git-stash.ts +124 -0
  636. package/scripts/git/git-status.ts +198 -0
  637. package/scripts/git/git-worktree.ts +110 -0
  638. package/scripts/git/github-issue-url.ts +105 -0
  639. package/scripts/git/gone-branch.ts +113 -0
  640. package/scripts/git/issue-labels.ts +279 -0
  641. package/scripts/git/listing-cutoff.ts +51 -0
  642. package/scripts/git/main-merge-guard.ts +134 -0
  643. package/scripts/git/main-merge.ts +120 -0
  644. package/scripts/git/main-sync.ts +121 -0
  645. package/scripts/git/parse-json-array.ts +102 -0
  646. package/scripts/git/schemas.ts +166 -0
  647. package/scripts/git/stash-orphans.ts +91 -0
  648. package/scripts/git/stash-pop-args.ts +59 -0
  649. package/scripts/git/stash-pop-cli.ts +105 -0
  650. package/scripts/git/telegram-notify.ts +404 -0
  651. package/scripts/hooks/batch-guard.ts +144 -0
  652. package/scripts/hooks/check-commit-message.ts +134 -0
  653. package/scripts/hooks/codex-hook-adapter.ts +155 -0
  654. package/scripts/hooks/edited-cspell.ts +128 -0
  655. package/scripts/hooks/format-edited-file-fixtures.ts +109 -0
  656. package/scripts/hooks/format-edited-file.ts +510 -0
  657. package/scripts/hooks/format-rewrite-notice.ts +99 -0
  658. package/scripts/hooks/pre-push-unit.ts +146 -0
  659. package/scripts/hooks/pretool-guard.ts +96 -0
  660. package/scripts/hooks/prevent-main-commit.ts +38 -0
  661. package/scripts/hooks/prompt-hooks.ts +38 -0
  662. package/scripts/hooks/reserved-run.ts +90 -0
  663. package/scripts/hooks/stop-guard.ts +135 -0
  664. package/scripts/init/claude-plugin-config.ts +51 -0
  665. package/scripts/init/distributed-paths.ts +100 -0
  666. package/scripts/init/hook-command-rewrite.ts +85 -0
  667. package/scripts/init/hook-launch.ts +31 -0
  668. package/scripts/init/init-actions.ts +147 -0
  669. package/scripts/init/init-ai-copy.ts +235 -0
  670. package/scripts/init/init-copy-content.ts +50 -0
  671. package/scripts/init/init-logic-deploy-vps.ts +43 -0
  672. package/scripts/init/init-logic-json-merge.ts +340 -0
  673. package/scripts/init/init-logic-migrate.ts +62 -0
  674. package/scripts/init/init-logic-package-key-order.ts +50 -0
  675. package/scripts/init/init-logic-secretlint.ts +36 -0
  676. package/scripts/init/init-logic-sonar.ts +197 -0
  677. package/scripts/init/init-logic-templates.ts +142 -0
  678. package/scripts/init/init-logic-workspace.ts +59 -0
  679. package/scripts/init/init-logic-yaml-merge.ts +57 -0
  680. package/scripts/init/init-logic.ts +474 -0
  681. package/scripts/init/init-paths.ts +11 -0
  682. package/scripts/init/init-sonar.ts +32 -0
  683. package/scripts/init/init.ts +219 -0
  684. package/scripts/init/kit-base-preset.ts +60 -0
  685. package/scripts/init/plugin-install-hint.ts +47 -0
  686. package/scripts/init/tsconfig-preset-migration.ts +67 -0
  687. package/scripts/issue/baseline-measure.ts +105 -0
  688. package/scripts/issue/behavior-change-lint.ts +122 -0
  689. package/scripts/issue/defect-rate-cli.ts +167 -0
  690. package/scripts/issue/defect-rate.ts +145 -0
  691. package/scripts/issue/issue-backlinks-cli.ts +97 -0
  692. package/scripts/issue/issue-backlinks.ts +164 -0
  693. package/scripts/issue/issue-cite-cli.ts +158 -0
  694. package/scripts/issue/issue-cite.ts +102 -0
  695. package/scripts/issue/issue-comment-cli.ts +95 -0
  696. package/scripts/issue/issue-fold-cli.ts +104 -0
  697. package/scripts/issue/issue-fold-existing-cli.ts +81 -0
  698. package/scripts/issue/issue-fold-existing.ts +73 -0
  699. package/scripts/issue/issue-fold.ts +42 -0
  700. package/scripts/issue/issue-lint-cli.ts +60 -0
  701. package/scripts/issue/issue-lint.ts +26 -0
  702. package/scripts/issue/issue-logic.ts +50 -0
  703. package/scripts/issue/issue-read-cli.ts +190 -0
  704. package/scripts/issue/issue-read.ts +145 -0
  705. package/scripts/issue/issue-scout-cli.ts +482 -0
  706. package/scripts/issue/issue-scout.ts +244 -0
  707. package/scripts/issue/issue-state-cli.ts +260 -0
  708. package/scripts/issue/issue-state.ts +109 -0
  709. package/scripts/issue/markdown-section.ts +39 -0
  710. package/scripts/issue/measure-rerun-cli.ts +98 -0
  711. package/scripts/issue/reproduction-measure.ts +59 -0
  712. package/scripts/josh/__snapshots__/josh-command-map.test.ts.snap +1171 -0
  713. package/scripts/josh/agent-session-environment.ts +188 -0
  714. package/scripts/josh/cli-body.ts +96 -0
  715. package/scripts/josh/command-suggest.ts +57 -0
  716. package/scripts/josh/file-map-stamp.ts +264 -0
  717. package/scripts/josh/hook-decision.ts +479 -0
  718. package/scripts/josh/josh-command-map.ts +196 -0
  719. package/scripts/josh/josh-command-types.ts +226 -0
  720. package/scripts/josh/josh-commands-ai.ts +327 -0
  721. package/scripts/josh/josh-commands-backlog.ts +54 -0
  722. package/scripts/josh/josh-commands-clone.ts +18 -0
  723. package/scripts/josh/josh-commands-development.ts +206 -0
  724. package/scripts/josh/josh-commands-document.ts +45 -0
  725. package/scripts/josh/josh-commands-guard.ts +38 -0
  726. package/scripts/josh/josh-commands-hooks.ts +42 -0
  727. package/scripts/josh/josh-commands-issue.ts +69 -0
  728. package/scripts/josh/josh-commands-lane.ts +75 -0
  729. package/scripts/josh/josh-commands-lint.ts +37 -0
  730. package/scripts/josh/josh-commands-maintenance.ts +80 -0
  731. package/scripts/josh/josh-commands-project.ts +53 -0
  732. package/scripts/josh/josh-commands-split.ts +20 -0
  733. package/scripts/josh/josh-commands-versioning.ts +48 -0
  734. package/scripts/josh/josh-commands-workflow.ts +116 -0
  735. package/scripts/josh/josh-composite-arguments.ts +55 -0
  736. package/scripts/josh/josh-environment-file.ts +31 -0
  737. package/scripts/josh/josh-in-process.ts +80 -0
  738. package/scripts/josh/josh-logic.ts +308 -0
  739. package/scripts/josh/josh-run.ts +53 -0
  740. package/scripts/josh/josh-script-reader.ts +11 -0
  741. package/scripts/josh/josh-verdict.ts +111 -0
  742. package/scripts/josh/josh.ts +60 -0
  743. package/scripts/josh/kit-only.ts +33 -0
  744. package/scripts/josh/path-decision.ts +104 -0
  745. package/scripts/josh/platform-temporary.ts +66 -0
  746. package/scripts/josh/process-identity.ts +335 -0
  747. package/scripts/josh/session-language-cli.ts +51 -0
  748. package/scripts/josh/session-language.ts +30 -0
  749. package/scripts/josh/stamp-file.ts +194 -0
  750. package/scripts/lane/lane-await.ts +165 -0
  751. package/scripts/lane/lane-cache-run.ts +39 -0
  752. package/scripts/lane/lane-cache.ts +135 -0
  753. package/scripts/lane/lane-capacity.ts +69 -0
  754. package/scripts/lane/lane-child-invocation.ts +73 -0
  755. package/scripts/lane/lane-child-marker.ts +58 -0
  756. package/scripts/lane/lane-cli.ts +410 -0
  757. package/scripts/lane/lane-close.ts +197 -0
  758. package/scripts/lane/lane-dispatch-log.ts +13 -0
  759. package/scripts/lane/lane-dispatch.ts +458 -0
  760. package/scripts/lane/lane-environment.ts +253 -0
  761. package/scripts/lane/lane-guard-policy.ts +136 -0
  762. package/scripts/lane/lane-install.ts +94 -0
  763. package/scripts/lane/lane-launch-cli.ts +133 -0
  764. package/scripts/lane/lane-occupancy.ts +112 -0
  765. package/scripts/lane/lane-open.ts +275 -0
  766. package/scripts/lane/lane-output.ts +124 -0
  767. package/scripts/lane/lane-paths.ts +96 -0
  768. package/scripts/lane/lane-reap.ts +137 -0
  769. package/scripts/lane/lane-registry.ts +261 -0
  770. package/scripts/lane/lane-relaunch.ts +68 -0
  771. package/scripts/lane/lane-report.ts +95 -0
  772. package/scripts/lane/lane-resume.ts +61 -0
  773. package/scripts/lane/lane-seed.ts +44 -0
  774. package/scripts/lane/lane-start-point.ts +175 -0
  775. package/scripts/lane/openai-lane-supervisor-cli.ts +32 -0
  776. package/scripts/lane/openai-lane-supervisor-decision.ts +63 -0
  777. package/scripts/lane/openai-lane-supervisor.ts +337 -0
  778. package/scripts/lib/bounded-pool.ts +109 -0
  779. package/scripts/lib/buffered-process.ts +82 -0
  780. package/scripts/lib/caddy-logs.sh +45 -0
  781. package/scripts/lib/cli-flags.ts +19 -0
  782. package/scripts/lib/json-value.ts +24 -0
  783. package/scripts/lib/poll.ts +57 -0
  784. package/scripts/lib/read-file.ts +16 -0
  785. package/scripts/lib/schemas.ts +67 -0
  786. package/scripts/lib/spawn-exit.ts +45 -0
  787. package/scripts/lib/status-icons.ts +24 -0
  788. package/scripts/lines/effective-limit.ts +156 -0
  789. package/scripts/lines/line-budget.ts +404 -0
  790. package/scripts/lines/line-targets.ts +80 -0
  791. package/scripts/lines/lines-command.ts +174 -0
  792. package/scripts/lint/cspell-cached.ts +41 -0
  793. package/scripts/lint/lint-parallel.ts +72 -0
  794. package/scripts/lint/lint-related-scope.ts +128 -0
  795. package/scripts/lint/lint-related.ts +104 -0
  796. package/scripts/managed-marker/index.ts +5 -0
  797. package/scripts/managed-marker/managed-marker-logic.ts +67 -0
  798. package/scripts/observations/observation-ledger-home.ts +32 -0
  799. package/scripts/observations/observation-ledger-line.ts +93 -0
  800. package/scripts/observations/observation-ledger.ts +35 -0
  801. package/scripts/observations/observations-flush-cli.ts +42 -0
  802. package/scripts/observations/observations-flush-landing.ts +97 -0
  803. package/scripts/observations/observations-flush.ts +420 -0
  804. package/scripts/overrides/lockfile-overrides.ts +105 -0
  805. package/scripts/overrides/overrides-check.ts +84 -0
  806. package/scripts/overrides/overrides-files.ts +19 -0
  807. package/scripts/overrides/overrides-logic.ts +211 -0
  808. package/scripts/overrides/schemas.ts +49 -0
  809. package/scripts/package/package-scout-cli.ts +195 -0
  810. package/scripts/package/package-scout-format.ts +151 -0
  811. package/scripts/package/package-scout.ts +121 -0
  812. package/scripts/ports/port-command.ts +87 -0
  813. package/scripts/propagate/propagate-git-failure.ts +191 -0
  814. package/scripts/propagate/propagate-git.ts +224 -0
  815. package/scripts/propagate/propagate-publish.ts +181 -0
  816. package/scripts/propagate/propagate-run.ts +201 -0
  817. package/scripts/propagate/propagate-steps.ts +421 -0
  818. package/scripts/propagate/propagate-targets.ts +160 -0
  819. package/scripts/propagate/propagate.ts +216 -0
  820. package/scripts/refactor/import-graph.ts +187 -0
  821. package/scripts/refactor/refactor-lint.ts +250 -0
  822. package/scripts/refactor/refactor-scan-cli.ts +10 -0
  823. package/scripts/refactor/refactor-scan.ts +124 -0
  824. package/scripts/refactor/refactor-targets.ts +103 -0
  825. package/scripts/release/release-cli.ts +88 -0
  826. package/scripts/release/release-history.ts +132 -0
  827. package/scripts/release/release-plan.ts +130 -0
  828. package/scripts/release/release-publish.ts +152 -0
  829. package/scripts/release/release-scope-cli.ts +103 -0
  830. package/scripts/release/release-tag.ts +93 -0
  831. package/scripts/release/release-worktree.ts +71 -0
  832. package/scripts/repo/auto-merge-setting-logic.ts +100 -0
  833. package/scripts/repo/auto-merge-setting.ts +37 -0
  834. package/scripts/repo/repo-setting.ts +112 -0
  835. package/scripts/report/report-lint-cli.ts +49 -0
  836. package/scripts/report/report-lint.ts +250 -0
  837. package/scripts/retrospective/retrospective-cli.ts +97 -0
  838. package/scripts/retrospective/retrospective.ts +127 -0
  839. package/scripts/review/disposition-cli.ts +44 -0
  840. package/scripts/review/disposition-logic.ts +45 -0
  841. package/scripts/review/live-evidence.ts +62 -0
  842. package/scripts/review/review-attest-cli.ts +115 -0
  843. package/scripts/review/review-attest.ts +319 -0
  844. package/scripts/review/review-brief-cli.ts +290 -0
  845. package/scripts/review/review-brief.ts +440 -0
  846. package/scripts/review/review-checkout.ts +56 -0
  847. package/scripts/review/review-finding-ledger.ts +167 -0
  848. package/scripts/review/review-findings-cli.ts +57 -0
  849. package/scripts/review/review-level.ts +86 -0
  850. package/scripts/review/review-record-cli.ts +196 -0
  851. package/scripts/review/review-record.ts +74 -0
  852. package/scripts/review/review-round2-cli.ts +84 -0
  853. package/scripts/review/review-round2.ts +139 -0
  854. package/scripts/review/review-stamps.ts +113 -0
  855. package/scripts/review/review-tree.ts +58 -0
  856. package/scripts/rules/bash-triggers.ts +44 -0
  857. package/scripts/rules/decision-oracle.ts +342 -0
  858. package/scripts/rules/delivered-rules-harness.ts +72 -0
  859. package/scripts/rules/delivered-rules.ts +793 -0
  860. package/scripts/rules/early-heartbeat.ts +241 -0
  861. package/scripts/rules/file-body.ts +150 -0
  862. package/scripts/rules/filing-cap.ts +133 -0
  863. package/scripts/rules/filing-offer.ts +81 -0
  864. package/scripts/rules/firing-point.ts +63 -0
  865. package/scripts/rules/gh-api.ts +65 -0
  866. package/scripts/rules/git-argv.ts +129 -0
  867. package/scripts/rules/git-force.ts +104 -0
  868. package/scripts/rules/implementation-cut-verdict.ts +84 -0
  869. package/scripts/rules/implementation-cut.ts +202 -0
  870. package/scripts/rules/issue-citation.ts +242 -0
  871. package/scripts/rules/issue-fold.ts +73 -0
  872. package/scripts/rules/issue-scout.ts +64 -0
  873. package/scripts/rules/josh-git-bare.ts +80 -0
  874. package/scripts/rules/lane-carry-conflict.ts +96 -0
  875. package/scripts/rules/lane-interactive-ask.ts +71 -0
  876. package/scripts/rules/lane-park.ts +122 -0
  877. package/scripts/rules/lane-switch-main.ts +139 -0
  878. package/scripts/rules/oracle-consulted.ts +81 -0
  879. package/scripts/rules/oracle-firing.ts +151 -0
  880. package/scripts/rules/oracle-list-cli.ts +81 -0
  881. package/scripts/rules/piped-verification.ts +126 -0
  882. package/scripts/rules/poll-loop.ts +125 -0
  883. package/scripts/rules/pre-gate-cut.ts +207 -0
  884. package/scripts/rules/prior-comment-read.ts +106 -0
  885. package/scripts/rules/raw-field-body.ts +56 -0
  886. package/scripts/rules/reply-language.ts +116 -0
  887. package/scripts/rules/rule-body-guard.ts +206 -0
  888. package/scripts/rules/rule-guard.ts +23 -0
  889. package/scripts/rules/rule-value-cli.ts +129 -0
  890. package/scripts/rules/rule-value.ts +397 -0
  891. package/scripts/rules/run-tail.ts +178 -0
  892. package/scripts/rules/shell-body-trigger.ts +204 -0
  893. package/scripts/rules/shell-segments.ts +45 -0
  894. package/scripts/rules/stop-rules.ts +329 -0
  895. package/scripts/rules/tail-commands.ts +35 -0
  896. package/scripts/rules/test-declared-commit.ts +51 -0
  897. package/scripts/rules/third-party-write.ts +90 -0
  898. package/scripts/rules/top-level-scripts-guard.ts +47 -0
  899. package/scripts/rules/worktree-guard.ts +130 -0
  900. package/scripts/run/detached-launch.ts +360 -0
  901. package/scripts/run/run-carry-args.ts +264 -0
  902. package/scripts/run/run-carry-change.ts +69 -0
  903. package/scripts/run/run-carry-cli.ts +441 -0
  904. package/scripts/run/run-carry-flush.ts +63 -0
  905. package/scripts/run/run-carry-stash.ts +71 -0
  906. package/scripts/run/run-carry-streak.ts +113 -0
  907. package/scripts/run/run-carry.ts +550 -0
  908. package/scripts/run/run-cut-args.ts +132 -0
  909. package/scripts/run/run-cut-cli.ts +461 -0
  910. package/scripts/run/run-cut-handoff.ts +126 -0
  911. package/scripts/run/run-cut.ts +531 -0
  912. package/scripts/run/run-ending-cli.ts +111 -0
  913. package/scripts/run/run-ending.ts +239 -0
  914. package/scripts/run/run-entry-cli.ts +135 -0
  915. package/scripts/run/run-entry.ts +95 -0
  916. package/scripts/run/run-event-cli.ts +210 -0
  917. package/scripts/run/run-event-follow.ts +65 -0
  918. package/scripts/run/run-event-render.ts +75 -0
  919. package/scripts/run/run-event-scope.ts +127 -0
  920. package/scripts/run/run-event-stream-emit.ts +140 -0
  921. package/scripts/run/run-event-stream.ts +258 -0
  922. package/scripts/run/run-event-watch.ts +37 -0
  923. package/scripts/run/run-headless.ts +105 -0
  924. package/scripts/run/run-hold-cli.ts +310 -0
  925. package/scripts/run/run-hold.ts +264 -0
  926. package/scripts/run/run-invocation.ts +237 -0
  927. package/scripts/run/run-issue-number.ts +19 -0
  928. package/scripts/run/run-liveness-cli.ts +169 -0
  929. package/scripts/run/run-liveness.ts +424 -0
  930. package/scripts/run/run-merge-cli.ts +385 -0
  931. package/scripts/run/run-merge-steps.ts +326 -0
  932. package/scripts/run/run-merge.ts +158 -0
  933. package/scripts/run/run-next-cli.ts +48 -0
  934. package/scripts/run/run-next.ts +80 -0
  935. package/scripts/run/run-preflight.ts +337 -0
  936. package/scripts/run/run-prep-cli.ts +151 -0
  937. package/scripts/run/run-prep.ts +84 -0
  938. package/scripts/run/run-progress-args.ts +65 -0
  939. package/scripts/run/run-progress-cli.ts +508 -0
  940. package/scripts/run/run-progress-clock.ts +320 -0
  941. package/scripts/run/run-progress-config.ts +119 -0
  942. package/scripts/run/run-progress-read.ts +199 -0
  943. package/scripts/run/run-progress.ts +366 -0
  944. package/scripts/run/run-report-cli.ts +71 -0
  945. package/scripts/run/run-report.ts +78 -0
  946. package/scripts/run/run-review-cli.ts +130 -0
  947. package/scripts/run/run-review-steps.ts +161 -0
  948. package/scripts/run/run-review.ts +121 -0
  949. package/scripts/run/run-ship-cli.ts +431 -0
  950. package/scripts/run/run-ship-detach.ts +200 -0
  951. package/scripts/run/run-ship-probe.ts +103 -0
  952. package/scripts/run/run-ship-return.ts +75 -0
  953. package/scripts/run/run-ship-review-steps.ts +227 -0
  954. package/scripts/run/run-ship-review.ts +177 -0
  955. package/scripts/run/run-ship-stage.ts +150 -0
  956. package/scripts/run/run-ship.ts +78 -0
  957. package/scripts/run/run-status-cli.ts +175 -0
  958. package/scripts/run/run-status.ts +77 -0
  959. package/scripts/run/run-step-cli.ts +111 -0
  960. package/scripts/run/run-step.ts +292 -0
  961. package/scripts/run/run-stop-notify.ts +52 -0
  962. package/scripts/run/run-stranded-cli.ts +31 -0
  963. package/scripts/run/run-stranded-detect.ts +134 -0
  964. package/scripts/run/run-stranded.ts +120 -0
  965. package/scripts/run/run-tail-cli.ts +105 -0
  966. package/scripts/run/run-tail.ts +61 -0
  967. package/scripts/run/run-transcript.golden.txt +57 -0
  968. package/scripts/run/run-wake-cli.ts +428 -0
  969. package/scripts/run/run-wake-describe.ts +97 -0
  970. package/scripts/run/run-wake-driver.ts +80 -0
  971. package/scripts/run/run-wake-handoff.ts +29 -0
  972. package/scripts/run/run-wake-loop.ts +223 -0
  973. package/scripts/run/run-wake-session.ts +150 -0
  974. package/scripts/run/run-wake-work.ts +104 -0
  975. package/scripts/run/run-wake.ts +607 -0
  976. package/scripts/run/run-watcher-guard-cli.ts +37 -0
  977. package/scripts/run/run-watcher-guard.ts +59 -0
  978. package/scripts/run/run-watcher-hook.ts +86 -0
  979. package/scripts/security/secretlint-scan.ts +86 -0
  980. package/scripts/security/security-audit-logic.ts +51 -0
  981. package/scripts/security/security-audit-provision-logic.ts +217 -0
  982. package/scripts/security/security-audit-provision.ts +186 -0
  983. package/scripts/security/security-audit.ts +132 -0
  984. package/scripts/security/security-updates-logic.ts +131 -0
  985. package/scripts/security/security-updates.ts +38 -0
  986. package/scripts/security/sonar-file.ts +44 -0
  987. package/scripts/self-sync-guard/index.ts +5 -0
  988. package/scripts/self-sync-guard/self-sync-guard-logic.ts +98 -0
  989. package/scripts/self-sync-guard/self-sync-refusal.ts +22 -0
  990. package/scripts/sonar/sonar-hotspots-cli.ts +149 -0
  991. package/scripts/sonar/sonar-hotspots.ts +111 -0
  992. package/scripts/split/split-assess-cli.ts +52 -0
  993. package/scripts/split/split-assess.ts +124 -0
  994. package/scripts/sync/dependabot-pin-logic.ts +135 -0
  995. package/scripts/sync/directory-copy-guard.ts +187 -0
  996. package/scripts/sync/file-content.ts +49 -0
  997. package/scripts/sync/managed-config-scope-cli.ts +64 -0
  998. package/scripts/sync/managed-config-scope.ts +123 -0
  999. package/scripts/sync/plugin-skill-directories.ts +15 -0
  1000. package/scripts/sync/reconcile-templates.ts +53 -0
  1001. package/scripts/sync/removed-skill-manifest.ts +27 -0
  1002. package/scripts/sync/skill-migration.ts +192 -0
  1003. package/scripts/sync/sync-configs.ts +156 -0
  1004. package/scripts/sync/sync-hook-safety.ts +82 -0
  1005. package/scripts/sync/sync.ts +417 -0
  1006. package/scripts/sync/synced-paths.ts +52 -0
  1007. package/scripts/sync/template-source-logic.ts +122 -0
  1008. package/scripts/sync/workflow-pin-logic.ts +240 -0
  1009. package/scripts/test/classify-isolation.ts +149 -0
  1010. package/scripts/test/e2e-retry-check.ts +150 -0
  1011. package/scripts/test/http-fault-injection.ts +79 -0
  1012. package/scripts/test/josh-harness-environment.ts +260 -0
  1013. package/scripts/test/josh-harness.ts +96 -0
  1014. package/scripts/test/pilot-files.ts +457 -0
  1015. package/scripts/test/pilot-measure.ts +78 -0
  1016. package/scripts/test/test-declared-changed.ts +99 -0
  1017. package/scripts/test/test-declared-logic.ts +91 -0
  1018. package/scripts/test/test-declared-match.ts +106 -0
  1019. package/scripts/test/test-declared.ts +180 -0
  1020. package/scripts/test/test-e2e-guard.ts +86 -0
  1021. package/scripts/test/test-network-guard.ts +453 -0
  1022. package/scripts/test/test-red-commit.ts +51 -0
  1023. package/scripts/test/test-red-logic.ts +76 -0
  1024. package/scripts/test/test-red.ts +154 -0
  1025. package/scripts/test/test-related-scope.ts +115 -0
  1026. package/scripts/test/test-related.ts +73 -0
  1027. package/scripts/test/test-repository-guard.ts +317 -0
  1028. package/scripts/test/test-state-guard.ts +85 -0
  1029. package/scripts/test/test-stdout-guard.ts +54 -0
  1030. package/scripts/test/test-telegram-guard.ts +90 -0
  1031. package/scripts/test/test-type-logic.ts +31 -0
  1032. package/scripts/test/test-unit-guard.ts +185 -0
  1033. package/scripts/test/unit-guard-environment.ts +12 -0
  1034. package/scripts/test/unit-projects.ts +139 -0
  1035. package/scripts/test/unit-worker-share.ts +251 -0
  1036. package/scripts/test/vitest-include-globs.ts +12 -0
  1037. package/scripts/time-runtime/time-agent-bundles.ts +128 -0
  1038. package/scripts/time-runtime/time-background.ts +300 -0
  1039. package/scripts/time-runtime/time-batch-guard-fixtures.ts +66 -0
  1040. package/scripts/time-runtime/time-batch-guard.ts +529 -0
  1041. package/scripts/time-runtime/time-bundle-call.ts +575 -0
  1042. package/scripts/time-runtime/time-bundles.ts +536 -0
  1043. package/scripts/time-runtime/time-call-identity.ts +37 -0
  1044. package/scripts/time-runtime/time-command-key.ts +35 -0
  1045. package/scripts/time-runtime/time-density-hook.ts +166 -0
  1046. package/scripts/time-runtime/time-density.ts +147 -0
  1047. package/scripts/time-runtime/time-followup-stage.ts +107 -0
  1048. package/scripts/time-runtime/time-format.ts +186 -0
  1049. package/scripts/time-runtime/time-hook-transcript.ts +82 -0
  1050. package/scripts/time-runtime/time-instant.ts +20 -0
  1051. package/scripts/time-runtime/time-markers.ts +228 -0
  1052. package/scripts/time-runtime/time-phase-names.ts +123 -0
  1053. package/scripts/time-runtime/time-reported-failure.ts +227 -0
  1054. package/scripts/time-runtime/time-round-trips.ts +279 -0
  1055. package/scripts/time-runtime/time-shell.ts +286 -0
  1056. package/scripts/time-runtime/time-single-check.ts +65 -0
  1057. package/scripts/time-runtime/time-spans.ts +545 -0
  1058. package/scripts/time-runtime/time-transcript-line.ts +253 -0
  1059. package/scripts/time-runtime/time-writes.ts +71 -0
  1060. package/scripts/ui/ui-routes-cli.ts +122 -0
  1061. package/scripts/ui/ui-routes.ts +102 -0
  1062. package/scripts/version/bump-version.ts +71 -0
  1063. package/scripts/version/effective-upstream.ts +93 -0
  1064. package/scripts/version/index.ts +25 -0
  1065. package/scripts/version/kit-descriptor.ts +10 -0
  1066. package/scripts/version/kit-version-config.ts +30 -0
  1067. package/scripts/version/latest-corepack.ts +404 -0
  1068. package/scripts/version/latest-lane-guard.ts +49 -0
  1069. package/scripts/version/latest-regression.ts +93 -0
  1070. package/scripts/version/latest-scope-cli.ts +147 -0
  1071. package/scripts/version/latest-stamp.ts +107 -0
  1072. package/scripts/version/latest-update.ts +198 -0
  1073. package/scripts/version/package-manager-version.ts +95 -0
  1074. package/scripts/version/parse-json.ts +13 -0
  1075. package/scripts/version/preinstall-version-update.ts +84 -0
  1076. package/scripts/version/publishable-range-check.ts +74 -0
  1077. package/scripts/version/publishable-range.ts +123 -0
  1078. package/scripts/version/release-age.ts +146 -0
  1079. package/scripts/version/release-hold.ts +142 -0
  1080. package/scripts/version/running-binary.ts +42 -0
  1081. package/scripts/version/upgrade-command-guard.ts +49 -0
  1082. package/scripts/version/upgrade-shell-command.ts +30 -0
  1083. package/scripts/version/version-check-logic.ts +333 -0
  1084. package/scripts/version/version-check.ts +14 -0
  1085. package/scripts/version/version-command-config.ts +177 -0
  1086. package/scripts/version/version-commands.ts +296 -0
  1087. package/scripts/version/version-remote.ts +86 -0
  1088. package/scripts/version/version-targets.ts +81 -0
  1089. package/scripts/yaml/yaml-document.ts +46 -0
  1090. package/scripts-ai/completion-gate.ts +13 -0
  1091. package/scripts-ai/environment-loader.ts +9 -0
  1092. package/scripts-ai/epic-check.ts +34 -0
  1093. package/scripts-ai/epic-cli-argv.ts +77 -0
  1094. package/scripts-ai/epic-cli-remove.ts +71 -0
  1095. package/scripts-ai/epic-cli.ts +413 -0
  1096. package/scripts-ai/epic.ts +192 -0
  1097. package/scripts-ai/followup-issue-number.ts +31 -0
  1098. package/scripts-ai/git-followup-finish.ts +217 -0
  1099. package/scripts-ai/git-followup-workflow.ts +252 -0
  1100. package/scripts-ai/git-workflow.ts +246 -0
  1101. package/scripts-ai/telegram-test-logic.ts +88 -0
  1102. package/scripts-ai/telegram-test.ts +130 -0
  1103. package/templates/gitignore +76 -0
  1104. package/templates/sonar-project.properties +52 -0
  1105. package/templates/workflows/ci.yml +639 -0
  1106. package/templates/workflows/dependabot-auto-merge.yml +428 -0
  1107. package/tsconfig/base.json +50 -0
  1108. package/tsconfig.sonar.json +34 -0
@@ -0,0 +1,793 @@
1
+ import { investigation_reads } from '#scripts/delegation/investigation-reads'
2
+ import { hook_decision, type GuardRun, type TranscriptGuardSpec } from '#scripts/josh/hook-decision'
3
+ import { lane_guard_policy } from '#scripts/lane/lane-guard-policy'
4
+ import { time_batch_guard, type GuardedCall } from '#scripts/time-runtime/time-batch-guard'
5
+ import { bash_triggers } from './bash-triggers'
6
+ import { early_heartbeat } from './early-heartbeat'
7
+ import { file_body } from './file-body'
8
+ import { filing_cap } from './filing-cap'
9
+ import { gh_api } from './gh-api'
10
+ import { git_force } from './git-force'
11
+ import { implementation_cut } from './implementation-cut'
12
+ import { issue_fold } from './issue-fold'
13
+ import { issue_scout } from './issue-scout'
14
+ import { josh_git_bare } from './josh-git-bare'
15
+ import { lane_carry_conflict } from './lane-carry-conflict'
16
+ import { lane_interactive_ask } from './lane-interactive-ask'
17
+ import { lane_park } from './lane-park'
18
+ import { lane_switch_main } from './lane-switch-main'
19
+ import { oracle_consulted } from './oracle-consulted'
20
+ import { piped_verification } from './piped-verification'
21
+ import { poll_loop } from './poll-loop'
22
+ import { pre_gate_cut } from './pre-gate-cut'
23
+ import { prior_comment_read } from './prior-comment-read'
24
+ import { raw_field_body } from './raw-field-body'
25
+ import { rule_body_guard } from './rule-body-guard'
26
+ import { run_tail } from './run-tail'
27
+ import { shell_body_trigger } from './shell-body-trigger'
28
+ import { shell_segments } from './shell-segments'
29
+ import { test_declared_commit } from './test-declared-commit'
30
+ import { third_party_write } from './third-party-write'
31
+ import { worktree_guard } from './worktree-guard'
32
+
33
+ // The enumeration of rules delivered at the moment they bind, rather than carried resident in
34
+ // `CLAUDE.md` on every turn (joshuafolkken/kit#1524).
35
+ //
36
+ // **It exists because residency ran out and delivery did not.** `CLAUDE.md` sits 6 tokens under the
37
+ // ceiling `scripts/claude/workflow-skills.test.ts` enforces, while `prompts/` and `.claude/skills/` hold
38
+ // fifteen times as much on demand — so the pressure is on the one channel that costs every turn.
39
+ // joshuafolkken/kit#1344 measured three consecutive runs in which resident prose about batching moved
40
+ // the number not at all, and joshuafolkken/kit#1460 measured the same for the investigation
41
+ // threshold; in both, a `PreToolUse` refusal was what finally moved it. A rule whose trigger can be
42
+ // named is therefore cheaper **and** stronger delivered than carried.
43
+ //
44
+ // **No new machinery.** `hook_decision.create_transcript_guard` is the shell both existing guards
45
+ // already share (joshuafolkken/kit#1460) — the payload schema, the deny envelope, the switch, the
46
+ // `.env` load and the once-per-run stamp — and every entry below is one of its specs. Building a
47
+ // second delivery path would be the clone `CLAUDE.md` prohibits, in the one place where two paths
48
+ // would disagree about whether a rule was delivered at all.
49
+ //
50
+ // **What this file is not.** It holds no rule *text* that exists nowhere else: each entry's reason is
51
+ // the trigger plus the instruction that must be obeyed before anything else is read, and names the
52
+ // topic file that carries the procedure — the same "trigger plus pointer" shape a resident rule takes
53
+ // (`prompts/collaboration-workflow/residency.md`).
54
+
55
+ // The escape hatch, on by default like the other two guards. A distributed convention nobody enabled
56
+ // would leave this Issue where it started.
57
+ const SWITCH_ENV_KEY = 'JOSH_RULE_GUARD'
58
+
59
+ // **What a compliance test is asked of: the call, the turn it went out in, and the run it belongs
60
+ // to** — the calls the same assistant message issued, and every call the run made
61
+ // (joshuafolkken/kit#1792 for the turn, joshuafolkken/kit#1867 for the run). Every row but two answers
62
+ // from the call alone and simply ignores the rest, which is why widening the one signature costs them
63
+ // nothing. **The batching rule cannot be written without the turn**: its subject is *how many calls a
64
+ // turn carried*, and no field of a single call says that. **The pre-gate cut cannot be written without
65
+ // the run**: a cut relaunches a second process that issues the identical entry check, so the two
66
+ // halves are separable only by a call one of them makes elsewhere in the run. In both cases the
67
+ // alternative was a second predicate slot beside this one, i.e. two ways to declare the same thing.
68
+ type CallTest = (
69
+ call: GuardedCall,
70
+ turn: ReadonlyArray<GuardedCall>,
71
+ run: ReadonlyArray<GuardedCall>,
72
+ ) => boolean
73
+
74
+ // One rule delivered by trigger. `id` keys its own refusal record, so one rule firing never spends
75
+ // another's budget.
76
+ interface DeliveredRule {
77
+ id: string
78
+ // Whether this call is the moment the rule binds, judged from the call alone.
79
+ is_trigger: (call: GuardedCall) => boolean
80
+ // What the model is told. The deny reason is the only text that reaches it, so it carries the
81
+ // instruction and the pointer rather than a summary of either.
82
+ reason: string
83
+ // **A stand-down read from the transcript tail, not the call** (joshuafolkken/kit#1905). A rule
84
+ // whose subject a run can *satisfy earlier in the run* — the comments read on the first open, so a
85
+ // later body read of the same Issue asks for nothing new — supplies this so the delivery is
86
+ // suppressed once that earlier act is on the tail. It is checked before `is_first_delivery`, so a
87
+ // satisfied call neither refuses nor spends the once-per-run record. Absent, delivery is unchanged.
88
+ already_satisfied?: (tail: string, call: GuardedCall) => boolean
89
+ // **A rule that has to bind on every occurrence supplies this, and once-per-run stops applying to
90
+ // it** (joshuafolkken/kit#1570). Once per run is right for a rule a run then obeys — read the
91
+ // comments, count the Issues, put the body in a file — because the refusal changes what the run
92
+ // knows. It is wrong for one whose subject is a *recurring* act: refused once and free
93
+ // afterwards, the enforcement is back to the parent's self-restraint, which is the thing that
94
+ // failed. A row with this field is asked it instead, and it is asked on every candidate call —
95
+ // `can_record` is what the batching stand-aside becomes for such a row (see `delivery_decision`).
96
+ // **`delivered_at_ms` is this row's own last refusal instant** (joshuafolkken/kit#2385) — `fire_once`
97
+ // writes the stamp only when a refusal actually fired, so a row that fires per crossing but must let
98
+ // an immediate reissue through (the implementation-phase cut) can tell a fresh crossing from a
99
+ // reissue of the edit it just refused. Rows that refuse unconditionally ignore it.
100
+ decide?: (call: GuardedCall, run: GuardRun, can_record: boolean, at_ms: number) => boolean
101
+ // **What keeping this rule looks like, as a call** (joshuafolkken/kit#1525). It names the act the
102
+ // rule asks for, so a run that made it *before* the trigger fired can be told apart from one that
103
+ // complied only because the refusal made it. `scripts/rules/rule-value.ts` reads that difference
104
+ // off recorded sessions to score what the rule's carried text earns unaided; a row that declares
105
+ // none is reported unmeasured rather than scored, because "never kept" and "always kept" are both
106
+ // claims the absence of a predicate does not support. It lives here rather than in the
107
+ // measurement so a rule's trigger and its compliance test stay one definition.
108
+ keeps?: CallTest
109
+ // **The occasion the rule governs, read in either spelling** (joshuafolkken/kit#1643).
110
+ // `is_trigger` is the right denominator for a rule whose trigger is a *neutral* act — filing an
111
+ // Issue, reading one — because a run that keeps the rule makes that call too. It is the wrong one
112
+ // for a rule whose trigger is the violation itself: a run that backgrounded every push never trips
113
+ // `run-tail`, so it drops out of the reading altogether and the rate is taken over runs that broke
114
+ // the rule at least once. Such a row declares this instead, and `scripts/rules/rule-value.ts`
115
+ // counts a run that reached it whether or not the trigger fired. Absent, the denominator stays
116
+ // `is_trigger` and the row's reading is exactly what it was.
117
+ reaches?: CallTest
118
+ }
119
+
120
+ // **A rule the measurement scores, whether or not `pnpm josh rule:guard` is what delivers it**
121
+ // (joshuafolkken/kit#1792). `DELIVERED_RULES` is the *delivery* registry — every row in it becomes a
122
+ // live `PreToolUse` guard through `GUARDS` below — so a rule already delivered by a binary of its own
123
+ // cannot join it without being refused twice for one violation, each refusal spending a record the
124
+ // other cannot see. The batching guard is that rule: `pnpm josh batch:guard` has delivered it since
125
+ // joshuafolkken/kit#1344, and until now it was the one delivered rule `pnpm josh rule:value` could
126
+ // not read. So the two registries are separated rather than merged, and `is_trigger` — the field
127
+ // that only a *delivered* row needs, because it is what `guard_of` makes the candidate test from —
128
+ // becomes the one optional field here.
129
+ type MeasuredRule = Omit<DeliveredRule, 'is_trigger'> & {
130
+ is_trigger?: DeliveredRule['is_trigger']
131
+ }
132
+
133
+ const STAMP_PREFIX = 'josh-rule-guard-'
134
+
135
+ // **`is_issue_filing` and `on_bash_command` moved to `bash-triggers.ts`** (joshuafolkken/kit#2119):
136
+ // three rows now share the filing trigger — the WIP cap, the scout gate and the per-run filing cap —
137
+ // and the last two live in their own modules, which could not import the enumeration back to reach a
138
+ // private function of it. `on_bash_command` went with it because those modules build their own rows.
139
+ const { is_issue_filing, on_bash_command } = bash_triggers
140
+
141
+ // The whole of the WIP cap, in the shape a refusal can carry: the count, the refusal, the two
142
+ // exemptions and the three tests that decide the second one. The three tests are spelled out rather
143
+ // than named, because a delivery that said only "an interrupt is exempt" would hand the deciding back
144
+ // to judgement at exactly the moment nothing else is open to read (joshuafolkken/kit#1518).
145
+ const WIP_CAP_REASON =
146
+ "⛔ backlog WIP cap: count the target repository's open Issues before filing. With more than 30 " +
147
+ 'open, close one first; nothing honestly closable means do not file. Two filings are exempt and ' +
148
+ 'proceed while stating the overage — one the run is blocked by, and an interrupt, decided by ' +
149
+ 'three tests rather than judgement: a verification answers wrongly, a documented workflow cannot ' +
150
+ 'complete, or data is lost or written outside the repository. Meeting none of the three, the ' +
151
+ 'finding is discretionary and waits. The count command and both procedures are in ' +
152
+ '`prompts/collaboration-workflow/wip-cap.md`. Reissue this call once you have counted — it fires ' +
153
+ 'once per run and cannot repeat on the call in hand.'
154
+
155
+ // **A shell line carries several commands, and the subcommand has to be the one being invoked.**
156
+ // Each segment is judged on its own, anchored at its start, so `gh issue comment <N> -b "… gh issue
157
+ // view <N> …"` is read as the write it is rather than as the read it quotes. The cut itself is
158
+ // `shell-segments.ts`, shared with the triggers that need the same one.
159
+ // Global flags may precede the subcommand (`gh --repo o/r issue view 1`), so they are skipped —
160
+ // the same optional-flag prefix `gh-api.ts` skips in front of `api`, shared from there.
161
+ const ISSUE_VIEW_COMMAND = new RegExp(String.raw`^gh\s+${gh_api.GH_FLAGS}issue\s+view\s`, 'u')
162
+ // `…/issues/<N>` — **one** Issue's body. The number has to end the path, so the listing
163
+ // (`…/issues`) and every sub-resource under it (`…/issues/1319/comments`) are left alone.
164
+ const ISSUE_BODY_PATH = /repos\/[^\s'"]*\/issues\/\d+(?=$|["'\s])/u
165
+ // **A write to that path is not a read of it**, which is why the body read below asks `gh_api.is_read`:
166
+ // `gh api` sends POST as soon as any field flag appears, and `kickoff` PATCHes `…/issues/<N>` to
167
+ // normalize a title and to fill a blank body — so without the read check the delivery would be spent
168
+ // refusing a write, and the genuine body read later in the same run would never be guarded.
169
+ // A segment that fetches comments: the flag, a `comments` field in a `--json` projection, or the
170
+ // comments endpoint. The short `-c` is deliberately absent — it belongs to `wc`, `grep` and `sort`
171
+ // far more often than to `gh`, and reading it as "comments included" silenced the rule on any line
172
+ // that ended in a pipe. A run that types it pays one round trip instead.
173
+ const FETCHES_COMMENTS = /--comments\b|--json\s[\w,]*\bcomments\b|\/comments\b/u
174
+ const ISSUES_PATH = /repos\/[^\s'"]*\/issues\//u
175
+
176
+ // A field projection — `--jq` for `gh api`, `--json` for `gh issue view` — whose value never names the
177
+ // body. `gh api …/issues/<N> --jq '{state, labels}'` fetches the Issue only to read its state or its
178
+ // labels, which is a state check and not the body read this rule guards (joshuafolkken/kit#1905); a
179
+ // `--jq '.body'` still names the body and stays a body read. The value is taken quoted or bare, so the
180
+ // comma list `--json state,labels` and the expression `'{state, labels}'` are read the same way.
181
+ const FIELD_PROJECTION = /(?:--jq|--json)[= ]\s*('[^']*'|"[^"]*"|\S+)/u
182
+ const NAMES_THE_BODY = /\bbody\b/u
183
+
184
+ function projects_away_body(segment: string): boolean {
185
+ const projection = FIELD_PROJECTION.exec(segment)
186
+
187
+ return projection !== null && !NAMES_THE_BODY.test(projection[1] ?? '')
188
+ }
189
+
190
+ function is_body_read_segment(segment: string): boolean {
191
+ if (projects_away_body(segment)) return false
192
+
193
+ if (ISSUE_VIEW_COMMAND.test(segment)) return true
194
+
195
+ return gh_api.is_gh_api(segment) && ISSUE_BODY_PATH.test(segment) && gh_api.is_read(segment)
196
+ }
197
+
198
+ // **An Issue's comments, not just any comments.** Batching pushes a run to fetch the body and the
199
+ // comments on one line, so the allowance has to reach across segments — but `gh pr view 42 --json
200
+ // comments` says nothing about whether *this* Issue was read whole, so the segment doing the
201
+ // fetching has to be an Issue read itself.
202
+ function fetches_issue_comments(segment: string): boolean {
203
+ if (!FETCHES_COMMENTS.test(segment)) return false
204
+
205
+ return (
206
+ ISSUE_VIEW_COMMAND.test(segment) || (gh_api.is_gh_api(segment) && ISSUES_PATH.test(segment))
207
+ )
208
+ }
209
+
210
+ // **The trigger is the body read, not the start of implementation.** The moment an Issue's body
211
+ // reaches a run is the moment the rule binds, and it is one shell call — the test
212
+ // `prompts/collaboration-workflow/rule-delivery.md` sets for leaving residency.
213
+ function is_body_only_issue_read(command: string): boolean {
214
+ const segments = shell_segments.segments_of(command)
215
+
216
+ if (segments.some((segment) => fetches_issue_comments(segment))) return false
217
+
218
+ return segments.some((segment) => is_body_read_segment(segment))
219
+ }
220
+
221
+ // **The refusal hands over the command that fixes it**, because reading is not the same as
222
+ // obeying: a sentence saying "also read the comments" is prose of exactly the kind
223
+ // joshuafolkken/kit#1344 measured as moving nothing, while a refused body read leaves the run
224
+ // holding the reissue that makes the comments *present*. The conflict rule ships with it — a
225
+ // delivery that said only "read them" would hand back the deciding at the moment nothing else is
226
+ // open to read, the mistake joshuafolkken/kit#1518 corrected for the WIP cap.
227
+ const ISSUE_COMMENTS_REASON =
228
+ "⛔ an Issue's comments are part of the Issue: read them before implementing, not only the body. " +
229
+ 'A decision recorded after the body was written lives only in a comment — a corrected diagnosis ' +
230
+ '(joshuafolkken/kit#1537), a changed default and an added acceptance criterion ' +
231
+ '(joshuafolkken/kit#1520), a scope handed to another Issue (joshuafolkken/kit#1304) — and ' +
232
+ 'nothing in the body says it was superseded, so a body-only reader builds the wrong thing and ' +
233
+ 'sees no contradiction. Reissue this read with the comments included: ' +
234
+ "`gh api repos/{owner}/{repo}/issues/<N>/comments --jq '.[] | {user: .user.login, created_at, " +
235
+ "body}'` beside the body read, or `gh issue view <N> --comments` where GraphQL is reachable. " +
236
+ 'Then the later text is the agreement in force — a comment supersedes the body it contradicts — ' +
237
+ "except for two answers that are not the run's to make: work a comment reassigns to another " +
238
+ 'Issue is out of scope and is not implemented, and a comment saying the Issue no longer has a ' +
239
+ 'reason to exist stops the run with a `confirmation` Telegram. The procedure is ' +
240
+ '`.claude/skills/workflow-commands/SKILL.md` → "An Issue\'s comments are part of the Issue". It ' +
241
+ 'fires once per run and cannot repeat on the call in hand.'
242
+
243
+ // The reading of the call itself — which spellings carry a body inline, and what the shell does to
244
+ // the value — is `shell-body-trigger.ts`, beside its own cases, as is the refusal text. A row states
245
+ // its trigger and its text; a model of zsh quoting is more than a row.
246
+ const { SHELL_BODY_REASON, carries_a_body, is_shell_evaluated_body, keeps_body_safe } =
247
+ shell_body_trigger
248
+
249
+ // **Keeping the WIP cap is counting the open Issues**, which is the one act the rule asks for before
250
+ // a filing.
251
+ //
252
+ // **It has to be Issues, open, and a listing — all three, in one segment.** A pattern that took any
253
+ // of them alone scored `gh pr list --state open` and `epic:bundle`'s candidate search as the count,
254
+ // and those inflate exactly the ratio the retirement decision reads. `gh issue list` alone is not
255
+ // enough either: the cap is about *open* Issues, and a listing that does not say so is some other
256
+ // question. Segment-wise like the comments predicate, so a spelling quoted inside a filing's body
257
+ // is not read as the count that filing skipped.
258
+ const ISSUE_LISTING = /^gh\s+(?:-{1,2}[\w-]+(?:[= ]\S+)?\s+)*issue\s+list\b/u
259
+ const ISSUES_QUERY = /repos\/[^\s'"]*\/issues\?[^\s'"]*state=open/u
260
+ const OPEN_STATE = /--state[= ]open|state=open/u
261
+ // **A label filter makes it a different question.** `gh issue list --label epic --state open` and
262
+ // `…/issues?labels=epic&state=open` ask which epics are open, which is what `epic:bundle` and the
263
+ // Issue template do; counting either as the WIP count would credit the cap as kept by a run that
264
+ // never counted the backlog. The residual the pattern cannot separate is named in
265
+ // `docs/josh-commands.md`: the inventory command in the `diag` skill is byte-identical to the count
266
+ // command in `wip-cap.md`, so no pattern can tell those two apart.
267
+ const LABEL_FILTER = /--label\b|[?&]labels=/u
268
+
269
+ function counts_open_issues(command: string): boolean {
270
+ return shell_segments.segments_of(command).some((segment) => {
271
+ if (LABEL_FILTER.test(segment)) return false
272
+
273
+ return (ISSUE_LISTING.test(segment) && OPEN_STATE.test(segment)) || ISSUES_QUERY.test(segment)
274
+ })
275
+ }
276
+
277
+ // **Keeping the comments rule is fetching them**, in any of the spellings the refusal hands back.
278
+ function reads_issue_comments(command: string): boolean {
279
+ return shell_segments.segments_of(command).some((segment) => fetches_issue_comments(segment))
280
+ }
281
+
282
+ // **The occasion the pre-gate cut governs, in the one shape that separates a cut run's two halves**
283
+ // (joshuafolkken/kit#1867). Asking about the cut is what a lane child does whatever it goes on to do;
284
+ // claiming the working tree is what only the process on the near side of the boundary does, because
285
+ // the `resume` verdict tells its counterpart to skip that claim. A run doing both reached the
286
+ // boundary; a run that asked without claiming is the session the cut produced, which had no cut of
287
+ const DELIVERED_RULES: ReadonlyArray<DeliveredRule> = [
288
+ // **Listed first, ahead of the filing trigger it overlaps** (joshuafolkken/kit#2122). A `gh api`
289
+ // that files an Issue into a repository we do not own trips both this row and `wip-cap` /
290
+ // `issue-scout` / `filing-cap` — but the backlog count, the scout and the per-run cap are all about
291
+ // filing into *our own* backlog, so on a third-party target the right answer is to stop the write
292
+ // entirely rather than to count anything. Placing it first means a third-party write is refused
293
+ // before any of those speak; on a first-party filing it is silent (the owners match), so `wip-cap`
294
+ // still speaks first, exactly as before. It fires on every occurrence (`git-force.ts`).
295
+ third_party_write.ROW,
296
+ {
297
+ id: 'wip-cap',
298
+ is_trigger: on_bash_command(is_issue_filing),
299
+ reason: WIP_CAP_REASON,
300
+ keeps: on_bash_command(counts_open_issues),
301
+ },
302
+ // **Three rows share the filing trigger** (joshuafolkken/kit#2119), listed after `wip-cap` so the
303
+ // backlog count still speaks first: `issue-scout` refuses a filing the run has not scouted (once per
304
+ // run, stood down once the scout is on the tail), and `filing-cap` refuses every filing past the
305
+ // per-run ceiling. Each is a real instance of the admissible overlap the comment on `delivery`
306
+ // describes — the losing rule's delivery is still correct one reissue later — so a scout-less,
307
+ // over-cap filing is delivered `wip-cap`, then `issue-scout`, then `filing-cap` across its reissues.
308
+ issue_scout.ROW,
309
+ filing_cap.ROW,
310
+ // **`issue-fold` shares the same filing trigger** (joshuafolkken/kit#2213), listed after
311
+ // `filing-cap`: it refuses a *second* filing the run has not folded, once per run, stood down off
312
+ // the tail when the run has already folded or has filed nothing earlier. It is another instance of
313
+ // the admissible overlap — the losing rule's delivery is still correct one reissue later — so a
314
+ // scout-less, unfolded, over-cap second filing is delivered `wip-cap`, then `issue-scout`, then
315
+ // `filing-cap`, then `issue-fold` across its reissues.
316
+ issue_fold.ROW,
317
+ {
318
+ id: 'issue-comments',
319
+ is_trigger: on_bash_command(is_body_only_issue_read),
320
+ reason: ISSUE_COMMENTS_REASON,
321
+ already_satisfied: prior_comment_read.already_read_for_call,
322
+ keeps: on_bash_command(reads_issue_comments),
323
+ },
324
+ {
325
+ id: 'shell-body',
326
+ is_trigger: on_bash_command(is_shell_evaluated_body),
327
+ reason: SHELL_BODY_REASON,
328
+ keeps: on_bash_command(keeps_body_safe),
329
+ reaches: on_bash_command(carries_a_body),
330
+ },
331
+ // **The sibling of `shell-body`, one call further along** (joshuafolkken/kit#2304). `shell-body`
332
+ // refuses a body passed inline so the shell evaluates it; this refuses a body passed by path with
333
+ // the raw field flag (`-f` / `--raw-field body=@<path>`), which posts the literal `@<path>`. It
334
+ // claims no command any row above does — `shell-body` triggers on a backtick or `$`, which the
335
+ // `@<path>` misfire carries neither, and `is_issue_filing` leaves the comment endpoint alone — so
336
+ // the exactly-one-rule invariant over its fixtures holds. It fires on every occurrence (`git-force.ts`).
337
+ raw_field_body.ROW,
338
+ {
339
+ id: 'piped-verification',
340
+ is_trigger: on_bash_command(piped_verification.is_masked_verification),
341
+ reason: piped_verification.PIPED_VERIFICATION_REASON,
342
+ keeps: on_bash_command(piped_verification.keeps_verdict_intact),
343
+ reaches: on_bash_command(piped_verification.runs_verification),
344
+ },
345
+ {
346
+ id: 'early-heartbeat',
347
+ is_trigger: on_bash_command(early_heartbeat.is_wait_timer),
348
+ reason: early_heartbeat.EARLY_HEARTBEAT_REASON,
349
+ decide: early_heartbeat.decide,
350
+ keeps: on_bash_command(early_heartbeat.is_progress_watch),
351
+ reaches: on_bash_command(early_heartbeat.waits_for_progress),
352
+ },
353
+ // **Listed before `run-tail`, the one row it deliberately overlaps** (joshuafolkken/kit#2118). A
354
+ // foreground `pnpm josh git -y` with no test beside the change is claimed by both: `test-declared`
355
+ // decides whether the commit should happen at all, so it is listed first, exactly as `wip-cap`
356
+ // precedes `shell-body` for deciding whether an Issue should exist. Nothing is lost by `run-tail`
357
+ // losing the race — the stamps are keyed per `id`, so the reissued push is delivered `run-tail`,
358
+ // which is asserted rather than assumed. The overlap only arises in a real checkout where the
359
+ // verdict is `required`; in the hermetic non-repo suite the git read fails to `exempt`, so
360
+ // `test-declared` claims nothing and the "exactly one rule" invariant over `run-tail`'s fixture holds.
361
+ test_declared_commit.ROW,
362
+ // **The one row whose trigger reads a field of the input beside the command**, so it supplies its
363
+ // own tool-name check rather than going through `on_bash_command`: a push step already issued with
364
+ // `run_in_background` is the rule obeyed, and refusing it would charge a run for doing the right
365
+ // thing. It supplies `decide` because a push is a recurring act — one per child in a batch, and a
366
+ // second inside one `fullrun` when round 2 fixes a finding in place.
367
+ {
368
+ id: 'run-tail',
369
+ is_trigger: run_tail.is_foreground_push_step,
370
+ reason: run_tail.RUN_TAIL_REASON,
371
+ decide: run_tail.decide,
372
+ keeps: run_tail.is_backgrounded_push_step,
373
+ reaches: run_tail.is_push_step_call,
374
+ },
375
+ // **The one row whose trigger consults the world beside the command**, because "is this a lane that
376
+ // has not cut" is not readable from the call: it is the working directory's own name and the cut
377
+ // record on disk. Both reads are synchronous, and the command match runs first, so a run that never
378
+ // types `pnpm josh gate` pays nothing for it.
379
+ //
380
+ // **Once per run rather than `decide`, and the direction of the error is why.** Taking the cut ends
381
+ // the process, so this is not the recurring act joshuafolkken/kit#1570 wrote `decide` for — and the
382
+ // five verdicts that legitimately leave a run at the gate (`not-a-lane`, `unready`, `busy`,
383
+ // `failed`, `unknown`) all need the reissue to go through. A row that refused every time would wedge exactly
384
+ // those runs; a row that refuses once cannot.
385
+ //
386
+ // **`pnpm josh rule:value` read this row with a ceiling of about 50%, and joshuafolkken/kit#1867 is
387
+ // what removed it** (the ceiling was recorded here by joshuafolkken/kit#1864's review round 2). A
388
+ // cut relaunches a *new session*, which the measurement groups as a run of its own, and that
389
+ // resumed run issues the entry check — so scored on the asking alone it joined the denominator
390
+ // while never being able to satisfy `keeps`, which only the cutting run can, and ten perfectly
391
+ // obedient children read as ten kept out of twenty. **The two halves are separable, just not from
392
+ // one call**: both processes issue byte-identical `--resume` strings, but the `fresh` verdict sends
393
+ // a run on to claim the working-tree hold while the `resume` verdict tells its counterpart to skip
394
+ // that claim. `reaches_the_pre_gate_boundary` is that conjunction, and it is why `CallTest` is
395
+ // handed the run's calls beside the turn's rather than a second predicate slot of its own.
396
+ // Dropping `reaches` altogether is still strictly worse — the trigger evaluates against the
397
+ // *measuring* process's working directory, so it is always false from the main checkout and the row
398
+ // would read as no runs at all.
399
+ //
400
+ // **It overlaps `piped-verification` on a piped gate call, and the order is safe in both
401
+ // directions.** `pnpm josh gate | tail` in an uncut lane is a real instance of both defects; the
402
+ // earlier row speaks, its own reason says to reissue, and this one delivers on the reissue — the
403
+ // reading "the losing rule's delivery is still correct one call later" that the comment below
404
+ // requires of any admissible overlap.
405
+ {
406
+ id: 'pre-gate-cut',
407
+ is_trigger: on_bash_command(pre_gate_cut.is_uncut_gate),
408
+ reason: pre_gate_cut.PRE_GATE_CUT_REASON,
409
+ keeps: on_bash_command(pre_gate_cut.takes_the_cut),
410
+ reaches: pre_gate_cut.reaches_the_pre_gate_boundary,
411
+ },
412
+ // **The second row whose trigger consults the world beside the command** (joshuafolkken/kit#2034):
413
+ // "is this a dispatched lane child" is the dispatch mark against this checkout's own issue, read
414
+ // synchronously by `lane_child_marker.is_child_of`, and the command match runs first so an ordinary
415
+ // run pays nothing for it.
416
+ //
417
+ // **Once per run rather than `decide`, and no `already_satisfied`.** The stop ends the turn, so it
418
+ // is not the recurring act joshuafolkken/kit#1570 wrote `decide` for. It carries no
419
+ // `already_satisfied` because the park it asks for is a GitHub label a synchronous guard cannot
420
+ // read, and the transcript-tail alternative would read a child that merely *read*
421
+ // `backlogrun-park.md` — whose prose carries the `labels[]=needs-decision` command — as compliant
422
+ // and fall silent on a real violation. `lane-park.ts` states why one wasted reissue on the compliant
423
+ // path is the safe direction. `keeps` reads an actual label-application `Bash` command, never the
424
+ // tail, so it is not fooled the same way; `reaches` stays `is_trigger`, since a compliant run issues
425
+ // the same confirmation notify and belongs in the denominator.
426
+ {
427
+ id: 'lane-park',
428
+ is_trigger: on_bash_command(lane_park.is_unparked_stop),
429
+ reason: lane_park.LANE_PARK_REASON,
430
+ keeps: on_bash_command(lane_park.records_the_park),
431
+ },
432
+ // **joshuafolkken/kit#2034's rule, one tool-call earlier** (joshuafolkken/kit#2201). `lane-park`
433
+ // fires on the `confirmation` notify a routed child reaches; a child that reaches for
434
+ // `AskUserQuestion` never gets there, because the harness ends its turn at the refused ask. This
435
+ // row's trigger is that ask, so the refusal becomes an instruction — park the question — instead of
436
+ // the child's death. Its trigger reads the input's tool name and consults the dispatch mark, like
437
+ // `lane-park`, and shares no command with any Bash row, so it claims no `gh` / `git` / `josh` call.
438
+ // It fires on every occurrence (`decide` returns true), the disposition `git-force.ts` takes: an
439
+ // interactive ask must never succeed in a child, and the route is always the park, never a reissue.
440
+ lane_interactive_ask.ROW,
441
+ // **The parent budget commands a lane child must never run** (joshuafolkken/kit#2267). A dispatched
442
+ // child that ran `pnpm josh run:merge` read its `busy` as a competing session and parked its Issue
443
+ // unimplemented — but the live carry record is the parent that launched it, never a competitor. This
444
+ // row refuses `run:merge` / `run:carry` in a lane child and hands back the mechanical branch: the
445
+ // record is the parent's, so continue implementing rather than park or ask. Its trigger claims a
446
+ // `josh` subcommand no other row does (the filing rows are `gh`, `run-tail` is `git push`), so it
447
+ // overlaps nothing. It fires on every occurrence (`decide` returns true): a child must never run
448
+ // these, and the route is always "continue", never a reissue (`git-force.ts`).
449
+ lane_carry_conflict.ROW,
450
+ // **The `git switch main` a lane child can never succeed at** (joshuafolkken/kit#2313), the fifth of
451
+ // the "always fails" misfires joshuafolkken/kit#2297 catalogued. A lane is a linked work tree and the
452
+ // primary checkout holds the default branch, so a child's `git switch main` fails structurally
453
+ // (`already used by worktree`); this refuses it before it fails and hands back the next command —
454
+ // skip the step, `pnpm josh main:merge` brings the default in during the gate. Its trigger reads the
455
+ // dispatch mark and the lane branch like `lane-carry-conflict`, and claims a `git switch` no row
456
+ // above matches — `git-force` is `git push` / `git branch`, `worktree-mutation` is `git checkout --`
457
+ // / `restore` / `stash` — so no two rows claim one command. It fires on every occurrence (`decide`
458
+ // returns true): a child must never run this, and the route is always "continue" (`git-force.ts`).
459
+ lane_switch_main.ROW,
460
+ // **A `pnpm josh git` with no `-y` cannot succeed from an agent** (joshuafolkken/kit#2297). It
461
+ // prompts to confirm the staging, the no-TTY prompt cancels, and the run reissues with `-y` after
462
+ // throwing away the time it took to fail. This row refuses the bare call and hands back the `-y`
463
+ // form. It is disjoint from `run-tail` by the flag — that row requires `-y`, this refuses its
464
+ // absence — so no two rows claim one command. It fires on every occurrence (`decide` returns true):
465
+ // a bare call wastes the same time each time, so the route is always the `-y` reissue
466
+ // (`git-force.ts`).
467
+ josh_git_bare.ROW,
468
+ // **The three Bash-string gaps the deny glob cannot express** (joshuafolkken/kit#2120), each reading
469
+ // the command's argv rather than a literal a glob keys on. They share no trigger with any row above —
470
+ // force/delete is `git push` / `git branch`, the worktree change is `git checkout` / `restore` /
471
+ // `stash`, and the file body is a heredoc / `node -e` / `perl -i` — so no two rows claim one command,
472
+ // which `delivered-rules-bash.test.ts` pins. Each declares `decide` returning true: a destructive or
473
+ // billed act is refused on every occurrence, never once per run (`git-force.ts`).
474
+ git_force.ROW,
475
+ worktree_guard.ROW,
476
+ file_body.ROW,
477
+ // **The hand-written wait loop a lane child improvises over a backgrounded command's output**
478
+ // (joshuafolkken/kit#2371). `early-heartbeat` refuses a bare `sleep` and stands down on any loop
479
+ // keyword; this is the loop it left — a `while`/`until` that sleeps between probes of an output
480
+ // file. Its trigger claims a command no row above matches: the loop-plus-`sleep` shape carries no
481
+ // `gh` / `git` / `josh` subcommand any other trigger keys on, and a poll loop is never a bare
482
+ // `sleep` (the loop keyword makes `early-heartbeat.is_wait_timer` false), so the Bash
483
+ // `rules_claiming` invariant holds. It fires on every occurrence (`decide` returns true): a poll
484
+ // loop wastes the same round trips each time, so the route is always "background it and end the
485
+ // turn", never a reissue (`git-force.ts`).
486
+ poll_loop.ROW,
487
+ // **The second row whose trigger is an `Edit` / `Write` rather than a shell call**
488
+ // (joshuafolkken/kit#2310), and the third that consults the world beside the call: "is this a lane
489
+ // child whose recent-context cost has crossed the threshold" reads the dispatch mark, the cut record
490
+ // on disk and the synchronous `pnpm josh cost --cut` verdict — the same measurement the parent
491
+ // hand-off uses, never a second one (joshuafolkken/kit#1933). The `Edit` / `Write` name match runs
492
+ // first, then the lane read, then the transcript-priced verdict, so a run that is not a dispatched
493
+ // child in an uncut lane pays nothing for it. It self-gates on the tool name, so it claims no `Bash`
494
+ // command any row above matches — the Bash `rules_claiming` invariant is untouched.
495
+ //
496
+ // **Listed before `rule-body`, the one row it can overlap.** Both trigger on an `Edit` / `Write`; a
497
+ // rule-document edit made in a lane child that is already over threshold trips both. The cut is the
498
+ // right thing to do first — end the process and drop the accumulated context — and on the reissue in
499
+ // the fresh, under-threshold process this row is silent and `rule-body` delivers, the "losing rule's
500
+ // delivery still correct one reissue later" reading any admissible overlap needs.
501
+ //
502
+ // **It carries `decide`, and the inversion of the pre-gate cut's reasoning is why** (joshuafolkken/kit#2385).
503
+ // `pre-gate-cut` and `lane-park` are once per run because taking the cut, or the park, *ends the
504
+ // process* — the one act is not a recurring one, and the five verdicts that leave a run holding it
505
+ // all need the one reissue to go through. This cut ends the process too, but its *trigger* does not:
506
+ // crossing the threshold mid-implementation is a recurring state that once-per-run silenced for the
507
+ // rest of a process the moment its first refusal landed — so a `busy` / `failed` / `unready` verdict,
508
+ // or an edit the model reissued unchanged, left the context to grow unwatched (joshuafolkken/kit#2382
509
+ // ran to 282,747 tokens with the cut never taken). `decide` re-asks on every over-threshold edit, and
510
+ // its `delivered_at_ms` lets an edit reissued right after a refusal through, so `busy` / `failed`
511
+ // cannot wedge the run edit after edit — the reissue path once-per-run gave for free, now made
512
+ // explicit. The fresh process after a successful cut reads its own transcript under threshold, so it
513
+ // is silent without needing a carried record to quiet it.
514
+ //
515
+ // **No `reaches`, because the occasion is live-only.** `pre-gate-cut` gives a `reaches` because both
516
+ // its halves leave a command-string trace (`run:cut --resume` at entry); this row's occasion —
517
+ // crossing the threshold mid-implementation — is the working directory, the cut record and the cost
518
+ // verdict, none of which a transcript records. `pnpm josh rule:value` therefore reads it as no runs
519
+ // rather than as 0% kept (`keeps` stays, so the compliance act is named for a future measurement
520
+ // redesign), the same honest-unmeasured stance the batching and investigation rows take for the same
521
+ // reason: a trigger no transcript can reconstruct. The row itself lives in `implementation-cut.ts`.
522
+ implementation_cut.ROW,
523
+ // **The first row whose trigger is an `Edit` / `Write` rather than a shell call**
524
+ // (joshuafolkken/kit#2272). It delivers the residency questions at the edit that writes a rule into
525
+ // prose, and self-gates on the tool name and the file path, so it claims no `Bash` command any row
526
+ // above matches — the `rules_claiming` invariant over Bash fixtures is untouched. It carries no
527
+ // `decide`, so it is once per run and takes the batching stand-aside `is_first_delivery` gives every
528
+ // default row: the batching guard treats an `Edit` as a candidate, exactly as it treats an Issue
529
+ // read, so this row stands aside on a batched turn and delivers on the reissue.
530
+ rule_body_guard.ROW,
531
+ // **The generic oracle-consulted rows, one per oracle that declared a firing point**
532
+ // (joshuafolkken/kit#2324). Each refuses the action the oracle governs when the run has not run that
533
+ // oracle's command first, stood down once it has — `issue-scout`'s shape read from the registry
534
+ // rather than hand-written. Listed last so an oracle whose firing point overlaps a filing
535
+ // (`issue:lint`) delivers on the reissue, after `wip-cap` / `issue-scout` / `filing-cap` /
536
+ // `issue-fold` have each had their turn. The non-overlapping firing point (`pkg:scout` on a package
537
+ // add) claims a command no row above matches.
538
+ ...oracle_consulted.ROWS,
539
+ ]
540
+
541
+ // A turn that issued more than this many calls is a turn that batched. The guard counts turns that
542
+ // issued a *single* tool call, so the boundary is the same one `SEQUENCE_BEFORE_LIMIT` is counted in.
543
+ const ALONE_IN_TURN = 1
544
+
545
+ // **Keeping the batching rule is a refusable call that went out beside siblings** — the one
546
+ // compliance test of the seven that cannot be read off the call alone (joshuafolkken/kit#1792). The
547
+ // guard's whole subject is the run of turns that each issued one call, so the act it asks for is a
548
+ // turn carrying more than one, and `is_guarded_call` is what keeps the credit to calls the guard
549
+ // could actually have refused: a turn of two `Write`s is not the rule being kept, because neither
550
+ // call was ever at risk.
551
+ function batches_the_turn(call: GuardedCall, turn: ReadonlyArray<GuardedCall>): boolean {
552
+ return time_batch_guard.is_guarded_call(call) && turn.length > ALONE_IN_TURN
553
+ }
554
+
555
+ // **The row `pnpm josh rule:value` scores the batching guard from** (joshuafolkken/kit#1792). It is
556
+ // measured but not delivered, for the reason `MeasuredRule` states.
557
+ //
558
+ // **It declares no `is_trigger`, and that is the honest answer rather than a gap.** Whether a call
559
+ // would be refused depends on the turns *behind* it — `time_batch_guard.should_block` reads the
560
+ // transcript tail for exactly that — and `scripts/rules/rule-value.ts` hands a predicate one call at
561
+ // a time, so a call-shaped trigger here could only ever be a guess. What the transcript does record
562
+ // is the refusal itself, and the measurement takes that as the trigger: compliance credited after a
563
+ // refusal is the delivery's contribution, which is the same line every other row is scored on.
564
+ //
565
+ // **The `reaches` half is what keeps the reading off zero**, the failure joshuafolkken/kit#1643
566
+ // named. The batching guard fires only on the violation, so scored against its trigger the rate
567
+ // would be taken over runs that broke the rule at least once and would read near zero by
568
+ // construction — a manufactured retirement candidate for the most-cited resident rule there is. The
569
+ // occasion it governs is issuing a call the guard could refuse, in *either* spelling: alone in its
570
+ // turn, or beside the calls that did not need its result.
571
+ const BATCHING_RULE: MeasuredRule = {
572
+ id: 'batching',
573
+ reason: time_batch_guard.REASON,
574
+ keeps: batches_the_turn,
575
+ reaches: time_batch_guard.is_guarded_call,
576
+ }
577
+
578
+ // **The row `pnpm josh rule:value` scores the investigation guard from** (joshuafolkken/kit#1764).
579
+ // It is measured but not delivered, for exactly the reason the batching row is: `josh
580
+ // investigation:guard` has delivered it since joshuafolkken/kit#1460, and a row in `DELIVERED_RULES`
581
+ // would refuse the same violation a second time, each refusal spending a record the other cannot
582
+ // see. Until now it was the second delivered rule the measurement could not read at all — and the
583
+ // one whose subject, `investigation` at 35.9% of a run's turns, is the largest contributor any
584
+ // mechanism here addresses.
585
+ //
586
+ // **It declares no `is_trigger`, and that is honest rather than a gap.** Whether a read would be
587
+ // refused depends on the reads *behind* it — `investigation_reads.should_block` reads the transcript
588
+ // tail for exactly that — and the measurement hands a predicate one call at a time, so a call-shaped
589
+ // trigger could only be a guess. The refusal itself is what the transcript records, and
590
+ // `observe_error` takes that as the trigger.
591
+ //
592
+ // **`reaches` is the read the guard could have refused, not the refusal**, the distinction
593
+ // joshuafolkken/kit#1643 drew: scored against a trigger that fires only on the violation, the rate
594
+ // would be taken over runs that broke the rule at least once and would read near zero by
595
+ // construction.
596
+ //
597
+ // **It declares no `keeps` either, and the unmeasured cell is the honest answer rather than a gap.**
598
+ // The obvious predicate — a subagent dispatch — credits *any* dispatch, because that is what the
599
+ // guard's own reset does; a run that read twenty files in the main line, was never refused and sent
600
+ // one review agent at the end would score as full compliance. That row would sit near 100% for the
601
+ // rule this very Issue measures as let through on a third of all reads, and `pnpm josh rule:value` is
602
+ // what retirement decisions are read from. The module's own doctrine settles it: a rule with no
603
+ // `keeps` is reported unmeasured, because 0 and 1 are both claims the data does not make. **The
604
+ // compliance reading exists elsewhere and is better**: `pnpm josh time`'s `Investigation reads:`
605
+ // block, built from this same guard's predicates, says per run how much reading was refused, let
606
+ // through, or main-line by design. What this row adds is the reach and the delivery count, which is
607
+ // the continuous reading the guard had none of.
608
+ const INVESTIGATION_RULE: MeasuredRule = {
609
+ id: 'investigation',
610
+ reason: investigation_reads.REASON,
611
+ reaches: investigation_reads.is_refusable_call,
612
+ }
613
+
614
+ // Every rule the measurement can score, delivery registry first so a printed table reads in
615
+ // enumeration order with the rows delivered from here at the top.
616
+ const MEASURED_RULES: ReadonlyArray<MeasuredRule> = [
617
+ ...DELIVERED_RULES,
618
+ BATCHING_RULE,
619
+ INVESTIGATION_RULE,
620
+ ]
621
+
622
+ // **Once per run, never once per call.** A rule delivered again on the next call would wedge a run
623
+ // that had already obeyed it, which is the failure `hook_decision`'s stamp exists to prevent; the
624
+ // reason text says so, so a reader knows reissuing is the expected next move.
625
+ //
626
+ // **The tail read is what keeps two `Bash` guards off the same call.** `pnpm josh batch:guard` is
627
+ // wired to `Bash` as well, and the shared shell records the stamp *before* returning a reason. Claude
628
+ // Code surfaces one permission decision per call, so a call both hooks refused would lose one of the
629
+ // two reasons while both records were already written — and a rule whose record is set can never fire
630
+ // again in that run. That is a silent deletion, of exactly the kind this enumeration exists to
631
+ // prevent. So a call the batching guard may refuse is **stepped aside from rather than delivered
632
+ // on**: nothing is recorded (the shared shell stamps only after `should_block` answers true), the
633
+ // batching guard's own reason says to reissue the call, and this rule delivers on the reissue.
634
+ //
635
+ // **Inert for `wip-cap` and live for `issue-comments`, which is why it was written before either
636
+ // needed it.** The batching guard does not treat a filing call as a candidate at all, so the branch
637
+ // never fires for `wip-cap`; it *does* treat `gh issue view` as one, so the second row genuinely
638
+ // stands aside on a turn the batching guard is about to refuse and delivers on the reissue.
639
+ // `delivered-rules.test.ts` pins both halves, and it is what any new row has to be re-checked
640
+ // against. Erring toward standing aside costs at most one call's delay, while erring the other way
641
+ // costs the rule for the whole run.
642
+ // The batching guard's own record for this run, read through the same shell that writes it.
643
+ const BATCH_STAMP = hook_decision.create_refusal_stamp(time_batch_guard.STAMP_PREFIX)
644
+
645
+ // **A record this young is the batching guard speaking about the call in hand.** The two hooks are
646
+ // separate processes started for the same `PreToolUse` event with no ordering between them, and the
647
+ // shared shell writes its stamp *before* it returns a reason — so presence alone cannot answer "has
648
+ // it refused?" without making the stand-aside depend on which process won the race. A record older
649
+ // than this window is a refusal about an earlier call, which that guard will not repeat on the same
650
+ // open sequence, and this rule is free to speak.
651
+ const BATCH_REFUSAL_WINDOW_MS = 10_000
652
+
653
+ // **The question is what the batching guard will do on this call, not what it would do from a clean
654
+ // slate.** Asked with `NEVER_MS` in place of its record, the answer stayed `true` for the whole of an
655
+ // open sequence it had *already* refused — and since that guard will not refuse the same sequence
656
+ // twice, a run that kept single-calling after being refused had neither hook speak, and this rule was
657
+ // lost for the run with nothing recorded to say so. That is the silent deletion the stand-aside
658
+ // exists to prevent, arrived at from the other side.
659
+ function will_batch_guard_refuse(tail: string, call: GuardedCall, run: GuardRun): boolean {
660
+ // In a dispatched lane child the batching guard no longer refuses (joshuafolkken/kit#2138,
661
+ // joshuafolkken/kit#2164, joshuafolkken/kit#2178, joshuafolkken/kit#2276): its mode is `notice`, so it
662
+ // speaks but never denies. It will *refuse* nothing there, and the stand-aside must agree — or a lone
663
+ // rule trigger (`shell-body`) would be stepped aside from for a batching refusal that can no longer
664
+ // come and lost for the run. The test is therefore "will it refuse", i.e. mode `refuse`, not "is it
665
+ // notice or off".
666
+ if (lane_guard_policy.mode_here('batching') !== 'refuse') return false
667
+
668
+ const refused_at_ms = BATCH_STAMP.last_ms(BATCH_STAMP.path(run.transcript))
669
+
670
+ if (run.now_ms - refused_at_ms < BATCH_REFUSAL_WINDOW_MS) return true
671
+
672
+ return time_batch_guard.should_block(tail, call, refused_at_ms)
673
+ }
674
+
675
+ function is_first_delivery(
676
+ tail: string,
677
+ call: GuardedCall,
678
+ delivered_at_ms: number,
679
+ run: GuardRun,
680
+ ): boolean {
681
+ return delivered_at_ms === hook_decision.NEVER_MS && !will_batch_guard_refuse(tail, call, run)
682
+ }
683
+
684
+ // **For a row that decides for itself, the stand-aside changes what it protects.** For a once-per-run
685
+ // row it protects the *record*, because a lost race spends the one delivery the run gets. A recurring
686
+ // row cannot be silently deleted that way — it fires again — and standing aside from the refusal would
687
+ // instead make it silent on precisely the lone `Bash` call the batching guard also claims, which is
688
+ // what an armed timer always is, for the whole ten-second window and the reissue inside it. So the
689
+ // refusal is asked unconditionally and the stand-aside is handed to the row as `can_record`: what must
690
+ // not happen on a call another hook may stop is the *write*, which would record a timer that never ran.
691
+ // **It is a trade, and the other side is named rather than hidden**: an arm allowed inside that window
692
+ // that really does run is not recorded either, so a second one before it fires goes uncaught. A missing
693
+ // record loses one detection; a wrong one blocks every arm until it expires.
694
+ // **Both extras hang off `is_first_delivery`, and a row declares at most one.** `decide` is for a
695
+ // recurring rule (joshuafolkken/kit#1570); `already_satisfied` is for a once-per-run rule the run can
696
+ // satisfy earlier (joshuafolkken/kit#1905), where the earlier act stands the delivery down before the
697
+ // once-per-run record is spent. A row with neither takes `is_first_delivery` unchanged.
698
+ function delivery_decision(rule: DeliveredRule): TranscriptGuardSpec['should_block'] {
699
+ const { decide, already_satisfied } = rule
700
+
701
+ if (decide === undefined && already_satisfied === undefined) return is_first_delivery
702
+
703
+ return function should_block(
704
+ tail: string,
705
+ call: GuardedCall,
706
+ delivered_at_ms: number,
707
+ run: GuardRun,
708
+ ): boolean {
709
+ if (already_satisfied?.(tail, call) === true) return false
710
+ if (decide === undefined) return is_first_delivery(tail, call, delivered_at_ms, run)
711
+
712
+ return decide(call, run, !will_batch_guard_refuse(tail, call, run), delivered_at_ms)
713
+ }
714
+ }
715
+
716
+ function guard_of(rule: DeliveredRule): ReturnType<typeof hook_decision.create_transcript_guard> {
717
+ return hook_decision.create_transcript_guard({
718
+ prefix: `${STAMP_PREFIX}${rule.id}-`,
719
+ switch_key: SWITCH_ENV_KEY,
720
+ is_candidate: rule.is_trigger,
721
+ should_block: delivery_decision(rule),
722
+ reason: rule.reason,
723
+ })
724
+ }
725
+
726
+ const GUARDS = new Map(DELIVERED_RULES.map((rule) => [rule.id, guard_of(rule)]))
727
+
728
+ // Where one rule's once-per-run record lives, so a caller can clear it. Exposed for the suite: the
729
+ // records land in the shared temp directory rather than under any directory a test owns, and a record
730
+ // left behind would silence the next case exactly as it silences the next call.
731
+ function delivery_path(rule_id: string, transcript_path: string): string {
732
+ return GUARDS.get(rule_id)?.refusal_path(transcript_path) ?? ''
733
+ }
734
+
735
+ // **The first entry whose delivery actually fires wins — not the first whose trigger matches.** Only
736
+ // one refusal can leave a `PreToolUse` hook, so a rule that matched but has already been delivered
737
+ // this run falls through and a later rule may speak on the same call. **A rule added here whose
738
+ // trigger another row also matches is admissible only when the overlap is safe** — the losing rule's
739
+ // delivery still correct one reissue later — and the enumeration's own suite asserts, per fixture,
740
+ // that every command is claimed by exactly the rows meant to overlap on it.
741
+ //
742
+ // **The filing trigger is shared by three rows, and the order is what makes the overlap safe**
743
+ // (joshuafolkken/kit#2119). `wip-cap`, `issue-scout` and `filing-cap` all match a filing; a
744
+ // scout-less, over-cap filing is delivered `wip-cap`, then `issue-scout`, then `filing-cap` across its
745
+ // reissues, each still the right thing to say when it is reached. `wip-cap` is listed first because it
746
+ // decides whether the backlog has room at all — the same reason it precedes `shell-body`, which claims
747
+ // a filing whose body carries a backtick (joshuafolkken/kit#1198). Nothing is lost by losing a race:
748
+ // the stamps are keyed per `id`, so the reissued call is delivered the next rule.
749
+ function delivery(raw_payload: string, now_ms: number = Date.now()): string | undefined {
750
+ for (const guard of GUARDS.values()) {
751
+ const reason = guard.refusal(raw_payload, now_ms)
752
+
753
+ if (reason !== undefined) return reason
754
+ }
755
+
756
+ return undefined
757
+ }
758
+
759
+ function is_enabled(): boolean {
760
+ return hook_decision.is_switch_enabled(SWITCH_ENV_KEY)
761
+ }
762
+
763
+ const delivered_rules = {
764
+ DELIVERED_RULES,
765
+ EARLY_HEARTBEAT_REASON: early_heartbeat.EARLY_HEARTBEAT_REASON,
766
+ FILE_BODY_REASON: file_body.FILE_BODY_REASON,
767
+ FILING_CAP_REASON: filing_cap.FILING_CAP_REASON,
768
+ GIT_FORCE_REASON: git_force.GIT_FORCE_REASON,
769
+ ISSUE_COMMENTS_REASON,
770
+ ISSUE_FOLD_REASON: issue_fold.ISSUE_FOLD_REASON,
771
+ ISSUE_SCOUT_REASON: issue_scout.ISSUE_SCOUT_REASON,
772
+ LANE_INTERACTIVE_ASK_REASON: lane_interactive_ask.LANE_INTERACTIVE_ASK_REASON,
773
+ LANE_PARK_REASON: lane_park.LANE_PARK_REASON,
774
+ MEASURED_RULES,
775
+ PIPED_VERIFICATION_REASON: piped_verification.PIPED_VERIFICATION_REASON,
776
+ POLL_LOOP_REASON: poll_loop.POLL_LOOP_REASON,
777
+ PRE_GATE_CUT_REASON: pre_gate_cut.PRE_GATE_CUT_REASON,
778
+ RAW_FIELD_BODY_REASON: raw_field_body.RAW_FIELD_BODY_REASON,
779
+ RUN_TAIL_REASON: run_tail.RUN_TAIL_REASON,
780
+ SHELL_BODY_REASON,
781
+ SWITCH_ENV_KEY,
782
+ THIRD_PARTY_WRITE_REASON: third_party_write.THIRD_PARTY_WRITE_REASON,
783
+ WIP_CAP_REASON,
784
+ WORKTREE_MUTATION_REASON: worktree_guard.WORKTREE_MUTATION_REASON,
785
+ delivery,
786
+ delivery_path,
787
+ is_body_only_issue_read,
788
+ is_enabled,
789
+ is_issue_filing,
790
+ }
791
+
792
+ export type { DeliveredRule, MeasuredRule }
793
+ export { delivered_rules }