@joshuafolkken/kit 1.1050.0 → 1.1094.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 (581) 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 +19 -11
  4. package/.claude/skills/workflow-commands/background-commands.md +4 -3
  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 +1 -1
  8. package/.claude/skills/workflow-commands/backlogrun-steps.md +10 -10
  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 +3 -2
  16. package/.claude/skills/workflow-commands/halfrun.md +16 -19
  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 +1 -1
  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/prerequisite.md +1 -1
  25. package/.claude/skills/workflow-commands/prrun.md +36 -0
  26. package/.claude/skills/workflow-commands/retrospective.md +1 -1
  27. package/.claude/skills/workflow-commands/working-tree-hold.md +22 -2
  28. package/.codex/hooks.json +16 -20
  29. package/.github/actions/setup-pnpm/action.yml +93 -0
  30. package/.github/dependabot.yml +5 -1
  31. package/.github/workflows/ci.yml +26 -128
  32. package/.github/workflows/pr-classification.yml +5 -41
  33. package/.github/workflows/publish.yml +33 -38
  34. package/.github/workflows/sonar-qube.yml +37 -4
  35. package/AGENTS.md +12 -2
  36. package/CLAUDE.md +15 -16
  37. package/GEMINI.md +14 -2
  38. package/README.md +59 -18
  39. package/SECURITY.md +36 -6
  40. package/cspell/index.yaml +2 -1
  41. package/dist/CLAUDE.md +15 -16
  42. package/dist/config-merge/index.js +15 -3
  43. package/dist/hooks/batch-guard.js +4 -4
  44. package/dist/hooks/{chunk-HJIISEAC.js → chunk-3C4YCCEF.js} +5 -13
  45. package/dist/hooks/{chunk-EJDX2TOB.js → chunk-7ZPFAVR7.js} +7 -88
  46. package/dist/hooks/{chunk-WQ4OSBSS.js → chunk-E54KGFEQ.js} +2 -2
  47. package/dist/hooks/{chunk-GQ7KP45M.js → chunk-IL27YTPH.js} +2 -2
  48. package/dist/hooks/{chunk-DMQN45FN.js → chunk-KHWHKJOM.js} +3 -3
  49. package/dist/hooks/{chunk-5BK3K7V4.js → chunk-M2XDCUKD.js} +997 -478
  50. package/dist/hooks/{chunk-7VPDUBRN.js → chunk-NKOG3XAV.js} +150 -153
  51. package/dist/hooks/{chunk-NJQOBE6L.js → chunk-O4LL4HTI.js} +2 -7
  52. package/dist/hooks/{chunk-NAS4C7GP.js → chunk-OIZUHPJI.js} +2 -2
  53. package/dist/hooks/{chunk-RLDX5SOC.js → chunk-UD24EAIL.js} +2084 -1412
  54. package/dist/hooks/codex-hook-adapter.js +10 -11
  55. package/dist/hooks/duplicate-read-guard.js +5 -5
  56. package/dist/hooks/format-edited.js +2 -2
  57. package/dist/hooks/inputs.json +279 -0
  58. package/dist/hooks/investigation-guard.js +5 -5
  59. package/dist/hooks/pretool-guard.js +9 -9
  60. package/dist/hooks/session-lang.js +0 -1
  61. package/dist/hooks/stop-guard.js +178 -324
  62. package/dist/josh.js +162 -119
  63. package/dist/managed-marker/index.js +2 -1
  64. package/dist/version/index.js +34 -58
  65. package/eslint/rules/promise.js +5 -0
  66. package/package.json +9 -4
  67. package/prompts/collaboration-workflow/issue-citation.md +5 -5
  68. package/prompts/collaboration-workflow/operating-rules.md +4 -4
  69. package/prompts/collaboration-workflow/overview.md +13 -1
  70. package/prompts/collaboration-workflow/report-format.md +1 -1
  71. package/prompts/collaboration-workflow/residency.md +3 -3
  72. package/prompts/collaboration-workflow/rule-delivery.md +1 -1
  73. package/prompts/collaboration-workflow/turn-batching.md +3 -3
  74. package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
  75. package/prompts/collaboration-workflow/wip-cap.md +25 -22
  76. package/prompts/collaboration-workflow.md +5 -8
  77. package/prompts/review-rubric.md +1 -1
  78. package/prompts/review.md +3 -3
  79. package/prompts/sonar-hotspot-handling.md +11 -3
  80. package/prompts/testing-guide.md +3 -3
  81. package/scripts/adopt/adopt-toolkits.ts +0 -2
  82. package/scripts/adopt/adopt.ts +0 -2
  83. package/scripts/agent/agent-argv.ts +0 -2
  84. package/scripts/agent/agent-diagnostics.ts +1 -1
  85. package/scripts/agent/agent-role-profile.ts +0 -7
  86. package/scripts/agent/claude-agent-argv.ts +0 -2
  87. package/scripts/agent/codex-agent-argv.ts +1 -1
  88. package/scripts/agent/codex-hooks.ts +92 -0
  89. package/scripts/agent/interactive-ask.ts +1 -1
  90. package/scripts/auto-ok/auto-ok-cli.ts +6 -16
  91. package/scripts/backlog/backlog-budget.ts +0 -2
  92. package/scripts/backlog/backlog-defect-priority.ts +2 -2
  93. package/scripts/backlog/backlog-drive-cli.ts +10 -8
  94. package/scripts/backlog/backlog-drive-named-offer.ts +16 -3
  95. package/scripts/backlog/backlog-drive-named.ts +2 -1
  96. package/scripts/backlog/backlog-drive.ts +76 -16
  97. package/scripts/backlog/backlog-named.ts +0 -3
  98. package/scripts/backlog/backlog-next.ts +9 -15
  99. package/scripts/backlog/backlog-offer-cli.ts +0 -5
  100. package/scripts/backlog/backlog-plan-cli.ts +1 -7
  101. package/scripts/backlog/backlog-plan.ts +1 -1
  102. package/scripts/backlog/backlog-pool.ts +3 -6
  103. package/scripts/backlog/backlog-rank.ts +2 -2
  104. package/scripts/backlog/backlog-ready.ts +19 -3
  105. package/scripts/backlog/backlog-scope.ts +1 -3
  106. package/scripts/backlog/backlog-stalled-detect.ts +2 -2
  107. package/scripts/backlog/backlog-stalled.ts +0 -1
  108. package/scripts/backlog/backlog-waves.ts +5 -2
  109. package/scripts/behavior/behavior-cli.ts +1 -1
  110. package/scripts/build/build-codex-hooks.ts +26 -0
  111. package/scripts/build/build-hooks.ts +85 -9
  112. package/scripts/build/hook-bundle-stamp.ts +111 -0
  113. package/scripts/cases/cases-cli.ts +1 -1
  114. package/scripts/cases/cases-logic.ts +1 -1
  115. package/scripts/ci/composite-actions.ts +30 -0
  116. package/scripts/ci/pr-classification.ts +3 -3
  117. package/scripts/claude/workflow-destination.ts +10 -1
  118. package/scripts/clone/clone-fingerprint.ts +0 -1
  119. package/scripts/clone/clone-scan-cli.ts +1 -1
  120. package/scripts/clone/clone-scan.ts +1 -1
  121. package/scripts/config-merge/json-format.ts +0 -1
  122. package/scripts/config-merge/patch-yaml-list.ts +1 -1
  123. package/scripts/cost-runtime/codex-usage.ts +2 -9
  124. package/scripts/cost-runtime/cost-attribute.ts +0 -1
  125. package/scripts/cost-runtime/cost-cli.ts +0 -3
  126. package/scripts/cost-runtime/cost-corpus.ts +0 -2
  127. package/scripts/cost-runtime/cost-format.ts +0 -3
  128. package/scripts/cost-runtime/cost-pricing.ts +0 -1
  129. package/scripts/cost-runtime/cost-tokens.ts +0 -1
  130. package/scripts/delegation/delegation-cli.ts +1 -1
  131. package/scripts/delegation/delegation-policy.ts +0 -1
  132. package/scripts/delegation/duplicate-read-guard.ts +0 -8
  133. package/scripts/delegation/fanout-cli.ts +1 -1
  134. package/scripts/delegation/fanout.ts +0 -2
  135. package/scripts/delegation/investigation-reads.ts +1 -164
  136. package/scripts/discovery/repo-map-logic.ts +0 -1
  137. package/scripts/discovery/repo-party-cli.ts +1 -1
  138. package/scripts/doctor/doctor-consumer.ts +4 -6
  139. package/scripts/doctor/doctor-logic.ts +0 -4
  140. package/scripts/doctor/doctor.ts +14 -9
  141. package/scripts/document/document-byte-budget.ts +4 -5
  142. package/scripts/document/document-byte-check.ts +0 -1
  143. package/scripts/document/document-read-cli.ts +0 -2
  144. package/scripts/document/document-section-cli.ts +1 -1
  145. package/scripts/document/document-section.ts +0 -3
  146. package/scripts/document/edit-files-cli.ts +0 -1
  147. package/scripts/document/entry-read-budget.ts +10 -2
  148. package/scripts/document/lane-child-read-set.ts +1 -6
  149. package/scripts/document/read-files-cli.ts +0 -4
  150. package/scripts/document/read-set-cli.ts +0 -2
  151. package/scripts/document/read-set-point-of-use.ts +1 -0
  152. package/scripts/document/read-set-pricing.ts +0 -1
  153. package/scripts/document/read-set-trim.ts +1 -1
  154. package/scripts/epic/epic-add.ts +1 -1
  155. package/scripts/epic/epic-audit-cli.ts +1 -4
  156. package/scripts/epic/epic-audit-orphans.ts +1 -3
  157. package/scripts/epic/epic-audit-rationale.ts +0 -1
  158. package/scripts/epic/epic-audit-report.ts +0 -2
  159. package/scripts/epic/epic-audit.ts +5 -4
  160. package/scripts/epic/epic-bundle-cli.ts +1 -1
  161. package/scripts/epic/epic-bundle-evidence.ts +0 -1
  162. package/scripts/epic/epic-bundle-referenced.ts +1 -5
  163. package/scripts/epic/epic-bundle.ts +0 -4
  164. package/scripts/epic/epic-busy.ts +4 -5
  165. package/scripts/epic/epic-candidate-confirm.ts +0 -5
  166. package/scripts/epic/epic-classify.ts +2 -2
  167. package/scripts/epic/epic-cli-argv.ts +0 -1
  168. package/scripts/epic/epic-close-comment.ts +1 -1
  169. package/scripts/epic/epic-close.ts +5 -2
  170. package/scripts/epic/epic-cross-repo.ts +2 -4
  171. package/scripts/epic/epic-decision.ts +0 -1
  172. package/scripts/epic/epic-fetch.ts +2 -2
  173. package/scripts/epic/epic-index.ts +2 -3
  174. package/scripts/epic/epic-issue.ts +1 -15
  175. package/scripts/epic/epic-lane-offer.ts +9 -8
  176. package/scripts/epic/epic-nested.ts +1 -1
  177. package/scripts/epic/epic-next-read.ts +1 -3
  178. package/scripts/epic/epic-next-views.ts +0 -1
  179. package/scripts/epic/epic-next.ts +1 -10
  180. package/scripts/epic/epic-parse.ts +0 -1
  181. package/scripts/epic/epic-promote.ts +0 -9
  182. package/scripts/epic/epic-rank.ts +2 -2
  183. package/scripts/epic/epic-read.ts +1 -2
  184. package/scripts/epic/epic-reconcile.ts +1 -1
  185. package/scripts/epic/epic-reference.ts +1 -13
  186. package/scripts/epic/epic-relation-recheck.ts +1 -1
  187. package/scripts/epic/epic-relations.ts +1 -1
  188. package/scripts/epic/epic-remove.ts +1 -1
  189. package/scripts/epic/epic-report.ts +0 -1
  190. package/scripts/epic/epic-run.ts +2 -3
  191. package/scripts/epic/epic-shape.ts +1 -1
  192. package/scripts/epic/epic-solo-stale.ts +107 -0
  193. package/scripts/epic/epic-solo.ts +3 -2
  194. package/scripts/epic/epic-triage.ts +1 -1
  195. package/scripts/epic/epic-validate.ts +1 -1
  196. package/scripts/epic/epic.ts +1 -1
  197. package/scripts/exports/unused-members-cli.ts +53 -0
  198. package/scripts/{git → followup}/followup-issue-number.ts +1 -6
  199. package/scripts/{git → followup}/git-followup-cleanup.ts +2 -1
  200. package/scripts/{git → followup}/git-followup-finish.ts +1 -3
  201. package/scripts/{git → followup}/git-followup-flush.ts +2 -2
  202. package/scripts/{git → followup}/git-followup-issue-close.ts +2 -2
  203. package/scripts/{git → followup}/git-followup-label.ts +4 -4
  204. package/scripts/followup/git-followup-merged.ts +112 -0
  205. package/scripts/{git → followup}/git-followup-pending.ts +1 -1
  206. package/scripts/{git → followup}/git-followup-workflow.ts +19 -11
  207. package/scripts/{git → followup}/git-pr-followup-wrapup.ts +9 -3
  208. package/scripts/{git → followup}/git-pr-followup.ts +53 -16
  209. package/scripts/gate/core-budget.ts +3 -9
  210. package/scripts/gate/gate-plan.ts +7 -4
  211. package/scripts/gate/gate-report.ts +0 -6
  212. package/scripts/gate/gate-tree.ts +1 -1
  213. package/scripts/gate/pre-commit-type-check.ts +0 -6
  214. package/scripts/gate/project-checks.ts +7 -8
  215. package/scripts/gate/scoped-green.ts +0 -1
  216. package/scripts/gate/type-check-step.ts +1 -1
  217. package/scripts/gate/verification-gate.ts +0 -2
  218. package/scripts/gh/fix-gh-packages.ts +15 -12
  219. package/scripts/gh/gh-spawn.ts +2 -2
  220. package/scripts/{git → gh}/git-ai-review-scan.ts +1 -5
  221. package/scripts/{git → gh}/git-gh-check.ts +2 -1
  222. package/scripts/{git → gh}/git-gh-exec.ts +1 -1
  223. package/scripts/{git → gh}/git-gh-failure.ts +1 -1
  224. package/scripts/{git → gh}/git-gh-helpers.ts +0 -1
  225. package/scripts/{git → gh}/git-gh-issue-list.ts +2 -0
  226. package/scripts/{git → gh}/git-gh-issue-read.ts +1 -1
  227. package/scripts/{git → gh}/git-gh-issue-rest.ts +6 -3
  228. package/scripts/{git → gh}/git-gh-pr-read.ts +24 -0
  229. package/scripts/{git → gh}/git-gh-pr-rest.ts +5 -2
  230. package/scripts/{git → gh}/git-gh-pr-review.ts +2 -2
  231. package/scripts/{git → gh}/git-gh-pr-rollup.ts +1 -3
  232. package/scripts/{git → gh}/git-gh-pr.ts +3 -1
  233. package/scripts/{git → gh}/git-pr-ai-review.ts +2 -5
  234. package/scripts/{git → gh}/git-pr-checks-eval.ts +0 -10
  235. package/scripts/{git → gh}/git-pr-checks-parse.ts +4 -20
  236. package/scripts/{git → gh}/git-pr-checks.ts +2 -1
  237. package/scripts/{git → gh}/git-pr-coderabbit.ts +2 -5
  238. package/scripts/{git → gh}/git-pr-confirmation.ts +1 -3
  239. package/scripts/{git → gh}/git-pr-managed-config.ts +2 -3
  240. package/scripts/{git → gh}/git-pr.ts +3 -3
  241. package/scripts/git/changed-file-scope.ts +0 -1
  242. package/scripts/git/git-branch.ts +3 -6
  243. package/scripts/git/git-commit.ts +1 -1
  244. package/scripts/git/git-common-directory.ts +80 -24
  245. package/scripts/git/git-error.ts +66 -9
  246. package/scripts/git/git-issue.ts +1 -1
  247. package/scripts/git/git-preflight.ts +2 -2
  248. package/scripts/git/git-prompt.ts +6 -31
  249. package/scripts/git/git-push.ts +1 -1
  250. package/scripts/git/git-staging.ts +1 -0
  251. package/scripts/git/git-status.ts +1 -1
  252. package/scripts/git/git-workflow.ts +1 -1
  253. package/scripts/git/gone-branch.ts +1 -0
  254. package/scripts/git/listing-cutoff.ts +1 -1
  255. package/scripts/git/main-merge.ts +1 -1
  256. package/scripts/git/main-sync.ts +19 -1
  257. package/scripts/git/parse-json-array.ts +0 -3
  258. package/scripts/git/repository-lock.ts +16 -16
  259. package/scripts/git/{git-stash.ts → stash/git-stash.ts} +1 -1
  260. package/scripts/git/{stash-pop-args.ts → stash/stash-pop-args.ts} +1 -1
  261. package/scripts/git/{stash-pop-cli.ts → stash/stash-pop-cli.ts} +0 -1
  262. package/scripts/git/{stash-sweep-lock.ts → stash/stash-sweep-lock.ts} +3 -3
  263. package/scripts/hooks/codex-hook-adapter.ts +0 -1
  264. package/scripts/hooks/edited-cspell.ts +1 -1
  265. package/scripts/hooks/format-edited-file.ts +2 -0
  266. package/scripts/hooks/pre-push-unit.ts +0 -4
  267. package/scripts/hooks/pretool-guard.ts +22 -4
  268. package/scripts/hooks/reserved-run.ts +1 -1
  269. package/scripts/hooks/step-zero-notice.ts +76 -0
  270. package/scripts/hooks/stop-guard.ts +47 -21
  271. package/scripts/init/claude-plugin-config.ts +4 -5
  272. package/scripts/init/hook-command-rewrite.ts +16 -8
  273. package/scripts/init/hook-launch.ts +41 -15
  274. package/scripts/init/init-basic.ts +2 -5
  275. package/scripts/init/init-logic.ts +7 -0
  276. package/scripts/init/init.ts +0 -3
  277. package/scripts/init/project-profile.ts +6 -11
  278. package/scripts/init/start-exec.ts +1 -1
  279. package/scripts/init/start-setup-pr.ts +6 -6
  280. package/scripts/init/start-steps.ts +1 -0
  281. package/scripts/issue/behavior-change-lint.ts +0 -1
  282. package/scripts/issue/defect-rate-cli.ts +3 -3
  283. package/scripts/issue/defect-rate.ts +1 -2
  284. package/scripts/{git → issue}/git-next-issues.ts +3 -3
  285. package/scripts/issue/issue-backlinks-cli.ts +1 -5
  286. package/scripts/issue/issue-cite-cli.ts +2 -6
  287. package/scripts/issue/issue-cite.ts +0 -2
  288. package/scripts/issue/issue-classification.ts +1 -9
  289. package/scripts/issue/issue-closing-pr.ts +4 -4
  290. package/scripts/issue/issue-comment-cli.ts +2 -2
  291. package/scripts/issue/issue-file-cli.ts +5 -5
  292. package/scripts/issue/issue-file.ts +2 -2
  293. package/scripts/issue/issue-fold-cli.ts +1 -1
  294. package/scripts/issue/issue-fold-existing-cli.ts +1 -1
  295. package/scripts/{git → issue}/issue-labels.ts +8 -0
  296. package/scripts/issue/issue-lint-cli.ts +1 -1
  297. package/scripts/issue/issue-merged.ts +2 -2
  298. package/scripts/{git → issue}/issue-rank.ts +1 -1
  299. package/scripts/issue/issue-read-cli.ts +8 -47
  300. package/scripts/issue/issue-read.ts +0 -2
  301. package/scripts/issue/issue-report-failures.ts +80 -0
  302. package/scripts/issue/issue-scout-cli.ts +1 -7
  303. package/scripts/issue/issue-scout-closed.ts +2 -2
  304. package/scripts/issue/issue-scout.ts +0 -2
  305. package/scripts/issue/issue-state-cli.ts +5 -46
  306. package/scripts/issue/issue-state.ts +1 -5
  307. package/scripts/issue/markdown-section.ts +1 -1
  308. package/scripts/issue/measure-rerun-cli.ts +1 -1
  309. package/scripts/issue/reproduction-measure.ts +1 -1
  310. package/scripts/josh/cli-body.ts +1 -1
  311. package/scripts/josh/file-map-stamp.ts +0 -3
  312. package/scripts/josh/josh-command-map.ts +2 -0
  313. package/scripts/josh/josh-commands-ai.ts +9 -102
  314. package/scripts/josh/josh-commands-backlog.ts +5 -1
  315. package/scripts/josh/josh-commands-development.ts +8 -1
  316. package/scripts/josh/josh-commands-issue.ts +2 -2
  317. package/scripts/josh/josh-commands-maintenance.ts +7 -0
  318. package/scripts/josh/josh-commands-project.ts +6 -0
  319. package/scripts/josh/josh-commands-run.ts +114 -0
  320. package/scripts/josh/josh-commands-versioning.ts +8 -0
  321. package/scripts/josh/josh-commands-workflow.ts +2 -2
  322. package/scripts/josh/path-decision.ts +0 -3
  323. package/scripts/josh/process-owner.ts +16 -0
  324. package/scripts/josh/session-language-cli.ts +0 -1
  325. package/scripts/lane/lane-await.ts +3 -6
  326. package/scripts/lane/lane-capacity.ts +6 -3
  327. package/scripts/lane/lane-child-invocation.ts +20 -7
  328. package/scripts/lane/lane-cli.ts +1 -4
  329. package/scripts/lane/lane-close.ts +1 -3
  330. package/scripts/lane/lane-dispatch.ts +3 -4
  331. package/scripts/lane/lane-environment.ts +0 -9
  332. package/scripts/lane/lane-handoff.ts +38 -0
  333. package/scripts/lane/lane-launch-cli.ts +21 -11
  334. package/scripts/lane/lane-open.ts +0 -3
  335. package/scripts/lane/lane-output.ts +0 -1
  336. package/scripts/lane/lane-registry.ts +9 -0
  337. package/scripts/lane/openai-lane-ship.ts +2 -0
  338. package/scripts/lane/openai-lane-supervisor-decision.ts +2 -1
  339. package/scripts/lane/openai-lane-supervisor.ts +6 -4
  340. package/scripts/lane/openai-review-broker.ts +3 -0
  341. package/scripts/lib/bounded-pool.ts +1 -0
  342. package/scripts/lib/json-value.ts +5 -4
  343. package/scripts/lib/poll.ts +3 -1
  344. package/scripts/lib/timed-fetch.ts +15 -0
  345. package/scripts/lib/timeouts.ts +13 -0
  346. package/scripts/{yaml → lib}/yaml-document.ts +3 -1
  347. package/scripts/{bytes → lines}/bytes-command.ts +0 -2
  348. package/scripts/lines/lines-command.ts +0 -1
  349. package/scripts/lint/lint-related-scope.ts +0 -1
  350. package/scripts/lint/lint-related.ts +1 -1
  351. package/scripts/{git → notify}/telegram-notify.ts +2 -2
  352. package/scripts/{git → notify}/telegram-test.ts +4 -4
  353. package/scripts/observations/observation-ledger-home.ts +0 -1
  354. package/scripts/observations/observation-ledger-line.ts +0 -1
  355. package/scripts/observations/observation-ledger-migrate.ts +1 -1
  356. package/scripts/observations/observations-flush-landing.ts +3 -3
  357. package/scripts/observations/observations-flush.ts +2 -2
  358. package/scripts/overrides/lockfile-overrides.ts +1 -1
  359. package/scripts/overrides/overrides-logic.ts +1 -1
  360. package/scripts/package/package-scout-cli.ts +2 -7
  361. package/scripts/package/package-scout.ts +0 -2
  362. package/scripts/propagate/propagate-git-failure.ts +0 -1
  363. package/scripts/propagate/propagate-git.ts +0 -2
  364. package/scripts/propagate/propagate-publish.ts +2 -3
  365. package/scripts/propagate/propagate-run.ts +0 -2
  366. package/scripts/propagate/propagate-steps.ts +3 -5
  367. package/scripts/propagate/propagate-targets.ts +0 -4
  368. package/scripts/propagate/propagate.ts +0 -4
  369. package/scripts/refactor/import-graph.ts +0 -1
  370. package/scripts/refactor/refactor-lint.ts +0 -2
  371. package/scripts/refactor/refactor-scan.ts +0 -1
  372. package/scripts/refactor/refactor-targets.ts +0 -1
  373. package/scripts/registry-migration/migrate-logic.ts +0 -2
  374. package/scripts/registry-migration/migrate.ts +19 -9
  375. package/scripts/release/github-release-cli.ts +8 -6
  376. package/scripts/release/github-release-environment.ts +46 -0
  377. package/scripts/release/github-release.ts +151 -94
  378. package/scripts/release/release-history.ts +0 -1
  379. package/scripts/release/release-plan.ts +0 -1
  380. package/scripts/release/release-publish.ts +2 -3
  381. package/scripts/release/release-scope-cli.ts +1 -2
  382. package/scripts/release/release-tag.ts +2 -4
  383. package/scripts/repo/auto-merge-setting-logic.ts +1 -4
  384. package/scripts/repo/repo-setting.ts +1 -1
  385. package/scripts/repo/repository-labels.ts +3 -3
  386. package/scripts/repo/required-checks-logic.ts +206 -0
  387. package/scripts/repo/required-checks-report.ts +71 -0
  388. package/scripts/repo/ruleset-check-cli.ts +53 -0
  389. package/scripts/repo/ruleset-check.ts +147 -0
  390. package/scripts/report/report-lint-cli.ts +0 -4
  391. package/scripts/review/disposition-cli.ts +1 -1
  392. package/scripts/review/live-evidence.ts +1 -1
  393. package/scripts/review/review-attest-cli.ts +0 -6
  394. package/scripts/review/review-attest.ts +4 -16
  395. package/scripts/review/review-brief-cli.ts +23 -6
  396. package/scripts/review/review-brief.ts +21 -8
  397. package/scripts/review/review-diff-parts.ts +89 -0
  398. package/scripts/review/review-diff-write.ts +97 -0
  399. package/scripts/review/review-finding-ledger.ts +0 -1
  400. package/scripts/review/review-record-cli.ts +1 -1
  401. package/scripts/review/review-record.ts +0 -1
  402. package/scripts/review/review-round2-cli.ts +1 -1
  403. package/scripts/review/review-stamps.ts +0 -3
  404. package/scripts/review/review-tree.ts +14 -2
  405. package/scripts/rules/decision-oracle-stage.ts +18 -0
  406. package/scripts/rules/decision-oracle.ts +10 -7
  407. package/scripts/rules/delivered-rules.ts +9 -1
  408. package/scripts/rules/destructive-command.ts +119 -0
  409. package/scripts/rules/direct-filing.ts +1 -1
  410. package/scripts/rules/file-body.ts +0 -3
  411. package/scripts/rules/filing-cap.ts +0 -2
  412. package/scripts/rules/gh-api.ts +7 -2
  413. package/scripts/rules/git-argv.ts +18 -7
  414. package/scripts/rules/git-force.ts +0 -2
  415. package/scripts/rules/implementation-cut.ts +0 -1
  416. package/scripts/rules/index-guard.ts +71 -0
  417. package/scripts/rules/issue-citation.ts +50 -25
  418. package/scripts/rules/lane-background.ts +15 -7
  419. package/scripts/rules/lane-park.ts +13 -6
  420. package/scripts/rules/last-prompt.ts +1 -0
  421. package/scripts/rules/oracle-consulted.ts +1 -1
  422. package/scripts/rules/oracle-firing.ts +1 -0
  423. package/scripts/rules/oracle-list-cli.ts +0 -3
  424. package/scripts/rules/permission-guards.ts +14 -0
  425. package/scripts/rules/protected-files.ts +74 -0
  426. package/scripts/rules/reply-language.ts +1 -1
  427. package/scripts/rules/rule-body-guard.ts +0 -3
  428. package/scripts/rules/rule-value-cli.ts +0 -1
  429. package/scripts/rules/shell-body-trigger.ts +0 -1
  430. package/scripts/rules/shell-segments.ts +0 -1
  431. package/scripts/rules/stop-rules.ts +13 -5
  432. package/scripts/rules/tail-commands.ts +1 -1
  433. package/scripts/rules/test-declared-commit.ts +1 -1
  434. package/scripts/rules/third-party-write.ts +0 -1
  435. package/scripts/rules/worktree-guard.ts +26 -9
  436. package/scripts/run/run-carry-cli.ts +0 -2
  437. package/scripts/run/run-carry-stash.ts +2 -2
  438. package/scripts/run/run-carry-streak.ts +1 -1
  439. package/scripts/run/run-cut-cli.ts +0 -7
  440. package/scripts/run/run-cut.ts +8 -54
  441. package/scripts/run/run-ending-cli.ts +1 -1
  442. package/scripts/run/run-ending.ts +1 -4
  443. package/scripts/run/run-entry-cli.ts +101 -24
  444. package/scripts/run/run-entry.ts +0 -1
  445. package/scripts/run/run-event-cli.ts +0 -2
  446. package/scripts/run/run-event-follow.ts +1 -0
  447. package/scripts/run/run-event-render.ts +1 -1
  448. package/scripts/run/run-event-scope.ts +53 -4
  449. package/scripts/run/run-event-stream.ts +0 -3
  450. package/scripts/run/run-event-watch.ts +1 -0
  451. package/scripts/run/run-halfrun-resume.ts +20 -7
  452. package/scripts/run/run-headless.ts +2 -2
  453. package/scripts/run/run-hold-cli.ts +33 -10
  454. package/scripts/run/run-hold.ts +25 -5
  455. package/scripts/run/run-issue-number.ts +1 -1
  456. package/scripts/run/run-liveness-cli.ts +1 -1
  457. package/scripts/run/run-liveness.ts +2 -3
  458. package/scripts/run/run-merge-cli.ts +5 -13
  459. package/scripts/run/run-merge-steps.ts +5 -5
  460. package/scripts/run/run-merge.ts +1 -1
  461. package/scripts/run/run-next-cli.ts +1 -1
  462. package/scripts/run/run-parent-cut-hook.ts +0 -1
  463. package/scripts/run/run-preflight.ts +2 -9
  464. package/scripts/run/run-prep-cli.ts +2 -2
  465. package/scripts/run/run-prep-locate.ts +1 -1
  466. package/scripts/run/run-progress-cli.ts +4 -7
  467. package/scripts/run/run-progress-clock.ts +6 -34
  468. package/scripts/run/run-progress-config.ts +0 -4
  469. package/scripts/run/run-progress-read.ts +1 -2
  470. package/scripts/run/run-progress.ts +1 -2
  471. package/scripts/run/run-prrun-resume.ts +117 -0
  472. package/scripts/run/run-report-cli.ts +1 -2
  473. package/scripts/run/run-report.ts +0 -1
  474. package/scripts/run/run-retrospective.ts +1 -1
  475. package/scripts/run/run-review-cli.ts +0 -3
  476. package/scripts/run/run-review-steps.ts +2 -0
  477. package/scripts/run/run-review.ts +0 -2
  478. package/scripts/run/run-ship-cli.ts +21 -3
  479. package/scripts/run/run-ship-detach.ts +1 -0
  480. package/scripts/run/run-ship-next.ts +106 -0
  481. package/scripts/run/run-ship-preflight.ts +1 -1
  482. package/scripts/run/run-ship-return.ts +8 -3
  483. package/scripts/run/run-ship-review-steps.ts +18 -4
  484. package/scripts/run/run-ship-review.ts +11 -0
  485. package/scripts/run/run-ship-scoped.ts +1 -0
  486. package/scripts/run/run-ship-steps.ts +1 -1
  487. package/scripts/run/run-ship.ts +0 -1
  488. package/scripts/run/run-stage-read.ts +62 -0
  489. package/scripts/run/run-stage.ts +160 -0
  490. package/scripts/run/run-status-cli.ts +1 -1
  491. package/scripts/run/run-step-cli.ts +21 -14
  492. package/scripts/run/run-step.ts +1 -1
  493. package/scripts/run/run-stop-notify.ts +1 -3
  494. package/scripts/run/run-stranded-cli.ts +0 -4
  495. package/scripts/run/run-stranded-detect.ts +2 -2
  496. package/scripts/run/run-tail-cli.ts +17 -11
  497. package/scripts/run/run-tail.ts +2 -0
  498. package/scripts/run/run-tidy-lanes.ts +2 -1
  499. package/scripts/run/run-tidy-stashes.ts +12 -12
  500. package/scripts/run/run-wake-cli.ts +2 -3
  501. package/scripts/run/run-wake-loop.ts +2 -2
  502. package/scripts/run/run-wake.ts +2 -4
  503. package/scripts/run/run-watcher-guard-cli.ts +0 -4
  504. package/scripts/run/run-watcher-guard.ts +9 -7
  505. package/scripts/run/run-watcher-hook.ts +1 -1
  506. package/scripts/safe-chain/ci-installer-pin.ts +11 -5
  507. package/scripts/safe-chain/project-config.ts +1 -1
  508. package/scripts/security/security-audit-provision-logic.ts +0 -1
  509. package/scripts/security/security-audit-provision.ts +3 -2
  510. package/scripts/security/security-audit.ts +0 -1
  511. package/scripts/security/security-updates-logic.ts +0 -1
  512. package/scripts/sonar/sonar-hotspots-cli.ts +10 -52
  513. package/scripts/sonar/sonar-hotspots.ts +0 -1
  514. package/scripts/sonar/sonar-new-code-cli.ts +150 -0
  515. package/scripts/sonar/sonar-new-code.ts +79 -0
  516. package/scripts/sonar/sonar-project.ts +97 -0
  517. package/scripts/split/split-assess-cli.ts +1 -1
  518. package/scripts/split/split-assess.ts +2 -5
  519. package/scripts/sync/managed-config-scope-cli.ts +1 -1
  520. package/scripts/sync/skill-migration.ts +0 -1
  521. package/scripts/sync/sync-hook-safety.ts +2 -3
  522. package/scripts/sync/sync.ts +1 -8
  523. package/scripts/sync/template-source-logic.ts +0 -1
  524. package/scripts/sync/workflow-pin-logic.ts +16 -28
  525. package/scripts/test/test-declared-logic.ts +0 -1
  526. package/scripts/test/test-declared.ts +0 -2
  527. package/scripts/test/test-red-commit.ts +2 -2
  528. package/scripts/test/test-red.ts +14 -7
  529. package/scripts/test/test-type-logic.ts +1 -1
  530. package/scripts/test/unit-worker-share.ts +7 -16
  531. package/scripts/time-runtime/time-batch-guard.ts +1 -2
  532. package/scripts/time-runtime/time-bundle-call.ts +0 -1
  533. package/scripts/time-runtime/time-bundles.ts +0 -4
  534. package/scripts/time-runtime/time-density-hook.ts +0 -2
  535. package/scripts/time-runtime/time-followup-stage.ts +1 -1
  536. package/scripts/time-runtime/time-format.ts +0 -73
  537. package/scripts/time-runtime/time-round-trips.ts +0 -4
  538. package/scripts/time-runtime/time-single-check.ts +1 -1
  539. package/scripts/time-runtime/time-spans.ts +1 -1
  540. package/scripts/time-runtime/time-transcript-line.ts +1 -2
  541. package/scripts/ui/ui-routes-cli.ts +0 -5
  542. package/scripts/ui/ui-routes.ts +0 -5
  543. package/scripts/version/effective-upstream.ts +2 -2
  544. package/scripts/version/latest-corepack.ts +7 -9
  545. package/scripts/version/latest-scope-cli.ts +0 -2
  546. package/scripts/version/latest-update.ts +0 -2
  547. package/scripts/version/npm-registry.ts +2 -2
  548. package/scripts/version/publishable-range-check.ts +1 -1
  549. package/scripts/version/release-hold.ts +0 -4
  550. package/scripts/version/running-binary.ts +2 -2
  551. package/scripts/version/version-check-logic.ts +0 -2
  552. package/scripts/version/version-remote.ts +3 -3
  553. package/scripts/version/version-targets.ts +4 -4
  554. package/templates/sonar-project.properties +28 -1
  555. package/templates/workflows/dependabot-auto-merge.yml +5 -3
  556. package/templates/workflows/github-release.yml +81 -0
  557. package/prompts/collaboration-workflow/cross-repo-epic.md +0 -5
  558. package/prompts/collaboration-workflow/epic-audit.md +0 -5
  559. package/prompts/collaboration-workflow/epic-bundle.md +0 -5
  560. package/scripts/init/plugin-install-hint.ts +0 -47
  561. package/scripts/version/parse-json.ts +0 -13
  562. /package/scripts/{git → followup}/git-followup-stages.ts +0 -0
  563. /package/scripts/{git → gh}/git-gh-api-path.ts +0 -0
  564. /package/scripts/{git → gh}/git-gh-command.ts +0 -0
  565. /package/scripts/{git → gh}/git-gh-issue-write.ts +0 -0
  566. /package/scripts/{git → gh}/git-gh-issue.ts +0 -0
  567. /package/scripts/{git → gh}/git-gh-pr-auto-merge.ts +0 -0
  568. /package/scripts/{git → gh}/git-gh-pr-snapshot.ts +0 -0
  569. /package/scripts/{git → gh}/git-gh-reachability.ts +0 -0
  570. /package/scripts/{git → gh}/git-gh-repo.ts +0 -0
  571. /package/scripts/{git → gh}/git-gh-rest-state.ts +0 -0
  572. /package/scripts/{git → gh}/git-pr-checks-watch.ts +0 -0
  573. /package/scripts/{git → gh}/git-pr-error.ts +0 -0
  574. /package/scripts/{git → gh}/git-pr-messages.ts +0 -0
  575. /package/scripts/{git → gh}/github-issue-url.ts +0 -0
  576. /package/scripts/git/{stash-orphans.ts → stash/stash-orphans.ts} +0 -0
  577. /package/scripts/{git → issue}/issue-reference.ts +0 -0
  578. /package/scripts/{git → lib}/animation-helpers.ts +0 -0
  579. /package/scripts/{git → lib}/git-animation.ts +0 -0
  580. /package/scripts/{git → notify}/git-notify.ts +0 -0
  581. /package/scripts/{git → notify}/telegram-test-logic.ts +0 -0
