@joshuafolkken/kit 1.1471.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 (895) hide show
  1. package/.claude/agents/investigator.md +1 -1
  2. package/.claude/settings.json +6 -6
  3. package/.claude/skills/epic-commands/SKILL.md +26 -77
  4. package/.claude/skills/epic-commands/epic-bundle.md +12 -6
  5. package/.claude/skills/epic-commands/execution-waves.md +1 -2
  6. package/.claude/skills/verify-ui/SKILL.md +1 -2
  7. package/.claude/skills/workflow-commands/SKILL.md +12 -14
  8. package/.claude/skills/workflow-commands/background-commands.md +8 -12
  9. package/.claude/skills/workflow-commands/backlogrun-child.md +13 -18
  10. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
  11. package/.claude/skills/workflow-commands/backlogrun-lanes.md +23 -28
  12. package/.claude/skills/workflow-commands/backlogrun-park.md +16 -31
  13. package/.claude/skills/workflow-commands/backlogrun-progress.md +12 -21
  14. package/.claude/skills/workflow-commands/backlogrun-recovery.md +12 -12
  15. package/.claude/skills/workflow-commands/backlogrun-steps.md +12 -20
  16. package/.claude/skills/workflow-commands/backlogrun.md +32 -51
  17. package/.claude/skills/workflow-commands/chain-rule.md +18 -11
  18. package/.claude/skills/workflow-commands/delegation.md +13 -8
  19. package/.claude/skills/workflow-commands/entry-sequence.md +10 -12
  20. package/.claude/skills/workflow-commands/followup.md +10 -35
  21. package/.claude/skills/workflow-commands/fullrun-steps.md +38 -49
  22. package/.claude/skills/workflow-commands/fullrun.md +6 -8
  23. package/.claude/skills/workflow-commands/halfrun.md +20 -32
  24. package/.claude/skills/workflow-commands/into-target.md +1 -2
  25. package/.claude/skills/workflow-commands/issue-comments.md +19 -15
  26. package/.claude/skills/workflow-commands/issue-scout.md +5 -4
  27. package/.claude/skills/workflow-commands/kickoff.md +24 -23
  28. package/.claude/skills/workflow-commands/latest-gate.md +9 -18
  29. package/.claude/skills/workflow-commands/needs-human-review.md +11 -19
  30. package/.claude/skills/workflow-commands/observation-filing.md +4 -50
  31. package/.claude/skills/workflow-commands/observation-ledger.md +5 -10
  32. package/.claude/skills/workflow-commands/pre-gate-cut.md +22 -44
  33. package/.claude/skills/workflow-commands/prerequisite.md +11 -18
  34. package/.claude/skills/workflow-commands/progress-watcher.md +3 -8
  35. package/.claude/skills/workflow-commands/prrun.md +6 -12
  36. package/.claude/skills/workflow-commands/retrospective.md +5 -5
  37. package/.claude/skills/workflow-commands/split-assessment.md +14 -4
  38. package/.claude/skills/workflow-commands/target-repository.md +1 -2
  39. package/.claude/skills/workflow-commands/working-tree-hold.md +11 -13
  40. package/.codex/hooks.json +6 -6
  41. package/.github/actions/setup-node/action.yml +10 -1
  42. package/.github/actions/setup-pnpm/action.yml +1 -1
  43. package/.github/dependabot.yml +16 -0
  44. package/.github/release.yml +0 -2
  45. package/.github/workflows/ci.yml +121 -11
  46. package/.github/workflows/publish.yml +10 -3
  47. package/.github/workflows/sonar-qube.yml +1 -0
  48. package/.prettierignore +2 -0
  49. package/.vscode/tasks.json +1 -2
  50. package/CLAUDE.md +4 -8
  51. package/README.md +4 -2
  52. package/SECURITY.md +1 -1
  53. package/cspell/index.yaml +7 -0
  54. package/dist/CLAUDE.md +4 -8
  55. package/dist/commands/document-read-cli.js +882 -0
  56. package/dist/commands/{document-section-cli.js → document-section-main.js} +137 -62
  57. package/dist/commands/read-set-cli.js +1867 -0
  58. package/dist/commands/run-prep-main.js +21653 -0
  59. package/dist/commands/run-step-cli.js +23880 -0
  60. package/dist/config-merge/index.js +5 -1
  61. package/dist/hooks/audit-provision.js +20 -35
  62. package/dist/hooks/{chunk-DGT54IH5.js → chunk-AZX4FGQ3.js} +63 -17
  63. package/dist/hooks/chunk-CWMBGKYW.js +6483 -0
  64. package/dist/hooks/chunk-O2YBIDSI.js +4306 -0
  65. package/dist/hooks/{chunk-AS74OU3D.js → chunk-PT5R6UJD.js} +4582 -2118
  66. package/dist/hooks/chunk-TUIFS5E7.js +72 -0
  67. package/dist/hooks/{chunk-723HKZO5.js → chunk-VWWCFGWK.js} +1 -1
  68. package/dist/hooks/{chunk-E7OIKX5Z.js → chunk-WR2KQAYZ.js} +1863 -382
  69. package/dist/hooks/{chunk-KC5AK2GF.js → chunk-XGBNSWEI.js} +248 -46
  70. package/dist/hooks/chunk-YCDOIR3I.js +3456 -0
  71. package/dist/hooks/codex-hook-adapter.js +10 -19
  72. package/dist/hooks/format-edited.js +5 -5
  73. package/dist/hooks/inputs.json +436 -257
  74. package/dist/hooks/pretool-guard.js +7 -22
  75. package/dist/hooks/session-lang.js +380 -42
  76. package/dist/hooks/stop-guard.js +8711 -782
  77. package/dist/josh.js +5263 -997
  78. package/dist/self-sync-guard/index.js +74 -10
  79. package/dist/version/index.js +115 -406
  80. package/eslint/base.js +1 -1
  81. package/lefthook/base.yml +8 -4
  82. package/package.json +17 -53
  83. package/pnpm-workspace.yaml +4 -2
  84. package/prompts/coding-standards.md +1 -1
  85. package/prompts/collaboration-workflow/file-edits.md +1 -9
  86. package/prompts/collaboration-workflow/gh-rest.md +1 -2
  87. package/prompts/collaboration-workflow/issue-citation.md +2 -4
  88. package/prompts/collaboration-workflow/issue-template.md +42 -17
  89. package/prompts/collaboration-workflow/lane-instructions.md +34 -0
  90. package/prompts/collaboration-workflow/measurement.md +37 -0
  91. package/prompts/collaboration-workflow/operating-rules.md +6 -12
  92. package/prompts/collaboration-workflow/output-bounds.md +4 -9
  93. package/prompts/collaboration-workflow/overview.md +1 -1
  94. package/prompts/collaboration-workflow/plan-comment.md +3 -42
  95. package/prompts/collaboration-workflow/principles.md +19 -8
  96. package/prompts/collaboration-workflow/report-format.md +37 -57
  97. package/prompts/collaboration-workflow/residency.md +12 -8
  98. package/prompts/collaboration-workflow/rule-delivery.md +3 -11
  99. package/prompts/collaboration-workflow/shell-body.md +8 -18
  100. package/prompts/collaboration-workflow/turn-batching.md +4 -6
  101. package/prompts/collaboration-workflow/upstream-interrupt.md +16 -6
  102. package/prompts/collaboration-workflow/wip-cap.md +7 -7
  103. package/prompts/collaboration-workflow.md +4 -7
  104. package/prompts/refactoring.md +1 -1
  105. package/prompts/review-rubric.md +1 -2
  106. package/prompts/review.md +45 -26
  107. package/prompts/testing-guide.md +10 -45
  108. package/scripts/agent/agent-argv.ts +20 -4
  109. package/scripts/agent/agent-event.ts +15 -15
  110. package/scripts/agent/agent-exit-record.ts +13 -1
  111. package/scripts/agent/agent-role-profile.ts +101 -45
  112. package/scripts/agent/agent-safe-text.ts +60 -0
  113. package/scripts/agent/api-auth.ts +41 -0
  114. package/scripts/agent/api-outage.ts +1 -1
  115. package/scripts/agent/claude-agent-argv.ts +14 -0
  116. package/scripts/agent/codex-agent-argv.ts +2 -0
  117. package/scripts/agent/lane-instructions.ts +144 -0
  118. package/scripts/auto-ok/auto-ok-cli.ts +14 -16
  119. package/scripts/auto-ok/auto-ok-judge-read.ts +12 -3
  120. package/scripts/auto-ok/auto-ok-judge-write.ts +46 -19
  121. package/scripts/auto-ok/auto-ok-judge.ts +13 -2
  122. package/scripts/auto-ok/auto-ok-main.ts +17 -0
  123. package/scripts/backlog/backlog-arrival.ts +14 -3
  124. package/scripts/backlog/backlog-budget-cli.ts +7 -33
  125. package/scripts/backlog/backlog-budget-main.ts +16 -0
  126. package/scripts/backlog/backlog-budget.ts +6 -7
  127. package/scripts/backlog/backlog-defect-priority.ts +4 -3
  128. package/scripts/backlog/backlog-drive-adopt.ts +67 -0
  129. package/scripts/backlog/backlog-drive-args.ts +4 -5
  130. package/scripts/backlog/backlog-drive-cli.ts +113 -28
  131. package/scripts/backlog/backlog-drive-hold.ts +162 -0
  132. package/scripts/backlog/backlog-drive-idle.ts +151 -0
  133. package/scripts/backlog/backlog-drive-judge.ts +25 -0
  134. package/scripts/backlog/backlog-drive-memory.ts +126 -0
  135. package/scripts/backlog/backlog-drive-named-offer.ts +5 -10
  136. package/scripts/backlog/backlog-drive-named.ts +54 -7
  137. package/scripts/backlog/backlog-drive-offer-argv.ts +3 -8
  138. package/scripts/backlog/backlog-drive-paused.ts +169 -0
  139. package/scripts/backlog/backlog-drive-restore.ts +39 -8
  140. package/scripts/backlog/backlog-drive-seats.ts +18 -8
  141. package/scripts/backlog/backlog-drive-token-handling.ts +38 -0
  142. package/scripts/backlog/backlog-drive.ts +79 -75
  143. package/scripts/backlog/backlog-next-main.ts +16 -0
  144. package/scripts/backlog/backlog-next-shared.ts +73 -0
  145. package/scripts/backlog/backlog-next.ts +48 -16
  146. package/scripts/backlog/backlog-occupied.ts +69 -0
  147. package/scripts/backlog/backlog-offer-cli.ts +6 -21
  148. package/scripts/backlog/backlog-offer-exclude.ts +15 -0
  149. package/scripts/backlog/backlog-offer-main.ts +12 -0
  150. package/scripts/backlog/backlog-offer.ts +36 -3
  151. package/scripts/backlog/backlog-overlap.ts +22 -4
  152. package/scripts/backlog/backlog-plan-read.ts +6 -2
  153. package/scripts/backlog/backlog-plan.ts +18 -4
  154. package/scripts/backlog/backlog-pool.ts +10 -10
  155. package/scripts/backlog/backlog-rank.ts +10 -2
  156. package/scripts/backlog/backlog-ready.ts +137 -18
  157. package/scripts/backlog/backlog-stalled-detect.ts +109 -36
  158. package/scripts/backlog/backlog-stalled.ts +52 -16
  159. package/scripts/backlog/backlog-wait-cause.ts +86 -0
  160. package/scripts/backlog/backlog-waves.ts +39 -13
  161. package/scripts/backlog/backlogrun-args.ts +19 -7
  162. package/scripts/backlog/backlogrun-cli.ts +19 -5
  163. package/scripts/backlog/backlogrun-launch.ts +6 -0
  164. package/scripts/backlog/backlogrun-restart.ts +97 -0
  165. package/scripts/backlog/backlogrun-stop.ts +79 -7
  166. package/scripts/behavior/behavior-cli.ts +2 -2
  167. package/scripts/behavior/behavior-rules.ts +47 -24
  168. package/scripts/build/build-bin.ts +2 -16
  169. package/scripts/build/build-claude-md.ts +0 -7
  170. package/scripts/build/build-commands.ts +0 -13
  171. package/scripts/build/build-hooks.ts +49 -48
  172. package/scripts/build/hook-bundle-stamp.ts +29 -11
  173. package/scripts/build/local-bin.ts +1 -1
  174. package/scripts/cases/cases-cli.ts +25 -13
  175. package/scripts/cases/cases-interaction-scan.ts +134 -0
  176. package/scripts/cases/cases-interaction.ts +183 -0
  177. package/scripts/cases/cases-logic.ts +39 -6
  178. package/scripts/ci/pr-classification-main.ts +18 -0
  179. package/scripts/ci/pr-classification.ts +10 -17
  180. package/scripts/clone/clone-scan.ts +1 -1
  181. package/scripts/cost-runtime/cost-blocks.ts +22 -37
  182. package/scripts/cost-runtime/cost-cli.ts +31 -14
  183. package/scripts/cost-runtime/cost-main.ts +12 -0
  184. package/scripts/cost-runtime/cost-transcript.ts +1 -0
  185. package/scripts/delegation/delegation-policy.ts +17 -4
  186. package/scripts/delegation/duplicate-read-guard.ts +2 -10
  187. package/scripts/delegation/investigation-guard.ts +15 -73
  188. package/scripts/delegation/investigation-reads.ts +3 -5
  189. package/scripts/dependabot/dependabot-cooldown.ts +194 -0
  190. package/scripts/discovery/repo-discovery.ts +24 -6
  191. package/scripts/doctor/doctor-consumer.ts +2 -5
  192. package/scripts/document/document-byte-budget.ts +9 -6
  193. package/scripts/document/document-scan.ts +1 -1
  194. package/scripts/document/document-section-cli.ts +17 -13
  195. package/scripts/document/document-section-main.ts +12 -0
  196. package/scripts/document/entry-read-budget.ts +2 -2
  197. package/scripts/document/read-set-cli.ts +4 -1
  198. package/scripts/epic/epic-audit-cli.ts +12 -6
  199. package/scripts/epic/epic-audit-orphans.ts +5 -8
  200. package/scripts/epic/epic-audit.ts +52 -1
  201. package/scripts/epic/epic-bundle-apply.ts +137 -0
  202. package/scripts/epic/epic-bundle-cli.ts +32 -121
  203. package/scripts/epic/epic-bundle-evidence.ts +49 -26
  204. package/scripts/epic/epic-bundle-format.ts +116 -0
  205. package/scripts/epic/epic-bundle-main.ts +17 -0
  206. package/scripts/epic/epic-bundle-referenced.ts +14 -3
  207. package/scripts/epic/epic-bundle.ts +17 -9
  208. package/scripts/epic/epic-busy.ts +5 -12
  209. package/scripts/epic/epic-classify.ts +24 -15
  210. package/scripts/epic/epic-cli-argv.ts +31 -0
  211. package/scripts/epic/epic-cli-decide.ts +42 -0
  212. package/scripts/epic/epic-cli.ts +6 -38
  213. package/scripts/epic/epic-close.ts +112 -55
  214. package/scripts/epic/epic-cross-repo.ts +4 -7
  215. package/scripts/epic/epic-decide.ts +119 -0
  216. package/scripts/epic/epic-decision.ts +9 -0
  217. package/scripts/epic/epic-fetch.ts +4 -0
  218. package/scripts/epic/epic-graph.ts +2 -0
  219. package/scripts/epic/epic-issue.ts +5 -1
  220. package/scripts/epic/epic-label-age.ts +1 -1
  221. package/scripts/epic/epic-lane-offer.ts +39 -4
  222. package/scripts/epic/epic-next-main.ts +24 -0
  223. package/scripts/epic/epic-next.ts +6 -24
  224. package/scripts/epic/epic-outside-blocker.ts +6 -2
  225. package/scripts/epic/epic-parse.ts +9 -3
  226. package/scripts/epic/epic-read.ts +1 -0
  227. package/scripts/epic/epic-reconcile.ts +39 -0
  228. package/scripts/epic/epic-run.ts +10 -1
  229. package/scripts/epic/epic-solo.ts +50 -14
  230. package/scripts/epic/epic.ts +41 -7
  231. package/scripts/exports/unused-members-cli.ts +2 -2
  232. package/scripts/followup/followup-checks-event.ts +8 -3
  233. package/scripts/followup/followup-coderabbit-wait.ts +82 -0
  234. package/scripts/followup/followup-review-gates.ts +81 -0
  235. package/scripts/followup/git-followup-stages.ts +13 -3
  236. package/scripts/followup/git-followup-workflow.ts +31 -60
  237. package/scripts/followup/git-pr-followup-wrapup.ts +9 -14
  238. package/scripts/followup/git-pr-followup.ts +36 -8
  239. package/scripts/fresh-machine/fresh-machine-cli.ts +1 -1
  240. package/scripts/fresh-machine/fresh-machine-run.ts +8 -8
  241. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +1 -1
  242. package/scripts/gate/busy-average.ts +58 -0
  243. package/scripts/gate/check-cpu.ts +60 -0
  244. package/scripts/gate/check-inputs.ts +73 -0
  245. package/scripts/gate/check-reuse.ts +141 -0
  246. package/scripts/gate/command-memory.ts +192 -0
  247. package/scripts/gate/core-admission.ts +218 -28
  248. package/scripts/gate/core-budget-timing.ts +37 -0
  249. package/scripts/gate/core-budget.ts +150 -119
  250. package/scripts/gate/core-wait-record.ts +48 -0
  251. package/scripts/gate/core-wait.ts +162 -0
  252. package/scripts/gate/core-weights.ts +86 -0
  253. package/scripts/gate/free-cores.ts +72 -0
  254. package/scripts/gate/gate-ledger.ts +49 -7
  255. package/scripts/gate/gate-plan.ts +44 -15
  256. package/scripts/gate/gate-report.ts +29 -4
  257. package/scripts/gate/gate-run-steps.ts +195 -0
  258. package/scripts/gate/gate-skip.ts +12 -2
  259. package/scripts/gate/gate-steps.ts +12 -1
  260. package/scripts/gate/held-mark.ts +55 -0
  261. package/scripts/gate/input-fingerprint.ts +42 -0
  262. package/scripts/gate/machine-capacity.ts +124 -31
  263. package/scripts/gate/moved-paths.ts +67 -0
  264. package/scripts/gate/pre-commit-type-check.ts +14 -1
  265. package/scripts/gate/project-checks.ts +5 -12
  266. package/scripts/gate/scoped-green.ts +12 -8
  267. package/scripts/gate/since-green.ts +62 -0
  268. package/scripts/gate/toolchain-inputs.ts +115 -0
  269. package/scripts/gate/verification-gate.ts +65 -129
  270. package/scripts/gate/verification-inputs.ts +250 -0
  271. package/scripts/gh/gh-author-association.ts +96 -9
  272. package/scripts/gh/git-ai-review-scan.ts +4 -2
  273. package/scripts/gh/git-gh-api-path.ts +15 -0
  274. package/scripts/gh/git-gh-branch-rules.ts +73 -0
  275. package/scripts/gh/git-gh-conditional.ts +5 -2
  276. package/scripts/gh/git-gh-issue-read.ts +5 -1
  277. package/scripts/gh/git-gh-issue-rest.ts +1 -0
  278. package/scripts/gh/git-gh-issue-write.ts +77 -17
  279. package/scripts/gh/git-gh-issue.ts +7 -3
  280. package/scripts/gh/git-gh-poll-read.ts +89 -0
  281. package/scripts/gh/git-gh-pr-auto-merge.ts +8 -3
  282. package/scripts/gh/git-gh-pr-rest.ts +1 -1
  283. package/scripts/gh/git-gh-pr-snapshot.ts +33 -20
  284. package/scripts/gh/git-gh-pr.ts +27 -15
  285. package/scripts/gh/git-pr-checks-eval.ts +39 -7
  286. package/scripts/gh/git-pr-checks-parse.ts +39 -9
  287. package/scripts/gh/git-pr-merge-checked.ts +80 -0
  288. package/scripts/gh/git-pr.ts +13 -1
  289. package/scripts/git/base-tree.ts +19 -2
  290. package/scripts/git/changed-file-scope.ts +6 -4
  291. package/scripts/git/changed-paths.ts +18 -1
  292. package/scripts/git/git-diff-reads.ts +27 -2
  293. package/scripts/git/git-grep-hits.ts +85 -0
  294. package/scripts/git/git-location-environment.ts +1 -1
  295. package/scripts/git/git-merge-conflicts.ts +83 -0
  296. package/scripts/git/git-preflight.ts +37 -12
  297. package/scripts/git/git-push-transport.ts +1 -2
  298. package/scripts/git/git-schemas.ts +17 -7
  299. package/scripts/git/git-spawn.ts +1 -2
  300. package/scripts/git/git-status.ts +4 -4
  301. package/scripts/git/main-merge-main.ts +12 -0
  302. package/scripts/git/main-merge-regenerate.ts +78 -0
  303. package/scripts/git/main-merge.ts +39 -14
  304. package/scripts/git/main-sync-main.ts +12 -0
  305. package/scripts/git/main-sync.ts +0 -9
  306. package/scripts/git/stash/git-stash.ts +27 -4
  307. package/scripts/git/stash/{stash-pop-args.ts → stash-args.ts} +13 -10
  308. package/scripts/git/stash/stash-pop-cli.ts +6 -12
  309. package/scripts/git/stash/stash-pop-main.ts +12 -0
  310. package/scripts/git/stash/stash-push-cli.ts +76 -0
  311. package/scripts/git/stash/stash-push-main.ts +12 -0
  312. package/scripts/hooks/batch-guard.ts +5 -16
  313. package/scripts/hooks/check-commit-message-main.ts +8 -0
  314. package/scripts/hooks/check-commit-message.ts +4 -7
  315. package/scripts/hooks/format-edited-file.ts +8 -24
  316. package/scripts/hooks/pre-commit-lint.ts +118 -0
  317. package/scripts/hooks/pre-push-unit.ts +4 -2
  318. package/scripts/hooks/pretool-guard-cli.ts +1 -8
  319. package/scripts/hooks/pretool-guard.ts +57 -69
  320. package/scripts/hooks/reserved-run.ts +67 -8
  321. package/scripts/hooks/run-hook.sh +18 -11
  322. package/scripts/hooks/shell-rules-notice.ts +37 -0
  323. package/scripts/hooks/stop-actions.ts +185 -0
  324. package/scripts/hooks/stop-guard.ts +72 -27
  325. package/scripts/init/hook-command-rewrite.ts +19 -5
  326. package/scripts/init/hook-launch.ts +15 -12
  327. package/scripts/init/init-actions.ts +0 -6
  328. package/scripts/init/init-ai-copy.ts +10 -36
  329. package/scripts/init/init-bootstrap.ts +9 -8
  330. package/scripts/init/init-dry-run-report.ts +1 -1
  331. package/scripts/init/init-dry-run.ts +1 -1
  332. package/scripts/init/init-file-action.ts +7 -9
  333. package/scripts/init/init-logic-json-merge.ts +2 -2
  334. package/scripts/init/init-logic-migrate.ts +9 -82
  335. package/scripts/init/init-logic.ts +3 -2
  336. package/scripts/init/init-main.ts +12 -0
  337. package/scripts/init/init.ts +5 -12
  338. package/scripts/init/kit-development-versions.ts +3 -7
  339. package/scripts/init/kit-written-paths.ts +2 -2
  340. package/scripts/init/project-profile.ts +5 -4
  341. package/scripts/init/tsconfig-preset-migration.ts +2 -1
  342. package/scripts/init/vscode-tasks.ts +1 -1
  343. package/scripts/issue/defect-origin-cli.ts +106 -0
  344. package/scripts/issue/defect-origin-line.ts +60 -0
  345. package/scripts/issue/defect-origin-main.ts +11 -0
  346. package/scripts/issue/defect-origin.ts +114 -0
  347. package/scripts/issue/defect-rate-cli.ts +34 -78
  348. package/scripts/issue/defect-rate.ts +0 -16
  349. package/scripts/issue/defect-report-cli.ts +128 -0
  350. package/scripts/issue/defect-report-format.ts +56 -0
  351. package/scripts/issue/defect-report-main.ts +11 -0
  352. package/scripts/issue/defect-report.ts +160 -0
  353. package/scripts/issue/expected-effect-lint.ts +60 -0
  354. package/scripts/issue/issue-already-done-cli.ts +62 -0
  355. package/scripts/issue/issue-body-or-comment.ts +40 -0
  356. package/scripts/issue/issue-cite-cli.ts +33 -22
  357. package/scripts/issue/issue-cite-main.ts +12 -0
  358. package/scripts/issue/issue-classification.ts +13 -8
  359. package/scripts/issue/issue-comment-cli.ts +10 -24
  360. package/scripts/issue/issue-comment-main.ts +12 -0
  361. package/scripts/issue/issue-evidence-exit.ts +100 -0
  362. package/scripts/issue/issue-file-cli.ts +29 -7
  363. package/scripts/issue/issue-file.ts +19 -19
  364. package/scripts/issue/issue-fold-cli.ts +2 -11
  365. package/scripts/issue/issue-fold-main.ts +12 -0
  366. package/scripts/issue/issue-labels.ts +81 -90
  367. package/scripts/issue/issue-lint-cli.ts +7 -13
  368. package/scripts/issue/issue-lint-main.ts +12 -0
  369. package/scripts/issue/issue-measured-cli.ts +56 -0
  370. package/scripts/issue/issue-merged.ts +19 -2
  371. package/scripts/issue/issue-not-before-label.ts +135 -0
  372. package/scripts/issue/issue-not-before.ts +111 -0
  373. package/scripts/issue/issue-number-shape.ts +15 -1
  374. package/scripts/issue/issue-park.ts +28 -0
  375. package/scripts/issue/issue-plan-cli.ts +151 -0
  376. package/scripts/issue/issue-priority.ts +151 -0
  377. package/scripts/issue/issue-rank.ts +7 -1
  378. package/scripts/issue/issue-read-cli.ts +3 -10
  379. package/scripts/issue/issue-read-main.ts +12 -0
  380. package/scripts/issue/issue-read.ts +29 -5
  381. package/scripts/issue/issue-release-cli.ts +0 -10
  382. package/scripts/issue/issue-release-main.ts +13 -0
  383. package/scripts/issue/issue-release.ts +7 -12
  384. package/scripts/issue/issue-sample-gate.ts +192 -0
  385. package/scripts/issue/issue-sample-source.ts +76 -0
  386. package/scripts/issue/issue-scout-cli.ts +19 -25
  387. package/scripts/issue/issue-scout-main.ts +14 -0
  388. package/scripts/issue/issue-state-cli.ts +0 -10
  389. package/scripts/issue/issue-state-main.ts +12 -0
  390. package/scripts/issue/issue-watch-diff.ts +56 -15
  391. package/scripts/issue/issue-watch.ts +2 -1
  392. package/scripts/issue/issue-wip.ts +2 -7
  393. package/scripts/issue/markdown-section.ts +19 -5
  394. package/scripts/issue/measure-rerun-cli.ts +13 -8
  395. package/scripts/issue/plan-consumers-cli.ts +39 -0
  396. package/scripts/issue/plan-consumers-main.ts +11 -0
  397. package/scripts/issue/plan-consumers-section.ts +55 -0
  398. package/scripts/issue/plan-consumers.ts +127 -0
  399. package/scripts/josh/agent-session-environment.ts +1 -1
  400. package/scripts/josh/command-usage.ts +82 -0
  401. package/scripts/josh/file-map-stamp.ts +49 -16
  402. package/scripts/josh/hook-decision.ts +32 -20
  403. package/scripts/josh/josh-command-map.ts +6 -1
  404. package/scripts/josh/josh-command-types.ts +65 -13
  405. package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
  406. package/scripts/josh/josh-commands-ai.ts +169 -157
  407. package/scripts/josh/josh-commands-backlog.ts +82 -16
  408. package/scripts/josh/josh-commands-clone.ts +1 -0
  409. package/scripts/josh/josh-commands-development.ts +111 -71
  410. package/scripts/josh/josh-commands-document.ts +43 -1
  411. package/scripts/josh/josh-commands-epic.ts +171 -0
  412. package/scripts/josh/josh-commands-hooks.ts +31 -2
  413. package/scripts/josh/josh-commands-issue-write.ts +181 -0
  414. package/scripts/josh/josh-commands-issue.ts +124 -24
  415. package/scripts/josh/josh-commands-lane.ts +112 -2
  416. package/scripts/josh/josh-commands-lint.ts +19 -8
  417. package/scripts/josh/josh-commands-maintenance.ts +112 -4
  418. package/scripts/josh/josh-commands-pause.ts +29 -0
  419. package/scripts/josh/josh-commands-progress.ts +87 -0
  420. package/scripts/josh/josh-commands-project.ts +138 -9
  421. package/scripts/josh/josh-commands-review.ts +124 -0
  422. package/scripts/josh/josh-commands-run.ts +211 -23
  423. package/scripts/josh/josh-commands-ship.ts +169 -0
  424. package/scripts/josh/josh-commands-split.ts +9 -0
  425. package/scripts/josh/josh-commands-versioning.ts +49 -2
  426. package/scripts/josh/josh-commands-workflow.ts +149 -6
  427. package/scripts/josh/josh-logic.ts +11 -27
  428. package/scripts/josh/josh.ts +14 -5
  429. package/scripts/josh/package-directory.ts +18 -0
  430. package/scripts/josh/process-identity.ts +13 -4
  431. package/scripts/josh/session-language-cli.ts +4 -8
  432. package/scripts/josh/session-language-main.ts +13 -0
  433. package/scripts/josh/session-language.ts +6 -1
  434. package/scripts/josh/shared-cache.ts +90 -0
  435. package/scripts/josh/stamp-file.ts +9 -15
  436. package/scripts/lane/lane-await.ts +51 -12
  437. package/scripts/lane/lane-cache.ts +5 -30
  438. package/scripts/lane/lane-capacity.ts +19 -22
  439. package/scripts/lane/lane-check-stats.ts +97 -0
  440. package/scripts/lane/lane-child-invocation.ts +43 -4
  441. package/scripts/lane/lane-cli.ts +15 -5
  442. package/scripts/lane/lane-close.ts +86 -18
  443. package/scripts/lane/lane-core-wait-stats.ts +66 -0
  444. package/scripts/lane/lane-dispatch.ts +27 -6
  445. package/scripts/lane/lane-gap-stats.ts +156 -0
  446. package/scripts/lane/lane-guard-policy.ts +2 -2
  447. package/scripts/lane/lane-handoff.ts +76 -1
  448. package/scripts/lane/lane-held-stats.ts +129 -0
  449. package/scripts/lane/lane-install.ts +16 -15
  450. package/scripts/lane/lane-launch-cli.ts +0 -9
  451. package/scripts/lane/lane-launch-main.ts +12 -0
  452. package/scripts/lane/lane-ledger-schema.ts +266 -0
  453. package/scripts/lane/lane-ledger.ts +108 -97
  454. package/scripts/lane/lane-limit-cli.ts +19 -9
  455. package/scripts/lane/lane-measure-cli.ts +58 -10
  456. package/scripts/lane/lane-open.ts +9 -1
  457. package/scripts/lane/lane-parked.ts +3 -3
  458. package/scripts/lane/lane-pause-cli.ts +130 -0
  459. package/scripts/lane/lane-pause.ts +158 -0
  460. package/scripts/lane/lane-preserve.ts +29 -1
  461. package/scripts/lane/lane-process-table.ts +166 -0
  462. package/scripts/lane/lane-reap-settle.ts +124 -0
  463. package/scripts/lane/lane-reap.ts +50 -15
  464. package/scripts/lane/lane-registry.ts +33 -10
  465. package/scripts/lane/lane-residents.ts +162 -0
  466. package/scripts/lane/lane-restart.ts +26 -27
  467. package/scripts/lane/lane-round-two-stats.ts +49 -0
  468. package/scripts/lane/lane-sampler.ts +4 -0
  469. package/scripts/lane/lane-session-action.ts +160 -0
  470. package/scripts/lane/lane-session-broker.ts +134 -134
  471. package/scripts/lane/lane-snapshot-trace.ts +84 -0
  472. package/scripts/lane/lane-spans.ts +51 -0
  473. package/scripts/lane/lane-spent.ts +6 -3
  474. package/scripts/lane/lane-stage-stats.ts +7 -2
  475. package/scripts/lane/lane-state.ts +302 -0
  476. package/scripts/lane/lane-stats.ts +58 -4
  477. package/scripts/lane/lane-stop-stats.ts +113 -37
  478. package/scripts/lane/lane-test-related-stats.ts +127 -0
  479. package/scripts/lane/lane-transcript-calls.ts +145 -0
  480. package/scripts/lane/lane-transcript-stats.ts +168 -0
  481. package/scripts/lane/lane-vacant.ts +13 -3
  482. package/scripts/lane/lane-withdraw-cli.ts +72 -0
  483. package/scripts/lane/lane-withdraw.ts +183 -0
  484. package/scripts/lane/process-directories.ts +70 -0
  485. package/scripts/lane/process-lane-marks.ts +94 -0
  486. package/scripts/lib/atomic-write.ts +62 -0
  487. package/scripts/lib/buffered-process.ts +12 -5
  488. package/scripts/lib/cli-flags.ts +53 -0
  489. package/scripts/lib/figure-format.ts +63 -0
  490. package/scripts/lib/json-value.ts +9 -1
  491. package/scripts/lib/package-manifest.ts +35 -0
  492. package/scripts/lib/read-file.ts +3 -1
  493. package/scripts/lib/stamped-memo.ts +63 -0
  494. package/scripts/lib/stdout-on-stderr.ts +24 -0
  495. package/scripts/lib/timeouts.ts +9 -0
  496. package/scripts/lib/transcript-record.ts +91 -0
  497. package/scripts/lines/effective-limit.ts +1 -1
  498. package/scripts/lint/eslint-cache-dependencies.ts +145 -0
  499. package/scripts/lint/eslint-daemon.ts +265 -0
  500. package/scripts/lint/format.ts +14 -5
  501. package/scripts/lint/import-graph.ts +279 -0
  502. package/scripts/lint/lint-gate-scope.ts +102 -0
  503. package/scripts/lint/lint-parallel-main.ts +19 -0
  504. package/scripts/lint/lint-parallel.ts +72 -33
  505. package/scripts/lint/lint-related-scope.ts +33 -24
  506. package/scripts/lint/lint-related.ts +38 -6
  507. package/scripts/notify/confirmation-options.ts +1 -2
  508. package/scripts/notify/telegram-notify.ts +20 -20
  509. package/scripts/notify/telegram-test-logic.ts +0 -1
  510. package/scripts/notify/telegram-test-main.ts +8 -0
  511. package/scripts/notify/telegram-test.ts +12 -11
  512. package/scripts/observations/observation-ledger.ts +13 -0
  513. package/scripts/observations/observations-flush-landing.ts +5 -3
  514. package/scripts/observations/observations-flush.ts +6 -1
  515. package/scripts/overrides/overrides-check.ts +2 -5
  516. package/scripts/overrides/overrides-files.ts +2 -1
  517. package/scripts/overrides/overrides-logic.ts +3 -6
  518. package/scripts/package/verify-optional-eslint-install.ts +8 -6
  519. package/scripts/propagate/propagate-publish.ts +2 -7
  520. package/scripts/propagate/propagate-targets.ts +4 -12
  521. package/scripts/refactor/import-graph.ts +9 -7
  522. package/scripts/release/github-release-runs.ts +17 -6
  523. package/scripts/release/release-approval-prune.ts +18 -0
  524. package/scripts/release/release-history.ts +1 -3
  525. package/scripts/release/release-progress.ts +42 -22
  526. package/scripts/release/release-publish-run.ts +39 -0
  527. package/scripts/release/release-publish.ts +6 -6
  528. package/scripts/release/release-scope-cli.ts +0 -10
  529. package/scripts/release/release-scope-main.ts +12 -0
  530. package/scripts/repo/repo-setting.ts +3 -6
  531. package/scripts/repo/required-checks-logic.ts +6 -15
  532. package/scripts/report/report-format-reference.ts +4 -0
  533. package/scripts/report/report-labels.ts +155 -0
  534. package/scripts/report/report-lint-cli.ts +3 -0
  535. package/scripts/report/report-lint.ts +85 -110
  536. package/scripts/report/report-template-cli.ts +59 -0
  537. package/scripts/report/report-template.ts +112 -0
  538. package/scripts/review/acceptance-map-check.ts +61 -0
  539. package/scripts/review/acceptance-map.ts +206 -0
  540. package/scripts/review/removed-tests-check.ts +86 -0
  541. package/scripts/review/removed-tests.ts +149 -0
  542. package/scripts/review/review-brief-cli.ts +82 -16
  543. package/scripts/review/review-brief-main.ts +12 -0
  544. package/scripts/review/review-brief.ts +31 -3
  545. package/scripts/review/review-code-tree.ts +10 -6
  546. package/scripts/review/review-comment-round.ts +26 -8
  547. package/scripts/review/review-finding-ledger.ts +30 -15
  548. package/scripts/review/review-interaction.ts +94 -0
  549. package/scripts/review/review-readers-scan.ts +163 -0
  550. package/scripts/review/review-record-cli.ts +69 -30
  551. package/scripts/review/review-record-main.ts +12 -0
  552. package/scripts/review/review-round-one-blobs.ts +221 -0
  553. package/scripts/review/review-round2-cli.ts +49 -12
  554. package/scripts/review/review-round2.ts +80 -12
  555. package/scripts/review/review-stamps.ts +19 -1
  556. package/scripts/review/review-stop-log.ts +96 -0
  557. package/scripts/review/review-stops-cli.ts +85 -0
  558. package/scripts/review/review-tree.ts +6 -17
  559. package/scripts/review/review-untouched-readers.ts +146 -0
  560. package/scripts/review/test-titles.ts +118 -0
  561. package/scripts/rules/agent-model.ts +67 -0
  562. package/scripts/rules/bash-triggers.ts +46 -3
  563. package/scripts/rules/decision-oracle-batch.ts +9 -1
  564. package/scripts/rules/decision-oracle.ts +2 -2
  565. package/scripts/rules/delivered-rules.ts +90 -3
  566. package/scripts/rules/destructive-command.ts +8 -1
  567. package/scripts/rules/direct-filing.ts +10 -2
  568. package/scripts/rules/direct-issue-comment.ts +117 -0
  569. package/scripts/rules/direct-pr-create.ts +69 -3
  570. package/scripts/rules/early-heartbeat.ts +2 -1
  571. package/scripts/rules/file-body.ts +7 -0
  572. package/scripts/rules/filing-cap.ts +8 -0
  573. package/scripts/rules/firing-point.ts +6 -5
  574. package/scripts/rules/git-argv.ts +72 -14
  575. package/scripts/rules/git-force.ts +12 -2
  576. package/scripts/rules/guard-remedy.ts +121 -0
  577. package/scripts/rules/implementation-cut-verdict.ts +1 -1
  578. package/scripts/rules/implementation-cut.ts +11 -3
  579. package/scripts/rules/index-guard.ts +8 -1
  580. package/scripts/rules/issue-comments.ts +76 -7
  581. package/scripts/rules/josh-git-bare.ts +7 -0
  582. package/scripts/rules/lane-background.ts +67 -25
  583. package/scripts/rules/lane-carry-conflict.ts +6 -0
  584. package/scripts/rules/lane-direct-tool.ts +74 -0
  585. package/scripts/rules/lane-interactive-ask.ts +9 -2
  586. package/scripts/rules/lane-park.ts +45 -23
  587. package/scripts/rules/lane-split-park.ts +10 -2
  588. package/scripts/rules/lane-switch-main.ts +7 -0
  589. package/scripts/rules/last-prompt.ts +50 -5
  590. package/scripts/rules/oracle-consulted.ts +10 -0
  591. package/scripts/rules/oracle-firing.ts +1 -0
  592. package/scripts/rules/oracle-list-cli.ts +7 -0
  593. package/scripts/rules/permission-guards.ts +3 -0
  594. package/scripts/rules/piped-verification.ts +4 -2
  595. package/scripts/rules/poll-loop.ts +7 -0
  596. package/scripts/rules/pr-merge.ts +123 -0
  597. package/scripts/rules/protected-files.ts +32 -5
  598. package/scripts/rules/raw-field-body.ts +6 -0
  599. package/scripts/rules/rule-body-guard.ts +8 -0
  600. package/scripts/rules/rule-list.ts +12 -28
  601. package/scripts/rules/rule-rewrite.ts +114 -0
  602. package/scripts/rules/rule-value-cache.ts +4 -9
  603. package/scripts/rules/rule-value-cli.ts +51 -32
  604. package/scripts/rules/rule-value.ts +8 -2
  605. package/scripts/rules/shell-segments.ts +50 -0
  606. package/scripts/rules/stop-decision.ts +77 -0
  607. package/scripts/rules/stop-rule-rows.ts +64 -0
  608. package/scripts/rules/stop-rules.ts +150 -51
  609. package/scripts/rules/tail-commands.ts +15 -1
  610. package/scripts/rules/test-declared-commit.ts +11 -1
  611. package/scripts/rules/third-party-write.ts +7 -0
  612. package/scripts/rules/timed-rerun.ts +69 -0
  613. package/scripts/rules/worktree-guard.ts +13 -3
  614. package/scripts/run/board/run-board-app-name.ts +23 -0
  615. package/scripts/run/board/run-board-cli.ts +65 -30
  616. package/scripts/run/board/run-board-closed.ts +8 -2
  617. package/scripts/run/board/run-board-earlier.ts +94 -0
  618. package/scripts/run/board/run-board-ending-reason.ts +67 -0
  619. package/scripts/run/board/run-board-estimate-schedule.ts +103 -0
  620. package/scripts/run/board/run-board-estimate.ts +98 -0
  621. package/scripts/run/board/run-board-fit.ts +153 -36
  622. package/scripts/run/board/run-board-fold.ts +123 -0
  623. package/scripts/run/board/run-board-fresh.ts +2 -2
  624. package/scripts/run/board/run-board-gather-live.ts +29 -0
  625. package/scripts/run/board/run-board-gather-thread.ts +189 -0
  626. package/scripts/run/board/run-board-gather-worker.ts +29 -0
  627. package/scripts/run/board/run-board-gather.ts +187 -0
  628. package/scripts/run/board/run-board-github.ts +119 -31
  629. package/scripts/run/board/run-board-header.ts +86 -21
  630. package/scripts/run/board/run-board-keys.ts +58 -0
  631. package/scripts/run/board/run-board-kind.ts +20 -6
  632. package/scripts/run/board/run-board-labels.ts +118 -71
  633. package/scripts/run/board/run-board-lane-state.ts +109 -0
  634. package/scripts/run/board/run-board-lane-time.ts +122 -0
  635. package/scripts/run/board/run-board-layout.ts +240 -61
  636. package/scripts/run/board/run-board-length.ts +52 -0
  637. package/scripts/run/board/run-board-machine.ts +8 -4
  638. package/scripts/run/board/run-board-main.ts +12 -0
  639. package/scripts/run/board/run-board-notes.ts +52 -31
  640. package/scripts/run/board/run-board-now.ts +1 -1
  641. package/scripts/run/board/run-board-operation.ts +15 -33
  642. package/scripts/run/board/run-board-phase.ts +1 -1
  643. package/scripts/run/board/run-board-plan-shared.ts +115 -0
  644. package/scripts/run/board/run-board-plan.ts +55 -3
  645. package/scripts/run/board/run-board-planning.ts +45 -0
  646. package/scripts/run/board/run-board-priority.ts +44 -0
  647. package/scripts/run/board/run-board-process-groups.ts +195 -0
  648. package/scripts/run/board/run-board-read.ts +153 -13
  649. package/scripts/run/board/run-board-reason.ts +238 -45
  650. package/scripts/run/board/run-board-released.ts +35 -0
  651. package/scripts/run/board/run-board-render-checks.ts +39 -5
  652. package/scripts/run/board/run-board-render-condition.ts +96 -0
  653. package/scripts/run/board/run-board-render-drawn.ts +67 -0
  654. package/scripts/run/board/run-board-render-foot.ts +59 -0
  655. package/scripts/run/board/run-board-render-icon.ts +35 -0
  656. package/scripts/run/board/run-board-render-lanes.ts +145 -0
  657. package/scripts/run/board/run-board-render-lead.ts +80 -0
  658. package/scripts/run/board/run-board-render-legend.ts +117 -47
  659. package/scripts/run/board/run-board-render-notes.ts +156 -29
  660. package/scripts/run/board/run-board-render-processes.ts +196 -0
  661. package/scripts/run/board/run-board-render-section.ts +119 -0
  662. package/scripts/run/board/run-board-render-slot.ts +3 -36
  663. package/scripts/run/board/run-board-render-tail.ts +115 -48
  664. package/scripts/run/board/run-board-render-time.ts +56 -0
  665. package/scripts/run/board/run-board-render-title.ts +117 -24
  666. package/scripts/run/board/run-board-render-waits.ts +125 -0
  667. package/scripts/run/board/run-board-render.ts +206 -259
  668. package/scripts/run/board/run-board-roots.ts +54 -0
  669. package/scripts/run/board/run-board-row-yield.ts +10 -4
  670. package/scripts/run/board/run-board-setup.ts +1 -12
  671. package/scripts/run/board/run-board-snapshot.ts +111 -0
  672. package/scripts/run/board/run-board-spin.ts +2 -2
  673. package/scripts/run/board/run-board-state.ts +23 -29
  674. package/scripts/run/board/run-board-status.ts +206 -79
  675. package/scripts/run/board/run-board-thanks-read.ts +2 -2
  676. package/scripts/run/board/run-board-tick.ts +123 -104
  677. package/scripts/run/board/run-board-usage-board.ts +78 -0
  678. package/scripts/run/board/run-board-usage-lanes.ts +113 -0
  679. package/scripts/run/board/run-board-usage-listing.ts +93 -0
  680. package/scripts/run/board/run-board-usage-read.ts +120 -150
  681. package/scripts/run/board/run-board-usage-rusage.ts +19 -7
  682. package/scripts/run/board/run-board-usage-text.ts +139 -51
  683. package/scripts/run/board/run-board-usage-top.ts +102 -0
  684. package/scripts/run/board/run-board-usage.ts +89 -72
  685. package/scripts/run/board/run-board-usual.ts +20 -9
  686. package/scripts/run/carry/run-carry-args.ts +4 -7
  687. package/scripts/run/carry/run-carry-conversation.ts +1 -1
  688. package/scripts/run/carry/run-carry.ts +9 -4
  689. package/scripts/run/cut/run-cut-cli.ts +3 -2
  690. package/scripts/run/cut/run-cut-handoff.ts +2 -2
  691. package/scripts/run/cut/run-cut-report.ts +16 -0
  692. package/scripts/run/detached-launch.ts +23 -4
  693. package/scripts/run/entry/run-entry-cli.ts +8 -1
  694. package/scripts/run/event/run-event-cli.ts +1 -5
  695. package/scripts/run/event/run-event-filed.ts +12 -6
  696. package/scripts/run/event/run-event-follow.ts +2 -3
  697. package/scripts/run/event/run-event-render.ts +7 -10
  698. package/scripts/run/event/run-event-scope.ts +20 -2
  699. package/scripts/run/event/run-event-stream-emit.ts +78 -11
  700. package/scripts/run/event/run-event-stream.ts +37 -7
  701. package/scripts/run/hold/run-hold-adopt.ts +65 -0
  702. package/scripts/run/hold/run-hold-cli.ts +93 -22
  703. package/scripts/run/hold/run-hold-main.ts +12 -0
  704. package/scripts/run/hold/run-hold-member.ts +37 -0
  705. package/scripts/run/hold/run-hold-session.ts +46 -0
  706. package/scripts/run/hold/run-hold.ts +7 -1
  707. package/scripts/run/hold/run-stop-notify.ts +183 -0
  708. package/scripts/run/launch-priority.ts +32 -0
  709. package/scripts/run/merge/run-merge-auth.ts +31 -0
  710. package/scripts/run/merge/run-merge-cli.ts +72 -107
  711. package/scripts/run/merge/run-merge-close.ts +74 -0
  712. package/scripts/run/merge/run-merge-collect.ts +6 -13
  713. package/scripts/run/merge/run-merge-driver.ts +71 -0
  714. package/scripts/run/merge/run-merge-main.ts +12 -0
  715. package/scripts/run/merge/run-merge-outcome.ts +23 -0
  716. package/scripts/run/merge/run-merge-restart.ts +39 -0
  717. package/scripts/run/merge/run-merge-ship.ts +20 -4
  718. package/scripts/run/merge/run-merge-signals.ts +123 -0
  719. package/scripts/run/merge/run-merge-steps.ts +128 -83
  720. package/scripts/run/merge/run-merge.ts +53 -40
  721. package/scripts/run/park/run-park-cli.ts +91 -0
  722. package/scripts/run/park/run-park.ts +88 -0
  723. package/scripts/run/park/run-stalled.ts +68 -0
  724. package/scripts/run/pause/run-pause-cli.ts +73 -0
  725. package/scripts/run/pause/run-pause.ts +251 -0
  726. package/scripts/run/progress/run-progress-cli.ts +4 -12
  727. package/scripts/run/progress/run-progress-clock.ts +1 -1
  728. package/scripts/run/progress/run-progress-config.ts +6 -14
  729. package/scripts/run/progress/run-progress-main.ts +12 -0
  730. package/scripts/run/progress/run-progress.ts +1 -4
  731. package/scripts/run/review/run-review.ts +2 -1
  732. package/scripts/run/run-ending.ts +1 -0
  733. package/scripts/run/run-invocation.ts +5 -6
  734. package/scripts/run/run-liveness-cli.ts +6 -8
  735. package/scripts/run/run-liveness.ts +61 -30
  736. package/scripts/run/run-next.ts +1 -1
  737. package/scripts/run/run-parent-cut-hook.ts +2 -2
  738. package/scripts/run/run-poll-hook.ts +157 -0
  739. package/scripts/run/run-preflight.ts +18 -3
  740. package/scripts/run/run-prep-cli.ts +1 -10
  741. package/scripts/run/run-prep-locate.ts +7 -50
  742. package/scripts/run/run-prep-main.ts +12 -0
  743. package/scripts/run/run-prep.ts +6 -0
  744. package/scripts/run/run-report-cli.ts +101 -13
  745. package/scripts/run/run-report-handoff.ts +114 -0
  746. package/scripts/run/run-step-cli.ts +22 -15
  747. package/scripts/run/run-step-section.ts +85 -0
  748. package/scripts/run/run-step.ts +1 -1
  749. package/scripts/run/run-stranded-detect.ts +13 -0
  750. package/scripts/run/run-watcher-guard-cli.ts +1 -1
  751. package/scripts/run/run-watcher-guard.ts +1 -1
  752. package/scripts/run/ship/run-ship-args.ts +121 -0
  753. package/scripts/run/ship/run-ship-body-draft.ts +110 -0
  754. package/scripts/run/ship/run-ship-cli.ts +67 -151
  755. package/scripts/run/ship/run-ship-detach.ts +27 -7
  756. package/scripts/run/ship/run-ship-infra-retry.ts +59 -0
  757. package/scripts/run/ship/run-ship-next.ts +27 -3
  758. package/scripts/run/ship/run-ship-overlap.ts +232 -0
  759. package/scripts/run/ship/run-ship-place.ts +96 -0
  760. package/scripts/run/ship/run-ship-pre-detach-timed.ts +43 -0
  761. package/scripts/run/ship/run-ship-pre-detach.ts +102 -27
  762. package/scripts/run/ship/run-ship-preflight.ts +161 -30
  763. package/scripts/run/ship/run-ship-probe.ts +11 -3
  764. package/scripts/run/ship/run-ship-relaunch-cap.ts +70 -0
  765. package/scripts/run/ship/run-ship-removed-rows.ts +61 -0
  766. package/scripts/run/ship/run-ship-return.ts +123 -15
  767. package/scripts/run/ship/run-ship-review-steps.ts +105 -149
  768. package/scripts/run/ship/run-ship-review.ts +73 -6
  769. package/scripts/run/ship/run-ship-reviewer.ts +207 -0
  770. package/scripts/run/ship/run-ship-stage.ts +55 -6
  771. package/scripts/run/ship/run-ship-steps.ts +46 -15
  772. package/scripts/run/ship/run-ship-stop-cause.ts +135 -0
  773. package/scripts/run/ship/run-ship-stop-context.ts +206 -0
  774. package/scripts/run/ship/run-ship-stop-text.ts +11 -6
  775. package/scripts/run/ship/run-ship-sync.ts +57 -12
  776. package/scripts/run/ship/run-ship.ts +30 -2
  777. package/scripts/run/tidy/run-tidy-cli.ts +0 -4
  778. package/scripts/run/tidy/run-tidy-lanes.ts +3 -0
  779. package/scripts/run/tidy/run-tidy-main.ts +8 -0
  780. package/scripts/run/wake/run-wake-cli.ts +119 -100
  781. package/scripts/run/wake/run-wake-code.ts +83 -0
  782. package/scripts/run/wake/run-wake-driver.ts +19 -8
  783. package/scripts/run/wake/run-wake-loop.ts +34 -3
  784. package/scripts/run/wake/run-wake-main.ts +13 -0
  785. package/scripts/run/wake/run-wake-ports.ts +90 -0
  786. package/scripts/run/wake/run-wake-takeover.ts +66 -0
  787. package/scripts/run/wake/run-wake.ts +2 -1
  788. package/scripts/safe-chain/pack-hook.ts +2 -2
  789. package/scripts/safe-chain/preinstall-command.ts +2 -1
  790. package/scripts/safe-chain/project-config.ts +3 -9
  791. package/scripts/security/security-audit-main.ts +8 -0
  792. package/scripts/security/security-audit-provision-logic.ts +0 -11
  793. package/scripts/security/security-audit-provision-main.ts +12 -0
  794. package/scripts/security/security-audit-provision.ts +11 -26
  795. package/scripts/security/security-audit.ts +6 -7
  796. package/scripts/self-sync-guard/self-sync-guard-logic.ts +6 -13
  797. package/scripts/split/split-assess-cli.ts +2 -2
  798. package/scripts/split/split-assess.ts +15 -0
  799. package/scripts/split/split-measure.ts +65 -0
  800. package/scripts/sync/claude-settings-merge.ts +8 -15
  801. package/scripts/sync/directory-copy-guard.ts +4 -9
  802. package/scripts/sync/file-content.ts +78 -8
  803. package/scripts/sync/sync-ai-files.ts +3 -5
  804. package/scripts/sync/sync-configs.ts +11 -23
  805. package/scripts/sync/sync-hook-safety.ts +4 -10
  806. package/scripts/sync/sync-main.ts +11 -0
  807. package/scripts/sync/sync.ts +25 -37
  808. package/scripts/test/test-declared-changed.ts +2 -2
  809. package/scripts/test/test-declared.ts +1 -1
  810. package/scripts/test/test-e2e-guard.ts +55 -6
  811. package/scripts/test/test-e2e-stamp.ts +38 -0
  812. package/scripts/test/test-pinned-logic.ts +145 -0
  813. package/scripts/test/test-pinned-main.ts +78 -0
  814. package/scripts/test/test-pinned.ts +100 -0
  815. package/scripts/test/test-read-map.ts +264 -0
  816. package/scripts/test/test-read-recording.ts +91 -0
  817. package/scripts/test/test-read-trace.ts +148 -0
  818. package/scripts/test/test-red-main.ts +12 -0
  819. package/scripts/test/test-red.ts +12 -30
  820. package/scripts/test/test-related-main.ts +18 -0
  821. package/scripts/test/test-related-record.ts +119 -0
  822. package/scripts/test/test-related-scope.ts +229 -43
  823. package/scripts/test/test-related.ts +300 -22
  824. package/scripts/test/test-unit-guard-main.ts +15 -0
  825. package/scripts/test/test-unit-guard.ts +54 -21
  826. package/scripts/test/unit-count-file.ts +37 -0
  827. package/scripts/test/unit-run-marker.ts +162 -0
  828. package/scripts/test/unit-setup-files.ts +51 -0
  829. package/scripts/test/unit-worker-share.ts +71 -137
  830. package/scripts/test/whole-suite-files.ts +63 -0
  831. package/scripts/time-runtime/time-background.ts +20 -2
  832. package/scripts/time-runtime/time-bundles.ts +4 -3
  833. package/scripts/time-runtime/time-density-hook.ts +8 -6
  834. package/scripts/time-runtime/time-followup-stage.ts +1 -3
  835. package/scripts/time-runtime/time-format.ts +5 -28
  836. package/scripts/time-runtime/time-markers.ts +10 -1
  837. package/scripts/time-runtime/time-shell.ts +126 -14
  838. package/scripts/time-runtime/time-spans.ts +1 -0
  839. package/scripts/time-runtime/time-tool-call.ts +7 -0
  840. package/scripts/time-runtime/time-transcript-line.ts +49 -62
  841. package/scripts/uninstall/uninstall.ts +1 -1
  842. package/scripts/version/bump-version-main.ts +12 -0
  843. package/scripts/version/bump-version.ts +25 -25
  844. package/scripts/version/effective-upstream.ts +6 -12
  845. package/scripts/version/latest-corepack.ts +17 -32
  846. package/scripts/version/latest-if-required-cli.ts +93 -0
  847. package/scripts/version/latest-lane-guard-main.ts +8 -0
  848. package/scripts/version/latest-lane-guard.ts +0 -4
  849. package/scripts/version/latest-scope-cli.ts +0 -9
  850. package/scripts/version/latest-scope-main.ts +12 -0
  851. package/scripts/version/latest-update.ts +5 -5
  852. package/scripts/version/npm-registry.ts +44 -6
  853. package/scripts/version/publishable-range-check.ts +5 -16
  854. package/scripts/version/release-age.ts +1 -1
  855. package/scripts/version/release-hold.ts +1 -1
  856. package/scripts/version/release-window.ts +38 -0
  857. package/scripts/version/running-binary.ts +1 -1
  858. package/scripts/version/safe-chain-version-update.ts +3 -8
  859. package/scripts/version/version-targets.ts +6 -28
  860. package/templates/dependabot.yml +29 -0
  861. package/templates/gitignore +10 -3
  862. package/templates/pnpm-workspace.basic.yaml +1 -1
  863. package/templates/sonar-project.properties +3 -2
  864. package/templates/workflows/ci.yml +12 -4
  865. package/templates/workflows/github-release.yml +4 -0
  866. package/tsconfig.sonar.json +1 -1
  867. package/.ncurc.json +0 -3
  868. package/dist/hooks/batch-guard.js +0 -29
  869. package/dist/hooks/chunk-43ZHT22P.js +0 -3495
  870. package/dist/hooks/chunk-CDY4NFQG.js +0 -15
  871. package/dist/hooks/chunk-EUMACUK2.js +0 -2038
  872. package/dist/hooks/chunk-H5HVWYXK.js +0 -359
  873. package/dist/hooks/chunk-IIGFYXKC.js +0 -7104
  874. package/dist/hooks/chunk-IX6TTTI6.js +0 -95
  875. package/dist/hooks/chunk-J47HU5H5.js +0 -237
  876. package/dist/hooks/chunk-K4EOONYM.js +0 -45
  877. package/dist/hooks/chunk-K4LMBQC2.js +0 -68
  878. package/dist/hooks/chunk-SHGPANFB.js +0 -56
  879. package/dist/hooks/chunk-YHBZAJSV.js +0 -79
  880. package/dist/hooks/chunk-YYPI7SJZ.js +0 -131
  881. package/dist/hooks/duplicate-read-guard.js +0 -30
  882. package/dist/hooks/investigation-guard.js +0 -32
  883. package/scripts/backlog/backlog-stalled-cli.ts +0 -30
  884. package/scripts/cost-runtime/cost-format.ts +0 -29
  885. package/scripts/init/basic-path-migration.ts +0 -24
  886. package/scripts/issue/issue-backlinks-cli.ts +0 -93
  887. package/scripts/josh/josh-commands-guard.ts +0 -38
  888. package/scripts/lint/cross-file-recheck.ts +0 -155
  889. package/scripts/registry-migration/migrate-logic.ts +0 -237
  890. package/scripts/registry-migration/migrate.ts +0 -292
  891. package/scripts/registry-migration/user-npmrc.ts +0 -15
  892. package/scripts/rules/rule-guard.ts +0 -23
  893. package/scripts/rules/rule-registry-rows.ts +0 -282
  894. package/scripts/rules/rule-registry.ts +0 -109
  895. package/scripts/run/run-stranded-cli.ts +0 -27
