@joshuafolkken/kit 1.1784.0 → 1.2116.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (690) hide show
  1. package/.claude/agents/reviewer-verification.md +19 -0
  2. package/.claude/agents/reviewer.md +19 -0
  3. package/.claude/settings.json +5 -6
  4. package/.claude/skills/dependency-update/SKILL.md +9 -10
  5. package/.claude/skills/workflow-commands/SKILL.md +6 -6
  6. package/.claude/skills/workflow-commands/background-commands.md +8 -5
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +3 -1
  8. package/.claude/skills/workflow-commands/backlogrun-lanes.md +1 -1
  9. package/.claude/skills/workflow-commands/backlogrun-park.md +5 -2
  10. package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -3
  11. package/.claude/skills/workflow-commands/backlogrun-recovery.md +1 -1
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +3 -2
  13. package/.claude/skills/workflow-commands/backlogrun.md +1 -1
  14. package/.claude/skills/workflow-commands/chain-rule.md +41 -32
  15. package/.claude/skills/workflow-commands/delegation.md +6 -6
  16. package/.claude/skills/workflow-commands/entry-sequence.md +2 -2
  17. package/.claude/skills/workflow-commands/followup.md +7 -5
  18. package/.claude/skills/workflow-commands/fullrun-steps.md +6 -6
  19. package/.claude/skills/workflow-commands/fullrun.md +1 -1
  20. package/.claude/skills/workflow-commands/issue-comments.md +9 -4
  21. package/.claude/skills/workflow-commands/issue-fold-existing.md +2 -1
  22. package/.claude/skills/workflow-commands/kickoff.md +2 -2
  23. package/.claude/skills/workflow-commands/observation-filing.md +1 -1
  24. package/.claude/skills/workflow-commands/observation-ledger.md +6 -4
  25. package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -7
  26. package/.claude/skills/workflow-commands/prerequisite.md +3 -2
  27. package/.claude/skills/workflow-commands/retrospective.md +2 -2
  28. package/.claude/skills/workflow-commands/split-assessment.md +7 -5
  29. package/.codex/hooks.json +5 -5
  30. package/.github/actions/setup-pnpm/action.yml +9 -16
  31. package/.github/dependabot.yml +16 -0
  32. package/.github/workflows/auto-tag.yml +45 -0
  33. package/.github/workflows/ci.yml +155 -15
  34. package/.github/workflows/dependabot-auto-merge.yml +63 -4
  35. package/.github/workflows/production.yml +8 -0
  36. package/.github/workflows/publish.yml +60 -45
  37. package/.vscode/settings.json +19 -0
  38. package/CLAUDE.md +5 -12
  39. package/SECURITY.md +2 -2
  40. package/dist/CLAUDE.md +5 -12
  41. package/dist/commands/document-read-cli.js +2 -1
  42. package/dist/commands/document-section-main.js +2 -1
  43. package/dist/commands/read-set-cli.js +194 -134
  44. package/dist/commands/run-prep-main.js +9694 -10173
  45. package/dist/commands/run-step-cli.js +22138 -18285
  46. package/dist/hooks/audit-provision.js +23 -5
  47. package/dist/hooks/chunk-3GKE653K.js +6204 -0
  48. package/dist/hooks/chunk-45CJJOO7.js +1243 -0
  49. package/dist/hooks/{chunk-CWMBGKYW.js → chunk-5PM2JRGV.js} +2153 -856
  50. package/dist/hooks/{chunk-WR2KQAYZ.js → chunk-7SIUNQXK.js} +1207 -1470
  51. package/dist/hooks/{chunk-O2YBIDSI.js → chunk-CQD4LJE6.js} +1682 -1130
  52. package/dist/hooks/{chunk-VWWCFGWK.js → chunk-OPSRGWFU.js} +1 -1
  53. package/dist/hooks/{chunk-XGBNSWEI.js → chunk-UJ3FPMMM.js} +132 -49
  54. package/dist/hooks/chunk-VVNYJWEI.js +30 -0
  55. package/dist/hooks/chunk-Z6DQJKH3.js +2806 -0
  56. package/dist/hooks/codex-hook-adapter.js +8 -8
  57. package/dist/hooks/format-edited.js +4 -5
  58. package/dist/hooks/inputs.json +386 -360
  59. package/dist/hooks/pretool-guard.js +7 -6
  60. package/dist/hooks/session-lang.js +101 -258
  61. package/dist/hooks/stop-guard.js +1744 -2576
  62. package/dist/josh.js +7133 -6368
  63. package/dist/version/index.js +161 -1
  64. package/eslint/rules/comment-why-only.js +108 -0
  65. package/package.json +16 -9
  66. package/prompts/coding-standards.md +1 -1
  67. package/prompts/collaboration-workflow/file-edits.md +14 -11
  68. package/prompts/collaboration-workflow/issue-citation.md +0 -4
  69. package/prompts/collaboration-workflow/issue-template.md +40 -21
  70. package/prompts/collaboration-workflow/lane-instructions.md +3 -1
  71. package/prompts/collaboration-workflow/measurement.md +8 -1
  72. package/prompts/collaboration-workflow/operating-rules.md +11 -2
  73. package/prompts/collaboration-workflow/output-bounds.md +6 -2
  74. package/prompts/collaboration-workflow/plan-comment.md +1 -1
  75. package/prompts/collaboration-workflow/principles.md +9 -0
  76. package/prompts/collaboration-workflow/residency.md +3 -2
  77. package/prompts/collaboration-workflow/rule-delivery.md +13 -1
  78. package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
  79. package/prompts/collaboration-workflow/wip-cap.md +3 -1
  80. package/prompts/review-rubric.md +8 -0
  81. package/prompts/review.md +31 -22
  82. package/prompts/testing-guide.md +1 -0
  83. package/scripts/agent/agent-argv.ts +14 -16
  84. package/scripts/agent/agent-provider.ts +138 -0
  85. package/scripts/agent/agent-role-profile.ts +108 -156
  86. package/scripts/agent/agent-safe-text.ts +20 -5
  87. package/scripts/agent/api-usage-limit.ts +65 -0
  88. package/scripts/agent/claude-agent-argv.ts +19 -9
  89. package/scripts/agent/codex-agent-argv.ts +118 -22
  90. package/scripts/agent/usage-limit-reset.ts +179 -0
  91. package/scripts/auth/claude-token-output.ts +2 -2
  92. package/scripts/auto-ok/auto-ok-author.ts +53 -0
  93. package/scripts/auto-ok/auto-ok-cli.ts +20 -9
  94. package/scripts/backlog/backlog-defect-priority.ts +1 -1
  95. package/scripts/backlog/backlog-drive-cli.ts +6 -1
  96. package/scripts/backlog/backlog-drive-hold.ts +3 -3
  97. package/scripts/backlog/backlog-drive-idle.ts +10 -0
  98. package/scripts/backlog/backlog-drive-launch-pass.ts +90 -0
  99. package/scripts/backlog/backlog-drive-launch.ts +8 -2
  100. package/scripts/backlog/backlog-drive-named-offer.ts +73 -30
  101. package/scripts/backlog/backlog-drive-named.ts +28 -7
  102. package/scripts/backlog/backlog-drive-paused.ts +5 -4
  103. package/scripts/backlog/backlog-drive-restore.ts +11 -3
  104. package/scripts/backlog/backlog-drive.ts +21 -60
  105. package/scripts/backlog/backlog-gate-scope.ts +61 -0
  106. package/scripts/backlog/backlog-measure-close.ts +112 -0
  107. package/scripts/backlog/backlog-next.ts +39 -49
  108. package/scripts/backlog/backlog-occupied.ts +2 -2
  109. package/scripts/backlog/backlog-overlap.ts +42 -8
  110. package/scripts/backlog/backlog-plan-cli.ts +4 -1
  111. package/scripts/backlog/backlog-plan-comment.ts +81 -0
  112. package/scripts/backlog/backlog-plan-read.ts +19 -6
  113. package/scripts/backlog/backlog-pool.ts +50 -12
  114. package/scripts/backlog/backlog-rank.ts +60 -13
  115. package/scripts/backlog/backlog-stalled-detect.ts +2 -1
  116. package/scripts/backlog/backlog-waves.ts +17 -2
  117. package/scripts/backlog/backlogrun-launch.ts +7 -4
  118. package/scripts/cost-runtime/context-cut-payback.ts +27 -25
  119. package/scripts/cost-runtime/cost-cli.ts +37 -16
  120. package/scripts/cost-runtime/cost-pricing.ts +9 -0
  121. package/scripts/cost-runtime/cost-verdict.ts +4 -1
  122. package/scripts/delegation/delegation-policy.ts +2 -2
  123. package/scripts/delegation/duplicate-read-guard.ts +1 -0
  124. package/scripts/delegation/investigation-guard.ts +14 -2
  125. package/scripts/delegation/investigation-reads.ts +45 -23
  126. package/scripts/dependabot/dependabot-cooldown.ts +3 -2
  127. package/scripts/discovery/repo-party.ts +80 -20
  128. package/scripts/discovery/session-owner-pin.ts +51 -0
  129. package/scripts/document/capped-print.ts +1 -1
  130. package/scripts/document/command-reference-line-budget.ts +42 -0
  131. package/scripts/document/document-byte-budget.ts +17 -7
  132. package/scripts/document/document-checks.ts +20 -0
  133. package/scripts/document/document-ratchet-check.ts +101 -0
  134. package/scripts/document/document-section.ts +1 -0
  135. package/scripts/document/entry-read-budget.ts +7 -3
  136. package/scripts/document/issue-citation-budget.ts +94 -0
  137. package/scripts/epic/epic-cli-argv.ts +2 -2
  138. package/scripts/epic/epic-fetch.ts +4 -2
  139. package/scripts/epic/epic-graph.ts +7 -2
  140. package/scripts/epic/epic-issue.ts +3 -1
  141. package/scripts/epic/epic-rank.ts +5 -0
  142. package/scripts/exports/unused-members-check.ts +62 -0
  143. package/scripts/exports/unused-members-cli.ts +6 -51
  144. package/scripts/followup/followup-ci-path.ts +67 -0
  145. package/scripts/followup/followup-coderabbit-retrigger.ts +261 -0
  146. package/scripts/followup/followup-coderabbit-wait.ts +13 -10
  147. package/scripts/followup/followup-failed-tests.ts +160 -0
  148. package/scripts/followup/followup-job-needs.ts +100 -0
  149. package/scripts/followup/followup-job-rerun.ts +303 -0
  150. package/scripts/followup/followup-main-move.ts +113 -0
  151. package/scripts/followup/git-followup-finish.ts +43 -11
  152. package/scripts/followup/git-followup-pending.ts +3 -3
  153. package/scripts/followup/git-followup-stages.ts +41 -11
  154. package/scripts/followup/git-pr-followup-checks.ts +55 -16
  155. package/scripts/followup/git-pr-followup-wrapup.ts +24 -5
  156. package/scripts/followup/git-pr-followup.ts +62 -27
  157. package/scripts/fresh-machine/fresh-machine-script.ts +5 -9
  158. package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +2 -2
  159. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +2 -2
  160. package/scripts/gate/busy-average.ts +34 -2
  161. package/scripts/gate/check-related-pinned.ts +43 -0
  162. package/scripts/gate/check-related-reuse.ts +64 -0
  163. package/scripts/gate/check-related-section.ts +57 -0
  164. package/scripts/gate/check-related-unplanned.ts +34 -0
  165. package/scripts/gate/check-related.ts +265 -0
  166. package/scripts/gate/command-memory.ts +1 -1
  167. package/scripts/gate/core-admission.ts +24 -6
  168. package/scripts/gate/core-budget-timing.ts +20 -6
  169. package/scripts/gate/core-budget.ts +40 -11
  170. package/scripts/gate/core-wait-record.ts +3 -2
  171. package/scripts/gate/core-wait.ts +25 -2
  172. package/scripts/gate/core-weights.ts +15 -7
  173. package/scripts/gate/gate-labels.ts +46 -0
  174. package/scripts/gate/gate-ledger.ts +14 -6
  175. package/scripts/gate/gate-plan.ts +103 -58
  176. package/scripts/gate/gate-report.ts +9 -7
  177. package/scripts/gate/gate-run-steps.ts +26 -3
  178. package/scripts/gate/gate-skip.ts +45 -6
  179. package/scripts/gate/gate-static-group.ts +60 -0
  180. package/scripts/gate/gate-steps.ts +2 -1
  181. package/scripts/gate/gate-tree.ts +4 -2
  182. package/scripts/gate/hook-gate-reuse.ts +19 -2
  183. package/scripts/gate/metrics-totals.ts +59 -0
  184. package/scripts/gate/scoped-green.ts +68 -15
  185. package/scripts/gate/since-green.ts +14 -6
  186. package/scripts/gate/structural-checks.ts +96 -0
  187. package/scripts/gate/verification-gate.ts +51 -16
  188. package/scripts/gate/verification-inputs.ts +21 -6
  189. package/scripts/gate/verification-tail.ts +52 -0
  190. package/scripts/gh/gh-author-association.ts +23 -2
  191. package/scripts/gh/git-ai-review-scan.ts +1 -1
  192. package/scripts/gh/git-gh-api-path.ts +12 -3
  193. package/scripts/gh/git-gh-comments-unreadable.ts +36 -0
  194. package/scripts/gh/git-gh-exec.ts +32 -2
  195. package/scripts/gh/git-gh-issue-read.ts +4 -2
  196. package/scripts/gh/git-gh-issue-rest.ts +1 -0
  197. package/scripts/gh/git-gh-issue-write.ts +8 -2
  198. package/scripts/gh/git-gh-issue.ts +12 -5
  199. package/scripts/gh/git-gh-pr-auto-merge.ts +13 -6
  200. package/scripts/gh/git-gh-pr-graphql-state.ts +56 -0
  201. package/scripts/gh/git-gh-pr-read.ts +74 -13
  202. package/scripts/gh/git-gh-pr-rest.ts +3 -1
  203. package/scripts/gh/git-gh-pr-snapshot.ts +22 -7
  204. package/scripts/gh/git-gh-pr-too-large.ts +20 -0
  205. package/scripts/gh/git-gh-pr.ts +21 -7
  206. package/scripts/gh/git-gh-retry.ts +141 -0
  207. package/scripts/gh/git-pr-ai-review.ts +15 -6
  208. package/scripts/gh/git-pr-checks-eval.ts +3 -0
  209. package/scripts/gh/git-pr-checks.ts +5 -5
  210. package/scripts/git/base-tree.ts +30 -0
  211. package/scripts/git/change-base.ts +4 -10
  212. package/scripts/git/changed-paths-sync.ts +63 -0
  213. package/scripts/git/changed-paths.ts +16 -1
  214. package/scripts/git/git-common-directory.ts +11 -1
  215. package/scripts/git/git-diff-reads.ts +66 -20
  216. package/scripts/git/git-error.ts +9 -2
  217. package/scripts/git/git-schemas.ts +13 -0
  218. package/scripts/git/git-worktree.ts +13 -0
  219. package/scripts/git/gone-branch.ts +4 -1
  220. package/scripts/git/main-merge-budget-conflict.ts +89 -0
  221. package/scripts/git/main-merge-guard.ts +55 -18
  222. package/scripts/git/main-merge-regenerate.ts +59 -25
  223. package/scripts/git/main-merge.ts +53 -5
  224. package/scripts/git/no-base-checkout.ts +127 -0
  225. package/scripts/git/stash/git-stash.ts +11 -2
  226. package/scripts/git/stash/stash-push-cli.ts +10 -0
  227. package/scripts/hooks/batch-guard.ts +40 -21
  228. package/scripts/hooks/edited-cspell.ts +37 -11
  229. package/scripts/hooks/format-edited-file.ts +22 -2
  230. package/scripts/hooks/lane-plan-guard.ts +50 -0
  231. package/scripts/hooks/pre-commit-lint-switch.ts +9 -0
  232. package/scripts/hooks/pre-commit-lint.ts +14 -1
  233. package/scripts/hooks/pre-push-related-switch.ts +10 -0
  234. package/scripts/hooks/pre-push-unit.ts +76 -10
  235. package/scripts/hooks/pretool-guard.ts +2 -0
  236. package/scripts/hooks/reserved-run.ts +14 -1
  237. package/scripts/hooks/run-hook.sh +23 -8
  238. package/scripts/hooks/step-zero-notice.ts +6 -1
  239. package/scripts/hooks/stop-actions.ts +3 -15
  240. package/scripts/hooks/stop-guard.ts +7 -6
  241. package/scripts/init/distributed-paths.ts +1 -0
  242. package/scripts/init/hook-command-rewrite.ts +5 -1
  243. package/scripts/init/hook-launch.ts +4 -2
  244. package/scripts/issue/aggregation-split.ts +52 -0
  245. package/scripts/issue/defect-origin-line.ts +19 -1
  246. package/scripts/issue/defect-rate-cli.ts +5 -102
  247. package/scripts/issue/defect-report.ts +4 -4
  248. package/scripts/issue/effect-audit-cli.ts +178 -0
  249. package/scripts/issue/effect-audit.ts +185 -0
  250. package/scripts/issue/expected-effect-lint.ts +64 -9
  251. package/scripts/issue/git-next-issues.ts +5 -0
  252. package/scripts/issue/issue-body-or-comment.ts +38 -4
  253. package/scripts/issue/issue-cite-cli.ts +1 -3
  254. package/scripts/issue/issue-classification.ts +1 -0
  255. package/scripts/issue/issue-closing-pr.ts +8 -1
  256. package/scripts/issue/issue-evidence-exit.ts +4 -2
  257. package/scripts/issue/issue-file-cap.ts +58 -0
  258. package/scripts/issue/issue-file-cli.ts +111 -38
  259. package/scripts/issue/issue-file-deferral.ts +52 -0
  260. package/scripts/issue/issue-file-fold.ts +29 -10
  261. package/scripts/issue/issue-file-interrupt.ts +85 -0
  262. package/scripts/issue/issue-file-lane-hint.ts +30 -0
  263. package/scripts/issue/issue-file.ts +43 -6
  264. package/scripts/issue/issue-labels.ts +19 -2
  265. package/scripts/issue/issue-lint-cli.ts +27 -2
  266. package/scripts/issue/issue-measured-cli.ts +13 -35
  267. package/scripts/issue/issue-measured-close.ts +58 -0
  268. package/scripts/issue/issue-not-before-label.ts +2 -2
  269. package/scripts/issue/issue-not-before.ts +4 -1
  270. package/scripts/issue/issue-priority-cli.ts +60 -0
  271. package/scripts/issue/issue-priority-raise.ts +55 -0
  272. package/scripts/issue/issue-priority.ts +174 -43
  273. package/scripts/issue/issue-rank.ts +21 -4
  274. package/scripts/issue/issue-read-cli.ts +32 -6
  275. package/scripts/issue/issue-read.ts +37 -12
  276. package/scripts/issue/issue-sample-gate.ts +95 -74
  277. package/scripts/issue/issue-sample-prime.ts +127 -0
  278. package/scripts/issue/issue-sample-required.ts +57 -0
  279. package/scripts/issue/issue-sample-source.ts +12 -11
  280. package/scripts/issue/issue-search.ts +124 -0
  281. package/scripts/issue/issue-state.ts +13 -1
  282. package/scripts/issue/issue-template-section.ts +43 -0
  283. package/scripts/issue/issue-watch-diff.ts +31 -1
  284. package/scripts/issue/issue-watch-hook.ts +11 -2
  285. package/scripts/issue/issue-watch.ts +55 -12
  286. package/scripts/issue/markdown-section.ts +1 -0
  287. package/scripts/issue/measure-declaration.ts +121 -0
  288. package/scripts/issue/measure-rerun-cli.ts +7 -70
  289. package/scripts/issue/plan-consumers-section.ts +22 -1
  290. package/scripts/issue/reproduction-measure.ts +3 -1
  291. package/scripts/issue/size-estimate.ts +90 -0
  292. package/scripts/issue/trusted-measure.ts +84 -0
  293. package/scripts/josh/command-usage.ts +3 -2
  294. package/scripts/josh/durable-state-migrate.ts +105 -0
  295. package/scripts/josh/durable-state.ts +112 -0
  296. package/scripts/josh/josh-aliases.ts +95 -0
  297. package/scripts/josh/josh-command-map.ts +1 -82
  298. package/scripts/josh/josh-commands-agent-hooks.ts +6 -6
  299. package/scripts/josh/josh-commands-ai.ts +5 -5
  300. package/scripts/josh/josh-commands-development.ts +59 -58
  301. package/scripts/josh/josh-commands-issue-write.ts +23 -4
  302. package/scripts/josh/josh-commands-issue.ts +32 -0
  303. package/scripts/josh/josh-commands-lane.ts +87 -4
  304. package/scripts/josh/josh-commands-lint.ts +16 -3
  305. package/scripts/josh/josh-commands-maintenance.ts +15 -0
  306. package/scripts/josh/josh-commands-review.ts +41 -6
  307. package/scripts/josh/josh-commands-ship.ts +56 -8
  308. package/scripts/josh/josh-commands-test-check.ts +80 -0
  309. package/scripts/josh/josh-commands-workflow.ts +1 -1
  310. package/scripts/josh/josh-environment-file.ts +43 -3
  311. package/scripts/josh/josh-in-process.ts +2 -2
  312. package/scripts/josh/josh-logic.ts +5 -3
  313. package/scripts/josh/josh-run.ts +19 -1
  314. package/scripts/josh/run-record-path.ts +15 -0
  315. package/scripts/josh/stamp-file.ts +11 -2
  316. package/scripts/lane/lane-adopt-cli.ts +98 -0
  317. package/scripts/lane/lane-adopt.ts +208 -0
  318. package/scripts/lane/lane-await.ts +5 -8
  319. package/scripts/lane/lane-baseline.ts +123 -0
  320. package/scripts/lane/lane-breakdown-cli.ts +64 -0
  321. package/scripts/lane/lane-breakdown-implement.ts +170 -0
  322. package/scripts/lane/lane-breakdown-laps.ts +107 -0
  323. package/scripts/lane/lane-breakdown-pinned.ts +76 -0
  324. package/scripts/lane/lane-breakdown-text.ts +145 -0
  325. package/scripts/lane/lane-breakdown.ts +239 -0
  326. package/scripts/lane/lane-check-stats.ts +29 -8
  327. package/scripts/lane/lane-child-invocation.ts +9 -2
  328. package/scripts/lane/lane-child-mark-keys.ts +12 -0
  329. package/scripts/lane/lane-child-marker.ts +20 -1
  330. package/scripts/lane/lane-ci-path-stats.ts +73 -0
  331. package/scripts/lane/lane-claim-stats.ts +84 -0
  332. package/scripts/lane/lane-close.ts +8 -3
  333. package/scripts/lane/lane-dispatch-log.ts +3 -3
  334. package/scripts/lane/lane-dispatch.ts +2 -2
  335. package/scripts/lane/lane-gap-stats.ts +7 -6
  336. package/scripts/lane/lane-guard-policy.ts +7 -1
  337. package/scripts/lane/lane-implement-stats.ts +207 -0
  338. package/scripts/lane/lane-implement-subagents.ts +90 -0
  339. package/scripts/lane/lane-investigation-switch.ts +16 -0
  340. package/scripts/lane/lane-ledger-kind.ts +31 -0
  341. package/scripts/lane/lane-ledger-schema-ship.ts +49 -0
  342. package/scripts/lane/lane-ledger-schema.ts +119 -36
  343. package/scripts/lane/lane-ledger-write.ts +257 -0
  344. package/scripts/lane/lane-ledger.ts +31 -177
  345. package/scripts/lane/lane-load.ts +1 -1
  346. package/scripts/lane/lane-measure-cli.ts +176 -59
  347. package/scripts/lane/lane-net-read.ts +44 -0
  348. package/scripts/lane/lane-net-time.ts +212 -0
  349. package/scripts/lane/lane-open.ts +16 -7
  350. package/scripts/lane/lane-output.ts +2 -4
  351. package/scripts/lane/lane-overrun-prompt.ts +147 -0
  352. package/scripts/lane/lane-overrun.ts +274 -0
  353. package/scripts/lane/lane-paths.ts +24 -1
  354. package/scripts/lane/lane-pause-cli.ts +4 -1
  355. package/scripts/lane/lane-paused-spans.ts +97 -0
  356. package/scripts/lane/lane-plan-check.ts +207 -0
  357. package/scripts/lane/lane-plan-cli.ts +41 -0
  358. package/scripts/lane/lane-plan.ts +144 -0
  359. package/scripts/lane/lane-registry.ts +14 -1
  360. package/scripts/lane/lane-relaunch.ts +1 -1
  361. package/scripts/lane/lane-round-one-stats.ts +51 -0
  362. package/scripts/lane/lane-sampler.ts +23 -4
  363. package/scripts/lane/lane-session-action.ts +93 -18
  364. package/scripts/lane/lane-session-broker.ts +49 -21
  365. package/scripts/lane/lane-session-reread-main.ts +14 -0
  366. package/scripts/lane/lane-session-reread.ts +51 -0
  367. package/scripts/lane/lane-ship-lap-stats.ts +74 -0
  368. package/scripts/lane/lane-sleep.ts +58 -0
  369. package/scripts/lane/lane-spent.ts +1 -1
  370. package/scripts/lane/lane-split-stats.ts +28 -0
  371. package/scripts/lane/lane-stage-stats.ts +13 -1
  372. package/scripts/lane/lane-state.ts +41 -9
  373. package/scripts/lane/lane-stats-tables.ts +58 -0
  374. package/scripts/lane/lane-stats.ts +21 -5
  375. package/scripts/lane/lane-stop-stats.ts +51 -19
  376. package/scripts/lane/lane-tail-stats.ts +32 -0
  377. package/scripts/lane/lane-transcript-calls.ts +67 -10
  378. package/scripts/lane/lane-transcript-stats.ts +44 -12
  379. package/scripts/lane/lane-value-cell.ts +72 -0
  380. package/scripts/lane/lane-value.ts +118 -0
  381. package/scripts/lane/lane-withdraw-closed.ts +124 -0
  382. package/scripts/lane/lane-withdraw.ts +108 -31
  383. package/scripts/lane/lane-yield.ts +85 -0
  384. package/scripts/lane/openai-lane-ship.ts +12 -11
  385. package/scripts/lane/openai-lane-supervisor-decision.ts +6 -8
  386. package/scripts/lane/openai-lane-supervisor-owner.ts +5 -8
  387. package/scripts/lane/openai-lane-supervisor.ts +5 -4
  388. package/scripts/lib/poll.ts +38 -9
  389. package/scripts/lib/settled-together.ts +10 -0
  390. package/scripts/lib/shell-quote.ts +21 -0
  391. package/scripts/lib/token-shape.ts +111 -0
  392. package/scripts/lint/eslint-daemon-sources.ts +79 -0
  393. package/scripts/lint/eslint-daemon.ts +45 -6
  394. package/scripts/lint/eslint-warm-cli.ts +7 -0
  395. package/scripts/lint/eslint-warm.ts +66 -0
  396. package/scripts/lint/import-graph.ts +141 -11
  397. package/scripts/lint/lint-gate-scope.ts +2 -2
  398. package/scripts/lint/lint-parallel.ts +54 -6
  399. package/scripts/lint/lint-related.ts +154 -33
  400. package/scripts/lint/rename-cli.ts +179 -0
  401. package/scripts/lint/rename-identifier.ts +192 -0
  402. package/scripts/lint/type-only-imports.ts +58 -0
  403. package/scripts/notify/telegram-notify.ts +12 -3
  404. package/scripts/observations/observation-record.ts +42 -16
  405. package/scripts/observations/observations-flush.ts +32 -9
  406. package/scripts/overrides/overrides-check.ts +9 -1
  407. package/scripts/release/release-approval-prune.ts +7 -1
  408. package/scripts/repo/required-checks-logic.ts +4 -1
  409. package/scripts/repo/ruleset-check.ts +4 -3
  410. package/scripts/report/markdown-shape.ts +28 -0
  411. package/scripts/report/report-format-reference.ts +15 -1
  412. package/scripts/report/report-labels.ts +12 -1
  413. package/scripts/report/report-lint-child-summary.ts +94 -0
  414. package/scripts/report/report-lint-cli.ts +26 -7
  415. package/scripts/report/report-lint.ts +2 -20
  416. package/scripts/review/prose-stale-cli.ts +88 -0
  417. package/scripts/review/prose-stale-scan.ts +152 -0
  418. package/scripts/review/review-attest.ts +73 -23
  419. package/scripts/review/review-brief-cli.ts +68 -19
  420. package/scripts/review/review-brief-paths.ts +22 -0
  421. package/scripts/review/review-brief.ts +14 -7
  422. package/scripts/review/review-comment-carry.ts +47 -0
  423. package/scripts/review/review-comment-round.ts +85 -22
  424. package/scripts/review/review-finding-ledger.ts +109 -7
  425. package/scripts/review/review-finding-text.ts +43 -0
  426. package/scripts/review/review-interaction.ts +11 -0
  427. package/scripts/review/review-lane-handover.ts +68 -0
  428. package/scripts/review/review-lint-cli.ts +57 -0
  429. package/scripts/review/review-lint-findings.ts +92 -0
  430. package/scripts/review/review-lint-sections.ts +80 -0
  431. package/scripts/review/review-lint.ts +221 -0
  432. package/scripts/review/review-prior-findings.ts +102 -0
  433. package/scripts/review/review-readers-scan.ts +4 -2
  434. package/scripts/review/review-record-cli.ts +177 -54
  435. package/scripts/review/review-record-code-round.ts +55 -0
  436. package/scripts/review/review-record-comment.ts +60 -0
  437. package/scripts/review/review-record-interaction.ts +35 -0
  438. package/scripts/review/review-record-pinned.ts +108 -0
  439. package/scripts/review/review-record.ts +25 -1
  440. package/scripts/review/review-reviewed-tree.ts +307 -0
  441. package/scripts/review/review-round-one-closure.ts +62 -0
  442. package/scripts/review/review-round-reuse.ts +106 -0
  443. package/scripts/review/review-round2-cli.ts +91 -29
  444. package/scripts/review/review-round2-skip-comment.ts +55 -0
  445. package/scripts/review/review-round2.ts +24 -8
  446. package/scripts/review/review-stamps.ts +7 -3
  447. package/scripts/review/review-stop-log.ts +20 -6
  448. package/scripts/review/review-stops-cli.ts +2 -1
  449. package/scripts/review/review-submit-cli.ts +101 -0
  450. package/scripts/rules/agent-model.ts +1 -1
  451. package/scripts/rules/bash-triggers.ts +3 -3
  452. package/scripts/rules/concise-reply.ts +88 -0
  453. package/scripts/rules/credential-body.ts +77 -0
  454. package/scripts/rules/decision-oracle.ts +1 -1
  455. package/scripts/rules/delivered-rules.ts +36 -17
  456. package/scripts/rules/destructive-command.ts +3 -11
  457. package/scripts/rules/direct-issue-comment.ts +34 -12
  458. package/scripts/rules/direct-issue-read.ts +191 -0
  459. package/scripts/rules/direct-pr-create.ts +4 -24
  460. package/scripts/rules/early-heartbeat.ts +2 -0
  461. package/scripts/rules/edit-tool.ts +27 -0
  462. package/scripts/rules/file-edit-rows.ts +17 -0
  463. package/scripts/rules/file-rewrite.ts +146 -0
  464. package/scripts/rules/firing-point.ts +3 -2
  465. package/scripts/rules/gh-api.ts +128 -7
  466. package/scripts/rules/gh-repo-selector.ts +84 -0
  467. package/scripts/rules/git-force.ts +2 -2
  468. package/scripts/rules/guard-remedy.ts +14 -5
  469. package/scripts/rules/implementation-cut.ts +61 -28
  470. package/scripts/rules/investigator-foreground.ts +231 -0
  471. package/scripts/rules/issue-citation.ts +15 -60
  472. package/scripts/rules/issue-comments.ts +9 -4
  473. package/scripts/rules/josh-git-bare.ts +1 -1
  474. package/scripts/rules/lane-background.ts +41 -13
  475. package/scripts/rules/lane-direct-tool.ts +107 -9
  476. package/scripts/rules/lane-interactive-ask.ts +4 -1
  477. package/scripts/rules/lane-park.ts +4 -2
  478. package/scripts/rules/lane-spilled-read.ts +90 -0
  479. package/scripts/rules/lane-split-park.ts +1 -1
  480. package/scripts/rules/lane-switch-main.ts +4 -4
  481. package/scripts/rules/last-prompt.ts +20 -47
  482. package/scripts/rules/oracle-consulted.ts +1 -1
  483. package/scripts/rules/permission-guards.ts +5 -1
  484. package/scripts/rules/piped-verification-shapes.ts +110 -0
  485. package/scripts/rules/piped-verification.ts +67 -17
  486. package/scripts/rules/poll-loop.ts +72 -9
  487. package/scripts/rules/pr-merge.ts +5 -5
  488. package/scripts/rules/pre-gate-cut.ts +3 -3
  489. package/scripts/rules/protected-files.ts +88 -24
  490. package/scripts/rules/reply-language.ts +3 -17
  491. package/scripts/rules/reply-prose.ts +34 -0
  492. package/scripts/rules/repo-admin.ts +132 -0
  493. package/scripts/rules/reviewer-foreground.ts +88 -0
  494. package/scripts/rules/round-one-check-related.ts +120 -0
  495. package/scripts/rules/rule-body-guard.ts +5 -15
  496. package/scripts/rules/rule-value-cache.ts +53 -5
  497. package/scripts/rules/rule-value-candidates.ts +84 -0
  498. package/scripts/rules/rule-value-cli.ts +59 -11
  499. package/scripts/rules/rule-value.ts +17 -4
  500. package/scripts/rules/run-tail-rule.ts +1 -1
  501. package/scripts/rules/sed-in-place.ts +196 -0
  502. package/scripts/rules/shell-segments.ts +10 -2
  503. package/scripts/rules/stop-rule-rows.ts +1 -13
  504. package/scripts/rules/stop-rules.ts +33 -58
  505. package/scripts/rules/test-declared-commit.ts +1 -1
  506. package/scripts/rules/third-party-write.ts +110 -23
  507. package/scripts/rules/timed-rerun.ts +1 -1
  508. package/scripts/rules/turn-filings.ts +90 -0
  509. package/scripts/rules/worktree-guard.ts +22 -7
  510. package/scripts/run/board/run-board-ending-reason.ts +6 -2
  511. package/scripts/run/board/run-board-fit.ts +24 -1
  512. package/scripts/run/board/run-board-found.ts +134 -0
  513. package/scripts/run/board/run-board-header.ts +8 -0
  514. package/scripts/run/board/run-board-labels.ts +11 -1
  515. package/scripts/run/board/run-board-lane-time.ts +1 -0
  516. package/scripts/run/board/run-board-link.ts +15 -2
  517. package/scripts/run/board/run-board-notes.ts +7 -1
  518. package/scripts/run/board/run-board-operation.ts +4 -2
  519. package/scripts/run/board/run-board-phase.ts +2 -5
  520. package/scripts/run/board/run-board-plan.ts +1 -1
  521. package/scripts/run/board/run-board-read.ts +46 -1
  522. package/scripts/run/board/run-board-reason.ts +20 -8
  523. package/scripts/run/board/run-board-render-checks.ts +3 -2
  524. package/scripts/run/board/run-board-render-drawn.ts +11 -0
  525. package/scripts/run/board/run-board-render-found.ts +157 -0
  526. package/scripts/run/board/run-board-render-lead.ts +9 -0
  527. package/scripts/run/board/run-board-render-legend.ts +19 -0
  528. package/scripts/run/board/run-board-render-tail.ts +1 -1
  529. package/scripts/run/board/run-board-render.ts +82 -18
  530. package/scripts/run/board/run-board-spin.ts +1 -3
  531. package/scripts/run/board/run-board-status.ts +2 -0
  532. package/scripts/run/board/run-board-tick.ts +39 -10
  533. package/scripts/run/carry/run-carry-ended.ts +3 -2
  534. package/scripts/run/carry/run-carry.ts +3 -2
  535. package/scripts/run/cut/run-cut-cli.ts +33 -133
  536. package/scripts/run/cut/run-cut-digest.ts +152 -0
  537. package/scripts/run/cut/run-cut-handoff.ts +52 -8
  538. package/scripts/run/cut/run-cut-report.ts +24 -3
  539. package/scripts/run/cut/run-cut-resume.ts +129 -0
  540. package/scripts/run/cut/run-cut-review.ts +105 -0
  541. package/scripts/run/cut/run-cut.ts +18 -7
  542. package/scripts/run/detached-launch.ts +1 -1
  543. package/scripts/run/entry/run-entry-cli.ts +88 -19
  544. package/scripts/run/entry/run-entry-spill.ts +83 -0
  545. package/scripts/run/entry/run-entry-stop.ts +5 -1
  546. package/scripts/run/entry/run-entry-trust.ts +91 -0
  547. package/scripts/run/event/run-event-baseline.ts +56 -0
  548. package/scripts/run/event/run-event-filed.ts +9 -3
  549. package/scripts/run/event/run-event-overrun.ts +197 -0
  550. package/scripts/run/event/run-event-render.ts +4 -0
  551. package/scripts/run/event/run-event-stream.ts +25 -3
  552. package/scripts/run/hold/run-stop-notify.ts +3 -8
  553. package/scripts/run/merge/run-merge-cap.ts +57 -0
  554. package/scripts/run/merge/run-merge-cli.ts +66 -23
  555. package/scripts/run/merge/run-merge-outcome.ts +2 -0
  556. package/scripts/run/merge/run-merge-ship.ts +13 -3
  557. package/scripts/run/merge/run-merge-signals.ts +40 -23
  558. package/scripts/run/merge/run-merge-steps.ts +56 -36
  559. package/scripts/run/merge/run-merge-usage-limit.ts +53 -0
  560. package/scripts/run/merge/run-merge-withdrawn.ts +53 -0
  561. package/scripts/run/merge/run-merge.ts +41 -14
  562. package/scripts/run/review/run-review-cli.ts +306 -20
  563. package/scripts/run/review/run-review-early-push.ts +121 -0
  564. package/scripts/run/review/run-review-join-read.ts +94 -0
  565. package/scripts/run/review/run-review-pinned-accepted.ts +126 -0
  566. package/scripts/run/review/run-review-pinned-join.ts +216 -0
  567. package/scripts/run/review/run-review-pinned-steps.ts +383 -0
  568. package/scripts/run/review/run-review-pinned-tree.ts +37 -0
  569. package/scripts/run/review/run-review-pinned.ts +53 -0
  570. package/scripts/run/review/run-review-steps.ts +70 -34
  571. package/scripts/run/review/run-review.ts +26 -6
  572. package/scripts/run/run-parent-cut-hook.ts +3 -4
  573. package/scripts/run/run-prep.ts +1 -0
  574. package/scripts/run/run-stage-read.ts +2 -6
  575. package/scripts/run/run-step-cli.ts +17 -5
  576. package/scripts/run/run-step-lane-plan.ts +27 -0
  577. package/scripts/run/run-step-section.ts +26 -7
  578. package/scripts/run/run-step.ts +5 -2
  579. package/scripts/run/ship/run-ship-args.ts +19 -0
  580. package/scripts/run/ship/run-ship-brokered-review.ts +106 -0
  581. package/scripts/run/ship/run-ship-cli.ts +131 -39
  582. package/scripts/run/ship/run-ship-conflict-probe.ts +59 -0
  583. package/scripts/run/ship/run-ship-detach.ts +10 -4
  584. package/scripts/run/ship/run-ship-handover.ts +106 -0
  585. package/scripts/run/ship/run-ship-infra-retry.ts +16 -1
  586. package/scripts/run/ship/run-ship-lap.ts +63 -0
  587. package/scripts/run/ship/run-ship-next.ts +27 -26
  588. package/scripts/run/ship/run-ship-overlap.ts +8 -3
  589. package/scripts/run/ship/run-ship-place.ts +9 -2
  590. package/scripts/run/ship/run-ship-planned.ts +92 -0
  591. package/scripts/run/ship/run-ship-pre-detach-pinned.ts +197 -0
  592. package/scripts/run/ship/run-ship-pre-detach-timed.ts +7 -8
  593. package/scripts/run/ship/run-ship-pre-detach.ts +77 -23
  594. package/scripts/run/ship/run-ship-preflight.ts +16 -4
  595. package/scripts/run/ship/run-ship-probe.ts +23 -9
  596. package/scripts/run/ship/run-ship-relaunch-cap.ts +43 -7
  597. package/scripts/run/ship/run-ship-relaunch.ts +51 -0
  598. package/scripts/run/ship/run-ship-return.ts +103 -29
  599. package/scripts/run/ship/run-ship-review-reason.ts +24 -0
  600. package/scripts/run/ship/run-ship-review-steps.ts +230 -59
  601. package/scripts/run/ship/run-ship-review.ts +171 -51
  602. package/scripts/run/ship/run-ship-reviewer.ts +138 -42
  603. package/scripts/run/ship/run-ship-scoped.ts +39 -10
  604. package/scripts/run/ship/run-ship-stage.ts +49 -13
  605. package/scripts/run/ship/run-ship-steps.ts +24 -4
  606. package/scripts/run/ship/run-ship-stop-cause.ts +43 -2
  607. package/scripts/run/ship/run-ship-stop-context.ts +50 -13
  608. package/scripts/run/ship/run-ship-sync.ts +171 -30
  609. package/scripts/run/ship/run-ship-synced-scope.ts +178 -0
  610. package/scripts/run/ship/run-ship-wait-cli.ts +145 -0
  611. package/scripts/run/ship/run-ship-waiter.ts +114 -0
  612. package/scripts/run/ship/run-ship.ts +16 -2
  613. package/scripts/run/wake/run-wake-caffeinate.ts +48 -0
  614. package/scripts/run/wake/run-wake-cli.ts +6 -113
  615. package/scripts/run/wake/run-wake-code.ts +53 -11
  616. package/scripts/run/wake/run-wake-driver.ts +5 -3
  617. package/scripts/run/wake/run-wake-finish.ts +137 -0
  618. package/scripts/run/wake/run-wake-loop.ts +5 -3
  619. package/scripts/run/wake/run-wake-ports.ts +11 -3
  620. package/scripts/run/wake/run-wake-session.ts +2 -0
  621. package/scripts/run/wake/run-wake.ts +3 -2
  622. package/scripts/safe-chain/ci-installer-pin.ts +49 -8
  623. package/scripts/safe-chain/project-config.ts +3 -2
  624. package/scripts/security/secretlint-scan.ts +42 -9
  625. package/scripts/security/security-audit-provision-main.ts +9 -1
  626. package/scripts/security/security-audit-provision.ts +1 -1
  627. package/scripts/security/security-audit.ts +21 -1
  628. package/scripts/security/sonar-file.ts +10 -5
  629. package/scripts/split/split-assess.ts +12 -3
  630. package/scripts/split/split-early-notice.ts +116 -0
  631. package/scripts/split/split-measure.ts +20 -2
  632. package/scripts/split/split-resolution.ts +107 -0
  633. package/scripts/test/direct-importers.ts +185 -0
  634. package/scripts/test/pure-files-entries.ts +83 -0
  635. package/scripts/test/related-heavy-tests.ts +81 -0
  636. package/scripts/test/test-no-base.ts +88 -0
  637. package/scripts/test/test-pinned-cache-logic.ts +363 -0
  638. package/scripts/test/test-pinned-cache.ts +337 -0
  639. package/scripts/test/test-pinned-emit.ts +49 -0
  640. package/scripts/test/test-pinned-functions.ts +116 -0
  641. package/scripts/test/test-pinned-ledger.ts +80 -0
  642. package/scripts/test/test-pinned-logic.ts +208 -20
  643. package/scripts/test/test-pinned-main.ts +84 -18
  644. package/scripts/test/test-pinned-pool.ts +73 -0
  645. package/scripts/test/test-pinned-probe.ts +254 -0
  646. package/scripts/test/test-pinned-prune-logic.ts +118 -0
  647. package/scripts/test/test-pinned-reach.ts +194 -0
  648. package/scripts/test/test-pinned-record.ts +196 -0
  649. package/scripts/test/test-pinned-rewire.ts +148 -0
  650. package/scripts/test/test-pinned-spawn.ts +81 -0
  651. package/scripts/test/test-pinned-stage.ts +70 -0
  652. package/scripts/test/test-pinned.ts +258 -47
  653. package/scripts/test/test-reach-cli.ts +61 -0
  654. package/scripts/test/test-read-map.ts +35 -11
  655. package/scripts/test/test-read-recording.ts +17 -5
  656. package/scripts/test/test-read-trace.ts +26 -8
  657. package/scripts/test/test-red-logic.ts +46 -7
  658. package/scripts/test/test-red.ts +34 -14
  659. package/scripts/test/test-related-claim.ts +37 -0
  660. package/scripts/test/test-related-main.ts +4 -1
  661. package/scripts/test/test-related-moved.ts +91 -0
  662. package/scripts/test/test-related-record.ts +43 -23
  663. package/scripts/test/test-related-scope.ts +99 -34
  664. package/scripts/test/test-related-synced.ts +135 -0
  665. package/scripts/test/test-related-touched.ts +84 -0
  666. package/scripts/test/test-related.ts +167 -83
  667. package/scripts/test/test-unit-guard.ts +28 -5
  668. package/scripts/test/unit-durations.ts +41 -0
  669. package/scripts/test/unit-worker-share.ts +5 -4
  670. package/scripts/test/vitest-cache-directory.ts +19 -0
  671. package/scripts/test/vitest-cli-excludes.ts +14 -0
  672. package/scripts/test/vitest-failure-summary.ts +111 -0
  673. package/scripts/test/whole-suite-files.ts +12 -1
  674. package/scripts/time-runtime/time-batch-guard.ts +42 -4
  675. package/scripts/time-runtime/time-bundle-call.ts +1 -1
  676. package/scripts/time-runtime/time-bundles.ts +36 -5
  677. package/scripts/time-runtime/time-markers.ts +2 -2
  678. package/scripts/time-runtime/time-search-call.ts +38 -0
  679. package/scripts/time-runtime/time-shell.ts +1 -1
  680. package/scripts/time-runtime/time-transcript-line.ts +17 -5
  681. package/scripts/version/development-engines-verdict.ts +124 -0
  682. package/scripts/version/latest-corepack.ts +2 -0
  683. package/templates/gitignore +2 -0
  684. package/templates/workflows/ci.yml +41 -0
  685. package/dist/hooks/chunk-AZX4FGQ3.js +0 -207
  686. package/dist/hooks/chunk-PT5R6UJD.js +0 -7131
  687. package/dist/hooks/chunk-TUIFS5E7.js +0 -72
  688. package/dist/hooks/chunk-YCDOIR3I.js +0 -3456
  689. package/scripts/cost-runtime/context-cut-threshold.ts +0 -11
  690. package/scripts/rules/filing-cap.ts +0 -139
