@joshuafolkken/kit 1.1514.0 → 1.1784.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 (858) hide show
  1. package/.claude/agents/investigator.md +1 -1
  2. package/.claude/settings.json +5 -5
  3. package/.claude/skills/epic-commands/SKILL.md +26 -65
  4. package/.claude/skills/epic-commands/epic-bundle.md +3 -1
  5. package/.claude/skills/workflow-commands/SKILL.md +5 -5
  6. package/.claude/skills/workflow-commands/background-commands.md +5 -5
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +10 -8
  8. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
  9. package/.claude/skills/workflow-commands/backlogrun-lanes.md +17 -13
  10. package/.claude/skills/workflow-commands/backlogrun-park.md +14 -23
  11. package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -2
  12. package/.claude/skills/workflow-commands/backlogrun-recovery.md +5 -5
  13. package/.claude/skills/workflow-commands/backlogrun-steps.md +10 -10
  14. package/.claude/skills/workflow-commands/backlogrun.md +1 -1
  15. package/.claude/skills/workflow-commands/chain-rule.md +13 -7
  16. package/.claude/skills/workflow-commands/delegation.md +6 -5
  17. package/.claude/skills/workflow-commands/entry-sequence.md +9 -9
  18. package/.claude/skills/workflow-commands/followup.md +9 -31
  19. package/.claude/skills/workflow-commands/fullrun-steps.md +36 -45
  20. package/.claude/skills/workflow-commands/fullrun.md +2 -2
  21. package/.claude/skills/workflow-commands/halfrun.md +17 -25
  22. package/.claude/skills/workflow-commands/issue-comments.md +16 -12
  23. package/.claude/skills/workflow-commands/issue-scout.md +2 -2
  24. package/.claude/skills/workflow-commands/kickoff.md +24 -23
  25. package/.claude/skills/workflow-commands/latest-gate.md +7 -12
  26. package/.claude/skills/workflow-commands/needs-human-review.md +9 -14
  27. package/.claude/skills/workflow-commands/observation-filing.md +4 -36
  28. package/.claude/skills/workflow-commands/observation-ledger.md +1 -1
  29. package/.claude/skills/workflow-commands/pre-gate-cut.md +13 -30
  30. package/.claude/skills/workflow-commands/prerequisite.md +10 -16
  31. package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
  32. package/.claude/skills/workflow-commands/prrun.md +3 -7
  33. package/.claude/skills/workflow-commands/retrospective.md +1 -1
  34. package/.claude/skills/workflow-commands/split-assessment.md +13 -1
  35. package/.claude/skills/workflow-commands/working-tree-hold.md +9 -9
  36. package/.codex/hooks.json +5 -5
  37. package/.github/actions/setup-node/action.yml +9 -0
  38. package/.github/actions/setup-pnpm/action.yml +1 -1
  39. package/.github/dependabot.yml +16 -0
  40. package/.github/release.yml +0 -2
  41. package/.github/workflows/ci.yml +120 -10
  42. package/.github/workflows/publish.yml +8 -1
  43. package/.github/workflows/sonar-qube.yml +1 -0
  44. package/.prettierignore +2 -0
  45. package/.vscode/tasks.json +1 -2
  46. package/CLAUDE.md +3 -7
  47. package/README.md +4 -2
  48. package/SECURITY.md +1 -1
  49. package/dist/CLAUDE.md +3 -7
  50. package/dist/commands/document-read-cli.js +882 -0
  51. package/dist/commands/{document-section-cli.js → document-section-main.js} +79 -37
  52. package/dist/commands/read-set-cli.js +1867 -0
  53. package/dist/commands/run-prep-main.js +21653 -0
  54. package/dist/commands/run-step-cli.js +23880 -0
  55. package/dist/config-merge/index.js +5 -1
  56. package/dist/hooks/audit-provision.js +20 -35
  57. package/dist/hooks/{chunk-DGT54IH5.js → chunk-AZX4FGQ3.js} +63 -17
  58. package/dist/hooks/chunk-CWMBGKYW.js +6483 -0
  59. package/dist/hooks/chunk-O2YBIDSI.js +4306 -0
  60. package/dist/hooks/{chunk-TNUMY6NL.js → chunk-PT5R6UJD.js} +4193 -1900
  61. package/dist/hooks/chunk-TUIFS5E7.js +72 -0
  62. package/dist/hooks/{chunk-723HKZO5.js → chunk-VWWCFGWK.js} +1 -1
  63. package/dist/hooks/{chunk-APUO6U4J.js → chunk-WR2KQAYZ.js} +1843 -440
  64. package/dist/hooks/{chunk-O6GDRNJB.js → chunk-XGBNSWEI.js} +248 -46
  65. package/dist/hooks/chunk-YCDOIR3I.js +3456 -0
  66. package/dist/hooks/codex-hook-adapter.js +10 -22
  67. package/dist/hooks/format-edited.js +5 -6
  68. package/dist/hooks/inputs.json +443 -317
  69. package/dist/hooks/pretool-guard.js +7 -25
  70. package/dist/hooks/session-lang.js +44 -51
  71. package/dist/hooks/stop-guard.js +7716 -2187
  72. package/dist/josh.js +6002 -3583
  73. package/dist/self-sync-guard/index.js +74 -10
  74. package/dist/version/index.js +115 -406
  75. package/eslint/base.js +1 -1
  76. package/lefthook/base.yml +3 -1
  77. package/package.json +10 -48
  78. package/pnpm-workspace.yaml +4 -2
  79. package/prompts/coding-standards.md +1 -1
  80. package/prompts/collaboration-workflow/file-edits.md +1 -7
  81. package/prompts/collaboration-workflow/issue-citation.md +1 -1
  82. package/prompts/collaboration-workflow/issue-template.md +33 -16
  83. package/prompts/collaboration-workflow/lane-instructions.md +1 -2
  84. package/prompts/collaboration-workflow/measurement.md +37 -0
  85. package/prompts/collaboration-workflow/operating-rules.md +4 -6
  86. package/prompts/collaboration-workflow/output-bounds.md +2 -7
  87. package/prompts/collaboration-workflow/plan-comment.md +3 -42
  88. package/prompts/collaboration-workflow/principles.md +5 -0
  89. package/prompts/collaboration-workflow/report-format.md +31 -60
  90. package/prompts/collaboration-workflow/residency.md +2 -2
  91. package/prompts/collaboration-workflow/shell-body.md +6 -16
  92. package/prompts/collaboration-workflow/turn-batching.md +0 -2
  93. package/prompts/collaboration-workflow/upstream-interrupt.md +14 -4
  94. package/prompts/collaboration-workflow/wip-cap.md +1 -1
  95. package/prompts/collaboration-workflow.md +3 -7
  96. package/prompts/refactoring.md +1 -1
  97. package/prompts/review-rubric.md +1 -2
  98. package/prompts/review.md +41 -21
  99. package/prompts/testing-guide.md +8 -43
  100. package/scripts/agent/agent-event.ts +15 -15
  101. package/scripts/agent/agent-exit-record.ts +13 -1
  102. package/scripts/agent/api-auth.ts +41 -0
  103. package/scripts/agent/api-outage.ts +1 -1
  104. package/scripts/auto-ok/auto-ok-cli.ts +14 -16
  105. package/scripts/auto-ok/auto-ok-judge-read.ts +12 -3
  106. package/scripts/auto-ok/auto-ok-judge-write.ts +46 -19
  107. package/scripts/auto-ok/auto-ok-judge.ts +13 -2
  108. package/scripts/auto-ok/auto-ok-main.ts +17 -0
  109. package/scripts/backlog/backlog-arrival.ts +14 -3
  110. package/scripts/backlog/backlog-budget-cli.ts +7 -33
  111. package/scripts/backlog/backlog-budget-main.ts +16 -0
  112. package/scripts/backlog/backlog-budget.ts +2 -3
  113. package/scripts/backlog/backlog-defect-priority.ts +4 -3
  114. package/scripts/backlog/backlog-drive-adopt.ts +67 -0
  115. package/scripts/backlog/backlog-drive-args.ts +4 -5
  116. package/scripts/backlog/backlog-drive-cli.ts +113 -28
  117. package/scripts/backlog/backlog-drive-hold.ts +162 -0
  118. package/scripts/backlog/backlog-drive-idle.ts +151 -0
  119. package/scripts/backlog/backlog-drive-judge.ts +25 -0
  120. package/scripts/backlog/backlog-drive-memory.ts +126 -0
  121. package/scripts/backlog/backlog-drive-named-offer.ts +5 -10
  122. package/scripts/backlog/backlog-drive-named.ts +53 -6
  123. package/scripts/backlog/backlog-drive-offer-argv.ts +3 -8
  124. package/scripts/backlog/backlog-drive-paused.ts +169 -0
  125. package/scripts/backlog/backlog-drive-restore.ts +30 -7
  126. package/scripts/backlog/backlog-drive-seats.ts +18 -8
  127. package/scripts/backlog/backlog-drive-token-handling.ts +38 -0
  128. package/scripts/backlog/backlog-drive.ts +79 -75
  129. package/scripts/backlog/backlog-next-main.ts +16 -0
  130. package/scripts/backlog/backlog-next-shared.ts +73 -0
  131. package/scripts/backlog/backlog-next.ts +48 -16
  132. package/scripts/backlog/backlog-occupied.ts +52 -39
  133. package/scripts/backlog/backlog-offer-cli.ts +6 -21
  134. package/scripts/backlog/backlog-offer-exclude.ts +15 -0
  135. package/scripts/backlog/backlog-offer-main.ts +12 -0
  136. package/scripts/backlog/backlog-offer.ts +36 -3
  137. package/scripts/backlog/backlog-overlap.ts +22 -4
  138. package/scripts/backlog/backlog-plan-read.ts +6 -2
  139. package/scripts/backlog/backlog-plan.ts +18 -4
  140. package/scripts/backlog/backlog-pool.ts +10 -10
  141. package/scripts/backlog/backlog-rank.ts +10 -2
  142. package/scripts/backlog/backlog-ready.ts +112 -30
  143. package/scripts/backlog/backlog-stalled-detect.ts +109 -36
  144. package/scripts/backlog/backlog-stalled.ts +52 -16
  145. package/scripts/backlog/backlog-wait-cause.ts +86 -0
  146. package/scripts/backlog/backlog-waves.ts +39 -13
  147. package/scripts/backlog/backlogrun-args.ts +19 -7
  148. package/scripts/backlog/backlogrun-cli.ts +19 -5
  149. package/scripts/backlog/backlogrun-launch.ts +6 -0
  150. package/scripts/backlog/backlogrun-restart.ts +97 -0
  151. package/scripts/backlog/backlogrun-stop.ts +79 -7
  152. package/scripts/behavior/behavior-cli.ts +2 -2
  153. package/scripts/behavior/behavior-rules.ts +47 -24
  154. package/scripts/build/build-bin.ts +2 -16
  155. package/scripts/build/build-claude-md.ts +0 -7
  156. package/scripts/build/build-commands.ts +0 -13
  157. package/scripts/build/build-hooks.ts +49 -48
  158. package/scripts/build/hook-bundle-stamp.ts +29 -11
  159. package/scripts/build/local-bin.ts +1 -1
  160. package/scripts/cases/cases-cli.ts +25 -13
  161. package/scripts/cases/cases-interaction-scan.ts +134 -0
  162. package/scripts/cases/cases-interaction.ts +183 -0
  163. package/scripts/cases/cases-logic.ts +39 -6
  164. package/scripts/ci/pr-classification-main.ts +18 -0
  165. package/scripts/ci/pr-classification.ts +10 -17
  166. package/scripts/clone/clone-scan.ts +1 -1
  167. package/scripts/cost-runtime/cost-blocks.ts +22 -37
  168. package/scripts/cost-runtime/cost-cli.ts +31 -14
  169. package/scripts/cost-runtime/cost-main.ts +12 -0
  170. package/scripts/cost-runtime/cost-transcript.ts +1 -0
  171. package/scripts/delegation/delegation-policy.ts +17 -4
  172. package/scripts/delegation/duplicate-read-guard.ts +0 -8
  173. package/scripts/delegation/investigation-guard.ts +0 -8
  174. package/scripts/delegation/investigation-reads.ts +3 -4
  175. package/scripts/dependabot/dependabot-cooldown.ts +194 -0
  176. package/scripts/discovery/repo-discovery.ts +24 -6
  177. package/scripts/doctor/doctor-consumer.ts +2 -5
  178. package/scripts/document/document-byte-budget.ts +8 -6
  179. package/scripts/document/document-scan.ts +1 -1
  180. package/scripts/document/document-section-cli.ts +0 -8
  181. package/scripts/document/document-section-main.ts +12 -0
  182. package/scripts/epic/epic-audit-cli.ts +12 -6
  183. package/scripts/epic/epic-bundle-apply.ts +137 -0
  184. package/scripts/epic/epic-bundle-cli.ts +32 -121
  185. package/scripts/epic/epic-bundle-format.ts +116 -0
  186. package/scripts/epic/epic-bundle-main.ts +17 -0
  187. package/scripts/epic/epic-busy.ts +5 -12
  188. package/scripts/epic/epic-classify.ts +24 -15
  189. package/scripts/epic/epic-cli-argv.ts +31 -0
  190. package/scripts/epic/epic-cli-decide.ts +42 -0
  191. package/scripts/epic/epic-cli.ts +6 -38
  192. package/scripts/epic/epic-close.ts +112 -55
  193. package/scripts/epic/epic-cross-repo.ts +4 -7
  194. package/scripts/epic/epic-decide.ts +119 -0
  195. package/scripts/epic/epic-decision.ts +9 -0
  196. package/scripts/epic/epic-fetch.ts +4 -0
  197. package/scripts/epic/epic-graph.ts +2 -0
  198. package/scripts/epic/epic-issue.ts +5 -1
  199. package/scripts/epic/epic-label-age.ts +1 -1
  200. package/scripts/epic/epic-lane-offer.ts +39 -4
  201. package/scripts/epic/epic-next-main.ts +24 -0
  202. package/scripts/epic/epic-next.ts +6 -24
  203. package/scripts/epic/epic-outside-blocker.ts +6 -2
  204. package/scripts/epic/epic-parse.ts +9 -3
  205. package/scripts/epic/epic-read.ts +1 -0
  206. package/scripts/epic/epic-reconcile.ts +39 -0
  207. package/scripts/epic/epic-run.ts +10 -1
  208. package/scripts/epic/epic-solo.ts +50 -14
  209. package/scripts/epic/epic.ts +41 -7
  210. package/scripts/exports/unused-members-cli.ts +2 -2
  211. package/scripts/followup/followup-checks-event.ts +8 -3
  212. package/scripts/followup/followup-coderabbit-wait.ts +82 -0
  213. package/scripts/followup/followup-review-gates.ts +81 -0
  214. package/scripts/followup/git-followup-stages.ts +13 -3
  215. package/scripts/followup/git-followup-workflow.ts +19 -66
  216. package/scripts/followup/git-pr-followup-wrapup.ts +9 -14
  217. package/scripts/followup/git-pr-followup.ts +36 -8
  218. package/scripts/fresh-machine/fresh-machine-cli.ts +1 -1
  219. package/scripts/fresh-machine/fresh-machine-run.ts +8 -8
  220. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +1 -1
  221. package/scripts/gate/busy-average.ts +58 -0
  222. package/scripts/gate/check-cpu.ts +60 -0
  223. package/scripts/gate/check-inputs.ts +39 -95
  224. package/scripts/gate/check-reuse.ts +33 -54
  225. package/scripts/gate/command-memory.ts +192 -0
  226. package/scripts/gate/core-admission.ts +218 -28
  227. package/scripts/gate/core-budget-timing.ts +37 -0
  228. package/scripts/gate/core-budget.ts +80 -98
  229. package/scripts/gate/core-wait-record.ts +48 -0
  230. package/scripts/gate/core-wait.ts +37 -5
  231. package/scripts/gate/core-weights.ts +86 -0
  232. package/scripts/gate/free-cores.ts +27 -4
  233. package/scripts/gate/gate-ledger.ts +32 -4
  234. package/scripts/gate/gate-plan.ts +41 -34
  235. package/scripts/gate/gate-report.ts +14 -2
  236. package/scripts/gate/gate-run-steps.ts +53 -8
  237. package/scripts/gate/gate-skip.ts +12 -2
  238. package/scripts/gate/gate-steps.ts +12 -1
  239. package/scripts/gate/input-fingerprint.ts +42 -0
  240. package/scripts/gate/machine-capacity.ts +65 -31
  241. package/scripts/gate/moved-paths.ts +67 -0
  242. package/scripts/gate/project-checks.ts +5 -12
  243. package/scripts/gate/scoped-green.ts +12 -8
  244. package/scripts/gate/since-green.ts +62 -0
  245. package/scripts/gate/toolchain-inputs.ts +115 -0
  246. package/scripts/gate/verification-gate.ts +27 -24
  247. package/scripts/gate/verification-inputs.ts +250 -0
  248. package/scripts/gh/gh-author-association.ts +96 -9
  249. package/scripts/gh/git-ai-review-scan.ts +4 -2
  250. package/scripts/gh/git-gh-api-path.ts +15 -0
  251. package/scripts/gh/git-gh-branch-rules.ts +73 -0
  252. package/scripts/gh/git-gh-conditional.ts +5 -2
  253. package/scripts/gh/git-gh-issue-read.ts +5 -1
  254. package/scripts/gh/git-gh-issue-write.ts +67 -29
  255. package/scripts/gh/git-gh-issue.ts +7 -3
  256. package/scripts/gh/git-gh-poll-read.ts +89 -0
  257. package/scripts/gh/git-gh-pr-auto-merge.ts +8 -3
  258. package/scripts/gh/git-gh-pr-rest.ts +1 -1
  259. package/scripts/gh/git-gh-pr-snapshot.ts +33 -20
  260. package/scripts/gh/git-gh-pr.ts +27 -15
  261. package/scripts/gh/git-pr-checks-eval.ts +39 -7
  262. package/scripts/gh/git-pr-checks-parse.ts +39 -9
  263. package/scripts/gh/git-pr-merge-checked.ts +80 -0
  264. package/scripts/git/base-tree.ts +19 -2
  265. package/scripts/git/changed-file-scope.ts +6 -4
  266. package/scripts/git/changed-paths.ts +18 -1
  267. package/scripts/git/git-diff-reads.ts +27 -2
  268. package/scripts/git/git-grep-hits.ts +85 -0
  269. package/scripts/git/git-location-environment.ts +1 -1
  270. package/scripts/git/git-merge-conflicts.ts +83 -0
  271. package/scripts/git/git-preflight.ts +37 -12
  272. package/scripts/git/git-push-transport.ts +1 -2
  273. package/scripts/git/git-schemas.ts +17 -7
  274. package/scripts/git/git-spawn.ts +1 -2
  275. package/scripts/git/git-status.ts +4 -4
  276. package/scripts/git/main-merge-main.ts +12 -0
  277. package/scripts/git/main-merge-regenerate.ts +2 -2
  278. package/scripts/git/main-merge.ts +25 -9
  279. package/scripts/git/main-sync-main.ts +12 -0
  280. package/scripts/git/main-sync.ts +0 -9
  281. package/scripts/git/stash/git-stash.ts +27 -4
  282. package/scripts/git/stash/{stash-pop-args.ts → stash-args.ts} +13 -10
  283. package/scripts/git/stash/stash-pop-cli.ts +6 -12
  284. package/scripts/git/stash/stash-pop-main.ts +12 -0
  285. package/scripts/git/stash/stash-push-cli.ts +76 -0
  286. package/scripts/git/stash/stash-push-main.ts +12 -0
  287. package/scripts/hooks/batch-guard.ts +0 -8
  288. package/scripts/hooks/check-commit-message-main.ts +8 -0
  289. package/scripts/hooks/check-commit-message.ts +4 -7
  290. package/scripts/hooks/format-edited-file.ts +8 -24
  291. package/scripts/hooks/pre-commit-lint.ts +30 -3
  292. package/scripts/hooks/pre-push-unit.ts +4 -2
  293. package/scripts/hooks/pretool-guard-cli.ts +1 -8
  294. package/scripts/hooks/pretool-guard.ts +32 -19
  295. package/scripts/hooks/reserved-run.ts +67 -9
  296. package/scripts/hooks/run-hook.sh +13 -4
  297. package/scripts/hooks/shell-rules-notice.ts +37 -0
  298. package/scripts/hooks/stop-actions.ts +2 -21
  299. package/scripts/hooks/stop-guard.ts +13 -9
  300. package/scripts/init/hook-command-rewrite.ts +19 -5
  301. package/scripts/init/hook-launch.ts +15 -17
  302. package/scripts/init/init-actions.ts +0 -6
  303. package/scripts/init/init-ai-copy.ts +10 -36
  304. package/scripts/init/init-bootstrap.ts +9 -8
  305. package/scripts/init/init-dry-run-report.ts +1 -1
  306. package/scripts/init/init-dry-run.ts +1 -1
  307. package/scripts/init/init-file-action.ts +7 -9
  308. package/scripts/init/init-logic-json-merge.ts +2 -2
  309. package/scripts/init/init-logic-migrate.ts +9 -82
  310. package/scripts/init/init-logic.ts +3 -2
  311. package/scripts/init/init-main.ts +12 -0
  312. package/scripts/init/init.ts +5 -12
  313. package/scripts/init/kit-development-versions.ts +3 -7
  314. package/scripts/init/kit-written-paths.ts +2 -2
  315. package/scripts/init/project-profile.ts +5 -4
  316. package/scripts/init/tsconfig-preset-migration.ts +2 -1
  317. package/scripts/init/vscode-tasks.ts +1 -1
  318. package/scripts/issue/defect-origin-cli.ts +106 -0
  319. package/scripts/issue/defect-origin-line.ts +60 -0
  320. package/scripts/issue/defect-origin-main.ts +11 -0
  321. package/scripts/issue/defect-origin.ts +114 -0
  322. package/scripts/issue/defect-rate-cli.ts +34 -78
  323. package/scripts/issue/defect-rate.ts +0 -16
  324. package/scripts/issue/defect-report-cli.ts +128 -0
  325. package/scripts/issue/defect-report-format.ts +56 -0
  326. package/scripts/issue/defect-report-main.ts +11 -0
  327. package/scripts/issue/defect-report.ts +160 -0
  328. package/scripts/issue/expected-effect-lint.ts +1 -0
  329. package/scripts/issue/issue-already-done-cli.ts +62 -0
  330. package/scripts/issue/issue-body-or-comment.ts +40 -0
  331. package/scripts/issue/issue-cite-cli.ts +0 -9
  332. package/scripts/issue/issue-cite-main.ts +12 -0
  333. package/scripts/issue/issue-classification.ts +12 -7
  334. package/scripts/issue/issue-comment-cli.ts +10 -24
  335. package/scripts/issue/issue-comment-main.ts +12 -0
  336. package/scripts/issue/issue-evidence-exit.ts +100 -0
  337. package/scripts/issue/issue-file-cli.ts +29 -7
  338. package/scripts/issue/issue-file.ts +19 -19
  339. package/scripts/issue/issue-fold-cli.ts +2 -11
  340. package/scripts/issue/issue-fold-main.ts +12 -0
  341. package/scripts/issue/issue-labels.ts +81 -90
  342. package/scripts/issue/issue-lint-cli.ts +2 -10
  343. package/scripts/issue/issue-lint-main.ts +12 -0
  344. package/scripts/issue/issue-measured-cli.ts +56 -0
  345. package/scripts/issue/issue-merged.ts +19 -2
  346. package/scripts/issue/issue-not-before-label.ts +135 -0
  347. package/scripts/issue/issue-not-before.ts +111 -0
  348. package/scripts/issue/issue-number-shape.ts +15 -1
  349. package/scripts/issue/issue-park.ts +28 -0
  350. package/scripts/issue/issue-plan-cli.ts +151 -0
  351. package/scripts/issue/issue-priority.ts +151 -0
  352. package/scripts/issue/issue-rank.ts +7 -1
  353. package/scripts/issue/issue-read-cli.ts +3 -10
  354. package/scripts/issue/issue-read-main.ts +12 -0
  355. package/scripts/issue/issue-read.ts +29 -5
  356. package/scripts/issue/issue-release-cli.ts +0 -10
  357. package/scripts/issue/issue-release-main.ts +13 -0
  358. package/scripts/issue/issue-release.ts +7 -12
  359. package/scripts/issue/issue-sample-gate.ts +192 -0
  360. package/scripts/issue/issue-sample-source.ts +76 -0
  361. package/scripts/issue/issue-scout-cli.ts +0 -11
  362. package/scripts/issue/issue-scout-main.ts +14 -0
  363. package/scripts/issue/issue-state-cli.ts +0 -10
  364. package/scripts/issue/issue-state-main.ts +12 -0
  365. package/scripts/issue/issue-watch-diff.ts +56 -15
  366. package/scripts/issue/issue-watch.ts +2 -1
  367. package/scripts/issue/issue-wip.ts +2 -7
  368. package/scripts/issue/measure-rerun-cli.ts +13 -8
  369. package/scripts/issue/plan-consumers-cli.ts +39 -0
  370. package/scripts/issue/plan-consumers-main.ts +11 -0
  371. package/scripts/issue/plan-consumers-section.ts +55 -0
  372. package/scripts/issue/plan-consumers.ts +127 -0
  373. package/scripts/josh/agent-session-environment.ts +1 -1
  374. package/scripts/josh/command-usage.ts +15 -43
  375. package/scripts/josh/file-map-stamp.ts +49 -16
  376. package/scripts/josh/hook-decision.ts +32 -20
  377. package/scripts/josh/josh-command-map.ts +4 -1
  378. package/scripts/josh/josh-command-types.ts +12 -6
  379. package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
  380. package/scripts/josh/josh-commands-ai.ts +157 -158
  381. package/scripts/josh/josh-commands-backlog.ts +82 -16
  382. package/scripts/josh/josh-commands-clone.ts +1 -0
  383. package/scripts/josh/josh-commands-development.ts +111 -71
  384. package/scripts/josh/josh-commands-document.ts +43 -1
  385. package/scripts/josh/josh-commands-epic.ts +171 -0
  386. package/scripts/josh/josh-commands-hooks.ts +25 -2
  387. package/scripts/josh/josh-commands-issue-write.ts +181 -0
  388. package/scripts/josh/josh-commands-issue.ts +124 -24
  389. package/scripts/josh/josh-commands-lane.ts +103 -2
  390. package/scripts/josh/josh-commands-lint.ts +19 -8
  391. package/scripts/josh/josh-commands-maintenance.ts +112 -4
  392. package/scripts/josh/josh-commands-pause.ts +29 -0
  393. package/scripts/josh/josh-commands-progress.ts +87 -0
  394. package/scripts/josh/josh-commands-project.ts +138 -9
  395. package/scripts/josh/josh-commands-review.ts +124 -0
  396. package/scripts/josh/josh-commands-run.ts +211 -23
  397. package/scripts/josh/josh-commands-ship.ts +169 -0
  398. package/scripts/josh/josh-commands-split.ts +9 -0
  399. package/scripts/josh/josh-commands-versioning.ts +49 -2
  400. package/scripts/josh/josh-commands-workflow.ts +144 -6
  401. package/scripts/josh/josh-logic.ts +6 -13
  402. package/scripts/josh/package-directory.ts +2 -4
  403. package/scripts/josh/process-identity.ts +13 -4
  404. package/scripts/josh/session-language-cli.ts +4 -8
  405. package/scripts/josh/session-language-main.ts +13 -0
  406. package/scripts/josh/session-language.ts +6 -1
  407. package/scripts/josh/shared-cache.ts +90 -0
  408. package/scripts/josh/stamp-file.ts +9 -15
  409. package/scripts/lane/lane-await.ts +51 -12
  410. package/scripts/lane/lane-cache.ts +5 -30
  411. package/scripts/lane/lane-capacity.ts +14 -23
  412. package/scripts/lane/lane-check-stats.ts +62 -21
  413. package/scripts/lane/lane-child-invocation.ts +8 -0
  414. package/scripts/lane/lane-cli.ts +15 -5
  415. package/scripts/lane/lane-close.ts +86 -18
  416. package/scripts/lane/lane-core-wait-stats.ts +66 -0
  417. package/scripts/lane/lane-dispatch.ts +24 -3
  418. package/scripts/lane/lane-gap-stats.ts +156 -0
  419. package/scripts/lane/lane-handoff.ts +69 -1
  420. package/scripts/lane/lane-held-stats.ts +129 -0
  421. package/scripts/lane/lane-install.ts +4 -11
  422. package/scripts/lane/lane-launch-cli.ts +0 -9
  423. package/scripts/lane/lane-launch-main.ts +12 -0
  424. package/scripts/lane/lane-ledger-schema.ts +266 -0
  425. package/scripts/lane/lane-ledger.ts +92 -123
  426. package/scripts/lane/lane-limit-cli.ts +12 -1
  427. package/scripts/lane/lane-measure-cli.ts +57 -11
  428. package/scripts/lane/lane-open.ts +9 -1
  429. package/scripts/lane/lane-parked.ts +3 -3
  430. package/scripts/lane/lane-pause-cli.ts +130 -0
  431. package/scripts/lane/lane-pause.ts +158 -0
  432. package/scripts/lane/lane-process-table.ts +166 -0
  433. package/scripts/lane/lane-reap-settle.ts +124 -0
  434. package/scripts/lane/lane-reap.ts +50 -15
  435. package/scripts/lane/lane-registry.ts +24 -3
  436. package/scripts/lane/lane-residents.ts +162 -0
  437. package/scripts/lane/lane-restart.ts +22 -2
  438. package/scripts/lane/lane-round-two-stats.ts +49 -0
  439. package/scripts/lane/lane-sampler.ts +4 -0
  440. package/scripts/lane/lane-session-action.ts +19 -5
  441. package/scripts/lane/lane-session-broker.ts +102 -21
  442. package/scripts/lane/lane-snapshot-trace.ts +84 -0
  443. package/scripts/lane/lane-spans.ts +51 -0
  444. package/scripts/lane/lane-spent.ts +6 -3
  445. package/scripts/lane/lane-stage-stats.ts +7 -2
  446. package/scripts/lane/lane-state.ts +302 -0
  447. package/scripts/lane/lane-stats.ts +58 -4
  448. package/scripts/lane/lane-stop-stats.ts +113 -37
  449. package/scripts/lane/lane-test-related-stats.ts +127 -0
  450. package/scripts/lane/lane-transcript-calls.ts +145 -0
  451. package/scripts/lane/lane-transcript-stats.ts +168 -0
  452. package/scripts/lane/lane-vacant.ts +13 -3
  453. package/scripts/lane/lane-withdraw-cli.ts +5 -4
  454. package/scripts/lane/lane-withdraw.ts +50 -49
  455. package/scripts/lane/process-directories.ts +70 -0
  456. package/scripts/lane/process-lane-marks.ts +94 -0
  457. package/scripts/lib/atomic-write.ts +62 -0
  458. package/scripts/lib/buffered-process.ts +12 -5
  459. package/scripts/lib/cli-flags.ts +53 -0
  460. package/scripts/lib/figure-format.ts +63 -0
  461. package/scripts/lib/json-value.ts +9 -1
  462. package/scripts/lib/package-manifest.ts +35 -0
  463. package/scripts/lib/read-file.ts +3 -1
  464. package/scripts/lib/stamped-memo.ts +63 -0
  465. package/scripts/lib/stdout-on-stderr.ts +24 -0
  466. package/scripts/lib/timeouts.ts +9 -0
  467. package/scripts/lib/transcript-record.ts +91 -0
  468. package/scripts/lines/effective-limit.ts +1 -1
  469. package/scripts/lint/eslint-cache-dependencies.ts +145 -0
  470. package/scripts/lint/eslint-daemon.ts +265 -0
  471. package/scripts/lint/format.ts +11 -2
  472. package/scripts/lint/import-graph.ts +279 -0
  473. package/scripts/lint/lint-gate-scope.ts +102 -0
  474. package/scripts/lint/lint-parallel-main.ts +19 -0
  475. package/scripts/lint/lint-parallel.ts +62 -30
  476. package/scripts/lint/lint-related-scope.ts +30 -24
  477. package/scripts/lint/lint-related.ts +38 -6
  478. package/scripts/notify/confirmation-options.ts +1 -2
  479. package/scripts/notify/telegram-notify.ts +20 -20
  480. package/scripts/notify/telegram-test-logic.ts +0 -1
  481. package/scripts/notify/telegram-test-main.ts +8 -0
  482. package/scripts/notify/telegram-test.ts +2 -6
  483. package/scripts/observations/observation-ledger.ts +13 -0
  484. package/scripts/observations/observations-flush-landing.ts +5 -3
  485. package/scripts/observations/observations-flush.ts +6 -1
  486. package/scripts/overrides/overrides-check.ts +2 -5
  487. package/scripts/overrides/overrides-files.ts +2 -1
  488. package/scripts/overrides/overrides-logic.ts +3 -6
  489. package/scripts/package/verify-optional-eslint-install.ts +8 -6
  490. package/scripts/propagate/propagate-publish.ts +2 -7
  491. package/scripts/propagate/propagate-targets.ts +4 -12
  492. package/scripts/refactor/import-graph.ts +9 -7
  493. package/scripts/release/github-release-runs.ts +17 -6
  494. package/scripts/release/release-approval-prune.ts +18 -0
  495. package/scripts/release/release-history.ts +1 -3
  496. package/scripts/release/release-progress.ts +42 -22
  497. package/scripts/release/release-publish-run.ts +39 -0
  498. package/scripts/release/release-publish.ts +6 -6
  499. package/scripts/release/release-scope-cli.ts +0 -10
  500. package/scripts/release/release-scope-main.ts +12 -0
  501. package/scripts/repo/repo-setting.ts +3 -6
  502. package/scripts/repo/required-checks-logic.ts +6 -15
  503. package/scripts/report/report-format-reference.ts +2 -0
  504. package/scripts/report/report-labels.ts +155 -0
  505. package/scripts/report/report-lint-cli.ts +3 -0
  506. package/scripts/report/report-lint.ts +85 -110
  507. package/scripts/report/report-template-cli.ts +59 -0
  508. package/scripts/report/report-template.ts +112 -0
  509. package/scripts/review/acceptance-map.ts +1 -0
  510. package/scripts/review/removed-tests-check.ts +86 -0
  511. package/scripts/review/removed-tests.ts +149 -0
  512. package/scripts/review/review-brief-cli.ts +81 -15
  513. package/scripts/review/review-brief-main.ts +12 -0
  514. package/scripts/review/review-brief.ts +31 -3
  515. package/scripts/review/review-code-tree.ts +10 -6
  516. package/scripts/review/review-comment-round.ts +26 -8
  517. package/scripts/review/review-finding-ledger.ts +30 -15
  518. package/scripts/review/review-interaction.ts +94 -0
  519. package/scripts/review/review-readers-scan.ts +163 -0
  520. package/scripts/review/review-record-cli.ts +69 -30
  521. package/scripts/review/review-record-main.ts +12 -0
  522. package/scripts/review/review-round-one-blobs.ts +221 -0
  523. package/scripts/review/review-round2-cli.ts +49 -12
  524. package/scripts/review/review-round2.ts +80 -12
  525. package/scripts/review/review-stamps.ts +19 -1
  526. package/scripts/review/review-stop-log.ts +96 -0
  527. package/scripts/review/review-stops-cli.ts +85 -0
  528. package/scripts/review/review-tree.ts +6 -17
  529. package/scripts/review/review-untouched-readers.ts +146 -0
  530. package/scripts/review/test-titles.ts +118 -0
  531. package/scripts/rules/agent-model.ts +8 -0
  532. package/scripts/rules/bash-triggers.ts +46 -3
  533. package/scripts/rules/decision-oracle-batch.ts +9 -1
  534. package/scripts/rules/decision-oracle.ts +2 -2
  535. package/scripts/rules/delivered-rules.ts +80 -2
  536. package/scripts/rules/destructive-command.ts +8 -1
  537. package/scripts/rules/direct-filing.ts +10 -2
  538. package/scripts/rules/direct-issue-comment.ts +117 -0
  539. package/scripts/rules/direct-pr-create.ts +69 -3
  540. package/scripts/rules/early-heartbeat.ts +2 -1
  541. package/scripts/rules/file-body.ts +7 -0
  542. package/scripts/rules/filing-cap.ts +7 -0
  543. package/scripts/rules/git-argv.ts +72 -14
  544. package/scripts/rules/git-force.ts +12 -2
  545. package/scripts/rules/guard-remedy.ts +4 -0
  546. package/scripts/rules/implementation-cut-verdict.ts +1 -1
  547. package/scripts/rules/implementation-cut.ts +11 -3
  548. package/scripts/rules/index-guard.ts +8 -1
  549. package/scripts/rules/issue-comments.ts +9 -1
  550. package/scripts/rules/josh-git-bare.ts +7 -0
  551. package/scripts/rules/lane-background.ts +67 -25
  552. package/scripts/rules/lane-carry-conflict.ts +6 -0
  553. package/scripts/rules/lane-direct-tool.ts +74 -0
  554. package/scripts/rules/lane-interactive-ask.ts +9 -2
  555. package/scripts/rules/lane-park.ts +45 -23
  556. package/scripts/rules/lane-split-park.ts +10 -2
  557. package/scripts/rules/lane-switch-main.ts +7 -0
  558. package/scripts/rules/oracle-consulted.ts +10 -0
  559. package/scripts/rules/oracle-firing.ts +1 -0
  560. package/scripts/rules/permission-guards.ts +3 -0
  561. package/scripts/rules/piped-verification.ts +1 -1
  562. package/scripts/rules/poll-loop.ts +7 -0
  563. package/scripts/rules/pr-merge.ts +123 -0
  564. package/scripts/rules/protected-files.ts +32 -5
  565. package/scripts/rules/raw-field-body.ts +6 -0
  566. package/scripts/rules/rule-body-guard.ts +8 -0
  567. package/scripts/rules/rule-list.ts +9 -28
  568. package/scripts/rules/rule-value-cache.ts +4 -9
  569. package/scripts/rules/rule-value-cli.ts +51 -32
  570. package/scripts/rules/rule-value.ts +1 -1
  571. package/scripts/rules/shell-segments.ts +35 -0
  572. package/scripts/rules/stop-rule-rows.ts +64 -0
  573. package/scripts/rules/stop-rules.ts +3 -4
  574. package/scripts/rules/test-declared-commit.ts +11 -1
  575. package/scripts/rules/third-party-write.ts +7 -0
  576. package/scripts/rules/timed-rerun.ts +69 -0
  577. package/scripts/rules/worktree-guard.ts +13 -3
  578. package/scripts/run/board/run-board-app-name.ts +23 -0
  579. package/scripts/run/board/run-board-cli.ts +65 -32
  580. package/scripts/run/board/run-board-earlier.ts +94 -0
  581. package/scripts/run/board/run-board-ending-reason.ts +67 -0
  582. package/scripts/run/board/run-board-estimate-schedule.ts +103 -0
  583. package/scripts/run/board/run-board-estimate.ts +98 -0
  584. package/scripts/run/board/run-board-fit.ts +153 -36
  585. package/scripts/run/board/run-board-fold.ts +123 -0
  586. package/scripts/run/board/run-board-fresh.ts +2 -2
  587. package/scripts/run/board/run-board-gather-live.ts +29 -0
  588. package/scripts/run/board/run-board-gather-thread.ts +189 -0
  589. package/scripts/run/board/run-board-gather-worker.ts +29 -0
  590. package/scripts/run/board/run-board-gather.ts +187 -0
  591. package/scripts/run/board/run-board-github.ts +118 -38
  592. package/scripts/run/board/run-board-header.ts +82 -20
  593. package/scripts/run/board/run-board-keys.ts +58 -0
  594. package/scripts/run/board/run-board-kind.ts +20 -6
  595. package/scripts/run/board/run-board-labels.ts +116 -71
  596. package/scripts/run/board/run-board-lane-state.ts +109 -0
  597. package/scripts/run/board/run-board-lane-time.ts +122 -0
  598. package/scripts/run/board/run-board-layout.ts +239 -60
  599. package/scripts/run/board/run-board-length.ts +52 -0
  600. package/scripts/run/board/run-board-machine.ts +8 -4
  601. package/scripts/run/board/run-board-main.ts +12 -0
  602. package/scripts/run/board/run-board-notes.ts +52 -31
  603. package/scripts/run/board/run-board-now.ts +1 -1
  604. package/scripts/run/board/run-board-operation.ts +15 -33
  605. package/scripts/run/board/run-board-phase.ts +1 -1
  606. package/scripts/run/board/run-board-plan-shared.ts +115 -0
  607. package/scripts/run/board/run-board-plan.ts +55 -3
  608. package/scripts/run/board/run-board-planning.ts +45 -0
  609. package/scripts/run/board/run-board-priority.ts +44 -0
  610. package/scripts/run/board/run-board-process-groups.ts +195 -0
  611. package/scripts/run/board/run-board-read.ts +151 -27
  612. package/scripts/run/board/run-board-reason.ts +235 -51
  613. package/scripts/run/board/run-board-released.ts +35 -0
  614. package/scripts/run/board/run-board-render-checks.ts +39 -5
  615. package/scripts/run/board/run-board-render-condition.ts +96 -0
  616. package/scripts/run/board/run-board-render-drawn.ts +67 -0
  617. package/scripts/run/board/run-board-render-foot.ts +59 -0
  618. package/scripts/run/board/run-board-render-icon.ts +35 -0
  619. package/scripts/run/board/run-board-render-lanes.ts +145 -0
  620. package/scripts/run/board/run-board-render-lead.ts +80 -0
  621. package/scripts/run/board/run-board-render-legend.ts +117 -48
  622. package/scripts/run/board/run-board-render-notes.ts +156 -29
  623. package/scripts/run/board/run-board-render-processes.ts +196 -0
  624. package/scripts/run/board/run-board-render-section.ts +119 -0
  625. package/scripts/run/board/run-board-render-slot.ts +3 -36
  626. package/scripts/run/board/run-board-render-tail.ts +115 -48
  627. package/scripts/run/board/run-board-render-time.ts +56 -0
  628. package/scripts/run/board/run-board-render-title.ts +117 -24
  629. package/scripts/run/board/run-board-render-waits.ts +104 -20
  630. package/scripts/run/board/run-board-render.ts +207 -265
  631. package/scripts/run/board/run-board-roots.ts +54 -0
  632. package/scripts/run/board/run-board-row-yield.ts +9 -4
  633. package/scripts/run/board/run-board-setup.ts +1 -12
  634. package/scripts/run/board/run-board-snapshot.ts +111 -0
  635. package/scripts/run/board/run-board-spin.ts +2 -2
  636. package/scripts/run/board/run-board-state.ts +22 -33
  637. package/scripts/run/board/run-board-status.ts +147 -71
  638. package/scripts/run/board/run-board-thanks-read.ts +2 -2
  639. package/scripts/run/board/run-board-tick.ts +122 -107
  640. package/scripts/run/board/run-board-usage-board.ts +78 -0
  641. package/scripts/run/board/run-board-usage-lanes.ts +113 -0
  642. package/scripts/run/board/run-board-usage-listing.ts +93 -0
  643. package/scripts/run/board/run-board-usage-read.ts +120 -150
  644. package/scripts/run/board/run-board-usage-rusage.ts +19 -7
  645. package/scripts/run/board/run-board-usage-text.ts +139 -51
  646. package/scripts/run/board/run-board-usage-top.ts +102 -0
  647. package/scripts/run/board/run-board-usage.ts +89 -72
  648. package/scripts/run/board/run-board-usual.ts +20 -9
  649. package/scripts/run/carry/run-carry-args.ts +4 -7
  650. package/scripts/run/carry/run-carry-conversation.ts +1 -1
  651. package/scripts/run/carry/run-carry.ts +9 -4
  652. package/scripts/run/cut/run-cut-handoff.ts +2 -2
  653. package/scripts/run/event/run-event-cli.ts +1 -5
  654. package/scripts/run/event/run-event-filed.ts +12 -6
  655. package/scripts/run/event/run-event-follow.ts +2 -3
  656. package/scripts/run/event/run-event-render.ts +6 -10
  657. package/scripts/run/event/run-event-scope.ts +2 -2
  658. package/scripts/run/event/run-event-stream-emit.ts +82 -22
  659. package/scripts/run/event/run-event-stream.ts +34 -8
  660. package/scripts/run/hold/run-hold-adopt.ts +65 -0
  661. package/scripts/run/hold/run-hold-cli.ts +93 -22
  662. package/scripts/run/hold/run-hold-main.ts +12 -0
  663. package/scripts/run/hold/run-hold-member.ts +37 -0
  664. package/scripts/run/hold/run-stop-notify.ts +183 -0
  665. package/scripts/run/merge/run-merge-auth.ts +31 -0
  666. package/scripts/run/merge/run-merge-cli.ts +62 -48
  667. package/scripts/run/merge/run-merge-close.ts +74 -0
  668. package/scripts/run/merge/run-merge-collect.ts +6 -13
  669. package/scripts/run/merge/run-merge-driver.ts +71 -0
  670. package/scripts/run/merge/run-merge-main.ts +12 -0
  671. package/scripts/run/merge/run-merge-outcome.ts +23 -0
  672. package/scripts/run/merge/run-merge-restart.ts +39 -0
  673. package/scripts/run/merge/run-merge-ship.ts +20 -4
  674. package/scripts/run/merge/run-merge-signals.ts +33 -9
  675. package/scripts/run/merge/run-merge-steps.ts +120 -85
  676. package/scripts/run/merge/run-merge.ts +38 -37
  677. package/scripts/run/park/run-park-cli.ts +91 -0
  678. package/scripts/run/park/run-park.ts +88 -0
  679. package/scripts/run/park/run-stalled.ts +68 -0
  680. package/scripts/run/pause/run-pause-cli.ts +73 -0
  681. package/scripts/run/pause/run-pause.ts +251 -0
  682. package/scripts/run/progress/run-progress-cli.ts +4 -12
  683. package/scripts/run/progress/run-progress-clock.ts +1 -1
  684. package/scripts/run/progress/run-progress-config.ts +6 -14
  685. package/scripts/run/progress/run-progress-main.ts +12 -0
  686. package/scripts/run/progress/run-progress.ts +1 -4
  687. package/scripts/run/review/run-review.ts +2 -1
  688. package/scripts/run/run-ending.ts +1 -0
  689. package/scripts/run/run-invocation.ts +5 -6
  690. package/scripts/run/run-liveness-cli.ts +6 -8
  691. package/scripts/run/run-liveness.ts +60 -29
  692. package/scripts/run/run-next.ts +1 -1
  693. package/scripts/run/run-parent-cut-hook.ts +2 -2
  694. package/scripts/run/run-preflight.ts +18 -3
  695. package/scripts/run/run-prep-cli.ts +1 -10
  696. package/scripts/run/run-prep-locate.ts +7 -50
  697. package/scripts/run/run-prep-main.ts +12 -0
  698. package/scripts/run/run-prep.ts +6 -0
  699. package/scripts/run/run-report-cli.ts +101 -13
  700. package/scripts/run/run-report-handoff.ts +114 -0
  701. package/scripts/run/run-step.ts +1 -1
  702. package/scripts/run/run-stranded-detect.ts +13 -0
  703. package/scripts/run/run-watcher-guard-cli.ts +1 -1
  704. package/scripts/run/run-watcher-guard.ts +1 -1
  705. package/scripts/run/ship/run-ship-args.ts +121 -0
  706. package/scripts/run/ship/run-ship-body-draft.ts +110 -0
  707. package/scripts/run/ship/run-ship-cli.ts +63 -140
  708. package/scripts/run/ship/run-ship-detach.ts +19 -8
  709. package/scripts/run/ship/run-ship-infra-retry.ts +59 -0
  710. package/scripts/run/ship/run-ship-next.ts +18 -2
  711. package/scripts/run/ship/run-ship-overlap.ts +42 -5
  712. package/scripts/run/ship/run-ship-place.ts +96 -0
  713. package/scripts/run/ship/run-ship-pre-detach-timed.ts +43 -0
  714. package/scripts/run/ship/run-ship-pre-detach.ts +81 -24
  715. package/scripts/run/ship/run-ship-preflight.ts +137 -32
  716. package/scripts/run/ship/run-ship-probe.ts +11 -3
  717. package/scripts/run/ship/run-ship-relaunch-cap.ts +70 -0
  718. package/scripts/run/ship/run-ship-removed-rows.ts +61 -0
  719. package/scripts/run/ship/run-ship-return.ts +107 -23
  720. package/scripts/run/ship/run-ship-review-steps.ts +105 -151
  721. package/scripts/run/ship/run-ship-review.ts +73 -6
  722. package/scripts/run/ship/run-ship-reviewer.ts +207 -0
  723. package/scripts/run/ship/run-ship-stage.ts +55 -6
  724. package/scripts/run/ship/run-ship-steps.ts +46 -15
  725. package/scripts/run/ship/run-ship-stop-cause.ts +135 -0
  726. package/scripts/run/ship/run-ship-stop-text.ts +11 -6
  727. package/scripts/run/ship/run-ship-sync.ts +43 -6
  728. package/scripts/run/ship/run-ship.ts +30 -2
  729. package/scripts/run/tidy/run-tidy-cli.ts +0 -4
  730. package/scripts/run/tidy/run-tidy-lanes.ts +3 -0
  731. package/scripts/run/tidy/run-tidy-main.ts +8 -0
  732. package/scripts/run/wake/run-wake-cli.ts +119 -100
  733. package/scripts/run/wake/run-wake-code.ts +83 -0
  734. package/scripts/run/wake/run-wake-driver.ts +19 -8
  735. package/scripts/run/wake/run-wake-loop.ts +34 -3
  736. package/scripts/run/wake/run-wake-main.ts +13 -0
  737. package/scripts/run/wake/run-wake-ports.ts +90 -0
  738. package/scripts/run/wake/run-wake-takeover.ts +66 -0
  739. package/scripts/run/wake/run-wake.ts +2 -1
  740. package/scripts/safe-chain/pack-hook.ts +2 -2
  741. package/scripts/safe-chain/preinstall-command.ts +2 -1
  742. package/scripts/safe-chain/project-config.ts +3 -9
  743. package/scripts/security/security-audit-main.ts +8 -0
  744. package/scripts/security/security-audit-provision-logic.ts +0 -11
  745. package/scripts/security/security-audit-provision-main.ts +12 -0
  746. package/scripts/security/security-audit-provision.ts +11 -26
  747. package/scripts/security/security-audit.ts +6 -7
  748. package/scripts/self-sync-guard/self-sync-guard-logic.ts +6 -13
  749. package/scripts/split/split-assess-cli.ts +2 -2
  750. package/scripts/split/split-assess.ts +15 -0
  751. package/scripts/split/split-measure.ts +65 -0
  752. package/scripts/sync/claude-settings-merge.ts +8 -15
  753. package/scripts/sync/directory-copy-guard.ts +4 -9
  754. package/scripts/sync/file-content.ts +78 -8
  755. package/scripts/sync/sync-ai-files.ts +3 -5
  756. package/scripts/sync/sync-configs.ts +11 -23
  757. package/scripts/sync/sync-hook-safety.ts +4 -10
  758. package/scripts/sync/sync-main.ts +11 -0
  759. package/scripts/sync/sync.ts +25 -37
  760. package/scripts/test/test-declared-changed.ts +2 -2
  761. package/scripts/test/test-declared.ts +1 -1
  762. package/scripts/test/test-e2e-guard.ts +25 -1
  763. package/scripts/test/test-e2e-stamp.ts +38 -0
  764. package/scripts/test/test-pinned-logic.ts +145 -0
  765. package/scripts/test/test-pinned-main.ts +78 -0
  766. package/scripts/test/test-pinned.ts +100 -0
  767. package/scripts/test/test-read-map.ts +264 -0
  768. package/scripts/test/test-read-recording.ts +91 -0
  769. package/scripts/test/test-read-trace.ts +148 -0
  770. package/scripts/test/test-red-main.ts +12 -0
  771. package/scripts/test/test-red.ts +12 -30
  772. package/scripts/test/test-related-main.ts +18 -0
  773. package/scripts/test/test-related-record.ts +119 -0
  774. package/scripts/test/test-related-scope.ts +229 -43
  775. package/scripts/test/test-related.ts +300 -22
  776. package/scripts/test/test-unit-guard-main.ts +15 -0
  777. package/scripts/test/test-unit-guard.ts +42 -24
  778. package/scripts/test/unit-count-file.ts +37 -0
  779. package/scripts/test/unit-run-marker.ts +162 -0
  780. package/scripts/test/unit-setup-files.ts +51 -0
  781. package/scripts/test/unit-worker-share.ts +61 -149
  782. package/scripts/test/whole-suite-files.ts +63 -0
  783. package/scripts/time-runtime/time-background.ts +20 -2
  784. package/scripts/time-runtime/time-bundles.ts +4 -3
  785. package/scripts/time-runtime/time-density-hook.ts +8 -6
  786. package/scripts/time-runtime/time-followup-stage.ts +1 -3
  787. package/scripts/time-runtime/time-format.ts +5 -28
  788. package/scripts/time-runtime/time-markers.ts +10 -1
  789. package/scripts/time-runtime/time-shell.ts +97 -10
  790. package/scripts/time-runtime/time-transcript-line.ts +49 -62
  791. package/scripts/uninstall/uninstall.ts +1 -1
  792. package/scripts/version/bump-version-main.ts +12 -0
  793. package/scripts/version/bump-version.ts +25 -25
  794. package/scripts/version/effective-upstream.ts +6 -12
  795. package/scripts/version/latest-corepack.ts +17 -32
  796. package/scripts/version/latest-if-required-cli.ts +93 -0
  797. package/scripts/version/latest-lane-guard-main.ts +8 -0
  798. package/scripts/version/latest-lane-guard.ts +0 -4
  799. package/scripts/version/latest-scope-cli.ts +0 -9
  800. package/scripts/version/latest-scope-main.ts +12 -0
  801. package/scripts/version/latest-update.ts +5 -5
  802. package/scripts/version/npm-registry.ts +44 -6
  803. package/scripts/version/publishable-range-check.ts +5 -16
  804. package/scripts/version/release-age.ts +1 -1
  805. package/scripts/version/release-hold.ts +1 -1
  806. package/scripts/version/release-window.ts +38 -0
  807. package/scripts/version/running-binary.ts +1 -1
  808. package/scripts/version/safe-chain-version-update.ts +3 -8
  809. package/scripts/version/version-targets.ts +6 -28
  810. package/templates/dependabot.yml +29 -0
  811. package/templates/gitignore +4 -1
  812. package/templates/pnpm-workspace.basic.yaml +1 -1
  813. package/templates/sonar-project.properties +3 -2
  814. package/templates/workflows/ci.yml +12 -4
  815. package/templates/workflows/github-release.yml +4 -0
  816. package/tsconfig.sonar.json +1 -1
  817. package/.ncurc.json +0 -3
  818. package/dist/hooks/batch-guard.js +0 -29
  819. package/dist/hooks/chunk-4KKD2UTK.js +0 -66
  820. package/dist/hooks/chunk-6TS2JD6D.js +0 -237
  821. package/dist/hooks/chunk-7DSBJVFH.js +0 -50
  822. package/dist/hooks/chunk-A65Y4YOR.js +0 -79
  823. package/dist/hooks/chunk-CDY4NFQG.js +0 -15
  824. package/dist/hooks/chunk-EFXE6C37.js +0 -81
  825. package/dist/hooks/chunk-GP4IEC4O.js +0 -20
  826. package/dist/hooks/chunk-JP45SOCJ.js +0 -56
  827. package/dist/hooks/chunk-LAOV7NLM.js +0 -45
  828. package/dist/hooks/chunk-M4HGZV7U.js +0 -83
  829. package/dist/hooks/chunk-PF2NZL2A.js +0 -131
  830. package/dist/hooks/chunk-PTICX4OL.js +0 -358
  831. package/dist/hooks/chunk-RT27QRJW.js +0 -6247
  832. package/dist/hooks/chunk-SYOTDYCI.js +0 -3533
  833. package/dist/hooks/chunk-UPUZF3AN.js +0 -279
  834. package/dist/hooks/chunk-WK6SMBIC.js +0 -3180
  835. package/dist/hooks/duplicate-read-guard.js +0 -30
  836. package/dist/hooks/investigation-guard.js +0 -29
  837. package/scripts/backlog/backlog-stalled-cli.ts +0 -30
  838. package/scripts/cost-runtime/cost-format.ts +0 -29
  839. package/scripts/init/basic-path-migration.ts +0 -24
  840. package/scripts/issue/issue-backlinks-cli.ts +0 -93
  841. package/scripts/josh/josh-commands-guard.ts +0 -38
  842. package/scripts/josh/josh-usage-automation.ts +0 -121
  843. package/scripts/josh/josh-usage-backlog.ts +0 -180
  844. package/scripts/josh/josh-usage-developer.ts +0 -230
  845. package/scripts/josh/josh-usage-hooks.ts +0 -38
  846. package/scripts/josh/josh-usage-issue.ts +0 -205
  847. package/scripts/josh/josh-usage-review.ts +0 -101
  848. package/scripts/josh/josh-usage-run.ts +0 -252
  849. package/scripts/josh/josh-usage-session.ts +0 -238
  850. package/scripts/josh/josh-usage-workflow.ts +0 -212
  851. package/scripts/lint/cross-file-recheck.ts +0 -155
  852. package/scripts/registry-migration/migrate-logic.ts +0 -237
  853. package/scripts/registry-migration/migrate.ts +0 -292
  854. package/scripts/registry-migration/user-npmrc.ts +0 -15
  855. package/scripts/rules/rule-guard.ts +0 -23
  856. package/scripts/rules/rule-registry-rows.ts +0 -292
  857. package/scripts/rules/rule-registry.ts +0 -112
  858. package/scripts/run/run-stranded-cli.ts +0 -27
