@joshuafolkken/kit 1.1166.0 → 1.1229.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 (437) hide show
  1. package/.claude/.claude-plugin/plugin.json +1 -1
  2. package/.claude/settings.json +2 -2
  3. package/.claude/skills/dependency-update/SKILL.md +4 -8
  4. package/.claude/skills/epic-commands/SKILL.md +2 -2
  5. package/.claude/skills/epic-commands/epic-bundle.md +1 -1
  6. package/.claude/skills/workflow-commands/SKILL.md +2 -4
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +6 -4
  8. package/.claude/skills/workflow-commands/backlogrun-lanes.md +9 -5
  9. package/.claude/skills/workflow-commands/backlogrun-park.md +29 -9
  10. package/.claude/skills/workflow-commands/backlogrun-progress.md +7 -2
  11. package/.claude/skills/workflow-commands/backlogrun-recovery.md +4 -3
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +24 -15
  13. package/.claude/skills/workflow-commands/chain-rule.md +1 -1
  14. package/.claude/skills/workflow-commands/delegation.md +2 -2
  15. package/.claude/skills/workflow-commands/followup.md +5 -0
  16. package/.claude/skills/workflow-commands/fullrun-steps.md +1 -1
  17. package/.claude/skills/workflow-commands/halfrun.md +1 -1
  18. package/.claude/skills/workflow-commands/issue-scout.md +1 -1
  19. package/.claude/skills/workflow-commands/kickoff.md +1 -1
  20. package/.claude/skills/workflow-commands/observation-ledger.md +3 -3
  21. package/.claude/skills/workflow-commands/pre-gate-cut.md +10 -5
  22. package/.claude/skills/workflow-commands/prerequisite.md +2 -2
  23. package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
  24. package/.claude/skills/workflow-commands/working-tree-hold.md +1 -1
  25. package/.codex/hooks.json +2 -2
  26. package/.cursorrules +6 -41
  27. package/.github/actions/setup-node/action.yml +1 -1
  28. package/.github/workflows/auto-tag.yml +3 -4
  29. package/.github/workflows/ci.yml +47 -33
  30. package/.github/workflows/dependabot-auto-merge.yml +13 -6
  31. package/.github/workflows/publish.yml +48 -4
  32. package/.github/workflows/sonar-qube.yml +3 -0
  33. package/.pnpmfile.mjs +4 -3
  34. package/.prettierignore +8 -2
  35. package/CLAUDE.md +18 -20
  36. package/README.md +26 -19
  37. package/SECURITY.md +15 -1
  38. package/dist/CLAUDE.md +18 -20
  39. package/dist/commands/document-section-cli.js +734 -0
  40. package/dist/hooks/audit-provision.js +346 -0
  41. package/dist/hooks/batch-guard.js +5 -4
  42. package/dist/hooks/{chunk-DYAVAM6S.js → chunk-55HHG5PX.js} +1405 -631
  43. package/dist/hooks/{chunk-A6P7PN7P.js → chunk-5VMKCCC4.js} +25 -10
  44. package/dist/hooks/chunk-5VNDSNG3.js +12 -0
  45. package/dist/hooks/{chunk-5KTCMCOT.js → chunk-6HJJXRBX.js} +4 -2
  46. package/dist/hooks/chunk-CDY4NFQG.js +15 -0
  47. package/dist/hooks/chunk-ELCN5LCH.js +135 -0
  48. package/dist/hooks/{chunk-ENA7P5FB.js → chunk-F56MFS4B.js} +3 -3
  49. package/dist/hooks/{chunk-ANJ2WGFD.js → chunk-FIVDHQGT.js} +7 -6
  50. package/dist/hooks/{chunk-3V37IID6.js → chunk-JBBMAPC4.js} +23 -14
  51. package/dist/hooks/{chunk-GU5MATVE.js → chunk-JUDKDCDP.js} +499 -389
  52. package/dist/hooks/{chunk-ZDZ555YH.js → chunk-NV2JRZZO.js} +743 -909
  53. package/dist/hooks/{chunk-V2BTOZHT.js → chunk-RNWHN5BP.js} +3 -3
  54. package/dist/hooks/{chunk-URJA6XY4.js → chunk-TQNPDZNH.js} +4 -4
  55. package/dist/hooks/{chunk-GYNGP7HI.js → chunk-VC3PZPZO.js} +1 -1
  56. package/dist/hooks/codex-hook-adapter.js +14 -12
  57. package/dist/hooks/duplicate-read-guard.js +6 -5
  58. package/dist/hooks/format-edited.js +4 -3
  59. package/dist/hooks/inputs.json +232 -210
  60. package/dist/hooks/investigation-guard.js +6 -5
  61. package/dist/hooks/pretool-guard.js +12 -10
  62. package/dist/hooks/session-lang.js +2 -4
  63. package/dist/hooks/stop-guard.js +81 -59
  64. package/dist/josh.js +872 -75
  65. package/dist/version/index.d.ts +7 -2
  66. package/dist/version/index.js +152 -75
  67. package/eslint/base.js +23 -1
  68. package/eslint/rules/code-quality.js +3 -0
  69. package/eslint/rules/early-return-one-liner.js +98 -0
  70. package/eslint/rules/unicorn.js +16 -1
  71. package/package.json +7 -6
  72. package/pnpm-workspace.yaml +9 -4
  73. package/prettier/basic.d.ts +3 -1
  74. package/prettier/index.d.ts +3 -1
  75. package/prettier/static.d.ts +3 -1
  76. package/prompts/coding-standards.md +1 -1
  77. package/prompts/collaboration-workflow/file-edits.md +4 -4
  78. package/prompts/collaboration-workflow/glossary.md +1 -1
  79. package/prompts/collaboration-workflow/operating-rules.md +17 -9
  80. package/prompts/collaboration-workflow/overview.md +2 -2
  81. package/prompts/collaboration-workflow/principles.md +14 -12
  82. package/prompts/collaboration-workflow/report-format.md +1 -1
  83. package/prompts/collaboration-workflow/residency.md +1 -1
  84. package/prompts/collaboration-workflow/rule-delivery.md +6 -6
  85. package/prompts/collaboration-workflow/shell-body.md +6 -6
  86. package/prompts/collaboration-workflow/turn-batching.md +1 -1
  87. package/prompts/collaboration-workflow/upstream-interrupt.md +12 -2
  88. package/prompts/collaboration-workflow/wip-cap.md +10 -10
  89. package/prompts/review-rubric.md +1 -2
  90. package/prompts/review.md +1 -1
  91. package/scripts/agent/agent-headless.ts +29 -0
  92. package/scripts/agent/agent-launch-environment.ts +6 -2
  93. package/scripts/agent/codex-agent-argv.ts +2 -1
  94. package/scripts/auto-ok/auto-ok-cli.ts +1 -1
  95. package/scripts/backlog/backlog-arrival.ts +3 -3
  96. package/scripts/backlog/backlog-budget.ts +1 -1
  97. package/scripts/backlog/backlog-drive-args.ts +135 -0
  98. package/scripts/backlog/backlog-drive-cli.ts +11 -137
  99. package/scripts/backlog/backlog-drive-launch.ts +39 -0
  100. package/scripts/backlog/backlog-drive-named-offer.ts +3 -5
  101. package/scripts/backlog/backlog-drive-named.ts +3 -3
  102. package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
  103. package/scripts/backlog/backlog-drive-owner.ts +1 -1
  104. package/scripts/backlog/backlog-drive-restore.ts +1 -1
  105. package/scripts/backlog/backlog-drive-retrospective.ts +1 -1
  106. package/scripts/backlog/backlog-drive.ts +1 -1
  107. package/scripts/backlog/backlog-next.ts +31 -9
  108. package/scripts/backlog/backlog-offer-cli.ts +6 -6
  109. package/scripts/backlog/backlog-offer.ts +1 -1
  110. package/scripts/backlog/backlog-plan-cli.ts +7 -6
  111. package/scripts/backlog/backlog-pool.ts +57 -11
  112. package/scripts/backlog/backlog-rank.ts +18 -9
  113. package/scripts/backlog/backlog-ready.ts +1 -1
  114. package/scripts/backlog/backlog-restructure.ts +152 -0
  115. package/scripts/backlog/backlog-scope.ts +1 -1
  116. package/scripts/backlog/backlog-stalled-detect.ts +2 -2
  117. package/scripts/backlog/backlog-stalled.ts +1 -1
  118. package/scripts/backlog/backlog-waves.ts +15 -17
  119. package/scripts/build/build-codex-hooks.ts +3 -1
  120. package/scripts/build/build-commands.ts +66 -0
  121. package/scripts/build/build-hooks.ts +2 -1
  122. package/scripts/build/build-library.ts +12 -3
  123. package/scripts/build/build.ts +70 -0
  124. package/scripts/build/local-bin.ts +3 -13
  125. package/scripts/cost-runtime/context-cut-threshold.ts +1 -9
  126. package/scripts/cost-runtime/cost-verdict.ts +15 -28
  127. package/scripts/delegation/investigation-reads.ts +3 -1
  128. package/scripts/discovery/repo-origin.ts +5 -5
  129. package/scripts/doctor/doctor-consumer.ts +2 -2
  130. package/scripts/doctor/doctor-io.ts +2 -3
  131. package/scripts/document/capped-print-part.ts +30 -0
  132. package/scripts/document/capped-print.ts +3 -4
  133. package/scripts/document/document-byte-budget.ts +11 -2
  134. package/scripts/document/document-scan.ts +117 -0
  135. package/scripts/document/document-section.ts +143 -16
  136. package/scripts/document/entry-read-budget.ts +5 -3
  137. package/scripts/document/entry-read-set.ts +10 -89
  138. package/scripts/document/read-set-cost.ts +98 -0
  139. package/scripts/epic/epic-add-body.ts +1 -0
  140. package/scripts/epic/epic-audit-checks.ts +1 -1
  141. package/scripts/epic/epic-audit-rationale.ts +4 -3
  142. package/scripts/epic/epic-bundle-cli.ts +14 -3
  143. package/scripts/epic/epic-bundle-poll.ts +41 -0
  144. package/scripts/epic/epic-busy.ts +1 -1
  145. package/scripts/epic/epic-candidate-confirm.ts +3 -2
  146. package/scripts/epic/epic-classify.ts +1 -1
  147. package/scripts/epic/epic-cli-argv.ts +78 -46
  148. package/scripts/epic/epic-cli-remove.ts +11 -19
  149. package/scripts/epic/epic-cli.ts +74 -73
  150. package/scripts/epic/epic-close-comment.ts +1 -1
  151. package/scripts/epic/epic-close.ts +1 -1
  152. package/scripts/epic/epic-cross-repo.ts +5 -5
  153. package/scripts/epic/epic-graph.ts +1 -1
  154. package/scripts/epic/epic-index.ts +1 -1
  155. package/scripts/epic/epic-issue.ts +2 -6
  156. package/scripts/epic/epic-lane-offer.ts +2 -2
  157. package/scripts/epic/epic-next.ts +29 -42
  158. package/scripts/epic/epic-solo-stale.ts +1 -1
  159. package/scripts/epic/epic-triage.ts +8 -4
  160. package/scripts/epic/epic-validate.ts +1 -1
  161. package/scripts/followup/git-followup-finish.ts +2 -2
  162. package/scripts/followup/git-followup-label.ts +2 -2
  163. package/scripts/followup/git-followup-merged.ts +2 -2
  164. package/scripts/followup/git-followup-stages.ts +9 -0
  165. package/scripts/followup/git-pr-followup-checks.ts +142 -0
  166. package/scripts/followup/git-pr-followup.ts +5 -130
  167. package/scripts/gate/core-budget.ts +69 -1
  168. package/scripts/gate/gate-plan.ts +47 -7
  169. package/scripts/gate/gate-skip.ts +38 -7
  170. package/scripts/gate/hook-gate-reuse.ts +12 -10
  171. package/scripts/gate/pre-commit-type-check.ts +4 -1
  172. package/scripts/gate/project-checks.ts +6 -9
  173. package/scripts/gate/type-check-step.ts +2 -3
  174. package/scripts/gate/verification-gate.ts +27 -8
  175. package/scripts/gh/git-gh-api-path.ts +2 -2
  176. package/scripts/gh/git-gh-issue-rest.ts +3 -3
  177. package/scripts/gh/git-gh-issue-write.ts +53 -7
  178. package/scripts/gh/git-gh-issue.ts +5 -3
  179. package/scripts/gh/git-gh-pr-read.ts +68 -19
  180. package/scripts/gh/git-gh-pr-rest.ts +1 -1
  181. package/scripts/gh/git-gh-pr.ts +5 -1
  182. package/scripts/gh/git-pr-ai-review.ts +1 -1
  183. package/scripts/gh/git-pr-checks-eval.ts +9 -3
  184. package/scripts/gh/git-pr-checks-parse.ts +1 -1
  185. package/scripts/gh/git-pr-checks-watch.ts +6 -5
  186. package/scripts/gh/git-pr-checks.ts +18 -6
  187. package/scripts/gh/git-pr-coderabbit.ts +1 -1
  188. package/scripts/gh/git-pr-error.ts +1 -3
  189. package/scripts/gh/git-pr.ts +9 -13
  190. package/scripts/gh/github-issue-url.ts +2 -2
  191. package/scripts/git/constants.ts +12 -6
  192. package/scripts/git/git-command.ts +20 -218
  193. package/scripts/git/git-diff-reads.ts +225 -0
  194. package/scripts/git/git-error.ts +4 -12
  195. package/scripts/git/git-pre-push-hook.ts +139 -0
  196. package/scripts/git/git-prompt.ts +2 -6
  197. package/scripts/git/{schemas.ts → git-schemas.ts} +2 -0
  198. package/scripts/git/git-spawn-sync.ts +3 -1
  199. package/scripts/git/git-spawn.ts +1 -1
  200. package/scripts/git/git-staging.ts +4 -6
  201. package/scripts/git/git-status.ts +3 -9
  202. package/scripts/git/main-merge.ts +57 -21
  203. package/scripts/hooks/codex-hook-adapter.ts +1 -1
  204. package/scripts/hooks/edited-cspell.ts +2 -4
  205. package/scripts/hooks/format-edited-file.ts +3 -12
  206. package/scripts/hooks/pre-push-unit.ts +31 -9
  207. package/scripts/hooks/reserved-run.ts +2 -2
  208. package/scripts/hooks/run-hook.sh +5 -4
  209. package/scripts/hooks/stop-guard.ts +5 -3
  210. package/scripts/init/init-actions.ts +0 -5
  211. package/scripts/init/init-ai-copy.ts +13 -2
  212. package/scripts/init/init-logic-json-merge.ts +19 -0
  213. package/scripts/init/init-logic-secretlint.ts +7 -7
  214. package/scripts/init/init-logic-workspace.ts +41 -2
  215. package/scripts/init/init-logic.ts +16 -26
  216. package/scripts/init/init.ts +5 -15
  217. package/scripts/init/initial-commit.ts +4 -4
  218. package/scripts/init/kit-development-versions.ts +40 -0
  219. package/scripts/init/kit-setup-state.ts +2 -2
  220. package/scripts/init/start-exec.ts +68 -19
  221. package/scripts/init/start-setup-pr.ts +9 -9
  222. package/scripts/init/start-steps.ts +6 -10
  223. package/scripts/issue/defect-rate-cli.ts +1 -1
  224. package/scripts/issue/git-next-issues.ts +1 -1
  225. package/scripts/issue/issue-auto-ok.ts +1 -1
  226. package/scripts/issue/issue-backlinks-cli.ts +2 -2
  227. package/scripts/issue/issue-backlinks.ts +9 -9
  228. package/scripts/issue/issue-comment-cli.ts +19 -13
  229. package/scripts/issue/issue-file-cli.ts +45 -18
  230. package/scripts/issue/issue-file.ts +24 -1
  231. package/scripts/issue/issue-scout-closed.ts +1 -1
  232. package/scripts/issue/issue-state-cli.ts +30 -74
  233. package/scripts/josh/josh-command-map.ts +2 -0
  234. package/scripts/josh/josh-command-types.ts +11 -0
  235. package/scripts/josh/josh-commands-ai.ts +4 -4
  236. package/scripts/josh/josh-commands-backlog.ts +4 -1
  237. package/scripts/josh/josh-commands-development.ts +11 -1
  238. package/scripts/josh/josh-commands-document.ts +1 -0
  239. package/scripts/josh/josh-commands-lane.ts +22 -0
  240. package/scripts/josh/josh-commands-maintenance.ts +4 -4
  241. package/scripts/josh/josh-commands-run.ts +12 -7
  242. package/scripts/josh/josh-in-process.ts +28 -9
  243. package/scripts/josh/josh-logic.ts +33 -15
  244. package/scripts/josh/process-identity.ts +1 -3
  245. package/scripts/josh/session-language-cli.ts +3 -4
  246. package/scripts/lane/lane-await.ts +5 -1
  247. package/scripts/lane/lane-child-invocation.ts +2 -2
  248. package/scripts/lane/lane-cli.ts +3 -3
  249. package/scripts/lane/lane-dispatch.ts +14 -10
  250. package/scripts/lane/lane-environment.ts +5 -1
  251. package/scripts/lane/lane-handoff.ts +1 -1
  252. package/scripts/lane/lane-install.ts +2 -13
  253. package/scripts/lane/lane-launch-cli.ts +35 -3
  254. package/scripts/lane/lane-ledger.ts +145 -0
  255. package/scripts/lane/lane-leftover.ts +1 -1
  256. package/scripts/lane/lane-load.ts +108 -0
  257. package/scripts/lane/lane-measure-cli.ts +149 -0
  258. package/scripts/lane/lane-occupancy.ts +3 -0
  259. package/scripts/lane/lane-reap.ts +1 -3
  260. package/scripts/lane/lane-relaunch.ts +1 -1
  261. package/scripts/lane/lane-stats.ts +224 -0
  262. package/scripts/lane/lane-vacant.ts +36 -0
  263. package/scripts/lane/openai-lane-ship.ts +2 -2
  264. package/scripts/lane/openai-lane-supervisor-owner.ts +180 -0
  265. package/scripts/lane/openai-lane-supervisor.ts +7 -165
  266. package/scripts/lane/openai-review-broker.ts +2 -4
  267. package/scripts/lib/ancestor-directories.ts +35 -0
  268. package/scripts/lib/animation-helpers.ts +2 -2
  269. package/scripts/lib/buffered-process.ts +3 -7
  270. package/scripts/lib/cli-flags.ts +71 -1
  271. package/scripts/lib/spawn-exit.ts +2 -2
  272. package/scripts/lib/timeouts.ts +35 -2
  273. package/scripts/lines/line-budget.ts +4 -6
  274. package/scripts/notify/telegram-notify.ts +26 -1
  275. package/scripts/notify/telegram-test.ts +6 -0
  276. package/scripts/observations/observation-ledger-line.ts +6 -6
  277. package/scripts/observations/observation-ledger-migrate.ts +55 -4
  278. package/scripts/observations/observation-ledger.ts +26 -7
  279. package/scripts/overrides/lockfile-overrides.ts +1 -1
  280. package/scripts/overrides/overrides-logic.ts +1 -1
  281. package/scripts/propagate/propagate-git.ts +1 -1
  282. package/scripts/propagate/propagate-publish.ts +2 -2
  283. package/scripts/propagate/propagate-steps.ts +20 -15
  284. package/scripts/propagate/propagate.ts +36 -27
  285. package/scripts/refactor/import-graph.ts +18 -1
  286. package/scripts/refactor/refactor-lint.ts +4 -4
  287. package/scripts/repo/repository-labels.ts +2 -2
  288. package/scripts/repo/required-checks-logic.ts +1 -3
  289. package/scripts/review/live-evidence.ts +2 -4
  290. package/scripts/review/review-brief-cli.ts +1 -1
  291. package/scripts/review/review-finding-ledger.ts +1 -1
  292. package/scripts/review/review-findings-cli.ts +1 -3
  293. package/scripts/rules/decision-oracle-batch.ts +128 -0
  294. package/scripts/rules/decision-oracle-tokens.ts +21 -0
  295. package/scripts/rules/decision-oracle.ts +8 -120
  296. package/scripts/rules/delivered-rules.ts +26 -182
  297. package/scripts/rules/direct-filing.ts +1 -1
  298. package/scripts/rules/early-heartbeat.ts +3 -3
  299. package/scripts/rules/git-argv.ts +1 -1
  300. package/scripts/rules/git-force.ts +1 -1
  301. package/scripts/rules/implementation-cut.ts +2 -2
  302. package/scripts/rules/index-guard.ts +1 -1
  303. package/scripts/rules/issue-comments.ts +118 -0
  304. package/scripts/rules/{issue-fold.ts → issue-fold-rule.ts} +2 -2
  305. package/scripts/rules/lane-background.ts +2 -2
  306. package/scripts/rules/lane-park.ts +18 -0
  307. package/scripts/rules/lane-split-park.ts +128 -0
  308. package/scripts/rules/oracle-firing.ts +1 -1
  309. package/scripts/rules/poll-loop.ts +1 -1
  310. package/scripts/rules/pre-gate-cut.ts +3 -3
  311. package/scripts/rules/protected-files.ts +59 -4
  312. package/scripts/rules/{run-tail.ts → run-tail-rule.ts} +2 -2
  313. package/scripts/rules/shell-body-trigger.ts +1 -1
  314. package/scripts/rules/stop-rules.ts +18 -7
  315. package/scripts/rules/test-declared-commit.ts +4 -4
  316. package/scripts/rules/wip-cap.ts +63 -0
  317. package/scripts/run/{run-carry-args.ts → carry/run-carry-args.ts} +37 -13
  318. package/scripts/run/{run-carry-change.ts → carry/run-carry-change.ts} +29 -7
  319. package/scripts/run/{run-carry-cli.ts → carry/run-carry-cli.ts} +4 -6
  320. package/scripts/run/{run-carry.ts → carry/run-carry.ts} +12 -6
  321. package/scripts/run/{run-cut-args.ts → cut/run-cut-args.ts} +1 -1
  322. package/scripts/run/{run-cut-cli.ts → cut/run-cut-cli.ts} +3 -3
  323. package/scripts/run/{run-cut-report.ts → cut/run-cut-report.ts} +2 -2
  324. package/scripts/run/{run-cut.ts → cut/run-cut.ts} +1 -1
  325. package/scripts/run/{run-entry-cli.ts → entry/run-entry-cli.ts} +11 -11
  326. package/scripts/run/{run-entry.ts → entry/run-entry.ts} +2 -2
  327. package/scripts/run/{run-event-scope.ts → event/run-event-scope.ts} +1 -1
  328. package/scripts/run/{run-event-stream-emit.ts → event/run-event-stream-emit.ts} +1 -1
  329. package/scripts/run/{run-event-stream.ts → event/run-event-stream.ts} +16 -2
  330. package/scripts/run/{run-hold-cli.ts → hold/run-hold-cli.ts} +5 -5
  331. package/scripts/run/{run-merge-cli.ts → merge/run-merge-cli.ts} +10 -5
  332. package/scripts/run/{run-merge-steps.ts → merge/run-merge-steps.ts} +53 -5
  333. package/scripts/run/{run-merge.ts → merge/run-merge.ts} +1 -1
  334. package/scripts/run/{run-progress-cli.ts → progress/run-progress-cli.ts} +1 -1
  335. package/scripts/run/{run-progress-config.ts → progress/run-progress-config.ts} +2 -17
  336. package/scripts/run/{run-progress-read.ts → progress/run-progress-read.ts} +5 -5
  337. package/scripts/run/{run-progress.ts → progress/run-progress.ts} +1 -1
  338. package/scripts/run/{run-review-steps.ts → review/run-review-steps.ts} +2 -3
  339. package/scripts/run/run-ending.ts +2 -2
  340. package/scripts/run/run-halfrun-resume.ts +6 -1
  341. package/scripts/run/run-headless.ts +1 -1
  342. package/scripts/run/run-invocation.ts +85 -84
  343. package/scripts/run/run-liveness.ts +1 -1
  344. package/scripts/run/run-parent-cut-hook.ts +1 -1
  345. package/scripts/run/run-preflight.ts +6 -6
  346. package/scripts/run/run-prep-cli.ts +1 -1
  347. package/scripts/run/run-prrun-resume.ts +1 -1
  348. package/scripts/run/run-report-cli.ts +4 -4
  349. package/scripts/run/run-report.ts +2 -2
  350. package/scripts/run/run-status-cli.ts +1 -1
  351. package/scripts/run/run-step-cli.ts +3 -3
  352. package/scripts/run/run-step.ts +2 -2
  353. package/scripts/run/run-stop-notify.ts +1 -1
  354. package/scripts/run/run-stranded-detect.ts +4 -4
  355. package/scripts/run/run-stranded.ts +2 -2
  356. package/scripts/run/run-watcher-guard-cli.ts +1 -1
  357. package/scripts/run/run-watcher-guard.ts +5 -3
  358. package/scripts/run/run-watcher-hook.ts +1 -1
  359. package/scripts/run/{run-ship-cli.ts → ship/run-ship-cli.ts} +29 -8
  360. package/scripts/run/{run-ship-detach.ts → ship/run-ship-detach.ts} +3 -3
  361. package/scripts/run/ship/run-ship-lock.ts +50 -0
  362. package/scripts/run/{run-ship-next.ts → ship/run-ship-next.ts} +13 -0
  363. package/scripts/run/ship/run-ship-pre-detach.ts +66 -0
  364. package/scripts/run/{run-ship-preflight.ts → ship/run-ship-preflight.ts} +6 -2
  365. package/scripts/run/{run-ship-probe.ts → ship/run-ship-probe.ts} +2 -2
  366. package/scripts/run/{run-ship-return.ts → ship/run-ship-return.ts} +10 -6
  367. package/scripts/run/{run-ship-review-steps.ts → ship/run-ship-review-steps.ts} +3 -3
  368. package/scripts/run/{run-ship-scoped.ts → ship/run-ship-scoped.ts} +10 -1
  369. package/scripts/run/{run-ship-stage.ts → ship/run-ship-stage.ts} +13 -0
  370. package/scripts/run/{run-ship-steps.ts → ship/run-ship-steps.ts} +15 -8
  371. package/scripts/run/ship/run-ship-stop-text.ts +13 -0
  372. package/scripts/run/ship/run-ship-sync.ts +128 -0
  373. package/scripts/run/{run-ship.ts → ship/run-ship.ts} +6 -0
  374. package/scripts/run/{run-tidy-lanes.ts → tidy/run-tidy-lanes.ts} +1 -1
  375. package/scripts/run/{run-wake-cli.ts → wake/run-wake-cli.ts} +31 -9
  376. package/scripts/run/{run-wake-describe.ts → wake/run-wake-describe.ts} +3 -3
  377. package/scripts/run/{run-wake-driver.ts → wake/run-wake-driver.ts} +99 -17
  378. package/scripts/run/{run-wake-handoff.ts → wake/run-wake-handoff.ts} +1 -1
  379. package/scripts/run/{run-wake-loop.ts → wake/run-wake-loop.ts} +8 -2
  380. package/scripts/run/wake/run-wake-restart.ts +58 -0
  381. package/scripts/run/{run-wake-session.ts → wake/run-wake-session.ts} +3 -3
  382. package/scripts/run/{run-wake.ts → wake/run-wake.ts} +1 -1
  383. package/scripts/safe-chain/preinstall-command.ts +20 -21
  384. package/scripts/safe-chain/project-config.ts +19 -15
  385. package/scripts/sync/sync-ai-files.ts +1 -1
  386. package/scripts/sync/sync-configs.ts +2 -1
  387. package/scripts/sync/sync.ts +15 -2
  388. package/scripts/test/test-red-logic.ts +17 -2
  389. package/scripts/test/test-red.ts +8 -7
  390. package/scripts/test/unit-worker-share.ts +1 -0
  391. package/scripts/time-runtime/time-background.ts +5 -1
  392. package/scripts/time-runtime/time-instant.ts +3 -1
  393. package/scripts/time-runtime/time-spans.ts +6 -139
  394. package/scripts/time-runtime/time-tool-call.ts +160 -0
  395. package/scripts/time-runtime/time-transcript-line.ts +27 -1
  396. package/scripts/version/effective-upstream.ts +2 -20
  397. package/scripts/version/latest-corepack.ts +17 -17
  398. package/scripts/version/latest-regression.ts +1 -1
  399. package/scripts/version/latest-update.ts +4 -4
  400. package/scripts/version/npm-registry.ts +20 -5
  401. package/scripts/version/publishable-range-check.ts +2 -2
  402. package/scripts/version/publishable-range.ts +1 -1
  403. package/scripts/version/release-age.ts +48 -38
  404. package/scripts/version/release-hold.ts +1 -1
  405. package/scripts/version/safe-chain-version-update.ts +40 -0
  406. package/scripts/version/upgrade-shell-command.ts +48 -8
  407. package/scripts/version/version-check-logic.ts +23 -14
  408. package/scripts/version/version-commands.ts +23 -11
  409. package/scripts/version/version-remote.ts +28 -13
  410. package/templates/pnpm-workspace.basic.yaml +4 -0
  411. package/templates/workflows/dependabot-auto-merge.yml +5 -5
  412. package/templates/workflows/github-release.yml +2 -0
  413. package/scripts/build/build-config-merge.ts +0 -27
  414. package/scripts/build/build-managed-marker.ts +0 -27
  415. package/scripts/build/build-self-sync-guard.ts +0 -27
  416. package/scripts/build/build-version.ts +0 -26
  417. package/scripts/version/preinstall-version-update.ts +0 -86
  418. /package/scripts/overrides/{schemas.ts → overrides-schemas.ts} +0 -0
  419. /package/scripts/run/{run-carry-conversation.ts → carry/run-carry-conversation.ts} +0 -0
  420. /package/scripts/run/{run-carry-reclaim.ts → carry/run-carry-reclaim.ts} +0 -0
  421. /package/scripts/run/{run-carry-stash.ts → carry/run-carry-stash.ts} +0 -0
  422. /package/scripts/run/{run-carry-streak.ts → carry/run-carry-streak.ts} +0 -0
  423. /package/scripts/run/{run-cut-handoff.ts → cut/run-cut-handoff.ts} +0 -0
  424. /package/scripts/run/{run-entry-stop.ts → entry/run-entry-stop.ts} +0 -0
  425. /package/scripts/run/{run-event-cli.ts → event/run-event-cli.ts} +0 -0
  426. /package/scripts/run/{run-event-follow.ts → event/run-event-follow.ts} +0 -0
  427. /package/scripts/run/{run-event-render.ts → event/run-event-render.ts} +0 -0
  428. /package/scripts/run/{run-event-watch.ts → event/run-event-watch.ts} +0 -0
  429. /package/scripts/run/{run-hold.ts → hold/run-hold.ts} +0 -0
  430. /package/scripts/run/{run-progress-args.ts → progress/run-progress-args.ts} +0 -0
  431. /package/scripts/run/{run-progress-clock.ts → progress/run-progress-clock.ts} +0 -0
  432. /package/scripts/run/{run-review-cli.ts → review/run-review-cli.ts} +0 -0
  433. /package/scripts/run/{run-review.ts → review/run-review.ts} +0 -0
  434. /package/scripts/run/{run-ship-review.ts → ship/run-ship-review.ts} +0 -0
  435. /package/scripts/run/{run-tidy-cli.ts → tidy/run-tidy-cli.ts} +0 -0
  436. /package/scripts/run/{run-tidy-stashes.ts → tidy/run-tidy-stashes.ts} +0 -0
  437. /package/scripts/run/{run-tidy.ts → tidy/run-tidy.ts} +0 -0
