@joshuafolkken/kit 1.1178.0 → 1.1229.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (425) 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 +6 -2
  9. package/.claude/skills/workflow-commands/backlogrun-park.md +23 -2
  10. package/.claude/skills/workflow-commands/backlogrun-progress.md +7 -2
  11. package/.claude/skills/workflow-commands/backlogrun-recovery.md +4 -3
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +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 +5 -0
  16. package/.claude/skills/workflow-commands/fullrun-steps.md +1 -1
  17. package/.claude/skills/workflow-commands/halfrun.md +1 -1
  18. package/.claude/skills/workflow-commands/issue-scout.md +1 -1
  19. package/.claude/skills/workflow-commands/kickoff.md +1 -1
  20. package/.claude/skills/workflow-commands/observation-ledger.md +3 -3
  21. package/.claude/skills/workflow-commands/pre-gate-cut.md +6 -1
  22. package/.claude/skills/workflow-commands/prerequisite.md +2 -2
  23. package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
  24. package/.claude/skills/workflow-commands/working-tree-hold.md +1 -1
  25. package/.codex/hooks.json +2 -2
  26. package/.cursorrules +6 -41
  27. package/.github/actions/setup-node/action.yml +1 -1
  28. package/.github/workflows/auto-tag.yml +3 -4
  29. package/.github/workflows/ci.yml +32 -31
  30. package/.github/workflows/dependabot-auto-merge.yml +13 -6
  31. package/.github/workflows/publish.yml +48 -4
  32. package/.github/workflows/sonar-qube.yml +3 -0
  33. package/.pnpmfile.mjs +4 -3
  34. package/.prettierignore +8 -2
  35. package/CLAUDE.md +18 -20
  36. package/README.md +26 -19
  37. package/SECURITY.md +15 -1
  38. package/dist/CLAUDE.md +18 -20
  39. package/dist/commands/document-section-cli.js +734 -0
  40. package/dist/hooks/audit-provision.js +346 -0
  41. package/dist/hooks/batch-guard.js +5 -4
  42. package/dist/hooks/{chunk-S6X6WYKR.js → chunk-55HHG5PX.js} +1210 -711
  43. package/dist/hooks/{chunk-ZAL3NRGL.js → chunk-5VMKCCC4.js} +25 -10
  44. package/dist/hooks/chunk-5VNDSNG3.js +12 -0
  45. package/dist/hooks/{chunk-32GQTL4F.js → chunk-6HJJXRBX.js} +4 -2
  46. package/dist/hooks/chunk-CDY4NFQG.js +15 -0
  47. package/dist/hooks/chunk-ELCN5LCH.js +135 -0
  48. package/dist/hooks/{chunk-VESKRQOF.js → chunk-F56MFS4B.js} +3 -3
  49. package/dist/hooks/{chunk-UAGLLIGZ.js → chunk-FIVDHQGT.js} +7 -6
  50. package/dist/hooks/{chunk-3V37IID6.js → chunk-JBBMAPC4.js} +23 -14
  51. package/dist/hooks/{chunk-G6KRCKEC.js → chunk-JUDKDCDP.js} +496 -378
  52. package/dist/hooks/{chunk-GDS5N2KB.js → chunk-NV2JRZZO.js} +718 -681
  53. package/dist/hooks/{chunk-VQLLNFNT.js → chunk-RNWHN5BP.js} +3 -3
  54. package/dist/hooks/{chunk-DO6NWWHU.js → chunk-TQNPDZNH.js} +4 -4
  55. package/dist/hooks/{chunk-I4XSL4TT.js → chunk-VC3PZPZO.js} +1 -1
  56. package/dist/hooks/codex-hook-adapter.js +14 -12
  57. package/dist/hooks/duplicate-read-guard.js +6 -5
  58. package/dist/hooks/format-edited.js +4 -3
  59. package/dist/hooks/inputs.json +217 -195
  60. package/dist/hooks/investigation-guard.js +6 -5
  61. package/dist/hooks/pretool-guard.js +12 -10
  62. package/dist/hooks/session-lang.js +2 -4
  63. package/dist/hooks/stop-guard.js +66 -58
  64. package/dist/josh.js +868 -74
  65. package/dist/version/index.d.ts +7 -2
  66. package/dist/version/index.js +152 -75
  67. package/eslint/base.js +23 -1
  68. package/eslint/rules/code-quality.js +3 -0
  69. package/eslint/rules/early-return-one-liner.js +98 -0
  70. package/eslint/rules/unicorn.js +16 -1
  71. package/package.json +7 -6
  72. package/pnpm-workspace.yaml +9 -4
  73. package/prettier/basic.d.ts +3 -1
  74. package/prettier/index.d.ts +3 -1
  75. package/prettier/static.d.ts +3 -1
  76. package/prompts/coding-standards.md +1 -1
  77. package/prompts/collaboration-workflow/file-edits.md +4 -4
  78. package/prompts/collaboration-workflow/glossary.md +1 -1
  79. package/prompts/collaboration-workflow/operating-rules.md +17 -9
  80. package/prompts/collaboration-workflow/overview.md +2 -2
  81. package/prompts/collaboration-workflow/principles.md +14 -12
  82. package/prompts/collaboration-workflow/report-format.md +1 -1
  83. package/prompts/collaboration-workflow/residency.md +1 -1
  84. package/prompts/collaboration-workflow/rule-delivery.md +6 -6
  85. package/prompts/collaboration-workflow/shell-body.md +6 -6
  86. package/prompts/collaboration-workflow/turn-batching.md +1 -1
  87. package/prompts/collaboration-workflow/upstream-interrupt.md +12 -2
  88. package/prompts/collaboration-workflow/wip-cap.md +10 -10
  89. package/prompts/review-rubric.md +1 -2
  90. package/prompts/review.md +1 -1
  91. package/scripts/agent/agent-headless.ts +29 -0
  92. package/scripts/agent/agent-launch-environment.ts +6 -2
  93. package/scripts/agent/codex-agent-argv.ts +2 -1
  94. package/scripts/auto-ok/auto-ok-cli.ts +1 -1
  95. package/scripts/backlog/backlog-arrival.ts +3 -3
  96. package/scripts/backlog/backlog-budget.ts +1 -1
  97. package/scripts/backlog/backlog-drive-args.ts +135 -0
  98. package/scripts/backlog/backlog-drive-cli.ts +11 -137
  99. package/scripts/backlog/backlog-drive-launch.ts +39 -0
  100. package/scripts/backlog/backlog-drive-named-offer.ts +3 -5
  101. package/scripts/backlog/backlog-drive-named.ts +3 -3
  102. package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
  103. package/scripts/backlog/backlog-drive-owner.ts +1 -1
  104. package/scripts/backlog/backlog-drive-restore.ts +1 -1
  105. package/scripts/backlog/backlog-drive-retrospective.ts +1 -1
  106. package/scripts/backlog/backlog-drive.ts +1 -1
  107. package/scripts/backlog/backlog-next.ts +16 -5
  108. package/scripts/backlog/backlog-offer-cli.ts +6 -6
  109. package/scripts/backlog/backlog-offer.ts +1 -1
  110. package/scripts/backlog/backlog-plan-cli.ts +1 -1
  111. package/scripts/backlog/backlog-pool.ts +57 -11
  112. package/scripts/backlog/backlog-ready.ts +1 -1
  113. package/scripts/backlog/backlog-scope.ts +1 -1
  114. package/scripts/backlog/backlog-stalled-detect.ts +2 -2
  115. package/scripts/backlog/backlog-stalled.ts +1 -1
  116. package/scripts/build/build-codex-hooks.ts +3 -1
  117. package/scripts/build/build-commands.ts +66 -0
  118. package/scripts/build/build-hooks.ts +2 -1
  119. package/scripts/build/build-library.ts +12 -3
  120. package/scripts/build/build.ts +70 -0
  121. package/scripts/build/local-bin.ts +3 -13
  122. package/scripts/delegation/investigation-reads.ts +3 -1
  123. package/scripts/discovery/repo-origin.ts +5 -5
  124. package/scripts/doctor/doctor-consumer.ts +2 -2
  125. package/scripts/doctor/doctor-io.ts +2 -3
  126. package/scripts/document/capped-print-part.ts +30 -0
  127. package/scripts/document/capped-print.ts +3 -4
  128. package/scripts/document/document-byte-budget.ts +11 -2
  129. package/scripts/document/document-scan.ts +117 -0
  130. package/scripts/document/document-section.ts +143 -16
  131. package/scripts/document/entry-read-budget.ts +5 -3
  132. package/scripts/document/entry-read-set.ts +10 -89
  133. package/scripts/document/read-set-cost.ts +98 -0
  134. package/scripts/epic/epic-add-body.ts +1 -0
  135. package/scripts/epic/epic-audit-checks.ts +1 -1
  136. package/scripts/epic/epic-audit-rationale.ts +4 -3
  137. package/scripts/epic/epic-bundle-cli.ts +14 -3
  138. package/scripts/epic/epic-bundle-poll.ts +41 -0
  139. package/scripts/epic/epic-busy.ts +1 -1
  140. package/scripts/epic/epic-candidate-confirm.ts +3 -2
  141. package/scripts/epic/epic-classify.ts +1 -1
  142. package/scripts/epic/epic-cli-argv.ts +78 -46
  143. package/scripts/epic/epic-cli-remove.ts +11 -19
  144. package/scripts/epic/epic-cli.ts +74 -73
  145. package/scripts/epic/epic-close-comment.ts +1 -1
  146. package/scripts/epic/epic-close.ts +1 -1
  147. package/scripts/epic/epic-cross-repo.ts +5 -5
  148. package/scripts/epic/epic-graph.ts +1 -1
  149. package/scripts/epic/epic-index.ts +1 -1
  150. package/scripts/epic/epic-issue.ts +2 -6
  151. package/scripts/epic/epic-lane-offer.ts +2 -2
  152. package/scripts/epic/epic-next.ts +29 -42
  153. package/scripts/epic/epic-solo-stale.ts +1 -1
  154. package/scripts/epic/epic-triage.ts +8 -4
  155. package/scripts/epic/epic-validate.ts +1 -1
  156. package/scripts/followup/git-followup-finish.ts +2 -2
  157. package/scripts/followup/git-followup-label.ts +2 -2
  158. package/scripts/followup/git-followup-merged.ts +2 -2
  159. package/scripts/followup/git-pr-followup-checks.ts +142 -0
  160. package/scripts/followup/git-pr-followup.ts +4 -129
  161. package/scripts/gate/core-budget.ts +69 -1
  162. package/scripts/gate/gate-plan.ts +47 -7
  163. package/scripts/gate/gate-skip.ts +38 -7
  164. package/scripts/gate/hook-gate-reuse.ts +12 -10
  165. package/scripts/gate/pre-commit-type-check.ts +4 -1
  166. package/scripts/gate/project-checks.ts +6 -9
  167. package/scripts/gate/type-check-step.ts +2 -3
  168. package/scripts/gate/verification-gate.ts +27 -8
  169. package/scripts/gh/git-gh-api-path.ts +2 -2
  170. package/scripts/gh/git-gh-issue-rest.ts +3 -3
  171. package/scripts/gh/git-gh-issue-write.ts +53 -7
  172. package/scripts/gh/git-gh-pr-read.ts +64 -19
  173. package/scripts/gh/git-gh-pr-rest.ts +1 -1
  174. package/scripts/gh/git-gh-pr.ts +5 -1
  175. package/scripts/gh/git-pr-ai-review.ts +1 -1
  176. package/scripts/gh/git-pr-checks-eval.ts +1 -3
  177. package/scripts/gh/git-pr-checks-parse.ts +1 -1
  178. package/scripts/gh/git-pr-checks-watch.ts +6 -5
  179. package/scripts/gh/git-pr-checks.ts +7 -5
  180. package/scripts/gh/git-pr-coderabbit.ts +1 -1
  181. package/scripts/gh/git-pr-error.ts +1 -3
  182. package/scripts/gh/git-pr.ts +9 -13
  183. package/scripts/gh/github-issue-url.ts +2 -2
  184. package/scripts/git/constants.ts +2 -6
  185. package/scripts/git/git-command.ts +20 -218
  186. package/scripts/git/git-diff-reads.ts +225 -0
  187. package/scripts/git/git-error.ts +4 -12
  188. package/scripts/git/git-pre-push-hook.ts +139 -0
  189. package/scripts/git/git-prompt.ts +2 -6
  190. package/scripts/git/git-spawn-sync.ts +3 -1
  191. package/scripts/git/git-spawn.ts +1 -1
  192. package/scripts/git/git-staging.ts +4 -6
  193. package/scripts/git/git-status.ts +3 -9
  194. package/scripts/hooks/codex-hook-adapter.ts +1 -1
  195. package/scripts/hooks/edited-cspell.ts +2 -4
  196. package/scripts/hooks/format-edited-file.ts +3 -12
  197. package/scripts/hooks/pre-push-unit.ts +31 -9
  198. package/scripts/hooks/reserved-run.ts +2 -2
  199. package/scripts/hooks/run-hook.sh +5 -4
  200. package/scripts/hooks/stop-guard.ts +5 -3
  201. package/scripts/init/init-actions.ts +0 -5
  202. package/scripts/init/init-ai-copy.ts +13 -2
  203. package/scripts/init/init-logic-json-merge.ts +19 -0
  204. package/scripts/init/init-logic-secretlint.ts +7 -7
  205. package/scripts/init/init-logic-workspace.ts +41 -2
  206. package/scripts/init/init-logic.ts +16 -26
  207. package/scripts/init/init.ts +5 -15
  208. package/scripts/init/initial-commit.ts +4 -4
  209. package/scripts/init/kit-development-versions.ts +40 -0
  210. package/scripts/init/kit-setup-state.ts +2 -2
  211. package/scripts/init/start-exec.ts +68 -19
  212. package/scripts/init/start-setup-pr.ts +9 -9
  213. package/scripts/init/start-steps.ts +6 -10
  214. package/scripts/issue/defect-rate-cli.ts +1 -1
  215. package/scripts/issue/git-next-issues.ts +1 -1
  216. package/scripts/issue/issue-auto-ok.ts +1 -1
  217. package/scripts/issue/issue-backlinks-cli.ts +2 -2
  218. package/scripts/issue/issue-backlinks.ts +9 -9
  219. package/scripts/issue/issue-comment-cli.ts +19 -13
  220. package/scripts/issue/issue-file-cli.ts +45 -18
  221. package/scripts/issue/issue-file.ts +24 -1
  222. package/scripts/issue/issue-scout-closed.ts +1 -1
  223. package/scripts/issue/issue-state-cli.ts +30 -74
  224. package/scripts/josh/josh-command-map.ts +2 -0
  225. package/scripts/josh/josh-command-types.ts +11 -0
  226. package/scripts/josh/josh-commands-ai.ts +4 -4
  227. package/scripts/josh/josh-commands-backlog.ts +4 -1
  228. package/scripts/josh/josh-commands-development.ts +10 -0
  229. package/scripts/josh/josh-commands-document.ts +1 -0
  230. package/scripts/josh/josh-commands-lane.ts +22 -0
  231. package/scripts/josh/josh-commands-maintenance.ts +4 -4
  232. package/scripts/josh/josh-commands-run.ts +12 -7
  233. package/scripts/josh/josh-in-process.ts +28 -9
  234. package/scripts/josh/josh-logic.ts +33 -15
  235. package/scripts/josh/process-identity.ts +1 -3
  236. package/scripts/josh/session-language-cli.ts +3 -4
  237. package/scripts/lane/lane-await.ts +5 -1
  238. package/scripts/lane/lane-child-invocation.ts +2 -2
  239. package/scripts/lane/lane-cli.ts +3 -3
  240. package/scripts/lane/lane-dispatch.ts +14 -10
  241. package/scripts/lane/lane-environment.ts +5 -1
  242. package/scripts/lane/lane-handoff.ts +1 -1
  243. package/scripts/lane/lane-install.ts +2 -13
  244. package/scripts/lane/lane-launch-cli.ts +15 -1
  245. package/scripts/lane/lane-ledger.ts +145 -0
  246. package/scripts/lane/lane-leftover.ts +1 -1
  247. package/scripts/lane/lane-load.ts +108 -0
  248. package/scripts/lane/lane-measure-cli.ts +149 -0
  249. package/scripts/lane/lane-occupancy.ts +3 -0
  250. package/scripts/lane/lane-reap.ts +1 -3
  251. package/scripts/lane/lane-relaunch.ts +1 -1
  252. package/scripts/lane/lane-stats.ts +224 -0
  253. package/scripts/lane/lane-vacant.ts +36 -0
  254. package/scripts/lane/openai-lane-ship.ts +2 -2
  255. package/scripts/lane/openai-lane-supervisor-owner.ts +180 -0
  256. package/scripts/lane/openai-lane-supervisor.ts +7 -165
  257. package/scripts/lane/openai-review-broker.ts +2 -4
  258. package/scripts/lib/ancestor-directories.ts +35 -0
  259. package/scripts/lib/animation-helpers.ts +2 -2
  260. package/scripts/lib/buffered-process.ts +3 -7
  261. package/scripts/lib/cli-flags.ts +71 -1
  262. package/scripts/lib/spawn-exit.ts +2 -2
  263. package/scripts/lib/timeouts.ts +35 -2
  264. package/scripts/lines/line-budget.ts +4 -6
  265. package/scripts/notify/telegram-test.ts +6 -0
  266. package/scripts/observations/observation-ledger-line.ts +6 -6
  267. package/scripts/observations/observation-ledger-migrate.ts +55 -4
  268. package/scripts/observations/observation-ledger.ts +26 -7
  269. package/scripts/overrides/lockfile-overrides.ts +1 -1
  270. package/scripts/overrides/overrides-logic.ts +1 -1
  271. package/scripts/propagate/propagate-git.ts +1 -1
  272. package/scripts/propagate/propagate-publish.ts +2 -2
  273. package/scripts/propagate/propagate-steps.ts +20 -15
  274. package/scripts/propagate/propagate.ts +36 -27
  275. package/scripts/refactor/import-graph.ts +18 -1
  276. package/scripts/refactor/refactor-lint.ts +4 -4
  277. package/scripts/repo/repository-labels.ts +2 -2
  278. package/scripts/repo/required-checks-logic.ts +1 -3
  279. package/scripts/review/live-evidence.ts +2 -4
  280. package/scripts/review/review-brief-cli.ts +1 -1
  281. package/scripts/review/review-finding-ledger.ts +1 -1
  282. package/scripts/review/review-findings-cli.ts +1 -3
  283. package/scripts/rules/decision-oracle-batch.ts +128 -0
  284. package/scripts/rules/decision-oracle-tokens.ts +21 -0
  285. package/scripts/rules/decision-oracle.ts +8 -120
  286. package/scripts/rules/delivered-rules.ts +26 -182
  287. package/scripts/rules/direct-filing.ts +1 -1
  288. package/scripts/rules/early-heartbeat.ts +3 -3
  289. package/scripts/rules/git-argv.ts +1 -1
  290. package/scripts/rules/git-force.ts +1 -1
  291. package/scripts/rules/implementation-cut.ts +2 -2
  292. package/scripts/rules/index-guard.ts +1 -1
  293. package/scripts/rules/issue-comments.ts +118 -0
  294. package/scripts/rules/{issue-fold.ts → issue-fold-rule.ts} +2 -2
  295. package/scripts/rules/lane-background.ts +2 -2
  296. package/scripts/rules/lane-park.ts +18 -0
  297. package/scripts/rules/lane-split-park.ts +128 -0
  298. package/scripts/rules/oracle-firing.ts +1 -1
  299. package/scripts/rules/poll-loop.ts +1 -1
  300. package/scripts/rules/pre-gate-cut.ts +1 -1
  301. package/scripts/rules/protected-files.ts +59 -4
  302. package/scripts/rules/{run-tail.ts → run-tail-rule.ts} +2 -2
  303. package/scripts/rules/shell-body-trigger.ts +1 -1
  304. package/scripts/rules/stop-rules.ts +18 -7
  305. package/scripts/rules/test-declared-commit.ts +4 -4
  306. package/scripts/rules/wip-cap.ts +63 -0
  307. package/scripts/run/{run-carry-args.ts → carry/run-carry-args.ts} +37 -13
  308. package/scripts/run/{run-carry-change.ts → carry/run-carry-change.ts} +29 -7
  309. package/scripts/run/{run-carry-cli.ts → carry/run-carry-cli.ts} +4 -6
  310. package/scripts/run/{run-carry.ts → carry/run-carry.ts} +1 -1
  311. package/scripts/run/{run-cut-args.ts → cut/run-cut-args.ts} +1 -1
  312. package/scripts/run/{run-cut-cli.ts → cut/run-cut-cli.ts} +2 -2
  313. package/scripts/run/{run-cut.ts → cut/run-cut.ts} +1 -1
  314. package/scripts/run/{run-entry-cli.ts → entry/run-entry-cli.ts} +11 -11
  315. package/scripts/run/{run-entry.ts → entry/run-entry.ts} +2 -2
  316. package/scripts/run/{run-event-scope.ts → event/run-event-scope.ts} +1 -1
  317. package/scripts/run/{run-event-stream-emit.ts → event/run-event-stream-emit.ts} +1 -1
  318. package/scripts/run/{run-event-stream.ts → event/run-event-stream.ts} +16 -2
  319. package/scripts/run/{run-hold-cli.ts → hold/run-hold-cli.ts} +5 -5
  320. package/scripts/run/{run-merge-cli.ts → merge/run-merge-cli.ts} +10 -5
  321. package/scripts/run/{run-merge-steps.ts → merge/run-merge-steps.ts} +53 -5
  322. package/scripts/run/{run-merge.ts → merge/run-merge.ts} +1 -1
  323. package/scripts/run/{run-progress-cli.ts → progress/run-progress-cli.ts} +1 -1
  324. package/scripts/run/{run-progress-config.ts → progress/run-progress-config.ts} +2 -17
  325. package/scripts/run/{run-progress-read.ts → progress/run-progress-read.ts} +5 -5
  326. package/scripts/run/{run-progress.ts → progress/run-progress.ts} +1 -1
  327. package/scripts/run/{run-review-steps.ts → review/run-review-steps.ts} +2 -3
  328. package/scripts/run/run-ending.ts +2 -2
  329. package/scripts/run/run-halfrun-resume.ts +6 -1
  330. package/scripts/run/run-headless.ts +1 -1
  331. package/scripts/run/run-invocation.ts +85 -84
  332. package/scripts/run/run-liveness.ts +1 -1
  333. package/scripts/run/run-parent-cut-hook.ts +1 -1
  334. package/scripts/run/run-preflight.ts +6 -6
  335. package/scripts/run/run-prep-cli.ts +1 -1
  336. package/scripts/run/run-prrun-resume.ts +1 -1
  337. package/scripts/run/run-report-cli.ts +4 -4
  338. package/scripts/run/run-report.ts +2 -2
  339. package/scripts/run/run-status-cli.ts +1 -1
  340. package/scripts/run/run-step-cli.ts +3 -3
  341. package/scripts/run/run-step.ts +2 -2
  342. package/scripts/run/run-stop-notify.ts +1 -1
  343. package/scripts/run/run-stranded-detect.ts +4 -4
  344. package/scripts/run/run-stranded.ts +2 -2
  345. package/scripts/run/run-watcher-guard-cli.ts +1 -1
  346. package/scripts/run/run-watcher-guard.ts +5 -3
  347. package/scripts/run/run-watcher-hook.ts +1 -1
  348. package/scripts/run/{run-ship-cli.ts → ship/run-ship-cli.ts} +2 -2
  349. package/scripts/run/{run-ship-detach.ts → ship/run-ship-detach.ts} +3 -3
  350. package/scripts/run/ship/run-ship-lock.ts +50 -0
  351. package/scripts/run/{run-ship-preflight.ts → ship/run-ship-preflight.ts} +6 -2
  352. package/scripts/run/{run-ship-probe.ts → ship/run-ship-probe.ts} +2 -2
  353. package/scripts/run/{run-ship-return.ts → ship/run-ship-return.ts} +4 -3
  354. package/scripts/run/{run-ship-review-steps.ts → ship/run-ship-review-steps.ts} +3 -3
  355. package/scripts/run/{run-ship-scoped.ts → ship/run-ship-scoped.ts} +10 -1
  356. package/scripts/run/{run-ship-steps.ts → ship/run-ship-steps.ts} +11 -12
  357. package/scripts/run/ship/run-ship-stop-text.ts +13 -0
  358. package/scripts/run/{run-ship-sync.ts → ship/run-ship-sync.ts} +25 -11
  359. package/scripts/run/{run-tidy-lanes.ts → tidy/run-tidy-lanes.ts} +1 -1
  360. package/scripts/run/{run-wake-cli.ts → wake/run-wake-cli.ts} +23 -8
  361. package/scripts/run/{run-wake-describe.ts → wake/run-wake-describe.ts} +3 -3
  362. package/scripts/run/{run-wake-driver.ts → wake/run-wake-driver.ts} +59 -8
  363. package/scripts/run/{run-wake-handoff.ts → wake/run-wake-handoff.ts} +1 -1
  364. package/scripts/run/{run-wake-loop.ts → wake/run-wake-loop.ts} +8 -2
  365. package/scripts/run/wake/run-wake-restart.ts +58 -0
  366. package/scripts/run/{run-wake-session.ts → wake/run-wake-session.ts} +3 -3
  367. package/scripts/run/{run-wake.ts → wake/run-wake.ts} +1 -1
  368. package/scripts/safe-chain/preinstall-command.ts +20 -21
  369. package/scripts/safe-chain/project-config.ts +19 -15
  370. package/scripts/sync/sync-ai-files.ts +1 -1
  371. package/scripts/sync/sync-configs.ts +2 -1
  372. package/scripts/sync/sync.ts +15 -2
  373. package/scripts/test/unit-worker-share.ts +1 -0
  374. package/scripts/time-runtime/time-background.ts +5 -1
  375. package/scripts/time-runtime/time-instant.ts +3 -1
  376. package/scripts/time-runtime/time-spans.ts +6 -139
  377. package/scripts/time-runtime/time-tool-call.ts +160 -0
  378. package/scripts/version/effective-upstream.ts +2 -20
  379. package/scripts/version/latest-corepack.ts +17 -17
  380. package/scripts/version/latest-regression.ts +1 -1
  381. package/scripts/version/latest-update.ts +4 -4
  382. package/scripts/version/npm-registry.ts +20 -5
  383. package/scripts/version/publishable-range-check.ts +2 -2
  384. package/scripts/version/publishable-range.ts +1 -1
  385. package/scripts/version/release-age.ts +48 -38
  386. package/scripts/version/release-hold.ts +1 -1
  387. package/scripts/version/safe-chain-version-update.ts +40 -0
  388. package/scripts/version/upgrade-shell-command.ts +48 -8
  389. package/scripts/version/version-check-logic.ts +23 -14
  390. package/scripts/version/version-commands.ts +23 -11
  391. package/scripts/version/version-remote.ts +28 -13
  392. package/templates/pnpm-workspace.basic.yaml +4 -0
  393. package/templates/workflows/dependabot-auto-merge.yml +5 -5
  394. package/templates/workflows/github-release.yml +2 -0
  395. package/scripts/build/build-config-merge.ts +0 -27
  396. package/scripts/build/build-managed-marker.ts +0 -27
  397. package/scripts/build/build-self-sync-guard.ts +0 -27
  398. package/scripts/build/build-version.ts +0 -26
  399. package/scripts/version/preinstall-version-update.ts +0 -86
  400. /package/scripts/git/{schemas.ts → git-schemas.ts} +0 -0
  401. /package/scripts/overrides/{schemas.ts → overrides-schemas.ts} +0 -0
  402. /package/scripts/run/{run-carry-conversation.ts → carry/run-carry-conversation.ts} +0 -0
  403. /package/scripts/run/{run-carry-reclaim.ts → carry/run-carry-reclaim.ts} +0 -0
  404. /package/scripts/run/{run-carry-stash.ts → carry/run-carry-stash.ts} +0 -0
  405. /package/scripts/run/{run-carry-streak.ts → carry/run-carry-streak.ts} +0 -0
  406. /package/scripts/run/{run-cut-handoff.ts → cut/run-cut-handoff.ts} +0 -0
  407. /package/scripts/run/{run-cut-report.ts → cut/run-cut-report.ts} +0 -0
  408. /package/scripts/run/{run-entry-stop.ts → entry/run-entry-stop.ts} +0 -0
  409. /package/scripts/run/{run-event-cli.ts → event/run-event-cli.ts} +0 -0
  410. /package/scripts/run/{run-event-follow.ts → event/run-event-follow.ts} +0 -0
  411. /package/scripts/run/{run-event-render.ts → event/run-event-render.ts} +0 -0
  412. /package/scripts/run/{run-event-watch.ts → event/run-event-watch.ts} +0 -0
  413. /package/scripts/run/{run-hold.ts → hold/run-hold.ts} +0 -0
  414. /package/scripts/run/{run-progress-args.ts → progress/run-progress-args.ts} +0 -0
  415. /package/scripts/run/{run-progress-clock.ts → progress/run-progress-clock.ts} +0 -0
  416. /package/scripts/run/{run-review-cli.ts → review/run-review-cli.ts} +0 -0
  417. /package/scripts/run/{run-review.ts → review/run-review.ts} +0 -0
  418. /package/scripts/run/{run-ship-next.ts → ship/run-ship-next.ts} +0 -0
  419. /package/scripts/run/{run-ship-pre-detach.ts → ship/run-ship-pre-detach.ts} +0 -0
  420. /package/scripts/run/{run-ship-review.ts → ship/run-ship-review.ts} +0 -0
  421. /package/scripts/run/{run-ship-stage.ts → ship/run-ship-stage.ts} +0 -0
  422. /package/scripts/run/{run-ship.ts → ship/run-ship.ts} +0 -0
  423. /package/scripts/run/{run-tidy-cli.ts → tidy/run-tidy-cli.ts} +0 -0
  424. /package/scripts/run/{run-tidy-stashes.ts → tidy/run-tidy-stashes.ts} +0 -0
  425. /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,589 @@ 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 availableParallelism2 } 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
