@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,7 +1,7 @@
1
1
  #!/usr/bin/env tsx
2
2
  import { fileURLToPath } from 'node:url'
3
- import { parseArgs } from 'node:util'
4
3
  import { josh_command } from '#scripts/josh/josh-run'
4
+ import { cli_flags } from '#scripts/lib/cli-flags'
5
5
  import { rule_value_cache } from '#scripts/rules/rule-value-cache'
6
6
  import { run_event_stream } from '#scripts/run/run-event-stream'
7
7
  import { run_event_stream_emit } from '#scripts/run/run-event-stream-emit'
@@ -61,15 +61,7 @@ type ParsedValues = Partial<Record<OptionName, string | boolean | ReadonlyArray<
61
61
  const FORWARDED = ['started', 'active', 'merged', 'running', 'max', 'idle'] as const
62
62
 
63
63
  function read_values(argv: ReadonlyArray<string>): ParsedValues | undefined {
64
- try {
65
- return parseArgs({ args: [...argv], options: OPTIONS, strict: true }).values
66
- } catch {
67
- return undefined
68
- }
69
- }
70
-
71
- function text_of(value: string | boolean | ReadonlyArray<string> | undefined): string | undefined {
72
- return typeof value === 'string' ? value : undefined
64
+ return cli_flags.values_of(argv, OPTIONS)
73
65
  }
74
66
 