@@ -1,13 +1,15 @@
1
1
  import { api_auth } from '#scripts/agent/api-auth'
2
2
  import { api_outage } from '#scripts/agent/api-outage'
3
+ import { api_usage_limit } from '#scripts/agent/api-usage-limit'
3
4
  import { issue_closing_pr } from '#scripts/issue/issue-closing-pr'
4
5
  import { issue_merged } from '#scripts/issue/issue-merged'
5
6
  import type { issue_state_cli } from '#scripts/issue/issue-state-cli'
7
+ import { lane_yield } from '#scripts/lane/lane-yield'
6
8
  import { run_event_scope } from '#scripts/run/event/run-event-scope'
7
- import { run_event_stream } from '#scripts/run/event/run-event-stream'
8
9
  import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
9
10
  import { run_ending } from '#scripts/run/run-ending'
10
11
  import { run_merge, type ChildOutcome, type EndingSignals } from './run-merge'
12
+ import { run_merge_cap } from './run-merge-cap'
11
13
  import { run_merge_restart } from './run-merge-restart'
12
14
  import { run_merge_ship } from './run-merge-ship'
13
15
  import { run_merge_steps, type MergeContext } from './run-merge-steps'
@@ -36,16 +38,6 @@ function read_is_auth_failure(output: string | undefined): boolean {
36
38
  return api_auth.is_auth_failed_transcript(run_ending.read_transcript(output))
37
39
  }
