@joshuafolkken/kit 1.1178.0 → 1.1240.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 (442) 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 +7 -3
  9. package/.claude/skills/workflow-commands/backlogrun-park.md +23 -2
  10. package/.claude/skills/workflow-commands/backlogrun-progress.md +9 -4
  11. package/.claude/skills/workflow-commands/backlogrun-recovery.md +4 -3
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +21 -13
  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 +10 -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 +2 -1
  20. package/.claude/skills/workflow-commands/latest-gate.md +1 -1
  21. package/.claude/skills/workflow-commands/observation-ledger.md +3 -3
  22. package/.claude/skills/workflow-commands/pre-gate-cut.md +6 -1
  23. package/.claude/skills/workflow-commands/prerequisite.md +2 -2
  24. package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
  25. package/.claude/skills/workflow-commands/working-tree-hold.md +1 -1
  26. package/.codex/hooks.json +2 -2
  27. package/.cursorrules +6 -41
  28. package/.github/actions/setup-node/action.yml +1 -1
  29. package/.github/workflows/auto-tag.yml +3 -4
  30. package/.github/workflows/ci.yml +32 -31
  31. package/.github/workflows/dependabot-auto-merge.yml +13 -6
  32. package/.github/workflows/publish.yml +50 -4
  33. package/.github/workflows/sonar-qube.yml +3 -0
  34. package/.pnpmfile.mjs +4 -3
  35. package/.prettierignore +8 -2
  36. package/CLAUDE.md +18 -20
  37. package/README.md +44 -38
  38. package/SECURITY.md +15 -1
  39. package/dist/CLAUDE.md +18 -20
  40. package/dist/commands/document-section-cli.js +734 -0
  41. package/dist/hooks/audit-provision.js +346 -0
  42. package/dist/hooks/batch-guard.js +5 -4
  43. package/dist/hooks/{chunk-G6KRCKEC.js → chunk-4TZVB44A.js} +496 -378
  44. package/dist/hooks/chunk-5VNDSNG3.js +12 -0
  45. package/dist/hooks/chunk-CDY4NFQG.js +15 -0
  46. package/dist/hooks/chunk-ELCN5LCH.js +135 -0
  47. package/dist/hooks/{chunk-VQLLNFNT.js → chunk-F3ELQ2AF.js} +3 -3
  48. package/dist/hooks/{chunk-I4XSL4TT.js → chunk-GPTFMK5E.js} +1 -1
  49. package/dist/hooks/{chunk-3V37IID6.js → chunk-JBBMAPC4.js} +23 -14
  50. package/dist/hooks/{chunk-UAGLLIGZ.js → chunk-KHGB5S3Y.js} +7 -6
  51. package/dist/hooks/{chunk-GDS5N2KB.js → chunk-KHX4U3BG.js} +735 -683
  52. package/dist/hooks/{chunk-VESKRQOF.js → chunk-KRBERBBI.js} +3 -3
  53. package/dist/hooks/{chunk-DO6NWWHU.js → chunk-QVSWU24O.js} +4 -4
  54. package/dist/hooks/{chunk-S6X6WYKR.js → chunk-WK2XSHSI.js} +1643 -923
  55. package/dist/hooks/{chunk-ZAL3NRGL.js → chunk-XZYKEM6J.js} +25 -10
  56. package/dist/hooks/{chunk-32GQTL4F.js → chunk-ZQGD4GBY.js} +4 -2
  57. package/dist/hooks/codex-hook-adapter.js +14 -12
  58. package/dist/hooks/duplicate-read-guard.js +6 -5
  59. package/dist/hooks/format-edited.js +4 -3
  60. package/dist/hooks/inputs.json +203 -179
  61. package/dist/hooks/investigation-guard.js +6 -5
  62. package/dist/hooks/pretool-guard.js +12 -10
  63. package/dist/hooks/session-lang.js +2 -4
  64. package/dist/hooks/stop-guard.js +66 -72
  65. package/dist/josh.js +1088 -78
  66. package/dist/version/index.d.ts +7 -2
  67. package/dist/version/index.js +152 -75
  68. package/eslint/base.js +23 -1
  69. package/eslint/rules/code-quality.js +3 -0
  70. package/eslint/rules/early-return-one-liner.js +98 -0
  71. package/eslint/rules/unicorn.js +16 -1
  72. package/package.json +7 -6
  73. package/pnpm-workspace.yaml +9 -4
  74. package/prettier/basic.d.ts +3 -1
  75. package/prettier/index.d.ts +3 -1
  76. package/prettier/static.d.ts +3 -1
  77. package/prompts/coding-standards.md +1 -1
  78. package/prompts/collaboration-workflow/file-edits.md +4 -4
  79. package/prompts/collaboration-workflow/glossary.md +1 -1
  80. package/prompts/collaboration-workflow/issue-template.md +1 -0
  81. package/prompts/collaboration-workflow/operating-rules.md +17 -9
  82. package/prompts/collaboration-workflow/overview.md +2 -2
  83. package/prompts/collaboration-workflow/principles.md +14 -12
  84. package/prompts/collaboration-workflow/report-format.md +1 -1
  85. package/prompts/collaboration-workflow/residency.md +1 -1
  86. package/prompts/collaboration-workflow/rule-delivery.md +6 -6
  87. package/prompts/collaboration-workflow/shell-body.md +6 -6
  88. package/prompts/collaboration-workflow/turn-batching.md +1 -1
  89. package/prompts/collaboration-workflow/upstream-interrupt.md +12 -2
  90. package/prompts/collaboration-workflow/wip-cap.md +10 -10
  91. package/prompts/review-rubric.md +1 -2
  92. package/prompts/review.md +1 -1
  93. package/scripts/agent/agent-headless.ts +29 -0
  94. package/scripts/agent/agent-launch-environment.ts +6 -2
  95. package/scripts/agent/codex-agent-argv.ts +2 -1
  96. package/scripts/auto-ok/auto-ok-cli.ts +1 -1
  97. package/scripts/backlog/backlog-arrival.ts +3 -3
  98. package/scripts/backlog/backlog-budget.ts +1 -1
  99. package/scripts/backlog/backlog-drive-args.ts +135 -0
  100. package/scripts/backlog/backlog-drive-cli.ts +11 -137
  101. package/scripts/backlog/backlog-drive-launch.ts +39 -0
  102. package/scripts/backlog/backlog-drive-named-offer.ts +3 -5
  103. package/scripts/backlog/backlog-drive-named.ts +3 -3
  104. package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
  105. package/scripts/backlog/backlog-drive-owner.ts +1 -1
  106. package/scripts/backlog/backlog-drive-restore.ts +1 -1
  107. package/scripts/backlog/backlog-drive-retrospective.ts +1 -1
  108. package/scripts/backlog/backlog-drive.ts +1 -1
  109. package/scripts/backlog/backlog-next.ts +16 -5
  110. package/scripts/backlog/backlog-offer-cli.ts +6 -6
  111. package/scripts/backlog/backlog-offer.ts +1 -1
  112. package/scripts/backlog/backlog-plan-cli.ts +1 -1
  113. package/scripts/backlog/backlog-pool.ts +57 -11
  114. package/scripts/backlog/backlog-ready.ts +1 -1
  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/build/build-codex-hooks.ts +3 -1
  119. package/scripts/build/build-commands.ts +66 -0
  120. package/scripts/build/build-hooks.ts +2 -1
  121. package/scripts/build/build-library.ts +12 -3
  122. package/scripts/build/build.ts +70 -0
  123. package/scripts/build/local-bin.ts +3 -13
  124. package/scripts/delegation/investigation-reads.ts +3 -1
  125. package/scripts/discovery/repo-origin.ts +5 -5
  126. package/scripts/doctor/doctor-consumer.ts +2 -2
  127. package/scripts/doctor/doctor-io.ts +2 -3
  128. package/scripts/document/capped-print-part.ts +30 -0
  129. package/scripts/document/capped-print.ts +3 -4
  130. package/scripts/document/document-byte-budget.ts +11 -2
  131. package/scripts/document/document-scan.ts +117 -0
  132. package/scripts/document/document-section.ts +143 -16
  133. package/scripts/document/entry-read-budget.ts +5 -3
  134. package/scripts/document/entry-read-set.ts +10 -89
  135. package/scripts/document/read-set-cost.ts +98 -0
  136. package/scripts/epic/epic-add-body.ts +1 -0
  137. package/scripts/epic/epic-audit-checks.ts +1 -1
  138. package/scripts/epic/epic-audit-rationale.ts +4 -3
  139. package/scripts/epic/epic-bundle-cli.ts +14 -3
  140. package/scripts/epic/epic-bundle-poll.ts +41 -0
  141. package/scripts/epic/epic-busy.ts +1 -1
  142. package/scripts/epic/epic-candidate-confirm.ts +3 -2
  143. package/scripts/epic/epic-classify.ts +1 -1
  144. package/scripts/epic/epic-cli-argv.ts +78 -46
  145. package/scripts/epic/epic-cli-remove.ts +11 -19
  146. package/scripts/epic/epic-cli.ts +74 -73
  147. package/scripts/epic/epic-close-comment.ts +1 -1
  148. package/scripts/epic/epic-close.ts +1 -1
  149. package/scripts/epic/epic-cross-repo.ts +5 -5
  150. package/scripts/epic/epic-graph.ts +1 -1
  151. package/scripts/epic/epic-index.ts +1 -1
  152. package/scripts/epic/epic-issue.ts +2 -6
  153. package/scripts/epic/epic-lane-offer.ts +2 -2
  154. package/scripts/epic/epic-next.ts +29 -42
  155. package/scripts/epic/epic-solo-stale.ts +1 -1
  156. package/scripts/epic/epic-triage.ts +8 -4
  157. package/scripts/epic/epic-validate.ts +1 -1
  158. package/scripts/followup/git-followup-finish.ts +2 -2
  159. package/scripts/followup/git-followup-label.ts +2 -2
  160. package/scripts/followup/git-followup-merged.ts +2 -2
  161. package/scripts/followup/git-pr-followup-checks.ts +142 -0
  162. package/scripts/followup/git-pr-followup.ts +4 -129
  163. package/scripts/gate/core-admission.ts +162 -0
  164. package/scripts/gate/core-budget.ts +190 -68
  165. package/scripts/gate/gate-plan.ts +80 -7
  166. package/scripts/gate/gate-report.ts +28 -9
  167. package/scripts/gate/gate-skip.ts +38 -7
  168. package/scripts/gate/hook-gate-reuse.ts +12 -10
  169. package/scripts/gate/machine-capacity.ts +175 -0
  170. package/scripts/gate/pre-commit-type-check.ts +4 -1
  171. package/scripts/gate/project-checks.ts +6 -9
  172. package/scripts/gate/type-check-step.ts +2 -3
  173. package/scripts/gate/verification-gate.ts +34 -10
  174. package/scripts/gh/git-gh-api-path.ts +2 -2
  175. package/scripts/gh/git-gh-issue-rest.ts +3 -3
  176. package/scripts/gh/git-gh-issue-write.ts +53 -7
  177. package/scripts/gh/git-gh-pr-read.ts +64 -19
  178. package/scripts/gh/git-gh-pr-rest.ts +1 -1
  179. package/scripts/gh/git-gh-pr.ts +5 -1
  180. package/scripts/gh/git-pr-ai-review.ts +1 -1
  181. package/scripts/gh/git-pr-checks-eval.ts +1 -3
  182. package/scripts/gh/git-pr-checks-parse.ts +1 -1
  183. package/scripts/gh/git-pr-checks-watch.ts +6 -5
  184. package/scripts/gh/git-pr-checks.ts +7 -5
  185. package/scripts/gh/git-pr-coderabbit.ts +1 -1
  186. package/scripts/gh/git-pr-error.ts +1 -3
  187. package/scripts/gh/git-pr.ts +9 -13
  188. package/scripts/gh/github-issue-url.ts +2 -2
  189. package/scripts/git/constants.ts +2 -6
  190. package/scripts/git/git-command.ts +20 -218
  191. package/scripts/git/git-diff-reads.ts +225 -0
  192. package/scripts/git/git-error.ts +4 -12
  193. package/scripts/git/git-pre-push-hook.ts +139 -0
  194. package/scripts/git/git-prompt.ts +2 -6
  195. package/scripts/git/git-spawn-sync.ts +3 -1
  196. package/scripts/git/git-spawn.ts +1 -1
  197. package/scripts/git/git-staging.ts +4 -6
  198. package/scripts/git/git-status.ts +3 -9
  199. package/scripts/hooks/codex-hook-adapter.ts +1 -1
  200. package/scripts/hooks/edited-cspell.ts +2 -4
  201. package/scripts/hooks/format-edited-file.ts +3 -12
  202. package/scripts/hooks/pre-push-unit.ts +31 -9
  203. package/scripts/hooks/reserved-run.ts +2 -2
  204. package/scripts/hooks/run-hook.sh +5 -4
  205. package/scripts/hooks/stop-guard.ts +5 -3
  206. package/scripts/init/init-actions.ts +0 -5
  207. package/scripts/init/init-ai-copy.ts +13 -2
  208. package/scripts/init/init-logic-json-merge.ts +19 -0
  209. package/scripts/init/init-logic-secretlint.ts +7 -7
  210. package/scripts/init/init-logic-workspace.ts +41 -2
  211. package/scripts/init/init-logic.ts +16 -26
  212. package/scripts/init/init.ts +10 -16
  213. package/scripts/init/initial-commit.ts +4 -4
  214. package/scripts/init/kit-development-versions.ts +40 -0
  215. package/scripts/init/kit-setup-state.ts +2 -2
  216. package/scripts/init/package-manager-pin.ts +35 -0
  217. package/scripts/init/start-exec.ts +68 -19
  218. package/scripts/init/start-setup-pr.ts +9 -9
  219. package/scripts/init/start-steps.ts +6 -10
  220. package/scripts/issue/defect-rate-cli.ts +1 -1
  221. package/scripts/issue/git-next-issues.ts +1 -1
  222. package/scripts/issue/issue-auto-ok.ts +32 -7
  223. package/scripts/issue/issue-backlinks-cli.ts +2 -2
  224. package/scripts/issue/issue-backlinks.ts +9 -9
  225. package/scripts/issue/issue-comment-cli.ts +19 -13
  226. package/scripts/issue/issue-file-cli.ts +72 -22
  227. package/scripts/issue/issue-file.ts +29 -1
  228. package/scripts/issue/issue-labels.ts +13 -0
  229. package/scripts/issue/issue-release-cli.ts +155 -0
  230. package/scripts/issue/issue-release.ts +58 -0
  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 +14 -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 +18 -0
  238. package/scripts/josh/josh-commands-document.ts +1 -0
  239. package/scripts/josh/josh-commands-issue.ts +8 -1
  240. package/scripts/josh/josh-commands-lane.ts +24 -1
  241. package/scripts/josh/josh-commands-maintenance.ts +6 -6
  242. package/scripts/josh/josh-commands-run.ts +12 -7
  243. package/scripts/josh/josh-in-process.ts +28 -9
  244. package/scripts/josh/josh-logic.ts +34 -15
  245. package/scripts/josh/process-identity.ts +1 -3
  246. package/scripts/josh/session-language-cli.ts +3 -4
  247. package/scripts/lane/lane-await.ts +5 -1
  248. package/scripts/lane/lane-child-invocation.ts +2 -2
  249. package/scripts/lane/lane-cli.ts +12 -4
  250. package/scripts/lane/lane-dispatch.ts +14 -10
  251. package/scripts/lane/lane-environment.ts +5 -1
  252. package/scripts/lane/lane-handoff.ts +1 -1
  253. package/scripts/lane/lane-install.ts +2 -13
  254. package/scripts/lane/lane-launch-cli.ts +15 -1
  255. package/scripts/lane/lane-ledger.ts +145 -0
  256. package/scripts/lane/lane-leftover.ts +44 -30
  257. package/scripts/lane/lane-load.ts +108 -0
  258. package/scripts/lane/lane-measure-cli.ts +149 -0
  259. package/scripts/lane/lane-occupancy.ts +3 -0
  260. package/scripts/lane/lane-open.ts +5 -5
  261. package/scripts/lane/lane-paths.ts +13 -0
  262. package/scripts/lane/lane-reap.ts +1 -3
  263. package/scripts/lane/lane-registry.ts +11 -0
  264. package/scripts/lane/lane-relaunch.ts +1 -1
  265. package/scripts/lane/lane-stats.ts +224 -0
  266. package/scripts/lane/lane-stray.ts +140 -0
  267. package/scripts/lane/lane-vacant.ts +36 -0
  268. package/scripts/lane/openai-lane-ship.ts +2 -2
  269. package/scripts/lane/openai-lane-supervisor-owner.ts +180 -0
  270. package/scripts/lane/openai-lane-supervisor.ts +7 -165
  271. package/scripts/lane/openai-review-broker.ts +2 -4
  272. package/scripts/lib/ancestor-directories.ts +35 -0
  273. package/scripts/lib/animation-helpers.ts +2 -2
  274. package/scripts/lib/buffered-process.ts +3 -7
  275. package/scripts/lib/cli-flags.ts +71 -1
  276. package/scripts/lib/spawn-exit.ts +2 -2
  277. package/scripts/lib/timeouts.ts +35 -2
  278. package/scripts/lines/line-budget.ts +4 -6
  279. package/scripts/notify/telegram-test.ts +6 -0
  280. package/scripts/observations/observation-ledger-line.ts +6 -6
  281. package/scripts/observations/observation-ledger-migrate.ts +55 -4
  282. package/scripts/observations/observation-ledger.ts +26 -7
  283. package/scripts/overrides/lockfile-overrides.ts +1 -1
  284. package/scripts/overrides/overrides-logic.ts +1 -1
  285. package/scripts/propagate/propagate-git.ts +1 -1
  286. package/scripts/propagate/propagate-publish.ts +2 -2
  287. package/scripts/propagate/propagate-steps.ts +20 -15
  288. package/scripts/propagate/propagate.ts +36 -27
  289. package/scripts/refactor/import-graph.ts +18 -1
  290. package/scripts/refactor/refactor-lint.ts +4 -4
  291. package/scripts/release/github-release-environment.ts +1 -0
  292. package/scripts/release/github-release-runs.ts +115 -0
  293. package/scripts/release/github-release.ts +13 -67
  294. package/scripts/repo/repository-labels.ts +2 -2
  295. package/scripts/repo/required-checks-logic.ts +1 -3
  296. package/scripts/review/live-evidence.ts +2 -4
  297. package/scripts/review/review-brief-cli.ts +1 -1
  298. package/scripts/review/review-finding-ledger.ts +1 -1
  299. package/scripts/review/review-findings-cli.ts +1 -3
  300. package/scripts/rules/decision-oracle-batch.ts +128 -0
  301. package/scripts/rules/decision-oracle-tokens.ts +21 -0
  302. package/scripts/rules/decision-oracle.ts +8 -120
  303. package/scripts/rules/delivered-rules.ts +26 -182
  304. package/scripts/rules/direct-filing.ts +1 -1
  305. package/scripts/rules/early-heartbeat.ts +3 -3
  306. package/scripts/rules/git-argv.ts +1 -1
  307. package/scripts/rules/git-force.ts +1 -1
  308. package/scripts/rules/implementation-cut.ts +2 -2
  309. package/scripts/rules/index-guard.ts +1 -1
  310. package/scripts/rules/issue-comments.ts +118 -0
  311. package/scripts/rules/{issue-fold.ts → issue-fold-rule.ts} +2 -2
  312. package/scripts/rules/lane-background.ts +2 -2
  313. package/scripts/rules/lane-park.ts +18 -0
  314. package/scripts/rules/lane-split-park.ts +128 -0
  315. package/scripts/rules/oracle-firing.ts +1 -1
  316. package/scripts/rules/poll-loop.ts +1 -1
  317. package/scripts/rules/pre-gate-cut.ts +1 -1
  318. package/scripts/rules/protected-files.ts +59 -4
  319. package/scripts/rules/{run-tail.ts → run-tail-rule.ts} +2 -2
  320. package/scripts/rules/shell-body-trigger.ts +1 -1
  321. package/scripts/rules/stop-rules.ts +18 -7
  322. package/scripts/rules/test-declared-commit.ts +4 -4
  323. package/scripts/rules/wip-cap.ts +63 -0
  324. package/scripts/run/{run-carry-args.ts → carry/run-carry-args.ts} +37 -13
  325. package/scripts/run/{run-carry-change.ts → carry/run-carry-change.ts} +29 -7
  326. package/scripts/run/{run-carry-cli.ts → carry/run-carry-cli.ts} +4 -6
  327. package/scripts/run/{run-carry.ts → carry/run-carry.ts} +1 -1
  328. package/scripts/run/{run-cut-args.ts → cut/run-cut-args.ts} +1 -1
  329. package/scripts/run/{run-cut-cli.ts → cut/run-cut-cli.ts} +18 -5
  330. package/scripts/run/{run-cut.ts → cut/run-cut.ts} +1 -1
  331. package/scripts/run/{run-entry-cli.ts → entry/run-entry-cli.ts} +11 -11
  332. package/scripts/run/{run-entry.ts → entry/run-entry.ts} +2 -2
  333. package/scripts/run/{run-event-render.ts → event/run-event-render.ts} +1 -0
  334. package/scripts/run/{run-event-scope.ts → event/run-event-scope.ts} +1 -1
  335. package/scripts/run/{run-event-stream-emit.ts → event/run-event-stream-emit.ts} +1 -1
  336. package/scripts/run/{run-event-stream.ts → event/run-event-stream.ts} +20 -2
  337. package/scripts/run/{run-hold-cli.ts → hold/run-hold-cli.ts} +5 -5
  338. package/scripts/run/{run-merge-cli.ts → merge/run-merge-cli.ts} +10 -5
  339. package/scripts/run/{run-merge-steps.ts → merge/run-merge-steps.ts} +53 -5
  340. package/scripts/run/{run-merge.ts → merge/run-merge.ts} +1 -1
  341. package/scripts/run/{run-progress-cli.ts → progress/run-progress-cli.ts} +1 -1
  342. package/scripts/run/{run-progress-config.ts → progress/run-progress-config.ts} +2 -17
  343. package/scripts/run/{run-progress-read.ts → progress/run-progress-read.ts} +5 -5
  344. package/scripts/run/{run-progress.ts → progress/run-progress.ts} +1 -1
  345. package/scripts/run/{run-review-steps.ts → review/run-review-steps.ts} +2 -3
  346. package/scripts/run/run-ending.ts +2 -2
  347. package/scripts/run/run-halfrun-resume.ts +6 -1
  348. package/scripts/run/run-headless.ts +1 -1
  349. package/scripts/run/run-invocation.ts +85 -84
  350. package/scripts/run/run-liveness.ts +1 -1
  351. package/scripts/run/run-parent-cut-hook.ts +1 -1
  352. package/scripts/run/run-preflight.ts +6 -6
  353. package/scripts/run/run-prep-cli.ts +1 -1
  354. package/scripts/run/run-prrun-resume.ts +1 -1
  355. package/scripts/run/run-report-cli.ts +4 -4
  356. package/scripts/run/run-report.ts +2 -2
  357. package/scripts/run/run-status-cli.ts +1 -1
  358. package/scripts/run/run-step-cli.ts +3 -3
  359. package/scripts/run/run-step.ts +7 -4
  360. package/scripts/run/run-stop-notify.ts +1 -1
  361. package/scripts/run/run-stranded-detect.ts +4 -4
  362. package/scripts/run/run-stranded.ts +2 -2
  363. package/scripts/run/run-watcher-guard-cli.ts +1 -1
  364. package/scripts/run/run-watcher-guard.ts +5 -3
  365. package/scripts/run/run-watcher-hook.ts +1 -1
  366. package/scripts/run/{run-ship-cli.ts → ship/run-ship-cli.ts} +2 -2
  367. package/scripts/run/{run-ship-detach.ts → ship/run-ship-detach.ts} +3 -3
  368. package/scripts/run/ship/run-ship-lock.ts +50 -0
  369. package/scripts/run/{run-ship-preflight.ts → ship/run-ship-preflight.ts} +6 -2
  370. package/scripts/run/{run-ship-probe.ts → ship/run-ship-probe.ts} +2 -2
  371. package/scripts/run/{run-ship-return.ts → ship/run-ship-return.ts} +4 -3
  372. package/scripts/run/{run-ship-review-steps.ts → ship/run-ship-review-steps.ts} +3 -3
  373. package/scripts/run/{run-ship-scoped.ts → ship/run-ship-scoped.ts} +10 -1
  374. package/scripts/run/{run-ship-steps.ts → ship/run-ship-steps.ts} +11 -12
  375. package/scripts/run/ship/run-ship-stop-text.ts +13 -0
  376. package/scripts/run/{run-ship-sync.ts → ship/run-ship-sync.ts} +25 -11
  377. package/scripts/run/{run-tidy-lanes.ts → tidy/run-tidy-lanes.ts} +1 -1
  378. package/scripts/run/{run-wake-cli.ts → wake/run-wake-cli.ts} +25 -11
  379. package/scripts/run/{run-wake-describe.ts → wake/run-wake-describe.ts} +58 -7
  380. package/scripts/run/{run-wake-driver.ts → wake/run-wake-driver.ts} +59 -8
  381. package/scripts/run/{run-wake-handoff.ts → wake/run-wake-handoff.ts} +1 -1
  382. package/scripts/run/{run-wake-loop.ts → wake/run-wake-loop.ts} +13 -15
  383. package/scripts/run/wake/run-wake-restart.ts +58 -0
  384. package/scripts/run/{run-wake-session.ts → wake/run-wake-session.ts} +3 -3
  385. package/scripts/run/{run-wake.ts → wake/run-wake.ts} +16 -65
  386. package/scripts/safe-chain/preinstall-command.ts +20 -21
  387. package/scripts/safe-chain/project-config.ts +19 -15
  388. package/scripts/sync/sync-ai-files.ts +1 -1
  389. package/scripts/sync/sync-configs.ts +2 -1
  390. package/scripts/sync/sync.ts +15 -2
  391. package/scripts/test/unit-worker-share.ts +1 -0
  392. package/scripts/time-runtime/time-background.ts +5 -1
  393. package/scripts/time-runtime/time-instant.ts +3 -1
  394. package/scripts/time-runtime/time-spans.ts +6 -139
  395. package/scripts/time-runtime/time-tool-call.ts +160 -0
  396. package/scripts/version/effective-upstream.ts +2 -20
  397. package/scripts/version/latest-corepack.ts +124 -93
  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 +6 -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/git/{schemas.ts → git-schemas.ts} +0 -0
  419. /package/scripts/overrides/{schemas.ts → overrides-schemas.ts} +0 -0
  420. /package/scripts/run/{run-carry-conversation.ts → carry/run-carry-conversation.ts} +0 -0
  421. /package/scripts/run/{run-carry-reclaim.ts → carry/run-carry-reclaim.ts} +0 -0
  422. /package/scripts/run/{run-carry-stash.ts → carry/run-carry-stash.ts} +0 -0
  423. /package/scripts/run/{run-carry-streak.ts → carry/run-carry-streak.ts} +0 -0
  424. /package/scripts/run/{run-cut-handoff.ts → cut/run-cut-handoff.ts} +0 -0
  425. /package/scripts/run/{run-cut-report.ts → cut/run-cut-report.ts} +0 -0
  426. /package/scripts/run/{run-entry-stop.ts → entry/run-entry-stop.ts} +0 -0
  427. /package/scripts/run/{run-event-cli.ts → event/run-event-cli.ts} +0 -0
  428. /package/scripts/run/{run-event-follow.ts → event/run-event-follow.ts} +0 -0
  429. /package/scripts/run/{run-event-watch.ts → event/run-event-watch.ts} +0 -0
  430. /package/scripts/run/{run-hold.ts → hold/run-hold.ts} +0 -0
  431. /package/scripts/run/{run-progress-args.ts → progress/run-progress-args.ts} +0 -0
  432. /package/scripts/run/{run-progress-clock.ts → progress/run-progress-clock.ts} +0 -0
  433. /package/scripts/run/{run-review-cli.ts → review/run-review-cli.ts} +0 -0
  434. /package/scripts/run/{run-review.ts → review/run-review.ts} +0 -0
  435. /package/scripts/run/{run-ship-next.ts → ship/run-ship-next.ts} +0 -0
  436. /package/scripts/run/{run-ship-pre-detach.ts → ship/run-ship-pre-detach.ts} +0 -0
  437. /package/scripts/run/{run-ship-review.ts → ship/run-ship-review.ts} +0 -0
  438. /package/scripts/run/{run-ship-stage.ts → ship/run-ship-stage.ts} +0 -0
  439. /package/scripts/run/{run-ship.ts → ship/run-ship.ts} +0 -0
  440. /package/scripts/run/{run-tidy-cli.ts → tidy/run-tidy-cli.ts} +0 -0
  441. /package/scripts/run/{run-tidy-stashes.ts → tidy/run-tidy-stashes.ts} +0 -0
  442. /package/scripts/run/{run-tidy.ts → tidy/run-tidy.ts} +0 -0
