@joshuafolkken/kit 1.1471.0 → 1.1784.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 (895) hide show
  1. package/.claude/agents/investigator.md +1 -1
  2. package/.claude/settings.json +6 -6
  3. package/.claude/skills/epic-commands/SKILL.md +26 -77
  4. package/.claude/skills/epic-commands/epic-bundle.md +12 -6
  5. package/.claude/skills/epic-commands/execution-waves.md +1 -2
  6. package/.claude/skills/verify-ui/SKILL.md +1 -2
  7. package/.claude/skills/workflow-commands/SKILL.md +12 -14
  8. package/.claude/skills/workflow-commands/background-commands.md +8 -12
  9. package/.claude/skills/workflow-commands/backlogrun-child.md +13 -18
  10. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
  11. package/.claude/skills/workflow-commands/backlogrun-lanes.md +23 -28
  12. package/.claude/skills/workflow-commands/backlogrun-park.md +16 -31
  13. package/.claude/skills/workflow-commands/backlogrun-progress.md +12 -21
  14. package/.claude/skills/workflow-commands/backlogrun-recovery.md +12 -12
  15. package/.claude/skills/workflow-commands/backlogrun-steps.md +12 -20
  16. package/.claude/skills/workflow-commands/backlogrun.md +32 -51
  17. package/.claude/skills/workflow-commands/chain-rule.md +18 -11
  18. package/.claude/skills/workflow-commands/delegation.md +13 -8
  19. package/.claude/skills/workflow-commands/entry-sequence.md +10 -12
  20. package/.claude/skills/workflow-commands/followup.md +10 -35
  21. package/.claude/skills/workflow-commands/fullrun-steps.md +38 -49
  22. package/.claude/skills/workflow-commands/fullrun.md +6 -8
  23. package/.claude/skills/workflow-commands/halfrun.md +20 -32
  24. package/.claude/skills/workflow-commands/into-target.md +1 -2
  25. package/.claude/skills/workflow-commands/issue-comments.md +19 -15
  26. package/.claude/skills/workflow-commands/issue-scout.md +5 -4
  27. package/.claude/skills/workflow-commands/kickoff.md +24 -23
  28. package/.claude/skills/workflow-commands/latest-gate.md +9 -18
  29. package/.claude/skills/workflow-commands/needs-human-review.md +11 -19
  30. package/.claude/skills/workflow-commands/observation-filing.md +4 -50
  31. package/.claude/skills/workflow-commands/observation-ledger.md +5 -10
  32. package/.claude/skills/workflow-commands/pre-gate-cut.md +22 -44
  33. package/.claude/skills/workflow-commands/prerequisite.md +11 -18
  34. package/.claude/skills/workflow-commands/progress-watcher.md +3 -8
  35. package/.claude/skills/workflow-commands/prrun.md +6 -12
  36. package/.claude/skills/workflow-commands/retrospective.md +5 -5
  37. package/.claude/skills/workflow-commands/split-assessment.md +14 -4
  38. package/.claude/skills/workflow-commands/target-repository.md +1 -2
  39. package/.claude/skills/workflow-commands/working-tree-hold.md +11 -13
  40. package/.codex/hooks.json +6 -6
  41. package/.github/actions/setup-node/action.yml +10 -1
  42. package/.github/actions/setup-pnpm/action.yml +1 -1
  43. package/.github/dependabot.yml +16 -0
  44. package/.github/release.yml +0 -2
  45. package/.github/workflows/ci.yml +121 -11
  46. package/.github/workflows/publish.yml +10 -3
  47. package/.github/workflows/sonar-qube.yml +1 -0
  48. package/.prettierignore +2 -0
  49. package/.vscode/tasks.json +1 -2
  50. package/CLAUDE.md +4 -8
  51. package/README.md +4 -2
  52. package/SECURITY.md +1 -1
  53. package/cspell/index.yaml +7 -0
  54. package/dist/CLAUDE.md +4 -8
  55. package/dist/commands/document-read-cli.js +882 -0
  56. package/dist/commands/{document-section-cli.js → document-section-main.js} +137 -62
  57. package/dist/commands/read-set-cli.js +1867 -0
  58. package/dist/commands/run-prep-main.js +21653 -0
  59. package/dist/commands/run-step-cli.js +23880 -0
  60. package/dist/config-merge/index.js +5 -1
  61. package/dist/hooks/audit-provision.js +20 -35
  62. package/dist/hooks/{chunk-DGT54IH5.js → chunk-AZX4FGQ3.js} +63 -17
  63. package/dist/hooks/chunk-CWMBGKYW.js +6483 -0
  64. package/dist/hooks/chunk-O2YBIDSI.js +4306 -0
  65. package/dist/hooks/{chunk-AS74OU3D.js → chunk-PT5R6UJD.js} +4582 -2118
  66. package/dist/hooks/chunk-TUIFS5E7.js +72 -0
  67. package/dist/hooks/{chunk-723HKZO5.js → chunk-VWWCFGWK.js} +1 -1
  68. package/dist/hooks/{chunk-E7OIKX5Z.js → chunk-WR2KQAYZ.js} +1863 -382
  69. package/dist/hooks/{chunk-KC5AK2GF.js → chunk-XGBNSWEI.js} +248 -46
  70. package/dist/hooks/chunk-YCDOIR3I.js +3456 -0
  71. package/dist/hooks/codex-hook-adapter.js +10 -19
  72. package/dist/hooks/format-edited.js +5 -5
  73. package/dist/hooks/inputs.json +436 -257
  74. package/dist/hooks/pretool-guard.js +7 -22
  75. package/dist/hooks/session-lang.js +380 -42
  76. package/dist/hooks/stop-guard.js +8711 -782
  77. package/dist/josh.js +5263 -997
  78. package/dist/self-sync-guard/index.js +74 -10
  79. package/dist/version/index.js +115 -406
  80. package/eslint/base.js +1 -1
  81. package/lefthook/base.yml +8 -4
  82. package/package.json +17 -53
  83. package/pnpm-workspace.yaml +4 -2
  84. package/prompts/coding-standards.md +1 -1
  85. package/prompts/collaboration-workflow/file-edits.md +1 -9
  86. package/prompts/collaboration-workflow/gh-rest.md +1 -2
  87. package/prompts/collaboration-workflow/issue-citation.md +2 -4
  88. package/prompts/collaboration-workflow/issue-template.md +42 -17
  89. package/prompts/collaboration-workflow/lane-instructions.md +34 -0
  90. package/prompts/collaboration-workflow/measurement.md +37 -0
  91. package/prompts/collaboration-workflow/operating-rules.md +6 -12
  92. package/prompts/collaboration-workflow/output-bounds.md +4 -9
  93. package/prompts/collaboration-workflow/overview.md +1 -1
  94. package/prompts/collaboration-workflow/plan-comment.md +3 -42
  95. package/prompts/collaboration-workflow/principles.md +19 -8
  96. package/prompts/collaboration-workflow/report-format.md +37 -57
  97. package/prompts/collaboration-workflow/residency.md +12 -8
  98. package/prompts/collaboration-workflow/rule-delivery.md +3 -11
  99. package/prompts/collaboration-workflow/shell-body.md +8 -18
  100. package/prompts/collaboration-workflow/turn-batching.md +4 -6
  101. package/prompts/collaboration-workflow/upstream-interrupt.md +16 -6
  102. package/prompts/collaboration-workflow/wip-cap.md +7 -7
  103. package/prompts/collaboration-workflow.md +4 -7
  104. package/prompts/refactoring.md +1 -1
  105. package/prompts/review-rubric.md +1 -2
  106. package/prompts/review.md +45 -26
  107. package/prompts/testing-guide.md +10 -45
  108. package/scripts/agent/agent-argv.ts +20 -4
  109. package/scripts/agent/agent-event.ts +15 -15
  110. package/scripts/agent/agent-exit-record.ts +13 -1
  111. package/scripts/agent/agent-role-profile.ts +101 -45
  112. package/scripts/agent/agent-safe-text.ts +60 -0
  113. package/scripts/agent/api-auth.ts +41 -0
  114. package/scripts/agent/api-outage.ts +1 -1
  115. package/scripts/agent/claude-agent-argv.ts +14 -0
  116. package/scripts/agent/codex-agent-argv.ts +2 -0
  117. package/scripts/agent/lane-instructions.ts +144 -0
  118. package/scripts/auto-ok/auto-ok-cli.ts +14 -16
  119. package/scripts/auto-ok/auto-ok-judge-read.ts +12 -3
  120. package/scripts/auto-ok/auto-ok-judge-write.ts +46 -19
  121. package/scripts/auto-ok/auto-ok-judge.ts +13 -2
  122. package/scripts/auto-ok/auto-ok-main.ts +17 -0
  123. package/scripts/backlog/backlog-arrival.ts +14 -3
  124. package/scripts/backlog/backlog-budget-cli.ts +7 -33
  125. package/scripts/backlog/backlog-budget-main.ts +16 -0
  126. package/scripts/backlog/backlog-budget.ts +6 -7
  127. package/scripts/backlog/backlog-defect-priority.ts +4 -3
  128. package/scripts/backlog/backlog-drive-adopt.ts +67 -0
  129. package/scripts/backlog/backlog-drive-args.ts +4 -5
  130. package/scripts/backlog/backlog-drive-cli.ts +113 -28
  131. package/scripts/backlog/backlog-drive-hold.ts +162 -0
  132. package/scripts/backlog/backlog-drive-idle.ts +151 -0
  133. package/scripts/backlog/backlog-drive-judge.ts +25 -0
  134. package/scripts/backlog/backlog-drive-memory.ts +126 -0
  135. package/scripts/backlog/backlog-drive-named-offer.ts +5 -10
  136. package/scripts/backlog/backlog-drive-named.ts +54 -7
  137. package/scripts/backlog/backlog-drive-offer-argv.ts +3 -8
  138. package/scripts/backlog/backlog-drive-paused.ts +169 -0
  139. package/scripts/backlog/backlog-drive-restore.ts +39 -8
  140. package/scripts/backlog/backlog-drive-seats.ts +18 -8
  141. package/scripts/backlog/backlog-drive-token-handling.ts +38 -0
  142. package/scripts/backlog/backlog-drive.ts +79 -75
  143. package/scripts/backlog/backlog-next-main.ts +16 -0
  144. package/scripts/backlog/backlog-next-shared.ts +73 -0
  145. package/scripts/backlog/backlog-next.ts +48 -16
  146. package/scripts/backlog/backlog-occupied.ts +69 -0
  147. package/scripts/backlog/backlog-offer-cli.ts +6 -21
  148. package/scripts/backlog/backlog-offer-exclude.ts +15 -0
  149. package/scripts/backlog/backlog-offer-main.ts +12 -0
  150. package/scripts/backlog/backlog-offer.ts +36 -3
  151. package/scripts/backlog/backlog-overlap.ts +22 -4
  152. package/scripts/backlog/backlog-plan-read.ts +6 -2
  153. package/scripts/backlog/backlog-plan.ts +18 -4
  154. package/scripts/backlog/backlog-pool.ts +10 -10
  155. package/scripts/backlog/backlog-rank.ts +10 -2
  156. package/scripts/backlog/backlog-ready.ts +137 -18
  157. package/scripts/backlog/backlog-stalled-detect.ts +109 -36
  158. package/scripts/backlog/backlog-stalled.ts +52 -16
  159. package/scripts/backlog/backlog-wait-cause.ts +86 -0
  160. package/scripts/backlog/backlog-waves.ts +39 -13
  161. package/scripts/backlog/backlogrun-args.ts +19 -7
  162. package/scripts/backlog/backlogrun-cli.ts +19 -5
  163. package/scripts/backlog/backlogrun-launch.ts +6 -0
  164. package/scripts/backlog/backlogrun-restart.ts +97 -0
  165. package/scripts/backlog/backlogrun-stop.ts +79 -7
  166. package/scripts/behavior/behavior-cli.ts +2 -2
  167. package/scripts/behavior/behavior-rules.ts +47 -24
  168. package/scripts/build/build-bin.ts +2 -16
  169. package/scripts/build/build-claude-md.ts +0 -7
  170. package/scripts/build/build-commands.ts +0 -13
  171. package/scripts/build/build-hooks.ts +49 -48
  172. package/scripts/build/hook-bundle-stamp.ts +29 -11
  173. package/scripts/build/local-bin.ts +1 -1
  174. package/scripts/cases/cases-cli.ts +25 -13
  175. package/scripts/cases/cases-interaction-scan.ts +134 -0
  176. package/scripts/cases/cases-interaction.ts +183 -0
  177. package/scripts/cases/cases-logic.ts +39 -6
  178. package/scripts/ci/pr-classification-main.ts +18 -0
  179. package/scripts/ci/pr-classification.ts +10 -17
  180. package/scripts/clone/clone-scan.ts +1 -1
  181. package/scripts/cost-runtime/cost-blocks.ts +22 -37
  182. package/scripts/cost-runtime/cost-cli.ts +31 -14
  183. package/scripts/cost-runtime/cost-main.ts +12 -0
  184. package/scripts/cost-runtime/cost-transcript.ts +1 -0
  185. package/scripts/delegation/delegation-policy.ts +17 -4
  186. package/scripts/delegation/duplicate-read-guard.ts +2 -10
  187. package/scripts/delegation/investigation-guard.ts +15 -73
  188. package/scripts/delegation/investigation-reads.ts +3 -5
  189. package/scripts/dependabot/dependabot-cooldown.ts +194 -0
  190. package/scripts/discovery/repo-discovery.ts +24 -6
  191. package/scripts/doctor/doctor-consumer.ts +2 -5
  192. package/scripts/document/document-byte-budget.ts +9 -6
  193. package/scripts/document/document-scan.ts +1 -1
  194. package/scripts/document/document-section-cli.ts +17 -13
  195. package/scripts/document/document-section-main.ts +12 -0
  196. package/scripts/document/entry-read-budget.ts +2 -2
  197. package/scripts/document/read-set-cli.ts +4 -1
  198. package/scripts/epic/epic-audit-cli.ts +12 -6
  199. package/scripts/epic/epic-audit-orphans.ts +5 -8
  200. package/scripts/epic/epic-audit.ts +52 -1
  201. package/scripts/epic/epic-bundle-apply.ts +137 -0
  202. package/scripts/epic/epic-bundle-cli.ts +32 -121
  203. package/scripts/epic/epic-bundle-evidence.ts +49 -26
  204. package/scripts/epic/epic-bundle-format.ts +116 -0
  205. package/scripts/epic/epic-bundle-main.ts +17 -0
  206. package/scripts/epic/epic-bundle-referenced.ts +14 -3
  207. package/scripts/epic/epic-bundle.ts +17 -9
  208. package/scripts/epic/epic-busy.ts +5 -12
  209. package/scripts/epic/epic-classify.ts +24 -15
  210. package/scripts/epic/epic-cli-argv.ts +31 -0
  211. package/scripts/epic/epic-cli-decide.ts +42 -0
  212. package/scripts/epic/epic-cli.ts +6 -38
  213. package/scripts/epic/epic-close.ts +112 -55
  214. package/scripts/epic/epic-cross-repo.ts +4 -7
  215. package/scripts/epic/epic-decide.ts +119 -0
  216. package/scripts/epic/epic-decision.ts +9 -0
  217. package/scripts/epic/epic-fetch.ts +4 -0
  218. package/scripts/epic/epic-graph.ts +2 -0
  219. package/scripts/epic/epic-issue.ts +5 -1
  220. package/scripts/epic/epic-label-age.ts +1 -1
  221. package/scripts/epic/epic-lane-offer.ts +39 -4
  222. package/scripts/epic/epic-next-main.ts +24 -0
  223. package/scripts/epic/epic-next.ts +6 -24
  224. package/scripts/epic/epic-outside-blocker.ts +6 -2
  225. package/scripts/epic/epic-parse.ts +9 -3
  226. package/scripts/epic/epic-read.ts +1 -0
  227. package/scripts/epic/epic-reconcile.ts +39 -0
  228. package/scripts/epic/epic-run.ts +10 -1
  229. package/scripts/epic/epic-solo.ts +50 -14
  230. package/scripts/epic/epic.ts +41 -7
  231. package/scripts/exports/unused-members-cli.ts +2 -2
  232. package/scripts/followup/followup-checks-event.ts +8 -3
  233. package/scripts/followup/followup-coderabbit-wait.ts +82 -0
  234. package/scripts/followup/followup-review-gates.ts +81 -0
  235. package/scripts/followup/git-followup-stages.ts +13 -3
  236. package/scripts/followup/git-followup-workflow.ts +31 -60
  237. package/scripts/followup/git-pr-followup-wrapup.ts +9 -14
  238. package/scripts/followup/git-pr-followup.ts +36 -8
  239. package/scripts/fresh-machine/fresh-machine-cli.ts +1 -1
  240. package/scripts/fresh-machine/fresh-machine-run.ts +8 -8
  241. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +1 -1
  242. package/scripts/gate/busy-average.ts +58 -0
  243. package/scripts/gate/check-cpu.ts +60 -0
  244. package/scripts/gate/check-inputs.ts +73 -0
  245. package/scripts/gate/check-reuse.ts +141 -0
  246. package/scripts/gate/command-memory.ts +192 -0
  247. package/scripts/gate/core-admission.ts +218 -28
  248. package/scripts/gate/core-budget-timing.ts +37 -0
  249. package/scripts/gate/core-budget.ts +150 -119
  250. package/scripts/gate/core-wait-record.ts +48 -0
  251. package/scripts/gate/core-wait.ts +162 -0
  252. package/scripts/gate/core-weights.ts +86 -0
  253. package/scripts/gate/free-cores.ts +72 -0
  254. package/scripts/gate/gate-ledger.ts +49 -7
  255. package/scripts/gate/gate-plan.ts +44 -15
  256. package/scripts/gate/gate-report.ts +29 -4
  257. package/scripts/gate/gate-run-steps.ts +195 -0
  258. package/scripts/gate/gate-skip.ts +12 -2
  259. package/scripts/gate/gate-steps.ts +12 -1
  260. package/scripts/gate/held-mark.ts +55 -0
  261. package/scripts/gate/input-fingerprint.ts +42 -0
  262. package/scripts/gate/machine-capacity.ts +124 -31
  263. package/scripts/gate/moved-paths.ts +67 -0
  264. package/scripts/gate/pre-commit-type-check.ts +14 -1
  265. package/scripts/gate/project-checks.ts +5 -12
  266. package/scripts/gate/scoped-green.ts +12 -8
  267. package/scripts/gate/since-green.ts +62 -0
  268. package/scripts/gate/toolchain-inputs.ts +115 -0
  269. package/scripts/gate/verification-gate.ts +65 -129
  270. package/scripts/gate/verification-inputs.ts +250 -0
  271. package/scripts/gh/gh-author-association.ts +96 -9
  272. package/scripts/gh/git-ai-review-scan.ts +4 -2
  273. package/scripts/gh/git-gh-api-path.ts +15 -0
  274. package/scripts/gh/git-gh-branch-rules.ts +73 -0
  275. package/scripts/gh/git-gh-conditional.ts +5 -2
  276. package/scripts/gh/git-gh-issue-read.ts +5 -1
  277. package/scripts/gh/git-gh-issue-rest.ts +1 -0
  278. package/scripts/gh/git-gh-issue-write.ts +77 -17
  279. package/scripts/gh/git-gh-issue.ts +7 -3
  280. package/scripts/gh/git-gh-poll-read.ts +89 -0
  281. package/scripts/gh/git-gh-pr-auto-merge.ts +8 -3
  282. package/scripts/gh/git-gh-pr-rest.ts +1 -1
  283. package/scripts/gh/git-gh-pr-snapshot.ts +33 -20
  284. package/scripts/gh/git-gh-pr.ts +27 -15
  285. package/scripts/gh/git-pr-checks-eval.ts +39 -7
  286. package/scripts/gh/git-pr-checks-parse.ts +39 -9
  287. package/scripts/gh/git-pr-merge-checked.ts +80 -0
  288. package/scripts/gh/git-pr.ts +13 -1
  289. package/scripts/git/base-tree.ts +19 -2
  290. package/scripts/git/changed-file-scope.ts +6 -4
  291. package/scripts/git/changed-paths.ts +18 -1
  292. package/scripts/git/git-diff-reads.ts +27 -2
  293. package/scripts/git/git-grep-hits.ts +85 -0
  294. package/scripts/git/git-location-environment.ts +1 -1
  295. package/scripts/git/git-merge-conflicts.ts +83 -0
  296. package/scripts/git/git-preflight.ts +37 -12
  297. package/scripts/git/git-push-transport.ts +1 -2
  298. package/scripts/git/git-schemas.ts +17 -7
  299. package/scripts/git/git-spawn.ts +1 -2
  300. package/scripts/git/git-status.ts +4 -4
  301. package/scripts/git/main-merge-main.ts +12 -0
  302. package/scripts/git/main-merge-regenerate.ts +78 -0
  303. package/scripts/git/main-merge.ts +39 -14
  304. package/scripts/git/main-sync-main.ts +12 -0
  305. package/scripts/git/main-sync.ts +0 -9
  306. package/scripts/git/stash/git-stash.ts +27 -4
  307. package/scripts/git/stash/{stash-pop-args.ts → stash-args.ts} +13 -10
  308. package/scripts/git/stash/stash-pop-cli.ts +6 -12
  309. package/scripts/git/stash/stash-pop-main.ts +12 -0
  310. package/scripts/git/stash/stash-push-cli.ts +76 -0
  311. package/scripts/git/stash/stash-push-main.ts +12 -0
  312. package/scripts/hooks/batch-guard.ts +5 -16
  313. package/scripts/hooks/check-commit-message-main.ts +8 -0
  314. package/scripts/hooks/check-commit-message.ts +4 -7
  315. package/scripts/hooks/format-edited-file.ts +8 -24
  316. package/scripts/hooks/pre-commit-lint.ts +118 -0
  317. package/scripts/hooks/pre-push-unit.ts +4 -2
  318. package/scripts/hooks/pretool-guard-cli.ts +1 -8
  319. package/scripts/hooks/pretool-guard.ts +57 -69
  320. package/scripts/hooks/reserved-run.ts +67 -8
  321. package/scripts/hooks/run-hook.sh +18 -11
  322. package/scripts/hooks/shell-rules-notice.ts +37 -0
  323. package/scripts/hooks/stop-actions.ts +185 -0
  324. package/scripts/hooks/stop-guard.ts +72 -27
  325. package/scripts/init/hook-command-rewrite.ts +19 -5
  326. package/scripts/init/hook-launch.ts +15 -12
  327. package/scripts/init/init-actions.ts +0 -6
  328. package/scripts/init/init-ai-copy.ts +10 -36
  329. package/scripts/init/init-bootstrap.ts +9 -8
  330. package/scripts/init/init-dry-run-report.ts +1 -1
  331. package/scripts/init/init-dry-run.ts +1 -1
  332. package/scripts/init/init-file-action.ts +7 -9
  333. package/scripts/init/init-logic-json-merge.ts +2 -2
  334. package/scripts/init/init-logic-migrate.ts +9 -82
  335. package/scripts/init/init-logic.ts +3 -2
  336. package/scripts/init/init-main.ts +12 -0
  337. package/scripts/init/init.ts +5 -12
  338. package/scripts/init/kit-development-versions.ts +3 -7
  339. package/scripts/init/kit-written-paths.ts +2 -2
  340. package/scripts/init/project-profile.ts +5 -4
  341. package/scripts/init/tsconfig-preset-migration.ts +2 -1
  342. package/scripts/init/vscode-tasks.ts +1 -1
  343. package/scripts/issue/defect-origin-cli.ts +106 -0
  344. package/scripts/issue/defect-origin-line.ts +60 -0
  345. package/scripts/issue/defect-origin-main.ts +11 -0
  346. package/scripts/issue/defect-origin.ts +114 -0
  347. package/scripts/issue/defect-rate-cli.ts +34 -78
  348. package/scripts/issue/defect-rate.ts +0 -16
  349. package/scripts/issue/defect-report-cli.ts +128 -0
  350. package/scripts/issue/defect-report-format.ts +56 -0
  351. package/scripts/issue/defect-report-main.ts +11 -0
  352. package/scripts/issue/defect-report.ts +160 -0
  353. package/scripts/issue/expected-effect-lint.ts +60 -0
  354. package/scripts/issue/issue-already-done-cli.ts +62 -0
  355. package/scripts/issue/issue-body-or-comment.ts +40 -0
  356. package/scripts/issue/issue-cite-cli.ts +33 -22
  357. package/scripts/issue/issue-cite-main.ts +12 -0
  358. package/scripts/issue/issue-classification.ts +13 -8
  359. package/scripts/issue/issue-comment-cli.ts +10 -24
  360. package/scripts/issue/issue-comment-main.ts +12 -0
  361. package/scripts/issue/issue-evidence-exit.ts +100 -0
  362. package/scripts/issue/issue-file-cli.ts +29 -7
  363. package/scripts/issue/issue-file.ts +19 -19
  364. package/scripts/issue/issue-fold-cli.ts +2 -11
  365. package/scripts/issue/issue-fold-main.ts +12 -0
  366. package/scripts/issue/issue-labels.ts +81 -90
  367. package/scripts/issue/issue-lint-cli.ts +7 -13
  368. package/scripts/issue/issue-lint-main.ts +12 -0
  369. package/scripts/issue/issue-measured-cli.ts +56 -0
  370. package/scripts/issue/issue-merged.ts +19 -2
  371. package/scripts/issue/issue-not-before-label.ts +135 -0
  372. package/scripts/issue/issue-not-before.ts +111 -0
  373. package/scripts/issue/issue-number-shape.ts +15 -1
  374. package/scripts/issue/issue-park.ts +28 -0
  375. package/scripts/issue/issue-plan-cli.ts +151 -0
  376. package/scripts/issue/issue-priority.ts +151 -0
  377. package/scripts/issue/issue-rank.ts +7 -1
  378. package/scripts/issue/issue-read-cli.ts +3 -10
  379. package/scripts/issue/issue-read-main.ts +12 -0
  380. package/scripts/issue/issue-read.ts +29 -5
  381. package/scripts/issue/issue-release-cli.ts +0 -10
  382. package/scripts/issue/issue-release-main.ts +13 -0
  383. package/scripts/issue/issue-release.ts +7 -12
  384. package/scripts/issue/issue-sample-gate.ts +192 -0
  385. package/scripts/issue/issue-sample-source.ts +76 -0
  386. package/scripts/issue/issue-scout-cli.ts +19 -25
  387. package/scripts/issue/issue-scout-main.ts +14 -0
  388. package/scripts/issue/issue-state-cli.ts +0 -10
  389. package/scripts/issue/issue-state-main.ts +12 -0
  390. package/scripts/issue/issue-watch-diff.ts +56 -15
  391. package/scripts/issue/issue-watch.ts +2 -1
  392. package/scripts/issue/issue-wip.ts +2 -7
  393. package/scripts/issue/markdown-section.ts +19 -5
  394. package/scripts/issue/measure-rerun-cli.ts +13 -8
  395. package/scripts/issue/plan-consumers-cli.ts +39 -0
  396. package/scripts/issue/plan-consumers-main.ts +11 -0
  397. package/scripts/issue/plan-consumers-section.ts +55 -0
  398. package/scripts/issue/plan-consumers.ts +127 -0
  399. package/scripts/josh/agent-session-environment.ts +1 -1
  400. package/scripts/josh/command-usage.ts +82 -0
  401. package/scripts/josh/file-map-stamp.ts +49 -16
  402. package/scripts/josh/hook-decision.ts +32 -20
  403. package/scripts/josh/josh-command-map.ts +6 -1
  404. package/scripts/josh/josh-command-types.ts +65 -13
  405. package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
  406. package/scripts/josh/josh-commands-ai.ts +169 -157
  407. package/scripts/josh/josh-commands-backlog.ts +82 -16
  408. package/scripts/josh/josh-commands-clone.ts +1 -0
  409. package/scripts/josh/josh-commands-development.ts +111 -71
  410. package/scripts/josh/josh-commands-document.ts +43 -1
  411. package/scripts/josh/josh-commands-epic.ts +171 -0
  412. package/scripts/josh/josh-commands-hooks.ts +31 -2
  413. package/scripts/josh/josh-commands-issue-write.ts +181 -0
  414. package/scripts/josh/josh-commands-issue.ts +124 -24
  415. package/scripts/josh/josh-commands-lane.ts +112 -2
  416. package/scripts/josh/josh-commands-lint.ts +19 -8
  417. package/scripts/josh/josh-commands-maintenance.ts +112 -4
  418. package/scripts/josh/josh-commands-pause.ts +29 -0
  419. package/scripts/josh/josh-commands-progress.ts +87 -0
  420. package/scripts/josh/josh-commands-project.ts +138 -9
  421. package/scripts/josh/josh-commands-review.ts +124 -0
  422. package/scripts/josh/josh-commands-run.ts +211 -23
  423. package/scripts/josh/josh-commands-ship.ts +169 -0
  424. package/scripts/josh/josh-commands-split.ts +9 -0
  425. package/scripts/josh/josh-commands-versioning.ts +49 -2
  426. package/scripts/josh/josh-commands-workflow.ts +149 -6
  427. package/scripts/josh/josh-logic.ts +11 -27
  428. package/scripts/josh/josh.ts +14 -5
  429. package/scripts/josh/package-directory.ts +18 -0
  430. package/scripts/josh/process-identity.ts +13 -4
  431. package/scripts/josh/session-language-cli.ts +4 -8
  432. package/scripts/josh/session-language-main.ts +13 -0
  433. package/scripts/josh/session-language.ts +6 -1
  434. package/scripts/josh/shared-cache.ts +90 -0
  435. package/scripts/josh/stamp-file.ts +9 -15
  436. package/scripts/lane/lane-await.ts +51 -12
  437. package/scripts/lane/lane-cache.ts +5 -30
  438. package/scripts/lane/lane-capacity.ts +19 -22
  439. package/scripts/lane/lane-check-stats.ts +97 -0
  440. package/scripts/lane/lane-child-invocation.ts +43 -4
  441. package/scripts/lane/lane-cli.ts +15 -5
  442. package/scripts/lane/lane-close.ts +86 -18
  443. package/scripts/lane/lane-core-wait-stats.ts +66 -0
  444. package/scripts/lane/lane-dispatch.ts +27 -6
  445. package/scripts/lane/lane-gap-stats.ts +156 -0
  446. package/scripts/lane/lane-guard-policy.ts +2 -2
  447. package/scripts/lane/lane-handoff.ts +76 -1
  448. package/scripts/lane/lane-held-stats.ts +129 -0
  449. package/scripts/lane/lane-install.ts +16 -15
  450. package/scripts/lane/lane-launch-cli.ts +0 -9
  451. package/scripts/lane/lane-launch-main.ts +12 -0
  452. package/scripts/lane/lane-ledger-schema.ts +266 -0
  453. package/scripts/lane/lane-ledger.ts +108 -97
  454. package/scripts/lane/lane-limit-cli.ts +19 -9
  455. package/scripts/lane/lane-measure-cli.ts +58 -10
  456. package/scripts/lane/lane-open.ts +9 -1
  457. package/scripts/lane/lane-parked.ts +3 -3
  458. package/scripts/lane/lane-pause-cli.ts +130 -0
  459. package/scripts/lane/lane-pause.ts +158 -0
  460. package/scripts/lane/lane-preserve.ts +29 -1
  461. package/scripts/lane/lane-process-table.ts +166 -0
  462. package/scripts/lane/lane-reap-settle.ts +124 -0
  463. package/scripts/lane/lane-reap.ts +50 -15
  464. package/scripts/lane/lane-registry.ts +33 -10
  465. package/scripts/lane/lane-residents.ts +162 -0
  466. package/scripts/lane/lane-restart.ts +26 -27
  467. package/scripts/lane/lane-round-two-stats.ts +49 -0
  468. package/scripts/lane/lane-sampler.ts +4 -0
  469. package/scripts/lane/lane-session-action.ts +160 -0
  470. package/scripts/lane/lane-session-broker.ts +134 -134
  471. package/scripts/lane/lane-snapshot-trace.ts +84 -0
  472. package/scripts/lane/lane-spans.ts +51 -0
  473. package/scripts/lane/lane-spent.ts +6 -3
  474. package/scripts/lane/lane-stage-stats.ts +7 -2
  475. package/scripts/lane/lane-state.ts +302 -0
  476. package/scripts/lane/lane-stats.ts +58 -4
  477. package/scripts/lane/lane-stop-stats.ts +113 -37
  478. package/scripts/lane/lane-test-related-stats.ts +127 -0
  479. package/scripts/lane/lane-transcript-calls.ts +145 -0
  480. package/scripts/lane/lane-transcript-stats.ts +168 -0
  481. package/scripts/lane/lane-vacant.ts +13 -3
  482. package/scripts/lane/lane-withdraw-cli.ts +72 -0
  483. package/scripts/lane/lane-withdraw.ts +183 -0
  484. package/scripts/lane/process-directories.ts +70 -0
  485. package/scripts/lane/process-lane-marks.ts +94 -0
  486. package/scripts/lib/atomic-write.ts +62 -0
  487. package/scripts/lib/buffered-process.ts +12 -5
  488. package/scripts/lib/cli-flags.ts +53 -0
  489. package/scripts/lib/figure-format.ts +63 -0
  490. package/scripts/lib/json-value.ts +9 -1
  491. package/scripts/lib/package-manifest.ts +35 -0
  492. package/scripts/lib/read-file.ts +3 -1
  493. package/scripts/lib/stamped-memo.ts +63 -0
  494. package/scripts/lib/stdout-on-stderr.ts +24 -0
  495. package/scripts/lib/timeouts.ts +9 -0
  496. package/scripts/lib/transcript-record.ts +91 -0
  497. package/scripts/lines/effective-limit.ts +1 -1
  498. package/scripts/lint/eslint-cache-dependencies.ts +145 -0
  499. package/scripts/lint/eslint-daemon.ts +265 -0
  500. package/scripts/lint/format.ts +14 -5
  501. package/scripts/lint/import-graph.ts +279 -0
  502. package/scripts/lint/lint-gate-scope.ts +102 -0
  503. package/scripts/lint/lint-parallel-main.ts +19 -0
  504. package/scripts/lint/lint-parallel.ts +72 -33
  505. package/scripts/lint/lint-related-scope.ts +33 -24
  506. package/scripts/lint/lint-related.ts +38 -6
  507. package/scripts/notify/confirmation-options.ts +1 -2
  508. package/scripts/notify/telegram-notify.ts +20 -20
  509. package/scripts/notify/telegram-test-logic.ts +0 -1
  510. package/scripts/notify/telegram-test-main.ts +8 -0
  511. package/scripts/notify/telegram-test.ts +12 -11
  512. package/scripts/observations/observation-ledger.ts +13 -0
  513. package/scripts/observations/observations-flush-landing.ts +5 -3
  514. package/scripts/observations/observations-flush.ts +6 -1
  515. package/scripts/overrides/overrides-check.ts +2 -5
  516. package/scripts/overrides/overrides-files.ts +2 -1
  517. package/scripts/overrides/overrides-logic.ts +3 -6
  518. package/scripts/package/verify-optional-eslint-install.ts +8 -6
  519. package/scripts/propagate/propagate-publish.ts +2 -7
  520. package/scripts/propagate/propagate-targets.ts +4 -12
  521. package/scripts/refactor/import-graph.ts +9 -7
  522. package/scripts/release/github-release-runs.ts +17 -6
  523. package/scripts/release/release-approval-prune.ts +18 -0
  524. package/scripts/release/release-history.ts +1 -3
  525. package/scripts/release/release-progress.ts +42 -22
  526. package/scripts/release/release-publish-run.ts +39 -0
  527. package/scripts/release/release-publish.ts +6 -6
  528. package/scripts/release/release-scope-cli.ts +0 -10
  529. package/scripts/release/release-scope-main.ts +12 -0
  530. package/scripts/repo/repo-setting.ts +3 -6
  531. package/scripts/repo/required-checks-logic.ts +6 -15
  532. package/scripts/report/report-format-reference.ts +4 -0
  533. package/scripts/report/report-labels.ts +155 -0
  534. package/scripts/report/report-lint-cli.ts +3 -0
  535. package/scripts/report/report-lint.ts +85 -110
  536. package/scripts/report/report-template-cli.ts +59 -0
  537. package/scripts/report/report-template.ts +112 -0
  538. package/scripts/review/acceptance-map-check.ts +61 -0
  539. package/scripts/review/acceptance-map.ts +206 -0
  540. package/scripts/review/removed-tests-check.ts +86 -0
  541. package/scripts/review/removed-tests.ts +149 -0
  542. package/scripts/review/review-brief-cli.ts +82 -16
  543. package/scripts/review/review-brief-main.ts +12 -0
  544. package/scripts/review/review-brief.ts +31 -3
  545. package/scripts/review/review-code-tree.ts +10 -6
  546. package/scripts/review/review-comment-round.ts +26 -8
  547. package/scripts/review/review-finding-ledger.ts +30 -15
  548. package/scripts/review/review-interaction.ts +94 -0
  549. package/scripts/review/review-readers-scan.ts +163 -0
  550. package/scripts/review/review-record-cli.ts +69 -30
  551. package/scripts/review/review-record-main.ts +12 -0
  552. package/scripts/review/review-round-one-blobs.ts +221 -0
  553. package/scripts/review/review-round2-cli.ts +49 -12
  554. package/scripts/review/review-round2.ts +80 -12
  555. package/scripts/review/review-stamps.ts +19 -1
  556. package/scripts/review/review-stop-log.ts +96 -0
  557. package/scripts/review/review-stops-cli.ts +85 -0
  558. package/scripts/review/review-tree.ts +6 -17
  559. package/scripts/review/review-untouched-readers.ts +146 -0
  560. package/scripts/review/test-titles.ts +118 -0
  561. package/scripts/rules/agent-model.ts +67 -0
  562. package/scripts/rules/bash-triggers.ts +46 -3
  563. package/scripts/rules/decision-oracle-batch.ts +9 -1
  564. package/scripts/rules/decision-oracle.ts +2 -2
  565. package/scripts/rules/delivered-rules.ts +90 -3
  566. package/scripts/rules/destructive-command.ts +8 -1
  567. package/scripts/rules/direct-filing.ts +10 -2
  568. package/scripts/rules/direct-issue-comment.ts +117 -0
  569. package/scripts/rules/direct-pr-create.ts +69 -3
  570. package/scripts/rules/early-heartbeat.ts +2 -1
  571. package/scripts/rules/file-body.ts +7 -0
  572. package/scripts/rules/filing-cap.ts +8 -0
  573. package/scripts/rules/firing-point.ts +6 -5
  574. package/scripts/rules/git-argv.ts +72 -14
  575. package/scripts/rules/git-force.ts +12 -2
  576. package/scripts/rules/guard-remedy.ts +121 -0
  577. package/scripts/rules/implementation-cut-verdict.ts +1 -1
  578. package/scripts/rules/implementation-cut.ts +11 -3
  579. package/scripts/rules/index-guard.ts +8 -1
  580. package/scripts/rules/issue-comments.ts +76 -7
  581. package/scripts/rules/josh-git-bare.ts +7 -0
  582. package/scripts/rules/lane-background.ts +67 -25
  583. package/scripts/rules/lane-carry-conflict.ts +6 -0
  584. package/scripts/rules/lane-direct-tool.ts +74 -0
  585. package/scripts/rules/lane-interactive-ask.ts +9 -2
  586. package/scripts/rules/lane-park.ts +45 -23
  587. package/scripts/rules/lane-split-park.ts +10 -2
  588. package/scripts/rules/lane-switch-main.ts +7 -0
  589. package/scripts/rules/last-prompt.ts +50 -5
  590. package/scripts/rules/oracle-consulted.ts +10 -0
  591. package/scripts/rules/oracle-firing.ts +1 -0
  592. package/scripts/rules/oracle-list-cli.ts +7 -0
  593. package/scripts/rules/permission-guards.ts +3 -0
  594. package/scripts/rules/piped-verification.ts +4 -2
  595. package/scripts/rules/poll-loop.ts +7 -0
  596. package/scripts/rules/pr-merge.ts +123 -0
  597. package/scripts/rules/protected-files.ts +32 -5
  598. package/scripts/rules/raw-field-body.ts +6 -0
  599. package/scripts/rules/rule-body-guard.ts +8 -0
  600. package/scripts/rules/rule-list.ts +12 -28
  601. package/scripts/rules/rule-rewrite.ts +114 -0
  602. package/scripts/rules/rule-value-cache.ts +4 -9
  603. package/scripts/rules/rule-value-cli.ts +51 -32
  604. package/scripts/rules/rule-value.ts +8 -2
  605. package/scripts/rules/shell-segments.ts +50 -0
  606. package/scripts/rules/stop-decision.ts +77 -0
  607. package/scripts/rules/stop-rule-rows.ts +64 -0
  608. package/scripts/rules/stop-rules.ts +150 -51
  609. package/scripts/rules/tail-commands.ts +15 -1
  610. package/scripts/rules/test-declared-commit.ts +11 -1
  611. package/scripts/rules/third-party-write.ts +7 -0
  612. package/scripts/rules/timed-rerun.ts +69 -0
  613. package/scripts/rules/worktree-guard.ts +13 -3
  614. package/scripts/run/board/run-board-app-name.ts +23 -0
  615. package/scripts/run/board/run-board-cli.ts +65 -30
  616. package/scripts/run/board/run-board-closed.ts +8 -2
  617. package/scripts/run/board/run-board-earlier.ts +94 -0
  618. package/scripts/run/board/run-board-ending-reason.ts +67 -0
  619. package/scripts/run/board/run-board-estimate-schedule.ts +103 -0
  620. package/scripts/run/board/run-board-estimate.ts +98 -0
  621. package/scripts/run/board/run-board-fit.ts +153 -36
  622. package/scripts/run/board/run-board-fold.ts +123 -0
  623. package/scripts/run/board/run-board-fresh.ts +2 -2
  624. package/scripts/run/board/run-board-gather-live.ts +29 -0
  625. package/scripts/run/board/run-board-gather-thread.ts +189 -0
  626. package/scripts/run/board/run-board-gather-worker.ts +29 -0
  627. package/scripts/run/board/run-board-gather.ts +187 -0
  628. package/scripts/run/board/run-board-github.ts +119 -31
  629. package/scripts/run/board/run-board-header.ts +86 -21
  630. package/scripts/run/board/run-board-keys.ts +58 -0
  631. package/scripts/run/board/run-board-kind.ts +20 -6
  632. package/scripts/run/board/run-board-labels.ts +118 -71
  633. package/scripts/run/board/run-board-lane-state.ts +109 -0
  634. package/scripts/run/board/run-board-lane-time.ts +122 -0
  635. package/scripts/run/board/run-board-layout.ts +240 -61
  636. package/scripts/run/board/run-board-length.ts +52 -0
  637. package/scripts/run/board/run-board-machine.ts +8 -4
  638. package/scripts/run/board/run-board-main.ts +12 -0
  639. package/scripts/run/board/run-board-notes.ts +52 -31
  640. package/scripts/run/board/run-board-now.ts +1 -1
  641. package/scripts/run/board/run-board-operation.ts +15 -33
  642. package/scripts/run/board/run-board-phase.ts +1 -1
  643. package/scripts/run/board/run-board-plan-shared.ts +115 -0
  644. package/scripts/run/board/run-board-plan.ts +55 -3
  645. package/scripts/run/board/run-board-planning.ts +45 -0
  646. package/scripts/run/board/run-board-priority.ts +44 -0
  647. package/scripts/run/board/run-board-process-groups.ts +195 -0
  648. package/scripts/run/board/run-board-read.ts +153 -13
  649. package/scripts/run/board/run-board-reason.ts +238 -45
  650. package/scripts/run/board/run-board-released.ts +35 -0
  651. package/scripts/run/board/run-board-render-checks.ts +39 -5
  652. package/scripts/run/board/run-board-render-condition.ts +96 -0
  653. package/scripts/run/board/run-board-render-drawn.ts +67 -0
  654. package/scripts/run/board/run-board-render-foot.ts +59 -0
  655. package/scripts/run/board/run-board-render-icon.ts +35 -0
  656. package/scripts/run/board/run-board-render-lanes.ts +145 -0
  657. package/scripts/run/board/run-board-render-lead.ts +80 -0
  658. package/scripts/run/board/run-board-render-legend.ts +117 -47
  659. package/scripts/run/board/run-board-render-notes.ts +156 -29
  660. package/scripts/run/board/run-board-render-processes.ts +196 -0
  661. package/scripts/run/board/run-board-render-section.ts +119 -0
  662. package/scripts/run/board/run-board-render-slot.ts +3 -36
  663. package/scripts/run/board/run-board-render-tail.ts +115 -48
  664. package/scripts/run/board/run-board-render-time.ts +56 -0
  665. package/scripts/run/board/run-board-render-title.ts +117 -24
  666. package/scripts/run/board/run-board-render-waits.ts +125 -0
  667. package/scripts/run/board/run-board-render.ts +206 -259
  668. package/scripts/run/board/run-board-roots.ts +54 -0
  669. package/scripts/run/board/run-board-row-yield.ts +10 -4
  670. package/scripts/run/board/run-board-setup.ts +1 -12
  671. package/scripts/run/board/run-board-snapshot.ts +111 -0
  672. package/scripts/run/board/run-board-spin.ts +2 -2
  673. package/scripts/run/board/run-board-state.ts +23 -29
  674. package/scripts/run/board/run-board-status.ts +206 -79
  675. package/scripts/run/board/run-board-thanks-read.ts +2 -2
  676. package/scripts/run/board/run-board-tick.ts +123 -104
  677. package/scripts/run/board/run-board-usage-board.ts +78 -0
  678. package/scripts/run/board/run-board-usage-lanes.ts +113 -0
  679. package/scripts/run/board/run-board-usage-listing.ts +93 -0
  680. package/scripts/run/board/run-board-usage-read.ts +120 -150
  681. package/scripts/run/board/run-board-usage-rusage.ts +19 -7
  682. package/scripts/run/board/run-board-usage-text.ts +139 -51
  683. package/scripts/run/board/run-board-usage-top.ts +102 -0
  684. package/scripts/run/board/run-board-usage.ts +89 -72
  685. package/scripts/run/board/run-board-usual.ts +20 -9
  686. package/scripts/run/carry/run-carry-args.ts +4 -7
  687. package/scripts/run/carry/run-carry-conversation.ts +1 -1
  688. package/scripts/run/carry/run-carry.ts +9 -4
  689. package/scripts/run/cut/run-cut-cli.ts +3 -2
  690. package/scripts/run/cut/run-cut-handoff.ts +2 -2
  691. package/scripts/run/cut/run-cut-report.ts +16 -0
  692. package/scripts/run/detached-launch.ts +23 -4
  693. package/scripts/run/entry/run-entry-cli.ts +8 -1
  694. package/scripts/run/event/run-event-cli.ts +1 -5
  695. package/scripts/run/event/run-event-filed.ts +12 -6
  696. package/scripts/run/event/run-event-follow.ts +2 -3
  697. package/scripts/run/event/run-event-render.ts +7 -10
  698. package/scripts/run/event/run-event-scope.ts +20 -2
  699. package/scripts/run/event/run-event-stream-emit.ts +78 -11
  700. package/scripts/run/event/run-event-stream.ts +37 -7
  701. package/scripts/run/hold/run-hold-adopt.ts +65 -0
  702. package/scripts/run/hold/run-hold-cli.ts +93 -22
  703. package/scripts/run/hold/run-hold-main.ts +12 -0
  704. package/scripts/run/hold/run-hold-member.ts +37 -0
  705. package/scripts/run/hold/run-hold-session.ts +46 -0
  706. package/scripts/run/hold/run-hold.ts +7 -1
  707. package/scripts/run/hold/run-stop-notify.ts +183 -0
  708. package/scripts/run/launch-priority.ts +32 -0
  709. package/scripts/run/merge/run-merge-auth.ts +31 -0
  710. package/scripts/run/merge/run-merge-cli.ts +72 -107
  711. package/scripts/run/merge/run-merge-close.ts +74 -0
  712. package/scripts/run/merge/run-merge-collect.ts +6 -13
  713. package/scripts/run/merge/run-merge-driver.ts +71 -0
  714. package/scripts/run/merge/run-merge-main.ts +12 -0
  715. package/scripts/run/merge/run-merge-outcome.ts +23 -0
  716. package/scripts/run/merge/run-merge-restart.ts +39 -0
  717. package/scripts/run/merge/run-merge-ship.ts +20 -4
  718. package/scripts/run/merge/run-merge-signals.ts +123 -0
  719. package/scripts/run/merge/run-merge-steps.ts +128 -83
  720. package/scripts/run/merge/run-merge.ts +53 -40
  721. package/scripts/run/park/run-park-cli.ts +91 -0
  722. package/scripts/run/park/run-park.ts +88 -0
  723. package/scripts/run/park/run-stalled.ts +68 -0
  724. package/scripts/run/pause/run-pause-cli.ts +73 -0
  725. package/scripts/run/pause/run-pause.ts +251 -0
  726. package/scripts/run/progress/run-progress-cli.ts +4 -12
  727. package/scripts/run/progress/run-progress-clock.ts +1 -1
  728. package/scripts/run/progress/run-progress-config.ts +6 -14
  729. package/scripts/run/progress/run-progress-main.ts +12 -0
  730. package/scripts/run/progress/run-progress.ts +1 -4
  731. package/scripts/run/review/run-review.ts +2 -1
  732. package/scripts/run/run-ending.ts +1 -0
  733. package/scripts/run/run-invocation.ts +5 -6
  734. package/scripts/run/run-liveness-cli.ts +6 -8
  735. package/scripts/run/run-liveness.ts +61 -30
  736. package/scripts/run/run-next.ts +1 -1
  737. package/scripts/run/run-parent-cut-hook.ts +2 -2
  738. package/scripts/run/run-poll-hook.ts +157 -0
  739. package/scripts/run/run-preflight.ts +18 -3
  740. package/scripts/run/run-prep-cli.ts +1 -10
  741. package/scripts/run/run-prep-locate.ts +7 -50
  742. package/scripts/run/run-prep-main.ts +12 -0
  743. package/scripts/run/run-prep.ts +6 -0
  744. package/scripts/run/run-report-cli.ts +101 -13
  745. package/scripts/run/run-report-handoff.ts +114 -0
  746. package/scripts/run/run-step-cli.ts +22 -15
  747. package/scripts/run/run-step-section.ts +85 -0
  748. package/scripts/run/run-step.ts +1 -1
  749. package/scripts/run/run-stranded-detect.ts +13 -0
  750. package/scripts/run/run-watcher-guard-cli.ts +1 -1
  751. package/scripts/run/run-watcher-guard.ts +1 -1
  752. package/scripts/run/ship/run-ship-args.ts +121 -0
  753. package/scripts/run/ship/run-ship-body-draft.ts +110 -0
  754. package/scripts/run/ship/run-ship-cli.ts +67 -151
  755. package/scripts/run/ship/run-ship-detach.ts +27 -7
  756. package/scripts/run/ship/run-ship-infra-retry.ts +59 -0
  757. package/scripts/run/ship/run-ship-next.ts +27 -3
  758. package/scripts/run/ship/run-ship-overlap.ts +232 -0
  759. package/scripts/run/ship/run-ship-place.ts +96 -0
  760. package/scripts/run/ship/run-ship-pre-detach-timed.ts +43 -0
  761. package/scripts/run/ship/run-ship-pre-detach.ts +102 -27
  762. package/scripts/run/ship/run-ship-preflight.ts +161 -30
  763. package/scripts/run/ship/run-ship-probe.ts +11 -3
  764. package/scripts/run/ship/run-ship-relaunch-cap.ts +70 -0
  765. package/scripts/run/ship/run-ship-removed-rows.ts +61 -0
  766. package/scripts/run/ship/run-ship-return.ts +123 -15
  767. package/scripts/run/ship/run-ship-review-steps.ts +105 -149
  768. package/scripts/run/ship/run-ship-review.ts +73 -6
  769. package/scripts/run/ship/run-ship-reviewer.ts +207 -0
  770. package/scripts/run/ship/run-ship-stage.ts +55 -6
  771. package/scripts/run/ship/run-ship-steps.ts +46 -15
  772. package/scripts/run/ship/run-ship-stop-cause.ts +135 -0
  773. package/scripts/run/ship/run-ship-stop-context.ts +206 -0
  774. package/scripts/run/ship/run-ship-stop-text.ts +11 -6
  775. package/scripts/run/ship/run-ship-sync.ts +57 -12
  776. package/scripts/run/ship/run-ship.ts +30 -2
  777. package/scripts/run/tidy/run-tidy-cli.ts +0 -4
  778. package/scripts/run/tidy/run-tidy-lanes.ts +3 -0
  779. package/scripts/run/tidy/run-tidy-main.ts +8 -0
  780. package/scripts/run/wake/run-wake-cli.ts +119 -100
  781. package/scripts/run/wake/run-wake-code.ts +83 -0
  782. package/scripts/run/wake/run-wake-driver.ts +19 -8
  783. package/scripts/run/wake/run-wake-loop.ts +34 -3
  784. package/scripts/run/wake/run-wake-main.ts +13 -0
  785. package/scripts/run/wake/run-wake-ports.ts +90 -0
  786. package/scripts/run/wake/run-wake-takeover.ts +66 -0
  787. package/scripts/run/wake/run-wake.ts +2 -1
  788. package/scripts/safe-chain/pack-hook.ts +2 -2
  789. package/scripts/safe-chain/preinstall-command.ts +2 -1
  790. package/scripts/safe-chain/project-config.ts +3 -9
  791. package/scripts/security/security-audit-main.ts +8 -0
  792. package/scripts/security/security-audit-provision-logic.ts +0 -11
  793. package/scripts/security/security-audit-provision-main.ts +12 -0
  794. package/scripts/security/security-audit-provision.ts +11 -26
  795. package/scripts/security/security-audit.ts +6 -7
  796. package/scripts/self-sync-guard/self-sync-guard-logic.ts +6 -13
  797. package/scripts/split/split-assess-cli.ts +2 -2
  798. package/scripts/split/split-assess.ts +15 -0
  799. package/scripts/split/split-measure.ts +65 -0
  800. package/scripts/sync/claude-settings-merge.ts +8 -15
  801. package/scripts/sync/directory-copy-guard.ts +4 -9
  802. package/scripts/sync/file-content.ts +78 -8
  803. package/scripts/sync/sync-ai-files.ts +3 -5
  804. package/scripts/sync/sync-configs.ts +11 -23
  805. package/scripts/sync/sync-hook-safety.ts +4 -10
  806. package/scripts/sync/sync-main.ts +11 -0
  807. package/scripts/sync/sync.ts +25 -37
  808. package/scripts/test/test-declared-changed.ts +2 -2
  809. package/scripts/test/test-declared.ts +1 -1
  810. package/scripts/test/test-e2e-guard.ts +55 -6
  811. package/scripts/test/test-e2e-stamp.ts +38 -0
  812. package/scripts/test/test-pinned-logic.ts +145 -0
  813. package/scripts/test/test-pinned-main.ts +78 -0
  814. package/scripts/test/test-pinned.ts +100 -0
  815. package/scripts/test/test-read-map.ts +264 -0
  816. package/scripts/test/test-read-recording.ts +91 -0
  817. package/scripts/test/test-read-trace.ts +148 -0
  818. package/scripts/test/test-red-main.ts +12 -0
  819. package/scripts/test/test-red.ts +12 -30
  820. package/scripts/test/test-related-main.ts +18 -0
  821. package/scripts/test/test-related-record.ts +119 -0
  822. package/scripts/test/test-related-scope.ts +229 -43
  823. package/scripts/test/test-related.ts +300 -22
  824. package/scripts/test/test-unit-guard-main.ts +15 -0
  825. package/scripts/test/test-unit-guard.ts +54 -21
  826. package/scripts/test/unit-count-file.ts +37 -0
  827. package/scripts/test/unit-run-marker.ts +162 -0
  828. package/scripts/test/unit-setup-files.ts +51 -0
  829. package/scripts/test/unit-worker-share.ts +71 -137
  830. package/scripts/test/whole-suite-files.ts +63 -0
  831. package/scripts/time-runtime/time-background.ts +20 -2
  832. package/scripts/time-runtime/time-bundles.ts +4 -3
  833. package/scripts/time-runtime/time-density-hook.ts +8 -6
  834. package/scripts/time-runtime/time-followup-stage.ts +1 -3
  835. package/scripts/time-runtime/time-format.ts +5 -28
  836. package/scripts/time-runtime/time-markers.ts +10 -1
  837. package/scripts/time-runtime/time-shell.ts +126 -14
  838. package/scripts/time-runtime/time-spans.ts +1 -0
  839. package/scripts/time-runtime/time-tool-call.ts +7 -0
  840. package/scripts/time-runtime/time-transcript-line.ts +49 -62
  841. package/scripts/uninstall/uninstall.ts +1 -1
  842. package/scripts/version/bump-version-main.ts +12 -0
  843. package/scripts/version/bump-version.ts +25 -25
  844. package/scripts/version/effective-upstream.ts +6 -12
  845. package/scripts/version/latest-corepack.ts +17 -32
  846. package/scripts/version/latest-if-required-cli.ts +93 -0
  847. package/scripts/version/latest-lane-guard-main.ts +8 -0
  848. package/scripts/version/latest-lane-guard.ts +0 -4
  849. package/scripts/version/latest-scope-cli.ts +0 -9
  850. package/scripts/version/latest-scope-main.ts +12 -0
  851. package/scripts/version/latest-update.ts +5 -5
  852. package/scripts/version/npm-registry.ts +44 -6
  853. package/scripts/version/publishable-range-check.ts +5 -16
  854. package/scripts/version/release-age.ts +1 -1
  855. package/scripts/version/release-hold.ts +1 -1
  856. package/scripts/version/release-window.ts +38 -0
  857. package/scripts/version/running-binary.ts +1 -1
  858. package/scripts/version/safe-chain-version-update.ts +3 -8
  859. package/scripts/version/version-targets.ts +6 -28
  860. package/templates/dependabot.yml +29 -0
  861. package/templates/gitignore +10 -3
  862. package/templates/pnpm-workspace.basic.yaml +1 -1
  863. package/templates/sonar-project.properties +3 -2
  864. package/templates/workflows/ci.yml +12 -4
  865. package/templates/workflows/github-release.yml +4 -0
  866. package/tsconfig.sonar.json +1 -1
  867. package/.ncurc.json +0 -3
  868. package/dist/hooks/batch-guard.js +0 -29
  869. package/dist/hooks/chunk-43ZHT22P.js +0 -3495
  870. package/dist/hooks/chunk-CDY4NFQG.js +0 -15
  871. package/dist/hooks/chunk-EUMACUK2.js +0 -2038
  872. package/dist/hooks/chunk-H5HVWYXK.js +0 -359
  873. package/dist/hooks/chunk-IIGFYXKC.js +0 -7104
  874. package/dist/hooks/chunk-IX6TTTI6.js +0 -95
  875. package/dist/hooks/chunk-J47HU5H5.js +0 -237
  876. package/dist/hooks/chunk-K4EOONYM.js +0 -45
  877. package/dist/hooks/chunk-K4LMBQC2.js +0 -68
  878. package/dist/hooks/chunk-SHGPANFB.js +0 -56
  879. package/dist/hooks/chunk-YHBZAJSV.js +0 -79
  880. package/dist/hooks/chunk-YYPI7SJZ.js +0 -131
  881. package/dist/hooks/duplicate-read-guard.js +0 -30
  882. package/dist/hooks/investigation-guard.js +0 -32
  883. package/scripts/backlog/backlog-stalled-cli.ts +0 -30
  884. package/scripts/cost-runtime/cost-format.ts +0 -29
  885. package/scripts/init/basic-path-migration.ts +0 -24
  886. package/scripts/issue/issue-backlinks-cli.ts +0 -93
  887. package/scripts/josh/josh-commands-guard.ts +0 -38
  888. package/scripts/lint/cross-file-recheck.ts +0 -155
  889. package/scripts/registry-migration/migrate-logic.ts +0 -237
  890. package/scripts/registry-migration/migrate.ts +0 -292
  891. package/scripts/registry-migration/user-npmrc.ts +0 -15
  892. package/scripts/rules/rule-guard.ts +0 -23
  893. package/scripts/rules/rule-registry-rows.ts +0 -282
  894. package/scripts/rules/rule-registry.ts +0 -109
  895. package/scripts/run/run-stranded-cli.ts +0 -27
