@joshuafolkken/kit 1.1784.0 → 1.2114.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 (690) hide show
  1. package/.claude/agents/reviewer-verification.md +19 -0
  2. package/.claude/agents/reviewer.md +19 -0
  3. package/.claude/settings.json +5 -6
  4. package/.claude/skills/dependency-update/SKILL.md +9 -10
  5. package/.claude/skills/workflow-commands/SKILL.md +6 -6
  6. package/.claude/skills/workflow-commands/background-commands.md +8 -5
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +3 -1
  8. package/.claude/skills/workflow-commands/backlogrun-lanes.md +1 -1
  9. package/.claude/skills/workflow-commands/backlogrun-park.md +5 -2
  10. package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -3
  11. package/.claude/skills/workflow-commands/backlogrun-recovery.md +1 -1
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +3 -2
  13. package/.claude/skills/workflow-commands/backlogrun.md +1 -1
  14. package/.claude/skills/workflow-commands/chain-rule.md +41 -32
  15. package/.claude/skills/workflow-commands/delegation.md +6 -6
  16. package/.claude/skills/workflow-commands/entry-sequence.md +2 -2
  17. package/.claude/skills/workflow-commands/followup.md +7 -5
  18. package/.claude/skills/workflow-commands/fullrun-steps.md +6 -6
  19. package/.claude/skills/workflow-commands/fullrun.md +1 -1
  20. package/.claude/skills/workflow-commands/issue-comments.md +9 -4
  21. package/.claude/skills/workflow-commands/issue-fold-existing.md +2 -1
  22. package/.claude/skills/workflow-commands/kickoff.md +2 -2
  23. package/.claude/skills/workflow-commands/observation-filing.md +1 -1
  24. package/.claude/skills/workflow-commands/observation-ledger.md +6 -4
  25. package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -7
  26. package/.claude/skills/workflow-commands/prerequisite.md +3 -2
  27. package/.claude/skills/workflow-commands/retrospective.md +2 -2
  28. package/.claude/skills/workflow-commands/split-assessment.md +7 -5
  29. package/.codex/hooks.json +5 -5
  30. package/.github/actions/setup-pnpm/action.yml +9 -16
  31. package/.github/dependabot.yml +16 -0
  32. package/.github/workflows/auto-tag.yml +45 -0
  33. package/.github/workflows/ci.yml +155 -15
  34. package/.github/workflows/dependabot-auto-merge.yml +63 -4
  35. package/.github/workflows/production.yml +8 -0
  36. package/.github/workflows/publish.yml +59 -45
  37. package/.vscode/settings.json +19 -0
  38. package/CLAUDE.md +5 -12
  39. package/SECURITY.md +2 -2
  40. package/dist/CLAUDE.md +5 -12
  41. package/dist/commands/document-read-cli.js +2 -1
  42. package/dist/commands/document-section-main.js +2 -1
  43. package/dist/commands/read-set-cli.js +194 -134
  44. package/dist/commands/run-prep-main.js +9694 -10173
  45. package/dist/commands/run-step-cli.js +22138 -18285
  46. package/dist/hooks/audit-provision.js +23 -5
  47. package/dist/hooks/chunk-3GKE653K.js +6204 -0
  48. package/dist/hooks/chunk-45CJJOO7.js +1243 -0
  49. package/dist/hooks/{chunk-CWMBGKYW.js → chunk-5PM2JRGV.js} +2153 -856
  50. package/dist/hooks/{chunk-WR2KQAYZ.js → chunk-7SIUNQXK.js} +1207 -1470
  51. package/dist/hooks/{chunk-O2YBIDSI.js → chunk-CQD4LJE6.js} +1682 -1130
  52. package/dist/hooks/{chunk-VWWCFGWK.js → chunk-OPSRGWFU.js} +1 -1
  53. package/dist/hooks/{chunk-XGBNSWEI.js → chunk-UJ3FPMMM.js} +132 -49
  54. package/dist/hooks/chunk-VVNYJWEI.js +30 -0
  55. package/dist/hooks/chunk-Z6DQJKH3.js +2806 -0
  56. package/dist/hooks/codex-hook-adapter.js +8 -8
  57. package/dist/hooks/format-edited.js +4 -5
  58. package/dist/hooks/inputs.json +415 -389
  59. package/dist/hooks/pretool-guard.js +7 -6
  60. package/dist/hooks/session-lang.js +101 -258
  61. package/dist/hooks/stop-guard.js +1744 -2576
  62. package/dist/josh.js +7133 -6368
  63. package/dist/version/index.js +161 -1
  64. package/eslint/rules/comment-why-only.js +108 -0
  65. package/package.json +15 -8
  66. package/prompts/coding-standards.md +1 -1
  67. package/prompts/collaboration-workflow/file-edits.md +14 -11
  68. package/prompts/collaboration-workflow/issue-citation.md +0 -4
  69. package/prompts/collaboration-workflow/issue-template.md +40 -21
  70. package/prompts/collaboration-workflow/lane-instructions.md +3 -1
  71. package/prompts/collaboration-workflow/measurement.md +8 -1
  72. package/prompts/collaboration-workflow/operating-rules.md +11 -2
  73. package/prompts/collaboration-workflow/output-bounds.md +6 -2
  74. package/prompts/collaboration-workflow/plan-comment.md +1 -1
  75. package/prompts/collaboration-workflow/principles.md +9 -0
  76. package/prompts/collaboration-workflow/residency.md +3 -2
  77. package/prompts/collaboration-workflow/rule-delivery.md +13 -1
  78. package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
  79. package/prompts/collaboration-workflow/wip-cap.md +3 -1
  80. package/prompts/review-rubric.md +8 -0
  81. package/prompts/review.md +31 -22
  82. package/prompts/testing-guide.md +1 -0
  83. package/scripts/agent/agent-argv.ts +14 -16
  84. package/scripts/agent/agent-provider.ts +138 -0
  85. package/scripts/agent/agent-role-profile.ts +108 -156
  86. package/scripts/agent/agent-safe-text.ts +20 -5
  87. package/scripts/agent/api-usage-limit.ts +65 -0
  88. package/scripts/agent/claude-agent-argv.ts +19 -9
  89. package/scripts/agent/codex-agent-argv.ts +118 -22
  90. package/scripts/agent/usage-limit-reset.ts +179 -0
  91. package/scripts/auth/claude-token-output.ts +2 -2
  92. package/scripts/auto-ok/auto-ok-author.ts +53 -0
  93. package/scripts/auto-ok/auto-ok-cli.ts +20 -9
  94. package/scripts/backlog/backlog-defect-priority.ts +1 -1
  95. package/scripts/backlog/backlog-drive-cli.ts +6 -1
  96. package/scripts/backlog/backlog-drive-hold.ts +3 -3
  97. package/scripts/backlog/backlog-drive-idle.ts +10 -0
  98. package/scripts/backlog/backlog-drive-launch-pass.ts +90 -0
  99. package/scripts/backlog/backlog-drive-launch.ts +8 -2
  100. package/scripts/backlog/backlog-drive-named-offer.ts +73 -30
  101. package/scripts/backlog/backlog-drive-named.ts +28 -7
  102. package/scripts/backlog/backlog-drive-paused.ts +5 -4
  103. package/scripts/backlog/backlog-drive-restore.ts +11 -3
  104. package/scripts/backlog/backlog-drive.ts +21 -60
  105. package/scripts/backlog/backlog-gate-scope.ts +61 -0
  106. package/scripts/backlog/backlog-measure-close.ts +112 -0
  107. package/scripts/backlog/backlog-next.ts +39 -49
  108. package/scripts/backlog/backlog-occupied.ts +2 -2
  109. package/scripts/backlog/backlog-overlap.ts +42 -8
  110. package/scripts/backlog/backlog-plan-cli.ts +4 -1
  111. package/scripts/backlog/backlog-plan-comment.ts +81 -0
  112. package/scripts/backlog/backlog-plan-read.ts +19 -6
  113. package/scripts/backlog/backlog-pool.ts +50 -12
  114. package/scripts/backlog/backlog-rank.ts +60 -13
  115. package/scripts/backlog/backlog-stalled-detect.ts +2 -1
  116. package/scripts/backlog/backlog-waves.ts +17 -2
  117. package/scripts/backlog/backlogrun-launch.ts +7 -4
  118. package/scripts/cost-runtime/context-cut-payback.ts +27 -25
  119. package/scripts/cost-runtime/cost-cli.ts +37 -16
  120. package/scripts/cost-runtime/cost-pricing.ts +9 -0
  121. package/scripts/cost-runtime/cost-verdict.ts +4 -1
  122. package/scripts/delegation/delegation-policy.ts +2 -2
  123. package/scripts/delegation/duplicate-read-guard.ts +1 -0
  124. package/scripts/delegation/investigation-guard.ts +14 -2
  125. package/scripts/delegation/investigation-reads.ts +45 -23
  126. package/scripts/dependabot/dependabot-cooldown.ts +3 -2
  127. package/scripts/discovery/repo-party.ts +80 -20
  128. package/scripts/discovery/session-owner-pin.ts +51 -0
  129. package/scripts/document/capped-print.ts +1 -1
  130. package/scripts/document/command-reference-line-budget.ts +42 -0
  131. package/scripts/document/document-byte-budget.ts +17 -7
  132. package/scripts/document/document-checks.ts +20 -0
  133. package/scripts/document/document-ratchet-check.ts +101 -0
  134. package/scripts/document/document-section.ts +1 -0
  135. package/scripts/document/entry-read-budget.ts +7 -3
  136. package/scripts/document/issue-citation-budget.ts +94 -0
  137. package/scripts/epic/epic-cli-argv.ts +2 -2
  138. package/scripts/epic/epic-fetch.ts +4 -2
  139. package/scripts/epic/epic-graph.ts +7 -2
  140. package/scripts/epic/epic-issue.ts +3 -1
  141. package/scripts/epic/epic-rank.ts +5 -0
  142. package/scripts/exports/unused-members-check.ts +62 -0
  143. package/scripts/exports/unused-members-cli.ts +6 -51
  144. package/scripts/followup/followup-ci-path.ts +67 -0
  145. package/scripts/followup/followup-coderabbit-retrigger.ts +261 -0
  146. package/scripts/followup/followup-coderabbit-wait.ts +13 -10
  147. package/scripts/followup/followup-failed-tests.ts +160 -0
  148. package/scripts/followup/followup-job-needs.ts +100 -0
  149. package/scripts/followup/followup-job-rerun.ts +303 -0
  150. package/scripts/followup/followup-main-move.ts +113 -0
  151. package/scripts/followup/git-followup-finish.ts +43 -11
  152. package/scripts/followup/git-followup-pending.ts +3 -3
  153. package/scripts/followup/git-followup-stages.ts +41 -11
  154. package/scripts/followup/git-pr-followup-checks.ts +55 -16
  155. package/scripts/followup/git-pr-followup-wrapup.ts +24 -5
  156. package/scripts/followup/git-pr-followup.ts +62 -27
  157. package/scripts/fresh-machine/fresh-machine-script.ts +5 -9
  158. package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +2 -2
  159. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +2 -2
  160. package/scripts/gate/busy-average.ts +34 -2
  161. package/scripts/gate/check-related-pinned.ts +43 -0
  162. package/scripts/gate/check-related-reuse.ts +64 -0
  163. package/scripts/gate/check-related-section.ts +57 -0
  164. package/scripts/gate/check-related-unplanned.ts +34 -0
  165. package/scripts/gate/check-related.ts +265 -0
  166. package/scripts/gate/command-memory.ts +1 -1
  167. package/scripts/gate/core-admission.ts +24 -6
  168. package/scripts/gate/core-budget-timing.ts +20 -6
  169. package/scripts/gate/core-budget.ts +40 -11
  170. package/scripts/gate/core-wait-record.ts +3 -2
  171. package/scripts/gate/core-wait.ts +25 -2
  172. package/scripts/gate/core-weights.ts +15 -7
  173. package/scripts/gate/gate-labels.ts +46 -0
  174. package/scripts/gate/gate-ledger.ts +14 -6
  175. package/scripts/gate/gate-plan.ts +103 -58
  176. package/scripts/gate/gate-report.ts +9 -7
  177. package/scripts/gate/gate-run-steps.ts +26 -3
  178. package/scripts/gate/gate-skip.ts +45 -6
  179. package/scripts/gate/gate-static-group.ts +60 -0
  180. package/scripts/gate/gate-steps.ts +2 -1
  181. package/scripts/gate/gate-tree.ts +4 -2
  182. package/scripts/gate/hook-gate-reuse.ts +19 -2
  183. package/scripts/gate/metrics-totals.ts +59 -0
  184. package/scripts/gate/scoped-green.ts +68 -15
  185. package/scripts/gate/since-green.ts +14 -6
  186. package/scripts/gate/structural-checks.ts +96 -0
  187. package/scripts/gate/verification-gate.ts +51 -16
  188. package/scripts/gate/verification-inputs.ts +21 -6
  189. package/scripts/gate/verification-tail.ts +52 -0
  190. package/scripts/gh/gh-author-association.ts +23 -2
  191. package/scripts/gh/git-ai-review-scan.ts +1 -1
  192. package/scripts/gh/git-gh-api-path.ts +12 -3
  193. package/scripts/gh/git-gh-comments-unreadable.ts +36 -0
  194. package/scripts/gh/git-gh-exec.ts +32 -2
  195. package/scripts/gh/git-gh-issue-read.ts +4 -2
  196. package/scripts/gh/git-gh-issue-rest.ts +1 -0
  197. package/scripts/gh/git-gh-issue-write.ts +8 -2
  198. package/scripts/gh/git-gh-issue.ts +12 -5
  199. package/scripts/gh/git-gh-pr-auto-merge.ts +13 -6
  200. package/scripts/gh/git-gh-pr-graphql-state.ts +56 -0
  201. package/scripts/gh/git-gh-pr-read.ts +74 -13
  202. package/scripts/gh/git-gh-pr-rest.ts +3 -1
  203. package/scripts/gh/git-gh-pr-snapshot.ts +22 -7
  204. package/scripts/gh/git-gh-pr-too-large.ts +20 -0
  205. package/scripts/gh/git-gh-pr.ts +21 -7
  206. package/scripts/gh/git-gh-retry.ts +141 -0
  207. package/scripts/gh/git-pr-ai-review.ts +15 -6
  208. package/scripts/gh/git-pr-checks-eval.ts +3 -0
  209. package/scripts/gh/git-pr-checks.ts +5 -5
  210. package/scripts/git/base-tree.ts +30 -0
  211. package/scripts/git/change-base.ts +4 -10
  212. package/scripts/git/changed-paths-sync.ts +63 -0
  213. package/scripts/git/changed-paths.ts +16 -1
  214. package/scripts/git/git-common-directory.ts +11 -1
  215. package/scripts/git/git-diff-reads.ts +66 -20
  216. package/scripts/git/git-error.ts +9 -2
  217. package/scripts/git/git-schemas.ts +13 -0
  218. package/scripts/git/git-worktree.ts +13 -0
  219. package/scripts/git/gone-branch.ts +4 -1
  220. package/scripts/git/main-merge-budget-conflict.ts +89 -0
  221. package/scripts/git/main-merge-guard.ts +55 -18
  222. package/scripts/git/main-merge-regenerate.ts +59 -25
  223. package/scripts/git/main-merge.ts +53 -5
  224. package/scripts/git/no-base-checkout.ts +127 -0
  225. package/scripts/git/stash/git-stash.ts +11 -2
  226. package/scripts/git/stash/stash-push-cli.ts +10 -0
  227. package/scripts/hooks/batch-guard.ts +40 -21
  228. package/scripts/hooks/edited-cspell.ts +37 -11
  229. package/scripts/hooks/format-edited-file.ts +22 -2
  230. package/scripts/hooks/lane-plan-guard.ts +50 -0
  231. package/scripts/hooks/pre-commit-lint-switch.ts +9 -0
  232. package/scripts/hooks/pre-commit-lint.ts +14 -1
  233. package/scripts/hooks/pre-push-related-switch.ts +10 -0
  234. package/scripts/hooks/pre-push-unit.ts +76 -10
  235. package/scripts/hooks/pretool-guard.ts +2 -0
  236. package/scripts/hooks/reserved-run.ts +14 -1
  237. package/scripts/hooks/run-hook.sh +23 -8
  238. package/scripts/hooks/step-zero-notice.ts +6 -1
  239. package/scripts/hooks/stop-actions.ts +3 -15
  240. package/scripts/hooks/stop-guard.ts +7 -6
  241. package/scripts/init/distributed-paths.ts +1 -0
  242. package/scripts/init/hook-command-rewrite.ts +5 -1
  243. package/scripts/init/hook-launch.ts +4 -2
  244. package/scripts/issue/aggregation-split.ts +52 -0
  245. package/scripts/issue/defect-origin-line.ts +19 -1
  246. package/scripts/issue/defect-rate-cli.ts +5 -102
  247. package/scripts/issue/defect-report.ts +4 -4
  248. package/scripts/issue/effect-audit-cli.ts +178 -0
  249. package/scripts/issue/effect-audit.ts +185 -0
  250. package/scripts/issue/expected-effect-lint.ts +64 -9
  251. package/scripts/issue/git-next-issues.ts +5 -0
  252. package/scripts/issue/issue-body-or-comment.ts +38 -4
  253. package/scripts/issue/issue-cite-cli.ts +1 -3
  254. package/scripts/issue/issue-classification.ts +1 -0
  255. package/scripts/issue/issue-closing-pr.ts +8 -1
  256. package/scripts/issue/issue-evidence-exit.ts +4 -2
  257. package/scripts/issue/issue-file-cap.ts +58 -0
  258. package/scripts/issue/issue-file-cli.ts +111 -38
  259. package/scripts/issue/issue-file-deferral.ts +52 -0
  260. package/scripts/issue/issue-file-fold.ts +29 -10
  261. package/scripts/issue/issue-file-interrupt.ts +85 -0
  262. package/scripts/issue/issue-file-lane-hint.ts +30 -0
  263. package/scripts/issue/issue-file.ts +43 -6
  264. package/scripts/issue/issue-labels.ts +19 -2
  265. package/scripts/issue/issue-lint-cli.ts +27 -2
  266. package/scripts/issue/issue-measured-cli.ts +13 -35
  267. package/scripts/issue/issue-measured-close.ts +58 -0
  268. package/scripts/issue/issue-not-before-label.ts +2 -2
  269. package/scripts/issue/issue-not-before.ts +4 -1
  270. package/scripts/issue/issue-priority-cli.ts +60 -0
  271. package/scripts/issue/issue-priority-raise.ts +55 -0
  272. package/scripts/issue/issue-priority.ts +174 -43
  273. package/scripts/issue/issue-rank.ts +21 -4
  274. package/scripts/issue/issue-read-cli.ts +32 -6
  275. package/scripts/issue/issue-read.ts +37 -12
  276. package/scripts/issue/issue-sample-gate.ts +95 -74
  277. package/scripts/issue/issue-sample-prime.ts +127 -0
  278. package/scripts/issue/issue-sample-required.ts +57 -0
  279. package/scripts/issue/issue-sample-source.ts +12 -11
  280. package/scripts/issue/issue-search.ts +124 -0
  281. package/scripts/issue/issue-state.ts +13 -1
  282. package/scripts/issue/issue-template-section.ts +43 -0
  283. package/scripts/issue/issue-watch-diff.ts +31 -1
  284. package/scripts/issue/issue-watch-hook.ts +11 -2
  285. package/scripts/issue/issue-watch.ts +55 -12
  286. package/scripts/issue/markdown-section.ts +1 -0
  287. package/scripts/issue/measure-declaration.ts +121 -0
  288. package/scripts/issue/measure-rerun-cli.ts +7 -70
  289. package/scripts/issue/plan-consumers-section.ts +22 -1
  290. package/scripts/issue/reproduction-measure.ts +3 -1
  291. package/scripts/issue/size-estimate.ts +90 -0
  292. package/scripts/issue/trusted-measure.ts +84 -0
  293. package/scripts/josh/command-usage.ts +3 -2
  294. package/scripts/josh/durable-state-migrate.ts +105 -0
  295. package/scripts/josh/durable-state.ts +112 -0
  296. package/scripts/josh/josh-aliases.ts +95 -0
  297. package/scripts/josh/josh-command-map.ts +1 -82
  298. package/scripts/josh/josh-commands-agent-hooks.ts +6 -6
  299. package/scripts/josh/josh-commands-ai.ts +5 -5
  300. package/scripts/josh/josh-commands-development.ts +59 -58
  301. package/scripts/josh/josh-commands-issue-write.ts +23 -4
  302. package/scripts/josh/josh-commands-issue.ts +32 -0
  303. package/scripts/josh/josh-commands-lane.ts +87 -4
  304. package/scripts/josh/josh-commands-lint.ts +16 -3
  305. package/scripts/josh/josh-commands-maintenance.ts +15 -0
  306. package/scripts/josh/josh-commands-review.ts +41 -6
  307. package/scripts/josh/josh-commands-ship.ts +56 -8
  308. package/scripts/josh/josh-commands-test-check.ts +80 -0
  309. package/scripts/josh/josh-commands-workflow.ts +1 -1
  310. package/scripts/josh/josh-environment-file.ts +43 -3
  311. package/scripts/josh/josh-in-process.ts +2 -2
  312. package/scripts/josh/josh-logic.ts +5 -3
  313. package/scripts/josh/josh-run.ts +19 -1
  314. package/scripts/josh/run-record-path.ts +15 -0
  315. package/scripts/josh/stamp-file.ts +11 -2
  316. package/scripts/lane/lane-adopt-cli.ts +98 -0
  317. package/scripts/lane/lane-adopt.ts +208 -0
  318. package/scripts/lane/lane-await.ts +5 -8
  319. package/scripts/lane/lane-baseline.ts +123 -0
  320. package/scripts/lane/lane-breakdown-cli.ts +64 -0
  321. package/scripts/lane/lane-breakdown-implement.ts +170 -0
  322. package/scripts/lane/lane-breakdown-laps.ts +107 -0
  323. package/scripts/lane/lane-breakdown-pinned.ts +76 -0
  324. package/scripts/lane/lane-breakdown-text.ts +145 -0
  325. package/scripts/lane/lane-breakdown.ts +239 -0
  326. package/scripts/lane/lane-check-stats.ts +29 -8
  327. package/scripts/lane/lane-child-invocation.ts +9 -2
  328. package/scripts/lane/lane-child-mark-keys.ts +12 -0
  329. package/scripts/lane/lane-child-marker.ts +20 -1
  330. package/scripts/lane/lane-ci-path-stats.ts +73 -0
  331. package/scripts/lane/lane-claim-stats.ts +84 -0
  332. package/scripts/lane/lane-close.ts +8 -3
  333. package/scripts/lane/lane-dispatch-log.ts +3 -3
  334. package/scripts/lane/lane-dispatch.ts +2 -2
  335. package/scripts/lane/lane-gap-stats.ts +7 -6
  336. package/scripts/lane/lane-guard-policy.ts +7 -1
  337. package/scripts/lane/lane-implement-stats.ts +207 -0
  338. package/scripts/lane/lane-implement-subagents.ts +90 -0
  339. package/scripts/lane/lane-investigation-switch.ts +16 -0
  340. package/scripts/lane/lane-ledger-kind.ts +31 -0
  341. package/scripts/lane/lane-ledger-schema-ship.ts +49 -0
  342. package/scripts/lane/lane-ledger-schema.ts +119 -36
  343. package/scripts/lane/lane-ledger-write.ts +257 -0
  344. package/scripts/lane/lane-ledger.ts +31 -177
  345. package/scripts/lane/lane-load.ts +1 -1
  346. package/scripts/lane/lane-measure-cli.ts +176 -59
  347. package/scripts/lane/lane-net-read.ts +44 -0
  348. package/scripts/lane/lane-net-time.ts +212 -0
  349. package/scripts/lane/lane-open.ts +16 -7
  350. package/scripts/lane/lane-output.ts +2 -4
  351. package/scripts/lane/lane-overrun-prompt.ts +147 -0
  352. package/scripts/lane/lane-overrun.ts +274 -0
  353. package/scripts/lane/lane-paths.ts +24 -1
  354. package/scripts/lane/lane-pause-cli.ts +4 -1
  355. package/scripts/lane/lane-paused-spans.ts +97 -0
  356. package/scripts/lane/lane-plan-check.ts +207 -0
  357. package/scripts/lane/lane-plan-cli.ts +41 -0
  358. package/scripts/lane/lane-plan.ts +144 -0
  359. package/scripts/lane/lane-registry.ts +14 -1
  360. package/scripts/lane/lane-relaunch.ts +1 -1
  361. package/scripts/lane/lane-round-one-stats.ts +51 -0
  362. package/scripts/lane/lane-sampler.ts +23 -4
  363. package/scripts/lane/lane-session-action.ts +93 -18
  364. package/scripts/lane/lane-session-broker.ts +49 -21
  365. package/scripts/lane/lane-session-reread-main.ts +14 -0
  366. package/scripts/lane/lane-session-reread.ts +51 -0
  367. package/scripts/lane/lane-ship-lap-stats.ts +74 -0
  368. package/scripts/lane/lane-sleep.ts +58 -0
  369. package/scripts/lane/lane-spent.ts +1 -1
  370. package/scripts/lane/lane-split-stats.ts +28 -0
  371. package/scripts/lane/lane-stage-stats.ts +13 -1
  372. package/scripts/lane/lane-state.ts +41 -9
  373. package/scripts/lane/lane-stats-tables.ts +58 -0
  374. package/scripts/lane/lane-stats.ts +21 -5
  375. package/scripts/lane/lane-stop-stats.ts +51 -19
  376. package/scripts/lane/lane-tail-stats.ts +32 -0
  377. package/scripts/lane/lane-transcript-calls.ts +67 -10
  378. package/scripts/lane/lane-transcript-stats.ts +44 -12
  379. package/scripts/lane/lane-value-cell.ts +72 -0
  380. package/scripts/lane/lane-value.ts +118 -0
  381. package/scripts/lane/lane-withdraw-closed.ts +124 -0
  382. package/scripts/lane/lane-withdraw.ts +108 -31
  383. package/scripts/lane/lane-yield.ts +85 -0
  384. package/scripts/lane/openai-lane-ship.ts +12 -11
  385. package/scripts/lane/openai-lane-supervisor-decision.ts +6 -8
  386. package/scripts/lane/openai-lane-supervisor-owner.ts +5 -8
  387. package/scripts/lane/openai-lane-supervisor.ts +5 -4
  388. package/scripts/lib/poll.ts +38 -9
  389. package/scripts/lib/settled-together.ts +10 -0
  390. package/scripts/lib/shell-quote.ts +21 -0
  391. package/scripts/lib/token-shape.ts +111 -0
  392. package/scripts/lint/eslint-daemon-sources.ts +79 -0
  393. package/scripts/lint/eslint-daemon.ts +45 -6
  394. package/scripts/lint/eslint-warm-cli.ts +7 -0
  395. package/scripts/lint/eslint-warm.ts +66 -0
  396. package/scripts/lint/import-graph.ts +141 -11
  397. package/scripts/lint/lint-gate-scope.ts +2 -2
  398. package/scripts/lint/lint-parallel.ts +54 -6
  399. package/scripts/lint/lint-related.ts +154 -33
  400. package/scripts/lint/rename-cli.ts +179 -0
  401. package/scripts/lint/rename-identifier.ts +192 -0
  402. package/scripts/lint/type-only-imports.ts +58 -0
  403. package/scripts/notify/telegram-notify.ts +12 -3
  404. package/scripts/observations/observation-record.ts +42 -16
  405. package/scripts/observations/observations-flush.ts +32 -9
  406. package/scripts/overrides/overrides-check.ts +9 -1
  407. package/scripts/release/release-approval-prune.ts +7 -1
  408. package/scripts/repo/required-checks-logic.ts +4 -1
  409. package/scripts/repo/ruleset-check.ts +4 -3
  410. package/scripts/report/markdown-shape.ts +28 -0
  411. package/scripts/report/report-format-reference.ts +15 -1
  412. package/scripts/report/report-labels.ts +12 -1
  413. package/scripts/report/report-lint-child-summary.ts +94 -0
  414. package/scripts/report/report-lint-cli.ts +26 -7
  415. package/scripts/report/report-lint.ts +2 -20
  416. package/scripts/review/prose-stale-cli.ts +88 -0
  417. package/scripts/review/prose-stale-scan.ts +152 -0
  418. package/scripts/review/review-attest.ts +73 -23
  419. package/scripts/review/review-brief-cli.ts +68 -19
  420. package/scripts/review/review-brief-paths.ts +22 -0
  421. package/scripts/review/review-brief.ts +14 -7
  422. package/scripts/review/review-comment-carry.ts +47 -0
  423. package/scripts/review/review-comment-round.ts +85 -22
  424. package/scripts/review/review-finding-ledger.ts +109 -7
  425. package/scripts/review/review-finding-text.ts +43 -0
  426. package/scripts/review/review-interaction.ts +11 -0
  427. package/scripts/review/review-lane-handover.ts +68 -0
  428. package/scripts/review/review-lint-cli.ts +57 -0
  429. package/scripts/review/review-lint-findings.ts +92 -0
  430. package/scripts/review/review-lint-sections.ts +80 -0
  431. package/scripts/review/review-lint.ts +221 -0
  432. package/scripts/review/review-prior-findings.ts +102 -0
  433. package/scripts/review/review-readers-scan.ts +4 -2
  434. package/scripts/review/review-record-cli.ts +177 -54
  435. package/scripts/review/review-record-code-round.ts +55 -0
  436. package/scripts/review/review-record-comment.ts +60 -0
  437. package/scripts/review/review-record-interaction.ts +35 -0
  438. package/scripts/review/review-record-pinned.ts +108 -0
  439. package/scripts/review/review-record.ts +25 -1
  440. package/scripts/review/review-reviewed-tree.ts +307 -0
  441. package/scripts/review/review-round-one-closure.ts +62 -0
  442. package/scripts/review/review-round-reuse.ts +106 -0
  443. package/scripts/review/review-round2-cli.ts +91 -29
  444. package/scripts/review/review-round2-skip-comment.ts +55 -0
  445. package/scripts/review/review-round2.ts +24 -8
  446. package/scripts/review/review-stamps.ts +7 -3
  447. package/scripts/review/review-stop-log.ts +20 -6
  448. package/scripts/review/review-stops-cli.ts +2 -1
  449. package/scripts/review/review-submit-cli.ts +101 -0
  450. package/scripts/rules/agent-model.ts +1 -1
  451. package/scripts/rules/bash-triggers.ts +3 -3
  452. package/scripts/rules/concise-reply.ts +88 -0
  453. package/scripts/rules/credential-body.ts +77 -0
  454. package/scripts/rules/decision-oracle.ts +1 -1
  455. package/scripts/rules/delivered-rules.ts +36 -17
  456. package/scripts/rules/destructive-command.ts +3 -11
  457. package/scripts/rules/direct-issue-comment.ts +34 -12
  458. package/scripts/rules/direct-issue-read.ts +191 -0
  459. package/scripts/rules/direct-pr-create.ts +4 -24
  460. package/scripts/rules/early-heartbeat.ts +2 -0
  461. package/scripts/rules/edit-tool.ts +27 -0
  462. package/scripts/rules/file-edit-rows.ts +17 -0
  463. package/scripts/rules/file-rewrite.ts +146 -0
  464. package/scripts/rules/firing-point.ts +3 -2
  465. package/scripts/rules/gh-api.ts +128 -7
  466. package/scripts/rules/gh-repo-selector.ts +84 -0
  467. package/scripts/rules/git-force.ts +2 -2
  468. package/scripts/rules/guard-remedy.ts +14 -5
  469. package/scripts/rules/implementation-cut.ts +61 -28
  470. package/scripts/rules/investigator-foreground.ts +231 -0
  471. package/scripts/rules/issue-citation.ts +15 -60
  472. package/scripts/rules/issue-comments.ts +9 -4
  473. package/scripts/rules/josh-git-bare.ts +1 -1
  474. package/scripts/rules/lane-background.ts +41 -13
  475. package/scripts/rules/lane-direct-tool.ts +107 -9
  476. package/scripts/rules/lane-interactive-ask.ts +4 -1
  477. package/scripts/rules/lane-park.ts +4 -2
  478. package/scripts/rules/lane-spilled-read.ts +90 -0
  479. package/scripts/rules/lane-split-park.ts +1 -1
  480. package/scripts/rules/lane-switch-main.ts +4 -4
  481. package/scripts/rules/last-prompt.ts +20 -47
  482. package/scripts/rules/oracle-consulted.ts +1 -1
  483. package/scripts/rules/permission-guards.ts +5 -1
  484. package/scripts/rules/piped-verification-shapes.ts +110 -0
  485. package/scripts/rules/piped-verification.ts +67 -17
  486. package/scripts/rules/poll-loop.ts +72 -9
  487. package/scripts/rules/pr-merge.ts +5 -5
  488. package/scripts/rules/pre-gate-cut.ts +3 -3
  489. package/scripts/rules/protected-files.ts +88 -24
  490. package/scripts/rules/reply-language.ts +3 -17
  491. package/scripts/rules/reply-prose.ts +34 -0
  492. package/scripts/rules/repo-admin.ts +132 -0
  493. package/scripts/rules/reviewer-foreground.ts +88 -0
  494. package/scripts/rules/round-one-check-related.ts +120 -0
  495. package/scripts/rules/rule-body-guard.ts +5 -15
  496. package/scripts/rules/rule-value-cache.ts +53 -5
  497. package/scripts/rules/rule-value-candidates.ts +84 -0
  498. package/scripts/rules/rule-value-cli.ts +59 -11
  499. package/scripts/rules/rule-value.ts +17 -4
  500. package/scripts/rules/run-tail-rule.ts +1 -1
  501. package/scripts/rules/sed-in-place.ts +196 -0
  502. package/scripts/rules/shell-segments.ts +10 -2
  503. package/scripts/rules/stop-rule-rows.ts +1 -13
  504. package/scripts/rules/stop-rules.ts +33 -58
  505. package/scripts/rules/test-declared-commit.ts +1 -1
  506. package/scripts/rules/third-party-write.ts +110 -23
  507. package/scripts/rules/timed-rerun.ts +1 -1
  508. package/scripts/rules/turn-filings.ts +90 -0
  509. package/scripts/rules/worktree-guard.ts +22 -7
  510. package/scripts/run/board/run-board-ending-reason.ts +6 -2
  511. package/scripts/run/board/run-board-fit.ts +24 -1
  512. package/scripts/run/board/run-board-found.ts +134 -0
  513. package/scripts/run/board/run-board-header.ts +8 -0
  514. package/scripts/run/board/run-board-labels.ts +11 -1
  515. package/scripts/run/board/run-board-lane-time.ts +1 -0
  516. package/scripts/run/board/run-board-link.ts +15 -2
  517. package/scripts/run/board/run-board-notes.ts +7 -1
  518. package/scripts/run/board/run-board-operation.ts +4 -2
  519. package/scripts/run/board/run-board-phase.ts +2 -5
  520. package/scripts/run/board/run-board-plan.ts +1 -1
  521. package/scripts/run/board/run-board-read.ts +46 -1
  522. package/scripts/run/board/run-board-reason.ts +20 -8
  523. package/scripts/run/board/run-board-render-checks.ts +3 -2
  524. package/scripts/run/board/run-board-render-drawn.ts +11 -0
  525. package/scripts/run/board/run-board-render-found.ts +157 -0
  526. package/scripts/run/board/run-board-render-lead.ts +9 -0
  527. package/scripts/run/board/run-board-render-legend.ts +19 -0
  528. package/scripts/run/board/run-board-render-tail.ts +1 -1
  529. package/scripts/run/board/run-board-render.ts +82 -18
  530. package/scripts/run/board/run-board-spin.ts +1 -3
  531. package/scripts/run/board/run-board-status.ts +2 -0
  532. package/scripts/run/board/run-board-tick.ts +39 -10
  533. package/scripts/run/carry/run-carry-ended.ts +3 -2
  534. package/scripts/run/carry/run-carry.ts +3 -2
  535. package/scripts/run/cut/run-cut-cli.ts +33 -133
  536. package/scripts/run/cut/run-cut-digest.ts +152 -0
  537. package/scripts/run/cut/run-cut-handoff.ts +52 -8
  538. package/scripts/run/cut/run-cut-report.ts +24 -3
  539. package/scripts/run/cut/run-cut-resume.ts +129 -0
  540. package/scripts/run/cut/run-cut-review.ts +105 -0
  541. package/scripts/run/cut/run-cut.ts +18 -7
  542. package/scripts/run/detached-launch.ts +1 -1
  543. package/scripts/run/entry/run-entry-cli.ts +88 -19
  544. package/scripts/run/entry/run-entry-spill.ts +83 -0
  545. package/scripts/run/entry/run-entry-stop.ts +5 -1
  546. package/scripts/run/entry/run-entry-trust.ts +91 -0
  547. package/scripts/run/event/run-event-baseline.ts +56 -0
  548. package/scripts/run/event/run-event-filed.ts +9 -3
  549. package/scripts/run/event/run-event-overrun.ts +197 -0
  550. package/scripts/run/event/run-event-render.ts +4 -0
  551. package/scripts/run/event/run-event-stream.ts +25 -3
  552. package/scripts/run/hold/run-stop-notify.ts +3 -8
  553. package/scripts/run/merge/run-merge-cap.ts +57 -0
  554. package/scripts/run/merge/run-merge-cli.ts +66 -23
  555. package/scripts/run/merge/run-merge-outcome.ts +2 -0
  556. package/scripts/run/merge/run-merge-ship.ts +13 -3
  557. package/scripts/run/merge/run-merge-signals.ts +40 -23
  558. package/scripts/run/merge/run-merge-steps.ts +56 -36
  559. package/scripts/run/merge/run-merge-usage-limit.ts +53 -0
  560. package/scripts/run/merge/run-merge-withdrawn.ts +53 -0
  561. package/scripts/run/merge/run-merge.ts +41 -14
  562. package/scripts/run/review/run-review-cli.ts +306 -20
  563. package/scripts/run/review/run-review-early-push.ts +121 -0
  564. package/scripts/run/review/run-review-join-read.ts +94 -0
  565. package/scripts/run/review/run-review-pinned-accepted.ts +126 -0
  566. package/scripts/run/review/run-review-pinned-join.ts +216 -0
  567. package/scripts/run/review/run-review-pinned-steps.ts +383 -0
  568. package/scripts/run/review/run-review-pinned-tree.ts +37 -0
  569. package/scripts/run/review/run-review-pinned.ts +53 -0
  570. package/scripts/run/review/run-review-steps.ts +70 -34
  571. package/scripts/run/review/run-review.ts +26 -6
  572. package/scripts/run/run-parent-cut-hook.ts +3 -4
  573. package/scripts/run/run-prep.ts +1 -0
  574. package/scripts/run/run-stage-read.ts +2 -6
  575. package/scripts/run/run-step-cli.ts +17 -5
  576. package/scripts/run/run-step-lane-plan.ts +27 -0
  577. package/scripts/run/run-step-section.ts +26 -7
  578. package/scripts/run/run-step.ts +5 -2
  579. package/scripts/run/ship/run-ship-args.ts +19 -0
  580. package/scripts/run/ship/run-ship-brokered-review.ts +106 -0
  581. package/scripts/run/ship/run-ship-cli.ts +131 -39
  582. package/scripts/run/ship/run-ship-conflict-probe.ts +59 -0
  583. package/scripts/run/ship/run-ship-detach.ts +10 -4
  584. package/scripts/run/ship/run-ship-handover.ts +106 -0
  585. package/scripts/run/ship/run-ship-infra-retry.ts +16 -1
  586. package/scripts/run/ship/run-ship-lap.ts +63 -0
  587. package/scripts/run/ship/run-ship-next.ts +27 -26
  588. package/scripts/run/ship/run-ship-overlap.ts +8 -3
  589. package/scripts/run/ship/run-ship-place.ts +9 -2
  590. package/scripts/run/ship/run-ship-planned.ts +92 -0
  591. package/scripts/run/ship/run-ship-pre-detach-pinned.ts +197 -0
  592. package/scripts/run/ship/run-ship-pre-detach-timed.ts +7 -8
  593. package/scripts/run/ship/run-ship-pre-detach.ts +77 -23
  594. package/scripts/run/ship/run-ship-preflight.ts +16 -4
  595. package/scripts/run/ship/run-ship-probe.ts +23 -9
  596. package/scripts/run/ship/run-ship-relaunch-cap.ts +43 -7
  597. package/scripts/run/ship/run-ship-relaunch.ts +51 -0
  598. package/scripts/run/ship/run-ship-return.ts +103 -29
  599. package/scripts/run/ship/run-ship-review-reason.ts +24 -0
  600. package/scripts/run/ship/run-ship-review-steps.ts +230 -59
  601. package/scripts/run/ship/run-ship-review.ts +171 -51
  602. package/scripts/run/ship/run-ship-reviewer.ts +138 -42
  603. package/scripts/run/ship/run-ship-scoped.ts +39 -10
  604. package/scripts/run/ship/run-ship-stage.ts +49 -13
  605. package/scripts/run/ship/run-ship-steps.ts +24 -4
  606. package/scripts/run/ship/run-ship-stop-cause.ts +43 -2
  607. package/scripts/run/ship/run-ship-stop-context.ts +50 -13
  608. package/scripts/run/ship/run-ship-sync.ts +171 -30
  609. package/scripts/run/ship/run-ship-synced-scope.ts +178 -0
  610. package/scripts/run/ship/run-ship-wait-cli.ts +145 -0
  611. package/scripts/run/ship/run-ship-waiter.ts +114 -0
  612. package/scripts/run/ship/run-ship.ts +16 -2
  613. package/scripts/run/wake/run-wake-caffeinate.ts +48 -0
  614. package/scripts/run/wake/run-wake-cli.ts +6 -113
  615. package/scripts/run/wake/run-wake-code.ts +53 -11
  616. package/scripts/run/wake/run-wake-driver.ts +5 -3
  617. package/scripts/run/wake/run-wake-finish.ts +137 -0
  618. package/scripts/run/wake/run-wake-loop.ts +5 -3
  619. package/scripts/run/wake/run-wake-ports.ts +11 -3
  620. package/scripts/run/wake/run-wake-session.ts +2 -0
  621. package/scripts/run/wake/run-wake.ts +3 -2
  622. package/scripts/safe-chain/ci-installer-pin.ts +49 -8
  623. package/scripts/safe-chain/project-config.ts +3 -2
  624. package/scripts/security/secretlint-scan.ts +42 -9
  625. package/scripts/security/security-audit-provision-main.ts +9 -1
  626. package/scripts/security/security-audit-provision.ts +1 -1
  627. package/scripts/security/security-audit.ts +21 -1
  628. package/scripts/security/sonar-file.ts +10 -5
  629. package/scripts/split/split-assess.ts +12 -3
  630. package/scripts/split/split-early-notice.ts +116 -0
  631. package/scripts/split/split-measure.ts +20 -2
  632. package/scripts/split/split-resolution.ts +107 -0
  633. package/scripts/test/direct-importers.ts +185 -0
  634. package/scripts/test/pure-files-entries.ts +83 -0
  635. package/scripts/test/related-heavy-tests.ts +81 -0
  636. package/scripts/test/test-no-base.ts +88 -0
  637. package/scripts/test/test-pinned-cache-logic.ts +363 -0
  638. package/scripts/test/test-pinned-cache.ts +337 -0
  639. package/scripts/test/test-pinned-emit.ts +49 -0
  640. package/scripts/test/test-pinned-functions.ts +116 -0
  641. package/scripts/test/test-pinned-ledger.ts +80 -0
  642. package/scripts/test/test-pinned-logic.ts +208 -20
  643. package/scripts/test/test-pinned-main.ts +84 -18
  644. package/scripts/test/test-pinned-pool.ts +73 -0
  645. package/scripts/test/test-pinned-probe.ts +254 -0
  646. package/scripts/test/test-pinned-prune-logic.ts +118 -0
  647. package/scripts/test/test-pinned-reach.ts +194 -0
  648. package/scripts/test/test-pinned-record.ts +196 -0
  649. package/scripts/test/test-pinned-rewire.ts +148 -0
  650. package/scripts/test/test-pinned-spawn.ts +81 -0
  651. package/scripts/test/test-pinned-stage.ts +70 -0
  652. package/scripts/test/test-pinned.ts +258 -47
  653. package/scripts/test/test-reach-cli.ts +61 -0
  654. package/scripts/test/test-read-map.ts +35 -11
  655. package/scripts/test/test-read-recording.ts +17 -5
  656. package/scripts/test/test-read-trace.ts +26 -8
  657. package/scripts/test/test-red-logic.ts +46 -7
  658. package/scripts/test/test-red.ts +34 -14
  659. package/scripts/test/test-related-claim.ts +37 -0
  660. package/scripts/test/test-related-main.ts +4 -1
  661. package/scripts/test/test-related-moved.ts +91 -0
  662. package/scripts/test/test-related-record.ts +43 -23
  663. package/scripts/test/test-related-scope.ts +99 -34
  664. package/scripts/test/test-related-synced.ts +135 -0
  665. package/scripts/test/test-related-touched.ts +84 -0
  666. package/scripts/test/test-related.ts +167 -83
  667. package/scripts/test/test-unit-guard.ts +28 -5
  668. package/scripts/test/unit-durations.ts +41 -0
  669. package/scripts/test/unit-worker-share.ts +5 -4
  670. package/scripts/test/vitest-cache-directory.ts +19 -0
  671. package/scripts/test/vitest-cli-excludes.ts +14 -0
  672. package/scripts/test/vitest-failure-summary.ts +111 -0
  673. package/scripts/test/whole-suite-files.ts +12 -1
  674. package/scripts/time-runtime/time-batch-guard.ts +42 -4
  675. package/scripts/time-runtime/time-bundle-call.ts +1 -1
  676. package/scripts/time-runtime/time-bundles.ts +36 -5
  677. package/scripts/time-runtime/time-markers.ts +2 -2
  678. package/scripts/time-runtime/time-search-call.ts +38 -0
  679. package/scripts/time-runtime/time-shell.ts +1 -1
  680. package/scripts/time-runtime/time-transcript-line.ts +17 -5
  681. package/scripts/version/development-engines-verdict.ts +124 -0
  682. package/scripts/version/latest-corepack.ts +2 -0
  683. package/templates/gitignore +2 -0
  684. package/templates/workflows/ci.yml +41 -0
  685. package/dist/hooks/chunk-AZX4FGQ3.js +0 -207
  686. package/dist/hooks/chunk-PT5R6UJD.js +0 -7131
  687. package/dist/hooks/chunk-TUIFS5E7.js +0 -72
  688. package/dist/hooks/chunk-YCDOIR3I.js +0 -3456
  689. package/scripts/cost-runtime/context-cut-threshold.ts +0 -11
  690. package/scripts/rules/filing-cap.ts +0 -139