@@ -1,6 +1,8 @@
1
- import { EPIC_LABEL, has_label_name } from '#scripts/git/issue-labels'
1
+ import { EPIC_LABEL, has_label_name, NEEDS_DECISION_LABEL } from '#scripts/issue/issue-labels'
2
+ import type { IssueState } from '#scripts/issue/issue-state'
2
3
  import { issue_state_cli } from '#scripts/issue/issue-state-cli'
3
4
  import type { RunCarry } from '#scripts/run/run-carry'
5
+ import type { MergeResult } from '#scripts/run/run-merge-cli'
4
6
  import { backlog_budget } from './backlog-budget'
5
7
  import type { DriveState, OfferRead } from './backlog-drive'
6
8
  import { backlog_drive_named } from './backlog-drive-named'
@@ -44,6 +46,15 @@ function budget_offer(
44
46
  }
45
47
  }
46
48
 
49
+ // The outcome a named issue has already reached without this run dispatching it: closed is merged, and
50
+ // a `needs-decision` park waits on a person, so re-dispatching it only repeats the stop it parked on
51
+ // (joshuafolkken/kit#2965). Either is booked done rather than offered.
52
+ function settled_outcome(state: IssueState): MergeResult['outcome'] | undefined {
53
+ if (state.state.toUpperCase() === 'CLOSED') return 'merged'
54
+
55
+ return has_label_name(state.labels, NEEDS_DECISION_LABEL) ? 'parked' : undefined
56
+ }
57
+
47
58
  async function classify(issue: string, named: OfferRead, owner: string): Promise<OfferRead> {
48
59
  const result = await issue_state_cli.read_issue(issue)
49
60
 
@@ -51,8 +62,10 @@ async function classify(issue: string, named: OfferRead, owner: string): Promise
51
62
  return { verdict: 'issue-state', issues: [], retries: NO_RETRIES }
52
63
  }
