@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
@@ -0,0 +1,107 @@
1
+ import { lane_breakdown, type Breakdown, type Segment, type Stage } from './lane-breakdown'
2
+ import { lane_breakdown_implement } from './lane-breakdown-implement'
3
+ import { lane_ledger, type LedgerEntry } from './lane-ledger'
4
+ import type { ToolCall } from './lane-transcript-calls'
5
+
6
+ // What each ship stage of a lane's breakdown spent its time on (joshuafolkken/kit#5294): the laps the
7
+ // ship wrote for its inner steps (`run-ship-lap.ts`), the lane's core-budget waits and the checks of
8
+ // the lane's gates, each under the stage it ended in, and the time between two ship stages split by
9
+ // the Bash the lane child ran there, by the implementation's kinds (`lane-breakdown-implement.ts`).
10
+ // A lap and a wait or a check inside it overlap — the gate's wait for cores and its checks, run side
11
+ // by side, are part of its `josh gate` lap — so a stage's laps can add up to more.
12
+
13
+ const { KIND } = lane_ledger
14
+ const CORE_WAIT_STEP = 'core-budget wait'
15
+
16
+ // Each stage's laps, longest first, keyed by the stage's name in the breakdown.
17
+ type Laps = ReadonlyMap<string, ReadonlyArray<Stage>>
18
+
19
+ interface Placed {
20
+ at_ms: number
21
+ part: Stage
22
+ }
23
+
24
+ function lap_of(entry: LedgerEntry, issue: number): ReadonlyArray<Placed> {
25
+ if (entry.kind !== KIND.SHIP_LAP || entry.issue !== issue) return []
26
+
27
+ return [{ at_ms: Date.parse(entry.at), part: { name: entry.step, ms: entry.elapsed_ms } }]
28
+ }
29
+
30
+ function wait_of(entry: LedgerEntry, issue: number): ReadonlyArray<Placed> {
31
+ if (entry.kind !== KIND.CORE_WAIT || entry.issue !== issue) return []
32
+
33
+ return [{ at_ms: Date.parse(entry.at), part: { name: CORE_WAIT_STEP, ms: entry.waited_ms } }]
34
+ }
35
+
36
+ // Each check the lane's gate ran, placed where the gate ended (joshuafolkken/kit#5319). A row with no
37
+ // `issue` — outside a lane, or written before the gate recorded it — is no lane's; a reused check
38
+ // started nothing, so its zero is no time spent.
39
+ function checks_of(entry: LedgerEntry, issue: number): ReadonlyArray<Placed> {
40
+ if (entry.kind !== KIND.GATE || entry.issue !== issue) return []
41
+ const at_ms = Date.parse(entry.at)
42
+
43
+ return (entry.checks ?? [])
44
+ .filter((check) => check.is_reused !== true)
45
+ .map((check) => ({ at_ms, part: { name: check.label, ms: check.elapsed_ms } }))
46
+ }
47
+
48
+ // The ship stage a lap, a wait or a check ended in — never the time between stages, which the ship runs nothing in.
49
+ function stage_at(segments: ReadonlyArray<Segment>, at_ms: number): string | undefined {
50
+ const segment = segments.find((span) => at_ms > span.from_ms && at_ms <= span.to_ms)
51
+
52
+ return segment?.stage === lane_breakdown.BETWEEN_STAGE ? undefined : segment?.stage
53
+ }
54
+
55
+ function grouped(
56
+ placed: ReadonlyArray<Placed>,
57
+ segments: ReadonlyArray<Segment>,
58
+ ): Map<string, Array<Stage>> {
59
+ const groups = new Map<string, Array<Stage>>()
60
+
61
+ for (const { at_ms, part } of placed) {
62
+ const stage = stage_at(segments, at_ms)
63
+
64
+ if (stage !== undefined) groups.set(stage, [...(groups.get(stage) ?? []), part])
65
+ }
66
+
67
+ return groups
68
+ }
69
+
70
+ function between_of(
71
+ calls: ReadonlyArray<ToolCall>,
72
+ segments: ReadonlyArray<Segment>,
73
+ ): Array<Stage> {
74
+ const between = segments.filter((segment) => segment.stage === lane_breakdown.BETWEEN_STAGE)
75
+
76
+ return lane_breakdown_implement.bash_kinds(calls, between)
77
+ }
78
+
79
+ /** `issue`'s ship stages split by their laps, and the time between them by the lane child's Bash. */
80
+ function of(
81
+ entries: ReadonlyArray<LedgerEntry>,
82
+ issue: number,
83
+ breakdown: Breakdown,
84
+ calls: ReadonlyArray<ToolCall>,
85
+ ): Laps {
86
+ const placed = entries.flatMap((entry) => [
87
+ ...lap_of(entry, issue),
88
+ ...wait_of(entry, issue),
89
+ ...checks_of(entry, issue),
90
+ ])
91
+ const laps = new Map(
92
+ [...grouped(placed, breakdown.ship)].map(([stage, parts]) => [
93
+ stage,
94
+ lane_breakdown.ranked(parts),
95
+ ]),
96
+ )
97
+ const between = between_of(calls, breakdown.ship)
98
+
99
+ if (between.length > 0) laps.set(lane_breakdown.BETWEEN_STAGE, between)
100
+
101
+ return laps
102
+ }
103
+
104
+ const lane_breakdown_laps = { CORE_WAIT_STEP, of }
105
+
106
+ export { lane_breakdown_laps }
107
+ export type { Laps }
@@ -0,0 +1,76 @@
1
+ import { lane_breakdown, type Breakdown } from './lane-breakdown'
2
+ import { lane_ledger, type LedgerEntry, type TestPinnedEntry } from './lane-ledger'
3
+
4
+ // What a lane's ship pre-detach spent on `josh test:pinned` (joshuafolkken/kit#5078): the lane's
5
+ // `test-pinned` rows written inside that stage, as hunks the cache answered and the probed hunks'
6
+ // test files and wall time, the longest first.
7
+
8
+ type PinnedProbe = TestPinnedEntry['probes'][number]
9
+
10
+ // The longest probes named; the rest are counted in the head alone.
11
+ const MAX_SHOWN = 5
12
+
13
+ // `run:review`'s check and the pre-detach's probe past its stop (joshuafolkken/kit#5327) alike.
14
+ const DISCARDED_LABEL = 'background test:pinned probes discarded'
15
+
16
+ function is_lane_row(entry: LedgerEntry, issue: number): entry is TestPinnedEntry {
17
+ return entry.kind === lane_ledger.KIND.TEST_PINNED && entry.issue === issue
18
+ }
19
+
20
+ function is_discarded(entry: TestPinnedEntry): boolean {
21
+ return entry.discarded === true
22
+ }
23
+
24
+ function is_in_pre_detach(entry: TestPinnedEntry, breakdown: Breakdown): boolean {
25
+ const at_ms = Date.parse(entry.at)
26
+
27
+ return breakdown.pre_detach.some((span) => at_ms >= span.from_ms && at_ms <= span.to_ms)
28
+ }
29
+
30
+ // `issue`'s `test-pinned` rows written inside its ship pre-detach stage.
31
+ function rows_of(
32
+ entries: ReadonlyArray<LedgerEntry>,
33
+ issue: number,
34
+ breakdown: Breakdown,
35
+ ): Array<TestPinnedEntry> {
36
+ return entries
37
+ .filter((entry) => is_lane_row(entry, issue))
38
+ .filter((entry) => !is_discarded(entry) && is_in_pre_detach(entry, breakdown))
39
+ }
40
+
41
+ // `issue`'s background probes stopped before their answer (joshuafolkken/kit#5262, #5327), as a
42
+ // count and their wall time; `''` when none was.
43
+ function discarded_text(entries: ReadonlyArray<LedgerEntry>, issue: number): string {
44
+ const rows = entries
45
+ .filter((entry) => is_lane_row(entry, issue))
46
+ .filter((entry) => is_discarded(entry))
47
+ if (rows.length === 0) return ''
48
+ const elapsed_ms = rows.reduce((sum, row) => sum + row.elapsed_ms, 0)
49
+
50
+ return `${DISCARDED_LABEL} ${String(rows.length)}, ${lane_breakdown.minutes_text(elapsed_ms)}`
51
+ }
52
+
53
+ function probe_text(probe: PinnedProbe): string {
54
+ const tests = probe.tests === undefined ? '' : ` ${String(probe.tests)} test files`
55
+
56
+ return `${probe.file}${tests} ${lane_breakdown.minutes_text(probe.elapsed_ms)}`
57
+ }
58
+
59
+ // The detail the pre-detach line carries, or `''` when no probe ran inside it.
60
+ function detail_text(rows: ReadonlyArray<TestPinnedEntry>): string {
61
+ if (rows.length === 0) return ''
62
+ const probes = rows
63
+ .flatMap((row) => row.probes)
64
+ .toSorted((left, right) => right.elapsed_ms - left.elapsed_ms)
65
+ const held = rows.reduce((sum, row) => sum + row.held, 0)
66
+ const rewired = rows.reduce((sum, row) => sum + (row.rewired ?? 0), 0)
67
+ const total = held + rewired + probes.length
68
+ const head = `test:pinned ${String(total)} hunks, ${String(held)} cached, ${String(probes.length)} probed`
69
+ const counts = rewired === 0 ? [head] : [head, `${String(rewired)} rewired`]
70
+
71
+ return ` (${[...counts, ...probes.slice(0, MAX_SHOWN).map((probe) => probe_text(probe))].join(', ')})`
72
+ }
73
+
74
+ const lane_breakdown_pinned = { detail_text, discarded_text, rows_of }
75
+
76
+ export { lane_breakdown_pinned }
@@ -0,0 +1,145 @@
1
+ import { lane_breakdown, type Breakdown, type Stage } from './lane-breakdown'
2
+ import { lane_breakdown_implement, type ImplementDetail } from './lane-breakdown-implement'
3
+ import { lane_breakdown_laps, type Laps } from './lane-breakdown-laps'
4
+ import { lane_breakdown_pinned } from './lane-breakdown-pinned'
5
+ import { lane_ci_path_stats } from './lane-ci-path-stats'
6
+ import type { LedgerEntry } from './lane-ledger'
7
+
8
+ // A lane's breakdown in words (joshuafolkken/kit#4995): the stages longest first, the implementation's
9
+ // tool-call kinds beside it, and the waits taken out last. `josh lane:breakdown` prints it, the overrun
10
+ // investigation comments it on the lane's Issue and leads its prompt with it (`lane-overrun.ts`).
11
+
12
+ const HEADING = 'Net time by stage, longest first'
13
+ const EXCLUDED = 'waits taken out (park, outage, usage limit, yield, host sleep)'
14
+ const SLEPT = 'of which host sleep'
15
+ const YIELDED = 'of which yield wait'
16
+
17
+ interface Report {
18
+ breakdown: Breakdown
19
+ detail: ImplementDetail
20
+ // The ship pre-detach line's `test:pinned` detail, `''` when none (joshuafolkken/kit#5078).
21
+ pinned?: string
22
+ // The discarded `run:review` background probes' line, `''` when none (joshuafolkken/kit#5262).
23
+ discarded?: string
24
+ // The followup's CI wait's last check to settle, `''` when none was recorded (joshuafolkken/kit#5295).
25
+ critical?: string
26
+ // Each ship stage's laps, and the Bash between ship stages, longest first (joshuafolkken/kit#5294).
27
+ laps?: Laps
28
+ }
29
+
30
+ // A stage's line and the laps printed under it.
31
+ interface Entry {
32
+ text: string
33
+ laps: ReadonlyArray<string>
34
+ }
35
+
36
+ function part_text(part: Stage): string {
37
+ return `${part.name} ${lane_breakdown.minutes_text(part.ms)}`
38
+ }
39
+
40
+ // A kind's minutes, and the backgrounded subagent calls it counted at no time.
41
+ function kind_text(kind: Stage, untimed: ImplementDetail['untimed']): string {
42
+ const count = untimed.get(kind.name) ?? 0
43
+
44
+ return count > 0 ? `${part_text(kind)} + ${String(count)} backgrounded, untimed` : part_text(kind)
45
+ }
46
+
47
+ function detail_text(detail: ImplementDetail): string {
48
+ const kinds = detail.kinds.map((kind) => kind_text(kind, detail.untimed))
49
+ const count = String(detail.background)
50
+ const background =
51
+ detail.background > 0 ? [`${count} backgrounded calls, their waits in editing & thinking`] : []
52
+
53
+ return ` (${[...kinds, ...background].join(', ')})`
54
+ }
55
+
56
+ // Why a ship stage ran or was skipped, as its event line said (joshuafolkken/kit#5296).
57
+ function reason_text(reason: string | undefined): string {
58
+ return reason === undefined ? '' : ` (${reason})`
59
+ }
60
+
61
+ // The detail a stage's line carries after its minutes, `''` for a stage with none.
62
+ function suffix_of(name: string, report: Report): string {
63
+ const suffixes: Record<string, string | undefined> = {
64
+ [lane_breakdown.IMPLEMENT_STAGE]: detail_text(report.detail),
65
+ [lane_breakdown.PRE_DETACH_STAGE]: report.pinned,
66
+ [lane_breakdown.FOLLOWUP_STAGE]: report.critical,
67
+ }
68
+
69
+ return suffixes[name] ?? reason_text(report.breakdown.reasons?.get(name))
70
+ }
71
+
72
+ function stage_entry(stage: Stage, report: Report): Entry {
73
+ const laps = report.laps?.get(stage.name) ?? []
74
+
75
+ return {
76
+ text: `${part_text(stage)}${suffix_of(stage.name, report)}`,
77
+ laps: laps.map((lap) => part_text(lap)),
78
+ }
79
+ }
80
+
81
+ function entries_of(report: Report): Array<Entry> {
82
+ const { breakdown } = report
83
+ const yielded = `${YIELDED} ${lane_breakdown.minutes_text(breakdown.yield_ms)}`
84
+ const slept = `${SLEPT} ${lane_breakdown.minutes_text(breakdown.slept_ms)}`
85
+ const excluded = `${EXCLUDED} ${lane_breakdown.minutes_text(breakdown.excluded_ms)}, ${yielded}, ${slept}`
86
+
87
+ const discarded =
88
+ report.discarded === undefined || report.discarded === '' ? [] : [report.discarded]
89
+
90
+ const tail = [...discarded, excluded].map((text) => ({ text, laps: [] }))
91
+
92
+ return [...breakdown.stages.map((stage) => stage_entry(stage, report)), ...tail]
93
+ }
94
+
95
+ function bullets_of(entry: Entry): Array<string> {
96
+ return [`- ${entry.text}`, ...entry.laps.map((lap) => ` - ${lap}`)]
97
+ }
98
+
99
+ function inline_of(entry: Entry): string {
100
+ return entry.laps.length > 0 ? `${entry.text} [${entry.laps.join(', ')}]` : entry.text
101
+ }
102
+
103
+ // `issue`'s breakdown with its implementation's tool calls read off its transcripts, and its ship
104
+ // pre-detach's `test:pinned` rows read off `entries`.
105
+ function report_of(
106
+ issue: number,
107
+ breakdown: Breakdown,
108
+ entries: ReadonlyArray<LedgerEntry>,
109
+ ): Report {
110
+ const calls = lane_breakdown_implement.read(issue, breakdown)
111
+ const rows = lane_breakdown_pinned.rows_of(entries, issue, breakdown)
112
+
113
+ return {
114
+ breakdown,
115
+ detail: lane_breakdown_implement.of(calls, breakdown),
116
+ laps: lane_breakdown_laps.of(entries, issue, breakdown, calls),
117
+ pinned: lane_breakdown_pinned.detail_text(rows),
118
+ discarded: lane_breakdown_pinned.discarded_text(entries, issue),
119
+ critical: lane_ci_path_stats.last_check_text(entries, issue),
120
+ }
121
+ }
122
+
123
+ // The Issue comment and the printout: a heading, then one bullet per stage.
124
+ function comment(issue: number, minutes: number, report: Report): string {
125
+ const lead = `${HEADING}, ${String(minutes)} min of net time`
126
+ const source = `(\`pnpm josh lane:breakdown ${String(issue)}\`):`
127
+
128
+ return [
129
+ `${lead} ${source}`,
130
+ '',
131
+ ...entries_of(report).flatMap((entry) => bullets_of(entry)),
132
+ ].join('\n')
133
+ }
134
+
135
+ // One line, the form the investigation's prompt leads with.
136
+ function line(report: Report): string {
137
+ return `${HEADING}: ${entries_of(report)
138
+ .map((entry) => inline_of(entry))
139
+ .join('; ')}.`
140
+ }
141
+
142
+ const lane_breakdown_text = { comment, line, report_of }
143
+
144
+ export { lane_breakdown_text }
145
+ export type { Report }
@@ -0,0 +1,239 @@
1
+ import { MS_PER_MINUTE } from '#scripts/lib/timeouts'
2
+ import { run_event_stream, type RunEvent } from '#scripts/run/event/run-event-stream'
3
+ import { run_ship_stage } from '#scripts/run/ship/run-ship-stage'
4
+ import { lane_ledger, type LedgerEntry } from './lane-ledger'
5
+ import { lane_net_time, type LaneSpan } from './lane-net-time'
6
+ import { lane_stop_stats } from './lane-stop-stats'
7
+
8
+ // A lane's net time by stage (joshuafolkken/kit#4995), read off the run events it already leaves: from
9
+ // its dispatch to its `plan`, the implementation from the `plan` (or `lane-phase implement`) to the first
10
+ // ship stage, each ship stage from its start to its end, and the time between ship stages — a stopped
11
+ // stage's fix included. The waits `lane:net` takes out are taken out of the stage they fell in and
12
+ // counted apart, so the stages add up to the net time. A cut and its resume open no stage: the
13
+ // implementation stays one stage across them.
14
+
15
+ const { EVENT_KIND } = run_event_stream
16
+ const { PHASE } = run_ship_stage
17
+
18
+ const PLAN_STAGE = 'start to plan'
19
+ const IMPLEMENT_STAGE = 'implement'
20
+ const BETWEEN_STAGE = 'between ship stages'
21
+ const SHIP_LEAD = 'ship '
22
+ const IMPLEMENT_SUFFIX = ' implement'
23
+ const PRE_DETACH_STAGE = `${SHIP_LEAD}${lane_ledger.PRE_DETACH_STAGE}`
24
+ const FOLLOWUP_STAGE = `${SHIP_LEAD}${run_ship_stage.STAGE.FOLLOWUP}`
25
+
26
+ // One stage's net milliseconds.
27
+ interface Stage {
28
+ name: string
29
+ ms: number
30
+ }
31
+
32
+ interface Breakdown {
33
+ // Longest first, the waits taken out.
34
+ stages: ReadonlyArray<Stage>
35
+ // The waits taken out, together.
36
+ excluded_ms: number
37
+ // The host's sleeps among them (joshuafolkken/kit#5032).
38
+ slept_ms: number
39
+ // The yields' waits for a redispatch among them (joshuafolkken/kit#5216).
40
+ yield_ms: number
41
+ // The waits taken out, each — the implementation's split leaves them out of its remainder too.
42
+ waits: ReadonlyArray<LaneSpan>
43
+ // The implementation's spans, waits left in — the window its tool calls are read in.
44
+ implement: ReadonlyArray<LaneSpan>
45
+ // The ship pre-detach stage's spans — the window its `test:pinned` rows are read in
46
+ // (joshuafolkken/kit#5078).
47
+ pre_detach: ReadonlyArray<LaneSpan>
48
+ // Each ship stage's spans and the spans between them, waits left in — the windows its laps and the
49
+ // fixes between stages are read in (joshuafolkken/kit#5294).
50
+ ship: ReadonlyArray<Segment>
51
+ // Why each ship stage last ran or was skipped, where its event line said (joshuafolkken/kit#5296).
52
+ reasons?: ReadonlyMap<string, string>
53
+ }
54
+
55
+ interface Segment extends LaneSpan {
56
+ stage: string
57
+ }
58
+
59
+ function is_ship(segment: Segment): boolean {
60
+ return segment.stage.startsWith(SHIP_LEAD) || segment.stage === BETWEEN_STAGE
61
+ }
62
+
63
+ interface Marker {
64
+ at_ms: number
65
+ stage: string
66
+ }
67
+
68
+ function ship_stage_of(text: string): string {
69
+ const { stage, phase } = run_ship_stage.words_of(text)
70
+
71
+ return phase === PHASE.START ? `${SHIP_LEAD}${stage}` : BETWEEN_STAGE
72
+ }
73
+
74
+ // The stage an event opens, `undefined` for one that opens none.
75
+ function stage_of(event: RunEvent): string | undefined {
76
+ if (event.kind === EVENT_KIND.SHIP_STAGE) return ship_stage_of(event.text)
77
+ const is_implement =
78
+ event.kind === EVENT_KIND.PLAN ||
79
+ (event.kind === EVENT_KIND.LANE_PHASE && event.text.endsWith(IMPLEMENT_SUFFIX))
80
+
81
+ return is_implement ? IMPLEMENT_STAGE : undefined
82
+ }
83
+
84
+ function is_inside(at_ms: number, span: LaneSpan): boolean {
85
+ return at_ms >= span.from_ms && at_ms < span.to_ms
86
+ }
87
+
88
+ function is_lane_event(event: RunEvent, issue: number, span: LaneSpan): boolean {
89
+ return lane_stop_stats.issue_of(event) === issue && is_inside(Date.parse(event.at), span)
90
+ }
91
+
92
+ function marker_of(event: RunEvent, issue: number, span: LaneSpan): ReadonlyArray<Marker> {
93
+ const stage = stage_of(event)
94
+ const at_ms = Date.parse(event.at)
95
+
96
+ return stage !== undefined && is_lane_event(event, issue, span) ? [{ at_ms, stage }] : []
97
+ }
98
+
99
+ function reason_of(event: RunEvent, issue: number, span: LaneSpan): Array<[string, string]> {
100
+ if (event.kind !== EVENT_KIND.SHIP_STAGE || !is_lane_event(event, issue, span)) return []
101
+
102
+ const reason = run_ship_stage.reason_of(event.text)
103
+ const stage = `${SHIP_LEAD}${run_ship_stage.words_of(event.text).stage}`
104
+
105
+ return reason === undefined ? [] : [[stage, reason]]
106
+ }
107
+
108
+ // The newest reason each ship stage's event line gave, by the stage's name.
109
+ function reasons_of(
110
+ events: ReadonlyArray<RunEvent>,
111
+ issue: number,
112
+ span: LaneSpan,
113
+ ): Map<string, string> {
114
+ const ordered = events.toSorted((left, right) => Date.parse(left.at) - Date.parse(right.at))
115
+
116
+ return new Map(ordered.flatMap((event) => reason_of(event, issue, span)))
117
+ }
118
+
119
+ function segments_of(
120
+ events: ReadonlyArray<RunEvent>,
121
+ issue: number,
122
+ span: LaneSpan,
123
+ ): Array<Segment> {
124
+ const opened = events
125
+ .flatMap((event) => marker_of(event, issue, span))
126
+ .toSorted((left, right) => left.at_ms - right.at_ms)
127
+ // A marker of the stage already open opens nothing: the `plan` and `lane-phase implement` of one
128
+ // start, or of a resumed session, leave the implementation one span.
129
+ const markers = [{ at_ms: span.from_ms, stage: PLAN_STAGE }, ...opened].filter(
130
+ (marker, index, all) => marker.stage !== all[index - 1]?.stage,
131
+ )
132
+
133
+ return markers.map((marker, index) => ({
134
+ stage: marker.stage,
135
+ from_ms: marker.at_ms,
136
+ to_ms: markers[index + 1]?.at_ms ?? span.to_ms,
137
+ }))
138
+ }
139
+
140
+ function clipped(segment: LaneSpan, parts: ReadonlyArray<LaneSpan>): Array<LaneSpan> {
141
+ return parts
142
+ .map((part) => ({
143
+ from_ms: Math.max(segment.from_ms, part.from_ms),
144
+ to_ms: Math.min(segment.to_ms, part.to_ms),
145
+ }))
146
+ .filter((part) => part.to_ms > part.from_ms)
147
+ .toSorted((left, right) => left.from_ms - right.from_ms)
148
+ }
149
+
150
+ // The milliseconds of `segment` that any of `parts` covers, each covered millisecond once — parallel
151
+ // tool calls, or a call across a wait, overlap.
152
+ function covered_ms(segment: LaneSpan, parts: ReadonlyArray<LaneSpan>): number {
153
+ let reached_ms = segment.from_ms
154
+ let total_ms = 0
155
+
156
+ for (const part of clipped(segment, parts)) {
157
+ total_ms += Math.max(0, part.to_ms - Math.max(part.from_ms, reached_ms))
158
+ reached_ms = Math.max(reached_ms, part.to_ms)
159
+ }
160
+
161
+ return total_ms
162
+ }
163
+
164
+ // Each name's milliseconds summed, longest first — the stages here and the tool-call kinds of the
165
+ // implementation (`lane-breakdown-implement.ts`) alike.
166
+ function ranked(parts: ReadonlyArray<Stage>): Array<Stage> {
167
+ const totals = new Map<string, number>()
168
+
169
+ for (const part of parts) totals.set(part.name, (totals.get(part.name) ?? 0) + part.ms)
170
+
171
+ return [...totals]
172
+ .map(([name, ms]) => ({ name, ms }))
173
+ .toSorted((left, right) => right.ms - left.ms)
174
+ }
175
+
176
+ function spans_ms(spans: ReadonlyArray<LaneSpan>): number {
177
+ return spans.reduce((sum, span) => sum + span.to_ms - span.from_ms, 0)
178
+ }
179
+
180
+ /**
181
+ * `issue`'s lane by stage, or `undefined` when the ledger holds no dispatch and merge of it — the same
182
+ * span and waits `lane_net_time.net_ms` reads, so the stages add up to it.
183
+ */
184
+ function of(
185
+ entries: ReadonlyArray<LedgerEntry>,
186
+ events: ReadonlyArray<RunEvent>,
187
+ issue: number,
188
+ ): Breakdown | undefined {
189
+ const span = lane_net_time.span_of(entries, issue)
190
+
191
+ if (span === undefined) return undefined
192
+
193
+ const waits = lane_net_time.waits(entries, events, issue, span)
194
+ const segments = segments_of(events, issue, span)
195
+ const parts = segments.map((segment) => ({
196
+ name: segment.stage,
197
+ ms: segment.to_ms - segment.from_ms - covered_ms(segment, waits),
198
+ }))
199
+
200
+ return {
201
+ stages: ranked(parts),
202
+ excluded_ms: spans_ms(waits),
203
+ slept_ms: spans_ms(lane_net_time.slept(events, span)),
204
+ yield_ms: spans_ms(lane_net_time.yielded(entries, events, issue, span)),
205
+ waits,
206
+ implement: segments.filter((segment) => segment.stage === IMPLEMENT_STAGE),
207
+ pre_detach: segments.filter((segment) => segment.stage === PRE_DETACH_STAGE),
208
+ ship: segments.filter((segment) => is_ship(segment)),
209
+ reasons: reasons_of(events, issue, span),
210
+ }
211
+ }
212
+
213
+ function minutes_text(ms: number): string {
214
+ return `${(ms / MS_PER_MINUTE).toFixed(1)} min`
215
+ }
216
+
217
+ // The longest stage in whole minutes, the words the overrun's start note carries.
218
+ function longest_of(breakdown: Breakdown): { name: string; minutes: number } | undefined {
219
+ const [longest] = breakdown.stages
220
+
221
+ return longest === undefined
222
+ ? undefined
223
+ : { name: longest.name, minutes: Math.round(longest.ms / MS_PER_MINUTE) }
224
+ }
225
+
226
+ const lane_breakdown = {
227
+ BETWEEN_STAGE,
228
+ FOLLOWUP_STAGE,
229
+ IMPLEMENT_STAGE,
230
+ PRE_DETACH_STAGE,
231
+ covered_ms,
232
+ longest_of,
233
+ minutes_text,
234
+ of,
235
+ ranked,
236
+ }
237
+
238
+ export { lane_breakdown }
239
+ export type { Breakdown, Segment, Stage }
@@ -1,10 +1,16 @@
1
1
  import { MS_PER_SECOND } from '#scripts/lib/timeouts'
