@joshuafolkken/kit 1.1050.0 → 1.1128.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 (630) hide show
  1. package/.claude/settings.json +9 -8
  2. package/.claude/skills/epic-commands/SKILL.md +5 -7
  3. package/.claude/skills/workflow-commands/SKILL.md +20 -12
  4. package/.claude/skills/workflow-commands/background-commands.md +36 -84
  5. package/.claude/skills/workflow-commands/backlogrun-child.md +1 -1
  6. package/.claude/skills/workflow-commands/backlogrun-lanes.md +8 -6
  7. package/.claude/skills/workflow-commands/backlogrun-progress.md +30 -33
  8. package/.claude/skills/workflow-commands/backlogrun-steps.md +12 -12
  9. package/.claude/skills/workflow-commands/backlogrun.md +2 -2
  10. package/.claude/skills/workflow-commands/chain-rule.md +4 -2
  11. package/.claude/skills/workflow-commands/delegation.md +3 -3
  12. package/.claude/skills/workflow-commands/followup-reference.md +1 -1
  13. package/.claude/skills/workflow-commands/followup.md +7 -3
  14. package/.claude/skills/workflow-commands/fullrun-steps.md +3 -2
  15. package/.claude/skills/workflow-commands/fullrun.md +8 -6
  16. package/.claude/skills/workflow-commands/halfrun.md +19 -21
  17. package/.claude/skills/workflow-commands/issue-comments.md +1 -1
  18. package/.claude/skills/workflow-commands/issue-fold-existing.md +10 -10
  19. package/.claude/skills/workflow-commands/issue-scout.md +1 -1
  20. package/.claude/skills/workflow-commands/kickoff.md +9 -4
  21. package/.claude/skills/workflow-commands/latest-gate.md +8 -16
  22. package/.claude/skills/workflow-commands/needs-human-review.md +1 -1
  23. package/.claude/skills/workflow-commands/observation-filing.md +3 -3
  24. package/.claude/skills/workflow-commands/pre-gate-cut.md +4 -8
  25. package/.claude/skills/workflow-commands/prerequisite.md +1 -1
  26. package/.claude/skills/workflow-commands/prrun.md +36 -0
  27. package/.claude/skills/workflow-commands/retrospective.md +1 -1
  28. package/.claude/skills/workflow-commands/split-assessment.md +4 -18
  29. package/.claude/skills/workflow-commands/working-tree-hold.md +22 -2
  30. package/.codex/hooks.json +16 -20
  31. package/.github/actions/setup-node/action.yml +33 -0
  32. package/.github/actions/setup-pnpm/action.yml +93 -0
  33. package/.github/dependabot.yml +5 -1
  34. package/.github/workflows/auto-tag.yml +2 -3
  35. package/.github/workflows/ci.yml +31 -134
  36. package/.github/workflows/dependabot-auto-merge.yml +1 -0
  37. package/.github/workflows/pr-classification.yml +6 -44
  38. package/.github/workflows/production.yml +1 -0
  39. package/.github/workflows/publish.yml +43 -47
  40. package/.github/workflows/sonar-qube.yml +41 -4
  41. package/.pnpmfile.mjs +29 -0
  42. package/AGENTS.md +5 -2
  43. package/CLAUDE.md +33 -27
  44. package/GEMINI.md +5 -2
  45. package/README.md +66 -20
  46. package/SECURITY.md +37 -6
  47. package/cspell/index.yaml +6 -1
  48. package/dist/CLAUDE.basic.md +6 -6
  49. package/dist/CLAUDE.md +33 -27
  50. package/dist/CLAUDE.static.md +6 -6
  51. package/dist/config-merge/index.js +48 -12
  52. package/dist/hooks/batch-guard.js +4 -4
  53. package/dist/hooks/{chunk-7VPDUBRN.js → chunk-4JZDP5X5.js} +152 -155
  54. package/dist/hooks/{chunk-HJIISEAC.js → chunk-5SD2YM7Z.js} +5 -13
  55. package/dist/hooks/{chunk-NAS4C7GP.js → chunk-77J7IEQM.js} +2 -2
  56. package/dist/hooks/{chunk-DMQN45FN.js → chunk-7HVB7SZG.js} +3 -3
  57. package/dist/hooks/{chunk-RLDX5SOC.js → chunk-AIOIOMPX.js} +4413 -1970
  58. package/dist/hooks/{chunk-5BK3K7V4.js → chunk-M7QKEKWO.js} +873 -2049
  59. package/dist/hooks/{chunk-WQ4OSBSS.js → chunk-MKVGBQPA.js} +2 -2
  60. package/dist/hooks/{chunk-EJDX2TOB.js → chunk-NXYMNPUQ.js} +7 -88
  61. package/dist/hooks/{chunk-NJQOBE6L.js → chunk-QVLT52OV.js} +2 -7
  62. package/dist/hooks/{chunk-GQ7KP45M.js → chunk-XYUIQOW3.js} +2 -2
  63. package/dist/hooks/codex-hook-adapter.js +12 -48
  64. package/dist/hooks/duplicate-read-guard.js +5 -5
  65. package/dist/hooks/format-edited.js +2 -2
  66. package/dist/hooks/inputs.json +280 -0
  67. package/dist/hooks/investigation-guard.js +5 -5
  68. package/dist/hooks/pretool-guard.js +9 -9
  69. package/dist/hooks/session-lang.js +0 -1
  70. package/dist/hooks/stop-guard.js +192 -333
  71. package/dist/josh.js +240 -148
  72. package/dist/managed-marker/index.js +2 -1
  73. package/dist/version/index.js +70 -78
  74. package/eslint/rules/promise.js +5 -0
  75. package/eslint/rules/unicorn.js +3 -2
  76. package/package.json +26 -5
  77. package/pnpm-workspace.yaml +5 -7
  78. package/prompts/collaboration-workflow/glossary.md +17 -0
  79. package/prompts/collaboration-workflow/issue-citation.md +5 -5
  80. package/prompts/collaboration-workflow/issue-template.md +1 -1
  81. package/prompts/collaboration-workflow/operating-rules.md +5 -5
  82. package/prompts/collaboration-workflow/overview.md +13 -1
  83. package/prompts/collaboration-workflow/principles.md +9 -0
  84. package/prompts/collaboration-workflow/report-format.md +1 -1
  85. package/prompts/collaboration-workflow/residency.md +3 -3
  86. package/prompts/collaboration-workflow/rule-delivery.md +1 -1
  87. package/prompts/collaboration-workflow/turn-batching.md +3 -3
  88. package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
  89. package/prompts/collaboration-workflow/wip-cap.md +25 -22
  90. package/prompts/collaboration-workflow.md +6 -8
  91. package/prompts/review-rubric.md +1 -1
  92. package/prompts/review.md +3 -3
  93. package/prompts/sonar-hotspot-handling.md +11 -3
  94. package/prompts/testing-guide.md +3 -3
  95. package/scripts/adopt/adopt-toolkits.ts +0 -2
  96. package/scripts/adopt/adopt.ts +0 -2
  97. package/scripts/agent/agent-argv.ts +0 -2
  98. package/scripts/agent/agent-diagnostics.ts +1 -1
  99. package/scripts/agent/agent-role-profile.ts +0 -7
  100. package/scripts/agent/claude-agent-argv.ts +0 -2
  101. package/scripts/agent/codex-agent-argv.ts +1 -1
  102. package/scripts/agent/codex-hooks.ts +92 -0
  103. package/scripts/agent/interactive-ask.ts +1 -1
  104. package/scripts/auto-ok/auto-ok-cli.ts +6 -16
  105. package/scripts/backlog/backlog-arrival.ts +30 -10
  106. package/scripts/backlog/backlog-budget-cli.ts +15 -16
  107. package/scripts/backlog/backlog-budget.ts +0 -2
  108. package/scripts/backlog/backlog-defect-priority.ts +2 -2
  109. package/scripts/backlog/backlog-drive-cli.ts +10 -8
  110. package/scripts/backlog/backlog-drive-named-offer.ts +16 -3
  111. package/scripts/backlog/backlog-drive-named.ts +2 -1
  112. package/scripts/backlog/backlog-drive.ts +76 -16
  113. package/scripts/backlog/backlog-named.ts +0 -3
  114. package/scripts/backlog/backlog-next.ts +9 -15
  115. package/scripts/backlog/backlog-offer-cli.ts +6 -19
  116. package/scripts/backlog/backlog-plan-cli.ts +1 -7
  117. package/scripts/backlog/backlog-plan.ts +30 -19
  118. package/scripts/backlog/backlog-pool.ts +3 -6
  119. package/scripts/backlog/backlog-rank.ts +2 -2
  120. package/scripts/backlog/backlog-ready.ts +39 -10
  121. package/scripts/backlog/backlog-scope.ts +1 -3
  122. package/scripts/backlog/backlog-stalled-detect.ts +2 -2
  123. package/scripts/backlog/backlog-stalled.ts +0 -1
  124. package/scripts/backlog/backlog-waves.ts +5 -2
  125. package/scripts/behavior/behavior-cli.ts +1 -1
  126. package/scripts/build/build-codex-hooks.ts +26 -0
  127. package/scripts/build/build-hooks.ts +85 -9
  128. package/scripts/build/hook-bundle-stamp.ts +111 -0
  129. package/scripts/cases/cases-cli.ts +1 -1
  130. package/scripts/cases/cases-logic.ts +1 -1
  131. package/scripts/ci/composite-actions.ts +30 -0
  132. package/scripts/ci/pr-classification.ts +3 -3
  133. package/scripts/claude/workflow-destination.ts +10 -1
  134. package/scripts/clone/clone-fingerprint.ts +0 -1
  135. package/scripts/clone/clone-scan-cli.ts +1 -1
  136. package/scripts/clone/clone-scan.ts +1 -1
  137. package/scripts/config-merge/json-format.ts +0 -1
  138. package/scripts/config-merge/parse-jsonc.ts +33 -3
  139. package/scripts/config-merge/patch-json-key.ts +13 -6
  140. package/scripts/config-merge/patch-yaml-list.ts +1 -1
  141. package/scripts/cost-runtime/codex-usage.ts +2 -9
  142. package/scripts/cost-runtime/cost-attribute.ts +0 -1
  143. package/scripts/cost-runtime/cost-cli.ts +3 -10
  144. package/scripts/cost-runtime/cost-corpus.ts +0 -2
  145. package/scripts/cost-runtime/cost-format.ts +0 -3
  146. package/scripts/cost-runtime/cost-pricing.ts +0 -1
  147. package/scripts/cost-runtime/cost-tokens.ts +0 -1
  148. package/scripts/delegation/delegation-cli.ts +1 -1
  149. package/scripts/delegation/delegation-policy.ts +0 -1
  150. package/scripts/delegation/duplicate-read-guard.ts +0 -8
  151. package/scripts/delegation/fanout-cli.ts +1 -1
  152. package/scripts/delegation/fanout.ts +0 -2
  153. package/scripts/delegation/investigation-reads.ts +1 -164
  154. package/scripts/discovery/repo-map-logic.ts +0 -1
  155. package/scripts/discovery/repo-party-cli.ts +1 -1
  156. package/scripts/doctor/doctor-consumer.ts +6 -10
  157. package/scripts/doctor/doctor-io.ts +9 -13
  158. package/scripts/doctor/doctor-logic.ts +0 -4
  159. package/scripts/doctor/doctor.ts +14 -9
  160. package/scripts/document/backlogrun-parent-read-set.ts +12 -1
  161. package/scripts/document/document-byte-budget.ts +5 -5
  162. package/scripts/document/document-byte-check.ts +0 -1
  163. package/scripts/document/document-read-cli.ts +0 -2
  164. package/scripts/document/document-section-cli.ts +1 -1
  165. package/scripts/document/document-section.ts +0 -3
  166. package/scripts/document/edit-files-cli.ts +0 -1
  167. package/scripts/document/entry-read-budget.ts +21 -7
  168. package/scripts/document/entry-read-set.ts +32 -8
  169. package/scripts/document/lane-child-read-set.ts +8 -6
  170. package/scripts/document/read-files-cli.ts +0 -4
  171. package/scripts/document/read-set-cli.ts +0 -2
  172. package/scripts/document/read-set-point-of-use.ts +9 -3
  173. package/scripts/document/read-set-pricing.ts +0 -1
  174. package/scripts/document/read-set-trim.ts +4 -2
  175. package/scripts/epic/epic-add.ts +1 -1
  176. package/scripts/epic/epic-audit-cli.ts +1 -4
  177. package/scripts/epic/epic-audit-orphans.ts +1 -3
  178. package/scripts/epic/epic-audit-rationale.ts +0 -1
  179. package/scripts/epic/epic-audit-report.ts +0 -2
  180. package/scripts/epic/epic-audit.ts +8 -22
  181. package/scripts/epic/epic-bundle-cli.ts +1 -1
  182. package/scripts/epic/epic-bundle-evidence.ts +0 -1
  183. package/scripts/epic/epic-bundle-referenced.ts +1 -5
  184. package/scripts/epic/epic-bundle.ts +0 -4
  185. package/scripts/epic/epic-busy.ts +4 -5
  186. package/scripts/epic/epic-candidate-confirm.ts +0 -5
  187. package/scripts/epic/epic-classify.ts +2 -2
  188. package/scripts/epic/epic-cli-argv.ts +0 -1
  189. package/scripts/epic/epic-close-comment.ts +1 -1
  190. package/scripts/epic/epic-close.ts +5 -2
  191. package/scripts/epic/epic-cross-repo.ts +2 -4
  192. package/scripts/epic/epic-decision.ts +0 -1
  193. package/scripts/epic/epic-fetch.ts +2 -2
  194. package/scripts/epic/epic-index.ts +2 -3
  195. package/scripts/epic/epic-issue.ts +1 -15
  196. package/scripts/epic/epic-lane-offer.ts +9 -8
  197. package/scripts/epic/epic-nested.ts +1 -1
  198. package/scripts/epic/epic-next-read.ts +1 -3
  199. package/scripts/epic/epic-next-views.ts +0 -1
  200. package/scripts/epic/epic-next.ts +1 -10
  201. package/scripts/epic/epic-parse.ts +0 -1
  202. package/scripts/epic/epic-promote.ts +0 -9
  203. package/scripts/epic/epic-rank.ts +2 -2
  204. package/scripts/epic/epic-read.ts +1 -2
  205. package/scripts/epic/epic-reconcile.ts +1 -1
  206. package/scripts/epic/epic-reference.ts +1 -13
  207. package/scripts/epic/epic-relation-recheck.ts +1 -1
  208. package/scripts/epic/epic-relations.ts +1 -1
  209. package/scripts/epic/epic-remove.ts +1 -1
  210. package/scripts/epic/epic-report.ts +0 -1
  211. package/scripts/epic/epic-run.ts +2 -3
  212. package/scripts/epic/epic-shape.ts +1 -1
  213. package/scripts/epic/epic-solo-stale.ts +107 -0
  214. package/scripts/epic/epic-solo.ts +3 -2
  215. package/scripts/epic/epic-triage.ts +1 -1
  216. package/scripts/epic/epic-validate.ts +1 -1
  217. package/scripts/epic/epic.ts +1 -1
  218. package/scripts/exports/unused-members-cli.ts +53 -0
  219. package/scripts/{git → followup}/followup-issue-number.ts +1 -6
  220. package/scripts/{git → followup}/git-followup-cleanup.ts +2 -1
  221. package/scripts/{git → followup}/git-followup-finish.ts +1 -3
  222. package/scripts/{git → followup}/git-followup-flush.ts +2 -2
  223. package/scripts/{git → followup}/git-followup-issue-close.ts +2 -2
  224. package/scripts/{git → followup}/git-followup-label.ts +4 -4
  225. package/scripts/followup/git-followup-merged.ts +112 -0
  226. package/scripts/{git → followup}/git-followup-pending.ts +1 -1
  227. package/scripts/{git → followup}/git-followup-workflow.ts +19 -11
  228. package/scripts/{git → followup}/git-pr-followup-wrapup.ts +9 -3
  229. package/scripts/{git → followup}/git-pr-followup.ts +53 -16
  230. package/scripts/gate/core-budget.ts +3 -9
  231. package/scripts/gate/gate-plan.ts +7 -4
  232. package/scripts/gate/gate-report.ts +0 -6
  233. package/scripts/gate/gate-tree.ts +1 -1
  234. package/scripts/gate/pre-commit-type-check.ts +0 -6
  235. package/scripts/gate/project-checks.ts +7 -8
  236. package/scripts/gate/scoped-green.ts +0 -1
  237. package/scripts/gate/type-check-step.ts +1 -1
  238. package/scripts/gate/verification-gate.ts +0 -2
  239. package/scripts/gh/fix-gh-packages.ts +15 -12
  240. package/scripts/gh/gh-spawn.ts +2 -2
  241. package/scripts/{git → gh}/git-ai-review-scan.ts +1 -5
  242. package/scripts/{git → gh}/git-gh-check.ts +2 -1
  243. package/scripts/{git → gh}/git-gh-exec.ts +1 -1
  244. package/scripts/{git → gh}/git-gh-failure.ts +1 -1
  245. package/scripts/{git → gh}/git-gh-helpers.ts +0 -1
  246. package/scripts/{git → gh}/git-gh-issue-list.ts +13 -10
  247. package/scripts/{git → gh}/git-gh-issue-read.ts +1 -1
  248. package/scripts/{git → gh}/git-gh-issue-rest.ts +6 -3
  249. package/scripts/{git → gh}/git-gh-issue-write.ts +4 -1
  250. package/scripts/{git → gh}/git-gh-pr-auto-merge.ts +4 -1
  251. package/scripts/{git → gh}/git-gh-pr-read.ts +24 -0
  252. package/scripts/{git → gh}/git-gh-pr-rest.ts +5 -2
  253. package/scripts/{git → gh}/git-gh-pr-review.ts +2 -2
  254. package/scripts/{git → gh}/git-gh-pr-rollup.ts +1 -3
  255. package/scripts/{git → gh}/git-gh-pr.ts +3 -1
  256. package/scripts/{git → gh}/git-pr-ai-review.ts +2 -5
  257. package/scripts/{git → gh}/git-pr-checks-eval.ts +0 -10
  258. package/scripts/{git → gh}/git-pr-checks-parse.ts +4 -20
  259. package/scripts/{git → gh}/git-pr-checks.ts +2 -1
  260. package/scripts/{git → gh}/git-pr-coderabbit.ts +2 -5
  261. package/scripts/{git → gh}/git-pr-confirmation.ts +1 -3
  262. package/scripts/{git → gh}/git-pr-managed-config.ts +2 -3
  263. package/scripts/{git → gh}/git-pr.ts +3 -3
  264. package/scripts/git/changed-file-scope.ts +0 -1
  265. package/scripts/git/git-branch.ts +3 -6
  266. package/scripts/git/git-command.ts +6 -1
  267. package/scripts/git/git-commit.ts +1 -1
  268. package/scripts/git/git-common-directory.ts +80 -24
  269. package/scripts/git/git-error.ts +66 -9
  270. package/scripts/git/git-issue.ts +1 -1
  271. package/scripts/git/git-preflight.ts +2 -2
  272. package/scripts/git/git-prompt.ts +6 -31
  273. package/scripts/git/git-push.ts +1 -1
  274. package/scripts/git/git-spawn-sync.ts +65 -0
  275. package/scripts/git/git-spawn.ts +5 -4
  276. package/scripts/git/git-staging.ts +1 -0
  277. package/scripts/git/git-status.ts +1 -1
  278. package/scripts/git/git-workflow.ts +1 -1
  279. package/scripts/git/gone-branch.ts +1 -0
  280. package/scripts/git/listing-cutoff.ts +1 -1
  281. package/scripts/git/main-merge.ts +1 -1
  282. package/scripts/git/main-sync.ts +19 -1
  283. package/scripts/git/parse-json-array.ts +0 -3
  284. package/scripts/git/repository-lock.ts +16 -16
  285. package/scripts/git/{git-stash.ts → stash/git-stash.ts} +1 -1
  286. package/scripts/git/{stash-pop-args.ts → stash/stash-pop-args.ts} +2 -7
  287. package/scripts/git/{stash-pop-cli.ts → stash/stash-pop-cli.ts} +0 -1
  288. package/scripts/git/{stash-sweep-lock.ts → stash/stash-sweep-lock.ts} +3 -3
  289. package/scripts/hooks/codex-hook-adapter.ts +0 -1
  290. package/scripts/hooks/edited-cspell.ts +1 -1
  291. package/scripts/hooks/format-edited-file.ts +2 -0
  292. package/scripts/hooks/pre-push-unit.ts +0 -4
  293. package/scripts/hooks/pretool-guard.ts +22 -4
  294. package/scripts/hooks/reserved-run.ts +1 -1
  295. package/scripts/hooks/step-zero-notice.ts +76 -0
  296. package/scripts/hooks/stop-guard.ts +47 -21
  297. package/scripts/init/claude-plugin-config.ts +4 -5
  298. package/scripts/init/hook-command-rewrite.ts +16 -8
  299. package/scripts/init/hook-launch.ts +41 -15
  300. package/scripts/init/init-basic.ts +2 -5
  301. package/scripts/init/init-file-action.ts +54 -0
  302. package/scripts/init/init-logic-migrate.ts +35 -17
  303. package/scripts/init/init-logic-secretlint.ts +1 -1
  304. package/scripts/init/init-logic.ts +10 -19
  305. package/scripts/init/init.ts +11 -71
  306. package/scripts/init/kit-written-paths.ts +2 -0
  307. package/scripts/init/project-profile.ts +9 -17
  308. package/scripts/init/start-exec.ts +1 -1
  309. package/scripts/init/start-setup-pr.ts +6 -6
  310. package/scripts/init/start-steps.ts +3 -1
  311. package/scripts/issue/behavior-change-lint.ts +0 -1
  312. package/scripts/issue/defect-rate-cli.ts +64 -23
  313. package/scripts/issue/defect-rate.ts +1 -2
  314. package/scripts/{git → issue}/git-next-issues.ts +3 -3
  315. package/scripts/issue/issue-backlinks-cli.ts +1 -5
  316. package/scripts/issue/issue-backlinks.ts +7 -14
  317. package/scripts/issue/issue-cite-cli.ts +2 -6
  318. package/scripts/issue/issue-cite.ts +12 -8
  319. package/scripts/issue/issue-classification.ts +1 -9
  320. package/scripts/issue/issue-closing-pr.ts +4 -4
  321. package/scripts/issue/issue-comment-cli.ts +2 -2
  322. package/scripts/issue/issue-file-cli.ts +5 -5
  323. package/scripts/issue/issue-file.ts +7 -14
  324. package/scripts/issue/issue-fold-cli.ts +1 -1
  325. package/scripts/issue/issue-fold-existing-cli.ts +1 -1
  326. package/scripts/{git → issue}/issue-labels.ts +8 -0
  327. package/scripts/issue/issue-lint-cli.ts +1 -1
  328. package/scripts/issue/issue-merged.ts +2 -2
  329. package/scripts/{git → issue}/issue-rank.ts +1 -1
  330. package/scripts/issue/issue-read-cli.ts +8 -47
  331. package/scripts/issue/issue-read.ts +0 -2
  332. package/scripts/issue/issue-report-failures.ts +80 -0
  333. package/scripts/issue/issue-scout-cli.ts +1 -7
  334. package/scripts/issue/issue-scout-closed.ts +2 -2
  335. package/scripts/issue/issue-scout.ts +0 -2
  336. package/scripts/issue/issue-state-cli.ts +5 -46
  337. package/scripts/issue/issue-state.ts +1 -5
  338. package/scripts/issue/markdown-section.ts +21 -6
  339. package/scripts/issue/measure-rerun-cli.ts +74 -15
  340. package/scripts/issue/reproduction-measure.ts +1 -1
  341. package/scripts/josh/cli-body.ts +1 -1
  342. package/scripts/josh/file-map-stamp.ts +0 -3
  343. package/scripts/josh/josh-command-map.ts +2 -0
  344. package/scripts/josh/josh-commands-ai.ts +9 -102
  345. package/scripts/josh/josh-commands-backlog.ts +5 -1
  346. package/scripts/josh/josh-commands-development.ts +8 -1
  347. package/scripts/josh/josh-commands-issue.ts +2 -2
  348. package/scripts/josh/josh-commands-maintenance.ts +7 -0
  349. package/scripts/josh/josh-commands-project.ts +7 -1
  350. package/scripts/josh/josh-commands-run.ts +114 -0
  351. package/scripts/josh/josh-commands-versioning.ts +8 -0
  352. package/scripts/josh/josh-commands-workflow.ts +3 -3
  353. package/scripts/josh/path-decision.ts +0 -3
  354. package/scripts/josh/process-owner.ts +16 -0
  355. package/scripts/josh/run-github-prerequisite.ts +3 -6
  356. package/scripts/josh/session-language-cli.ts +0 -1
  357. package/scripts/lane/lane-await.ts +46 -19
  358. package/scripts/lane/lane-capacity.ts +6 -3
  359. package/scripts/lane/lane-child-invocation.ts +20 -7
  360. package/scripts/lane/lane-cli.ts +1 -4
  361. package/scripts/lane/lane-close.ts +5 -4
  362. package/scripts/lane/lane-dispatch.ts +3 -4
  363. package/scripts/lane/lane-environment.ts +0 -9
  364. package/scripts/lane/lane-handoff.ts +38 -0
  365. package/scripts/lane/lane-launch-cli.ts +31 -27
  366. package/scripts/lane/lane-open.ts +0 -3
  367. package/scripts/lane/lane-output.ts +0 -1
  368. package/scripts/lane/lane-registry.ts +9 -0
  369. package/scripts/lane/openai-lane-ship.ts +2 -0
  370. package/scripts/lane/openai-lane-supervisor-decision.ts +2 -1
  371. package/scripts/lane/openai-lane-supervisor.ts +6 -4
  372. package/scripts/lane/openai-review-broker.ts +7 -1
  373. package/scripts/lib/bounded-pool.ts +1 -0
  374. package/scripts/lib/cli-flags.ts +31 -2
  375. package/scripts/lib/error-message.ts +12 -1
  376. package/scripts/lib/json-value.ts +5 -4
  377. package/scripts/lib/poll.ts +3 -1
  378. package/scripts/lib/timed-fetch.ts +15 -0
  379. package/scripts/lib/timeouts.ts +13 -0
  380. package/scripts/{yaml → lib}/yaml-document.ts +3 -1
  381. package/scripts/{bytes → lines}/bytes-command.ts +0 -2
  382. package/scripts/lines/line-targets.ts +0 -11
  383. package/scripts/lines/lines-command.ts +5 -4
  384. package/scripts/lint/lint-related-scope.ts +0 -1
  385. package/scripts/lint/lint-related.ts +1 -1
  386. package/scripts/{git → notify}/telegram-notify.ts +2 -2
  387. package/scripts/{git → notify}/telegram-test.ts +4 -4
  388. package/scripts/observations/observation-ledger-home.ts +0 -1
  389. package/scripts/observations/observation-ledger-line.ts +0 -1
  390. package/scripts/observations/observation-ledger-migrate.ts +1 -1
  391. package/scripts/observations/observations-flush-landing.ts +3 -3
  392. package/scripts/observations/observations-flush.ts +2 -2
  393. package/scripts/overrides/lockfile-overrides.ts +1 -1
  394. package/scripts/overrides/overrides-logic.ts +1 -1
  395. package/scripts/package/package-scout-cli.ts +2 -7
  396. package/scripts/package/package-scout.ts +0 -2
  397. package/scripts/propagate/propagate-git-failure.ts +0 -1
  398. package/scripts/propagate/propagate-git.ts +3 -10
  399. package/scripts/propagate/propagate-publish.ts +2 -3
  400. package/scripts/propagate/propagate-run.ts +0 -2
  401. package/scripts/propagate/propagate-steps.ts +3 -5
  402. package/scripts/propagate/propagate-targets.ts +0 -4
  403. package/scripts/propagate/propagate.ts +0 -4
  404. package/scripts/refactor/import-graph.ts +0 -1
  405. package/scripts/refactor/refactor-lint.ts +0 -2
  406. package/scripts/refactor/refactor-scan.ts +2 -2
  407. package/scripts/refactor/refactor-targets.ts +0 -1
  408. package/scripts/registry-migration/migrate-logic.ts +28 -21
  409. package/scripts/registry-migration/migrate.ts +25 -14
  410. package/scripts/release/github-release-cli.ts +19 -6
  411. package/scripts/release/github-release-environment.ts +46 -0
  412. package/scripts/release/github-release.ts +151 -94
  413. package/scripts/release/release-history.ts +0 -1
  414. package/scripts/release/release-plan.ts +0 -1
  415. package/scripts/release/release-publish.ts +38 -5
  416. package/scripts/release/release-scope-cli.ts +1 -2
  417. package/scripts/release/release-tag.ts +2 -4
  418. package/scripts/release/release-worktree.ts +97 -2
  419. package/scripts/repo/auto-merge-setting-logic.ts +1 -4
  420. package/scripts/repo/repo-setting.ts +1 -1
  421. package/scripts/repo/repository-labels.ts +3 -3
  422. package/scripts/repo/required-checks-logic.ts +206 -0
  423. package/scripts/repo/required-checks-report.ts +71 -0
  424. package/scripts/repo/ruleset-check-cli.ts +53 -0
  425. package/scripts/repo/ruleset-check.ts +147 -0
  426. package/scripts/report/report-lint-cli.ts +0 -4
  427. package/scripts/review/disposition-cli.ts +1 -1
  428. package/scripts/review/live-evidence.ts +1 -1
  429. package/scripts/review/review-attest-cli.ts +0 -6
  430. package/scripts/review/review-attest.ts +4 -16
  431. package/scripts/review/review-brief-cli.ts +23 -6
  432. package/scripts/review/review-brief.ts +21 -8
  433. package/scripts/review/review-checkout.ts +3 -2
  434. package/scripts/review/review-diff-parts.ts +89 -0
  435. package/scripts/review/review-diff-write.ts +97 -0
  436. package/scripts/review/review-finding-ledger.ts +0 -1
  437. package/scripts/review/review-record-cli.ts +10 -17
  438. package/scripts/review/review-record.ts +0 -1
  439. package/scripts/review/review-round2-cli.ts +1 -1
  440. package/scripts/review/review-stamps.ts +0 -3
  441. package/scripts/review/review-tree.ts +14 -2
  442. package/scripts/rules/decision-oracle-stage.ts +18 -0
  443. package/scripts/rules/decision-oracle.ts +10 -7
  444. package/scripts/rules/delivered-rules.ts +9 -1
  445. package/scripts/rules/destructive-command.ts +119 -0
  446. package/scripts/rules/direct-filing.ts +1 -1
  447. package/scripts/rules/early-heartbeat.ts +4 -3
  448. package/scripts/rules/file-body.ts +0 -3
  449. package/scripts/rules/filing-cap.ts +0 -2
  450. package/scripts/rules/gh-api.ts +7 -2
  451. package/scripts/rules/git-argv.ts +18 -7
  452. package/scripts/rules/git-force.ts +0 -2
  453. package/scripts/rules/implementation-cut.ts +0 -1
  454. package/scripts/rules/index-guard.ts +71 -0
  455. package/scripts/rules/issue-citation.ts +50 -25
  456. package/scripts/rules/lane-background.ts +15 -7
  457. package/scripts/rules/lane-park.ts +22 -6
  458. package/scripts/rules/last-prompt.ts +1 -0
  459. package/scripts/rules/oracle-consulted.ts +1 -1
  460. package/scripts/rules/oracle-firing.ts +1 -0
  461. package/scripts/rules/oracle-list-cli.ts +0 -3
  462. package/scripts/rules/permission-guards.ts +14 -0
  463. package/scripts/rules/protected-files.ts +74 -0
  464. package/scripts/rules/reply-language.ts +1 -1
  465. package/scripts/rules/rule-body-guard.ts +0 -3
  466. package/scripts/rules/rule-value-cli.ts +0 -1
  467. package/scripts/rules/shell-body-trigger.ts +0 -1
  468. package/scripts/rules/shell-segments.ts +0 -1
  469. package/scripts/rules/stop-rules.ts +20 -9
  470. package/scripts/rules/tail-commands.ts +1 -1
  471. package/scripts/rules/test-declared-commit.ts +1 -1
  472. package/scripts/rules/third-party-write.ts +0 -1
  473. package/scripts/rules/worktree-guard.ts +26 -9
  474. package/scripts/run/run-carry-args.ts +8 -12
  475. package/scripts/run/run-carry-cli.ts +0 -2
  476. package/scripts/run/run-carry-stash.ts +2 -2
  477. package/scripts/run/run-carry-streak.ts +1 -1
  478. package/scripts/run/run-cut-args.ts +1 -6
  479. package/scripts/run/run-cut-cli.ts +0 -7
  480. package/scripts/run/run-cut.ts +8 -54
  481. package/scripts/run/run-ending-cli.ts +2 -6
  482. package/scripts/run/run-ending.ts +1 -4
  483. package/scripts/run/run-entry-cli.ts +133 -25
  484. package/scripts/run/run-entry-stop.ts +104 -0
  485. package/scripts/run/run-entry.ts +0 -1
  486. package/scripts/run/run-event-cli.ts +0 -2
  487. package/scripts/run/run-event-follow.ts +1 -0
  488. package/scripts/run/run-event-render.ts +1 -1
  489. package/scripts/run/run-event-scope.ts +53 -4
  490. package/scripts/run/run-event-stream-emit.ts +7 -2
  491. package/scripts/run/run-event-stream.ts +0 -3
  492. package/scripts/run/run-event-watch.ts +1 -0
  493. package/scripts/run/run-halfrun-resume.ts +20 -7
  494. package/scripts/run/run-headless.ts +2 -2
  495. package/scripts/run/run-hold-cli.ts +33 -10
  496. package/scripts/run/run-hold.ts +29 -6
  497. package/scripts/run/run-issue-number.ts +1 -1
  498. package/scripts/run/run-liveness-cli.ts +2 -6
  499. package/scripts/run/run-liveness.ts +2 -3
  500. package/scripts/run/run-merge-cli.ts +7 -23
  501. package/scripts/run/run-merge-steps.ts +5 -5
  502. package/scripts/run/run-merge.ts +1 -1
  503. package/scripts/run/run-next-cli.ts +1 -1
  504. package/scripts/run/run-parent-cut-hook.ts +4 -2
  505. package/scripts/run/run-preflight.ts +2 -9
  506. package/scripts/run/run-prep-cli.ts +6 -3
  507. package/scripts/run/run-prep-locate.ts +1 -1
  508. package/scripts/run/run-progress-args.ts +20 -4
  509. package/scripts/run/run-progress-cli.ts +35 -36
  510. package/scripts/run/run-progress-clock.ts +10 -35
  511. package/scripts/run/run-progress-config.ts +0 -4
  512. package/scripts/run/run-progress-read.ts +1 -2
  513. package/scripts/run/run-progress.ts +1 -2
  514. package/scripts/run/run-prrun-resume.ts +117 -0
  515. package/scripts/run/run-report-cli.ts +1 -2
  516. package/scripts/run/run-report.ts +0 -1
  517. package/scripts/run/run-retrospective.ts +1 -1
  518. package/scripts/run/run-review-cli.ts +0 -3
  519. package/scripts/run/run-review-steps.ts +2 -0
  520. package/scripts/run/run-review.ts +0 -2
  521. package/scripts/run/run-ship-cli.ts +29 -19
  522. package/scripts/run/run-ship-detach.ts +1 -0
  523. package/scripts/run/run-ship-next.ts +106 -0
  524. package/scripts/run/run-ship-preflight.ts +1 -1
  525. package/scripts/run/run-ship-probe.ts +4 -1
  526. package/scripts/run/run-ship-return.ts +8 -3
  527. package/scripts/run/run-ship-review-steps.ts +18 -4
  528. package/scripts/run/run-ship-review.ts +11 -0
  529. package/scripts/run/run-ship-scoped.ts +1 -0
  530. package/scripts/run/run-ship-steps.ts +1 -1
  531. package/scripts/run/run-ship.ts +0 -1
  532. package/scripts/run/run-stage-read.ts +62 -0
  533. package/scripts/run/run-stage.ts +160 -0
  534. package/scripts/run/run-status-cli.ts +3 -16
  535. package/scripts/run/run-step-cli.ts +21 -14
  536. package/scripts/run/run-step.ts +1 -1
  537. package/scripts/run/run-stop-notify.ts +1 -3
  538. package/scripts/run/run-stranded-cli.ts +0 -4
  539. package/scripts/run/run-stranded-detect.ts +2 -2
  540. package/scripts/run/run-tail-cli.ts +17 -11
  541. package/scripts/run/run-tail.ts +2 -0
  542. package/scripts/run/run-tidy-lanes.ts +6 -2
  543. package/scripts/run/run-tidy-stashes.ts +12 -12
  544. package/scripts/run/run-wake-cli.ts +4 -13
  545. package/scripts/run/run-wake-loop.ts +2 -2
  546. package/scripts/run/run-wake.ts +2 -4
  547. package/scripts/run/run-watcher-guard-cli.ts +0 -4
  548. package/scripts/run/run-watcher-guard.ts +18 -12
  549. package/scripts/run/run-watcher-hook.ts +1 -1
  550. package/scripts/safe-chain/ci-installer-pin.ts +11 -5
  551. package/scripts/safe-chain/pack-hook.ts +92 -0
  552. package/scripts/safe-chain/project-config.ts +1 -1
  553. package/scripts/security/security-audit-provision-logic.ts +0 -1
  554. package/scripts/security/security-audit-provision.ts +3 -2
  555. package/scripts/security/security-audit.ts +0 -1
  556. package/scripts/security/security-updates-logic.ts +0 -1
  557. package/scripts/sonar/sonar-hotspots-cli.ts +10 -52
  558. package/scripts/sonar/sonar-hotspots.ts +0 -1
  559. package/scripts/sonar/sonar-new-code-cli.ts +150 -0
  560. package/scripts/sonar/sonar-new-code.ts +79 -0
  561. package/scripts/sonar/sonar-project.ts +97 -0
  562. package/scripts/split/split-assess-cli.ts +1 -1
  563. package/scripts/split/split-assess.ts +2 -5
  564. package/scripts/sync/managed-config-scope-cli.ts +1 -1
  565. package/scripts/sync/skill-migration.ts +0 -1
  566. package/scripts/sync/sync-ai-files.ts +4 -0
  567. package/scripts/sync/sync-hook-safety.ts +2 -3
  568. package/scripts/sync/sync.ts +1 -8
  569. package/scripts/sync/template-source-logic.ts +0 -1
  570. package/scripts/sync/workflow-pin-logic.ts +16 -28
  571. package/scripts/test/test-declared-changed.ts +13 -16
  572. package/scripts/test/test-declared-logic.ts +0 -1
  573. package/scripts/test/test-declared.ts +3 -9
  574. package/scripts/test/test-red-commit.ts +2 -2
  575. package/scripts/test/test-red.ts +14 -7
  576. package/scripts/test/test-type-logic.ts +1 -1
  577. package/scripts/test/unit-worker-share.ts +7 -16
  578. package/scripts/time-runtime/time-batch-guard.ts +1 -2
  579. package/scripts/time-runtime/time-bundle-call.ts +0 -1
  580. package/scripts/time-runtime/time-bundles.ts +0 -4
  581. package/scripts/time-runtime/time-density-hook.ts +0 -2
  582. package/scripts/time-runtime/time-followup-stage.ts +1 -1
  583. package/scripts/time-runtime/time-format.ts +0 -73
  584. package/scripts/time-runtime/time-round-trips.ts +0 -4
  585. package/scripts/time-runtime/time-single-check.ts +1 -1
  586. package/scripts/time-runtime/time-spans.ts +1 -1
  587. package/scripts/time-runtime/time-transcript-line.ts +1 -2
  588. package/scripts/ui/ui-routes-cli.ts +0 -5
  589. package/scripts/ui/ui-routes.ts +0 -5
  590. package/scripts/version/effective-upstream.ts +2 -2
  591. package/scripts/version/latest-corepack.ts +7 -9
  592. package/scripts/version/latest-scope-cli.ts +0 -2
  593. package/scripts/version/latest-update.ts +0 -2
  594. package/scripts/version/npm-registry.ts +2 -2
  595. package/scripts/version/publishable-range-check.ts +1 -1
  596. package/scripts/version/release-hold.ts +0 -4
  597. package/scripts/version/running-binary.ts +2 -2
  598. package/scripts/version/version-check-logic.ts +0 -2
  599. package/scripts/version/version-commands.ts +11 -1
  600. package/scripts/version/version-remote.ts +3 -3
  601. package/scripts/version/version-targets.ts +4 -4
  602. package/templates/CLAUDE.basic.md +6 -6
  603. package/templates/sonar-project.properties +28 -1
  604. package/templates/workflows/ci.yml +16 -82
  605. package/templates/workflows/dependabot-auto-merge.yml +6 -3
  606. package/templates/workflows/github-release.yml +79 -0
  607. package/tsconfig.sonar.json +4 -22
  608. package/prompts/collaboration-workflow/cross-repo-epic.md +0 -5
  609. package/prompts/collaboration-workflow/epic-audit.md +0 -5
  610. package/prompts/collaboration-workflow/epic-bundle.md +0 -5
  611. package/scripts/init/plugin-install-hint.ts +0 -47
  612. package/scripts/version/parse-json.ts +0 -13
  613. /package/scripts/{git → followup}/git-followup-stages.ts +0 -0
  614. /package/scripts/{git → gh}/git-gh-api-path.ts +0 -0
  615. /package/scripts/{git → gh}/git-gh-command.ts +0 -0
  616. /package/scripts/{git → gh}/git-gh-issue.ts +0 -0
  617. /package/scripts/{git → gh}/git-gh-pr-snapshot.ts +0 -0
  618. /package/scripts/{git → gh}/git-gh-reachability.ts +0 -0
  619. /package/scripts/{git → gh}/git-gh-repo.ts +0 -0
  620. /package/scripts/{git → gh}/git-gh-rest-state.ts +0 -0
  621. /package/scripts/{git → gh}/git-pr-checks-watch.ts +0 -0
  622. /package/scripts/{git → gh}/git-pr-error.ts +0 -0
  623. /package/scripts/{git → gh}/git-pr-messages.ts +0 -0
  624. /package/scripts/{git → gh}/github-issue-url.ts +0 -0
  625. /package/scripts/git/{stash-orphans.ts → stash/stash-orphans.ts} +0 -0
  626. /package/scripts/{git → issue}/issue-reference.ts +0 -0
  627. /package/scripts/{git → lib}/animation-helpers.ts +0 -0
  628. /package/scripts/{git → lib}/git-animation.ts +0 -0
  629. /package/scripts/{git → notify}/git-notify.ts +0 -0
  630. /package/scripts/{git → notify}/telegram-test-logic.ts +0 -0
