@joshuafolkken/kit 1.1514.0 → 1.1784.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 (858) hide show
  1. package/.claude/agents/investigator.md +1 -1
  2. package/.claude/settings.json +5 -5
  3. package/.claude/skills/epic-commands/SKILL.md +26 -65
  4. package/.claude/skills/epic-commands/epic-bundle.md +3 -1
  5. package/.claude/skills/workflow-commands/SKILL.md +5 -5
  6. package/.claude/skills/workflow-commands/background-commands.md +5 -5
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +10 -8
  8. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
  9. package/.claude/skills/workflow-commands/backlogrun-lanes.md +17 -13
  10. package/.claude/skills/workflow-commands/backlogrun-park.md +14 -23
  11. package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -2
  12. package/.claude/skills/workflow-commands/backlogrun-recovery.md +5 -5
  13. package/.claude/skills/workflow-commands/backlogrun-steps.md +10 -10
  14. package/.claude/skills/workflow-commands/backlogrun.md +1 -1
  15. package/.claude/skills/workflow-commands/chain-rule.md +13 -7
  16. package/.claude/skills/workflow-commands/delegation.md +6 -5
  17. package/.claude/skills/workflow-commands/entry-sequence.md +9 -9
  18. package/.claude/skills/workflow-commands/followup.md +9 -31
  19. package/.claude/skills/workflow-commands/fullrun-steps.md +36 -45
  20. package/.claude/skills/workflow-commands/fullrun.md +2 -2
  21. package/.claude/skills/workflow-commands/halfrun.md +17 -25
  22. package/.claude/skills/workflow-commands/issue-comments.md +16 -12
  23. package/.claude/skills/workflow-commands/issue-scout.md +2 -2
  24. package/.claude/skills/workflow-commands/kickoff.md +24 -23
  25. package/.claude/skills/workflow-commands/latest-gate.md +7 -12
  26. package/.claude/skills/workflow-commands/needs-human-review.md +9 -14
  27. package/.claude/skills/workflow-commands/observation-filing.md +4 -36
  28. package/.claude/skills/workflow-commands/observation-ledger.md +1 -1
  29. package/.claude/skills/workflow-commands/pre-gate-cut.md +13 -30
  30. package/.claude/skills/workflow-commands/prerequisite.md +10 -16
  31. package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
  32. package/.claude/skills/workflow-commands/prrun.md +3 -7
  33. package/.claude/skills/workflow-commands/retrospective.md +1 -1
  34. package/.claude/skills/workflow-commands/split-assessment.md +13 -1
  35. package/.claude/skills/workflow-commands/working-tree-hold.md +9 -9
  36. package/.codex/hooks.json +5 -5
  37. package/.github/actions/setup-node/action.yml +9 -0
  38. package/.github/actions/setup-pnpm/action.yml +1 -1
  39. package/.github/dependabot.yml +16 -0
  40. package/.github/release.yml +0 -2
  41. package/.github/workflows/ci.yml +120 -10
  42. package/.github/workflows/publish.yml +8 -1
  43. package/.github/workflows/sonar-qube.yml +1 -0
  44. package/.prettierignore +2 -0
  45. package/.vscode/tasks.json +1 -2
  46. package/CLAUDE.md +3 -7
  47. package/README.md +4 -2
  48. package/SECURITY.md +1 -1
  49. package/dist/CLAUDE.md +3 -7
  50. package/dist/commands/document-read-cli.js +882 -0
  51. package/dist/commands/{document-section-cli.js → document-section-main.js} +79 -37
  52. package/dist/commands/read-set-cli.js +1867 -0
  53. package/dist/commands/run-prep-main.js +21653 -0
  54. package/dist/commands/run-step-cli.js +23880 -0
  55. package/dist/config-merge/index.js +5 -1
  56. package/dist/hooks/audit-provision.js +20 -35
  57. package/dist/hooks/{chunk-DGT54IH5.js → chunk-AZX4FGQ3.js} +63 -17
  58. package/dist/hooks/chunk-CWMBGKYW.js +6483 -0
  59. package/dist/hooks/chunk-O2YBIDSI.js +4306 -0
  60. package/dist/hooks/{chunk-TNUMY6NL.js → chunk-PT5R6UJD.js} +4193 -1900
  61. package/dist/hooks/chunk-TUIFS5E7.js +72 -0
  62. package/dist/hooks/{chunk-723HKZO5.js → chunk-VWWCFGWK.js} +1 -1
  63. package/dist/hooks/{chunk-APUO6U4J.js → chunk-WR2KQAYZ.js} +1843 -440
  64. package/dist/hooks/{chunk-O6GDRNJB.js → chunk-XGBNSWEI.js} +248 -46
  65. package/dist/hooks/chunk-YCDOIR3I.js +3456 -0
  66. package/dist/hooks/codex-hook-adapter.js +10 -22
  67. package/dist/hooks/format-edited.js +5 -6
  68. package/dist/hooks/inputs.json +443 -317
  69. package/dist/hooks/pretool-guard.js +7 -25
  70. package/dist/hooks/session-lang.js +44 -51
  71. package/dist/hooks/stop-guard.js +7716 -2187
  72. package/dist/josh.js +6002 -3583
  73. package/dist/self-sync-guard/index.js +74 -10
  74. package/dist/version/index.js +115 -406
  75. package/eslint/base.js +1 -1
  76. package/lefthook/base.yml +3 -1
  77. package/package.json +10 -48
  78. package/pnpm-workspace.yaml +4 -2
  79. package/prompts/coding-standards.md +1 -1
  80. package/prompts/collaboration-workflow/file-edits.md +1 -7
  81. package/prompts/collaboration-workflow/issue-citation.md +1 -1
  82. package/prompts/collaboration-workflow/issue-template.md +33 -16
  83. package/prompts/collaboration-workflow/lane-instructions.md +1 -2
  84. package/prompts/collaboration-workflow/measurement.md +37 -0
  85. package/prompts/collaboration-workflow/operating-rules.md +4 -6
  86. package/prompts/collaboration-workflow/output-bounds.md +2 -7
  87. package/prompts/collaboration-workflow/plan-comment.md +3 -42
  88. package/prompts/collaboration-workflow/principles.md +5 -0
  89. package/prompts/collaboration-workflow/report-format.md +31 -60
  90. package/prompts/collaboration-workflow/residency.md +2 -2
  91. package/prompts/collaboration-workflow/shell-body.md +6 -16
  92. package/prompts/collaboration-workflow/turn-batching.md +0 -2
  93. package/prompts/collaboration-workflow/upstream-interrupt.md +14 -4
  94. package/prompts/collaboration-workflow/wip-cap.md +1 -1
  95. package/prompts/collaboration-workflow.md +3 -7
  96. package/prompts/refactoring.md +1 -1
  97. package/prompts/review-rubric.md +1 -2
  98. package/prompts/review.md +41 -21
  99. package/prompts/testing-guide.md +8 -43
  100. package/scripts/agent/agent-event.ts +15 -15
  101. package/scripts/agent/agent-exit-record.ts +13 -1
  102. package/scripts/agent/api-auth.ts +41 -0
  103. package/scripts/agent/api-outage.ts +1 -1
  104. package/scripts/auto-ok/auto-ok-cli.ts +14 -16
  105. package/scripts/auto-ok/auto-ok-judge-read.ts +12 -3
  106. package/scripts/auto-ok/auto-ok-judge-write.ts +46 -19
  107. package/scripts/auto-ok/auto-ok-judge.ts +13 -2
  108. package/scripts/auto-ok/auto-ok-main.ts +17 -0
  109. package/scripts/backlog/backlog-arrival.ts +14 -3
  110. package/scripts/backlog/backlog-budget-cli.ts +7 -33
  111. package/scripts/backlog/backlog-budget-main.ts +16 -0
  112. package/scripts/backlog/backlog-budget.ts +2 -3
  113. package/scripts/backlog/backlog-defect-priority.ts +4 -3
  114. package/scripts/backlog/backlog-drive-adopt.ts +67 -0
  115. package/scripts/backlog/backlog-drive-args.ts +4 -5
  116. package/scripts/backlog/backlog-drive-cli.ts +113 -28
  117. package/scripts/backlog/backlog-drive-hold.ts +162 -0
  118. package/scripts/backlog/backlog-drive-idle.ts +151 -0
  119. package/scripts/backlog/backlog-drive-judge.ts +25 -0
  120. package/scripts/backlog/backlog-drive-memory.ts +126 -0
  121. package/scripts/backlog/backlog-drive-named-offer.ts +5 -10
  122. package/scripts/backlog/backlog-drive-named.ts +53 -6
  123. package/scripts/backlog/backlog-drive-offer-argv.ts +3 -8
  124. package/scripts/backlog/backlog-drive-paused.ts +169 -0
  125. package/scripts/backlog/backlog-drive-restore.ts +30 -7
  126. package/scripts/backlog/backlog-drive-seats.ts +18 -8
  127. package/scripts/backlog/backlog-drive-token-handling.ts +38 -0
  128. package/scripts/backlog/backlog-drive.ts +79 -75
  129. package/scripts/backlog/backlog-next-main.ts +16 -0
  130. package/scripts/backlog/backlog-next-shared.ts +73 -0
  131. package/scripts/backlog/backlog-next.ts +48 -16
  132. package/scripts/backlog/backlog-occupied.ts +52 -39
  133. package/scripts/backlog/backlog-offer-cli.ts +6 -21
  134. package/scripts/backlog/backlog-offer-exclude.ts +15 -0
  135. package/scripts/backlog/backlog-offer-main.ts +12 -0
  136. package/scripts/backlog/backlog-offer.ts +36 -3
  137. package/scripts/backlog/backlog-overlap.ts +22 -4
  138. package/scripts/backlog/backlog-plan-read.ts +6 -2
  139. package/scripts/backlog/backlog-plan.ts +18 -4
  140. package/scripts/backlog/backlog-pool.ts +10 -10
  141. package/scripts/backlog/backlog-rank.ts +10 -2
  142. package/scripts/backlog/backlog-ready.ts +112 -30
  143. package/scripts/backlog/backlog-stalled-detect.ts +109 -36
  144. package/scripts/backlog/backlog-stalled.ts +52 -16
  145. package/scripts/backlog/backlog-wait-cause.ts +86 -0
  146. package/scripts/backlog/backlog-waves.ts +39 -13
  147. package/scripts/backlog/backlogrun-args.ts +19 -7
  148. package/scripts/backlog/backlogrun-cli.ts +19 -5
  149. package/scripts/backlog/backlogrun-launch.ts +6 -0
  150. package/scripts/backlog/backlogrun-restart.ts +97 -0
  151. package/scripts/backlog/backlogrun-stop.ts +79 -7
  152. package/scripts/behavior/behavior-cli.ts +2 -2
  153. package/scripts/behavior/behavior-rules.ts +47 -24
  154. package/scripts/build/build-bin.ts +2 -16
  155. package/scripts/build/build-claude-md.ts +0 -7
  156. package/scripts/build/build-commands.ts +0 -13
  157. package/scripts/build/build-hooks.ts +49 -48
  158. package/scripts/build/hook-bundle-stamp.ts +29 -11
  159. package/scripts/build/local-bin.ts +1 -1
  160. package/scripts/cases/cases-cli.ts +25 -13
  161. package/scripts/cases/cases-interaction-scan.ts +134 -0
  162. package/scripts/cases/cases-interaction.ts +183 -0
  163. package/scripts/cases/cases-logic.ts +39 -6
  164. package/scripts/ci/pr-classification-main.ts +18 -0
  165. package/scripts/ci/pr-classification.ts +10 -17
  166. package/scripts/clone/clone-scan.ts +1 -1
  167. package/scripts/cost-runtime/cost-blocks.ts +22 -37
  168. package/scripts/cost-runtime/cost-cli.ts +31 -14
  169. package/scripts/cost-runtime/cost-main.ts +12 -0
  170. package/scripts/cost-runtime/cost-transcript.ts +1 -0
  171. package/scripts/delegation/delegation-policy.ts +17 -4
  172. package/scripts/delegation/duplicate-read-guard.ts +0 -8
  173. package/scripts/delegation/investigation-guard.ts +0 -8
  174. package/scripts/delegation/investigation-reads.ts +3 -4
  175. package/scripts/dependabot/dependabot-cooldown.ts +194 -0
  176. package/scripts/discovery/repo-discovery.ts +24 -6
  177. package/scripts/doctor/doctor-consumer.ts +2 -5
  178. package/scripts/document/document-byte-budget.ts +8 -6
  179. package/scripts/document/document-scan.ts +1 -1
  180. package/scripts/document/document-section-cli.ts +0 -8
  181. package/scripts/document/document-section-main.ts +12 -0
  182. package/scripts/epic/epic-audit-cli.ts +12 -6
  183. package/scripts/epic/epic-bundle-apply.ts +137 -0
  184. package/scripts/epic/epic-bundle-cli.ts +32 -121
  185. package/scripts/epic/epic-bundle-format.ts +116 -0
  186. package/scripts/epic/epic-bundle-main.ts +17 -0
  187. package/scripts/epic/epic-busy.ts +5 -12
  188. package/scripts/epic/epic-classify.ts +24 -15
  189. package/scripts/epic/epic-cli-argv.ts +31 -0
  190. package/scripts/epic/epic-cli-decide.ts +42 -0
  191. package/scripts/epic/epic-cli.ts +6 -38
  192. package/scripts/epic/epic-close.ts +112 -55
  193. package/scripts/epic/epic-cross-repo.ts +4 -7
  194. package/scripts/epic/epic-decide.ts +119 -0
  195. package/scripts/epic/epic-decision.ts +9 -0
  196. package/scripts/epic/epic-fetch.ts +4 -0
  197. package/scripts/epic/epic-graph.ts +2 -0
  198. package/scripts/epic/epic-issue.ts +5 -1
  199. package/scripts/epic/epic-label-age.ts +1 -1
  200. package/scripts/epic/epic-lane-offer.ts +39 -4
  201. package/scripts/epic/epic-next-main.ts +24 -0
  202. package/scripts/epic/epic-next.ts +6 -24
  203. package/scripts/epic/epic-outside-blocker.ts +6 -2
  204. package/scripts/epic/epic-parse.ts +9 -3
  205. package/scripts/epic/epic-read.ts +1 -0
  206. package/scripts/epic/epic-reconcile.ts +39 -0
  207. package/scripts/epic/epic-run.ts +10 -1
  208. package/scripts/epic/epic-solo.ts +50 -14
  209. package/scripts/epic/epic.ts +41 -7
  210. package/scripts/exports/unused-members-cli.ts +2 -2
  211. package/scripts/followup/followup-checks-event.ts +8 -3
  212. package/scripts/followup/followup-coderabbit-wait.ts +82 -0
  213. package/scripts/followup/followup-review-gates.ts +81 -0
  214. package/scripts/followup/git-followup-stages.ts +13 -3
  215. package/scripts/followup/git-followup-workflow.ts +19 -66
  216. package/scripts/followup/git-pr-followup-wrapup.ts +9 -14
  217. package/scripts/followup/git-pr-followup.ts +36 -8
  218. package/scripts/fresh-machine/fresh-machine-cli.ts +1 -1
  219. package/scripts/fresh-machine/fresh-machine-run.ts +8 -8
  220. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +1 -1
  221. package/scripts/gate/busy-average.ts +58 -0
  222. package/scripts/gate/check-cpu.ts +60 -0
  223. package/scripts/gate/check-inputs.ts +39 -95
  224. package/scripts/gate/check-reuse.ts +33 -54
  225. package/scripts/gate/command-memory.ts +192 -0
  226. package/scripts/gate/core-admission.ts +218 -28
  227. package/scripts/gate/core-budget-timing.ts +37 -0
  228. package/scripts/gate/core-budget.ts +80 -98
  229. package/scripts/gate/core-wait-record.ts +48 -0
  230. package/scripts/gate/core-wait.ts +37 -5
  231. package/scripts/gate/core-weights.ts +86 -0
  232. package/scripts/gate/free-cores.ts +27 -4
  233. package/scripts/gate/gate-ledger.ts +32 -4
  234. package/scripts/gate/gate-plan.ts +41 -34
  235. package/scripts/gate/gate-report.ts +14 -2
  236. package/scripts/gate/gate-run-steps.ts +53 -8
  237. package/scripts/gate/gate-skip.ts +12 -2
  238. package/scripts/gate/gate-steps.ts +12 -1
  239. package/scripts/gate/input-fingerprint.ts +42 -0
  240. package/scripts/gate/machine-capacity.ts +65 -31
  241. package/scripts/gate/moved-paths.ts +67 -0
  242. package/scripts/gate/project-checks.ts +5 -12
  243. package/scripts/gate/scoped-green.ts +12 -8
  244. package/scripts/gate/since-green.ts +62 -0
  245. package/scripts/gate/toolchain-inputs.ts +115 -0
  246. package/scripts/gate/verification-gate.ts +27 -24
  247. package/scripts/gate/verification-inputs.ts +250 -0
  248. package/scripts/gh/gh-author-association.ts +96 -9
  249. package/scripts/gh/git-ai-review-scan.ts +4 -2
  250. package/scripts/gh/git-gh-api-path.ts +15 -0
  251. package/scripts/gh/git-gh-branch-rules.ts +73 -0
  252. package/scripts/gh/git-gh-conditional.ts +5 -2
  253. package/scripts/gh/git-gh-issue-read.ts +5 -1
  254. package/scripts/gh/git-gh-issue-write.ts +67 -29
  255. package/scripts/gh/git-gh-issue.ts +7 -3
  256. package/scripts/gh/git-gh-poll-read.ts +89 -0
  257. package/scripts/gh/git-gh-pr-auto-merge.ts +8 -3
  258. package/scripts/gh/git-gh-pr-rest.ts +1 -1
  259. package/scripts/gh/git-gh-pr-snapshot.ts +33 -20
  260. package/scripts/gh/git-gh-pr.ts +27 -15
  261. package/scripts/gh/git-pr-checks-eval.ts +39 -7
  262. package/scripts/gh/git-pr-checks-parse.ts +39 -9
  263. package/scripts/gh/git-pr-merge-checked.ts +80 -0
  264. package/scripts/git/base-tree.ts +19 -2
  265. package/scripts/git/changed-file-scope.ts +6 -4
  266. package/scripts/git/changed-paths.ts +18 -1
  267. package/scripts/git/git-diff-reads.ts +27 -2
  268. package/scripts/git/git-grep-hits.ts +85 -0
  269. package/scripts/git/git-location-environment.ts +1 -1
  270. package/scripts/git/git-merge-conflicts.ts +83 -0
  271. package/scripts/git/git-preflight.ts +37 -12
  272. package/scripts/git/git-push-transport.ts +1 -2
  273. package/scripts/git/git-schemas.ts +17 -7
  274. package/scripts/git/git-spawn.ts +1 -2
  275. package/scripts/git/git-status.ts +4 -4
  276. package/scripts/git/main-merge-main.ts +12 -0
  277. package/scripts/git/main-merge-regenerate.ts +2 -2
  278. package/scripts/git/main-merge.ts +25 -9
  279. package/scripts/git/main-sync-main.ts +12 -0
  280. package/scripts/git/main-sync.ts +0 -9
  281. package/scripts/git/stash/git-stash.ts +27 -4
  282. package/scripts/git/stash/{stash-pop-args.ts → stash-args.ts} +13 -10
  283. package/scripts/git/stash/stash-pop-cli.ts +6 -12
  284. package/scripts/git/stash/stash-pop-main.ts +12 -0
  285. package/scripts/git/stash/stash-push-cli.ts +76 -0
  286. package/scripts/git/stash/stash-push-main.ts +12 -0
  287. package/scripts/hooks/batch-guard.ts +0 -8
  288. package/scripts/hooks/check-commit-message-main.ts +8 -0
  289. package/scripts/hooks/check-commit-message.ts +4 -7
  290. package/scripts/hooks/format-edited-file.ts +8 -24
  291. package/scripts/hooks/pre-commit-lint.ts +30 -3
  292. package/scripts/hooks/pre-push-unit.ts +4 -2
  293. package/scripts/hooks/pretool-guard-cli.ts +1 -8
  294. package/scripts/hooks/pretool-guard.ts +32 -19
  295. package/scripts/hooks/reserved-run.ts +67 -9
  296. package/scripts/hooks/run-hook.sh +13 -4
  297. package/scripts/hooks/shell-rules-notice.ts +37 -0
  298. package/scripts/hooks/stop-actions.ts +2 -21
  299. package/scripts/hooks/stop-guard.ts +13 -9
  300. package/scripts/init/hook-command-rewrite.ts +19 -5
  301. package/scripts/init/hook-launch.ts +15 -17
  302. package/scripts/init/init-actions.ts +0 -6
  303. package/scripts/init/init-ai-copy.ts +10 -36
  304. package/scripts/init/init-bootstrap.ts +9 -8
  305. package/scripts/init/init-dry-run-report.ts +1 -1
  306. package/scripts/init/init-dry-run.ts +1 -1
  307. package/scripts/init/init-file-action.ts +7 -9
  308. package/scripts/init/init-logic-json-merge.ts +2 -2
  309. package/scripts/init/init-logic-migrate.ts +9 -82
  310. package/scripts/init/init-logic.ts +3 -2
  311. package/scripts/init/init-main.ts +12 -0
  312. package/scripts/init/init.ts +5 -12
  313. package/scripts/init/kit-development-versions.ts +3 -7
  314. package/scripts/init/kit-written-paths.ts +2 -2
  315. package/scripts/init/project-profile.ts +5 -4
  316. package/scripts/init/tsconfig-preset-migration.ts +2 -1
  317. package/scripts/init/vscode-tasks.ts +1 -1
  318. package/scripts/issue/defect-origin-cli.ts +106 -0
  319. package/scripts/issue/defect-origin-line.ts +60 -0
  320. package/scripts/issue/defect-origin-main.ts +11 -0
  321. package/scripts/issue/defect-origin.ts +114 -0
  322. package/scripts/issue/defect-rate-cli.ts +34 -78
  323. package/scripts/issue/defect-rate.ts +0 -16
  324. package/scripts/issue/defect-report-cli.ts +128 -0
  325. package/scripts/issue/defect-report-format.ts +56 -0
  326. package/scripts/issue/defect-report-main.ts +11 -0
  327. package/scripts/issue/defect-report.ts +160 -0
  328. package/scripts/issue/expected-effect-lint.ts +1 -0
  329. package/scripts/issue/issue-already-done-cli.ts +62 -0
  330. package/scripts/issue/issue-body-or-comment.ts +40 -0
  331. package/scripts/issue/issue-cite-cli.ts +0 -9
  332. package/scripts/issue/issue-cite-main.ts +12 -0
  333. package/scripts/issue/issue-classification.ts +12 -7
  334. package/scripts/issue/issue-comment-cli.ts +10 -24
  335. package/scripts/issue/issue-comment-main.ts +12 -0
  336. package/scripts/issue/issue-evidence-exit.ts +100 -0
  337. package/scripts/issue/issue-file-cli.ts +29 -7
  338. package/scripts/issue/issue-file.ts +19 -19
  339. package/scripts/issue/issue-fold-cli.ts +2 -11
  340. package/scripts/issue/issue-fold-main.ts +12 -0
  341. package/scripts/issue/issue-labels.ts +81 -90
  342. package/scripts/issue/issue-lint-cli.ts +2 -10
  343. package/scripts/issue/issue-lint-main.ts +12 -0
  344. package/scripts/issue/issue-measured-cli.ts +56 -0
  345. package/scripts/issue/issue-merged.ts +19 -2
  346. package/scripts/issue/issue-not-before-label.ts +135 -0
  347. package/scripts/issue/issue-not-before.ts +111 -0
  348. package/scripts/issue/issue-number-shape.ts +15 -1
  349. package/scripts/issue/issue-park.ts +28 -0
  350. package/scripts/issue/issue-plan-cli.ts +151 -0
  351. package/scripts/issue/issue-priority.ts +151 -0
  352. package/scripts/issue/issue-rank.ts +7 -1
  353. package/scripts/issue/issue-read-cli.ts +3 -10
  354. package/scripts/issue/issue-read-main.ts +12 -0
  355. package/scripts/issue/issue-read.ts +29 -5
  356. package/scripts/issue/issue-release-cli.ts +0 -10
  357. package/scripts/issue/issue-release-main.ts +13 -0
  358. package/scripts/issue/issue-release.ts +7 -12
  359. package/scripts/issue/issue-sample-gate.ts +192 -0
  360. package/scripts/issue/issue-sample-source.ts +76 -0
  361. package/scripts/issue/issue-scout-cli.ts +0 -11
  362. package/scripts/issue/issue-scout-main.ts +14 -0
  363. package/scripts/issue/issue-state-cli.ts +0 -10
  364. package/scripts/issue/issue-state-main.ts +12 -0
  365. package/scripts/issue/issue-watch-diff.ts +56 -15
  366. package/scripts/issue/issue-watch.ts +2 -1
  367. package/scripts/issue/issue-wip.ts +2 -7
  368. package/scripts/issue/measure-rerun-cli.ts +13 -8
  369. package/scripts/issue/plan-consumers-cli.ts +39 -0
  370. package/scripts/issue/plan-consumers-main.ts +11 -0
  371. package/scripts/issue/plan-consumers-section.ts +55 -0
  372. package/scripts/issue/plan-consumers.ts +127 -0
  373. package/scripts/josh/agent-session-environment.ts +1 -1
  374. package/scripts/josh/command-usage.ts +15 -43
  375. package/scripts/josh/file-map-stamp.ts +49 -16
  376. package/scripts/josh/hook-decision.ts +32 -20
  377. package/scripts/josh/josh-command-map.ts +4 -1
  378. package/scripts/josh/josh-command-types.ts +12 -6
  379. package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
  380. package/scripts/josh/josh-commands-ai.ts +157 -158
  381. package/scripts/josh/josh-commands-backlog.ts +82 -16
  382. package/scripts/josh/josh-commands-clone.ts +1 -0
  383. package/scripts/josh/josh-commands-development.ts +111 -71
  384. package/scripts/josh/josh-commands-document.ts +43 -1
  385. package/scripts/josh/josh-commands-epic.ts +171 -0
  386. package/scripts/josh/josh-commands-hooks.ts +25 -2
  387. package/scripts/josh/josh-commands-issue-write.ts +181 -0
  388. package/scripts/josh/josh-commands-issue.ts +124 -24
  389. package/scripts/josh/josh-commands-lane.ts +103 -2
  390. package/scripts/josh/josh-commands-lint.ts +19 -8
  391. package/scripts/josh/josh-commands-maintenance.ts +112 -4
  392. package/scripts/josh/josh-commands-pause.ts +29 -0
  393. package/scripts/josh/josh-commands-progress.ts +87 -0
  394. package/scripts/josh/josh-commands-project.ts +138 -9
  395. package/scripts/josh/josh-commands-review.ts +124 -0
  396. package/scripts/josh/josh-commands-run.ts +211 -23
  397. package/scripts/josh/josh-commands-ship.ts +169 -0
  398. package/scripts/josh/josh-commands-split.ts +9 -0
  399. package/scripts/josh/josh-commands-versioning.ts +49 -2
  400. package/scripts/josh/josh-commands-workflow.ts +144 -6
  401. package/scripts/josh/josh-logic.ts +6 -13
  402. package/scripts/josh/package-directory.ts +2 -4
  403. package/scripts/josh/process-identity.ts +13 -4
  404. package/scripts/josh/session-language-cli.ts +4 -8
  405. package/scripts/josh/session-language-main.ts +13 -0
  406. package/scripts/josh/session-language.ts +6 -1
  407. package/scripts/josh/shared-cache.ts +90 -0
  408. package/scripts/josh/stamp-file.ts +9 -15
  409. package/scripts/lane/lane-await.ts +51 -12
  410. package/scripts/lane/lane-cache.ts +5 -30
  411. package/scripts/lane/lane-capacity.ts +14 -23
  412. package/scripts/lane/lane-check-stats.ts +62 -21
  413. package/scripts/lane/lane-child-invocation.ts +8 -0
  414. package/scripts/lane/lane-cli.ts +15 -5
  415. package/scripts/lane/lane-close.ts +86 -18
  416. package/scripts/lane/lane-core-wait-stats.ts +66 -0
  417. package/scripts/lane/lane-dispatch.ts +24 -3
  418. package/scripts/lane/lane-gap-stats.ts +156 -0
  419. package/scripts/lane/lane-handoff.ts +69 -1
  420. package/scripts/lane/lane-held-stats.ts +129 -0
  421. package/scripts/lane/lane-install.ts +4 -11
  422. package/scripts/lane/lane-launch-cli.ts +0 -9
  423. package/scripts/lane/lane-launch-main.ts +12 -0
  424. package/scripts/lane/lane-ledger-schema.ts +266 -0
  425. package/scripts/lane/lane-ledger.ts +92 -123
  426. package/scripts/lane/lane-limit-cli.ts +12 -1
  427. package/scripts/lane/lane-measure-cli.ts +57 -11
  428. package/scripts/lane/lane-open.ts +9 -1
  429. package/scripts/lane/lane-parked.ts +3 -3
  430. package/scripts/lane/lane-pause-cli.ts +130 -0
  431. package/scripts/lane/lane-pause.ts +158 -0
  432. package/scripts/lane/lane-process-table.ts +166 -0
  433. package/scripts/lane/lane-reap-settle.ts +124 -0
  434. package/scripts/lane/lane-reap.ts +50 -15
  435. package/scripts/lane/lane-registry.ts +24 -3
  436. package/scripts/lane/lane-residents.ts +162 -0
  437. package/scripts/lane/lane-restart.ts +22 -2
  438. package/scripts/lane/lane-round-two-stats.ts +49 -0
  439. package/scripts/lane/lane-sampler.ts +4 -0
  440. package/scripts/lane/lane-session-action.ts +19 -5
  441. package/scripts/lane/lane-session-broker.ts +102 -21
  442. package/scripts/lane/lane-snapshot-trace.ts +84 -0
  443. package/scripts/lane/lane-spans.ts +51 -0
  444. package/scripts/lane/lane-spent.ts +6 -3
  445. package/scripts/lane/lane-stage-stats.ts +7 -2
  446. package/scripts/lane/lane-state.ts +302 -0
  447. package/scripts/lane/lane-stats.ts +58 -4
  448. package/scripts/lane/lane-stop-stats.ts +113 -37
  449. package/scripts/lane/lane-test-related-stats.ts +127 -0
  450. package/scripts/lane/lane-transcript-calls.ts +145 -0
  451. package/scripts/lane/lane-transcript-stats.ts +168 -0
  452. package/scripts/lane/lane-vacant.ts +13 -3
  453. package/scripts/lane/lane-withdraw-cli.ts +5 -4
  454. package/scripts/lane/lane-withdraw.ts +50 -49
  455. package/scripts/lane/process-directories.ts +70 -0
  456. package/scripts/lane/process-lane-marks.ts +94 -0
  457. package/scripts/lib/atomic-write.ts +62 -0
  458. package/scripts/lib/buffered-process.ts +12 -5
  459. package/scripts/lib/cli-flags.ts +53 -0
  460. package/scripts/lib/figure-format.ts +63 -0
  461. package/scripts/lib/json-value.ts +9 -1
  462. package/scripts/lib/package-manifest.ts +35 -0
  463. package/scripts/lib/read-file.ts +3 -1
  464. package/scripts/lib/stamped-memo.ts +63 -0
  465. package/scripts/lib/stdout-on-stderr.ts +24 -0
  466. package/scripts/lib/timeouts.ts +9 -0
  467. package/scripts/lib/transcript-record.ts +91 -0
  468. package/scripts/lines/effective-limit.ts +1 -1
  469. package/scripts/lint/eslint-cache-dependencies.ts +145 -0
  470. package/scripts/lint/eslint-daemon.ts +265 -0
  471. package/scripts/lint/format.ts +11 -2
  472. package/scripts/lint/import-graph.ts +279 -0
  473. package/scripts/lint/lint-gate-scope.ts +102 -0
  474. package/scripts/lint/lint-parallel-main.ts +19 -0
  475. package/scripts/lint/lint-parallel.ts +62 -30
  476. package/scripts/lint/lint-related-scope.ts +30 -24
  477. package/scripts/lint/lint-related.ts +38 -6
  478. package/scripts/notify/confirmation-options.ts +1 -2
  479. package/scripts/notify/telegram-notify.ts +20 -20
  480. package/scripts/notify/telegram-test-logic.ts +0 -1
  481. package/scripts/notify/telegram-test-main.ts +8 -0
  482. package/scripts/notify/telegram-test.ts +2 -6
  483. package/scripts/observations/observation-ledger.ts +13 -0
  484. package/scripts/observations/observations-flush-landing.ts +5 -3
  485. package/scripts/observations/observations-flush.ts +6 -1
  486. package/scripts/overrides/overrides-check.ts +2 -5
  487. package/scripts/overrides/overrides-files.ts +2 -1
  488. package/scripts/overrides/overrides-logic.ts +3 -6
  489. package/scripts/package/verify-optional-eslint-install.ts +8 -6
  490. package/scripts/propagate/propagate-publish.ts +2 -7
  491. package/scripts/propagate/propagate-targets.ts +4 -12
  492. package/scripts/refactor/import-graph.ts +9 -7
  493. package/scripts/release/github-release-runs.ts +17 -6
  494. package/scripts/release/release-approval-prune.ts +18 -0
  495. package/scripts/release/release-history.ts +1 -3
  496. package/scripts/release/release-progress.ts +42 -22
  497. package/scripts/release/release-publish-run.ts +39 -0
  498. package/scripts/release/release-publish.ts +6 -6
  499. package/scripts/release/release-scope-cli.ts +0 -10
  500. package/scripts/release/release-scope-main.ts +12 -0
  501. package/scripts/repo/repo-setting.ts +3 -6
  502. package/scripts/repo/required-checks-logic.ts +6 -15
  503. package/scripts/report/report-format-reference.ts +2 -0
  504. package/scripts/report/report-labels.ts +155 -0
  505. package/scripts/report/report-lint-cli.ts +3 -0
  506. package/scripts/report/report-lint.ts +85 -110
  507. package/scripts/report/report-template-cli.ts +59 -0
  508. package/scripts/report/report-template.ts +112 -0
  509. package/scripts/review/acceptance-map.ts +1 -0
  510. package/scripts/review/removed-tests-check.ts +86 -0
  511. package/scripts/review/removed-tests.ts +149 -0
  512. package/scripts/review/review-brief-cli.ts +81 -15
  513. package/scripts/review/review-brief-main.ts +12 -0
  514. package/scripts/review/review-brief.ts +31 -3
  515. package/scripts/review/review-code-tree.ts +10 -6
  516. package/scripts/review/review-comment-round.ts +26 -8
  517. package/scripts/review/review-finding-ledger.ts +30 -15
  518. package/scripts/review/review-interaction.ts +94 -0
  519. package/scripts/review/review-readers-scan.ts +163 -0
  520. package/scripts/review/review-record-cli.ts +69 -30
  521. package/scripts/review/review-record-main.ts +12 -0
  522. package/scripts/review/review-round-one-blobs.ts +221 -0
  523. package/scripts/review/review-round2-cli.ts +49 -12
  524. package/scripts/review/review-round2.ts +80 -12
  525. package/scripts/review/review-stamps.ts +19 -1
  526. package/scripts/review/review-stop-log.ts +96 -0
  527. package/scripts/review/review-stops-cli.ts +85 -0
  528. package/scripts/review/review-tree.ts +6 -17
  529. package/scripts/review/review-untouched-readers.ts +146 -0
  530. package/scripts/review/test-titles.ts +118 -0
  531. package/scripts/rules/agent-model.ts +8 -0
  532. package/scripts/rules/bash-triggers.ts +46 -3
  533. package/scripts/rules/decision-oracle-batch.ts +9 -1
  534. package/scripts/rules/decision-oracle.ts +2 -2
  535. package/scripts/rules/delivered-rules.ts +80 -2
  536. package/scripts/rules/destructive-command.ts +8 -1
  537. package/scripts/rules/direct-filing.ts +10 -2
  538. package/scripts/rules/direct-issue-comment.ts +117 -0
  539. package/scripts/rules/direct-pr-create.ts +69 -3
  540. package/scripts/rules/early-heartbeat.ts +2 -1
  541. package/scripts/rules/file-body.ts +7 -0
  542. package/scripts/rules/filing-cap.ts +7 -0
  543. package/scripts/rules/git-argv.ts +72 -14
  544. package/scripts/rules/git-force.ts +12 -2
  545. package/scripts/rules/guard-remedy.ts +4 -0
  546. package/scripts/rules/implementation-cut-verdict.ts +1 -1
  547. package/scripts/rules/implementation-cut.ts +11 -3
  548. package/scripts/rules/index-guard.ts +8 -1
  549. package/scripts/rules/issue-comments.ts +9 -1
  550. package/scripts/rules/josh-git-bare.ts +7 -0
  551. package/scripts/rules/lane-background.ts +67 -25
  552. package/scripts/rules/lane-carry-conflict.ts +6 -0
  553. package/scripts/rules/lane-direct-tool.ts +74 -0
  554. package/scripts/rules/lane-interactive-ask.ts +9 -2
  555. package/scripts/rules/lane-park.ts +45 -23
  556. package/scripts/rules/lane-split-park.ts +10 -2
  557. package/scripts/rules/lane-switch-main.ts +7 -0
  558. package/scripts/rules/oracle-consulted.ts +10 -0
  559. package/scripts/rules/oracle-firing.ts +1 -0
  560. package/scripts/rules/permission-guards.ts +3 -0
  561. package/scripts/rules/piped-verification.ts +1 -1
  562. package/scripts/rules/poll-loop.ts +7 -0
  563. package/scripts/rules/pr-merge.ts +123 -0
  564. package/scripts/rules/protected-files.ts +32 -5
  565. package/scripts/rules/raw-field-body.ts +6 -0
  566. package/scripts/rules/rule-body-guard.ts +8 -0
  567. package/scripts/rules/rule-list.ts +9 -28
  568. package/scripts/rules/rule-value-cache.ts +4 -9
  569. package/scripts/rules/rule-value-cli.ts +51 -32
  570. package/scripts/rules/rule-value.ts +1 -1
  571. package/scripts/rules/shell-segments.ts +35 -0
  572. package/scripts/rules/stop-rule-rows.ts +64 -0
  573. package/scripts/rules/stop-rules.ts +3 -4
  574. package/scripts/rules/test-declared-commit.ts +11 -1
  575. package/scripts/rules/third-party-write.ts +7 -0
  576. package/scripts/rules/timed-rerun.ts +69 -0
  577. package/scripts/rules/worktree-guard.ts +13 -3
  578. package/scripts/run/board/run-board-app-name.ts +23 -0
  579. package/scripts/run/board/run-board-cli.ts +65 -32
  580. package/scripts/run/board/run-board-earlier.ts +94 -0
  581. package/scripts/run/board/run-board-ending-reason.ts +67 -0
  582. package/scripts/run/board/run-board-estimate-schedule.ts +103 -0
  583. package/scripts/run/board/run-board-estimate.ts +98 -0
  584. package/scripts/run/board/run-board-fit.ts +153 -36
  585. package/scripts/run/board/run-board-fold.ts +123 -0
  586. package/scripts/run/board/run-board-fresh.ts +2 -2
  587. package/scripts/run/board/run-board-gather-live.ts +29 -0
  588. package/scripts/run/board/run-board-gather-thread.ts +189 -0
  589. package/scripts/run/board/run-board-gather-worker.ts +29 -0
  590. package/scripts/run/board/run-board-gather.ts +187 -0
  591. package/scripts/run/board/run-board-github.ts +118 -38
  592. package/scripts/run/board/run-board-header.ts +82 -20
  593. package/scripts/run/board/run-board-keys.ts +58 -0
  594. package/scripts/run/board/run-board-kind.ts +20 -6
  595. package/scripts/run/board/run-board-labels.ts +116 -71
  596. package/scripts/run/board/run-board-lane-state.ts +109 -0
  597. package/scripts/run/board/run-board-lane-time.ts +122 -0
  598. package/scripts/run/board/run-board-layout.ts +239 -60
  599. package/scripts/run/board/run-board-length.ts +52 -0
  600. package/scripts/run/board/run-board-machine.ts +8 -4
  601. package/scripts/run/board/run-board-main.ts +12 -0
  602. package/scripts/run/board/run-board-notes.ts +52 -31
  603. package/scripts/run/board/run-board-now.ts +1 -1
  604. package/scripts/run/board/run-board-operation.ts +15 -33
  605. package/scripts/run/board/run-board-phase.ts +1 -1
  606. package/scripts/run/board/run-board-plan-shared.ts +115 -0
  607. package/scripts/run/board/run-board-plan.ts +55 -3
  608. package/scripts/run/board/run-board-planning.ts +45 -0
  609. package/scripts/run/board/run-board-priority.ts +44 -0
  610. package/scripts/run/board/run-board-process-groups.ts +195 -0
  611. package/scripts/run/board/run-board-read.ts +151 -27
  612. package/scripts/run/board/run-board-reason.ts +235 -51
  613. package/scripts/run/board/run-board-released.ts +35 -0
  614. package/scripts/run/board/run-board-render-checks.ts +39 -5
  615. package/scripts/run/board/run-board-render-condition.ts +96 -0
  616. package/scripts/run/board/run-board-render-drawn.ts +67 -0
  617. package/scripts/run/board/run-board-render-foot.ts +59 -0
  618. package/scripts/run/board/run-board-render-icon.ts +35 -0
  619. package/scripts/run/board/run-board-render-lanes.ts +145 -0
  620. package/scripts/run/board/run-board-render-lead.ts +80 -0
  621. package/scripts/run/board/run-board-render-legend.ts +117 -48
  622. package/scripts/run/board/run-board-render-notes.ts +156 -29
  623. package/scripts/run/board/run-board-render-processes.ts +196 -0
  624. package/scripts/run/board/run-board-render-section.ts +119 -0
  625. package/scripts/run/board/run-board-render-slot.ts +3 -36
  626. package/scripts/run/board/run-board-render-tail.ts +115 -48
  627. package/scripts/run/board/run-board-render-time.ts +56 -0
  628. package/scripts/run/board/run-board-render-title.ts +117 -24
  629. package/scripts/run/board/run-board-render-waits.ts +104 -20
  630. package/scripts/run/board/run-board-render.ts +207 -265
  631. package/scripts/run/board/run-board-roots.ts +54 -0
  632. package/scripts/run/board/run-board-row-yield.ts +9 -4
  633. package/scripts/run/board/run-board-setup.ts +1 -12
  634. package/scripts/run/board/run-board-snapshot.ts +111 -0
  635. package/scripts/run/board/run-board-spin.ts +2 -2
  636. package/scripts/run/board/run-board-state.ts +22 -33
  637. package/scripts/run/board/run-board-status.ts +147 -71
  638. package/scripts/run/board/run-board-thanks-read.ts +2 -2
  639. package/scripts/run/board/run-board-tick.ts +122 -107
  640. package/scripts/run/board/run-board-usage-board.ts +78 -0
  641. package/scripts/run/board/run-board-usage-lanes.ts +113 -0
  642. package/scripts/run/board/run-board-usage-listing.ts +93 -0
  643. package/scripts/run/board/run-board-usage-read.ts +120 -150
  644. package/scripts/run/board/run-board-usage-rusage.ts +19 -7
  645. package/scripts/run/board/run-board-usage-text.ts +139 -51
  646. package/scripts/run/board/run-board-usage-top.ts +102 -0
  647. package/scripts/run/board/run-board-usage.ts +89 -72
  648. package/scripts/run/board/run-board-usual.ts +20 -9
  649. package/scripts/run/carry/run-carry-args.ts +4 -7
  650. package/scripts/run/carry/run-carry-conversation.ts +1 -1
  651. package/scripts/run/carry/run-carry.ts +9 -4
  652. package/scripts/run/cut/run-cut-handoff.ts +2 -2
  653. package/scripts/run/event/run-event-cli.ts +1 -5
  654. package/scripts/run/event/run-event-filed.ts +12 -6
  655. package/scripts/run/event/run-event-follow.ts +2 -3
  656. package/scripts/run/event/run-event-render.ts +6 -10
  657. package/scripts/run/event/run-event-scope.ts +2 -2
  658. package/scripts/run/event/run-event-stream-emit.ts +82 -22
  659. package/scripts/run/event/run-event-stream.ts +34 -8
  660. package/scripts/run/hold/run-hold-adopt.ts +65 -0
  661. package/scripts/run/hold/run-hold-cli.ts +93 -22
  662. package/scripts/run/hold/run-hold-main.ts +12 -0
  663. package/scripts/run/hold/run-hold-member.ts +37 -0
  664. package/scripts/run/hold/run-stop-notify.ts +183 -0
  665. package/scripts/run/merge/run-merge-auth.ts +31 -0
  666. package/scripts/run/merge/run-merge-cli.ts +62 -48
  667. package/scripts/run/merge/run-merge-close.ts +74 -0
  668. package/scripts/run/merge/run-merge-collect.ts +6 -13
  669. package/scripts/run/merge/run-merge-driver.ts +71 -0
  670. package/scripts/run/merge/run-merge-main.ts +12 -0
  671. package/scripts/run/merge/run-merge-outcome.ts +23 -0
  672. package/scripts/run/merge/run-merge-restart.ts +39 -0
  673. package/scripts/run/merge/run-merge-ship.ts +20 -4
  674. package/scripts/run/merge/run-merge-signals.ts +33 -9
  675. package/scripts/run/merge/run-merge-steps.ts +120 -85
  676. package/scripts/run/merge/run-merge.ts +38 -37
  677. package/scripts/run/park/run-park-cli.ts +91 -0
  678. package/scripts/run/park/run-park.ts +88 -0
  679. package/scripts/run/park/run-stalled.ts +68 -0
  680. package/scripts/run/pause/run-pause-cli.ts +73 -0
  681. package/scripts/run/pause/run-pause.ts +251 -0
  682. package/scripts/run/progress/run-progress-cli.ts +4 -12
  683. package/scripts/run/progress/run-progress-clock.ts +1 -1
  684. package/scripts/run/progress/run-progress-config.ts +6 -14
  685. package/scripts/run/progress/run-progress-main.ts +12 -0
  686. package/scripts/run/progress/run-progress.ts +1 -4
  687. package/scripts/run/review/run-review.ts +2 -1
  688. package/scripts/run/run-ending.ts +1 -0
  689. package/scripts/run/run-invocation.ts +5 -6
  690. package/scripts/run/run-liveness-cli.ts +6 -8
  691. package/scripts/run/run-liveness.ts +60 -29
  692. package/scripts/run/run-next.ts +1 -1
  693. package/scripts/run/run-parent-cut-hook.ts +2 -2
  694. package/scripts/run/run-preflight.ts +18 -3
  695. package/scripts/run/run-prep-cli.ts +1 -10
  696. package/scripts/run/run-prep-locate.ts +7 -50
  697. package/scripts/run/run-prep-main.ts +12 -0
  698. package/scripts/run/run-prep.ts +6 -0
  699. package/scripts/run/run-report-cli.ts +101 -13
  700. package/scripts/run/run-report-handoff.ts +114 -0
  701. package/scripts/run/run-step.ts +1 -1
  702. package/scripts/run/run-stranded-detect.ts +13 -0
  703. package/scripts/run/run-watcher-guard-cli.ts +1 -1
  704. package/scripts/run/run-watcher-guard.ts +1 -1
  705. package/scripts/run/ship/run-ship-args.ts +121 -0
  706. package/scripts/run/ship/run-ship-body-draft.ts +110 -0
  707. package/scripts/run/ship/run-ship-cli.ts +63 -140
  708. package/scripts/run/ship/run-ship-detach.ts +19 -8
  709. package/scripts/run/ship/run-ship-infra-retry.ts +59 -0
  710. package/scripts/run/ship/run-ship-next.ts +18 -2
  711. package/scripts/run/ship/run-ship-overlap.ts +42 -5
  712. package/scripts/run/ship/run-ship-place.ts +96 -0
  713. package/scripts/run/ship/run-ship-pre-detach-timed.ts +43 -0
  714. package/scripts/run/ship/run-ship-pre-detach.ts +81 -24
  715. package/scripts/run/ship/run-ship-preflight.ts +137 -32
  716. package/scripts/run/ship/run-ship-probe.ts +11 -3
  717. package/scripts/run/ship/run-ship-relaunch-cap.ts +70 -0
  718. package/scripts/run/ship/run-ship-removed-rows.ts +61 -0
  719. package/scripts/run/ship/run-ship-return.ts +107 -23
  720. package/scripts/run/ship/run-ship-review-steps.ts +105 -151
  721. package/scripts/run/ship/run-ship-review.ts +73 -6
  722. package/scripts/run/ship/run-ship-reviewer.ts +207 -0
  723. package/scripts/run/ship/run-ship-stage.ts +55 -6
  724. package/scripts/run/ship/run-ship-steps.ts +46 -15
  725. package/scripts/run/ship/run-ship-stop-cause.ts +135 -0
  726. package/scripts/run/ship/run-ship-stop-text.ts +11 -6
  727. package/scripts/run/ship/run-ship-sync.ts +43 -6
  728. package/scripts/run/ship/run-ship.ts +30 -2
  729. package/scripts/run/tidy/run-tidy-cli.ts +0 -4
  730. package/scripts/run/tidy/run-tidy-lanes.ts +3 -0
  731. package/scripts/run/tidy/run-tidy-main.ts +8 -0
  732. package/scripts/run/wake/run-wake-cli.ts +119 -100
  733. package/scripts/run/wake/run-wake-code.ts +83 -0
  734. package/scripts/run/wake/run-wake-driver.ts +19 -8
  735. package/scripts/run/wake/run-wake-loop.ts +34 -3
  736. package/scripts/run/wake/run-wake-main.ts +13 -0
  737. package/scripts/run/wake/run-wake-ports.ts +90 -0
  738. package/scripts/run/wake/run-wake-takeover.ts +66 -0
  739. package/scripts/run/wake/run-wake.ts +2 -1
  740. package/scripts/safe-chain/pack-hook.ts +2 -2
  741. package/scripts/safe-chain/preinstall-command.ts +2 -1
  742. package/scripts/safe-chain/project-config.ts +3 -9
  743. package/scripts/security/security-audit-main.ts +8 -0
  744. package/scripts/security/security-audit-provision-logic.ts +0 -11
  745. package/scripts/security/security-audit-provision-main.ts +12 -0
  746. package/scripts/security/security-audit-provision.ts +11 -26
  747. package/scripts/security/security-audit.ts +6 -7
  748. package/scripts/self-sync-guard/self-sync-guard-logic.ts +6 -13
  749. package/scripts/split/split-assess-cli.ts +2 -2
  750. package/scripts/split/split-assess.ts +15 -0
  751. package/scripts/split/split-measure.ts +65 -0
  752. package/scripts/sync/claude-settings-merge.ts +8 -15
  753. package/scripts/sync/directory-copy-guard.ts +4 -9
  754. package/scripts/sync/file-content.ts +78 -8
  755. package/scripts/sync/sync-ai-files.ts +3 -5
  756. package/scripts/sync/sync-configs.ts +11 -23
  757. package/scripts/sync/sync-hook-safety.ts +4 -10
  758. package/scripts/sync/sync-main.ts +11 -0
  759. package/scripts/sync/sync.ts +25 -37
  760. package/scripts/test/test-declared-changed.ts +2 -2
  761. package/scripts/test/test-declared.ts +1 -1
  762. package/scripts/test/test-e2e-guard.ts +25 -1
  763. package/scripts/test/test-e2e-stamp.ts +38 -0
  764. package/scripts/test/test-pinned-logic.ts +145 -0
  765. package/scripts/test/test-pinned-main.ts +78 -0
  766. package/scripts/test/test-pinned.ts +100 -0
  767. package/scripts/test/test-read-map.ts +264 -0
  768. package/scripts/test/test-read-recording.ts +91 -0
  769. package/scripts/test/test-read-trace.ts +148 -0
  770. package/scripts/test/test-red-main.ts +12 -0
  771. package/scripts/test/test-red.ts +12 -30
  772. package/scripts/test/test-related-main.ts +18 -0
  773. package/scripts/test/test-related-record.ts +119 -0
  774. package/scripts/test/test-related-scope.ts +229 -43
  775. package/scripts/test/test-related.ts +300 -22
  776. package/scripts/test/test-unit-guard-main.ts +15 -0
  777. package/scripts/test/test-unit-guard.ts +42 -24
  778. package/scripts/test/unit-count-file.ts +37 -0
  779. package/scripts/test/unit-run-marker.ts +162 -0
  780. package/scripts/test/unit-setup-files.ts +51 -0
  781. package/scripts/test/unit-worker-share.ts +61 -149
  782. package/scripts/test/whole-suite-files.ts +63 -0
  783. package/scripts/time-runtime/time-background.ts +20 -2
  784. package/scripts/time-runtime/time-bundles.ts +4 -3
  785. package/scripts/time-runtime/time-density-hook.ts +8 -6
  786. package/scripts/time-runtime/time-followup-stage.ts +1 -3
  787. package/scripts/time-runtime/time-format.ts +5 -28
  788. package/scripts/time-runtime/time-markers.ts +10 -1
  789. package/scripts/time-runtime/time-shell.ts +97 -10
  790. package/scripts/time-runtime/time-transcript-line.ts +49 -62
  791. package/scripts/uninstall/uninstall.ts +1 -1
  792. package/scripts/version/bump-version-main.ts +12 -0
  793. package/scripts/version/bump-version.ts +25 -25
  794. package/scripts/version/effective-upstream.ts +6 -12
  795. package/scripts/version/latest-corepack.ts +17 -32
  796. package/scripts/version/latest-if-required-cli.ts +93 -0
  797. package/scripts/version/latest-lane-guard-main.ts +8 -0
  798. package/scripts/version/latest-lane-guard.ts +0 -4
  799. package/scripts/version/latest-scope-cli.ts +0 -9
  800. package/scripts/version/latest-scope-main.ts +12 -0
  801. package/scripts/version/latest-update.ts +5 -5
  802. package/scripts/version/npm-registry.ts +44 -6
  803. package/scripts/version/publishable-range-check.ts +5 -16
  804. package/scripts/version/release-age.ts +1 -1
  805. package/scripts/version/release-hold.ts +1 -1
  806. package/scripts/version/release-window.ts +38 -0
  807. package/scripts/version/running-binary.ts +1 -1
  808. package/scripts/version/safe-chain-version-update.ts +3 -8
  809. package/scripts/version/version-targets.ts +6 -28
  810. package/templates/dependabot.yml +29 -0
  811. package/templates/gitignore +4 -1
  812. package/templates/pnpm-workspace.basic.yaml +1 -1
  813. package/templates/sonar-project.properties +3 -2
  814. package/templates/workflows/ci.yml +12 -4
  815. package/templates/workflows/github-release.yml +4 -0
  816. package/tsconfig.sonar.json +1 -1
  817. package/.ncurc.json +0 -3
  818. package/dist/hooks/batch-guard.js +0 -29
  819. package/dist/hooks/chunk-4KKD2UTK.js +0 -66
  820. package/dist/hooks/chunk-6TS2JD6D.js +0 -237
  821. package/dist/hooks/chunk-7DSBJVFH.js +0 -50
  822. package/dist/hooks/chunk-A65Y4YOR.js +0 -79
  823. package/dist/hooks/chunk-CDY4NFQG.js +0 -15
  824. package/dist/hooks/chunk-EFXE6C37.js +0 -81
  825. package/dist/hooks/chunk-GP4IEC4O.js +0 -20
  826. package/dist/hooks/chunk-JP45SOCJ.js +0 -56
  827. package/dist/hooks/chunk-LAOV7NLM.js +0 -45
  828. package/dist/hooks/chunk-M4HGZV7U.js +0 -83
  829. package/dist/hooks/chunk-PF2NZL2A.js +0 -131
  830. package/dist/hooks/chunk-PTICX4OL.js +0 -358
  831. package/dist/hooks/chunk-RT27QRJW.js +0 -6247
  832. package/dist/hooks/chunk-SYOTDYCI.js +0 -3533
  833. package/dist/hooks/chunk-UPUZF3AN.js +0 -279
  834. package/dist/hooks/chunk-WK6SMBIC.js +0 -3180
  835. package/dist/hooks/duplicate-read-guard.js +0 -30
  836. package/dist/hooks/investigation-guard.js +0 -29
  837. package/scripts/backlog/backlog-stalled-cli.ts +0 -30
  838. package/scripts/cost-runtime/cost-format.ts +0 -29
  839. package/scripts/init/basic-path-migration.ts +0 -24
  840. package/scripts/issue/issue-backlinks-cli.ts +0 -93
  841. package/scripts/josh/josh-commands-guard.ts +0 -38
  842. package/scripts/josh/josh-usage-automation.ts +0 -121
  843. package/scripts/josh/josh-usage-backlog.ts +0 -180
  844. package/scripts/josh/josh-usage-developer.ts +0 -230
  845. package/scripts/josh/josh-usage-hooks.ts +0 -38
  846. package/scripts/josh/josh-usage-issue.ts +0 -205
  847. package/scripts/josh/josh-usage-review.ts +0 -101
  848. package/scripts/josh/josh-usage-run.ts +0 -252
  849. package/scripts/josh/josh-usage-session.ts +0 -238
  850. package/scripts/josh/josh-usage-workflow.ts +0 -212
  851. package/scripts/lint/cross-file-recheck.ts +0 -155
  852. package/scripts/registry-migration/migrate-logic.ts +0 -237
  853. package/scripts/registry-migration/migrate.ts +0 -292
  854. package/scripts/registry-migration/user-npmrc.ts +0 -15
  855. package/scripts/rules/rule-guard.ts +0 -23
  856. package/scripts/rules/rule-registry-rows.ts +0 -292
  857. package/scripts/rules/rule-registry.ts +0 -112
  858. package/scripts/run/run-stranded-cli.ts +0 -27