2
- import { lane_ledger, type GateCheckRecord, type GateEntry, type LedgerEntry } from './lane-ledger'
2
+ import {
3
+ lane_ledger,
4
+ type GateCheckRecord,
5
+ type GateEntry,
6
+ type LedgerEntry,
7
+ type PushMissEntry,
8
+ } from './lane-ledger'
3
9
  import { lane_stage_stats } from './lane-stage-stats'
4
10
  import { lane_stats, type StatsWindow } from './lane-stats'
5
11
 
6
12
  // Which check a gate waited on: one period's per-check rows reduced to one row per check — median,
7
- // maximum, runs, reuses, no-ops and whole-suite fallbacks — printed last by `josh lane:stats`.
13
+ // maximum, runs, reuses, no-ops and whole-suite fallbacks — printed by `josh lane:stats`.
8
14
  //
9
15
  // The whole gate is the first row, since its reuse started no check (joshuafolkken/kit#4397); the
10
16
  // checks follow in the order they first appear.
@@ -15,7 +21,8 @@ import { lane_stats, type StatsWindow } from './lane-stats'
15
21
  // would stand for a run that tested nothing.
16
22
  //
17
23
  // **The fallbacks are broken down by why** in a second table, one row per reason kind, so a slow unit
18
- // leg can be read as the full suite it ran and the reason it had to.
24
+ // leg can be read as the full suite it ran and the reason it had to. A pre-push hook that ran a suite
25
+ // over a record it could not reuse joins it, prefixed `pre-push <scope>:`.
19
26
 