@@ -0,0 +1,264 @@
1
+ import { readdirSync, readFileSync, rmSync, statSync } from 'node:fs'
2
+ import path from 'node:path'
3
+ import { git_common_directory } from '#scripts/git/git-common-directory'
4
+ import { atomic_write } from '#scripts/lib/atomic-write'
5
+ import { json_value } from '#scripts/lib/json-value'
6
+ import { test_read_trace, type ReadRecords } from './test-read-trace'
7
+
8
+ // The test-read map: for every repository path a full unit run read, the modules that read it.
9
+ // `josh test:related` resolves a changed non-code file through it to the code files `vitest related`
10
+ // can walk, so a changed document runs the tests that read it rather than the whole suite.
11
+ //
12
+ // **The map is valid against the tree it was recorded on, and only that tree.** It records the
13
+ // commit and the files that differed from it, so the change a narrowing reads is the change since
14
+ // then. A tree whose own code changed what it reads has changed that code, and `vitest related`
15
+ // runs the tests importing it. **It lives in the git common directory**, which every lane worktree of
16
+ // one clone shares along with the commits it names, so one lane's full run narrows the next lane's.
17
+ // **One file per version** (joshuafolkken/kit#4423): a lane on an older kit writing its map leaves a
18
+ // newer lane's map in place, so a version bump no longer sends either to the whole suite.
19
+
20
+ interface ReadMap {
21
+ version: number
22
+ commit: string
23
+ // The files that differed from `commit` when the map was recorded, each with the digest of its
24
+ // content then (`input_fingerprint.of_files`), so one whose content has not moved since does not count as changed
25
+ // (joshuafolkken/kit#4425).
26
+ dirty: Record<string, string>
27
+ // The directories `commit` holds, so a directory new since then is told apart from one no test
28
+ // read — the map's own keys cannot say which, since an unread directory has none.
29
+ directories: Array<string>
30
+ readers: ReadRecords
31
+ }
32
+
33
+ // Bumped whenever the shape, what a reader means or how `dirty` is digested changes, so a map an older
34
+ // kit wrote reads as no map at all and the next full run writes it afresh. 6: `dirty` is
35
+ // `input-fingerprint.ts`'s digest of every changed file (joshuafolkken/kit#4497).
36
+ const MAP_VERSION = 6
37
+
38
+ const MAP_DIRECTORY = 'josh'
39
+ const MAP_FILE_STEM = 'test-read-map'
40
+ const RECORD_EXTENSION = '.json'
41
+
42
+ // A map file of another version no lane has written for this long belongs to no kit still running,
43
+ // and is removed by the next write: one week.
44
+ const STALE_AFTER_MS = 604_800_000
45
+
46
+ type ReadPair = [string, string]
47
+
48
+ function record_pairs(record: ReadRecords): Array<ReadPair> {
49
+ return Object.entries(record).flatMap(([read_path, readers]) =>
50
+ readers.map((reader): ReadPair => [read_path, reader]),
51
+ )
52
+ }
53
+
54
+ function merge_records(records: ReadonlyArray<ReadRecords>): ReadRecords {
55
+ const merged = new Map<string, Set<string>>()
56
+ const pairs = records.flatMap((record) => record_pairs(record))
57
+
58
+ for (const [read_path, reader] of pairs) {
59
+ test_read_trace.add_reader(merged, read_path, reader)
60
+ }
61
+
62
+ return test_read_trace.to_records(merged)
63
+ }
64
+
65
+ function is_object(value: unknown): value is object {
66
+ return typeof value === 'object' && value !== null
67
+ }
68
+
69
+ function is_string_array(value: unknown): value is Array<string> {
70
+ return Array.isArray(value) && value.every((entry) => typeof entry === 'string')
71
+ }
72
+
73
+ function is_read_records(value: unknown): value is ReadRecords {
74
+ return is_object(value) && Object.values(value).every(is_string_array)
75
+ }
76
+
77
+ function is_digest_record(value: unknown): value is Record<string, string> {
78
+ if (!is_object(value) || Array.isArray(value)) return false
79
+
80
+ return Object.values(value).every((digest) => typeof digest === 'string')
81
+ }
82
+
83
+ const FIELD_CHECKS: ReadonlyArray<[keyof ReadMap, (field: unknown) => boolean]> = [
84
+ ['version', (field) => field === MAP_VERSION],
85
+ ['commit', (field) => typeof field === 'string'],
86
+ ['dirty', is_digest_record],
87
+ ['directories', is_string_array],
88
+ ['readers', is_read_records],
89
+ ]
90
+
91
+ function is_read_map(value: unknown): value is ReadMap {
92
+ if (!is_object(value)) return false
93
+
94
+ return FIELD_CHECKS.every(([field, is_valid]) => is_valid(Reflect.get(value, field)))
95
+ }
96
+
97
+ // **The files whose content differs from the tree the map was recorded on** (joshuafolkken/kit#4425).
98
+ // `since` is every path that differs from `map.commit` now, and `current` the digest of every path
99
+ // that was dirty then. A path dirty then is changed only when its digest moved: counted by name, a
100
+ // lane's own change the map was recorded over read as changed on every later run, so a gate reused
101
+ // no green unit step whenever the lane held any code.
102
+ function changed_since_tree(
103
+ map: ReadMap,
104
+ since: ReadonlyArray<string>,
105
+ current: Readonly<Record<string, string>>,
106
+ ): Array<string> {
107
+ const fresh = since.filter((file) => !Object.hasOwn(map.dirty, file))
108
+ const moved = Object.entries(map.dirty)
109
+ .filter(([file, digest]) => current[file] !== digest)
110
+ .map(([file]) => file)
111
+
112
+ return [...new Set([...fresh, ...moved])]
113
+ }
114
+
115
+ function parse_map(text: string): ReadMap | undefined {
116
+ const value = json_value.parse_or_undefined(text)
117
+
118
+ return is_read_map(value) ? value : undefined
119
+ }
120
+
121
+ function parse_records(text: string): ReadRecords {
122
+ const value = json_value.parse_or_undefined(text)
123
+
124
+ return is_read_records(value) ? value : {}
125
+ }
126
+
127
+ // Innermost first, ending at the root `.`.
128
+ function directories_above(relative: string): Array<string> {
129
+ const parent = path.dirname(relative)
130
+
131
+ if (parent === relative) return []
132
+
133
+ return [parent, ...directories_above(parent)]
134
+ }
135
+
136
+ // The directories on the file's path the recorded commit did not hold, innermost first. The root
137
+ // always existed.
138
+ function created_directories(
139
+ directories: ReadonlyArray<string>,
140
+ recorded: ReadonlySet<string>,
141
+ ): Array<string> {
142
+ return directories.filter(
143
+ (directory) => directory !== test_read_trace.ROOT_ENTRY && !recorded.has(directory),
144
+ )
145
+ }
146
+
147
+ // A changed file is read by whoever read it, listed its own directory or walked any directory above
148
+ // it. A directory new since the recording is also a new entry in the listing above it and a probe of
149
+ // it that now answers differently; a directory that already existed reads the same to both, whatever
150
+ // changed deeper down.
151
+ function lookup_keys(relative: string, recorded: ReadonlySet<string>): Array<string> {
152
+ const directories = directories_above(relative)
153
+ const created = created_directories(directories, recorded)
154
+ const listed = [
155
+ directories[0] ?? test_read_trace.ROOT_ENTRY,
156
+ ...created.map((directory) => path.dirname(directory)),
157
+ ]
158
+
159
+ return [
160
+ relative,
161
+ ...created,
162
+ ...listed.map((directory) => test_read_trace.read_key(directory, 'listing')),
163
+ ...directories.map((directory) => test_read_trace.read_key(directory, 'walk')),
164
+ ]
165
+ }
166
+
167
+ function readers_of(map: ReadMap, relative: string): Array<string> {
168
+ const keys = lookup_keys(relative, new Set(map.directories))
169
+
170
+ return [...new Set(keys.flatMap((key) => map.readers[key] ?? []))]
171
+ }
172
+
173
+ // **A directory the recorded tree held, inside which no recorded test listed, walked or read any
174
+ // entry** (joshuafolkken/kit#4303). A file added to it since is one no test reads, as surely as one
175
+ // the tree already held there: a test that builds a path into it reads some file there, and one that
176
+ // enumerates it lists it, both of which leave a key whose directory is this one.
177
+ function in_unread_directory(map: ReadMap, relative: string): boolean {
178
+ const directory = path.dirname(relative)
179
+
180
+ if (!map.directories.includes(directory)) return false
181
+
182
+ return Object.keys(map.readers).every((key) => path.dirname(key) !== directory)
183
+ }
184
+
185
+ function map_path(root: string, version: number = MAP_VERSION): string | undefined {
186
+ const common = git_common_directory.repository(root)
187
+ const name = `${MAP_FILE_STEM}.v${String(version)}${RECORD_EXTENSION}`
188
+
189
+ return common === undefined ? undefined : path.join(common, MAP_DIRECTORY, name)
190
+ }
191
+
192
+ // Every version's map, the unversioned one kits before joshuafolkken/kit#4423 wrote included; a
193
+ // staging file ends in `.tmp`, not the extension.
194
+ function is_map_file(name: string): boolean {
195
+ return name.startsWith(MAP_FILE_STEM) && name.endsWith(RECORD_EXTENSION)
196
+ }
197
+
198
+ // A file another lane's write pruned meanwhile has no stat, and is not this write's to remove.
199
+ function is_stale(file_path: string, now: number): boolean {
200
+ const modified = statSync(file_path, { throwIfNoEntry: false })?.mtimeMs ?? now
201
+
202
+ return now - modified > STALE_AFTER_MS
203
+ }
204
+
205
+ // The map just written is never stale, so it survives its own prune.
206
+ function prune_stale_maps(directory: string): void {
207
+ const now = Date.now()
208
+ const maps = readdirSync(directory)
209
+ .filter((name) => is_map_file(name))
210
+ .map((name) => path.join(directory, name))
211
+
212
+ for (const file_path of maps) {
213
+ if (is_stale(file_path, now)) rmSync(file_path, { force: true })
214
+ }
215
+ }
216
+
217
+ function read_text(file_path: string): string | undefined {
218
+ try {
219
+ return readFileSync(file_path, 'utf8')
220
+ } catch {
221
+ return undefined
222
+ }
223
+ }
224
+
225
+ function read_map(root: string): ReadMap | undefined {
226
+ const file_path = map_path(root)
227
+ const text = file_path === undefined ? undefined : read_text(file_path)
228
+
229
+ return text === undefined ? undefined : parse_map(text)
230
+ }
231
+
232
+ // Written beside the target and renamed over it, so a lane reading the map while another lane
233
+ // replaces it reads one whole map or the other. It lands in its own version's file.
234
+ function write_map(root: string, map: ReadMap): void {
235
+ const file_path = map_path(root, map.version)
236
+
237
+ if (file_path === undefined) return
238
+
239
+ atomic_write.replace_file(file_path, JSON.stringify(map))
240
+ prune_stale_maps(path.dirname(file_path))
241
+ }
242
+
243
+ // Every worker writes its own files into the run's directory; this reads them all back.
244
+ function collect_records(directory: string): Array<ReadRecords> {
245
+ return readdirSync(directory)
246
+ .filter((name) => name.endsWith(RECORD_EXTENSION))
247
+ .map((name) => parse_records(read_text(path.join(directory, name)) ?? ''))
248
+ }
249
+
250
+ const test_read_map = {
251
+ MAP_VERSION,
252
+ changed_since_tree,
253
+ collect_records,
254
+ in_unread_directory,
255
+ map_path,
256
+ merge_records,
257
+ parse_map,
258
+ read_map,
259
+ readers_of,
260
+ write_map,
261
+ }
262
+
263
+ export type { ReadMap }
264
+ export { test_read_map }
@@ -0,0 +1,91 @@
1
+ import { mkdtempSync, rmSync } from 'node:fs'
2
+ import { tmpdir } from 'node:os'
3
+ import path from 'node:path'
4
+ import { input_fingerprint } from '#scripts/gate/input-fingerprint'
5
+ import { changed_paths } from '#scripts/git/changed-paths'
6
+ import { git_command } from '#scripts/git/git-command'
7
+ import { git_spawn } from '#scripts/git/git-spawn'
8
+ import { test_read_map, type ReadMap } from './test-read-map'
9
+ import { test_read_trace } from './test-read-trace'
10
+
11
+ // When a unit run records the test-read map, and how the records become one. **Only a run of the
12
+ // whole suite records**: a map is read as "nothing else reads this file", which a narrowed, sharded
13
+ // or filtered run cannot vouch for. **Only a green run replaces the map**: a failed test may have
14
+ // stopped before the read it would have made.
15
+
16
+ type RecordingEnvironment = Record<string, string>
17
+
18
+ const RUN_SUBCOMMAND = 'run'
19
+
20
+ // The one flag a whole-suite run still carries — the gate's worker cap, which sizes the run without
21
+ // narrowing it.
22
+ const WORKER_FLAG_PREFIX = '--maxWorkers'
23
+
24
+ const RECORD_DIRECTORY_PREFIX = 'josh-test-reads-'
25
+
26
+ function is_recordable(vitest_arguments: ReadonlyArray<string>): boolean {
27
+ const [subcommand, ...flags] = vitest_arguments
28
+
29
+ return subcommand === RUN_SUBCOMMAND && flags.every((flag) => flag.startsWith(WORKER_FLAG_PREFIX))
30
+ }
31
+
32
+ // Every directory the commit holds, NUL-separated so a name git would quote reads as itself.
33
+ async function commit_directories(commit: string): Promise<Array<string>> {
34
+ const output = await git_spawn.read(['ls-tree', '-r', '-d', '--name-only', '-z', commit])
35
+
36
+ return output.split('\0').filter((listed) => listed.length > 0)
37
+ }
38
+
39
+ type TreeSnapshot = Pick<ReadMap, 'commit' | 'dirty' | 'directories'>
40
+
41
+ // The tree the run read: the commit, every file that differed from it with its content's digest, and
42
+ // the directories it holds. **Read before the run starts**: a digest taken after it would vouch for
43
+ // an edit made while the tests ran as content they read.
44
+ async function tree_snapshot(root: string): Promise<TreeSnapshot> {
45
+ const commit = await git_command.head_commit()
46
+ const dirty = input_fingerprint.of_files(root, await changed_paths.read_changed_since(commit))
47
+
48
+ return { commit, dirty, directories: await commit_directories(commit) }
49
+ }
50
+
51
+ // A map that cannot be written — no git, a read-only common directory — leaves the previous map in
52
+ // place, and a narrowing over a stale map is refused by the commit it names.
53
+ function save_map(root: string, directory: string, snapshot: TreeSnapshot): void {
54
+ try {
55
+ const readers = test_read_map.merge_records(test_read_map.collect_records(directory))
56
+
57
+ test_read_map.write_map(root, { version: test_read_map.MAP_VERSION, ...snapshot, readers })
58
+ } catch {
59
+ // The previous map stays; the run's own result is unaffected.
60
+ }
61
+ }
62
+
63
+ async function with_read_recording(
64
+ root: string,
65
+ vitest_arguments: ReadonlyArray<string>,
66
+ run: (environment: RecordingEnvironment) => Promise<number>,
67
+ ): Promise<number> {
68
+ if (!is_recordable(vitest_arguments)) return await run({})
69
+
70
+ const directory = mkdtempSync(path.join(tmpdir(), RECORD_DIRECTORY_PREFIX))
71
+
72
+ try {
73
+ // Settled rather than awaited, so a tree git cannot read records no map and fails no run.
74
+ const [tree] = await Promise.allSettled([tree_snapshot(root)])
75
+ const exit_code = await run({
76
+ [test_read_trace.RECORD_DIRECTORY_KEY]: directory,
77
+ [test_read_trace.ROOT_KEY]: root,
78
+ })
79
+
80
+ if (exit_code === 0 && tree.status === 'fulfilled') save_map(root, directory, tree.value)
81
+
82
+ return exit_code
83
+ } finally {
84
+ rmSync(directory, { recursive: true, force: true })
85
+ }
86
+ }
87
+
88
+ const test_read_recording = { is_recordable, with_read_recording }
89
+
90
+ export type { RecordingEnvironment }
91
+ export { test_read_recording }
@@ -0,0 +1,148 @@
1
+ import path from 'node:path'
2
+ import { fileURLToPath } from 'node:url'
3
+
4
+ // What one recorded read says, decided without touching `fs`: which repository path was read, and
5
+ // which module read it. `test-read-capture.ts`, armed by the `test-read-recorder.ts` setup file,
6
+ // feeds this from inside every unit worker; everything here is pure so the decisions are testable without patching `fs`.
7
+ //
8
+ // **The reader is the outermost repository frame on the stack, not the test file alone.** Under
9
+ // `isolate: false` a module that reads a document at load time is evaluated once per worker, so its
10
+ // read lands on whichever test imported it first. Recording the module whose evaluation made the read
11
+ // lets `vitest related` widen the read to every test that imports it, on any worker. A read a test
12
+ // makes has the test outermost, so a shared helper it reads through — every test importing it — is
13
+ // never the reader (joshuafolkken/kit#4417). The test file is recorded beside it, because an async
14
+ // callback (a directory walk inside a dependency) leaves no repository frame at all.
15
+
16
+ type ReadRecords = Record<string, Array<string>>
17
+
18
+ // The worker setup file and the run that starts it agree on these two names and nothing else. They
19
+ // live here rather than beside the map because the setup file is loaded before any test's
20
+ // `vi.mock`: whatever it imports, no test can mock.
21
+ const RECORD_DIRECTORY_KEY = 'JOSH_TEST_READS_DIRECTORY'
22
+ const ROOT_KEY = 'JOSH_TEST_READS_ROOT'
23
+
24
+ const FILE_URL_PREFIX = 'file://'
25
+ const NODE_MODULES = 'node_modules'
26
+ const GIT_DIRECTORY = '.git'
27
+ const ROOT_ENTRY = '.'
28
+
29
+ // **What a read depends on is decided by the call, not by the path alone.** Reading or probing a
30
+ // path depends on that path; listing a directory depends on its direct entries; a recursive listing
31
+ // depends on everything beneath it. The two directory kinds are keyed with a glob-shaped suffix so
32
+ // the map keeps one shape: `scripts/*` is a listing of `scripts`, `scripts/**` a walk over it, and a
33
+ // listing of the root is `*`.
34
+ type ReadKind = 'path' | 'listing' | 'walk'
35
+
36
+ const LISTING_READS: ReadonlySet<string> = new Set([
37
+ 'readdir',
38
+ 'readdirSync',
39
+ 'opendir',
40
+ 'opendirSync',
41
+ ])
42
+
43
+ const KIND_SUFFIX: Record<Exclude<ReadKind, 'path'>, string> = { listing: '*', walk: '**' }
44
+
45
+ function is_recursive(options: unknown): boolean {
46
+ return (
47
+ typeof options === 'object' && options !== null && Reflect.get(options, 'recursive') === true
48
+ )
49
+ }
50
+
51
+ // The kind of read an `fs` call by this name makes, given its second argument.
52
+ function read_kind(name: string, options: unknown): ReadKind {
53
+ if (!LISTING_READS.has(name)) return 'path'
54
+
55
+ return is_recursive(options) ? 'walk' : 'listing'
56
+ }
57
+
58
+ function read_key(relative: string, kind: ReadKind): string {
59
+ return kind === 'path' ? relative : path.join(relative, KIND_SUFFIX[kind])
60
+ }
61
+
62
+ // The file a call site's script name points at — an absolute path or a `file://` URL — or
63
+ // `undefined` for a `node:` internal or an evaluated string.
64
+ function script_path(script_name: string): string | undefined {
65
+ if (script_name.startsWith(FILE_URL_PREFIX)) return fileURLToPath(script_name)
66
+
67
+ return path.isAbsolute(script_name) ? script_name : undefined
68
+ }
69
+
70
+ function is_outside(relative: string): boolean {
71
+ return relative.startsWith('..') || path.isAbsolute(relative)
72
+ }
73
+
74
+ function is_ignored(relative: string): boolean {
75
+ const segments = relative.split(path.sep)
76
+
77
+ return segments.includes(NODE_MODULES) || segments[0] === GIT_DIRECTORY
78
+ }
79
+
80
+ // A path relative to the root, or `undefined` when it lies outside it or inside a directory no test
81
+ // result depends on. The root itself is `.`.
82
+ function repository_path(root: string, file_path: string): string | undefined {
83
+ const relative = path.relative(root, file_path)
84
+
85
+ if (relative === '') return ROOT_ENTRY
86
+
87
+ return is_outside(relative) || is_ignored(relative) ? undefined : relative
88
+ }
89
+
90
+ // The path an `fs` call names. A descriptor or a buffer names no path this map can key on.
91
+ function read_target(argument: unknown, cwd: string): string | undefined {
92
+ if (typeof argument === 'string') return path.resolve(cwd, argument)
93
+ if (argument instanceof URL) return fileURLToPath(argument)
94
+
95
+ return undefined
96
+ }
97
+
98
+ interface ReaderQuery {
99
+ root: string
100
+ // The script name of every call site, innermost first.
101
+ scripts: ReadonlyArray<string>
102
+ // The recorder's own file, which is always the top frame and never the reader.
103
+ recorder: string
104
+ }
105
+
106
+ function frame_reader(query: ReaderQuery, script_name: string): string | undefined {
107
+ const file_path = script_path(script_name)
108
+
109
+ if (file_path === undefined || file_path === query.recorder) return undefined
110
+
111
+ const relative = repository_path(query.root, file_path)
112
+
113
+ return relative === ROOT_ENTRY ? undefined : relative
114
+ }
115
+
116
+ function stack_reader(query: ReaderQuery): string | undefined {
117
+ return query.scripts
118
+ .map((script_name) => frame_reader(query, script_name))
119
+ .findLast((reader) => reader !== undefined)
120
+ }
121
+
122
+ function add_reader(records: Map<string, Set<string>>, read_path: string, reader: string): void {
123
+ const readers = records.get(read_path) ?? new Set<string>()
124
+
125
+ readers.add(reader)
126
+ records.set(read_path, readers)
127
+ }
128
+
129
+ function to_records(records: ReadonlyMap<string, ReadonlySet<string>>): ReadRecords {
130
+ return Object.fromEntries([...records].map(([read_path, readers]) => [read_path, [...readers]]))
131
+ }
132
+
133
+ const test_read_trace = {
134
+ RECORD_DIRECTORY_KEY,
135
+ ROOT_ENTRY,
136
+ ROOT_KEY,
137
+ add_reader,
138
+ read_key,
139
+ read_kind,
140
+ read_target,
141
+ repository_path,
142
+ script_path,
143
+ stack_reader,
144
+ to_records,
145
+ }
146
+
147
+ export type { ReadKind, ReaderQuery, ReadRecords }
148
+ export { test_read_trace }
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env tsx
2
+ import { fileURLToPath } from 'node:url'
3
+ import { test_red } from './test-red'
4
+
5
+ // The `josh test:red` entry, kept apart from `test-red.ts` because `test-red-commit.ts` imports that
6
+ // one: a bundle is one file, so a main guard there would fire for every command that carries it
7
+ // (joshuafolkken/kit#4186).
8
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
9
+ const ARGV_OFFSET = 2
10
+
11
+ process.exitCode = await test_red.main(process.argv.slice(ARGV_OFFSET))
12
+ }
@@ -1,7 +1,6 @@
1
1
  import { existsSync } from 'node:fs'