@@ -36,7 +36,6 @@ const LABEL_NAMES_FILTER = '.[].name'
36
36
  const LABELS_SEGMENT = '/labels'
37
37
  const COMMENTS_SEGMENT = '/comments'
38
38
  const CLOSED_STATE = 'closed'
39
- const NOT_PLANNED_REASON = 'not_planned'
40
39
  const COLOR_HASH = '#'
41
40
  const UNPROCESSABLE_STATUS = 422
42
41
  const ALREADY_EXISTS_CODE = 'already_exists'
@@ -57,21 +56,39 @@ async function did_write_succeed(write: () => Promise<unknown>): Promise<boolean
57
56
  }
58
57
  }
59
58
 
60
- async function issue_edit_body(issue_number: string, body: string): Promise<string> {
59
+ async function issue_patch(
60
+ issue_number: string,
61
+ fields: Readonly<Record<string, string>>,
62
+ repo?: string,
63
+ ): Promise<string> {
61
64
  return await git_gh_exec.exec_gh_api({
62
- path: git_gh_api_path.issue_api_path(issue_number),
65
+ path: git_gh_api_path.issue_api_path(issue_number, repo),
63
66
  method: PATCH_METHOD,
64
- body: JSON.stringify({ body }),
67
+ body: JSON.stringify(fields),
65
68
  jq_filter: HTML_URL_FILTER,
66
69
  })
67
70
  }
68
71
 
72
+ // The optional `repo` (`owner/name`) on these writes addresses an issue in another repository; left
73
+ // out, the path keeps gh's `{owner}/{repo}` placeholder — the checkout's own repository.
74
+ async function issue_edit_body(issue_number: string, body: string, repo?: string): Promise<string> {
75
+ return await issue_patch(issue_number, { body }, repo)
76
+ }
77
+
78
+ async function issue_edit_title(
79
+ issue_number: string,
80
+ title: string,
81
+ repo?: string,
82
+ ): Promise<string> {
83
+ return await issue_patch(issue_number, { title }, repo)
84
+ }
85
+
69
86
  // **Every comment josh posts carries `RUN_MARKER`**, an HTML comment GitHub does not render. A run
70
87
  // posts under the person's own `gh` login, so the marker is the only thing that tells the issue watch
71
88
  // (`issue-watch-diff.ts`) a run's comment from a person's update.
72
- async function issue_comment(issue_number: string, body: string): Promise<string> {
89
+ async function issue_comment(issue_number: string, body: string, repo?: string): Promise<string> {
73
90
  return await git_gh_exec.exec_gh_api({
74
- path: `${git_gh_api_path.issue_api_path(issue_number)}${COMMENTS_SEGMENT}`,
91
+ path: `${git_gh_api_path.issue_api_path(issue_number, repo)}${COMMENTS_SEGMENT}`,
75
92
  body: JSON.stringify({ body: `${body}\n\n${issue_watch_diff.RUN_MARKER}` }),
76
93
  jq_filter: HTML_URL_FILTER,
77
94
  })
@@ -119,18 +136,6 @@ async function issue_close(issue_number: string, comment: string | undefined): P
119
136
  return await close_with(issue_number, comment, { state: CLOSED_STATE })
120
137
  }
121
138
 
122
- // The same close as "not planned" — the reason `issue-merged.ts` reads as no merge, so a closed issue
123
- // that was withdrawn is never taken for one whose work landed.
124
- async function issue_close_not_planned(
125
- issue_number: string,
126
- comment: string | undefined,
127
- ): Promise<boolean> {
128
- return await close_with(issue_number, comment, {
129
- state: CLOSED_STATE,
130
- state_reason: NOT_PLANNED_REASON,
131
- })
132
- }
133
-
134
139
  // REST answers 422 `{"resource":"Label","code":"invalid","field":"color"}` for a color carrying a
135
140
  // leading `#`. The one caller passes the hash form (`EPIC_LABEL_COLOR`), so dropping it here is what
136
141
  // keeps that call site unchanged.
@@ -225,12 +230,16 @@ async function issue_create_with_label(input: {
225
230
  // say why it refused.
226
231
  type LabelWrite = { is_applied: true } | { is_applied: false; reason: string }
227
232
 
228
- // The issue's label names, read back after a failed write. A read that itself fails answers
229
- // `undefined`, which the caller treats as "not applied" — the write's own error is the reason then.
230
- async function read_label_names(issue_number: string): Promise<Array<string> | undefined> {
233
+ // The issue's label names, every page of them — read back after a failed write, and by a pull
234
+ // request's classification read. A read that itself fails answers `undefined`, which the write
235
+ // treats as "not applied" — its own error is the reason then.
236
+ async function read_label_names(
237
+ issue_number: string,
238
+ repo?: string,
239
+ ): Promise<Array<string> | undefined> {
231
240
  try {
232
241
  const raw = await git_gh_exec.exec_gh_api({
233
- path: `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`,
242
+ path: git_gh_api_path.issue_labels_api_path(issue_number, repo),
234
243
  should_paginate: true,
235
244
  jq_filter: LABEL_NAMES_FILTER,
236
245
  })
@@ -247,15 +256,19 @@ async function read_label_names(issue_number: string): Promise<Array<string> | u
247
256
  // after the write or a secondary rate limit can each throw after the label landed — which refused a
248
257
  // lane dispatch whose label was in fact applied. So a throw is confirmed by
249
258
  // reading the labels back, and only a label that is really absent answers `is_applied: false`.
250
- async function issue_apply_label(issue_number: string, label: string): Promise<LabelWrite> {
251
- const labels_path = `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`
259
+ async function issue_apply_label(
260
+ issue_number: string,
261
+ label: string,
262
+ repo?: string,
263
+ ): Promise<LabelWrite> {
264
+ const labels_path = git_gh_api_path.issue_labels_api_path(issue_number, repo)
252
265
 
253
266
  try {
254
267
  await git_gh_exec.exec_gh_api({ path: labels_path, body: JSON.stringify({ labels: [label] }) })
255
268
 
256
269
  return { is_applied: true }
257
270
  } catch (error) {
258
- const names = await read_label_names(issue_number)
271
+ const names = await read_label_names(issue_number, repo)
259
272
 
260
273
  if (names?.includes(label) === true) return { is_applied: true }
261
274
  error_text.trace_swallowed('git_gh_issue_write.issue_apply_label', error)
@@ -271,8 +284,12 @@ async function issue_apply_label(issue_number: string, label: string): Promise<L
271
284
  // Applied after the body edit so a failure leaves an issue with the epic sections and no label,
272
285
  // which `epic:check` reports — rather than a labelled issue with nothing to track. The caller checks
273
286
  // the return: the label is what the auto-close filters on.
274
- async function issue_add_label(issue_number: string, label: string): Promise<boolean> {
275
- const write = await issue_apply_label(issue_number, label)
287
+ async function issue_add_label(
288
+ issue_number: string,
289
+ label: string,
290
+ repo?: string,
291
+ ): Promise<boolean> {
292
+ const write = await issue_apply_label(issue_number, label, repo)
276
293
 
277
294
  return write.is_applied
278
295
  }
@@ -287,7 +304,7 @@ async function issue_add_label(issue_number: string, label: string): Promise<boo
287
304
  // a `false` swallowed here would reach that guard as a success and the step would be reported as
288
305
  // done.
289
306
  async function issue_remove_label(issue_number: string, label: string): Promise<void> {
290
- const labels_path = `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`
307
+ const labels_path = git_gh_api_path.issue_labels_api_path(issue_number)
291
308
 
292
309
  await git_gh_exec.exec_gh_api({
293
310
  path: `${labels_path}/${encodeURIComponent(label)}`,
@@ -295,6 +312,25 @@ async function issue_remove_label(issue_number: string, label: string): Promise<
295
312
  })
296
313
  }
297
314
 
315
+ // **The removal for a caller that wants the label gone, not removed by this call** — a release that
316
+ // may find the label already off. A failed DELETE is confirmed against the labels the issue carries,
317
+ // the read `issue_apply_label` confirms an addition with, so an absent label answers `true` and a
318
+ // failure that left the label on answers `false`.
319
+ async function issue_clear_label(issue_number: string, label: string): Promise<boolean> {
320
+ try {
321
+ await issue_remove_label(issue_number, label)
322
+
323
+ return true
324
+ } catch (error) {
325
+ const names = await read_label_names(issue_number)
326
+
327
+ if (names?.includes(label) === false) return true
328
+ error_text.trace_swallowed('git_gh_issue_write.issue_clear_label', error)
329
+
330
+ return false
331
+ }
332
+ }
333
+
298
334
  // The blocker's **database id**, which is the only thing the dependencies endpoint accepts — and the
299
335
  // reason this resolution exists rather than the issue number being sent straight through.
300
336
  //
@@ -354,16 +390,18 @@ async function issue_remove_blocked_by(issue_number: string, blocker: string): P
354
390
 
355
391
  const git_gh_issue_write = {
356
392
  issue_edit_body,
393
+ issue_edit_title,
357
394
  issue_comment,
358
395
  issue_try_comment,
359
396
  issue_close,
360
- issue_close_not_planned,
361
397
  label_ensure,
362
398
  issue_create_request,
363
399
  issue_create_with_label,
400
+ read_label_names,
364
401
  issue_apply_label,
365
402
  issue_add_label,
366
403
  issue_remove_label,
404
+ issue_clear_label,
367
405
  issue_add_blocked_by,
368
406
  issue_remove_blocked_by,
369
407
  }
@@ -4,6 +4,9 @@ import { BLOCKED_BY_COUNT_FIELD } from './git-gh-issue-rest'
4
4
  import { git_gh_issue_write } from './git-gh-issue-write'
5
5
 
6
6
  const NUMBER_AND_BODY_FIELDS = 'number,body'
7
+ // The label listing's fields. `stateReason` rides along on the same response: the epic auto-close
8
+ // reads `reopened` off it, so its sweep leaves an epic a person reopened to them (#4564).
9
+ const LABELLED_FIELDS = 'number,body,stateReason'
7
10
  // The backlog scan's fields. The title rides along because the pre-filing scan compares titles
8
11
  // and it costs nothing: the same listing request already carries it, so the
9
12
  // two consumers share one read rather than each making their own.
@@ -111,7 +114,7 @@ async function issue_search_body(term: string, limit: number): Promise<IssueList
111
114
  }
112
115
 
113
116
  async function issue_list_by_label(label: string, limit: number): Promise<IssueListOutcome> {
114
- return await issue_list({ json_fields: NUMBER_AND_BODY_FIELDS, limit, label })
117
+ return await issue_list({ json_fields: LABELLED_FIELDS, limit, label })
115
118
  }
116
119
 
117
120
  // The same filter with the fields the `auto-ok` pickup needs: it orders by
@@ -151,8 +154,9 @@ async function issue_list_by_label_in_repo(
151
154
  }
152
155
 
153
156
  // Every open issue with what `josh auto-ok:judge` judges it by — its labels and body — and `updatedAt`,
154
- // so the backlog driver's resident check reads an issue's comments again only once it has moved.
155
- const JUDGEMENT_FIELDS = 'number,title,body,labels,updatedAt'
157
+ // so the backlog driver's resident check reads an issue's comments again only once it has moved; and
158
+ // `author_association` and `user`, so an issue a third party filed is never judged.
159
+ const JUDGEMENT_FIELDS = 'number,title,body,labels,updatedAt,author_association,user'
156
160
 
157
161
  async function issue_list_open_for_judgement(limit: number): Promise<IssueListOutcome> {
158
162
  return await issue_list({ json_fields: JUDGEMENT_FIELDS, limit })
@@ -0,0 +1,89 @@
1
+ import { error_text } from '#scripts/lib/error-message'
2
+ import { json_value } from '#scripts/lib/json-value'
3
+ import { z } from 'zod'
4
+ import { FULL_PAGE_QUERY } from './git-gh-api-path'
5
+ import { git_gh_conditional, type ConditionalRead } from './git-gh-conditional'
6
+ import { git_gh_exec } from './git-gh-exec'
7
+
8
+ // The merge gate's per-poll reads, each sent with the ETag of this process's previous answer
9
+ // (joshuafolkken/kit#4550).
10
+ //
11
+ // **Never a pull request's detail**: GitHub computes its `mergeable_state` lazily, under an unchanged
12
+ // ETag, so a 304 would keep a stale state (joshuafolkken/kit#4589).
13
+ //
14
+ // **`pnpm josh followup` reads the same pull request every 10 seconds** while its checks run, and
15
+ // every lane waiting on its merge does so at once. A `304 Not Modified` does not count against the
16
+ // rate limit, so a poll that finds nothing changed costs only its pull detail read.
17
+ //
18
+ // **A listing is read one page at a time only while it fits in one.** A listing longer than a page is
19
+ // read through `--paginate --slurp` as before; the conditional read cannot page, and a partial
20
+ // listing would drop checks from the verdict.
21
+
22
+ const UNREADABLE_POLL_MESSAGE = 'gh api could not read a merge-gate poll'
23
+ const PAGE_SIZE = 100
24
+
25
+ interface KeptAnswer {
26
+ etag: string
27
+ body: string
28
+ }
29
+
30
+ const kept_by_path = new Map<string, KeptAnswer>()
31
+
32
+ const page_schema = z.object({ total_count: z.number() })
33
+
34
+ // gh's own failure rides along as the cause and in the message: the poll loop's warning prints the
35
+ // message alone, and a rate limit must read differently there from expired auth.
36
+ function unreadable(path: string, answer: ConditionalRead): Error {
37
+ const cause = answer.kind === 'unreadable' ? answer.cause : undefined
38
+ const reason = cause === undefined ? '' : `: ${error_text.message_of(cause)}`
39
+
40
+ return new Error(`${UNREADABLE_POLL_MESSAGE}: ${path}${reason}`, { cause })
41
+ }
42
+
43
+ function to_body(path: string, answer: ConditionalRead): string {
44
+ const previous = kept_by_path.get(path)
45
+
46
+ if (previous !== undefined && answer.kind === 'unchanged') return previous.body
47
+ if (answer.kind !== 'changed') throw unreadable(path, answer)
48
+ if (answer.etag !== undefined) kept_by_path.set(path, { etag: answer.etag, body: answer.body })
49
+
50
+ return answer.body
51
+ }
52
+
53
+ // The answer for `path`, or the previous one where GitHub says it has not changed. A failure throws,
54
+ // the contract the unconditional read had.
55
+ async function read(path: string): Promise<string> {
56
+ const answer = await git_gh_conditional.read_conditional(path, kept_by_path.get(path)?.etag)
57
+
58
+ return to_body(path, answer)
59
+ }
60
+
61
+ // A page that does not parse as a listing is not taken as the whole one: the full read answers it, and
62
+ // its own parser reports what it was.
63
+ function is_whole_listing(page: string): boolean {
64
+ const total = json_value.parse_with(page, page_schema)?.total_count
65
+
66
+ return total !== undefined && total <= PAGE_SIZE
67
+ }
68
+
69
+ // A commit listing in the `--slurp` shape — an array of pages — however it was read.
70
+ async function read_object_pages(path: string): Promise<string> {
71
+ const full_path = `${path}${FULL_PAGE_QUERY}`
72
+ const page = await read(full_path)
73
+
74
+ if (is_whole_listing(page)) return `[${page}]`
75
+
76
+ return await git_gh_exec.exec_gh_api({
77
+ path: full_path,
78
+ should_paginate: true,
79
+ should_slurp: true,
80
+ })
81
+ }
82
+
83
+ function forget_poll_reads(): void {
84
+ kept_by_path.clear()
85
+ }
86
+
87
+ const git_gh_poll_read = { UNREADABLE_POLL_MESSAGE, forget_poll_reads, read, read_object_pages }
88
+
89
+ export { git_gh_poll_read }
@@ -17,8 +17,10 @@ import { git_gh_pr_rest, type RestPull } from './git-gh-pr-rest'
17
17
  const GRAPHQL_PATH = 'graphql'
18
18
  const OPEN_PULLS_QUERY = `${git_gh_api_path.FULL_PAGE_QUERY}&state=open`
19
19
  const MISSING_NODE_ID_MESSAGE = 'gh api answered a pull request without a node_id'
20
+ // **`expectedHeadOid` binds the auto-merge to the commit the caller pushed** (#4036): GitHub then
21
+ // refuses it if the head has moved, rather than landing a commit nobody here pushed or checked.
20
22
  const ENABLE_AUTO_MERGE_MUTATION =
21
- 'mutation($id: ID!) { enablePullRequestAutoMerge(input: { pullRequestId: $id, mergeMethod: MERGE }) { clientMutationId } }'
23
+ 'mutation($id: ID!, $head: GitObjectID!) { enablePullRequestAutoMerge(input: { pullRequestId: $id, mergeMethod: MERGE, expectedHeadOid: $head }) { clientMutationId } }'
22
24
 
23
25
  interface OpenPull {
24
26
  number: number
@@ -26,13 +28,16 @@ interface OpenPull {
26
28
  has_auto_merge: boolean
27
29
  }
28
30
 
29
- async function pr_enable_auto_merge(branch_name: string): Promise<void> {
31
+ async function pr_enable_auto_merge(branch_name: string, head_sha: string): Promise<void> {
30
32
  const pull = await read_pull(await require_pr_number(branch_name))
31
33
  if (pull.node_id === undefined) throw new Error(MISSING_NODE_ID_MESSAGE)
32
34
 
33
35
  await git_gh_exec.exec_gh_api({
34
36
  path: GRAPHQL_PATH,
35
- body: JSON.stringify({ query: ENABLE_AUTO_MERGE_MUTATION, variables: { id: pull.node_id } }),
37
+ body: JSON.stringify({
38
+ query: ENABLE_AUTO_MERGE_MUTATION,
39
+ variables: { id: pull.node_id, head: head_sha },
40
+ }),
36
41
  })
37
42
  }
38
43
 
@@ -27,7 +27,7 @@ import { MERGED_STATE, to_gh_state } from './git-gh-rest-state'
27
27
  // branch name that says nothing about which repository holds it. Named once
28
28
  // because both sides of a pull request carry the same shape.
29
29
  const rest_repo_schema = z.looseObject({ full_name: z.string().optional() }).nullish()
30
- const rest_pull_side_schema = z.looseObject({ repo: rest_repo_schema })
30
+ const rest_pull_side_schema = z.looseObject({ ref: z.string().optional(), repo: rest_repo_schema })
31
31
 
32
32
  type RestPullSide = z.infer<typeof rest_pull_side_schema>
33
33
 
@@ -1,7 +1,9 @@
1
1
  import { FULL_PAGE_QUERY, git_gh_api_path } from './git-gh-api-path'
2
+ import { git_gh_branch_rules } from './git-gh-branch-rules'
2
3
  import { git_gh_exec } from './git-gh-exec'
3
- import { read_pull, require_pr_number } from './git-gh-pr-read'
4
- import type { RestPull } from './git-gh-pr-rest'
4
+ import { git_gh_poll_read } from './git-gh-poll-read'
5
+ import { require_pr_number } from './git-gh-pr-read'
6
+ import { git_gh_pr_rest, type RestPull } from './git-gh-pr-rest'
5
7
  import { git_gh_pr_review } from './git-gh-pr-review'
6
8
  import { git_gh_pr_rollup } from './git-gh-pr-rollup'
7
9
  import { to_gh_state } from './git-gh-rest-state'
@@ -19,17 +21,6 @@ import { to_gh_state } from './git-gh-rest-state'
19
21
 
20
22
  const NO_HEAD_SHA_MESSAGE = 'gh api answered a pull request with no head commit'
21
23
 
22
- // Both commit endpoints answer an *object* wrapping the listing, so `--paginate` alone would emit
23
- // one document per page and `JSON.parse` would reject the pair; `--slurp` wraps the pages in one
24
- // outer array instead (`git-gh-exec.ts` → `GhApiRequest`).
25
- async function read_object_pages(path: string): Promise<string> {
26
- return await git_gh_exec.exec_gh_api({
27
- path: `${path}${FULL_PAGE_QUERY}`,
28
- should_paginate: true,
29
- should_slurp: true,
30
- })
31
- }
32
-
33
24
  // The reviews endpoint answers a bare array, whose pages `gh` merges into one array on its own —
34
25
  // slurping it would produce `[[…],[…]]`, which the listing schema then rejects.
35
26
  async function read_array_pages(path: string): Promise<string> {
@@ -47,11 +38,12 @@ function read_head_sha(pull: RestPull): string {
47
38
  }
48
39
 
49
40
  // One pull request's rollup: the check runs and the status contexts, read from the head commit and
50
- // merged back into the single array `gh` answered with.
41
+ // merged back into the single array `gh` answered with. Both endpoints answer an *object* wrapping the
42
+ // listing, so their pages arrive slurped into one outer array (`git-gh-poll-read.ts`).
51
43
  async function read_status_check_rollup(commit_sha: string): Promise<Array<object>> {
52
44
  const [check_runs_json, status_json] = await Promise.all([
53
- read_object_pages(git_gh_api_path.commit_check_runs_api_path(commit_sha)),
54
- read_object_pages(git_gh_api_path.commit_status_api_path(commit_sha)),
45
+ git_gh_poll_read.read_object_pages(git_gh_api_path.commit_check_runs_api_path(commit_sha)),
46
+ git_gh_poll_read.read_object_pages(git_gh_api_path.commit_status_api_path(commit_sha)),
55
47
  ])
56
48
 
57
49
  return git_gh_pr_rollup.to_status_check_rollup({ check_runs_json, status_json })
@@ -69,10 +61,24 @@ async function pr_get_review_decision(pr_number: number): Promise<string> {
69
61
  // `git-pr-checks-eval.ts` compares strictly against: `MERGE_STATE_CLEAN` never matches a lower-case
70
62
  // `clean`, which would also take every pull request out of the CodeRabbit non-blocking exemption
71
63
  // keyed on `UNSTABLE`. The rule is shared with `to_pr_info` rather than written twice.
64
+ //
65
+ // **`headRefOid` is the commit the rollup was read from**, in `gh`'s spelling, so a merge can be bound
66
+ // to the head whose checks passed rather than to whatever the branch points at by then (#4036).
67
+ //
68
+ // **`requiredContexts` is the base branch's required checks** (`git-gh-branch-rules.ts`), which the
69
+ // merge gate reads to accept an `UNSTABLE` pull request held only by an optional check.
72
70
  async function build_checks_fields(pull: RestPull): Promise<Record<string, unknown>> {
71
+ const head_sha = read_head_sha(pull)
72
+ const [rollup, required_contexts] = await Promise.all([
73
+ read_status_check_rollup(head_sha),
74
+ git_gh_branch_rules.read_required_contexts(pull.base?.ref),
75
+ ])
76
+
73
77
  return {
74
- statusCheckRollup: await read_status_check_rollup(read_head_sha(pull)),
78
+ statusCheckRollup: rollup,
75
79
  mergeStateStatus: to_gh_state(pull.mergeable_state),
80
+ headRefOid: head_sha,
81
+ requiredContexts: required_contexts,
76
82
  }
77
83
  }
78
84
 
@@ -81,12 +87,19 @@ interface ResolvedPull {
81
87
  pull: RestPull
82
88
  }
83
89
 
84
- // The resolution and the detail read, which every path below needs and which the branch → number
85
- // memo in `git-gh-pr-read.ts` makes free after the first poll.
90
+ // The resolution and the detail read, which every path below needs. The branch → number memo in
91
+ // `git-gh-pr-read.ts` makes the first free after the first poll.
92
+ //
93
+ // **The detail is read without an ETag.** GitHub computes `mergeable_state` lazily and can change it
94
+ // under an unchanged ETag, so a 304 answered from the poll cache kept the gate reading a stale
95
+ // `blocked` on a pull request that had turned `clean` (joshuafolkken/kit#4589).
86
96
  async function resolve_pull(branch_name: string): Promise<ResolvedPull> {
87
97
  const pr_number = await require_pr_number(branch_name)
98
+ const json = await git_gh_exec.exec_gh_api({
99
+ path: git_gh_api_path.pull_api_path(String(pr_number)),
100
+ })
88
101
 
89
- return { pr_number, pull: await read_pull(pr_number) }
102
+ return { pr_number, pull: git_gh_pr_rest.parse_rest_pull(json) }
90
103
  }
91
104
 
92
105
  // Everything the snapshot carries except the review decision: three requests rather than four.
@@ -1,9 +1,9 @@
1
1
  import { pr_classification, type ReleaseClassification } from '#scripts/ci/pr-classification'
2
2
  import { git_command } from '#scripts/git/git-command'
3
3
  import { poll } from '#scripts/lib/poll'
4
- import { z } from 'zod'
5
4
  import { git_gh_api_path } from './git-gh-api-path'
6
5
  import { git_gh_exec } from './git-gh-exec'
6
+ import { gh_failure } from './git-gh-failure'
7
7
  import { git_gh_helpers } from './git-gh-helpers'
8
8
  import { git_gh_issue_write } from './git-gh-issue-write'
9
9
  import { forget_pr_numbers, git_gh_pr_read, read_pull, require_pr_number } from './git-gh-pr-read'
@@ -49,25 +49,27 @@ const MERGE_UNCONFIRMED_MESSAGE =
49
49
  'gh api could not read the pull request back after the merge request failed'
50
50
  const MERGE_READ_BACK_ATTEMPTS = 3
51
51
  const MERGE_READ_BACK_INTERVAL_MS = 1000
52
+ // `PUT pulls/{N}/merge` with a `sha` that is no longer the branch head.
53
+ const HEAD_MOVED_STATUS = 409
52
54
  const PR_NUMBER_PATTERN = /\/pull\/([1-9]\d*)$/u
53
- const LABELS_SEGMENT = '/labels'
54
- const PR_LABELS = z.array(z.object({ name: z.string() }))
55
55
 
56
+ // A pull request is an issue to the labels endpoint, so the write is the issue one: a failed answer
57
+ // is confirmed by reading the labels back before it is reported as a failed write.
56
58
  async function add_pr_classification(number: string, label: ReleaseClassification): Promise<void> {
57
- await git_gh_exec.exec_gh_api({
58
- path: `${git_gh_api_path.issue_api_path(number)}${LABELS_SEGMENT}`,
59
- body: JSON.stringify({ labels: [label] }),
60
- })
59
+ const write = await git_gh_issue_write.issue_apply_label(number, label)
60
+
61
+ if (!write.is_applied) throw new Error(write.reason)
61
62
  }
62
63
 
64
+ // Labels that could not be read are not "no classification": answering that would add a second
65
+ // classification beside the one a person already put on the pull request.
63
66
  async function pr_get_classification(
64
67
  branch_name: string,
65
68
  ): Promise<ReleaseClassification | undefined> {
66
69
  const number = await require_pr_number(branch_name)
67
- const response = await git_gh_exec.exec_gh_api({
68
- path: `${git_gh_api_path.issue_api_path(String(number))}${LABELS_SEGMENT}`,
69
- })
70
- const names = PR_LABELS.parse(JSON.parse(response)).map((label) => label.name.toLowerCase())
70
+ const labels = await git_gh_issue_write.read_label_names(String(number))
71
+ if (labels === undefined) throw new Error(`Unreadable labels on branch ${branch_name}`)
72
+ const names = labels.map((name) => name.toLowerCase())
71
73
  const selected = names.filter((name) => pr_classification.is_classification(name))
72
74
  if (selected.length === 0) return undefined
73
75
 
@@ -166,16 +168,25 @@ async function pr_update_body(branch_name: string, body: string): Promise<void>
166
168
  }
167
169
 
168
170
  // A merge moves the remembered detail read's state, so it is cleared first.
169
- async function put_merge(pr_number: number): Promise<void> {
171
+ //
172
+ // **`sha` binds the merge to the head the checks passed on** (#4036): without it GitHub merges
173
+ // whatever the branch points at, so a commit pushed after the gate went green would land unverified.
174
+ // A head that moved is answered 409 (`is_head_moved`).
175
+ async function put_merge(pr_number: number, head_sha: string): Promise<void> {
170
176
  forget_pr_numbers()
171
177
  await git_gh_exec.exec_gh_api({
172
178
  path: git_gh_api_path.pull_merge_api_path(String(pr_number)),
173
179
  method: PUT_METHOD,
174
- body: JSON.stringify({ merge_method: MERGE_COMMIT_METHOD }),
180
+ body: JSON.stringify({ merge_method: MERGE_COMMIT_METHOD, sha: head_sha }),
175
181
  timeout_ms: MERGE_REQUEST_TIMEOUT_MS,
176
182
  })
177
183
  }
178
184
 
185
+ // GitHub's answer to a merge whose `sha` is no longer the branch head.
186
+ function is_head_moved(error: unknown): boolean {
187
+ return gh_failure.failure_of(error)?.status === HEAD_MOVED_STATUS
188
+ }
189
+
179
190
  // `undefined` is "nobody read it", kept apart from the `false` that means "the pull request is not
180
191
  // merged". Folding the two would report an unread state as a settled answer.
181
192
  async function read_merge_state(pr_number: number): Promise<boolean | undefined> {
@@ -240,11 +251,11 @@ async function has_merge_landed(pr_number: number, merge_error: unknown): Promis
240
251
  // made by hand between the failure and the read leaves `followup` with exactly the same work to
241
252
  // finish. REST offers nothing that would tell the two apart without keeping the merge commit's SHA
242
253
  // across a request that never answered.
243
- async function pr_merge(branch_name: string): Promise<void> {
254
+ async function pr_merge(branch_name: string, head_sha: string): Promise<void> {
244
255
  const pr_number = await require_pr_number(branch_name)
245
256
 
246
257
  try {
247
- await put_merge(pr_number)
258
+ await put_merge(pr_number, head_sha)
248
259
  } catch (error) {
249
260
  if (!(await has_merge_landed(pr_number, error))) throw error
250
261
  }
@@ -259,6 +270,7 @@ const git_gh_pr = {
259
270
  pr_comment,
260
271
  pr_merge,
261
272
  pr_update_body,
273
+ is_head_moved,
262
274
  }
263
275
 
264
276
  export { git_gh_pr, MERGE_COMMIT_METHOD, MERGE_REQUEST_TIMEOUT_MS, MERGE_UNCONFIRMED_MESSAGE }
@@ -2,6 +2,7 @@ import {
2
2
  CHECK_STATUS_FAIL,
3
3
  CHECK_STATUS_MISSING,
4
4
  CHECK_STATUS_PASS,
5
+ CHECK_STATUS_PENDING,
5
6
  type PrStateSnapshot,
6
7
  type RollupCheck,
7
8
  } from './git-pr-checks-parse'
@@ -12,7 +13,7 @@ import {
12
13
  // to restore the old behavior. Revert once the fresh-context review subagent replaces it.
13
14
  const DEFAULT_REQUIRED_CHECKS = ['SonarQube']
14
15
  // The single source of the check name every CodeRabbit exemption is keyed on — the merge gate's
15
- // `is_unstable_only_from_coderabbit`, the look-ahead's `is_awaited_check`, and the fixtures the two
16
+ // `is_unstable_only_from_optional`, the look-ahead's `is_awaited_check`, and the fixtures the two
16
17
  // are tested from. A second literal spelling of it anywhere is how one of them silently stops
17
18
  // matching after CodeRabbit renames its context.
18
19
  const CODERABBIT_CHECK_NAME = 'CodeRabbit'
@@ -131,15 +132,46 @@ function is_coderabbit_rate_limited(check: RollupCheck): boolean {
131
132
  )
132
133
  }
133
134
 
134
- // Temporary: a pending or failing CodeRabbit check makes GitHub report UNSTABLE even
135
- // though CodeRabbit is not required. Accept that state only when CodeRabbit checks are the
136
- // sole non-passing ones — any other non-passing check keeps the gate strict.
137
- function is_unstable_only_from_coderabbit(snapshot: PrStateSnapshot): boolean {
135
+ function matches_any(check_name: string, required_names: ReadonlyArray<string>): boolean {
136
+ return required_names.some((required) => is_required_match(check_name, required))
137
+ }
138
+
139
+ // A check still running that the base branch's rules do not require — GitHub's default-setup
140
+ // `CodeQL`, which runs for about thirty minutes beside a six-minute CI (joshuafolkken/kit#4351).
141
+ // With no required context known nothing qualifies, so the gate waits for `CLEAN` as it always did.
142
+ function is_optional_pending(
143
+ check: RollupCheck,
144
+ required_contexts: ReadonlyArray<string>,
145
+ ): boolean {
146
+ if (required_contexts.length === 0 || check.status !== CHECK_STATUS_PENDING) return false
147
+
148
+ return !matches_any(check.name, required_contexts)
149
+ }
150
+
151
+ function is_every_context_passing(
152
+ checks: ReadonlyArray<RollupCheck>,
153
+ contexts: ReadonlyArray<string>,
154
+ ): boolean {
155
+ return contexts.every(
156
+ (context) => find_required_check(checks, context)?.status === CHECK_STATUS_PASS,
157
+ )
158
+ }
159
+
160
+ // GitHub reports UNSTABLE for a pull request whose required checks are green while a check outside
161
+ // them is pending or failing. Accept that state when every non-passing check is CodeRabbit's
162
+ // (temporary: CodeRabbit is not required) or an optional one still running, and every context the
163
+ // base branch requires has passed in the rollup itself — any other non-passing check keeps the gate
164
+ // strict. A failed optional check never reaches here: `collect_blocking_failures` ends the wait first.
165
+ function is_unstable_only_from_optional(snapshot: PrStateSnapshot): boolean {
138
166
  if (snapshot.merge_state_status !== MERGE_STATE_UNSTABLE) return false
167
+ const required_contexts = snapshot.required_contexts ?? []
139
168
  const non_passing = snapshot.rollup.filter((check) => check.status !== CHECK_STATUS_PASS)
140
169
  if (non_passing.length === 0) return false
170
+ const is_tolerated = non_passing.every(
171
+ (check) => is_coderabbit_check(check.name) || is_optional_pending(check, required_contexts),
172
+ )
141
173
 
142
- return non_passing.every((check) => is_coderabbit_check(check.name))
174
+ return is_tolerated && is_every_context_passing(snapshot.rollup, required_contexts)
143
175
  }
144
176
 
145
177
  function is_required_check(check_name: string): boolean {
@@ -169,7 +201,7 @@ function collect_blocking_failures(snapshot: PrStateSnapshot): Array<string> {
169
201
  function is_mergeable_state(snapshot: PrStateSnapshot): boolean {
170
202
  if (is_merge_state_clean(snapshot.merge_state_status)) return true
171
203
 
172
- return is_unstable_only_from_coderabbit(snapshot)
204
+ return is_unstable_only_from_optional(snapshot)
173
205
  }
174
206
 
175
207
  // The wait's own error text: naming the checks that failed is what turns a red `followup` into