@@ -1,18 +1,28 @@
1
- import { git_closes_keyword } from './git-closes-keyword'
1
+ import { git_gh_command } from '#scripts/gh/git-gh-command'
2
+ import { git_gh_helpers } from '#scripts/gh/git-gh-helpers'
3
+ import { git_pr_ai_review, type TelegramContext } from '#scripts/gh/git-pr-ai-review'
4
+ import {
5
+ DEFAULT_STABLE_READS,
6
+ git_pr_checks,
7
+ WATCH_CONFIRMED_STABLE_READS,
8
+ } from '#scripts/gh/git-pr-checks'
9
+ import { is_coderabbit_check } from '#scripts/gh/git-pr-checks-eval'
10
+ import { CHECK_STATUS_PASS, type PrStateSnapshot } from '#scripts/gh/git-pr-checks-parse'
11
+ import { git_pr_coderabbit } from '#scripts/gh/git-pr-coderabbit'
12
+ import { git_pr_managed_config } from '#scripts/gh/git-pr-managed-config'
13
+ import { github_issue_url } from '#scripts/gh/github-issue-url'
14
+ import { git_closes_keyword } from '#scripts/git/git-closes-keyword'
15
+ import { json_value } from '#scripts/lib/json-value'
16
+ import type { GitNotifyConfig } from '#scripts/notify/git-notify'
17
+ import {
18
+ telegram_notify,
19
+ type TelegramSendInput,
20
+ type TelegramTaskType,
21
+ } from '#scripts/notify/telegram-notify'
22
+ import { git_followup_merged } from './git-followup-merged'
2
23
  import { git_followup_pending } from './git-followup-pending'