@@ -1,29 +1,36 @@
1
1
  import {
2
2
  GIT_TIMEOUT_MS,
3
+ MS_PER_MINUTE,
4
+ MS_PER_SECOND,
3
5
  PLATFORM_TEMP_ROOT,
4
6
  PROBE_TIMEOUT_MS,
5
7
  SUITE_TIMEOUT_MS,
8
+ error_text,
6
9
  stamp_file
7
- } from "./chunk-DGT54IH5.js";
10
+ } from "./chunk-AZX4FGQ3.js";
8
11
 
9
12
  // scripts/lib/json-value.ts
10
- function parse_or_undefined(text) {
13
+ function parse_or_undefined(text2) {
11
14
  try {
12
- return JSON.parse(text);
15
+ return JSON.parse(text2);
13
16
  } catch {
14
17
  return void 0;
15
18
  }
16
19
  }
17
- function parse_with(text, schema) {
18
- const value = parse_or_undefined(text);
20
+ function parse_with(text2, schema) {
21
+ const value = parse_or_undefined(text2);
19
22
  if (value === void 0) return void 0;
20
23
  const parsed = schema.safeParse(value);
21
24
  return parsed.success ? parsed.data : void 0;
22
25
  }
26
+ function parse_array(text2) {
27
+ const value = parse_or_undefined(text2);
28
+ return Array.isArray(value) ? value : void 0;
29
+ }
23
30
  function is_record(value) {
24
31
  return typeof value === "object" && value !== null && !Array.isArray(value);
25
32
  }
26
- var json_value = { parse_or_undefined, parse_with, is_record };
33
+ var json_value = { parse_or_undefined, parse_with, parse_array, is_record };
27
34
 
28
35
  // scripts/git/constants.ts
29
36
  import { platform } from "node:os";
@@ -104,7 +111,6 @@ var git_ssh_keepalive = {
104
111
  };
105
112
 
106
113
  // scripts/git/git-push-transport.ts
107
- var MS_PER_SECOND = 1e3;
108
114
  var PUSH_TIMEOUT_SECONDS = 120;
109
115
  var PUSH_TIMEOUT_MS = PUSH_TIMEOUT_SECONDS * MS_PER_SECOND;
110
116
  var PUSH_TIMEOUT_LABEL = `${String(PUSH_TIMEOUT_SECONDS)}s`;
@@ -155,10 +161,9 @@ async function read(arguments_, timeout_ms = GIT_TIMEOUT_MS) {
155
161
  return stdout.trimEnd();
156
162
  }
157
163
  var REMOTE_TIMEOUT_MS = PUSH_TIMEOUT_MS;
158
- var MS_PER_SECOND2 = 1e3;
159
164
  function to_budget_error(command, error, timeout_ms) {
160
165
  if (!has_timed_out(error)) return create_spawn_error(command, get_exit_code(error));
161
- const seconds = String(Math.round(timeout_ms / MS_PER_SECOND2));
166
+ const seconds = String(Math.round(timeout_ms / MS_PER_SECOND));
162
167
  return new Error(`git ${command} timed out after ${seconds}s`, {
163
168
  cause: { exit_code: TIMEOUT_EXIT_CODE }
164
169
  });
@@ -220,9 +225,9 @@ async function get_default_branch() {
220
225
  }
221
226
  }
222
227
  var MERGE_BASE_COMMAND = "merge-base";
223
- async function reference_exists(reference) {
228
+ async function reference_exists(reference2) {
224
229
  try {
225
- await git_spawn.read(["rev-parse", "--verify", "--quiet", reference]);
230
+ await git_spawn.read(["rev-parse", "--verify", "--quiet", reference2]);
226
231
  return true;
227
232
  } catch {
228
233
  return false;
@@ -250,17 +255,32 @@ var NO_RENAME_DETECTION = "--no-renames";
250
255
  async function change_base_commit() {
251
256
  return await git_spawn.read(["rev-parse", await change_base()]);
252
257
  }
253
- async function diff_main_names() {
258
+ async function diff_names_since(commit2) {
254
259
  return await git_spawn.read([
255
260
  ...NO_PATH_QUOTING,
256
261
  "diff",
257
262
  NAME_ONLY_FLAG,
258
263
  NO_RELATIVE_PATHS,
259
264
  NO_RENAME_DETECTION,
260
- await change_base(),
265
+ commit2,
261
266
  "--"
262
267
  ]);
263
268
  }
269
+ async function tree_names_at(commit2, paths) {
270
+ return await git_spawn.read([
271
+ ...NO_PATH_QUOTING,
272
+ "ls-tree",
273
+ "-r",
274
+ NAME_ONLY_FLAG,
275
+ "--full-tree",
276
+ commit2,
277
+ "--",
278
+ ...paths
279
+ ]);
280
+ }
281
+ async function diff_main_names() {
282
+ return await diff_names_since(await change_base());
283
+ }
264
284
  async function diff_cached_names() {
265
285
  return await git_spawn.read([
266
286
  ...NO_PATH_QUOTING,
@@ -303,7 +323,9 @@ var git_diff_reads = {
303
323
  diff_main,
304
324
  diff_main_names,
305
325
  diff_main_numstat,
326
+ diff_names_since,
306
327
  get_default_branch,
328
+ tree_names_at,
307
329
  untracked_names
308
330
  };
309
331
 
@@ -339,9 +361,9 @@ async function read_push_references() {
339
361
  return { branch: branch2, local_oid, remote_oid: await read_remote_oid(branch2) };
340
362
  }
341
363
  function to_stdin_line(references) {
342
- const reference = `refs/heads/${references.branch}`;
364
+ const reference2 = `refs/heads/${references.branch}`;
343
365
  const remote_oid = references.remote_oid ?? ZERO_DIGIT.repeat(references.local_oid.length);
344
- return `${reference} ${references.local_oid} ${reference} ${remote_oid}
366
+ return `${reference2} ${references.local_oid} ${reference2} ${remote_oid}
345
367
  `;
346
368
  }
347
369
  function to_hook_run_arguments(stdin_path, hook_name) {
@@ -792,10 +814,10 @@ function beacon_target(token) {
792
814
  if (path2.dirname(target) !== PLATFORM_TEMP_ROOT) return void 0;
793
815
  return is_valid_beacon_name(path2.basename(target)) ? target : void 0;
794
816
  }
795
- function run_socket_probe(target) {
817
+ function run_socket_probe(target, kill_after_ms = PROBE_TIMEOUT_MS) {
796
818
  return spawnSync(process.execPath, ["-e", SOCKET_PROBE_SOURCE, target], {
797
819
  stdio: "ignore",
798
- timeout: PROBE_TIMEOUT_MS
820
+ timeout: kill_after_ms
799
821
  }).status ?? void 0;
800
822
  }
801
823
  function is_live_beacon(target, probe = run_socket_probe) {
@@ -834,6 +856,9 @@ function is_own_process(pid, recorded_start) {
834
856
  return pid === process.pid && recorded_start === own_start();
835
857
  }
836
858
  var process_identity = {
859
+ PROBE_ENVIRONMENT,
860
+ START_PROBES,
861
+ START_TIME_FORMAT,
837
862
  close_beacon,
838
863
  is_live_beacon,
839
864
  is_live_pid,
@@ -845,68 +870,29 @@ var process_identity = {
845
870
  own_fields,
846
871
  own_start,
847
872
  read_start,
848
- resolve_own_start
873
+ resolve_own_start,
874
+ run_socket_probe
849
875
  };
850
876
 
851
- // scripts/backlog/backlog-budget-cli.ts
852
- import { fileURLToPath } from "node:url";
853
-
854
- // scripts/git/changed-paths.ts
855
- function to_paths(raw) {
856
- return raw.split("\n").map((line) => line.trim()).filter((line) => line !== "");
877
+ // scripts/issue/issue-number-shape.ts
878
+ var ISSUE_NUMBER_PATTERN = /^[1-9]\d*$/u;
879
+ var BAD_ISSUE_MESSAGE = "Not an issue number: ";
880
+ function is_issue_number(value) {
881
+ return ISSUE_NUMBER_PATTERN.test(value);
857
882
  }
858
- async function read_changed_paths(is_staged) {
859
- if (is_staged) return to_paths(await git_command.diff_cached_names());
860
- const tracked = to_paths(await git_command.diff_main_names());
861
- const untracked = to_paths(await git_command.untracked_names());
862
- return [...tracked, ...untracked];
883
+ function require_issue_number(issue2) {
884
+ if (!is_issue_number(issue2)) throw new Error(`${BAD_ISSUE_MESSAGE}${issue2}`);
863
885
  }
864
- var changed_paths = { read_changed_paths, to_paths };
865
-
866
- // scripts/josh/path-decision.ts
867
- var STAGED_FLAG = "--staged";
868
- var JSON_FLAG = "--json";
869
- var KNOWN_FLAGS = [STAGED_FLAG, JSON_FLAG];
870
- var FAILURE_EXIT_CODE = 1;
871
- var MAX_LISTED_PATHS = 5;
872
- function has_unknown_flag(argv, known) {
873
- return argv.some((argument) => !known.includes(argument));
874
- }
875
- function parse_options(argv) {
876
- if (has_unknown_flag(argv, KNOWN_FLAGS)) return void 0;
877
- return { is_staged: argv.includes(STAGED_FLAG), is_json: argv.includes(JSON_FLAG) };
878
- }
879
- function format_path_list(paths) {
880
- const listed = paths.slice(0, MAX_LISTED_PATHS).join(", ");
881
- if (paths.length <= MAX_LISTED_PATHS) return listed;
882
- return `${listed}, +${String(paths.length - MAX_LISTED_PATHS)} more`;
883
- }
884
- function print_decision(key, answer, reason, is_json) {
885
- if (is_json) {
886
- console.info(JSON.stringify({ [key]: answer, reason }));
887
- return;
888
- }
889
- console.info(answer);
890
- console.error(reason);
891
- }
892
- async function run_path_decision(argv, command) {
893
- const options = parse_options(argv);
894
- if (options === void 0) {
895
- console.error(command.usage);
896
- return FAILURE_EXIT_CODE;
897
- }
898
- const paths = await changed_paths.read_changed_paths(options.is_staged);
899
- const answer = command.decide(paths);
900
- print_decision(command.key, answer, command.explain(paths, answer), options.is_json);
901
- return 0;
902
- }
903
- var path_decision = {
904
- format_path_list,
905
- has_unknown_flag,
906
- JSON_FLAG,
907
- parse_options,
908
- print_decision,
909
- run_path_decision
886
+ function single_of(positionals) {
887
+ const [issue_number, ...rest] = positionals;
888
+ const is_single = rest.length === 0 && issue_number !== void 0;
889
+ return is_single && ISSUE_NUMBER_PATTERN.test(issue_number) ? issue_number : void 0;
890
+ }
891
+ var issue_number_shape = {
892
+ ISSUE_NUMBER_PATTERN,
893
+ is_issue_number,
894
+ require_issue_number,
895
+ single_of
910
896
  };
911
897
 
912
898
  // scripts/lib/cli-flags.ts
@@ -981,7 +967,30 @@ function attach_values(argv, flags) {
981
967
  for (const argument of argv) attach_one(attached, argument, flags);
982
968
  return attached;
983
969
  }
970
+ var COUNT_PATTERN = /^\d+$/u;
971
+ var POSITIVE_PATTERN = /^[1-9]\d*$/u;
972
+ function to_integer(raw, pattern) {
973
+ if (raw === void 0 || !pattern.test(raw)) return void 0;
974
+ const parsed = Number(raw);
975
+ return Number.isSafeInteger(parsed) ? parsed : void 0;
976
+ }
977
+ function to_count(raw) {
978
+ return to_integer(raw, COUNT_PATTERN);
979
+ }
980
+ function to_positive(raw) {
981
+ return to_integer(raw, POSITIVE_PATTERN);
982
+ }
983
+ function read_positive_setting(raw, name, fallback) {
984
+ const trimmed = raw?.trim() ?? "";
985
+ if (trimmed === "") return { kind: "limit", limit: fallback };
986
+ const limit = to_positive(trimmed);
987
+ if (limit !== void 0) return { kind: "limit", limit };
988
+ return { kind: "problem", problem: `${name} must be a positive integer, not "${trimmed}"` };
989
+ }
984
990
  var cli_flags = {
991
+ to_count,
992
+ to_positive,
993
+ read_positive_setting,
985
994
  attach_values,
986
995
  usage_line,
987
996
  refuse_unknown_flags,
@@ -995,258 +1004,11 @@ var cli_flags = {
995
1004
  is_value_unusable
996
1005
  };
997
1006
 
998
- // scripts/backlog/backlog-budget.ts
999
- var MS_PER_MINUTE = 6e4;
1000
- var MINUTES_PER_HOUR = 60;
1001
- var IDLE_WAIT_HOURS = 8;
1002
- var DEFAULT_IDLE_MINUTES = IDLE_WAIT_HOURS * MINUTES_PER_HOUR;
1003
- var DEFAULT_IDLE_MS = DEFAULT_IDLE_MINUTES * MS_PER_MINUTE;
1004
- var OFFER_INTERVAL_SECONDS = 60;
1005
- var MS_PER_SECOND3 = 1e3;
1006
- var OFFER_INTERVAL_MS = OFFER_INTERVAL_SECONDS * MS_PER_SECOND3;
1007
- var RUN_VERDICT = "run";
1008
- var WATCH_VERDICT = "watch";
1009
- var STOP_VERDICT = "stop";
1010
- var TRIAGE_VERDICT = "triage";
1011
- var ANSWERS = ["blocked", "candidates", "exhausted", "parked", "unreadable", "untriaged"];
1012
- var BLOCKED_REASON = "Everything opted in is blocked or already running, so waiting can still change the answer. Poll again at the polling interval.";
1013
- var TRIAGE_REASON = "An opted-in candidate carries neither `run:solo` nor `run:lane`, so nothing starts until it is judged. Read each issue named above, record its order and one of the two labels with a comment, then ask again.";
1014
- var EMPTY_BACKLOG = "The backlog is empty";
1015
- var WAITING_ON = {
1016
- exhausted: EMPTY_BACKLOG,
1017
- parked: "Nothing opted in can proceed without a person",
1018
- unreadable: "The backlog listing could not be read"
1019
- };
1020
- function waiting_on(answer) {
1021
- return WAITING_ON[answer] ?? EMPTY_BACKLOG;
1022
- }
1023
- function no_idle_watch_reason(answer) {
1024
- return `${waiting_on(answer)} and the idle watch was turned off with \`--idle 0\`, so the run finishes here.`;
1025
- }
1026
- function to_minutes(duration_ms) {
1027
- return String(Math.ceil(duration_ms / MS_PER_MINUTE));
1028
- }
1029
- function max_reached_reason(merged, max_issues) {
1030
- return `This run's maximum of ${String(max_issues)} is reached, with ${String(merged)} merged. Report what was done, including how many were picked up during an idle watch, and finish.`;
1031
- }
1032
- function draining_reason(running, reason) {
1033
- return `Start nothing more and poll until the running children merge (running: ${String(running)}). Then report and finish \u2014 ${reason}`;
1034
- }
1035
- function idle_expired_reason(answer, idle_budget_ms) {
1036
- return `${waiting_on(answer)}, and stayed so for the whole ${to_minutes(idle_budget_ms)}-minute idle watch. Report what was done, including how many were picked up during the watch, and finish.`;
1037
- }
1038
- function idle_watch_reason(answer, left_ms) {
1039
- return `${waiting_on(answer)} and the idle watch has about ${to_minutes(left_ms)} minutes left. Release the working tree, ask again in ${String(OFFER_INTERVAL_SECONDS)} seconds, and restart the watch the moment a candidate appears.`;
1040
- }
1041
- function running_watch_reason(answer, running, left_ms) {
1042
- return `${waiting_on(answer)} and the idle watch has about ${to_minutes(left_ms)} minutes left, with ${String(running)} still running. Keep the working tree until they merge and poll at the polling interval \u2014 the watch is running down meanwhile.`;
1043
- }
1044
- function watching_reason(input, left_ms) {
1045
- if (input.running === 0) return idle_watch_reason(input.answer, left_ms);
1046
- return running_watch_reason(input.answer, input.running, left_ms);
1047
- }
1048
- function taken_by(input) {
1049
- return input.merged + input.running;
1050
- }
1051
- function run_reason(input) {
1052
- const { max_issues } = input;
1053
- if (max_issues === void 0) return "No maximum was given, so start every issue offered.";
1054
- return `Start at most ${String(max_issues - taken_by(input))} more: this run's maximum is ${String(max_issues)}, with ${String(input.merged)} merged and ${String(input.running)} running.`;
1055
- }
1056
- function stopping(input, reason) {
1057
- if (input.running === 0) return { verdict: STOP_VERDICT, reason };
1058
- return { verdict: WATCH_VERDICT, reason: draining_reason(input.running, reason) };
1059
- }
1060
- function max_decision(input) {
1061
- const { max_issues } = input;
1062
- if (max_issues === void 0 || taken_by(input) < max_issues) return void 0;
1063
- return stopping(input, max_reached_reason(input.merged, max_issues));
1064
- }
1065
- function idle_decision(input) {
1066
- const { idle_budget_ms } = input;
1067
- if (idle_budget_ms === void 0) return stopping(input, no_idle_watch_reason(input.answer));
1068
- const left_ms = idle_budget_ms - (input.now_ms - input.active_at_ms);
1069
- if (left_ms > 0) return { verdict: WATCH_VERDICT, reason: watching_reason(input, left_ms) };
1070
- return stopping(input, idle_expired_reason(input.answer, idle_budget_ms));
1071
- }
1072
- function is_finish(input) {
1073
- return input.answer === "exhausted" && max_decision(input) === void 0;
1074
- }
1075
- var FIXED_DECISIONS = {
1076
- blocked: { verdict: WATCH_VERDICT, reason: BLOCKED_REASON },
1077
- untriaged: { verdict: TRIAGE_VERDICT, reason: TRIAGE_REASON }
1078
- };
1079
- function answer_decision(input) {
1080
- if (input.answer === "candidates") return { verdict: RUN_VERDICT, reason: run_reason(input) };
1081
- return FIXED_DECISIONS[input.answer] ?? idle_decision(input);
1082
- }
1083
- function decide(input) {
1084
- return max_decision(input) ?? answer_decision(input);
1085
- }
1086
- var backlog_budget = {
1087
- ANSWERS,
1088
- BLOCKED_REASON,
1089
- DEFAULT_IDLE_MINUTES,
1090
- DEFAULT_IDLE_MS,
1091
- IDLE_WAIT_HOURS,
1092
- MS_PER_MINUTE,
1093
- OFFER_INTERVAL_MS,
1094
- RUN_VERDICT,
1095
- STOP_VERDICT,
1096
- TRIAGE_REASON,
1097
- TRIAGE_VERDICT,
1098
- WAITING_ON,
1099
- WATCH_VERDICT,
1100
- decide,
1101
- draining_reason,
1102
- idle_expired_reason,
1103
- idle_watch_reason,
1104
- is_finish,
1105
- max_reached_reason,
1106
- no_idle_watch_reason,
1107
- run_reason,
1108
- running_watch_reason,
1109
- taken_by
1110
- };
1111
-
1112
- // scripts/backlog/backlog-budget-cli.ts
1113
- var ARGV_OFFSET = 2;
1114
- var SUCCESS_EXIT_CODE2 = 0;
1115
- var FAILURE_EXIT_CODE2 = 1;
1116
- var JSON_KEY = "budget";
1117
- var USAGE = `Usage: josh backlog:budget --answer <${backlog_budget.ANSWERS.join("|")}> --started <ISO-8601> [--active <ISO-8601>, required unless the watch is off] [--merged <count>] [--running <count>] [--max <count>] [--idle <minutes>, 0 to turn the watch off] [--json]`;
1118
- var OPTIONS = {
1119
- active: { type: "string" },
1120
- answer: { type: "string" },
1121
- idle: { type: "string" },
1122
- json: { type: "boolean" },
1123
- max: { type: "string" },
1124
- merged: { type: "string" },
1125
- running: { type: "string" },
1126
- started: { type: "string" }
1127
- };
1128
- function read_arguments(argv) {
1129
- return cli_flags.values_of(argv, OPTIONS);
1130
- }
1131
- function to_answer(raw) {
1132
- return backlog_budget.ANSWERS.find((answer) => answer === raw);
1133
- }
1134
- function to_time_ms(raw) {
1135
- if (raw === void 0) return void 0;
1136
- const parsed = Date.parse(raw);
1137
- return Number.isNaN(parsed) ? void 0 : parsed;
1138
- }
1139
- var COUNT_PATTERN = /^\d+$/u;
1140
- function to_count(raw) {
1141
- if (raw === void 0 || !COUNT_PATTERN.test(raw)) return void 0;
1142
- const parsed = Number(raw);
1143
- return Number.isSafeInteger(parsed) ? parsed : void 0;
1144
- }
1145
- function is_readable(raw, parsed) {
1146
- return raw === void 0 || parsed !== void 0;
1147
- }
1148
- var COUNT_NAMES = ["idle", "max", "merged", "running"];
1149
- function counts_of(values) {
1150
- return {
1151
- idle: to_count(cli_flags.string_of(values.idle)),
1152
- max: to_count(cli_flags.string_of(values.max)),
1153
- merged: to_count(cli_flags.string_of(values.merged)),
1154
- running: to_count(cli_flags.string_of(values.running))
1155
- };
1156
- }
1157
- function are_counts_readable(values, counts) {
1158
- return COUNT_NAMES.every((name) => is_readable(cli_flags.string_of(values[name]), counts[name]));
1159
- }
1160
- var NO_IDLE_MINUTES = 0;
1161
- function to_idle_ms(idle_minutes) {
1162
- if (idle_minutes === void 0) return backlog_budget.DEFAULT_IDLE_MS;
1163
- if (idle_minutes === NO_IDLE_MINUTES) return void 0;
1164
- return idle_minutes * backlog_budget.MS_PER_MINUTE;
1165
- }
1166
- function is_watch_readable(values) {
1167
- if (to_idle_ms(to_count(cli_flags.string_of(values.idle))) === void 0) return true;
1168
- return cli_flags.string_of(values.active) !== void 0;
1169
- }
1170
- function are_values_readable(values) {
1171
- return is_readable(
1172
- cli_flags.string_of(values.active),
1173
- to_time_ms(cli_flags.string_of(values.active))
1174
- ) && is_watch_readable(values) && are_counts_readable(values, counts_of(values));
1175
- }
1176
- function input_of(values, base) {
1177
- const counts = counts_of(values);
1178
- return {
1179
- ...base,
1180
- active_at_ms: to_time_ms(cli_flags.string_of(values.active)) ?? base.started_at_ms,
1181
- merged: counts.merged ?? 0,
1182
- running: counts.running ?? 0,
1183
- max_issues: counts.max,
1184
- idle_budget_ms: to_idle_ms(counts.idle)
1185
- };
1186
- }
1187
- function build_input(values, now_ms) {
1188
- const answer = to_answer(cli_flags.string_of(values.answer));
1189
- if (answer === void 0) return void 0;
1190
- const started_at_ms = to_time_ms(cli_flags.string_of(values.started));
1191
- if (started_at_ms === void 0 || !are_values_readable(values)) return void 0;
1192
- return input_of(values, { answer, now_ms, started_at_ms });
1193
- }
1194
- function print_json(input, decision) {
1195
- const { verdict, reason } = decision;
1196
- const is_finish2 = backlog_budget.is_finish(input);
1197
- console.info(JSON.stringify({ [JSON_KEY]: verdict, reason, is_finish: is_finish2 }));
1198
- }
1199
- function refuse() {
1200
- console.error(USAGE);
1201
- return FAILURE_EXIT_CODE2;
1202
- }
1203
- function run3(argv, now_ms = Date.now()) {
1204
- const values = read_arguments(argv);
1205
- if (values === void 0) return refuse();
1206
- const input = build_input(values, now_ms);
1207
- if (input === void 0) return refuse();
1208
- const decision = backlog_budget.decide(input);
1209
- if (values.json === true) {
1210
- print_json(input, decision);
1211
- return SUCCESS_EXIT_CODE2;
1212
- }
1213
- path_decision.print_decision(JSON_KEY, decision.verdict, decision.reason, false);
1214
- return SUCCESS_EXIT_CODE2;
1215
- }
1216
- function main(argv) {
1217
- process.exitCode = run3(argv);
1218
- }
1219
- var backlog_budget_cli = {
1220
- JSON_KEY,
1221
- OPTIONS,
1222
- SUCCESS_EXIT_CODE: SUCCESS_EXIT_CODE2,
1223
- USAGE,
1224
- build_input,
1225
- main,
1226
- read_arguments,
1227
- run: run3,
1228
- to_answer,
1229
- to_count,
1230
- to_time_ms
1231
- };
1232
- if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET));
1233
-
1234
- // scripts/issue/issue-number-shape.ts
1235
- var ISSUE_NUMBER_PATTERN = /^[1-9]\d*$/u;
1236
- var BAD_ISSUE_MESSAGE = "Not an issue number: ";
1237
- function is_issue_number(value) {
1238
- return ISSUE_NUMBER_PATTERN.test(value);
1239
- }
1240
- function require_issue_number(issue) {
1241
- if (!is_issue_number(issue)) throw new Error(`${BAD_ISSUE_MESSAGE}${issue}`);
1242
- }
1243
- var issue_number_shape = { ISSUE_NUMBER_PATTERN, is_issue_number, require_issue_number };
1244
-
1245
1007
  // scripts/run/run-invocation.ts
1246
1008
  var BACKLOG_COMMAND = "backlogrun";
1247
- var KNOWN_FLAGS2 = ["--max", "--idle"];
1009
+ var KNOWN_FLAGS = ["--max", "--idle"];
1248
1010
  var ONLY_FLAG = "--only";
1249
- var OPTIONS2 = {
1011
+ var OPTIONS = {
1250
1012
  max: { type: "string" },
1251
1013
  idle: { type: "string" },
1252
1014
  only: { type: "boolean" }
@@ -1263,8 +1025,8 @@ function tokens_of(invocation) {
1263
1025
  }
1264
1026
  function render_option(token) {
1265
1027
  if (token.name === cli_flags.option_name(ONLY_FLAG)) return ONLY_FLAG;
1266
- const flag = KNOWN_FLAGS2.find((known) => cli_flags.option_name(known) === token.name);
1267
- const value = backlog_budget_cli.to_count(token.value);
1028
+ const flag = KNOWN_FLAGS.find((known) => cli_flags.option_name(known) === token.name);
1029
+ const value = cli_flags.to_count(token.value);
1268
1030
  if (flag === void 0 || value === void 0) return void 0;
1269
1031
  return `${flag} ${String(value)}`;
1270
1032
  }
@@ -1281,15 +1043,15 @@ function issue_of(token) {
1281
1043
  if (!token.startsWith(ISSUE_PREFIX)) return void 0;
1282
1044
  const digits = token.slice(ISSUE_PREFIX.length);
1283
1045
  if (!issue_number_shape.ISSUE_NUMBER_PATTERN.test(digits)) return void 0;
1284
- const issue = Number(digits);
1285
- return Number.isSafeInteger(issue) ? issue : void 0;
1046
+ const issue2 = Number(digits);
1047
+ return Number.isSafeInteger(issue2) ? issue2 : void 0;
1286
1048
  }
1287
1049
  function issues_of(tokens) {
1288
1050
  const issues = [];
1289
1051
  for (const token of tokens) {
1290
- const issue = issue_of(token.value ?? "");
1291
- if (issue === void 0) return void 0;
1292
- issues.push(issue);
1052
+ const issue2 = issue_of(token.value ?? "");
1053
+ if (issue2 === void 0) return void 0;
1054
+ issues.push(issue2);
1293
1055
  }
1294
1056
  return issues;
1295
1057
  }
@@ -1298,7 +1060,7 @@ function argument_tokens(invocation) {
1298
1060
  if (tokens[FIRST_TOKEN] !== BACKLOG_COMMAND) return void 0;
1299
1061
  return cli_flags.parse_or_undefined({
1300
1062
  args: tokens.slice(FIRST_ARGUMENT_INDEX),
1301
- options: OPTIONS2,
1063
+ options: OPTIONS,
1302
1064
  allowPositionals: true,
1303
1065
  tokens: true
1304
1066
  })?.tokens;
@@ -1313,8 +1075,8 @@ function parse(invocation) {
1313
1075
  if (issues === void 0 || flags === void 0) return void 0;
1314
1076
  return { issues, flags };
1315
1077
  }
1316
- function issue_token(issue) {
1317
- return `${ISSUE_PREFIX}${String(issue)}`;
1078
+ function issue_token(issue2) {
1079
+ return `${ISSUE_PREFIX}${String(issue2)}`;
1318
1080
  }
1319
1081
  function joined(command, rendered) {
1320
1082
  return [command, ...rendered].join(TOKEN_SEPARATOR);
@@ -1323,7 +1085,7 @@ function rebuild(invocation) {
1323
1085
  const parsed = parse(invocation);
1324
1086
  if (parsed === void 0) return void 0;
1325
1087
  return joined(BACKLOG_COMMAND, [
1326
- ...parsed.issues.map((issue) => issue_token(issue)),
1088
+ ...parsed.issues.map((issue2) => issue_token(issue2)),
1327
1089
  ...parsed.flags
1328
1090
  ]);
1329
1091
  }
@@ -1353,7 +1115,7 @@ function issues_of2(added, is_priority) {
1353
1115
  }
1354
1116
  function ordered(declared, added = []) {
1355
1117
  const sequence = [...issues_of2(added, true), ...declared, ...issues_of2(added, false)];
1356
- return sequence.filter((issue, index) => sequence.indexOf(issue) === index);
1118
+ return sequence.filter((issue2, index) => sequence.indexOf(issue2) === index);
1357
1119
  }
1358
1120
  function next_added(carry, additions) {
1359
1121
  const next = [...carry.added ?? []];
@@ -1416,14 +1178,14 @@ function next_done(carry, done) {
1416
1178
  const current = carry.done ?? [];
1417
1179
  return current.includes(done) ? current : [...current, done];
1418
1180
  }
1419
- function next_merged_issues(carry, issue) {
1420
- if (issue === void 0) return carry.merged_issues;
1181
+ function next_merged_issues(carry, issue2) {
1182
+ if (issue2 === void 0) return carry.merged_issues;
1421
1183
  const current = carry.merged_issues ?? [];
1422
- return current.includes(issue) ? current : [...current, issue];
1184
+ return current.includes(issue2) ? current : [...current, issue2];
1423
1185
  }
1424
1186
  function is_duplicate_merge(carry, change) {
1425
- const issue = change.merged_issue;
1426
- return issue !== void 0 && carry.merged_issues?.includes(issue) === true;
1187
+ const issue2 = change.merged_issue;
1188
+ return issue2 !== void 0 && carry.merged_issues?.includes(issue2) === true;
1427
1189
  }
1428
1190
  function has_other_change(change) {
1429
1191
  const amounts = [change.filed, change.cuts, change.failures, change.outages];
@@ -1484,8 +1246,8 @@ function lane_root(repository_root2, environment = process.env) {
1484
1246
  const configured = environment[LANE_ROOT_KEY]?.trim() ?? "";
1485
1247
  return configured.length === 0 ? default_lane_root(repository_root2) : path3.resolve(configured);
1486
1248
  }
1487
- function lane_directory(root, issue) {
1488
- return path3.join(root, issue);
1249
+ function lane_directory(root, issue2) {
1250
+ return path3.join(root, issue2);
1489
1251
  }
1490
1252
  var DEFAULT_LANE_ROOT_PATTERN = new RegExp(String.raw`^\..+${LANE_DIRECTORY_SUFFIX}$`, "u");
1491
1253
  function is_lane_root(directory, environment) {
@@ -1495,12 +1257,12 @@ function is_lane_root(directory, environment) {
1495
1257
  }
1496
1258
  function lane_issue_of(directory, environment = process.env) {
1497
1259
  const resolved = path3.resolve(directory);
1498
- const issue = path3.basename(resolved);
1499
- if (!issue_number_shape.ISSUE_NUMBER_PATTERN.test(issue)) return void 0;
1500
- return is_lane_root(path3.dirname(resolved), environment) ? issue : void 0;
1260
+ const issue2 = path3.basename(resolved);
1261
+ if (!issue_number_shape.ISSUE_NUMBER_PATTERN.test(issue2)) return void 0;
1262
+ return is_lane_root(path3.dirname(resolved), environment) ? issue2 : void 0;
1501
1263
  }
1502
- function lane_branch(issue) {
1503
- return `${issue}${LANE_BRANCH_SUFFIX}`;
1264
+ function lane_branch(issue2) {
1265
+ return `${issue2}${LANE_BRANCH_SUFFIX}`;
1504
1266
  }
1505
1267
  var SEAT_LOCK_DIR = ".seat-locks";
1506
1268
  function is_lane_entry(name) {
@@ -1524,25 +1286,25 @@ var ABSENT_CODE = "ENOENT";
1524
1286
  function is_absent(error) {
1525
1287
  return error instanceof Error && "code" in error && error.code === ABSENT_CODE;
1526
1288
  }
1527
- function read_optional(path7) {
1289
+ function read_optional(path11) {
1528
1290
  try {
1529
- return readFileSync2(path7, "utf8");
1291
+ return readFileSync2(path11, "utf8");
1530
1292
  } catch (error) {
1531
1293
  if (is_absent(error)) return void 0;
1532
1294
  throw error;
1533
1295
  }
1534
1296
  }
1535
- function read_file_or_empty(path7) {
1536
- return read_optional(path7) ?? "";
1297
+ function read_file_or_empty(path11) {
1298
+ return read_optional(path11) ?? "";
1537
1299
  }
1538
- function read_if_readable(path7) {
1300
+ function read_if_readable(path11) {
1539
1301
  try {
1540
- return readFileSync2(path7, "utf8");
1302
+ return readFileSync2(path11, "utf8");
1541
1303
  } catch {
1542
1304
  return void 0;
1543
1305
  }
1544
1306
  }
1545
- var file_reader = { read_optional, read_file_or_empty, read_if_readable };
1307
+ var file_reader = { is_absent, read_optional, read_file_or_empty, read_if_readable };
1546
1308
 
1547
1309
  // scripts/time-runtime/time-instant.ts
1548
1310
  function parse_instant(raw) {
@@ -1734,9 +1496,9 @@ function lane_transcript_directories(main_cwd, home) {
1734
1496
  ).map((name) => path4.join(projects, name));
1735
1497
  }
1736
1498
  function transcript_directories(cwd, home = homedir()) {
1737
- const own = transcript_directory(cwd, home);
1499
+ const own2 = transcript_directory(cwd, home);
1738
1500
  const lanes = session_cwd(cwd) === cwd ? lane_transcript_directories(cwd, home) : [];
1739
- return [.../* @__PURE__ */ new Set([own, ...lanes])];
1501
+ return [.../* @__PURE__ */ new Set([own2, ...lanes])];
1740
1502
  }
1741
1503
  var OWN_DEPTH = 0;
1742
1504
  function home_directory() {
@@ -1797,9 +1559,9 @@ function list_sessions(directory) {
1797
1559
  (left, right) => right.modified_ms - left.modified_ms
1798
1560
  );
1799
1561
  }
1800
- function list_sessions_across(directories) {
1562
+ function list_sessions_across(directories2) {
1801
1563
  const seen = /* @__PURE__ */ new Set();
1802
- const merged = directories.flatMap((directory) => list_sessions(directory));
1564
+ const merged = directories2.flatMap((directory) => list_sessions(directory));
1803
1565
  const newest_first = merged.toSorted((left, right) => right.modified_ms - left.modified_ms);
1804
1566
  const kept = [];
1805
1567
  for (const file of newest_first) {
@@ -1863,8 +1625,8 @@ function directory_exists(directory) {
1863
1625
  return false;
1864
1626
  }
1865
1627
  }
1866
- function searched_directories(directories) {
1867
- return directories.map((directory) => ({
1628
+ function searched_directories(directories2) {
1629
+ return directories2.map((directory) => ({
1868
1630
  path: directory,
1869
1631
  exists: directory_exists(directory)
1870
1632
  }));
@@ -1890,6 +1652,7 @@ var cost_transcript = {
1890
1652
  transcript_directory,
1891
1653
  transcript_directories,
1892
1654
  session_cwd,
1655
+ lane_transcript_directories,
1893
1656
  unit_directory,
1894
1657
  list_sessions,
1895
1658
  list_sessions_across,
@@ -2009,11 +1772,11 @@ var own_session = {
2009
1772
 
2010
1773
  // scripts/run/carry/run-carry-conversation.ts
2011
1774
  var CONVERSATION_QUIET_MS = 6e5;
2012
- function own_transcript(environment = process.env, directories = cost_transcript.transcript_directories(process.cwd())) {
1775
+ function own_transcript(environment = process.env, directories2 = cost_transcript.transcript_directories(process.cwd())) {
2013
1776
  const session_id = own_session.session_id_of(environment);
2014
1777
  if (session_id === void 0) return void 0;
2015
1778
  const name = `${session_id}${cost_transcript.TRANSCRIPT_EXTENSION}`;
2016
- return directories.map((directory) => path5.join(directory, name)).find((file) => existsSync(file));
1779
+ return directories2.map((directory) => path5.join(directory, name)).find((file) => existsSync(file));
2017
1780
  }
2018
1781
  function modified_ms(transcript) {
2019
1782
  try {
@@ -2084,8 +1847,8 @@ function carry_path(git_directory) {
2084
1847
  return stamp_file.stamp_path(CARRY_PREFIX, git_directory);
2085
1848
  }
2086
1849
  async function repository_directory() {
2087
- const directories = await git_command.git_directories();
2088
- return directories[REPOSITORY_DIRECTORY_INDEX];
1850
+ const directories2 = await git_command.git_directories();
1851
+ return directories2[REPOSITORY_DIRECTORY_INDEX];
2089
1852
  }
2090
1853
  function parse_carry(raw) {
2091
1854
  return json_value.parse_with(raw, run_carry_schema);
@@ -2135,9 +1898,9 @@ function adopt_carry(target, carry, owner = NO_OWNER) {
2135
1898
  stamp_file.remove_stamp(target);
2136
1899
  return stamp_file.create_stamp(target, next) ? next : void 0;
2137
1900
  }
2138
- function is_owner_live(carry, now = /* @__PURE__ */ new Date()) {
2139
- if (process_identity.is_same_process(carry.owner_pid, carry.owner_start) !== false) return true;
2140
- return run_carry_conversation.is_conversation_live(carry, now);
1901
+ function is_owner_live(carry, now = /* @__PURE__ */ new Date(), same_process = process_identity.is_same_process) {
1902
+ if (same_process(carry.owner_pid, carry.owner_start) !== false) return true;
1903
+ return carry.is_owner_headless !== true && run_carry_conversation.is_conversation_live(carry, now);
2141
1904
  }
2142
1905
  function is_owned_by(carry, owner) {
2143
1906
  if (run_carry_conversation.is_same_conversation(carry, owner)) return true;
@@ -2177,7 +1940,7 @@ function remaining_of(carry) {
2177
1940
  const declared = run_invocation.issue_numbers(carry.invocation);
2178
1941
  if (declared === void 0) return void 0;
2179
1942
  const done = carry.done ?? [];
2180
- return run_carry_added.ordered(declared, carry.added).filter((issue) => !done.includes(issue));
1943
+ return run_carry_added.ordered(declared, carry.added).filter((issue2) => !done.includes(issue2));
2181
1944
  }
2182
1945
  function done_note(carry) {
2183
1946
  const done = carry.done ?? [];
@@ -2336,38 +2099,1756 @@ var ports = {
2336
2099
  resolve_preview_port
2337
2100
  };
2338
2101
 
2339
- // scripts/josh/process-owner.ts
2102
+ // scripts/issue/issue-cite.ts
2103
+ var GITHUB_URL_PREFIX = "https://github.com/";
2104
+ var ISSUE_PATH = "/issues/";
2105
+ var SUMMARY_SEPARATOR = " \u2014 ";
2106
+ var REPO_QUALIFIED = /^([^\s/#]+\/[^\s/#]+)#(\d+)$/u;
2107
+ var BARE_NUMBER = /^#?(\d+)$/u;
2108
+ function plain(number, repo = "") {
2109
+ return `${repo}#${String(number)}`;
2110
+ }
2111
+ function issue_url(slug, number) {
2112
+ return `${GITHUB_URL_PREFIX}${slug}${ISSUE_PATH}${number}`;
2113
+ }
2114
+ function citation_line(slug, number, summary) {
2115
+ return `[${plain(number)}](${issue_url(slug, number)})${SUMMARY_SEPARATOR}${summary}`;
2116
+ }
2117
+ function reference(slug, number, title) {
2118
+ if (slug === void 0) return plain(number);
2119
+ return title === void 0 ? `[${plain(number)}](${issue_url(slug, number)})` : citation_line(slug, number, title);
2120
+ }
2121
+ function citer(slug, titles) {
2122
+ return function cite(number) {
2123
+ return reference(slug, number, titles.get(number));
2124
+ };
2125
+ }
2126
+ function qualified_target(token) {
2127
+ const match = REPO_QUALIFIED.exec(token);
2128
+ if (match === null) return void 0;
2129
+ const [, repo = "", number = ""] = match;
2130
+ return { number, repo };
2131
+ }
2132
+ function bare_target(token, default_repo) {
2133
+ const match = BARE_NUMBER.exec(token);
2134
+ if (match === null) return void 0;
2135
+ const [, number = ""] = match;
2136
+ return { number, repo: default_repo };
2137
+ }
2138
+ function parse_target(token, default_repo) {
2139
+ return qualified_target(token) ?? bare_target(token, default_repo);
2140
+ }
2141
+ function label(target) {
2142
+ return plain(target.number, target.repo);
2143
+ }
2144
+ function missing_line(target) {
2145
+ return `\u2716 ${label(target)}: issue does not resolve \u2014 check the number and the repository`;
2146
+ }
2147
+ function unreadable_line(target) {
2148
+ return `\u2716 ${label(target)}: could not be read \u2014 a rate limit, expired auth, or a dropped connection`;
2149
+ }
2150
+ function no_repo_line(target) {
2151
+ return `\u2716 ${label(target)}: could not read this repository \u2014 check gh auth and the origin remote`;
2152
+ }
2153
+ var issue_cite = {
2154
+ citation_line,
2155
+ citer,
2156
+ issue_url,
2157
+ missing_line,
2158
+ no_repo_line,
2159
+ parse_target,
2160
+ plain,
2161
+ reference,
2162
+ unreadable_line
2163
+ };
2164
+
2165
+ // scripts/git/git-common-directory.ts
2166
+ import { execFileSync as execFileSync2 } from "node:child_process";
2167
+ var OWN_GIT_DIRECTORY = 0;
2168
+ var COMMON_GIT_DIRECTORY = 1;
2169
+ var PROBE_TIMEOUT_MS2 = 5e3;
2170
+ var answers = /* @__PURE__ */ new Map();
2171
+ function probe_environment(cwd) {
2172
+ if (cwd === void 0) return process.env;
2173
+ return { ...process.env, ...git_location_environment.location_free_environment() };
2174
+ }
2175
+ function cache_key(cwd) {
2176
+ if (cwd !== void 0) return `explicit\0${cwd}`;
2177
+ const locations = GIT_LOCATION_VARIABLES.map((name) => process.env[name] ?? "");
2178
+ return ["inherited", process.cwd(), ...locations].join("\0");
2179
+ }
2180
+ function read_directories(cwd) {
2181
+ try {
2182
+ const output = execFileSync2(
2183
+ git_utilities.get_git_command_for_spawn(),
2184
+ [...git_command.GIT_DIRECTORY_ARGUMENTS],
2185
+ {
2186
+ cwd,
2187
+ env: probe_environment(cwd),
2188
+ encoding: "utf8",
2189
+ stdio: ["ignore", "pipe", "ignore"],
2190
+ timeout: PROBE_TIMEOUT_MS2
2191
+ }
2192
+ );
2193
+ return output.split("\n").filter((line) => line !== "");
2194
+ } catch {
2195
+ return [];
2196
+ }
2197
+ }
2198
+ function directories(cwd) {
2199
+ const key = cache_key(cwd);
2200
+ const known = answers.get(key);
2201
+ if (known !== void 0) return known;
2202
+ const read3 = read_directories(cwd);
2203
+ if (read3.length > 0) answers.set(key, read3);
2204
+ return read3;
2205
+ }
2206
+ function own(cwd) {
2207
+ return directories(cwd)[OWN_GIT_DIRECTORY];
2208
+ }
2209
+ function repository(cwd) {
2210
+ return directories(cwd)[COMMON_GIT_DIRECTORY];
2211
+ }
2212
+ function select_linked(found) {
2213
+ const own_directory = found[OWN_GIT_DIRECTORY];
2214
+ const common = found[COMMON_GIT_DIRECTORY];
2215
+ return own_directory === void 0 || common === void 0 || own_directory === common ? void 0 : common;
2216
+ }
2217
+ function resolve(cwd) {
2218
+ return select_linked(directories(cwd));
2219
+ }
2220
+ var git_common_directory = { directories, own, repository, resolve, select_linked };
2221
+
2222
+ // scripts/run/ship/run-ship-stage.ts
2340
2223
  import { z as z3 } from "zod";
2341
- var process_owner_schema = z3.object({ pid: z3.number(), process_start: z3.string().optional() });
2224
+ var STAGE = {
2225
+ PREFLIGHT: "preflight",
2226
+ REVIEW: "review",
2227
+ GATE: "gate",
2228
+ SYNC: "sync",
2229
+ COMMIT: "commit",
2230
+ ROUND_TWO: "round-2",
2231
+ FOLLOWUP: "followup",
2232
+ REPORT: "report"
2233
+ };
2234
+ var PHASE = {
2235
+ START: "start",
2236
+ DONE: "done",
2237
+ FAILED: "failed",
2238
+ SKIPPED: "skipped"
2239
+ };
2240
+ var RECORD_PREFIX = "josh-ship-stages-";
2241
+ var RECORD_SEPARATOR = "-";
2242
+ var SKIP_COMMIT_FLAG = "--skip-commit";
2243
+ var SKIP_PUSH_FLAG = "--skip-push";
2244
+ var WORD_SEPARATOR = " ";
2245
+ var STARTED_SEPARATOR = ",";
2246
+ var STARTED_INDEX = 3;
2247
+ var WORD_COUNT = STARTED_INDEX + 1;
2248
+ var record_schema = z3.object({
2249
+ done: z3.array(z3.string()),
2250
+ started: z3.array(z3.string()).default([]),
2251
+ is_merge_waiting: z3.boolean().default(false),
2252
+ is_place_waiting: z3.boolean().default(false)
2253
+ });
2254
+ var EMPTY_RECORD = {
2255
+ done: [],
2256
+ started: [],
2257
+ is_merge_waiting: false,
2258
+ is_place_waiting: false
2259
+ };
2260
+ function record_path(repository2, issue2) {
2261
+ return stamp_file.stamp_path(`${RECORD_PREFIX}${issue2}${RECORD_SEPARATOR}`, repository2);
2262
+ }
2263
+ function parse_record(raw) {
2264
+ return json_value.parse_with(raw, record_schema) ?? EMPTY_RECORD;
2265
+ }
2266
+ function read_record(target) {
2267
+ const raw = stamp_file.read_stamp_text(target);
2268
+ return raw === void 0 ? EMPTY_RECORD : parse_record(raw);
2269
+ }
2270
+ function read_done(target) {
2271
+ return new Set(read_record(target).done);
2272
+ }
2273
+ function mark_done(target, stage) {
2274
+ const record = read_record(target);
2275
+ stamp_file.replace_stamp(target, { ...record, done: [.../* @__PURE__ */ new Set([...record.done, stage])] });
2276
+ }
2277
+ function read_started(target) {
2278
+ return read_record(target).started;
2279
+ }
2280
+ function mark_started(target, stage) {
2281
+ const record = read_record(target);
2282
+ stamp_file.replace_stamp(target, { ...record, started: [.../* @__PURE__ */ new Set([...record.started, stage])] });
2283
+ }
2284
+ function end_attempt(target) {
2285
+ stamp_file.replace_stamp(target, { ...read_record(target), started: [], is_merge_waiting: false });
2286
+ }
2287
+ function read_merge_waiting(target) {
2288
+ return read_record(target).is_merge_waiting;
2289
+ }
2290
+ function mark_merge_waiting(target, is_merge_waiting) {
2291
+ stamp_file.replace_stamp(target, { ...read_record(target), is_merge_waiting });
2292
+ }
2293
+ function read_place_waiting(target) {
2294
+ return read_record(target).is_place_waiting;
2295
+ }
2296
+ function mark_place_waiting(target, is_place_waiting) {
2297
+ stamp_file.replace_stamp(target, { ...read_record(target), is_place_waiting });
2298
+ }
2299
+ function clear_waits(target) {
2300
+ stamp_file.replace_stamp(target, {
2301
+ ...read_record(target),
2302
+ is_merge_waiting: false,
2303
+ is_place_waiting: false
2304
+ });
2305
+ }
2306
+ function clear(target) {
2307
+ stamp_file.remove_stamp(target);
2308
+ }
2309
+ function is_shipped(state) {
2310
+ return state.is_committed && state.is_pushed;
2311
+ }
2312
+ var DONE_BY = {
2313
+ // The preflight asks what the commit stage would refuse on, so a commit is
2314
+ // its output as it is the gate's; a resumed commit stage still asks `git -y`'s own preflight.
2315
+ [STAGE.PREFLIGHT]: (_done, state) => state.is_merged || state.is_committed,
2316
+ // The `--review` round precedes the commit, so a commit is its output as it
2317
+ // is the gate's. A record alone is not honored: before a commit the tree may have been edited since
2318
+ // the recorded round, and only a commit pins the tree that round read — unless the issue changed since.
2319
+ [STAGE.REVIEW]: (_done, state) => state.is_merged || state.is_committed && state.is_review_stale !== true,
2320
+ [STAGE.GATE]: (_done, state) => state.is_merged || state.is_committed,
2321
+ // The merge of the default branch before the commit: once committed, a
2322
+ // conflicting pull request is the followup's to merge again.
2323
+ [STAGE.SYNC]: (_done, state) => state.is_merged || state.is_committed,
2324
+ [STAGE.COMMIT]: (done, state) => state.is_merged || done.has(STAGE.COMMIT) && is_shipped(state),
2325
+ // The round-2 pass reads the pushed fix delta, so its record is honored only
2326
+ // while that push still stands — new work pushed on top reruns it.
2327
+ [STAGE.ROUND_TWO]: (done, state) => state.is_merged || done.has(STAGE.ROUND_TWO) && is_shipped(state),
2328
+ // A recorded followup still needs the shipped state: a record left by a merged ship whose report
2329
+ // failed must not pass over the followup of new, not-yet-pushed work on the same issue.
2330
+ [STAGE.FOLLOWUP]: (done, state) => state.is_merged || done.has(STAGE.FOLLOWUP) && is_shipped(state),
2331
+ [STAGE.REPORT]: (done) => done.has(STAGE.REPORT)
2332
+ };
2333
+ function is_done(stage, done, state, has_body = false) {
2334
+ if (has_body && stage === STAGE.COMMIT && !state.is_merged) return false;
2335
+ return DONE_BY[stage](done, state);
2336
+ }
2337
+ function commit_flags(state) {
2338
+ if (!state.is_committed) return [];
2339
+ return state.is_pushed ? [SKIP_COMMIT_FLAG, SKIP_PUSH_FLAG] : [SKIP_COMMIT_FLAG];
2340
+ }
2341
+ function event_text(issue2, stage, phase, started = []) {
2342
+ const words = [issue_cite.plain(issue2), stage, phase];
2343
+ const listed = [...new Set(started)].join(STARTED_SEPARATOR);
2344
+ const full = started.length > 0 ? [...words, listed] : words;
2345
+ return full.join(WORD_SEPARATOR);
2346
+ }
2347
+ function started_of(text2) {
2348
+ return text2.split(WORD_SEPARATOR, WORD_COUNT)[STARTED_INDEX]?.split(STARTED_SEPARATOR);
2349
+ }
2350
+ var CONFLICT = "conflict";
2351
+ function stop_reason(stage, conflicts = []) {
2352
+ return conflicts.length > 0 ? CONFLICT : stage;
2353
+ }
2354
+ var run_ship_stage = {
2355
+ CONFLICT,
2356
+ PHASE,
2357
+ STAGE,
2358
+ clear,
2359
+ clear_waits,
2360
+ commit_flags,
2361
+ end_attempt,
2362
+ event_text,
2363
+ is_done,
2364
+ mark_done,
2365
+ mark_merge_waiting,
2366
+ mark_place_waiting,
2367
+ mark_started,
2368
+ read_done,
2369
+ read_merge_waiting,
2370
+ read_place_waiting,
2371
+ read_started,
2372
+ record_path,
2373
+ started_of,
2374
+ stop_reason
2375
+ };
2376
+
2377
+ // scripts/git/repository-lock.ts
2378
+ import { randomUUID as randomUUID2 } from "node:crypto";
2379
+ import { linkSync, renameSync, rmSync as rmSync2 } from "node:fs";
2380
+ import { setTimeout as sleep } from "node:timers/promises";
2381
+
2382
+ // scripts/josh/process-owner.ts
2383
+ import { z as z4 } from "zod";
2384
+ var process_owner_schema = z4.object({ pid: z4.number(), process_start: z4.string().optional() });
2385
+
2386
+ // scripts/git/repository-lock.ts
2387
+ var POLL_INTERVAL_MS = 200;
2388
+ var SYNC_POLL_INTERVAL_MS = 10;
2389
+ var SLEEP_CELL = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
2390
+ function lock_path(prefix, cwd) {
2391
+ return stamp_file.stamp_path(prefix, git_common_directory.repository(cwd) ?? cwd ?? process.cwd());
2392
+ }
2393
+ function parse_owner(raw) {
2394
+ if (raw === void 0) return void 0;
2395
+ const parsed = process_owner_schema.safeParse(json_value.parse_or_undefined(raw));
2396
+ return parsed.success ? parsed.data : void 0;
2397
+ }
2398
+ function read_owner(target) {
2399
+ return parse_owner(stamp_file.read_stamp_text(target));
2400
+ }
2401
+ function is_owner_gone(owner) {
2402
+ return process_identity.is_same_process(owner.pid, owner.process_start) === false;
2403
+ }
2404
+ function restore(aside, target) {
2405
+ try {
2406
+ linkSync(aside, target);
2407
+ } catch {
2408
+ }
2409
+ }
2410
+ function stale_record(target, is_gone) {
2411
+ const raw = stamp_file.read_stamp_text(target);
2412
+ const owner = parse_owner(raw);
2413
+ return owner !== void 0 && is_gone(owner) ? raw : void 0;
2414
+ }
2415
+ function move_aside(target) {
2416
+ const aside = `${target}.${String(process.pid)}.${randomUUID2()}`;
2417
+ try {
2418
+ renameSync(target, aside);
2419
+ return aside;
2420
+ } catch {
2421
+ return void 0;
2422
+ }
2423
+ }
2424
+ function clear_stale(target, is_gone = is_owner_gone) {
2425
+ const raw = stale_record(target, is_gone);
2426
+ if (raw === void 0) return;
2427
+ const aside = move_aside(target);
2428
+ if (aside === void 0) return;
2429
+ if (stamp_file.read_stamp_text(aside) !== raw) restore(aside, target);
2430
+ rmSync2(aside, { force: true });
2431
+ }
2432
+ function claim(target) {
2433
+ clear_stale(target);
2434
+ return stamp_file.create_stamp(target, process_identity.own_fields());
2435
+ }
2436
+ function release(target) {
2437
+ const owner = read_owner(target);
2438
+ if (owner !== void 0 && process_identity.is_own_process(owner.pid, owner.process_start)) {
2439
+ stamp_file.remove_stamp(target);
2440
+ }
2441
+ }
2442
+ async function acquire(target, max_wait_ms) {
2443
+ const deadline = Date.now() + max_wait_ms;
2444
+ while (!claim(target)) {
2445
+ if (Date.now() >= deadline) return false;
2446
+ await sleep(POLL_INTERVAL_MS);
2447
+ }
2448
+ return true;
2449
+ }
2450
+ function sleep_sync(ms) {
2451
+ Atomics.wait(SLEEP_CELL, 0, 0, ms);
2452
+ }
2453
+ function acquire_sync(target, max_wait_ms) {
2454
+ const deadline = Date.now() + max_wait_ms;
2455
+ while (!claim(target)) {
2456
+ if (Date.now() >= deadline) return false;
2457
+ sleep_sync(SYNC_POLL_INTERVAL_MS);
2458
+ }
2459
+ return true;
2460
+ }
2461
+ async function with_lock(work, target, max_wait_ms) {
2462
+ if (!await acquire(target, max_wait_ms)) return void 0;
2463
+ try {
2464
+ return await work();
2465
+ } finally {
2466
+ release(target);
2467
+ }
2468
+ }
2469
+ function with_lock_sync(work, target, max_wait_ms) {
2470
+ if (!acquire_sync(target, max_wait_ms)) return void 0;
2471
+ try {
2472
+ return work();
2473
+ } finally {
2474
+ release(target);
2475
+ }
2476
+ }
2477
+ var repository_lock = { clear_stale, lock_path, with_lock, with_lock_sync };
2478
+
2479
+ // scripts/run/event/run-event-stream.ts
2480
+ import { z as z5 } from "zod";
2481
+ var EVENT_PREFIX = "josh-run-events-";
2482
+ var EVENT_SUFFIX = ".jsonl";
2483
+ var EVENT_CAP = 15e3;
2484
+ var FIRST_POSITION = 0;
2485
+ var POSITION_INCREMENT = 1;
2486
+ var LINE_SEPARATOR = "\n";
2487
+ var WORD_SEPARATOR2 = " ";
2488
+ var STAGE_PHASE_INDEX = 2;
2489
+ var LOCK_SUFFIX = ".lock";
2490
+ var LOCK_WAIT_MS = 5e3;
2491
+ var EVENT_KIND = {
2492
+ PLAN: "plan",
2493
+ CHILD_LAUNCH: "child-launch",
2494
+ MERGE: "merge",
2495
+ PARK: "park",
2496
+ SPLIT: "split",
2497
+ OUTAGE: "outage",
2498
+ CUT: "cut",
2499
+ // A fresh session adopted an implementation cut — `run:cut --resume` answered `resume-impl`. The
2500
+ // resume clears the cut record, so without this the `cut` would stay the newest position and
2501
+ // `run:step` would keep answering the resume command it had just run.
2502
+ RESUME: "resume",
2503
+ // A person stopped a running lane child and re-dispatched its issue in a fresh session
2504
+ // (`lane:restart`). It follows the fresh dispatch's `CHILD_LAUNCH`, so it is a launch to the parent and
2505
+ // the board, and — like that launch — a batch record a lane child never reads as its own position.
2506
+ RESTART: "restart",
2507
+ // A person withdrew a lane child — stopped it and left its issue open for the next run (`lane:withdraw`).
2508
+ // It is written before the stop, so `run:merge` settles the child as withdrawn whatever GitHub says
2509
+ // by the time the parent collects it, and counts it as neither a merge, a failure nor an outage.
2510
+ WITHDRAW: "withdraw",
2511
+ // The backlog emptied while nothing of the run's own was in flight — the drain. It marks the position
2512
+ // at which the end-of-run retrospective is owed, *before* the idle watch opens, so `run:step` fires
2513
+ // the retrospective at the drain rather than after the watch runs its course. It is not itself a
2514
+ // stop: the run watches on once the retrospective has run, and the real `STOP` follows when the watch
2515
+ // expires.
2516
+ DRAIN: "drain",
2517
+ STOP: "stop",
2518
+ PR_OPENED: "pr-opened",
2519
+ REVIEW_ROUND: "review-round",
2520
+ // The end-of-run retrospective's result, recorded when the run marks the retrospective done. A
2521
+ // retrospective that files zero improvements and one that never ran look
2522
+ // the same from outside — no new Issue either way — so the result is put on the stream the report is
2523
+ // generated from: the issues filed (or that none were), and the candidates dropped with why. It is
2524
+ // emitted from the `run:carry --retrospective` close, so marking the retrospective done and recording
2525
+ // what it found are one action rather than two the run could do only one of.
2526
+ RETROSPECTIVE: "retrospective",
2527
+ // Ready backlog work is sitting undispatched while a lane is free and nothing has dispatched for a
2528
+ // while. Emitted once per stall episode by the stop-time detector, it is both the dedup marker —
2529
+ // `emit_once_since` refuses a second until a `CHILD_LAUNCH` intervenes — and the line a terminal
2530
+ // reader following the stream sees. `run:step` reads it as `backlog:next`, so a run that
2531
+ // stalled is pointed straight at dispatching the work rather than left waiting.
2532
+ STALL: "stall",
2533
+ // The run's own driver is gone: the cut handed the budget off, the owner has died, and no supervisor
2534
+ // is watching. Emitted once per strand episode by the stop-time detector — or by the `run:wake`
2535
+ // supervisor as it fails, leaves that state behind and has warned of it —
2536
+ // exactly as `STALL` is — the newest-event dedup keeps a run polled every stop from notifying more
2537
+ // than once, and a terminal reader following the stream sees the line. The strand is the step before
2538
+ // the stall: a stalled run still has a driver that could dispatch, a stranded one has none.
2539
+ STRANDED: "stranded",
2540
+ // One `josh ship` stage starting, succeeding or failing. It is a trace of the
2541
+ // composite's progress rather than a position the run is at — the positions a ship leaves behind are
2542
+ // the closed issue its `followup` merges, or a detached supervisor's `SHIP_LAUNCH` / `SHIP_STOP` below
2543
+ // — so it is one of the `TRACE_KINDS` the last-event read skips.
2544
+ SHIP_STAGE: "ship-stage",
2545
+ // One progress watcher line — the `at … / next …` heartbeat `run:progress` prints. Printed only to
2546
+ // the watcher's own output, a headless successor's heartbeat would be buried in its log after a cut;
2547
+ // on the stream it reaches the attached session's relay. It says
2548
+ // the run is alive rather than where it is, so it is a trace kind like `SHIP_STAGE`.
2549
+ HEARTBEAT: "heartbeat",
2550
+ // The post-implementation region handed to a detached `josh ship --detach` supervisor. Unlike a stage
2551
+ // trace it is a position: the agent has ended and the
2552
+ // supervisor carries the run, so `run:step` answers `wait` until it stops or the issue closes.
2553
+ SHIP_LAUNCH: "ship-launch",
2554
+ // The supervisor stopped at a failed stage — a red gate, a High/Medium review, a failed push, red CI
2555
+ // The position that hands control back: `run:step` prints the command that
2556
+ // shows the stopped report, so the agent fixes it and relaunches rather than rebuilding the context.
2557
+ SHIP_STOP: "ship-stop",
2558
+ // An Issue the run filed on its way, written by `issue:file`, so a run started from the command line
2559
+ // still surfaces what it found — `run:board`'s findings section reads it.
2560
+ FILED: "filed",
2561
+ // A one-line observation short of an Issue, written with `run:event --append note` and shown in the
2562
+ // same section.
2563
+ NOTE: "note",
2564
+ // A lane child reached a phase no other event marks — its first implementation edit, written by the
2565
+ // PreToolUse hook — so `run:board` draws how far the child has got. A trace,
2566
+ // like `SHIP_STAGE`: it says where the child's work is, not where the run is.
2567
+ LANE_PHASE: "lane-phase",
2568
+ // An issue `run:add` put into the live run. The parent's `--wait` watcher
2569
+ // ends on it, so the issue takes the next free lane without waiting out the arrival probe's minute. A
2570
+ // trace: it says what the run was handed, not where the run is.
2571
+ ADD: "add",
2572
+ // `josh lane:limit` raised a live run's lane limit. The `--wait` watcher's
2573
+ // arrival probe reads it as a wake: the lanes a raise frees are new room for a pool its baseline
2574
+ // already holds. A trace: it says the run gained room, not where the run is.
2575
+ LANE_LIMIT: "lane-limit",
2576
+ // One stage of the run's start — the session starting, the plan, the hand-off to the supervisor, a
2577
+ // lane opening (`run-event-setup.ts`). `run:board` draws it while the run stands at it, so the
2578
+ // minutes before one read as work rather than as a run that has stopped. A trace: it says the run is
2579
+ // getting ready, not where the run is.
2580
+ SETUP: "setup",
2581
+ // A child's pull request checks as `josh followup` last polled them — the CI counts and CodeRabbit's
2582
+ // state (`run-event-checks.ts`), written only when they change, so `run:board` draws a child waiting
2583
+ // in followup without asking GitHub (joshuafolkken/kit#3770). A trace: it says how the checks stand,
2584
+ // not where the run is.
2585
+ PR_CHECKS: "pr-checks",
2586
+ // `backlog:drive` reached a watch with no child running and nothing to dispatch — the point a person's
2587
+ // hand is wanted. Emitted once per idle episode (`emit_once_since_with`, reset by `CHILD_LAUNCH`), it
2588
+ // is the dedup marker for the one idle Telegram. A trace: a drain's retrospective is read off the
2589
+ // position beneath it, so the marker must not stand over it.
2590
+ IDLE_NOTICE: "idle-notice",
2591
+ // A person paused or resumed a lane child (`lane:pause` / `lane:resume`), so who halted a lane and
2592
+ // when is on the stream rather than only in a shell history (joshuafolkken/kit#4268). A trace: it
2593
+ // says what a lane's processes were told, not where the run is.
2594
+ LANE_STATE: "lane-state",
2595
+ // `backlog:drive` found nothing of the run in flight and only paused lanes left, paused past the
2596
+ // silent window (joshuafolkken/kit#4270). Emitted once per pause episode (`emit_once_since_with`,
2597
+ // reset by `LANE_STATE`), it is the dedup marker for the one paused-lane Telegram. A trace.
2598
+ PAUSED_NOTICE: "paused-notice"
2599
+ };
2600
+ var EVENT_KINDS = Object.values(EVENT_KIND);
2601
+ var TRACE_KINDS = /* @__PURE__ */ new Set([
2602
+ EVENT_KIND.SHIP_STAGE,
2603
+ EVENT_KIND.HEARTBEAT,
2604
+ EVENT_KIND.FILED,
2605
+ EVENT_KIND.NOTE,
2606
+ EVENT_KIND.LANE_PHASE,
2607
+ EVENT_KIND.ADD,
2608
+ EVENT_KIND.LANE_LIMIT,
2609
+ EVENT_KIND.SETUP,
2610
+ EVENT_KIND.PR_CHECKS,
2611
+ EVENT_KIND.IDLE_NOTICE,
2612
+ EVENT_KIND.LANE_STATE,
2613
+ EVENT_KIND.PAUSED_NOTICE
2614
+ ]);
2615
+ var DISPOSABLE_KINDS = /* @__PURE__ */ new Set([
2616
+ EVENT_KIND.SHIP_STAGE,
2617
+ EVENT_KIND.HEARTBEAT,
2618
+ EVENT_KIND.SETUP,
2619
+ EVENT_KIND.PR_CHECKS
2620
+ ]);
2621
+ var event_schema = z5.object({
2622
+ pos: z5.number(),
2623
+ at: z5.string(),
2624
+ kind: z5.string(),
2625
+ text: z5.string(),
2626
+ // The child's time on a lane, recorded once by the writer of an ending (joshuafolkken/kit#4481), so a
2627
+ // reader never has to find its launch again. An event written before it has none.
2628
+ elapsed_ms: z5.number().optional()
2629
+ });
2630
+ function is_event_kind(value) {
2631
+ return EVENT_KINDS.includes(value);
2632
+ }
2633
+ function target_of(repository2) {
2634
+ return stamp_file.stamp_path(EVENT_PREFIX, repository2, EVENT_SUFFIX);
2635
+ }
2636
+ function is_present(event) {
2637
+ return event !== void 0;
2638
+ }
2639
+ function parse_line2(line) {
2640
+ return event_schema.safeParse(json_value.parse_or_undefined(line)).data;
2641
+ }
2642
+ function read_lines(target) {
2643
+ const raw = stamp_file.read_stamp_text(target);
2644
+ if (raw === void 0) return [];
2645
+ return raw.split(LINE_SEPARATOR).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => parse_line2(line)).filter(is_present);
2646
+ }
2647
+ function read_events(target) {
2648
+ return read_lines(target).filter((event) => is_event_kind(event.kind));
2649
+ }
2650
+ function last_position(events) {
2651
+ return events[events.length - POSITION_INCREMENT]?.pos ?? FIRST_POSITION;
2652
+ }
2653
+ function issue_of2(event) {
2654
+ return event.text.split(WORD_SEPARATOR2)[FIRST_POSITION] ?? "";
2655
+ }
2656
+ function newest_by_issue(events, kind) {
2657
+ const newest = /* @__PURE__ */ new Map();
2658
+ for (const event of events) {
2659
+ if (event.kind === kind) newest.set(issue_of2(event), event);
2660
+ }
2661
+ return new Set(newest.values());
2662
+ }
2663
+ function is_stage_start(event) {
2664
+ if (event.kind !== EVENT_KIND.SHIP_STAGE) return false;
2665
+ return event.text.split(WORD_SEPARATOR2)[STAGE_PHASE_INDEX] === run_ship_stage.PHASE.START;
2666
+ }
2667
+ function drawn_lines(events) {
2668
+ const setup = events.findLast((event) => event.kind === EVENT_KIND.SETUP);
2669
+ return /* @__PURE__ */ new Set([
2670
+ ...newest_by_issue(events, EVENT_KIND.SHIP_STAGE),
2671
+ ...newest_by_issue(events, EVENT_KIND.PR_CHECKS),
2672
+ ...setup === void 0 ? [] : [setup]
2673
+ ]);
2674
+ }
2675
+ function droppable(events) {
2676
+ const kept = drawn_lines(events);
2677
+ const disposable = events.filter((event) => DISPOSABLE_KINDS.has(event.kind) && !kept.has(event));
2678
+ return [
2679
+ ...disposable.filter((event) => !is_stage_start(event)),
2680
+ ...disposable.filter((event) => is_stage_start(event))
2681
+ ];
2682
+ }
2683
+ function bounded(events) {
2684
+ const excess = events.length - EVENT_CAP;
2685
+ if (excess <= 0) return events;
2686
+ const dropped = new Set(droppable(events).slice(0, excess));
2687
+ return events.filter((event) => !dropped.has(event)).slice(-EVENT_CAP);
2688
+ }
2689
+ function serialize(events) {
2690
+ return `${events.map((event) => JSON.stringify(event)).join(LINE_SEPARATOR)}${LINE_SEPARATOR}`;
2691
+ }
2692
+ function append_held(target, event) {
2693
+ const position = last_position(read_lines(target)) + POSITION_INCREMENT;
2694
+ const events = bounded([...read_events(target), { pos: position, ...event }]);
2695
+ stamp_file.replace_text_stamp(target, serialize(events));
2696
+ return position;
2697
+ }
2698
+ function append_event(target, event) {
2699
+ if (!is_event_kind(event.kind)) return { appended: false, position: FIRST_POSITION };
2700
+ const lock = `${target}${LOCK_SUFFIX}`;
2701
+ const position = repository_lock.with_lock_sync(
2702
+ () => append_held(target, event),
2703
+ lock,
2704
+ LOCK_WAIT_MS
2705
+ );
2706
+ if (position === void 0) {
2707
+ const message = `run event stream: gave up waiting for the lock at ${lock}`;
2708
+ process.stderr.write(`${message}
2709
+ `);
2710
+ throw new Error(message);
2711
+ }
2712
+ return { appended: true, position };
2713
+ }
2714
+ function append(target, kind, text2, at) {
2715
+ return append_event(target, { at, kind, text: text2 });
2716
+ }
2717
+ function read_from(target, position) {
2718
+ const events = read_events(target);
2719
+ return {
2720
+ events: events.filter((event) => event.pos > position),
2721
+ next_position: last_position(events)
2722
+ };
2723
+ }
2724
+ function read_last(target) {
2725
+ return read_events(target).findLast((event) => !TRACE_KINDS.has(event.kind));
2726
+ }
2727
+ function has_since(events, kind, reset_kind) {
2728
+ const reset_at = events.findLastIndex((event) => event.kind === reset_kind);
2729
+ return events.slice(reset_at + POSITION_INCREMENT).some((event) => event.kind === kind);
2730
+ }
2731
+ var FIELD_SEPARATOR = " \xB7 ";
2732
+ function format_event(event) {
2733
+ return [event.at, event.kind, event.text].join(FIELD_SEPARATOR);
2734
+ }
2735
+ var run_event_stream = {
2736
+ EVENT_CAP,
2737
+ EVENT_KIND,
2738
+ EVENT_KINDS,
2739
+ TRACE_KINDS,
2740
+ append,
2741
+ append_event,
2742
+ format_event,
2743
+ has_since,
2744
+ is_stage_start,
2745
+ read_events,
2746
+ read_from,
2747
+ read_last,
2748
+ target_of
2749
+ };
2750
+
2751
+ // scripts/discovery/repo-origin.ts
2752
+ var GITHUB_HOST = "github.com";
2753
+ var SSH_ALIAS_PATTERN = /^github(?:-\w+)*$/u;
2754
+ var GIT_SUFFIX = ".git";
2755
+ var PATH_SEPARATOR2 = "/";
2756
+ var USER_SEPARATOR = "@";
2757
+ var HOST_SEPARATOR = ":";
2758
+ var OWNER_INDEX = 0;
2759
+ var REPO_INDEX = 1;
2760
+ var REPO_PATH_SEGMENTS = 2;
2761
+ var NOT_FOUND4 = -1;
2762
+ var SECTION_PREFIX = "[";
2763
+ var ORIGIN_SECTION = /^\[remote\s+"origin"\]$/u;
2764
+ var REMOTE_SECTION = /^\[remote\s+"[^"]+"\]$/u;
2765
+ var URL_KEY = "url";
2766
+ function is_github_hostname(host) {
2767
+ return host.toLowerCase() === GITHUB_HOST;
2768
+ }
2769
+ function is_github_ssh_host(host) {
2770
+ const normalized = host.toLowerCase();
2771
+ return is_github_hostname(normalized) || SSH_ALIAS_PATTERN.test(normalized);
2772
+ }
2773
+ function strip_git_suffix(name) {
2774
+ return name.endsWith(GIT_SUFFIX) ? name.slice(0, -GIT_SUFFIX.length) : name;
2775
+ }
2776
+ function to_identity(repository_path) {
2777
+ const segments = repository_path.split(PATH_SEPARATOR2).filter((segment) => segment !== "");
2778
+ if (segments.length !== REPO_PATH_SEGMENTS) return void 0;
2779
+ const owner = segments[OWNER_INDEX] ?? "";
2780
+ const repo = strip_git_suffix(segments[REPO_INDEX] ?? "");
2781
+ return repo === "" ? void 0 : { owner, repo };
2782
+ }
2783
+ function parse_scp_like(url) {
2784
+ const user_end = url.indexOf(USER_SEPARATOR);
2785
+ const authority = user_end === NOT_FOUND4 ? url : url.slice(user_end + 1);
2786
+ const host_end = authority.indexOf(HOST_SEPARATOR);
2787
+ if (host_end === NOT_FOUND4 || !is_github_ssh_host(authority.slice(0, host_end))) return void 0;
2788
+ return to_identity(authority.slice(host_end + 1));
2789
+ }
2790
+ function parse_url_like(url) {
2791
+ try {
2792
+ const parsed = new URL(url);
2793
+ return is_github_hostname(parsed.hostname) ? to_identity(parsed.pathname) : void 0;
2794
+ } catch {
2795
+ return void 0;
2796
+ }
2797
+ }
2798
+ function parse_origin_url(url) {
2799
+ const trimmed = url.trim();
2800
+ if (trimmed === "") return void 0;
2801
+ return parse_url_like(trimmed) ?? parse_scp_like(trimmed);
2802
+ }
2803
+ function is_section_header(line) {
2804
+ return line.startsWith(SECTION_PREFIX);
2805
+ }
2806
+ function origin_section_lines(lines) {
2807
+ const start = lines.findIndex((line) => ORIGIN_SECTION.test(line));
2808
+ if (start === NOT_FOUND4) return [];
2809
+ const rest = lines.slice(start + 1);
2810
+ const end = rest.findIndex((line) => is_section_header(line));
2811
+ return end === NOT_FOUND4 ? rest : rest.slice(0, end);
2812
+ }
2813
+ function url_value(line) {
2814
+ const separator = line.indexOf("=");
2815
+ if (separator === NOT_FOUND4 || line.slice(0, separator).trim() !== URL_KEY) return void 0;
2816
+ return line.slice(separator + 1).trim();
2817
+ }
2818
+ function parse_origin_from_config(content) {
2819
+ const lines = content.split("\n").map((line) => line.trim());
2820
+ return origin_section_lines(lines).map((line) => url_value(line)).find((url) => url !== void 0);
2821
+ }
2822
+ function section_groups(lines) {
2823
+ const groups = [];
2824
+ for (const line of lines) {
2825
+ if (is_section_header(line)) groups.push([line]);
2826
+ else groups.at(-1)?.push(line);
2827
+ }
2828
+ return groups;
2829
+ }
2830
+ function parse_remote_urls_from_config(content) {
2831
+ const lines = content.split("\n").map((line) => line.trim());
2832
+ return section_groups(lines).filter((group) => REMOTE_SECTION.test(group[0] ?? "")).flatMap((group) => group.map((line) => url_value(line))).filter((url) => url !== void 0);
2833
+ }
2834
+ function format_identity(identity) {
2835
+ return `${identity.owner}${PATH_SEPARATOR2}${identity.repo}`.toLowerCase();
2836
+ }
2837
+ var repo_origin = {
2838
+ GITHUB_HOST,
2839
+ is_github_hostname,
2840
+ is_github_ssh_host,
2841
+ parse_origin_from_config,
2842
+ parse_origin_url,
2843
+ parse_remote_urls_from_config,
2844
+ format_identity
2845
+ };
2846
+
2847
+ // scripts/discovery/repo-discovery.ts
2848
+ import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync4, statSync as statSync3 } from "node:fs";
2849
+ import path7 from "node:path";
2850
+
2851
+ // scripts/lib/stamped-memo.ts
2852
+ import { lstatSync } from "node:fs";
2853
+ var NO_STAMP = "";
2854
+ var STAMP_SEPARATOR = ":";
2855
+ function create() {
2856
+ const answers2 = /* @__PURE__ */ new Map();
2857
+ return {
2858
+ of(key, stamp, compute) {
2859
+ const known = answers2.get(key);
2860
+ if (known?.stamp === stamp) return known.value;
2861
+ const value = compute();
2862
+ answers2.set(key, { stamp, value });
2863
+ return value;
2864
+ },
2865
+ keep(keys) {
2866
+ for (const key of answers2.keys()) if (!keys.has(key)) answers2.delete(key);
2867
+ }
2868
+ };
2869
+ }
2870
+ function file_stamp(file) {
2871
+ try {
2872
+ const status2 = lstatSync(file);
2873
+ return [status2.ino, status2.mtimeMs, status2.ctimeMs, status2.size].join(STAMP_SEPARATOR);
2874
+ } catch {
2875
+ return NO_STAMP;
2876
+ }
2877
+ }
2878
+ var stamped_memo = { NO_STAMP, create, file_stamp };
2879
+
2880
+ // scripts/discovery/repo-map-logic.ts
2881
+ var OVERRIDE_ENTRY_SEPARATOR = ",";
2882
+ var OVERRIDE_PAIR_SEPARATOR = "=";
2883
+ var OVERRIDE_PAIR_PARTS = 2;
2884
+ var KEY_INDEX = 0;
2885
+ var PATH_INDEX = 1;
2886
+ function is_same_owner(identity, current_owner) {
2887
+ return identity.owner.toLowerCase() === current_owner.toLowerCase();
2888
+ }
2889
+ function add_entry(target, origin_url2, repository_path, current_owner) {
2890
+ if (origin_url2 === void 0) return;
2891
+ const identity = repo_origin.parse_origin_url(origin_url2);
2892
+ if (identity === void 0 || !is_same_owner(identity, current_owner)) return;
2893
+ target.set(repo_origin.format_identity(identity), repository_path);
2894
+ }
2895
+ function parse_override_entry(entry) {
2896
+ const parts = entry.split(OVERRIDE_PAIR_SEPARATOR).map((part) => part.trim());
2897
+ if (parts.length !== OVERRIDE_PAIR_PARTS) return void 0;
2898
+ const key = parts[KEY_INDEX] ?? "";
2899
+ const repository_path = parts[PATH_INDEX] ?? "";
2900
+ if (repository_path === "") return void 0;
2901
+ return { path: repository_path, origin_url: `https://${repo_origin.GITHUB_HOST}/${key}` };
2902
+ }
2903
+ function parse_overrides(raw) {
2904
+ if (raw === void 0) return [];
2905
+ return raw.split(OVERRIDE_ENTRY_SEPARATOR).map((entry) => parse_override_entry(entry)).filter((entry) => entry !== void 0);
2906
+ }
2907
+ function build_repository_map(discovered, current_owner, override_value) {
2908
+ const result = /* @__PURE__ */ new Map();
2909
+ for (const entry of discovered) add_entry(result, entry.origin_url, entry.path, current_owner);
2910
+ for (const entry of parse_overrides(override_value)) {
2911
+ add_entry(result, entry.origin_url, entry.path, current_owner);
2912
+ }
2913
+ return result;
2914
+ }
2915
+ var repo_map_logic = {
2916
+ is_same_owner,
2917
+ build_repository_map
2918
+ };
2919
+
2920
+ // scripts/discovery/repo-discovery.ts
2921
+ var GIT_DIRECTORY = ".git";
2922
+ var GIT_CONFIG = "config";
2923
+ var GITDIR_PREFIX2 = "gitdir:";
2924
+ var COMMON_DIRECTORY_FILE = "commondir";
2925
+ var OVERRIDE_ENV_KEY = "JOSH_REPO_PATHS";
2926
+ function resolve_common_directory(git_directory) {
2927
+ const pointer = path7.join(git_directory, COMMON_DIRECTORY_FILE);
2928
+ if (!existsSync3(pointer)) return git_directory;
2929
+ try {
2930
+ return path7.resolve(git_directory, readFileSync4(pointer, "utf8").trim());
2931
+ } catch {
2932
+ return git_directory;
2933
+ }
2934
+ }
2935
+ function follow_git_file(repository_path, git_file) {
2936
+ const pointer = readFileSync4(git_file, "utf8").trim();
2937
+ if (!pointer.startsWith(GITDIR_PREFIX2)) return void 0;
2938
+ return path7.resolve(repository_path, pointer.slice(GITDIR_PREFIX2.length).trim());
2939
+ }
2940
+ function resolve_git_directory(repository_path) {
2941
+ const candidate = path7.join(repository_path, GIT_DIRECTORY);
2942
+ if (!existsSync3(candidate)) return void 0;
2943
+ try {
2944
+ if (statSync3(candidate).isDirectory()) return candidate;
2945
+ const linked = follow_git_file(repository_path, candidate);
2946
+ return linked === void 0 ? void 0 : resolve_common_directory(linked);
2947
+ } catch {
2948
+ return void 0;
2949
+ }
2950
+ }
2951
+ function read_text(file) {
2952
+ try {
2953
+ return readFileSync4(file, "utf8");
2954
+ } catch {
2955
+ return void 0;
2956
+ }
2957
+ }
2958
+ var git_directories2 = stamped_memo.create();
2959
+ var configs = stamped_memo.create();
2960
+ function read_config(repository_path) {
2961
+ const git_entry = path7.join(repository_path, GIT_DIRECTORY);
2962
+ const git_directory = git_directories2.of(
2963
+ repository_path,
2964
+ stamped_memo.file_stamp(git_entry),
2965
+ () => resolve_git_directory(repository_path)
2966
+ );
2967
+ if (git_directory === void 0) return void 0;
2968
+ const config = path7.join(git_directory, GIT_CONFIG);
2969
+ return configs.of(config, stamped_memo.file_stamp(config), () => read_text(config));
2970
+ }
2971
+ function read_origin_url(repository_path) {
2972
+ const config = read_config(repository_path);
2973
+ return config === void 0 ? void 0 : repo_origin.parse_origin_from_config(config);
2974
+ }
2975
+ function read_remote_urls(repository_path) {
2976
+ const config = read_config(repository_path);
2977
+ return config === void 0 ? [] : repo_origin.parse_remote_urls_from_config(config);
2978
+ }
2979
+ function sibling_directories(parent) {
2980
+ try {
2981
+ return readdirSync2(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => path7.join(parent, entry.name)).toSorted((left, right) => left.localeCompare(right));
2982
+ } catch {
2983
+ return [];
2984
+ }
2985
+ }
2986
+ function scan_siblings(parent) {
2987
+ return sibling_directories(parent).map((repository_path) => ({
2988
+ path: repository_path,
2989
+ origin_url: read_origin_url(repository_path)
2990
+ }));
2991
+ }
2992
+ function resolve_current_owner(repository_path) {
2993
+ const origin_url2 = read_origin_url(repository_path);
2994
+ if (origin_url2 === void 0) return void 0;
2995
+ return repo_origin.parse_origin_url(origin_url2)?.owner;
2996
+ }
2997
+ function main_worktree(repository_path) {
2998
+ const git_directory = resolve_git_directory(repository_path);
2999
+ if (git_directory === void 0 || path7.basename(git_directory) !== GIT_DIRECTORY) {
3000
+ return repository_path;
3001
+ }
3002
+ return path7.dirname(git_directory);
3003
+ }
3004
+ function discover_repositories(repository_path, environment = process.env) {
3005
+ const main = main_worktree(repository_path);
3006
+ const current_owner = resolve_current_owner(main);
3007
+ if (current_owner === void 0) return /* @__PURE__ */ new Map();
3008
+ return repo_map_logic.build_repository_map(
3009
+ scan_siblings(path7.dirname(main)),
3010
+ current_owner,
3011
+ environment[OVERRIDE_ENV_KEY]
3012
+ );
3013
+ }
3014
+ var repo_discovery = {
3015
+ OVERRIDE_ENV_KEY,
3016
+ main_worktree,
3017
+ read_origin_url,
3018
+ read_remote_urls,
3019
+ resolve_current_owner,
3020
+ scan_siblings,
3021
+ discover_repositories
3022
+ };
3023
+
3024
+ // scripts/rules/issue-citation.ts
3025
+ var ISSUE_NUMBER = /#\d+/gu;
3026
+ var REFERENCE_BOUNDARY = /[\s#()[\]<>|]/u;
3027
+ var OWNER_REPO = /^[^\s/#]+\/[^\s/#]+$/u;
3028
+ var MARKDOWN_LINK = /\[[^[\]]*\]\([^()]*\)/gu;
3029
+ var NUMBER_CONTINUATION = /^(?:\w|-[a-z])/iu;
3030
+ var CONTINUATION_WIDTH = 2;
3031
+ var GLUED_LEAD = /[&./]/u;
3032
+ var FENCE_MARKER = /^\s*(?:`{3,}|~{3,})/u;
3033
+ var QUOTE_LINE = /^\s*>/u;
3034
+ var PR_PREFIX = /\b(?:pr|pull request)\s*$/iu;
3035
+ var BACKTICK_PAIR = 2;
3036
+ function link_covers(link, index) {
3037
+ const start = link.index ?? 0;
3038
+ return index >= start && index < start + link[0].length;
3039
+ }
3040
+ function is_linked_at(line, index) {
3041
+ for (const link of line.matchAll(MARKDOWN_LINK)) {
3042
+ if (link_covers(link, index)) return true;
3043
+ }
3044
+ return false;
3045
+ }
3046
+ function lead_token(message, hash_index) {
3047
+ let start = hash_index;
3048
+ while (start > 0 && !REFERENCE_BOUNDARY.test(message.charAt(start - 1))) start -= 1;
3049
+ return message.slice(start, hash_index);
3050
+ }
3051
+ function repo_prefix(message, hash_index) {
3052
+ const token = lead_token(message, hash_index);
3053
+ return OWNER_REPO.test(token) ? token : "";
3054
+ }
3055
+ function is_inline_code_at(line, index) {
3056
+ const backticks = line.slice(0, index).split("`").length - 1;
3057
+ return backticks % BACKTICK_PAIR === 1;
3058
+ }
3059
+ function is_bare_at(line, index) {
3060
+ if (is_linked_at(line, index) || is_inline_code_at(line, index)) return false;
3061
+ return !PR_PREFIX.test(line.slice(0, index));
3062
+ }
3063
+ function is_glued(line, reference2) {
3064
+ const end = reference2.index + reference2.text.length;
3065
+ if (NUMBER_CONTINUATION.test(line.slice(end, end + CONTINUATION_WIDTH))) return true;
3066
+ return reference2.prefix === "" && GLUED_LEAD.test(lead_token(line, reference2.index));
3067
+ }
3068
+ function line_references(line) {
3069
+ const references = [];
3070
+ for (const match of line.matchAll(ISSUE_NUMBER)) {
3071
+ const reference2 = { index: match.index, prefix: repo_prefix(line, match.index), text: match[0] };
3072
+ if (!is_glued(line, reference2) && is_bare_at(line, match.index)) references.push(reference2);
3073
+ }
3074
+ return references;
3075
+ }
3076
+ function collect_line_references(line, found) {
3077
+ for (const reference2 of line_references(line)) found.push(`${reference2.prefix}${reference2.text}`);
3078
+ }
3079
+ function lines_outside_fences(message) {
3080
+ const lines = [];
3081
+ let is_in_fence = false;
3082
+ for (const line of message.split("\n")) {
3083
+ if (FENCE_MARKER.test(line)) is_in_fence = !is_in_fence;
3084
+ else if (!is_in_fence) lines.push(line);
3085
+ }
3086
+ return lines;
3087
+ }
3088
+ function prose_lines(message) {
3089
+ return lines_outside_fences(message).filter((line) => !QUOTE_LINE.test(line));
3090
+ }
3091
+ function bare_references(message) {
3092
+ const found = [];
3093
+ for (const line of prose_lines(message)) collect_line_references(line, found);
3094
+ return [...new Set(found)];
3095
+ }
3096
+ function prompt_references(prompt) {
3097
+ const found = /* @__PURE__ */ new Set();
3098
+ for (const match of prompt.matchAll(ISSUE_NUMBER)) {
3099
+ found.add(repo_prefix(prompt, match.index) + match[0]);
3100
+ }
3101
+ return found;
3102
+ }
3103
+ function unquoted_references(message, prompt) {
3104
+ const quoted = prompt_references(prompt);
3105
+ return bare_references(message).filter((reference2) => !quoted.has(reference2));
3106
+ }
3107
+ function has_bare_reference(message) {
3108
+ return bare_references(message).length > 0;
3109
+ }
3110
+ function cite_argument(reference2) {
3111
+ return reference2.startsWith("#") ? reference2.slice(1) : reference2;
3112
+ }
3113
+ function cite_arguments(references) {
3114
+ return references.map((reference2) => cite_argument(reference2));
3115
+ }
3116
+ function reference_link(reference2, default_slug) {
3117
+ const slug = reference2.prefix === "" ? default_slug : reference2.prefix;
3118
+ const number = reference2.text.slice(1);
3119
+ return `[${reference2.prefix}${reference2.text}](${issue_cite.issue_url(slug, number)})`;
3120
+ }
3121
+ function linkify_line(line, slug) {
3122
+ let result = "";
3123
+ let cursor = 0;
3124
+ for (const reference2 of line_references(line)) {
3125
+ const start = reference2.index - reference2.prefix.length;
3126
+ result += line.slice(cursor, start) + reference_link(reference2, slug);
3127
+ cursor = reference2.index + reference2.text.length;
3128
+ }
3129
+ return result + line.slice(cursor);
3130
+ }
3131
+ function rewrite_line(line, slug, is_in_fence) {
3132
+ if (is_in_fence || FENCE_MARKER.test(line) || QUOTE_LINE.test(line)) return line;
3133
+ return linkify_line(line, slug);
3134
+ }
3135
+ function linkify(message, slug) {
3136
+ const out = [];
3137
+ let is_in_fence = false;
3138
+ for (const line of message.split("\n")) {
3139
+ if (FENCE_MARKER.test(line)) is_in_fence = !is_in_fence;
3140
+ out.push(rewrite_line(line, slug, is_in_fence));
3141
+ }
3142
+ return out.join("\n");
3143
+ }
3144
+ var issue_citation = {
3145
+ bare_references,
3146
+ cite_arguments,
3147
+ has_bare_reference,
3148
+ linkify,
3149
+ prose_lines,
3150
+ unquoted_references
3151
+ };
3152
+
3153
+ // scripts/issue/session-cite.ts
3154
+ function session_repo() {
3155
+ const url = repo_discovery.read_origin_url(process.cwd());
3156
+ const identity = url === void 0 ? void 0 : repo_origin.parse_origin_url(url);
3157
+ return identity === void 0 ? void 0 : `${identity.owner}/${identity.repo}`;
3158
+ }
3159
+ function issue(number, title, repo = session_repo()) {
3160
+ return issue_cite.reference(repo, String(number), title);
3161
+ }
3162
+ function text(message) {
3163
+ const repo = session_repo();
3164
+ return repo === void 0 ? message : issue_citation.linkify(message, repo);
3165
+ }
3166
+ var session_cite = {
3167
+ issue,
3168
+ session_repo,
3169
+ text
3170
+ };
3171
+
3172
+ // scripts/lane/lane-state.ts
3173
+ import { readdirSync as readdirSync3 } from "node:fs";
3174
+ import path8 from "node:path";
3175
+
3176
+ // scripts/lib/figure-format.ts
3177
+ var USD_DECIMALS = 4;
3178
+ var PERCENT_SCALE = 100;
3179
+ var PERCENT_DECIMALS = 1;
3180
+ var MINUTE_DECIMALS = 1;
3181
+ var CLOCK_WIDTH = 2;
3182
+ var CLOCK_PAD = "0";
3183
+ function format_usd(usd, decimals = USD_DECIMALS) {
3184
+ return `$${usd.toFixed(decimals)}`;
3185
+ }
3186
+ function format_tokens(count) {
3187
+ return count.toLocaleString("en-US");
3188
+ }
3189
+ function format_share(part, whole) {
3190
+ if (whole === 0) return "n/a";
3191
+ return `${(part / whole * PERCENT_SCALE).toFixed(PERCENT_DECIMALS)}%`;
3192
+ }
3193
+ function format_minutes(duration_ms) {
3194
+ return `${(duration_ms / MS_PER_MINUTE).toFixed(MINUTE_DECIMALS)} min`;
3195
+ }
3196
+ function two_digits(value) {
3197
+ return String(value).padStart(CLOCK_WIDTH, CLOCK_PAD);
3198
+ }
3199
+ function clock_of(ms) {
3200
+ const date = new Date(ms);
3201
+ return [date.getHours(), date.getMinutes(), date.getSeconds()].map((value) => two_digits(value)).join(":");
3202
+ }
3203
+ function minute_of(ms) {
3204
+ const date = new Date(ms);
3205
+ return [date.getHours(), date.getMinutes()].map((value) => two_digits(value)).join(":");
3206
+ }
3207
+ var figure_format = {
3208
+ format_usd,
3209
+ format_tokens,
3210
+ format_share,
3211
+ format_minutes,
3212
+ two_digits,
3213
+ clock_of,
3214
+ minute_of
3215
+ };
3216
+
3217
+ // scripts/lane/lane-state.ts
3218
+ import { z as z6 } from "zod";
3219
+ var STATE_PREFIX = "josh-lane-state-";
3220
+ var STATE_SUFFIX = ".json";
3221
+ var LOCK_SUFFIX2 = ".lock";
3222
+ var LOCK_WAIT_MS2 = 5e3;
3223
+ var LANE_STATES = ["open", "running", "paused", "ended"];
3224
+ var NO_STATE_HINT = "no lane state \u2014 counted in use";
3225
+ var lane_run_schema = z6.object({ started_at: z6.string(), owner_pid: z6.number().optional() });
3226
+ var stuck_schema = z6.object({ pid: z6.number(), reason: z6.string() });
3227
+ var lane_state_schema = z6.object({
3228
+ issue: z6.string(),
3229
+ run: lane_run_schema.optional(),
3230
+ state: z6.enum(LANE_STATES),
3231
+ launched_at: z6.string().optional(),
3232
+ changed_at: z6.string(),
3233
+ changed_by: z6.string(),
3234
+ stuck: z6.array(stuck_schema).optional()
3235
+ });
3236
+ var TRANSITIONS = {
3237
+ open: ["open", "running", "ended"],
3238
+ running: ["running", "paused", "ended"],
3239
+ paused: ["paused", "running", "ended"],
3240
+ ended: ["ended", "open"]
3241
+ };
3242
+ function state_path(directory, issue2) {
3243
+ return stamp_file.stamp_path(STATE_PREFIX, directory, `-${issue2}${STATE_SUFFIX}`);
3244
+ }
3245
+ function is_allowed(from, to) {
3246
+ return from === void 0 || TRANSITIONS[from].includes(to);
3247
+ }
3248
+ function read_record2(directory, issue2) {
3249
+ const raw = stamp_file.read_stamp_text(state_path(directory, issue2));
3250
+ return raw === void 0 ? void 0 : json_value.parse_with(raw, lane_state_schema);
3251
+ }
3252
+ function write_record(directory, record) {
3253
+ stamp_file.replace_stamp(state_path(directory, record.issue), record);
3254
+ }
3255
+ function current_run(directory) {
3256
+ const carried = run_carry.read_carry(run_carry.carry_path(directory));
3257
+ if (carried.kind !== "carried") return void 0;
3258
+ return { started_at: carried.carry.started_at, owner_pid: carried.carry.owner_pid };
3259
+ }
3260
+ function launch_fields(change, directory, now) {
3261
+ if (change.is_launch !== true) return {};
3262
+ return { run: current_run(directory), launched_at: now.toISOString() };
3263
+ }
3264
+ function next_record(change, previous, directory, now) {
3265
+ return {
3266
+ // An open starts a fresh life: a reopened lane keeps nothing of the run that launched it before.
3267
+ ...change.state !== "open" && previous,
3268
+ issue: change.issue,
3269
+ state: change.state,
3270
+ changed_at: now.toISOString(),
3271
+ changed_by: change.command,
3272
+ ...launch_fields(change, directory, now)
3273
+ };
3274
+ }
3275
+ function apply_held(change, directory, now) {
3276
+ const previous = read_record2(directory, change.issue);
3277
+ if (!is_allowed(previous?.state, change.state)) {
3278
+ return { kind: "skipped", reason: `no ${previous?.state ?? ""} \u2192 ${change.state} transition` };
3279
+ }
3280
+ const record = next_record(change, previous, directory, now);
3281
+ write_record(directory, record);
3282
+ return { kind: "written", record };
3283
+ }
3284
+ var NO_DIRECTORY = { kind: "skipped", reason: "no git directory" };
3285
+ function locked(directory, issue2, held) {
3286
+ const lock = `${state_path(directory, issue2)}${LOCK_SUFFIX2}`;
3287
+ const outcome = repository_lock.with_lock_sync(held, lock, LOCK_WAIT_MS2);
3288
+ return outcome ?? { kind: "skipped", reason: `gave up waiting for the lock at ${lock}` };
3289
+ }
3290
+ function apply(change, directory, now) {
3291
+ return locked(directory, change.issue, () => apply_held(change, directory, now));
3292
+ }
3293
+ function warn(change, reason) {
3294
+ console.warn(
3295
+ `${change.command} ${session_cite.issue(change.issue)}: lane state not recorded \u2014 ${reason}`
3296
+ );
3297
+ }
3298
+ async function resolve_directory(directory) {
3299
+ return directory ?? await run_carry.repository_directory();
3300
+ }
3301
+ async function outcome_of(change, options) {
3302
+ const directory = await resolve_directory(options.directory);
3303
+ if (directory === void 0) return NO_DIRECTORY;
3304
+ return apply(change, directory, options.now ?? /* @__PURE__ */ new Date());
3305
+ }
3306
+ async function settled_outcome(change, options) {
3307
+ try {
3308
+ return await outcome_of(change, options);
3309
+ } catch (error) {
3310
+ return { kind: "skipped", reason: error instanceof Error ? error.message : String(error) };
3311
+ }
3312
+ }
3313
+ async function record_change(change, options = {}) {
3314
+ const outcome = await settled_outcome(change, options);
3315
+ if (outcome.kind === "skipped") warn(change, outcome.reason);
3316
+ return outcome;
3317
+ }
3318
+ async function read_state(issue2, directory) {
3319
+ const root = await resolve_directory(directory);
3320
+ return root === void 0 ? void 0 : read_record2(root, issue2);
3321
+ }
3322
+ function recorded_issues(directory) {
3323
+ const empty = state_path(directory, "");
3324
+ const head = path8.basename(empty).slice(0, -STATE_SUFFIX.length);
3325
+ return readdirSync3(path8.dirname(empty)).filter((name) => name.startsWith(head) && name.endsWith(STATE_SUFFIX)).map((name) => name.slice(head.length, -STATE_SUFFIX.length)).filter((issue2) => issue2.length > 0);
3326
+ }
3327
+ async function read_records(directory) {
3328
+ const root = await resolve_directory(directory);
3329
+ if (root === void 0) return [];
3330
+ const records = recorded_issues(root).map((issue2) => read_record2(root, issue2));
3331
+ return records.filter((record) => record !== void 0);
3332
+ }
3333
+ function stuck_held(issue2, stuck, directory) {
3334
+ const previous = read_record2(directory, issue2);
3335
+ if (previous === void 0) return { kind: "skipped", reason: "no record" };
3336
+ const record = { ...previous, stuck };
3337
+ write_record(directory, record);
3338
+ return { kind: "written", record };
3339
+ }
3340
+ async function record_stuck(issue2, stuck, directory) {
3341
+ const root = await resolve_directory(directory);
3342
+ if (root === void 0) return NO_DIRECTORY;
3343
+ return locked(root, issue2, () => stuck_held(issue2, stuck, root));
3344
+ }
3345
+ async function read_states(issues, directory) {
3346
+ const root = await resolve_directory(directory);
3347
+ if (root === void 0) return /* @__PURE__ */ new Map();
3348
+ const read3 = issues.map((issue2) => [
3349
+ issue2,
3350
+ read_record2(root, issue2)
3351
+ ]);
3352
+ return new Map(read3.filter((entry) => entry[1] !== void 0));
3353
+ }
3354
+ function paused_text(since_ms, changed_by) {
3355
+ return `paused since ${figure_format.minute_of(since_ms)} by ${changed_by}`;
3356
+ }
3357
+ function paused_note(record) {
3358
+ if (record?.state !== "paused") return void 0;
3359
+ return paused_text(Date.parse(record.changed_at), record.changed_by);
3360
+ }
3361
+ var lane_state = {
3362
+ LANE_STATES,
3363
+ NO_STATE_HINT,
3364
+ is_allowed,
3365
+ paused_note,
3366
+ paused_text,
3367
+ read_records,
3368
+ read_state,
3369
+ read_states,
3370
+ record_change,
3371
+ record_stuck,
3372
+ state_path
3373
+ };
3374
+
3375
+ // scripts/run/event/run-event-scope.ts
3376
+ var SINCE_SCOPE = "since";
3377
+ var UNKNOWN_SCOPE = "unknown";
3378
+ var UNKNOWN_EVENT_SCOPE = { kind: UNKNOWN_SCOPE };
3379
+ function moment_of(at) {
3380
+ const parsed = Date.parse(at);
3381
+ return Number.isNaN(parsed) ? void 0 : parsed;
3382
+ }
3383
+ function is_within(event, floor) {
3384
+ const at = moment_of(event.at);
3385
+ return at !== void 0 && at >= floor;
3386
+ }
3387
+ function scoped_events(events, scope) {
3388
+ if (scope.kind === UNKNOWN_SCOPE) return void 0;
3389
+ const floor = moment_of(scope.started_at);
3390
+ if (floor === void 0) return void 0;
3391
+ return events.filter((event) => is_within(event, floor));
3392
+ }
3393
+ function scope_of(read3) {
3394
+ if (read3.kind !== "carried") return UNKNOWN_EVENT_SCOPE;
3395
+ return { kind: SINCE_SCOPE, started_at: read3.carry.started_at };
3396
+ }
3397
+ function last_scoped_event(events, scope) {
3398
+ return scoped_events(events, scope)?.findLast(
3399
+ (event) => !run_event_stream.TRACE_KINDS.has(event.kind)
3400
+ );
3401
+ }
3402
+ var SHIP_POSITION_KINDS = /* @__PURE__ */ new Set([
3403
+ run_event_stream.EVENT_KIND.SHIP_LAUNCH,
3404
+ run_event_stream.EVENT_KIND.SHIP_STOP
3405
+ ]);
3406
+ var KIND = run_event_stream.EVENT_KIND;
3407
+ var BATCH_RECORD_KINDS = /* @__PURE__ */ new Set([
3408
+ KIND.CHILD_LAUNCH,
3409
+ KIND.RESTART,
3410
+ KIND.WITHDRAW,
3411
+ KIND.PARK,
3412
+ KIND.SPLIT,
3413
+ KIND.RETROSPECTIVE,
3414
+ KIND.STRANDED
3415
+ ]);
3416
+ var ISSUE_REFERENCE = /#(\d+)/u;
3417
+ function is_foreign_ship_event(event, issue2) {
3418
+ return SHIP_POSITION_KINDS.has(event.kind) && !event.text.startsWith(`${issue_cite.plain(issue2)} `);
3419
+ }
3420
+ function is_own_ship_event(event, issue2) {
3421
+ return SHIP_POSITION_KINDS.has(event.kind) && !is_foreign_ship_event(event, issue2);
3422
+ }
3423
+ function issue_named(event) {
3424
+ return ISSUE_REFERENCE.exec(event.text)?.[1];
3425
+ }
3426
+ function names_issue(event, issue2) {
3427
+ return issue_named(event) === issue2;
3428
+ }
3429
+ function is_lane_position(event, issue2) {
3430
+ return !BATCH_RECORD_KINDS.has(event.kind) && names_issue(event, issue2);
3431
+ }
3432
+ function since_own_launch(events, issue2) {
3433
+ const launch = events.findLastIndex(
3434
+ (event) => event.kind === KIND.CHILD_LAUNCH && names_issue(event, issue2)
3435
+ );
3436
+ return events.slice(launch + 1);
3437
+ }
3438
+ function is_foreign_event(event, issue2, is_lane_child) {
3439
+ if (is_lane_child) return !is_lane_position(event, issue2);
3440
+ return is_foreign_ship_event(event, issue2);
3441
+ }
3442
+ function last_issue_event(events, scope, issue2, is_lane_child) {
3443
+ const attempt = is_lane_child ? since_own_launch(events, issue2) : events;
3444
+ const own2 = attempt.filter((event) => !is_foreign_event(event, issue2, is_lane_child));
3445
+ if (scope.kind === SINCE_SCOPE) return last_scoped_event(own2, scope);
3446
+ return own2.findLast((event) => is_own_ship_event(event, issue2));
3447
+ }
3448
+ var LAUNCH_OR_SETTLE_KINDS = /* @__PURE__ */ new Set([
3449
+ KIND.CHILD_LAUNCH,
3450
+ KIND.MERGE,
3451
+ KIND.PARK,
3452
+ KIND.SPLIT,
3453
+ KIND.WITHDRAW
3454
+ ]);
3455
+ function is_merge_owed(events, scope, issue2) {
3456
+ const newest = (scoped_events(events, scope) ?? []).findLast(
3457
+ (event) => LAUNCH_OR_SETTLE_KINDS.has(event.kind) && names_issue(event, issue2)
3458
+ );
3459
+ return newest?.kind === KIND.CHILD_LAUNCH;
3460
+ }
3461
+ function is_launch_or_withdrawal(event, issue2) {
3462
+ const is_kind = event.kind === KIND.CHILD_LAUNCH || event.kind === KIND.WITHDRAW;
3463
+ return is_kind && names_issue(event, issue2);
3464
+ }
3465
+ function is_withdrawn(events, issue2) {
3466
+ const newest = events.findLast((event) => is_launch_or_withdrawal(event, issue2));
3467
+ return newest?.kind === KIND.WITHDRAW;
3468
+ }
3469
+ var run_event_scope = {
3470
+ UNKNOWN_EVENT_SCOPE,
3471
+ is_merge_owed,
3472
+ is_withdrawn,
3473
+ issue_named,
3474
+ last_issue_event,
3475
+ last_scoped_event,
3476
+ moment_of,
3477
+ scope_of,
3478
+ scoped_events,
3479
+ since_own_launch
3480
+ };
3481
+
3482
+ // scripts/lane/lane-spans.ts
3483
+ function next_start_ms(starts, issue2, from_ms) {
3484
+ const later = starts.filter((other) => other.issue === issue2 && other.at_ms > from_ms);
3485
+ return Math.min(...later.map((other) => other.at_ms));
3486
+ }
3487
+ function issue_spans(pair) {
3488
+ return pair.starts.map((start) => {
3489
+ const until_ms = next_start_ms(pair.bounds, start.issue, start.at_ms);
3490
+ return {
3491
+ from_ms: start.at_ms,
3492
+ end_ms: pair.ends.find(
3493
+ (end) => end.issue === start.issue && end.at_ms >= start.at_ms && end.at_ms < until_ms
3494
+ )?.at_ms
3495
+ };
3496
+ });
3497
+ }
3498
+ var lane_spans = { issue_spans };
3499
+
3500
+ // scripts/run/board/run-board-lane-time.ts
3501
+ var KIND2 = run_event_stream.EVENT_KIND;
3502
+ var LAUNCH_KINDS = /* @__PURE__ */ new Set([KIND2.CHILD_LAUNCH, KIND2.RESTART]);
3503
+ var OFF_LANE_KINDS = /* @__PURE__ */ new Set([
3504
+ KIND2.MERGE,
3505
+ KIND2.PARK,
3506
+ KIND2.WITHDRAW,
3507
+ KIND2.OUTAGE,
3508
+ KIND2.SPLIT,
3509
+ KIND2.STOP
3510
+ ]);
3511
+ function moments_of(events, kinds) {
3512
+ return events.filter((event) => kinds.has(event.kind)).map((event) => ({
3513
+ issue: Number(run_event_scope.issue_named(event)),
3514
+ at_ms: Date.parse(event.at)
3515
+ }));
3516
+ }
3517
+ function spans_of(events) {
3518
+ const launches = moments_of(events, LAUNCH_KINDS);
3519
+ const ends = moments_of(events, OFF_LANE_KINDS);
3520
+ const issues = new Set(launches.map((launch) => launch.issue));
3521
+ return new Map(
3522
+ [...issues].map((issue2) => {
3523
+ const starts = launches.filter((launch) => launch.issue === issue2);
3524
+ return [issue2, lane_spans.issue_spans({ starts, bounds: starts, ends })];
3525
+ })
3526
+ );
3527
+ }
3528
+ function span_ms(span, until_ms, end_ms) {
3529
+ return Math.max(0, Math.min(span.end_ms ?? until_ms, end_ms) - span.from_ms);
3530
+ }
3531
+ function in_lane_ms(spans, end_ms) {
3532
+ return spans.reduce(
3533
+ (total, span, index) => total + span_ms(span, spans[index + 1]?.from_ms ?? end_ms, end_ms),
3534
+ 0
3535
+ );
3536
+ }
3537
+ function elapsed_of(spans, started_ms, ended_ms) {
3538
+ return spans.length === 0 ? ended_ms - started_ms : in_lane_ms(spans, ended_ms);
3539
+ }
3540
+ function launched_ms(record) {
3541
+ const launched_at = record?.launched_at;
3542
+ return launched_at === void 0 ? void 0 : Date.parse(launched_at);
3543
+ }
3544
+ function counted_from(run3, started_ms) {
3545
+ return run3 === void 0 ? started_ms : Date.parse(run3.started_at);
3546
+ }
3547
+ function is_ended(spans) {
3548
+ return spans.at(-1)?.end_ms !== void 0;
3549
+ }
3550
+ function ending_elapsed(read3) {
3551
+ const started_ms = launched_ms(read3.record);
3552
+ if (started_ms === void 0) return void 0;
3553
+ const from_ms = counted_from(read3.record?.run, started_ms);
3554
+ const spans = (spans_of(read3.events).get(read3.issue) ?? []).filter(
3555
+ (span) => span.from_ms >= from_ms
3556
+ );
3557
+ return is_ended(spans) ? void 0 : elapsed_of(spans, started_ms, read3.ended_ms);
3558
+ }
3559
+ var run_board_lane_time = {
3560
+ LAUNCH_KINDS,
3561
+ OFF_LANE_KINDS,
3562
+ elapsed_of,
3563
+ ending_elapsed,
3564
+ in_lane_ms,
3565
+ spans_of
3566
+ };
3567
+
3568
+ // scripts/run/event/run-event-stream-emit.ts
3569
+ function now_iso() {
3570
+ return (/* @__PURE__ */ new Date()).toISOString();
3571
+ }
3572
+ async function stream_target() {
3573
+ const repository2 = await run_carry.repository_directory();
3574
+ return repository2 === void 0 ? void 0 : run_event_stream.target_of(repository2);
3575
+ }
3576
+ async function lane_record(issue2) {
3577
+ try {
3578
+ return await lane_state.read_state(issue2);
3579
+ } catch (error) {
3580
+ error_text.trace_swallowed("run_event_stream_emit.lane_record", error);
3581
+ return void 0;
3582
+ }
3583
+ }
3584
+ async function ending_fields(target, event) {
3585
+ const issue2 = run_event_scope.issue_named(event);
3586
+ if (issue2 === void 0 || !run_board_lane_time.OFF_LANE_KINDS.has(event.kind)) return {};
3587
+ const elapsed_ms = run_board_lane_time.ending_elapsed({
3588
+ events: run_event_stream.read_events(target),
3589
+ issue: Number(issue2),
3590
+ record: await lane_record(issue2),
3591
+ ended_ms: Date.parse(event.at)
3592
+ });
3593
+ return elapsed_ms === void 0 ? {} : { elapsed_ms };
3594
+ }
3595
+ async function append_at(target, kind, text2, at) {
3596
+ const event = { kind, text: text2, at: at.toISOString() };
3597
+ return run_event_stream.append_event(target, {
3598
+ ...event,
3599
+ ...await ending_fields(target, event)
3600
+ });
3601
+ }
3602
+ async function emit(kind, text2, at = /* @__PURE__ */ new Date()) {
3603
+ try {
3604
+ const target = await stream_target();
3605
+ if (target === void 0) return;
3606
+ await append_at(target, kind, text2, at);
3607
+ } catch {
3608
+ }
3609
+ }
3610
+ async function emit_once(kind, text2) {
3611
+ try {
3612
+ const target = await stream_target();
3613
+ if (target === void 0 || run_event_stream.read_last(target)?.kind === kind) return false;
3614
+ return run_event_stream.append(target, kind, text2, now_iso()).appended;
3615
+ } catch (error) {
3616
+ error_text.trace_swallowed("run_event_stream_emit.emit_once", error);
3617
+ return false;
3618
+ }
3619
+ }
3620
+ function invocation_events(repository2, target) {
3621
+ const events = run_event_stream.read_events(target);
3622
+ const scope = run_event_scope.scope_of(run_carry.read_carry(run_carry.carry_path(repository2)));
3623
+ return run_event_scope.scoped_events(events, scope) ?? events;
3624
+ }
3625
+ async function emit_once_since_with(kind, reset_kind, compose) {
3626
+ try {
3627
+ const repository2 = await run_carry.repository_directory();
3628
+ if (repository2 === void 0) return void 0;
3629
+ const target = run_event_stream.target_of(repository2);
3630
+ if (run_event_stream.has_since(invocation_events(repository2, target), kind, reset_kind)) {
3631
+ return void 0;
3632
+ }
3633
+ const text2 = await compose();
3634
+ return run_event_stream.append(target, kind, text2, now_iso()).appended ? text2 : void 0;
3635
+ } catch (error) {
3636
+ error_text.trace_swallowed("run_event_stream_emit.emit_once_since", error);
3637
+ return void 0;
3638
+ }
3639
+ }
3640
+ async function emit_once_since(kind, text2, reset_kind) {
3641
+ const appended = await emit_once_since_with(kind, reset_kind, async () => text2);
3642
+ return appended !== void 0;
3643
+ }
3644
+ async function emit_heartbeat(line) {
3645
+ await emit(run_event_stream.EVENT_KIND.HEARTBEAT, line);
3646
+ }
3647
+ async function current_events() {
3648
+ try {
3649
+ const repository2 = await run_carry.repository_directory();
3650
+ if (repository2 === void 0) return [];
3651
+ const read3 = run_carry.read_carry(run_carry.carry_path(repository2));
3652
+ const scope = run_event_scope.scope_of(read3);
3653
+ const events = run_event_stream.read_events(run_event_stream.target_of(repository2));
3654
+ return run_event_scope.scoped_events(events, scope) ?? [];
3655
+ } catch {
3656
+ return [];
3657
+ }
3658
+ }
3659
+ async function invocation_or_all_events() {
3660
+ try {
3661
+ const repository2 = await run_carry.repository_directory();
3662
+ return repository2 === void 0 ? [] : invocation_events(repository2, run_event_stream.target_of(repository2));
3663
+ } catch {
3664
+ return [];
3665
+ }
3666
+ }
3667
+ async function all_events() {
3668
+ try {
3669
+ const target = await stream_target();
3670
+ return target === void 0 ? [] : run_event_stream.read_events(target);
3671
+ } catch {
3672
+ return [];
3673
+ }
3674
+ }
3675
+ var run_event_stream_emit = {
3676
+ all_events,
3677
+ append_at,
3678
+ current_events,
3679
+ emit,
3680
+ emit_heartbeat,
3681
+ emit_once,
3682
+ emit_once_since,
3683
+ emit_once_since_with,
3684
+ invocation_or_all_events,
3685
+ stream_target
3686
+ };
3687
+
3688
+ // scripts/lib/ancestor-directories.ts
3689
+ import path9 from "node:path";
3690
+ var MAX_DEPTH = 64;
3691
+ function list(start_directory) {
3692
+ const directories2 = [];
3693
+ let current = path9.resolve(start_directory);
3694
+ while (directories2.length < MAX_DEPTH && !directories2.includes(current)) {
3695
+ directories2.push(current);
3696
+ current = path9.dirname(current);
3697
+ }
3698
+ return directories2;
3699
+ }
3700
+ function nearest(start_directory, is_match) {
3701
+ return list(start_directory).find((directory) => is_match(directory));
3702
+ }
3703
+ var ancestor_directories = { list, nearest };
3704
+
3705
+ // scripts/lib/package-manifest.ts
3706
+ import { readFileSync as readFileSync5 } from "node:fs";
3707
+ import path10 from "node:path";
3708
+ var PACKAGE_JSON = "package.json";
3709
+ function manifest_path(directory) {
3710
+ return path10.join(directory, PACKAGE_JSON);
3711
+ }
3712
+ function read_manifest(directory, schema) {
3713
+ const text2 = readFileSync5(manifest_path(directory), "utf8");
3714
+ return schema.parse(JSON.parse(text2));
3715
+ }
3716
+ function read_manifest_if_valid(directory, schema) {
3717
+ const text2 = file_reader.read_if_readable(manifest_path(directory));
3718
+ if (text2 === void 0) return void 0;
3719
+ return json_value.parse_with(text2, schema);
3720
+ }
3721
+ var package_manifest = { manifest_path, read_manifest, read_manifest_if_valid };
3722
+
3723
+ // scripts/git/git-schemas.ts
3724
+ import { z as z7 } from "zod";
3725
+ var package_name_schema = z7.object({ name: z7.string().min(1) });
3726
+ var rollup_item_schema = z7.looseObject({
3727
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- GraphQL field name from GitHub API
3728
+ __typename: z7.string().nullish(),
3729
+ state: z7.string().nullish(),
3730
+ status: z7.string().nullish(),
3731
+ conclusion: z7.string().nullish(),
3732
+ name: z7.string().nullish(),
3733
+ context: z7.string().nullish(),
3734
+ description: z7.string().nullish()
3735
+ });
3736
+ var pr_raw_schema = z7.object({
3737
+ statusCheckRollup: z7.array(rollup_item_schema).optional(),
3738
+ // The base branch's required status check contexts, read from its rules — empty where none are
3739
+ // set or they could not be read (`git-gh-branch-rules.ts`).
3740
+ requiredContexts: z7.array(z7.string()).optional(),
3741
+ mergeStateStatus: z7.string().optional(),
3742
+ reviewDecision: z7.string().optional(),
3743
+ headRefOid: z7.string().optional()
3744
+ });
3745
+ var pull_comment_schema = z7.object({
3746
+ body: z7.string().optional(),
3747
+ html_url: z7.string().optional(),
3748
+ user: z7.object({ login: z7.string().optional() }).optional()
3749
+ });
3750
+ var ai_review_pull_comment_schema = z7.object({
3751
+ body: z7.string().optional(),
3752
+ url: z7.string().optional(),
3753
+ author: z7.object({ login: z7.string().optional() }).optional()
3754
+ });
3755
+ var pr_info_schema = z7.object({
3756
+ mergeable: z7.union([z7.boolean(), z7.string()]).nullable().optional(),
3757
+ mergeStateStatus: z7.string().nullable().optional(),
3758
+ state: z7.string().optional()
3759
+ });
3760
+ var epic_issue_schema = z7.object({
3761
+ number: z7.number(),
3762
+ body: z7.string().optional(),
3763
+ // REST answers null for an issue never closed and `reopened` for one a person reopened.
3764
+ stateReason: z7.string().nullish()
3765
+ });
3766
+ var blocking_issue_schema = z7.object({
3767
+ number: z7.number(),
3768
+ state: z7.string().optional(),
3769
+ repository_url: z7.string().optional()
3770
+ });
3771
+ var blocked_by_schema = z7.object({
3772
+ nodes: z7.array(blocking_issue_schema).default([]),
3773
+ totalCount: z7.number().optional()
3774
+ }).optional();
3775
+ var epic_child_schema = z7.object({
3776
+ state: z7.string().optional(),
3777
+ blockedBy: blocked_by_schema
3778
+ });
3779
+ var rest_comment_schema = z7.looseObject({
3780
+ body: z7.string().nullish(),
3781
+ html_url: z7.string().optional(),
3782
+ user: z7.looseObject({ login: z7.string().optional() }).nullish()
3783
+ });
3784
+ var issue_label_schema = z7.object({ name: z7.string() });
3785
+ var epic_subject_schema = z7.object({
3786
+ number: z7.number(),
3787
+ state: z7.string().optional(),
3788
+ labels: z7.array(issue_label_schema).optional(),
3789
+ body: z7.string().optional()
3790
+ });
3791
+ var open_issue_schema = z7.object({
3792
+ number: z7.number(),
3793
+ title: z7.string(),
3794
+ labels: z7.array(issue_label_schema).optional(),
3795
+ createdAt: z7.string(),
3796
+ blockedBy: blocked_by_schema,
3797
+ // Present only on the pickup listing, which reads it for the paths each issue declares.
3798
+ body: z7.string().optional()
3799
+ });
2342
3800
 
2343
3801
  export {
2344
3802
  json_value,
2345
- PORT_SEED_KEY,
2346
- LANE_SEAT_KEY,
2347
- ENV_FILE_NAME,
2348
- ports,
3803
+ file_reader,
2349
3804
  process_identity,
2350
3805
  process_owner_schema,
3806
+ issue_number_shape,
3807
+ lane_paths,
3808
+ stamped_memo,
2351
3809
  PORCELAIN_FLAG,
2352
3810
  UNTRACKED_FILES_FLAG,
2353
- git_utilities,
3811
+ get_exit_code,
2354
3812
  has_timed_out,
2355
3813
  git_spawn,
2356
3814
  git_diff_reads,
2357
3815
  GIT_LOCATION_VARIABLES,
2358
- git_location_environment,
2359
3816
  git_spawn_sync,
2360
3817
  git_command,
2361
3818
  cli_flags,
2362
- backlog_budget,
2363
- issue_number_shape,
2364
3819
  run_invocation,
2365
- lane_paths,
2366
- file_reader,
2367
3820
  time_instant,
2368
3821
  cost_usage,
2369
3822
  cost_transcript,
2370
3823
  agent_session_environment,
2371
3824
  own_session,
2372
- run_carry
3825
+ run_carry,
3826
+ PORT_SEED_KEY,
3827
+ LANE_SEAT_KEY,
3828
+ ENV_FILE_NAME,
3829
+ ports,
3830
+ figure_format,
3831
+ pr_raw_schema,
3832
+ epic_issue_schema,
3833
+ blocking_issue_schema,
3834
+ blocked_by_schema,
3835
+ rest_comment_schema,
3836
+ issue_label_schema,
3837
+ open_issue_schema,
3838
+ issue_cite,
3839
+ git_common_directory,
3840
+ repository_lock,
3841
+ run_ship_stage,
3842
+ run_event_stream,
3843
+ repo_origin,
3844
+ repo_map_logic,
3845
+ repo_discovery,
3846
+ issue_citation,
3847
+ session_cite,
3848
+ lane_state,
3849
+ run_event_scope,
3850
+ run_event_stream_emit,
3851
+ ancestor_directories,
3852
+ PACKAGE_JSON,
3853
+ package_manifest
2373
3854
  };