20
27
  const DECIMALS = 1
21
28
  const WHOLE_GATE_LABEL = 'gate (whole)'
@@ -69,8 +76,21 @@ function whole_gate(gate: GateEntry): GateCheckRecord {
69
76
  }
70
77
  }
71
78
 
72
- function fallback_table(checks: ReadonlyArray<GateCheckRecord>): string {
73
- const reasons = checks.map((check) => check.fallback).filter((reason) => reason !== undefined)
79
+ function is_push_miss(entry: LedgerEntry): entry is PushMissEntry {
80
+ return entry.kind === lane_ledger.KIND.PUSH_MISS
81
+ }
82
+
83
+ // A pre-push hook's miss, told apart from the gate's own fallbacks by its scope (joshuafolkken/kit#5234).
84
+ function push_reason(miss: PushMissEntry): string {
85
+ return `pre-push ${miss.scope}: ${miss.reason}`
86
+ }
87
+
88
+ function fallback_table(
89
+ checks: ReadonlyArray<GateCheckRecord>,
90
+ misses: ReadonlyArray<PushMissEntry>,
91
+ ): string {
92
+ const fallbacks = checks.map((check) => check.fallback).filter((reason) => reason !== undefined)
93
+ const reasons = [...fallbacks, ...misses.map((miss) => push_reason(miss))]
74
94
  const kinds = [...new Set(reasons)]
75
95
  const rows = kinds.map((kind) =>
76
96
  lane_stats.to_row([kind, String(reasons.filter((reason) => reason === kind).length)]),
@@ -81,17 +101,18 @@ function fallback_table(checks: ReadonlyArray<GateCheckRecord>): string {
81
101
 
82
102
  // The period's tables: `entries` is the whole ledger, filtered here to `window`.
83
103
  function table(entries: ReadonlyArray<LedgerEntry>, window: StatsWindow): string {
84
- const gates = lane_stats.in_window(entries, window).filter(is_gate)
104
+ const windowed = lane_stats.in_window(entries, window)
105
+ const gates = windowed.filter(is_gate)
85
106
  const checks = gates.flatMap((gate) => gate.checks ?? [])
86
107
  const rows = [...gates.map((gate) => whole_gate(gate)), ...checks]
87
108
  const labels = [...new Set(rows.map((row) => row.label))]
88
109
 
89
110
  return [
90
111
  [...header(COLUMNS), ...labels.map((label) => check_row(label, rows))].join('\n'),
91
- fallback_table(checks),
112
+ fallback_table(checks, windowed.filter(is_push_miss)),
92
113
  ].join('\n\n')
93
114
  }
94
115
 
95
- const lane_check_stats = { WHOLE_GATE_LABEL, table }
116
+ const lane_check_stats = { WHOLE_GATE_LABEL, cell, header, table }
96
117
 
97
118
  export { lane_check_stats }
@@ -95,8 +95,8 @@ function outage_resume_invocation(issue: string): string {
95
95
  // tail and the changed files (`run-ship-stop-context.ts`), so the session starts at the fix rather than
96
96
  // at `josh ship --log` and `git diff` (joshuafolkken/kit#3923).
97
97
  //
98
- // The context gets what the rest of the prompt leaves of the one argv element's cap, so the whole
99
- // prompt still launches (joshuafolkken/kit#3964).
98
+ // The context gets what the rest of the prompt leaves of `MAX_VALUE_LENGTH`, so the whole prompt
99
+ // stays within it and launches (joshuafolkken/kit#3964).
100
100
  function known_stop_lines(
101
101
  issue: string,
102
102
  stop: ShipStop,
@@ -127,6 +127,12 @@ function ship_stop_invocation(issue: string, stop?: ShipStop): string {
127
127
  return [opening, ...middle, closing].join(LINE_BREAK)
128
128
  }
129
129
 
130
+ // The same stop for the session that launched the ship and still waits on it (`run-ship-waiter.ts`):
131
+ // the next command and the context alone, since that session has the run in front of it already.
132
+ function ship_stop_note(issue: string, stop: ShipStop): string {
133
+ return known_stop_lines(issue, stop, []).join(LINE_BREAK)
134
+ }
135
+
130
136
  const lane_child_invocation = {
131
137
  child_invocation,
132
138
  outage_resume_invocation,
@@ -135,6 +141,7 @@ const lane_child_invocation = {
135
141
  review_invocation,
136
142
  ship_pattern,
137
143
  ship_stop_invocation,
144
+ ship_stop_note,
138
145
  }
139
146
 
140
147
  export type { ShipStop }
@@ -0,0 +1,12 @@
1
+ // The environment keys a launcher marks a lane child with, in a module of their own so the unit
2
+ // suite's vitest config reads them without widening its import graph (`whole-suite-files.ts`).
3
+ // `lane-child-marker.ts` documents each mark; a mark added there is added here, and the unit suite
4
+ // then blanks it with no list of its own (joshuafolkken/kit#5029).
5
+
6
+ const KEY = 'JOSH_LANE_CHILD'
7
+ const OVERRUN_KEY = 'JOSH_LANE_OVERRUN'
8
+ const MARK_KEYS: ReadonlyArray<string> = [KEY, OVERRUN_KEY]
9
+
10
+ const lane_child_mark_keys = { KEY, MARK_KEYS, OVERRUN_KEY }
11
+
12
+ export { lane_child_mark_keys }