@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,208 @@
1
+ import { git_gh_issue_read } from '#scripts/gh/git-gh-issue-read'
2
+ import {
3
+ git_gh_pr_read,
4
+ read_pull_or_listed,
5
+ read_pull as read_rest_pull,
6
+ } from '#scripts/gh/git-gh-pr-read'
7
+ import { git_gh_pr_rest } from '#scripts/gh/git-gh-pr-rest'
8
+ import { git_command } from '#scripts/git/git-command'
9
+ import { issue_state, type IssueState } from '#scripts/issue/issue-state'
10
+ import { session_cite } from '#scripts/issue/session-cite'
11
+ import { PROCESS_ALIVE, PROCESS_NONE, type ProcessTrace } from '#scripts/run/run-liveness'
12
+ import { lane_await } from './lane-await'
13
+ import type { LaneInfo } from './lane-registry'
14
+ import { lane_spent } from './lane-spent'
15
+ import {
16
+ lane_state,
17
+ type LaneChange,
18
+ type LaneRecords,
19
+ type LaneState,
20
+ type RecordOutcome,
21
+ } from './lane-state'
22
+
23
+ // `josh lane:adopt` (joshuafolkken/kit#4744): give a lane whose state record was lost — a restart, a
24
+ // usage limit, an interrupted run — a record again, from what can be read off it, without touching its
25
+ // branch, its work tree or its pull request.
26
+ //
27
+ // **Nothing is guessed.** A lane is written `open` — opened, no child working in it — only when its
28
+ // process probe answers that no child is there and its work tree status, its unpushed commits, its pull
29
+ // request and its issue all read; any one unread leaves it unknown, counted in use as before
30
+ // (`backlog-occupied.ts`). `open` rather than `paused`: nobody suspended it, and a paused lane is one
31
+ // `run:liveness` says not to recover. The next launch moves it to `running` (`lane-state.ts`), and
32
+ // the next `backlogrun` takes the lane back while its issue still carries `in-progress`
33
+ // (`backlog-drive-carried.ts`).
34
+
35
+ const ADOPT_COMMAND = 'lane:adopt'
36
+ const ISSUE_FIELDS = 'state,labels'
37
+ const SEPARATOR = ' · '
38
+
39
+ // The branch's pull request — the open one, else the newest (`git_gh_pr_rest.select_pull`) — with its
40
+ // gh state, since a reopened lane's branch can still carry the merged one.
41
+ interface Pull {
42
+ number: number
43
+ state: string
44
+ }
45
+
46
+ // A pull request read: the branch's pull request, or none.
47
+ interface PullRead {
48
+ pull: Pull | undefined
49
+ }
50
+
51
+ interface LaneFacts {
52
+ branch: string
53
+ is_dirty: boolean
54
+ unpushed: number
55
+ pull: Pull | undefined
56
+ issue: IssueState
57
+ }
58
+
59
+ // Each read answers `undefined` when it could not be made.
60
+ interface AdoptPorts {
61
+ process_trace: (issue: string) => ProcessTrace
62
+ tree_status: (directory: string) => Promise<string | undefined>
63
+ unpushed_commits: (branch: string) => Promise<number | undefined>
64
+ pull_request: (branch: string) => Promise<PullRead | undefined>
65
+ issue: (issue: string) => Promise<IssueState | undefined>
66
+ record: (change: LaneChange) => Promise<RecordOutcome>
67
+ }
68
+
69
+ type Adoption =
70
+ | { kind: 'adopted'; facts: LaneFacts }
71
+ | { kind: 'kept'; state: LaneState }
72
+ | { kind: 'left'; reason: string }
73
+
74
+ async function read_tree_status(directory: string): Promise<string | undefined> {
75
+ try {
76
+ return await git_command.status(directory)
77
+ } catch {
78
+ return undefined
79
+ }
80
+ }
81
+
82
+ async function read_pull(branch: string): Promise<Pull | undefined> {
83
+ const number = await git_gh_pr_read.pr_get_number(branch)
84
+
85
+ if (number === undefined) return undefined
86
+
87
+ // The listing row carries `state` and `merged_at` too, so it stands in for a detail GitHub refuses
88
+ // as too many files changed.
89
+ const pull = await read_pull_or_listed(branch, number, read_rest_pull)
90
+ const state = git_gh_pr_rest.to_pr_state(pull)
91
+
92
+ return state === undefined ? undefined : { number, state }
93
+ }
94
+
95
+ // `undefined` when anything could not be read, including a pull request that exists but whose number
96
+ // or state did not resolve.
97
+ async function read_pull_request(branch: string): Promise<PullRead | undefined> {
98
+ try {
99
+ if (!(await git_gh_pr_read.pr_exists(branch))) return { pull: undefined }
100
+
101
+ const pull = await read_pull(branch)
102
+
103
+ return pull === undefined ? undefined : { pull }
104
+ } catch {
105
+ return undefined
106
+ }
107
+ }
108
+
109
+ async function read_issue(issue: string): Promise<IssueState | undefined> {
110
+ const json = await git_gh_issue_read.issue_view_json(issue, ISSUE_FIELDS)
111
+
112
+ return json === undefined ? undefined : issue_state.parse_issue_state(json)
113
+ }
114
+
115
+ async function record_open(change: LaneChange): Promise<RecordOutcome> {
116
+ return await lane_state.record_adopted(change)
117
+ }
118
+
119
+ const LIVE_PORTS: AdoptPorts = {
120
+ process_trace: lane_await.process_trace_default,
121
+ tree_status: read_tree_status,
122
+ unpushed_commits: lane_spent.read_unpushed_commits,
123
+ pull_request: read_pull_request,
124
+ issue: read_issue,
125
+ record: record_open,
126
+ }
127
+
128
+ function left(reason: string): Adoption {
129
+ return { kind: 'left', reason }
130
+ }
131
+
132
+ function process_reason(lane: LaneInfo, ports: AdoptPorts): string | undefined {
133
+ if (lane.is_stranded) return 'its work tree is gone'
134
+
135
+ const trace = ports.process_trace(lane.issue)
136
+
137
+ if (trace === PROCESS_ALIVE) return 'a child is working in it'
138
+
139
+ return trace === PROCESS_NONE ? undefined : 'its process probe did not answer'
140
+ }
141
+
142
+ // What each fact is called where it could not be read, in the order `facts_of` reads them.
143
+ const FACT_NAMES = ['work tree status', 'unpushed commits', 'pull request', 'issue'] as const
144
+
145
+ function unread_names(reads: ReadonlyArray<unknown>): string {
146
+ return FACT_NAMES.filter((_name, index) => reads[index] === undefined).join(', ')
147
+ }
148
+
149
+ async function facts_of(lane: LaneInfo, ports: AdoptPorts): Promise<LaneFacts | string> {
150
+ const reads = await Promise.all([
151
+ ports.tree_status(lane.directory),
152
+ ports.unpushed_commits(lane.branch),
153
+ ports.pull_request(lane.branch),
154
+ ports.issue(lane.issue),
155
+ ])
156
+ const [status, unpushed, pull, issue] = reads
157
+
158
+ if (status === undefined || unpushed === undefined || pull === undefined || issue === undefined) {
159
+ return `could not read its ${unread_names(reads)}`
160
+ }
161
+
162
+ return { branch: lane.branch, is_dirty: status.trim() !== '', unpushed, pull: pull.pull, issue }
163
+ }
164
+
165
+ async function written(issue: string, facts: LaneFacts, ports: AdoptPorts): Promise<Adoption> {
166
+ const outcome = await ports.record({ issue, state: 'open', command: ADOPT_COMMAND })
167
+
168
+ return outcome.kind === 'written' ? { kind: 'adopted', facts } : left(outcome.reason)
169
+ }
170
+
171
+ /** Write an `open` record for `lane` when it has none and every fact about it reads. */
172
+ async function adopt(
173
+ lane: LaneInfo,
174
+ records: LaneRecords,
175
+ ports: AdoptPorts = LIVE_PORTS,
176
+ ): Promise<Adoption> {
177
+ const recorded = records.get(lane.issue)
178
+
179
+ if (recorded !== undefined) return { kind: 'kept', state: recorded.state }
180
+
181
+ const blocked = process_reason(lane, ports)
182
+
183
+ if (blocked !== undefined) return left(blocked)
184
+
185
+ const facts = await facts_of(lane, ports)
186
+
187
+ return typeof facts === 'string' ? left(facts) : await written(lane.issue, facts, ports)
188
+ }
189
+
190
+ /** `branch 4744-lane · uncommitted changes · 2 unpushed commit(s) · PR [#4801](…) OPEN · issue OPEN (in-progress)` */
191
+ function facts_text(facts: LaneFacts): string {
192
+ const labels = facts.issue.labels.length > 0 ? ` (${facts.issue.labels.join(', ')})` : ''
193
+
194
+ return [
195
+ `branch ${facts.branch}`,
196
+ facts.is_dirty ? 'uncommitted changes' : 'clean tree',
197
+ `${String(facts.unpushed)} unpushed commit(s)`,
198
+ facts.pull === undefined
199
+ ? 'no PR'
200
+ : `PR ${session_cite.issue(facts.pull.number)} ${facts.pull.state}`,
201
+ `issue ${facts.issue.state}${labels}`,
202
+ ].join(SEPARATOR)
203
+ }
204
+
205
+ const lane_adopt = { ADOPT_COMMAND, adopt, facts_text, read_pull_request }
206
+
207
+ export { lane_adopt }
208
+ export type { AdoptPorts, Adoption, LaneFacts }
@@ -2,6 +2,7 @@ import { spawnSync } from 'node:child_process'
2
2
  import { setTimeout as sleep } from 'node:timers/promises'