@@ -9,6 +9,7 @@ import { git_gh_issue_list, MAX_SCANNED } from '#scripts/gh/git-gh-issue-list'
9
9
  import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
10
10
  import { github_issue_url } from '#scripts/gh/github-issue-url'
11
11
  import { error_text } from '#scripts/lib/error-message'
12
+ import type { PollOptions } from '#scripts/lib/poll'
12
13
  import { repository_labels } from '#scripts/repo/repository-labels'
13
14
  import { issue_auto_ok } from './issue-auto-ok'
14
15
  import { issue_file, type FileArguments } from './issue-file'
@@ -19,9 +20,10 @@ import { issue_wip } from './issue-wip'
19
20
  // `josh issue:file "<title>" --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>]…
20
21
  // [--repo <owner/repo>] [--distinct <N,…>] [--over-cap] [--no-auto-ok]` — file an Issue with every
21
22
  // filing step run in order (joshuafolkken/kit#2808): the third-party refusal, the body lint, the
22
- // `## Origin` check for another repository, the WIP cap count (joshuafolkken/kit#3181), the duplicate
23
- // scout, the missing workflow labels created (joshuafolkken/kit#3176), the `auto-ok` decision
24
- // (joshuafolkken/kit#3213), the create call carrying every label, and `epic:bundle` after it.
23
+ // `## Origin` check for another repository, the `auto-ok` decision (joshuafolkken/kit#3213) with the
24
+ // run label it owes (joshuafolkken/kit#3313), the WIP cap count (joshuafolkken/kit#3181), the duplicate
25
+ // scout, the missing workflow labels created (joshuafolkken/kit#3176), the create call carrying every
26
+ // label, and `epic:bundle` after it.
25
27
  // A direct `gh api …/issues` filing is refused by the `direct-filing` delivered rule and pointed here.