38
40
 
39
- async function child_outages(child: string): Promise<number> {
40
- const events = await run_event_stream_emit.current_events()
41
-
42
- return events.filter(
43
- (event) =>
44
- event.kind === run_event_stream.EVENT_KIND.OUTAGE &&
45
- run_event_scope.issue_named(event) === child,
46
- ).length
47
- }
48
-
49
41
  // Why an unfinished child is re-dispatchable, or `undefined` when it is not. **Only an API outage adds
50
42
  // to the run-wide streak**: a host restart is over by the time the child is read (joshuafolkken/kit#4540),
51
43
  // and an unanswered ship stop reached the API (joshuafolkken/kit#3974).
@@ -61,18 +53,24 @@ async function retry_cause(
61
53
  }
62
54
 
63
55
  // An outage child is re-dispatched only so many times: one that ends the same way on every dispatch is
64
- // parked, since merges in other lanes reset the run-wide outage streak and would never stop it.
56
+ // parked, since merges in other lanes reset the run-wide outage streak and would never stop it. Its park
57
+ // says so (`run-merge-cap.ts`).
65
58
  async function read_retryable(
66
59
  child: string,
67
60
  output: string | undefined,
68
- ): Promise<{ is_outage: boolean; is_streak_exempt: boolean }> {
61
+ ): Promise<Pick<EndingSignals, 'is_outage' | 'is_streak_exempt' | 'capped_note'>> {
69
62
  const cause = await retry_cause(child, output)
70
63
 
71
64
  if (cause === undefined) return { is_outage: false, is_streak_exempt: false }
72
65
 
73
- const is_outage = (await child_outages(child)) < run_merge.CONSECUTIVE_OUTAGE_LIMIT
66
+ const events = await run_event_stream_emit.current_events()
67
+ const limit = run_merge.CONSECUTIVE_OUTAGE_LIMIT
68
+
69
+ if (run_merge_cap.outages(events, child) >= limit) {
70
+ return { is_outage: false, capped_note: run_merge_cap.note_of(events, child, limit) }
71
+ }
74
72
 
75
- return { is_outage, is_streak_exempt: is_outage && cause === 'exempt' }
73
+ return { is_outage: true, is_streak_exempt: cause === 'exempt' }
76
74
  }
