@joshuafolkken/kit 1.1178.0 → 1.1229.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 (425) hide show
  1. package/.claude/.claude-plugin/plugin.json +1 -1
  2. package/.claude/settings.json +2 -2
  3. package/.claude/skills/dependency-update/SKILL.md +4 -8
  4. package/.claude/skills/epic-commands/SKILL.md +2 -2
  5. package/.claude/skills/epic-commands/epic-bundle.md +1 -1
  6. package/.claude/skills/workflow-commands/SKILL.md +2 -4
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +6 -4
  8. package/.claude/skills/workflow-commands/backlogrun-lanes.md +6 -2
  9. package/.claude/skills/workflow-commands/backlogrun-park.md +23 -2
  10. package/.claude/skills/workflow-commands/backlogrun-progress.md +7 -2
  11. package/.claude/skills/workflow-commands/backlogrun-recovery.md +4 -3
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +21 -13
  13. package/.claude/skills/workflow-commands/chain-rule.md +1 -1
  14. package/.claude/skills/workflow-commands/delegation.md +2 -2
  15. package/.claude/skills/workflow-commands/followup.md +5 -0
  16. package/.claude/skills/workflow-commands/fullrun-steps.md +1 -1
  17. package/.claude/skills/workflow-commands/halfrun.md +1 -1
  18. package/.claude/skills/workflow-commands/issue-scout.md +1 -1
  19. package/.claude/skills/workflow-commands/kickoff.md +1 -1
  20. package/.claude/skills/workflow-commands/observation-ledger.md +3 -3
  21. package/.claude/skills/workflow-commands/pre-gate-cut.md +6 -1
  22. package/.claude/skills/workflow-commands/prerequisite.md +2 -2
  23. package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
  24. package/.claude/skills/workflow-commands/working-tree-hold.md +1 -1
  25. package/.codex/hooks.json +2 -2
  26. package/.cursorrules +6 -41
  27. package/.github/actions/setup-node/action.yml +1 -1
  28. package/.github/workflows/auto-tag.yml +3 -4
  29. package/.github/workflows/ci.yml +32 -31
  30. package/.github/workflows/dependabot-auto-merge.yml +13 -6
  31. package/.github/workflows/publish.yml +48 -4
  32. package/.github/workflows/sonar-qube.yml +3 -0
  33. package/.pnpmfile.mjs +4 -3
  34. package/.prettierignore +8 -2
  35. package/CLAUDE.md +18 -20
  36. package/README.md +26 -19
  37. package/SECURITY.md +15 -1
  38. package/dist/CLAUDE.md +18 -20
  39. package/dist/commands/document-section-cli.js +734 -0
  40. package/dist/hooks/audit-provision.js +346 -0
  41. package/dist/hooks/batch-guard.js +5 -4
  42. package/dist/hooks/{chunk-S6X6WYKR.js → chunk-55HHG5PX.js} +1210 -711
  43. package/dist/hooks/{chunk-ZAL3NRGL.js → chunk-5VMKCCC4.js} +25 -10
  44. package/dist/hooks/chunk-5VNDSNG3.js +12 -0
  45. package/dist/hooks/{chunk-32GQTL4F.js → chunk-6HJJXRBX.js} +4 -2
  46. package/dist/hooks/chunk-CDY4NFQG.js +15 -0
  47. package/dist/hooks/chunk-ELCN5LCH.js +135 -0
  48. package/dist/hooks/{chunk-VESKRQOF.js → chunk-F56MFS4B.js} +3 -3
  49. package/dist/hooks/{chunk-UAGLLIGZ.js → chunk-FIVDHQGT.js} +7 -6
  50. package/dist/hooks/{chunk-3V37IID6.js → chunk-JBBMAPC4.js} +23 -14
  51. package/dist/hooks/{chunk-G6KRCKEC.js → chunk-JUDKDCDP.js} +496 -378
  52. package/dist/hooks/{chunk-GDS5N2KB.js → chunk-NV2JRZZO.js} +718 -681
  53. package/dist/hooks/{chunk-VQLLNFNT.js → chunk-RNWHN5BP.js} +3 -3
  54. package/dist/hooks/{chunk-DO6NWWHU.js → chunk-TQNPDZNH.js} +4 -4
  55. package/dist/hooks/{chunk-I4XSL4TT.js → chunk-VC3PZPZO.js} +1 -1
  56. package/dist/hooks/codex-hook-adapter.js +14 -12
  57. package/dist/hooks/duplicate-read-guard.js +6 -5
  58. package/dist/hooks/format-edited.js +4 -3
  59. package/dist/hooks/inputs.json +217 -195
  60. package/dist/hooks/investigation-guard.js +6 -5
  61. package/dist/hooks/pretool-guard.js +12 -10
  62. package/dist/hooks/session-lang.js +2 -4
  63. package/dist/hooks/stop-guard.js +66 -58
  64. package/dist/josh.js +868 -74
  65. package/dist/version/index.d.ts +7 -2
  66. package/dist/version/index.js +152 -75
  67. package/eslint/base.js +23 -1
  68. package/eslint/rules/code-quality.js +3 -0
  69. package/eslint/rules/early-return-one-liner.js +98 -0
  70. package/eslint/rules/unicorn.js +16 -1
  71. package/package.json +7 -6
  72. package/pnpm-workspace.yaml +9 -4
  73. package/prettier/basic.d.ts +3 -1
  74. package/prettier/index.d.ts +3 -1
  75. package/prettier/static.d.ts +3 -1
  76. package/prompts/coding-standards.md +1 -1
  77. package/prompts/collaboration-workflow/file-edits.md +4 -4
  78. package/prompts/collaboration-workflow/glossary.md +1 -1
  79. package/prompts/collaboration-workflow/operating-rules.md +17 -9
  80. package/prompts/collaboration-workflow/overview.md +2 -2
  81. package/prompts/collaboration-workflow/principles.md +14 -12
  82. package/prompts/collaboration-workflow/report-format.md +1 -1
  83. package/prompts/collaboration-workflow/residency.md +1 -1
  84. package/prompts/collaboration-workflow/rule-delivery.md +6 -6
  85. package/prompts/collaboration-workflow/shell-body.md +6 -6
  86. package/prompts/collaboration-workflow/turn-batching.md +1 -1
  87. package/prompts/collaboration-workflow/upstream-interrupt.md +12 -2
  88. package/prompts/collaboration-workflow/wip-cap.md +10 -10
  89. package/prompts/review-rubric.md +1 -2
  90. package/prompts/review.md +1 -1
  91. package/scripts/agent/agent-headless.ts +29 -0
  92. package/scripts/agent/agent-launch-environment.ts +6 -2
  93. package/scripts/agent/codex-agent-argv.ts +2 -1
  94. package/scripts/auto-ok/auto-ok-cli.ts +1 -1
  95. package/scripts/backlog/backlog-arrival.ts +3 -3
  96. package/scripts/backlog/backlog-budget.ts +1 -1
  97. package/scripts/backlog/backlog-drive-args.ts +135 -0
  98. package/scripts/backlog/backlog-drive-cli.ts +11 -137
  99. package/scripts/backlog/backlog-drive-launch.ts +39 -0
  100. package/scripts/backlog/backlog-drive-named-offer.ts +3 -5
  101. package/scripts/backlog/backlog-drive-named.ts +3 -3
  102. package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
  103. package/scripts/backlog/backlog-drive-owner.ts +1 -1
  104. package/scripts/backlog/backlog-drive-restore.ts +1 -1
  105. package/scripts/backlog/backlog-drive-retrospective.ts +1 -1
  106. package/scripts/backlog/backlog-drive.ts +1 -1
  107. package/scripts/backlog/backlog-next.ts +16 -5
  108. package/scripts/backlog/backlog-offer-cli.ts +6 -6
  109. package/scripts/backlog/backlog-offer.ts +1 -1
  110. package/scripts/backlog/backlog-plan-cli.ts +1 -1
  111. package/scripts/backlog/backlog-pool.ts +57 -11
  112. package/scripts/backlog/backlog-ready.ts +1 -1
  113. package/scripts/backlog/backlog-scope.ts +1 -1
  114. package/scripts/backlog/backlog-stalled-detect.ts +2 -2
  115. package/scripts/backlog/backlog-stalled.ts +1 -1
  116. package/scripts/build/build-codex-hooks.ts +3 -1
  117. package/scripts/build/build-commands.ts +66 -0
  118. package/scripts/build/build-hooks.ts +2 -1
  119. package/scripts/build/build-library.ts +12 -3
  120. package/scripts/build/build.ts +70 -0
  121. package/scripts/build/local-bin.ts +3 -13
  122. package/scripts/delegation/investigation-reads.ts +3 -1
  123. package/scripts/discovery/repo-origin.ts +5 -5
  124. package/scripts/doctor/doctor-consumer.ts +2 -2
  125. package/scripts/doctor/doctor-io.ts +2 -3
  126. package/scripts/document/capped-print-part.ts +30 -0
  127. package/scripts/document/capped-print.ts +3 -4
  128. package/scripts/document/document-byte-budget.ts +11 -2
  129. package/scripts/document/document-scan.ts +117 -0
  130. package/scripts/document/document-section.ts +143 -16
  131. package/scripts/document/entry-read-budget.ts +5 -3
  132. package/scripts/document/entry-read-set.ts +10 -89
  133. package/scripts/document/read-set-cost.ts +98 -0
  134. package/scripts/epic/epic-add-body.ts +1 -0
  135. package/scripts/epic/epic-audit-checks.ts +1 -1
  136. package/scripts/epic/epic-audit-rationale.ts +4 -3
  137. package/scripts/epic/epic-bundle-cli.ts +14 -3
  138. package/scripts/epic/epic-bundle-poll.ts +41 -0
  139. package/scripts/epic/epic-busy.ts +1 -1
  140. package/scripts/epic/epic-candidate-confirm.ts +3 -2
  141. package/scripts/epic/epic-classify.ts +1 -1
  142. package/scripts/epic/epic-cli-argv.ts +78 -46
  143. package/scripts/epic/epic-cli-remove.ts +11 -19
  144. package/scripts/epic/epic-cli.ts +74 -73
  145. package/scripts/epic/epic-close-comment.ts +1 -1
  146. package/scripts/epic/epic-close.ts +1 -1
  147. package/scripts/epic/epic-cross-repo.ts +5 -5
  148. package/scripts/epic/epic-graph.ts +1 -1
  149. package/scripts/epic/epic-index.ts +1 -1
  150. package/scripts/epic/epic-issue.ts +2 -6
  151. package/scripts/epic/epic-lane-offer.ts +2 -2
  152. package/scripts/epic/epic-next.ts +29 -42
  153. package/scripts/epic/epic-solo-stale.ts +1 -1
  154. package/scripts/epic/epic-triage.ts +8 -4
  155. package/scripts/epic/epic-validate.ts +1 -1
  156. package/scripts/followup/git-followup-finish.ts +2 -2
  157. package/scripts/followup/git-followup-label.ts +2 -2
  158. package/scripts/followup/git-followup-merged.ts +2 -2
  159. package/scripts/followup/git-pr-followup-checks.ts +142 -0
  160. package/scripts/followup/git-pr-followup.ts +4 -129
  161. package/scripts/gate/core-budget.ts +69 -1
  162. package/scripts/gate/gate-plan.ts +47 -7
  163. package/scripts/gate/gate-skip.ts +38 -7
  164. package/scripts/gate/hook-gate-reuse.ts +12 -10
  165. package/scripts/gate/pre-commit-type-check.ts +4 -1
  166. package/scripts/gate/project-checks.ts +6 -9
  167. package/scripts/gate/type-check-step.ts +2 -3
  168. package/scripts/gate/verification-gate.ts +27 -8
  169. package/scripts/gh/git-gh-api-path.ts +2 -2
  170. package/scripts/gh/git-gh-issue-rest.ts +3 -3
  171. package/scripts/gh/git-gh-issue-write.ts +53 -7
  172. package/scripts/gh/git-gh-pr-read.ts +64 -19
  173. package/scripts/gh/git-gh-pr-rest.ts +1 -1
  174. package/scripts/gh/git-gh-pr.ts +5 -1
  175. package/scripts/gh/git-pr-ai-review.ts +1 -1
  176. package/scripts/gh/git-pr-checks-eval.ts +1 -3
  177. package/scripts/gh/git-pr-checks-parse.ts +1 -1
  178. package/scripts/gh/git-pr-checks-watch.ts +6 -5
  179. package/scripts/gh/git-pr-checks.ts +7 -5
  180. package/scripts/gh/git-pr-coderabbit.ts +1 -1
  181. package/scripts/gh/git-pr-error.ts +1 -3
  182. package/scripts/gh/git-pr.ts +9 -13
  183. package/scripts/gh/github-issue-url.ts +2 -2
  184. package/scripts/git/constants.ts +2 -6
  185. package/scripts/git/git-command.ts +20 -218
  186. package/scripts/git/git-diff-reads.ts +225 -0
  187. package/scripts/git/git-error.ts +4 -12
  188. package/scripts/git/git-pre-push-hook.ts +139 -0
  189. package/scripts/git/git-prompt.ts +2 -6
  190. package/scripts/git/git-spawn-sync.ts +3 -1
  191. package/scripts/git/git-spawn.ts +1 -1
  192. package/scripts/git/git-staging.ts +4 -6
  193. package/scripts/git/git-status.ts +3 -9
  194. package/scripts/hooks/codex-hook-adapter.ts +1 -1
  195. package/scripts/hooks/edited-cspell.ts +2 -4
  196. package/scripts/hooks/format-edited-file.ts +3 -12
  197. package/scripts/hooks/pre-push-unit.ts +31 -9
  198. package/scripts/hooks/reserved-run.ts +2 -2
  199. package/scripts/hooks/run-hook.sh +5 -4
  200. package/scripts/hooks/stop-guard.ts +5 -3
  201. package/scripts/init/init-actions.ts +0 -5
  202. package/scripts/init/init-ai-copy.ts +13 -2
  203. package/scripts/init/init-logic-json-merge.ts +19 -0
  204. package/scripts/init/init-logic-secretlint.ts +7 -7
  205. package/scripts/init/init-logic-workspace.ts +41 -2
  206. package/scripts/init/init-logic.ts +16 -26
  207. package/scripts/init/init.ts +5 -15
  208. package/scripts/init/initial-commit.ts +4 -4
  209. package/scripts/init/kit-development-versions.ts +40 -0
  210. package/scripts/init/kit-setup-state.ts +2 -2
  211. package/scripts/init/start-exec.ts +68 -19
  212. package/scripts/init/start-setup-pr.ts +9 -9
  213. package/scripts/init/start-steps.ts +6 -10
  214. package/scripts/issue/defect-rate-cli.ts +1 -1
  215. package/scripts/issue/git-next-issues.ts +1 -1
  216. package/scripts/issue/issue-auto-ok.ts +1 -1
  217. package/scripts/issue/issue-backlinks-cli.ts +2 -2
  218. package/scripts/issue/issue-backlinks.ts +9 -9
  219. package/scripts/issue/issue-comment-cli.ts +19 -13
  220. package/scripts/issue/issue-file-cli.ts +45 -18
  221. package/scripts/issue/issue-file.ts +24 -1
  222. package/scripts/issue/issue-scout-closed.ts +1 -1
  223. package/scripts/issue/issue-state-cli.ts +30 -74
  224. package/scripts/josh/josh-command-map.ts +2 -0
  225. package/scripts/josh/josh-command-types.ts +11 -0
  226. package/scripts/josh/josh-commands-ai.ts +4 -4
  227. package/scripts/josh/josh-commands-backlog.ts +4 -1
  228. package/scripts/josh/josh-commands-development.ts +10 -0
  229. package/scripts/josh/josh-commands-document.ts +1 -0
  230. package/scripts/josh/josh-commands-lane.ts +22 -0
  231. package/scripts/josh/josh-commands-maintenance.ts +4 -4
  232. package/scripts/josh/josh-commands-run.ts +12 -7
  233. package/scripts/josh/josh-in-process.ts +28 -9
  234. package/scripts/josh/josh-logic.ts +33 -15
  235. package/scripts/josh/process-identity.ts +1 -3
  236. package/scripts/josh/session-language-cli.ts +3 -4
  237. package/scripts/lane/lane-await.ts +5 -1
  238. package/scripts/lane/lane-child-invocation.ts +2 -2
  239. package/scripts/lane/lane-cli.ts +3 -3
  240. package/scripts/lane/lane-dispatch.ts +14 -10
  241. package/scripts/lane/lane-environment.ts +5 -1
  242. package/scripts/lane/lane-handoff.ts +1 -1
  243. package/scripts/lane/lane-install.ts +2 -13
  244. package/scripts/lane/lane-launch-cli.ts +15 -1
  245. package/scripts/lane/lane-ledger.ts +145 -0
  246. package/scripts/lane/lane-leftover.ts +1 -1
  247. package/scripts/lane/lane-load.ts +108 -0
  248. package/scripts/lane/lane-measure-cli.ts +149 -0
  249. package/scripts/lane/lane-occupancy.ts +3 -0
  250. package/scripts/lane/lane-reap.ts +1 -3
  251. package/scripts/lane/lane-relaunch.ts +1 -1
  252. package/scripts/lane/lane-stats.ts +224 -0
  253. package/scripts/lane/lane-vacant.ts +36 -0
  254. package/scripts/lane/openai-lane-ship.ts +2 -2
  255. package/scripts/lane/openai-lane-supervisor-owner.ts +180 -0
  256. package/scripts/lane/openai-lane-supervisor.ts +7 -165
  257. package/scripts/lane/openai-review-broker.ts +2 -4
  258. package/scripts/lib/ancestor-directories.ts +35 -0
  259. package/scripts/lib/animation-helpers.ts +2 -2
  260. package/scripts/lib/buffered-process.ts +3 -7
  261. package/scripts/lib/cli-flags.ts +71 -1
  262. package/scripts/lib/spawn-exit.ts +2 -2
  263. package/scripts/lib/timeouts.ts +35 -2
  264. package/scripts/lines/line-budget.ts +4 -6
  265. package/scripts/notify/telegram-test.ts +6 -0
  266. package/scripts/observations/observation-ledger-line.ts +6 -6
  267. package/scripts/observations/observation-ledger-migrate.ts +55 -4
  268. package/scripts/observations/observation-ledger.ts +26 -7
  269. package/scripts/overrides/lockfile-overrides.ts +1 -1
  270. package/scripts/overrides/overrides-logic.ts +1 -1
  271. package/scripts/propagate/propagate-git.ts +1 -1
  272. package/scripts/propagate/propagate-publish.ts +2 -2
  273. package/scripts/propagate/propagate-steps.ts +20 -15
  274. package/scripts/propagate/propagate.ts +36 -27
  275. package/scripts/refactor/import-graph.ts +18 -1
  276. package/scripts/refactor/refactor-lint.ts +4 -4
  277. package/scripts/repo/repository-labels.ts +2 -2
  278. package/scripts/repo/required-checks-logic.ts +1 -3
  279. package/scripts/review/live-evidence.ts +2 -4
  280. package/scripts/review/review-brief-cli.ts +1 -1
  281. package/scripts/review/review-finding-ledger.ts +1 -1
  282. package/scripts/review/review-findings-cli.ts +1 -3
  283. package/scripts/rules/decision-oracle-batch.ts +128 -0
  284. package/scripts/rules/decision-oracle-tokens.ts +21 -0
  285. package/scripts/rules/decision-oracle.ts +8 -120
  286. package/scripts/rules/delivered-rules.ts +26 -182
  287. package/scripts/rules/direct-filing.ts +1 -1
  288. package/scripts/rules/early-heartbeat.ts +3 -3
  289. package/scripts/rules/git-argv.ts +1 -1
  290. package/scripts/rules/git-force.ts +1 -1
  291. package/scripts/rules/implementation-cut.ts +2 -2
  292. package/scripts/rules/index-guard.ts +1 -1
  293. package/scripts/rules/issue-comments.ts +118 -0
  294. package/scripts/rules/{issue-fold.ts → issue-fold-rule.ts} +2 -2
  295. package/scripts/rules/lane-background.ts +2 -2
  296. package/scripts/rules/lane-park.ts +18 -0
  297. package/scripts/rules/lane-split-park.ts +128 -0
  298. package/scripts/rules/oracle-firing.ts +1 -1
  299. package/scripts/rules/poll-loop.ts +1 -1
  300. package/scripts/rules/pre-gate-cut.ts +1 -1
  301. package/scripts/rules/protected-files.ts +59 -4
  302. package/scripts/rules/{run-tail.ts → run-tail-rule.ts} +2 -2
  303. package/scripts/rules/shell-body-trigger.ts +1 -1
  304. package/scripts/rules/stop-rules.ts +18 -7
  305. package/scripts/rules/test-declared-commit.ts +4 -4
  306. package/scripts/rules/wip-cap.ts +63 -0
  307. package/scripts/run/{run-carry-args.ts → carry/run-carry-args.ts} +37 -13
  308. package/scripts/run/{run-carry-change.ts → carry/run-carry-change.ts} +29 -7
  309. package/scripts/run/{run-carry-cli.ts → carry/run-carry-cli.ts} +4 -6
  310. package/scripts/run/{run-carry.ts → carry/run-carry.ts} +1 -1
  311. package/scripts/run/{run-cut-args.ts → cut/run-cut-args.ts} +1 -1
  312. package/scripts/run/{run-cut-cli.ts → cut/run-cut-cli.ts} +2 -2
  313. package/scripts/run/{run-cut.ts → cut/run-cut.ts} +1 -1
  314. package/scripts/run/{run-entry-cli.ts → entry/run-entry-cli.ts} +11 -11
  315. package/scripts/run/{run-entry.ts → entry/run-entry.ts} +2 -2
  316. package/scripts/run/{run-event-scope.ts → event/run-event-scope.ts} +1 -1
  317. package/scripts/run/{run-event-stream-emit.ts → event/run-event-stream-emit.ts} +1 -1
  318. package/scripts/run/{run-event-stream.ts → event/run-event-stream.ts} +16 -2
  319. package/scripts/run/{run-hold-cli.ts → hold/run-hold-cli.ts} +5 -5
  320. package/scripts/run/{run-merge-cli.ts → merge/run-merge-cli.ts} +10 -5
  321. package/scripts/run/{run-merge-steps.ts → merge/run-merge-steps.ts} +53 -5
  322. package/scripts/run/{run-merge.ts → merge/run-merge.ts} +1 -1
  323. package/scripts/run/{run-progress-cli.ts → progress/run-progress-cli.ts} +1 -1
  324. package/scripts/run/{run-progress-config.ts → progress/run-progress-config.ts} +2 -17
  325. package/scripts/run/{run-progress-read.ts → progress/run-progress-read.ts} +5 -5
  326. package/scripts/run/{run-progress.ts → progress/run-progress.ts} +1 -1
  327. package/scripts/run/{run-review-steps.ts → review/run-review-steps.ts} +2 -3
  328. package/scripts/run/run-ending.ts +2 -2
  329. package/scripts/run/run-halfrun-resume.ts +6 -1
  330. package/scripts/run/run-headless.ts +1 -1
  331. package/scripts/run/run-invocation.ts +85 -84
  332. package/scripts/run/run-liveness.ts +1 -1
  333. package/scripts/run/run-parent-cut-hook.ts +1 -1
  334. package/scripts/run/run-preflight.ts +6 -6
  335. package/scripts/run/run-prep-cli.ts +1 -1
  336. package/scripts/run/run-prrun-resume.ts +1 -1
  337. package/scripts/run/run-report-cli.ts +4 -4
  338. package/scripts/run/run-report.ts +2 -2
  339. package/scripts/run/run-status-cli.ts +1 -1
  340. package/scripts/run/run-step-cli.ts +3 -3
  341. package/scripts/run/run-step.ts +2 -2
  342. package/scripts/run/run-stop-notify.ts +1 -1
  343. package/scripts/run/run-stranded-detect.ts +4 -4
  344. package/scripts/run/run-stranded.ts +2 -2
  345. package/scripts/run/run-watcher-guard-cli.ts +1 -1
  346. package/scripts/run/run-watcher-guard.ts +5 -3
  347. package/scripts/run/run-watcher-hook.ts +1 -1
  348. package/scripts/run/{run-ship-cli.ts → ship/run-ship-cli.ts} +2 -2
  349. package/scripts/run/{run-ship-detach.ts → ship/run-ship-detach.ts} +3 -3
  350. package/scripts/run/ship/run-ship-lock.ts +50 -0
  351. package/scripts/run/{run-ship-preflight.ts → ship/run-ship-preflight.ts} +6 -2
  352. package/scripts/run/{run-ship-probe.ts → ship/run-ship-probe.ts} +2 -2
  353. package/scripts/run/{run-ship-return.ts → ship/run-ship-return.ts} +4 -3
  354. package/scripts/run/{run-ship-review-steps.ts → ship/run-ship-review-steps.ts} +3 -3
  355. package/scripts/run/{run-ship-scoped.ts → ship/run-ship-scoped.ts} +10 -1
  356. package/scripts/run/{run-ship-steps.ts → ship/run-ship-steps.ts} +11 -12
  357. package/scripts/run/ship/run-ship-stop-text.ts +13 -0
  358. package/scripts/run/{run-ship-sync.ts → ship/run-ship-sync.ts} +25 -11
  359. package/scripts/run/{run-tidy-lanes.ts → tidy/run-tidy-lanes.ts} +1 -1
  360. package/scripts/run/{run-wake-cli.ts → wake/run-wake-cli.ts} +23 -8
  361. package/scripts/run/{run-wake-describe.ts → wake/run-wake-describe.ts} +3 -3
  362. package/scripts/run/{run-wake-driver.ts → wake/run-wake-driver.ts} +59 -8
  363. package/scripts/run/{run-wake-handoff.ts → wake/run-wake-handoff.ts} +1 -1
  364. package/scripts/run/{run-wake-loop.ts → wake/run-wake-loop.ts} +8 -2
  365. package/scripts/run/wake/run-wake-restart.ts +58 -0
  366. package/scripts/run/{run-wake-session.ts → wake/run-wake-session.ts} +3 -3
  367. package/scripts/run/{run-wake.ts → wake/run-wake.ts} +1 -1
  368. package/scripts/safe-chain/preinstall-command.ts +20 -21
  369. package/scripts/safe-chain/project-config.ts +19 -15
  370. package/scripts/sync/sync-ai-files.ts +1 -1
  371. package/scripts/sync/sync-configs.ts +2 -1
  372. package/scripts/sync/sync.ts +15 -2
  373. package/scripts/test/unit-worker-share.ts +1 -0
  374. package/scripts/time-runtime/time-background.ts +5 -1
  375. package/scripts/time-runtime/time-instant.ts +3 -1
  376. package/scripts/time-runtime/time-spans.ts +6 -139
  377. package/scripts/time-runtime/time-tool-call.ts +160 -0
  378. package/scripts/version/effective-upstream.ts +2 -20
  379. package/scripts/version/latest-corepack.ts +17 -17
  380. package/scripts/version/latest-regression.ts +1 -1
  381. package/scripts/version/latest-update.ts +4 -4
  382. package/scripts/version/npm-registry.ts +20 -5
  383. package/scripts/version/publishable-range-check.ts +2 -2
  384. package/scripts/version/publishable-range.ts +1 -1
  385. package/scripts/version/release-age.ts +48 -38
  386. package/scripts/version/release-hold.ts +1 -1
  387. package/scripts/version/safe-chain-version-update.ts +40 -0
  388. package/scripts/version/upgrade-shell-command.ts +48 -8
  389. package/scripts/version/version-check-logic.ts +23 -14
  390. package/scripts/version/version-commands.ts +23 -11
  391. package/scripts/version/version-remote.ts +28 -13
  392. package/templates/pnpm-workspace.basic.yaml +4 -0
  393. package/templates/workflows/dependabot-auto-merge.yml +5 -5
  394. package/templates/workflows/github-release.yml +2 -0
  395. package/scripts/build/build-config-merge.ts +0 -27
  396. package/scripts/build/build-managed-marker.ts +0 -27
  397. package/scripts/build/build-self-sync-guard.ts +0 -27
  398. package/scripts/build/build-version.ts +0 -26
  399. package/scripts/version/preinstall-version-update.ts +0 -86
  400. /package/scripts/git/{schemas.ts → git-schemas.ts} +0 -0
  401. /package/scripts/overrides/{schemas.ts → overrides-schemas.ts} +0 -0
  402. /package/scripts/run/{run-carry-conversation.ts → carry/run-carry-conversation.ts} +0 -0
  403. /package/scripts/run/{run-carry-reclaim.ts → carry/run-carry-reclaim.ts} +0 -0
  404. /package/scripts/run/{run-carry-stash.ts → carry/run-carry-stash.ts} +0 -0
  405. /package/scripts/run/{run-carry-streak.ts → carry/run-carry-streak.ts} +0 -0
  406. /package/scripts/run/{run-cut-handoff.ts → cut/run-cut-handoff.ts} +0 -0
  407. /package/scripts/run/{run-cut-report.ts → cut/run-cut-report.ts} +0 -0
  408. /package/scripts/run/{run-entry-stop.ts → entry/run-entry-stop.ts} +0 -0
  409. /package/scripts/run/{run-event-cli.ts → event/run-event-cli.ts} +0 -0
  410. /package/scripts/run/{run-event-follow.ts → event/run-event-follow.ts} +0 -0
  411. /package/scripts/run/{run-event-render.ts → event/run-event-render.ts} +0 -0
  412. /package/scripts/run/{run-event-watch.ts → event/run-event-watch.ts} +0 -0
  413. /package/scripts/run/{run-hold.ts → hold/run-hold.ts} +0 -0
  414. /package/scripts/run/{run-progress-args.ts → progress/run-progress-args.ts} +0 -0
  415. /package/scripts/run/{run-progress-clock.ts → progress/run-progress-clock.ts} +0 -0
  416. /package/scripts/run/{run-review-cli.ts → review/run-review-cli.ts} +0 -0
  417. /package/scripts/run/{run-review.ts → review/run-review.ts} +0 -0
  418. /package/scripts/run/{run-ship-next.ts → ship/run-ship-next.ts} +0 -0
  419. /package/scripts/run/{run-ship-pre-detach.ts → ship/run-ship-pre-detach.ts} +0 -0
  420. /package/scripts/run/{run-ship-review.ts → ship/run-ship-review.ts} +0 -0
  421. /package/scripts/run/{run-ship-stage.ts → ship/run-ship-stage.ts} +0 -0
  422. /package/scripts/run/{run-ship.ts → ship/run-ship.ts} +0 -0
  423. /package/scripts/run/{run-tidy-cli.ts → tidy/run-tidy-cli.ts} +0 -0
  424. /package/scripts/run/{run-tidy-stashes.ts → tidy/run-tidy-stashes.ts} +0 -0
  425. /package/scripts/run/{run-tidy.ts → tidy/run-tidy.ts} +0 -0