3
24
  import { git_followup_stages, type StageLog } from './git-followup-stages'
4
- import { git_gh_command } from './git-gh-command'
5
- import { git_gh_helpers } from './git-gh-helpers'
6
- import type { GitNotifyConfig } from './git-notify'
7
- import { git_pr_ai_review, type TelegramContext } from './git-pr-ai-review'
8
- import { DEFAULT_STABLE_READS, git_pr_checks, WATCH_CONFIRMED_STABLE_READS } from './git-pr-checks'
9
- import { is_coderabbit_check } from './git-pr-checks-eval'
10
- import { CHECK_STATUS_PASS, git_pr_checks_parse, type PrStateSnapshot } from './git-pr-checks-parse'
11
- import { git_pr_coderabbit } from './git-pr-coderabbit'
12
25
  import { git_pr_followup_wrapup } from './git-pr-followup-wrapup'
13
- import { git_pr_managed_config } from './git-pr-managed-config'
14
- import { github_issue_url } from './github-issue-url'
15
- import { telegram_notify, type TelegramSendInput, type TelegramTaskType } from './telegram-notify'
16
26
 
17
27
  const { STAGE, lap } = git_followup_stages
18
28
 
@@ -64,6 +74,10 @@ interface FollowupInput {
64
74
  ai_review_ignore_reason: string | undefined
65
75
  is_skip_watch: boolean
66
76
  should_merge: boolean
77
+ // The pull request merged before this run (joshuafolkken/kit#3023): only the tail is left to run.
78
+ is_merged?: boolean | undefined
79
+ // When it merged — a completion report posted before it is the `prrun` stop's, not this tail's.
80
+ merged_at?: string | undefined
67
81
  }