26
28
 
27
29
  const SUCCESS_EXIT_CODE = 0
@@ -36,6 +38,9 @@ const THIRD_PARTY_MESSAGE =
36
38
  // `GH_REPO` is the variable `gh` reads `{owner}/{repo}` from, so setting it points every listing the
37
39
  // scout and `epic:bundle` make at the target repository rather than at this checkout.
38
40
  const GH_REPO_VARIABLE = 'GH_REPO'
41
+ // The open listing `epic:bundle` reads trails the create call, so the issue just filed is looked for
42
+ // again for up to ten seconds before the placement is given up (joshuafolkken/kit#3332).
43
+ const FRESH_ISSUE_POLL: PollOptions = { attempts: 6, interval_ms: 2000 }
39
44
 
40
45
  interface Filing {
41
46
  args: FileArguments
@@ -130,11 +135,9 @@ async function is_scout_clear(filing: Filing): Promise<boolean> {
130
135
  return open.length === 0
131
136
  }
132
137
 
133
- // `undefined` when the create call failed. `gh`'s standard error is captured into the thrown error
134
- // rather than printed, so it is printed here — otherwise the filing fails with no reason given. A label
135
- // the create applies is provisioned first, so it never arrives with a generated color.
136
- async function create(filing: Filing): Promise<string | undefined> {
137
- repository_labels.ensure_labels(filing.target)
138
+ // Every label the create call carries, or `undefined` when an `auto-ok` filing names neither run label
139
+ // (joshuafolkken/kit#3313). Decided before the WIP count and the scout, so a refusal costs no listing.
140
+ async function labels_of(filing: Filing): Promise<ReadonlyArray<string> | undefined> {
138
141
  const auto_ok = await issue_auto_ok.resolve(
139
142
  filing.args.is_auto_ok_opted_out,
140
143
  filing.target,
@@ -142,10 +145,24 @@ async function create(filing: Filing): Promise<string | undefined> {
142
145
  )
143
146
 
144
147
  console.info(issue_auto_ok.line_of(auto_ok))
148
+ const labels = issue_file.labels_of(filing.args, filing.body, auto_ok.is_applied)
149
+ const problem = issue_file.triage_problem(labels)
150
+
151
+ if (problem === undefined) return labels
152
+ console.error(`✖ ${problem}`)
153
+
154
+ return undefined
155
+ }
156
+
157
+ // `undefined` when the create call failed. `gh`'s standard error is captured into the thrown error
158
+ // rather than printed, so it is printed here — otherwise the filing fails with no reason given. A label
159
+ // the create applies is provisioned first, so it never arrives with a generated color.
160
+ async function create(filing: Filing, labels: ReadonlyArray<string>): Promise<string | undefined> {
161
+ repository_labels.ensure_labels(filing.target)
145
162
  const request = git_gh_issue_write.issue_create_request({
146
163
  title: filing.args.title,
147
164
  body: filing.body,
148
- labels: issue_file.labels_of(filing.args, filing.body, auto_ok.is_applied),
165
+ labels,
149
166
  repo: filing.target,
150
167
  })
151
168
 
@@ -165,7 +182,7 @@ async function create(filing: Filing): Promise<string | undefined> {
165
182
  async function place(url: string, target: string): Promise<void> {
166
183
  const issue_number = Number(github_issue_url.parse(url)?.issue_number)
167
184
  const exit_code = Number.isSafeInteger(issue_number)
168
- ? await epic_bundle_cli.report_for(issue_number, target)
185
+ ? await epic_bundle_cli.report_for(issue_number, target, FRESH_ISSUE_POLL)
169
186
  : FAILURE_EXIT_CODE
170
187
 
171
188
  if (exit_code !== SUCCESS_EXIT_CODE) {
@@ -173,17 +190,17 @@ async function place(url: string, target: string): Promise<void> {
173
190
  }
174
191
  }
175
192
 
176
- async function file(filing: Filing): Promise<number> {
193
+ function is_admitted(filing: Filing): boolean {
177
194
  const refusals = refusals_of(filing)
178
195
 
179
- if (refusals.length > 0) {
180
- console.error(refusals.join('\n'))
196
+ if (refusals.length === 0) return true
197
+ console.error(refusals.join('\n'))
181
198
 
182
- return FAILURE_EXIT_CODE
183
- }
199
+ return false
200
+ }
184
201
 
185
- if (!(await is_wip_clear(filing)) || !(await is_scout_clear(filing))) return FAILURE_EXIT_CODE
186
- const url = await create(filing)
202
+ async function send(filing: Filing, labels: ReadonlyArray<string>): Promise<number> {
203
+ const url = await create(filing, labels)
187
204
 
188
205
  if (url === undefined) return FAILURE_EXIT_CODE
189
206
  console.info(url)
@@ -192,6 +209,16 @@ async function file(filing: Filing): Promise<number> {
192
209
  return SUCCESS_EXIT_CODE
193
210
  }
194
211
 
212
+ async function file(filing: Filing): Promise<number> {
213
+ if (!is_admitted(filing)) return FAILURE_EXIT_CODE
214
+ const labels = await labels_of(filing)
215
+
216
+ if (labels === undefined) return FAILURE_EXIT_CODE
217
+ if (!(await is_wip_clear(filing)) || !(await is_scout_clear(filing))) return FAILURE_EXIT_CODE
218
+
219
+ return await send(filing, labels)
220
+ }
221
+
195
222
  async function filing_of(args: FileArguments): Promise<Filing | string> {
196
223
  const body = await read_body(args.body_file)
197
224
 
@@ -228,7 +255,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
228
255
  process.exitCode = await run(argv)
229
256
  }
230
257
 
231
- const issue_file_cli = { THIRD_PARTY_MESSAGE, run }
258
+ const issue_file_cli = { FRESH_ISSUE_POLL, THIRD_PARTY_MESSAGE, run }
232
259
 
233
260
  if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
234
261
 
@@ -1,5 +1,6 @@
1
1
  import type { parseArgs } from 'node:util'
2
2
  import { epic_issue } from '#scripts/epic/epic-issue'
3
+ import { epic_triage } from '#scripts/epic/epic-triage'
3
4
  import { github_issue_url } from '#scripts/gh/github-issue-url'
4
5
  import { cli_flags } from '#scripts/lib/cli-flags'
5
6
  import { issue_backlinks } from './issue-backlinks'
@@ -9,6 +10,8 @@ import {
9
10
  DEPTH_LABEL_ORDER,
10
11
  FILING_ROUTE_LABELS,
11
12
  has_label_name,
13
+ RUN_LANE_LABEL,
14
+ RUN_SOLO_LABEL,
12
15
  } from './issue-labels'
13
16
  import { markdown_section } from './markdown-section'
14
17
 
@@ -152,6 +155,19 @@ function labels_of(args: FileArguments, body: string, is_auto_ok = false): Reado
152
155
  return [...labels, AUTO_OK_LABEL]
153
156
  }
154
157
 
158
+ // Why an `auto-ok` filing with neither `run:lane` nor `run:solo` is refused, or `undefined` when it is
159
+ // not (joshuafolkken/kit#3313). The offer paths withhold every candidate while one opted-in Issue is
160
+ // untriaged, so a run's own filing without the judgement stopped every lane. No default is applied:
161
+ // `run:solo` is the answer that keeps a verification defect from running beside others, and only a
162
+ // reading of the Issue gives it (`backlogrun-lanes.md`).
163
+ function triage_problem(labels: ReadonlyArray<string>): string | undefined {
164
+ const is_owed = has_label_name(labels, AUTO_OK_LABEL) && !epic_triage.has_triage_label(labels)
165
+
166
+ if (!is_owed) return undefined
167
+
168
+ return `an \`${AUTO_OK_LABEL}\` filing needs \`--label ${RUN_LANE_LABEL}\` or \`--label ${RUN_SOLO_LABEL}\` — \`${RUN_SOLO_LABEL}\` only for a defect in kit's own verification that makes unrelated PRs answer wrongly on main now (\`backlogrun-lanes.md\`), else \`${RUN_LANE_LABEL}\``
169
+ }
170
+
155
171
  function is_same_repository(target: string, current: string): boolean {
156
172
  return target.toLowerCase() === current.toLowerCase()
157
173
  }
@@ -202,7 +218,14 @@ function unacknowledged(
202
218
  return candidates.filter((candidate) => !distinct.includes(candidate))
203
219
  }
204
220
 
205
- const issue_file = { parse, labels_of, origin_problem, unacknowledged, is_same_repository }
221
+ const issue_file = {
222
+ parse,
223
+ labels_of,
224
+ origin_problem,
225
+ triage_problem,
226
+ unacknowledged,
227
+ is_same_repository,
228
+ }
206
229
 
207
230
  export type { FileArguments }
208
231
  export { issue_file }
@@ -1,7 +1,7 @@
1
1
  import { git_gh_command } from '#scripts/gh/git-gh-command'
2
+ import { issue_label_schema } from '#scripts/git/git-schemas'
2
3
  import { PAGE_CEILING_CAUSE } from '#scripts/git/listing-cutoff'
3
4
  import { parse_json_array_or_undefined } from '#scripts/git/parse-json-array'
4
- import { issue_label_schema } from '#scripts/git/schemas'
5
5
  import { z } from 'zod'
6
6
  import { EPIC_LABEL, has_any_label } from './issue-labels'
7
7
  import type { ScoutIssue } from './issue-scout'
@@ -2,6 +2,7 @@
2
2
  import { fileURLToPath } from 'node:url'
3
3
  import { git_gh_command } from '#scripts/gh/git-gh-command'
4
4
  import { bounded_pool } from '#scripts/lib/bounded-pool'
5
+ import { cli_flags } from '#scripts/lib/cli-flags'
5
6
  import { issue_report_failures, type ReadFailureKind } from './issue-report-failures'
6
7
  import { issue_state, type IssueState } from './issue-state'
7
8
 
@@ -28,9 +29,6 @@ import { issue_state, type IssueState } from './issue-state'
28
29
 
29
30
  const FAILURE_EXIT_CODE = 1
30
31
  const ARGV_OFFSET = 2
31
- const REPO_FLAG = '--repo'
32
- const FLAG_PREFIX = '-'
33
- const INLINE_REPO_FLAG = `${REPO_FLAG}=`
34
32
  const ISSUE_NUMBER_PATTERN = /^[1-9]\d*$/u
35
33
  const USAGE = 'Usage: josh issue:state <issue-number> [<issue-number> ...] [--repo <owner/repo>]'
36
34
  // A blank line between the blocks of a multi-number report, so a person sees where one issue ends
@@ -60,85 +58,43 @@ interface IssueReport {
60
58
  result: StateRead
61
59
  }
62
60
 
63
- // `absent` and "given but with nothing usable after it" are different answers. Falling back to the
64
- // session's repository on the second would print a confident state for a *different* issue of the
65
- // same number, which is the exact misread the `--repo` argument exists to prevent.
66
- //
67
- // A named flag carries the argv positions it actually occupied, never the token text it matched
68
- // (joshuafolkken/kit#1355). Removing tokens by value removes every token that happens to look like
69
- // one of them — a second `--repo`, a repeated `owner/repo` — and a token removed is a token nobody
70
- // is told about, which is the whole failure this file refuses elsewhere.
71
- type RepoFlag =
72
- | { kind: 'absent' }
73
- | { kind: 'named'; repo: string; consumed: ReadonlyArray<number> }
74
- | { kind: 'incomplete' }
75
-
76
- // Both spellings gh itself accepts. `--repo=owner/repo` falling through to the separate-word branch
77
- // would read as no repository at all, which is the fall back to the session's repository above.
78
- function read_inline_repo(argv: ReadonlyArray<string>): RepoFlag | undefined {
79
- const inline = argv.find((argument) => argument.startsWith(INLINE_REPO_FLAG))
80
-
81
- if (inline === undefined) return undefined
82
-
83
- const repo = inline.slice(INLINE_REPO_FLAG.length)
84
-
85
- if (repo.length === 0) return { kind: 'incomplete' }
86
-
87
- return { kind: 'named', repo, consumed: [argv.indexOf(inline)] }
61
+ // The read goes through `cli_flags`, both spellings gh itself accepts included (`--repo owner/repo`,
62
+ // `--repo=owner/repo`), and is strict (joshuafolkken/kit#3261). An unrecognized flag refuses the
63
+ // call: `--rep=owner/repo` used to be discarded for starting with a dash, so the call fell back to
64
+ // the session's repository and printed a confident state for a *different* repository's issue of
65
+ // that number (joshuafolkken/kit#1355).
66
+ const OPTIONS = { repo: { type: 'string', multiple: true } } as const
67
+
68
+ // `absent` and "given but with nothing usable" are different answers. Falling back to the session's
69
+ // repository on the second — an empty value, or `--repo` given twice — would print a confident state
70
+ // for a *different* issue of the same number, which is the exact misread `--repo` exists to prevent.
71
+ function read_repo(given: ReadonlyArray<string> | undefined): { repo?: string } | undefined {
72
+ if (given === undefined) return {}
73
+ const [repo, ...rest] = given
74
+
75
+ return repo !== undefined && rest.length === 0 && repo.length > 0 ? { repo } : undefined
88
76
  }
89
77
 
90
- function read_separate_repo(argv: ReadonlyArray<string>): RepoFlag {
91
- const index = argv.indexOf(REPO_FLAG)
92
-
93
- if (index === -1) return { kind: 'absent' }
94
-
95
- const value_index = index + 1
96
- const repo = argv[value_index]
97
-
98
- if (repo === undefined || repo.startsWith(FLAG_PREFIX)) return { kind: 'incomplete' }
99
-
100
- return { kind: 'named', repo, consumed: [index, value_index] }
101
- }
102
-
103
- function read_repo_flag(argv: ReadonlyArray<string>): RepoFlag {
104
- return read_inline_repo(argv) ?? read_separate_repo(argv)
105
- }
106
-
107
- // The argv positions the repository flag occupied, and nothing else. Everything outside this set was
108
- // offered as an issue number, whatever it looks like — so a flag nobody recognizes reaches the check
109
- // below and refuses the call instead of vanishing from it (joshuafolkken/kit#1355).
110
- function consumed_indices(repo_flag: RepoFlag): ReadonlySet<number> {
111
- return new Set(repo_flag.kind === 'named' ? repo_flag.consumed : [])
78
+ // A token that is not a number refuses the whole invocation rather than being dropped. Dropping it
79
+ // answers fewer numbers than were asked for and still exits zero — and with one number left, the
80
+ // surviving block prints in the single-number shape, so nothing in the output says a number went
81
+ // unanswered. `#1262` copied out of a `diag` table is exactly that token.
82
+ function is_issue_numbers(positionals: ReadonlyArray<string>): boolean {
83
+ return (
84
+ positionals.length > 0 && positionals.every((argument) => ISSUE_NUMBER_PATTERN.test(argument))
85
+ )
112
86
  }
113
87
 
114
88
  function parse_request(argv: ReadonlyArray<string>): StateRequest | undefined {
115
- const repo_flag = read_repo_flag(argv)
116
-
117
- if (repo_flag.kind === 'incomplete') return undefined
118
-
119
- // The repository is read first, flag word and value together, so neither is ever mistaken for an
120
- // issue number — and nothing else is removed here. Every remaining token is one the caller offered
121
- // as an issue number, whatever it looks like.
122
- const consumed = consumed_indices(repo_flag)
123
- const rest = argv.filter((_argument, index) => !consumed.has(index))
124
- const numbers = rest.filter((argument) => ISSUE_NUMBER_PATTERN.test(argument))
125
-
126
- // A token that is not a number refuses the whole invocation rather than being dropped. Dropping
127
- // it answers fewer numbers than were asked for and still exits zero — and with one number left,
128
- // the surviving block prints in the single-number shape, so nothing in the output says a number
129
- // went unanswered. `#1262` copied out of a `diag` table is exactly that token.
130
- //
131
- // An unrecognized flag reaches this same check rather than a lenient one of its own
132
- // (joshuafolkken/kit#1355). `--rep=owner/repo` used to be discarded for starting with a dash, so
133
- // the call fell back to the session's repository and printed a confident state for a *different*
134
- // repository's issue of that number — the misread `incomplete` already exists to prevent.
135
- if (numbers.length === 0 || numbers.length !== rest.length) return undefined
89
+ const parsed = cli_flags.arguments_of(argv, OPTIONS)
90
+ if (parsed === undefined) return undefined
91
+ const repo = read_repo(parsed.values.repo)
92
+
93
+ if (repo === undefined || !is_issue_numbers(parsed.positionals)) return undefined
136
94
 
137
95
  // In the order they were typed, with a repeat dropped: repeating a number would spend a second
138
96
  // read on an answer already in hand, and print a second block a caller counting rows counts twice.
139
- const issue_numbers = [...new Set(numbers)]
140
-
141
- return repo_flag.kind === 'named' ? { issue_numbers, repo: repo_flag.repo } : { issue_numbers }
97
+ return { issue_numbers: [...new Set(parsed.positionals)], ...repo }
142
98
  }
143
99
 
144
100
  // One number's read, reduced to what the report needs and nothing printed yet. Separating the two
@@ -78,6 +78,8 @@ const ALIASES: Record<string, string> = {
78
78
  rvf: 'review:findings',
79
79
  ruv: 'rule:value',
80
80
  ev: 'eval',
81
+ lsm: 'lane:sample',
82
+ lst: 'lane:stats',
81
83
  }
82
84
 
83
85
  // The canonical name of a `josh` subcommand: an alias expands, and anything else passes through
@@ -60,6 +60,17 @@ interface CommandEntry {
60
60
  // listing carries only what a consumer can run (joshuafolkken/kit#1988). The audience in
61
61
  // `reference` separately decides whether the command appears in the default listing.
62
62
  is_kit_only?: boolean
63
+ // Pre-built to `dist/commands/` so a consumer's `dist/josh.js` imports it in its own process
64
+ // instead of spawning tsx for it (joshuafolkken/kit#3328, `docs/maintainers/runtime-bundling.md`).
65
+ is_bundled?: boolean
66
+ // The cores the command reserves from the machine-wide budget before it starts its heavy tools
67
+ // (joshuafolkken/kit#3345). `josh-logic.ts` claims them at the one dispatch point every command
68
+ // passes through, so the command only declares the number. A function means the weight is read
69
+ // when the command starts: the unit suite's share depends on what else is running at that moment.
70
+ // **The edit hook declares none, on purpose.** It formats one file per edit and finishes in well
71
+ // under a second, so a wait for room on the machine would stall every edit for the length of
72
+ // another lane's check.
73
+ core_weight?: number | (() => number)
63
74
  }
64
75
 
65
76
  // The name `josh gate` registers under. It lives here rather than in `verification-gate.ts` so a
@@ -143,14 +143,14 @@ const AI_COMMANDS: Record<string, CommandEntry> = {
143
143
  reference: ['[<owner/repo>]', 'automation', ['none']],
144
144
  },
145
145
  'run:merge': {
146
- script: 'scripts/run/run-merge-cli.ts',
146
+ script: 'scripts/run/merge/run-merge-cli.ts',
147
147
  description:
148
148
  'Collapse a backlogrun merge event into one call: confirm the child, do the post-merge steps, offer the next child',
149
149
  category: 'AI tools',
150
150
  reference: [ISSUE_WITH_OPTIONS, 'automation', ['git', 'network']],
151
151
  },
152
152
  'run:review': {
153
- script: 'scripts/run/run-review-cli.ts',
153
+ script: 'scripts/run/review/run-review-cli.ts',
154
154
  description:
155
155
  'Start the gate in the background and print the /code-review brief in one call so the two overlap (--join to join the gate and check its verdict)',
156
156
  category: 'AI tools',
@@ -171,7 +171,7 @@ const AI_COMMANDS: Record<string, CommandEntry> = {
171
171
  // (`run:tail`) were four round trips re-billing the run's full context each. It stops at the first
172
172
  // failed step and names it, so the run reads only the step to fix.
173
173
  ship: {
174
- script: 'scripts/run/run-ship-cli.ts',
174
+ script: 'scripts/run/ship/run-ship-cli.ts',
175
175
  description:
176
176
  'Ship a change in one call: gate, commit/push/PR, the CI-wait merge and the report bookkeeping, stopping at the first failed step',
177
177
  category: 'AI tools',
@@ -182,7 +182,7 @@ const AI_COMMANDS: Record<string, CommandEntry> = {
182
182
  ],
183
183
  },
184
184
  'run:event': {
185
- script: 'scripts/run/run-event-cli.ts',
185
+ script: 'scripts/run/event/run-event-cli.ts',
186
186
  description:
187
187
  'Append to, read or watch the run’s append-only event stream (--append <kind> <text> | --from|--follow <n> | --watch [<n>] | --last)',
188
188
  category: 'AI tools',
@@ -1,4 +1,4 @@
1
- import type { CommandEntry } from './josh-command-types'
1
+ import { OPTIONAL_ENV_FILE_FLAGS, type CommandEntry } from './josh-command-types'
2
2
 
3
3
  // The `backlog:*` command registry, split out of `josh-commands-ai.ts` so that file stays under its
4
4
  // 300-code-line limit, exactly as `LANE_COMMANDS` and `SPLIT_COMMANDS` were for the same reason
@@ -41,6 +41,9 @@ const BACKLOG_COMMANDS: Record<string, CommandEntry> = {
41
41
  },
42
42
  'backlog:stalled': {
43
43
  script: 'scripts/backlog/backlog-stalled-cli.ts',
44
+ // A stall sends one Telegram warning (joshuafolkken/kit#3357). The `Stop` hook calls the detector
45
+ // directly, so this flag costs only the manual command its in-process dispatch.
46
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
44
47
  description:
45
48
  'Report whether ready backlog work is sitting undispatched with a free lane and no recent dispatch',
46
49
  category: 'AI tools',
@@ -1,3 +1,5 @@
1
+ import { core_budget } from '#scripts/gate/core-budget'
2
+ import { gate_plan } from '#scripts/gate/gate-plan'
1
3
  import { GATE_COMMAND, type CommandEntry } from './josh-command-types'
2
4
 
3
5
  const FILE_ARGUMENTS = '[files...]'
@@ -25,18 +27,21 @@ const DEV_COMMANDS: Record<string, CommandEntry> = {
25
27
  description: 'Check code with prettier and eslint (skips a tool a basic project lacks)',
26
28
  category: 'Development',
27
29
  reference: ['', 'developer', ['processes']],
30
+ core_weight: core_budget.CORE_WEIGHTS.lint,
28
31
  },
29
32
  'lint:related': {
30
33
  script: 'scripts/lint/lint-related.ts',
31
34
  description: 'Check only the changed files with prettier and eslint (whole tree on fallback)',
32
35
  category: 'Development',
33
36
  reference: [FILE_ARGUMENTS, 'developer', ['processes']],
37
+ core_weight: core_budget.CORE_WEIGHTS.lint,
34
38
  },
35
39
  lines: {
36
40
  script: 'scripts/lines/lines-command.ts',
37
41
  description: "Print a file's code lines against the max-lines limit and the headroom left",
38
42
  category: 'Development',
39
43
  reference: [REQUIRED_FILE_ARGUMENTS, 'developer', ['none']],
44
+ core_weight: core_budget.CORE_WEIGHTS.eslint_scan,
40
45
  },
41
46
  'refactor:scan': {
42
47
  script: 'scripts/refactor/refactor-scan-cli.ts',
@@ -44,6 +49,7 @@ const DEV_COMMANDS: Record<string, CommandEntry> = {
44
49
  'List refactoring candidates in the changed scope by category and answer clear/candidates',
45
50
  category: 'Development',
46
51
  reference: ['', 'automation', ['processes']],
52
+ core_weight: core_budget.CORE_WEIGHTS.eslint_scan,
47
53
  },
48
54
  bytes: {
49
55
  script: 'scripts/lines/bytes-command.ts',
@@ -130,6 +136,7 @@ const DEV_COMMANDS: Record<string, CommandEntry> = {
130
136
  description: 'Run spell check including dotfiles',
131
137
  category: 'Development',
132
138
  reference: ['', 'developer', ['processes']],
139
+ core_weight: core_budget.CORE_WEIGHTS.spell_check,
133
140
  },
134
141
  behavior: {
135
142
  script: 'scripts/behavior/behavior-cli.ts',
@@ -151,12 +158,14 @@ const DEV_COMMANDS: Record<string, CommandEntry> = {
151
158
  'Run unit tests with Vitest (skips when Vitest is absent; fails when it has no tests)',
152
159
  category: 'Development',
153
160
  reference: [FILTER_ARGUMENTS, 'developer', ['processes']],
161
+ core_weight: gate_plan.direct_unit_weight,
154
162
  },
155
163
  'test:related': {
156
164
  script: 'scripts/test/test-related.ts',
157
165
  description: 'Run only the unit tests related to the changed files (full suite on fallback)',
158
166
  category: 'Development',
159
167
  reference: [FILE_ARGUMENTS, 'developer', ['processes']],
168
+ core_weight: gate_plan.direct_unit_weight,
160
169
  },
161
170
  'test:declared': {
162
171
  script: 'scripts/test/test-declared.ts',
@@ -168,7 +177,7 @@ const DEV_COMMANDS: Record<string, CommandEntry> = {
168
177
  'test:red': {
169
178
  script: 'scripts/test/test-red.ts',
170
179
  description:
171
- 'Run the changed unit tests against the pre-fix tree (merge-base worktree) and report red/green/no-test',
180
+ 'Run the changed unit tests against the pre-fix tree (merge-base worktree) and report red/green/no-test/test-only',
172
181
  category: 'Development',
173
182
  reference: ['', 'developer', ['git', 'processes']],
174
183
  },
@@ -203,6 +212,7 @@ const DEV_COMMANDS: Record<string, CommandEntry> = {
203
212
  description: 'Type-check with tsc (skips a basic project with no TypeScript to check)',
204
213
  category: 'Development',
205
214
  reference: ['[arguments...]', 'developer', ['processes']],
215
+ core_weight: core_budget.CORE_WEIGHTS.type_check,
206
216
  },
207
217
  port: {
208
218
  script: 'scripts/ports/port-command.ts',
@@ -13,6 +13,7 @@ const DOCUMENT_COMMANDS: Record<string, CommandEntry> = {
13
13
  description: 'Print one section of a markdown document, for a `file.md` → "Heading" reference',
14
14
  category: 'AI tools',
15
15
  reference: ['<file> <heading>', 'automation', ['none']],
16
+ is_bundled: true,
16
17
  },
17
18
  'read:set': {
18
19
  script: 'scripts/document/read-set-cli.ts',
@@ -9,6 +9,10 @@ const LANE_SCRIPT = 'scripts/lane/lane-cli.ts'
9
9
  // has to read `.env` to see them — without this the two are documented and unreachable.
10
10
  const LANE_ARGUMENTS = { script: LANE_SCRIPT, tsx_arguments: OPTIONAL_ENV_FILE_FLAGS } as const
11
11
  const ISSUE_WITH_OPTIONS = '<issue> [options]'
12
+ const MEASURE_ARGUMENTS = {
13
+ script: 'scripts/lane/lane-measure-cli.ts',
14
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
15
+ } as const
12
16
 
13
17
  /* eslint-disable @typescript-eslint/naming-convention */
14
18
  const LANE_COMMANDS: Record<string, CommandEntry> = {
@@ -69,6 +73,24 @@ const LANE_COMMANDS: Record<string, CommandEntry> = {
69
73
  category: 'AI tools',
70
74
  reference: ['<issue> [--stash <message>]', 'automation', ['files', 'git', 'processes']],
71
75
  },
76
+ // The lane-limit measurement (joshuafolkken/kit#3355): `.env` is read so `lane:stats` labels the row
77
+ // with the `JOSH_LANE_LIMIT` a person set there.
78
+ 'lane:sample': {
79
+ ...MEASURE_ARGUMENTS,
80
+ description:
81
+ 'Record the machine load (load average, swap, free memory, working lanes) to the lane ledger',
82
+ category: 'AI tools',
83
+ reference: ['[--every <seconds>]', 'maintainer', ['files']],
84
+ default_script_arguments: ['sample'],
85
+ },
86
+ 'lane:stats': {
87
+ ...MEASURE_ARGUMENTS,
88
+ description:
89
+ 'Print one table row of lane throughput, gate duration and machine load over a period',
90
+ category: 'AI tools',
91
+ reference: ['--period <days> [--limit <lane-limit>]', 'maintainer', ['none']],
92
+ default_script_arguments: ['stats'],
93
+ },
72
94
  }
73
95
  /* eslint-enable @typescript-eslint/naming-convention */
74
96
 
@@ -21,7 +21,7 @@ const MAINTENANCE_COMMANDS: Record<string, CommandEntry> = {
21
21
  script: 'scripts/overrides/overrides-check.ts',
22
22
  description: 'Check pnpm overrides for drift',
23
23
  category: 'Maintenance',
24
- reference: ['[--save]', 'maintainer', ['files']],
24
+ reference: ['[--save]', 'developer', ['files']],
25
25
  },
26
26
  audit: {
27
27
  script: 'scripts/security/security-audit.ts',
@@ -49,7 +49,7 @@ const MAINTENANCE_COMMANDS: Record<string, CommandEntry> = {
49
49
  ],
50
50
  description: 'Update pnpm, dependencies, and run security audit',
51
51
  category: 'Maintenance',
52
- reference: ['', 'maintainer', ['files', 'network', 'processes']],
52
+ reference: ['', 'developer', ['files', 'network', 'processes']],
53
53
  argument_targets: ['latest:corepack', 'latest:update', 'audit'],
54
54
  },
55
55
  'latest:scope': {
@@ -73,13 +73,13 @@ const MAINTENANCE_COMMANDS: Record<string, CommandEntry> = {
73
73
  script: 'scripts/version/latest-corepack.ts',
74
74
  description: 'Update pnpm on the current major while preserving the integrity pin',
75
75
  category: 'Maintenance',
76
- reference: ['', 'maintainer', ['files', 'network']],
76
+ reference: ['', 'developer', ['files', 'network']],
77
77
  },
78
78
  'latest:update': {
79
79
  script: 'scripts/version/latest-update.ts',
80
80
  description: 'Update all dependencies to latest',
81
81
  category: 'Maintenance',
82
- reference: ['', 'maintainer', ['files', 'network']],
82
+ reference: ['', 'developer', ['files', 'network']],
83
83
  },
84
84
  }
85
85
  /* eslint-enable @typescript-eslint/naming-convention */
@@ -6,7 +6,7 @@ import { OPTIONAL_ENV_FILE_FLAGS, type CommandEntry } from './josh-command-types
6
6
  // the generated catalog keeps their order.
7
7
 
8
8
  // One script answers both `run:hold` and `run:release`; the flag below is what tells them apart.
9
- const RUN_HOLD_SCRIPT = 'scripts/run/run-hold-cli.ts'
9
+ const RUN_HOLD_SCRIPT = 'scripts/run/hold/run-hold-cli.ts'
10
10
 
11
11
  /* eslint-disable @typescript-eslint/naming-convention */
12
12
  const RUN_COMMANDS: Record<string, CommandEntry> = {
@@ -24,19 +24,22 @@ const RUN_COMMANDS: Record<string, CommandEntry> = {
24
24
  default_script_arguments: ['--release'],
25
25
  },
26
26
  'run:tidy': {
27
- script: 'scripts/run/run-tidy-cli.ts',
27
+ script: 'scripts/run/tidy/run-tidy-cli.ts',
28
28
  description: 'Close merged lanes and drop stashes whose issues are all merged',
29
29
  category: 'AI tools',
30
30
  reference: ['', 'automation', ['git', 'network', 'files']],
31
31
  },
32
32
  'run:carry': {
33
- script: 'scripts/run/run-carry-cli.ts',
33
+ script: 'scripts/run/carry/run-carry-cli.ts',
34
+ // `--stopped` sends the stop confirmation, so the Telegram credentials come from `.env` as for
35
+ // `run:wake` below (joshuafolkken/kit#3357).
36
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
34
37
  description: 'Carry one invocation’s budget across its own session cuts',
35
38
  category: 'AI tools',
36
39
  reference: ['<operation> [arguments...]', 'automation', ['files']],
37
40
  },
38
41
  'run:wake': {
39
- script: 'scripts/run/run-wake-cli.ts',
42
+ script: 'scripts/run/wake/run-wake-cli.ts',
40
43
  // `.env` rather than the ambient environment:
41
44
  // the failure warning needs the Telegram credentials, the same
42
45
  // reasons `notify` and `followup` carry these flags.
@@ -46,7 +49,7 @@ const RUN_COMMANDS: Record<string, CommandEntry> = {
46
49
  reference: ['[options]', 'automation', ['processes', 'notifications']],
47
50
  },
48
51
  'run:cut': {
49
- script: 'scripts/run/run-cut-cli.ts',
52
+ script: 'scripts/run/cut/run-cut-cli.ts',
50
53
  description: 'Cut a lane child before the gate and resume a fresh process',
51
54
  category: 'AI tools',
52
55
  reference: ['[--resume] <issue> [--impl] [--handoff <path>]', 'automation', ['files']],
@@ -64,7 +67,7 @@ const RUN_COMMANDS: Record<string, CommandEntry> = {
64
67
  reference: ['<issue> --output <path> [--repo <owner/repo>]', 'automation', ['network']],
65
68
  },
66
69
  'run:progress': {
67
- script: 'scripts/run/run-progress-cli.ts',
70
+ script: 'scripts/run/progress/run-progress-cli.ts',
68
71
  description: 'Report an unattended run’s progress once it has gone quiet for an interval',
69
72
  category: 'AI tools',
70
73
  reference: [
@@ -83,7 +86,9 @@ const RUN_COMMANDS: Record<string, CommandEntry> = {
83
86
  // read the budget, gather the issue reads and decide the pre-implementation step. `run:hold`,
84
87
  // `cost --cut`, `run:prep` and `run:step` were four round trips re-billing a lane's full context each.
85
88
  'run:entry': {
86
- script: 'scripts/run/run-entry-cli.ts',
89
+ script: 'scripts/run/entry/run-entry-cli.ts',
90
+ // A `busy` hold or an `over` budget sends the stop confirmation (joshuafolkken/kit#3357).
91
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
87
92
  description:
88
93
  'Open a run in one call: claim the tree, read the budget, bundle the reads, decide the pre-implementation step',
89
94
  category: 'AI tools',