@@ -1,11 +1,13 @@
1
+ import {
2
+ error_text
3
+ } from "./chunk-CDY4NFQG.js";
1
4
  import {
2
5
  lane_child_marker,
3
6
  run_issue_number
4
- } from "./chunk-32GQTL4F.js";
7
+ } from "./chunk-6HJJXRBX.js";
5
8
  import {
6
9
  CHECK_STATUS_FAIL,
7
10
  CHECK_STATUS_PENDING,
8
- PLATFORM_TEMP_ROOT,
9
11
  PrConflictError,
10
12
  blocking_issue_schema,
11
13
  cost_blocks,
@@ -21,19 +23,27 @@ import {
21
23
  json_value,
22
24
  lane_paths,
23
25
  parse_pr_state_snapshot,
26
+ process_identity,
27
+ process_owner_schema,
24
28
  read_string,
25
29
  rest_comment_schema,
26
- stamp_file,
27
30
  time_density_hook,
28
31
  time_shell,
29
32
  time_transcript_line
30
- } from "./chunk-S6X6WYKR.js";
33
+ } from "./chunk-55HHG5PX.js";
31
34
  import {
32
35
  ENV_FILE_NAME,
33
36
  LANE_SEAT_KEY,
34
37
  PORT_SEED_KEY,
35
38
  ports
36
39
  } from "./chunk-RKUAD3I6.js";
40
+ import {
41
+ COMMAND_TIMEOUT_MS,
42
+ GIT_TIMEOUT_MS,
43
+ PLATFORM_TEMP_ROOT,
44
+ PROBE_TIMEOUT_MS,
45
+ stamp_file
46
+ } from "./chunk-ELCN5LCH.js";
37
47
 
38
48
  // scripts/lib/bounded-pool.ts