68
82
 
69
83
  const { parse_closes_issue_number } = git_closes_keyword
@@ -116,7 +130,7 @@ async function warn_if_missing_closes(branch_name: string): Promise<string | und
116
130
  // on the path this whole change exists to remove. So the question asked here is the narrow one —
117
131
  // *is this definitely an empty rollup* — and every other outcome falls through.
118
132
  function reads_as_empty_rollup(raw_json: string): boolean {
119
- const parsed = git_pr_checks_parse.parse_json_safe(raw_json)
133
+ const parsed = json_value.parse_or_undefined(raw_json)
120
134
 
121
135
  if (typeof parsed !== 'object' || parsed === null || !('statusCheckRollup' in parsed)) {
122
136
  return false
@@ -342,6 +356,8 @@ async function run_review_checks(
342
356
  context: TelegramContext,
343
357
  log: StageLog,
344
358
  ): Promise<{ notes: Array<string>; managed: Array<string> }> {
359
+ if (input.is_merged === true) return { notes: [], managed: [] }
360
+
345
361
  const managed = await git_pr_managed_config.handle_managed_config_changes({
346
362
  should_merge: input.should_merge,
347
363
  })
@@ -359,6 +375,26 @@ async function run_review_checks(
359
375
  return { notes: [...managed, ...check_notes, ...scan_notes], managed }
360
376
  }
361
377
 
378
+ // **A tail re-run after a merge does not report twice** (joshuafolkken/kit#3023): where the issue
379
+ // already carries this pull request's completion report, the Telegram is skipped here and the comment
380
+ // in the wrapup. Answers whether it was recorded, so the wrapup skips on the same read.
381
+ async function notify_unless_recorded(
382
+ input: FollowupInput,
383
+ issue_number: string | undefined,
384
+ context: TelegramContext,
385
+ checks: { notes: Array<string> },
386
+ ): Promise<boolean> {
387
+ const is_recorded = await git_followup_merged.is_completion_recorded({
388
+ merged_at: input.is_merged === true ? input.merged_at : undefined,
389
+ issue_number,
390
+ pr_url: context.pr_url,
391
+ })
392
+
393
+ if (!is_recorded) await notify_completion(context, checks.notes, input.should_merge)
394
+
395
+ return is_recorded
396
+ }
397
+
362
398
  // **Answers with the issue number the run actually used** (joshuafolkken/kit#1539), which is the one
363
399
  // the invocation named or, failing that, the one the pull request body closes. Everything downstream
364
400
  // takes it from here rather than from the input, so the Telegram context, the completion comment and
@@ -369,8 +405,7 @@ async function run_stages(input: FollowupInput, log: StageLog): Promise<string |
369
405
 
370
406
  lap(log, STAGE.closes_and_context)
371
407
  const checks = await run_review_checks(input, context, log)
372
-
373
- await notify_completion(context, checks.notes, input.should_merge)
408
+ const is_completion_recorded = await notify_unless_recorded(input, issue_number, context, checks)
374
409
 
375
410
  lap(log, STAGE.telegram)
376
411
  await git_pr_followup_wrapup.run_wrapup(
@@ -382,6 +417,8 @@ async function run_stages(input: FollowupInput, log: StageLog): Promise<string |
382
417
  pr_url: context.pr_url,
383
418
  should_merge: input.should_merge,
384
419
  managed_notes: checks.managed,
420
+ is_merged: input.is_merged,
421
+ is_completion_recorded,
385
422
  },
386
423
  log,
387
424
  )
@@ -426,4 +463,4 @@ export {
426
463
  log_skip_notes,
427
464
  }
428
465
  export type { FollowupInput }
429
- export type { TelegramContext } from './git-pr-ai-review'
466
+ export type { TelegramContext } from '#scripts/gh/git-pr-ai-review'
@@ -4,6 +4,7 @@ import { availableParallelism } from 'node:os'
4
4
  import path from 'node:path'
5
5
  import { PLATFORM_TEMP_ROOT } from '#scripts/josh/platform-temporary'
6
6
  import { process_identity } from '#scripts/josh/process-identity'
7
+ import { process_owner_schema } from '#scripts/josh/process-owner'
7
8
  import { stamp_file } from '#scripts/josh/stamp-file'
8
9
  import { z } from 'zod'
9
10
 
@@ -45,9 +46,7 @@ const WAIT_CAP_MS = 120_000
45
46
  // The head of the ledger is always admitted, so the smallest budget worth planning against is one core.
46
47
  const MIN_BUDGET = 1
47
48
 
48
- const reservation_schema = z.object({
49
- pid: z.number(),
50
- process_start: z.string().optional(),
49
+ const reservation_schema = process_owner_schema.extend({
51
50
  weight: z.number(),
52
51
  claimed_at: z.number(),
53
52
  })
@@ -228,6 +227,7 @@ async function await_admission(context: WaitContext): Promise<void> {
228
227
  while (!is_admitted(context.key, live_reservations(context.directory), context.budget)) {
229
228
  if (context.now() >= context.deadline) return
230
229
 
230
+ // eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
231
231
  await context.sleep(context.poll_interval_ms)
232
232
  }
233
233
  }
@@ -273,16 +273,10 @@ async function with_core_reservation<T>(
273
273
  }
274
274
 
275
275
  const core_budget = {
276
- MIN_BUDGET,
277
- POLL_INTERVAL_MS,
278
276
  RESERVED_PREFIX,
279
- WAIT_CAP_MS,
280
277
  admitted_keys,
281
278
  admitted_load,
282
- is_admitted,
283
- is_running,
284
279
  live_reservations,
285
- read_reservation,
286
280
  release,
287
281
  reserve,
288
282
  with_core_reservation,
@@ -66,6 +66,11 @@ const STATIC_CHECKS: ReadonlyArray<GateCheck> = [
66
66
  { label: TYPE_CHECK_LABEL, target: 'check', reserved_cores: 1 },
67
67
  { label: 'cspell', target: 'cspell:dot', reserved_cores: 1 },
68
68
  { label: BEHAVIOR_LABEL, target: BEHAVIOR_LABEL, reserved_cores: 0 },
69
+ // **The unused-member check reserves no core** (joshuafolkken/kit#2987): it builds one TypeScript
70
+ // program and walks it single-threaded for about 5s — over well before lint and the type check, so
71
+ // a reservation would only take a place from the four-core CI runner's fan-out and a worker from
72
+ // the unit suite for the whole gate.
73
+ { label: 'exports', target: 'exports:unused', reserved_cores: 0 },
69
74
  ]
70
75
 
71
76
  // The checks, in the order their output is printed — the static set, then the unit suite last (the
@@ -91,8 +96,8 @@ function has_unit_check(checks: ReadonlyArray<GateCheck>): boolean {
91
96
  return checks.some((check) => check.label === UNIT_LABEL)
92
97
  }
93
98
 
94
- // What the three non-elastic checks hold between them: 2 + 1 + 1. Reduced over `STATIC_CHECKS`
95
- // rather than over all four, because that is the set the sentence above names: `resolve_unit_worker_cap`
99
+ // What the non-elastic checks hold between them: 2 + 1 + 1. Reduced over `STATIC_CHECKS`
100
+ // rather than over every check, because that is the set the sentence above names: `resolve_unit_worker_cap`
96
101
  // spends this as the cores the unit suite must leave to its siblings, so summing the unit check into
97
102
  // it would have the suite subtract its own reservation from its own budget the day that reservation
98
103
  // stops being zero. The two sets give the same number today, which is exactly why the narrower one
@@ -331,7 +336,6 @@ function format_gate_plan(
331
336
  }
332
337
 
333
338
  const gate_plan = {
334
- BEHAVIOR_LABEL,
335
339
  GATE_CHECKS,
336
340
  LINT_LABEL,
337
341
  MEASURED_CORES,
@@ -343,7 +347,6 @@ const gate_plan = {
343
347
  check_weight,
344
348
  format_gate_plan,
345
349
  format_machine,
346
- format_unit_cap,
347
350
  has_unit_check,
348
351
  plan_of,
349
352
  resolve_concurrency,
@@ -193,16 +193,10 @@ function report_gate_steps(
193
193
 
194
194
  const gate_report = {
195
195
  format_failure_actions,
196
- format_seconds,
197
- gate_step_header,
198
196
  has_checker_warning,
199
- has_warnings,
200
197
  is_gate_step_failed,
201
198
  is_skip_notice,
202
- print_gate_step,
203
- print_gate_summary,
204
199
  report_gate_steps,
205
- should_print_body,
206
200
  }
207
201
 
208
202
  export type { GateReport, GateStep, GateStepResult }
@@ -43,7 +43,7 @@ async function read_gate_tree(): Promise<GateTree> {
43
43
  return { files, base }
44
44
  }
45
45
 
46
- const gate_tree = { read_base, read_changed_files, read_gate_tree }
46
+ const gate_tree = { read_gate_tree }
47
47
 
48
48
  export type { GateTree }
49
49
  export { gate_tree }
@@ -174,13 +174,7 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) {
174
174
  const pre_commit_type_check = {
175
175
  FORCE_ENV,
176
176
  TYPE_CHECK_ARGUMENTS,
177
- format_refusal,
178
- format_skip,
179
- is_recorded_check_this_check,
180
- read_commit_tree,
181
- reusable_green_commit,
182
177
  run_pre_commit_type_check,
183
- unexpected_arguments,
184
178
  }
185
179
 
186
180
  export type { CommitTree }
@@ -2,6 +2,7 @@ import { existsSync, globSync, readFileSync } from 'node:fs'
2
2
  import path from 'node:path'
3
3
  import { find_local_bin_upwards } from '#scripts/build/local-bin'
4
4
  import { project_profile } from '#scripts/init/project-profile'
5
+ import { json_value } from '#scripts/lib/json-value'
5
6
  import { SKIP_MARKER } from '#scripts/test/skip-marker'
6
7
  import { z } from 'zod'
7
8
 
@@ -70,23 +71,23 @@ function has_bin(directory: string, bin_name: string): boolean {
70
71
  }
71
72
 
72
73
  function josh_settings(manifest: unknown): unknown {
73
- if (typeof manifest !== 'object' || manifest === null || !('josh' in manifest)) return undefined
74
-
75
- return manifest.josh
74
+ return json_value.is_record(manifest) ? manifest['josh'] : undefined
76
75
  }
77
76
 
78
77
  function is_basic_manifest(manifest: unknown): boolean {
79
78
  const josh = josh_settings(manifest)
80
- if (typeof josh !== 'object' || josh === null || !('profile' in josh)) return false
79
+ if (!json_value.is_record(josh)) return false
81
80
 
82
- return project_profile.parse_profile(josh.profile) === 'basic'
81
+ return project_profile.parse_profile(josh['profile']) === 'basic'
83
82
  }
84
83
 
84
+ // The try covers the read alone — a missing or unreadable manifest — since the parse already answers
85
+ // `undefined` for text that is not JSON.
85
86
  function read_manifest(directory: string): unknown {
86
87
  try {
87
88
  const manifest_path = path.join(project_root(directory), PACKAGE_JSON)
88
89
 
89
- return JSON.parse(readFileSync(manifest_path, 'utf8'))
90
+ return json_value.parse_or_undefined(readFileSync(manifest_path, 'utf8'))
90
91
  } catch {
91
92
  return undefined
92
93
  }
@@ -158,8 +159,6 @@ function eslint_skip_reason(directory: string): string | undefined {
158
159
  const project_checks = {
159
160
  CSPELL_CONFIGS,
160
161
  ESLINT_CONFIGS,
161
- SCRIPT_FILES,
162
- TYPE_CONFIGS,
163
162
  TYPE_FILES,
164
163
  WEB_FILES,
165
164
  eslint_skip_reason,
@@ -252,7 +252,6 @@ const scoped_green = {
252
252
  read_before,
253
253
  record_green,
254
254
  record_if_green,
255
- refusal,
256
255
  refusal_for,
257
256
  }
258
257
 
@@ -74,6 +74,7 @@ async function resolve_toolkit_step(
74
74
  // The command the gate spawns through `pnpm`, so a toolkit step resolves the same shim `pnpm` would.
75
75
  async function resolve_type_check_args(start_directory: string): Promise<ReadonlyArray<string>> {
76
76
  for (const bin_name of TOOLKIT_BINS) {
77
+ // eslint-disable-next-line no-await-in-loop -- the first toolkit bin that resolves wins
77
78
  const step = await resolve_toolkit_step(start_directory, bin_name)
78
79
  if (step !== undefined) return step
79
80
  }
@@ -83,7 +84,6 @@ async function resolve_type_check_args(start_directory: string): Promise<Readonl
83
84
 
84
85
  const type_check_step = {
85
86
  parse_usage_commands,
86
- resolve_toolkit_step,
87
87
  resolve_type_check_args,
88
88
  }
89
89
 
@@ -488,10 +488,8 @@ const verification_gate = {
488
488
  mark_gate_running,
489
489
  record_green_gate,
490
490
  run_gate_steps,
491
- run_marked_gate,
492
491
  scoped_precheck_refusal,
493
492
  with_gate_marker,
494
- run_checked_gate,
495
493
  run_gate_command,
496
494
  run_gate_step,
497
495
  run_verification_gate,
@@ -1,7 +1,9 @@
1
1
  import { existsSync, readFileSync, realpathSync, writeFileSync } from 'node:fs'
2
2
  import path from 'node:path'
3
3
  import { fileURLToPath } from 'node:url'
4
+ import { bounded_pool } from '#scripts/lib/bounded-pool'
4
5
  import { file_reader } from '#scripts/lib/read-file'
6
+ import { timed_fetch } from '#scripts/lib/timed-fetch'
5
7
  import { z } from 'zod'
6
8
  import { fix_gh_packages_logic, type LockfilePackage } from './fix-gh-packages-logic'
7
9
  import { gh_cli_token } from './gh-cli-token'
@@ -9,7 +11,8 @@ import { gh_cli_token } from './gh-cli-token'
9
11
  const LOCKFILE = 'pnpm-lock.yaml'
10
12
  const NPMRC = '.npmrc'
11
13
  const GH_PACKAGES_HOST = 'npm.pkg.github.com'
12
- const FETCH_TIMEOUT_MS = 10_000
14
+ // The packument reads are independent; the width keeps a large lockfile from bursting the registry.
15
+ const FETCH_CONCURRENCY = 8
13
16
 
14
17
  const npm_distribution_schema = z.looseObject({ tarball: z.string().optional() })
15
18
  const npm_version_schema = z.looseObject({ dist: npm_distribution_schema.optional() })
@@ -42,10 +45,7 @@ async function fetch_tarball_url(
42
45
  token: string,
43
46
  ): Promise<string | undefined> {
44
47
  const url = `https://${GH_PACKAGES_HOST}/${package_path}`
45
- const response = await fetch(url, {
46
- headers: { Authorization: `Bearer ${token}` },
47
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
48
- })
48
+ const response = await timed_fetch(url, { headers: { Authorization: `Bearer ${token}` } })
49
49
 
50
50
  if (!response.ok) {
51
51
  console.warn(`fix-gh-packages: fetch failed for ${package_path} (${String(response.status)})`)
@@ -79,14 +79,13 @@ async function collect_fixes(
79
79
  scopes: Set<string>,
80
80
  token: string,
81
81
  ): Promise<Map<string, string>> {
82
- const fixes = new Map<string, string>()
83
-
84
- for (const [key, entry] of Object.entries(packages)) {
85
- const pair = await process_package_entry(key, entry, scopes, token)
86
- if (pair !== undefined) fixes.set(pair[0], pair[1])
87
- }
82
+ const pairs = await bounded_pool.bounded_map(
83
+ Object.entries(packages),
84
+ FETCH_CONCURRENCY,
85
+ async ([key, entry]) => await process_package_entry(key, entry, scopes, token),
86
+ )
88
87
 
89
- return fixes
88
+ return new Map(pairs.filter((pair) => pair !== undefined))
90
89
  }
91
90
 
92
91
  async function apply_fixes(cwd: string, scopes: Set<string>, token: string): Promise<void> {
@@ -128,3 +127,7 @@ async function main(): Promise<void> {
128
127
 
129
128
  const [, argv1] = process.argv
130
129
  if (argv1 !== undefined && realpathSync(argv1) === fileURLToPath(import.meta.url)) await main()
130
+
131
+ const fix_gh_packages = { collect_fixes }
132
+
133
+ export { fix_gh_packages }
@@ -1,6 +1,6 @@
1
- import { git_gh_api_path } from '#scripts/git/git-gh-api-path'
2
- import { git_gh_exec } from '#scripts/git/git-gh-exec'
3
1
  import { PROJECT_ROOT } from '#scripts/init/init-paths'
2
+ import { git_gh_api_path } from './git-gh-api-path'
3
+ import { git_gh_exec } from './git-gh-exec'
4
4
 
5
5
  // The synchronous twin of `git_gh_repo.repo_get_name_with_owner`: same fact, read the same way, but
6
6
  // synchronously because `josh init` / `josh sync` / `josh doctor` decide before they can await.
@@ -146,9 +146,5 @@ function classify_ai_review_comments(comments: ReadonlyArray<ReviewComment>): Cl
146
146
  }
147
147
  }
148
148
 
149
- const git_ai_review_scan = {
150
- classify_ai_review_comments,
151
- }
152
-
153
- export { git_ai_review_scan, classify_ai_review_comments }
149
+ export { classify_ai_review_comments }
154
150
  export type { ReviewComment, ClassifiedFinding, ClassifiedFindings, FindingKind }
@@ -1,3 +1,4 @@
1
+ import { COMMAND_TIMEOUT_MS } from '#scripts/lib/timeouts'
1
2
  import { execa } from 'execa'
2
3
 
3
4
  const GH_NOT_INSTALLED_MSG = 'gh CLI is not installed. Install it from https://cli.github.com/'
@@ -6,7 +7,7 @@ const gh_check: { promise?: Promise<void> } = {}
6
7
 
7
8
  async function run_gh_check(): Promise<void> {
8
9
  try {
9
- await execa('gh', ['--version'])
10
+ await execa('gh', ['--version'], { timeout: COMMAND_TIMEOUT_MS })
10
11
  } catch {
11
12
  delete gh_check.promise
12
13
  throw new Error(GH_NOT_INSTALLED_MSG)
@@ -1,7 +1,7 @@
1
+ import { has_timed_out } from '#scripts/git/git-execa-error'
1
2
  import { agent_session_environment } from '#scripts/josh/agent-session-environment'
2
3
  import { error_text } from '#scripts/lib/error-message'
3
4
  import { execa, execaSync } from 'execa'
4
- import { has_timed_out } from './git-execa-error'
5
5
  import { check_gh_installed } from './git-gh-check'
6
6
  import { gh_failure } from './git-gh-failure'
7
7
 
@@ -1,5 +1,5 @@
1
+ import { parse_json } from '#scripts/git/parse-json-array'
1
2
  import { z } from 'zod'
2
- import { parse_json } from './parse-json-array'
3
3
 
4
4
  // Why one `gh api` request failed, taken from **that request** rather than from a later probe
5
5
  // (joshuafolkken/kit#1690).
@@ -36,7 +36,6 @@ function handle_pr_create_error(error: unknown): never {
36
36
 
37
37
  const git_gh_helpers = {
38
38
  parse_pr_state_string,
39
- is_pr_already_exists_message,
40
39
  get_error_message_with_stderr,
41
40
  handle_pr_create_error,
42
41
  }
@@ -1,3 +1,4 @@
1
+ import { bounded_pool } from '#scripts/lib/bounded-pool'
1
2
  import { git_gh_api_path } from './git-gh-api-path'
2
3
  import { git_gh_exec } from './git-gh-exec'
3
4
  import { read_blocked_by } from './git-gh-issue-read'
@@ -178,6 +179,7 @@ async function fetch_selected(request: IssueListRequest): Promise<SelectedRows>
178
179
  let has_more = true
179
180
 
180
181
  while (page <= MAX_PAGES && wants_more(has_more, selected.length, request.limit)) {
182
+ // eslint-disable-next-line no-await-in-loop -- paging stops as soon as enough rows are selected
181
183
  const result = await fetch_page(request, page)
182
184
 
183
185
  selected.push(...result.selected)
@@ -197,20 +199,21 @@ async function fetch_selected(request: IssueListRequest): Promise<SelectedRows>
197
199
  // issue GitHub itself reports as unblocked costs no request. A backlog with no declared blockers
198
200
  // therefore costs exactly what `gh` cost — one listing — rather than one request per row.
199
201
  //
200
- // Sequential rather than a burst: the only caller that asks for the field is the `auto-ok` pickup,
201
- // whose listing is already narrowed by a label, and a rate limit reached in parallel would fail rows
202
- // that a paced pass reads.
202
+ // Bounded rather than sequential (joshuafolkken/kit#3103): the pass was paced one request at a time,
203
+ // which made every `backlog:plan` wait about 0.7 s per opted-in issue declaring a blocker. The width
204
+ // is the one `epic:bundle` already reads the same endpoint at, so the burst stays bounded while a
205
+ // rate-limited read still fails the whole listing rather than a row (`bounded-pool.ts`).
206
+ const RELATION_CONCURRENCY = 8
207
+
203
208
  async function read_relations(
204
209
  rows: ReadonlyArray<RestIssue>,
205
210
  repo?: string,
206
211
  ): Promise<Array<BlockedBy>> {
207
- const relations: Array<BlockedBy> = []
208
-
209
- for (const row of rows) {
210
- relations.push(await read_blocked_by(String(row.number), row, repo))
211
- }
212
-
213
- return relations
212
+ return await bounded_pool.bounded_map(
213
+ rows,
214
+ RELATION_CONCURRENCY,
215
+ async (row) => await read_blocked_by(String(row.number), row, repo),
216
+ )
214
217
  }
215
218
 
216
219
  // The listing, plus what it could not cover. `json` is `undefined` — never `'[]'` — when the listing
@@ -1,3 +1,4 @@
1
+ import type { IssueReference } from '#scripts/issue/issue-reference'
1
2
  import { git_gh_api_path } from './git-gh-api-path'
2
3
  import { git_gh_exec } from './git-gh-exec'
3
4
  import { gh_failure, type GhFailure } from './git-gh-failure'
@@ -9,7 +10,6 @@ import {
9
10
  type RestIssue,
10
11
  } from './git-gh-issue-rest'
11
12
  import { gh_reachability } from './git-gh-reachability'
12
- import type { IssueReference } from './issue-reference'
13
13
 
14
14
  // Reading one issue. Split out of `git-gh-issue.ts`, which had grown past the file-length limit
15
15
  // while holding both the reads and the writes; the reads are what every epic command goes through,
@@ -1,8 +1,11 @@
1
+ import {
2
+ parse_json_array_or_undefined,
3
+ parse_json_object_safe,
4
+ } from '#scripts/git/parse-json-array'
5
+ import { blocking_issue_schema } from '#scripts/git/schemas'
6
+ import type { IssueReference } from '#scripts/issue/issue-reference'
1
7
  import { z } from 'zod'
2
8
  import { MERGED_STATE, to_gh_state } from './git-gh-rest-state'
3
- import type { IssueReference } from './issue-reference'
4
- import { parse_json_array_or_undefined, parse_json_object_safe } from './parse-json-array'
5
- import { blocking_issue_schema } from './schemas'
6
9
 
7
10
  // The translation between one REST issue (`repos/{owner}/{repo}/issues/{N}`) and the JSON shape
8
11
  // `gh issue view --json <fields>` used to answer with.
@@ -1,3 +1,4 @@
1
+ import { error_text } from '#scripts/lib/error-message'
1
2
  import { git_gh_api_path } from './git-gh-api-path'
2
3
  import { git_gh_exec, type GhApiRequest } from './git-gh-exec'
3
4
 
@@ -43,7 +44,9 @@ async function did_write_succeed(write: () => Promise<unknown>): Promise<boolean
43
44
  await write()
44
45
 
45
46
  return true
46
- } catch {
47
+ } catch (error) {
48
+ error_text.trace_swallowed('git_gh_issue_write.did_write_succeed', error)
49
+
47
50
  return false
48
51
  }
49
52
  }
@@ -1,3 +1,4 @@
1
+ import { error_text } from '#scripts/lib/error-message'
1
2
  import { git_gh_api_path } from './git-gh-api-path'
2
3
  import { git_gh_exec } from './git-gh-exec'
3
4
  import { read_pull, require_pr_number } from './git-gh-pr-read'
@@ -40,7 +41,9 @@ async function pr_enable_auto_merge(branch_name: string): Promise<void> {
40
41
  async function pr_is_merged(branch_name: string): Promise<boolean> {
41
42
  try {
42
43
  return git_gh_pr_rest.is_merged(await read_pull(await require_pr_number(branch_name)))
43
- } catch {
44
+ } catch (error) {
45
+ error_text.trace_swallowed('git_gh_pr_auto_merge.pr_is_merged', error)
46
+
44
47
  return false
45
48
  }
46
49
  }
@@ -77,6 +77,12 @@ async function fetch_pr_number(branch_name: string): Promise<number | undefined>
77
77
  // distinction is the point. The *classification* is cheaper here and needs no status probe: a branch
78
78
  // with no pull request is a 200 with an empty listing rather than a 404, so the lookup's own outcome
79
79
  // already separates them (joshuafolkken/kit#1048).
80
+ interface PullMergeState {
81
+ is_merged: boolean
82
+ merged_at: string | undefined
83
+ head_sha: string | undefined
84
+ }
85
+
80
86
  type PullNumberRead =
81
87
  { kind: 'read'; pr_number: number } | { kind: 'missing' } | { kind: 'unreadable'; cause: unknown }
82
88
 
@@ -215,6 +221,22 @@ async function pr_get_url(branch_name: string): Promise<string | undefined> {
215
221
  return git_gh_helpers.parse_pr_state_string(pull.html_url)
216
222
  }
217
223
 
224
+ // **Where the branch's pull request stands** — a merge a person made by hand included
225
+ // (joshuafolkken/kit#3023): whether it merged and when, and the commit its head is on, which a push
226
+ // made on GitHub moves without touching the local branch. `undefined` covers both "no pull request"
227
+ // and "nothing could be read": `followup` then takes its ordinary path, whose merge step settles a
228
+ // pull request that did merge after all (`pr_merge`), so an unread answer costs a wait, not a wrong tail.
229
+ async function pr_get_merge_state(branch_name: string): Promise<PullMergeState | undefined> {
230
+ const pull = await read_pull_of_branch(branch_name)
231
+ if (pull === undefined) return undefined
232
+
233
+ return {
234
+ is_merged: git_gh_pr_rest.is_merged(pull),
235
+ merged_at: pull.merged_at ?? undefined,
236
+ head_sha: pull.head?.sha,
237
+ }
238
+ }
239
+
218
240
  // REST answers JSON null for a pull request with no body where `gh --json body` answered an empty
219
241
  // string, and both used to arrive here as the empty answer this folds to `undefined`.
220
242
  async function pr_get_body(branch_name: string): Promise<string | undefined> {
@@ -281,6 +303,7 @@ const git_gh_pr_read = {
281
303
  pr_get_number,
282
304
  pr_get_url,
283
305
  pr_get_body,
306
+ pr_get_merge_state,
284
307
  pr_view,
285
308
  pr_get_comments,
286
309
  pr_get_review_comments,
@@ -290,6 +313,7 @@ const git_gh_pr_read = {
290
313
  // needs them separately: the reviews endpoint is keyed by number while the rollup is keyed by the
291
314
  // head commit the detail carries. Exported rather than re-derived so the memo above stays one memo
292
315
  // (joshuafolkken/kit#1028).
316
+ export type { PullMergeState }
293
317
  export {
294
318
  git_gh_pr_read,
295
319
  forget_pr_numbers,
@@ -1,7 +1,10 @@
1
+ import {
2
+ parse_json_array_or_undefined,
3
+ parse_json_object_safe,
4
+ } from '#scripts/git/parse-json-array'
5
+ import { rest_comment_schema } from '#scripts/git/schemas'
1
6
  import { z } from 'zod'
2
7
  import { MERGED_STATE, to_gh_state } from './git-gh-rest-state'
3
- import { parse_json_array_or_undefined, parse_json_object_safe } from './parse-json-array'
4
- import { rest_comment_schema } from './schemas'
5
8
 
6
9
  // The translation between one REST pull request (`repos/{owner}/{repo}/pulls/{N}`) and the JSON
7
10
  // shape `gh pr view --json <fields>` used to answer with.
@@ -1,5 +1,5 @@
1
+ import { parse_json_array_or_undefined } from '#scripts/git/parse-json-array'
1
2
  import { z } from 'zod'
2
- import { parse_json_array_or_undefined } from './parse-json-array'
3
3
 
4
4
  // GraphQL's `reviewDecision`, rebuilt from the review history REST serves.
5
5
  //
@@ -90,7 +90,7 @@ function to_review_decision(reviews_json: string): string {
90
90
  return latest.has(REVIEW_APPROVED) ? REVIEW_APPROVED : REVIEW_NONE
91
91
  }
92
92
 
93
- const git_gh_pr_review = { to_review_decision, parse_rest_reviews }
93
+ const git_gh_pr_review = { to_review_decision }
94
94
 
95
95
  export {
96
96
  git_gh_pr_review,