@@ -12,6 +12,7 @@ import {
12
12
  type BufferedProcessResult,
13
13
  } from '#scripts/lib/buffered-process'
14
14
  import { SKIP_MARKER } from '#scripts/test/skip-marker'
15
+ import { time_format } from '#scripts/time-runtime/time-format'
15
16
  import { eslint_cache_dependencies } from './eslint-cache-dependencies'
16
17
  import { eslint_daemon } from './eslint-daemon'
17
18
  import { lint_gate_scope } from './lint-gate-scope'
@@ -42,6 +43,11 @@ interface LintRunOptions {
42
43
 
43
44
  const COLD_RUN: LintRunOptions = { warm_daemon: false }
44
45
 
46
+ interface LintPair {
47
+ prettier: BufferedProcessResult
48
+ eslint: BufferedProcessResult
49
+ }
50
+
45
51
  // The warm daemon when asked for and reachable, else the cold `pnpm exec eslint` it falls back to.
46
52
  async function run_eslint_process(eslint: EslintRun): Promise<BufferedProcessResult> {
47
53
  if (eslint.warm_daemon) return await eslint_daemon.run_or_cold(eslint.args)
@@ -62,8 +68,13 @@ async function run_eslint(eslint: EslintRun): Promise<BufferedProcessResult> {
62
68
  })
63
69
  }