@@ -1,12 +1,12 @@
1
1
  import { json_value } from '#scripts/lib/json-value'
2
+ import { direct_pr_create } from '#scripts/rules/direct-pr-create'
2
3
  import { time_shell } from '#scripts/time-runtime/time-shell'
3
4
  import type { Block, TranscriptLine } from '#scripts/time-runtime/time-transcript-line'
4
5
  import type { Assertion, Finding } from './behavior-assertion'
5
6
 
6
- // The behavior assertions checked against recorded transcripts. This is the
7
- // **seed set** — the issue's own plan is to land one rule that is green across the recorded corpus,
8
- // then add more one at a time, each verified green before it joins. Starting with many would land a
9
- // wall of red that says nothing about which behavior actually regressed.
7
+ // The behavior assertions checked against recorded transcripts. Rules join one at a time, each
8
+ // verified green across the recorded corpus first — starting with many would land a wall of red that
9
+ // says nothing about which behavior actually regressed.
10
10
 
11
11
  const BASH_TOOL = 'Bash'
12
12
  const TOOL_USE = 'tool_use'
@@ -98,46 +98,69 @@ function denied_call_ids(lines: ReadonlyArray<TranscriptLine>): ReadonlySet<stri
98
98
  )
99
99
  }
100
100
 
101
- // The direct index mutations one transcript line ran, each as a finding at that line's position. A
102
- // line is one assistant content block, so its position is a place a reader can open in the file.
103
- function line_mutations(
101
+ // The Bash calls that ran on one transcript line and broke the rule, each as a finding at that line's
102
+ // position. A line is one assistant content block, so its position is a place a reader can open.
103
+ function line_findings(
104
104
  line: TranscriptLine,
105
- index: number,
105
+ position: number,
106
106
  denied_ids: ReadonlySet<string>,
107
+ rule: BashRule,
107
108
  ): ReadonlyArray<Finding> {
108
109
  return line.blocks
109
110
  .filter((block) => !denied_ids.has(block.id))
110
111
  .map((block) => command_of(block))
111
- .filter((command): command is string => command !== undefined && is_index_mutation(command))
112
- .map((command) => ({
113
- assertion: INDEX_ASSERTION_NAME,
114
- position: index + FIRST_POSITION_OFFSET,
115
- detail: command,
116
- }))
112
+ .filter((command): command is string => command !== undefined && rule.is_violation(command))
113
+ .map((command) => ({ assertion: rule.name, position, detail: command }))
117
114
  }
118
115
 
119
- function scan_index_mutation(lines: ReadonlyArray<TranscriptLine>): ReadonlyArray<Finding> {
120
- const denied_ids = denied_call_ids(lines)
116
+ interface BashRule {
117
+ name: string
118
+ describe: string
119
+ is_violation: (command: string) => boolean
120
+ }
121
+
122
+ // One assertion over the Bash calls a run actually executed: a call the permission layer or a
123
+ // PreToolUse hook refused never ran, so it breaks nothing.
124
+ function bash_assertion(rule: BashRule): Assertion {
125
+ function scan(lines: ReadonlyArray<TranscriptLine>): ReadonlyArray<Finding> {
126
+ const denied_ids = denied_call_ids(lines)
127
+
128
+ return lines.flatMap((line, index) =>
129
+ line_findings(line, index + FIRST_POSITION_OFFSET, denied_ids, rule),
130
+ )
131
+ }
121
132
 
122
- return lines.flatMap((line, index) => line_mutations(line, index, denied_ids))
133
+ return { name: rule.name, describe: rule.describe, scan }
123
134
  }
124
135
 
125
- const index_mutation_assertion: Assertion = {
136
+ const index_mutation_assertion = bash_assertion({
126
137
  name: INDEX_ASSERTION_NAME,
127
138
  describe: 'git staging or commit must go through `pnpm josh git`, never a direct git call',
128
- scan: scan_index_mutation,
129
- }
130
-
131
- // The seed set: every rule green across the recorded corpus today. A new rule is appended here only
132
- // after it has been verified green against past real runs.
133
- const ALL_ASSERTIONS: ReadonlyArray<Assertion> = [index_mutation_assertion]
139
+ is_violation: is_index_mutation,
140
+ })
141
+
142
+ // The matcher is the `direct-pr-create` guard's own, so the assertion and the refusal cannot drift. The
143
+ // guard refuses every match, so a finding means a direct PR call ran past it — every run since the
144
+ // guard landed is green; the only hits in the corpus predate it.
145
+ const PR_CREATE_ASSERTION_NAME = 'no-direct-pr-create'
146
+ const pr_create_assertion = bash_assertion({
147
+ name: PR_CREATE_ASSERTION_NAME,
148
+ describe: 'a pull request must be opened with `pnpm josh pr`, never `gh pr create` or `gh api`',
149
+ is_violation: direct_pr_create.is_direct_pr_create,
150
+ })
151
+
152
+ // Every rule green across the recorded corpus. A new rule is appended here only after it has been
153
+ // verified green against past real runs.
154
+ const ALL_ASSERTIONS: ReadonlyArray<Assertion> = [index_mutation_assertion, pr_create_assertion]
134
155
 
135
156
  const behavior_rules = {
136
157
  ALL_ASSERTIONS,
137
158
  INDEX_ASSERTION_NAME,
159
+ PR_CREATE_ASSERTION_NAME,
138
160
  command_of,
139
161
  index_mutation_assertion,
140
162
  is_index_mutation,
163
+ pr_create_assertion,
141
164
  }
142
165
 
143
166
  export { behavior_rules }
@@ -1,7 +1,5 @@
1
- #!/usr/bin/env tsx
2
1
  import path from 'node:path'
3
2
  import { fileURLToPath } from 'node:url'
4
- import { error_text } from '#scripts/lib/error-message'
5
3
  import { build } from 'esbuild'
6
4
 
7
5
  const PACKAGE_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..')
@@ -9,10 +7,10 @@ const ENTRY_POINT = path.join(PACKAGE_DIR, 'scripts', 'josh', 'josh.ts')
9
7
  const OUTFILE = path.join(PACKAGE_DIR, 'dist', 'josh.js')
10
8
  const NODE_BANNER = '#!/usr/bin/env node'
11
9
 
12
- async function build_bin(): Promise<void> {
10
+ async function build_bin(outfile: string = OUTFILE): Promise<void> {
13
11
  await build({
14
12
  entryPoints: [ENTRY_POINT],
15
- outfile: OUTFILE,
13
+ outfile,
16
14
  bundle: true,
17
15
  platform: 'node',
18
16
  format: 'esm',
@@ -22,16 +20,4 @@ async function build_bin(): Promise<void> {
22
20
  })
23
21
  }
24
22
 
25
- async function main(): Promise<void> {
26
- try {
27
- await build_bin()
28
- console.info(` ✔ ${OUTFILE} built`)
29
- } catch (error) {
30
- console.error(error_text.message_of(error))
31
- process.exit(1)
32
- }
33
- }
34
-
35
- if (process.argv[1] === fileURLToPath(import.meta.url)) await main()
36
-
37
23
  export { build_bin, NODE_BANNER, OUTFILE }
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env tsx
2
1
  import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'
3
2
  import path from 'node:path'
4
3
  import { fileURLToPath } from 'node:url'
@@ -40,12 +39,6 @@ function build_claude_md(): string {
40
39
  return DIST_CLAUDE_MD
41
40
  }
42
41
 
43
- function main(): void {
44
- console.info(` ✔ ${build_claude_md()} built`)
45
- }
46
-
47
- if (process.argv[1] === fileURLToPath(import.meta.url)) main()
48
-
49
42
  export {
50
43
  build_claude_md,
51
44
  DIST_BASIC_CLAUDE_MDS,
@@ -1,10 +1,8 @@
1
- #!/usr/bin/env tsx
2
1
  import { rmSync } from 'node:fs'
3
2
  import path from 'node:path'
4
3
  import { fileURLToPath } from 'node:url'
5
4
  import { COMMAND_MAP } from '#scripts/josh/josh-command-map'
6
5
  import { BUNDLED_COMMAND_DIRECTORY, josh_in_process } from '#scripts/josh/josh-in-process'
7
- import { error_text } from '#scripts/lib/error-message'
8
6
  import { build } from 'esbuild'
9
7
 
10
8
  const PACKAGE_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..')
@@ -52,15 +50,4 @@ async function build_commands(out_directory: string = OUT_DIR): Promise<string>
52
50
  return out_directory
53
51
  }
54
52
 
55
- async function main(): Promise<void> {
56
- try {
57
- console.info(` ✔ ${await build_commands()} built`)
58
- } catch (error) {
59
- console.error(error_text.message_of(error))
60
- process.exit(1)
61
- }
62
- }
63
-
64
- if (process.argv[1] === fileURLToPath(import.meta.url)) await main()
65
-
66
53
  export { build_commands, bundled_scripts, OUT_DIR }
@@ -1,20 +1,13 @@
1
- #!/usr/bin/env tsx
2
- import {
3
- mkdirSync,
4
- mkdtempSync,
5
- readdirSync,
6
- readFileSync,
7
- renameSync,
8
- rmSync,
9
- writeFileSync,
10
- } from 'node:fs'
1
+ import { mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync } from 'node:fs'
11
2
  import path from 'node:path'
12
3
  import { fileURLToPath } from 'node:url'
13
4
  import { hook_bundle_stamp } from '#scripts/build/hook-bundle-stamp'
14
- import { error_text } from '#scripts/lib/error-message'
5
+ import { toolchain_inputs } from '#scripts/gate/toolchain-inputs'
6
+ import { atomic_write } from '#scripts/lib/atomic-write'
15
7
  import { build, type OnLoadArgs, type OutputFile, type Plugin, type PluginBuild } from 'esbuild'
16
8
 
17
- const PACKAGE_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..')
9
+ const BUILD_SCRIPT = fileURLToPath(import.meta.url)
10
+ const PACKAGE_DIR = path.join(path.dirname(BUILD_SCRIPT), '..', '..')
18
11
  const OUT_DIR = path.join(PACKAGE_DIR, 'dist', 'hooks')
19
12
  const { STAMP_NAME } = hook_bundle_stamp
20
13
  const CHUNK_PREFIX = 'chunk-'
@@ -29,11 +22,11 @@ const ANY_PATH = /.*/
29
22
  //
30
23
  // **`splitting: true` is load-bearing, not an optimization.** Every hook module decides whether to
31
24
  // run its main from `process.argv[1] === fileURLToPath(import.meta.url)`. A single-file bundle would
32
- // collapse every imported module's `import.meta.url` to the one output path, so a call to
33
- // `node dist/hooks/pretool-guard.js` would fire the self-invoke of `batch-guard` and
34
- // `investigation-guard` too — each reads stdin, and the second read gets an empty payload. Code
35
- // splitting keeps every entry in its own file with its own `import.meta.url`, so an imported guard's
36
- // `import.meta.url` never equals `argv[1]` and only the file actually launched runs its main.
25
+ // collapse every imported module's `import.meta.url` to the one output path, so a call to one hook
26
+ // would fire the self-invoke of every other entry it carries — each reads stdin, and the second read
27
+ // gets an empty payload. Code splitting keeps every entry in its own file with its own
28
+ // `import.meta.url`, so only the file actually launched runs its main. The guards `pretool-guard`
29
+ // composes carry no self-invoke: theirs live in `*-main.ts` entries no module imports.
37
30
  //
38
31
  // **The flip side: an entry another entry imports loses its main**. Splitting
39
32
  // moves a module two entries share into a chunk, so a launched hook whose own module is imported
@@ -49,20 +42,15 @@ interface HookBundle {
49
42
  out: string
50
43
  }
51
44
 
52
- // The settings.json hooks (the session-start audit provisioner among them), the Codex input adapter, and the three guards `pretool-guard`
53
- // composes: `batch-guard`, `investigation-guard` and `duplicate-read-guard` each self-invoke, so they
54
- // must be their own entries to keep their `import.meta.url` out of `pretool-guard`'s file.
55
- // `delivered-rules` (the fourth guard) has no self-invoke, so it stays inlined.
45
+ // The settings.json hooks (the session-start audit provisioner among them) and the Codex input
46
+ // adapter — every hook a hook config launches, and nothing else.
56
47
  const HOOK_BUNDLES: ReadonlyArray<HookBundle> = [
57
48
  { source: 'scripts/hooks/codex-hook-adapter.ts', out: 'codex-hook-adapter' },
58
49
  { source: 'scripts/hooks/pretool-guard-cli.ts', out: 'pretool-guard' },
59
50
  { source: 'scripts/hooks/stop-guard.ts', out: 'stop-guard' },
60
51
  { source: 'scripts/hooks/format-edited-cli.ts', out: 'format-edited' },
61
- { source: 'scripts/josh/session-language-cli.ts', out: 'session-lang' },
62
- { source: 'scripts/security/security-audit-provision.ts', out: 'audit-provision' },
63
- { source: 'scripts/hooks/batch-guard.ts', out: 'batch-guard' },
64
- { source: 'scripts/delegation/investigation-guard.ts', out: 'investigation-guard' },
65
- { source: 'scripts/delegation/duplicate-read-guard.ts', out: 'duplicate-read-guard' },
52
+ { source: 'scripts/josh/session-language-main.ts', out: 'session-lang' },
53
+ { source: 'scripts/security/security-audit-provision-main.ts', out: 'audit-provision' },
66
54
  ]
67
55
 
68
56
  function entry_point(bundle: HookBundle): { in: string; out: string } {
@@ -83,9 +71,22 @@ function prune_stale_outputs(out_directory: string, outputs: ReadonlyArray<strin
83
71
  }
84
72
  }
85
73
 
74
+ // **A module inlined into an entry keeps no self-invoke.** Its `import.meta.url` collapses to the
75
+ // entry's output path, so its guard would match `argv[1]` and its main would run beside the hook's:
76
+ // `stop-guard` ran `josh run:hold`'s, `josh notify`'s and `josh run:tidy`'s on every stop, and their
77
+ // stdout ahead of the envelope made the harness drop the refusal (joshuafolkken/kit#4123). Only the
78
+ // launched entry runs a main, so every other module's guard is built as `false`.
79
+ const SELF_INVOKE_GUARD = 'process.argv[1] === fileURLToPath(import.meta.url)'
80
+
81
+ function loaded_contents(contents: Uint8Array, is_entry: boolean): string {
82
+ const source = Buffer.from(contents).toString('utf8')
83
+
84
+ return is_entry ? source : source.replaceAll(SELF_INVOKE_GUARD, 'false')
85
+ }
86
+
86
87
  // Every file the build loads is read here, so the stamp digests the exact bytes that were bundled —
87
88
  // a source edited mid-build is recorded as what it was, and the next launch rebuilds it.
88
- function source_recorder(sources: Map<string, Uint8Array>): Plugin {
89
+ function source_recorder(sources: Map<string, Uint8Array>, entries: ReadonlySet<string>): Plugin {
89
90
  return {
90
91
  name: 'hook-source-recorder',
91
92
  setup(plugin_build: PluginBuild): void {
@@ -94,7 +95,7 @@ function source_recorder(sources: Map<string, Uint8Array>): Plugin {
94
95
 
95
96
  sources.set(path.relative(PACKAGE_DIR, args.path), contents)
96
97
 
97
- return { contents, loader: 'default' }
98
+ return { contents: loaded_contents(contents, entries.has(args.path)), loader: 'default' }
98
99
  })
99
100
  },
100
101
  }
@@ -113,10 +114,7 @@ function is_chunk_first(left: OutputFile, right: OutputFile): number {
113
114
  // Each file is written into a private staging directory and renamed into place, so a hook never
114
115
  // reads a half-written bundle and two builds running side by side never write one file at once.
115
116
  function place(staging: string, target: string, contents: Uint8Array | string): void {
116
- const temporary = path.join(staging, path.basename(target))
117
-
118
- writeFileSync(temporary, contents)
119
- renameSync(temporary, target)
117
+ atomic_write.replace_file(target, contents, { staging_directory: staging })
120
118
  }
121
119
 
122
120
  function place_build(out_directory: string, files: ReadonlyArray<OutputFile>, stamp: string): void {
@@ -142,11 +140,26 @@ function place_build(out_directory: string, files: ReadonlyArray<OutputFile>, st
142
140
  // every tool call, and an emptied directory would make a hook launched mid-build fail to load and its
143
141
  // guard fail open. The source digest is placed last (`hook-bundle-stamp.ts`), so a launch only reads
144
142
  // the bundles as fresh once every one of them is in place.
143
+ //
144
+ // This script is an input too: it rewrites what it loads, so an edit to it changes the bundles while
145
+ // every bundled source stays byte-identical. So is the toolchain (`toolchain-inputs.ts`): the manifest
146
+ // maps the `#scripts/*` imports esbuild resolves, and the lockfile pins esbuild itself.
147
+ function build_inputs(): Map<string, Uint8Array> {
148
+ const toolchain = toolchain_inputs.paths(PACKAGE_DIR)
149
+
150
+ return new Map<string, Uint8Array>([
151
+ [path.relative(PACKAGE_DIR, BUILD_SCRIPT), readFileSync(BUILD_SCRIPT)],
152
+ ...toolchain.map((input) => [input, readFileSync(path.join(PACKAGE_DIR, input))] as const),
153
+ ])
154
+ }
155
+
145
156
  async function build_hooks(out_directory: string = OUT_DIR): Promise<void> {
146
- const sources = new Map<string, Uint8Array>()
157
+ const sources = build_inputs()
158
+ const entry_points = HOOK_BUNDLES.map((bundle) => entry_point(bundle))
159
+ const entries = new Set(entry_points.map((entry) => entry.in))
147
160
  const { outputFiles: files } = await build({
148
161
  absWorkingDir: PACKAGE_DIR,
149
- entryPoints: HOOK_BUNDLES.map((bundle) => entry_point(bundle)),
162
+ entryPoints: entry_points,
150
163
  outdir: out_directory,
151
164
  bundle: true,
152
165
  splitting: true,
@@ -155,7 +168,7 @@ async function build_hooks(out_directory: string = OUT_DIR): Promise<void> {
155
168
  target: 'node22',
156
169
  packages: 'external',
157
170
  write: false,
158
- plugins: [source_recorder(sources)],
171
+ plugins: [source_recorder(sources, entries)],
159
172
  })
160
173
  const stamp = hook_bundle_stamp.stamp_text(
161
174
  sources,
@@ -165,17 +178,5 @@ async function build_hooks(out_directory: string = OUT_DIR): Promise<void> {
165
178
  place_build(out_directory, files, stamp)
166
179
  }
167
180
 
168
- async function main(): Promise<void> {
169
- try {
170
- await build_hooks()
171
- for (const bundle of HOOK_BUNDLES) console.info(` ✔ ${outfile_for(bundle)} built`)
172
- } catch (error) {
173
- console.error(error_text.message_of(error))
174
- process.exit(1)
175
- }
176
- }
177
-
178
- if (process.argv[1] === fileURLToPath(import.meta.url)) await main()
179
-
180
181
  export type { HookBundle }
181
- export { build_hooks, HOOK_BUNDLES, OUT_DIR, outfile_for }
182
+ export { build_hooks, HOOK_BUNDLES, OUT_DIR, outfile_for, STAGING_PREFIX }
@@ -1,6 +1,8 @@
1
1
  import { createHash } from 'node:crypto'
2
- import { existsSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs'
2
+ import { existsSync, readFileSync, statSync } from 'node:fs'
3
3
  import path from 'node:path'
4
+ import { toolchain_inputs } from '#scripts/gate/toolchain-inputs'
5
+ import { atomic_write } from '#scripts/lib/atomic-write'
4
6
  import { json_value } from '#scripts/lib/json-value'
5
7
 
6
8
  // What a hook build was made from, so a later launch can tell whether `dist/hooks/` still matches the
@@ -31,7 +33,7 @@ import { json_value } from '#scripts/lib/json-value'
31
33
  // again. Once an mtime is older than the window any later write moves it, so only settled inputs are
32
34
  // remembered; a launch inside the window simply hashes.
33
35
  //
34
- // This module is loaded by plain `node` on every hook launch (`scripts/hooks/hook-bundle-ready.ts`),
36
+ // This module is loaded by plain `node` on every hook launch (`tools/hooks/hook-bundle-ready.ts`),
35
37
  // so it imports `node:` built-ins and `#scripts/*` subpaths alone — nothing slow to load.
36
38
 
37
39
  const STAMP_NAME = 'inputs.json'
@@ -171,13 +173,10 @@ function is_remembered(
171
173
  // Written through a rename so a concurrent launch never reads half a record. Best-effort: a tree that
172
174
  // cannot be written is simply hashed again next time.
173
175
  function remember(out_directory: string, verified: VerifiedDigest): void {
174
- const temporary_path = path.join(out_directory, `${VERIFIED_NAME}.${String(process.pid)}`)
175
-
176
176
  try {
177
- writeFileSync(temporary_path, JSON.stringify(verified))
178
- renameSync(temporary_path, path.join(out_directory, VERIFIED_NAME))
177
+ atomic_write.replace_file(path.join(out_directory, VERIFIED_NAME), JSON.stringify(verified))
179
178
  } catch {
180
- rmSync(temporary_path, { force: true })
179
+ // A record that could not be written leaves the digest to be computed again.
181
180
  }
182
181
  }
183
182
 
@@ -194,12 +193,31 @@ function is_digest_current(
194
193
  return true
195
194
  }
196
195
 
197
- // Fresh only when the record exists, every output it lists is still there, and the listed inputs hash
198
- // to the recorded digest — a missing or deleted input counts as stale. The hash is skipped when the
199
- // inputs still carry the signatures of an earlier launch that verified this digest.
196
+ // The build records the toolchain inputs among its sources (`build-hooks.ts`), so an edited one
197
+ // changes the digest; one created since — a new `tsconfig.*.json` or rule module — is in no record.
198
+ function lists_toolchain(stamp: HookBundleStamp, package_directory: string): boolean {
199
+ const recorded = new Set(stamp.inputs.map((input) => input.split(path.sep).join('/')))
200
+
201
+ return toolchain_inputs.paths(package_directory).every((input) => recorded.has(input))
202
+ }
203
+
204
+ function is_complete(
205
+ stamp: HookBundleStamp,
206
+ out_directory: string,
207
+ package_directory: string,
208
+ ): boolean {
209
+ if (stamp.outputs.some((output) => !existsSync(path.join(out_directory, output)))) return false
210
+
211
+ return lists_toolchain(stamp, package_directory)
212
+ }
213
+
214
+ // Fresh only when the record exists, every output it lists is still there, it lists every toolchain
215
+ // input, and the listed inputs hash to the recorded digest — a missing or deleted input counts as
216
+ // stale. The hash is skipped when the inputs still carry the signatures of an earlier launch that
217
+ // verified this digest.
200
218
  function is_fresh(out_directory: string, package_directory: string): boolean {
201
219
  const stamp = read_stamp(out_directory)
202
- if (!stamp?.outputs.every((output) => existsSync(path.join(out_directory, output)))) return false
220
+ if (stamp === undefined || !is_complete(stamp, out_directory, package_directory)) return false
203
221
  const snapshot = read_snapshot(package_directory, stamp.inputs)
204
222
  if (snapshot === undefined) return false
205
223
  if (is_remembered(out_directory, stamp.digest, snapshot.signatures)) return true
@@ -2,13 +2,13 @@ import { existsSync, readFileSync } from 'node:fs'
2
2
  import { createRequire } from 'node:module'
3
3
  import path from 'node:path'
4
4
  import { ancestor_directories } from '#scripts/lib/ancestor-directories'
5
+ import { PACKAGE_JSON } from '#scripts/lib/package-manifest'
5
6
  import { package_bin_schema } from '#scripts/lib/schemas'
6
7
 
7
8
  const NODE_MODULES = 'node_modules'
8
9
  const BIN_DIR = '.bin'
9
10
  const WINDOWS_PLATFORM = 'win32'
10
11
  const WINDOWS_SHIM_SUFFIX = '.cmd'
11
- const PACKAGE_JSON = 'package.json'
12
12
 
13
13
  // Every spawn site that reaches for a locally-installed CLI needs the same two details: pnpm
14
14
  // writes the shims under `node_modules/.bin`, and on Windows the executable one carries a
@@ -1,11 +1,13 @@
1
1
  #!/usr/bin/env tsx
2
2
  import { fileURLToPath } from 'node:url'
3
+ import { cases_interaction_scan, type Findings } from './cases-interaction-scan'
3
4
  import { cases, type Boundary } from './cases-logic'
4
5
 
5
- // `josh cases <path...>` — print the I/O boundaries the changed paths cross and the abnormal cases
6
- // each owes. The boundary tokens go on stdout so `$(pnpm josh cases …)` reads
7
- // them; the required cases go on stderr so a person sees them without a shell parsing around them.
8
- // The logic and the vocabulary live in `cases-logic.ts`; everything here is the invocation.
6
+ // `josh cases <path...>` — print the I/O boundaries the changed paths cross, the shared state and the
7
+ // environment they depend on, and the abnormal cases each owes. The tokens go on stdout so
8
+ // `$(pnpm josh cases …)` reads them; the required cases go on stderr so a person sees them without a
9
+ // shell parsing around them. The logic and the vocabulary live in `cases-logic.ts` and
10
+ // `cases-interaction.ts`; everything here is the invocation.
9
11
 
10
12
  const ARGV_OFFSET = 2
11
13
  const USAGE = 'Usage: josh cases <path...>'
@@ -13,19 +15,27 @@ const FAILURE_EXIT_CODE = 1
13
15
 
14
16
  function report_none(): number {
15
17
  console.info(cases.NONE)
16
- console.error('no network, process, filesystem or time boundary crossed')
18
+ console.error(
19
+ 'no network, process, filesystem, time, shared-state or environment boundary crossed',
20
+ )
17
21
 
18
22
  return 0
19
23
  }
20
24
 
21
- function report_boundaries(boundaries: ReadonlyArray<Boundary>): number {
22
- console.info(boundaries.join(' '))
23
- console.error(`required abnormal cases: ${cases.cases_for(boundaries).join(' / ')}`)
25
+ // The interaction lines come first, as `report:template` places them at the head of "if it breaks".
26
+ function report_crossed(boundaries: ReadonlyArray<Boundary>, findings: Findings): number {
27
+ console.info([...boundaries, ...cases_interaction_scan.interactions_of(findings)].join(' '))
28
+
29
+ for (const line of cases_interaction_scan.lines_for(findings)) console.error(line)
30
+
31
+ if (boundaries.length > 0) {
32
+ console.error(`required abnormal cases: ${cases.cases_for(boundaries).join(' / ')}`)
33
+ }
24
34
 
25
35
  return 0
26
36
  }
27
37
 
28
- function run(argv: ReadonlyArray<string>): number {
38
+ async function run(argv: ReadonlyArray<string>): Promise<number> {
29
39
  if (argv.length === 0) {
30
40
  console.error(USAGE)
31
41
 
@@ -33,16 +43,18 @@ function run(argv: ReadonlyArray<string>): number {
33
43
  }
34
44
 
35
45
  const boundaries = cases.boundaries_in(argv)
46
+ const findings = await cases_interaction_scan.scan(argv)
47
+ const is_crossed = boundaries.length + cases_interaction_scan.interactions_of(findings).length > 0
36
48
 
37
- return boundaries.length === 0 ? report_none() : report_boundaries(boundaries)
49
+ return is_crossed ? report_crossed(boundaries, findings) : report_none()
38
50
  }
39
51
 
40
- function main(argv: ReadonlyArray<string>): void {
41
- process.exitCode = run(argv)
52
+ async function main(argv: ReadonlyArray<string>): Promise<void> {
53
+ process.exitCode = await run(argv)
42
54
  }
43
55
 
44
56
  const cases_cli = { run }
45
57
 
46
- if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET))
58
+ if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
47
59
 
48
60
  export { cases_cli }
@@ -0,0 +1,134 @@
1
+ import path from 'node:path'
2
+ import { git_grep_hits, type GrepResult } from '#scripts/git/git-grep-hits'
3
+ import { file_reader } from '#scripts/lib/read-file'
4
+ import {
5
+ cases_interaction,
6
+ type Interaction,
7
+ type StatePath,
8
+ type Wording,
9
+ } from './cases-interaction'
10
+
11
+ // The I/O half of `josh cases`' interaction boundaries (joshuafolkken/kit#4491): read the changed
12
+ // sources, then search the rest of the repository for each state path they name — by its literal and
13
+ // by every constant this source binds it to — so the summary lists the other readers and writers as
14
+ // `file:line`. Tests are left out of the search: a fixture path is not a second writer at run time.
15
+
16
+ const SOURCE_EXTENSIONS: ReadonlySet<string> = new Set(['.ts', '.js', '.mjs', '.cjs', '.svelte'])
17
+ const SOURCE_PATHSPECS: ReadonlyArray<string> = [
18
+ '*.ts',
19
+ '*.js',
20
+ '*.mjs',
21
+ '*.cjs',
22
+ '*.svelte',
23
+ ':(exclude)*.test.ts',
24
+ ]
25
+ const WHOLE_WORD = ['-w']
26
+ const MAX_OTHERS = 10
27
+
28
+ interface SharedState {
29
+ path: string
30
+ others: ReadonlyArray<string>
31
+ has_failed: boolean
32
+ }
33
+
34
+ interface Findings {
35
+ states: ReadonlyArray<SharedState>
36
+ variables: ReadonlyArray<string>
37
+ residents: ReadonlyArray<string>
38
+ }
39
+
40
+ function is_source(file: string): boolean {
41
+ return SOURCE_EXTENSIONS.has(path.extname(file))
42
+ }
43
+
44
+ function repo_relative(file: string): string {
45
+ return path.relative(process.cwd(), path.resolve(file))
46
+ }
47
+
48
+ // A module that declares its own constant of the same name holds its own state, not this one.
49
+ async function constant_hits(name: string): Promise<GrepResult> {
50
+ const result = await git_grep_hits.search(name, WHOLE_WORD, SOURCE_PATHSPECS)
51
+ const declaration = new RegExp(String.raw`\b(?:const|let|var)\s+${name}\b`, 'u')
52
+ const declaring = new Set(
53
+ result.hits.filter((hit) => declaration.test(hit.excerpt)).map((hit) => hit.path),
54
+ )
55
+
56
+ return { ...result, hits: result.hits.filter((hit) => !declaring.has(hit.path)) }
57
+ }
58
+
59
+ async function shared_state(state: StatePath, own: ReadonlySet<string>): Promise<SharedState> {
60
+ const results = await Promise.all([
61
+ git_grep_hits.search(state.path, [], SOURCE_PATHSPECS),
62
+ ...state.constants.map(async (name) => await constant_hits(name)),
63
+ ])
64
+ const sites = results
65
+ .flatMap((result) => result.hits)
66
+ .filter((hit) => !own.has(hit.path))
67
+ .map((hit) => `${hit.path}:${hit.line}`)
68
+
69
+ return {
70
+ path: state.path,
71
+ others: [...new Set(sites)],
72
+ has_failed: results.some((result) => result.has_failed),
73
+ }
74
+ }
75
+
76
+ async function scan(paths: ReadonlyArray<string>): Promise<Findings> {
77
+ const content = paths
78
+ .filter((file) => is_source(file))
79
+ .map((file) => file_reader.read_if_readable(file) ?? '')
80
+ .join('\n')
81
+ const own = new Set(paths.map((file) => repo_relative(file)))
82
+ const states = await Promise.all(
83
+ cases_interaction.state_paths_in(content).map(async (state) => await shared_state(state, own)),
84
+ )
85
+
86
+ return { states, ...cases_interaction.environment_in(content) }
87
+ }
88
+
89
+ function interactions_of(findings: Findings): ReadonlyArray<Interaction> {
90
+ const has_environment = findings.variables.length + findings.residents.length > 0
91
+ const crossed = { state: findings.states.length > 0, env: has_environment }
92
+
93
+ return cases_interaction.INTERACTIONS.filter((interaction) => crossed[interaction])
94
+ }
95
+
96
+ function others_text(state: SharedState, words: Wording): string {
97
+ if (state.has_failed) return words.search_failed
98
+ if (state.others.length === 0) return words.no_others
99
+
100
+ const shown = state.others.slice(0, MAX_OTHERS)
101
+ const rest = state.others.length - shown.length
102
+
103
+ return rest > 0 ? `${shown.join(', ')}, +${String(rest)}` : shown.join(', ')
104
+ }
105
+
106
+ function line(label: string, subject: string, owed: ReadonlyArray<string>): string {
107
+ return `${label} ${subject}: ${owed.join(' / ')}`
108
+ }
109
+
110
+ // One line per state, variable and resident process, in that order — each carries its own subject,
111
+ // so the reader sees whose cases they are without a second table.
112
+ function lines_for(findings: Findings, lang?: string): ReadonlyArray<string> {
113
+ const words = cases_interaction.wording(lang)
114
+ const state_lines = findings.states.map((state) =>
115
+ line(
116
+ words.state,
117
+ `\`${state.path}\` (${words.others}: ${others_text(state, words)})`,
118
+ words.state_cases,
119
+ ),
120
+ )
121
+ const variable_lines = findings.variables.map((name) =>
122
+ line(words.variable, `\`${name}\``, words.variable_cases),
123
+ )
124
+ const resident_lines = findings.residents.map((name) =>
125
+ line(words.resident, `\`${name}\``, words.resident_cases),
126
+ )
127
+
128
+ return [...state_lines, ...variable_lines, ...resident_lines]
129
+ }
130
+
131
+ const cases_interaction_scan = { scan, interactions_of, lines_for }
132
+
133
+ export type { Findings, SharedState }
134
+ export { cases_interaction_scan }