package/dist/josh.js CHANGED
@@ -20,6 +20,10 @@ function read_spawn_stderr(result) {
20
20
  return result.stderr ?? "";
21
21
  }
22
22
 
23
+ // scripts/lib/timeouts.ts
24
+ var PROBE_TIMEOUT_MS = 2e3;
25
+ var GIT_TIMEOUT_MS = 1e4;
26
+
23
27
  // scripts/git/git-spawn-sync.ts
24
28
  import { execaSync } from "execa";
25
29
 
@@ -28,17 +32,13 @@ import { platform } from "node:os";
28
32
  var GIT_COMMAND_UNIX = "/usr/bin/git";
29
33
  var GIT_BINARY_KEY = "JOSH_GIT_BINARY";
30
34
  function get_git_command() {
31
- if (platform() === "win32") {
32
- return String.raw`"C:\Program Files\Git\cmd\git.exe"`;
33
- }
35
+ if (platform() === "win32") return String.raw`"C:\Program Files\Git\cmd\git.exe"`;
34
36
  return GIT_COMMAND_UNIX;
35
37
  }
36
38
  function get_git_command_for_spawn() {
37
39
  const binary = process.env[GIT_BINARY_KEY];
38
40
  if (binary !== void 0 && binary !== "") return binary;
39
- if (platform() === "win32") {
40
- return String.raw`C:\Program Files\Git\cmd\git.exe`;
41
- }
41
+ if (platform() === "win32") return String.raw`C:\Program Files\Git\cmd\git.exe`;
42
42
  return GIT_COMMAND_UNIX;
43
43
  }
