@joshuafolkken/kit 1.1455.0 → 1.1514.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 (374) hide show
  1. package/.claude/settings.json +6 -6
  2. package/.claude/skills/dependency-update/SKILL.md +26 -55
  3. package/.claude/skills/epic-commands/SKILL.md +83 -156
  4. package/.claude/skills/epic-commands/epic-bundle.md +51 -79
  5. package/.claude/skills/epic-commands/execution-waves.md +43 -81
  6. package/.claude/skills/verify-ui/SKILL.md +24 -50
  7. package/.claude/skills/workflow-commands/SKILL.md +7 -9
  8. package/.claude/skills/workflow-commands/background-commands.md +31 -46
  9. package/.claude/skills/workflow-commands/backlogrun-child.md +65 -85
  10. package/.claude/skills/workflow-commands/backlogrun-lanes.md +86 -125
  11. package/.claude/skills/workflow-commands/backlogrun-park.md +68 -118
  12. package/.claude/skills/workflow-commands/backlogrun-progress.md +17 -28
  13. package/.claude/skills/workflow-commands/backlogrun-recovery.md +17 -26
  14. package/.claude/skills/workflow-commands/backlogrun-steps.md +35 -52
  15. package/.claude/skills/workflow-commands/backlogrun.md +31 -50
  16. package/.claude/skills/workflow-commands/chain-rule.md +31 -40
  17. package/.claude/skills/workflow-commands/delegation.md +12 -8
  18. package/.claude/skills/workflow-commands/entry-sequence.md +1 -3
  19. package/.claude/skills/workflow-commands/followup.md +55 -77
  20. package/.claude/skills/workflow-commands/fullrun-steps.md +3 -5
  21. package/.claude/skills/workflow-commands/fullrun.md +4 -6
  22. package/.claude/skills/workflow-commands/halfrun.md +3 -7
  23. package/.claude/skills/workflow-commands/into-target.md +1 -2
  24. package/.claude/skills/workflow-commands/issue-comments.md +43 -60
  25. package/.claude/skills/workflow-commands/issue-scout.md +3 -2
  26. package/.claude/skills/workflow-commands/kickoff.md +65 -74
  27. package/.claude/skills/workflow-commands/latest-gate.md +2 -6
  28. package/.claude/skills/workflow-commands/needs-human-review.md +2 -5
  29. package/.claude/skills/workflow-commands/observation-filing.md +59 -118
  30. package/.claude/skills/workflow-commands/observation-ledger.md +52 -112
  31. package/.claude/skills/workflow-commands/pre-gate-cut.md +88 -142
  32. package/.claude/skills/workflow-commands/prerequisite.md +11 -17
  33. package/.claude/skills/workflow-commands/progress-watcher.md +23 -33
  34. package/.claude/skills/workflow-commands/prrun.md +3 -5
  35. package/.claude/skills/workflow-commands/retrospective.md +35 -54
  36. package/.claude/skills/workflow-commands/split-assessment.md +32 -58
  37. package/.claude/skills/workflow-commands/target-repository.md +1 -2
  38. package/.claude/skills/workflow-commands/working-tree-hold.md +54 -73
  39. package/.codex/hooks.json +6 -6
  40. package/.github/actions/setup-node/action.yml +1 -1
  41. package/.github/workflows/ci.yml +1 -1
  42. package/.github/workflows/publish.yml +2 -2
  43. package/CLAUDE.md +7 -6
  44. package/cspell/index.yaml +7 -0
  45. package/dist/CLAUDE.md +7 -6
  46. package/dist/commands/document-section-cli.js +67 -34
  47. package/dist/hooks/batch-guard.js +6 -6
  48. package/dist/hooks/chunk-4KKD2UTK.js +66 -0
  49. package/dist/hooks/{chunk-GPLGZ6IC.js → chunk-6TS2JD6D.js} +14 -3
  50. package/dist/hooks/chunk-7DSBJVFH.js +50 -0
  51. package/dist/hooks/{chunk-5H4SSDSD.js → chunk-A65Y4YOR.js} +3 -3
  52. package/dist/hooks/{chunk-3C4XRYG6.js → chunk-APUO6U4J.js} +102 -19
  53. package/dist/hooks/{chunk-IX6TTTI6.js → chunk-EFXE6C37.js} +8 -22
  54. package/dist/hooks/chunk-GP4IEC4O.js +20 -0
  55. package/dist/hooks/chunk-JP45SOCJ.js +56 -0
  56. package/dist/hooks/{chunk-OLMO72ON.js → chunk-LAOV7NLM.js} +1 -1
  57. package/dist/hooks/chunk-M4HGZV7U.js +83 -0
  58. package/dist/hooks/{chunk-TBJFTSUY.js → chunk-O6GDRNJB.js} +9 -7
  59. package/dist/hooks/{chunk-HFGWYGUV.js → chunk-PF2NZL2A.js} +5 -5
  60. package/dist/hooks/{chunk-WNLVGT7E.js → chunk-PTICX4OL.js} +4 -5
  61. package/dist/hooks/{chunk-HHI6FO3R.js → chunk-RT27QRJW.js} +763 -1515
  62. package/dist/hooks/{chunk-7WQBPLUN.js → chunk-SYOTDYCI.js} +1149 -1095
  63. package/dist/hooks/{chunk-LIAFCXL7.js → chunk-TNUMY6NL.js} +1519 -1332
  64. package/dist/hooks/chunk-UPUZF3AN.js +279 -0
  65. package/dist/hooks/{chunk-Z4XI7CZS.js → chunk-WK6SMBIC.js} +1932 -784
  66. package/dist/hooks/codex-hook-adapter.js +17 -14
  67. package/dist/hooks/duplicate-read-guard.js +7 -7
  68. package/dist/hooks/format-edited.js +5 -4
  69. package/dist/hooks/inputs.json +302 -247
  70. package/dist/hooks/investigation-guard.js +8 -11
  71. package/dist/hooks/pretool-guard.js +16 -13
  72. package/dist/hooks/session-lang.js +372 -26
  73. package/dist/hooks/stop-guard.js +2593 -189
  74. package/dist/josh.js +2128 -282
  75. package/dist/managed-marker/index.js +1 -2
  76. package/dist/version/index.js +15 -12
  77. package/eslint/base.js +2 -1
  78. package/eslint/rules/unicorn.js +16 -0
  79. package/lefthook/base.yml +5 -3
  80. package/package.json +14 -12
  81. package/prompts/coding-standards.md +12 -22
  82. package/prompts/collaboration-workflow/file-edits.md +25 -45
  83. package/prompts/collaboration-workflow/gh-rest.md +19 -36
  84. package/prompts/collaboration-workflow/glossary.md +5 -7
  85. package/prompts/collaboration-workflow/issue-citation.md +6 -14
  86. package/prompts/collaboration-workflow/issue-template.md +40 -32
  87. package/prompts/collaboration-workflow/lane-instructions.md +35 -0
  88. package/prompts/collaboration-workflow/operating-rules.md +33 -46
  89. package/prompts/collaboration-workflow/output-bounds.md +15 -15
  90. package/prompts/collaboration-workflow/overview.md +14 -19
  91. package/prompts/collaboration-workflow/plan-comment.md +13 -13
  92. package/prompts/collaboration-workflow/principles.md +57 -54
  93. package/prompts/collaboration-workflow/proposal-request.md +1 -9
  94. package/prompts/collaboration-workflow/report-format.md +41 -49
  95. package/prompts/collaboration-workflow/residency.md +15 -11
  96. package/prompts/collaboration-workflow/rule-delivery.md +7 -15
  97. package/prompts/collaboration-workflow/shell-body.md +10 -20
  98. package/prompts/collaboration-workflow/turn-batching.md +8 -14
  99. package/prompts/collaboration-workflow/upstream-interrupt.md +26 -34
  100. package/prompts/collaboration-workflow/wip-cap.md +26 -32
  101. package/prompts/collaboration-workflow.md +25 -25
  102. package/prompts/refactoring.md +33 -43
  103. package/prompts/review-rubric.md +84 -129
  104. package/prompts/review.md +110 -141
  105. package/prompts/sonar-hotspot-handling.md +22 -50
  106. package/prompts/testing-guide.md +48 -99
  107. package/scripts/adopt/adopt-toolkits.ts +2 -4
  108. package/scripts/agent/agent-argv.ts +20 -4
  109. package/scripts/agent/agent-exit-record.ts +23 -1
  110. package/scripts/agent/agent-role-profile.ts +101 -45
  111. package/scripts/agent/agent-safe-text.ts +60 -0
  112. package/scripts/agent/claude-agent-argv.ts +14 -0
  113. package/scripts/agent/codex-agent-argv.ts +9 -2
  114. package/scripts/agent/lane-instructions.ts +144 -0
  115. package/scripts/backlog/backlog-budget-cli.ts +1 -2
  116. package/scripts/backlog/backlog-budget.ts +4 -4
  117. package/scripts/backlog/backlog-drive-carried.ts +26 -0
  118. package/scripts/backlog/backlog-drive-cli.ts +10 -5
  119. package/scripts/backlog/backlog-drive-named.ts +3 -5
  120. package/scripts/backlog/backlog-drive-restore.ts +28 -2
  121. package/scripts/backlog/backlog-drive-seats.ts +27 -0
  122. package/scripts/backlog/backlog-drive.ts +11 -6
  123. package/scripts/backlog/backlog-occupied.ts +56 -0
  124. package/scripts/backlog/backlog-ready.ts +59 -15
  125. package/scripts/behavior/behavior-rules.ts +3 -2
  126. package/scripts/cost-runtime/codex-usage.ts +4 -2
  127. package/scripts/cost-runtime/cost-cli.ts +1 -2
  128. package/scripts/delegation/duplicate-read-guard.ts +2 -2
  129. package/scripts/delegation/investigation-guard.ts +15 -65
  130. package/scripts/delegation/investigation-reads.ts +1 -2
  131. package/scripts/discovery/repo-discovery.ts +4 -2
  132. package/scripts/discovery/repo-origin.ts +2 -4
  133. package/scripts/doctor/doctor-logic.ts +6 -3
  134. package/scripts/document/document-byte-budget.ts +28 -27
  135. package/scripts/document/document-byte-check.ts +1 -2
  136. package/scripts/document/document-section-cli.ts +17 -5
  137. package/scripts/document/entry-read-budget.ts +3 -3
  138. package/scripts/document/read-set-cli.ts +4 -1
  139. package/scripts/epic/epic-audit-orphans.ts +5 -8
  140. package/scripts/epic/epic-audit-rationale.ts +8 -2
  141. package/scripts/epic/epic-audit.ts +52 -1
  142. package/scripts/epic/epic-bundle-cli.ts +1 -2
  143. package/scripts/epic/epic-bundle-evidence.ts +49 -26
  144. package/scripts/epic/epic-bundle-referenced.ts +14 -3
  145. package/scripts/epic/epic-bundle.ts +17 -9
  146. package/scripts/epic/epic-chains.ts +6 -2
  147. package/scripts/epic/epic-close-comment.ts +1 -2
  148. package/scripts/followup/git-followup-workflow.ts +19 -1
  149. package/scripts/gate/check-inputs.ts +129 -0
  150. package/scripts/gate/check-reuse.ts +162 -0
  151. package/scripts/gate/core-budget.ts +93 -44
  152. package/scripts/gate/core-wait.ts +130 -0
  153. package/scripts/gate/free-cores.ts +49 -0
  154. package/scripts/gate/gate-ledger.ts +17 -3
  155. package/scripts/gate/gate-plan.ts +23 -1
  156. package/scripts/gate/gate-report.ts +15 -2
  157. package/scripts/gate/gate-run-steps.ts +150 -0
  158. package/scripts/gate/held-mark.ts +55 -0
  159. package/scripts/gate/machine-capacity.ts +70 -11
  160. package/scripts/gate/pre-commit-type-check.ts +14 -1
  161. package/scripts/gate/verification-gate.ts +65 -127
  162. package/scripts/gh/git-gh-issue-rest.ts +1 -0
  163. package/scripts/gh/git-gh-issue-write.ts +24 -2
  164. package/scripts/gh/git-pr.ts +19 -3
  165. package/scripts/git/git-common-directory.ts +3 -3
  166. package/scripts/git/git-diff-reads.ts +16 -9
  167. package/scripts/git/git-execa-error.ts +1 -2
  168. package/scripts/git/main-merge-regenerate.ts +78 -0
  169. package/scripts/git/main-merge.ts +14 -5
  170. package/scripts/hooks/batch-guard.ts +5 -8
  171. package/scripts/hooks/format-edited-file.ts +10 -4
  172. package/scripts/hooks/pre-commit-lint.ts +91 -0
  173. package/scripts/hooks/pre-push-unit.ts +15 -4
  174. package/scripts/hooks/pretool-guard.ts +48 -79
  175. package/scripts/hooks/reserved-run.ts +1 -0
  176. package/scripts/hooks/run-hook.sh +10 -12
  177. package/scripts/hooks/step-zero-notice.ts +3 -2
  178. package/scripts/hooks/stop-actions.ts +204 -0
  179. package/scripts/hooks/stop-guard.ts +62 -21
  180. package/scripts/init/hook-command-rewrite.ts +6 -2
  181. package/scripts/init/hook-launch.ts +12 -7
  182. package/scripts/init/init-logic-deploy-vps.ts +4 -2
  183. package/scripts/issue/behavior-change-lint.ts +12 -6
  184. package/scripts/issue/expected-effect-lint.ts +59 -0
  185. package/scripts/issue/issue-cite-cli.ts +35 -15
  186. package/scripts/issue/issue-classification.ts +1 -1
  187. package/scripts/issue/issue-lint-cli.ts +5 -3
  188. package/scripts/issue/issue-scout-cli.ts +22 -16
  189. package/scripts/issue/markdown-section.ts +19 -5
  190. package/scripts/josh/command-usage.ts +110 -0
  191. package/scripts/josh/file-map-stamp.ts +1 -3
  192. package/scripts/josh/hook-decision.ts +17 -2
  193. package/scripts/josh/josh-command-map.ts +2 -0
  194. package/scripts/josh/josh-command-types.ts +55 -9
  195. package/scripts/josh/josh-commands-ai.ts +13 -0
  196. package/scripts/josh/josh-commands-development.ts +1 -1
  197. package/scripts/josh/josh-commands-hooks.ts +6 -0
  198. package/scripts/josh/josh-commands-lane.ts +10 -1
  199. package/scripts/josh/josh-commands-workflow.ts +5 -0
  200. package/scripts/josh/josh-logic.ts +6 -15
  201. package/scripts/josh/josh-usage-automation.ts +121 -0
  202. package/scripts/josh/josh-usage-backlog.ts +180 -0
  203. package/scripts/josh/josh-usage-developer.ts +230 -0
  204. package/scripts/josh/josh-usage-hooks.ts +38 -0
  205. package/scripts/josh/josh-usage-issue.ts +205 -0
  206. package/scripts/josh/josh-usage-review.ts +101 -0
  207. package/scripts/josh/josh-usage-run.ts +252 -0
  208. package/scripts/josh/josh-usage-session.ts +238 -0
  209. package/scripts/josh/josh-usage-workflow.ts +212 -0
  210. package/scripts/josh/josh.ts +14 -5
  211. package/scripts/josh/package-directory.ts +20 -0
  212. package/scripts/lane/lane-await.ts +3 -2
  213. package/scripts/lane/lane-capacity.ts +8 -2
  214. package/scripts/lane/lane-check-stats.ts +56 -0
  215. package/scripts/lane/lane-child-invocation.ts +49 -5
  216. package/scripts/lane/lane-dispatch.ts +3 -3
  217. package/scripts/lane/lane-guard-policy.ts +5 -5
  218. package/scripts/lane/lane-handoff.ts +8 -1
  219. package/scripts/lane/lane-install.ts +12 -4
  220. package/scripts/lane/lane-ledger.ts +52 -1
  221. package/scripts/lane/lane-limit-cli.ts +8 -9
  222. package/scripts/lane/lane-load.ts +9 -2
  223. package/scripts/lane/lane-measure-cli.ts +4 -0
  224. package/scripts/lane/lane-parked.ts +18 -0
  225. package/scripts/lane/lane-preserve.ts +29 -1
  226. package/scripts/lane/lane-process-load.ts +125 -0
  227. package/scripts/lane/lane-process-stats.ts +93 -0
  228. package/scripts/lane/lane-registry.ts +17 -10
  229. package/scripts/lane/lane-restart.ts +5 -26
  230. package/scripts/lane/lane-session-action.ts +146 -0
  231. package/scripts/lane/lane-session-broker.ts +68 -125
  232. package/scripts/lane/lane-spent.ts +14 -3
  233. package/scripts/lane/lane-stats.ts +1 -0
  234. package/scripts/lane/lane-withdraw-cli.ts +71 -0
  235. package/scripts/lane/lane-withdraw.ts +182 -0
  236. package/scripts/lint/format.ts +4 -4
  237. package/scripts/lint/lint-parallel.ts +10 -3
  238. package/scripts/lint/lint-related-scope.ts +4 -1
  239. package/scripts/managed-marker/managed-marker-logic.ts +1 -2
  240. package/scripts/notify/telegram-test.ts +10 -5
  241. package/scripts/overrides/lockfile-overrides.ts +1 -3
  242. package/scripts/propagate/propagate.ts +1 -2
  243. package/scripts/release/release-progress.ts +3 -2
  244. package/scripts/report/report-format-reference.ts +2 -0
  245. package/scripts/report/report-lint.ts +7 -4
  246. package/scripts/review/acceptance-map-check.ts +61 -0
  247. package/scripts/review/acceptance-map.ts +205 -0
  248. package/scripts/review/review-brief-cli.ts +1 -1
  249. package/scripts/review/review-record-cli.ts +6 -2
  250. package/scripts/rules/agent-model.ts +59 -0
  251. package/scripts/rules/delivered-rules.ts +11 -2
  252. package/scripts/rules/destructive-command.ts +6 -9
  253. package/scripts/rules/direct-filing.ts +3 -7
  254. package/scripts/rules/early-heartbeat.ts +7 -18
  255. package/scripts/rules/file-body.ts +6 -13
  256. package/scripts/rules/filing-cap.ts +4 -6
  257. package/scripts/rules/firing-point.ts +6 -5
  258. package/scripts/rules/git-force.ts +5 -9
  259. package/scripts/rules/guard-remedy.ts +117 -0
  260. package/scripts/rules/implementation-cut.ts +37 -35
  261. package/scripts/rules/index-guard.ts +4 -7
  262. package/scripts/rules/issue-comments.ts +67 -16
  263. package/scripts/rules/josh-git-bare.ts +3 -6
  264. package/scripts/rules/lane-background.ts +10 -21
  265. package/scripts/rules/lane-carry-conflict.ts +7 -17
  266. package/scripts/rules/lane-interactive-ask.ts +6 -11
  267. package/scripts/rules/lane-park.ts +5 -13
  268. package/scripts/rules/lane-split-park.ts +2 -7
  269. package/scripts/rules/lane-switch-main.ts +9 -12
  270. package/scripts/rules/last-prompt.ts +50 -5
  271. package/scripts/rules/oracle-consulted.ts +4 -5
  272. package/scripts/rules/oracle-list-cli.ts +7 -0
  273. package/scripts/rules/piped-verification.ts +84 -32
  274. package/scripts/rules/poll-loop.ts +7 -17
  275. package/scripts/rules/pre-gate-cut.ts +7 -21
  276. package/scripts/rules/prior-comment-read.ts +7 -5
  277. package/scripts/rules/protected-files.ts +5 -9
  278. package/scripts/rules/raw-field-body.ts +3 -7
  279. package/scripts/rules/rule-body-guard.ts +4 -11
  280. package/scripts/rules/rule-list.ts +4 -1
  281. package/scripts/rules/rule-registry-rows.ts +10 -0
  282. package/scripts/rules/rule-registry.ts +7 -4
  283. package/scripts/rules/rule-rewrite.ts +114 -0
  284. package/scripts/rules/rule-value.ts +7 -1
  285. package/scripts/rules/run-tail-rule.ts +6 -22
  286. package/scripts/rules/shell-body-trigger.ts +4 -6
  287. package/scripts/rules/shell-segments.ts +22 -0
  288. package/scripts/rules/stop-decision.ts +77 -0
  289. package/scripts/rules/stop-rules.ts +164 -77
  290. package/scripts/rules/tail-commands.ts +15 -1
  291. package/scripts/rules/test-declared-commit.ts +4 -10
  292. package/scripts/rules/third-party-write.ts +5 -10
  293. package/scripts/rules/worktree-guard.ts +5 -12
  294. package/scripts/run/board/run-board-cli.ts +2 -0
  295. package/scripts/run/board/run-board-closed.ts +8 -2
  296. package/scripts/run/board/run-board-github.ts +19 -3
  297. package/scripts/run/board/run-board-header.ts +4 -1
  298. package/scripts/run/board/run-board-idle.ts +31 -0
  299. package/scripts/run/board/run-board-labels.ts +2 -0
  300. package/scripts/run/board/run-board-layout.ts +1 -1
  301. package/scripts/run/board/run-board-read.ts +25 -12
  302. package/scripts/run/board/run-board-reason.ts +17 -4
  303. package/scripts/run/board/run-board-render-legend.ts +1 -0
  304. package/scripts/run/board/run-board-render-slot.ts +1 -1
  305. package/scripts/run/board/run-board-render-waits.ts +41 -0
  306. package/scripts/run/board/run-board-render.ts +6 -1
  307. package/scripts/run/board/run-board-row-yield.ts +1 -0
  308. package/scripts/run/board/run-board-state.ts +9 -0
  309. package/scripts/run/board/run-board-status.ts +89 -23
  310. package/scripts/run/board/run-board-thanks.ts +7 -2
  311. package/scripts/run/board/run-board-tick.ts +37 -8
  312. package/scripts/run/carry/run-carry-args.ts +1 -3
  313. package/scripts/run/carry/run-carry-conversation.ts +7 -2
  314. package/scripts/run/cut/run-cut-cli.ts +18 -22
  315. package/scripts/run/cut/run-cut-decline.ts +72 -0
  316. package/scripts/run/cut/run-cut-ready.ts +74 -0
  317. package/scripts/run/cut/run-cut-report.ts +29 -0
  318. package/scripts/run/cut/run-cut.ts +10 -1
  319. package/scripts/run/detached-launch.ts +23 -4
  320. package/scripts/run/entry/run-entry-cli.ts +8 -1
  321. package/scripts/run/event/run-event-render.ts +1 -0
  322. package/scripts/run/event/run-event-scope.ts +19 -1
  323. package/scripts/run/event/run-event-stream-emit.ts +13 -6
  324. package/scripts/run/event/run-event-stream.ts +4 -0
  325. package/scripts/run/hold/run-hold-cli.ts +14 -3
  326. package/scripts/run/hold/run-hold-session.ts +46 -0
  327. package/scripts/run/hold/run-hold.ts +13 -4
  328. package/scripts/run/launch-priority.ts +32 -0
  329. package/scripts/run/merge/run-merge-cli.ts +16 -42
  330. package/scripts/run/merge/run-merge-ship.ts +59 -1
  331. package/scripts/run/merge/run-merge-signals.ts +99 -0
  332. package/scripts/run/merge/run-merge-steps.ts +11 -1
  333. package/scripts/run/merge/run-merge.ts +22 -9
  334. package/scripts/run/run-ending.ts +31 -3
  335. package/scripts/run/run-liveness.ts +1 -1
  336. package/scripts/run/run-parent-cut-hook.ts +5 -10
  337. package/scripts/run/run-poll-hook.ts +157 -0
  338. package/scripts/run/run-preflight.ts +1 -2
  339. package/scripts/run/run-step-cli.ts +22 -15
  340. package/scripts/run/run-step-section.ts +85 -0
  341. package/scripts/run/run-stop-notify.ts +1 -2
  342. package/scripts/run/run-watcher-guard.ts +6 -3
  343. package/scripts/run/ship/run-ship-cli.ts +5 -12
  344. package/scripts/run/ship/run-ship-detach.ts +9 -0
  345. package/scripts/run/ship/run-ship-next.ts +10 -2
  346. package/scripts/run/ship/run-ship-overlap.ts +195 -0
  347. package/scripts/run/ship/run-ship-pre-detach.ts +33 -15
  348. package/scripts/run/ship/run-ship-preflight.ts +28 -2
  349. package/scripts/run/ship/run-ship-return.ts +31 -7
  350. package/scripts/run/ship/run-ship-review-steps.ts +25 -14
  351. package/scripts/run/ship/run-ship-review.ts +15 -2
  352. package/scripts/run/ship/run-ship-steps.ts +1 -1
  353. package/scripts/run/ship/run-ship-stop-context.ts +206 -0
  354. package/scripts/run/ship/run-ship-sync.ts +14 -6
  355. package/scripts/run/tidy/run-tidy-cli.ts +3 -3
  356. package/scripts/run/tidy/run-tidy-lanes.ts +3 -2
  357. package/scripts/safe-chain/project-config.ts +7 -2
  358. package/scripts/sync/sync-hook-safety.ts +8 -2
  359. package/scripts/test/test-e2e-guard.ts +30 -5
  360. package/scripts/test/test-unit-guard.ts +16 -1
  361. package/scripts/test/unit-worker-share.ts +26 -3
  362. package/scripts/time-runtime/time-batch-guard.ts +3 -3
  363. package/scripts/time-runtime/time-hook-transcript.ts +3 -2
  364. package/scripts/time-runtime/time-shell.ts +39 -4
  365. package/scripts/time-runtime/time-spans.ts +1 -0
  366. package/scripts/time-runtime/time-tool-call.ts +7 -0
  367. package/scripts/version/effective-upstream.ts +3 -4
  368. package/scripts/version/kit-version-config.ts +8 -2
  369. package/scripts/version/latest-corepack.ts +1 -2
  370. package/scripts/version/release-hold.ts +11 -4
  371. package/scripts/version/version-commands.ts +12 -4
  372. package/templates/gitignore +6 -2
  373. package/dist/hooks/chunk-D5QBTOCZ.js +0 -68
  374. package/dist/hooks/chunk-UT7YC3N2.js +0 -56