77
75
 
78
76
  // The timeline is read only for an OPEN, unparked child — the one classification a merged closing pull
@@ -84,30 +82,49 @@ async function read_merged_pr(child: string, read: IssueRead): Promise<string |
84
82
  return await issue_closing_pr.read_closing_pr(child)
85
83
  }
86
84
 
87
- // A child that merged before `lane:withdraw` stopped it is merged, not withdrawn: the withdrawal's
88
- // event is already written, so only the timeline tells its merged close from the not-planned one. An
89
- // unread timeline answers `undefined`, and `outcome_of` asks again rather than guessing.
85
+ // **A CLOSED child is withdrawn unless a merge closed it**, whether or not `lane:withdraw` ran: an issue
86
+ // closed as not planned, or closed with no merged pull request, never merged, so it must not be booked
87
+ // as a merge (joshuafolkken/kit#4916). Only the timeline tells a merged close from the rest, so it
88
+ // decides — and a child that merged before `lane:withdraw` stopped it is merged. Any other child is
89
+ // withdrawn only by its event. An unread timeline answers `undefined`, and `outcome_of` asks again
90
+ // rather than guessing.
90
91
  async function read_is_withdrawn(child: string, read: IssueRead): Promise<boolean | undefined> {
91
- const events = await run_event_stream_emit.current_events()
92
+ if (read.kind !== 'state' || run_merge.classify_child(read.state) !== 'merged') {
93
+ return run_event_scope.is_withdrawn(await run_event_stream_emit.current_events(), child)
94
+ }
92
95
 
93
- if (!run_event_scope.is_withdrawn(events, child)) return false
94
- if (read.kind !== 'state' || run_merge.classify_child(read.state) !== 'merged') return true
95
96
  const is_merged = await issue_merged.read_merge_state(child)
96
97
 
97
98
  return is_merged === undefined ? undefined : !is_merged
98
99
  }