75
67
  function to_count(raw: string | undefined): number | undefined {
@@ -94,8 +86,8 @@ interface OfferCounts {
94
86
  // The two counts the mapping needs: `--running` decides `wait`, `--retries` decides `retry`. Either
95
87
  // given but unreadable refuses the whole invocation.
96
88
  function counts_of(values: ParsedValues): OfferCounts | undefined {
97
- const running = count_of(text_of(values.running), DEFAULT_COUNT)
98
- const retries = count_of(text_of(values.retries), DEFAULT_COUNT)
89
+ const running = count_of(cli_flags.string_of(values.running), DEFAULT_COUNT)
90
+ const retries = count_of(cli_flags.string_of(values.retries), DEFAULT_COUNT)
99
91
 
100
92
  if (running === undefined || retries === undefined) return undefined
101
93
 
@@ -109,7 +101,7 @@ function excludes_of(values: ParsedValues): ReadonlyArray<string> {
109
101
  }
110
102
 
111
103
  function next_argv(values: ParsedValues): ReadonlyArray<string> {
112
- const repo = text_of(values.repo)
104
+ const repo = cli_flags.string_of(values.repo)
113
105
 
114
106
  return [
115
107
  'backlog:next',
@@ -120,7 +112,7 @@ function next_argv(values: ParsedValues): ReadonlyArray<string> {
120
112
 
121
113
  function budget_argv(values: ParsedValues, answer: string): ReadonlyArray<string> {
122
114
  const forwarded = FORWARDED.flatMap((name) => {
123
- const value = text_of(values[name])
115
+ const value = cli_flags.string_of(values[name])
124
116
 
125
117
  return value === undefined ? [] : [`--${name}`, value]
126
118
  })
@@ -262,16 +254,11 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
262
254
 
263
255
  const backlog_offer_cli = {
264
256
  JSON_KEY,
265
- USAGE,
266
257
  budget_argv,
267
258
  counts_of,
268
- emit,
269
- main,
270
- mark_drain,
271
259
  next_argv,
272
260
  read_values,
273
261
  run,
274
- to_tokens,
275
262
  }
276
263
 
277
264
  if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
@@ -3,7 +3,7 @@ import { fileURLToPath } from 'node:url'
3
3
  import { auto_ok_cli } from '#scripts/auto-ok/auto-ok-cli'
4
4
  import { epic_index } from '#scripts/epic/epic-index'
5
5
  import type { EpicNextResult } from '#scripts/epic/epic-report'
6
- import { git_gh_command } from '#scripts/git/git-gh-command'
6
+ import { git_gh_command } from '#scripts/gh/git-gh-command'
7
7
  import { read_json_listing } from '#scripts/git/parse-json-array'
8
8
  import { open_issue_schema, type OpenIssueData } from '#scripts/git/schemas'
9
9
  import { run_invocation } from '#scripts/run/run-invocation'
@@ -263,13 +263,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
263
263
  const backlog_plan_cli = {
264
264
  OPEN_TRUNCATED_MESSAGE,
265
265
  OPEN_UNREADABLE_MESSAGE,
266
- USAGE,
267
266
  WAVES_WITH_NAMED_MESSAGE,
268
- classify,
269
- fetch_open,
270
- main,
271
- print_plan,
272
- report,
273
267
  run,
274
268
  }
275
269
 
@@ -3,7 +3,8 @@ import type { IssueReference } from '#scripts/epic/epic-reference'
3
3
  import { epic_report, type EpicNextResult } from '#scripts/epic/epic-report'
4
4
  import { epic_solo } from '#scripts/epic/epic-solo'
5
5
  import { epic_triage } from '#scripts/epic/epic-triage'
6
- import { has_label_name, IN_PROGRESS_LABEL, RUN_SOLO_LABEL } from '#scripts/git/issue-labels'
6
+ import { issue_cite } from '#scripts/issue/issue-cite'
7
+ import { has_label_name, IN_PROGRESS_LABEL, RUN_SOLO_LABEL } from '#scripts/issue/issue-labels'
7
8
  import type { OutOfScopeRow } from './backlog-scope'
8
9
 
9
10
  // The plan a person reads before a `backlogrun` starts (joshuafolkken/kit#1652).
@@ -57,23 +58,29 @@ interface PlanContext {
57
58
 
58
59
  // A child elsewhere is qualified, because a bare number would name *this* repository's issue of that
59
60
  // number — a different issue (joshuafolkken/kit#1016). Takes the reference rather than the child, so
60
- // a `blocked_by` edge is named by the same rule the child itself is.
61
- function reference_of(reference: IssueReference, repo: string): string {
61
+ // a `blocked_by` edge is named by the same rule the child itself is. This repository's issue is cited
62
+ // (joshuafolkken/kit#3099): the plan is copied into a report verbatim, so the line it prints is the
63
+ // citation the report carries.
64
+ function cite_of(reference: IssueReference, repo: string, title: string | undefined): string {
62
65
  const number = String(reference.number)
63
66
 
64
- return reference.repo === repo ? `#${number}` : `${reference.repo}#${number}`
67
+ return reference.repo === repo
68
+ ? issue_cite.reference(repo, number, title)
69
+ : `${reference.repo}#${number}`
70
+ }
71
+
72
+ function reference_of(reference: IssueReference, repo: string): string {
73
+ return cite_of(reference, repo, undefined)
65
74
  }
66
75
 
67
76
  // A title is only known for this repository's issues — the open listing the titles come from is this
68
77
  // repository's. A child elsewhere is still named, just without one.
69
- function title_of(child: EpicChild, context: PlanContext): string {
70
- return child.repo === context.repo ? (context.titles.get(child.number) ?? '') : ''
78
+ function title_of(child: EpicChild, context: PlanContext): string | undefined {
79
+ return child.repo === context.repo ? context.titles.get(child.number) : undefined
71
80
  }
72
81
 
73
- function join_row(reference: string, title: string, note: string): string {
74
- const parts = [reference, title, note === '' ? '' : `— ${note}`].filter((part) => part !== '')
75
-
76
- return `${ROW_INDENT}${parts.join(' ')}`
82
+ function join_row(reference: string, note: string): string {
83
+ return note === '' ? `${ROW_INDENT}${reference}` : `${ROW_INDENT}${reference} — ${note}`
77
84
  }
78
85
 
79
86
  // A `run:solo` child is marked beside its number, so a person reading the plan sees which issues
@@ -89,15 +96,15 @@ function mark_of(child: EpicChild): string | undefined {
89
96
  return epic_triage.is_triaged(child) ? undefined : UNTRIAGED_MARK
90
97
  }
91
98
 
92
- function marked_reference(child: EpicChild, repo: string): string {
93
- const reference = reference_of(child, repo)
99
+ function marked_reference(child: EpicChild, repo: string, title?: string): string {
100
+ const reference = cite_of(child, repo, title)
94
101
  const mark = mark_of(child)
95
102
 
96
103
  return mark === undefined ? reference : `${reference} ${mark}`
97
104
  }
98
105
 
99
106
  function row_of(child: EpicChild, context: PlanContext, note: string): string {
100
- return join_row(marked_reference(child, context.repo), title_of(child, context), note)
107
+ return join_row(marked_reference(child, context.repo, title_of(child, context)), note)
101
108
  }
102
109
 
103
110
  // Why this one is not offered yet. The blocker numbers are the answer whenever there are any — that
@@ -164,8 +171,10 @@ function waiting_lines(children: ReadonlyArray<EpicChild>, context: PlanContext)
164
171
  })
165
172
  }
166
173
 
167
- function scope_lines(rows: ReadonlyArray<OutOfScopeRow>): Array<string> {
168
- return rows.map((row) => join_row(`#${String(row.number)}`, row.title, row.reason))
174
+ function scope_lines(rows: ReadonlyArray<OutOfScopeRow>, repo: string): Array<string> {
175
+ return rows.map((row) =>
176
+ join_row(issue_cite.reference(repo, String(row.number), row.title), row.reason),
177
+ )
169
178
  }
170
179
 
171
180
  // The classification could not be made, so every section below it would be rendered from buckets
@@ -186,10 +195,12 @@ interface NamedPlan {
186
195
  only: boolean
187
196
  }
188
197
 
189
- // The named issues are this repository's own, so a bare `#N` names them and a title is looked up the
190
- // same way the pool's rows are. The order is the invocation's, never sorted.
198
+ // The named issues are this repository's own, so they are cited against it and a title is looked up
199
+ // the same way the pool's rows are. The order is the invocation's, never sorted.
191
200
  function named_lines(named: ReadonlyArray<number>, context: PlanContext): Array<string> {
192
- return named.map((issue) => join_row(`#${String(issue)}`, context.titles.get(issue) ?? '', ''))
201
+ return named.map((issue) =>
202
+ join_row(issue_cite.reference(context.repo, String(issue), context.titles.get(issue)), ''),
203
+ )
193
204
  }
194
205
 
195
206
  // The section leads the plan when the invocation named issues, and is absent otherwise — a bare
@@ -230,7 +241,7 @@ function format_plan(
230
241
  '',
231
242
  section(HUMAN_HEADING, child_lines(result.blocked_on_people, context, no_note)),
232
243
  '',
233
- section(SCOPE_HEADING, scope_lines(out_of_scope)),
244
+ section(SCOPE_HEADING, scope_lines(out_of_scope, context.repo)),
234
245
  ].join('\n')
235
246
  }
236
247
 
@@ -5,14 +5,14 @@ import { epic_index } from '#scripts/epic/epic-index'
5
5
  import { epic_issue } from '#scripts/epic/epic-issue'
6
6
  import type { EpicView } from '#scripts/epic/epic-next-views'
7
7
  import { epic_outside_blocker } from '#scripts/epic/epic-outside-blocker'
8
- import { git_next_issues } from '#scripts/git/git-next-issues'
8
+ import type { OpenIssueData } from '#scripts/git/schemas'
9
+ import { git_next_issues } from '#scripts/issue/git-next-issues'
9
10
  import {
10
11
  ALREADY_DONE_LABEL,
11
12
  EPIC_LABEL,
12
13
  has_any_label,
13
14
  NEEDS_DECISION_LABEL,
14
- } from '#scripts/git/issue-labels'
15
- import type { OpenIssueData } from '#scripts/git/schemas'
15
+ } from '#scripts/issue/issue-labels'
16
16
 
17
17
  // The candidate pool `josh backlog:next` answers from (joshuafolkken/kit#1630).
18
18
  //
@@ -328,14 +328,11 @@ const backlog_pool = {
328
328
  standalone_keys,
329
329
  drop_excluded,
330
330
  epic_classification,
331
- is_epic_row,
332
- keys_of,
333
331
  merge_classifications,
334
332
  opted_in_epics,
335
333
  standalone_rows,
336
334
  to_child,
337
335
  to_children,
338
- unique_children,
339
336
  }
340
337
 
341
338
  export { backlog_pool }
@@ -3,7 +3,7 @@ import { epic_graph, type EpicChild } from '#scripts/epic/epic-graph'
3
3
  import { epic_rank } from '#scripts/epic/epic-rank'
4
4
  import type { EpicNextResult } from '#scripts/epic/epic-report'
5
5
  import { epic_solo, type SoloGate, type SoloSelection } from '#scripts/epic/epic-solo'
6
- import { git_next_issues } from '#scripts/git/git-next-issues'
6
+ import { git_next_issues } from '#scripts/issue/git-next-issues'
7
7
 
8
8
  // What the backlog offers, in the order it is decided (joshuafolkken/kit#2928): rank, then the
9
9
  // `run:solo` gate, then the cap. `backlog:next` and `backlog:plan --waves` both call `select`, so the
@@ -100,7 +100,7 @@ function gate(
100
100
  )
101
101
  }
102
102
 
103
- const backlog_rank = { everything_in, gate, rank, rank_result, select }
103
+ const backlog_rank = { everything_in, gate, rank_result, select }
104
104
 
105
105
  export { backlog_rank }
106
106
  export type { OfferInput }
@@ -1,3 +1,5 @@
1
+ import { git_gh_command } from '#scripts/gh/git-gh-command'
2
+ import { issue_cite } from '#scripts/issue/issue-cite'
1
3
  import { josh_command, type JoshResult } from '#scripts/josh/josh-run'
2
4
  import { lane_capacity } from '#scripts/lane/lane-capacity'
3
5
  import { lane_registry } from '#scripts/lane/lane-registry'
@@ -21,6 +23,13 @@ interface ReadyPorts {
21
23
  ready_issues: () => Promise<ReadonlyArray<string>>
22
24
  }
23
25
 
26
+ async function free_under(limit: number): Promise<number> {
27
+ const lanes = await lane_registry.list_lanes()
28
+ const live = lanes.filter((lane) => !lane.is_stranded).length
29
+
30
+ return lane_capacity.free_lanes(limit, live)
31
+ }
32
+
24
33
  // Free lanes right now: the limit less the live lanes. An unreadable limit reads as no free lane — the
25
34
  // safe direction, since both the stall and the ready line need a free lane and reporting one that is
26
35
  // not there is the false positive neither may raise.
@@ -35,10 +44,18 @@ async function free_lane_count(): Promise<number> {
35
44
 
36
45
  if (limit.kind !== 'limit') return NO_FREE
37
46
 
38
- const lanes = await lane_registry.list_lanes()
39
- const live = lanes.filter((lane) => !lane.is_stranded).length
47
+ return await free_under(limit.limit)
48
+ }
40
49
 
41
- return lane_capacity.free_lanes(limit.limit, live)
50
+ // **The drive's count throws on an unreadable limit** (joshuafolkken/kit#3027). The drive launches no
51
+ // more than this count, so the safe-direction zero above would leave it launching nothing and reporting
52
+ // nothing for good; a bad setting is the hard error `lane_capacity` says it is, ending the drive loudly.
53
+ async function drive_free_lane_count(): Promise<number> {
54
+ const limit = lane_capacity.lane_limit()
55
+
56
+ if (limit.kind !== 'limit') throw new Error(limit.problem)
57
+
58
+ return await free_under(limit.limit)
42
59
  }
43
60
 
44
61
  // **A `--only` run has no pool to drain** (joshuafolkken/kit#2472). `backlog:next` lists the opted-in
@@ -77,35 +94,46 @@ async function read_ready(ports: ReadyPorts = DEFAULT_PORTS): Promise<ReadyReadi
77
94
  return { issues: await ports.ready_issues(), free_lanes }
78
95
  }
79
96
 
80
- // `undefined` unless there is both runnable work and a lane for it — the only state worth a line.
81
- function ready_line(reading: ReadyReading): string | undefined {
97
+ // `undefined` unless there is both runnable work and a lane for it — the only state worth a line. Each
98
+ // issue is a number-link against `slug` (joshuafolkken/kit#3099): the parent copies this line into its
99
+ // report, so a bare `#N` here is the citation the Stop guard sends back.
100
+ function ready_line(reading: ReadyReading, slug: string | undefined): string | undefined {
82
101
  if (reading.issues.length === NONE || reading.free_lanes <= NO_FREE) return undefined
83
102
 
84
- const issues = reading.issues.map((issue) => `#${issue}`).join(' ')
103
+ const cite = issue_cite.citer(slug, new Map())
104
+ const issues = reading.issues.map((issue) => cite(issue)).join(' ')
85
105
 
86
106
  return `ready ${issues} · free lanes ${String(reading.free_lanes)}`
87
107
  }
88
108
 
109
+ type RepoRead = () => Promise<string | undefined>
110
+
89
111
  // The watcher's line on exit, for the driving parent alone — a `fullrun` watcher has no pool to pick
90
112
  // from. Best-effort: a reading that fails prints nothing rather than failing the watcher whose exit is
91
113
  // the wake.
92
114
  async function parent_ready_line(
93
115
  ports: ReadyPorts,
94
116
  is_parent: () => Promise<boolean>,
117
+ read_repo: RepoRead,
95
118
  ): Promise<string | undefined> {
96
119
  if (!(await is_parent())) return undefined
97
120
 
98
- return ready_line(await read_ready(ports))
121
+ const reading = await read_ready(ports)
122
+
123
+ return reading.issues.length === NONE ? undefined : ready_line(reading, await read_repo())
124
+ }
125
+
126
+ function print_line(line: string | undefined): void {
127
+ if (line !== undefined) console.info(line)
99
128
  }
100
129
 
101
130
  async function print_ready_line(
102
131
  ports: ReadyPorts = DEFAULT_PORTS,
103
132
  is_parent: () => Promise<boolean> = run_headless.is_backlog_parent,
133
+ read_repo: RepoRead = git_gh_command.repo_get_name_with_owner,
104
134
  ): Promise<void> {
105
135
  try {
106
- const line = await parent_ready_line(ports, is_parent)
107
-
108
- if (line !== undefined) console.info(line)
136
+ print_line(await parent_ready_line(ports, is_parent, read_repo))
109
137
  } catch {
110
138
  // A pick-up line is a hint; the wake it rides must still be delivered.
111
139
  }
@@ -135,6 +163,7 @@ const backlog_ready = {
135
163
  read_backlog_next,
136
164
  print_offer_hint,
137
165
  free_lane_count,
166
+ drive_free_lane_count,
138
167
  drains_pool,
139
168
  print_ready_line,
140
169
  read_ready,
@@ -1,6 +1,6 @@
1
1
  import type { EpicNextResult } from '#scripts/epic/epic-report'
2
- import { AUTO_OK_LABEL, EPIC_LABEL, has_any_label } from '#scripts/git/issue-labels'
3
2
  import type { OpenIssueData } from '#scripts/git/schemas'
3
+ import { AUTO_OK_LABEL, EPIC_LABEL, has_any_label } from '#scripts/issue/issue-labels'
4
4
 
5
5
  // Which open issues the backlog will not run, and why (joshuafolkken/kit#1652).
6
6
  //
@@ -135,8 +135,6 @@ const backlog_scope = {
135
135
  OPTED_IN_UNPLACED_REASON,
136
136
  open_numbers_of,
137
137
  out_of_scope,
138
- planned_numbers,
139
- reason_for,
140
138
  titles_of,
141
139
  }
142
140
 
@@ -1,4 +1,4 @@
1
- import { telegram_notify } from '#scripts/git/telegram-notify'
1
+ import { telegram_notify } from '#scripts/notify/telegram-notify'
2
2
  import { run_event_stream, type RunEvent } from '#scripts/run/run-event-stream'
3
3
  import { run_event_stream_emit } from '#scripts/run/run-event-stream-emit'
4
4
  import { backlog_ready, type ReadyPorts } from './backlog-ready'
@@ -137,7 +137,7 @@ async function run_stall_check(ready: ReadyPorts = backlog_ready.DEFAULT_PORTS):
137
137
  }
138
138
  }
139
139
 
140
- const backlog_stalled_detect = { DEFAULT_PORTS, detect_and_report, gather, report, run_stall_check }
140
+ const backlog_stalled_detect = { detect_and_report, run_stall_check }
141
141
 
142
142
  export { backlog_stalled_detect }
143
143
  export type { DetectPorts }
@@ -118,7 +118,6 @@ const backlog_stalled = {
118
118
  count_ready_tokens,
119
119
  describe,
120
120
  dispatch_age_ms,
121
- is_stalled,
122
121
  needs_triage,
123
122
  ready_tokens,
124
123
  }
@@ -4,7 +4,11 @@ import { epic_cross_repo } from '#scripts/epic/epic-cross-repo'
4
4
  import { epic_graph, type EpicChild } from '#scripts/epic/epic-graph'
5
5
  import { epic_outside_blocker } from '#scripts/epic/epic-outside-blocker'
6
6
  import { epic_report, type EpicNextResult } from '#scripts/epic/epic-report'
7
- import { has_label_name, IN_PROGRESS_LABEL, NEEDS_DECISION_LABEL } from '#scripts/git/issue-labels'
7
+ import {
8
+ has_label_name,
9
+ IN_PROGRESS_LABEL,
10
+ NEEDS_DECISION_LABEL,
11
+ } from '#scripts/issue/issue-labels'
8
12
  import { backlog_plan, type PlanContext } from './backlog-plan'
9
13
  import { backlog_rank } from './backlog-rank'
10
14
 
@@ -171,7 +175,6 @@ function format_waves(
171
175
  const backlog_waves = {
172
176
  HEADING_ASSUMPTION,
173
177
  NEEDS_DECISION_NOTE,
174
- NOT_REACHED_NOTE,
175
178
  PARALLEL_NOTE,
176
179
  UNREACHED_HEADING,
177
180
  build,
@@ -81,7 +81,7 @@ function run(cwd: string = process.cwd()): number {
81
81
  return file === undefined ? report_no_transcript() : check_session(file)
82
82
  }
83
83
 
84
- const behavior_cli = { LABEL, check_session, current_session, run }
84
+ const behavior_cli = { check_session, run }
85
85
 
86
86
  if (process.argv[1] === fileURLToPath(import.meta.url)) process.exitCode = run()
87
87
 
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env tsx
2
+ import { readFileSync, writeFileSync } from 'node:fs'
3
+ import path from 'node:path'
4
+ import { fileURLToPath } from 'node:url'
5
+ import { codex_hooks } from '#scripts/agent/codex-hooks'
6
+
7
+ const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..')
8
+ const CLAUDE_SETTINGS = path.join(REPO_ROOT, '.claude', 'settings.json')
9
+ const CODEX_HOOKS = path.join(REPO_ROOT, '.codex', 'hooks.json')
10
+
11
+ // Regenerate `.codex/hooks.json` from `.claude/settings.json` (joshuafolkken/kit#2997). The output is
12
+ // committed rather than gitignored: Codex reads it straight from a fresh clone of kit, before any
13
+ // build has run, and `josh init` / `josh sync` copy it to consumers from the package.
14
+ function build_codex_hooks(): string {
15
+ writeFileSync(CODEX_HOOKS, codex_hooks.codex_hooks_text(readFileSync(CLAUDE_SETTINGS, 'utf8')))
16
+
17
+ return CODEX_HOOKS
18
+ }
19
+
20
+ function main(): void {
21
+ console.info(` ✔ ${build_codex_hooks()} built`)
22
+ }
23
+
24
+ if (process.argv[1] === fileURLToPath(import.meta.url)) main()
25
+
26
+ export { build_codex_hooks, CLAUDE_SETTINGS, CODEX_HOOKS }
@@ -1,12 +1,27 @@
1
1
  #!/usr/bin/env tsx
2
- import { readdirSync, rmSync } from 'node:fs'
2
+ import {
3
+ mkdirSync,
4
+ mkdtempSync,
5
+ readdirSync,
6
+ readFileSync,
7
+ renameSync,
8
+ rmSync,
9
+ writeFileSync,
10
+ } from 'node:fs'
3
11
  import path from 'node:path'
4
12
  import { fileURLToPath } from 'node:url'
13
+ import { hook_bundle_stamp } from '#scripts/build/hook-bundle-stamp'
5
14
  import { error_text } from '#scripts/lib/error-message'
6
- import { build } from 'esbuild'
15
+ import { build, type OnLoadArgs, type OutputFile, type Plugin, type PluginBuild } from 'esbuild'
7
16
 
8
17
  const PACKAGE_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..')
9
18
  const OUT_DIR = path.join(PACKAGE_DIR, 'dist', 'hooks')
19
+ const { STAMP_NAME } = hook_bundle_stamp
20
+ const CHUNK_PREFIX = 'chunk-'
21
+ const STAGING_PREFIX = '.hooks-staging-'
22
+ // esbuild compiles a plugin filter as a Go regexp, which rejects the `u` flag.
23
+ // eslint-disable-next-line require-unicode-regexp
24
+ const ANY_PATH = /.*/
10
25
 
11
26
  // Each Claude Code hook is bundled to its own `dist/hooks/<name>.js`, so a consumer (and kit itself)
12
27
  // invokes `node dist/hooks/<name>.js` directly — no `pnpm` launch and no `tsx` re-spawn from the
@@ -60,20 +75,76 @@ function outfile_for(bundle: HookBundle): string {
60
75
  // The output directory is flat (every entry and chunk sits at its top level), so a file whose name
61
76
  // this build did not emit is a leftover of an earlier one.
62
77
  function prune_stale_outputs(out_directory: string, outputs: ReadonlyArray<string>): void {
63
- const live = new Set(outputs.map((output) => path.basename(output)))
78
+ const live = new Set([...outputs.map((output) => path.basename(output)), STAMP_NAME])
64
79
 
65
80
  for (const name of readdirSync(out_directory)) {
66
81
  if (!live.has(name)) rmSync(path.join(out_directory, name), { recursive: true, force: true })
67
82
  }
68
83
  }
69
84
 
85
+ // Every file the build loads is read here, so the stamp digests the exact bytes that were bundled —
86
+ // a source edited mid-build is recorded as what it was, and the next launch rebuilds it.
87
+ function source_recorder(sources: Map<string, Uint8Array>): Plugin {
88
+ return {
89
+ name: 'hook-source-recorder',
90
+ setup(plugin_build: PluginBuild): void {
91
+ plugin_build.onLoad({ filter: ANY_PATH, namespace: 'file' }, function load(args: OnLoadArgs) {
92
+ const contents = readFileSync(args.path)
93
+
94
+ sources.set(path.relative(PACKAGE_DIR, args.path), contents)
95
+
96
+ return { contents, loader: 'default' }
97
+ })
98
+ },
99
+ }
100
+ }
101
+
102
+ function is_chunk(file: OutputFile): boolean {
103
+ return path.basename(file.path).startsWith(CHUNK_PREFIX)
104
+ }
105
+
106
+ // Shared chunks first, then the entries that import them: an entry swapped in before its chunks
107
+ // would fail to load in a hook launched at that moment.
108
+ function is_chunk_first(left: OutputFile, right: OutputFile): number {
109
+ return Number(is_chunk(right)) - Number(is_chunk(left))
110
+ }
111
+
112
+ // Each file is written into a private staging directory and renamed into place, so a hook never
113
+ // reads a half-written bundle and two builds running side by side never write one file at once.
114
+ function place(staging: string, target: string, contents: Uint8Array | string): void {
115
+ const temporary = path.join(staging, path.basename(target))
116
+
117
+ writeFileSync(temporary, contents)
118
+ renameSync(temporary, target)
119
+ }
120
+
121
+ function place_build(out_directory: string, files: ReadonlyArray<OutputFile>, stamp: string): void {
122
+ mkdirSync(out_directory, { recursive: true })
123
+ const staging = mkdtempSync(path.join(path.dirname(out_directory), STAGING_PREFIX))
124
+
125
+ try {
126
+ for (const file of files.toSorted(is_chunk_first)) place(staging, file.path, file.contents)
127
+ prune_stale_outputs(
128
+ out_directory,
129
+ files.map((file) => file.path),
130
+ )
131
+ place(staging, path.join(out_directory, STAMP_NAME), stamp)
132
+ } finally {
133
+ rmSync(staging, { recursive: true, force: true })
134
+ }
135
+ }
136
+
70
137
  // With `splitting: true` every build emits freshly hashed `chunk-*.js` files, so without a cleanup
71
138
  // the chunks of every earlier build pile up beside the live ones and ship in any local pack
72
- // (joshuafolkken/kit#2885). The cleanup runs after the build rather than emptying the directory
73
- // first: this checkout's own settings.json launches `node dist/hooks/<name>.js` on every tool call,
74
- // and an emptied directory would make a hook launched mid-build fail to load and its guard fail open.
139
+ // (joshuafolkken/kit#2885). The cleanup runs after the new files are in place rather than emptying
140
+ // the directory first: this checkout's own settings.json launches `node dist/hooks/<name>.js` on
141
+ // every tool call, and an emptied directory would make a hook launched mid-build fail to load and its
142
+ // guard fail open. The source digest is placed last (`hook-bundle-stamp.ts`), so a launch only reads
143
+ // the bundles as fresh once every one of them is in place (joshuafolkken/kit#2984).
75
144
  async function build_hooks(out_directory: string = OUT_DIR): Promise<void> {
76
- const { metafile } = await build({
145
+ const sources = new Map<string, Uint8Array>()
146
+ const { outputFiles: files } = await build({
147
+ absWorkingDir: PACKAGE_DIR,
77
148
  entryPoints: HOOK_BUNDLES.map((bundle) => entry_point(bundle)),
78
149
  outdir: out_directory,
79
150
  bundle: true,
@@ -82,10 +153,15 @@ async function build_hooks(out_directory: string = OUT_DIR): Promise<void> {
82
153
  format: 'esm',
83
154
  target: 'node22',
84
155
  packages: 'external',
85
- metafile: true,
156
+ write: false,
157
+ plugins: [source_recorder(sources)],
86
158
  })
159
+ const stamp = hook_bundle_stamp.stamp_text(
160
+ sources,
161
+ files.map((file) => file.path),
162
+ )
87
163
 
88
- prune_stale_outputs(out_directory, Object.keys(metafile.outputs))
164
+ place_build(out_directory, files, stamp)
89
165
  }
90
166
 
91
167
  async function main(): Promise<void> {