2
- import { copyFile, mkdir, readFile } from 'node:fs/promises'
2
+ import { readFile, rm } from 'node:fs/promises'
3
3
  import path from 'node:path'
4
- import { fileURLToPath } from 'node:url'
5
4
  import { base_tree, type BaseTree } from '#scripts/git/base-tree'
6
5
  import { change_base } from '#scripts/git/change-base'
7
6
  import { changed_paths } from '#scripts/git/changed-paths'
@@ -16,7 +15,6 @@ import { test_red_logic, type RedVerdict } from './test-red-logic'
16
15
  // (`base-tree.ts`). The tests are copied in from the working tree, so what runs is the new test
17
16
  // against the old code.
18
17
 
19
- const ARGV_OFFSET = 2
20
18
  const TREE_PREFIX = 'josh-test-red-'
21
19
  const REPORT_NAME = 'report.json'
22
20
  const VITEST_BIN = path.join(base_tree.NODE_MODULES, '.bin', 'vitest')
@@ -33,22 +31,6 @@ function changed_tests(paths: ReadonlyArray<string>): Array<string> {
33
31
  return test_red_logic.unit_test_files(paths).filter((file) => existsSync(file))
34
32
  }
35
33
 
36
- async function copy_one(tree: string, file: string): Promise<void> {
37
- const target = path.join(tree, file)
38
-
39
- await mkdir(path.dirname(target), { recursive: true })
40
- await copyFile(file, target)
41
- }
42
-
43
- // Each file has its own target, and a recursive `mkdir` tolerates a sibling creating the same parent.
44
- async function copy_in(tree: string, files: ReadonlyArray<string>): Promise<void> {
45
- await Promise.all(
46
- files.map(async (file) => {
47
- await copy_one(tree, file)
48
- }),
49
- )
50
- }
51
-
52
34
  function reporter_arguments(report: string): Array<string> {
53
35
  // The plain `--outputFile`, not `--outputFile.json`: a config that sets `test.outputFile` as a string
54
36
  // wins over the keyed form, which would send the report into the tree and read every run `no-test`.
@@ -59,16 +41,20 @@ async function read_report(report: string): Promise<string> {
59
41
  return existsSync(report) ? await readFile(report, 'utf8') : ''
60
42
  }
61
43
 
62
- // The verdict of one run. `--passWithNoTests` keeps "the filter matched nothing" from reading as a
44
+ // The verdict of one run over `selection` — `run <files>`, or `related <file> --run` for
45
+ // `josh test:pinned`. `--passWithNoTests` keeps "the filter matched nothing" from reading as a
63
46
  // failure, and the JSON report — written beside the tree, never into it — says whether anything ran at
64
47
  // all, so a file the old config excludes is `no-test` rather than a `green` that refuses a correct fix.
65
- // A test that ran and broke, or a file that could not load against the old code, makes it `red`.
48
+ // A test that ran and broke, or a file that could not load against the old code, makes it `red`. The
49
+ // report is removed first, so a run that writes none never reads the one before it.
66
50
  async function verdict_in(
67
51
  { parent, tree }: BaseTree,
68
- files: ReadonlyArray<string>,
52
+ selection: ReadonlyArray<string>,
69
53
  ): Promise<RedVerdict> {
70
54
  const report = path.join(parent, REPORT_NAME)
71
- const vitest_args = ['run', '--passWithNoTests', ...reporter_arguments(report), ...files]
55
+ const vitest_args = [...selection, '--passWithNoTests', ...reporter_arguments(report)]
56
+
57
+ await rm(report, { force: true })
72
58
  const result = await execa(path.join(tree, VITEST_BIN), vitest_args, {
73
59
  cwd: tree,
74
60
  env: git_location_environment.location_free_environment(),
@@ -82,9 +68,9 @@ async function verdict_in(
82
68
 
83
69
  async function verdict_on(base: string, files: ReadonlyArray<string>): Promise<RedVerdict> {
84
70
  return await base_tree.with_tree(TREE_PREFIX, base, async (pre_fix) => {
85
- await copy_in(pre_fix.tree, files)
71
+ await base_tree.copy_in(pre_fix.tree, files)
86
72
 
87
- return await verdict_in(pre_fix, files)
73
+ return await verdict_in(pre_fix, ['run', ...files])
88
74
  })
89
75
  }
90
76
 
@@ -117,11 +103,7 @@ async function main(argv: ReadonlyArray<string>): Promise<number> {
117
103
  return 0
118
104
  }
119
105
 
120
- if (process.argv[1] === fileURLToPath(import.meta.url)) {
121
- process.exitCode = await main(process.argv.slice(ARGV_OFFSET))
122
- }
123
-
124
- const test_red = { run }
106
+ const test_red = { main, run, verdict_in }
125
107
 
126
108
  export type { RedRun }
127
109
  export { test_red }
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env tsx
2
+ import { fileURLToPath } from 'node:url'
3
+ import { changed_file_scope } from '#scripts/git/changed-file-scope'
4
+ import { run_ship_removed_rows } from '#scripts/run/ship/run-ship-removed-rows'
5
+ import { test_related } from './test-related'
6
+
7
+ // The `josh test:related` entry, kept apart from `test-related.ts` because `check-inputs.ts` imports
8
+ // that one: a bundle is one file, so a main guard there would fire for every command that carries it
9
+ // (joshuafolkken/kit#4186). A green run then shows the tests the change removed, the one place a run
10
+ // meets them before `josh ship` (joshuafolkken/kit#4563).
11
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
12
+ const exit_code = await test_related.run_related_tests(
13
+ process.argv.slice(changed_file_scope.ARGV_START),
14
+ )
15
+
16
+ if (exit_code === 0) await run_ship_removed_rows.surface()
17
+ process.exitCode = exit_code
18
+ }