99
100
 
101
+ // The child's own yield is on the stream, read locally, as a person's withdrawal is.
102
+ async function read_is_yielded(child: string): Promise<boolean> {
103
+ return lane_yield.is_yielded(await run_event_stream_emit.current_events(), child)
104
+ }
105
+
106
+ // When a usage limit that stopped the child resets — off without `--output`, as the outage read is. The
107
+ // reset is read from the transcript's last write, not from this late collection of it.
108
+ function read_resume_ms(output: string | undefined): number | undefined {
109
+ if (output === undefined) return undefined
110
+ const transcript = run_ending.read_transcript(output)
111
+
112
+ return api_usage_limit.transcript_resume_ms(transcript, Date.now(), run_ending.written_at(output))
113
+ }
114
+
100
115
  async function read_signals(ctx: MergeContext, read: IssueRead): Promise<EndingSignals> {
101
- const [is_cut, merged_pr, retryable, is_withdrawn] = await Promise.all([
116
+ const [is_cut, merged_pr, retryable, is_withdrawn, is_yielded] = await Promise.all([
102
117
  run_merge_steps.has_resumable_cut(ctx.child),
103
118
  read_merged_pr(ctx.child, read),
104
119
  read_retryable(ctx.child, ctx.output),
105
120
  read_is_withdrawn(ctx.child, read),
121
+ read_is_yielded(ctx.child),
106
122
  ])
107
123
 
108
124
  const is_auth_failure = read_is_auth_failure(ctx.output)
125
+ const resume_ms = read_resume_ms(ctx.output)
109
126
 
110
- return { ...retryable, is_cut, merged_pr, is_withdrawn, is_auth_failure }
127
+ return { ...retryable, is_cut, merged_pr, is_withdrawn, is_yielded, is_auth_failure, resume_ms }
111
128
  }
112
129
 
113
130
  // An unread state is `unresolved` unless a withdrawal already settled the child, which is read locally;
@@ -7,7 +7,7 @@ import { issue_cite } from '#scripts/issue/issue-cite'
7
7
  import { has_label_name, NOT_BEFORE_LABEL, RUN_STALLED_LABEL } from '#scripts/issue/issue-labels'
8
8
  import { issue_not_before } from '#scripts/issue/issue-not-before'
9
9
  import { issue_park } from '#scripts/issue/issue-park'
10
- import { issue_sample_gate } from '#scripts/issue/issue-sample-gate'
10
+ import { issue_sample_prime } from '#scripts/issue/issue-sample-prime'
11
11
  import { issue_state_cli } from '#scripts/issue/issue-state-cli'
12
12
  import { session_cite } from '#scripts/issue/session-cite'
13
13
  import { josh_command, type JoshResult } from '#scripts/josh/josh-run'
@@ -18,6 +18,7 @@ import { lane_registry, type LaneInfo } from '#scripts/lane/lane-registry'
18
18
  import { lane_relaunch } from '#scripts/lane/lane-relaunch'
19
19
  import { lane_vacant } from '#scripts/lane/lane-vacant'
20
20
  import { poll } from '#scripts/lib/poll'
21
+ import { settled_together } from '#scripts/lib/settled-together'
21
22
  import {
22
23
  run_carry,
23
24
  type CarryChange,
@@ -26,11 +27,11 @@ import {
26
27
  } from '#scripts/run/carry/run-carry'
27
28
  import { run_carry_conversation } from '#scripts/run/carry/run-carry-conversation'
28
29
  import { run_cut, type RunCut } from '#scripts/run/cut/run-cut'
29
- import { run_stalled, type StallCause } from '#scripts/run/park/run-stalled'
30
+ import type { StallCause } from '#scripts/run/park/run-stalled'
30
31
  import { run_label } from '#scripts/run/run-label'
31
- import { run_merge } from './run-merge'
32
+ import { run_merge, type EndingSignals } from './run-merge'
33
+ import { run_merge_cap } from './run-merge-cap'
32
34
  import { run_merge_close } from './run-merge-close'
33
- import { run_merge_ship } from './run-merge-ship'
34
35
 
35
36
  // The result of attempting to apply a carry change. Distinguishing `refused` from `applied` lets
36
37
  // callers surface the refusal as a hard failure rather than silently continuing on a carry that was
@@ -56,25 +57,24 @@ const GIT_ENTRY = '.git'
56
57
  const OPEN_STATE = 'OPEN'
57
58
  const SYNC_RETRY = { attempts: 3, interval_ms: 5000 }
58
59
 
59
- // One returned child's context, gathered from the command line by the CLI.
60
- interface MergeContext {
60
+ // One returned child's context, gathered from the command line by the CLI, and the ending signals its
61
+ // handlers act on — each one's meaning is `EndingSignals`'s.
62
+ interface MergeContext extends Pick<
63
+ EndingSignals,
64
+ 'merged_pr' | 'is_streak_exempt' | 'capped_note' | 'resume_ms'
65
+ > {
61
66
  child: string
62
67
  epic: string | undefined
63
68
  repo: string | undefined
64
- // The hand-off threshold, or `undefined` where no AI session owns the loop — the supervisor's
65
- // `backlog:drive` has no context to cut, so a merge there is never handed back as `over`.
66
- over: number | undefined
69
+ // `true` where the merge asks the session's `pnpm josh cost --cut` verdict, or `undefined` where no
70
+ // AI session owns the loop — the supervisor's `backlog:drive` has no context to cut, so a merge
71
+ // there is never handed back as `over`.
72
+ over: true | undefined
67
73
  owner: CarryOwner
68
74
  // The child's transcript output path, when the caller passed `--output`. Read to tell an API-outage
69
75
  // ending apart from a genuine child failure; absent leaves outage detection off, so the child is
70
76
  // classified from its GitHub state alone.
71
77
  output?: string | undefined
72
- // The merged pull request that closes the child, when GitHub left the child OPEN after the merge —
73
- // the one `merged` child whose issue this command still has to close.
74
- merged_pr?: string | undefined
75
- // The outage is not an API outage (`EndingSignals.is_streak_exempt`): re-dispatched, but not added
76
- // to the streak.
77
- is_streak_exempt?: boolean | undefined
78
78
  }
79
79
 
80
80
  interface FailedResult {
@@ -213,6 +213,10 @@ async function preserve_uncommitted(child: string): Promise<boolean> {
213
213
  }
214
214
  }
215
215
 
216
+ async function close_preserved_lane(child: string): Promise<void> {
217
+ if (await preserve_uncommitted(child)) await close_lane(child)
218
+ }
219
+
216
220
  function kept_lane_comment(directory: string): string {
217
221
  return `The split left this issue's lane open: it still holds a commit, an uncommitted change or a live process — ${directory}`
218
222
  }
@@ -251,27 +255,44 @@ async function post_counters(ctx: MergeContext, carry: RunCarry | undefined): Pr
251
255
  await git_gh_issue_write.issue_try_comment(ctx.epic, run_merge.counters_comment(carry))
252
256
  }
253
257
 
254
- // A merged child: close it if GitHub left it OPEN and close the epics it completed
255
- // (`run-merge-close.ts`), count the merge (which resets the failure streak), return to the default branch,
256
- // stash any uncommitted work the lane still holds and close it, and mirror the counters onto the epic. Returns the carry when the ownership check
257
- // fails — the caller treats a non-undefined return as a hard refusal and must not offer a next child.
258
- // Returns `undefined` on success.
259
- async function do_merged(ctx: MergeContext): Promise<RunCarry | undefined> {
258
+ // Count the merge, which resets the failure streak.
259
+ async function count_merged(ctx: MergeContext): Promise<ApplyCarryResult> {
260
+ return await apply_carry(ctx, {
261
+ ...run_merge.change_of('merged'),
262
+ merged_issue: Number(ctx.child),
263
+ })
264
+ }
265
+
266
+ // A merged child: closed if GitHub left it OPEN, with the epics it completed (`run-merge-close.ts`),
267
+ // while the primary checkout returns to the default branch; then counted and put on record by `record`,
268
+ // dated to the moment the ownership check passed (joshuafolkken/kit#4734); then the lane — stashed of
269
+ // any uncommitted work — is closed while the counters are mirrored onto the epic. **A failed sync
270
+ // leaves neither the count nor the record**, so the run's next pass (a restored drive, `run:carry
271
+ // --end`) still reads the child as unsettled and collects it again. **What the next offer reads ends
272
+ // before this returns**: the closed issue and epics, the count, the lane's freed seat, and the default
273
+ // branch whose code the next `josh` runs. Returns the carry when the ownership check fails — the caller
274
+ // treats a non-undefined return as a hard refusal and must not offer a next child. Returns `undefined`
275
+ // on success.
276
+ async function do_merged(
277
+ ctx: MergeContext,
278
+ record: (child: string, at: Date) => Promise<void>,
279
+ ): Promise<RunCarry | undefined> {
260
280
  const refused = await refused_carry(ctx)
261
281
 
262
282
  if (refused !== undefined) return refused
263
283
 
264
- await run_merge_close.close_merged(ctx)
265
- await sync_main()
266
- const result = await apply_carry(ctx, {
267
- ...run_merge.change_of('merged'),
268
- merged_issue: Number(ctx.child),
269
- })
284
+ const confirmed_at = new Date()
285
+
286
+ await settled_together(run_merge_close.close_merged(ctx), sync_main())
287
+ const result = await count_merged(ctx)
270
288
 
271
289
  if (result.kind === 'refused') return result.carry
272
290
 
273
- if (await preserve_uncommitted(ctx.child)) await close_lane(ctx.child)
274
- await post_counters(ctx, result.kind === 'applied' ? result.carry : undefined)
291
+ await record(ctx.child, confirmed_at)
292
+
293
+ const carry = result.kind === 'applied' ? result.carry : undefined
294
+
295
+ await Promise.all([close_preserved_lane(ctx.child), post_counters(ctx, carry)])
275
296
 
276
297
  return undefined
277
298
  }
@@ -319,7 +340,7 @@ async function start_date_wait(ctx: MergeContext): Promise<ReadonlyArray<string>
319
340
 
320
341
  if (body === undefined) return (await has_not_before_label(ctx)) ? [NOT_BEFORE_WAIT] : NO_WAITS
321
342
 
322
- await issue_sample_gate.prime([body])
343
+ await issue_sample_prime.prime([body])
323
344
  const reason = issue_not_before.waiting_reason(body)
324
345
 
325
346
  return reason === undefined ? NO_WAITS : [reason]
@@ -379,9 +400,7 @@ async function do_failed(ctx: MergeContext, cause?: StallCause): Promise<FailedR
379
400
 
380
401
  if (waits.length > 0) return await do_waiting(ctx, waits)
381
402
 
382
- const judged = cause ?? run_merge_ship.cause(ctx.child) ?? run_stalled.SESSION_UNFINISHED
383
-
384
- return await park_failed(ctx, judged)
403
+ return await park_failed(ctx, run_merge_cap.park_cause(ctx.child, cause, ctx.capped_note))
385
404
  }
386
405
 
387
406
  // The outcome of counting an outage: the record to read the streak against, and whether the count was
@@ -463,11 +482,12 @@ async function resume_cut(child: string): Promise<boolean> {
463
482
  }
464
483
 
465
484
  // The hand-off check, asked at a merge alone. A subprocess that cannot measure exits non-zero, which
466
- // is read as `over` — "could not measure" is never "still cheap". No threshold is no session to measure.
467
- async function is_over_budget(over: number | undefined): Promise<boolean> {
485
+ // is read as `over` — "could not measure" is never "still cheap". No check is no session to measure.
486
+ // `--cut`, not a number: the threshold is priced at the session's own model.
487
+ async function is_over_budget(over: true | undefined): Promise<boolean> {
468
488
  if (over === undefined) return false
469
489
 
470
- const result = await josh(['cost', '--over', String(over)])
490
+ const result = await josh(['cost', '--cut'])
471
491
 
472
492
  return result.code !== 0 || result.out === OVER
473
493
  }
@@ -0,0 +1,53 @@
1
+ import { issue_cite } from '#scripts/issue/issue-cite'
2
+ import { run_event_stream, type RunEvent } from '#scripts/run/event/run-event-stream'
3
+ import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
4
+
5
+ // A returned child a Claude usage limit stopped (joshuafolkken/kit#4745). Nothing is counted and no park
6
+ // label is put on it — the limit is the account's, not the child's — so it is released for the backlog
7
+ // to offer again, and the stop is written to the event stream with the time the limit resets.
8
+ // `backlog:drive` reads that time back and launches nothing before it. **It is no `OUTAGE`**: the
9
+ // per-child cap counts those (`run-merge-cap.ts`), and a wait for a known reset is no outage streak.
10
+ // Script-emitted, so English.
11
+
12
+ const KIND = run_event_stream.EVENT_KIND.USAGE_LIMIT
13
+ const RESUMES_AT = /resumes at (\S+)$/u
14
+
15
+ function stop_text(child: string, reset_ms: number): string {
16
+ return `${issue_cite.plain(child)} usage limit — resumes at ${new Date(reset_ms).toISOString()}`
17
+ }
18
+
19
+ async function record(child: string, reset_ms: number): Promise<void> {
20
+ await run_event_stream_emit.emit(KIND, stop_text(child, reset_ms))
21
+ }
22
+
23
+ // The time a stop's text names, or `undefined` when it does not parse.
24
+ function time_of(text: string): number | undefined {
25
+ const parsed = Date.parse(RESUMES_AT.exec(text)?.[1] ?? '')
26
+
27
+ return Number.isNaN(parsed) ? undefined : parsed
28
+ }
29
+
30
+ // The reset the newest usage-limit stop names, in epoch milliseconds, or `undefined` when the stream
31
+ // holds none — every lane shares the one account, so the newest stop is the limit in force.
32
+ function resume_ms(events: ReadonlyArray<RunEvent>): number | undefined {
33
+ const newest = events.findLast((event) => event.kind === KIND)
34
+
35
+ return newest === undefined ? undefined : time_of(newest.text)
36
+ }
37
+
38
+ // The reset a usage limit still holds launches until at `now_ms`, or `undefined` once it has passed —
39
+ // what `run:board` names a waiting row's hold by (joshuafolkken/kit#4796).
40
+ function held_until(events: ReadonlyArray<RunEvent>, now_ms: number): number | undefined {
41
+ const reset_ms = resume_ms(events)
42
+
43
+ return reset_ms !== undefined && reset_ms > now_ms ? reset_ms : undefined
44
+ }
45
+
46
+ // Whether a usage limit still holds launches at `now_ms` — the production `usage_limited` port.
47
+ async function is_held(now_ms: number): Promise<boolean> {
48
+ return held_until(await run_event_stream_emit.current_events(), now_ms) !== undefined
49
+ }
50
+
51
+ const run_merge_usage_limit = { held_until, is_held, record, resume_ms }
52
+
53
+ export { run_merge_usage_limit }
@@ -0,0 +1,53 @@
1
+ import { lane_registry } from '#scripts/lane/lane-registry'
2
+ import { lane_withdraw_closed } from '#scripts/lane/lane-withdraw-closed'
3
+ import { lane_yield } from '#scripts/lane/lane-yield'
4
+ import { run_event_scope } from '#scripts/run/event/run-event-scope'
5
+ import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
6
+
7
+ // The lane of a child `run:merge` booked `withdrawn` (joshuafolkken/kit#4916). A person's
8
+ // `lane:withdraw` already stopped the child, closed its lane and put itself on the stream, so nothing is
9
+ // left to do. A child whose issue closed without a merge had no such withdrawal: its lane is still open,
10
+ // so it is withdrawn here through the `run:wake` sweep's guarded path — kept where its branch has
11
+ // commits on no remote, else stopped, its work stashed, the lane closed and the withdrawal put on the
12
+ // stream — and never booked as a merge. A withdrawal that could not read the child stopped and closed
13
+ // nothing, so it asks for a retry rather than leak the lane.
14
+
15
+ const UNMERGED_REASON = 'its issue was closed without a merged pull request'
16
+
17
+ interface Collected {
18
+ // The withdrawal's note, or `undefined` where a withdrawal is on the stream or no lane is open.
19
+ note: string | undefined
20
+ is_retry: boolean
21
+ }
22
+
23
+ const NOTHING_LEFT: Collected = { note: undefined, is_retry: false }
24
+
25
+ /** Withdraw `#<child>`'s open lane unless a withdrawal that closed it is already on the stream. */
26
+ async function collect(child: string): Promise<Collected> {
27
+ const events = await run_event_stream_emit.current_events()
28
+
29
+ if (run_event_scope.is_withdrawn(events, child)) return NOTHING_LEFT
30
+ const lane = await lane_registry.find_open_lane(child)
31
+
32
+ return lane === undefined
33
+ ? NOTHING_LEFT
34
+ : await lane_withdraw_closed.withdraw_lane(lane, UNMERGED_REASON, 'merge')
35
+ }
36
+
37
+ /**
38
+ * Close the open lane of `#<child>`, which gave it back (`lane-yield.ts`): the child noted its yield
39
+ * from inside the lane, which it could not close, so the lane is closed here, named as the yield. A
40
+ * lane already closed — a second `run:merge` — leaves nothing to do.
41
+ */
42
+ async function collect_yield(child: string): Promise<Collected> {
43
+ const lane = await lane_registry.find_open_lane(child)
44
+
45
+ return lane === undefined
46
+ ? NOTHING_LEFT
47
+ : await lane_withdraw_closed.withdraw_lane(lane, lane_yield.YIELD_REASON, 'yield')
48
+ }
49
+
50
+ const run_merge_withdrawn = { UNMERGED_REASON, collect, collect_yield }
51
+
52
+ export type { Collected }
53
+ export { run_merge_withdrawn }
@@ -35,7 +35,7 @@ const ONE = 1
35
35
 
36
36
  // What a returned child turned out to be, decided from its GitHub state and — for the failed case
37
37
  // alone — the exit record.
38
- // - `merged` — CLOSED; the child finished and its pull request merged. Also an OPEN, unparked
38
+ // - `merged` — CLOSED by a merge; the child finished and its pull request merged. Also an OPEN, unparked
39
39
  // child a merged pull request's `closes #N` names — GitHub merged it without closing
40
40
  // the issue.
41
41
  // - `human-review` — OPEN and carrying `needs-human-review`; the run's own ending (needs-human-review.md).
@@ -50,9 +50,14 @@ const ONE = 1
50
50
  // - `unauthenticated` — OPEN and carrying neither, but the exit record shows the session could not
51
51
  // authenticate; no child can run until a person runs `/login`, so the run stops with
52
52
  // the child left `in-progress` and nothing counted (joshuafolkken/kit#4216).
53
+ // - `usage-limit` — OPEN and carrying neither, but the exit record shows a Claude usage limit stopped
54
+ // it; nothing is counted or parked, and the run dispatches again once the limit
55
+ // resets (joshuafolkken/kit#4745).
53
56
  // - `failed` — OPEN and carrying neither, and not an outage; the child did not finish.
54
57
  // - `withdrawn` — a person withdrew it with `lane:withdraw`, read from the event stream before the
55
- // GitHub state: left OPEN for the next run, it is neither merged nor failed.
58
+ // GitHub state: left OPEN for the next run, it is neither merged nor failed. Also a
59
+ // CLOSED child no merge closed — closed as not planned, or with no merged pull
60
+ // request (joshuafolkken/kit#4916).
56
61
  // - `unresolved` — the state could not be read; re-read before deciding.
57
62
  // The names themselves are `run-merge-outcome.ts`'s.
58
63
 
@@ -64,13 +69,22 @@ interface EndingSignals {
64
69
  // The merged pull request whose `closes #N` names the child, when GitHub left the child OPEN after
65
70
  // merging it.
66
71
  merged_pr?: string | undefined
67
- // The newest launch of the child was withdrawn by a person (`run_event_scope.is_withdrawn`).
72
+ // The newest launch of the child was withdrawn by a person (`run_event_scope.is_withdrawn`), or its
73
+ // issue was closed without a merge (`run-merge-signals.ts` → `read_is_withdrawn`).
68
74
  is_withdrawn?: boolean | undefined
75
+ // The newest launch of the child gave its lane back on its `lane:plan` (`lane-yield.ts`).
76
+ is_yielded?: boolean | undefined
69
77
  // The outage is not an API the child could not reach — a ship stop no relaunch answered, or a host
70
78
  // restart that killed it — so it is left out of the run-wide streak.
71
79
  is_streak_exempt?: boolean | undefined
72
80
  // The exit record shows the session could not authenticate (`api-auth.ts`).
73
81
  is_auth_failure?: boolean | undefined
82
+ // When a usage limit that stopped the session lets the run dispatch again, in epoch milliseconds
83
+ // (`api-usage-limit.ts`); absent when no usage limit stopped it.
84
+ resume_ms?: number | undefined
85
+ // A re-dispatchable ending the per-child cap turned into `failed`: the line its park leads with
86
+ // (`run-merge-cap.ts`).
87
+ capped_note?: string | undefined
74
88
  }
75
89
 
76
90
  const NO_SIGNALS: EndingSignals = { is_outage: false, is_cut: false }
@@ -85,7 +99,18 @@ function is_parked(state: IssueState): boolean {
85
99
  return has_parked_label(state.labels)
86
100
  }
87
101
 
88
- // **CLOSED means merged, whatever labels it carries** — a child that finished and merged keeps the
102
+ // An unfinished child its environment ended: it could not authenticate, a usage limit stopped it, or it
103
+ // could not reach the API — read in that order, each more specific than the next.
104
+ function environment_outcome(signals: EndingSignals): ChildOutcome {
105
+ if (signals.is_auth_failure === true) return 'unauthenticated'
106
+
107
+ if (signals.resume_ms !== undefined) return 'usage-limit'
108
+
109
+ return signals.is_outage ? 'outage' : 'failed'
110
+ }
111
+
112
+ // **CLOSED means merged, whatever labels it carries**, once the withdrawal signal has ruled out a close
113
+ // no merge made (`classify_child`) — a child that finished and merged keeps the
89
114
  // `needs-human-review` a person put on it, so that label is read only on an OPEN child
90
115
  // (`backlogrun-progress.md` → "Running a named epic's children").
91
116
  // An OPEN, unparked child that is not waiting on a person: a declared cut is resumed, and it is read
@@ -98,9 +123,7 @@ function unfinished_outcome(signals: EndingSignals): ChildOutcome {
98
123
 
99
124
  if (signals.is_cut) return 'cut'
100
125
 
101
- if (signals.is_auth_failure === true) return 'unauthenticated'
102
-
103
- return signals.is_outage ? 'outage' : 'failed'
126
+ return environment_outcome(signals)
104
127
  }
105
128
 
106
129
  function open_outcome(state: IssueState, signals: EndingSignals): ChildOutcome {
@@ -113,25 +136,29 @@ function open_outcome(state: IssueState, signals: EndingSignals): ChildOutcome {
113
136
  return unfinished_outcome(signals)
114
137
  }
115
138
 
139
+ function state_outcome(state: IssueState, signals: EndingSignals): ChildOutcome {
140
+ return is_closed(state) ? 'merged' : open_outcome(state, signals)
141
+ }
142
+
116
143
  // The signals are read by the CLI and, but for a withdrawal, matter only for an OPEN child — a CLOSED
117
- // child is merged regardless of how the process exited. **A withdrawal is read first**: `lane:withdraw`
144
+ // child arrives already filtered by `is_withdrawn` (its timeline), so one that reaches here is merged
145
+ // regardless of how the process exited. **A yield, then a withdrawal, is read first**: a yield leaves
146
+ // its issue OPEN and its lane open for `run:merge` to close (`lane-yield.ts`), and `lane:withdraw`
118
147
  // records it before stopping the child and leaves the issue OPEN, which would otherwise read as a child
119
148
  // to resume or park.
120
149
  function classify_child(
121
150
  state: IssueState | undefined,
122
151
  signals: EndingSignals = NO_SIGNALS,
123
152
  ): ChildOutcome {
124
- if (signals.is_withdrawn === true) return 'withdrawn'
125
-
126
- if (state === undefined) return 'unresolved'
153
+ if (signals.is_yielded === true) return 'yielded'
127
154
 
128
- if (is_closed(state)) return 'merged'
155
+ if (signals.is_withdrawn === true) return 'withdrawn'
129
156
 
130
- return open_outcome(state, signals)
157
+ return state === undefined ? 'unresolved' : state_outcome(state, signals)
131
158
  }
132
159
 
133
160
  // The counter change a child's outcome implies. A merge counts a merge (which resets the failure
134
- // streak); a failure counts a failure; a split, parked, withdrawn or human-review child counts nothing —
161
+ // streak); a failure counts a failure; a split, parked, withdrawn, yielded or human-review child counts nothing —
135
162
  // a decision a person made or still owes is not the environment failing — and `undefined` says the
136
163
  // carry record is left untouched.
137
164
  function change_of(outcome: ChildOutcome): CarryChange | undefined {