+ var RESERVED_PREFIX = "josh-core-reserved-";
716
+ var RESERVED_SUFFIX = ".json";
717
+ var POLL_INTERVAL_MS = 50;
718
+ var WAIT_CAP_MS = 12e4;
719
+ var MIN_BUDGET = 1;
720
+ var CORE_WEIGHTS = {
721
+ lint: 2,
722
+ type_check: 1,
723
+ spell_check: 1,
724
+ eslint_scan: 1
725
+ };
726
+ var HELD_KEY = "JOSH_CORE_RESERVED";
727
+ var HELD_VALUE = "1";
728
+ var reservation_schema = process_owner_schema.extend({
729
+ weight: z4.number(),
730
+ claimed_at: z4.number()
731
+ });
732
+ function marker_name(key) {
733
+ return `${RESERVED_PREFIX}${key}${RESERVED_SUFFIX}`;
734
+ }
735
+ function is_running2(reservation) {
736
+ return process_identity.is_same_process(reservation.pid, reservation.process_start) !== false;
737
+ }
738
+ function read_reservation(source) {
739
+ const raw = stamp_file.read_stamp_text(source);
740
+ if (raw === void 0) return void 0;
741
+ try {
742
+ const parsed = reservation_schema.safeParse(JSON.parse(raw));
743
+ return parsed.success ? parsed.data : void 0;
744
+ } catch {
745
+ return void 0;
746
+ }
747
+ }
748
+ function sweep_marker2(source) {
749
+ try {
750
+ stamp_file.remove_stamp(source);
751
+ } catch {
752
+ }
753
+ }
754
+ function live_reservation(source) {
755
+ const reservation = read_reservation(source);
756
+ if (reservation === void 0) return void 0;
757
+ if (is_running2(reservation)) return reservation;
758
+ sweep_marker2(source);
759
+ return void 0;
760
+ }
761
+ function marker_files2(directory) {
762
+ try {
763
+ return readdirSync2(directory).filter((name) => name.startsWith(RESERVED_PREFIX));
764
+ } catch {
765
+ return [];
766
+ }
767
+ }
768
+ function live_reservations(directory = PLATFORM_TEMP_ROOT) {
769
+ return marker_files2(directory).flatMap((name) => {
770
+ const reservation = live_reservation(path8.join(directory, name));
771
+ return reservation === void 0 ? [] : { key: name, reservation };
772
+ });
773
+ }
774
+ function compare_claim(left, right) {
775
+ const by_time = left.reservation.claimed_at - right.reservation.claimed_at;
776
+ return by_time === 0 ? left.key.localeCompare(right.key) : by_time;
777
+ }
778
+ function admitted_keys(reservations, budget) {
779
+ const admitted = /* @__PURE__ */ new Set();
780
+ let cumulative = 0;
781
+ for (const [index, entry] of reservations.toSorted(compare_claim).entries()) {
782
+ cumulative += entry.reservation.weight;
783
+ if (index !== 0 && cumulative > budget) break;
784
+ admitted.add(entry.key);
785
+ }
786
+ return admitted;
787
+ }
788
+ function is_admitted(key, reservations, budget) {
789
+ return admitted_keys(reservations, budget).has(key);
790
+ }
791
+ function admitted_load(reservations, budget) {
792
+ const admitted = admitted_keys(reservations, budget);
793
+ return reservations.filter((entry) => admitted.has(entry.key)).reduce((total, entry) => total + entry.reservation.weight, 0);
794
+ }
795
+ function normalize_budget(budget) {
796
+ return Number.isFinite(budget) ? Math.max(MIN_BUDGET, Math.floor(budget)) : MIN_BUDGET;
797
+ }
798
+ async function default_sleep(ms) {
799
+ await new Promise((resolve) => {
800
+ setTimeout(resolve, ms);
801
+ });
802
+ }
803
+ function write_reservation(target, weight, claimed_at) {
804
+ stamp_file.write_stamp(target, { ...process_identity.own_fields(), weight, claimed_at });
805
+ }
806
+ function resolve_timing(options) {
807
+ return {
808
+ now: options.now ?? Date.now,
809
+ sleep: options.sleep ?? default_sleep,
810
+ poll_interval_ms: options.poll_interval_ms ?? POLL_INTERVAL_MS
811
+ };
812
+ }
813
+ async function await_admission(context) {
814
+ while (!is_admitted(context.key, live_reservations(context.directory), context.budget)) {
815
+ if (context.now() >= context.deadline) return;
816
+ await context.sleep(context.poll_interval_ms);
817
+ }
818
+ }
819
+ async function reserve(weight, options = {}) {
820
+ const timing = resolve_timing(options);
821
+ const directory = options.directory ?? PLATFORM_TEMP_ROOT;
822
+ const budget = normalize_budget(options.budget ?? availableParallelism2());
823
+ const claimed_at = timing.now();
824
+ const name = marker_name(randomUUID3());
825
+ const target = path8.join(directory, name);
826
+ write_reservation(target, weight, claimed_at);
827
+ await await_admission({
828
+ ...timing,
829
+ key: name,
830
+ directory,
831
+ budget,
832
+ deadline: claimed_at + (options.wait_cap_ms ?? WAIT_CAP_MS)
833
+ });
834
+ return { target };
835
+ }
836
+ function release(handle) {
837
+ sweep_marker2(handle.target);
838
+ }
839
+ async function with_core_reservation(weight, run2, options = {}) {
840
+ const handle = await reserve(weight, options);
841
+ try {
842
+ return await run2();
843
+ } finally {
844
+ release(handle);
845
+ }
846
+ }
847
+ function is_held() {
848
+ return process.env[HELD_KEY] === HELD_VALUE;
849
+ }
850
+ function set_held_mark(value) {
851
+ process.env[HELD_KEY] = value;
852
+ }
853
+ async function with_held_mark(run2) {
854
+ const previous = process.env[HELD_KEY] ?? "";
855
+ set_held_mark(HELD_VALUE);
856
+ try {
857
+ return await run2();
858
+ } finally {
859
+ set_held_mark(previous);
860
+ }
861
+ }
862
+ async function with_command_reservation(weight, run2, options = {}) {
863
+ if (is_held() || unit_worker_share.is_nested_run()) return await run2();
864
+ return await with_core_reservation(weight, async () => await with_held_mark(run2), options);
865
+ }
866
+ var core_budget = {
867
+ CORE_WEIGHTS,
868
+ HELD_KEY,
869
+ HELD_VALUE,
870
+ RESERVED_PREFIX,
871
+ admitted_keys,
872
+ admitted_load,
873
+ is_held,
874
+ live_reservations,
875
+ release,
876
+ reserve,
877
+ with_command_reservation,
878
+ with_core_reservation,
879
+ with_held_mark
880
+ };
881
+
304
882
  // scripts/josh/josh-logic.ts