64
70
 
71
+ // execa strips the child's final newline, so each output is closed here: unclosed, the next tool's
72
+ // output, or the timing line, would start on the same line as prettier's last one.
65
73
  function write_output(result: BufferedProcessResult): void {
66
- if (result.output) process.stdout.write(result.output)
74
+ const { output } = result
75
+ if (!output) return
76
+
77
+ process.stdout.write(output.endsWith('\n') ? output : `${output}\n`)
67
78
  }
68
79
 
69
80
  function skipped(check: string, reason: string): BufferedProcessResult {
@@ -118,24 +129,59 @@ function lint_exit_code(prettier: BufferedProcessResult, eslint: BufferedProcess
118
129
  // and through the same basic-project skip, so a narrowed run never reaches a tool the whole-tree
119
130
  // run would have skipped. The skip reasons answer nothing for a full
120
131
  // project, so the one path serves both profiles.
121
- async function run_lint_checks(
132
+ async function run_lint_pair(
122
133
  prettier_args: ReadonlyArray<string>,
123
134
  eslint_args: ReadonlyArray<string>,
124
135
  cache_file: string,
125
- options: LintRunOptions = COLD_RUN,
126
- ): Promise<number> {
136
+ options: LintRunOptions,
137
+ ): Promise<LintPair> {
127
138
  const directory = process.cwd()
128
139
  const [prettier, eslint] = await Promise.all([
129
140
  run_prettier(directory, prettier_args),
130
141
  run_checked_eslint(directory, { args: eslint_args, cache_file, ...options }),
131
142
  ])
132
143
 
144
+ return { prettier, eslint }
145
+ }
146
+
147
+ function write_lint_pair({ prettier, eslint }: LintPair): number {
133
148
  write_output(with_ran_notice('prettier', prettier, eslint))
134
149
  write_output(with_ran_notice('eslint', eslint, prettier))
135
150
 
136
151
  return lint_exit_code(prettier, eslint)
137
152
  }
138
153
 
154
+ async function run_lint_checks(
155
+ prettier_args: ReadonlyArray<string>,
156
+ eslint_args: ReadonlyArray<string>,
157
+ cache_file: string,
158
+ options: LintRunOptions = COLD_RUN,
159
+ ): Promise<number> {
160
+ return write_lint_pair(await run_lint_pair(prettier_args, eslint_args, cache_file, options))
161
+ }
162
+
163
+ // joshuafolkken/kit#5116: the gate times `lint` as one step, and the two tools run side by side, so
164
+ // the step's seconds name neither tool as the long pole. This line, the gate's lint alone, does.
165
+ function timing_line({ prettier, eslint }: LintPair): string {
166
+ const prettier_seconds = time_format.format_seconds(prettier.elapsed_ms)
167
+ const eslint_seconds = time_format.format_seconds(eslint.elapsed_ms)
168
+
169
+ return `lint timing — prettier ${prettier_seconds} · eslint ${eslint_seconds}\n`
170
+ }
171
+
172
+ async function run_timed_lint_checks(
173
+ prettier_args: ReadonlyArray<string>,
174
+ eslint_args: ReadonlyArray<string>,
175
+ cache_file: string,
176
+ ): Promise<number> {
177
+ const pair = await run_lint_pair(prettier_args, eslint_args, cache_file, COLD_RUN)
178
+ const exit_code = write_lint_pair(pair)
179
+
180
+ process.stdout.write(timing_line(pair))
181
+
182
+ return exit_code
183
+ }
184
+
139
185
  async function run_lint_parallel_checks(): Promise<number> {
140
186
  return await run_lint_checks(PRETTIER_ARGS, ESLINT_ARGS, ESLINT_CACHE_FILE)
141
187
  }
@@ -150,11 +196,13 @@ async function run_changed_lint_checks(): Promise<number> {
150
196
 
151
197
  process.stdout.write(`${lint_gate_scope.describe_scope(scope, root)}\n`)
152
198
 
153
- if (scope.mode === 'all') return await run_lint_parallel_checks()
199
+ if (scope.mode === 'all') {
200
+ return await run_timed_lint_checks(PRETTIER_ARGS, ESLINT_ARGS, ESLINT_CACHE_FILE)
201
+ }
154
202
 
155
203
  const narrowed = lint_gate_scope.narrowed_run(scope.files)
156
204
 
157
- return await run_lint_checks(narrowed.prettier, narrowed.eslint, narrowed.eslint_cache_file)
205
+ return await run_timed_lint_checks(narrowed.prettier, narrowed.eslint, narrowed.eslint_cache_file)
158
206
  }
159
207
 
160
208
  async function run_lint_command(command_arguments: ReadonlyArray<string>): Promise<number> {
@@ -2,12 +2,18 @@
2
2
  import { existsSync } from 'node:fs'
3
3
  import path from 'node:path'
4
4
  import { fileURLToPath } from 'node:url'
5
- import { document_byte_check } from '#scripts/document/document-byte-check'
6
- import { gate_plan } from '#scripts/gate/gate-plan'
5
+ import { document_checks } from '#scripts/document/document-checks'
6
+ import { unused_members_check } from '#scripts/exports/unused-members-check'
7
+ import { gate_labels } from '#scripts/gate/gate-labels'
8
+ import type { GateTree } from '#scripts/gate/gate-tree'
9
+ import { metrics_totals } from '#scripts/gate/metrics-totals'
7
10
  import { scoped_green } from '#scripts/gate/scoped-green'
8
11
  import { since_green } from '#scripts/gate/since-green'
12
+ import { structural_checks } from '#scripts/gate/structural-checks'
13
+ import { verification_tail } from '#scripts/gate/verification-tail'
9
14
  import { changed_file_scope, type ChangedFileScope } from '#scripts/git/changed-file-scope'
10
15
  import { review_stamps } from '#scripts/review/review-stamps'
16
+ import { split_early_notice } from '#scripts/split/split-early-notice'
11
17
  import { lint_parallel } from './lint-parallel'
12
18
  import { lint_related_scope } from './lint-related-scope'
13
19
 
@@ -44,34 +50,85 @@ async function lint_exit_code(scope: ChangedFileScope): Promise<number> {
44
50
  )
45
51
  }
46
52
 
47
- // The byte check over the same scope the lint just ran: the resolved file list when narrowed, and
48
- // the whole budget when lint fell back to the whole tree — so the byte check is a superset in the
49
- // fallback exactly as lint is, never an empty list that would pass silently.
50
- function byte_check_exit_code(scope: ChangedFileScope, root: string): number {
51
- if (scope.mode === 'all') return document_byte_check.check_all(root)
53
+ // The document checks over the same scope the lint just ran: the resolved file list when narrowed,
54
+ // and the whole budget when lint fell back to the whole tree — so each is a superset in the
55
+ // fallback exactly as lint is, never an empty list that would pass silently. Both run, so one edit
56
+ // reports its byte ceiling and its ratchets (`document-ratchet-check.ts`) in one pass.
57
+ function document_check_exit_code(scope: ChangedFileScope, root: string): number {
58
+ if (scope.mode === 'all') return document_checks.check_all(root)
52
59
 
53
- return document_byte_check.check_files(root, scope.files)
60
+ return document_checks.check_files(root, scope.files)
54
61
  }
55
62
 
56
- // The lint result folded together with the fast byte-ceiling check: the
57
- // same check the gate's `document-byte-budget.test.ts` runs, brought forward to this between-edits
58
- // path so a mandated documentation update over its ceiling surfaces in seconds. It reads no change
63
+ interface LintOutcome {
64
+ stage: string
65
+ exit_code: number
66
+ }
67
+
68
+ const UNMOVED: LintOutcome = { stage: 'unmoved', exit_code: 0 }
69
+
70
+ function is_failed(outcome: LintOutcome): boolean {
71
+ return outcome.exit_code !== 0
72
+ }
73
+
74
+ // The lint result folded together with the fast document checks: the
75
+ // same checks the gate's `document-byte-budget.test.ts`, `command-reference.test.ts` and
76
+ // `issue-citation-budget.test.ts` run, brought forward to this between-edits path so a mandated
77
+ // documentation update over a ceiling surfaces in seconds. It reads no change
59
78
  // of its own — it takes the files this run already resolved, so the git contract is the lint
60
- // command's alone. A lint failure is reported as-is; only a green lint runs the byte check, so the
79
+ // command's alone. A lint failure is reported as-is; only a green lint runs the document checks, so the
61
80
  // two never race to the exit code, and a green tree here is green on both — which is what the record
62
- // below then vouches for.
63
- async function scoped_exit_code(scope: ChangedFileScope, root: string): Promise<number> {
64
- const lint_exit = await lint_exit_code(scope)
65
- if (lint_exit !== 0) return lint_exit
81
+ // below then vouches for. The structural checks (`structural-checks.ts`) run beside the lint rather
82
+ // than after it, so their whole-program scan costs no wall clock the lint has not already spent.
83
+ //
84
+ // The gate's `exports` check comes after them on the same terms: a namespace member nothing reads is
85
+ // reported here for the namespaces the changed files declare or import directly
86
+ // (joshuafolkken/kit#4645, joshuafolkken/kit#4649), rather than at ship's pre-detach gate. The
87
+ // fallback scans the whole program, a superset as the lint's is.
88
+ //
89
+ // The outcome names the stage that failed first, which the verdict line names (joshuafolkken/kit#5162).
90
+ async function scoped_outcome(scope: ChangedFileScope, root: string): Promise<LintOutcome> {
91
+ const structural = structural_checks.run_structural(scope, root)
92
+ const lint = { stage: 'lint', exit_code: await lint_exit_code(scope) }
93
+ const failed = [lint, { stage: 'structural', exit_code: await structural }].find((outcome) =>
94
+ is_failed(outcome),
95
+ )
96
+
97
+ if (failed !== undefined) return failed
98
+ // The linters' buffered output ends without a newline; keep the checks' own lines apart from it.
99
+ process.stdout.write('\n')
100
+ const documents = { stage: 'documents', exit_code: document_check_exit_code(scope, root) }
101
+ if (is_failed(documents)) return documents
102
+
103
+ const files = scope.mode === 'all' ? undefined : scope.files
66
104
 
67
- return byte_check_exit_code(scope, root)
105
+ return {
106
+ stage: 'unused members',
107
+ exit_code: await unused_members_check.run_unused_members(root, files),
108
+ }
68
109
  }
69
110
 
70
- // **A bare run reads only what moved since its last green run** (`since-green.ts`), while a lintable file
71
- // is among it; otherwise the whole branch change, as before.
72
- async function since_green_scope(root: string): Promise<ChangedFileScope | undefined> {
73
- const moved = await since_green.read_moved(review_stamps.lint_related_stamp, gate_plan.LINT_LABEL)
111
+ // **A bare run reads only what moved since its last green run** (`since-green.ts`), against the tree
112
+ // its green record is read from, so one run reads the gate tree once (joshuafolkken/kit#4655).
113
+ // Explicit file arguments read no tree, so they never consult the record.
114
+ async function read_since_green(
115
+ before: GateTree | undefined,
116
+ ): Promise<ReadonlyArray<string> | undefined> {
117
+ if (before === undefined) return undefined
118
+
119
+ return await since_green.read_moved(
120
+ review_stamps.lint_related_stamp,
121
+ gate_labels.LINT_LABEL,
122
+ undefined,
123
+ before,
124
+ )
125
+ }
74
126
 
127
+ // Narrowed to what moved while a lintable file is among it; otherwise the whole branch change, as before.
128
+ function since_green_scope(
129
+ root: string,
130
+ moved: ReadonlyArray<string> | undefined,
131
+ ): ChangedFileScope | undefined {
75
132
  if (moved === undefined) return undefined
76
133
 
77
134
  const inputs = lint_related_scope.scope_inputs(existsSync)
@@ -87,8 +144,9 @@ async function since_green_scope(root: string): Promise<ChangedFileScope | undef
87
144
  async function resolve_lint_scope(
88
145
  command_arguments: ReadonlyArray<string>,
89
146
  root: string,
147
+ moved: ReadonlyArray<string> | undefined,
90
148
  ): Promise<ChangedFileScope> {
91
- const since = command_arguments.length === 0 ? await since_green_scope(root) : undefined
149
+ const since = since_green_scope(root, moved)
92
150
 
93
151
  if (since !== undefined) return since
94
152
 
@@ -99,17 +157,33 @@ async function resolve_lint_scope(
99
157
  })
100
158
  }
101
159
 
160
+ // In kit, a metrics total grown past the merge-base is reported after the lint and changes no exit
161
+ // code (`metrics-totals.ts`). The totals are a whole-repository pass, so only a green bare run pays
162
+ // for it: a red lint is edited again anyway, and a run narrowed by file arguments is a spot check.
163
+ async function outcome_with_notice(
164
+ command_arguments: ReadonlyArray<string>,
165
+ scope: ChangedFileScope,
166
+ root: string,
167
+ ): Promise<LintOutcome> {
168
+ const outcome = await scoped_outcome(scope, root)
169
+ if (is_failed(outcome) || command_arguments.length > 0) return outcome
170
+
171
+ const notice = await metrics_totals.growth_notice(root)
172
+
173
+ // On a line of its own: a linter's buffered output need not end with a newline.
174
+ if (notice !== undefined) process.stdout.write(`\n${notice}\n`)
175
+
176
+ return outcome
177
+ }
178
+
102
179
  // The narrowing line is printed before either child starts, so a scoped run is never read as a
103
180
  // whole one, and a fallback says which of the two it was rather than looking like a narrow run
104
181
  // that found nothing.
105
- //
106
- // **A green run leaves a record of the tree it was green on**, so
107
- // `josh review:brief` can tell a tree this check has read from one it has not. What the record means,
108
- // and the three states in which it is withheld, are `scoped-green.ts`.
109
- async function run_related_lint(command_arguments: ReadonlyArray<string>): Promise<number> {
110
- const root = await changed_file_scope.repository_root_or_cwd()
111
- const scope = await resolve_lint_scope(command_arguments, root)
112
-
182
+ function report_scope(
183
+ command_arguments: ReadonlyArray<string>,
184
+ scope: ChangedFileScope,
185
+ root: string,
186
+ ): void {
113
187
  changed_file_scope.report_unusable_arguments(
114
188
  command_arguments,
115
189
  scope,
@@ -117,17 +191,64 @@ async function run_related_lint(command_arguments: ReadonlyArray<string>): Promi
117
191
  )
118
192
  report_ignored_flags(command_arguments)
119
193
  process.stdout.write(`${lint_related_scope.describe_scope(scope, root)}\n`)
194
+ }
195
+
196
+ // **Nothing moved since the last green run lints nothing** (joshuafolkken/kit#4593), as
197
+ // `josh test:related` runs no test.
198
+ function report_unmoved(): LintOutcome {
199
+ process.stdout.write(
200
+ `${lint_related_scope.COMMAND_LABEL}: ${since_green.UNMOVED_REASON} — linting nothing.\n`,
201
+ )
202
+
203
+ return UNMOVED
204
+ }
205
+
206
+ async function checked_outcome(
207
+ command_arguments: ReadonlyArray<string>,
208
+ root: string,
209
+ moved: ReadonlyArray<string> | undefined,
210
+ ): Promise<LintOutcome> {
211
+ if (moved?.length === 0) return report_unmoved()
120
212
 
213
+ const scope = await resolve_lint_scope(command_arguments, root, moved)
214
+
215
+ report_scope(command_arguments, scope, root)
216
+
217
+ return await outcome_with_notice(command_arguments, scope, root)
218
+ }
219
+
220
+ // The run's last line names the stage that failed, or says it passed; the console is the only copy of
221
+ // the output, so there is no log notice (`verification-tail.ts`).
222
+ function report_verdict(outcome: LintOutcome): void {
223
+ const failed = is_failed(outcome) ? [outcome.stage] : []
224
+ const verdict = verification_tail.format_verdict(lint_related_scope.COMMAND_LABEL, failed)
225
+
226
+ process.stdout.write(`\n${verification_tail.format_tail({ failures: '', verdict })}`)
227
+ }
228
+
229
+ // **A green run leaves a record of the tree it was green on**, so
230
+ // `josh review:brief` can tell a tree this check has read from one it has not. What the record means,
231
+ // and the three states in which it is withheld, are `scoped-green.ts`. An unmoved run records too, as
232
+ // `josh test:related`'s does: a main sync can move the base while moving no path, and a record left on
233
+ // the old base would refuse `josh gate` while every re-run kept linting nothing.
234
+ async function run_related_lint(command_arguments: ReadonlyArray<string>): Promise<number> {
235
+ const root = await changed_file_scope.repository_root_or_cwd()
121
236
  const before = await scoped_green.read_before(command_arguments)
122
- const exit_code = await scoped_exit_code(scope, root)
237
+ const moved = await read_since_green(before)
238
+ const outcome = await checked_outcome(command_arguments, root, moved)
123
239
 
124
- await scoped_green.record_if_green(review_stamps.lint_related_stamp, { before, exit_code })
240
+ report_verdict(outcome)
241
+ await scoped_green.record_if_green(review_stamps.lint_related_stamp, {
242
+ before,
243
+ exit_code: outcome.exit_code,
244
+ })
125
245
 
126
- return exit_code
246
+ return outcome.exit_code
127
247
  }
128
248
 
129
249
  if (process.argv[1] === fileURLToPath(import.meta.url)) {
130
250
  process.exitCode = await run_related_lint(process.argv.slice(changed_file_scope.ARGV_START))
251
+ await split_early_notice.surface()
131
252
  }
132
253
 
133
254
  const lint_related = { run_related_lint }
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env tsx
2
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs'
3
+ import path from 'node:path'
4
+ import { fileURLToPath } from 'node:url'
5
+ import { format_edited_payload } from '#scripts/hooks/format-edited-file'
6
+ import { rename_identifier, type RenameRequest, type TypeScriptApi } from './rename-identifier'
7
+
8
+ // `josh rename <old> <new> [--import <old-specifier> <new-specifier>] <file...>` — one identifier, and
9
+ // the import specifier it moved with, renamed across files in one call (joshuafolkken/kit#5236), where
10
+ // a lane would otherwise spend one Read and one Edit per file.
11
+ //
12
+ // **All or nothing**: a file the rename would not touch is named and nothing is written, since a path
13
+ // passed by mistake means the file list is not the one the caller thinks it is. Each written file is
14
+ // then formatted the way the edit hook formats an edited one — a Bash write gets no hook.
15
+
16
+ const ARGV_OFFSET = 2
17
+ const FAILURE_EXIT_CODE = 1
18
+ const IMPORT_FLAG = '--import'
19
+ const SPECIFIER_COUNT = 2
20
+ // What the TypeScript parser reads whole; a `.svelte` file's markup would be parsed as script.
21
+ const SCRIPT_EXTENSIONS: ReadonlySet<string> = new Set([
22
+ '.ts',
23
+ '.tsx',
24
+ '.mts',
25
+ '.cts',
26
+ '.js',
27
+ '.jsx',
28
+ '.mjs',
29
+ '.cjs',
30
+ ])
31
+ const IDENTIFIER = /^[$A-Z_a-z][\w$]*$/u
32
+ const USAGE = `Usage: josh rename <old-identifier> <new-identifier> [${IMPORT_FLAG} <old-specifier> <new-specifier>] <file...>`
33
+
34
+ interface RenameArguments {
35
+ request: RenameRequest
36
+ files: ReadonlyArray<string>
37
+ }
38
+
39
+ interface FileRename {
40
+ file: string
41
+ text: string
42
+ count: number
43
+ is_taken: boolean
44
+ }
45
+
46
+ type Formatter = (files: ReadonlyArray<string>) => Promise<void>
47
+
48
+ interface SplitArguments {
49
+ specifier: RenameRequest['specifier']
50
+ rest: ReadonlyArray<string>
51
+ }
52
+
53
+ function split_import(argv: ReadonlyArray<string>): SplitArguments | undefined {
54
+ const at = argv.indexOf(IMPORT_FLAG)
55
+
56
+ if (at === -1) return { specifier: undefined, rest: argv }
57
+ const [from, to] = argv.slice(at + 1, at + 1 + SPECIFIER_COUNT)
58
+ if (from === undefined || to === undefined) return undefined
59
+
60
+ return { specifier: [from, to], rest: argv.toSpliced(at, 1 + SPECIFIER_COUNT) }
61
+ }
62
+
63
+ function arguments_of(split: SplitArguments): RenameArguments | undefined {
64
+ const [old_name = '', new_name = '', ...files] = split.rest
65
+
66
+ if (!IDENTIFIER.test(old_name) || !IDENTIFIER.test(new_name)) return undefined
67
+
68
+ return { request: { old_name, new_name, specifier: split.specifier }, files }
69
+ }
70
+
71
+ function parse(argv: ReadonlyArray<string>): RenameArguments | undefined {
72
+ const split = split_import(argv)
73
+ const parsed = split === undefined ? undefined : arguments_of(split)
74
+
75
+ return parsed?.files.length === 0 ? undefined : parsed
76
+ }
77
+
78
+ function refuse(reason: string, files: ReadonlyArray<string>): number {
79
+ console.error(`josh rename: ${reason}: ${files.join(', ')} — nothing was written`)
80
+
81
+ return FAILURE_EXIT_CODE
82
+ }
83
+
84
+ function rename_all(api: TypeScriptApi, parsed: RenameArguments): ReadonlyArray<FileRename> {
85
+ return parsed.files.map((file) => ({
86
+ file,
87
+ ...rename_identifier.rewrite(api, file, readFileSync(file, 'utf8'), parsed.request),
88
+ }))
89
+ }
90
+
91
+ async function write_all(
92
+ renames: ReadonlyArray<FileRename>,
93
+ formatter: Formatter,
94
+ ): Promise<number> {
95
+ for (const rename of renames) {
96
+ writeFileSync(rename.file, rename.text)
97
+ console.info(`${rename.file}: ${String(rename.count)}`)
98
+ }
99
+
100
+ await formatter(renames.map((rename) => rename.file))
101
+
102
+ return 0
103
+ }
104
+
105
+ function file_refusal(files: ReadonlyArray<string>): number | undefined {
106
+ const missing = files.filter((file) => !existsSync(file))
107
+ if (missing.length > 0) return refuse('no such file', missing)
108
+ const unparsed = files.filter((file) => !SCRIPT_EXTENSIONS.has(path.extname(file)))
109
+
110
+ return unparsed.length > 0 ? refuse('not a TypeScript or JavaScript file', unparsed) : undefined
111
+ }
112
+
113
+ function files_where(
114
+ renames: ReadonlyArray<FileRename>,
115
+ is_match: (rename: FileRename) => boolean,
116
+ ): ReadonlyArray<string> {
117
+ return renames.filter((rename) => is_match(rename)).map((rename) => rename.file)
118
+ }
119
+
120
+ // The rename matches by spelling, so a file that already binds the new name could end up with one
121
+ // binding shadowing or merging with another; it is refused rather than guessed at.
122
+ function rename_refusal(renames: ReadonlyArray<FileRename>, new_name: string): number | undefined {
123
+ const untouched = files_where(renames, (rename) => rename.count === 0)
124
+ if (untouched.length > 0) return refuse('no replacement', untouched)
125
+ const taken = files_where(renames, (rename) => rename.is_taken)
126
+
127
+ return taken.length > 0 ? refuse(`\`${new_name}\` is already bound`, taken) : undefined
128
+ }
129
+
130
+ async function apply(
131
+ api: TypeScriptApi,
132
+ parsed: RenameArguments,
133
+ formatter: Formatter,
134
+ ): Promise<number> {
135
+ const file_stop = file_refusal(parsed.files)
136
+ if (file_stop !== undefined) return file_stop
137
+ const renames = rename_all(api, parsed)
138
+
139
+ return rename_refusal(renames, parsed.request.new_name) ?? (await write_all(renames, formatter))
140
+ }
141
+
142
+ // The edit hook's own formatter, one file at a time: each run rewrites the file the next may import.
143
+ async function format_files(
144
+ files: ReadonlyArray<string>,
145
+ format_one: typeof format_edited_payload = format_edited_payload,
146
+ ): Promise<void> {
147
+ for (const file of files) {
148
+ const payload = JSON.stringify({ tool_input: { file_path: path.resolve(file) } })
149
+ // eslint-disable-next-line no-await-in-loop -- formatters rewrite files the next run reads
150
+ const diagnostics = await format_one(payload, process.cwd())
151
+
152
+ if (diagnostics !== undefined) console.info(diagnostics)
153
+ }
154
+ }
155
+
156
+ async function run(
157
+ argv: ReadonlyArray<string>,
158
+ api: TypeScriptApi,
159
+ formatter: Formatter = format_files,
160
+ ): Promise<number> {
161
+ const parsed = parse(argv)
162
+
163
+ if (parsed !== undefined) return await apply(api, parsed, formatter)
164
+ console.error(USAGE)
165
+
166
+ return FAILURE_EXIT_CODE
167
+ }
168
+
169
+ async function main(argv: ReadonlyArray<string>): Promise<void> {
170
+ const typescript = await import('typescript')
171
+
172
+ process.exitCode = await run(argv, typescript.default)
173
+ }
174
+
175
+ const rename_cli = { USAGE, format_files, main, run }
176
+
177
+ if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
178
+
179
+ export { rename_cli }