53
64
 
54
- if (result.state.state.toUpperCase() === 'CLOSED') {
55
- await backlog_drive_named.mark_done(issue, { outcome: 'merged', code: 0, token: 'none' }, owner)
65
+ const outcome = settled_outcome(result.state)
66
+
67
+ if (outcome !== undefined) {
68
+ await backlog_drive_named.mark_done(issue, { outcome, code: 0, token: 'none' }, owner)
56
69
 
57
70
  return { verdict: 'wait', issues: [], retries: NO_RETRIES }
58
71
  }
@@ -1,4 +1,4 @@
1
- import { has_label_name, NEEDS_DECISION_LABEL } from '#scripts/git/issue-labels'
1
+ import { has_label_name, NEEDS_DECISION_LABEL } from '#scripts/issue/issue-labels'
2
2
  import { issue_state_cli } from '#scripts/issue/issue-state-cli'
3
3
  import { run_carry, type RunCarry } from '#scripts/run/run-carry'
4
4
  import type { RunEvent } from '#scripts/run/run-event-stream'
@@ -94,6 +94,7 @@ async function reconcile(
94
94
  for (const issue of completed) {
95
95
  const outcome = parked.has(issue) ? 'parked' : 'merged'
96
96
 
97
+ // eslint-disable-next-line no-await-in-loop -- each mark rewrites the same carry file
97
98
  await mark_done(String(issue), { outcome, code: 0, token: 'none' }, owner)
98
99
  }
99
100
  }
@@ -16,6 +16,9 @@
16
16
  // **Everything it touches is a port**, the pattern `run-wake-loop.ts` set, so the sequencing is pinned
17
17
  // without a process, a network or a clock.
18
18
 
19
+ import type { LaunchOutcome } from '#scripts/lane/lane-launch-cli'
20
+ import type { MergeResult } from '#scripts/run/run-merge-cli'
21
+
19
22
  const RUN_VERDICT = 'run'
20
23
  const STOP_VERDICT = 'stop'
21
24
  // The `run:merge` tokens that end the loop at once: a hand-off, a person's stop, the environment down,
@@ -32,6 +35,7 @@ const IMMEDIATE_TOKENS: ReadonlySet<string> = new Set([
32
35
  // and the children still in flight are collected before the loop ends (joshuafolkken/kit#2881).
33
36
  const HANDOFF_TOKENS: ReadonlySet<string> = new Set([...IMMEDIATE_TOKENS, STOP_VERDICT])
34
37
  const RESUMED_TOKEN = 'resumed'
38
+ const MERGED_OUTCOME = 'merged'
35
39
  const WATCH_VERDICT = 'watch'
36
40
  // The verdicts the loop acts on without the parent. Any other is handed back as it was printed.
37
41
  const KNOWN_VERDICTS: ReadonlySet<string> = new Set([
@@ -41,6 +45,9 @@ const KNOWN_VERDICTS: ReadonlySet<string> = new Set([
41
45
  'wait',
42
46
  ])
43
47
  const NO_RETRIES = 0
48
+ const NO_FREE_LANES = 0
49
+ const LAUNCHED = 'launched'
50
+ const UNOPENED = 'unopened'
44
51
 
45
52
  interface OfferRead {
46
53
  verdict: string
@@ -57,7 +64,9 @@ interface OfferRead {
57
64
  interface DriveState {
58
65
  // The children this run has in flight — seeded from the open lanes, so a restarted loop resumes them.
59
66
  in_flight: Array<string>
60
- // Every child collected, fed back to `backlog:offer` because GitHub closes a merged issue late.
67
+ // Every child merged, fed back to `backlog:offer` because GitHub closes a merged issue late. A parked
68
+ // child is left out: its labels classify it, so one a person released is offered again
69
+ // (joshuafolkken/kit#3041).
61
70
  exclude: Array<string>
62
71
  // When the run last did something, handed to `backlog:budget` as `--active`.
63
72
  active: string
@@ -80,14 +89,20 @@ interface DriveEnd {
80
89
  is_finish?: boolean | undefined
81
90
  }
82
91
 
92
+ type Collected = Pick<MergeResult, 'token' | 'outcome'>
93
+
83
94
  interface DrivePorts {
84
95
  // Whether a child's process has confirmed-ended — `lane:await`'s re-confirmed check in production.
85
96
  is_finished: (issue: string) => boolean
86
- // `run:merge <N>`'s first stdout token.
87
- merge: (issue: string) => Promise<string>
97
+ // `run:merge <N>`'s first stdout token and the outcome it handled the child as.
98
+ merge: (issue: string) => Promise<Collected>
88
99
  // `backlog:offer`'s answer for the state, or `undefined` when it exited non-zero.
89
100
  offer: (state: DriveState) => Promise<OfferRead | undefined>
90
- launch: (issue: string) => Promise<boolean>
101
+ // Where `lane:launch`'s chain ended — `launched`, `unopened` (no lane taken) or `failed` (one taken).
102
+ launch: (issue: string) => Promise<LaunchOutcome['kind']>
103
+ // The lanes free right now — `backlog_ready.drive_free_lane_count` in production, the limit less the
104
+ // open lanes.
105
+ free_lanes: () => Promise<number>
91
106
  now: () => Date
92
107
  }
93
108
 
@@ -150,29 +165,40 @@ function merge_stopped(issue: string, state: DriveState): DriveState {
150
165
  }
151
166
  }
152
167
 
153
- // The child collected and excluded, and — unless its cut was resumed in place — out of flight.
168
+ // Only a merged child is excluded: `backlog:next` may still read it OPEN. Any other is classified by
169
+ // its labels, so excluding it would hide a child a person released for the rest of the process.
170
+ function excluded(issue: string, outcome: Collected['outcome'], state: DriveState): Array<string> {
171
+ if (outcome !== MERGED_OUTCOME || state.exclude.includes(issue)) return state.exclude
172
+
173
+ return [...state.exclude, issue]
174
+ }
175
+
176
+ // The child collected, and — unless its cut was resumed in place — out of flight.
154
177
  function collected_state(
155
178
  issue: string,
156
- token: string,
179
+ collected: Collected,
157
180
  state: DriveState,
158
181
  active: string,
159
182
  ): DriveState {
160
183
  const in_flight =
161
- token === RESUMED_TOKEN ? state.in_flight : state.in_flight.filter((item) => item !== issue)
162
- const exclude = state.exclude.includes(issue) ? state.exclude : [...state.exclude, issue]
184
+ collected.token === RESUMED_TOKEN
185
+ ? state.in_flight
186
+ : state.in_flight.filter((item) => item !== issue)
187
+ const exclude = excluded(issue, collected.outcome, state)
163
188
 
164
189
  return { ...state, in_flight, exclude, active }
165
190
  }
166
191
 
167
192
  // One finished child: handed back on an immediate token, otherwise collected.
168
193
  async function collect(issue: string, state: DriveState, ports: DrivePorts): Promise<PassResult> {
169
- const token = await ports.merge(issue)
194
+ const collected = await ports.merge(issue)
195
+ const { token } = collected
170
196
 
171
197
  // An empty first line is a `run:merge` that failed before printing one: never read as a collection.
172
198
  if (token === '') return ended('merge', state, undefined, issue)
173
199
  if (IMMEDIATE_TOKENS.has(token)) return ended('merge', state, token, issue)
174
200
 
175
- const next = collected_state(issue, token, state, ports.now().toISOString())
201
+ const next = collected_state(issue, collected, state, ports.now().toISOString())
176
202
 
177
203
  return { kind: 'continue', state: token === STOP_VERDICT ? merge_stopped(issue, next) : next }
178
204
  }
@@ -182,6 +208,7 @@ async function collect_finished(state: DriveState, ports: DrivePorts): Promise<P
182
208
  let current = state
183
209
 
184
210
  for (const issue of finished) {
211
+ // eslint-disable-next-line no-await-in-loop -- each collect starts from the state the previous one returned
185
212
  const result = await collect(issue, current, ports)
186
213
 
187
214
  if (result.kind === 'end') return { ...result, state: current }
@@ -192,22 +219,55 @@ async function collect_finished(state: DriveState, ports: DrivePorts): Promise<P
192
219
  return { kind: 'continue', state: current }
193
220
  }
194
221
 
222
+ // A `lane:open` refused with every lane taken is a wait, not a judgement (joshuafolkken/kit#3027): the
223
+ // next offer after a lane frees retries it. A step failing after the lane opened is always handed back —
224
+ // that lane holds the last seat itself, so the free count would read the failure as a full pool.
225
+ async function refused(
226
+ issue: string,
227
+ outcome: LaunchOutcome['kind'],
228
+ state: DriveState,
229
+ ports: DrivePorts,
230
+ ): Promise<PassResult> {
231
+ if (outcome !== UNOPENED) return ended('launch', state, undefined, issue)
232
+ if ((await ports.free_lanes()) <= NO_FREE_LANES) return { kind: 'continue', state }
233
+
234
+ return ended('launch', state, undefined, issue)
235
+ }
236
+
237
+ // **No more launches than free lanes** (joshuafolkken/kit#3027). `backlog:offer` lists every ready issue
238
+ // without reading the lanes, so launching all of them overran `JOSH_LANE_LIMIT` until `lane:open` ran
239
+ // out of seats. The free count is read once, before the first launch, because every launch here opens
240
+ // a lane the count would otherwise have to be told about.
241
+ //
242
+ // **Only a launch is activity** (joshuafolkken/kit#3027): a pass that started nothing — every lane taken
243
+ // — keeps `active` where it was, or the once-a-minute offer would restart the idle budget for good.
244
+ function launched(state: DriveState, in_flight: Array<string>, ports: DrivePorts): DriveState {
245
+ if (in_flight.length === state.in_flight.length) return { ...state, in_flight }
246
+
247
+ return { ...state, in_flight, active: ports.now().toISOString() }
248
+ }
249
+
195
250
  async function launch_all(
196
251
  issues: ReadonlyArray<string>,
197
252
  state: DriveState,
198
253
  ports: DrivePorts,
199
254
  ): Promise<PassResult> {
200
255
  const in_flight = [...state.in_flight]
256
+ const free = await ports.free_lanes()
201
257
 
202
- for (const issue of issues) {
203
- const is_launched = await ports.launch(issue)
258
+ for (const issue of issues.slice(0, free)) {
259
+ // eslint-disable-next-line no-await-in-loop -- lanes launch in order and the first refusal ends the pass
260
+ const outcome = await ports.launch(issue)
204
261
 
205
- if (!is_launched) return ended('launch', { ...state, in_flight }, undefined, issue)
262
+ if (outcome !== LAUNCHED) {
263
+ // eslint-disable-next-line no-await-in-loop -- lanes launch in order and the first refusal ends the pass
264
+ return await refused(issue, outcome, launched(state, in_flight, ports), ports)
265
+ }
206
266
 
207
267
  in_flight.push(issue)
208
268
  }
209
269
 
210
- return { kind: 'continue', state: { ...state, in_flight, active: ports.now().toISOString() } }
270
+ return { kind: 'continue', state: launched(state, in_flight, ports) }
211
271
  }
212
272
 
213
273
  // A watch with nothing in flight is the drain: `run:step` owes the retrospective there, so it is the
@@ -337,7 +397,9 @@ async function run_loop(
337
397
  let step = await loop_step(first, config, ports)
338
398
 
339
399
  while (step.kind === 'next') {
400
+ // eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
340
401
  await ports.sleep(config.poll_ms)
402
+ // eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
341
403
  step = await loop_step(step.run, config, ports)
342
404
  }
343
405
 
@@ -348,10 +410,8 @@ async function run_loop(
348
410
 
349
411
  const backlog_drive = {
350
412
  HANDOFF_TOKENS,
351
- collect,
352
413
  initial_state,
353
414
  merge_stopped,
354
- on_verdict,
355
415
  run_loop,
356
416
  run_pass,
357
417
  }
@@ -141,9 +141,6 @@ function epic_item_outcome(
141
141
  }
142
142
 
143
143
  const backlog_named = {
144
- BACKLOG_KIND,
145
- END_KIND,
146
- NAMED_KIND,
147
144
  NOTHING_TO_RUN,
148
145
  after_failure,
149
146
  epic_item_outcome,
@@ -9,8 +9,9 @@ import { epic_next } from '#scripts/epic/epic-next'
9
9
  import { epic_next_read, type EpicRead } from '#scripts/epic/epic-next-read'
10
10
  import type { EpicView } from '#scripts/epic/epic-next-views'
11
11
  import { epic_report, type EpicNextResult, type EpicVerdict } from '#scripts/epic/epic-report'
12
+ import { epic_solo_stale } from '#scripts/epic/epic-solo-stale'
12
13
  import { epic_triage, type TriageVerdict } from '#scripts/epic/epic-triage'
13
- import { git_gh_command } from '#scripts/git/git-gh-command'
14
+ import { git_gh_command } from '#scripts/gh/git-gh-command'
14
15
  import { PROJECT_ROOT } from '#scripts/init/init-paths'
15
16
  import { issue_citation } from '#scripts/rules/issue-citation'
16
17
  import { backlog_defect_priority } from './backlog-defect-priority'
@@ -294,7 +295,13 @@ async function gate_solo(result: EpicNextResult, context: PoolContext): Promise<
294
295
  if (result.verdict !== 'run') return result
295
296
 
296
297
  const { repo } = context
297
- const read = await epic_busy.read_repository(repo)
298
+ const { read, notice } = await epic_solo_stale.release(
299
+ await epic_busy.read_repository(repo),
300
+ repo,
301
+ )
302
+
303
+ if (notice !== undefined) console.error(notice)
304
+
298
305
  const gated = backlog_rank.gate(result, read, repo, standalone_keys(context))
299
306
 
300
307
  if (gated.notice !== undefined) console.error(gated.notice)
@@ -410,23 +417,10 @@ const backlog_next = {
410
417
  RETRY_MESSAGE,
411
418
  READ_FAILURES,
412
419
  VERDICT_TOKENS,
413
- tokens_of,
414
- warn_epic_gap,
415
- warn_gaps,
416
- report,
417
- combine,
418
- views_from,
419
420
  resolve,
420
421
  standalone_keys,
421
- is_transport_failure,
422
- report_retry,
423
- report_triage,
424
422
  context_of,
425
- answer_pool,
426
- report_none,
427
- answer,
428
423
  run,
429
- main,
430
424
  }
431
425
 
432
426
  if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
@@ -262,16 +262,11 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
262
262
 
263
263
  const backlog_offer_cli = {
264
264
  JSON_KEY,
265
- USAGE,
266
265
  budget_argv,
267
266
  counts_of,
268
- emit,
269
- main,
270
- mark_drain,
271
267
  next_argv,
272
268
  read_values,
273
269
  run,
274
- to_tokens,
275
270
  }
276
271
 
277
272
  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,7 @@ 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 { has_label_name, IN_PROGRESS_LABEL, RUN_SOLO_LABEL } from '#scripts/issue/issue-labels'
7
7
  import type { OutOfScopeRow } from './backlog-scope'
8
8
 
9
9
  // The plan a person reads before a `backlogrun` starts (joshuafolkken/kit#1652).
@@ -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 }
@@ -21,6 +21,13 @@ interface ReadyPorts {
21
21
  ready_issues: () => Promise<ReadonlyArray<string>>
22
22
  }
23
23
 
24
+ async function free_under(limit: number): Promise<number> {
25
+ const lanes = await lane_registry.list_lanes()
26
+ const live = lanes.filter((lane) => !lane.is_stranded).length
27
+
28
+ return lane_capacity.free_lanes(limit, live)
29
+ }
30
+
24
31
  // Free lanes right now: the limit less the live lanes. An unreadable limit reads as no free lane — the
25
32
  // safe direction, since both the stall and the ready line need a free lane and reporting one that is
26
33
  // not there is the false positive neither may raise.
@@ -35,10 +42,18 @@ async function free_lane_count(): Promise<number> {
35
42
 
36
43
  if (limit.kind !== 'limit') return NO_FREE
37
44
 
38
- const lanes = await lane_registry.list_lanes()
39
- const live = lanes.filter((lane) => !lane.is_stranded).length
45
+ return await free_under(limit.limit)
46
+ }
47
+
48
+ // **The drive's count throws on an unreadable limit** (joshuafolkken/kit#3027). The drive launches no
49
+ // more than this count, so the safe-direction zero above would leave it launching nothing and reporting
50
+ // nothing for good; a bad setting is the hard error `lane_capacity` says it is, ending the drive loudly.
51
+ async function drive_free_lane_count(): Promise<number> {
52
+ const limit = lane_capacity.lane_limit()
53
+
54
+ if (limit.kind !== 'limit') throw new Error(limit.problem)
40
55
 
41
- return lane_capacity.free_lanes(limit.limit, live)
56
+ return await free_under(limit.limit)
42
57
  }
43
58
 
44
59
  // **A `--only` run has no pool to drain** (joshuafolkken/kit#2472). `backlog:next` lists the opted-in
@@ -135,6 +150,7 @@ const backlog_ready = {
135
150
  read_backlog_next,
136
151
  print_offer_hint,
137
152
  free_lane_count,
153
+ drive_free_lane_count,
138
154
  drains_pool,
139
155
  print_ready_line,
140
156
  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 }