44
44
  var git_utilities = {
@@ -47,7 +47,6 @@ var git_utilities = {
47
47
  };
48
48
 
49
49
  // scripts/git/git-spawn-sync.ts
50
- var GIT_TIMEOUT_MS = 1e4;
51
50
  var SUCCESS_EXIT_CODE = 0;
52
51
  var C_LOCALE = { LC_ALL: "C", LANGUAGE: "C" };
53
52
  function run(args, options = {}) {
@@ -94,20 +93,20 @@ var ABSENT_CODE = "ENOENT";
94
93
  function is_absent(error) {
95
94
  return error instanceof Error && "code" in error && error.code === ABSENT_CODE;
96
95
  }
97
- function read_optional(path5) {
96
+ function read_optional(path12) {
98
97
  try {
99
- return readFileSync(path5, "utf8");
98
+ return readFileSync(path12, "utf8");
100
99
  } catch (error) {
101
100
  if (is_absent(error)) return void 0;
102
101
  throw error;
103
102
  }
104
103
  }
105
- function read_file_or_empty(path5) {
106
- return read_optional(path5) ?? "";
104
+ function read_file_or_empty(path12) {
105
+ return read_optional(path12) ?? "";
107
106
  }
108
- function read_if_readable(path5) {
107
+ function read_if_readable(path12) {
109
108
  try {
110
- return readFileSync(path5, "utf8");
109
+ return readFileSync(path12, "utf8");
111
110
  } catch {
112
111
  return void 0;
113
112
  }
@@ -125,7 +124,6 @@ var CLAUDE_MD = "CLAUDE.md";
125
124
  var PLUGIN_ID = "kit@kit";
126
125
  var CLAUDE_MD_POINTER = `@${NODE_MODULES}/${KIT_PACKAGE_NAME}/dist/${CLAUDE_MD}`;
127
126
  var SECRETLINT_BIN = path.join(NODE_MODULES, ".bin", "secretlint");
128
- var GIT_TIMEOUT_MS2 = 2e3;
129
127
  var manifest_schema = z.object({
130
128
  name: z.string().optional(),
131
129
  dependencies: z.record(z.string(), z.string()).optional(),
@@ -160,7 +158,7 @@ function is_plugin_declared(root) {
160
158
  }
161
159
  function configured_hooks_path(root) {
162
160
  const value = git_spawn_sync.read(["-C", root, "config", "--get", "core.hooksPath"], {
163
- timeout: GIT_TIMEOUT_MS2
161
+ timeout: PROBE_TIMEOUT_MS
164
162
  });
165
163
  return value === "" ? void 0 : value;
166
164
  }
@@ -232,14 +230,31 @@ var doctor_consumer = {
232
230
  };
233
231
 
234
232
  // scripts/josh/josh-logic.ts
235
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
236
- import path4 from "node:path";
237
- import { fileURLToPath } from "node:url";
233
+ import { existsSync as existsSync4, readFileSync as readFileSync5 } from "node:fs";
234
+ import path11 from "node:path";
235
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
238
236
 
239
237
  // scripts/build/local-bin.ts
240
238
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
241
239
  import { createRequire } from "node:module";
240
+ import path3 from "node:path";
241
+
242
+ // scripts/lib/ancestor-directories.ts
242
243
  import path2 from "node:path";
244
+ var MAX_DEPTH = 64;
245
+ function list(start_directory) {
246
+ const directories = [];
247
+ let current = path2.resolve(start_directory);
248
+ while (directories.length < MAX_DEPTH && !directories.includes(current)) {
249
+ directories.push(current);
250
+ current = path2.dirname(current);
251
+ }
252
+ return directories;
253
+ }
254
+ function nearest(start_directory, is_match) {
255
+ return list(start_directory).find((directory) => is_match(directory));
256
+ }
257
+ var ancestor_directories = { list, nearest };
243
258
 
244
259
  // scripts/lib/schemas.ts
245
260
  import { z as z2 } from "zod";
@@ -281,26 +296,767 @@ var WINDOWS_SHIM_SUFFIX = ".cmd";
281
296
  var PACKAGE_JSON = "package.json";
282
297
  function resolve_local_bin(project_root, bin_name) {
283
298
  const shim = process.platform === WINDOWS_PLATFORM ? `${bin_name}${WINDOWS_SHIM_SUFFIX}` : bin_name;
284
- return path2.join(project_root, NODE_MODULES2, BIN_DIR, shim);
299
+ return path3.join(project_root, NODE_MODULES2, BIN_DIR, shim);
285
300
  }
286
301
  function read_bin_entry(manifest_path, package_name, bin_name) {
287
302
  const { bin } = package_bin_schema.parse(JSON.parse(readFileSync2(manifest_path, "utf8")));
288
- if (typeof bin === "string") return bin_name === path2.basename(package_name) ? bin : void 0;
303
+ if (typeof bin === "string") return bin_name === path3.basename(package_name) ? bin : void 0;
289
304
  return bin?.[bin_name];
290
305
  }
291
306
  function resolve_package_bin(base_directory, package_name, bin_name) {
292
307
  try {
293
- const resolve_from = createRequire(path2.join(base_directory, PACKAGE_JSON));
308
+ const resolve_from = createRequire(path3.join(base_directory, PACKAGE_JSON));
294
309
  const manifest_path = resolve_from.resolve(`${package_name}/${PACKAGE_JSON}`);
295
310
  const bin_entry = read_bin_entry(manifest_path, package_name, bin_name);
296
311
  if (bin_entry === void 0) return void 0;
297
- const cli_entry = path2.join(path2.dirname(manifest_path), bin_entry);
312
+ const cli_entry = path3.join(path3.dirname(manifest_path), bin_entry);
298
313
  return existsSync2(cli_entry) ? cli_entry : void 0;
299
314
  } catch {
300
315
  return void 0;
301
316
  }
302
317
  }
303
318
 
319
+ // scripts/gate/core-budget.ts
320
+ import { randomUUID as randomUUID3 } from "node:crypto";
321
+ import { readdirSync as readdirSync2 } from "node:fs";
322
+ import { availableParallelism as availableParallelism3 } from "node:os";
323
+ import path8 from "node:path";
324
+
325
+ // scripts/josh/platform-temporary.ts
326
+ import { accessSync, constants } from "node:fs";
327
+ import { tmpdir } from "node:os";
328
+ var POSIX_TEMP_ROOT = "/tmp";
329
+ var WINDOWS_PLATFORM2 = "win32";
330
+ function is_writable_directory(directory) {
331
+ try {
332
+ accessSync(directory, constants.W_OK);
333
+ return true;
334
+ } catch {
335
+ return false;
336
+ }
337
+ }
338
+ function resolve_temporary_root(platform2, can_write = is_writable_directory) {
339
+ if (platform2 === WINDOWS_PLATFORM2) return tmpdir();
340
+ return can_write(POSIX_TEMP_ROOT) ? POSIX_TEMP_ROOT : tmpdir();
341
+ }
342
+ var TEMP_ROOT_KEY = "JOSH_TEMP_ROOT";
343
+ function temporary_root(override, platform2) {
344
+ return override === void 0 || override === "" ? resolve_temporary_root(platform2) : override;
345
+ }
346
+ var PLATFORM_TEMP_ROOT = temporary_root(process.env[TEMP_ROOT_KEY], process.platform);
347
+
348
+ // scripts/josh/process-identity.ts
349
+ import { execFileSync, spawnSync } from "node:child_process";
350
+ import { randomUUID } from "node:crypto";
351
+ import { readFileSync as readFileSync3, rmSync } from "node:fs";
352
+ import { createServer } from "node:net";
353
+ import path4 from "node:path";
354
+ var PS_COMMAND = "/bin/ps";
355
+ var FORMAT_FLAG = "-o";
356
+ var START_TIME_FORMAT = "lstart=";
357
+ var PID_FLAG = "-p";
358
+ var PROBE_ENVIRONMENT = { TZ: "UTC", LC_ALL: "C" };
359
+ var LIVENESS_SIGNAL = 0;
360
+ var LOWEST_REAL_PID = 1;
361
+ var PROC_START_FIELD_INDEX = 19;
362
+ var BEACON_SCHEME = "socket:";
363
+ var BEACON_SUFFIX = ".sock";
364
+ var BEACON_PREFIX = `josh-process-identity-${String(process.getuid?.() ?? "")}-`;
365
+ var BEACON_ID_LENGTH = 36;
366
+ var BEACON_ID_PATTERN = /^[\da-f-]+$/u;
367
+ var WINDOWS_PLATFORM3 = "win32";
368
+ var SOCKET_PROBE_SOURCE = "const net=require('node:net');const socket=net.createConnection(process.argv[1]);socket.once('connect',()=>process.exit(0));socket.once('error',()=>process.exit(1));socket.setTimeout(1000,()=>process.exit(1));";
369
+ var beacons = /* @__PURE__ */ new Map();
370
+ var exit_cleanup = { is_registered: false };
371
+ function is_live_pid(pid) {
372
+ if (pid < LOWEST_REAL_PID) return false;
373
+ try {
374
+ process.kill(pid, LIVENESS_SIGNAL);
375
+ return true;
376
+ } catch {
377
+ return false;
378
+ }
379
+ }
380
+ function read_proc_start(pid) {
381
+ try {
382
+ const stat = readFileSync3(`/proc/${String(pid)}/stat`, "utf8");
383
+ const fields = stat.slice(stat.lastIndexOf(")") + 1).trim().split(/\s+/u);
384
+ const start = fields[PROC_START_FIELD_INDEX];
385
+ return start === void 0 ? void 0 : `proc:${start}`;
386
+ } catch {
387
+ return void 0;
388
+ }
389
+ }
390
+ function read_ps_start(pid) {
391
+ try {
392
+ const printed = execFileSync(
393
+ PS_COMMAND,
394
+ [FORMAT_FLAG, START_TIME_FORMAT, PID_FLAG, String(pid)],
395
+ {
396
+ encoding: "utf8",
397
+ timeout: PROBE_TIMEOUT_MS,
398
+ stdio: ["ignore", "pipe", "ignore"],
399
+ env: PROBE_ENVIRONMENT
400
+ }
401
+ ).trim();
402
+ return printed.length > 0 ? printed : void 0;
403
+ } catch {
404
+ return void 0;
405
+ }
406
+ }
407
+ var START_PROBES = { read_proc_start, read_ps_start };
408
+ function safe_probe(probe, pid) {
409
+ try {
410
+ return probe(pid);
411
+ } catch {
412
+ return void 0;
413
+ }
414
+ }
415
+ function read_start(pid, probes = START_PROBES) {
416
+ return safe_probe(probes.read_proc_start, pid) ?? safe_probe(probes.read_ps_start, pid);
417
+ }
418
+ function close_beacon(token) {
419
+ const server = beacons.get(token);
420
+ if (server === void 0) return;
421
+ beacons.delete(token);
422
+ server.close();
423
+ rmSync(token.slice(BEACON_SCHEME.length), { force: true });
424
+ }
425
+ function close_beacons() {
426
+ for (const token of beacons.keys()) close_beacon(token);
427
+ }
428
+ function ensure_exit_cleanup() {
429
+ if (exit_cleanup.is_registered) return;
430
+ exit_cleanup.is_registered = true;
431
+ process.once("exit", close_beacons);
432
+ }
433
+ function ignore_beacon_error() {
434
+ }
435
+ function bind_beacon(target) {
436
+ return createServer().on("error", ignore_beacon_error).listen(target);
437
+ }
438
+ function try_bind_beacon(bind, target) {
439
+ try {
440
+ const server = bind(target);
441
+ return server.listening ? server : void 0;
442
+ } catch {
443
+ return void 0;
444
+ }
445
+ }
446
+ function open_beacon(bind = bind_beacon) {
447
+ const target = path4.join(PLATFORM_TEMP_ROOT, `${BEACON_PREFIX}${randomUUID()}${BEACON_SUFFIX}`);
448
+ const token = `${BEACON_SCHEME}${target}`;
449
+ const server = try_bind_beacon(bind, target);
450
+ if (server === void 0) return void 0;
451
+ server.unref();
452
+ beacons.set(token, server);
453
+ ensure_exit_cleanup();
454
+ return token;
455
+ }
456
+ function resolve_own_start(probes = START_PROBES, platform2 = process.platform) {
457
+ const start = read_start(process.pid, probes);
458
+ if (start !== void 0 || platform2 === WINDOWS_PLATFORM3) return start;
459
+ return open_beacon();
460
+ }
461
+ function is_valid_beacon_name(name) {
462
+ if (!name.startsWith(BEACON_PREFIX) || !name.endsWith(BEACON_SUFFIX)) return false;
463
+ const id = name.slice(BEACON_PREFIX.length, -BEACON_SUFFIX.length);
464
+ return id.length === BEACON_ID_LENGTH && BEACON_ID_PATTERN.test(id);
465
+ }
466
+ function beacon_target(token) {
467
+ if (!token.startsWith(BEACON_SCHEME)) return void 0;
468
+ const target = token.slice(BEACON_SCHEME.length);
469
+ if (path4.dirname(target) !== PLATFORM_TEMP_ROOT) return void 0;
470
+ return is_valid_beacon_name(path4.basename(target)) ? target : void 0;
471
+ }
472
+ function is_live_beacon(target) {
473
+ return spawnSync(process.execPath, ["-e", SOCKET_PROBE_SOURCE, target], {
474
+ stdio: "ignore",
475
+ timeout: PROBE_TIMEOUT_MS
476
+ }).status === 0;
477
+ }
478
+ function has_matching_start(pid, recorded_start, read2) {
479
+ const observed = read2(pid);
480
+ return observed === void 0 ? void 0 : observed === recorded_start;
481
+ }
482
+ function matches_recorded_start(pid, recorded_start, read2) {
483
+ const target = beacon_target(recorded_start);
484
+ return target === void 0 ? has_matching_start(pid, recorded_start, read2) : is_live_beacon(target);
485
+ }
486
+ var own_probe = /* @__PURE__ */ new Map();
487
+ function own_start() {
488
+ if (!own_probe.has(process.pid)) own_probe.set(process.pid, resolve_own_start());
489
+ return own_probe.get(process.pid);
490
+ }
491
+ function own_fields() {
492
+ const start = own_start();
493
+ return { pid: process.pid, ...start !== void 0 && { process_start: start } };
494
+ }
495
+ function is_same_process(pid, recorded_start, read2 = read_start) {
496
+ if (pid === void 0 || !is_live_pid(pid)) return false;
497
+ if (recorded_start === void 0) return void 0;
498
+ return matches_recorded_start(pid, recorded_start, read2);
499
+ }
500
+ function is_own_process(pid, recorded_start) {
501
+ return pid === process.pid && recorded_start === own_start();
502
+ }
503
+ var process_identity = {
504
+ close_beacon,
505
+ is_live_pid,
506
+ is_own_process,
507
+ is_same_process,
508
+ open_beacon,
509
+ own_fields,
510
+ own_start,
511
+ read_start,
512
+ resolve_own_start
513
+ };
514
+
515
+ // scripts/josh/process-owner.ts
516
+ import { z as z3 } from "zod";
517
+ var process_owner_schema = z3.object({ pid: z3.number(), process_start: z3.string().optional() });
518
+
519
+ // scripts/josh/stamp-file.ts
520
+ import { createHash, randomUUID as randomUUID2 } from "node:crypto";
521
+ import { lstatSync, readFileSync as readFileSync4, renameSync, rmSync as rmSync2, writeFileSync } from "node:fs";
522
+ import path6 from "node:path";
523
+
524
+ // scripts/init/init-paths.ts
525
+ import path5 from "node:path";
526
+ import { fileURLToPath } from "node:url";
527
+ var PACKAGE_DIR = path5.join(path5.dirname(fileURLToPath(import.meta.url)), "..", "..");
528
+ var PROJECT_ROOT = process.cwd();
529
+
530
+ // scripts/josh/stamp-file.ts
531
+ var HASH_ALGORITHM = "sha256";
532
+ var STAMP_SUFFIX = ".json";
533
+ var STAMP_KEY_LENGTH = 16;
534
+ var STAMP_FILE_MODE = 384;
535
+ var STAMP_WRITE_FLAG = "wx";
536
+ var STAMP_CREATE_FLAG = STAMP_WRITE_FLAG;
537
+ var EXISTS_ERROR_CODE = "EEXIST";
538
+ var ACCOUNT_KEY_SEPARATOR = ":";
539
+ function digest(content) {
540
+ return createHash(HASH_ALGORITHM).update(content).digest("hex");
541
+ }
542
+ function account_key() {
543
+ return String(process.getuid?.() ?? "");
544
+ }
545
+ function stamp_path(prefix, root = PACKAGE_DIR, suffix = STAMP_SUFFIX) {
546
+ const key = digest(`${account_key()}${ACCOUNT_KEY_SEPARATOR}${root}`).slice(0, STAMP_KEY_LENGTH);
547
+ return path6.join(PLATFORM_TEMP_ROOT, `${prefix}${key}${suffix}`);
548
+ }
549
+ function write_exclusively(target, content) {
550
+ rmSync2(target, { force: true });
551
+ writeFileSync(target, content, { flag: STAMP_WRITE_FLAG, mode: STAMP_FILE_MODE });
552
+ return target;
553
+ }
554
+ function write_stamp(target, payload) {
555
+ return write_exclusively(target, JSON.stringify(payload));
556
+ }
557
+ function replace_stamp(target, payload) {
558
+ const temporary = `${target}.${String(process.pid)}.${randomUUID2()}`;
559
+ try {
560
+ writeFileSync(temporary, JSON.stringify(payload), {
561
+ flag: STAMP_CREATE_FLAG,
562
+ mode: STAMP_FILE_MODE
563
+ });
564
+ renameSync(temporary, target);
565
+ return target;
566
+ } finally {
567
+ rmSync2(temporary, { force: true });
568
+ }
569
+ }
570
+ function write_text_stamp(target, text) {
571
+ return write_exclusively(target, text);
572
+ }
573
+ function create_stamp(target, payload) {
574
+ try {
575
+ writeFileSync(target, JSON.stringify(payload), {
576
+ flag: STAMP_CREATE_FLAG,
577
+ mode: STAMP_FILE_MODE
578
+ });
579
+ return true;
580
+ } catch (error) {
581
+ if (error.code === EXISTS_ERROR_CODE) return false;
582
+ throw error;
583
+ }
584
+ }
585
+ function remove_stamp(target) {
586
+ rmSync2(target, { force: true });
587
+ }
588
+ function is_own_regular_file(source) {
589
+ const stats = lstatSync(source);
590
+ if (!stats.isFile()) return false;
591
+ const uid = process.getuid?.();
592
+ return uid === void 0 || stats.uid === uid;
593
+ }
594
+ function read_stamp_text(source) {
595
+ try {
596
+ if (!is_own_regular_file(source)) return void 0;
597
+ return readFileSync4(source, "utf8");
598
+ } catch {
599
+ return void 0;
600
+ }
601
+ }
602
+ var stamp_file = {
603
+ create_stamp,
604
+ digest,
605
+ is_own_regular_file,
606
+ read_stamp_text,
607
+ replace_stamp,
608
+ remove_stamp,
609
+ stamp_path,
610
+ write_stamp,
611
+ write_text_stamp
612
+ };
613
+
614
+ // scripts/test/unit-worker-share.ts
615
+ import { readdirSync } from "node:fs";
616
+ import { availableParallelism } from "node:os";
617
+ import path7 from "node:path";
618
+ var RUN_PREFIX = "josh-unit-running-";
619
+ var WORKER_FLAG = "--maxWorkers";
620
+ var WORKER_FLAGS = [WORKER_FLAG, "--max-workers"];
621
+ var MIN_WORKERS = 1;
622
+ var SOLO_RUNS = 1;
623
+ function marker_path(pid = process.pid) {
624
+ return stamp_file.stamp_path(RUN_PREFIX, String(pid));
625
+ }
626
+ function is_running(marker) {
627
+ return process_identity.is_same_process(marker.pid, marker.process_start) !== false;
628
+ }
629
+ function read_marker(source) {
630
+ const raw = stamp_file.read_stamp_text(source);
631
+ if (raw === void 0) return void 0;
632
+ const parsed = process_owner_schema.safeParse(json_value.parse_or_undefined(raw));
633
+ return parsed.success ? parsed.data : void 0;
634
+ }
635
+ function marker_files(directory = PLATFORM_TEMP_ROOT) {
636
+ try {
637
+ return readdirSync(directory).filter((name) => name.startsWith(RUN_PREFIX));
638
+ } catch {
639
+ return [];
640
+ }
641
+ }
642
+ function sweep_marker(source) {
643
+ try {
644
+ stamp_file.remove_stamp(source);
645
+ } catch {
646
+ }
647
+ }
648
+ function is_marker_live(source) {
649
+ const marker = read_marker(source);
650
+ if (marker === void 0) return false;
651
+ if (is_running(marker)) return true;
652
+ sweep_marker(source);
653
+ return false;
654
+ }
655
+ function live_run_count(directory = PLATFORM_TEMP_ROOT) {
656
+ return marker_files(directory).filter((name) => is_marker_live(path7.join(directory, name))).length;
657
+ }
658
+ var NESTED_KEY = "JOSH_UNIT_RUN_MARKED";
659
+ var NESTED_VALUE = "1";
660
+ function is_nested_run() {
661
+ return process.env[NESTED_KEY] === NESTED_VALUE;
662
+ }
663
+ function resolve_unit_workers(available_cores, runs) {
664
+ if (runs <= SOLO_RUNS) return void 0;
665
+ return Math.max(MIN_WORKERS, Math.floor(available_cores / runs));
666
+ }
667
+ function current_share(available_cores = availableParallelism(), live_runs = live_run_count()) {
668
+ const own_run = is_nested_run() ? 0 : SOLO_RUNS;
669
+ return resolve_unit_workers(available_cores, live_runs + own_run);
670
+ }
671
+ function is_worker_flag(argument) {
672
+ return WORKER_FLAGS.some((flag) => argument === flag || argument.startsWith(`${flag}=`));
673
+ }
674
+ function worker_arguments(vitest_arguments, share) {
675
+ if (share === void 0) return [];
676
+ if (vitest_arguments.some((argument) => is_worker_flag(argument))) return [];
677
+ return [`${WORKER_FLAG}=${String(share)}`];
678
+ }
679
+ function mark_run_started(target) {
680
+ try {
681
+ stamp_file.write_stamp(target, process_identity.own_fields());
682
+ } catch {
683
+ }
684
+ }
685
+ async function with_run_marker(run2) {
686
+ if (is_nested_run()) return await run2();
687
+ const target = marker_path();
688
+ mark_run_started(target);
689
+ process.env[NESTED_KEY] = NESTED_VALUE;
690
+ try {
691
+ return await run2();
692
+ } finally {
693
+ process.env[NESTED_KEY] = "";
694
+ stamp_file.remove_stamp(target);
695
+ }
696
+ }
697
+ var unit_worker_share = {
698
+ MIN_WORKERS,
699
+ NESTED_KEY,
700
+ NESTED_VALUE,
701
+ RUN_PREFIX,
702
+ SOLO_RUNS,
703
+ current_share,
704
+ is_nested_run,
705
+ live_run_count,
706
+ marker_path,
707
+ read_marker,
708
+ resolve_unit_workers,
709
+ with_run_marker,
710
+ worker_arguments
711
+ };
712
+
713
+ // scripts/gate/core-budget.ts
714
+ import { z as z4 } from "zod";
715
+
716
+ // scripts/gate/core-admission.ts
717
+ var MS_PER_SECOND = 1e3;
718
+ var RAMP_UP_MS = 3e4;
719
+ function compare_claim(left, right) {
720
+ const by_time = left.reservation.claimed_at - right.reservation.claimed_at;
721
+ return by_time === 0 ? left.key.localeCompare(right.key) : by_time;
722
+ }
723
+ function add_load(totals, reservation) {
724
+ totals.cores += reservation.weight;
725
+ totals.memory_mb += reservation.memory_mb ?? 0;
726
+ }
727
+ function exceeds(totals, budget) {
728
+ return totals.cores > budget.cores || totals.memory_mb > budget.memory_mb;
729
+ }
730
+ function admitted_keys(reservations, budget, memory_budget = Infinity) {
731
+ const limit = { cores: budget, memory_mb: memory_budget };
732
+ const totals = { cores: 0, memory_mb: 0 };
733
+ const admitted = /* @__PURE__ */ new Set();
734
+ for (const [index, entry] of reservations.toSorted(compare_claim).entries()) {
735
+ add_load(totals, entry.reservation);
736
+ if (index !== 0 && exceeds(totals, limit)) break;
737
+ admitted.add(entry.key);
738
+ }
739
+ return admitted;
740
+ }
741
+ function is_admitted(key, reservations, budget) {
742
+ return admitted_keys(reservations, budget.cores, budget.memory_mb).has(key);
743
+ }
744
+ function sum_load(reservations) {
745
+ const load = { cores: 0, memory_mb: 0 };
746
+ for (const entry of reservations) add_load(load, entry.reservation);
747
+ return load;
748
+ }
749
+ function is_ramped(reservation, now) {
750
+ const { admitted_at } = reservation;
751
+ return admitted_at !== void 0 && now - admitted_at >= RAMP_UP_MS;
752
+ }
753
+ function ledger_load(reservations, now) {
754
+ const admitted = reservations.filter((entry) => entry.reservation.admitted_at !== void 0);
755
+ const ramped = admitted.filter((entry) => is_ramped(entry.reservation, now));
756
+ return { cores: sum_load(admitted).cores, memory_mb: sum_load(ramped).memory_mb };
757
+ }
758
+ function total_weight(reservations) {
759
+ return sum_load(reservations).cores;
760
+ }
761
+ function admitted_load(reservations, budget) {
762
+ const admitted = admitted_keys(reservations, budget);
763
+ return total_weight(reservations.filter((entry) => admitted.has(entry.key)));
764
+ }
765
+ function describe_memory(ledger, budget) {
766
+ if (!Number.isFinite(budget.memory_mb)) return "";
767
+ return ` and ${String(Math.round(ledger.memory_mb))} MB of memory against ${String(Math.round(budget.memory_mb))} MB`;
768
+ }
769
+ function describe_overflow(admission) {
770
+ const { overflow } = admission;
771
+ if (overflow === void 0) return void 0;
772
+ const { ledger, budget } = overflow;
773
+ const waited = String(Math.round(overflow.waited_ms / MS_PER_SECOND));
774
+ const cores = `the ledger held ${String(ledger.cores)} cores against a budget of ${String(budget.cores)}`;
775
+ return `started past the core budget after ${waited}s \u2014 ${cores}${describe_memory(ledger, budget)}`;
776
+ }
777
+ var core_admission = {
778
+ RAMP_UP_MS,
779
+ admitted_keys,
780
+ admitted_load,
781
+ describe_overflow,
782
+ is_admitted,
783
+ ledger_load,
784
+ sum_load
785
+ };
786
+
787
+ // scripts/gate/machine-capacity.ts
788
+ import { readFile } from "node:fs/promises";
789
+ import { availableParallelism as availableParallelism2, cpus, totalmem } from "node:os";
790
+ import { execa } from "execa";
791
+ var SAMPLE_WINDOW_MS = 250;
792
+ var BASELINE_CORES = 2;
793
+ var BYTES_PER_MB = 1048576;
794
+ var KB_PER_MB = 1024;
795
+ var PERCENT = 100;
796
+ var MEMINFO_PATH = "/proc/meminfo";
797
+ var LINUX_AVAILABLE = /^MemAvailable:\s+(?<kb>\d+) kB/mu;
798
+ var PRESSURE_ARGUMENTS = ["-n", "kern.memorystatus_level"];
799
+ var PRESSURE_LEVEL = /^\s*(?<level>\d+)\s*$/u;
800
+ function cpu_times() {
801
+ let busy = 0;
802
+ let idle = 0;
803
+ for (const { times } of cpus()) {
804
+ busy += times.user + times.nice + times.sys + times.irq;
805
+ idle += times.idle;
806
+ }
807
+ return { busy, total: busy + idle };
808
+ }
809
+ function busy_cores_between(before, after, cores) {
810
+ const total = after.total - before.total;
811
+ if (total <= 0) return void 0;
812
+ return (after.busy - before.busy) / total * cores;
813
+ }
814
+ function parse_darwin_pressure(output, total_bytes) {
815
+ const level = PRESSURE_LEVEL.exec(output)?.groups?.["level"];
816
+ if (level === void 0) return void 0;
817
+ return Number(level) / PERCENT * (total_bytes / BYTES_PER_MB);
818
+ }
819
+ function parse_linux_available(meminfo) {
820
+ const kb = LINUX_AVAILABLE.exec(meminfo)?.groups?.["kb"];
821
+ return kb === void 0 ? void 0 : Number(kb) / KB_PER_MB;
822
+ }
823
+ async function read_available_mb(platform2 = process.platform) {
824
+ try {
825
+ if (platform2 === "darwin") {
826
+ const { stdout } = await execa("sysctl", PRESSURE_ARGUMENTS);
827
+ return parse_darwin_pressure(stdout, totalmem());
828
+ }
829
+ return platform2 === "linux" ? parse_linux_available(await readFile(MEMINFO_PATH, "utf8")) : void 0;
830
+ } catch {
831
+ return void 0;
832
+ }
833
+ }
834
+ function is_unquoted() {
835
+ return cpus().length > 0 && cpus().length === availableParallelism2();
836
+ }
837
+ async function default_sleep(ms) {
838
+ await new Promise((resolve) => {
839
+ setTimeout(resolve, ms);
840
+ });
841
+ }
842
+ async function read_machine(sleep = default_sleep) {
843
+ const before = cpu_times();
844
+ const [available_mb] = await Promise.all([read_available_mb(), sleep(SAMPLE_WINDOW_MS)]);
845
+ const busy_cores = is_unquoted() ? busy_cores_between(before, cpu_times(), cpus().length) : void 0;
846
+ return { busy_cores, available_mb };
847
+ }
848
+ function external_cores(busy_cores, ledger_cores) {
849
+ if (busy_cores === void 0) return 0;
850
+ return Math.floor(Math.max(0, busy_cores - ledger_cores - BASELINE_CORES));
851
+ }
852
+ function machine_budget(cores, reading, ledger) {
853
+ return {
854
+ cores: cores - external_cores(reading.busy_cores, ledger.cores),
855
+ memory_mb: reading.available_mb === void 0 ? Infinity : reading.available_mb + ledger.memory_mb
856
+ };
857
+ }
858
+ var machine_capacity = {
859
+ BASELINE_CORES,
860
+ busy_cores_between,
861
+ machine_budget,
862
+ parse_darwin_pressure,
863
+ parse_linux_available,
864
+ read_machine
865
+ };
866
+
867
+ // scripts/gate/core-budget.ts
868
+ var RESERVED_PREFIX = "josh-core-reserved-";
869
+ var RESERVED_SUFFIX = ".json";
870
+ var POLL_INTERVAL_MS = 50;
871
+ var WAIT_CAP_MS = 12e4;
872
+ var MIN_BUDGET = 1;
873
+ var CORE_WEIGHTS = {
874
+ lint: 2,
875
+ type_check: 1,
876
+ spell_check: 1,
877
+ eslint_scan: 1
878
+ };
879
+ var MEMORY_MB = {
880
+ lint: 2400,
881
+ type_check: 1300,
882
+ spell_check: 350,
883
+ eslint_scan: 2400,
884
+ unit_worker: 350
885
+ };
886
+ var HELD_KEY = "JOSH_CORE_RESERVED";
887
+ var HELD_VALUE = "1";
888
+ var reservation_schema = process_owner_schema.extend({
889
+ weight: z4.number(),
890
+ claimed_at: z4.number(),
891
+ memory_mb: z4.number().optional(),
892
+ admitted_at: z4.number().optional()
893
+ });
894
+ function marker_name(key) {
895
+ return `${RESERVED_PREFIX}${key}${RESERVED_SUFFIX}`;
896
+ }
897
+ function is_running2(reservation) {
898
+ return process_identity.is_same_process(reservation.pid, reservation.process_start) !== false;
899
+ }
900
+ function read_reservation(source) {
901
+ const raw = stamp_file.read_stamp_text(source);
902
+ if (raw === void 0) return void 0;
903
+ try {
904
+ const parsed = reservation_schema.safeParse(JSON.parse(raw));
905
+ return parsed.success ? parsed.data : void 0;
906
+ } catch {
907
+ return void 0;
908
+ }
909
+ }
910
+ function sweep_marker2(source) {
911
+ try {
912
+ stamp_file.remove_stamp(source);
913
+ } catch {
914
+ }
915
+ }
916
+ function live_reservation(source) {
917
+ const reservation = read_reservation(source);
918
+ if (reservation === void 0) return void 0;
919
+ if (is_running2(reservation)) return reservation;
920
+ sweep_marker2(source);
921
+ return void 0;
922
+ }
923
+ function marker_files2(directory) {
924
+ try {
925
+ return readdirSync2(directory).filter(
926
+ (name) => name.startsWith(RESERVED_PREFIX) && name.endsWith(RESERVED_SUFFIX)
927
+ );
928
+ } catch {
929
+ return [];
930
+ }
931
+ }
932
+ function live_reservations(directory = PLATFORM_TEMP_ROOT) {
933
+ return marker_files2(directory).flatMap((name) => {
934
+ const reservation = live_reservation(path8.join(directory, name));
935
+ return reservation === void 0 ? [] : { key: name, reservation };
936
+ });
937
+ }
938
+ function normalize_budget(budget) {
939
+ return Number.isFinite(budget) ? Math.max(MIN_BUDGET, Math.floor(budget)) : MIN_BUDGET;
940
+ }
941
+ async function default_sleep2(ms) {
942
+ await new Promise((resolve) => {
943
+ setTimeout(resolve, ms);
944
+ });
945
+ }
946
+ function write_reservation(target, fields) {
947
+ stamp_file.replace_stamp(target, { ...process_identity.own_fields(), ...fields });
948
+ }
949
+ function resolve_timing(options) {
950
+ return {
951
+ now: options.now ?? Date.now,
952
+ sleep: options.sleep ?? default_sleep2,
953
+ poll_interval_ms: options.poll_interval_ms ?? POLL_INTERVAL_MS,
954
+ wait_cap_ms: options.wait_cap_ms ?? WAIT_CAP_MS
955
+ };
956
+ }
957
+ async function current_budget(context, reservations) {
958
+ if (reservations.length <= 1) return { cores: context.budget, memory_mb: Infinity };
959
+ const reading = await context.read_machine();
960
+ const ledger = core_admission.ledger_load(reservations, context.now());
961
+ const budget = machine_capacity.machine_budget(context.budget, reading, ledger);
962
+ return { ...budget, cores: normalize_budget(budget.cores) };
963
+ }
964
+ function admit(context, overflow) {
965
+ write_reservation(context.target, { ...context.fields, admitted_at: context.now() });
966
+ return { overflow };
967
+ }
968
+ function overflow_of(context, reservations, budget) {
969
+ return {
970
+ waited_ms: context.now() - context.fields.claimed_at,
971
+ ledger: core_admission.sum_load(reservations),
972
+ budget
973
+ };
974
+ }
975
+ async function poll_admission(context) {
976
+ const reservations = live_reservations(context.directory);
977
+ const budget = await current_budget(context, reservations);
978
+ if (core_admission.is_admitted(context.key, reservations, budget)) return admit(context);
979
+ if (context.now() >= context.deadline) {
980
+ return admit(context, overflow_of(context, reservations, budget));
981
+ }
982
+ return void 0;
983
+ }
984
+ async function await_admission(context) {
985
+ let admission = await poll_admission(context);
986
+ while (admission === void 0) {
987
+ await context.sleep(context.poll_interval_ms);
988
+ admission = await poll_admission(context);
989
+ }
990
+ return admission;
991
+ }
992
+ async function reserve(weight, options = {}) {
993
+ const timing = resolve_timing(options);
994
+ const directory = options.directory ?? PLATFORM_TEMP_ROOT;
995
+ const claimed_at = timing.now();
996
+ const name = marker_name(randomUUID3());
997
+ const target = path8.join(directory, name);
998
+ const fields = { weight, claimed_at, memory_mb: options.memory_mb };
999
+ write_reservation(target, fields);
1000
+ const admission = await await_admission({
1001
+ ...timing,
1002
+ key: name,
1003
+ target,
1004
+ directory,
1005
+ budget: normalize_budget(options.budget ?? availableParallelism3()),
1006
+ deadline: claimed_at + timing.wait_cap_ms,
1007
+ fields,
1008
+ read_machine: options.read_machine ?? machine_capacity.read_machine
1009
+ });
1010
+ return { target, admission };
1011
+ }
1012
+ function release(handle) {
1013
+ sweep_marker2(handle.target);
1014
+ }
1015
+ async function with_core_reservation(weight, run2, options = {}) {
1016
+ const handle = await reserve(weight, options);
1017
+ try {
1018
+ return await run2(handle.admission);
1019
+ } finally {
1020
+ release(handle);
1021
+ }
1022
+ }
1023
+ function is_held() {
1024
+ return process.env[HELD_KEY] === HELD_VALUE;
1025
+ }
1026
+ function set_held_mark(value) {
1027
+ process.env[HELD_KEY] = value;
1028
+ }
1029
+ async function with_held_mark(run2) {
1030
+ const previous = process.env[HELD_KEY] ?? "";
1031
+ set_held_mark(HELD_VALUE);
1032
+ try {
1033
+ return await run2();
1034
+ } finally {
1035
+ set_held_mark(previous);
1036
+ }
1037
+ }
1038
+ async function with_command_reservation(weight, run2, options = {}) {
1039
+ if (is_held() || unit_worker_share.is_nested_run()) return await run2();
1040
+ return await with_core_reservation(weight, async () => await with_held_mark(run2), options);
1041
+ }
1042
+ var core_budget = {
1043
+ CORE_WEIGHTS,
1044
+ HELD_KEY,
1045
+ HELD_VALUE,
1046
+ MEMORY_MB,
1047
+ RESERVED_PREFIX,
1048
+ admitted_keys: core_admission.admitted_keys,
1049
+ admitted_load: core_admission.admitted_load,
1050
+ describe_overflow: core_admission.describe_overflow,
1051
+ is_held,
1052
+ live_reservations,
1053
+ release,
1054
+ reserve,
1055
+ with_command_reservation,
1056
+ with_core_reservation,
1057
+ with_held_mark
1058
+ };
1059
+
304
1060
  // scripts/josh/josh-logic.ts
305
1061
  import { execaSync as execaSync2 } from "execa";
306
1062
 
@@ -410,6 +1166,9 @@ var BACKLOG_COMMANDS = {
410
1166
  },
411
1167
  "backlog:stalled": {
412
1168
  script: "scripts/backlog/backlog-stalled-cli.ts",
1169
+ // A stall sends one Telegram warning (joshuafolkken/kit#3357). The `Stop` hook calls the detector
1170
+ // directly, so this flag costs only the manual command its in-process dispatch.
1171
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
413
1172
  description: "Report whether ready backlog work is sitting undispatched with a free lane and no recent dispatch",
414
1173
  category: "AI tools",
415
1174
  reference: ["", "automation", ["network"]]
@@ -428,7 +1187,8 @@ var DOCUMENT_COMMANDS = {
428
1187
  script: "scripts/document/document-section-cli.ts",
429
1188
  description: 'Print one section of a markdown document, for a `file.md` \u2192 "Heading" reference',
430
1189
  category: "AI tools",
431
- reference: ["<file> <heading>", "automation", ["none"]]
1190
+ reference: ["<file> <heading>", "automation", ["none"]],
1191
+ is_bundled: true
432
1192
  },
433
1193
  "read:set": {
434
1194
  script: "scripts/document/read-set-cli.ts",
@@ -534,10 +1294,16 @@ var ISSUE_COMMANDS = {
534
1294
  description: "File an Issue with every filing step: lint, Origin, WIP cap, duplicate scout, labels, then epic:bundle",
535
1295
  category: "AI tools",
536
1296
  reference: [
537
- "<title> --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>] [--distinct <N,\u2026>] [--over-cap] [--no-auto-ok]",
1297
+ "<title> --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>] [--distinct <N,\u2026>] [--over-cap] [--no-auto-ok] [--release]",
538
1298
  "automation",
539
1299
  ["network"]
540
1300
  ]
1301
+ },
1302
+ "issue:release": {
1303
+ script: "scripts/issue/issue-release-cli.ts",
1304
+ description: "Link an Issue to the repository's open release Issue as its blocker, filing one when none is open",
1305
+ category: "AI tools",
1306
+ reference: ["<issue>", "automation", ["network"]]
541
1307
  }
542
1308
  };
543
1309
 
@@ -545,6 +1311,10 @@ var ISSUE_COMMANDS = {
545
1311
  var LANE_SCRIPT = "scripts/lane/lane-cli.ts";
546
1312
  var LANE_ARGUMENTS = { script: LANE_SCRIPT, tsx_arguments: OPTIONAL_ENV_FILE_FLAGS };
547
1313
  var ISSUE_WITH_OPTIONS = "<issue> [options]";
1314
+ var MEASURE_ARGUMENTS = {
1315
+ script: "scripts/lane/lane-measure-cli.ts",
1316
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS
1317
+ };
548
1318
  var LANE_COMMANDS = {
549
1319
  "lane:open": {
550
1320
  ...LANE_ARGUMENTS,
@@ -569,7 +1339,7 @@ var LANE_COMMANDS = {
569
1339
  },
570
1340
  "lane:prune": {
571
1341
  ...LANE_ARGUMENTS,
572
- description: "Close every lane an interruption left without its work tree",
1342
+ description: "Close every lane an interruption left without its work tree, then sweep unregistered leftovers under the lanes root",
573
1343
  category: "AI tools",
574
1344
  reference: ["", "automation", ["files", "git"]],
575
1345
  default_script_arguments: ["prune"]
@@ -600,11 +1370,27 @@ var LANE_COMMANDS = {
600
1370
  description: "Collapse a backlogrun lane-start event into one call: open the lane, pop and re-install on the first, dispatch the child",
601
1371
  category: "AI tools",
602
1372
  reference: ["<issue> [--stash <message>]", "automation", ["files", "git", "processes"]]
1373
+ },
1374
+ // The lane-limit measurement (joshuafolkken/kit#3355): `.env` is read so `lane:stats` labels the row
1375
+ // with the `JOSH_LANE_LIMIT` a person set there.
1376
+ "lane:sample": {
1377
+ ...MEASURE_ARGUMENTS,
1378
+ description: "Record the machine load (load average, swap, free memory, working lanes) to the lane ledger",
1379
+ category: "AI tools",
1380
+ reference: ["[--every <seconds>]", "maintainer", ["files"]],
1381
+ default_script_arguments: ["sample"]
1382
+ },
1383
+ "lane:stats": {
1384
+ ...MEASURE_ARGUMENTS,
1385
+ description: "Print one table row of lane throughput, gate duration and machine load over a period",
1386
+ category: "AI tools",
1387
+ reference: ["--period <days> [--limit <lane-limit>]", "maintainer", ["none"]],
1388
+ default_script_arguments: ["stats"]
603
1389
  }
604
1390
  };
605
1391
 
606
1392
  // scripts/josh/josh-commands-run.ts
607
- var RUN_HOLD_SCRIPT = "scripts/run/run-hold-cli.ts";
1393
+ var RUN_HOLD_SCRIPT = "scripts/run/hold/run-hold-cli.ts";
608
1394
  var RUN_COMMANDS = {
609
1395
  "run:hold": {
610
1396
  script: RUN_HOLD_SCRIPT,
@@ -620,19 +1406,22 @@ var RUN_COMMANDS = {
620
1406
  default_script_arguments: ["--release"]
621
1407
  },
622
1408
  "run:tidy": {
623
- script: "scripts/run/run-tidy-cli.ts",
1409
+ script: "scripts/run/tidy/run-tidy-cli.ts",
624
1410
  description: "Close merged lanes and drop stashes whose issues are all merged",
625
1411
  category: "AI tools",
626
1412
  reference: ["", "automation", ["git", "network", "files"]]
627
1413
  },
628
1414
  "run:carry": {
629
- script: "scripts/run/run-carry-cli.ts",
1415
+ script: "scripts/run/carry/run-carry-cli.ts",
1416
+ // `--stopped` sends the stop confirmation, so the Telegram credentials come from `.env` as for
1417
+ // `run:wake` below (joshuafolkken/kit#3357).
1418
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
630
1419
  description: "Carry one invocation\u2019s budget across its own session cuts",
631
1420
  category: "AI tools",
632
1421
  reference: ["<operation> [arguments...]", "automation", ["files"]]
633
1422
  },
634
1423
  "run:wake": {
635
- script: "scripts/run/run-wake-cli.ts",
1424
+ script: "scripts/run/wake/run-wake-cli.ts",
636
1425
  // `.env` rather than the ambient environment:
637
1426
  // the failure warning needs the Telegram credentials, the same
638
1427
  // reasons `notify` and `followup` carry these flags.
@@ -642,7 +1431,7 @@ var RUN_COMMANDS = {
642
1431
  reference: ["[options]", "automation", ["processes", "notifications"]]
643
1432
  },
644
1433
  "run:cut": {
645
- script: "scripts/run/run-cut-cli.ts",
1434
+ script: "scripts/run/cut/run-cut-cli.ts",
646
1435
  description: "Cut a lane child before the gate and resume a fresh process",
647
1436
  category: "AI tools",
648
1437
  reference: ["[--resume] <issue> [--impl] [--handoff <path>]", "automation", ["files"]]
@@ -660,7 +1449,7 @@ var RUN_COMMANDS = {
660
1449
  reference: ["<issue> --output <path> [--repo <owner/repo>]", "automation", ["network"]]
661
1450
  },
662
1451
  "run:progress": {
663
- script: "scripts/run/run-progress-cli.ts",
1452
+ script: "scripts/run/progress/run-progress-cli.ts",
664
1453
  description: "Report an unattended run\u2019s progress once it has gone quiet for an interval",
665
1454
  category: "AI tools",
666
1455
  reference: [
@@ -679,7 +1468,9 @@ var RUN_COMMANDS = {
679
1468
  // read the budget, gather the issue reads and decide the pre-implementation step. `run:hold`,
680
1469
  // `cost --cut`, `run:prep` and `run:step` were four round trips re-billing a lane's full context each.
681
1470
  "run:entry": {
682
- script: "scripts/run/run-entry-cli.ts",
1471
+ script: "scripts/run/entry/run-entry-cli.ts",
1472
+ // A `busy` hold or an `over` budget sends the stop confirmation (joshuafolkken/kit#3357).
1473
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
683
1474
  description: "Open a run in one call: claim the tree, read the budget, bundle the reads, decide the pre-implementation step",
684
1475
  category: "AI tools",
685
1476
  reference: ["<issue> [--to <command>]", "automation", ["git", "network", "files"]]
@@ -843,13 +1634,13 @@ var AI_COMMANDS = {
843
1634
  reference: ["[<owner/repo>]", "automation", ["none"]]
844
1635
  },
845
1636
  "run:merge": {
846
- script: "scripts/run/run-merge-cli.ts",
1637
+ script: "scripts/run/merge/run-merge-cli.ts",
847
1638
  description: "Collapse a backlogrun merge event into one call: confirm the child, do the post-merge steps, offer the next child",
848
1639
  category: "AI tools",
849
1640
  reference: [ISSUE_WITH_OPTIONS2, "automation", ["git", "network"]]
850
1641
  },
851
1642
  "run:review": {
852
- script: "scripts/run/run-review-cli.ts",
1643
+ script: "scripts/run/review/run-review-cli.ts",
853
1644
  description: "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)",
854
1645
  category: "AI tools",
855
1646
  reference: ["[--join]", "automation", ["processes", "files"]]
@@ -868,7 +1659,7 @@ var AI_COMMANDS = {
868
1659
  // (`run:tail`) were four round trips re-billing the run's full context each. It stops at the first
869
1660
  // failed step and names it, so the run reads only the step to fix.
870
1661
  ship: {
871
- script: "scripts/run/run-ship-cli.ts",
1662
+ script: "scripts/run/ship/run-ship-cli.ts",
872
1663
  description: "Ship a change in one call: gate, commit/push/PR, the CI-wait merge and the report bookkeeping, stopping at the first failed step",
873
1664
  category: "AI tools",
874
1665
  reference: [
@@ -878,7 +1669,7 @@ var AI_COMMANDS = {
878
1669
  ]
879
1670
  },
880
1671
  "run:event": {
881
- script: "scripts/run/run-event-cli.ts",
1672
+ script: "scripts/run/event/run-event-cli.ts",
882
1673
  description: "Append to, read or watch the run\u2019s append-only event stream (--append <kind> <text> | --from|--follow <n> | --watch [<n>] | --last)",
883
1674
  category: "AI tools",
884
1675
  reference: [
@@ -938,6 +1729,192 @@ var CLONE_COMMANDS = {
938
1729
  }
939
1730
  };
940
1731
 
1732
+ // scripts/gate/gate-plan.ts
1733
+ import { availableParallelism as availableParallelism4 } from "node:os";
1734
+
1735
+ // scripts/lib/status-icons.ts
1736
+ var FAIL_ICON = "\u2717";
1737
+ var PASS_ICON = "\u2714";
1738
+ var status_icons = { FAIL_ICON, PASS_ICON };
1739
+
1740
+ // scripts/josh/josh-verdict.ts
1741
+ var { FAIL_ICON: FAIL_ICON2, PASS_ICON: PASS_ICON2 } = status_icons;
1742
+ var GATE_SUBJECT = "verification gate";
1743
+ var GATE_PASSED_PREFIX = `${PASS_ICON2} ${GATE_SUBJECT} passed`;
1744
+ var GATE_FAILED_PREFIX = `${FAIL_ICON2} ${GATE_SUBJECT} failed`;
1745
+ var PASSED_VERDICT = "passed";
1746
+ var FAILED_VERDICT = "failed";
1747
+ function format_gate_passed(step_count, total) {
1748
+ return `${GATE_PASSED_PREFIX} (${step_count} checks) in ${total}.`;
1749
+ }
1750
+ function format_gate_failed(failed_labels, total) {
1751
+ return `${GATE_FAILED_PREFIX}: ${failed_labels} (${total})`;
1752
+ }
1753
+ var GATE_OPENING_PREFIX = "plan: ";
1754
+ var GATE_OPENING_MARK = " checks at once";
1755
+ function is_gate_opening(line) {
1756
+ const trimmed = line.trimStart();
1757
+ return trimmed.startsWith(GATE_OPENING_PREFIX) && trimmed.includes(GATE_OPENING_MARK);
1758
+ }
1759
+ function read_verdict(line) {
1760
+ const trimmed = line.trimStart();
1761
+ if (trimmed.startsWith(GATE_FAILED_PREFIX)) return FAILED_VERDICT;
1762
+ if (trimmed.startsWith(GATE_PASSED_PREFIX)) return PASSED_VERDICT;
1763
+ return void 0;
1764
+ }
1765
+ var josh_verdict = {
1766
+ PASSED_VERDICT,
1767
+ FAILED_VERDICT,
1768
+ format_gate_passed,
1769
+ format_gate_failed,
1770
+ GATE_OPENING_MARK,
1771
+ GATE_OPENING_PREFIX,
1772
+ is_gate_opening,
1773
+ read_verdict
1774
+ };
1775
+
1776
+ // scripts/gate/gate-plan.ts
1777
+ var LINT_LABEL = "lint";
1778
+ var TYPE_CHECK_LABEL = "check";
1779
+ var UNIT_LABEL = "test:unit";
1780
+ var BEHAVIOR_LABEL = "behavior";
1781
+ var WARNING_CHECKER_LABELS = [LINT_LABEL, TYPE_CHECK_LABEL];
1782
+ var STATIC_CHECKS = [
1783
+ {
1784
+ label: LINT_LABEL,
1785
+ target: "lint",
1786
+ reserved_cores: core_budget.CORE_WEIGHTS.lint,
1787
+ memory_mb: core_budget.MEMORY_MB.lint
1788
+ },
1789
+ {
1790
+ label: TYPE_CHECK_LABEL,
1791
+ target: "check",
1792
+ reserved_cores: core_budget.CORE_WEIGHTS.type_check,
1793
+ memory_mb: core_budget.MEMORY_MB.type_check
1794
+ },
1795
+ {
1796
+ label: "cspell",
1797
+ target: "cspell:dot",
1798
+ reserved_cores: core_budget.CORE_WEIGHTS.spell_check,
1799
+ memory_mb: core_budget.MEMORY_MB.spell_check
1800
+ },
1801
+ { label: BEHAVIOR_LABEL, target: BEHAVIOR_LABEL, reserved_cores: 0 },
1802
+ // **The unused-member check reserves no core** (joshuafolkken/kit#2987): it builds one TypeScript
1803
+ // program and walks it for about 5s, and it is over well before lint and the type check. A
1804
+ // reservation would only take a place from the four-core CI runner's fan-out and a worker from the
1805
+ // unit suite for the whole gate.
1806
+ { label: "exports", target: "exports:unused", reserved_cores: 0 }
1807
+ ];
1808
+ var GATE_CHECKS = [
1809
+ ...STATIC_CHECKS,
1810
+ { label: UNIT_LABEL, target: UNIT_LABEL, reserved_cores: 0 }
1811
+ ];
1812
+ function select_gate_checks(is_unit_included) {
1813
+ return is_unit_included ? GATE_CHECKS : STATIC_CHECKS;
1814
+ }
1815
+ function has_unit_check(checks) {
1816
+ return checks.some((check) => check.label === UNIT_LABEL);
1817
+ }
1818
+ var RESERVED_CORES = STATIC_CHECKS.reduce(
1819
+ (total, check) => total + check.reserved_cores,
1820
+ 0
1821
+ );
1822
+ var MEASURED_CORES = 11;
1823
+ var MIN_CONCURRENCY = 1;
1824
+ var MIN_SHARED_CORES = 1;
1825
+ function shared_cores(available_cores, concurrent_runs) {
1826
+ const runs = Number.isFinite(concurrent_runs) ? Math.max(unit_worker_share.SOLO_RUNS, concurrent_runs) : unit_worker_share.SOLO_RUNS;
1827
+ return Math.max(MIN_SHARED_CORES, Math.floor(available_cores / runs));
1828
+ }
1829
+ function resolve_concurrency(available_cores, concurrent_runs = unit_worker_share.SOLO_RUNS, checks = GATE_CHECKS) {
1830
+ const share = shared_cores(available_cores, concurrent_runs);
1831
+ let admitted = 0;
1832
+ let reserved = 0;
1833
+ for (const check of checks) {
1834
+ reserved += check.reserved_cores;
1835
+ if (reserved > share) break;
1836
+ admitted += 1;
1837
+ }
1838
+ return Math.max(MIN_CONCURRENCY, admitted);
1839
+ }
1840
+ function resolve_unit_worker_cap(available_cores, concurrent_runs = unit_worker_share.SOLO_RUNS) {
1841
+ const share = unit_worker_share.resolve_unit_workers(available_cores, concurrent_runs);
1842
+ if (share !== void 0) return share;
1843
+ if (available_cores < MEASURED_CORES) return void 0;
1844
+ return available_cores - RESERVED_CORES;
1845
+ }
1846
+ function solo_unit_weight(available_cores) {
1847
+ return Math.max(0, available_cores - RESERVED_CORES);
1848
+ }
1849
+ function check_weight(check, plan, available_cores) {
1850
+ if (check.label !== UNIT_LABEL) return check.reserved_cores;
1851
+ return plan.unit_worker_cap ?? solo_unit_weight(available_cores);
1852
+ }
1853
+ function unit_memory(workers) {
1854
+ return workers * core_budget.MEMORY_MB.unit_worker;
1855
+ }
1856
+ function check_memory(check, plan, available_cores) {
1857
+ if (check.label !== UNIT_LABEL) return check.memory_mb ?? 0;
1858
+ return unit_memory(check_weight(check, plan, available_cores));
1859
+ }
1860
+ function direct_unit_weight(available_cores = availableParallelism4(), live_runs = unit_worker_share.live_run_count()) {
1861
+ const weight = unit_worker_share.current_share(available_cores, live_runs) ?? solo_unit_weight(available_cores);
1862
+ return Math.max(unit_worker_share.MIN_WORKERS, weight);
1863
+ }
1864
+ function direct_unit_memory() {
1865
+ return unit_memory(direct_unit_weight());
1866
+ }
1867
+ function plan_of(concurrency, unit_worker_cap, checks = GATE_CHECKS) {
1868
+ return { checks, concurrency, unit_worker_cap };
1869
+ }
1870
+ function resolve_gate_plan(available_cores = availableParallelism4(), concurrent_runs = unit_worker_share.SOLO_RUNS, is_unit_included = true) {
1871
+ const checks = select_gate_checks(is_unit_included);
1872
+ return {
1873
+ checks,
1874
+ concurrency: resolve_concurrency(available_cores, concurrent_runs, checks),
1875
+ unit_worker_cap: is_unit_included ? resolve_unit_worker_cap(available_cores, concurrent_runs) : void 0
1876
+ };
1877
+ }
1878
+ function format_machine(available_cores, concurrent_runs) {
1879
+ const cores = `${String(available_cores)} cores`;
1880
+ if (concurrent_runs <= unit_worker_share.SOLO_RUNS) return cores;
1881
+ return `${cores}, ${String(concurrent_runs)} unit runs`;
1882
+ }
1883
+ function format_unit_cap(plan) {
1884
+ if (!has_unit_check(plan.checks)) return `${UNIT_LABEL} elsewhere`;
1885
+ if (plan.unit_worker_cap === void 0) return `${UNIT_LABEL} unrestricted`;
1886
+ return `${UNIT_LABEL} at ${String(plan.unit_worker_cap)} workers`;
1887
+ }
1888
+ function format_gate_plan(plan, available_cores = availableParallelism4(), concurrent_runs = unit_worker_share.SOLO_RUNS) {
1889
+ const cap = format_unit_cap(plan);
1890
+ const count = `${String(plan.concurrency)} of ${String(plan.checks.length)}`;
1891
+ const width = `${count}${josh_verdict.GATE_OPENING_MARK}`;
1892
+ const machine = format_machine(available_cores, concurrent_runs);
1893
+ return `${josh_verdict.GATE_OPENING_PREFIX}${width}, ${cap} (${machine})`;
1894
+ }
1895
+ var gate_plan = {
1896
+ GATE_CHECKS,
1897
+ LINT_LABEL,
1898
+ MEASURED_CORES,
1899
+ RESERVED_CORES,
1900
+ STATIC_CHECKS,
1901
+ TYPE_CHECK_LABEL,
1902
+ UNIT_LABEL,
1903
+ WARNING_CHECKER_LABELS,
1904
+ check_memory,
1905
+ check_weight,
1906
+ direct_unit_memory,
1907
+ direct_unit_weight,
1908
+ format_gate_plan,
1909
+ format_machine,
1910
+ has_unit_check,
1911
+ plan_of,
1912
+ resolve_concurrency,
1913
+ resolve_gate_plan,
1914
+ resolve_unit_worker_cap,
1915
+ select_gate_checks
1916
+ };
1917
+
941
1918
  // scripts/josh/josh-commands-development.ts
942
1919
  var FILE_ARGUMENTS = "[files...]";
943
1920
  var REQUIRED_FILE_ARGUMENTS = "<files...>";
@@ -961,25 +1938,33 @@ var DEV_COMMANDS = {
961
1938
  script: "scripts/lint/lint-parallel.ts",
962
1939
  description: "Check code with prettier and eslint (skips a tool a basic project lacks)",
963
1940
  category: "Development",
964
- reference: ["", "developer", ["processes"]]
1941
+ reference: ["", "developer", ["processes"]],
1942
+ core_weight: core_budget.CORE_WEIGHTS.lint,
1943
+ memory_mb: core_budget.MEMORY_MB.lint
965
1944
  },
966
1945
  "lint:related": {
967
1946
  script: "scripts/lint/lint-related.ts",
968
1947
  description: "Check only the changed files with prettier and eslint (whole tree on fallback)",
969
1948
  category: "Development",
970
- reference: [FILE_ARGUMENTS, "developer", ["processes"]]
1949
+ reference: [FILE_ARGUMENTS, "developer", ["processes"]],
1950
+ core_weight: core_budget.CORE_WEIGHTS.lint,
1951
+ memory_mb: core_budget.MEMORY_MB.lint
971
1952
  },
972
1953
  lines: {
973
1954
  script: "scripts/lines/lines-command.ts",
974
1955
  description: "Print a file's code lines against the max-lines limit and the headroom left",
975
1956
  category: "Development",
976
- reference: [REQUIRED_FILE_ARGUMENTS, "developer", ["none"]]
1957
+ reference: [REQUIRED_FILE_ARGUMENTS, "developer", ["none"]],
1958
+ core_weight: core_budget.CORE_WEIGHTS.eslint_scan,
1959
+ memory_mb: core_budget.MEMORY_MB.eslint_scan
977
1960
  },
978
1961
  "refactor:scan": {
979
1962
  script: "scripts/refactor/refactor-scan-cli.ts",
980
1963
  description: "List refactoring candidates in the changed scope by category and answer clear/candidates",
981
1964
  category: "Development",
982
- reference: ["", "automation", ["processes"]]
1965
+ reference: ["", "automation", ["processes"]],
1966
+ core_weight: core_budget.CORE_WEIGHTS.eslint_scan,
1967
+ memory_mb: core_budget.MEMORY_MB.eslint_scan
983
1968
  },
984
1969
  bytes: {
985
1970
  script: "scripts/lines/bytes-command.ts",
@@ -1058,7 +2043,9 @@ var DEV_COMMANDS = {
1058
2043
  script: "scripts/lint/cspell-cached.ts",
1059
2044
  description: "Run spell check including dotfiles",
1060
2045
  category: "Development",
1061
- reference: ["", "developer", ["processes"]]
2046
+ reference: ["", "developer", ["processes"]],
2047
+ core_weight: core_budget.CORE_WEIGHTS.spell_check,
2048
+ memory_mb: core_budget.MEMORY_MB.spell_check
1062
2049
  },
1063
2050
  behavior: {
1064
2051
  script: "scripts/behavior/behavior-cli.ts",
@@ -1076,13 +2063,17 @@ var DEV_COMMANDS = {
1076
2063
  script: "scripts/test/test-unit-guard.ts",
1077
2064
  description: "Run unit tests with Vitest (skips when Vitest is absent; fails when it has no tests)",
1078
2065
  category: "Development",
1079
- reference: [FILTER_ARGUMENTS, "developer", ["processes"]]
2066
+ reference: [FILTER_ARGUMENTS, "developer", ["processes"]],
2067
+ core_weight: gate_plan.direct_unit_weight,
2068
+ memory_mb: gate_plan.direct_unit_memory
1080
2069
  },
1081
2070
  "test:related": {
1082
2071
  script: "scripts/test/test-related.ts",
1083
2072
  description: "Run only the unit tests related to the changed files (full suite on fallback)",
1084
2073
  category: "Development",
1085
- reference: [FILE_ARGUMENTS, "developer", ["processes"]]
2074
+ reference: [FILE_ARGUMENTS, "developer", ["processes"]],
2075
+ core_weight: gate_plan.direct_unit_weight,
2076
+ memory_mb: gate_plan.direct_unit_memory
1086
2077
  },
1087
2078
  "test:declared": {
1088
2079
  script: "scripts/test/test-declared.ts",
@@ -1125,7 +2116,9 @@ var DEV_COMMANDS = {
1125
2116
  script: "scripts/gate/type-check-command.ts",
1126
2117
  description: "Type-check with tsc (skips a basic project with no TypeScript to check)",
1127
2118
  category: "Development",
1128
- reference: ["[arguments...]", "developer", ["processes"]]
2119
+ reference: ["[arguments...]", "developer", ["processes"]],
2120
+ core_weight: core_budget.CORE_WEIGHTS.type_check,
2121
+ memory_mb: core_budget.MEMORY_MB.type_check
1129
2122
  },
1130
2123
  port: {
1131
2124
  script: "scripts/ports/port-command.ts",
@@ -1222,7 +2215,7 @@ var MAINTENANCE_COMMANDS = {
1222
2215
  script: "scripts/overrides/overrides-check.ts",
1223
2216
  description: "Check pnpm overrides for drift",
1224
2217
  category: "Maintenance",
1225
- reference: ["[--save]", "maintainer", ["files"]]
2218
+ reference: ["[--save]", "developer", ["files"]]
1226
2219
  },
1227
2220
  audit: {
1228
2221
  script: "scripts/security/security-audit.ts",
@@ -1246,11 +2239,11 @@ var MAINTENANCE_COMMANDS = {
1246
2239
  shell: [
1247
2240
  "sh",
1248
2241
  "-c",
1249
- "export NODE_AUTH_TOKEN=$(gh auth token) && pnpm josh latest:guard && pnpm josh latest:corepack && pnpm josh latest:update && pnpm josh ranges && pnpm josh audit && pnpm josh latest:scope --record"
2242
+ "export NODE_AUTH_TOKEN=$(gh auth token) && pnpm josh latest:guard && pnpm josh latest:update && pnpm josh ranges && pnpm josh audit && pnpm josh latest:corepack && pnpm josh latest:scope --record"
1250
2243
  ],
1251
- description: "Update pnpm, dependencies, and run security audit",
2244
+ description: "Update dependencies, run security audit, then update pnpm",
1252
2245
  category: "Maintenance",
1253
- reference: ["", "maintainer", ["files", "network", "processes"]],
2246
+ reference: ["", "developer", ["files", "network", "processes"]],
1254
2247
  argument_targets: ["latest:corepack", "latest:update", "audit"]
1255
2248
  },
1256
2249
  "latest:scope": {
@@ -1273,13 +2266,13 @@ var MAINTENANCE_COMMANDS = {
1273
2266
  script: "scripts/version/latest-corepack.ts",
1274
2267
  description: "Update pnpm on the current major while preserving the integrity pin",
1275
2268
  category: "Maintenance",
1276
- reference: ["", "maintainer", ["files", "network"]]
2269
+ reference: ["", "developer", ["files", "network"]]
1277
2270
  },
1278
2271
  "latest:update": {
1279
2272
  script: "scripts/version/latest-update.ts",
1280
2273
  description: "Update all dependencies to latest",
1281
2274
  category: "Maintenance",
1282
- reference: ["", "maintainer", ["files", "network"]]
2275
+ reference: ["", "developer", ["files", "network"]]
1283
2276
  }
1284
2277
  };
1285
2278
 
@@ -1602,7 +2595,9 @@ var ALIASES = {
1602
2595
  rtr: "retrospective",
1603
2596
  rvf: "review:findings",
1604
2597
  ruv: "rule:value",
1605
- ev: "eval"
2598
+ ev: "eval",
2599
+ lsm: "lane:sample",
2600
+ lst: "lane:stats"
1606
2601
  };
1607
2602
 
1608
2603
  // scripts/josh/josh-composite-arguments.ts
@@ -1633,15 +2628,23 @@ var composite_arguments = { format_rejection, is_composite_shell, reject_extra_a
1633
2628
 
1634
2629
  // scripts/josh/josh-in-process.ts
1635
2630
  import { realpathSync } from "node:fs";
2631
+ import path9 from "node:path";
1636
2632
  import { pathToFileURL } from "node:url";
1637
2633
  var TYPESCRIPT_EXTENSION = ".ts";
2634
+ var JAVASCRIPT_EXTENSION = ".js";
2635
+ var BUNDLED_COMMAND_DIRECTORY = path9.join("dist", "commands");
1638
2636
  var FAILURE_EXIT_CODE = 1;
1639
2637
  function is_typescript_dispatcher(dispatcher_url) {
1640
2638
  return dispatcher_url.endsWith(TYPESCRIPT_EXTENSION);
1641
2639
  }
1642
- function can_run_in_process(entry, dispatcher_url) {
1643
- if (entry.script === void 0 || entry.tsx_arguments !== void 0) return false;
1644
- return is_typescript_dispatcher(dispatcher_url);
2640
+ function bundled_script_path(package_directory, script) {
2641
+ const name = `${path9.basename(script, TYPESCRIPT_EXTENSION)}${JAVASCRIPT_EXTENSION}`;
2642
+ return path9.join(package_directory, BUNDLED_COMMAND_DIRECTORY, name);
2643
+ }
2644
+ function in_process_target(entry, package_directory, dispatcher_url) {
2645
+ if (entry.script === void 0 || entry.tsx_arguments !== void 0) return void 0;
2646
+ if (is_typescript_dispatcher(dispatcher_url)) return path9.join(package_directory, entry.script);
2647
+ return entry.is_bundled === true ? bundled_script_path(package_directory, entry.script) : void 0;
1645
2648
  }
1646
2649
  function read_exit_code() {
1647
2650
  const code = process.exitCode;
@@ -1665,7 +2668,7 @@ async function run_in_process(script_path, script_arguments) {
1665
2668
  }
1666
2669
  return read_exit_code();
1667
2670
  }
1668
- var josh_in_process = { can_run_in_process, run_in_process };
2671
+ var josh_in_process = { bundled_script_path, in_process_target, run_in_process };
1669
2672
 
1670
2673
  // scripts/josh/kit-only.ts
1671
2674
  function kit_only_notice(cmd) {
@@ -1685,7 +2688,7 @@ var kit_only = {
1685
2688
 
1686
2689
  // scripts/josh/run-github-prerequisite.ts
1687
2690
  import { existsSync as existsSync3 } from "node:fs";
1688
- import path3 from "node:path";
2691
+ import path10 from "node:path";
1689
2692
 
1690
2693
  // scripts/discovery/repo-origin.ts
1691
2694
  var GITHUB_HOST = "github.com";
@@ -1750,15 +2753,15 @@ function origin_section_lines(lines) {
1750
2753
  const end = rest.findIndex((line) => is_section_header(line));
1751
2754
  return end === NOT_FOUND ? rest : rest.slice(0, end);
1752
2755
  }
1753
- function entry_value(line, key) {
2756
+ function url_value(line) {
1754
2757
  const separator = line.indexOf("=");
1755
2758
  if (separator === NOT_FOUND) return void 0;
1756
- if (line.slice(0, separator).trim() !== key) return void 0;
2759
+ if (line.slice(0, separator).trim() !== URL_KEY) return void 0;
1757
2760
  return line.slice(separator + 1).trim();
1758
2761
  }
1759
2762
  function parse_origin_from_config(content) {
1760
2763
  const lines = content.split("\n").map((line) => line.trim());
1761
- return origin_section_lines(lines).map((line) => entry_value(line, URL_KEY)).find((url) => url !== void 0);
2764
+ return origin_section_lines(lines).map((line) => url_value(line)).find((url) => url !== void 0);
1762
2765
  }
1763
2766
  function section_groups(lines) {
1764
2767
  const groups = [];
@@ -1770,7 +2773,7 @@ function section_groups(lines) {
1770
2773
  }
1771
2774
  function parse_remote_urls_from_config(content) {
1772
2775
  const lines = content.split("\n").map((line) => line.trim());
1773
- return section_groups(lines).filter((group) => REMOTE_SECTION.test(group[0] ?? "")).flatMap((group) => group.map((line) => entry_value(line, URL_KEY))).filter((url) => url !== void 0);
2776
+ return section_groups(lines).filter((group) => REMOTE_SECTION.test(group[0] ?? "")).flatMap((group) => group.map((line) => url_value(line))).filter((url) => url !== void 0);
1774
2777
  }
1775
2778
  function format_identity(identity) {
1776
2779
  return `${identity.owner}${PATH_SEPARATOR2}${identity.repo}`.toLowerCase();
@@ -1796,7 +2799,7 @@ var GITHUB_RUN_COMMANDS = /* @__PURE__ */ new Set([
1796
2799
  ]);
1797
2800
  function explanation(root, command) {
1798
2801
  if (!GITHUB_RUN_COMMANDS.has(command)) return void 0;
1799
- if (!existsSync3(path3.join(root, ".git"))) {
2802
+ if (!existsSync3(path10.join(root, ".git"))) {
1800
2803
  return `${command} requires Git and a GitHub origin. Run git init and add a GitHub origin first.`;
1801
2804
  }
1802
2805
  const url = git_spawn_sync.origin_url(root);
@@ -1813,24 +2816,21 @@ var TSX_PACKAGE = "tsx";
1813
2816
  var PACKAGE_JSON2 = "package.json";
1814
2817
  var UNKNOWN_COMMAND_EXIT_CODE = -1;
1815
2818
  function find_package_directory(start_directory) {
1816
- let current = start_directory;
1817
- while (!existsSync4(path4.join(current, PACKAGE_JSON2))) {
1818
- const parent = path4.dirname(current);
1819
- if (parent === current) return start_directory;
1820
- current = parent;
1821
- }
1822
- return current;
2819
+ return ancestor_directories.nearest(
2820
+ start_directory,
2821
+ (directory) => existsSync4(path11.join(directory, PACKAGE_JSON2))
2822
+ ) ?? start_directory;
1823
2823
  }
1824
- var PACKAGE_DIR = find_package_directory(path4.dirname(fileURLToPath(import.meta.url)));
2824
+ var PACKAGE_DIR2 = find_package_directory(path11.dirname(fileURLToPath2(import.meta.url)));
1825
2825
  function resolve_tsx_executable() {
1826
2826
  const candidates = [
1827
- resolve_local_bin(PACKAGE_DIR, TSX_BIN),
2827
+ resolve_local_bin(PACKAGE_DIR2, TSX_BIN),
1828
2828
  resolve_local_bin(process.cwd(), TSX_BIN)
1829
2829
  ];
1830
2830
  return candidates.find(existsSync4) ?? TSX_BIN;
1831
2831
  }
1832
2832
  function resolve_tsx_cli_entry() {
1833
- for (const base_directory of [PACKAGE_DIR, process.cwd()]) {
2833
+ for (const base_directory of [PACKAGE_DIR2, process.cwd()]) {
1834
2834
  const cli_entry = resolve_package_bin(base_directory, TSX_PACKAGE, TSX_BIN);
1835
2835
  if (cli_entry !== void 0) return cli_entry;
1836
2836
  }
@@ -1844,7 +2844,7 @@ function resolve_tsx_runner() {
1844
2844
  return { executable: resolve_tsx_executable(), leading_arguments: [] };
1845
2845
  }
1846
2846
  function read_package_version() {
1847
- const raw = readFileSync3(path4.join(PACKAGE_DIR, PACKAGE_JSON2), "utf8");
2847
+ const raw = readFileSync5(path11.join(PACKAGE_DIR2, PACKAGE_JSON2), "utf8");
1848
2848
  return package_version_schema.parse(JSON.parse(raw)).version;
1849
2849
  }
1850
2850
  var HEADER = `josh v${read_package_version()} \u2014 Joshua Folkken's dev toolkit`;
@@ -1928,12 +2928,10 @@ function spawn_script_entry(entry, script_path, script_arguments) {
1928
2928
  ]);
1929
2929
  }
1930
2930
  async function run_script_entry(entry, subcommand_arguments) {
1931
- const script_path = path4.join(PACKAGE_DIR, entry.script ?? "");
1932
2931
  const script_arguments = [...entry.default_script_arguments ?? [], ...subcommand_arguments];
1933
- if (josh_in_process.can_run_in_process(entry, import.meta.url)) {
1934
- return await josh_in_process.run_in_process(script_path, script_arguments);
1935
- }
1936
- return spawn_script_entry(entry, script_path, script_arguments);
2932
+ const target = josh_in_process.in_process_target(entry, PACKAGE_DIR2, import.meta.url);
2933
+ if (target !== void 0) return await josh_in_process.run_in_process(target, script_arguments);
2934
+ return spawn_script_entry(entry, path11.join(PACKAGE_DIR2, entry.script ?? ""), script_arguments);
1937
2935
  }
1938
2936
  function github_prerequisite_exit(resolved, is_consumer) {
1939
2937
  if (!is_consumer) return void 0;
@@ -1958,10 +2956,22 @@ function pre_dispatch_exit(resolved, entry, subcommand_arguments, is_consumer) {
1958
2956
  console.error(rejection);
1959
2957
  return USAGE_ERROR_EXIT_CODE;
1960
2958
  }
1961
- async function dispatch_entry(entry, subcommand_arguments) {
2959
+ async function run_entry(entry, subcommand_arguments) {
1962
2960
  if (entry.shell) return run_shell_command(entry.shell, subcommand_arguments);
1963
2961
  return await run_script_entry(entry, subcommand_arguments);
1964
2962
  }
2963
+ function declared(value) {
2964
+ return typeof value === "function" ? value() : value;
2965
+ }
2966
+ async function dispatch_entry(entry, subcommand_arguments) {
2967
+ const weight = declared(entry.core_weight);
2968
+ if (weight === void 0) return await run_entry(entry, subcommand_arguments);
2969
+ return await core_budget.with_command_reservation(
2970
+ weight,
2971
+ async () => await run_entry(entry, subcommand_arguments),
2972
+ { memory_mb: declared(entry.memory_mb) }
2973
+ );
2974
+ }
1965
2975
  async function run_command(cmd, subcommand_arguments, is_consumer = false) {
1966
2976
  const resolved = resolve_alias(cmd);
1967
2977
  const entry = Object.hasOwn(COMMAND_MAP, resolved) ? COMMAND_MAP[resolved] : void 0;