@@ -0,0 +1,110 @@
1
+ import { canonical_command, COMMAND_MAP } from './josh-command-map'
2
+ import type { CommandUsage } from './josh-command-types'
3
+ import { AUTOMATION_USAGE } from './josh-usage-automation'
4
+ import { BACKLOG_USAGE } from './josh-usage-backlog'
5
+ import { DEVELOPER_USAGE } from './josh-usage-developer'
6
+ import { HOOK_USAGE } from './josh-usage-hooks'
7
+ import { ISSUE_USAGE } from './josh-usage-issue'
8
+ import { REVIEW_USAGE } from './josh-usage-review'
9
+ import { RUN_USAGE } from './josh-usage-run'
10
+ import { SESSION_USAGE } from './josh-usage-session'
11
+ import { WORKFLOW_USAGE } from './josh-usage-workflow'
12
+
13
+ // The single renderer of a command's usage. `josh help <command>` prints it and
14
+ // `scripts/document/generate-command-usage.ts` writes it between a reference page's usage markers,
15
+ // so the terminal and the page are one text (#3932).
16
+
17
+ type UsageTable = Readonly<Record<string, CommandUsage>>
18
+
19
+ // Which reference page renders each usage table — the one place a table is tied to its page, so the
20
+ // generator's coverage check and `josh help` read the same set (#3981).
21
+ /* eslint-disable @typescript-eslint/naming-convention */
22
+ const USAGE_PAGE_TABLES: Readonly<Record<string, ReadonlyArray<UsageTable>>> = {
23
+ 'docs/josh-commands.md': [DEVELOPER_USAGE],
24
+ 'docs/josh-commands-run.md': [RUN_USAGE, SESSION_USAGE],
25
+ 'docs/josh-commands-backlog.md': [ISSUE_USAGE, BACKLOG_USAGE, REVIEW_USAGE],
26
+ 'docs/josh-commands-automation.md': [AUTOMATION_USAGE, WORKFLOW_USAGE, HOOK_USAGE],
27
+ }
28
+ /* eslint-enable @typescript-eslint/naming-convention */
29
+ const COMMAND_USAGE: UsageTable = Object.fromEntries(
30
+ Object.values(USAGE_PAGE_TABLES)
31
+ .flat()
32
+ .flatMap((table) => Object.entries(table)),
33
+ )
34
+ const NOTE_GAP = 3
35
+
36
+ interface ExampleLine {
37
+ command: string
38
+ note: string | undefined
39
+ }
40
+
41
+ function usage_for(name: string): CommandUsage | undefined {
42
+ return Object.hasOwn(COMMAND_USAGE, name) ? COMMAND_USAGE[name] : undefined
43
+ }
44
+
45
+ function example_line(name: string, example: CommandUsage['examples'][number]): ExampleLine {
46
+ const command = example.arguments ? `pnpm josh ${name} ${example.arguments}` : `pnpm josh ${name}`
47
+
48
+ return { command, note: example.note }
49
+ }
50
+
51
+ // Every comment starts in one column, so a block reads as a table of what each spelling does.
52
+ function format_examples(name: string, usage: CommandUsage): string {
53
+ const lines = usage.examples.map((example) => example_line(name, example))
54
+ const width = Math.max(...lines.map((line) => line.command.length)) + NOTE_GAP
55
+ const rendered = lines.map((line) =>
56
+ line.note === undefined ? line.command : `${line.command.padEnd(width)}# ${line.note}`,
57
+ )
58
+
59
+ return ['```bash', ...rendered, '```'].join('\n')
60
+ }
61
+
62
+ function code_span(text: string): string {
63
+ return `\`${text}\``
64
+ }
65
+
66
+ function format_flags(flags: NonNullable<CommandUsage['flags']>): string {
67
+ const items = flags.map(
68
+ (flag) =>
69
+ `- ${flag.names.map((spelling) => code_span(spelling)).join(' / ')} — ${flag.description}`,
70
+ )
71
+
72
+ return ['**Options:**', '', ...items].join('\n')
73
+ }
74
+
75
+ function format_usage(name: string): string | undefined {
76
+ const usage = usage_for(name)
77
+ if (usage === undefined) return undefined
78
+ const flags = usage.flags === undefined ? [] : [format_flags(usage.flags)]
79
+
80
+ return [format_examples(name, usage), ...flags].join('\n\n')
81
+ }
82
+
83
+ // `josh help <command>`: the synopsis line, the description, then the usage block when the command
84
+ // has one. An alias resolves to its command; a name that is neither answers `undefined`.
85
+ function format_command_help(input: string): string | undefined {
86
+ const name = canonical_command(input)
87
+ const entry = Object.hasOwn(COMMAND_MAP, name) ? COMMAND_MAP[name] : undefined
88
+ if (entry === undefined) return undefined
89
+ const [synopsis] = entry.reference
90
+ const head = synopsis ? `josh ${name} ${synopsis}` : `josh ${name}`
91
+ const usage = format_usage(name)
92
+
93
+ return [head, '', entry.description, ...(usage === undefined ? [] : ['', usage])].join('\n')
94
+ }
95
+
96
+ // The commands whose usage blocks a reference page renders — the keys of the tables tied to it.
97
+ function page_commands(page: string): Array<string> {
98
+ const tables = Object.hasOwn(USAGE_PAGE_TABLES, page) ? USAGE_PAGE_TABLES[page] : undefined
99
+
100
+ return (tables ?? []).flatMap((table) => Object.keys(table))
101
+ }
102
+
103
+ const command_usage = {
104
+ USAGE_PAGES: Object.keys(USAGE_PAGE_TABLES),
105
+ format_command_help,
106
+ format_usage,
107
+ page_commands,
108
+ }
109
+
110
+ export { command_usage }
@@ -211,9 +211,7 @@ function is_own_record(stamp: FileMapStamp): boolean {
211
211
  function complete_at(target: string): string | undefined {
212
212
  const stamp = read_at(target)
213
213
 
214
- if (stamp === undefined) return undefined
215
-
216
- if (!is_own_record(stamp)) return undefined
214
+ if (stamp === undefined || !is_own_record(stamp)) return undefined
217
215
 
218
216
  return stamp_file.write_stamp(target, { ...stamp, completed_at: new Date().toISOString() })
219
217
  }
@@ -87,8 +87,8 @@ function deny_envelope(reason: string): string {
87
87
  }
88
88
 
89
89
  // **A rewrite, not a refusal**: the call proceeds with `updated_input` merged
90
- // over its own. `allow` is the decision the harness applies an `updatedInput` under; a settings `deny`
91
- // rule still wins over it, so this never widens what the call may do.
90
+ // over its own and is allowed past the permission prompt; a settings `deny` rule still wins over it.
91
+ // Where the line may carry commands the hook did not write, `flow_rewrite_envelope` is the one to use.
92
92
  function rewrite_envelope(updated_input: Record<string, unknown>, context: string): string {
93
93
  return JSON.stringify({
94
94
  systemMessage: context,
@@ -101,6 +101,20 @@ function rewrite_envelope(updated_input: Record<string, unknown>, context: strin
101
101
  })
102
102
  }
103
103
 
104
+ // **A rewrite that leaves the permission to the harness.** No `permissionDecision`, so the rewritten
105
+ // call meets the same permission flow the typed one would have — whatever else rides the line beside
106
+ // the rewritten part is prompted for, or not, exactly as before (joshuafolkken/kit#3875).
107
+ function flow_rewrite_envelope(updated_input: Record<string, unknown>, context: string): string {
108
+ return JSON.stringify({
109
+ systemMessage: context,
110
+ hookSpecificOutput: {
111
+ hookEventName: HOOK_EVENT_NAME,
112
+ updatedInput: updated_input,
113
+ additionalContext: context,
114
+ },
115
+ })
116
+ }
117
+
104
118
  // **A notice, not a decision.** It carries no `permissionDecision`, so the call proceeds exactly as it
105
119
  // would have; `additionalContext` is what reaches the model, and `systemMessage` is what the person
106
120
  // watching sees. Both are filled because either channel alone leaves one of the two blind — and the
@@ -476,6 +490,7 @@ const hook_decision = {
476
490
  deny_envelope,
477
491
  emit_outcome,
478
492
  fault_notice,
493
+ flow_rewrite_envelope,
479
494
  is_switch_enabled,
480
495
  is_switch_opt_in,
481
496
  load_environment_file,
@@ -77,6 +77,7 @@ const ALIASES: Record<string, string> = {
77
77
  tm: 'time',
78
78
  tmd: 'time:density',
79
79
  rtr: 'retrospective',
80
+ ca: 'cost:audit',
80
81
  rvf: 'review:findings',
81
82
  ruv: 'rule:value',
82
83
  ev: 'eval',
@@ -86,6 +87,7 @@ const ALIASES: Record<string, string> = {
86
87
  lst: 'lane:stats',
87
88
  lli: 'lane:limit',
88
89
  lrs: 'lane:restart',
90
+ lwd: 'lane:withdraw',
89
91
  blr: 'backlogrun',
90
92
  }
91
93
 
@@ -43,6 +43,25 @@ type CommandReference = readonly [
43
43
  side_effects: ReadonlyArray<CommandSideEffect>,
44
44
  ]
45
45
 
46
+ // One `pnpm josh <command> <arguments>` line of a usage block, with the comment printed after it.
47
+ interface CommandExample {
48
+ arguments: string
49
+ note?: string
50
+ }
51
+
52
+ // Spellings of one option — `-y` and `--yes` — rendered side by side.
53
+ interface CommandFlag {
54
+ names: ReadonlyArray<string>
55
+ description: string
56
+ }
57
+
58
+ // What `josh help <command>` prints and what the reference pages render between their usage
59
+ // markers — one source for both, so the page and the terminal cannot disagree (#3932).
60
+ interface CommandUsage {
61
+ examples: ReadonlyArray<CommandExample>
62
+ flags?: ReadonlyArray<CommandFlag>
63
+ }
64
+
46
65
  interface CommandEntry {
47
66
  script?: string
48
67
  shell?: ReadonlyArray<string>
@@ -109,6 +128,13 @@ const TS_BUILD_INFO_FILE = '.tsbuildinfo'
109
128
  const CSPELL_CACHE_FILE = '.cspellcache'
110
129
  const ESLINT_EDIT_CACHE_FILE = '.eslintcache.edit'
111
130
  const ESLINT_RELATED_CACHE_FILE = '.eslintcache.related'
131
+ const PRETTIER_CACHE_FILE = '.prettiercache'
132
+ const PRETTIER_RELATED_CACHE_FILE = '.prettiercache.related'
133
+ // The pre-commit hook's own, because a staged-files run on the gate's file degrades it: cspell prunes
134
+ // every entry the run did not visit (measured 892 KB down to 18 KB), and `eslint --quiet` stores a
135
+ // report without its warnings under the same config hash the gate reads.
136
+ const CSPELL_COMMIT_CACHE_FILE = '.cspellcache.commit'
137
+ const ESLINT_COMMIT_CACHE_FILE = '.eslintcache.commit'
112
138
 
113
139
  type GateCachePortability = 'raw' | 'rooted-json'
114
140
 
@@ -139,6 +165,10 @@ const ESLINT_RELATED_CACHE_SPEC: GateCacheSpec = {
139
165
  cache_file: ESLINT_RELATED_CACHE_FILE,
140
166
  portability: ROOTED_JSON_PORTABILITY,
141
167
  }
168
+ // **Prettier's caches are in neither list: they do not survive a move to another checkout.**
169
+ // Prettier 3 hashes each file's resolved options, *its absolute `filepath` included*, into the entry,
170
+ // so rebasing the keys as ESLint's are still leaves every entry a miss — two checkouts of one tree
171
+ // were measured sharing none of their 3,526 option hashes. Each checkout keeps a warm cache of its own.
142
172
  const GATE_CACHE_SPECS: ReadonlyArray<GateCacheSpec> = [
143
173
  ESLINT_CACHE_SPEC,
144
174
  TS_CACHE_SPEC,
@@ -175,14 +205,20 @@ const GATE_CACHE_FILES: ReadonlyArray<string> = GATE_CACHE_SPECS.map((spec) => s
175
205
  //
176
206
  // **The lint's target scope is untouched.** This is where a cache is written, not what is read:
177
207
  // `josh lint:related` narrows in front of the gate and `josh gate` still runs `josh lint` over the
178
- // whole tree before any commit.
208
+ // whole tree before any commit. The scoped lint's prettier cache is its own for the same reason:
209
+ // prettier rewrites its cache file whole as well.
179
210
  // What the ignore rules are asserted against: every cache file this package writes, wherever it is
180
- // written from. The gate's three, the edit hook's, and the scoped lint's — a cache file that is not
181
- // ignored is committed, or spell-checked, which is a red gate with nothing misspelled in the tree.
211
+ // written from. The gate's, the edit hook's, the scoped lint's and the pre-commit hook's — a cache
212
+ // file that is not ignored is committed, or spell-checked, which is a red gate with nothing
213
+ // misspelled in the tree.
182
214
  const IGNORED_CACHE_FILES: ReadonlyArray<string> = [
183
215
  ...GATE_CACHE_FILES,
184
216
  ESLINT_EDIT_CACHE_FILE,
185
217
  ESLINT_RELATED_CACHE_FILE,
218
+ PRETTIER_CACHE_FILE,
219
+ PRETTIER_RELATED_CACHE_FILE,
220
+ CSPELL_COMMIT_CACHE_FILE,
221
+ ESLINT_COMMIT_CACHE_FILE,
186
222
  ]
187
223
 
188
224
  // `--cache --cache-strategy content` is one convention rather than two coincidences: cspell adopted
@@ -190,11 +226,11 @@ const IGNORED_CACHE_FILES: ReadonlyArray<string> = [
190
226
  const CONTENT_CACHE_FLAGS = ['--cache', '--cache-strategy', 'content'] as const
191
227
  const CACHE_LOCATION_FLAG = '--cache-location'
192
228
 
193
- // Four locations are written with these same four flags — the gate's eslint cache, the scoped lint's,
194
- // the edit hook's and the spell check's — so the sequence is built here once. Spelled out per
195
- // location, a fix to the order would have to be made four times and each copy fails silently: a flag
196
- // and its value are one unit, and a wrong order makes the tool read `--cache-strategy` as the file
197
- // name rather than erroring.
229
+ // Every location is written with these same four flags — the eslint, prettier and spell-check caches
230
+ // of the gate, the scoped lint, the edit hook and the pre-commit hook — so the sequence is built here
231
+ // once. Spelled out per location, a fix to the order would have to be made once per location and
232
+ // each copy fails silently: a flag and its value are one unit, and a wrong order makes the tool read
233
+ // `--cache-strategy` as the file name rather than erroring.
198
234
  function content_cache_flags(cache_file: string): ReadonlyArray<string> {
199
235
  return [...CONTENT_CACHE_FLAGS, CACHE_LOCATION_FLAG, cache_file]
200
236
  }
@@ -204,8 +240,12 @@ const ESLINT_EDIT_CACHE_FLAGS = content_cache_flags(ESLINT_EDIT_CACHE_FILE)
204
240
  const ESLINT_RELATED_CACHE_FLAGS = content_cache_flags(ESLINT_RELATED_CACHE_FILE)
205
241
  const TS_CACHE_FLAGS = ['--incremental', '--tsBuildInfoFile', TS_BUILD_INFO_FILE] as const
206
242
  const CSPELL_CACHE_FLAGS = content_cache_flags(CSPELL_CACHE_FILE)
243
+ const PRETTIER_CACHE_FLAGS = content_cache_flags(PRETTIER_CACHE_FILE)
244
+ const PRETTIER_RELATED_CACHE_FLAGS = content_cache_flags(PRETTIER_RELATED_CACHE_FILE)
245
+ const CSPELL_COMMIT_CACHE_FLAGS = content_cache_flags(CSPELL_COMMIT_CACHE_FILE)
246
+ const ESLINT_COMMIT_CACHE_FLAGS = content_cache_flags(ESLINT_COMMIT_CACHE_FILE)
207
247
 
208
- export type { CommandCategory, CommandEntry, GateCacheSpec }
248
+ export type { CommandCategory, CommandEntry, CommandUsage, GateCacheSpec }
209
249
  // The three cache files are exported one by one as well as as a list, because `josh bench` clears
210
250
  // them per target: the lint step writes only the eslint one, so a target
211
251
  // that cleared the list would report a cold type check as the lint's own cost. The edit hook's cache
@@ -216,8 +256,10 @@ export {
216
256
  COMMAND_SIDE_EFFECTS,
217
257
  CSPELL_CACHE_FILE,
218
258
  CSPELL_CACHE_FLAGS,
259
+ CSPELL_COMMIT_CACHE_FLAGS,
219
260
  ESLINT_CACHE_FILE,
220
261
  ESLINT_CACHE_FLAGS,
262
+ ESLINT_COMMIT_CACHE_FLAGS,
221
263
  ESLINT_EDIT_CACHE_FLAGS,
222
264
  ESLINT_RELATED_CACHE_FLAGS,
223
265
  ESLINT_RELATED_CACHE_FILE,
@@ -226,6 +268,10 @@ export {
226
268
  GATE_COMMAND,
227
269
  IGNORED_CACHE_FILES,
228
270
  OPTIONAL_ENV_FILE_FLAGS,
271
+ PRETTIER_CACHE_FILE,
272
+ PRETTIER_CACHE_FLAGS,
273
+ PRETTIER_RELATED_CACHE_FILE,
274
+ PRETTIER_RELATED_CACHE_FLAGS,
229
275
  SHARED_CACHE_SPECS,
230
276
  TS_BUILD_INFO_FILE,
231
277
  TS_CACHE_FLAGS,
@@ -1,3 +1,4 @@
1
+ import { core_budget } from '#scripts/gate/core-budget'
1
2
  import { OPTIONAL_ENV_FILE_FLAGS, type CommandEntry } from './josh-command-types'
2
3
  import { BACKLOG_COMMANDS } from './josh-commands-backlog'
3
4
  import { DOCUMENT_COMMANDS } from './josh-commands-document'
@@ -80,6 +81,16 @@ const AI_COMMANDS: Record<string, CommandEntry> = {
80
81
  category: 'AI tools',
81
82
  reference: ['(--cut | --over <tokens-per-request>) [--path <dir>]', 'automation', ['none']],
82
83
  },
84
+ 'cost:audit': {
85
+ script: 'scripts/cost-audit/cost-audit-cli.ts',
86
+ description:
87
+ 'Report AI cost over a period by session kind, tool category and guard, with cost per merge and regressions against the period before',
88
+ category: 'AI tools',
89
+ reference: ['[--period <days>]', 'maintainer', ['none']],
90
+ // Kit-only: it reads kit's own transcript store, like `josh retrospective`, which carries its
91
+ // summary line.
92
+ is_kit_only: true,
93
+ },
83
94
  ...DOCUMENT_COMMANDS,
84
95
  time: {
85
96
  script: 'scripts/time/time-cli.ts',
@@ -108,6 +119,8 @@ const AI_COMMANDS: Record<string, CommandEntry> = {
108
119
  "Aggregate a finished run's cost, review findings, observation ledger and events into one digest",
109
120
  category: 'AI tools',
110
121
  reference: ['', 'maintainer', ['none']],
122
+ core_weight: core_budget.CORE_WEIGHTS.retrospective,
123
+ memory_mb: core_budget.MEMORY_MB.retrospective,
111
124
  // Kit-only: it reads kit's own development run — the transcript store, the review ledger and the
112
125
  // run event stream — so it means nothing in a consumer project and is dropped from a consumer's
113
126
  // help, through the same declaration `josh time` uses for the same reason.
@@ -129,7 +129,7 @@ const DEV_COMMANDS: Record<string, CommandEntry> = {
129
129
  'stop:guard': {
130
130
  script: 'scripts/hooks/stop-guard.ts',
131
131
  description:
132
- 'Claude Code Stop hook: deliver the three stop-time rules — hold notify/release and issue citation (reads the Stop payload on stdin)',
132
+ 'Claude Code Stop hook: send the hold notify, release the hold and print the issue citations itself; block on the rules that need the model (reads the Stop payload on stdin)',
133
133
  category: 'Development',
134
134
  reference: ['', 'automation', ['none']],
135
135
  // **No `tsx_arguments`, deliberately**, the same as `pretool:guard` above: this runs at every
@@ -19,6 +19,12 @@ const HOOKS_COMMANDS: Record<string, CommandEntry> = {
19
19
  category: 'Git hooks',
20
20
  reference: ['[paths...]', 'automation', ['none']],
21
21
  },
22
+ 'pre-commit-lint': {
23
+ script: 'scripts/hooks/pre-commit-lint.ts',
24
+ description: 'Git hook: run cspell, prettier or eslint over staged files from a content cache',
25
+ category: 'Git hooks',
26
+ reference: ['<cspell|prettier|eslint> [paths...]', 'automation', ['files']],
27
+ },
22
28
  'pre-push-unit': {
23
29
  script: 'scripts/hooks/pre-push-unit.ts',
24
30
  description: 'Git hook: run unit tests, reusing a green gate recorded on the pushed tree',
@@ -83,6 +83,15 @@ const LANE_COMMANDS: Record<string, CommandEntry> = {
83
83
  category: 'AI tools',
84
84
  reference: ['<issue>', 'developer', ['files', 'git', 'processes', 'network']],
85
85
  },
86
+ // `.env` is read for `JOSH_LANE_ROOT`, as every lane command reads it, so the lane is found.
87
+ 'lane:withdraw': {
88
+ script: 'scripts/lane/lane-withdraw-cli.ts',
89
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
90
+ description:
91
+ 'Stop a running lane child, stash its uncommitted work, close its issue as not planned and close the lane — booked withdrawn, not as an outage or a failure',
92
+ category: 'AI tools',
93
+ reference: ['<issue> --reason <text>', 'developer', ['files', 'git', 'processes', 'network']],
94
+ },
86
95
  // A live run's lane limit: `.env` is read so the bare form reports the
87
96
  // `JOSH_LANE_LIMIT` a person set there when no override stands.
88
97
  'lane:limit': {
@@ -106,7 +115,7 @@ const LANE_COMMANDS: Record<string, CommandEntry> = {
106
115
  'lane:stats': {
107
116
  ...MEASURE_ARGUMENTS,
108
117
  description:
109
- 'Print one table row of lane throughput, gate duration and machine load over a period, the per-stage durations of a lane under it, and the wait after each ship stop reason under those',
118
+ 'Print one table row of lane throughput, gate duration and machine load over a period, the per-stage durations of a lane under it, the wait after each ship stop reason under those, and the duration and reuse count of each gate check last',
110
119
  category: 'AI tools',
111
120
  reference: ['--period <days> [--limit <lane-limit>]', 'maintainer', ['none']],
112
121
  default_script_arguments: ['stats'],
@@ -112,6 +112,11 @@ const WORKFLOW_COMMANDS: Record<string, CommandEntry> = {
112
112
  // A script rather than an `sh -c` chain, because the strategy has to be named rather than left to
113
113
  // the caller's git configuration: a bare `git pull` aborts with `Need to specify how to reconcile
114
114
  // divergent branches` on exactly the diverged branch the command exists for.
115
+ //
116
+ // **It declares no core weight, by measurement** (joshuafolkken/kit#3944): its own work is git, and
117
+ // the catalog it may regenerate took 0.6s of CPU. The heavy processes seen beside it are commit
118
+ // hooks — its regenerated catalog's commit runs them — which reserve themselves, and a weight here
119
+ // would set the held mark they inherit, folding the parallel hook tools into this one place.
115
120
  'main:merge': {
116
121
  script: 'scripts/git/main-merge.ts',
117
122
  description: 'Merge origin default branch into the current branch',
@@ -3,7 +3,6 @@ import path from 'node:path'
3
3
  import { fileURLToPath } from 'node:url'
4
4
  import { resolve_local_bin, resolve_package_bin } from '#scripts/build/local-bin'
5
5
  import { core_budget } from '#scripts/gate/core-budget'
6
- import { ancestor_directories } from '#scripts/lib/ancestor-directories'
7
6
  import { package_version_schema } from '#scripts/lib/schemas'
8
7
  import { resolve_spawn_exit } from '#scripts/lib/spawn-exit'
9
8
  import { execaSync } from 'execa'
@@ -18,6 +17,7 @@ import {
18
17
  import { composite_arguments, USAGE_ERROR_EXIT_CODE } from './josh-composite-arguments'
19
18
  import { josh_in_process } from './josh-in-process'
20
19
  import { kit_only } from './kit-only'
20
+ import { find_package_directory } from './package-directory'
21
21
  import { run_github_prerequisite } from './run-github-prerequisite'
22
22
 
23
23
  const COLUMN_WIDTH = 26
@@ -35,17 +35,6 @@ interface TsxRunner {
35
35
  leading_arguments: ReadonlyArray<string>
36
36
  }
37
37
 
38
- // Resolve the kit package root by ascending to the nearest package.json. This works both
39
- // from the bundled dist/josh.js (one level under the root) and from the tsx source at
40
- // scripts/josh/ (two levels), so this file's depth no longer has to be hard-coded.
41
- function find_package_directory(start_directory: string): string {
42
- return (
43
- ancestor_directories.nearest(start_directory, (directory) =>
44
- existsSync(path.join(directory, PACKAGE_JSON)),
45
- ) ?? start_directory
46
- )
47
- }
48
-
49
38
  const PACKAGE_DIR = find_package_directory(path.dirname(fileURLToPath(import.meta.url)))
50
39
 
51
40
  function resolve_tsx_executable(): string {
@@ -287,6 +276,7 @@ function declared(value: number | (() => number) | undefined): number | undefine
287
276
  // without claiming a place. A command under a parent that already holds its cores claims nothing:
288
277
  // `core_budget.with_command_reservation` reads the mark that parent set.
289
278
  async function dispatch_entry(
279
+ command: string,
290
280
  entry: CommandEntry,
291
281
  subcommand_arguments: Array<string>,
292
282
  ): Promise<number> {
@@ -297,7 +287,7 @@ async function dispatch_entry(
297
287
  return await core_budget.with_command_reservation(
298
288
  weight,
299
289
  async () => await run_entry(entry, subcommand_arguments),
300
- { memory_mb: declared(entry.memory_mb) },
290
+ { memory_mb: declared(entry.memory_mb), command },
301
291
  )
302
292
  }
303
293
 
@@ -314,7 +304,7 @@ async function run_command(
314
304
  const early_exit = pre_dispatch_exit(resolved, entry, subcommand_arguments, is_consumer)
315
305
  if (early_exit !== undefined) return early_exit
316
306
 
317
- return await dispatch_entry(entry, subcommand_arguments)
307
+ return await dispatch_entry(resolved, entry, subcommand_arguments)
318
308
  }
319
309
 
320
310
  const josh_logic = {
@@ -330,10 +320,11 @@ export { ALIASES, COMMAND_MAP } from './josh-command-map'
330
320
  export { SPAWN_ERROR_EXIT_CODE } from '#scripts/lib/spawn-exit'
331
321
  export { composite_arguments, USAGE_ERROR_EXIT_CODE } from './josh-composite-arguments'
332
322
  export {
333
- find_package_directory,
334
323
  josh_logic,
335
324
  resolve_alias,
336
325
  resolve_tsx_executable,
337
326
  resolve_tsx_runner,
338
327
  UNKNOWN_COMMAND_EXIT_CODE,
339
328
  }
329
+
330
+ export { find_package_directory } from './package-directory'
@@ -0,0 +1,121 @@
1
+ import type { CommandUsage } from './josh-command-types'
2
+
3
+ // The usage of the commands `docs/josh-commands-automation.md` documents under "Development",
4
+ // "Project" and "AI tools", keyed by command name. The page's usage blocks are generated from this
5
+ // table and `josh help <command>` prints it, so an example or a flag is written once, here (#3939).
6
+ const STAGED = '--staged'
7
+ const JSON_FLAG = '--json'
8
+ const BRANCH_DIFF = 'the branch diff'
9
+ const STAGED_DIFF = 'the staged diff instead'
10
+ const PR_NUMBER = '42'
11
+ const DRY_RUN = '--dry-run'
12
+ const SKIP_PUBLISH_WAIT = '--skip-publish-wait'
13
+
14
+ /* eslint-disable @typescript-eslint/naming-convention */
15
+ const AUTOMATION_USAGE: Readonly<Record<string, CommandUsage>> = {
16
+ 'refactor:scan': { examples: [{ arguments: '' }] },
17
+ 'time:density': {
18
+ examples: [{ arguments: '' }, { arguments: '--lanes 5', note: 'the five most recent lanes' }],
19
+ flags: [
20
+ {
21
+ names: ['--lanes <n>'],
22
+ description: 'average over a different count of recent qualifying lanes (default 10).',
23
+ },
24
+ {
25
+ names: ['--path <dir>'],
26
+ description:
27
+ "read another project's lane transcripts, as `josh time` does. Run it from the main checkout — a lane reads only its own transcript.",
28
+ },
29
+ ],
30
+ },
31
+ 'e2e:retry-check': { examples: [{ arguments: '' }] },
32
+ 'sync:scope': {
33
+ examples: [
34
+ { arguments: '', note: BRANCH_DIFF },
35
+ { arguments: STAGED, note: STAGED_DIFF },
36
+ { arguments: JSON_FLAG, note: '{"scope":"managed","reason":"..."}' },
37
+ ],
38
+ flags: [
39
+ { names: [STAGED], description: 'inspect the staged diff instead of the branch diff.' },
40
+ { names: [JSON_FLAG], description: 'emit `{"scope","reason"}` as JSON.' },
41
+ ],
42
+ },
43
+ 'dogfood:commit': { examples: [{ arguments: '~/Development/kit-test-html-start' }] },
44
+ 'fresh:run': {
45
+ examples: [
46
+ { arguments: '--list', note: "kit's six patterns" },
47
+ { arguments: 'kit-test-html-init', note: 'one pattern, the packed checkout' },
48
+ {
49
+ arguments: 'kit-test-html-start',
50
+ note: 'a GitHub pattern, the latest published version',
51
+ },
52
+ { arguments: '--spec fresh/html-init.json', note: 'a scenario another toolkit wrote' },
53
+ ],
54
+ flags: [
55
+ { names: ['--list'], description: 'print the pattern names and run nothing.' },
56
+ {
57
+ names: ['--spec <file.json>'],
58
+ description:
59
+ 'run the scenario in this file instead of a named pattern; the path is relative to the project root.',
60
+ },
61
+ {
62
+ names: ['--package-version <version>'],
63
+ description:
64
+ "the published version a `package_source: published` scenario installs. Default: the registry's latest version of the package the command is run from.",
65
+ },
66
+ {
67
+ names: ['--log-dir <dir>'],
68
+ description: 'where the log is written. Default: `.claude/tmp/fresh-machine`.',
69
+ },
70
+ { names: ['--rebuild'], description: 'build the machine image without the layer cache.' },
71
+ ],
72
+ },
73
+ 'auth:setup': {
74
+ examples: [
75
+ { arguments: '', note: 'sign in and save the token' },
76
+ { arguments: '--check', note: 'ok: … saved on <date>, or missing: … and exit 1' },
77
+ ],
78
+ },
79
+ 'sonar:hotspots': { examples: [{ arguments: PR_NUMBER }] },
80
+ 'sonar:new-code': { examples: [{ arguments: PR_NUMBER }] },
81
+ 'ui:routes': {
82
+ examples: [
83
+ { arguments: '', note: BRANCH_DIFF },
84
+ { arguments: STAGED, note: STAGED_DIFF },
85
+ ],
86
+ },
87
+ propagate: {
88
+ examples: [
89
+ { arguments: '' },
90
+ { arguments: DRY_RUN, note: 'report targets and steps, write nothing' },
91
+ { arguments: SKIP_PUBLISH_WAIT, note: 'release already known to be published' },
92
+ { arguments: '--target app-kit', note: 'carry the release into one consumer only' },
93
+ ],
94
+ flags: [
95
+ {
96
+ names: [DRY_RUN],
97
+ description:
98
+ 'report targets and steps without writing; skips the publish wait, opens no issues.',
99
+ },
100
+ {
101
+ names: [SKIP_PUBLISH_WAIT],
102
+ description: 'skip the registry poll for an already-published release.',
103
+ },
104
+ {
105
+ names: ['--target <repo>'],
106
+ description:
107
+ 'process only that consumer (`app-kit` or `joshuafolkken/app-kit`); the rest are reported `skipped` and left untouched. An unknown, ambiguous or non-dependent name fails before the publish wait, writing nothing.',
108
+ },
109
+ ],
110
+ },
111
+ 'repo:party': {
112
+ examples: [
113
+ { arguments: 'joshuafolkken/kit', note: '→ first-party (in the kit session)' },
114
+ { arguments: 'sveltejs/kit', note: '→ third-party' },
115
+ { arguments: '', note: "no argument: the session's own repository" },
116
+ ],
117
+ },
118
+ }
119
+ /* eslint-enable @typescript-eslint/naming-convention */
120
+
121
+ export { AUTOMATION_USAGE }