3
3
  import { parseArgs } from 'node:util'
4
4
  import { issue_number_shape } from '#scripts/issue/issue-number-shape'
5
+ import { poll } from '#scripts/lib/poll'
5
6
  import { MS_PER_SECOND, PROBE_TIMEOUT_MS } from '#scripts/lib/timeouts'
6
7
  import {
7
8
  PROCESS_ALIVE,
@@ -290,14 +291,10 @@ async function wait_for_any(
290
291
  const config = resolve_options(options)
291
292
  const states = await make_states(issues, config.is_settled)
292
293
 
293
- for (;;) {
294
- const completed = check_any(states, config.now(), config)
295
-
296
- if (completed !== undefined) return completed
297
-
298
- // eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
299
- await config.sleep(config.poll_ms)
300
- }
294
+ return await poll.wait_for(() => check_any(states, config.now(), config), {
295
+ interval_ms: config.poll_ms,
296
+ sleeper: config.sleep,
297
+ })
301
298
  }
302
299
 
303
300
  const lane_await = {
@@ -0,0 +1,123 @@
1
+ import { detached_launch } from '#scripts/run/detached-launch'
2
+ import { run_event_baseline } from '#scripts/run/event/run-event-baseline'
3
+ import { run_event_stream, type RunEvent } from '#scripts/run/event/run-event-stream'
4
+ import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
5
+ import { lane_investigation_switch } from './lane-investigation-switch'
6
+ import { lane_ledger } from './lane-ledger'
7
+ import { lane_overrun } from './lane-overrun'
8
+ import { lane_overrun_prompt } from './lane-overrun-prompt'
9
+ import { lane_stage_stats } from './lane-stage-stats'
10
+
11
+ // Every `BASELINE_MERGES`-th merge the median lane itself is investigated (joshuafolkken/kit#4887).
12
+ // The overrun investigation (`lane-overrun.ts`) reads only a lane slower than the threshold, so the time
13
+ // every lane spends is never a candidate for a cut. `run:merge` asks at each merge: the last multiple the
14
+ // ledger's merge count reached, when no note has it yet, launches a detached worker session that reads
15
+ // `lane:stats`, takes the stages and sub-stages that spend the most per merge, and files their causes
16
+ // by the overrun investigation's filing rules — the same prompt part, a cause's reducible minutes cut
17
+ // from one median merge rather than one lane (joshuafolkken/kit#4928). Its filings name no lane they
18
+ // were found during. The launch and the session's result go on the run's event stream as notes, which
19
+ // `run:board` shows. It runs only while `JOSH_LANE_INVESTIGATION` is on (`lane-investigation-switch.ts`);
20
+ // off by default, a due bucket launches nothing and notes nothing (joshuafolkken/kit#5044).
21
+
22
+ const { EVENT_KIND } = run_event_stream
23
+ const BASELINE_MERGES = 30
24
+ const LOG_PREFIX = 'josh-lane-baseline-'
25
+ const STATS_PERIOD_DAYS = 3
26
+ const MEDIAN_PLACEHOLDER = '<median lane minutes>'
27
+ const SCOPE = 'the median merge, judged from the per-merge minutes `lane:stats` prints'
28
+
29
+ // The last multiple of `BASELINE_MERGES` the count reached: two merges recorded between two asks, or an
30
+ // ask that failed, still leave the bucket due at the next merge.
31
+ function due_bucket(merges: number): number {
32
+ return Math.floor(merges / BASELINE_MERGES) * BASELINE_MERGES
33
+ }
34
+
35
+ // A count investigated already — a retried merge finds its note — launches no second session. A
36
+ // failure names no count, so it never answers for one.
37
+ function is_noted(events: ReadonlyArray<RunEvent>, merges: number): boolean {
38
+ return events.some((event) => {
39
+ const note = event.kind === EVENT_KIND.NOTE ? run_event_baseline.parse(event.text) : undefined
40
+
41
+ return note !== undefined && note.kind !== 'failed' && note.merges === merges
42
+ })
43
+ }
44
+
45
+ // The due bucket of the ledger's merge count, else `undefined` before the first.
46
+ async function due_merges(): Promise<number | undefined> {
47
+ const path = await lane_ledger.target()
48
+
49
+ if (path === undefined) return undefined
50
+
51
+ const merges = lane_ledger.read_entries(path).filter((entry) => lane_stage_stats.is_merge(entry))
52
+ const bucket = due_bucket(merges.length)
53
+
54
+ return bucket > 0 ? bucket : undefined
55
+ }
56
+
57
+ function reading(merges: number): string {
58
+ return [
59
+ `Investigate the median lane after ${String(merges)} merges: not an overrun, but the time every lane`,
60
+ 'spends. Leave this checkout as it is: write any file, an issue body included, under the system temp',
61
+ 'directory, and never stage, commit or push.',
62
+ `Read \`pnpm josh lane:stats --period ${String(STATS_PERIOD_DAYS)}\` — its stage table and its`,
63
+ 'implement sub-stage table — and take the several stages and sub-stages with the largest per-merge',
64
+ "time, not just the one largest. Read the period lanes' transcripts (the lane directories `lane:stats`",
65
+ "reads) and the run events (`pnpm josh run:event --from 0`) for where each one's time goes, and find",
66
+ 'the causes a fix could cut.',
67
+ 'Trace each cause to what can fix it: the minutes it spends per merge, the signal that led to the',
68
+ 'spend (which command printed what), the `file:line` of the code or document that decided it, and',
69
+ 'where to fix it.',
70
+ ].join(' ')
71
+ }
72
+
73
+ // One line: `detached_launch` lets a prompt break lines, but a single line keeps the log header whole.
74
+ function prompt(issue: number, merges: number): string {
75
+ const handling = lane_overrun_prompt.cause_handling({
76
+ origin: undefined,
77
+ loss_lines: lane_overrun_prompt.loss_lines_of(issue, MEDIAN_PLACEHOLDER),
78
+ template: run_event_baseline.ended_text(merges, '<result>'),
79
+ scope: SCOPE,
80
+ })
81
+
82
+ return `${reading(merges)} ${handling}`
83
+ }
84
+
85
+ function note_failure(note: string): void {
86
+ void run_event_stream_emit.emit(EVENT_KIND.NOTE, run_event_baseline.failed_text(note))
87
+ }
88
+
89
+ // The launch at merge `issue`, the `merges`-th; its filings count against that lane.
90
+ function launched(issue: number, merges: number): string {
91
+ return lane_overrun.launch({
92
+ env: {},
93
+ prompt: prompt(issue, merges),
94
+ log_prefix: `${LOG_PREFIX}${String(merges)}-`,
95
+ on_failure: note_failure,
96
+ })
97
+ }
98
+
99
+ async function investigate_baseline(issue: number): Promise<void> {
100
+ const merges = await due_merges()
101
+
102
+ if (merges === undefined || is_noted(await run_event_stream_emit.all_events(), merges)) return
103
+
104
+ await run_event_stream_emit.emit(
105
+ EVENT_KIND.NOTE,
106
+ run_event_baseline.started_text(merges, launched(issue, merges)),
107
+ )
108
+ }
109
+
110
+ // Never fails the merge it follows: an error is a note on the stream, not a refused merge.
111
+ async function investigate(issue: number): Promise<void> {
112
+ if (!lane_investigation_switch.is_on()) return
113
+
114
+ try {
115
+ await investigate_baseline(issue)
116
+ } catch (error) {
117
+ note_failure(detached_launch.note_of(error))
118
+ }
119
+ }
120
+
121
+ const lane_baseline = { due_bucket, investigate }
122
+
123
+ export { lane_baseline }
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env tsx
2
+ import { fileURLToPath } from 'node:url'
3
+ import { issue_number_shape } from '#scripts/issue/issue-number-shape'
4
+ import { session_cite } from '#scripts/issue/session-cite'
5
+ import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
6
+ import { lane_breakdown } from './lane-breakdown'
7
+ import { lane_breakdown_text } from './lane-breakdown-text'
8
+ import { lane_ledger } from './lane-ledger'
9
+ import { lane_net_time } from './lane-net-time'
10
+
11
+ // `josh lane:breakdown <issue>` — a merged lane's net time by stage (joshuafolkken/kit#4995), the same
12
+ // breakdown its overrun investigation comments on its Issue.
13
+
14
+ const ARGV_OFFSET = 2
15
+ const FAILURE_EXIT_CODE = 1
16
+ const USAGE = 'Usage: josh lane:breakdown <issue>'
17
+
18
+ async function read_ledger(): Promise<ReturnType<typeof lane_ledger.read_entries>> {
19
+ const path = await lane_ledger.target()
20
+
21
+ return path === undefined ? [] : lane_ledger.read_entries(path)
22
+ }
23
+
24
+ function missing(issue: string): number {
25
+ const lane = session_cite.issue(issue)
26
+
27
+ console.error(`josh lane:breakdown ${issue}: the ledger holds no dispatch and merge of ${lane}`)
28
+
29
+ return FAILURE_EXIT_CODE
30
+ }
31
+
32
+ async function print(issue: string): Promise<number> {
33
+ const [entries, events] = [await read_ledger(), await run_event_stream_emit.all_events()]
34
+ const minutes = lane_net_time.net_minutes(entries, events, Number(issue))
35
+ const breakdown = lane_breakdown.of(entries, events, Number(issue))
36
+
37
+ if (minutes === undefined || breakdown === undefined) return missing(issue)
38
+
39
+ const report = lane_breakdown_text.report_of(Number(issue), breakdown, entries)
40
+
41
+ console.info(lane_breakdown_text.comment(Number(issue), minutes, report))
42
+
43
+ return 0
44
+ }
45
+
46
+ async function run(argv: ReadonlyArray<string>): Promise<number> {
47
+ const [issue = ''] = argv
48
+
49
+ if (argv.length === 1 && issue_number_shape.is_issue_number(issue)) return await print(issue)
50
+
51
+ console.error(USAGE)
52
+
53
+ return FAILURE_EXIT_CODE
54
+ }
55
+
56
+ async function main(argv: ReadonlyArray<string>): Promise<void> {
57
+ process.exitCode = await run(argv)
58
+ }
59
+
60
+ const lane_breakdown_cli = { USAGE, run }
61
+
62
+ if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
63
+
64
+ export { lane_breakdown_cli }
@@ -0,0 +1,170 @@
1
+ import { cost_transcript } from '#scripts/cost-runtime/cost-transcript'
2
+ import { lane_breakdown, type Breakdown, type Stage } from './lane-breakdown'
3
+ import type { LaneSpan } from './lane-net-time'
4
+ import type { Subagent, ToolCall } from './lane-transcript-calls'
5
+ import { lane_transcript_stats } from './lane-transcript-stats'
6
+
7
+ // The implementation stage of a lane's breakdown (joshuafolkken/kit#4995) split by what its tool calls
8
+ // spent, read off the lane's transcripts: the main josh commands, the subagents, the reads and the rest
9
+ // of Bash, and what no call spent — the edits and the thinking. A backgrounded call has no duration
10
+ // (`lane-transcript-calls.ts`), so the wait on its result falls in the remainder; only its count shows.
11
+ //
12
+ // **The subagents split by the agent dispatched** — `subagent: investigator`, `subagent: reviewer`, …
13
+ // — and a backgrounded subagent call still names its kind, at no time, with its count beside it
14
+ // (joshuafolkken/kit#5297). `run:review` and `ship` / `ship:wait` count apart from other bash
15
+ // (joshuafolkken/kit#5293).
16
+
17
+ const REMAINDER = 'editing & thinking'
18
+ const OTHER_BASH = 'other bash'
19
+ const BASH_TOOL = 'Bash'
20
+ const READ = 'read'
21
+
22
+ const TOOL_KINDS: ReadonlyMap<string, string> = new Map([
23
+ ['Read', READ],
24
+ ['Grep', READ],
25
+ ['Glob', READ],
26
+ ])
27
+
28
+ const COMMAND_KINDS: ReadonlyArray<readonly [RegExp, string]> = [
29
+ [/\bjosh main:merge\b/u, 'main:merge'],
30
+ [/\bjosh check:related\b/u, 'check:related'],
31
+ [/\bjosh gate\b/u, 'gate'],
32
+ [/\bjosh run:review\b/u, 'run:review'],
33
+ [/\bjosh ship(?::wait)?\b/u, 'ship / ship:wait'],
34
+ [/\bjosh test(?::[\w-]+)?\b/u, 'test'],
35
+ [/\bjosh (?:lint|cspell)(?::[\w-]+)?\b/u, 'lint / cspell'],
36
+ ]
37
+
38
+ interface ImplementDetail {
39
+ // Longest first, the remainder among them.
40
+ kinds: ReadonlyArray<Stage>
41
+ // The calls backgrounded inside the implementation.
42
+ background: number
43
+ // Each subagent kind's backgrounded calls, counted at no time.
44
+ untimed: ReadonlyMap<string, number>
45
+ }
46
+
47
+ function command_kind(command: string): string {
48
+ return COMMAND_KINDS.find(([pattern]) => pattern.test(command))?.[1] ?? OTHER_BASH
49
+ }
50
+
51
+ function subagent_kind(subagent: Subagent): string {
52
+ return `subagent: ${subagent.type}`
53
+ }
54
+
55
+ // The kind a call counts under, `undefined` for one that falls in the remainder (an edit included).
56
+ function kind_of(call: ToolCall): string | undefined {
57
+ if (call.tool === BASH_TOOL) return command_kind(call.command ?? '')
58
+ if (call.subagent !== undefined) return subagent_kind(call.subagent)
59
+
60
+ return TOOL_KINDS.get(call.tool ?? '')
61
+ }
62
+
63
+ interface TimedPart extends Stage {
64
+ from_ms: number
65
+ }
66
+
67
+ function is_untimed_subagent(call: ToolCall): boolean {
68
+ return call.background && call.subagent !== undefined
69
+ }
70
+
71
+ // A call's own milliseconds, cut at the end of the span it started in; a backgrounded subagent call's none.
72
+ function timed_part(call: ToolCall, span: LaneSpan): ReadonlyArray<TimedPart> {
73
+ const name = kind_of(call)
74
+
75
+ if (name === undefined) return []
76
+
77
+ const ms = Math.min(call.duration_ms ?? 0, span.to_ms - call.started_ms)
78
+ const is_counted = call.duration_ms !== undefined || is_untimed_subagent(call)
79
+
80
+ return is_counted ? [{ name, ms, from_ms: call.started_ms }] : []
81
+ }
82
+
83
+ function untimed_of(placed: ReadonlyArray<readonly [ToolCall, LaneSpan]>): Map<string, number> {
84
+ const counts = new Map<string, number>()
85
+ const kinds = placed.filter(([call]) => is_untimed_subagent(call)).map(([call]) => kind_of(call))
86
+
87
+ for (const kind of kinds) if (kind !== undefined) counts.set(kind, (counts.get(kind) ?? 0) + 1)
88
+
89
+ return counts
90
+ }
91
+
92
+ // What neither a timed call nor a wait covers of the implementation's spans, each millisecond once.
93
+ function remainder_ms(parts: ReadonlyArray<TimedPart>, breakdown: Breakdown): number {
94
+ const busy = parts.map((part) => ({ from_ms: part.from_ms, to_ms: part.from_ms + part.ms }))
95
+ const covering = [...busy, ...breakdown.waits]
96
+ const idle = breakdown.implement.map(
97
+ (span) => span.to_ms - span.from_ms - lane_breakdown.covered_ms(span, covering),
98
+ )
99
+
100
+ return idle.reduce((sum, ms) => sum + ms, 0)
101
+ }
102
+
103
+ function span_of(call: ToolCall, spans: ReadonlyArray<LaneSpan>): LaneSpan | undefined {
104
+ return spans.find((span) => call.started_ms >= span.from_ms && call.started_ms < span.to_ms)
105
+ }
106
+
107
+ function placed_of(
108
+ calls: ReadonlyArray<ToolCall>,
109
+ spans: ReadonlyArray<LaneSpan>,
110
+ ): Array<readonly [ToolCall, LaneSpan]> {
111
+ return calls.flatMap((call) => {
112
+ const span = span_of(call, spans)
113
+
114
+ return span === undefined ? [] : [[call, span] as const]
115
+ })
116
+ }
117
+
118
+ // The implementation split by the calls made inside it — parallel calls each count their own time, so
119
+ // the kinds can add up to more — and the remainder, the time no call and no wait covered.
120
+ function of(calls: ReadonlyArray<ToolCall>, breakdown: Breakdown): ImplementDetail {
121
+ const placed = placed_of(calls, breakdown.implement)
122
+ const parts = placed.flatMap(([call, span]) => timed_part(call, span))
123
+ const remainder = { name: REMAINDER, ms: remainder_ms(parts, breakdown) }
124
+
125
+ return {
126
+ kinds: lane_breakdown.ranked([...parts, remainder]),
127
+ background: placed.filter(([call]) => call.background).length,
128
+ untimed: untimed_of(placed),
129
+ }
130
+ }
131
+
132
+ // The Bash calls started inside `spans`, by the implementation's kinds — the fixes, re-ships and checks
133
+ // a lane child ran between two ship stages (joshuafolkken/kit#5294).
134
+ function bash_kinds(calls: ReadonlyArray<ToolCall>, spans: ReadonlyArray<LaneSpan>): Array<Stage> {
135
+ const placed = placed_of(
136
+ calls.filter((call) => call.tool === BASH_TOOL),
137
+ spans,
138
+ )
139
+
140
+ return lane_breakdown.ranked(placed.flatMap(([call, span]) => timed_part(call, span)))
141
+ }
142
+
143
+ // The lane's own transcript directories — `<lane root slug>-<issue>` under `~/.claude/projects`.
144
+ function transcript_directories(issue: number): ReadonlyArray<string> {
145
+ const main_cwd = cost_transcript.session_cwd(process.cwd())
146
+ const home = cost_transcript.home_directory()
147
+ const suffix = `-${String(issue)}`
148
+
149
+ return cost_transcript
150
+ .lane_transcript_directories(main_cwd, home)
151
+ .filter((directory) => directory.endsWith(suffix))
152
+ }
153
+
154
+ // The tool calls of `issue`'s lane sessions still written to once its implementation began, up to the
155
+ // end of its last ship stage.
156
+ function read(issue: number, breakdown: Breakdown): Array<ToolCall> {
157
+ const [first] = breakdown.implement
158
+ const last = breakdown.ship.at(-1) ?? breakdown.implement.at(-1)
159
+
160
+ if (first === undefined || last === undefined) return []
161
+
162
+ const window = { since_ms: first.from_ms, until_ms: last.to_ms }
163
+
164
+ return lane_transcript_stats.read_calls(transcript_directories(issue), window)
165
+ }
166
+
167
+ const lane_breakdown_implement = { bash_kinds, of, read, transcript_directories }
168
+
169
+ export { lane_breakdown_implement }
170
+ export type { ImplementDetail }