@joshuafolkken/kit 1.1784.0 → 1.2116.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 +60 -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 +386 -360
  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 +16 -9
  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
@@ -0,0 +1,107 @@
1
+ import { git_gh_issue_read } from '#scripts/gh/git-gh-issue-read'
2
+ import { SPLIT_ROUTE_LABEL } from '#scripts/issue/issue-labels'
3
+ import { issue_read } from '#scripts/issue/issue-read'
4
+ import { session_cite } from '#scripts/issue/session-cite'
5
+ import {
6
+ lane_ledger,
7
+ type LedgerEntry,
8
+ type SplitFiledEntry,
9
+ type SplitNoticeEntry,
10
+ } from '#scripts/lane/lane-ledger'
11
+ import { lane_ledger_write } from '#scripts/lane/lane-ledger-write'
12
+ import { split_assess } from './split-assess'
13
+
14
+ // **What answers a split notice** (joshuafolkken/kit#4695). Of the lanes the notice reached, none split
15
+ // and none recorded why it stayed one Issue (joshuafolkken/kit#4676): the notice asked, and nothing
16
+ // checked. The pre-gate `josh run:cut` now does. A noticed Issue passes once it has either answer:
17
+ //
18
+ // - **a split child** — a `josh issue:file --route split` filed from its lane, recorded in the lane
19
+ // ledger as the filing lands;
20
+ // - **a reason** — a trusted Issue comment carrying the filing's own reason line
21
+ // (`split_assess.REASON_PREFIX`), so one declaration reads the same at filing and before the gate.
22
+
23
+ const { REASON_PREFIX } = split_assess
24
+ const NOTICE_SECTION = `split-assessment.md → "${split_assess.NOTICE_SECTION}"`
25
+ const UNREAD_NOTE = 'Its comments could not be read, so no recorded reason was found. '
26
+
27
+ function is_notice(entry: LedgerEntry): entry is SplitNoticeEntry {
28
+ return entry.kind === lane_ledger.KIND.SPLIT_NOTICE
29
+ }
30
+
31
+ function is_split_child(entry: LedgerEntry): entry is SplitFiledEntry {
32
+ return entry.kind === lane_ledger.KIND.SPLIT_FILED
33
+ }
34
+
35
+ // The ledger's split notices, oldest first — `josh lane:stats` counts the lanes they reached.
36
+ function notices(entries: ReadonlyArray<LedgerEntry>): ReadonlyArray<SplitNoticeEntry> {
37
+ return entries.filter((entry) => is_notice(entry))
38
+ }
39
+
40
+ // The Issues whose lane filed a split child.
41
+ function split_issues(entries: ReadonlyArray<LedgerEntry>): ReadonlySet<number> {
42
+ return new Set(entries.filter((entry) => is_split_child(entry)).map((entry) => entry.issue))
43
+ }
44
+
45
+ function is_reason_line(line: string): boolean {
46
+ const text = line.trim()
47
+
48
+ return text.startsWith(REASON_PREFIX) && text !== REASON_PREFIX
49
+ }
50
+
51
+ function has_reason(bodies: ReadonlyArray<string>): boolean {
52
+ return bodies.some((body) => body.split('\n').some((line) => is_reason_line(line)))
53
+ }
54
+
55
+ // The trusted comments' bodies, or `undefined` when the listing could not be read.
56
+ async function trusted_comments(issue: number): Promise<ReadonlyArray<string> | undefined> {
57
+ const json = await git_gh_issue_read.issue_list_comments(String(issue))
58
+ const comments = await issue_read.parse_comments(json)
59
+
60
+ return comments === undefined ? undefined : issue_read.trusted_bodies(comments)
61
+ }
62
+
63
+ function refusal_text(notice: SplitNoticeEntry, bodies: ReadonlyArray<string> | undefined): string {
64
+ const counted = `${String(notice.files)} file(s), ${String(notice.lines)} line(s), tests excluded`
65
+ const unread = bodies === undefined ? UNREAD_NOTE : ''
66
+ const answers = `post an Issue comment with the line \`${REASON_PREFIX} <理由>\`, or file the rest with \`pnpm josh issue:file --route split\``
67
+
68
+ return `${session_cite.issue(notice.issue)} got the split notice (${counted}) and has neither a recorded reason nor a split child. ${unread}Either ${answers}, then run \`pnpm josh run:cut ${String(notice.issue)}\` again — ${NOTICE_SECTION}`
69
+ }
70
+
71
+ // The refusal for a noticed Issue that has no answer yet, else `undefined`. The ledger is read first,
72
+ // so an Issue the notice never reached costs no GitHub read.
73
+ async function refusal(
74
+ issue: number,
75
+ entries: ReadonlyArray<LedgerEntry>,
76
+ ): Promise<string | undefined> {
77
+ const notice = notices(entries).findLast((entry) => entry.issue === issue)
78
+
79
+ if (notice === undefined || split_issues(entries).has(issue)) return undefined
80
+ const bodies = await trusted_comments(issue)
81
+
82
+ return bodies !== undefined && has_reason(bodies) ? undefined : refusal_text(notice, bodies)
83
+ }
84
+
85
+ // The refusal against this repository's lane ledger; outside a repository there is none to read.
86
+ async function ledger_refusal(issue: number): Promise<string | undefined> {
87
+ const ledger = await lane_ledger.target()
88
+
89
+ return ledger === undefined ? undefined : await refusal(issue, lane_ledger.read_entries(ledger))
90
+ }
91
+
92
+ interface Filing {
93
+ route: string | undefined
94
+ found_during: string | undefined
95
+ child: string
96
+ }
97
+
98
+ // What `josh issue:file` just filed: a split child is recorded against the lane it was found in. Any
99
+ // other route, and a filing found in no lane, record nothing.
100
+ async function record_child({ route, found_during, child }: Filing): Promise<void> {
101
+ if (route !== SPLIT_ROUTE_LABEL || found_during === undefined) return
102
+ await lane_ledger_write.record_split_filed({ issue: Number(found_during), child })
103
+ }
104
+
105
+ const split_resolution = { ledger_refusal, notices, record_child, refusal, split_issues }
106
+
107
+ export { split_resolution }
@@ -0,0 +1,185 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import path from 'node:path'
3
+ import { git_spawn } from '#scripts/git/git-spawn'
4
+ import { test_declared_logic } from './test-declared-logic'
5
+ import { whole_suite_files } from './whole-suite-files'
6
+
7
+ // **The test files that import a module directly, read off their text** (joshuafolkken/kit#5122). A
8
+ // file every test imports (`whole_suite_files.EVERY_TEST_IMPORTS`) sends `vitest related` to the whole
9
+ // suite, so `josh test:related` and the `josh test:pinned` probe hand vitest the test files importing it
10
+ // directly instead. The whole suite still runs once, in the gate's `test:unit` and in every CI shard.
11
+ //
12
+ // The same reading decides which heavy test files a scoped run keeps (`related-heavy-tests.ts`).
13
+
14
+ const PACKAGE_FILE = 'package.json'
15
+ const WILDCARD = '*'
16
+ const CURRENT_DIRECTORY_PREFIX = './'
17
+ const NUL = '\0'
18
+
19
+ // The module specifiers a source names in a static or dynamic import, an export-from or a `vi.mock`.
20
+ const SPECIFIER_PATTERN = /(?:\bfrom\s+|\bimport\s*\(\s*|\bimport\s+|\bmock\(\s*)["']([^"']+)["']/gu
21
+
22
+ type ImportMap = Readonly<Record<string, string>>
23
+
24
+ interface SourceReader {
25
+ imports: ImportMap
26
+ read_source: (file: string) => string | undefined
27
+ }
28
+
29
+ // Repository-relative, `/`-separated and without its extension — the one key a specifier and a changed
30
+ // file are compared by, since an import names `./thing`, `./thing.ts` or `./thing.js` alike.
31
+ function module_key(file: string): string {
32
+ const posix = file.split(path.sep).join(path.posix.sep)
33
+
34
+ return posix.slice(0, posix.length - path.posix.extname(posix).length)
35
+ }
36
+
37
+ function specifiers_of(source: string): Array<string> {
38
+ return [...source.matchAll(SPECIFIER_PATTERN)].flatMap((match) => match.slice(1))
39
+ }
40
+
41
+ function alias_target(specifier: string, imports: ImportMap): string | undefined {
42
+ const exact = imports[specifier]
43
+
44
+ if (exact !== undefined) return exact
45
+
46
+ const key = Object.keys(imports).find(
47
+ (pattern) => pattern.endsWith(WILDCARD) && specifier.startsWith(pattern.slice(0, -1)),
48
+ )
49
+
50
+ if (key === undefined) return undefined
51
+
52
+ return imports[key]?.split(WILDCARD).join(specifier.slice(key.length - 1))
53
+ }
54
+
55
+ function relative_target(specifier: string, from: string): string {
56
+ return path.posix.join(path.posix.dirname(from), specifier)
57
+ }
58
+
59
+ // The repository-relative module key a specifier names, or `undefined` for a package import.
60
+ function resolve_specifier(
61
+ specifier: string,
62
+ from: string,
63
+ imports: ImportMap,
64
+ ): string | undefined {
65
+ if (specifier.startsWith('.')) return module_key(relative_target(specifier, from))
66
+
67
+ const target = alias_target(specifier, imports)
68
+
69
+ if (target === undefined) return undefined
70
+
71
+ return module_key(path.posix.normalize(target.replace(CURRENT_DIRECTORY_PREFIX, '')))
72
+ }
73
+
74
+ // Whether `source`, the text of `from`, imports one of the `scoped` module keys directly.
75
+ function names_any(
76
+ source: string,
77
+ from: string,
78
+ scoped: ReadonlySet<string>,
79
+ imports: ImportMap,
80
+ ): boolean {
81
+ return specifiers_of(source).some((specifier) => {
82
+ const resolved = resolve_specifier(specifier, from, imports)
83
+
84
+ return resolved !== undefined && scoped.has(resolved)
85
+ })
86
+ }
87
+
88
+ function read_imports(root: string): ImportMap {
89
+ try {
90
+ const parsed: unknown = JSON.parse(readFileSync(path.join(root, PACKAGE_FILE), 'utf8'))
91
+ const imports: unknown = Reflect.get(new Object(parsed), 'imports')
92
+
93
+ if (typeof imports !== 'object' || imports === null) return {}
94
+
95
+ // A conditional entry (`{ "node": … }`) names no single file, so it resolves nothing.
96
+ return Object.fromEntries(
97
+ Object.entries(imports).filter(
98
+ (entry): entry is [string, string] => typeof entry[1] === 'string',
99
+ ),
100
+ )
101
+ } catch {
102
+ return {}
103
+ }
104
+ }
105
+
106
+ function read_source_at(root: string, file: string): string | undefined {
107
+ try {
108
+ return readFileSync(path.join(root, file), 'utf8')
109
+ } catch {
110
+ return undefined
111
+ }
112
+ }
113
+
114
+ function source_reader(root: string): SourceReader {
115
+ return { imports: read_imports(root), read_source: (file) => read_source_at(root, file) }
116
+ }
117
+
118
+ // The test files the work tree at `root` holds, tracked or not but not ignored, repository-relative.
119
+ async function test_files(root: string): Promise<Array<string>> {
120
+ const listed = await git_spawn.read(['-C', root, 'ls-files', '-coz', '--exclude-standard'])
121
+
122
+ return listed.split(NUL).filter((file) => test_declared_logic.is_test_file(file))
123
+ }
124
+
125
+ // The test files of `tests` importing `file` directly; an unreadable one imports nothing.
126
+ function importers_among(
127
+ file: string,
128
+ tests: ReadonlyArray<string>,
129
+ reader: SourceReader,
130
+ ): Array<string> {
131
+ const scoped = new Set([module_key(file)])
132
+
133
+ return tests.filter((test) => {
134
+ const source = reader.read_source(test)
135
+
136
+ return source !== undefined && names_any(source, test, scoped, reader.imports)
137
+ })
138
+ }
139
+
140
+ function every_test_imports_of(files: ReadonlyArray<string>): Array<string> {
141
+ return files.filter((file) => whole_suite_files.EVERY_TEST_IMPORTS.has(path.normalize(file)))
142
+ }
143
+
144
+ // Whether a command argument, relative to the working directory or absolute, is a file every test imports.
145
+ function is_every_test_import(root: string, argument: string): boolean {
146
+ return whole_suite_files.EVERY_TEST_IMPORTS.has(path.relative(root, path.resolve(argument)))
147
+ }
148
+
149
+ // For each of `files`, the test files in the work tree at `root` importing it directly; a file no test
150
+ // imports directly maps to none.
151
+ async function importers_of(
152
+ root: string,
153
+ files: ReadonlyArray<string>,
154
+ ): Promise<Map<string, Array<string>>> {
155
+ if (files.length === 0) return new Map()
156
+
157
+ const tests = await test_files(root)
158
+ const reader = source_reader(root)
159
+
160
+ return new Map(files.map((file) => [file, importers_among(file, tests, reader)]))
161
+ }
162
+
163
+ // `importers_of` for the `files` every test imports; any other file is left out, for vitest to walk
164
+ // its graph.
165
+ async function every_test_importers(
166
+ root: string,
167
+ files: ReadonlyArray<string>,
168
+ ): Promise<Map<string, Array<string>>> {
169
+ return await importers_of(root, every_test_imports_of(files))
170
+ }
171
+
172
+ const direct_importers = {
173
+ every_test_importers,
174
+ every_test_imports_of,
175
+ importers_of,
176
+ is_every_test_import,
177
+ module_key,
178
+ names_any,
179
+ resolve_specifier,
180
+ source_reader,
181
+ specifiers_of,
182
+ }
183
+
184
+ export type { ImportMap, SourceReader }
185
+ export { direct_importers }
@@ -0,0 +1,83 @@
1
+ import path from 'node:path'
2
+ import { git_command } from '#scripts/git/git-command'
3
+ import { file_reader } from '#scripts/lib/read-file'
4
+
5
+ // **`tools/test/pure-files.ts` is a whole-suite file only for what is not its entries**
6
+ // (joshuafolkken/kit#5001). The vitest config imports it, so `vitest related` widens to every test on
7
+ // it, but an entry added, removed or rewritten moves only that test file between the pure and the
8
+ // isolated project. A change made of entry lines alone therefore reaches the moved entries and the two
9
+ // tests that hold the list to the classifier; any other line — an import, the export — still runs the
10
+ // whole suite.
11
+
12
+ const PURE_FILES_PATH = path.join('tools', 'test', 'pure-files.ts')
13
+ const LIST_TESTS: ReadonlyArray<string> = [
14
+ path.join('tools', 'test', 'pure-files.test.ts'),
15
+ path.join('tools', 'test', 'classify-isolation.test.ts'),
16
+ ]
17
+ const ENTRY_LINE = /^\t'(?<entry>[^']+)',$/u
18
+
19
+ function entry_of(line: string): string | undefined {
20
+ return ENTRY_LINE.exec(line)?.groups?.['entry']
21
+ }
22
+
23
+ function lines_of(text: string): Array<string> {
24
+ return text.trimEnd().split('\n')
25
+ }
26
+
27
+ function frame_of(text: string): string {
28
+ return lines_of(text)
29
+ .filter((line) => entry_of(line) === undefined)
30
+ .join('\n')
31
+ }
32
+
33
+ function entries_of(text: string): Set<string> {
34
+ return new Set(lines_of(text).flatMap((line) => entry_of(line) ?? []))
35
+ }
36
+
37
+ function missing_from(entries: ReadonlySet<string>, other: ReadonlySet<string>): Array<string> {
38
+ return [...entries].filter((entry) => !other.has(entry))
39
+ }
40
+
41
+ // The entries one text holds and the other does not, or `undefined` when anything but entry lines
42
+ // differs — the answer that keeps the whole suite.
43
+ function moved_entries(before: string, after: string): ReadonlyArray<string> | undefined {
44
+ if (frame_of(before) !== frame_of(after)) return undefined
45
+
46
+ const was = entries_of(before)
47
+ const is = entries_of(after)
48
+
49
+ return [...missing_from(is, was), ...missing_from(was, is)]
50
+ }
51
+
52
+ // The test files an entries-only change reaches, the list's own tests first.
53
+ function tests_of(entries: ReadonlyArray<string>): ReadonlyArray<string> {
54
+ return [...LIST_TESTS, ...entries]
55
+ }
56
+
57
+ async function base_text(): Promise<string | undefined> {
58
+ try {
59
+ return await git_command.show_file(`${await git_command.change_base()}:${PURE_FILES_PATH}`)
60
+ } catch {
61
+ return undefined
62
+ }
63
+ }
64
+
65
+ // The entries this branch moved in the list against its change base, or `undefined` when the list did
66
+ // not change, changed beyond its entries, or either side cannot be read.
67
+ async function read_moved(
68
+ root: string,
69
+ changed: ReadonlyArray<string> | undefined,
70
+ ): Promise<ReadonlyArray<string> | undefined> {
71
+ if (changed?.includes(PURE_FILES_PATH) !== true) return undefined
72
+
73
+ const before = await base_text()
74
+ const after = file_reader.read_if_readable(path.join(root, PURE_FILES_PATH))
75
+
76
+ if (before === undefined || after === undefined) return undefined
77
+
78
+ return moved_entries(before, after)
79
+ }
80
+
81
+ const pure_files_entries = { PURE_FILES_PATH, moved_entries, read_moved, tests_of }
82
+
83
+ export { pure_files_entries }
@@ -0,0 +1,81 @@
1
+ import path from 'node:path'
2
+ import { direct_importers, type SourceReader } from './direct-importers'
3
+ import type { RelatedScope } from './test-related-scope'
4
+ import { unit_durations, type Durations } from './unit-durations'
5
+ import { vitest_cli_excludes } from './vitest-cli-excludes'
6
+
7
+ // **A scoped run leaves out the heavy test files a change reaches only indirectly**
8
+ // (joshuafolkken/kit#5105). A hub module's change reaches the integration tests importing it through
9
+ // the shared harnesses, and a scoped run's wall clock is bounded below by its longest file — over
10
+ // `HEAVY_TEST_MS` each — whatever else it narrows. A heavy file still runs when this change moved it,
11
+ // the module it is named for, or a file it imports directly, so the test written for a module is never
12
+ // left out with it, even when it reaches that module through a harness.
13
+ //
14
+ // "Heavy" is read off the CI shards' duration record (`unit-durations.json`), never a named list, so
15
+ // a file that slows down or speeds up moves in or out on the record's next refresh. The whole-suite
16
+ // fallback and every CI shard carry no exclusion, so a heavy file left out here still runs before the
17
+ // merge.
18
+
19
+ const HEAVY_TEST_MS = 10_000
20
+ const { EXCLUDE_FLAG } = vitest_cli_excludes
21
+ // The suffix a test file's module key carries past the module it is named for.
22
+ const TEST_SUFFIX_PATTERN = /(?:\.integration)?\.test$/u
23
+ const { module_key } = direct_importers
24
+
25
+ interface HeavyReader extends SourceReader {
26
+ durations: Durations
27
+ }
28
+
29
+ function heavy_tests(durations: Durations): Array<string> {
30
+ return Object.keys(durations).filter((file) => (durations[file] ?? 0) > HEAVY_TEST_MS)
31
+ }
32
+
33
+ function imports_directly(file: string, scoped: ReadonlySet<string>, reader: HeavyReader): boolean {
34
+ const source = reader.read_source(file)
35
+
36
+ if (source === undefined) return true
37
+
38
+ return direct_importers.names_any(source, file, scoped, reader.imports)
39
+ }
40
+
41
+ function is_kept(file: string, scoped: ReadonlySet<string>, reader: HeavyReader): boolean {
42
+ const key = module_key(file)
43
+
44
+ if (scoped.has(key) || scoped.has(key.replace(TEST_SUFFIX_PATTERN, ''))) return true
45
+
46
+ return imports_directly(file, scoped, reader)
47
+ }
48
+
49
+ // The heavy files to leave out of a scoped run: every one this scope neither holds, names nor imports from.
50
+ function excluded_tests(scoped_files: ReadonlyArray<string>, reader: HeavyReader): Array<string> {
51
+ const scoped = new Set(scoped_files.map((file) => module_key(file)))
52
+
53
+ return heavy_tests(reader.durations).filter((file) => !is_kept(file, scoped, reader))
54
+ }
55
+
56
+ function file_reader(root: string): HeavyReader {
57
+ return { ...direct_importers.source_reader(root), durations: unit_durations.read(root) }
58
+ }
59
+
60
+ // The `--exclude` flags a scope's vitest run carries: none unless it narrowed to related files.
61
+ function exclude_flags(
62
+ scope: RelatedScope,
63
+ root: string,
64
+ reader: HeavyReader = file_reader(root),
65
+ ): Array<string> {
66
+ if (scope.mode !== 'related') return []
67
+
68
+ const scoped = scope.files.map((file) => path.relative(root, file))
69
+
70
+ return excluded_tests(scoped, reader).flatMap((file) => [EXCLUDE_FLAG, file])
71
+ }
72
+
73
+ const related_heavy_tests = {
74
+ EXCLUDE_FLAG,
75
+ HEAVY_TEST_MS,
76
+ exclude_flags,
77
+ heavy_tests,
78
+ }
79
+
80
+ export type { HeavyReader }
81
+ export { related_heavy_tests }
@@ -0,0 +1,88 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import path from 'node:path'
3
+ import { project_checks } from '#scripts/gate/project-checks'
4
+ import { no_base_checkout } from '#scripts/git/no-base-checkout'
5
+ import { test_related_claim } from './test-related-claim'
6
+ import { related_scope } from './test-related-scope'
7
+ import { test_unit_guard } from './test-unit-guard'
8
+
9
+ // **The second pass of `josh test:related` for a change that touches how the base branch is
10
+ // resolved** (joshuafolkken/kit#4710). A lane has a local `main`; CI's checkout has none, so a diff
11
+ // against a bare `main` passes every local check and fails only in CI. The related tests of each such
12
+ // file run again in `no-base-checkout.ts`'s checkout, which has none either.
13
+ //
14
+ // **A change that touches none of it runs nothing more** — no checkout, no vitest — so the gate takes
15
+ // no longer for it. **Nor does a consumer project**: the checkout holds only what git tracks, and a
16
+ // consumer's vitest config can read a generated, ignored file (`.svelte-kit/tsconfig.json`) it lacks.
17
+
18
+ // The names a file that resolves the base, or reads a diff against it, carries — the modules'
19
+ // own, and the bare default-branch name a caller could hand git.
20
+ const BASE_NAMES: ReadonlyArray<string> = [
21
+ 'change_base',
22
+ 'default_branch',
23
+ 'diff_main',
24
+ "'main'",
25
+ '"main"',
26
+ ]
27
+
28
+ // Shared with `test-related.ts`'s own reading of which files name another: a file it cannot read
29
+ // names nothing.
30
+ function text_of(file_path: string): string {
31
+ try {
32
+ return readFileSync(file_path, 'utf8')
33
+ } catch {
34
+ return ''
35
+ }
36
+ }
37
+
38
+ function names_any(text: string, names: ReadonlyArray<string>): boolean {
39
+ return names.some((name) => text.includes(name))
40
+ }
41
+
42
+ function touches_base(root: string, file: string): boolean {
43
+ if (!related_scope.is_relatable(file)) return false
44
+
45
+ return names_any(text_of(path.join(root, file)), BASE_NAMES)
46
+ }
47
+
48
+ function touching(root: string, changed: ReadonlyArray<string>): Array<string> {
49
+ return changed.filter((file) => touches_base(root, file))
50
+ }
51
+
52
+ async function run_in_checkout(
53
+ root: string,
54
+ files: ReadonlyArray<string>,
55
+ flags: ReadonlyArray<string>,
56
+ ): Promise<number> {
57
+ const directory = await no_base_checkout.create(root)
58
+
59
+ try {
60
+ return await test_unit_guard.run_vitest_in(directory, ['related', ...files, '--run', ...flags])
61
+ } finally {
62
+ no_base_checkout.remove(directory)
63
+ }
64
+ }
65
+
66
+ async function run_if_touched(
67
+ root: string,
68
+ changed: ReadonlyArray<string>,
69
+ flags: ReadonlyArray<string>,
70
+ ): Promise<number> {
71
+ const files = project_checks.is_kit_repository(root) ? touching(root, changed) : []
72
+
73
+ if (files.length === 0) return 0
74
+
75
+ process.stdout.write(
76
+ `josh test:related: ${String(files.length)} changed file(s) touch the base branch's resolution — their related tests run again in a checkout with no local main, as CI's has none\n`,
77
+ )
78
+
79
+ // Its own claim, since the first pass released its own before this one starts.
80
+ return await test_related_claim.with_unit_claim(
81
+ files,
82
+ async () => await run_in_checkout(root, files, flags),
83
+ )
84
+ }
85
+
86
+ const test_no_base = { names_any, run_if_touched, text_of, touching }
87
+
88
+ export { test_no_base }