39
49
  function pool_width(limit, total) {
@@ -157,8 +167,8 @@ function current_turn(tail) {
157
167
  function turn_filing_count(tail) {
158
168
  return prior_filing_count(current_turn(tail));
159
169
  }
160
- function decide(_call, run3) {
161
- return prior_filing_count(time_density_hook.read_tail(run3.transcript)) >= CAP_REACHED;
170
+ function decide(_call, run4) {
171
+ return prior_filing_count(time_density_hook.read_tail(run4.transcript)) >= CAP_REACHED;
162
172
  }
163
173
  var FILING_CAP_REASON = `\u26D4 filing cap: this run has already filed ${String(FILING_CAP)} Issues, the per-run ceiling \u2014 on reaching it, stop and report rather than filing more. Automatic filing is capped so a run cannot manufacture Issues faster than they can be closed (\`.claude/skills/workflow-commands/SKILL.md\` \u2192 \`prerequisite.md\`, \`observation-filing.md\`). A further Issue that genuinely must exist is a person's call, not this run's. **This rule fires on every filing past the cap, not once per run**, so reissuing the same filing will be refused again.`;
164
174
  var ROW = {
@@ -183,17 +193,13 @@ var PORCELAIN_FLAG = "--porcelain";
183
193
  var UNTRACKED_FILES_FLAG = "--untracked-files=all";
184
194
  var GIT_BINARY_KEY = "JOSH_GIT_BINARY";
185
195
  function get_git_command() {
186
- if (platform() === "win32") {
187
- return String.raw`"C:\Program Files\Git\cmd\git.exe"`;
188
- }
196
+ if (platform() === "win32") return String.raw`"C:\Program Files\Git\cmd\git.exe"`;
189
197
  return GIT_COMMAND_UNIX;
190
198
  }
191
199
  function get_git_command_for_spawn() {
192
200
  const binary = process.env[GIT_BINARY_KEY];
193
201
  if (binary !== void 0 && binary !== "") return binary;
194
- if (platform() === "win32") {
195
- return String.raw`C:\Program Files\Git\cmd\git.exe`;
196
- }
202
+ if (platform() === "win32") return String.raw`C:\Program Files\Git\cmd\git.exe`;
197
203
  return GIT_COMMAND_UNIX;
198
204
  }
199
205
  var git_utilities = {
@@ -201,6 +207,9 @@ var git_utilities = {
201
207
  get_git_command_for_spawn
202
208
  };
203
209
 
210
+ // scripts/git/git-spawn.ts
211
+ import { execa as execa3 } from "execa";
212
+
204
213
  // scripts/git/git-execa-error.ts
205
214
  function get_exit_code(error) {
206
215
  if (typeof error !== "object" || error === null) return void 0;
@@ -300,7 +309,6 @@ var git_push_transport = {
300
309
  };
301
310
 
302
311
  // scripts/git/git-spawn.ts
303
- import { execa as execa3 } from "execa";
304
312
  async function read(arguments_) {
305
313
  const git_cmd = git_utilities.get_git_command_for_spawn();
306
314
  const { stdout } = await execa3(git_cmd, arguments_);
@@ -352,73 +360,7 @@ var git_spawn = {
352
360
  with_output_remote
353
361
  };
354
362
 
355
- // scripts/lib/spawn-exit.ts
356
- function read_spawn_stdout(result) {
357
- return result.stdout ?? "";
358
- }
359
- function read_spawn_stderr(result) {
360
- return result.stderr ?? "";
361
- }
362
-
363
- // scripts/git/git-spawn-sync.ts
364
- import { execaSync } from "execa";
365
- var GIT_TIMEOUT_MS = 1e4;
366
- var SUCCESS_EXIT_CODE = 0;
367
- var C_LOCALE = { LC_ALL: "C", LANGUAGE: "C" };
368
- function run(args, options = {}) {
369
- const result = execaSync(git_utilities.get_git_command_for_spawn(), args, {
370
- ...options,
371
- extendEnv: true,
372
- reject: false,
373
- timeout: options.timeout ?? GIT_TIMEOUT_MS
374
- });
375
- return {
376
- exit_code: result.exitCode,
377
- stdout: read_spawn_stdout(result),
378
- stderr: read_spawn_stderr(result)
379
- };
380
- }
381
- function read2(args, options = {}) {
382
- const result = run(args, options);
383
- return result.exit_code === SUCCESS_EXIT_CODE ? result.stdout.trim() : void 0;
384
- }
385
- function origin_url(cwd) {
386
- return read2(["config", "--get", "remote.origin.url"], { cwd });
387
- }
388
- function toplevel(timeout = GIT_TIMEOUT_MS) {
389
- return run(["rev-parse", "--show-toplevel"], { env: C_LOCALE, timeout });
390
- }
391
- var git_spawn_sync = { GIT_TIMEOUT_MS, C_LOCALE, run, read: read2, origin_url, toplevel };
392
-
393
- // scripts/git/git-command.ts
394
- async function branch() {
395
- return await git_spawn.read(["rev-parse", "--abbrev-ref", "HEAD"]);
396
- }
397
- async function status(directory) {
398
- const location = directory === void 0 ? [] : ["-C", directory];
399
- return await git_spawn.read([...location, "status", PORCELAIN_FLAG, UNTRACKED_FILES_FLAG]);
400
- }
401
- async function repository_root() {
402
- const result = git_spawn_sync.toplevel();
403
- if (result.exit_code !== 0) throw create_spawn_error("rev-parse", result.exit_code);
404
- return result.stdout.trim();
405
- }
406
- async function head_commit() {
407
- return await git_spawn.read(["rev-parse", "HEAD"]);
408
- }
409
- var GIT_DIRECTORY_ARGUMENTS = [
410
- "rev-parse",
411
- "--absolute-git-dir",
412
- "--path-format=absolute",
413
- "--git-common-dir"
414
- ];
415
- async function git_directories() {
416
- const output = await git_spawn.read([...GIT_DIRECTORY_ARGUMENTS]);
417
- return output.split("\n").filter((line) => line !== "");
418
- }
419
- async function diff_cached(file_path) {
420
- return await git_spawn.read(["diff", "--cached", file_path]);
421
- }
363
+ // scripts/git/git-diff-reads.ts
422
364
  var REFS_REMOTES_ORIGIN_PREFIX = "refs/remotes/origin/";
423
365
  var NAME_ONLY_FLAG = "--name-only";
424
366
  var DEFAULT_BRANCH_FALLBACK = "main";
@@ -507,6 +449,164 @@ async function untracked_names() {
507
449
  WHOLE_TREE_PATHSPEC
508
450
  ]);
509
451
  }
452
+ var git_diff_reads = {
453
+ change_base,
454
+ change_base_commit,
455
+ default_branch_reference,
456
+ diff_cached_names,
457
+ diff_main,
458
+ diff_main_names,
459
+ diff_main_numstat,
460
+ get_default_branch,
461
+ untracked_names
462
+ };
463
+
464
+ // scripts/git/git-pre-push-hook.ts
465
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
466
+ import { tmpdir } from "node:os";
467
+ import path from "node:path";
468
+ var REMOTE = "origin";
469
+ var HOOK_NAME = "pre-push";
470
+ var PROBE_HOOK_NAME = "kit-hook-run-probe";
471
+ var ALLOW_UNKNOWN_HOOK_NAME_FLAG = "--allow-unknown-hook-name";
472
+ var HOOK_RUN = "run";
473
+ var STDIN_FILE = "refs";
474
+ var TEMPORARY_PREFIX = "kit-pre-push-";
475
+ var ZERO_DIGIT = "0";
476
+ async function read_remote_oid(branch2) {
477
+ try {
478
+ return await git_spawn.read([
479
+ "rev-parse",
480
+ "--verify",
481
+ "--quiet",
482
+ `refs/remotes/${REMOTE}/${branch2}`
483
+ ]);
484
+ } catch {
485
+ return void 0;
486
+ }
487
+ }
488
+ async function read_push_references() {
489
+ const [branch2, local_oid] = await Promise.all([
490
+ git_spawn.read(["rev-parse", "--abbrev-ref", "HEAD"]),
491
+ git_spawn.read(["rev-parse", "HEAD"])
492
+ ]);
493
+ return { branch: branch2, local_oid, remote_oid: await read_remote_oid(branch2) };
494
+ }
495
+ function to_stdin_line(references) {
496
+ const reference2 = `refs/heads/${references.branch}`;
497
+ const remote_oid = references.remote_oid ?? ZERO_DIGIT.repeat(references.local_oid.length);
498
+ return `${reference2} ${references.local_oid} ${reference2} ${remote_oid}
499
+ `;
500
+ }
501
+ function to_hook_run_arguments(stdin_path, hook_name) {
502
+ return [HOOK_RUN, "--ignore-missing", `--to-stdin=${stdin_path}`, hook_name];
503
+ }
504
+ async function can_probe(probe_arguments) {
505
+ try {
506
+ await git_spawn.read(["hook", ...probe_arguments]);
507
+ return true;
508
+ } catch {
509
+ return false;
510
+ }
511
+ }
512
+ async function can_run_hooks(stdin_path) {
513
+ const [, ...options] = to_hook_run_arguments(stdin_path, PROBE_HOOK_NAME);
514
+ if (await can_probe([HOOK_RUN, ALLOW_UNKNOWN_HOOK_NAME_FLAG, ...options])) return true;
515
+ return await can_probe([HOOK_RUN, ...options]);
516
+ }
517
+ async function run_with_stdin(stdin_line) {
518
+ const directory = await mkdtemp(path.join(tmpdir(), TEMPORARY_PREFIX));
519
+ const stdin_path = path.join(directory, STDIN_FILE);
520
+ try {
521
+ await writeFile(stdin_path, stdin_line);
522
+ if (!await can_run_hooks(stdin_path)) return false;
523
+ const url = await git_spawn.read(["remote", "get-url", REMOTE]);
524
+ await git_spawn.with_output("hook", [
525
+ ...to_hook_run_arguments(stdin_path, HOOK_NAME),
526
+ "--",
527
+ REMOTE,
528
+ url
529
+ ]);
530
+ return true;
531
+ } finally {
532
+ await rm(directory, { force: true, recursive: true });
533
+ }
534
+ }
535
+ async function run() {
536
+ const references = await read_push_references();
537
+ if (references.local_oid === references.remote_oid) return true;
538
+ return await run_with_stdin(to_stdin_line(references));
539
+ }
540
+ var git_pre_push_hook = {
541
+ run
542
+ };
543
+
544
+ // scripts/lib/spawn-exit.ts
545
+ function read_spawn_stdout(result) {
546
+ return result.stdout ?? "";
547
+ }
548
+ function read_spawn_stderr(result) {
549
+ return result.stderr ?? "";
550
+ }
551
+
552
+ // scripts/git/git-spawn-sync.ts
553
+ import { execaSync } from "execa";
554
+ var SUCCESS_EXIT_CODE = 0;
555
+ var C_LOCALE = { LC_ALL: "C", LANGUAGE: "C" };
556
+ function run2(args, options = {}) {
557
+ const result = execaSync(git_utilities.get_git_command_for_spawn(), args, {
558
+ ...options,
559
+ extendEnv: true,
560
+ reject: false,
561
+ timeout: options.timeout ?? GIT_TIMEOUT_MS
562
+ });
563
+ return {
564
+ exit_code: result.exitCode,
565
+ stdout: read_spawn_stdout(result),
566
+ stderr: read_spawn_stderr(result)
567
+ };
568
+ }
569
+ function read2(args, options = {}) {
570
+ const result = run2(args, options);
571
+ return result.exit_code === SUCCESS_EXIT_CODE ? result.stdout.trim() : void 0;
572
+ }
573
+ function origin_url(cwd) {
574
+ return read2(["config", "--get", "remote.origin.url"], { cwd });
575
+ }
576
+ function toplevel(timeout = GIT_TIMEOUT_MS) {
577
+ return run2(["rev-parse", "--show-toplevel"], { env: C_LOCALE, timeout });
578
+ }
579
+ var git_spawn_sync = { GIT_TIMEOUT_MS, C_LOCALE, run: run2, read: read2, origin_url, toplevel };
580
+
581
+ // scripts/git/git-command.ts
582
+ async function branch() {
583
+ return await git_spawn.read(["rev-parse", "--abbrev-ref", "HEAD"]);
584
+ }
585
+ async function status(directory) {
586
+ const location = directory === void 0 ? [] : ["-C", directory];
587
+ return await git_spawn.read([...location, "status", PORCELAIN_FLAG, UNTRACKED_FILES_FLAG]);
588
+ }
589
+ async function repository_root() {
590
+ const result = git_spawn_sync.toplevel();
591
+ if (result.exit_code !== 0) throw create_spawn_error("rev-parse", result.exit_code);
592
+ return result.stdout.trim();
593
+ }
594
+ async function head_commit() {
595
+ return await git_spawn.read(["rev-parse", "HEAD"]);
596
+ }
597
+ var GIT_DIRECTORY_ARGUMENTS = [
598
+ "rev-parse",
599
+ "--absolute-git-dir",
600
+ "--path-format=absolute",
601
+ "--git-common-dir"
602
+ ];
603
+ async function git_directories() {
604
+ const output = await git_spawn.read([...GIT_DIRECTORY_ARGUMENTS]);
605
+ return output.split("\n").filter((line) => line !== "");
606
+ }
607
+ async function diff_cached(file_path) {
608
+ return await git_spawn.read(["diff", "--cached", file_path]);
609
+ }
510
610
  async function fetch_branch(branch_name) {
511
611
  const refspec = `+refs/heads/${branch_name}:refs/remotes/origin/${branch_name}`;
512
612
  return await git_spawn.read(["fetch", "origin", refspec]);
@@ -548,16 +648,18 @@ function is_upstream_not_set_error(error) {
548
648
  const { cause } = error;
549
649
  return cause !== void 0 && is_exit_code_128(cause);
550
650
  }
551
- async function push_with_upstream(branch_name) {
552
- await git_push_transport.push(["--set-upstream", "origin", branch_name]);
651
+ var NO_VERIFY_FLAG = "--no-verify";
652
+ async function push_with_upstream(branch_name, verify_flags) {
653
+ await git_push_transport.push([...verify_flags, "--set-upstream", "origin", branch_name]);
553
654
  }
554
655
  async function push2() {
656
+ const verify_flags = await git_pre_push_hook.run() ? [NO_VERIFY_FLAG] : [];
555
657
  try {
556
- await git_push_transport.push([]);
658
+ await git_push_transport.push([...verify_flags]);
557
659
  } catch (error) {
558
660
  if (is_upstream_not_set_error(error)) {
559
661
  const current_branch = await branch();
560
- await push_with_upstream(current_branch);
662
+ await push_with_upstream(current_branch, verify_flags);
561
663
  return;
562
664
  }
563
665
  throw error;
@@ -642,15 +744,9 @@ var git_command = {
642
744
  head_commit,
643
745
  git_directories,
644
746
  diff_cached,
645
- diff_cached_names,
646
- diff_main,
647
- change_base,
648
- change_base_commit,
649
- diff_main_names,
650
- diff_main_numstat,
651
- untracked_names,
652
- get_default_branch,
653
- default_branch_reference,
747
+ // The default branch, the change base and every reading against it are `git-diff-reads.ts`'s
748
+ // (joshuafolkken/kit#3264), re-exported here so no call site, mock or spy moved with them.
749
+ ...git_diff_reads,
654
750
  fetch_branch,
655
751
  merge_fast_forward,
656
752
  fast_forward_local,
@@ -674,19 +770,7 @@ var git_command = {
674
770
  is_upstream_not_set_error
675
771
  };
676
772
 
677
- // scripts/lib/error-message.ts
678
- function message_of(error) {
679
- return error instanceof Error ? error.message : String(error);
680
- }
681
- var DEBUG_ENV_KEY = "JOSH_DEBUG";
682
- function trace_swallowed(where, error) {
683
- if ((process.env[DEBUG_ENV_KEY] ?? "").trim() === "") return;
684
- process.stderr.write(`josh debug: ${where}: ${message_of(error)}
685
- `);
686
- }
687
- var error_text = { message_of, trace_swallowed };
688
-
689
- // scripts/run/run-hold.ts
773
+ // scripts/run/hold/run-hold.ts
690
774
  import { z } from "zod";
691
775
  var HOLD_PREFIX = "josh-run-hold-";
692
776
  var UNNUMBERED_ISSUE = "new";
@@ -986,18 +1070,18 @@ function trimmed(value) {
986
1070
  const result = value?.trim();
987
1071
  return result === void 0 || result.length === EMPTY_LENGTH ? void 0 : result;
988
1072
  }
989
- function override_value(role, field, environment2) {
1073
+ function override_value(role, field, environment3) {
990
1074
  const key2 = ENV_KEYS[role][field];
991
- const value = trimmed(environment2[key2]);
1075
+ const value = trimmed(environment3[key2]);
992
1076
  if (value !== void 0) return { key: key2, value };
993
1077
  if (role !== WORKER) return { key: key2, value: void 0 };
994
1078
  const legacy = LEGACY_WORKER_KEYS[field];
995
- const legacy_value = trimmed(environment2[legacy]);
1079
+ const legacy_value = trimmed(environment3[legacy]);
996
1080
  return legacy_value === void 0 ? { key: key2, value: void 0 } : { key: legacy, value: legacy_value };
997
1081
  }
998
- function model_override(role, environment2, provider) {
1082
+ function model_override(role, environment3, provider) {
999
1083
  const key2 = ENV_KEYS[role].model;
1000
- return provider === OPENAI_PROVIDER ? { key: key2, value: void 0 } : override_value(role, "model", environment2);
1084
+ return provider === OPENAI_PROVIDER ? { key: key2, value: void 0 } : override_value(role, "model", environment3);
1001
1085
  }
1002
1086
  function rejection(key2, value, expected) {
1003
1087
  return { kind: "rejected", note: `${key2}=${value} ${expected}, so the agent was not started` };
@@ -1006,35 +1090,35 @@ function resolved_effort(override, fallback) {
1006
1090
  const parsed = EFFORT_SCHEMA.safeParse(override.value ?? fallback);
1007
1091
  return parsed.success ? { kind: "effort", effort: parsed.data } : rejection(override.key, override.value ?? "", "is not an allowed effort");
1008
1092
  }
1009
- function has_session(environment2, keys) {
1010
- return keys.some((key2) => trimmed(environment2[key2]) !== void 0);
1093
+ function has_session(environment3, keys) {
1094
+ return keys.some((key2) => trimmed(environment3[key2]) !== void 0);
1011
1095
  }
1012
1096
  function session_rejection(is_conflicting) {
1013
1097
  const note = is_conflicting ? "both Codex and Claude Code sessions were detected" : "no Codex or Claude Code session was detected";
1014
1098
  return { kind: "rejected", note };
1015
1099
  }
1016
1100
  var HANDED_PROVIDER_KEY = "JOSH_AGENT_PROVIDER";
1017
- function handed_provider(environment2) {
1018
- const value = trimmed(environment2[HANDED_PROVIDER_KEY]);
1101
+ function handed_provider(environment3) {
1102
+ const value = trimmed(environment3[HANDED_PROVIDER_KEY]);
1019
1103
  if (value === void 0) return session_rejection(false);
1020
1104
  const parsed = PROVIDER_SCHEMA.safeParse(value);
1021
1105
  return parsed.success ? { kind: "provider", provider: parsed.data } : rejection(HANDED_PROVIDER_KEY, value, "is not an allowed provider");
1022
1106
  }
1023
- function detected_provider(environment2) {
1024
- const has_codex = has_session(environment2, [CODEX_SESSION_KEY]);
1025
- const has_claude = has_session(environment2, agent_session_environment.PARENT_SESSION_KEYS);
1107
+ function detected_provider(environment3) {
1108
+ const has_codex = has_session(environment3, [CODEX_SESSION_KEY]);
1109
+ const has_claude = has_session(environment3, agent_session_environment.PARENT_SESSION_KEYS);
1026
1110
  if (has_codex === has_claude) return has_codex ? session_rejection(true) : void 0;
1027
1111
  return { kind: "provider", provider: has_codex ? OPENAI_PROVIDER : ANTHROPIC_PROVIDER };
1028
1112
  }
1029
- function resolve_provider(environment2 = process.env) {
1030
- return detected_provider(environment2) ?? handed_provider(environment2);
1113
+ function resolve_provider(environment3 = process.env) {
1114
+ return detected_provider(environment3) ?? handed_provider(environment3);
1031
1115
  }
1032
- function has_completion_callback(environment2 = process.env) {
1033
- const selected = resolve_provider(environment2);
1116
+ function has_completion_callback(environment3 = process.env) {
1117
+ const selected = resolve_provider(environment3);
1034
1118
  return selected.kind !== "provider" || selected.provider !== OPENAI_PROVIDER;
1035
1119
  }
1036
- function handoff_environment(environment2 = process.env) {
1037
- const selected = resolve_provider(environment2);
1120
+ function handoff_environment(environment3 = process.env) {
1121
+ const selected = resolve_provider(environment3);
1038
1122
  return selected.kind === "provider" ? { [HANDED_PROVIDER_KEY]: selected.provider } : {};
1039
1123
  }
1040
1124
  function validate(profile, model_key) {
@@ -1048,19 +1132,19 @@ function phase_effort(role, phase, fallback) {
1048
1132
  if (!parsed.success) return fallback;
1049
1133
  return PHASE_EFFORT[role]?.[parsed.data] ?? fallback;
1050
1134
  }
1051
- function overridden_effort(profile, phase, environment2) {
1052
- const parsed = EFFORT_SCHEMA.safeParse(override_value(profile.role, "effort", environment2).value);
1135
+ function overridden_effort(profile, phase, environment3) {
1136
+ const parsed = EFFORT_SCHEMA.safeParse(override_value(profile.role, "effort", environment3).value);
1053
1137
  return parsed.success ? parsed.data : phase_effort(profile.role, phase, profile.effort);
1054
1138
  }
1055
- function with_phase_effort(profile, phase, environment2 = process.env) {
1056
- return { ...profile, effort: overridden_effort(profile, phase, environment2) };
1139
+ function with_phase_effort(profile, phase, environment3 = process.env) {
1140
+ return { ...profile, effort: overridden_effort(profile, phase, environment3) };
1057
1141
  }
1058
- function resolve(role, environment2 = process.env, phase) {
1059
- const selected = resolve_provider(environment2);
1142
+ function resolve(role, environment3 = process.env, phase) {
1143
+ const selected = resolve_provider(environment3);
1060
1144
  if (selected.kind === "rejected") return selected;
1061
1145
  const defaults = PROVIDER_PROFILES[selected.provider][role];
1062
- const model = model_override(role, environment2, selected.provider);
1063
- const effort = override_value(role, "effort", environment2);
1146
+ const model = model_override(role, environment3, selected.provider);
1147
+ const effort = override_value(role, "effort", environment3);
1064
1148
  const resolved = resolved_effort(effort, phase_effort(role, phase, defaults.effort));
1065
1149
  if (resolved.kind === "rejected") return resolved;
1066
1150
  const profile = {
@@ -1371,7 +1455,7 @@ var git_location_environment = { clear_git_location_variables, location_free_env
1371
1455
  // scripts/git/git-common-directory.ts
1372
1456
  var OWN_GIT_DIRECTORY = 0;
1373
1457
  var COMMON_GIT_DIRECTORY = 1;
1374
- var PROBE_TIMEOUT_MS = 5e3;
1458
+ var PROBE_TIMEOUT_MS2 = 5e3;
1375
1459
  var answers = /* @__PURE__ */ new Map();
1376
1460
  function probe_environment(cwd) {
1377
1461
  if (cwd === void 0) return process.env;
@@ -1392,7 +1476,7 @@ function read_directories(cwd) {
1392
1476
  env: probe_environment(cwd),
1393
1477
  encoding: "utf8",
1394
1478
  stdio: ["ignore", "pipe", "ignore"],
1395
- timeout: PROBE_TIMEOUT_MS
1479
+ timeout: PROBE_TIMEOUT_MS2
1396
1480
  }
1397
1481
  );
1398
1482
  return output.split("\n").filter((line) => line !== "");
@@ -1424,7 +1508,7 @@ function resolve2(cwd) {
1424
1508
  }
1425
1509
  var git_common_directory = { directories, own, repository, resolve: resolve2, select_linked };
1426
1510
 
1427
- // scripts/run/run-ship-stage.ts
1511
+ // scripts/run/ship/run-ship-stage.ts
1428
1512
  import { z as z3 } from "zod";
1429
1513
  var STAGE = {
1430
1514
  PREFLIGHT: "preflight",
@@ -1520,7 +1604,7 @@ var run_ship_stage = {
1520
1604
  stop_reason: stop_reason2
1521
1605
  };
1522
1606
 
1523
- // scripts/run/run-ship-next.ts
1607
+ // scripts/run/ship/run-ship-next.ts
1524
1608
  var { STAGE: STAGE2 } = run_ship_stage;
1525
1609
  var COMMAND = {
1526
1610
  LOG: "pnpm josh ship --log",
@@ -1607,10 +1691,10 @@ var lane_child_invocation = {
1607
1691
  ship_stop_invocation
1608
1692
  };
1609
1693
 
1610
- // scripts/run/run-cut.ts
1694
+ // scripts/run/cut/run-cut.ts
1611
1695
  import { z as z5 } from "zod";
1612
1696
 
1613
- // scripts/run/run-cut-handoff.ts
1697
+ // scripts/run/cut/run-cut-handoff.ts
1614
1698
  import { readFileSync } from "node:fs";
1615
1699
  import { z as z4 } from "zod";
1616
1700
  var handoff_schema = z4.object({
@@ -1689,7 +1773,7 @@ var run_cut_handoff = {
1689
1773
  read_handoff_file
1690
1774
  };
1691
1775
 
1692
- // scripts/run/run-cut.ts
1776
+ // scripts/run/cut/run-cut.ts
1693
1777
  var CUT_PREFIX = "josh-run-cut-";
1694
1778
  var { PRE_GATE_PHASE: PRE_GATE_PHASE2, IMPLEMENTATION_PHASE: IMPLEMENTATION_PHASE2 } = agent_role_profile;
1695
1779
  var IMPLEMENTATION_CONTEXT_THRESHOLD = CONTEXT_CUT_THRESHOLD;
@@ -1888,7 +1972,7 @@ var run_cut = {
1888
1972
  worktree_git_directory_sync
1889
1973
  };
1890
1974
 
1891
- // scripts/rules/run-tail.ts
1975
+ // scripts/rules/run-tail-rule.ts
1892
1976
  var SEGMENT_PREFIX = String.raw`(?:\(\s*)?(?:[A-Za-z_][A-Za-z0-9_]*=\S*\s+)*(?:npx\s+|pnpm\s+(?:exec\s+|run\s+)?)?`;
1893
1977
  var WORD_END = String.raw`(?=\s|$|\))`;
1894
1978
  var PUSH_STEP_SEGMENT = new RegExp(String.raw`^${SEGMENT_PREFIX}josh\s+(?:git|g)${WORD_END}`, "u");
@@ -1928,7 +2012,7 @@ function decide3() {
1928
2012
  return true;
1929
2013
  }
1930
2014
  var RUN_TAIL_REASON = '\u26D4 run tail: this issues the commit-push-PR step in the foreground, where the harness decides when to stop waiting. Reissue it with `run_in_background` set. In `fullrun #1501` this call was given a 900-second timeout, the harness detached it at its own 600-second cap, and nothing read the output for a further 6m28s \u2014 45m03s of wall clock on about 17 minutes of work (joshuafolkken/kit#1510). **Never give a foreground call a timeout above the harness cap**: the cap decides, not the number. A backgrounded call re-invokes you when it exits, so the completion notification is what resumes the run. **When it arrives, the turn that reads it goes straight through any branch-2 filing and `pnpm josh epic:bundle` to `pnpm josh followup` \u2014 the turn never ends at the push.** CI went green 6m06s before the merge started in that run, and it started only because the person asked; joshuafolkken/kit#1333 had already settled that the merge is issued in the turn the review closes. While the push runs, do the work that writes nothing \u2014 drafting the completion body to a file, deciding the branch-2 disposition. `pnpm josh followup` itself stays in the **foreground** \u2014 nearly every step after it reads its result. But a tail does follow the merge, measured at 3.0 min and 5.9% of a run (joshuafolkken/kit#1462), so empty it beforehand: the steps that read the merge result stay after `followup`, and the rest are composed in the turn that issues it, bar the one exception background-commands.md names. The procedure is `.claude/skills/workflow-commands/background-commands.md`, "A command that can take minutes is issued in the background". **This rule fires on every foreground push, not once per run**, so reissuing the same call in the foreground will be refused again.';
1931
- var run_tail = {
2015
+ var run_tail_rule = {
1932
2016
  RUN_TAIL_REASON,
1933
2017
  decide: decide3,
1934
2018
  is_backgrounded_push_step,
@@ -1965,7 +2049,7 @@ function is_backgrounded_ship(call) {
1965
2049
  return command !== void 0 && ships_alone(command);
1966
2050
  }
1967
2051
  function is_candidate(call) {
1968
- if (run_tail.is_push_step_call(call)) return true;
2052
+ if (run_tail_rule.is_push_step_call(call)) return true;
1969
2053
  const command = backgrounded_bash_command(call);
1970
2054
  if (command === void 0 || is_backgrounded_ship(call)) return false;
1971
2055
  return long_commands_of(command).length > 0;
@@ -1986,344 +2070,41 @@ function unfinished_ids(tail, launched_ids) {
1986
2070
  const launched2 = blocks.flatMap((block) => launched_ids(block));
1987
2071
  return launched2.filter((id) => id !== "" && !finished.has(id));
1988
2072
  }
1989
- function pending_background_ids(tail) {
1990
- return unfinished_ids(tail, (block) => [block.background_id, block.agent_id]);
1991
- }
1992
- function pending_agent_ids(tail) {
1993
- return unfinished_ids(tail, (block) => [block.agent_id]);
1994
- }
1995
- var LANE_BACKGROUND_REASON = '\u26D4 lane background: this session is a dispatched lane child (`JOSH_LANE_CHILD`), a headless `claude -p` process whose background Bash tasks are killed when the turn ends \u2014 so a backgrounded `josh gate` / `josh git` / `josh followup` / `josh ship` never re-invokes you; it dies at `exit code 143` (joshuafolkken/kit#2704, measured on the #2606 child: implementation, review and live verification done, the run parked instead of merged). Hand the gate-to-merge region to the detached supervisor instead: `pnpm josh ship --detach --review "<title> #<N>"` (add `--cite <N>`) issued in the foreground \u2014 its preflight runs in this process before the supervisor exists, so a backgrounded `ship` dies with the turn (joshuafolkken/kit#3027; a backgrounded `ship` issued alone is moved to the foreground for you, joshuafolkken/kit#3154) \u2014 then end the turn on `launched` / `busy`. `.claude/skills/workflow-commands/chain-rule.md` step 0 is the single source. A single check you must read before continuing runs in the foreground within the tool timeout; the commit-push step does not \u2014 in a child it too belongs to the detached ship, in either spelling. This rule fires on every occurrence, not once per run.';
1996
- var LANE_BACKGROUND_STOP_REASON = "\u26D4 lane background stop: this is a dispatched lane child (`JOSH_LANE_CHILD`) and a background task it launched has not finished \u2014 ending this headless turn kills it, and nothing re-invokes you afterwards (joshuafolkken/kit#2704). Do not send a notification and do not stop: wait for the task in the foreground and act on its result, or re-issue the work through `pnpm josh ship --detach`, whose supervisor outlives the turn (`.claude/skills/workflow-commands/chain-rule.md` step 0). Do not repeat your previous reply.";
1997
- var ROW2 = {
1998
- id: "lane-background",
1999
- is_trigger: (call) => is_background_long_run(call),
2000
- reason: LANE_BACKGROUND_REASON,
2001
- decide: () => true
2002
- };
2003
- var lane_background = {
2004
- FOREGROUND_NOTE,
2005
- LANE_BACKGROUND_REASON,
2006
- LANE_BACKGROUND_STOP_REASON,
2007
- ROW: ROW2,
2008
- foreground_input,
2009
- is_background_long_run,
2010
- pending_agent_ids,
2011
- pending_background_ids
2012
- };
2013
-
2014
- // scripts/josh/process-identity.ts
2015
- import { execFileSync as execFileSync2, spawnSync } from "node:child_process";
2016
- import { randomUUID } from "node:crypto";
2017
- import { readFileSync as readFileSync2, rmSync } from "node:fs";
2018
- import { createServer } from "node:net";
2019
- import path from "node:path";
2020
- var PS_COMMAND = "/bin/ps";
2021
- var FORMAT_FLAG = "-o";
2022
- var START_TIME_FORMAT = "lstart=";
2023
- var PID_FLAG = "-p";
2024
- var PROBE_ENVIRONMENT = { TZ: "UTC", LC_ALL: "C" };
2025
- var PROBE_TIMEOUT_MS2 = 2e3;
2026
- var LIVENESS_SIGNAL = 0;
2027
- var LOWEST_REAL_PID = 1;
2028
- var PROC_START_FIELD_INDEX = 19;
2029
- var BEACON_SCHEME = "socket:";
2030
- var BEACON_SUFFIX = ".sock";
2031
- var BEACON_PREFIX = `josh-process-identity-${String(process.getuid?.() ?? "")}-`;
2032
- var BEACON_ID_LENGTH = 36;
2033
- var BEACON_ID_PATTERN = /^[\da-f-]+$/u;
2034
- var WINDOWS_PLATFORM = "win32";
2035
- var SOCKET_PROBE_SOURCE = "const net=require('node:net');const socket=net.createConnection(process.argv[1]);socket.once('connect',()=>process.exit(0));socket.once('error',()=>process.exit(1));socket.setTimeout(1000,()=>process.exit(1));";
2036
- var beacons = /* @__PURE__ */ new Map();
2037
- var exit_cleanup = { is_registered: false };
2038
- function is_live_pid(pid) {
2039
- if (pid < LOWEST_REAL_PID) return false;
2040
- try {
2041
- process.kill(pid, LIVENESS_SIGNAL);
2042
- return true;
2043
- } catch {
2044
- return false;
2045
- }
2046
- }
2047
- function read_proc_start(pid) {
2048
- try {
2049
- const stat = readFileSync2(`/proc/${String(pid)}/stat`, "utf8");
2050
- const fields = stat.slice(stat.lastIndexOf(")") + 1).trim().split(/\s+/u);
2051
- const start = fields[PROC_START_FIELD_INDEX];
2052
- return start === void 0 ? void 0 : `proc:${start}`;
2053
- } catch {
2054
- return void 0;
2055
- }
2056
- }
2057
- function read_ps_start(pid) {
2058
- try {
2059
- const printed = execFileSync2(
2060
- PS_COMMAND,
2061
- [FORMAT_FLAG, START_TIME_FORMAT, PID_FLAG, String(pid)],
2062
- {
2063
- encoding: "utf8",
2064
- timeout: PROBE_TIMEOUT_MS2,
2065
- stdio: ["ignore", "pipe", "ignore"],
2066
- env: PROBE_ENVIRONMENT
2067
- }
2068
- ).trim();
2069
- return printed.length > 0 ? printed : void 0;
2070
- } catch {
2071
- return void 0;
2072
- }
2073
- }
2074
- var START_PROBES = { read_proc_start, read_ps_start };
2075
- function safe_probe(probe, pid) {
2076
- try {
2077
- return probe(pid);
2078
- } catch {
2079
- return void 0;
2080
- }
2081
- }
2082
- function read_start(pid, probes = START_PROBES) {
2083
- return safe_probe(probes.read_proc_start, pid) ?? safe_probe(probes.read_ps_start, pid);
2084
- }
2085
- function close_beacon(token) {
2086
- const server = beacons.get(token);
2087
- if (server === void 0) return;
2088
- beacons.delete(token);
2089
- server.close();
2090
- rmSync(token.slice(BEACON_SCHEME.length), { force: true });
2091
- }
2092
- function close_beacons() {
2093
- for (const token of beacons.keys()) close_beacon(token);
2094
- }
2095
- function ensure_exit_cleanup() {
2096
- if (exit_cleanup.is_registered) return;
2097
- exit_cleanup.is_registered = true;
2098
- process.once("exit", close_beacons);
2099
- }
2100
- function ignore_beacon_error() {
2101
- }
2102
- function bind_beacon(target) {
2103
- return createServer().on("error", ignore_beacon_error).listen(target);
2104
- }
2105
- function try_bind_beacon(bind, target) {
2106
- try {
2107
- const server = bind(target);
2108
- return server.listening ? server : void 0;
2109
- } catch {
2110
- return void 0;
2111
- }
2112
- }
2113
- function open_beacon(bind = bind_beacon) {
2114
- const target = path.join(PLATFORM_TEMP_ROOT, `${BEACON_PREFIX}${randomUUID()}${BEACON_SUFFIX}`);
2115
- const token = `${BEACON_SCHEME}${target}`;
2116
- const server = try_bind_beacon(bind, target);
2117
- if (server === void 0) return void 0;
2118
- server.unref();
2119
- beacons.set(token, server);
2120
- ensure_exit_cleanup();
2121
- return token;
2122
- }
2123
- function resolve_own_start(probes = START_PROBES, platform2 = process.platform) {
2124
- const start = read_start(process.pid, probes);
2125
- if (start !== void 0 || platform2 === WINDOWS_PLATFORM) return start;
2126
- return open_beacon();
2127
- }
2128
- function is_valid_beacon_name(name) {
2129
- if (!name.startsWith(BEACON_PREFIX) || !name.endsWith(BEACON_SUFFIX)) return false;
2130
- const id = name.slice(BEACON_PREFIX.length, -BEACON_SUFFIX.length);
2131
- return id.length === BEACON_ID_LENGTH && BEACON_ID_PATTERN.test(id);
2132
- }
2133
- function beacon_target(token) {
2134
- if (!token.startsWith(BEACON_SCHEME)) return void 0;
2135
- const target = token.slice(BEACON_SCHEME.length);
2136
- if (path.dirname(target) !== PLATFORM_TEMP_ROOT) return void 0;
2137
- return is_valid_beacon_name(path.basename(target)) ? target : void 0;
2138
- }
2139
- function is_live_beacon(target) {
2140
- return spawnSync(process.execPath, ["-e", SOCKET_PROBE_SOURCE, target], {
2141
- stdio: "ignore",
2142
- timeout: PROBE_TIMEOUT_MS2
2143
- }).status === 0;
2144
- }
2145
- function has_matching_start(pid, recorded_start, read3) {
2146
- const observed = read3(pid);
2147
- return observed === void 0 ? void 0 : observed === recorded_start;
2148
- }
2149
- function matches_recorded_start(pid, recorded_start, read3) {
2150
- const target = beacon_target(recorded_start);
2151
- return target === void 0 ? has_matching_start(pid, recorded_start, read3) : is_live_beacon(target);
2152
- }
2153
- var own_probe = /* @__PURE__ */ new Map();
2154
- function own_start() {
2155
- if (!own_probe.has(process.pid)) own_probe.set(process.pid, resolve_own_start());
2156
- return own_probe.get(process.pid);
2157
- }
2158
- function own_fields() {
2159
- const start = own_start();
2160
- return { pid: process.pid, ...start !== void 0 && { process_start: start } };
2161
- }
2162
- function is_same_process(pid, recorded_start, read3 = read_start) {
2163
- if (pid === void 0 || !is_live_pid(pid)) return false;
2164
- if (recorded_start === void 0) return void 0;
2165
- return matches_recorded_start(pid, recorded_start, read3);
2166
- }
2167
- function is_own_process(pid, recorded_start) {
2168
- return pid === process.pid && recorded_start === own_start();
2169
- }
2170
- var process_identity = {
2171
- close_beacon,
2172
- is_live_pid,
2173
- is_own_process,
2174
- is_same_process,
2175
- open_beacon,
2176
- own_fields,
2177
- own_start,
2178
- read_start,
2179
- resolve_own_start
2180
- };
2181
-
2182
- // scripts/run/run-carry.ts
2183
- import { z as z6 } from "zod";
2184
-
2185
- // scripts/run/run-carry-streak.ts
2186
- var NO_INCREMENT = 0;
2187
- var OUTAGE_FOLD_WINDOW_MS = 12e4;
2188
- function has_increment(value) {
2189
- return (value ?? NO_INCREMENT) > NO_INCREMENT;
2190
- }
2191
- function next_failures(carry, change) {
2192
- if (has_increment(change.merged)) return NO_INCREMENT;
2193
- return carry.failures + (change.failures ?? NO_INCREMENT);
2194
- }
2195
- function is_within_fold_window(last_outage_at, now) {
2196
- if (last_outage_at === void 0) return false;
2197
- const last = Date.parse(last_outage_at);
2198
- if (Number.isNaN(last)) return false;
2199
- return now.getTime() - last <= OUTAGE_FOLD_WINDOW_MS;
2200
- }
2201
- function folded_outage(carry) {
2202
- return { outages: carry.outages, last_outage_at: carry.last_outage_at };
2203
- }
2204
- function counted_outage(carry, change, now) {
2205
- const outages = carry.outages + (change.outages ?? NO_INCREMENT);
2206
- return { outages, last_outage_at: now.toISOString() };
2207
- }
2208
- function next_outage(carry, change, now) {
2209
- if (has_increment(change.outages)) {
2210
- return is_within_fold_window(carry.last_outage_at, now) ? folded_outage(carry) : counted_outage(carry, change, now);
2211
- }
2212
- const is_reachable = has_increment(change.merged) || has_increment(change.failures);
2213
- return is_reachable ? { outages: NO_INCREMENT, last_outage_at: void 0 } : folded_outage(carry);
2214
- }
2215
- function next_state(carry, change, now) {
2216
- const outage = next_outage(carry, change, now);
2217
- return {
2218
- failures: next_failures(carry, change),
2219
- outages: outage.outages,
2220
- last_outage_at: outage.last_outage_at
2221
- };
2222
- }
2223
- var run_carry_streak = { next_state };
2224
-
2225
- // scripts/run/run-carry-change.ts
2226
- var NO_INCREMENT2 = 0;
2227
- function next_done(carry, done) {
2228
- if (done === void 0) return carry.done;
2229
- const current = carry.done ?? [];
2230
- return current.includes(done) ? current : [...current, done];
2231
- }
2232
- function next_merged_issues(carry, issue) {
2233
- if (issue === void 0) return carry.merged_issues;
2234
- return [...carry.merged_issues ?? [], issue];
2235
- }
2236
- function is_duplicate_merge(carry, change) {
2237
- const issue = change.merged_issue;
2238
- return issue !== void 0 && carry.merged_issues?.includes(issue) === true;
2239
- }
2240
- function next_counts(carry, change) {
2241
- const cuts = change.cuts ?? NO_INCREMENT2;
2242
- return {
2243
- merged: carry.merged + (change.merged ?? NO_INCREMENT2),
2244
- filed: carry.filed + (change.filed ?? NO_INCREMENT2),
2245
- cuts: carry.cuts + cuts,
2246
- is_handed_off: cuts > NO_INCREMENT2
2247
- };
2248
- }
2249
- function apply_change(target, carry, change, now = /* @__PURE__ */ new Date()) {
2250
- if (is_duplicate_merge(carry, change)) return carry;
2251
- const streak = run_carry_streak.next_state(carry, change, now);
2252
- const next = {
2253
- ...carry,
2254
- ...next_counts(carry, change),
2255
- merged_issues: next_merged_issues(carry, change.merged_issue),
2256
- failures: streak.failures,
2257
- outages: streak.outages,
2258
- last_outage_at: streak.last_outage_at,
2259
- done: next_done(carry, change.done),
2260
- retrospective: change.retrospective === true || carry.retrospective
2261
- };
2262
- stamp_file.write_stamp(target, next);
2263
- return next;
2264
- }
2265
- var run_carry_change = { apply_change };
2266
-
2267
- // scripts/run/run-carry-conversation.ts
2268
- import { existsSync, statSync } from "node:fs";
2269
- import path2 from "node:path";
2270
-
2271
- // scripts/cost-runtime/own-session.ts
2272
- var NOT_FOUND = -1;
2273
- function session_id_of(environment2) {
2274
- const value = environment2[agent_session_environment.SESSION_ID_KEY];
2275
- return value === void 0 || value === "" ? void 0 : value;
2276
- }
2277
- function select_own_session(files, environment2) {
2278
- const session_id = session_id_of(environment2);
2279
- if (session_id === void 0) {
2280
- return { kind: "own", index: cost_transcript.latest_own_index(files) };
2281
- }
2282
- const index = files.findIndex((file) => file.session_id === session_id);
2283
- return index === NOT_FOUND ? { kind: "absent", session_id } : { kind: "own", index };
2284
- }
2285
- var own_session = {
2286
- session_id_of,
2287
- select_own_session
2288
- };
2289
-
2290
- // scripts/run/run-carry-conversation.ts
2291
- var CONVERSATION_QUIET_MS = 6e5;
2292
- function own_transcript(environment2 = process.env, directories2 = cost_transcript.transcript_directories(process.cwd())) {
2293
- const session_id = own_session.session_id_of(environment2);
2294
- if (session_id === void 0) return void 0;
2295
- const name = `${session_id}${cost_transcript.TRANSCRIPT_EXTENSION}`;
2296
- return directories2.map((directory) => path2.join(directory, name)).find((file) => existsSync(file));
2297
- }
2298
- function modified_ms(transcript) {
2299
- try {
2300
- return statSync(transcript).mtimeMs;
2301
- } catch {
2302
- return void 0;
2303
- }
2304
- }
2305
- function is_recent(modified, now) {
2306
- return modified !== void 0 && now.getTime() - modified <= CONVERSATION_QUIET_MS;
2073
+ function pending_background_ids(tail) {
2074
+ return unfinished_ids(tail, (block) => [block.background_id, block.agent_id]);
2307
2075
  }
2308
- function is_conversation_live(carry, now = /* @__PURE__ */ new Date(), read_modified = modified_ms) {
2309
- if (carry.is_handed_off === true || carry.owner_transcript === void 0) return false;
2310
- return is_recent(read_modified(carry.owner_transcript), now);
2076
+ function pending_agent_ids(tail) {
2077
+ return unfinished_ids(tail, (block) => [block.agent_id]);
2311
2078
  }
2312
- function is_same_conversation(carry, owner) {
2313
- return owner.transcript !== void 0 && owner.transcript === carry.owner_transcript;
2079
+ var LANE_BACKGROUND_REASON = '\u26D4 lane background: this session is a dispatched lane child (`JOSH_LANE_CHILD`), a headless `claude -p` process whose background Bash tasks are killed when the turn ends \u2014 so a backgrounded `josh gate` / `josh git` / `josh followup` / `josh ship` never re-invokes you; it dies at `exit code 143` (joshuafolkken/kit#2704, measured on the #2606 child: implementation, review and live verification done, the run parked instead of merged). Hand the gate-to-merge region to the detached supervisor instead: `pnpm josh ship --detach --review "<title> #<N>"` (add `--cite <N>`) issued in the foreground \u2014 its preflight runs in this process before the supervisor exists, so a backgrounded `ship` dies with the turn (joshuafolkken/kit#3027; a backgrounded `ship` issued alone is moved to the foreground for you, joshuafolkken/kit#3154) \u2014 then end the turn on `launched` / `busy`. `.claude/skills/workflow-commands/chain-rule.md` step 0 is the single source. A single check you must read before continuing runs in the foreground within the tool timeout; the commit-push step does not \u2014 in a child it too belongs to the detached ship, in either spelling. This rule fires on every occurrence, not once per run.';
2080
+ var LANE_BACKGROUND_STOP_REASON = "\u26D4 lane background stop: this is a dispatched lane child (`JOSH_LANE_CHILD`) and a background task it launched has not finished \u2014 ending this headless turn kills it, and nothing re-invokes you afterwards (joshuafolkken/kit#2704). Do not send a notification and do not stop: wait for the task in the foreground and act on its result, or re-issue the work through `pnpm josh ship --detach`, whose supervisor outlives the turn (`.claude/skills/workflow-commands/chain-rule.md` step 0). Do not repeat your previous reply.";
2081
+ var ROW2 = {
2082
+ id: "lane-background",
2083
+ is_trigger: (call) => is_background_long_run(call),
2084
+ reason: LANE_BACKGROUND_REASON,
2085
+ decide: () => true
2086
+ };
2087
+ var lane_background = {
2088
+ FOREGROUND_NOTE,
2089
+ LANE_BACKGROUND_REASON,
2090
+ LANE_BACKGROUND_STOP_REASON,
2091
+ ROW: ROW2,
2092
+ foreground_input,
2093
+ is_background_long_run,
2094
+ pending_agent_ids,
2095
+ pending_background_ids
2096
+ };
2097
+
2098
+ // scripts/agent/agent-headless.ts
2099
+ var KEY = "JOSH_AGENT_HEADLESS";
2100
+ var VALUE = "1";
2101
+ function environment() {
2102
+ return { [KEY]: VALUE };
2314
2103
  }
2315
- function reclaim_owner(carry, owner) {
2316
- if (carry.is_handed_off === true || !is_same_conversation(carry, owner)) return carry;
2317
- if (owner.pid === carry.owner_pid) return carry;
2318
- return { ...carry, owner_pid: owner.pid, owner_start: owner.start };
2104
+ function is_headless(source = process.env) {
2105
+ return source[KEY] === VALUE;
2319
2106
  }
2320
- var run_carry_conversation = {
2321
- CONVERSATION_QUIET_MS,
2322
- own_transcript,
2323
- is_conversation_live,
2324
- is_same_conversation,
2325
- reclaim_owner
2326
- };
2107
+ var agent_headless = { KEY, environment, is_headless };
2327
2108
 
2328
2109
  // scripts/backlog/backlog-budget-cli.ts
2329
2110
  import { fileURLToPath } from "node:url";
@@ -2411,7 +2192,50 @@ function arguments_of(argv, options) {
2411
2192
  function string_of(value) {
2412
2193
  return typeof value === "string" ? value : void 0;
2413
2194
  }
2414
- var cli_flags = { refuse_unknown_flags, parse_or_undefined, values_of, arguments_of, string_of };
2195
+ var LONG_FLAG_PREFIX = "--";
2196
+ var SHORT_FLAG_PREFIX = "-";
2197
+ function option_name(flag) {
2198
+ return flag.slice(LONG_FLAG_PREFIX.length);
2199
+ }
2200
+ function is_unusable_value(value) {
2201
+ if (typeof value === "boolean" || value.length === 0) return true;
2202
+ return value !== SHORT_FLAG_PREFIX && value.startsWith(SHORT_FLAG_PREFIX);
2203
+ }
2204
+ function given_values(argv, flag) {
2205
+ const name = option_name(flag);
2206
+ const given = parse_or_undefined({
2207
+ args: [...argv],
2208
+ options: { [name]: { type: "string", multiple: true } },
2209
+ strict: false,
2210
+ allowPositionals: true
2211
+ })?.values[name];
2212
+ return Array.isArray(given) ? given : [];
2213
+ }
2214
+ function is_value_unusable(argv, flag) {
2215
+ return given_values(argv, flag).some((value) => is_unusable_value(value));
2216
+ }
2217
+ function attach_one(attached, argument, flags) {
2218
+ const previous = attached.at(-1);
2219
+ if (previous !== void 0 && flags.includes(previous)) {
2220
+ attached[attached.length - 1] = `${previous}=${argument}`;
2221
+ } else attached.push(argument);
2222
+ }
2223
+ function attach_values(argv, flags) {
2224
+ const attached = [];
2225
+ for (const argument of argv) attach_one(attached, argument, flags);
2226
+ return attached;
2227
+ }
2228
+ var cli_flags = {
2229
+ attach_values,
2230
+ refuse_unknown_flags,
2231
+ parse_or_undefined,
2232
+ values_of,
2233
+ arguments_of,
2234
+ string_of,
2235
+ option_name,
2236
+ given_values,
2237
+ is_value_unusable
2238
+ };
2415
2239
 
2416
2240
  // scripts/backlog/backlog-budget-cli.ts
2417
2241
  var ARGV_OFFSET = 2;
@@ -2500,7 +2324,7 @@ function refuse() {
2500
2324
  console.error(USAGE);
2501
2325
  return FAILURE_EXIT_CODE2;
2502
2326
  }
2503
- function run2(argv, now_ms = Date.now()) {
2327
+ function run3(argv, now_ms = Date.now()) {
2504
2328
  const values = read_arguments(argv);
2505
2329
  if (values === void 0) return refuse();
2506
2330
  const input = build_input(values, now_ms);
@@ -2516,7 +2340,7 @@ function run2(argv, now_ms = Date.now()) {
2516
2340
  return SUCCESS_EXIT_CODE2;
2517
2341
  }
2518
2342
  function main(argv) {
2519
- process.exitCode = run2(argv);
2343
+ process.exitCode = run3(argv);
2520
2344
  }
2521
2345
  var backlog_budget_cli = {
2522
2346
  JSON_KEY,
@@ -2526,7 +2350,7 @@ var backlog_budget_cli = {
2526
2350
  build_input,
2527
2351
  main,
2528
2352
  read_arguments,
2529
- run: run2,
2353
+ run: run3,
2530
2354
  to_answer,
2531
2355
  to_count,
2532
2356
  to_time_ms
@@ -2537,38 +2361,34 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(
2537
2361
  var BACKLOG_COMMAND = "backlogrun";
2538
2362
  var KNOWN_FLAGS2 = ["--max", "--idle"];
2539
2363
  var ONLY_FLAG = "--only";
2364
+ var OPTIONS2 = {
2365
+ max: { type: "string" },
2366
+ idle: { type: "string" },
2367
+ only: { type: "boolean" }
2368
+ };
2540
2369
  var ISSUE_PREFIX = "#";
2370
+ var FLAG_PREFIX = "-";
2541
2371
  var TOKEN_SEPARATOR = " ";
2542
2372
  var FIRST_TOKEN = 0;
2543
2373
  var FIRST_ARGUMENT_INDEX = 1;
2544
- var VALUE_OFFSET = 1;
2545
- var FLAG_PAIR_LENGTH = 2;
2546
- var ONLY_STEP = 1;
2547
2374
  var EMPTY_LENGTH2 = 0;
2548
- var NOT_FOUND2 = -1;
2375
+ var NOT_FOUND = -1;
2549
2376
  function tokens_of(invocation) {
2550
2377
  return invocation.split(TOKEN_SEPARATOR).filter((token) => token.length > EMPTY_LENGTH2);
2551
2378
  }
2552
- function flag_token(token, raw) {
2553
- const flag = KNOWN_FLAGS2.find((known) => known === token);
2554
- const value = backlog_budget_cli.to_count(raw);
2379
+ function render_option(token) {
2380
+ if (token.name === cli_flags.option_name(ONLY_FLAG)) return ONLY_FLAG;
2381
+ const flag = KNOWN_FLAGS2.find((known) => cli_flags.option_name(known) === token.name);
2382
+ const value = backlog_budget_cli.to_count(token.value);
2555
2383
  if (flag === void 0 || value === void 0) return void 0;
2556
2384
  return `${flag} ${String(value)}`;
2557
2385
  }
2558
- function read_flag(tokens, index) {
2559
- const token = tokens[index] ?? "";
2560
- if (token === ONLY_FLAG) return { part: ONLY_FLAG, advance: ONLY_STEP };
2561
- const part = flag_token(token, tokens[index + VALUE_OFFSET]);
2562
- return part === void 0 ? void 0 : { part, advance: FLAG_PAIR_LENGTH };
2563
- }
2564
- function flag_tokens(tokens, start) {
2386
+ function rendered_options(tokens) {
2565
2387
  const rendered = [];
2566
- let index = start;
2567
- while (index < tokens.length) {
2568
- const read3 = read_flag(tokens, index);
2569
- if (read3 === void 0) return void 0;
2570
- rendered.push(read3.part);
2571
- index += read3.advance;
2388
+ for (const token of tokens) {
2389
+ const part = render_option(token);
2390
+ if (part === void 0) return void 0;
2391
+ rendered.push(part);
2572
2392
  }
2573
2393
  return rendered;
2574
2394
  }
@@ -2579,49 +2399,59 @@ function issue_of(token) {
2579
2399
  const issue = Number(digits);
2580
2400
  return Number.isSafeInteger(issue) ? issue : void 0;
2581
2401
  }
2582
- function take_leading_prefixed(args) {
2583
- const stop = args.findIndex((token) => !token.startsWith(ISSUE_PREFIX));
2584
- return args.slice(FIRST_TOKEN, stop === NOT_FOUND2 ? args.length : stop);
2585
- }
2586
- function leading_issues(tokens) {
2402
+ function issues_of(tokens) {
2587
2403
  const issues = [];
2588
- const prefixed = take_leading_prefixed(tokens.slice(FIRST_ARGUMENT_INDEX));
2589
- for (const token of prefixed) {
2590
- const issue = issue_of(token);
2404
+ for (const token of tokens) {
2405
+ const issue = issue_of(token.value ?? "");
2591
2406
  if (issue === void 0) return void 0;
2592
2407
  issues.push(issue);
2593
2408
  }
2594
2409
  return issues;
2595
2410
  }
2411
+ function argument_tokens(invocation) {
2412
+ const tokens = tokens_of(invocation);
2413
+ if (tokens[FIRST_TOKEN] !== BACKLOG_COMMAND) return void 0;
2414
+ return cli_flags.parse_or_undefined({
2415
+ args: tokens.slice(FIRST_ARGUMENT_INDEX),
2416
+ options: OPTIONS2,
2417
+ allowPositionals: true,
2418
+ tokens: true
2419
+ })?.tokens;
2420
+ }
2421
+ function parse2(invocation) {
2422
+ const tokens = argument_tokens(invocation);
2423
+ if (tokens === void 0) return void 0;
2424
+ const stop = tokens.findIndex((token) => token.kind !== "positional");
2425
+ const split_at = stop === NOT_FOUND ? tokens.length : stop;
2426
+ const issues = issues_of(tokens.slice(FIRST_TOKEN, split_at));
2427
+ const flags = rendered_options(tokens.slice(split_at));
2428
+ if (issues === void 0 || flags === void 0) return void 0;
2429
+ return { issues, flags };
2430
+ }
2596
2431
  function issue_token(issue) {
2597
2432
  return `${ISSUE_PREFIX}${String(issue)}`;
2598
2433
  }
2599
2434
  function joined(command, rendered) {
2600
2435
  return [command, ...rendered].join(TOKEN_SEPARATOR);
2601
2436
  }
2602
- function rebuilt_backlog(tokens) {
2603
- const issues = leading_issues(tokens);
2604
- if (issues === void 0) return void 0;
2605
- const flags = flag_tokens(tokens, FIRST_ARGUMENT_INDEX + issues.length);
2606
- if (flags === void 0) return void 0;
2607
- return joined(BACKLOG_COMMAND, [...issues.map((issue) => issue_token(issue)), ...flags]);
2608
- }
2609
2437
  function rebuild(invocation) {
2610
- const tokens = tokens_of(invocation);
2611
- if (tokens[FIRST_TOKEN] !== BACKLOG_COMMAND) return void 0;
2612
- return rebuilt_backlog(tokens);
2438
+ const parsed = parse2(invocation);
2439
+ if (parsed === void 0) return void 0;
2440
+ return joined(BACKLOG_COMMAND, [
2441
+ ...parsed.issues.map((issue) => issue_token(issue)),
2442
+ ...parsed.flags
2443
+ ]);
2613
2444
  }
2614
2445
  function issue_numbers(invocation) {
2615
2446
  const tokens = tokens_of(invocation);
2616
- if (tokens[FIRST_TOKEN] !== BACKLOG_COMMAND) return void 0;
2617
- const issues = leading_issues(tokens);
2447
+ const stop = tokens.findIndex((token) => token.startsWith(FLAG_PREFIX));
2448
+ const leading = stop === NOT_FOUND ? tokens : tokens.slice(FIRST_TOKEN, stop);
2449
+ const issues = parse2(leading.join(TOKEN_SEPARATOR))?.issues;
2618
2450
  if (issues === void 0 || issues.length === EMPTY_LENGTH2) return void 0;
2619
2451
  return issues;
2620
2452
  }
2621
2453
  function has_only(invocation) {
2622
- const tokens = tokens_of(invocation);
2623
- if (tokens[FIRST_TOKEN] !== BACKLOG_COMMAND) return false;
2624
- return tokens.slice(FIRST_ARGUMENT_INDEX).includes(ONLY_FLAG);
2454
+ return parse2(invocation)?.flags.includes(ONLY_FLAG) === true;
2625
2455
  }
2626
2456
  var run_invocation = {
2627
2457
  has_only,
@@ -2629,7 +2459,164 @@ var run_invocation = {
2629
2459
  rebuild
2630
2460
  };
2631
2461
 
2632
- // scripts/run/run-carry.ts
2462
+ // scripts/run/carry/run-carry.ts
2463
+ import { z as z6 } from "zod";
2464
+
2465
+ // scripts/run/carry/run-carry-streak.ts
2466
+ var NO_INCREMENT = 0;
2467
+ var OUTAGE_FOLD_WINDOW_MS = 12e4;
2468
+ function has_increment(value) {
2469
+ return (value ?? NO_INCREMENT) > NO_INCREMENT;
2470
+ }
2471
+ function next_failures(carry, change) {
2472
+ if (has_increment(change.merged)) return NO_INCREMENT;
2473
+ return carry.failures + (change.failures ?? NO_INCREMENT);
2474
+ }
2475
+ function is_within_fold_window(last_outage_at, now) {
2476
+ if (last_outage_at === void 0) return false;
2477
+ const last = Date.parse(last_outage_at);
2478
+ if (Number.isNaN(last)) return false;
2479
+ return now.getTime() - last <= OUTAGE_FOLD_WINDOW_MS;
2480
+ }
2481
+ function folded_outage(carry) {
2482
+ return { outages: carry.outages, last_outage_at: carry.last_outage_at };
2483
+ }
2484
+ function counted_outage(carry, change, now) {
2485
+ const outages = carry.outages + (change.outages ?? NO_INCREMENT);
2486
+ return { outages, last_outage_at: now.toISOString() };
2487
+ }
2488
+ function next_outage(carry, change, now) {
2489
+ if (has_increment(change.outages)) {
2490
+ return is_within_fold_window(carry.last_outage_at, now) ? folded_outage(carry) : counted_outage(carry, change, now);
2491
+ }
2492
+ const is_reachable = has_increment(change.merged) || has_increment(change.failures);
2493
+ return is_reachable ? { outages: NO_INCREMENT, last_outage_at: void 0 } : folded_outage(carry);
2494
+ }
2495
+ function next_state(carry, change, now) {
2496
+ const outage = next_outage(carry, change, now);
2497
+ return {
2498
+ failures: next_failures(carry, change),
2499
+ outages: outage.outages,
2500
+ last_outage_at: outage.last_outage_at
2501
+ };
2502
+ }
2503
+ var run_carry_streak = { next_state };
2504
+
2505
+ // scripts/run/carry/run-carry-change.ts
2506
+ var NO_INCREMENT2 = 0;
2507
+ function next_done(carry, done) {
2508
+ if (done === void 0) return carry.done;
2509
+ const current = carry.done ?? [];
2510
+ return current.includes(done) ? current : [...current, done];
2511
+ }
2512
+ function next_merged_issues(carry, issue) {
2513
+ if (issue === void 0) return carry.merged_issues;
2514
+ const current = carry.merged_issues ?? [];
2515
+ return current.includes(issue) ? current : [...current, issue];
2516
+ }
2517
+ function is_duplicate_merge(carry, change) {
2518
+ const issue = change.merged_issue;
2519
+ return issue !== void 0 && carry.merged_issues?.includes(issue) === true;
2520
+ }
2521
+ function has_other_change(change) {
2522
+ const amounts = [change.filed, change.cuts, change.failures, change.outages];
2523
+ const has_amount = amounts.some((amount) => (amount ?? NO_INCREMENT2) > NO_INCREMENT2);
2524
+ return has_amount || change.done !== void 0 || change.retrospective === true;
2525
+ }
2526
+ function effective_change(carry, change) {
2527
+ if (!is_duplicate_merge(carry, change)) return change;
2528
+ return has_other_change(change) ? { ...change, merged: NO_INCREMENT2 } : void 0;
2529
+ }
2530
+ function next_counts(carry, change) {
2531
+ const cuts = change.cuts ?? NO_INCREMENT2;
2532
+ return {
2533
+ merged: carry.merged + (change.merged ?? NO_INCREMENT2),
2534
+ filed: carry.filed + (change.filed ?? NO_INCREMENT2),
2535
+ cuts: carry.cuts + cuts,
2536
+ is_handed_off: cuts > NO_INCREMENT2
2537
+ };
2538
+ }
2539
+ function apply_change(target, carry, change, now = /* @__PURE__ */ new Date()) {
2540
+ const effective = effective_change(carry, change);
2541
+ if (effective === void 0) return carry;
2542
+ const streak = run_carry_streak.next_state(carry, effective, now);
2543
+ const next = {
2544
+ ...carry,
2545
+ ...next_counts(carry, effective),
2546
+ merged_issues: next_merged_issues(carry, effective.merged_issue),
2547
+ failures: streak.failures,
2548
+ outages: streak.outages,
2549
+ last_outage_at: streak.last_outage_at,
2550
+ done: next_done(carry, effective.done),
2551
+ retrospective: effective.retrospective === true || carry.retrospective
2552
+ };
2553
+ stamp_file.write_stamp(target, next);
2554
+ return next;
2555
+ }
2556
+ var run_carry_change = { apply_change };
2557
+
2558
+ // scripts/run/carry/run-carry-conversation.ts
2559
+ import { existsSync, statSync } from "node:fs";
2560
+ import path2 from "node:path";
2561
+
2562
+ // scripts/cost-runtime/own-session.ts
2563
+ var NOT_FOUND2 = -1;
2564
+ function session_id_of(environment3) {
2565
+ const value = environment3[agent_session_environment.SESSION_ID_KEY];
2566
+ return value === void 0 || value === "" ? void 0 : value;
2567
+ }
2568
+ function select_own_session(files, environment3) {
2569
+ const session_id = session_id_of(environment3);
2570
+ if (session_id === void 0) {
2571
+ return { kind: "own", index: cost_transcript.latest_own_index(files) };
2572
+ }
2573
+ const index = files.findIndex((file) => file.session_id === session_id);
2574
+ return index === NOT_FOUND2 ? { kind: "absent", session_id } : { kind: "own", index };
2575
+ }
2576
+ var own_session = {
2577
+ session_id_of,
2578
+ select_own_session
2579
+ };
2580
+
2581
+ // scripts/run/carry/run-carry-conversation.ts
2582
+ var CONVERSATION_QUIET_MS = 6e5;
2583
+ function own_transcript(environment3 = process.env, directories2 = cost_transcript.transcript_directories(process.cwd())) {
2584
+ const session_id = own_session.session_id_of(environment3);
2585
+ if (session_id === void 0) return void 0;
2586
+ const name = `${session_id}${cost_transcript.TRANSCRIPT_EXTENSION}`;
2587
+ return directories2.map((directory) => path2.join(directory, name)).find((file) => existsSync(file));
2588
+ }
2589
+ function modified_ms(transcript) {
2590
+ try {
2591
+ return statSync(transcript).mtimeMs;
2592
+ } catch {
2593
+ return void 0;
2594
+ }
2595
+ }
2596
+ function is_recent(modified, now) {
2597
+ return modified !== void 0 && now.getTime() - modified <= CONVERSATION_QUIET_MS;
2598
+ }
2599
+ function is_conversation_live(carry, now = /* @__PURE__ */ new Date(), read_modified = modified_ms) {
2600
+ if (carry.is_handed_off === true || carry.owner_transcript === void 0) return false;
2601
+ return is_recent(read_modified(carry.owner_transcript), now);
2602
+ }
2603
+ function is_same_conversation(carry, owner) {
2604
+ return owner.transcript !== void 0 && owner.transcript === carry.owner_transcript;
2605
+ }
2606
+ function reclaim_owner(carry, owner) {
2607
+ if (carry.is_handed_off === true || !is_same_conversation(carry, owner)) return carry;
2608
+ if (owner.pid === carry.owner_pid) return carry;
2609
+ return { ...carry, owner_pid: owner.pid, owner_start: owner.start };
2610
+ }
2611
+ var run_carry_conversation = {
2612
+ CONVERSATION_QUIET_MS,
2613
+ own_transcript,
2614
+ is_conversation_live,
2615
+ is_same_conversation,
2616
+ reclaim_owner
2617
+ };
2618
+
2619
+ // scripts/run/carry/run-carry.ts
2633
2620
  var CARRY_PREFIX = "josh-run-carry-";
2634
2621
  var REPOSITORY_DIRECTORY_INDEX = 1;
2635
2622
  var CARRY_MAX_AGE_HOURS = backlog_budget.WHOLE_RUN_BUDGET_HOURS;
@@ -2852,10 +2839,9 @@ var run_carry = {
2852
2839
  unreadable_message: unreadable_message3
2853
2840
  };
2854
2841
 
2855
- // scripts/run/run-ship-detach.ts
2856
- import { randomUUID as randomUUID2 } from "node:crypto";
2842
+ // scripts/run/ship/run-ship-detach.ts
2843
+ import { randomUUID } from "node:crypto";
2857
2844
  import { setTimeout as sleep } from "node:timers/promises";
2858
- import { z as z8 } from "zod";
2859
2845
 
2860
2846
  // scripts/run/detached-launch.ts
2861
2847
  import { spawn } from "node:child_process";
@@ -2909,17 +2895,19 @@ function link_home_file(source_home, target_home, name) {
2909
2895
  const target = path4.join(target_home, name);
2910
2896
  if (!remove_old_home_link(source, target) && existsSync2(source)) symlinkSync(source, target);
2911
2897
  }
2912
- function reviewer_home(cwd, environment2) {
2913
- const source = environment2["CODEX_HOME"] ?? process.env["CODEX_HOME"] ?? codex_home_source.default_home();
2898
+ function reviewer_home(cwd, environment3) {
2899
+ const source = environment3["CODEX_HOME"] ?? process.env["CODEX_HOME"] ?? codex_home_source.default_home();
2914
2900
  const target = path4.resolve(cwd, ...REVIEWER_HOME);
2915
2901
  mkdirSync(target, { recursive: true, mode: PRIVATE_DIRECTORY_MODE });
2916
2902
  for (const name of HOME_FILES) link_home_file(source, target, name);
2917
2903
  return target;
2918
2904
  }
2919
- function build(cwd, profile, environment2 = {}) {
2920
- if (profile?.provider !== OPENAI_PROVIDER2) return environment2;
2921
- const base = { ...openai_environment(), ...environment2 };
2922
- return profile.role === agent_role_profile.REVIEWER ? { ...base, CODEX_HOME: reviewer_home(cwd, environment2) } : base;
2905
+ function build(cwd, profile, environment3 = {}) {
2906
+ if (profile === void 0) return environment3;
2907
+ const marked = { ...agent_headless.environment(), ...environment3 };
2908
+ if (profile.provider !== OPENAI_PROVIDER2) return marked;
2909
+ const base = { ...openai_environment(), ...marked };
2910
+ return profile.role === agent_role_profile.REVIEWER ? { ...base, CODEX_HOME: reviewer_home(cwd, environment3) } : base;
2923
2911
  }
2924
2912
  var agent_launch_environment = { build };
2925
2913
 
@@ -2977,12 +2965,12 @@ function ensure_log(log_path2, on_error) {
2977
2965
  const descriptor = open_log(log_path2, on_error);
2978
2966
  if (descriptor !== void 0) closeSync(descriptor);
2979
2967
  }
2980
- function spawn_options(cwd, log, environment2 = {}, is_detached = true) {
2968
+ function spawn_options(cwd, log, environment3 = {}, is_detached = true) {
2981
2969
  return {
2982
2970
  cwd,
2983
2971
  detached: is_detached,
2984
2972
  stdio: log === void 0 ? "ignore" : ["ignore", log, log],
2985
- env: { ...process.env, ...agent_session_environment.removed_environment(), ...environment2 }
2973
+ env: { ...process.env, ...agent_session_environment.removed_environment(), ...environment3 }
2986
2974
  };
2987
2975
  }
2988
2976
  function notify_spawn(pid, on_spawn, on_error) {
@@ -2995,11 +2983,11 @@ function notify_spawn(pid, on_spawn, on_error) {
2995
2983
  }
2996
2984
  async function attached_spawn(request, log, on_error, on_spawn) {
2997
2985
  return await new Promise((resolve3) => {
2998
- const environment2 = agent_launch_environment.build(request.cwd, request.profile, request.env);
2986
+ const environment3 = agent_launch_environment.build(request.cwd, request.profile, request.env);
2999
2987
  const child = spawn(
3000
2988
  request.argv.command,
3001
2989
  [...request.argv.args],
3002
- spawn_options(request.cwd, log, environment2, false)
2990
+ spawn_options(request.cwd, log, environment3, false)
3003
2991
  );
3004
2992
  child.once("error", (error) => {
3005
2993
  on_error(note_of(error));
@@ -3015,8 +3003,8 @@ function ignore_spawn(_pid) {
3015
3003
  }
3016
3004
  function spawned(request, log, on_error) {
3017
3005
  const { command, args } = request.argv;
3018
- const environment2 = agent_launch_environment.build(request.cwd, request.profile, request.env);
3019
- const child = spawn(command, [...args], spawn_options(request.cwd, log, environment2));
3006
+ const environment3 = agent_launch_environment.build(request.cwd, request.profile, request.env);
3007
+ const child = spawn(command, [...args], spawn_options(request.cwd, log, environment3));
3020
3008
  child.on("error", (error) => {
3021
3009
  on_error(note_of(error));
3022
3010
  });
@@ -3058,7 +3046,7 @@ var detached_launch = {
3058
3046
  note_of
3059
3047
  };
3060
3048
 
3061
- // scripts/run/run-event-stream.ts
3049
+ // scripts/run/event/run-event-stream.ts
3062
3050
  import { z as z7 } from "zod";
3063
3051
  var EVENT_PREFIX = "josh-run-events-";
3064
3052
  var EVENT_SUFFIX = ".jsonl";
@@ -3150,6 +3138,12 @@ function read_events(target) {
3150
3138
  function last_position(events) {
3151
3139
  return events[events.length - POSITION_INCREMENT]?.pos ?? FIRST_POSITION;
3152
3140
  }
3141
+ function bounded(events) {
3142
+ const excess = events.length - EVENT_CAP;
3143
+ if (excess <= 0) return events;
3144
+ const dropped = new Set(events.filter((event) => TRACE_KINDS.has(event.kind)).slice(0, excess));
3145
+ return events.filter((event) => !dropped.has(event)).slice(-EVENT_CAP);
3146
+ }
3153
3147
  function serialize(events) {
3154
3148
  return `${events.map((event) => JSON.stringify(event)).join(LINE_SEPARATOR)}${LINE_SEPARATOR}`;
3155
3149
  }
@@ -3157,8 +3151,8 @@ function append(target, kind, text, at) {
3157
3151
  if (!is_event_kind(kind)) return { appended: false, position: FIRST_POSITION };
3158
3152
  const existing = read_events(target);
3159
3153
  const position = last_position(existing) + POSITION_INCREMENT;
3160
- const bounded = [...existing, { pos: position, at, kind, text }].slice(-EVENT_CAP);
3161
- stamp_file.write_text_stamp(target, serialize(bounded));
3154
+ const events = bounded([...existing, { pos: position, at, kind, text }]);
3155
+ stamp_file.write_text_stamp(target, serialize(events));
3162
3156
  return { appended: true, position };
3163
3157
  }
3164
3158
  function read_from(target, position) {
@@ -3193,7 +3187,7 @@ var run_event_stream = {
3193
3187
  target_of
3194
3188
  };
3195
3189
 
3196
- // scripts/run/run-event-scope.ts
3190
+ // scripts/run/event/run-event-scope.ts
3197
3191
  var SINCE_SCOPE = "since";
3198
3192
  var UNKNOWN_SCOPE = "unknown";
3199
3193
  var UNKNOWN_EVENT_SCOPE = { kind: UNKNOWN_SCOPE };
@@ -3271,7 +3265,7 @@ var run_event_scope = {
3271
3265
  scoped_events
3272
3266
  };
3273
3267
 
3274
- // scripts/run/run-event-stream-emit.ts
3268
+ // scripts/run/event/run-event-stream-emit.ts
3275
3269
  function now_iso() {
3276
3270
  return (/* @__PURE__ */ new Date()).toISOString();
3277
3271
  }
@@ -3340,7 +3334,8 @@ var run_event_stream_emit = {
3340
3334
  stream_target
3341
3335
  };
3342
3336
 
3343
- // scripts/run/run-ship-detach.ts
3337
+ // scripts/run/ship/run-ship-detach.ts
3338
+ import { z as z8 } from "zod";
3344
3339
  var LOG_PREFIX = "josh-ship-log-";
3345
3340
  var PID_PREFIX = "josh-ship-pid-";
3346
3341
  var BODY_PREFIX = "josh-ship-notify-";
@@ -3491,7 +3486,7 @@ function supervisor_argv(request) {
3491
3486
  };
3492
3487
  }
3493
3488
  function prepare_launch(request) {
3494
- const launch_id = randomUUID2();
3489
+ const launch_id = randomUUID();
3495
3490
  const launcher = process_identity.own_fields();
3496
3491
  stamp_file.replace_stamp(result_path(request.repository, request.number), {
3497
3492
  launch_id,
@@ -3728,9 +3723,16 @@ function records_the_park(command) {
3728
3723
  return APPLIES_NEEDS_DECISION.test(command);
3729
3724
  }
3730
3725
  var LANE_PARK_REASON = '\u26D4 lane child park: this session is a dispatched lane child, and a stop that waits on a person must leave the question on the Issue before it sends this Telegram \u2014 otherwise the parent finds an OPEN Issue with `in-progress` and no question, and a person cannot tell what to answer (joshuafolkken/kit#2034 measured this twice in one run). The child is the only process that knows the question, the options and whether it stashed, so it records the park itself rather than leaving the parent to guess from a log. Before you notify and stop: apply `needs-decision` and post a comment carrying the question, the options, and whether work was stashed \u2014 `gh api repos/{owner}/{repo}/issues/<N>/labels -f \'labels[]=needs-decision\'` then `pnpm josh issue:comment <N> --body-file <path>`. If this stop is a `needs-human-review` or `already-done` one, that label is already on the Issue and there is nothing to add. Then reissue this notify \u2014 it fires once per run and cannot repeat on the call in hand. The procedure is `.claude/skills/workflow-commands/pre-gate-cut.md` \u2192 "A lane child records its park before it stops", and the park itself is `backlogrun-park.md` \u2192 "park and continue".';
3726
+ var ROW3 = {
3727
+ id: "lane-park",
3728
+ is_trigger: bash_triggers.on_bash_command(is_unparked_stop),
3729
+ reason: LANE_PARK_REASON,
3730
+ keeps: bash_triggers.on_bash_command(records_the_park)
3731
+ };
3731
3732
  var lane_park = {
3732
3733
  COMMAND_NOTIFY_MARKER,
3733
3734
  LANE_PARK_REASON,
3735
+ ROW: ROW3,
3734
3736
  is_confirmation_notify,
3735
3737
  is_parking_child,
3736
3738
  is_unparked_stop,
@@ -3739,7 +3741,7 @@ var lane_park = {
3739
3741
  };
3740
3742
 
3741
3743
  // scripts/discovery/repo-discovery.ts
3742
- import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3, statSync as statSync2 } from "node:fs";
3744
+ import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
3743
3745
  import path5 from "node:path";
3744
3746
 
3745
3747
  // scripts/discovery/repo-origin.ts
@@ -3805,15 +3807,15 @@ function origin_section_lines(lines) {
3805
3807
  const end = rest.findIndex((line) => is_section_header(line));
3806
3808
  return end === NOT_FOUND3 ? rest : rest.slice(0, end);
3807
3809
  }
3808
- function entry_value(line, key2) {
3810
+ function url_value(line) {
3809
3811
  const separator = line.indexOf("=");
3810
3812
  if (separator === NOT_FOUND3) return void 0;
3811
- if (line.slice(0, separator).trim() !== key2) return void 0;
3813
+ if (line.slice(0, separator).trim() !== URL_KEY) return void 0;
3812
3814
  return line.slice(separator + 1).trim();
3813
3815
  }
3814
3816
  function parse_origin_from_config(content) {
3815
3817
  const lines = content.split("\n").map((line) => line.trim());
3816
- return origin_section_lines(lines).map((line) => entry_value(line, URL_KEY)).find((url) => url !== void 0);
3818
+ return origin_section_lines(lines).map((line) => url_value(line)).find((url) => url !== void 0);
3817
3819
  }
3818
3820
  function section_groups(lines) {
3819
3821
  const groups = [];
@@ -3825,7 +3827,7 @@ function section_groups(lines) {
3825
3827
  }
3826
3828
  function parse_remote_urls_from_config(content) {
3827
3829
  const lines = content.split("\n").map((line) => line.trim());
3828
- return section_groups(lines).filter((group) => REMOTE_SECTION.test(group[0] ?? "")).flatMap((group) => group.map((line) => entry_value(line, URL_KEY))).filter((url) => url !== void 0);
3830
+ return section_groups(lines).filter((group) => REMOTE_SECTION.test(group[0] ?? "")).flatMap((group) => group.map((line) => url_value(line))).filter((url) => url !== void 0);
3829
3831
  }
3830
3832
  function format_identity(identity) {
3831
3833
  return `${identity.owner}${PATH_SEPARATOR2}${identity.repo}`.toLowerCase();
@@ -3890,13 +3892,13 @@ function resolve_common_directory(git_directory) {
3890
3892
  const pointer = path5.join(git_directory, COMMON_DIRECTORY_FILE);
3891
3893
  if (!existsSync3(pointer)) return git_directory;
3892
3894
  try {
3893
- return path5.resolve(git_directory, readFileSync3(pointer, "utf8").trim());
3895
+ return path5.resolve(git_directory, readFileSync2(pointer, "utf8").trim());
3894
3896
  } catch {
3895
3897
  return git_directory;
3896
3898
  }
3897
3899
  }
3898
3900
  function follow_git_file(repository_path, git_file) {
3899
- const pointer = readFileSync3(git_file, "utf8").trim();
3901
+ const pointer = readFileSync2(git_file, "utf8").trim();
3900
3902
  if (!pointer.startsWith(GITDIR_PREFIX)) return void 0;
3901
3903
  return path5.resolve(repository_path, pointer.slice(GITDIR_PREFIX.length).trim());
3902
3904
  }
@@ -3915,7 +3917,7 @@ function read_config(repository_path) {
3915
3917
  const git_directory = resolve_git_directory(repository_path);
3916
3918
  if (git_directory === void 0) return void 0;
3917
3919
  try {
3918
- return readFileSync3(path5.join(git_directory, GIT_CONFIG), "utf8");
3920
+ return readFileSync2(path5.join(git_directory, GIT_CONFIG), "utf8");
3919
3921
  } catch {
3920
3922
  return void 0;
3921
3923
  }
@@ -3952,14 +3954,14 @@ function main_worktree(repository_path) {
3952
3954
  if (path5.basename(git_directory) !== GIT_DIRECTORY) return repository_path;
3953
3955
  return path5.dirname(git_directory);
3954
3956
  }
3955
- function discover_repositories(repository_path, environment2 = process.env) {
3957
+ function discover_repositories(repository_path, environment3 = process.env) {
3956
3958
  const main2 = main_worktree(repository_path);
3957
3959
  const current_owner2 = resolve_current_owner(main2);
3958
3960
  if (current_owner2 === void 0) return /* @__PURE__ */ new Map();
3959
3961
  return repo_map_logic.build_repository_map(
3960
3962
  scan_siblings(path5.dirname(main2)),
3961
3963
  current_owner2,
3962
- environment2[OVERRIDE_ENV_KEY]
3964
+ environment3[OVERRIDE_ENV_KEY]
3963
3965
  );
3964
3966
  }
3965
3967
  var repo_discovery = {
@@ -3994,8 +3996,8 @@ function gh_repo_owners(gh_repo) {
3994
3996
  function remote_owners(repository_path) {
3995
3997
  return repo_discovery.read_remote_urls(repository_path).map((url) => repo_origin.parse_origin_url(url)?.owner);
3996
3998
  }
3997
- function placeholder_owners(repository_path = process.cwd(), environment2 = process.env) {
3998
- const gh_repo = environment2[GH_REPO_ENV_KEY];
3999
+ function placeholder_owners(repository_path = process.cwd(), environment3 = process.env) {
4000
+ const gh_repo = environment3[GH_REPO_ENV_KEY];
3999
4001
  return gh_repo === void 0 || gh_repo === "" ? remote_owners(repository_path) : gh_repo_owners(gh_repo);
4000
4002
  }
4001
4003
  var repo_party = {
@@ -4009,23 +4011,22 @@ var repo_party = {
4009
4011
  };
4010
4012
 
4011
4013
  // scripts/lane/lane-reap.ts
4012
- import { execFileSync as execFileSync3 } from "node:child_process";
4014
+ import { execFileSync as execFileSync2 } from "node:child_process";
4013
4015
  var PGREP_COMMAND = "pgrep";
4014
4016
  var MATCH_FULL_COMMAND_LINE = "-f";
4015
4017
  var CHILDREN_OF_FLAG = "-P";
4016
- var PS_COMMAND2 = "/bin/ps";
4018
+ var PS_COMMAND = "/bin/ps";
4017
4019
  var PARENT_FORMAT = ["-o", "ppid=", "-p"];
4018
4020
  var TERMINATE_SIGNAL = "SIGTERM";
4019
- var PROBE_TIMEOUT_MS3 = 2e3;
4020
4021
  var LOWEST_CHILD_PID = 2;
4021
4022
  function parse_pids(printed) {
4022
4023
  return printed.split("\n").map((line) => Number(line.trim())).filter((pid) => Number.isSafeInteger(pid) && pid >= LOWEST_CHILD_PID);
4023
4024
  }
4024
4025
  function run_probe(command, args) {
4025
4026
  try {
4026
- return execFileSync3(command, [...args], {
4027
+ return execFileSync2(command, [...args], {
4027
4028
  encoding: "utf8",
4028
- timeout: PROBE_TIMEOUT_MS3,
4029
+ timeout: PROBE_TIMEOUT_MS,
4029
4030
  stdio: ["ignore", "pipe", "ignore"]
4030
4031
  });
4031
4032
  } catch {
@@ -4033,7 +4034,7 @@ function run_probe(command, args) {
4033
4034
  }
4034
4035
  }
4035
4036
  function parent_of(pid) {
4036
- return parse_pids(run_probe(PS_COMMAND2, [...PARENT_FORMAT, String(pid)]))[0];
4037
+ return parse_pids(run_probe(PS_COMMAND, [...PARENT_FORMAT, String(pid)]))[0];
4037
4038
  }
4038
4039
  function terminate(pid) {
4039
4040
  try {
@@ -4101,15 +4102,9 @@ function ls_remote_branch_arguments(branch_name) {
4101
4102
  }
4102
4103
 
4103
4104
  // scripts/git/repository-lock.ts
4104
- import { randomUUID as randomUUID3 } from "node:crypto";
4105
- import { linkSync, renameSync, rmSync as rmSync2 } from "node:fs";
4105
+ import { randomUUID as randomUUID2 } from "node:crypto";
4106
+ import { linkSync, renameSync, rmSync } from "node:fs";
4106
4107
  import { setTimeout as sleep2 } from "node:timers/promises";
4107
-
4108
- // scripts/josh/process-owner.ts
4109
- import { z as z9 } from "zod";
4110
- var process_owner_schema = z9.object({ pid: z9.number(), process_start: z9.string().optional() });
4111
-
4112
- // scripts/git/repository-lock.ts
4113
4108
  var POLL_INTERVAL_MS = 200;
4114
4109
  function lock_path(prefix, cwd) {
4115
4110
  return stamp_file.stamp_path(prefix, git_common_directory.repository(cwd) ?? cwd ?? process.cwd());
@@ -4137,7 +4132,7 @@ function stale_record(target, is_gone2) {
4137
4132
  return owner !== void 0 && is_gone2(owner) ? raw : void 0;
4138
4133
  }
4139
4134
  function move_aside(target) {
4140
- const aside = `${target}.${String(process.pid)}.${randomUUID3()}`;
4135
+ const aside = `${target}.${String(process.pid)}.${randomUUID2()}`;
4141
4136
  try {
4142
4137
  renameSync(target, aside);
4143
4138
  return aside;
@@ -4151,7 +4146,7 @@ function clear_stale(target, is_gone2 = is_owner_gone) {
4151
4146
  const aside = move_aside(target);
4152
4147
  if (aside === void 0) return;
4153
4148
  if (stamp_file.read_stamp_text(aside) !== raw) restore(aside, target);
4154
- rmSync2(aside, { force: true });
4149
+ rmSync(aside, { force: true });
4155
4150
  }
4156
4151
  function claim(target) {
4157
4152
  clear_stale(target);
@@ -4285,13 +4280,13 @@ function read_lane_seat(content) {
4285
4280
  return raw === void 0 ? void 0 : ports.resolve_lane({ [LANE_SEAT_KEY]: raw });
4286
4281
  }
4287
4282
  function read_lane_ports(content) {
4288
- const environment2 = {
4283
+ const environment3 = {
4289
4284
  [PORT_SEED_KEY]: read_assignment(content, PORT_SEED_KEY),
4290
4285
  [LANE_SEAT_KEY]: read_assignment(content, LANE_SEAT_KEY)
4291
4286
  };
4292
4287
  return {
4293
- development: ports.resolve_development_port(environment2),
4294
- preview: ports.resolve_preview_port(environment2)
4288
+ development: ports.resolve_development_port(environment3),
4289
+ preview: ports.resolve_preview_port(environment3)
4295
4290
  };
4296
4291
  }
4297
4292
  function read_lane_output(content) {
@@ -4310,7 +4305,8 @@ function read_lane_profile(content) {
4310
4305
  function replace_assignment(lines, keep, assignment, key2) {
4311
4306
  return lines.flatMap((entry, index) => {
4312
4307
  if (index === keep) return [assignment];
4313
- return is_key_line(entry, key2) ? [] : [entry];
4308
+ if (is_key_line(entry, key2)) return [];
4309
+ return [entry];
4314
4310
  });
4315
4311
  }
4316
4312
  function upsert_assignment(content, key2, value) {
@@ -4453,10 +4449,10 @@ var lane_registry = {
4453
4449
  // scripts/run/run-headless.ts
4454
4450
  var HEADLESS_ENV_KEY = "JOSH_RUN_HEADLESS";
4455
4451
  var HEADLESS_VALUE = "1";
4456
- function environment() {
4452
+ function environment2() {
4457
4453
  return { [HEADLESS_ENV_KEY]: HEADLESS_VALUE };
4458
4454
  }
4459
- function is_headless(source = process.env) {
4455
+ function is_headless2(source = process.env) {
4460
4456
  return source[HEADLESS_ENV_KEY] === HEADLESS_VALUE;
4461
4457
  }
4462
4458
  function is_driving(read3) {
@@ -4467,7 +4463,7 @@ async function read_carry_here() {
4467
4463
  return repository2 === void 0 ? void 0 : run_carry.read_carry(run_carry.carry_path(repository2));
4468
4464
  }
4469
4465
  async function must_keep_waiting(source = process.env) {
4470
- const is_candidate2 = is_headless(source) && lane_child_marker.marked_issue(source) === void 0;
4466
+ const is_candidate2 = is_headless2(source) && lane_child_marker.marked_issue(source) === void 0;
4471
4467
  if (!is_candidate2 || !await lane_registry.has_lanes_in_flight()) return false;
4472
4468
  return is_driving(await read_carry_here());
4473
4469
  }
@@ -4493,9 +4489,9 @@ var run_headless = {
4493
4489
  HEADLESS_ENV_KEY,
4494
4490
  current_carry,
4495
4491
  driving_carry,
4496
- environment,
4492
+ environment: environment2,
4497
4493
  is_backlog_parent,
4498
- is_headless,
4494
+ is_headless: is_headless2,
4499
4495
  is_owned_here,
4500
4496
  must_keep_waiting
4501
4497
  };
@@ -4561,8 +4557,8 @@ var issue_cite = {
4561
4557
 
4562
4558
  // scripts/gh/git-gh-api-path.ts
4563
4559
  var FULL_PAGE_QUERY = "?per_page=100";
4564
- function repo_api_path(repo) {
4565
- return `repos/${repo ?? "{owner}/{repo}"}`;
4560
+ function repo_api_path(repo = "{owner}/{repo}") {
4561
+ return `repos/${repo}`;
4566
4562
  }
4567
4563
  function issues_api_path(repo) {
4568
4564
  return `${repo_api_path(repo)}/issues`;
@@ -4628,10 +4624,6 @@ var git_gh_api_path = {
4628
4624
  // scripts/gh/git-gh-exec.ts
4629
4625
  import { execa as execa5, execaSync as execaSync3 } from "execa";
4630
4626
 
4631
- // scripts/lib/timeouts.ts
4632
- var FETCH_TIMEOUT_MS = 1e4;
4633
- var COMMAND_TIMEOUT_MS = 3e4;
4634
-
4635
4627
  // scripts/gh/git-gh-check.ts
4636
4628
  import { execa as execa4 } from "execa";
4637
4629
  var GH_NOT_INSTALLED_MSG = "gh CLI is not installed. Install it from https://cli.github.com/";
@@ -4682,8 +4674,8 @@ var parse_json = {
4682
4674
  };
4683
4675
 
4684
4676
  // scripts/gh/git-gh-failure.ts
4685
- import { z as z10 } from "zod";
4686
- var error_document_schema = z10.object({ status: z10.union([z10.string(), z10.number()]).optional() }).catch({});
4677
+ import { z as z9 } from "zod";
4678
+ var error_document_schema = z9.object({ status: z9.union([z9.string(), z9.number()]).optional() }).catch({});
4687
4679
  var GH_FAILURE_FIELD = "gh_failure";
4688
4680
  function has_gh_failure(error) {
4689
4681
  return error instanceof Error && Object.hasOwn(error, GH_FAILURE_FIELD);
@@ -4886,7 +4878,7 @@ var git_gh_helpers = {
4886
4878
  };
4887
4879
 
4888
4880
  // scripts/gh/git-gh-issue-rest.ts
4889
- import { z as z11 } from "zod";
4881
+ import { z as z10 } from "zod";
4890
4882
 
4891
4883
  // scripts/gh/git-gh-rest-state.ts
4892
4884
  var MERGED_STATE = "MERGED";
@@ -4895,11 +4887,11 @@ function to_gh_state(state) {
4895
4887
  }
4896
4888
 
4897
4889
  // scripts/gh/git-gh-issue-rest.ts
4898
- var rest_issue_schema = z11.looseObject({
4899
- number: z11.number(),
4900
- issue_dependencies_summary: z11.looseObject({ total_blocked_by: z11.number().optional() }).nullish(),
4890
+ var rest_issue_schema = z10.looseObject({
4891
+ number: z10.number(),
4892
+ issue_dependencies_summary: z10.looseObject({ total_blocked_by: z10.number().optional() }).nullish(),
4901
4893
  // Present only on a pull request, which this endpoint serves as readily as an issue.
4902
- pull_request: z11.looseObject({ merged_at: z11.string().nullish() }).nullish()
4894
+ pull_request: z10.looseObject({ merged_at: z10.string().nullish() }).nullish()
4903
4895
  });
4904
4896
  var REPOSITORY_URL = /\/repos\/([\w.-]+\/[\w.-]+)$/u;
4905
4897
  var REPOSITORY_URL_GROUP = 1;
@@ -4951,8 +4943,8 @@ function parse_rest_issues(rest_json) {
4951
4943
  function empty_blocked_by() {
4952
4944
  return { nodes: [], totalCount: 0 };
4953
4945
  }
4954
- function repo_of_url(repository_url) {
4955
- const match = REPOSITORY_URL.exec(repository_url ?? "");
4946
+ function repo_of_url(repository_url = "") {
4947
+ const match = REPOSITORY_URL.exec(repository_url);
4956
4948
  return match?.[REPOSITORY_URL_GROUP];
4957
4949
  }
4958
4950
  function to_blocked_by(blockers_json, exact_total) {
@@ -5246,6 +5238,7 @@ var PATCH_METHOD = "PATCH";
5246
5238
  var DELETE_METHOD = "DELETE";
5247
5239
  var HTML_URL_FILTER = ".html_url";
5248
5240
  var ID_FILTER = ".id";
5241
+ var LABEL_NAMES_FILTER = ".[].name";
5249
5242
  var LABELS_SEGMENT = "/labels";
5250
5243
  var COMMENTS_SEGMENT = "/comments";
5251
5244
  var CLOSED_STATE = "closed";
@@ -5320,13 +5313,35 @@ async function issue_create_with_label(input) {
5320
5313
  issue_create_request({ title: input.title, body: input.body, labels: [input.label] })
5321
5314
  );
5322
5315
  }
5323
- async function issue_add_label(issue_number, label2) {
5324
- return await did_write_succeed(
5325
- async () => await git_gh_exec.exec_gh_api({
5316
+ async function read_label_names(issue_number) {
5317
+ try {
5318
+ const raw = await git_gh_exec.exec_gh_api({
5326
5319
  path: `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`,
5327
- body: JSON.stringify({ labels: [label2] })
5328
- })
5329
- );
5320
+ should_paginate: true,
5321
+ jq_filter: LABEL_NAMES_FILTER
5322
+ });
5323
+ return raw.split("\n").map((name) => name.trim());
5324
+ } catch (error) {
5325
+ error_text.trace_swallowed("git_gh_issue_write.read_label_names", error);
5326
+ return void 0;
5327
+ }
5328
+ }
5329
+ async function issue_apply_label(issue_number, label2) {
5330
+ const labels_path = `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`;
5331
+ try {
5332
+ await git_gh_exec.exec_gh_api({ path: labels_path, body: JSON.stringify({ labels: [label2] }) });
5333
+ return { is_applied: true };
5334
+ } catch (error) {
5335
+ const names = await read_label_names(issue_number);
5336
+ if (names?.includes(label2) === true) return { is_applied: true };
5337
+ error_text.trace_swallowed("git_gh_issue_write.issue_apply_label", error);
5338
+ const [gist = ""] = error_text.message_of(error).split("\n", 1);
5339
+ return { is_applied: false, reason: gist };
5340
+ }
5341
+ }
5342
+ async function issue_add_label(issue_number, label2) {
5343
+ const write = await issue_apply_label(issue_number, label2);
5344
+ return write.is_applied;
5330
5345
  }
5331
5346
  async function issue_remove_label(issue_number, label2) {
5332
5347
  const labels_path = `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`;
@@ -5373,6 +5388,7 @@ var git_gh_issue_write = {
5373
5388
  label_ensure,
5374
5389
  issue_create_request,
5375
5390
  issue_create_with_label,
5391
+ issue_apply_label,
5376
5392
  issue_add_label,
5377
5393
  issue_remove_label,
5378
5394
  issue_add_blocked_by,
@@ -5433,20 +5449,20 @@ var git_gh_issue = {
5433
5449
  };
5434
5450
 
5435
5451
  // scripts/ci/pr-classification.ts
5436
- import { readFileSync as readFileSync4 } from "node:fs";
5452
+ import { readFileSync as readFileSync3 } from "node:fs";
5437
5453
  import { fileURLToPath as fileURLToPath2 } from "node:url";
5438
- import { z as z12 } from "zod";
5454
+ import { z as z11 } from "zod";
5439
5455
  var CLASSIFICATION_SET = new Set(RELEASE_CLASSIFICATION_NAMES);
5440
5456
  var ISSUE_BUG_LABEL = "bug";
5441
5457
  var DECLARATION_PREFIX = "- \u30EA\u30EA\u30FC\u30B9\u5206\u985E: ";
5442
5458
  var DECLARATION = new RegExp(`^${DECLARATION_PREFIX}(.+)$`, "gmu");
5443
5459
  var LEGACY_LABELS = /* @__PURE__ */ new Set(["semver-major", "semver-minor"]);
5444
- var LABEL = z12.object({ name: z12.string() });
5445
- var USER = z12.object({ login: z12.string() });
5446
- var PULL_REQUEST = z12.object({ number: z12.number(), user: USER });
5447
- var EVENT = z12.object({
5460
+ var LABEL = z11.object({ name: z11.string() });
5461
+ var USER = z11.object({ login: z11.string() });
5462
+ var PULL_REQUEST = z11.object({ number: z11.number(), user: USER });
5463
+ var EVENT = z11.object({
5448
5464
  pull_request: PULL_REQUEST,
5449
- repository: z12.object({ full_name: z12.string() })
5465
+ repository: z11.object({ full_name: z11.string() })
5450
5466
  });
5451
5467
  function classification_error(labels, author) {
5452
5468
  const legacy = labels.filter((label2) => LEGACY_LABELS.has(label2.toLowerCase()));
@@ -5469,7 +5485,7 @@ function release_candidates(candidates) {
5469
5485
  return candidates.filter((candidate) => candidate !== ENHANCEMENT_LABEL);
5470
5486
  }
5471
5487
  function issue_candidates(issue_json) {
5472
- const issue = z12.object({ labels: z12.array(LABEL), body: z12.string().nullable() }).parse(JSON.parse(issue_json));
5488
+ const issue = z11.object({ labels: z11.array(LABEL), body: z11.string().nullable() }).parse(JSON.parse(issue_json));
5473
5489
  const names = issue.labels.map((label2) => label2.name.toLowerCase());
5474
5490
  const declared = [...(issue.body ?? "").matchAll(DECLARATION)].map((match) => match[1] ?? "");
5475
5491
  const candidates = [...release_candidates([...names, ...declared].filter(is_classification))];
@@ -5502,7 +5518,7 @@ function fetch_current_labels(repository2, pull_number) {
5502
5518
  }
5503
5519
  }
5504
5520
  function check_event(event_path, read_labels = fetch_current_labels) {
5505
- const event = EVENT.parse(JSON.parse(readFileSync4(event_path, "utf8")));
5521
+ const event = EVENT.parse(JSON.parse(readFileSync3(event_path, "utf8")));
5506
5522
  const labels = read_labels(event.repository.full_name, event.pull_request.number);
5507
5523
  return classification_error(labels, event.pull_request.user.login);
5508
5524
  }
@@ -5544,31 +5560,31 @@ async function poll_until(is_done2, options) {
5544
5560
  var poll = { poll_until, sleep: sleep3 };
5545
5561
 
5546
5562
  // scripts/gh/git-gh-pr.ts
5547
- import { z as z16 } from "zod";
5563
+ import { z as z15 } from "zod";
5548
5564
 
5549
5565
  // scripts/gh/git-gh-pr-rest.ts
5550
- import { z as z13 } from "zod";
5551
- var rest_repo_schema = z13.looseObject({ full_name: z13.string().optional() }).nullish();
5552
- var rest_pull_side_schema = z13.looseObject({ repo: rest_repo_schema });
5553
- var rest_pull_schema = z13.looseObject({
5554
- number: z13.number(),
5555
- html_url: z13.string().optional(),
5556
- body: z13.string().nullish(),
5557
- state: z13.string().optional(),
5558
- merged: z13.boolean().nullish(),
5559
- merged_at: z13.string().nullish(),
5560
- mergeable: z13.boolean().nullish(),
5561
- mergeable_state: z13.string().optional(),
5566
+ import { z as z12 } from "zod";
5567
+ var rest_repo_schema = z12.looseObject({ full_name: z12.string().optional() }).nullish();
5568
+ var rest_pull_side_schema = z12.looseObject({ repo: rest_repo_schema });
5569
+ var rest_pull_schema = z12.looseObject({
5570
+ number: z12.number(),
5571
+ html_url: z12.string().optional(),
5572
+ body: z12.string().nullish(),
5573
+ state: z12.string().optional(),
5574
+ merged: z12.boolean().nullish(),
5575
+ merged_at: z12.string().nullish(),
5576
+ mergeable: z12.boolean().nullish(),
5577
+ mergeable_state: z12.string().optional(),
5562
5578
  // `sha` is the head commit, which is what both halves of the merge-gate rollup are keyed by —
5563
5579
  // REST hangs the check runs and the status contexts off the commit rather than off the pull
5564
5580
  // request (joshuafolkken/kit#1028).
5565
- head: z13.looseObject({ ref: z13.string().optional(), sha: z13.string().optional(), repo: rest_repo_schema }).nullish(),
5581
+ head: z12.looseObject({ ref: z12.string().optional(), sha: z12.string().optional(), repo: rest_repo_schema }).nullish(),
5566
5582
  base: rest_pull_side_schema.nullish(),
5567
5583
  // `node_id` is what the GraphQL auto-merge mutation addresses a pull request by, and `auto_merge`
5568
5584
  // is `null` until auto-merge is enabled — both read by `git-gh-pr-auto-merge.ts`
5569
5585
  // (joshuafolkken/kit#2497).
5570
- node_id: z13.string().optional(),
5571
- auto_merge: z13.looseObject({}).nullish()
5586
+ node_id: z12.string().optional(),
5587
+ auto_merge: z12.looseObject({}).nullish()
5572
5588
  });
5573
5589
  var NOT_A_PULL_MESSAGE = "gh api answered something other than a pull request object";
5574
5590
  var NOT_A_PULL_LISTING_MESSAGE = "gh api answered something other than a pull request listing";
@@ -5644,6 +5660,7 @@ async function fetch_pr_number(branch_name) {
5644
5660
  return git_gh_pr_rest.select_pull(git_gh_pr_rest.parse_rest_pulls(json))?.number;
5645
5661
  }
5646
5662
  var pending_pr_number_by_branch = /* @__PURE__ */ new Map();
5663
+ var pull_by_number = /* @__PURE__ */ new Map();
5647
5664
  async function fetch_pr_number_read(branch_name) {
5648
5665
  try {
5649
5666
  const pr_number = await fetch_pr_number(branch_name);
@@ -5668,6 +5685,7 @@ async function start_pr_number_read(branch_name) {
5668
5685
  function forget_pr_numbers() {
5669
5686
  pr_number_by_branch.clear();
5670
5687
  pending_pr_number_by_branch.clear();
5688
+ pull_by_number.clear();
5671
5689
  }
5672
5690
  async function read_pr_number(branch_name) {
5673
5691
  const cached = pr_number_by_branch.get(branch_name);
@@ -5693,15 +5711,29 @@ async function read_pull(pr_number) {
5693
5711
  });
5694
5712
  return git_gh_pr_rest.parse_rest_pull(json);
5695
5713
  }
5696
- async function read_pull_of_branch(branch_name) {
5697
- const pr_number = await resolve_pr_number(branch_name);
5698
- if (pr_number === void 0) return void 0;
5714
+ async function read_remembered_pull(pr_number) {
5715
+ const pending = pull_by_number.get(pr_number) ?? read_pull(pr_number);
5716
+ pull_by_number.set(pr_number, pending);
5699
5717
  try {
5700
- return await read_pull(pr_number);
5701
- } catch {
5702
- return void 0;
5718
+ return await pending;
5719
+ } catch (error) {
5720
+ if (pull_by_number.get(pr_number) === pending) pull_by_number.delete(pr_number);
5721
+ throw error;
5722
+ }
5723
+ }
5724
+ async function read_pull_of_branch(branch_name, read3 = read_remembered_pull) {
5725
+ const number_read = await read_pr_number(branch_name);
5726
+ if (number_read.kind !== "read") return number_read;
5727
+ try {
5728
+ return { kind: "read", pull: await read3(number_read.pr_number) };
5729
+ } catch (error) {
5730
+ return { kind: "unreadable", cause: error };
5703
5731
  }
5704
5732
  }
5733
+ async function read_pull_or_undefined(branch_name) {
5734
+ const read3 = await read_pull_of_branch(branch_name);
5735
+ return read3.kind === "read" ? read3.pull : void 0;
5736
+ }
5705
5737
  async function pr_exists(branch_name) {
5706
5738
  const read3 = await read_pr_number(branch_name);
5707
5739
  if (read3.kind === "unreadable") throw to_unreadable_error(branch_name, read3.cause);
@@ -5711,13 +5743,14 @@ async function pr_get_number(branch_name) {
5711
5743
  return await resolve_pr_number(branch_name);
5712
5744
  }
5713
5745
  async function pr_get_url(branch_name) {
5714
- const pull = await read_pull_of_branch(branch_name);
5746
+ const pull = await read_pull_or_undefined(branch_name);
5715
5747
  if (pull?.html_url === void 0) return void 0;
5716
5748
  return git_gh_helpers.parse_pr_state_string(pull.html_url);
5717
5749
  }
5718
5750
  async function pr_get_merge_state(branch_name) {
5719
- const pull = await read_pull_of_branch(branch_name);
5720
- if (pull === void 0) return void 0;
5751
+ const read3 = await read_pull_of_branch(branch_name, read_pull);
5752
+ if (read3.kind !== "read") return void 0;
5753
+ const { pull } = read3;
5721
5754
  return {
5722
5755
  is_merged: git_gh_pr_rest.is_merged(pull),
5723
5756
  merged_at: pull.merged_at ?? void 0,
@@ -5726,14 +5759,15 @@ async function pr_get_merge_state(branch_name) {
5726
5759
  };
5727
5760
  }
5728
5761
  async function pr_get_body(branch_name) {
5729
- const pull = await read_pull_of_branch(branch_name);
5762
+ const pull = await read_pull_or_undefined(branch_name);
5730
5763
  const body = pull?.body;
5731
5764
  return typeof body === "string" && body.length > 0 ? body : void 0;
5732
5765
  }
5733
5766
  async function pr_view(branch_name) {
5734
- const pull = await read_pull_of_branch(branch_name);
5735
- if (pull === void 0) return "";
5736
- return JSON.stringify(git_gh_pr_rest.to_pr_info(pull));
5767
+ const read3 = await read_pull_of_branch(branch_name, read_pull);
5768
+ if (read3.kind === "unreadable") throw to_unreadable_error(branch_name, read3.cause);
5769
+ if (read3.kind === "missing") return "";
5770
+ return JSON.stringify(git_gh_pr_rest.to_pr_info(read3.pull));
5737
5771
  }
5738
5772
  async function read_comments(branch_name, to_path, to_json) {
5739
5773
  const pr_number = await resolve_pr_number(branch_name);
@@ -5769,14 +5803,14 @@ var git_gh_pr_read = {
5769
5803
  };
5770
5804
 
5771
5805
  // scripts/gh/git-gh-pr-review.ts
5772
- import { z as z14 } from "zod";
5806
+ import { z as z13 } from "zod";
5773
5807
  var REVIEW_APPROVED = "APPROVED";
5774
5808
  var REVIEW_CHANGES_REQUESTED = "CHANGES_REQUESTED";
5775
5809
  var REVIEW_NONE = "";
5776
5810
  var STATE_CHANGING_REVIEWS = /* @__PURE__ */ new Set([REVIEW_APPROVED, REVIEW_CHANGES_REQUESTED]);
5777
- var rest_review_schema = z14.looseObject({
5778
- state: z14.string().optional(),
5779
- user: z14.looseObject({ login: z14.string().optional() }).nullish()
5811
+ var rest_review_schema = z13.looseObject({
5812
+ state: z13.string().optional(),
5813
+ user: z13.looseObject({ login: z13.string().optional() }).nullish()
5780
5814
  });
5781
5815
  var NOT_A_REVIEW_LISTING = "gh api answered something other than a review listing";
5782
5816
  function parse_rest_reviews(reviews_json) {
@@ -5809,18 +5843,18 @@ function to_review_decision(reviews_json) {
5809
5843
  var git_gh_pr_review = { to_review_decision };
5810
5844
 
5811
5845
  // scripts/gh/git-gh-pr-rollup.ts
5812
- import { z as z15 } from "zod";
5846
+ import { z as z14 } from "zod";
5813
5847
  var STATUS_CONTEXT_TYPE_NAME = "StatusContext";
5814
5848
  var TYPE_NAME_KEY = "__typename";
5815
- var rollup_element_schema = z15.looseObject({});
5816
- var check_runs_page_schema = z15.looseObject({
5849
+ var rollup_element_schema = z14.looseObject({});
5850
+ var check_runs_page_schema = z14.looseObject({
5817
5851
  // Required, not optional: GitHub always names the key, and accepting a page without one would
5818
5852
  // answer an empty rollup — which `git-pr-followup.ts` reports as "this branch has no checks".
5819
- check_runs: z15.array(rollup_element_schema)
5853
+ check_runs: z14.array(rollup_element_schema)
5820
5854
  });
5821
- var id_holder_schema = z15.object({ id: z15.number() });
5822
- var status_page_schema = z15.looseObject({
5823
- statuses: z15.array(rollup_element_schema)
5855
+ var id_holder_schema = z14.object({ id: z14.number() });
5856
+ var status_page_schema = z14.looseObject({
5857
+ statuses: z14.array(rollup_element_schema)
5824
5858
  });
5825
5859
  var NOT_A_CHECK_RUNS_LISTING = "gh api answered something other than a check run listing";
5826
5860
  var NOT_A_STATUS_LISTING = "gh api answered something other than a commit status listing";
@@ -5834,15 +5868,15 @@ function read_id(value) {
5834
5868
  const parsed = id_holder_schema.safeParse(value);
5835
5869
  return parsed.success ? parsed.data.id : void 0;
5836
5870
  }
5837
- function check_run_group_key(run3) {
5838
- const { name, app } = run3;
5871
+ function check_run_group_key(run4) {
5872
+ const { name, app } = run4;
5839
5873
  if (typeof name !== "string") return void 0;
5840
5874
  return JSON.stringify([name, read_id(app)]);
5841
5875
  }
5842
- function read_rank(run3) {
5843
- const id = read_id(run3);
5876
+ function read_rank(run4) {
5877
+ const id = read_id(run4);
5844
5878
  if (id === void 0) return void 0;
5845
- return { suite: read_id(run3["check_suite"]) ?? NO_SUITE, run: id };
5879
+ return { suite: read_id(run4["check_suite"]) ?? NO_SUITE, run: id };
5846
5880
  }
5847
5881
  function is_ranked_above(candidate, current) {
5848
5882
  if (candidate.suite !== current.suite) return candidate.suite > current.suite;
@@ -5852,23 +5886,23 @@ function should_replace(previous, rank) {
5852
5886
  const previous_rank = previous === void 0 ? void 0 : read_rank(previous);
5853
5887
  return previous_rank === void 0 || is_ranked_above(rank, previous_rank);
5854
5888
  }
5855
- function remember_newest_run(run3, newest) {
5856
- const key2 = check_run_group_key(run3);
5857
- const rank = read_rank(run3);
5889
+ function remember_newest_run(run4, newest) {
5890
+ const key2 = check_run_group_key(run4);
5891
+ const rank = read_rank(run4);
5858
5892
  if (key2 === void 0 || rank === void 0) return;
5859
- if (should_replace(newest.get(key2), rank)) newest.set(key2, run3);
5893
+ if (should_replace(newest.get(key2), rank)) newest.set(key2, run4);
5860
5894
  }
5861
- function is_newest_run(run3, newest) {
5862
- const key2 = check_run_group_key(run3);
5863
- if (key2 === void 0 || read_rank(run3) === void 0) return true;
5864
- return newest.get(key2) === run3;
5895
+ function is_newest_run(run4, newest) {
5896
+ const key2 = check_run_group_key(run4);
5897
+ if (key2 === void 0 || read_rank(run4) === void 0) return true;
5898
+ return newest.get(key2) === run4;
5865
5899
  }
5866
5900
  function to_check_run_items(check_runs_json) {
5867
5901
  const pages = read_pages(check_runs_json, check_runs_page_schema, NOT_A_CHECK_RUNS_LISTING);
5868
5902
  const runs = pages.flatMap((page) => page.check_runs);
5869
5903
  const newest = /* @__PURE__ */ new Map();
5870
- for (const run3 of runs) remember_newest_run(run3, newest);
5871
- return runs.filter((run3) => is_newest_run(run3, newest));
5904
+ for (const run4 of runs) remember_newest_run(run4, newest);
5905
+ return runs.filter((run4) => is_newest_run(run4, newest));
5872
5906
  }
5873
5907
  function to_status_context_items(status_json) {
5874
5908
  const pages = read_pages(status_json, status_page_schema, NOT_A_STATUS_LISTING);
@@ -5954,7 +5988,7 @@ var MERGE_READ_BACK_ATTEMPTS = 3;
5954
5988
  var MERGE_READ_BACK_INTERVAL_MS = 1e3;
5955
5989
  var PR_NUMBER_PATTERN = /\/pull\/([1-9]\d*)$/u;
5956
5990
  var LABELS_SEGMENT2 = "/labels";
5957
- var PR_LABELS = z16.array(z16.object({ name: z16.string() }));
5991
+ var PR_LABELS = z15.array(z15.object({ name: z15.string() }));
5958
5992
  async function add_pr_classification(number, label2) {
5959
5993
  await git_gh_exec.exec_gh_api({
5960
5994
  path: `${git_gh_api_path.issue_api_path(number)}${LABELS_SEGMENT2}`,
@@ -6007,6 +6041,7 @@ async function pr_comment(branch_name, body) {
6007
6041
  }
6008
6042
  async function pr_update_body(branch_name, body) {
6009
6043
  const pr_number = await require_pr_number(branch_name);
6044
+ forget_pr_numbers();
6010
6045
  await git_gh_exec.exec_gh_api({
6011
6046
  path: git_gh_api_path.pull_api_path(String(pr_number)),
6012
6047
  method: PATCH_METHOD2,
@@ -6014,6 +6049,7 @@ async function pr_update_body(branch_name, body) {
6014
6049
  });
6015
6050
  }
6016
6051
  async function put_merge(pr_number) {
6052
+ forget_pr_numbers();
6017
6053
  await git_gh_exec.exec_gh_api({
6018
6054
  path: git_gh_api_path.pull_merge_api_path(String(pr_number)),
6019
6055
  method: PUT_METHOD,
@@ -6141,7 +6177,9 @@ var PR_CHECKS_TIMEOUT_MESSAGE = "Timed out while waiting for PR checks to comple
6141
6177
  function is_pr_checks_timeout(error) {
6142
6178
  return error instanceof Error && error.message === PR_CHECKS_TIMEOUT_MESSAGE;
6143
6179
  }
6144
- var SHOULD_ALWAYS_READ_REVIEW_DECISION = () => true;
6180
+ function should_always_read_review_decision() {
6181
+ return true;
6182
+ }
6145
6183
  var MERGE_GATE_EVALUATOR = {
6146
6184
  evaluate: evaluate_pr_state,
6147
6185
  describe: describe_pr_failure,
@@ -6168,7 +6206,7 @@ async function read_pr_state(input, evaluator) {
6168
6206
  try {
6169
6207
  const snapshot = await input.options.fetcher(
6170
6208
  input.options.branch_name,
6171
- evaluator.should_read_review_decision ?? SHOULD_ALWAYS_READ_REVIEW_DECISION
6209
+ evaluator.should_read_review_decision ?? should_always_read_review_decision
6172
6210
  );
6173
6211
  return { kind: "read", snapshot };
6174
6212
  } catch (error) {
@@ -6222,7 +6260,7 @@ async function wait_for_pr_success(options) {
6222
6260
  }
6223
6261
  throw to_exhaustion_error(carried.read_failure);
6224
6262
  }
6225
- async function default_fetch_pr_state(branch_name, should_read_review_decision = SHOULD_ALWAYS_READ_REVIEW_DECISION) {
6263
+ async function default_fetch_pr_state(branch_name, should_read_review_decision = should_always_read_review_decision) {
6226
6264
  const checks = await git_gh_pr_snapshot.pr_get_checks_snapshot(branch_name);
6227
6265
  const snapshot = parse_pr_state_snapshot(checks.snapshot_json);
6228
6266
  if (!should_read_review_decision(snapshot)) return snapshot;
@@ -6250,11 +6288,13 @@ function describe_checks_failure(snapshot) {
6250
6288
  const failed = snapshot.rollup.filter((check) => check.status === CHECK_STATUS_FAIL);
6251
6289
  return `${CHECKS_FAILED_MESSAGE}: ${failed.map((check) => check.name).join(", ")}`;
6252
6290
  }
6253
- var SHOULD_NEVER_READ_REVIEW_DECISION = () => false;
6291
+ function should_never_read_review_decision() {
6292
+ return false;
6293
+ }
6254
6294
  var CHECKS_SETTLED_EVALUATOR = {
6255
6295
  evaluate: evaluate_checks_settled,
6256
6296
  describe: describe_checks_failure,
6257
- should_read_review_decision: SHOULD_NEVER_READ_REVIEW_DECISION
6297
+ should_read_review_decision: should_never_read_review_decision
6258
6298
  };
6259
6299
  async function watch_until_settled(branch_name) {
6260
6300
  await wait_for_pr_success({
@@ -6270,7 +6310,7 @@ async function watch_until_settled(branch_name) {
6270
6310
  });
6271
6311
  }
6272
6312
  async function fail_when_no_checks(branch_name) {
6273
- const snapshot = await default_fetch_pr_state(branch_name, SHOULD_NEVER_READ_REVIEW_DECISION);
6313
+ const snapshot = await default_fetch_pr_state(branch_name, should_never_read_review_decision);
6274
6314
  if (snapshot.rollup.length === 0) throw new Error(NO_CHECKS_MESSAGE);
6275
6315
  }
6276
6316
  async function pr_checks_watch(branch_name) {
@@ -6304,7 +6344,6 @@ export {
6304
6344
  git_spawn_sync,
6305
6345
  git_command,
6306
6346
  git_common_directory,
6307
- error_text,
6308
6347
  tail_commands,
6309
6348
  filing_cap,
6310
6349
  CONTEXT_CUT_THRESHOLD,
@@ -6312,10 +6351,10 @@ export {
6312
6351
  cli_flags,
6313
6352
  own_session,
6314
6353
  backlog_budget,
6315
- run_cut_handoff,
6316
6354
  run_hold,
6355
+ run_cut_handoff,
6317
6356
  run_cut,
6318
- run_tail,
6357
+ run_tail_rule,
6319
6358
  lane_background,
6320
6359
  IN_PROGRESS_LABEL,
6321
6360
  NEEDS_DECISION_LABEL,
@@ -6325,7 +6364,7 @@ export {
6325
6364
  ALREADY_DONE_LABEL,
6326
6365
  has_any_label,
6327
6366
  has_label_name,
6328
- process_identity,
6367
+ agent_headless,
6329
6368
  run_event_stream,
6330
6369
  run_invocation,
6331
6370
  run_carry,
@@ -6334,11 +6373,9 @@ export {
6334
6373
  lane_park,
6335
6374
  repo_origin,
6336
6375
  repo_party,
6337
- process_owner_schema,
6338
6376
  lane_registry,
6339
6377
  run_headless,
6340
6378
  git_gh_api_path,
6341
- FETCH_TIMEOUT_MS,
6342
6379
  read_json_listing,
6343
6380
  parse_json_object_safe,
6344
6381
  git_gh_exec,