305
883
  import { execaSync as execaSync2 } from "execa";
306
884
 
@@ -410,6 +988,9 @@ var BACKLOG_COMMANDS = {
410
988
  },
411
989
  "backlog:stalled": {
412
990
  script: "scripts/backlog/backlog-stalled-cli.ts",
991
+ // A stall sends one Telegram warning (joshuafolkken/kit#3357). The `Stop` hook calls the detector
992
+ // directly, so this flag costs only the manual command its in-process dispatch.
993
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
413
994
  description: "Report whether ready backlog work is sitting undispatched with a free lane and no recent dispatch",
414
995
  category: "AI tools",
415
996
  reference: ["", "automation", ["network"]]
@@ -428,7 +1009,8 @@ var DOCUMENT_COMMANDS = {
428
1009
  script: "scripts/document/document-section-cli.ts",
429
1010
  description: 'Print one section of a markdown document, for a `file.md` \u2192 "Heading" reference',
430
1011
  category: "AI tools",
431
- reference: ["<file> <heading>", "automation", ["none"]]
1012
+ reference: ["<file> <heading>", "automation", ["none"]],
1013
+ is_bundled: true
432
1014
  },
433
1015
  "read:set": {
434
1016
  script: "scripts/document/read-set-cli.ts",
@@ -545,6 +1127,10 @@ var ISSUE_COMMANDS = {
545
1127
  var LANE_SCRIPT = "scripts/lane/lane-cli.ts";
546
1128
  var LANE_ARGUMENTS = { script: LANE_SCRIPT, tsx_arguments: OPTIONAL_ENV_FILE_FLAGS };
547
1129
  var ISSUE_WITH_OPTIONS = "<issue> [options]";
1130
+ var MEASURE_ARGUMENTS = {
1131
+ script: "scripts/lane/lane-measure-cli.ts",
1132
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS
1133
+ };
548
1134
  var LANE_COMMANDS = {
549
1135
  "lane:open": {
550
1136
  ...LANE_ARGUMENTS,
@@ -600,11 +1186,27 @@ var LANE_COMMANDS = {
600
1186
  description: "Collapse a backlogrun lane-start event into one call: open the lane, pop and re-install on the first, dispatch the child",
601
1187
  category: "AI tools",
602
1188
  reference: ["<issue> [--stash <message>]", "automation", ["files", "git", "processes"]]
1189
+ },
1190
+ // The lane-limit measurement (joshuafolkken/kit#3355): `.env` is read so `lane:stats` labels the row
1191
+ // with the `JOSH_LANE_LIMIT` a person set there.
1192
+ "lane:sample": {
1193
+ ...MEASURE_ARGUMENTS,
1194
+ description: "Record the machine load (load average, swap, free memory, working lanes) to the lane ledger",
1195
+ category: "AI tools",
1196
+ reference: ["[--every <seconds>]", "maintainer", ["files"]],
1197
+ default_script_arguments: ["sample"]
1198
+ },
1199
+ "lane:stats": {
1200
+ ...MEASURE_ARGUMENTS,
1201
+ description: "Print one table row of lane throughput, gate duration and machine load over a period",
1202
+ category: "AI tools",
1203
+ reference: ["--period <days> [--limit <lane-limit>]", "maintainer", ["none"]],
1204
+ default_script_arguments: ["stats"]
603
1205
  }
604
1206
  };
605
1207
 
606
1208
  // scripts/josh/josh-commands-run.ts
607
- var RUN_HOLD_SCRIPT = "scripts/run/run-hold-cli.ts";
1209
+ var RUN_HOLD_SCRIPT = "scripts/run/hold/run-hold-cli.ts";
608
1210
  var RUN_COMMANDS = {
609
1211
  "run:hold": {
610
1212
  script: RUN_HOLD_SCRIPT,
@@ -620,19 +1222,22 @@ var RUN_COMMANDS = {
620
1222
  default_script_arguments: ["--release"]
621
1223
  },
622
1224
  "run:tidy": {
623
- script: "scripts/run/run-tidy-cli.ts",
1225
+ script: "scripts/run/tidy/run-tidy-cli.ts",
624
1226
  description: "Close merged lanes and drop stashes whose issues are all merged",
625
1227
  category: "AI tools",
626
1228
  reference: ["", "automation", ["git", "network", "files"]]
627
1229
  },
628
1230
  "run:carry": {
629
- script: "scripts/run/run-carry-cli.ts",
1231
+ script: "scripts/run/carry/run-carry-cli.ts",
1232
+ // `--stopped` sends the stop confirmation, so the Telegram credentials come from `.env` as for
1233
+ // `run:wake` below (joshuafolkken/kit#3357).
1234
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
630
1235
  description: "Carry one invocation\u2019s budget across its own session cuts",
631
1236
  category: "AI tools",
632
1237
  reference: ["<operation> [arguments...]", "automation", ["files"]]
633
1238
  },
634
1239
  "run:wake": {
635
- script: "scripts/run/run-wake-cli.ts",
1240
+ script: "scripts/run/wake/run-wake-cli.ts",
636
1241
  // `.env` rather than the ambient environment:
637
1242
  // the failure warning needs the Telegram credentials, the same
638
1243
  // reasons `notify` and `followup` carry these flags.
@@ -642,7 +1247,7 @@ var RUN_COMMANDS = {
642
1247
  reference: ["[options]", "automation", ["processes", "notifications"]]
643
1248
  },
644
1249
  "run:cut": {
645
- script: "scripts/run/run-cut-cli.ts",
1250
+ script: "scripts/run/cut/run-cut-cli.ts",
646
1251
  description: "Cut a lane child before the gate and resume a fresh process",
647
1252
  category: "AI tools",
648
1253
  reference: ["[--resume] <issue> [--impl] [--handoff <path>]", "automation", ["files"]]
@@ -660,7 +1265,7 @@ var RUN_COMMANDS = {
660
1265
  reference: ["<issue> --output <path> [--repo <owner/repo>]", "automation", ["network"]]
661
1266
  },
662
1267
  "run:progress": {
663
- script: "scripts/run/run-progress-cli.ts",
1268
+ script: "scripts/run/progress/run-progress-cli.ts",
664
1269
  description: "Report an unattended run\u2019s progress once it has gone quiet for an interval",
665
1270
  category: "AI tools",
666
1271
  reference: [
@@ -679,7 +1284,9 @@ var RUN_COMMANDS = {
679
1284
  // read the budget, gather the issue reads and decide the pre-implementation step. `run:hold`,
680
1285
  // `cost --cut`, `run:prep` and `run:step` were four round trips re-billing a lane's full context each.
681
1286
  "run:entry": {
682
- script: "scripts/run/run-entry-cli.ts",
1287
+ script: "scripts/run/entry/run-entry-cli.ts",
1288
+ // A `busy` hold or an `over` budget sends the stop confirmation (joshuafolkken/kit#3357).
1289
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
683
1290
  description: "Open a run in one call: claim the tree, read the budget, bundle the reads, decide the pre-implementation step",
684
1291
  category: "AI tools",
685
1292
  reference: ["<issue> [--to <command>]", "automation", ["git", "network", "files"]]
@@ -843,13 +1450,13 @@ var AI_COMMANDS = {
843
1450
  reference: ["[<owner/repo>]", "automation", ["none"]]
844
1451
  },
845
1452
  "run:merge": {
846
- script: "scripts/run/run-merge-cli.ts",
1453
+ script: "scripts/run/merge/run-merge-cli.ts",
847
1454
  description: "Collapse a backlogrun merge event into one call: confirm the child, do the post-merge steps, offer the next child",
848
1455
  category: "AI tools",
849
1456
  reference: [ISSUE_WITH_OPTIONS2, "automation", ["git", "network"]]
850
1457
  },
851
1458
  "run:review": {
852
- script: "scripts/run/run-review-cli.ts",
1459
+ script: "scripts/run/review/run-review-cli.ts",
853
1460
  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
1461
  category: "AI tools",
855
1462
  reference: ["[--join]", "automation", ["processes", "files"]]
@@ -868,7 +1475,7 @@ var AI_COMMANDS = {
868
1475
  // (`run:tail`) were four round trips re-billing the run's full context each. It stops at the first
869
1476
  // failed step and names it, so the run reads only the step to fix.
870
1477
  ship: {
871
- script: "scripts/run/run-ship-cli.ts",
1478
+ script: "scripts/run/ship/run-ship-cli.ts",
872
1479
  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
1480
  category: "AI tools",
874
1481
  reference: [
@@ -878,7 +1485,7 @@ var AI_COMMANDS = {
878
1485
  ]
879
1486
  },
880
1487
  "run:event": {
881
- script: "scripts/run/run-event-cli.ts",
1488
+ script: "scripts/run/event/run-event-cli.ts",
882
1489
  description: "Append to, read or watch the run\u2019s append-only event stream (--append <kind> <text> | --from|--follow <n> | --watch [<n>] | --last)",
883
1490
  category: "AI tools",
884
1491
  reference: [
@@ -938,6 +1545,169 @@ var CLONE_COMMANDS = {
938
1545
  }
939
1546
  };
940
1547
 
1548
+ // scripts/gate/gate-plan.ts
1549
+ import { availableParallelism as availableParallelism3 } from "node:os";
1550
+
1551
+ // scripts/lib/status-icons.ts
1552
+ var FAIL_ICON = "\u2717";
1553
+ var PASS_ICON = "\u2714";
1554
+ var status_icons = { FAIL_ICON, PASS_ICON };
1555
+
1556
+ // scripts/josh/josh-verdict.ts
1557
+ var { FAIL_ICON: FAIL_ICON2, PASS_ICON: PASS_ICON2 } = status_icons;
1558
+ var GATE_SUBJECT = "verification gate";
1559
+ var GATE_PASSED_PREFIX = `${PASS_ICON2} ${GATE_SUBJECT} passed`;
1560
+ var GATE_FAILED_PREFIX = `${FAIL_ICON2} ${GATE_SUBJECT} failed`;
1561
+ var PASSED_VERDICT = "passed";
1562
+ var FAILED_VERDICT = "failed";
1563
+ function format_gate_passed(step_count, total) {
1564
+ return `${GATE_PASSED_PREFIX} (${step_count} checks) in ${total}.`;
1565
+ }
1566
+ function format_gate_failed(failed_labels, total) {
1567
+ return `${GATE_FAILED_PREFIX}: ${failed_labels} (${total})`;
1568
+ }
1569
+ var GATE_OPENING_PREFIX = "plan: ";
1570
+ var GATE_OPENING_MARK = " checks at once";
1571
+ function is_gate_opening(line) {
1572
+ const trimmed = line.trimStart();
1573
+ return trimmed.startsWith(GATE_OPENING_PREFIX) && trimmed.includes(GATE_OPENING_MARK);
1574
+ }
1575
+ function read_verdict(line) {
1576
+ const trimmed = line.trimStart();
1577
+ if (trimmed.startsWith(GATE_FAILED_PREFIX)) return FAILED_VERDICT;
1578
+ if (trimmed.startsWith(GATE_PASSED_PREFIX)) return PASSED_VERDICT;
1579
+ return void 0;
1580
+ }
1581
+ var josh_verdict = {
1582
+ PASSED_VERDICT,
1583
+ FAILED_VERDICT,
1584
+ format_gate_passed,
1585
+ format_gate_failed,
1586
+ GATE_OPENING_MARK,
1587
+ GATE_OPENING_PREFIX,
1588
+ is_gate_opening,
1589
+ read_verdict
1590
+ };
1591
+
1592
+ // scripts/gate/gate-plan.ts
1593
+ var LINT_LABEL = "lint";
1594
+ var TYPE_CHECK_LABEL = "check";
1595
+ var UNIT_LABEL = "test:unit";
1596
+ var BEHAVIOR_LABEL = "behavior";
1597
+ var WARNING_CHECKER_LABELS = [LINT_LABEL, TYPE_CHECK_LABEL];
1598
+ var STATIC_CHECKS = [
1599
+ { label: LINT_LABEL, target: "lint", reserved_cores: core_budget.CORE_WEIGHTS.lint },
1600
+ {
1601
+ label: TYPE_CHECK_LABEL,
1602
+ target: "check",
1603
+ reserved_cores: core_budget.CORE_WEIGHTS.type_check
1604
+ },
1605
+ { label: "cspell", target: "cspell:dot", reserved_cores: core_budget.CORE_WEIGHTS.spell_check },
1606
+ { label: BEHAVIOR_LABEL, target: BEHAVIOR_LABEL, reserved_cores: 0 },
1607
+ // **The unused-member check reserves no core** (joshuafolkken/kit#2987): it builds one TypeScript
1608
+ // program and walks it for about 5s, and it is over well before lint and the type check. A
1609
+ // reservation would only take a place from the four-core CI runner's fan-out and a worker from the
1610
+ // unit suite for the whole gate.
1611
+ { label: "exports", target: "exports:unused", reserved_cores: 0 }
1612
+ ];
1613
+ var GATE_CHECKS = [
1614
+ ...STATIC_CHECKS,
1615
+ { label: UNIT_LABEL, target: UNIT_LABEL, reserved_cores: 0 }
1616
+ ];
1617
+ function select_gate_checks(is_unit_included) {
1618
+ return is_unit_included ? GATE_CHECKS : STATIC_CHECKS;
1619
+ }
1620
+ function has_unit_check(checks) {
1621
+ return checks.some((check) => check.label === UNIT_LABEL);
1622
+ }
1623
+ var RESERVED_CORES = STATIC_CHECKS.reduce(
1624
+ (total, check) => total + check.reserved_cores,
1625
+ 0
1626
+ );
1627
+ var MEASURED_CORES = 11;
1628
+ var MIN_CONCURRENCY = 1;
1629
+ var MIN_SHARED_CORES = 1;
1630
+ function shared_cores(available_cores, concurrent_runs) {
1631
+ const runs = Number.isFinite(concurrent_runs) ? Math.max(unit_worker_share.SOLO_RUNS, concurrent_runs) : unit_worker_share.SOLO_RUNS;
1632
+ return Math.max(MIN_SHARED_CORES, Math.floor(available_cores / runs));
1633
+ }
1634
+ function resolve_concurrency(available_cores, concurrent_runs = unit_worker_share.SOLO_RUNS, checks = GATE_CHECKS) {
1635
+ const share = shared_cores(available_cores, concurrent_runs);
1636
+ let admitted = 0;
1637
+ let reserved = 0;
1638
+ for (const check of checks) {
1639
+ reserved += check.reserved_cores;
1640
+ if (reserved > share) break;
1641
+ admitted += 1;
1642
+ }
1643
+ return Math.max(MIN_CONCURRENCY, admitted);
1644
+ }
1645
+ function resolve_unit_worker_cap(available_cores, concurrent_runs = unit_worker_share.SOLO_RUNS) {
1646
+ const share = unit_worker_share.resolve_unit_workers(available_cores, concurrent_runs);
1647
+ if (share !== void 0) return share;
1648
+ if (available_cores < MEASURED_CORES) return void 0;
1649
+ return available_cores - RESERVED_CORES;
1650
+ }
1651
+ function solo_unit_weight(available_cores) {
1652
+ return Math.max(0, available_cores - RESERVED_CORES);
1653
+ }
1654
+ function check_weight(check, plan, available_cores) {
1655
+ if (check.label !== UNIT_LABEL) return check.reserved_cores;
1656
+ return plan.unit_worker_cap ?? solo_unit_weight(available_cores);
1657
+ }
1658
+ function direct_unit_weight(available_cores = availableParallelism3(), live_runs = unit_worker_share.live_run_count()) {
1659
+ const weight = unit_worker_share.current_share(available_cores, live_runs) ?? solo_unit_weight(available_cores);
1660
+ return Math.max(unit_worker_share.MIN_WORKERS, weight);
1661
+ }
1662
+ function plan_of(concurrency, unit_worker_cap, checks = GATE_CHECKS) {
1663
+ return { checks, concurrency, unit_worker_cap };
1664
+ }
1665
+ function resolve_gate_plan(available_cores = availableParallelism3(), concurrent_runs = unit_worker_share.SOLO_RUNS, is_unit_included = true) {
1666
+ const checks = select_gate_checks(is_unit_included);
1667
+ return {
1668
+ checks,
1669
+ concurrency: resolve_concurrency(available_cores, concurrent_runs, checks),
1670
+ unit_worker_cap: is_unit_included ? resolve_unit_worker_cap(available_cores, concurrent_runs) : void 0
1671
+ };
1672
+ }
1673
+ function format_machine(available_cores, concurrent_runs) {
1674
+ const cores = `${String(available_cores)} cores`;
1675
+ if (concurrent_runs <= unit_worker_share.SOLO_RUNS) return cores;
1676
+ return `${cores}, ${String(concurrent_runs)} unit runs`;
1677
+ }
1678
+ function format_unit_cap(plan) {
1679
+ if (!has_unit_check(plan.checks)) return `${UNIT_LABEL} elsewhere`;
1680
+ if (plan.unit_worker_cap === void 0) return `${UNIT_LABEL} unrestricted`;
1681
+ return `${UNIT_LABEL} at ${String(plan.unit_worker_cap)} workers`;
1682
+ }
1683
+ function format_gate_plan(plan, available_cores = availableParallelism3(), concurrent_runs = unit_worker_share.SOLO_RUNS) {
1684
+ const cap = format_unit_cap(plan);
1685
+ const count = `${String(plan.concurrency)} of ${String(plan.checks.length)}`;
1686
+ const width = `${count}${josh_verdict.GATE_OPENING_MARK}`;
1687
+ const machine = format_machine(available_cores, concurrent_runs);
1688
+ return `${josh_verdict.GATE_OPENING_PREFIX}${width}, ${cap} (${machine})`;
1689
+ }
1690
+ var gate_plan = {
1691
+ GATE_CHECKS,
1692
+ LINT_LABEL,
1693
+ MEASURED_CORES,
1694
+ RESERVED_CORES,
1695
+ STATIC_CHECKS,
1696
+ TYPE_CHECK_LABEL,
1697
+ UNIT_LABEL,
1698
+ WARNING_CHECKER_LABELS,
1699
+ check_weight,
1700
+ direct_unit_weight,
1701
+ format_gate_plan,
1702
+ format_machine,
1703
+ has_unit_check,
1704
+ plan_of,
1705
+ resolve_concurrency,
1706
+ resolve_gate_plan,
1707
+ resolve_unit_worker_cap,
1708
+ select_gate_checks
1709
+ };
1710
+
941
1711
  // scripts/josh/josh-commands-development.ts
942
1712
  var FILE_ARGUMENTS = "[files...]";
943
1713
  var REQUIRED_FILE_ARGUMENTS = "<files...>";
@@ -961,25 +1731,29 @@ var DEV_COMMANDS = {
961
1731
  script: "scripts/lint/lint-parallel.ts",
962
1732
  description: "Check code with prettier and eslint (skips a tool a basic project lacks)",
963
1733
  category: "Development",
964
- reference: ["", "developer", ["processes"]]
1734
+ reference: ["", "developer", ["processes"]],
1735
+ core_weight: core_budget.CORE_WEIGHTS.lint
965
1736
  },
966
1737
  "lint:related": {
967
1738
  script: "scripts/lint/lint-related.ts",
968
1739
  description: "Check only the changed files with prettier and eslint (whole tree on fallback)",
969
1740
  category: "Development",
970
- reference: [FILE_ARGUMENTS, "developer", ["processes"]]
1741
+ reference: [FILE_ARGUMENTS, "developer", ["processes"]],
1742
+ core_weight: core_budget.CORE_WEIGHTS.lint
971
1743
  },
972
1744
  lines: {
973
1745
  script: "scripts/lines/lines-command.ts",
974
1746
  description: "Print a file's code lines against the max-lines limit and the headroom left",
975
1747
  category: "Development",
976
- reference: [REQUIRED_FILE_ARGUMENTS, "developer", ["none"]]
1748
+ reference: [REQUIRED_FILE_ARGUMENTS, "developer", ["none"]],
1749
+ core_weight: core_budget.CORE_WEIGHTS.eslint_scan
977
1750
  },
978
1751
  "refactor:scan": {
979
1752
  script: "scripts/refactor/refactor-scan-cli.ts",
980
1753
  description: "List refactoring candidates in the changed scope by category and answer clear/candidates",
981
1754
  category: "Development",
982
- reference: ["", "automation", ["processes"]]
1755
+ reference: ["", "automation", ["processes"]],
1756
+ core_weight: core_budget.CORE_WEIGHTS.eslint_scan
983
1757
  },
984
1758
  bytes: {
985
1759
  script: "scripts/lines/bytes-command.ts",
@@ -1058,7 +1832,8 @@ var DEV_COMMANDS = {
1058
1832
  script: "scripts/lint/cspell-cached.ts",
1059
1833
  description: "Run spell check including dotfiles",
1060
1834
  category: "Development",
1061
- reference: ["", "developer", ["processes"]]
1835
+ reference: ["", "developer", ["processes"]],
1836
+ core_weight: core_budget.CORE_WEIGHTS.spell_check
1062
1837
  },
1063
1838
  behavior: {
1064
1839
  script: "scripts/behavior/behavior-cli.ts",
@@ -1076,13 +1851,15 @@ var DEV_COMMANDS = {
1076
1851
  script: "scripts/test/test-unit-guard.ts",
1077
1852
  description: "Run unit tests with Vitest (skips when Vitest is absent; fails when it has no tests)",
1078
1853
  category: "Development",
1079
- reference: [FILTER_ARGUMENTS, "developer", ["processes"]]
1854
+ reference: [FILTER_ARGUMENTS, "developer", ["processes"]],
1855
+ core_weight: gate_plan.direct_unit_weight
1080
1856
  },
1081
1857
  "test:related": {
1082
1858
  script: "scripts/test/test-related.ts",
1083
1859
  description: "Run only the unit tests related to the changed files (full suite on fallback)",
1084
1860
  category: "Development",
1085
- reference: [FILE_ARGUMENTS, "developer", ["processes"]]
1861
+ reference: [FILE_ARGUMENTS, "developer", ["processes"]],
1862
+ core_weight: gate_plan.direct_unit_weight
1086
1863
  },
1087
1864
  "test:declared": {
1088
1865
  script: "scripts/test/test-declared.ts",
@@ -1125,7 +1902,8 @@ var DEV_COMMANDS = {
1125
1902
  script: "scripts/gate/type-check-command.ts",
1126
1903
  description: "Type-check with tsc (skips a basic project with no TypeScript to check)",
1127
1904
  category: "Development",
1128
- reference: ["[arguments...]", "developer", ["processes"]]
1905
+ reference: ["[arguments...]", "developer", ["processes"]],
1906
+ core_weight: core_budget.CORE_WEIGHTS.type_check
1129
1907
  },
1130
1908
  port: {
1131
1909
  script: "scripts/ports/port-command.ts",
@@ -1222,7 +2000,7 @@ var MAINTENANCE_COMMANDS = {
1222
2000
  script: "scripts/overrides/overrides-check.ts",
1223
2001
  description: "Check pnpm overrides for drift",
1224
2002
  category: "Maintenance",
1225
- reference: ["[--save]", "maintainer", ["files"]]
2003
+ reference: ["[--save]", "developer", ["files"]]
1226
2004
  },
1227
2005
  audit: {
1228
2006
  script: "scripts/security/security-audit.ts",
@@ -1250,7 +2028,7 @@ var MAINTENANCE_COMMANDS = {
1250
2028
  ],
1251
2029
  description: "Update pnpm, dependencies, and run security audit",
1252
2030
  category: "Maintenance",
1253
- reference: ["", "maintainer", ["files", "network", "processes"]],
2031
+ reference: ["", "developer", ["files", "network", "processes"]],
1254
2032
  argument_targets: ["latest:corepack", "latest:update", "audit"]
1255
2033
  },
1256
2034
  "latest:scope": {
@@ -1273,13 +2051,13 @@ var MAINTENANCE_COMMANDS = {
1273
2051
  script: "scripts/version/latest-corepack.ts",
1274
2052
  description: "Update pnpm on the current major while preserving the integrity pin",
1275
2053
  category: "Maintenance",
1276
- reference: ["", "maintainer", ["files", "network"]]
2054
+ reference: ["", "developer", ["files", "network"]]
1277
2055
  },
1278
2056
  "latest:update": {
1279
2057
  script: "scripts/version/latest-update.ts",
1280
2058
  description: "Update all dependencies to latest",
1281
2059
  category: "Maintenance",
1282
- reference: ["", "maintainer", ["files", "network"]]
2060
+ reference: ["", "developer", ["files", "network"]]
1283
2061
  }
1284
2062
  };
1285
2063
 
@@ -1602,7 +2380,9 @@ var ALIASES = {
1602
2380
  rtr: "retrospective",
1603
2381
  rvf: "review:findings",
1604
2382
  ruv: "rule:value",
1605
- ev: "eval"
2383
+ ev: "eval",
2384
+ lsm: "lane:sample",
2385
+ lst: "lane:stats"
1606
2386
  };
1607
2387
 
1608
2388
  // scripts/josh/josh-composite-arguments.ts
@@ -1633,15 +2413,23 @@ var composite_arguments = { format_rejection, is_composite_shell, reject_extra_a
1633
2413
 
1634
2414
  // scripts/josh/josh-in-process.ts
1635
2415
  import { realpathSync } from "node:fs";
2416
+ import path9 from "node:path";
1636
2417
  import { pathToFileURL } from "node:url";
1637
2418
  var TYPESCRIPT_EXTENSION = ".ts";
2419
+ var JAVASCRIPT_EXTENSION = ".js";
2420
+ var BUNDLED_COMMAND_DIRECTORY = path9.join("dist", "commands");
1638
2421
  var FAILURE_EXIT_CODE = 1;
1639
2422
  function is_typescript_dispatcher(dispatcher_url) {
1640
2423
  return dispatcher_url.endsWith(TYPESCRIPT_EXTENSION);
1641
2424
  }
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);
2425
+ function bundled_script_path(package_directory, script) {
2426
+ const name = `${path9.basename(script, TYPESCRIPT_EXTENSION)}${JAVASCRIPT_EXTENSION}`;
2427
+ return path9.join(package_directory, BUNDLED_COMMAND_DIRECTORY, name);
2428
+ }
2429
+ function in_process_target(entry, package_directory, dispatcher_url) {
2430
+ if (entry.script === void 0 || entry.tsx_arguments !== void 0) return void 0;
2431
+ if (is_typescript_dispatcher(dispatcher_url)) return path9.join(package_directory, entry.script);
2432
+ return entry.is_bundled === true ? bundled_script_path(package_directory, entry.script) : void 0;
1645
2433
  }
1646
2434
  function read_exit_code() {
1647
2435
  const code = process.exitCode;
@@ -1665,7 +2453,7 @@ async function run_in_process(script_path, script_arguments) {
1665
2453
  }
1666
2454
  return read_exit_code();
1667
2455
  }
1668
- var josh_in_process = { can_run_in_process, run_in_process };
2456
+ var josh_in_process = { bundled_script_path, in_process_target, run_in_process };
1669
2457
 
1670
2458
  // scripts/josh/kit-only.ts
1671
2459
  function kit_only_notice(cmd) {
@@ -1685,7 +2473,7 @@ var kit_only = {
1685
2473
 
1686
2474
  // scripts/josh/run-github-prerequisite.ts
1687
2475
  import { existsSync as existsSync3 } from "node:fs";
1688
- import path3 from "node:path";
2476
+ import path10 from "node:path";
1689
2477
 
1690
2478
  // scripts/discovery/repo-origin.ts
1691
2479
  var GITHUB_HOST = "github.com";
@@ -1750,15 +2538,15 @@ function origin_section_lines(lines) {
1750
2538
  const end = rest.findIndex((line) => is_section_header(line));
1751
2539
  return end === NOT_FOUND ? rest : rest.slice(0, end);
1752
2540
  }
1753
- function entry_value(line, key) {
2541
+ function url_value(line) {
1754
2542
  const separator = line.indexOf("=");
1755
2543
  if (separator === NOT_FOUND) return void 0;
1756
- if (line.slice(0, separator).trim() !== key) return void 0;
2544
+ if (line.slice(0, separator).trim() !== URL_KEY) return void 0;
1757
2545
  return line.slice(separator + 1).trim();
1758
2546
  }
1759
2547
  function parse_origin_from_config(content) {
1760
2548
  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);
2549
+ return origin_section_lines(lines).map((line) => url_value(line)).find((url) => url !== void 0);
1762
2550
  }
1763
2551
  function section_groups(lines) {
1764
2552
  const groups = [];
@@ -1770,7 +2558,7 @@ function section_groups(lines) {
1770
2558
  }
1771
2559
  function parse_remote_urls_from_config(content) {
1772
2560
  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);
2561
+ 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
2562
  }
1775
2563
  function format_identity(identity) {
1776
2564
  return `${identity.owner}${PATH_SEPARATOR2}${identity.repo}`.toLowerCase();
@@ -1796,7 +2584,7 @@ var GITHUB_RUN_COMMANDS = /* @__PURE__ */ new Set([
1796
2584
  ]);
1797
2585
  function explanation(root, command) {
1798
2586
  if (!GITHUB_RUN_COMMANDS.has(command)) return void 0;
1799
- if (!existsSync3(path3.join(root, ".git"))) {
2587
+ if (!existsSync3(path10.join(root, ".git"))) {
1800
2588
  return `${command} requires Git and a GitHub origin. Run git init and add a GitHub origin first.`;
1801
2589
  }
1802
2590
  const url = git_spawn_sync.origin_url(root);
@@ -1813,24 +2601,21 @@ var TSX_PACKAGE = "tsx";
1813
2601
  var PACKAGE_JSON2 = "package.json";
1814
2602
  var UNKNOWN_COMMAND_EXIT_CODE = -1;
1815
2603
  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;
2604
+ return ancestor_directories.nearest(
2605
+ start_directory,
2606
+ (directory) => existsSync4(path11.join(directory, PACKAGE_JSON2))
2607
+ ) ?? start_directory;
1823
2608
  }
1824
- var PACKAGE_DIR = find_package_directory(path4.dirname(fileURLToPath(import.meta.url)));
2609
+ var PACKAGE_DIR2 = find_package_directory(path11.dirname(fileURLToPath2(import.meta.url)));
1825
2610
  function resolve_tsx_executable() {
1826
2611
  const candidates = [
1827
- resolve_local_bin(PACKAGE_DIR, TSX_BIN),
2612
+ resolve_local_bin(PACKAGE_DIR2, TSX_BIN),
1828
2613
  resolve_local_bin(process.cwd(), TSX_BIN)
1829
2614
  ];
1830
2615
  return candidates.find(existsSync4) ?? TSX_BIN;
1831
2616
  }
1832
2617
  function resolve_tsx_cli_entry() {
1833
- for (const base_directory of [PACKAGE_DIR, process.cwd()]) {
2618
+ for (const base_directory of [PACKAGE_DIR2, process.cwd()]) {
1834
2619
  const cli_entry = resolve_package_bin(base_directory, TSX_PACKAGE, TSX_BIN);
1835
2620
  if (cli_entry !== void 0) return cli_entry;
1836
2621
  }
@@ -1844,7 +2629,7 @@ function resolve_tsx_runner() {
1844
2629
  return { executable: resolve_tsx_executable(), leading_arguments: [] };
1845
2630
  }
1846
2631
  function read_package_version() {
1847
- const raw = readFileSync3(path4.join(PACKAGE_DIR, PACKAGE_JSON2), "utf8");
2632
+ const raw = readFileSync5(path11.join(PACKAGE_DIR2, PACKAGE_JSON2), "utf8");
1848
2633
  return package_version_schema.parse(JSON.parse(raw)).version;
1849
2634
  }
1850
2635
  var HEADER = `josh v${read_package_version()} \u2014 Joshua Folkken's dev toolkit`;
@@ -1928,12 +2713,10 @@ function spawn_script_entry(entry, script_path, script_arguments) {
1928
2713
  ]);
1929
2714
  }
1930
2715
  async function run_script_entry(entry, subcommand_arguments) {
1931
- const script_path = path4.join(PACKAGE_DIR, entry.script ?? "");
1932
2716
  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);
2717
+ const target = josh_in_process.in_process_target(entry, PACKAGE_DIR2, import.meta.url);
2718
+ if (target !== void 0) return await josh_in_process.run_in_process(target, script_arguments);
2719
+ return spawn_script_entry(entry, path11.join(PACKAGE_DIR2, entry.script ?? ""), script_arguments);
1937
2720
  }
1938
2721
  function github_prerequisite_exit(resolved, is_consumer) {
1939
2722
  if (!is_consumer) return void 0;
@@ -1958,10 +2741,21 @@ function pre_dispatch_exit(resolved, entry, subcommand_arguments, is_consumer) {
1958
2741
  console.error(rejection);
1959
2742
  return USAGE_ERROR_EXIT_CODE;
1960
2743
  }
1961
- async function dispatch_entry(entry, subcommand_arguments) {
2744
+ async function run_entry(entry, subcommand_arguments) {
1962
2745
  if (entry.shell) return run_shell_command(entry.shell, subcommand_arguments);
1963
2746
  return await run_script_entry(entry, subcommand_arguments);
1964
2747
  }
2748
+ function command_weight(entry) {
2749
+ return typeof entry.core_weight === "function" ? entry.core_weight() : entry.core_weight;
2750
+ }
2751
+ async function dispatch_entry(entry, subcommand_arguments) {
2752
+ const weight = command_weight(entry);
2753
+ if (weight === void 0) return await run_entry(entry, subcommand_arguments);
2754
+ return await core_budget.with_command_reservation(
2755
+ weight,
2756
+ async () => await run_entry(entry, subcommand_arguments)
2757
+ );
2758
+ }
1965
2759
  async function run_command(cmd, subcommand_arguments, is_consumer = false) {
1966
2760
  const resolved = resolve_alias(cmd);
1967
2761
  const entry = Object.hasOwn(COMMAND_MAP, resolved) ? COMMAND_MAP[resolved] : void 0;