@joshuafolkken/kit 1.1514.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 (858) hide show
  1. package/.claude/agents/investigator.md +1 -1
  2. package/.claude/settings.json +5 -5
  3. package/.claude/skills/epic-commands/SKILL.md +26 -65
  4. package/.claude/skills/epic-commands/epic-bundle.md +3 -1
  5. package/.claude/skills/workflow-commands/SKILL.md +5 -5
  6. package/.claude/skills/workflow-commands/background-commands.md +5 -5
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +10 -8
  8. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
  9. package/.claude/skills/workflow-commands/backlogrun-lanes.md +17 -13
  10. package/.claude/skills/workflow-commands/backlogrun-park.md +14 -23
  11. package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -2
  12. package/.claude/skills/workflow-commands/backlogrun-recovery.md +5 -5
  13. package/.claude/skills/workflow-commands/backlogrun-steps.md +10 -10
  14. package/.claude/skills/workflow-commands/backlogrun.md +1 -1
  15. package/.claude/skills/workflow-commands/chain-rule.md +13 -7
  16. package/.claude/skills/workflow-commands/delegation.md +6 -5
  17. package/.claude/skills/workflow-commands/entry-sequence.md +9 -9
  18. package/.claude/skills/workflow-commands/followup.md +9 -31
  19. package/.claude/skills/workflow-commands/fullrun-steps.md +36 -45
  20. package/.claude/skills/workflow-commands/fullrun.md +2 -2
  21. package/.claude/skills/workflow-commands/halfrun.md +17 -25
  22. package/.claude/skills/workflow-commands/issue-comments.md +16 -12
  23. package/.claude/skills/workflow-commands/issue-scout.md +2 -2
  24. package/.claude/skills/workflow-commands/kickoff.md +24 -23
  25. package/.claude/skills/workflow-commands/latest-gate.md +7 -12
  26. package/.claude/skills/workflow-commands/needs-human-review.md +9 -14
  27. package/.claude/skills/workflow-commands/observation-filing.md +4 -36
  28. package/.claude/skills/workflow-commands/observation-ledger.md +1 -1
  29. package/.claude/skills/workflow-commands/pre-gate-cut.md +13 -30
  30. package/.claude/skills/workflow-commands/prerequisite.md +10 -16
  31. package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
  32. package/.claude/skills/workflow-commands/prrun.md +3 -7
  33. package/.claude/skills/workflow-commands/retrospective.md +1 -1
  34. package/.claude/skills/workflow-commands/split-assessment.md +13 -1
  35. package/.claude/skills/workflow-commands/working-tree-hold.md +9 -9
  36. package/.codex/hooks.json +5 -5
  37. package/.github/actions/setup-node/action.yml +9 -0
  38. package/.github/actions/setup-pnpm/action.yml +1 -1
  39. package/.github/dependabot.yml +16 -0
  40. package/.github/release.yml +0 -2
  41. package/.github/workflows/ci.yml +120 -10
  42. package/.github/workflows/publish.yml +8 -1
  43. package/.github/workflows/sonar-qube.yml +1 -0
  44. package/.prettierignore +2 -0
  45. package/.vscode/tasks.json +1 -2
  46. package/CLAUDE.md +3 -7
  47. package/README.md +4 -2
  48. package/SECURITY.md +1 -1
  49. package/dist/CLAUDE.md +3 -7
  50. package/dist/commands/document-read-cli.js +882 -0
  51. package/dist/commands/{document-section-cli.js → document-section-main.js} +79 -37
  52. package/dist/commands/read-set-cli.js +1867 -0
  53. package/dist/commands/run-prep-main.js +21653 -0
  54. package/dist/commands/run-step-cli.js +23880 -0
  55. package/dist/config-merge/index.js +5 -1
  56. package/dist/hooks/audit-provision.js +20 -35
  57. package/dist/hooks/{chunk-DGT54IH5.js → chunk-AZX4FGQ3.js} +63 -17
  58. package/dist/hooks/chunk-CWMBGKYW.js +6483 -0
  59. package/dist/hooks/chunk-O2YBIDSI.js +4306 -0
  60. package/dist/hooks/{chunk-TNUMY6NL.js → chunk-PT5R6UJD.js} +4193 -1900
  61. package/dist/hooks/chunk-TUIFS5E7.js +72 -0
  62. package/dist/hooks/{chunk-723HKZO5.js → chunk-VWWCFGWK.js} +1 -1
  63. package/dist/hooks/{chunk-APUO6U4J.js → chunk-WR2KQAYZ.js} +1843 -440
  64. package/dist/hooks/{chunk-O6GDRNJB.js → chunk-XGBNSWEI.js} +248 -46
  65. package/dist/hooks/chunk-YCDOIR3I.js +3456 -0
  66. package/dist/hooks/codex-hook-adapter.js +10 -22
  67. package/dist/hooks/format-edited.js +5 -6
  68. package/dist/hooks/inputs.json +443 -317
  69. package/dist/hooks/pretool-guard.js +7 -25
  70. package/dist/hooks/session-lang.js +44 -51
  71. package/dist/hooks/stop-guard.js +7716 -2187
  72. package/dist/josh.js +6002 -3583
  73. package/dist/self-sync-guard/index.js +74 -10
  74. package/dist/version/index.js +115 -406
  75. package/eslint/base.js +1 -1
  76. package/lefthook/base.yml +3 -1
  77. package/package.json +10 -48
  78. package/pnpm-workspace.yaml +4 -2
  79. package/prompts/coding-standards.md +1 -1
  80. package/prompts/collaboration-workflow/file-edits.md +1 -7
  81. package/prompts/collaboration-workflow/issue-citation.md +1 -1
  82. package/prompts/collaboration-workflow/issue-template.md +33 -16
  83. package/prompts/collaboration-workflow/lane-instructions.md +1 -2
  84. package/prompts/collaboration-workflow/measurement.md +37 -0
  85. package/prompts/collaboration-workflow/operating-rules.md +4 -6
  86. package/prompts/collaboration-workflow/output-bounds.md +2 -7
  87. package/prompts/collaboration-workflow/plan-comment.md +3 -42
  88. package/prompts/collaboration-workflow/principles.md +5 -0
  89. package/prompts/collaboration-workflow/report-format.md +31 -60
  90. package/prompts/collaboration-workflow/residency.md +2 -2
  91. package/prompts/collaboration-workflow/shell-body.md +6 -16
  92. package/prompts/collaboration-workflow/turn-batching.md +0 -2
  93. package/prompts/collaboration-workflow/upstream-interrupt.md +14 -4
  94. package/prompts/collaboration-workflow/wip-cap.md +1 -1
  95. package/prompts/collaboration-workflow.md +3 -7
  96. package/prompts/refactoring.md +1 -1
  97. package/prompts/review-rubric.md +1 -2
  98. package/prompts/review.md +41 -21
  99. package/prompts/testing-guide.md +8 -43
  100. package/scripts/agent/agent-event.ts +15 -15
  101. package/scripts/agent/agent-exit-record.ts +13 -1
  102. package/scripts/agent/api-auth.ts +41 -0
  103. package/scripts/agent/api-outage.ts +1 -1
  104. package/scripts/auto-ok/auto-ok-cli.ts +14 -16
  105. package/scripts/auto-ok/auto-ok-judge-read.ts +12 -3
  106. package/scripts/auto-ok/auto-ok-judge-write.ts +46 -19
  107. package/scripts/auto-ok/auto-ok-judge.ts +13 -2
  108. package/scripts/auto-ok/auto-ok-main.ts +17 -0
  109. package/scripts/backlog/backlog-arrival.ts +14 -3
  110. package/scripts/backlog/backlog-budget-cli.ts +7 -33
  111. package/scripts/backlog/backlog-budget-main.ts +16 -0
  112. package/scripts/backlog/backlog-budget.ts +2 -3
  113. package/scripts/backlog/backlog-defect-priority.ts +4 -3
  114. package/scripts/backlog/backlog-drive-adopt.ts +67 -0
  115. package/scripts/backlog/backlog-drive-args.ts +4 -5
  116. package/scripts/backlog/backlog-drive-cli.ts +113 -28
  117. package/scripts/backlog/backlog-drive-hold.ts +162 -0
  118. package/scripts/backlog/backlog-drive-idle.ts +151 -0
  119. package/scripts/backlog/backlog-drive-judge.ts +25 -0
  120. package/scripts/backlog/backlog-drive-memory.ts +126 -0
  121. package/scripts/backlog/backlog-drive-named-offer.ts +5 -10
  122. package/scripts/backlog/backlog-drive-named.ts +53 -6
  123. package/scripts/backlog/backlog-drive-offer-argv.ts +3 -8
  124. package/scripts/backlog/backlog-drive-paused.ts +169 -0
  125. package/scripts/backlog/backlog-drive-restore.ts +30 -7
  126. package/scripts/backlog/backlog-drive-seats.ts +18 -8
  127. package/scripts/backlog/backlog-drive-token-handling.ts +38 -0
  128. package/scripts/backlog/backlog-drive.ts +79 -75
  129. package/scripts/backlog/backlog-next-main.ts +16 -0
  130. package/scripts/backlog/backlog-next-shared.ts +73 -0
  131. package/scripts/backlog/backlog-next.ts +48 -16
  132. package/scripts/backlog/backlog-occupied.ts +52 -39
  133. package/scripts/backlog/backlog-offer-cli.ts +6 -21
  134. package/scripts/backlog/backlog-offer-exclude.ts +15 -0
  135. package/scripts/backlog/backlog-offer-main.ts +12 -0
  136. package/scripts/backlog/backlog-offer.ts +36 -3
  137. package/scripts/backlog/backlog-overlap.ts +22 -4
  138. package/scripts/backlog/backlog-plan-read.ts +6 -2
  139. package/scripts/backlog/backlog-plan.ts +18 -4
  140. package/scripts/backlog/backlog-pool.ts +10 -10
  141. package/scripts/backlog/backlog-rank.ts +10 -2
  142. package/scripts/backlog/backlog-ready.ts +112 -30
  143. package/scripts/backlog/backlog-stalled-detect.ts +109 -36
  144. package/scripts/backlog/backlog-stalled.ts +52 -16
  145. package/scripts/backlog/backlog-wait-cause.ts +86 -0
  146. package/scripts/backlog/backlog-waves.ts +39 -13
  147. package/scripts/backlog/backlogrun-args.ts +19 -7
  148. package/scripts/backlog/backlogrun-cli.ts +19 -5
  149. package/scripts/backlog/backlogrun-launch.ts +6 -0
  150. package/scripts/backlog/backlogrun-restart.ts +97 -0
  151. package/scripts/backlog/backlogrun-stop.ts +79 -7
  152. package/scripts/behavior/behavior-cli.ts +2 -2
  153. package/scripts/behavior/behavior-rules.ts +47 -24
  154. package/scripts/build/build-bin.ts +2 -16
  155. package/scripts/build/build-claude-md.ts +0 -7
  156. package/scripts/build/build-commands.ts +0 -13
  157. package/scripts/build/build-hooks.ts +49 -48
  158. package/scripts/build/hook-bundle-stamp.ts +29 -11
  159. package/scripts/build/local-bin.ts +1 -1
  160. package/scripts/cases/cases-cli.ts +25 -13
  161. package/scripts/cases/cases-interaction-scan.ts +134 -0
  162. package/scripts/cases/cases-interaction.ts +183 -0
  163. package/scripts/cases/cases-logic.ts +39 -6
  164. package/scripts/ci/pr-classification-main.ts +18 -0
  165. package/scripts/ci/pr-classification.ts +10 -17
  166. package/scripts/clone/clone-scan.ts +1 -1
  167. package/scripts/cost-runtime/cost-blocks.ts +22 -37
  168. package/scripts/cost-runtime/cost-cli.ts +31 -14
  169. package/scripts/cost-runtime/cost-main.ts +12 -0
  170. package/scripts/cost-runtime/cost-transcript.ts +1 -0
  171. package/scripts/delegation/delegation-policy.ts +17 -4
  172. package/scripts/delegation/duplicate-read-guard.ts +0 -8
  173. package/scripts/delegation/investigation-guard.ts +0 -8
  174. package/scripts/delegation/investigation-reads.ts +3 -4
  175. package/scripts/dependabot/dependabot-cooldown.ts +194 -0
  176. package/scripts/discovery/repo-discovery.ts +24 -6
  177. package/scripts/doctor/doctor-consumer.ts +2 -5
  178. package/scripts/document/document-byte-budget.ts +8 -6
  179. package/scripts/document/document-scan.ts +1 -1
  180. package/scripts/document/document-section-cli.ts +0 -8
  181. package/scripts/document/document-section-main.ts +12 -0
  182. package/scripts/epic/epic-audit-cli.ts +12 -6
  183. package/scripts/epic/epic-bundle-apply.ts +137 -0
  184. package/scripts/epic/epic-bundle-cli.ts +32 -121
  185. package/scripts/epic/epic-bundle-format.ts +116 -0
  186. package/scripts/epic/epic-bundle-main.ts +17 -0
  187. package/scripts/epic/epic-busy.ts +5 -12
  188. package/scripts/epic/epic-classify.ts +24 -15
  189. package/scripts/epic/epic-cli-argv.ts +31 -0
  190. package/scripts/epic/epic-cli-decide.ts +42 -0
  191. package/scripts/epic/epic-cli.ts +6 -38
  192. package/scripts/epic/epic-close.ts +112 -55
  193. package/scripts/epic/epic-cross-repo.ts +4 -7
  194. package/scripts/epic/epic-decide.ts +119 -0
  195. package/scripts/epic/epic-decision.ts +9 -0
  196. package/scripts/epic/epic-fetch.ts +4 -0
  197. package/scripts/epic/epic-graph.ts +2 -0
  198. package/scripts/epic/epic-issue.ts +5 -1
  199. package/scripts/epic/epic-label-age.ts +1 -1
  200. package/scripts/epic/epic-lane-offer.ts +39 -4
  201. package/scripts/epic/epic-next-main.ts +24 -0
  202. package/scripts/epic/epic-next.ts +6 -24
  203. package/scripts/epic/epic-outside-blocker.ts +6 -2
  204. package/scripts/epic/epic-parse.ts +9 -3
  205. package/scripts/epic/epic-read.ts +1 -0
  206. package/scripts/epic/epic-reconcile.ts +39 -0
  207. package/scripts/epic/epic-run.ts +10 -1
  208. package/scripts/epic/epic-solo.ts +50 -14
  209. package/scripts/epic/epic.ts +41 -7
  210. package/scripts/exports/unused-members-cli.ts +2 -2
  211. package/scripts/followup/followup-checks-event.ts +8 -3
  212. package/scripts/followup/followup-coderabbit-wait.ts +82 -0
  213. package/scripts/followup/followup-review-gates.ts +81 -0
  214. package/scripts/followup/git-followup-stages.ts +13 -3
  215. package/scripts/followup/git-followup-workflow.ts +19 -66
  216. package/scripts/followup/git-pr-followup-wrapup.ts +9 -14
  217. package/scripts/followup/git-pr-followup.ts +36 -8
  218. package/scripts/fresh-machine/fresh-machine-cli.ts +1 -1
  219. package/scripts/fresh-machine/fresh-machine-run.ts +8 -8
  220. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +1 -1
  221. package/scripts/gate/busy-average.ts +58 -0
  222. package/scripts/gate/check-cpu.ts +60 -0
  223. package/scripts/gate/check-inputs.ts +39 -95
  224. package/scripts/gate/check-reuse.ts +33 -54
  225. package/scripts/gate/command-memory.ts +192 -0
  226. package/scripts/gate/core-admission.ts +218 -28
  227. package/scripts/gate/core-budget-timing.ts +37 -0
  228. package/scripts/gate/core-budget.ts +80 -98
  229. package/scripts/gate/core-wait-record.ts +48 -0
  230. package/scripts/gate/core-wait.ts +37 -5
  231. package/scripts/gate/core-weights.ts +86 -0
  232. package/scripts/gate/free-cores.ts +27 -4
  233. package/scripts/gate/gate-ledger.ts +32 -4
  234. package/scripts/gate/gate-plan.ts +41 -34
  235. package/scripts/gate/gate-report.ts +14 -2
  236. package/scripts/gate/gate-run-steps.ts +53 -8
  237. package/scripts/gate/gate-skip.ts +12 -2
  238. package/scripts/gate/gate-steps.ts +12 -1
  239. package/scripts/gate/input-fingerprint.ts +42 -0
  240. package/scripts/gate/machine-capacity.ts +65 -31
  241. package/scripts/gate/moved-paths.ts +67 -0
  242. package/scripts/gate/project-checks.ts +5 -12
  243. package/scripts/gate/scoped-green.ts +12 -8
  244. package/scripts/gate/since-green.ts +62 -0
  245. package/scripts/gate/toolchain-inputs.ts +115 -0
  246. package/scripts/gate/verification-gate.ts +27 -24
  247. package/scripts/gate/verification-inputs.ts +250 -0
  248. package/scripts/gh/gh-author-association.ts +96 -9
  249. package/scripts/gh/git-ai-review-scan.ts +4 -2
  250. package/scripts/gh/git-gh-api-path.ts +15 -0
  251. package/scripts/gh/git-gh-branch-rules.ts +73 -0
  252. package/scripts/gh/git-gh-conditional.ts +5 -2
  253. package/scripts/gh/git-gh-issue-read.ts +5 -1
  254. package/scripts/gh/git-gh-issue-write.ts +67 -29
  255. package/scripts/gh/git-gh-issue.ts +7 -3
  256. package/scripts/gh/git-gh-poll-read.ts +89 -0
  257. package/scripts/gh/git-gh-pr-auto-merge.ts +8 -3
  258. package/scripts/gh/git-gh-pr-rest.ts +1 -1
  259. package/scripts/gh/git-gh-pr-snapshot.ts +33 -20
  260. package/scripts/gh/git-gh-pr.ts +27 -15
  261. package/scripts/gh/git-pr-checks-eval.ts +39 -7
  262. package/scripts/gh/git-pr-checks-parse.ts +39 -9
  263. package/scripts/gh/git-pr-merge-checked.ts +80 -0
  264. package/scripts/git/base-tree.ts +19 -2
  265. package/scripts/git/changed-file-scope.ts +6 -4
  266. package/scripts/git/changed-paths.ts +18 -1
  267. package/scripts/git/git-diff-reads.ts +27 -2
  268. package/scripts/git/git-grep-hits.ts +85 -0
  269. package/scripts/git/git-location-environment.ts +1 -1
  270. package/scripts/git/git-merge-conflicts.ts +83 -0
  271. package/scripts/git/git-preflight.ts +37 -12
  272. package/scripts/git/git-push-transport.ts +1 -2
  273. package/scripts/git/git-schemas.ts +17 -7
  274. package/scripts/git/git-spawn.ts +1 -2
  275. package/scripts/git/git-status.ts +4 -4
  276. package/scripts/git/main-merge-main.ts +12 -0
  277. package/scripts/git/main-merge-regenerate.ts +2 -2
  278. package/scripts/git/main-merge.ts +25 -9
  279. package/scripts/git/main-sync-main.ts +12 -0
  280. package/scripts/git/main-sync.ts +0 -9
  281. package/scripts/git/stash/git-stash.ts +27 -4
  282. package/scripts/git/stash/{stash-pop-args.ts → stash-args.ts} +13 -10
  283. package/scripts/git/stash/stash-pop-cli.ts +6 -12
  284. package/scripts/git/stash/stash-pop-main.ts +12 -0
  285. package/scripts/git/stash/stash-push-cli.ts +76 -0
  286. package/scripts/git/stash/stash-push-main.ts +12 -0
  287. package/scripts/hooks/batch-guard.ts +0 -8
  288. package/scripts/hooks/check-commit-message-main.ts +8 -0
  289. package/scripts/hooks/check-commit-message.ts +4 -7
  290. package/scripts/hooks/format-edited-file.ts +8 -24
  291. package/scripts/hooks/pre-commit-lint.ts +30 -3
  292. package/scripts/hooks/pre-push-unit.ts +4 -2
  293. package/scripts/hooks/pretool-guard-cli.ts +1 -8
  294. package/scripts/hooks/pretool-guard.ts +32 -19
  295. package/scripts/hooks/reserved-run.ts +67 -9
  296. package/scripts/hooks/run-hook.sh +13 -4
  297. package/scripts/hooks/shell-rules-notice.ts +37 -0
  298. package/scripts/hooks/stop-actions.ts +2 -21
  299. package/scripts/hooks/stop-guard.ts +13 -9
  300. package/scripts/init/hook-command-rewrite.ts +19 -5
  301. package/scripts/init/hook-launch.ts +15 -17
  302. package/scripts/init/init-actions.ts +0 -6
  303. package/scripts/init/init-ai-copy.ts +10 -36
  304. package/scripts/init/init-bootstrap.ts +9 -8
  305. package/scripts/init/init-dry-run-report.ts +1 -1
  306. package/scripts/init/init-dry-run.ts +1 -1
  307. package/scripts/init/init-file-action.ts +7 -9
  308. package/scripts/init/init-logic-json-merge.ts +2 -2
  309. package/scripts/init/init-logic-migrate.ts +9 -82
  310. package/scripts/init/init-logic.ts +3 -2
  311. package/scripts/init/init-main.ts +12 -0
  312. package/scripts/init/init.ts +5 -12
  313. package/scripts/init/kit-development-versions.ts +3 -7
  314. package/scripts/init/kit-written-paths.ts +2 -2
  315. package/scripts/init/project-profile.ts +5 -4
  316. package/scripts/init/tsconfig-preset-migration.ts +2 -1
  317. package/scripts/init/vscode-tasks.ts +1 -1
  318. package/scripts/issue/defect-origin-cli.ts +106 -0
  319. package/scripts/issue/defect-origin-line.ts +60 -0
  320. package/scripts/issue/defect-origin-main.ts +11 -0
  321. package/scripts/issue/defect-origin.ts +114 -0
  322. package/scripts/issue/defect-rate-cli.ts +34 -78
  323. package/scripts/issue/defect-rate.ts +0 -16
  324. package/scripts/issue/defect-report-cli.ts +128 -0
  325. package/scripts/issue/defect-report-format.ts +56 -0
  326. package/scripts/issue/defect-report-main.ts +11 -0
  327. package/scripts/issue/defect-report.ts +160 -0
  328. package/scripts/issue/expected-effect-lint.ts +1 -0
  329. package/scripts/issue/issue-already-done-cli.ts +62 -0
  330. package/scripts/issue/issue-body-or-comment.ts +40 -0
  331. package/scripts/issue/issue-cite-cli.ts +0 -9
  332. package/scripts/issue/issue-cite-main.ts +12 -0
  333. package/scripts/issue/issue-classification.ts +12 -7
  334. package/scripts/issue/issue-comment-cli.ts +10 -24
  335. package/scripts/issue/issue-comment-main.ts +12 -0
  336. package/scripts/issue/issue-evidence-exit.ts +100 -0
  337. package/scripts/issue/issue-file-cli.ts +29 -7
  338. package/scripts/issue/issue-file.ts +19 -19
  339. package/scripts/issue/issue-fold-cli.ts +2 -11
  340. package/scripts/issue/issue-fold-main.ts +12 -0
  341. package/scripts/issue/issue-labels.ts +81 -90
  342. package/scripts/issue/issue-lint-cli.ts +2 -10
  343. package/scripts/issue/issue-lint-main.ts +12 -0
  344. package/scripts/issue/issue-measured-cli.ts +56 -0
  345. package/scripts/issue/issue-merged.ts +19 -2
  346. package/scripts/issue/issue-not-before-label.ts +135 -0
  347. package/scripts/issue/issue-not-before.ts +111 -0
  348. package/scripts/issue/issue-number-shape.ts +15 -1
  349. package/scripts/issue/issue-park.ts +28 -0
  350. package/scripts/issue/issue-plan-cli.ts +151 -0
  351. package/scripts/issue/issue-priority.ts +151 -0
  352. package/scripts/issue/issue-rank.ts +7 -1
  353. package/scripts/issue/issue-read-cli.ts +3 -10
  354. package/scripts/issue/issue-read-main.ts +12 -0
  355. package/scripts/issue/issue-read.ts +29 -5
  356. package/scripts/issue/issue-release-cli.ts +0 -10
  357. package/scripts/issue/issue-release-main.ts +13 -0
  358. package/scripts/issue/issue-release.ts +7 -12
  359. package/scripts/issue/issue-sample-gate.ts +192 -0
  360. package/scripts/issue/issue-sample-source.ts +76 -0
  361. package/scripts/issue/issue-scout-cli.ts +0 -11
  362. package/scripts/issue/issue-scout-main.ts +14 -0
  363. package/scripts/issue/issue-state-cli.ts +0 -10
  364. package/scripts/issue/issue-state-main.ts +12 -0
  365. package/scripts/issue/issue-watch-diff.ts +56 -15
  366. package/scripts/issue/issue-watch.ts +2 -1
  367. package/scripts/issue/issue-wip.ts +2 -7
  368. package/scripts/issue/measure-rerun-cli.ts +13 -8
  369. package/scripts/issue/plan-consumers-cli.ts +39 -0
  370. package/scripts/issue/plan-consumers-main.ts +11 -0
  371. package/scripts/issue/plan-consumers-section.ts +55 -0
  372. package/scripts/issue/plan-consumers.ts +127 -0
  373. package/scripts/josh/agent-session-environment.ts +1 -1
  374. package/scripts/josh/command-usage.ts +15 -43
  375. package/scripts/josh/file-map-stamp.ts +49 -16
  376. package/scripts/josh/hook-decision.ts +32 -20
  377. package/scripts/josh/josh-command-map.ts +4 -1
  378. package/scripts/josh/josh-command-types.ts +12 -6
  379. package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
  380. package/scripts/josh/josh-commands-ai.ts +157 -158
  381. package/scripts/josh/josh-commands-backlog.ts +82 -16
  382. package/scripts/josh/josh-commands-clone.ts +1 -0
  383. package/scripts/josh/josh-commands-development.ts +111 -71
  384. package/scripts/josh/josh-commands-document.ts +43 -1
  385. package/scripts/josh/josh-commands-epic.ts +171 -0
  386. package/scripts/josh/josh-commands-hooks.ts +25 -2
  387. package/scripts/josh/josh-commands-issue-write.ts +181 -0
  388. package/scripts/josh/josh-commands-issue.ts +124 -24
  389. package/scripts/josh/josh-commands-lane.ts +103 -2
  390. package/scripts/josh/josh-commands-lint.ts +19 -8
  391. package/scripts/josh/josh-commands-maintenance.ts +112 -4
  392. package/scripts/josh/josh-commands-pause.ts +29 -0
  393. package/scripts/josh/josh-commands-progress.ts +87 -0
  394. package/scripts/josh/josh-commands-project.ts +138 -9
  395. package/scripts/josh/josh-commands-review.ts +124 -0
  396. package/scripts/josh/josh-commands-run.ts +211 -23
  397. package/scripts/josh/josh-commands-ship.ts +169 -0
  398. package/scripts/josh/josh-commands-split.ts +9 -0
  399. package/scripts/josh/josh-commands-versioning.ts +49 -2
  400. package/scripts/josh/josh-commands-workflow.ts +144 -6
  401. package/scripts/josh/josh-logic.ts +6 -13
  402. package/scripts/josh/package-directory.ts +2 -4
  403. package/scripts/josh/process-identity.ts +13 -4
  404. package/scripts/josh/session-language-cli.ts +4 -8
  405. package/scripts/josh/session-language-main.ts +13 -0
  406. package/scripts/josh/session-language.ts +6 -1
  407. package/scripts/josh/shared-cache.ts +90 -0
  408. package/scripts/josh/stamp-file.ts +9 -15
  409. package/scripts/lane/lane-await.ts +51 -12
  410. package/scripts/lane/lane-cache.ts +5 -30
  411. package/scripts/lane/lane-capacity.ts +14 -23
  412. package/scripts/lane/lane-check-stats.ts +62 -21
  413. package/scripts/lane/lane-child-invocation.ts +8 -0
  414. package/scripts/lane/lane-cli.ts +15 -5
  415. package/scripts/lane/lane-close.ts +86 -18
  416. package/scripts/lane/lane-core-wait-stats.ts +66 -0
  417. package/scripts/lane/lane-dispatch.ts +24 -3
  418. package/scripts/lane/lane-gap-stats.ts +156 -0
  419. package/scripts/lane/lane-handoff.ts +69 -1
  420. package/scripts/lane/lane-held-stats.ts +129 -0
  421. package/scripts/lane/lane-install.ts +4 -11
  422. package/scripts/lane/lane-launch-cli.ts +0 -9
  423. package/scripts/lane/lane-launch-main.ts +12 -0
  424. package/scripts/lane/lane-ledger-schema.ts +266 -0
  425. package/scripts/lane/lane-ledger.ts +92 -123
  426. package/scripts/lane/lane-limit-cli.ts +12 -1
  427. package/scripts/lane/lane-measure-cli.ts +57 -11
  428. package/scripts/lane/lane-open.ts +9 -1
  429. package/scripts/lane/lane-parked.ts +3 -3
  430. package/scripts/lane/lane-pause-cli.ts +130 -0
  431. package/scripts/lane/lane-pause.ts +158 -0
  432. package/scripts/lane/lane-process-table.ts +166 -0
  433. package/scripts/lane/lane-reap-settle.ts +124 -0
  434. package/scripts/lane/lane-reap.ts +50 -15
  435. package/scripts/lane/lane-registry.ts +24 -3
  436. package/scripts/lane/lane-residents.ts +162 -0
  437. package/scripts/lane/lane-restart.ts +22 -2
  438. package/scripts/lane/lane-round-two-stats.ts +49 -0
  439. package/scripts/lane/lane-sampler.ts +4 -0
  440. package/scripts/lane/lane-session-action.ts +19 -5
  441. package/scripts/lane/lane-session-broker.ts +102 -21
  442. package/scripts/lane/lane-snapshot-trace.ts +84 -0
  443. package/scripts/lane/lane-spans.ts +51 -0
  444. package/scripts/lane/lane-spent.ts +6 -3
  445. package/scripts/lane/lane-stage-stats.ts +7 -2
  446. package/scripts/lane/lane-state.ts +302 -0
  447. package/scripts/lane/lane-stats.ts +58 -4
  448. package/scripts/lane/lane-stop-stats.ts +113 -37
  449. package/scripts/lane/lane-test-related-stats.ts +127 -0
  450. package/scripts/lane/lane-transcript-calls.ts +145 -0
  451. package/scripts/lane/lane-transcript-stats.ts +168 -0
  452. package/scripts/lane/lane-vacant.ts +13 -3
  453. package/scripts/lane/lane-withdraw-cli.ts +5 -4
  454. package/scripts/lane/lane-withdraw.ts +50 -49
  455. package/scripts/lane/process-directories.ts +70 -0
  456. package/scripts/lane/process-lane-marks.ts +94 -0
  457. package/scripts/lib/atomic-write.ts +62 -0
  458. package/scripts/lib/buffered-process.ts +12 -5
  459. package/scripts/lib/cli-flags.ts +53 -0
  460. package/scripts/lib/figure-format.ts +63 -0
  461. package/scripts/lib/json-value.ts +9 -1
  462. package/scripts/lib/package-manifest.ts +35 -0
  463. package/scripts/lib/read-file.ts +3 -1
  464. package/scripts/lib/stamped-memo.ts +63 -0
  465. package/scripts/lib/stdout-on-stderr.ts +24 -0
  466. package/scripts/lib/timeouts.ts +9 -0
  467. package/scripts/lib/transcript-record.ts +91 -0
  468. package/scripts/lines/effective-limit.ts +1 -1
  469. package/scripts/lint/eslint-cache-dependencies.ts +145 -0
  470. package/scripts/lint/eslint-daemon.ts +265 -0
  471. package/scripts/lint/format.ts +11 -2
  472. package/scripts/lint/import-graph.ts +279 -0
  473. package/scripts/lint/lint-gate-scope.ts +102 -0
  474. package/scripts/lint/lint-parallel-main.ts +19 -0
  475. package/scripts/lint/lint-parallel.ts +62 -30
  476. package/scripts/lint/lint-related-scope.ts +30 -24
  477. package/scripts/lint/lint-related.ts +38 -6
  478. package/scripts/notify/confirmation-options.ts +1 -2
  479. package/scripts/notify/telegram-notify.ts +20 -20
  480. package/scripts/notify/telegram-test-logic.ts +0 -1
  481. package/scripts/notify/telegram-test-main.ts +8 -0
  482. package/scripts/notify/telegram-test.ts +2 -6
  483. package/scripts/observations/observation-ledger.ts +13 -0
  484. package/scripts/observations/observations-flush-landing.ts +5 -3
  485. package/scripts/observations/observations-flush.ts +6 -1
  486. package/scripts/overrides/overrides-check.ts +2 -5
  487. package/scripts/overrides/overrides-files.ts +2 -1
  488. package/scripts/overrides/overrides-logic.ts +3 -6
  489. package/scripts/package/verify-optional-eslint-install.ts +8 -6
  490. package/scripts/propagate/propagate-publish.ts +2 -7
  491. package/scripts/propagate/propagate-targets.ts +4 -12
  492. package/scripts/refactor/import-graph.ts +9 -7
  493. package/scripts/release/github-release-runs.ts +17 -6
  494. package/scripts/release/release-approval-prune.ts +18 -0
  495. package/scripts/release/release-history.ts +1 -3
  496. package/scripts/release/release-progress.ts +42 -22
  497. package/scripts/release/release-publish-run.ts +39 -0
  498. package/scripts/release/release-publish.ts +6 -6
  499. package/scripts/release/release-scope-cli.ts +0 -10
  500. package/scripts/release/release-scope-main.ts +12 -0
  501. package/scripts/repo/repo-setting.ts +3 -6
  502. package/scripts/repo/required-checks-logic.ts +6 -15
  503. package/scripts/report/report-format-reference.ts +2 -0
  504. package/scripts/report/report-labels.ts +155 -0
  505. package/scripts/report/report-lint-cli.ts +3 -0
  506. package/scripts/report/report-lint.ts +85 -110
  507. package/scripts/report/report-template-cli.ts +59 -0
  508. package/scripts/report/report-template.ts +112 -0
  509. package/scripts/review/acceptance-map.ts +1 -0
  510. package/scripts/review/removed-tests-check.ts +86 -0
  511. package/scripts/review/removed-tests.ts +149 -0
  512. package/scripts/review/review-brief-cli.ts +81 -15
  513. package/scripts/review/review-brief-main.ts +12 -0
  514. package/scripts/review/review-brief.ts +31 -3
  515. package/scripts/review/review-code-tree.ts +10 -6
  516. package/scripts/review/review-comment-round.ts +26 -8
  517. package/scripts/review/review-finding-ledger.ts +30 -15
  518. package/scripts/review/review-interaction.ts +94 -0
  519. package/scripts/review/review-readers-scan.ts +163 -0
  520. package/scripts/review/review-record-cli.ts +69 -30
  521. package/scripts/review/review-record-main.ts +12 -0
  522. package/scripts/review/review-round-one-blobs.ts +221 -0
  523. package/scripts/review/review-round2-cli.ts +49 -12
  524. package/scripts/review/review-round2.ts +80 -12
  525. package/scripts/review/review-stamps.ts +19 -1
  526. package/scripts/review/review-stop-log.ts +96 -0
  527. package/scripts/review/review-stops-cli.ts +85 -0
  528. package/scripts/review/review-tree.ts +6 -17
  529. package/scripts/review/review-untouched-readers.ts +146 -0
  530. package/scripts/review/test-titles.ts +118 -0
  531. package/scripts/rules/agent-model.ts +8 -0
  532. package/scripts/rules/bash-triggers.ts +46 -3
  533. package/scripts/rules/decision-oracle-batch.ts +9 -1
  534. package/scripts/rules/decision-oracle.ts +2 -2
  535. package/scripts/rules/delivered-rules.ts +80 -2
  536. package/scripts/rules/destructive-command.ts +8 -1
  537. package/scripts/rules/direct-filing.ts +10 -2
  538. package/scripts/rules/direct-issue-comment.ts +117 -0
  539. package/scripts/rules/direct-pr-create.ts +69 -3
  540. package/scripts/rules/early-heartbeat.ts +2 -1
  541. package/scripts/rules/file-body.ts +7 -0
  542. package/scripts/rules/filing-cap.ts +7 -0
  543. package/scripts/rules/git-argv.ts +72 -14
  544. package/scripts/rules/git-force.ts +12 -2
  545. package/scripts/rules/guard-remedy.ts +4 -0
  546. package/scripts/rules/implementation-cut-verdict.ts +1 -1
  547. package/scripts/rules/implementation-cut.ts +11 -3
  548. package/scripts/rules/index-guard.ts +8 -1
  549. package/scripts/rules/issue-comments.ts +9 -1
  550. package/scripts/rules/josh-git-bare.ts +7 -0
  551. package/scripts/rules/lane-background.ts +67 -25
  552. package/scripts/rules/lane-carry-conflict.ts +6 -0
  553. package/scripts/rules/lane-direct-tool.ts +74 -0
  554. package/scripts/rules/lane-interactive-ask.ts +9 -2
  555. package/scripts/rules/lane-park.ts +45 -23
  556. package/scripts/rules/lane-split-park.ts +10 -2
  557. package/scripts/rules/lane-switch-main.ts +7 -0
  558. package/scripts/rules/oracle-consulted.ts +10 -0
  559. package/scripts/rules/oracle-firing.ts +1 -0
  560. package/scripts/rules/permission-guards.ts +3 -0
  561. package/scripts/rules/piped-verification.ts +1 -1
  562. package/scripts/rules/poll-loop.ts +7 -0
  563. package/scripts/rules/pr-merge.ts +123 -0
  564. package/scripts/rules/protected-files.ts +32 -5
  565. package/scripts/rules/raw-field-body.ts +6 -0
  566. package/scripts/rules/rule-body-guard.ts +8 -0
  567. package/scripts/rules/rule-list.ts +9 -28
  568. package/scripts/rules/rule-value-cache.ts +4 -9
  569. package/scripts/rules/rule-value-cli.ts +51 -32
  570. package/scripts/rules/rule-value.ts +1 -1
  571. package/scripts/rules/shell-segments.ts +35 -0
  572. package/scripts/rules/stop-rule-rows.ts +64 -0
  573. package/scripts/rules/stop-rules.ts +3 -4
  574. package/scripts/rules/test-declared-commit.ts +11 -1
  575. package/scripts/rules/third-party-write.ts +7 -0
  576. package/scripts/rules/timed-rerun.ts +69 -0
  577. package/scripts/rules/worktree-guard.ts +13 -3
  578. package/scripts/run/board/run-board-app-name.ts +23 -0
  579. package/scripts/run/board/run-board-cli.ts +65 -32
  580. package/scripts/run/board/run-board-earlier.ts +94 -0
  581. package/scripts/run/board/run-board-ending-reason.ts +67 -0
  582. package/scripts/run/board/run-board-estimate-schedule.ts +103 -0
  583. package/scripts/run/board/run-board-estimate.ts +98 -0
  584. package/scripts/run/board/run-board-fit.ts +153 -36
  585. package/scripts/run/board/run-board-fold.ts +123 -0
  586. package/scripts/run/board/run-board-fresh.ts +2 -2
  587. package/scripts/run/board/run-board-gather-live.ts +29 -0
  588. package/scripts/run/board/run-board-gather-thread.ts +189 -0
  589. package/scripts/run/board/run-board-gather-worker.ts +29 -0
  590. package/scripts/run/board/run-board-gather.ts +187 -0
  591. package/scripts/run/board/run-board-github.ts +118 -38
  592. package/scripts/run/board/run-board-header.ts +82 -20
  593. package/scripts/run/board/run-board-keys.ts +58 -0
  594. package/scripts/run/board/run-board-kind.ts +20 -6
  595. package/scripts/run/board/run-board-labels.ts +116 -71
  596. package/scripts/run/board/run-board-lane-state.ts +109 -0
  597. package/scripts/run/board/run-board-lane-time.ts +122 -0
  598. package/scripts/run/board/run-board-layout.ts +239 -60
  599. package/scripts/run/board/run-board-length.ts +52 -0
  600. package/scripts/run/board/run-board-machine.ts +8 -4
  601. package/scripts/run/board/run-board-main.ts +12 -0
  602. package/scripts/run/board/run-board-notes.ts +52 -31
  603. package/scripts/run/board/run-board-now.ts +1 -1
  604. package/scripts/run/board/run-board-operation.ts +15 -33
  605. package/scripts/run/board/run-board-phase.ts +1 -1
  606. package/scripts/run/board/run-board-plan-shared.ts +115 -0
  607. package/scripts/run/board/run-board-plan.ts +55 -3
  608. package/scripts/run/board/run-board-planning.ts +45 -0
  609. package/scripts/run/board/run-board-priority.ts +44 -0
  610. package/scripts/run/board/run-board-process-groups.ts +195 -0
  611. package/scripts/run/board/run-board-read.ts +151 -27
  612. package/scripts/run/board/run-board-reason.ts +235 -51
  613. package/scripts/run/board/run-board-released.ts +35 -0
  614. package/scripts/run/board/run-board-render-checks.ts +39 -5
  615. package/scripts/run/board/run-board-render-condition.ts +96 -0
  616. package/scripts/run/board/run-board-render-drawn.ts +67 -0
  617. package/scripts/run/board/run-board-render-foot.ts +59 -0
  618. package/scripts/run/board/run-board-render-icon.ts +35 -0
  619. package/scripts/run/board/run-board-render-lanes.ts +145 -0
  620. package/scripts/run/board/run-board-render-lead.ts +80 -0
  621. package/scripts/run/board/run-board-render-legend.ts +117 -48
  622. package/scripts/run/board/run-board-render-notes.ts +156 -29
  623. package/scripts/run/board/run-board-render-processes.ts +196 -0
  624. package/scripts/run/board/run-board-render-section.ts +119 -0
  625. package/scripts/run/board/run-board-render-slot.ts +3 -36
  626. package/scripts/run/board/run-board-render-tail.ts +115 -48
  627. package/scripts/run/board/run-board-render-time.ts +56 -0
  628. package/scripts/run/board/run-board-render-title.ts +117 -24
  629. package/scripts/run/board/run-board-render-waits.ts +104 -20
  630. package/scripts/run/board/run-board-render.ts +207 -265
  631. package/scripts/run/board/run-board-roots.ts +54 -0
  632. package/scripts/run/board/run-board-row-yield.ts +9 -4
  633. package/scripts/run/board/run-board-setup.ts +1 -12
  634. package/scripts/run/board/run-board-snapshot.ts +111 -0
  635. package/scripts/run/board/run-board-spin.ts +2 -2
  636. package/scripts/run/board/run-board-state.ts +22 -33
  637. package/scripts/run/board/run-board-status.ts +147 -71
  638. package/scripts/run/board/run-board-thanks-read.ts +2 -2
  639. package/scripts/run/board/run-board-tick.ts +122 -107
  640. package/scripts/run/board/run-board-usage-board.ts +78 -0
  641. package/scripts/run/board/run-board-usage-lanes.ts +113 -0
  642. package/scripts/run/board/run-board-usage-listing.ts +93 -0
  643. package/scripts/run/board/run-board-usage-read.ts +120 -150
  644. package/scripts/run/board/run-board-usage-rusage.ts +19 -7
  645. package/scripts/run/board/run-board-usage-text.ts +139 -51
  646. package/scripts/run/board/run-board-usage-top.ts +102 -0
  647. package/scripts/run/board/run-board-usage.ts +89 -72
  648. package/scripts/run/board/run-board-usual.ts +20 -9
  649. package/scripts/run/carry/run-carry-args.ts +4 -7
  650. package/scripts/run/carry/run-carry-conversation.ts +1 -1
  651. package/scripts/run/carry/run-carry.ts +9 -4
  652. package/scripts/run/cut/run-cut-handoff.ts +2 -2
  653. package/scripts/run/event/run-event-cli.ts +1 -5
  654. package/scripts/run/event/run-event-filed.ts +12 -6
  655. package/scripts/run/event/run-event-follow.ts +2 -3
  656. package/scripts/run/event/run-event-render.ts +6 -10
  657. package/scripts/run/event/run-event-scope.ts +2 -2
  658. package/scripts/run/event/run-event-stream-emit.ts +82 -22
  659. package/scripts/run/event/run-event-stream.ts +34 -8
  660. package/scripts/run/hold/run-hold-adopt.ts +65 -0
  661. package/scripts/run/hold/run-hold-cli.ts +93 -22
  662. package/scripts/run/hold/run-hold-main.ts +12 -0
  663. package/scripts/run/hold/run-hold-member.ts +37 -0
  664. package/scripts/run/hold/run-stop-notify.ts +183 -0
  665. package/scripts/run/merge/run-merge-auth.ts +31 -0
  666. package/scripts/run/merge/run-merge-cli.ts +62 -48
  667. package/scripts/run/merge/run-merge-close.ts +74 -0
  668. package/scripts/run/merge/run-merge-collect.ts +6 -13
  669. package/scripts/run/merge/run-merge-driver.ts +71 -0
  670. package/scripts/run/merge/run-merge-main.ts +12 -0
  671. package/scripts/run/merge/run-merge-outcome.ts +23 -0
  672. package/scripts/run/merge/run-merge-restart.ts +39 -0
  673. package/scripts/run/merge/run-merge-ship.ts +20 -4
  674. package/scripts/run/merge/run-merge-signals.ts +33 -9
  675. package/scripts/run/merge/run-merge-steps.ts +120 -85
  676. package/scripts/run/merge/run-merge.ts +38 -37
  677. package/scripts/run/park/run-park-cli.ts +91 -0
  678. package/scripts/run/park/run-park.ts +88 -0
  679. package/scripts/run/park/run-stalled.ts +68 -0
  680. package/scripts/run/pause/run-pause-cli.ts +73 -0
  681. package/scripts/run/pause/run-pause.ts +251 -0
  682. package/scripts/run/progress/run-progress-cli.ts +4 -12
  683. package/scripts/run/progress/run-progress-clock.ts +1 -1
  684. package/scripts/run/progress/run-progress-config.ts +6 -14
  685. package/scripts/run/progress/run-progress-main.ts +12 -0
  686. package/scripts/run/progress/run-progress.ts +1 -4
  687. package/scripts/run/review/run-review.ts +2 -1
  688. package/scripts/run/run-ending.ts +1 -0
  689. package/scripts/run/run-invocation.ts +5 -6
  690. package/scripts/run/run-liveness-cli.ts +6 -8
  691. package/scripts/run/run-liveness.ts +60 -29
  692. package/scripts/run/run-next.ts +1 -1
  693. package/scripts/run/run-parent-cut-hook.ts +2 -2
  694. package/scripts/run/run-preflight.ts +18 -3
  695. package/scripts/run/run-prep-cli.ts +1 -10
  696. package/scripts/run/run-prep-locate.ts +7 -50
  697. package/scripts/run/run-prep-main.ts +12 -0
  698. package/scripts/run/run-prep.ts +6 -0
  699. package/scripts/run/run-report-cli.ts +101 -13
  700. package/scripts/run/run-report-handoff.ts +114 -0
  701. package/scripts/run/run-step.ts +1 -1
  702. package/scripts/run/run-stranded-detect.ts +13 -0
  703. package/scripts/run/run-watcher-guard-cli.ts +1 -1
  704. package/scripts/run/run-watcher-guard.ts +1 -1
  705. package/scripts/run/ship/run-ship-args.ts +121 -0
  706. package/scripts/run/ship/run-ship-body-draft.ts +110 -0
  707. package/scripts/run/ship/run-ship-cli.ts +63 -140
  708. package/scripts/run/ship/run-ship-detach.ts +19 -8
  709. package/scripts/run/ship/run-ship-infra-retry.ts +59 -0
  710. package/scripts/run/ship/run-ship-next.ts +18 -2
  711. package/scripts/run/ship/run-ship-overlap.ts +42 -5
  712. package/scripts/run/ship/run-ship-place.ts +96 -0
  713. package/scripts/run/ship/run-ship-pre-detach-timed.ts +43 -0
  714. package/scripts/run/ship/run-ship-pre-detach.ts +81 -24
  715. package/scripts/run/ship/run-ship-preflight.ts +137 -32
  716. package/scripts/run/ship/run-ship-probe.ts +11 -3
  717. package/scripts/run/ship/run-ship-relaunch-cap.ts +70 -0
  718. package/scripts/run/ship/run-ship-removed-rows.ts +61 -0
  719. package/scripts/run/ship/run-ship-return.ts +107 -23
  720. package/scripts/run/ship/run-ship-review-steps.ts +105 -151
  721. package/scripts/run/ship/run-ship-review.ts +73 -6
  722. package/scripts/run/ship/run-ship-reviewer.ts +207 -0
  723. package/scripts/run/ship/run-ship-stage.ts +55 -6
  724. package/scripts/run/ship/run-ship-steps.ts +46 -15
  725. package/scripts/run/ship/run-ship-stop-cause.ts +135 -0
  726. package/scripts/run/ship/run-ship-stop-text.ts +11 -6
  727. package/scripts/run/ship/run-ship-sync.ts +43 -6
  728. package/scripts/run/ship/run-ship.ts +30 -2
  729. package/scripts/run/tidy/run-tidy-cli.ts +0 -4
  730. package/scripts/run/tidy/run-tidy-lanes.ts +3 -0
  731. package/scripts/run/tidy/run-tidy-main.ts +8 -0
  732. package/scripts/run/wake/run-wake-cli.ts +119 -100
  733. package/scripts/run/wake/run-wake-code.ts +83 -0
  734. package/scripts/run/wake/run-wake-driver.ts +19 -8
  735. package/scripts/run/wake/run-wake-loop.ts +34 -3
  736. package/scripts/run/wake/run-wake-main.ts +13 -0
  737. package/scripts/run/wake/run-wake-ports.ts +90 -0
  738. package/scripts/run/wake/run-wake-takeover.ts +66 -0
  739. package/scripts/run/wake/run-wake.ts +2 -1
  740. package/scripts/safe-chain/pack-hook.ts +2 -2
  741. package/scripts/safe-chain/preinstall-command.ts +2 -1
  742. package/scripts/safe-chain/project-config.ts +3 -9
  743. package/scripts/security/security-audit-main.ts +8 -0
  744. package/scripts/security/security-audit-provision-logic.ts +0 -11
  745. package/scripts/security/security-audit-provision-main.ts +12 -0
  746. package/scripts/security/security-audit-provision.ts +11 -26
  747. package/scripts/security/security-audit.ts +6 -7
  748. package/scripts/self-sync-guard/self-sync-guard-logic.ts +6 -13
  749. package/scripts/split/split-assess-cli.ts +2 -2
  750. package/scripts/split/split-assess.ts +15 -0
  751. package/scripts/split/split-measure.ts +65 -0
  752. package/scripts/sync/claude-settings-merge.ts +8 -15
  753. package/scripts/sync/directory-copy-guard.ts +4 -9
  754. package/scripts/sync/file-content.ts +78 -8
  755. package/scripts/sync/sync-ai-files.ts +3 -5
  756. package/scripts/sync/sync-configs.ts +11 -23
  757. package/scripts/sync/sync-hook-safety.ts +4 -10
  758. package/scripts/sync/sync-main.ts +11 -0
  759. package/scripts/sync/sync.ts +25 -37
  760. package/scripts/test/test-declared-changed.ts +2 -2
  761. package/scripts/test/test-declared.ts +1 -1
  762. package/scripts/test/test-e2e-guard.ts +25 -1
  763. package/scripts/test/test-e2e-stamp.ts +38 -0
  764. package/scripts/test/test-pinned-logic.ts +145 -0
  765. package/scripts/test/test-pinned-main.ts +78 -0
  766. package/scripts/test/test-pinned.ts +100 -0
  767. package/scripts/test/test-read-map.ts +264 -0
  768. package/scripts/test/test-read-recording.ts +91 -0
  769. package/scripts/test/test-read-trace.ts +148 -0
  770. package/scripts/test/test-red-main.ts +12 -0
  771. package/scripts/test/test-red.ts +12 -30
  772. package/scripts/test/test-related-main.ts +18 -0
  773. package/scripts/test/test-related-record.ts +119 -0
  774. package/scripts/test/test-related-scope.ts +229 -43
  775. package/scripts/test/test-related.ts +300 -22
  776. package/scripts/test/test-unit-guard-main.ts +15 -0
  777. package/scripts/test/test-unit-guard.ts +42 -24
  778. package/scripts/test/unit-count-file.ts +37 -0
  779. package/scripts/test/unit-run-marker.ts +162 -0
  780. package/scripts/test/unit-setup-files.ts +51 -0
  781. package/scripts/test/unit-worker-share.ts +61 -149
  782. package/scripts/test/whole-suite-files.ts +63 -0
  783. package/scripts/time-runtime/time-background.ts +20 -2
  784. package/scripts/time-runtime/time-bundles.ts +4 -3
  785. package/scripts/time-runtime/time-density-hook.ts +8 -6
  786. package/scripts/time-runtime/time-followup-stage.ts +1 -3
  787. package/scripts/time-runtime/time-format.ts +5 -28
  788. package/scripts/time-runtime/time-markers.ts +10 -1
  789. package/scripts/time-runtime/time-shell.ts +97 -10
  790. package/scripts/time-runtime/time-transcript-line.ts +49 -62
  791. package/scripts/uninstall/uninstall.ts +1 -1
  792. package/scripts/version/bump-version-main.ts +12 -0
  793. package/scripts/version/bump-version.ts +25 -25
  794. package/scripts/version/effective-upstream.ts +6 -12
  795. package/scripts/version/latest-corepack.ts +17 -32
  796. package/scripts/version/latest-if-required-cli.ts +93 -0
  797. package/scripts/version/latest-lane-guard-main.ts +8 -0
  798. package/scripts/version/latest-lane-guard.ts +0 -4
  799. package/scripts/version/latest-scope-cli.ts +0 -9
  800. package/scripts/version/latest-scope-main.ts +12 -0
  801. package/scripts/version/latest-update.ts +5 -5
  802. package/scripts/version/npm-registry.ts +44 -6
  803. package/scripts/version/publishable-range-check.ts +5 -16
  804. package/scripts/version/release-age.ts +1 -1
  805. package/scripts/version/release-hold.ts +1 -1
  806. package/scripts/version/release-window.ts +38 -0
  807. package/scripts/version/running-binary.ts +1 -1
  808. package/scripts/version/safe-chain-version-update.ts +3 -8
  809. package/scripts/version/version-targets.ts +6 -28
  810. package/templates/dependabot.yml +29 -0
  811. package/templates/gitignore +4 -1
  812. package/templates/pnpm-workspace.basic.yaml +1 -1
  813. package/templates/sonar-project.properties +3 -2
  814. package/templates/workflows/ci.yml +12 -4
  815. package/templates/workflows/github-release.yml +4 -0
  816. package/tsconfig.sonar.json +1 -1
  817. package/.ncurc.json +0 -3
  818. package/dist/hooks/batch-guard.js +0 -29
  819. package/dist/hooks/chunk-4KKD2UTK.js +0 -66
  820. package/dist/hooks/chunk-6TS2JD6D.js +0 -237
  821. package/dist/hooks/chunk-7DSBJVFH.js +0 -50
  822. package/dist/hooks/chunk-A65Y4YOR.js +0 -79
  823. package/dist/hooks/chunk-CDY4NFQG.js +0 -15
  824. package/dist/hooks/chunk-EFXE6C37.js +0 -81
  825. package/dist/hooks/chunk-GP4IEC4O.js +0 -20
  826. package/dist/hooks/chunk-JP45SOCJ.js +0 -56
  827. package/dist/hooks/chunk-LAOV7NLM.js +0 -45
  828. package/dist/hooks/chunk-M4HGZV7U.js +0 -83
  829. package/dist/hooks/chunk-PF2NZL2A.js +0 -131
  830. package/dist/hooks/chunk-PTICX4OL.js +0 -358
  831. package/dist/hooks/chunk-RT27QRJW.js +0 -6247
  832. package/dist/hooks/chunk-SYOTDYCI.js +0 -3533
  833. package/dist/hooks/chunk-UPUZF3AN.js +0 -279
  834. package/dist/hooks/chunk-WK6SMBIC.js +0 -3180
  835. package/dist/hooks/duplicate-read-guard.js +0 -30
  836. package/dist/hooks/investigation-guard.js +0 -29
  837. package/scripts/backlog/backlog-stalled-cli.ts +0 -30
  838. package/scripts/cost-runtime/cost-format.ts +0 -29
  839. package/scripts/init/basic-path-migration.ts +0 -24
  840. package/scripts/issue/issue-backlinks-cli.ts +0 -93
  841. package/scripts/josh/josh-commands-guard.ts +0 -38
  842. package/scripts/josh/josh-usage-automation.ts +0 -121
  843. package/scripts/josh/josh-usage-backlog.ts +0 -180
  844. package/scripts/josh/josh-usage-developer.ts +0 -230
  845. package/scripts/josh/josh-usage-hooks.ts +0 -38
  846. package/scripts/josh/josh-usage-issue.ts +0 -205
  847. package/scripts/josh/josh-usage-review.ts +0 -101
  848. package/scripts/josh/josh-usage-run.ts +0 -252
  849. package/scripts/josh/josh-usage-session.ts +0 -238
  850. package/scripts/josh/josh-usage-workflow.ts +0 -212
  851. package/scripts/lint/cross-file-recheck.ts +0 -155
  852. package/scripts/registry-migration/migrate-logic.ts +0 -237
  853. package/scripts/registry-migration/migrate.ts +0 -292
  854. package/scripts/registry-migration/user-npmrc.ts +0 -15
  855. package/scripts/rules/rule-guard.ts +0 -23
  856. package/scripts/rules/rule-registry-rows.ts +0 -292
  857. package/scripts/rules/rule-registry.ts +0 -112
  858. package/scripts/run/run-stranded-cli.ts +0 -27
@@ -1,3180 +0,0 @@
1
- import {
2
- error_text
3
- } from "./chunk-CDY4NFQG.js";
4
- import {
5
- agent_role_profile,
6
- agent_session_role
7
- } from "./chunk-UPUZF3AN.js";
8
- import {
9
- lane_child_marker
10
- } from "./chunk-LAOV7NLM.js";
11
- import {
12
- ENV_FILE_NAME,
13
- GIT_LOCATION_VARIABLES,
14
- LANE_SEAT_KEY,
15
- PORCELAIN_FLAG,
16
- PORT_SEED_KEY,
17
- agent_session_environment,
18
- changed_paths,
19
- file_reader,
20
- git_command,
21
- git_location_environment,
22
- git_spawn,
23
- git_utilities,
24
- has_timed_out,
25
- issue_number_shape,
26
- json_value,
27
- lane_paths,
28
- ports,
29
- process_identity,
30
- process_owner_schema,
31
- rest_comment_schema,
32
- run_carry
33
- } from "./chunk-APUO6U4J.js";
34
- import {
35
- COMMAND_TIMEOUT_MS,
36
- INSTALL_TIMEOUT_MS,
37
- PLATFORM_TEMP_ROOT,
38
- PROBE_TIMEOUT_MS,
39
- SUITE_TIMEOUT_MS,
40
- stamp_file
41
- } from "./chunk-DGT54IH5.js";
42
-
43
- // scripts/discovery/repo-discovery.ts
44
- import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
45
- import path from "node:path";
46
-
47
- // scripts/discovery/repo-origin.ts
48
- var GITHUB_HOST = "github.com";
49
- var SSH_ALIAS_PATTERN = /^github(?:-\w+)*$/u;
50
- var GIT_SUFFIX = ".git";
51
- var PATH_SEPARATOR = "/";
52
- var USER_SEPARATOR = "@";
53
- var HOST_SEPARATOR = ":";
54
- var OWNER_INDEX = 0;
55
- var REPO_INDEX = 1;
56
- var REPO_PATH_SEGMENTS = 2;
57
- var NOT_FOUND = -1;
58
- var SECTION_PREFIX = "[";
59
- var ORIGIN_SECTION = /^\[remote\s+"origin"\]$/u;
60
- var REMOTE_SECTION = /^\[remote\s+"[^"]+"\]$/u;
61
- var URL_KEY = "url";
62
- function is_github_hostname(host) {
63
- return host.toLowerCase() === GITHUB_HOST;
64
- }
65
- function is_github_ssh_host(host) {
66
- const normalized = host.toLowerCase();
67
- return is_github_hostname(normalized) || SSH_ALIAS_PATTERN.test(normalized);
68
- }
69
- function strip_git_suffix(name) {
70
- return name.endsWith(GIT_SUFFIX) ? name.slice(0, -GIT_SUFFIX.length) : name;
71
- }
72
- function to_identity(repository_path) {
73
- const segments = repository_path.split(PATH_SEPARATOR).filter((segment) => segment !== "");
74
- if (segments.length !== REPO_PATH_SEGMENTS) return void 0;
75
- const owner = segments[OWNER_INDEX] ?? "";
76
- const repo = strip_git_suffix(segments[REPO_INDEX] ?? "");
77
- return repo === "" ? void 0 : { owner, repo };
78
- }
79
- function parse_scp_like(url) {
80
- const user_end = url.indexOf(USER_SEPARATOR);
81
- const authority = user_end === NOT_FOUND ? url : url.slice(user_end + 1);
82
- const host_end = authority.indexOf(HOST_SEPARATOR);
83
- if (host_end === NOT_FOUND || !is_github_ssh_host(authority.slice(0, host_end))) return void 0;
84
- return to_identity(authority.slice(host_end + 1));
85
- }
86
- function parse_url_like(url) {
87
- try {
88
- const parsed = new URL(url);
89
- return is_github_hostname(parsed.hostname) ? to_identity(parsed.pathname) : void 0;
90
- } catch {
91
- return void 0;
92
- }
93
- }
94
- function parse_origin_url(url) {
95
- const trimmed = url.trim();
96
- if (trimmed === "") return void 0;
97
- return parse_url_like(trimmed) ?? parse_scp_like(trimmed);
98
- }
99
- function is_section_header(line) {
100
- return line.startsWith(SECTION_PREFIX);
101
- }
102
- function origin_section_lines(lines) {
103
- const start = lines.findIndex((line) => ORIGIN_SECTION.test(line));
104
- if (start === NOT_FOUND) return [];
105
- const rest = lines.slice(start + 1);
106
- const end = rest.findIndex((line) => is_section_header(line));
107
- return end === NOT_FOUND ? rest : rest.slice(0, end);
108
- }
109
- function url_value(line) {
110
- const separator = line.indexOf("=");
111
- if (separator === NOT_FOUND || line.slice(0, separator).trim() !== URL_KEY) return void 0;
112
- return line.slice(separator + 1).trim();
113
- }
114
- function parse_origin_from_config(content) {
115
- const lines = content.split("\n").map((line) => line.trim());
116
- return origin_section_lines(lines).map((line) => url_value(line)).find((url) => url !== void 0);
117
- }
118
- function section_groups(lines) {
119
- const groups = [];
120
- for (const line of lines) {
121
- if (is_section_header(line)) groups.push([line]);
122
- else groups.at(-1)?.push(line);
123
- }
124
- return groups;
125
- }
126
- function parse_remote_urls_from_config(content) {
127
- const lines = content.split("\n").map((line) => line.trim());
128
- return section_groups(lines).filter((group) => REMOTE_SECTION.test(group[0] ?? "")).flatMap((group) => group.map((line) => url_value(line))).filter((url) => url !== void 0);
129
- }
130
- function format_identity(identity) {
131
- return `${identity.owner}${PATH_SEPARATOR}${identity.repo}`.toLowerCase();
132
- }
133
- var repo_origin = {
134
- GITHUB_HOST,
135
- is_github_hostname,
136
- is_github_ssh_host,
137
- parse_origin_from_config,
138
- parse_origin_url,
139
- parse_remote_urls_from_config,
140
- format_identity
141
- };
142
-
143
- // scripts/discovery/repo-map-logic.ts
144
- var OVERRIDE_ENTRY_SEPARATOR = ",";
145
- var OVERRIDE_PAIR_SEPARATOR = "=";
146
- var OVERRIDE_PAIR_PARTS = 2;
147
- var KEY_INDEX = 0;
148
- var PATH_INDEX = 1;
149
- function is_same_owner(identity, current_owner) {
150
- return identity.owner.toLowerCase() === current_owner.toLowerCase();
151
- }
152
- function add_entry(target, origin_url, repository_path, current_owner) {
153
- if (origin_url === void 0) return;
154
- const identity = repo_origin.parse_origin_url(origin_url);
155
- if (identity === void 0 || !is_same_owner(identity, current_owner)) return;
156
- target.set(repo_origin.format_identity(identity), repository_path);
157
- }
158
- function parse_override_entry(entry) {
159
- const parts = entry.split(OVERRIDE_PAIR_SEPARATOR).map((part) => part.trim());
160
- if (parts.length !== OVERRIDE_PAIR_PARTS) return void 0;
161
- const key = parts[KEY_INDEX] ?? "";
162
- const repository_path = parts[PATH_INDEX] ?? "";
163
- if (repository_path === "") return void 0;
164
- return { path: repository_path, origin_url: `https://${repo_origin.GITHUB_HOST}/${key}` };
165
- }
166
- function parse_overrides(raw) {
167
- if (raw === void 0) return [];
168
- return raw.split(OVERRIDE_ENTRY_SEPARATOR).map((entry) => parse_override_entry(entry)).filter((entry) => entry !== void 0);
169
- }
170
- function build_repository_map(discovered, current_owner, override_value) {
171
- const result = /* @__PURE__ */ new Map();
172
- for (const entry of discovered) add_entry(result, entry.origin_url, entry.path, current_owner);
173
- for (const entry of parse_overrides(override_value)) {
174
- add_entry(result, entry.origin_url, entry.path, current_owner);
175
- }
176
- return result;
177
- }
178
- var repo_map_logic = {
179
- is_same_owner,
180
- build_repository_map
181
- };
182
-
183
- // scripts/discovery/repo-discovery.ts
184
- var GIT_DIRECTORY = ".git";
185
- var GIT_CONFIG = "config";
186
- var GITDIR_PREFIX = "gitdir:";
187
- var COMMON_DIRECTORY_FILE = "commondir";
188
- var OVERRIDE_ENV_KEY = "JOSH_REPO_PATHS";
189
- function resolve_common_directory(git_directory) {
190
- const pointer = path.join(git_directory, COMMON_DIRECTORY_FILE);
191
- if (!existsSync(pointer)) return git_directory;
192
- try {
193
- return path.resolve(git_directory, readFileSync(pointer, "utf8").trim());
194
- } catch {
195
- return git_directory;
196
- }
197
- }
198
- function follow_git_file(repository_path, git_file) {
199
- const pointer = readFileSync(git_file, "utf8").trim();
200
- if (!pointer.startsWith(GITDIR_PREFIX)) return void 0;
201
- return path.resolve(repository_path, pointer.slice(GITDIR_PREFIX.length).trim());
202
- }
203
- function resolve_git_directory(repository_path) {
204
- const candidate = path.join(repository_path, GIT_DIRECTORY);
205
- if (!existsSync(candidate)) return void 0;
206
- try {
207
- if (statSync(candidate).isDirectory()) return candidate;
208
- const linked = follow_git_file(repository_path, candidate);
209
- return linked === void 0 ? void 0 : resolve_common_directory(linked);
210
- } catch {
211
- return void 0;
212
- }
213
- }
214
- function read_config(repository_path) {
215
- const git_directory = resolve_git_directory(repository_path);
216
- if (git_directory === void 0) return void 0;
217
- try {
218
- return readFileSync(path.join(git_directory, GIT_CONFIG), "utf8");
219
- } catch {
220
- return void 0;
221
- }
222
- }
223
- function read_origin_url(repository_path) {
224
- const config = read_config(repository_path);
225
- return config === void 0 ? void 0 : repo_origin.parse_origin_from_config(config);
226
- }
227
- function read_remote_urls(repository_path) {
228
- const config = read_config(repository_path);
229
- return config === void 0 ? [] : repo_origin.parse_remote_urls_from_config(config);
230
- }
231
- function sibling_directories(parent) {
232
- try {
233
- return readdirSync(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => path.join(parent, entry.name)).toSorted((left, right) => left.localeCompare(right));
234
- } catch {
235
- return [];
236
- }
237
- }
238
- function scan_siblings(parent) {
239
- return sibling_directories(parent).map((repository_path) => ({
240
- path: repository_path,
241
- origin_url: read_origin_url(repository_path)
242
- }));
243
- }
244
- function resolve_current_owner(repository_path) {
245
- const origin_url = read_origin_url(repository_path);
246
- if (origin_url === void 0) return void 0;
247
- return repo_origin.parse_origin_url(origin_url)?.owner;
248
- }
249
- function main_worktree(repository_path) {
250
- const git_directory = resolve_git_directory(repository_path);
251
- if (git_directory === void 0 || path.basename(git_directory) !== GIT_DIRECTORY) {
252
- return repository_path;
253
- }
254
- return path.dirname(git_directory);
255
- }
256
- function discover_repositories(repository_path, environment3 = process.env) {
257
- const main = main_worktree(repository_path);
258
- const current_owner = resolve_current_owner(main);
259
- if (current_owner === void 0) return /* @__PURE__ */ new Map();
260
- return repo_map_logic.build_repository_map(
261
- scan_siblings(path.dirname(main)),
262
- current_owner,
263
- environment3[OVERRIDE_ENV_KEY]
264
- );
265
- }
266
- var repo_discovery = {
267
- OVERRIDE_ENV_KEY,
268
- main_worktree,
269
- read_origin_url,
270
- read_remote_urls,
271
- resolve_current_owner,
272
- scan_siblings,
273
- discover_repositories
274
- };
275
-
276
- // scripts/issue/issue-cite.ts
277
- var GITHUB_URL_PREFIX = "https://github.com/";
278
- var ISSUE_PATH = "/issues/";
279
- var SUMMARY_SEPARATOR = " \u2014 ";
280
- var REPO_QUALIFIED = /^([^\s/#]+\/[^\s/#]+)#(\d+)$/u;
281
- var BARE_NUMBER = /^#?(\d+)$/u;
282
- function plain(number, repo = "") {
283
- return `${repo}#${String(number)}`;
284
- }
285
- function issue_url(slug, number) {
286
- return `${GITHUB_URL_PREFIX}${slug}${ISSUE_PATH}${number}`;
287
- }
288
- function citation_line(slug, number, summary) {
289
- return `[${plain(number)}](${issue_url(slug, number)})${SUMMARY_SEPARATOR}${summary}`;
290
- }
291
- function reference(slug, number, title) {
292
- if (slug === void 0) return plain(number);
293
- return title === void 0 ? `[${plain(number)}](${issue_url(slug, number)})` : citation_line(slug, number, title);
294
- }
295
- function citer(slug, titles) {
296
- return function cite(number) {
297
- return reference(slug, number, titles.get(number));
298
- };
299
- }
300
- function qualified_target(token) {
301
- const match = REPO_QUALIFIED.exec(token);
302
- if (match === null) return void 0;
303
- const [, repo = "", number = ""] = match;
304
- return { number, repo };
305
- }
306
- function bare_target(token, default_repo) {
307
- const match = BARE_NUMBER.exec(token);
308
- if (match === null) return void 0;
309
- const [, number = ""] = match;
310
- return { number, repo: default_repo };
311
- }
312
- function parse_target(token, default_repo) {
313
- return qualified_target(token) ?? bare_target(token, default_repo);
314
- }
315
- function label(target) {
316
- return plain(target.number, target.repo);
317
- }
318
- function missing_line(target) {
319
- return `\u2716 ${label(target)}: issue does not resolve \u2014 check the number and the repository`;
320
- }
321
- function unreadable_line(target) {
322
- return `\u2716 ${label(target)}: could not be read \u2014 a rate limit, expired auth, or a dropped connection`;
323
- }
324
- function no_repo_line(target) {
325
- return `\u2716 ${label(target)}: could not read this repository \u2014 check gh auth and the origin remote`;
326
- }
327
- var issue_cite = {
328
- citation_line,
329
- citer,
330
- issue_url,
331
- missing_line,
332
- no_repo_line,
333
- parse_target,
334
- plain,
335
- reference,
336
- unreadable_line
337
- };
338
-
339
- // scripts/rules/issue-citation.ts
340
- var ISSUE_NUMBER = /#\d+/gu;
341
- var REFERENCE_BOUNDARY = /[\s#()[\]<>|]/u;
342
- var OWNER_REPO = /^[^\s/#]+\/[^\s/#]+$/u;
343
- var MARKDOWN_LINK = /\[[^[\]]*\]\([^()]*\)/gu;
344
- var NUMBER_CONTINUATION = /^(?:\w|-[a-z])/iu;
345
- var CONTINUATION_WIDTH = 2;
346
- var GLUED_LEAD = /[&./]/u;
347
- var FENCE_MARKER = /^\s*(?:`{3,}|~{3,})/u;
348
- var QUOTE_LINE = /^\s*>/u;
349
- var PR_PREFIX = /\b(?:pr|pull request)\s*$/iu;
350
- var BACKTICK_PAIR = 2;
351
- function link_covers(link, index) {
352
- const start = link.index ?? 0;
353
- return index >= start && index < start + link[0].length;
354
- }
355
- function is_linked_at(line, index) {
356
- for (const link of line.matchAll(MARKDOWN_LINK)) {
357
- if (link_covers(link, index)) return true;
358
- }
359
- return false;
360
- }
361
- function lead_token(message, hash_index) {
362
- let start = hash_index;
363
- while (start > 0 && !REFERENCE_BOUNDARY.test(message.charAt(start - 1))) start -= 1;
364
- return message.slice(start, hash_index);
365
- }
366
- function repo_prefix(message, hash_index) {
367
- const token = lead_token(message, hash_index);
368
- return OWNER_REPO.test(token) ? token : "";
369
- }
370
- function is_inline_code_at(line, index) {
371
- const backticks = line.slice(0, index).split("`").length - 1;
372
- return backticks % BACKTICK_PAIR === 1;
373
- }
374
- function is_bare_at(line, index) {
375
- if (is_linked_at(line, index) || is_inline_code_at(line, index)) return false;
376
- return !PR_PREFIX.test(line.slice(0, index));
377
- }
378
- function is_glued(line, reference2) {
379
- const end = reference2.index + reference2.text.length;
380
- if (NUMBER_CONTINUATION.test(line.slice(end, end + CONTINUATION_WIDTH))) return true;
381
- return reference2.prefix === "" && GLUED_LEAD.test(lead_token(line, reference2.index));
382
- }
383
- function line_references(line) {
384
- const references = [];
385
- for (const match of line.matchAll(ISSUE_NUMBER)) {
386
- const reference2 = { index: match.index, prefix: repo_prefix(line, match.index), text: match[0] };
387
- if (!is_glued(line, reference2) && is_bare_at(line, match.index)) references.push(reference2);
388
- }
389
- return references;
390
- }
391
- function collect_line_references(line, found) {
392
- for (const reference2 of line_references(line)) found.push(`${reference2.prefix}${reference2.text}`);
393
- }
394
- function lines_outside_fences(message) {
395
- const lines = [];
396
- let is_in_fence = false;
397
- for (const line of message.split("\n")) {
398
- if (FENCE_MARKER.test(line)) is_in_fence = !is_in_fence;
399
- else if (!is_in_fence) lines.push(line);
400
- }
401
- return lines;
402
- }
403
- function prose_lines(message) {
404
- return lines_outside_fences(message).filter((line) => !QUOTE_LINE.test(line));
405
- }
406
- function bare_references(message) {
407
- const found = [];
408
- for (const line of prose_lines(message)) collect_line_references(line, found);
409
- return [...new Set(found)];
410
- }
411
- function prompt_references(prompt) {
412
- const found = /* @__PURE__ */ new Set();
413
- for (const match of prompt.matchAll(ISSUE_NUMBER)) {
414
- found.add(repo_prefix(prompt, match.index) + match[0]);
415
- }
416
- return found;
417
- }
418
- function unquoted_references(message, prompt) {
419
- const quoted2 = prompt_references(prompt);
420
- return bare_references(message).filter((reference2) => !quoted2.has(reference2));
421
- }
422
- function has_bare_reference(message) {
423
- return bare_references(message).length > 0;
424
- }
425
- function cite_argument(reference2) {
426
- return reference2.startsWith("#") ? reference2.slice(1) : reference2;
427
- }
428
- function cite_arguments(references) {
429
- return references.map((reference2) => cite_argument(reference2));
430
- }
431
- function reference_link(reference2, default_slug) {
432
- const slug = reference2.prefix === "" ? default_slug : reference2.prefix;
433
- const number = reference2.text.slice(1);
434
- return `[${reference2.prefix}${reference2.text}](${issue_cite.issue_url(slug, number)})`;
435
- }
436
- function linkify_line(line, slug) {
437
- let result = "";
438
- let cursor = 0;
439
- for (const reference2 of line_references(line)) {
440
- const start = reference2.index - reference2.prefix.length;
441
- result += line.slice(cursor, start) + reference_link(reference2, slug);
442
- cursor = reference2.index + reference2.text.length;
443
- }
444
- return result + line.slice(cursor);
445
- }
446
- function rewrite_line(line, slug, is_in_fence) {
447
- if (is_in_fence || FENCE_MARKER.test(line) || QUOTE_LINE.test(line)) return line;
448
- return linkify_line(line, slug);
449
- }
450
- function linkify(message, slug) {
451
- const out = [];
452
- let is_in_fence = false;
453
- for (const line of message.split("\n")) {
454
- if (FENCE_MARKER.test(line)) is_in_fence = !is_in_fence;
455
- out.push(rewrite_line(line, slug, is_in_fence));
456
- }
457
- return out.join("\n");
458
- }
459
- var issue_citation = {
460
- bare_references,
461
- cite_arguments,
462
- has_bare_reference,
463
- linkify,
464
- prose_lines,
465
- unquoted_references
466
- };
467
-
468
- // scripts/issue/session-cite.ts
469
- function session_repo() {
470
- const url = repo_discovery.read_origin_url(process.cwd());
471
- const identity = url === void 0 ? void 0 : repo_origin.parse_origin_url(url);
472
- return identity === void 0 ? void 0 : `${identity.owner}/${identity.repo}`;
473
- }
474
- function issue(number, title, repo = session_repo()) {
475
- return issue_cite.reference(repo, String(number), title);
476
- }
477
- function text(message) {
478
- const repo = session_repo();
479
- return repo === void 0 ? message : issue_citation.linkify(message, repo);
480
- }
481
- var session_cite = {
482
- issue,
483
- session_repo,
484
- text
485
- };
486
-
487
- // scripts/josh/stamp-record.ts
488
- var NONE_READ = { kind: "none" };
489
- var UNREADABLE_READ = { kind: "unreadable" };
490
- function is_older_than(iso, max_age_ms, now) {
491
- const at = Date.parse(iso);
492
- if (Number.isNaN(at)) return true;
493
- return now.getTime() - at > max_age_ms;
494
- }
495
- function classify(raw, spec, now) {
496
- if (raw === void 0) return NONE_READ;
497
- const record = spec.parse(raw);
498
- if (record === void 0) return UNREADABLE_READ;
499
- const is_expired2 = is_older_than(spec.timestamp_of(record), spec.max_age_ms, now);
500
- return { kind: is_expired2 ? "expired" : "carried", record };
501
- }
502
- var stamp_record = { classify, is_older_than };
503
-
504
- // scripts/run/hold/run-hold.ts
505
- import { z } from "zod";
506
- var HOLD_PREFIX = "josh-run-hold-";
507
- var UNNUMBERED_ISSUE = "new";
508
- var HOLD_MAX_AGE_HOURS = 8;
509
- var MILLISECONDS_PER_HOUR = 36e5;
510
- var HOLD_MAX_AGE_MS = HOLD_MAX_AGE_HOURS * MILLISECONDS_PER_HOUR;
511
- var RELEASE_COMMAND = "pnpm josh run:release";
512
- var FORCE_RELEASE_COMMAND = `${RELEASE_COMMAND} --force`;
513
- var NOT_IDLE = 'that is not "nothing is running here"';
514
- var FREE_READ = { kind: "free" };
515
- var UNREADABLE_READ2 = { kind: "unreadable" };
516
- function hold_path(git_directory) {
517
- return stamp_file.stamp_path(HOLD_PREFIX, git_directory);
518
- }
519
- async function worktree_directory() {
520
- const directories2 = await git_command.git_directories();
521
- return directories2[0];
522
- }
523
- async function is_linked_worktree() {
524
- const directories2 = await git_command.git_directories();
525
- return directories2[0] !== void 0 && directories2[0] !== directories2[1];
526
- }
527
- var run_hold_schema = z.object({
528
- issue: z.string(),
529
- taken_at: z.string(),
530
- pid: z.number(),
531
- is_fullrun: z.boolean().optional(),
532
- is_halfrun_stop: z.boolean().optional(),
533
- prrun_stop_head: z.string().optional(),
534
- owner_pid: z.number().optional(),
535
- owner_start: z.string().optional(),
536
- notified_at: z.string().optional()
537
- });
538
- function parse_hold(raw) {
539
- return json_value.parse_with(raw, run_hold_schema);
540
- }
541
- function is_expired(hold, now) {
542
- return stamp_record.is_older_than(hold.taken_at, HOLD_MAX_AGE_MS, now);
543
- }
544
- function is_stop_marked(hold) {
545
- return hold.is_halfrun_stop === true || hold.prrun_stop_head !== void 0;
546
- }
547
- function is_owner_gone(hold) {
548
- if (is_stop_marked(hold) || hold.owner_pid === void 0) return false;
549
- return process_identity.is_same_process(hold.owner_pid, hold.owner_start) === false;
550
- }
551
- function is_stale(hold, now) {
552
- return is_expired(hold, now) || is_owner_gone(hold);
553
- }
554
- function classify2(raw, now) {
555
- if (raw === void 0) return FREE_READ;
556
- const hold = parse_hold(raw);
557
- if (hold === void 0) return UNREADABLE_READ2;
558
- return { kind: is_stale(hold, now) ? "stale" : "held", hold };
559
- }
560
- function read_hold(target, now = /* @__PURE__ */ new Date()) {
561
- return classify2(stamp_file.read_stamp_text(target), now);
562
- }
563
- function session_owner(environment3 = process.env) {
564
- const pid = Number(environment3[agent_session_environment.AGENT_PID_KEY]);
565
- if (!Number.isSafeInteger(pid) || pid <= 0) return {};
566
- return { owner_pid: pid, owner_start: process_identity.read_start(pid) };
567
- }
568
- function build_hold(issue2, now, is_fullrun) {
569
- return { issue: issue2, taken_at: now.toISOString(), pid: process.pid, is_fullrun, ...session_owner() };
570
- }
571
- function write_hold(target, issue2, now = /* @__PURE__ */ new Date()) {
572
- const hold = build_hold(issue2, now);
573
- stamp_file.write_stamp(target, hold);
574
- return hold;
575
- }
576
- function create_hold(target, issue2, now = /* @__PURE__ */ new Date(), is_fullrun) {
577
- return stamp_file.create_stamp(target, build_hold(issue2, now, is_fullrun));
578
- }
579
- var HALFRUN_STOP_FIELDS = { is_halfrun_stop: true };
580
- function create_stop_hold(target, issue2, mark, now = /* @__PURE__ */ new Date()) {
581
- return stamp_file.create_stamp(target, { ...build_hold(issue2, now), ...mark });
582
- }
583
- function create_halfrun_stop_hold(target, issue2, now = /* @__PURE__ */ new Date()) {
584
- return create_stop_hold(target, issue2, HALFRUN_STOP_FIELDS, now);
585
- }
586
- async function is_tree_dirty(directory) {
587
- try {
588
- const status = await git_command.status(directory);
589
- return status.trim() !== "";
590
- } catch (error) {
591
- error_text.trace_swallowed("run_hold.is_tree_dirty", error);
592
- return true;
593
- }
594
- }
595
- function release_hold(target) {
596
- stamp_file.remove_stamp(target);
597
- }
598
- function describe_holder(hold) {
599
- const holder = hold.issue === UNNUMBERED_ISSUE ? "an unnumbered run" : session_cite.issue(hold.issue);
600
- return `${holder}, recorded ${hold.taken_at} (pid ${String(hold.owner_pid ?? hold.pid)})`;
601
- }
602
- function own_release_command(issue2) {
603
- return issue2 === UNNUMBERED_ISSUE ? RELEASE_COMMAND : `${RELEASE_COMMAND} ${issue2}`;
604
- }
605
- function is_own_hold(hold, claimant) {
606
- return hold.issue === claimant;
607
- }
608
- function is_reentry(hold, claimant) {
609
- return claimant !== UNNUMBERED_ISSUE && is_own_hold(hold, claimant);
610
- }
611
- function held_message(hold) {
612
- return `This working tree is already held by ${describe_holder(hold)}. One run at a time per working tree: a second run here commits its files onto the other run's branch. If that record is stale, run \`${FORCE_RELEASE_COMMAND}\` in this working tree \u2014 it removes a record this run did not write, so be sure the run that did has ended \u2014 and ask again.`;
613
- }
614
- function foreign_release_message(hold) {
615
- return `This working tree is held by ${describe_holder(hold)}, and this release did not claim it \u2014 nothing was removed. Release it as that run with \`${own_release_command(hold.issue)}\`, or, once you are sure it has ended, remove the record with \`${FORCE_RELEASE_COMMAND}\`.`;
616
- }
617
- function forced_release_message(hold) {
618
- return `Forced: removed the run record held by ${describe_holder(hold)}.`;
619
- }
620
- function unreadable_message() {
621
- return `This working tree's run record could not be read \u2014 ${NOT_IDLE}. Run \`${FORCE_RELEASE_COMMAND}\` in this working tree to clear it, then ask again.`;
622
- }
623
- function stale_message(hold) {
624
- const why = is_owner_gone(hold) ? "the session that wrote it has ended" : `older than ${String(HOLD_MAX_AGE_HOURS)} hours`;
625
- return `Replaced a stale run record held by ${describe_holder(hold)}: ${why}, so the run that wrote it has ended without releasing it.`;
626
- }
627
- function uncommitted_message(hold) {
628
- return `This working tree still has uncommitted changes, and its run record \u2014 held by ${describe_holder(hold)} \u2014 has expired or outlived its session. That is a run which stopped for a person rather than one that finished, so the tree is not free: commit or stash the work, or run \`${own_release_command(hold.issue)}\` once you are done with it, then ask again.`;
629
- }
630
- function race_message(read, target) {
631
- if (read.kind === "held") return held_message(read.hold);
632
- return `A record already exists at ${target} and this run did not write it \u2014 ${NOT_IDLE}. Either another run claimed the tree at the same moment, or the record belongs to another account. Run \`${FORCE_RELEASE_COMMAND}\`, and remove that file by hand if it is still there.`;
633
- }
634
- function unknown_message() {
635
- return `Could not read this working tree's git directory \u2014 ${NOT_IDLE}. Run this from inside the checkout the run will edit.`;
636
- }
637
- var run_hold = {
638
- is_stop_marked,
639
- FORCE_RELEASE_COMMAND,
640
- HOLD_MAX_AGE_HOURS,
641
- HOLD_MAX_AGE_MS,
642
- RELEASE_COMMAND,
643
- UNNUMBERED_ISSUE,
644
- classify: classify2,
645
- create_halfrun_stop_hold,
646
- create_stop_hold,
647
- HALFRUN_STOP_FIELDS,
648
- create_hold,
649
- foreign_release_message,
650
- forced_release_message,
651
- held_message,
652
- hold_path,
653
- is_linked_worktree,
654
- is_own_hold,
655
- is_reentry,
656
- is_tree_dirty,
657
- own_release_command,
658
- race_message,
659
- read_hold,
660
- release_hold,
661
- session_owner,
662
- stale_message,
663
- uncommitted_message,
664
- unknown_message,
665
- unreadable_message,
666
- worktree_directory,
667
- write_hold
668
- };
669
-
670
- // scripts/agent/agent-headless.ts
671
- var KEY = "JOSH_AGENT_HEADLESS";
672
- var VALUE = "1";
673
- function environment() {
674
- return { [KEY]: VALUE };
675
- }
676
- function is_headless(source = process.env) {
677
- return source[KEY] === VALUE;
678
- }
679
- var agent_headless = { KEY, environment, is_headless };
680
-
681
- // scripts/josh/session-language.ts
682
- var ENV_KEY = "JOSH_SESSION_LANG";
683
- var DEFAULT_SESSION_LANG = "ja";
684
- function resolve_session_lang() {
685
- const value = process.env[ENV_KEY]?.trim();
686
- if (value) return { lang: value, is_default: false };
687
- return { lang: DEFAULT_SESSION_LANG, is_default: true };
688
- }
689
- var session_language = { DEFAULT_SESSION_LANG, ENV_KEY, resolve_session_lang };
690
-
691
- // scripts/lane/lane-reap.ts
692
- import { execFileSync as execFileSync2 } from "node:child_process";
693
-
694
- // scripts/run/ship/run-ship-stage.ts
695
- import { z as z2 } from "zod";
696
- var STAGE = {
697
- PREFLIGHT: "preflight",
698
- REVIEW: "review",
699
- GATE: "gate",
700
- SYNC: "sync",
701
- COMMIT: "commit",
702
- ROUND_TWO: "round-2",
703
- FOLLOWUP: "followup",
704
- REPORT: "report"
705
- };
706
- var PHASE = {
707
- START: "start",
708
- DONE: "done",
709
- FAILED: "failed",
710
- SKIPPED: "skipped"
711
- };
712
- var RECORD_PREFIX = "josh-ship-stages-";
713
- var RECORD_SEPARATOR = "-";
714
- var SKIP_COMMIT_FLAG = "--skip-commit";
715
- var SKIP_PUSH_FLAG = "--skip-push";
716
- var WORD_SEPARATOR = " ";
717
- var STARTED_SEPARATOR = ",";
718
- var STARTED_INDEX = 3;
719
- var WORD_COUNT = STARTED_INDEX + 1;
720
- var record_schema = z2.object({
721
- done: z2.array(z2.string()),
722
- started: z2.array(z2.string()).default([])
723
- });
724
- var EMPTY_RECORD = { done: [], started: [] };
725
- function record_path(repository2, issue2) {
726
- return stamp_file.stamp_path(`${RECORD_PREFIX}${issue2}${RECORD_SEPARATOR}`, repository2);
727
- }
728
- function parse_record(raw) {
729
- return json_value.parse_with(raw, record_schema) ?? EMPTY_RECORD;
730
- }
731
- function read_record(target) {
732
- const raw = stamp_file.read_stamp_text(target);
733
- return raw === void 0 ? EMPTY_RECORD : parse_record(raw);
734
- }
735
- function read_done(target) {
736
- return new Set(read_record(target).done);
737
- }
738
- function mark_done(target, stage) {
739
- const record = read_record(target);
740
- stamp_file.replace_stamp(target, { ...record, done: [.../* @__PURE__ */ new Set([...record.done, stage])] });
741
- }
742
- function read_started(target) {
743
- return read_record(target).started;
744
- }
745
- function mark_started(target, stage) {
746
- const record = read_record(target);
747
- stamp_file.replace_stamp(target, { ...record, started: [.../* @__PURE__ */ new Set([...record.started, stage])] });
748
- }
749
- function end_attempt(target) {
750
- stamp_file.replace_stamp(target, { ...read_record(target), started: [] });
751
- }
752
- function clear(target) {
753
- stamp_file.remove_stamp(target);
754
- }
755
- function is_shipped(state) {
756
- return state.is_committed && state.is_pushed;
757
- }
758
- var DONE_BY = {
759
- // The preflight asks what the commit stage would refuse on, so a commit is
760
- // its output as it is the gate's; a resumed commit stage still asks `git -y`'s own preflight.
761
- [STAGE.PREFLIGHT]: (_done, state) => state.is_merged || state.is_committed,
762
- // The `--review` round precedes the commit, so a commit is its output as it
763
- // is the gate's. A record alone is not honored: before a commit the tree may have been edited since
764
- // the recorded round, and only a commit pins the tree that round read.
765
- [STAGE.REVIEW]: (_done, state) => state.is_merged || state.is_committed,
766
- [STAGE.GATE]: (_done, state) => state.is_merged || state.is_committed,
767
- // The merge of the default branch before the commit: once committed, a
768
- // conflicting pull request is the followup's to merge again.
769
- [STAGE.SYNC]: (_done, state) => state.is_merged || state.is_committed,
770
- [STAGE.COMMIT]: (done, state) => state.is_merged || done.has(STAGE.COMMIT) && is_shipped(state),
771
- // The round-2 pass reads the pushed fix delta, so its record is honored only
772
- // while that push still stands — new work pushed on top reruns it.
773
- [STAGE.ROUND_TWO]: (done, state) => state.is_merged || done.has(STAGE.ROUND_TWO) && is_shipped(state),
774
- // A recorded followup still needs the shipped state: a record left by a merged ship whose report
775
- // failed must not pass over the followup of new, not-yet-pushed work on the same issue.
776
- [STAGE.FOLLOWUP]: (done, state) => state.is_merged || done.has(STAGE.FOLLOWUP) && is_shipped(state),
777
- [STAGE.REPORT]: (done) => done.has(STAGE.REPORT)
778
- };
779
- function is_done(stage, done, state, has_body = false) {
780
- if (has_body && stage === STAGE.COMMIT && !state.is_merged) return false;
781
- return DONE_BY[stage](done, state);
782
- }
783
- function commit_flags(state) {
784
- if (!state.is_committed) return [];
785
- return state.is_pushed ? [SKIP_COMMIT_FLAG, SKIP_PUSH_FLAG] : [SKIP_COMMIT_FLAG];
786
- }
787
- function event_text(issue2, stage, phase, started = []) {
788
- const words = [issue_cite.plain(issue2), stage, phase];
789
- const listed = [...new Set(started)].join(STARTED_SEPARATOR);
790
- const full = started.length > 0 ? [...words, listed] : words;
791
- return full.join(WORD_SEPARATOR);
792
- }
793
- function started_of(text2) {
794
- return text2.split(WORD_SEPARATOR, WORD_COUNT)[STARTED_INDEX]?.split(STARTED_SEPARATOR);
795
- }
796
- var CONFLICT = "conflict";
797
- function stop_reason(stage, conflicts = []) {
798
- return conflicts.length > 0 ? CONFLICT : stage;
799
- }
800
- var run_ship_stage = {
801
- CONFLICT,
802
- PHASE,
803
- STAGE,
804
- clear,
805
- commit_flags,
806
- end_attempt,
807
- event_text,
808
- is_done,
809
- mark_done,
810
- mark_started,
811
- read_done,
812
- read_started,
813
- record_path,
814
- started_of,
815
- stop_reason
816
- };
817
-
818
- // scripts/run/ship/run-ship-next.ts
819
- var { STAGE: STAGE2 } = run_ship_stage;
820
- var COMMAND = {
821
- LOG: "pnpm josh ship --log",
822
- DETACH: "pnpm josh ship --detach",
823
- DETACH_REVIEW: "pnpm josh ship --detach --review"
824
- };
825
- var ESCAPED_QUOTE = String.raw`'\''`;
826
- var BARE_WORD = /^[\w%+,./:=@-]+$/u;
827
- function quoted(title) {
828
- return `'${title.split("'").join(ESCAPED_QUOTE)}'`;
829
- }
830
- function shell_word(token) {
831
- return BARE_WORD.test(token) ? token : quoted(token);
832
- }
833
- function resume_of(args) {
834
- const cites = args.cites.flatMap((cite) => ["--cite", cite]);
835
- return {
836
- title: args.title,
837
- flags: [...args.notify, ...args.body, ...cites],
838
- is_review: args.is_review
839
- };
840
- }
841
- function ship_command(command, resume) {
842
- const words = [...resume.flags, resume.title].map((token) => shell_word(token));
843
- return [command, ...words].join(" ");
844
- }
845
- function detach_again(resume) {
846
- return `leave the fix uncommitted and run \`${ship_command(COMMAND.DETACH, resume)}\`.`;
847
- }
848
- function detach_as_started(resume) {
849
- const command = resume.is_review ? COMMAND.DETACH_REVIEW : COMMAND.DETACH;
850
- return `leave the fix uncommitted and run \`${ship_command(command, resume)}\`.`;
851
- }
852
- var AFTER_FIX = {
853
- [STAGE2.PREFLIGHT]: detach_as_started,
854
- [STAGE2.REVIEW]: detach_as_started,
855
- [STAGE2.GATE]: detach_as_started,
856
- [STAGE2.SYNC]: detach_as_started,
857
- [STAGE2.COMMIT]: detach_as_started,
858
- [STAGE2.ROUND_TWO]: detach_again,
859
- [STAGE2.FOLLOWUP]: detach_again,
860
- [STAGE2.REPORT]: detach_again
861
- };
862
- function conflict_step(conflicts) {
863
- return `Resolve the conflict with origin/main in ${conflicts.join(", ")} (the merge is left in progress: remove the conflict markers in those files), then`;
864
- }
865
- function fix_step(issue2, stage, is_excerpted) {
866
- if (is_excerpted) return `Fix the ${stage} failure shown in the output below`;
867
- return `Read the stopped report with \`${COMMAND.LOG} ${issue2}\`, fix the ${stage} failure`;
868
- }
869
- function next_step(issue2, stage, resume, is_excerpted = false) {
870
- const conflicts = resume.conflicts ?? [];
871
- if (conflicts.length > 0) return `${conflict_step(conflicts)} ${AFTER_FIX[stage](resume)}`;
872
- return `${fix_step(issue2, stage, is_excerpted)}, then ${AFTER_FIX[stage](resume)}`;
873
- }
874
- var run_ship_next = { COMMAND, next_step, quoted, resume_of };
875
-
876
- // scripts/run/ship/run-ship-stop-context.ts
877
- import { stripVTControlCharacters } from "node:util";
878
- import { z as z6 } from "zod";
879
-
880
- // scripts/git/git-ls-remote.ts
881
- var LS_REMOTE_COMMAND = "ls-remote";
882
- var HEADS_FLAG = "--heads";
883
- var ORIGIN_REMOTE = "origin";
884
- var HEADS_REF_PREFIX = "refs/heads/";
885
- function ls_remote_branch_arguments(branch_name) {
886
- return [LS_REMOTE_COMMAND, HEADS_FLAG, ORIGIN_REMOTE, `${HEADS_REF_PREFIX}${branch_name}`];
887
- }
888
-
889
- // scripts/git/repository-lock.ts
890
- import { randomUUID } from "node:crypto";
891
- import { linkSync, renameSync, rmSync } from "node:fs";
892
- import { setTimeout as sleep } from "node:timers/promises";
893
-
894
- // scripts/git/git-common-directory.ts
895
- import { execFileSync } from "node:child_process";
896
- var OWN_GIT_DIRECTORY = 0;
897
- var COMMON_GIT_DIRECTORY = 1;
898
- var PROBE_TIMEOUT_MS2 = 5e3;
899
- var answers = /* @__PURE__ */ new Map();
900
- function probe_environment(cwd) {
901
- if (cwd === void 0) return process.env;
902
- return { ...process.env, ...git_location_environment.location_free_environment() };
903
- }
904
- function cache_key(cwd) {
905
- if (cwd !== void 0) return `explicit\0${cwd}`;
906
- const locations = GIT_LOCATION_VARIABLES.map((name) => process.env[name] ?? "");
907
- return ["inherited", process.cwd(), ...locations].join("\0");
908
- }
909
- function read_directories(cwd) {
910
- try {
911
- const output = execFileSync(
912
- git_utilities.get_git_command_for_spawn(),
913
- [...git_command.GIT_DIRECTORY_ARGUMENTS],
914
- {
915
- cwd,
916
- env: probe_environment(cwd),
917
- encoding: "utf8",
918
- stdio: ["ignore", "pipe", "ignore"],
919
- timeout: PROBE_TIMEOUT_MS2
920
- }
921
- );
922
- return output.split("\n").filter((line) => line !== "");
923
- } catch {
924
- return [];
925
- }
926
- }
927
- function directories(cwd) {
928
- const key = cache_key(cwd);
929
- const known = answers.get(key);
930
- if (known !== void 0) return known;
931
- const read = read_directories(cwd);
932
- if (read.length > 0) answers.set(key, read);
933
- return read;
934
- }
935
- function own(cwd) {
936
- return directories(cwd)[OWN_GIT_DIRECTORY];
937
- }
938
- function repository(cwd) {
939
- return directories(cwd)[COMMON_GIT_DIRECTORY];
940
- }
941
- function select_linked(found) {
942
- const own_directory = found[OWN_GIT_DIRECTORY];
943
- const common = found[COMMON_GIT_DIRECTORY];
944
- return own_directory === void 0 || common === void 0 || own_directory === common ? void 0 : common;
945
- }
946
- function resolve(cwd) {
947
- return select_linked(directories(cwd));
948
- }
949
- var git_common_directory = { directories, own, repository, resolve, select_linked };
950
-
951
- // scripts/git/repository-lock.ts
952
- var POLL_INTERVAL_MS = 200;
953
- var SYNC_POLL_INTERVAL_MS = 10;
954
- var SLEEP_CELL = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
955
- function lock_path(prefix, cwd) {
956
- return stamp_file.stamp_path(prefix, git_common_directory.repository(cwd) ?? cwd ?? process.cwd());
957
- }
958
- function parse_owner(raw) {
959
- if (raw === void 0) return void 0;
960
- const parsed = process_owner_schema.safeParse(json_value.parse_or_undefined(raw));
961
- return parsed.success ? parsed.data : void 0;
962
- }
963
- function read_owner(target) {
964
- return parse_owner(stamp_file.read_stamp_text(target));
965
- }
966
- function is_owner_gone2(owner) {
967
- return process_identity.is_same_process(owner.pid, owner.process_start) === false;
968
- }
969
- function restore(aside, target) {
970
- try {
971
- linkSync(aside, target);
972
- } catch {
973
- }
974
- }
975
- function stale_record(target, is_gone2) {
976
- const raw = stamp_file.read_stamp_text(target);
977
- const owner = parse_owner(raw);
978
- return owner !== void 0 && is_gone2(owner) ? raw : void 0;
979
- }
980
- function move_aside(target) {
981
- const aside = `${target}.${String(process.pid)}.${randomUUID()}`;
982
- try {
983
- renameSync(target, aside);
984
- return aside;
985
- } catch {
986
- return void 0;
987
- }
988
- }
989
- function clear_stale(target, is_gone2 = is_owner_gone2) {
990
- const raw = stale_record(target, is_gone2);
991
- if (raw === void 0) return;
992
- const aside = move_aside(target);
993
- if (aside === void 0) return;
994
- if (stamp_file.read_stamp_text(aside) !== raw) restore(aside, target);
995
- rmSync(aside, { force: true });
996
- }
997
- function claim(target) {
998
- clear_stale(target);
999
- return stamp_file.create_stamp(target, process_identity.own_fields());
1000
- }
1001
- function release(target) {
1002
- const owner = read_owner(target);
1003
- if (owner !== void 0 && process_identity.is_own_process(owner.pid, owner.process_start)) {
1004
- stamp_file.remove_stamp(target);
1005
- }
1006
- }
1007
- async function acquire(target, max_wait_ms) {
1008
- const deadline = Date.now() + max_wait_ms;
1009
- while (!claim(target)) {
1010
- if (Date.now() >= deadline) return false;
1011
- await sleep(POLL_INTERVAL_MS);
1012
- }
1013
- return true;
1014
- }
1015
- function sleep_sync(ms) {
1016
- Atomics.wait(SLEEP_CELL, 0, 0, ms);
1017
- }
1018
- function acquire_sync(target, max_wait_ms) {
1019
- const deadline = Date.now() + max_wait_ms;
1020
- while (!claim(target)) {
1021
- if (Date.now() >= deadline) return false;
1022
- sleep_sync(SYNC_POLL_INTERVAL_MS);
1023
- }
1024
- return true;
1025
- }
1026
- async function with_lock(work, target, max_wait_ms) {
1027
- if (!await acquire(target, max_wait_ms)) return void 0;
1028
- try {
1029
- return await work();
1030
- } finally {
1031
- release(target);
1032
- }
1033
- }
1034
- function with_lock_sync(work, target, max_wait_ms) {
1035
- if (!acquire_sync(target, max_wait_ms)) return void 0;
1036
- try {
1037
- return work();
1038
- } finally {
1039
- release(target);
1040
- }
1041
- }
1042
- var repository_lock = { clear_stale, lock_path, with_lock, with_lock_sync };
1043
-
1044
- // scripts/git/git-worktree.ts
1045
- var WORKTREE = "worktree";
1046
- var WORKTREE_LOCK_PREFIX = "josh-worktree-lock-";
1047
- var WORKTREE_LOCK_MAX_WAIT_MS = 12e4;
1048
- async function locked(arguments_, timeout_ms) {
1049
- const target = repository_lock.lock_path(WORKTREE_LOCK_PREFIX);
1050
- const output = await repository_lock.with_lock(
1051
- async () => await git_spawn.read(arguments_, timeout_ms),
1052
- target,
1053
- WORKTREE_LOCK_MAX_WAIT_MS
1054
- );
1055
- if (output === void 0) {
1056
- throw new Error(
1057
- `git ${arguments_.join(" ")}: timed out waiting for the work-tree lock ${target}`
1058
- );
1059
- }
1060
- return output;
1061
- }
1062
- async function worktree_list() {
1063
- return await git_spawn.read([WORKTREE, "list", PORCELAIN_FLAG]);
1064
- }
1065
- async function worktree_add(directory, branch_name, start_point) {
1066
- const flags = start_point === void 0 ? ["add"] : ["add", "--no-track", "-b", branch_name];
1067
- return await locked([WORKTREE, ...flags, directory, start_point ?? branch_name], SUITE_TIMEOUT_MS);
1068
- }
1069
- async function worktree_add_detached(directory, commit) {
1070
- return await locked([WORKTREE, "add", "--detach", directory, commit], SUITE_TIMEOUT_MS);
1071
- }
1072
- async function worktree_remove(directory) {
1073
- return await locked([WORKTREE, "remove", "--force", directory], INSTALL_TIMEOUT_MS);
1074
- }
1075
- async function worktree_prune() {
1076
- return await locked([WORKTREE, "prune"]);
1077
- }
1078
- async function ls_remote_branch(branch_name) {
1079
- return await git_spawn.read_remote(ls_remote_branch_arguments(branch_name));
1080
- }
1081
- async function branch_delete(branch_name) {
1082
- return await git_spawn.read(["branch", "-D", branch_name]);
1083
- }
1084
- var git_worktree = {
1085
- branch_delete,
1086
- ls_remote_branch,
1087
- worktree_add,
1088
- worktree_add_detached,
1089
- worktree_list,
1090
- worktree_prune,
1091
- worktree_remove
1092
- };
1093
-
1094
- // scripts/gh/git-gh-api-path.ts
1095
- var FULL_PAGE_QUERY = "?per_page=100";
1096
- function repo_api_path(repo = "{owner}/{repo}") {
1097
- return `repos/${repo}`;
1098
- }
1099
- function issues_api_path(repo) {
1100
- return `${repo_api_path(repo)}/issues`;
1101
- }
1102
- function issue_api_path(issue_number, repo) {
1103
- return `${issues_api_path(repo)}/${issue_number}`;
1104
- }
1105
- function blocked_by_api_path(issue_number, repo) {
1106
- return `${issue_api_path(issue_number, repo)}/dependencies/blocked_by`;
1107
- }
1108
- function issue_comments_api_path(issue_number, repo) {
1109
- return `${issue_api_path(issue_number, repo)}/comments`;
1110
- }
1111
- function pulls_api_path(repo) {
1112
- return `${repo_api_path(repo)}/pulls`;
1113
- }
1114
- function pull_api_path(pr_number, repo) {
1115
- return `${pulls_api_path(repo)}/${pr_number}`;
1116
- }
1117
- function pull_merge_api_path(pr_number, repo) {
1118
- return `${pull_api_path(pr_number, repo)}/merge`;
1119
- }
1120
- function pull_comments_api_path(pr_number, repo) {
1121
- return `${pull_api_path(pr_number, repo)}/comments`;
1122
- }
1123
- function pull_reviews_api_path(pr_number, repo) {
1124
- return `${pull_api_path(pr_number, repo)}/reviews`;
1125
- }
1126
- function commit_api_path(commit_sha, repo) {
1127
- return `${repo_api_path(repo)}/commits/${commit_sha}`;
1128
- }
1129
- function commit_check_runs_api_path(commit_sha, repo) {
1130
- return `${commit_api_path(commit_sha, repo)}/check-runs`;
1131
- }
1132
- function commit_status_api_path(commit_sha, repo) {
1133
- return `${commit_api_path(commit_sha, repo)}/status`;
1134
- }
1135
- function tag_reference_api_path(tag, repo) {
1136
- return `${repo_api_path(repo)}/git/ref/tags/${tag}`;
1137
- }
1138
- function release_by_tag_api_path(tag, repo) {
1139
- return `${repo_api_path(repo)}/releases/tags/${tag}`;
1140
- }
1141
- var git_gh_api_path = {
1142
- FULL_PAGE_QUERY,
1143
- repo_api_path,
1144
- tag_ref_api_path: tag_reference_api_path,
1145
- release_by_tag_api_path,
1146
- issues_api_path,
1147
- issue_api_path,
1148
- blocked_by_api_path,
1149
- issue_comments_api_path,
1150
- pulls_api_path,
1151
- pull_api_path,
1152
- pull_merge_api_path,
1153
- pull_comments_api_path,
1154
- pull_reviews_api_path,
1155
- commit_api_path,
1156
- commit_check_runs_api_path,
1157
- commit_status_api_path
1158
- };
1159
-
1160
- // scripts/gh/git-gh-exec.ts
1161
- import { execa as execa2, execaSync } from "execa";
1162
-
1163
- // scripts/gh/git-gh-check.ts
1164
- import { execa } from "execa";
1165
- var GH_NOT_INSTALLED_MSG = "gh CLI is not installed. Install it from https://cli.github.com/";
1166
- var gh_check = {};
1167
- async function run_gh_check() {
1168
- try {
1169
- await execa("gh", ["--version"], { timeout: COMMAND_TIMEOUT_MS });
1170
- } catch {
1171
- delete gh_check.promise;
1172
- throw new Error(GH_NOT_INSTALLED_MSG);
1173
- }
1174
- }
1175
- async function check_gh_installed() {
1176
- gh_check.promise ??= run_gh_check();
1177
- await gh_check.promise;
1178
- }
1179
-
1180
- // scripts/git/parse-json-array.ts
1181
- function parse_json_loose(raw_json) {
1182
- return json_value.parse_or_undefined(raw_json);
1183
- }
1184
- function parse_json_array_or_undefined(raw_json, element_schema) {
1185
- const value = parse_json_loose(raw_json);
1186
- if (!Array.isArray(value)) return void 0;
1187
- return element_schema.array().parse(value);
1188
- }
1189
- function read_json_listing(raw_json, element_schema) {
1190
- try {
1191
- const rows = parse_json_array_or_undefined(raw_json, element_schema);
1192
- return rows === void 0 ? { kind: "unreadable" } : { kind: "read", rows };
1193
- } catch {
1194
- return { kind: "unexpected_shape" };
1195
- }
1196
- }
1197
- function parse_json_object_or_undefined(raw_json, schema) {
1198
- const value = parse_json_loose(raw_json);
1199
- if (value === void 0) return void 0;
1200
- return schema.parse(value);
1201
- }
1202
- var parse_json = {
1203
- parse_json_object_or_undefined
1204
- };
1205
-
1206
- // scripts/gh/git-gh-failure.ts
1207
- import { z as z3 } from "zod";
1208
- var error_document_schema = z3.object({ status: z3.union([z3.string(), z3.number()]).optional() }).catch({});
1209
- var GH_FAILURE_FIELD = "gh_failure";
1210
- function has_gh_failure(error) {
1211
- return error instanceof Error && Object.hasOwn(error, GH_FAILURE_FIELD);
1212
- }
1213
- function parse_response_status(stdout) {
1214
- const document = parse_json.parse_json_object_or_undefined(stdout, error_document_schema);
1215
- if (document?.status === void 0) return void 0;
1216
- const status = Number(document.status);
1217
- return Number.isSafeInteger(status) ? status : void 0;
1218
- }
1219
- function classify_stdout(stdout) {
1220
- return { status: parse_response_status(stdout) };
1221
- }
1222
- function attach(error, failure) {
1223
- Object.defineProperty(error, GH_FAILURE_FIELD, {
1224
- value: failure,
1225
- enumerable: false,
1226
- configurable: true
1227
- });
1228
- return error;
1229
- }
1230
- function failure_of(error) {
1231
- return has_gh_failure(error) ? error.gh_failure : void 0;
1232
- }
1233
- var gh_failure = { attach, classify_stdout, failure_of, parse_response_status };
1234
-
1235
- // scripts/gh/git-gh-exec.ts
1236
- var BODY_FROM_STDIN = "-";
1237
- var GH_REQUEST_TIMEOUT_MS = 6e4;
1238
- function to_timeout_option(timeout_ms) {
1239
- return { timeout: timeout_ms ?? GH_REQUEST_TIMEOUT_MS };
1240
- }
1241
- function direct_environment() {
1242
- const removed = agent_session_environment.removed_proxy_environment();
1243
- return Object.keys(removed).length > 0 ? { env: removed } : {};
1244
- }
1245
- function to_spawn_options(timeout_ms, cwd) {
1246
- return {
1247
- ...to_timeout_option(timeout_ms),
1248
- ...direct_environment(),
1249
- ...cwd !== void 0 && { cwd }
1250
- };
1251
- }
1252
- var GH_REQUEST_TIMEOUT_MESSAGE = "gh request timed out";
1253
- function has_stderr_field(error) {
1254
- return error instanceof Error && "stderr" in error && typeof error.stderr === "string";
1255
- }
1256
- function has_stdout_field(error) {
1257
- return error instanceof Error && "stdout" in error && typeof error.stdout === "string";
1258
- }
1259
- function to_timeout_prefix(error) {
1260
- return has_timed_out(error) ? `${GH_REQUEST_TIMEOUT_MESSAGE}: ` : "";
1261
- }
1262
- function to_gh_error(error) {
1263
- const stderr = has_stderr_field(error) ? error.stderr.trim() : "";
1264
- const stdout = has_stdout_field(error) ? error.stdout.trim() : "";
1265
- const summary = stderr.length > 0 ? stderr : error_text.message_of(error);
1266
- const detail = stdout.length > 0 ? `${summary}
1267
- ${stdout}` : summary;
1268
- return gh_failure.attach(
1269
- new Error(`${to_timeout_prefix(error)}${detail}`, { cause: error }),
1270
- gh_failure.classify_stdout(stdout)
1271
- );
1272
- }
1273
- async function exec_gh_command(arguments_, timeout_ms, cwd) {
1274
- await check_gh_installed();
1275
- const options = to_spawn_options(timeout_ms, cwd);
1276
- try {
1277
- const { stdout } = await execa2("gh", arguments_, options);
1278
- return stdout.trimEnd();
1279
- } catch (error) {
1280
- throw to_gh_error(error);
1281
- }
1282
- }
1283
- async function exec_gh_command_with_stdin(input) {
1284
- await check_gh_installed();
1285
- const options = { input: input.stdin_body, ...to_spawn_options(input.timeout_ms, input.cwd) };
1286
- try {
1287
- const { stdout } = await execa2("gh", input.args, options);
1288
- return stdout.trimEnd();
1289
- } catch (error) {
1290
- throw to_gh_error(error);
1291
- }
1292
- }
1293
- var STATUS_LINE_PATTERN = /^HTTP\/[\d.]+ (?<status>\d{3})\b/u;
1294
- function parse_status_line(output) {
1295
- const { status } = STATUS_LINE_PATTERN.exec(output)?.groups ?? {};
1296
- return status === void 0 ? void 0 : Number(status);
1297
- }
1298
- function status_of_failure(error) {
1299
- return has_stdout_field(error) ? parse_status_line(error.stdout) : void 0;
1300
- }
1301
- async function exec_gh_api_status(path6, timeout_ms) {
1302
- const options = to_spawn_options(timeout_ms);
1303
- try {
1304
- await check_gh_installed();
1305
- const { stdout } = await execa2("gh", ["api", "--include", "--silent", path6], options);
1306
- return parse_status_line(stdout);
1307
- } catch (error) {
1308
- return status_of_failure(error);
1309
- }
1310
- }
1311
- function exec_gh_api_status_sync(path6, timeout_ms) {
1312
- const options = to_spawn_options(timeout_ms);
1313
- try {
1314
- const { stdout } = execaSync("gh", ["api", "--include", "--silent", path6], options);
1315
- return parse_status_line(stdout);
1316
- } catch (error) {
1317
- return status_of_failure(error);
1318
- }
1319
- }
1320
- var METHOD_FLAG = "--method";
1321
- var INPUT_FLAG = "--input";
1322
- var PAGINATE_FLAG = "--paginate";
1323
- var SLURP_FLAG = "--slurp";
1324
- var JQ_FLAG = "--jq";
1325
- function optional_flag(flag, value) {
1326
- return value === void 0 ? [] : [flag, value];
1327
- }
1328
- function to_gh_api_args(request) {
1329
- const body_args = request.body === void 0 ? [] : [INPUT_FLAG, BODY_FROM_STDIN];
1330
- const paginate_args = request.should_paginate === true ? [PAGINATE_FLAG] : [];
1331
- const slurp_args = request.should_slurp === true ? [SLURP_FLAG] : [];
1332
- return [
1333
- "api",
1334
- request.path,
1335
- ...optional_flag(METHOD_FLAG, request.method),
1336
- ...body_args,
1337
- ...paginate_args,
1338
- ...slurp_args,
1339
- ...optional_flag(JQ_FLAG, request.jq_filter)
1340
- ];
1341
- }
1342
- async function exec_gh_api(request) {
1343
- const args = to_gh_api_args(request);
1344
- if (request.body === void 0) {
1345
- return await exec_gh_command(args, request.timeout_ms, request.cwd);
1346
- }
1347
- return await exec_gh_command_with_stdin({
1348
- args,
1349
- stdin_body: request.body,
1350
- timeout_ms: request.timeout_ms,
1351
- cwd: request.cwd
1352
- });
1353
- }
1354
- function exec_gh_api_sync(request) {
1355
- const body_option = request.body === void 0 ? {} : { input: request.body };
1356
- const options = { ...body_option, ...to_spawn_options(request.timeout_ms, request.cwd) };
1357
- try {
1358
- const { stdout } = execaSync("gh", to_gh_api_args(request), options);
1359
- return stdout.trimEnd();
1360
- } catch (error) {
1361
- throw to_gh_error(error);
1362
- }
1363
- }
1364
- function read_gh_api_sync(request) {
1365
- try {
1366
- return exec_gh_api_sync(request);
1367
- } catch {
1368
- return void 0;
1369
- }
1370
- }
1371
- var git_gh_exec = {
1372
- direct_environment,
1373
- exec_gh_command,
1374
- exec_gh_command_with_stdin,
1375
- exec_gh_api,
1376
- exec_gh_api_sync,
1377
- read_gh_api_sync,
1378
- exec_gh_api_status,
1379
- exec_gh_api_status_sync,
1380
- parse_status_line
1381
- };
1382
-
1383
- // scripts/gh/git-gh-helpers.ts
1384
- function parse_pr_state_string(result) {
1385
- const trimmed = result.trim();
1386
- return trimmed.length > 0 ? trimmed : void 0;
1387
- }
1388
- function is_pr_already_exists_message(error_message) {
1389
- return error_message.toLowerCase().includes("already exists");
1390
- }
1391
- function get_error_message_with_stderr(error) {
1392
- if (!(error instanceof Error)) return String(error);
1393
- if (has_stderr_field(error) && error.stderr.length > 0) return `${error.message}
1394
- ${error.stderr}`;
1395
- return error.message;
1396
- }
1397
- function handle_pr_create_error(error) {
1398
- const error_message = get_error_message_with_stderr(error);
1399
- if (is_pr_already_exists_message(error_message)) {
1400
- throw new Error("PR_ALREADY_EXISTS");
1401
- }
1402
- throw error;
1403
- }
1404
- var git_gh_helpers = {
1405
- parse_pr_state_string,
1406
- get_error_message_with_stderr,
1407
- handle_pr_create_error
1408
- };
1409
-
1410
- // scripts/gh/git-gh-pr-rest.ts
1411
- import { z as z4 } from "zod";
1412
-
1413
- // scripts/gh/git-gh-rest-state.ts
1414
- var MERGED_STATE = "MERGED";
1415
- function to_gh_state(state) {
1416
- return state?.toUpperCase();
1417
- }
1418
-
1419
- // scripts/gh/git-gh-pr-rest.ts
1420
- var rest_repo_schema = z4.looseObject({ full_name: z4.string().optional() }).nullish();
1421
- var rest_pull_side_schema = z4.looseObject({ repo: rest_repo_schema });
1422
- var rest_pull_schema = z4.looseObject({
1423
- number: z4.number(),
1424
- html_url: z4.string().optional(),
1425
- body: z4.string().nullish(),
1426
- state: z4.string().optional(),
1427
- merged: z4.boolean().nullish(),
1428
- merged_at: z4.string().nullish(),
1429
- mergeable: z4.boolean().nullish(),
1430
- mergeable_state: z4.string().optional(),
1431
- // `sha` is the head commit, which is what both halves of the merge-gate rollup are keyed by —
1432
- // REST hangs the check runs and the status contexts off the commit rather than off the pull
1433
- // request.
1434
- head: z4.looseObject({ ref: z4.string().optional(), sha: z4.string().optional(), repo: rest_repo_schema }).nullish(),
1435
- base: rest_pull_side_schema.nullish(),
1436
- // `node_id` is what the GraphQL auto-merge mutation addresses a pull request by, and `auto_merge`
1437
- // is `null` until auto-merge is enabled — both read by `git-gh-pr-auto-merge.ts`.
1438
- node_id: z4.string().optional(),
1439
- auto_merge: z4.looseObject({}).nullish()
1440
- });
1441
- var NOT_A_PULL_MESSAGE = "gh api answered something other than a pull request object";
1442
- var NOT_A_PULL_LISTING_MESSAGE = "gh api answered something other than a pull request listing";
1443
- var NOT_A_COMMENT_LISTING_MESSAGE = "gh api answered something other than a comment listing";
1444
- var OPEN_STATE = "open";
1445
- var EMPTY_BODY = "";
1446
- function parse_rest_pull(rest_json) {
1447
- const parsed = parse_json_object_or_undefined(rest_json, rest_pull_schema);
1448
- if (parsed === void 0) throw new Error(NOT_A_PULL_MESSAGE);
1449
- return parsed;
1450
- }
1451
- function parse_rest_pulls(rest_json) {
1452
- const parsed = parse_json_array_or_undefined(rest_json, rest_pull_schema);
1453
- if (parsed === void 0) throw new Error(NOT_A_PULL_LISTING_MESSAGE);
1454
- return parsed;
1455
- }
1456
- function select_pull(pulls) {
1457
- return pulls.find((pull) => pull.state === OPEN_STATE) ?? pulls[0];
1458
- }
1459
- function is_merged(pull) {
1460
- return pull.merged === true || typeof pull.merged_at === "string";
1461
- }
1462
- function to_pr_state(pull) {
1463
- return is_merged(pull) ? MERGED_STATE : to_gh_state(pull.state);
1464
- }
1465
- function to_repo_name(side) {
1466
- return side?.repo?.full_name;
1467
- }
1468
- function is_same_repository_head(pull) {
1469
- const head_repo = to_repo_name(pull.head);
1470
- return head_repo !== void 0 && head_repo === to_repo_name(pull.base);
1471
- }
1472
- function to_pr_info(pull) {
1473
- return {
1474
- mergeable: pull.mergeable,
1475
- mergeStateStatus: to_gh_state(pull.mergeable_state),
1476
- state: to_pr_state(pull)
1477
- };
1478
- }
1479
- function to_pr_comments(rest_json) {
1480
- const parsed = parse_json_array_or_undefined(rest_json, rest_comment_schema);
1481
- if (parsed === void 0) throw new Error(NOT_A_COMMENT_LISTING_MESSAGE);
1482
- return parsed.map((comment) => ({
1483
- body: comment.body ?? EMPTY_BODY,
1484
- url: comment.html_url,
1485
- author: { login: comment.user?.login }
1486
- }));
1487
- }
1488
- var git_gh_pr_rest = {
1489
- parse_rest_pull,
1490
- parse_rest_pulls,
1491
- select_pull,
1492
- is_same_repository_head,
1493
- is_merged,
1494
- to_pr_state,
1495
- to_pr_info,
1496
- to_pr_comments
1497
- };
1498
-
1499
- // scripts/gh/git-gh-pr-read.ts
1500
- var pr_number_by_branch = /* @__PURE__ */ new Map();
1501
- var LOOKUP_QUERY = "state=all&sort=created&direction=desc&per_page=100";
1502
- var COMMENTS_QUERY = FULL_PAGE_QUERY;
1503
- var OWNER_PLACEHOLDER = "{owner}";
1504
- var NO_PULL_REQUEST_MESSAGE = "gh api found no pull request for branch";
1505
- var UNREADABLE_PULL_REQUEST_MESSAGE = "gh api could not read the pull requests for branch";
1506
- function lookup_path(branch_name) {
1507
- const head = `${OWNER_PLACEHOLDER}:${encodeURIComponent(branch_name)}`;
1508
- return `${git_gh_api_path.pulls_api_path()}?head=${head}&${LOOKUP_QUERY}`;
1509
- }
1510
- async function fetch_pr_number(branch_name) {
1511
- const json = await git_gh_exec.exec_gh_api({ path: lookup_path(branch_name) });
1512
- return git_gh_pr_rest.select_pull(git_gh_pr_rest.parse_rest_pulls(json))?.number;
1513
- }
1514
- var pending_pr_number_by_branch = /* @__PURE__ */ new Map();
1515
- var pull_by_number = /* @__PURE__ */ new Map();
1516
- async function fetch_pr_number_read(branch_name) {
1517
- try {
1518
- const pr_number = await fetch_pr_number(branch_name);
1519
- if (pr_number === void 0) return { kind: "missing" };
1520
- pr_number_by_branch.set(branch_name, pr_number);
1521
- return { kind: "read", pr_number };
1522
- } catch (error) {
1523
- return { kind: "unreadable", cause: error };
1524
- }
1525
- }
1526
- async function start_pr_number_read(branch_name) {
1527
- const pending = pending_pr_number_by_branch.get(branch_name);
1528
- if (pending !== void 0) return await pending;
1529
- const lookup = fetch_pr_number_read(branch_name);
1530
- pending_pr_number_by_branch.set(branch_name, lookup);
1531
- try {
1532
- return await lookup;
1533
- } finally {
1534
- pending_pr_number_by_branch.delete(branch_name);
1535
- }
1536
- }
1537
- function forget_pr_numbers() {
1538
- pr_number_by_branch.clear();
1539
- pending_pr_number_by_branch.clear();
1540
- pull_by_number.clear();
1541
- }
1542
- async function read_pr_number(branch_name) {
1543
- const cached = pr_number_by_branch.get(branch_name);
1544
- if (cached !== void 0) return { kind: "read", pr_number: cached };
1545
- return await start_pr_number_read(branch_name);
1546
- }
1547
- async function resolve_pr_number(branch_name) {
1548
- const read = await read_pr_number(branch_name);
1549
- return read.kind === "read" ? read.pr_number : void 0;
1550
- }
1551
- function to_unreadable_error(branch_name, cause) {
1552
- return new Error(`${UNREADABLE_PULL_REQUEST_MESSAGE}: ${branch_name}`, { cause });
1553
- }
1554
- async function require_pr_number(branch_name) {
1555
- const read = await read_pr_number(branch_name);
1556
- if (read.kind === "read") return read.pr_number;
1557
- if (read.kind === "missing") throw new Error(`${NO_PULL_REQUEST_MESSAGE}: ${branch_name}`);
1558
- throw to_unreadable_error(branch_name, read.cause);
1559
- }
1560
- async function read_pull(pr_number) {
1561
- const json = await git_gh_exec.exec_gh_api({
1562
- path: git_gh_api_path.pull_api_path(String(pr_number))
1563
- });
1564
- return git_gh_pr_rest.parse_rest_pull(json);
1565
- }
1566
- async function read_remembered_pull(pr_number) {
1567
- const pending = pull_by_number.get(pr_number) ?? read_pull(pr_number);
1568
- pull_by_number.set(pr_number, pending);
1569
- try {
1570
- return await pending;
1571
- } catch (error) {
1572
- if (pull_by_number.get(pr_number) === pending) pull_by_number.delete(pr_number);
1573
- throw error;
1574
- }
1575
- }
1576
- async function read_pull_of_branch(branch_name, read = read_remembered_pull) {
1577
- const number_read = await read_pr_number(branch_name);
1578
- if (number_read.kind !== "read") return number_read;
1579
- try {
1580
- return { kind: "read", pull: await read(number_read.pr_number) };
1581
- } catch (error) {
1582
- return { kind: "unreadable", cause: error };
1583
- }
1584
- }
1585
- async function read_pull_or_undefined(branch_name) {
1586
- const read = await read_pull_of_branch(branch_name);
1587
- return read.kind === "read" ? read.pull : void 0;
1588
- }
1589
- async function pr_exists(branch_name) {
1590
- const read = await read_pr_number(branch_name);
1591
- if (read.kind === "unreadable") throw to_unreadable_error(branch_name, read.cause);
1592
- return read.kind === "read";
1593
- }
1594
- async function pr_get_number(branch_name) {
1595
- return await resolve_pr_number(branch_name);
1596
- }
1597
- async function pr_get_url(branch_name) {
1598
- const pull = await read_pull_or_undefined(branch_name);
1599
- if (pull?.html_url === void 0) return void 0;
1600
- return git_gh_helpers.parse_pr_state_string(pull.html_url);
1601
- }
1602
- async function pr_get_merge_state(branch_name) {
1603
- const read = await read_pull_of_branch(branch_name, read_pull);
1604
- if (read.kind !== "read") return void 0;
1605
- const { pull } = read;
1606
- return {
1607
- is_merged: git_gh_pr_rest.is_merged(pull),
1608
- merged_at: pull.merged_at ?? void 0,
1609
- head_sha: pull.head?.sha,
1610
- merge_state_status: to_gh_state(pull.mergeable_state)
1611
- };
1612
- }
1613
- async function pr_get_body(branch_name) {
1614
- const pull = await read_pull_or_undefined(branch_name);
1615
- const body = pull?.body;
1616
- return typeof body === "string" && body.length > 0 ? body : void 0;
1617
- }
1618
- async function pr_view(branch_name) {
1619
- const read = await read_pull_of_branch(branch_name, read_pull);
1620
- if (read.kind === "unreadable") throw to_unreadable_error(branch_name, read.cause);
1621
- if (read.kind === "missing") return "";
1622
- return JSON.stringify(git_gh_pr_rest.to_pr_info(read.pull));
1623
- }
1624
- async function read_comments(branch_name, to_path, to_json) {
1625
- const pr_number = await resolve_pr_number(branch_name);
1626
- if (pr_number === void 0) return void 0;
1627
- const path6 = `${to_path(String(pr_number))}${COMMENTS_QUERY}`;
1628
- try {
1629
- return to_json(await git_gh_exec.exec_gh_api({ path: path6, should_paginate: true }));
1630
- } catch {
1631
- return void 0;
1632
- }
1633
- }
1634
- function to_comments_json(raw) {
1635
- return JSON.stringify(git_gh_pr_rest.to_pr_comments(raw));
1636
- }
1637
- function as_served(raw) {
1638
- return raw;
1639
- }
1640
- async function pr_get_comments(branch_name) {
1641
- return await read_comments(branch_name, git_gh_api_path.issue_comments_api_path, to_comments_json);
1642
- }
1643
- async function pr_get_review_comments(branch_name) {
1644
- return await read_comments(branch_name, git_gh_api_path.pull_comments_api_path, as_served);
1645
- }
1646
- var git_gh_pr_read = {
1647
- pr_exists,
1648
- pr_get_number,
1649
- pr_get_url,
1650
- pr_get_body,
1651
- pr_get_merge_state,
1652
- pr_view,
1653
- pr_get_comments,
1654
- pr_get_review_comments
1655
- };
1656
-
1657
- // scripts/lane/lane-registry.ts
1658
- import { existsSync as existsSync2, statSync as statSync2 } from "node:fs";
1659
- import path2 from "node:path";
1660
-
1661
- // scripts/lane/lane-environment.ts
1662
- var LANE_OUTPUT_KEY = "JOSH_LANE_OUTPUT";
1663
- var LANE_PROVIDER_KEY = "JOSH_LANE_AGENT_PROVIDER";
1664
- var LANE_ROLE_KEY = "JOSH_LANE_AGENT_ROLE";
1665
- var LANE_MODEL_KEY = "JOSH_LANE_AGENT_MODEL";
1666
- var LANE_EFFORT_KEY = "JOSH_LANE_AGENT_EFFORT";
1667
- var ASSIGNMENT_SEPARATOR = "=";
1668
- var EXPORT_PREFIX = "export ";
1669
- var QUOTE_CHARACTERS = /* @__PURE__ */ new Set(['"', "'"]);
1670
- var MIN_QUOTED_LENGTH = 2;
1671
- var FIRST_CHARACTER_END = 1;
1672
- var LAST_CHARACTER_START = -1;
1673
- function strip_export(line) {
1674
- const trimmed = line.trimStart();
1675
- return trimmed.startsWith(EXPORT_PREFIX) ? trimmed.slice(EXPORT_PREFIX.length).trimStart() : trimmed;
1676
- }
1677
- function is_key_line(line, key) {
1678
- const body = strip_export(line);
1679
- if (!body.startsWith(key)) return false;
1680
- return body.slice(key.length).trimStart().startsWith(ASSIGNMENT_SEPARATOR);
1681
- }
1682
- function is_seat_line(line) {
1683
- return is_key_line(line, LANE_SEAT_KEY);
1684
- }
1685
- function is_output_line(line) {
1686
- return is_key_line(line, LANE_OUTPUT_KEY);
1687
- }
1688
- function split_lines(content) {
1689
- const trimmed = content.trimEnd();
1690
- return trimmed.length === 0 ? [] : trimmed.split("\n");
1691
- }
1692
- function is_quoted(raw) {
1693
- const first = raw.slice(0, FIRST_CHARACTER_END);
1694
- if (!QUOTE_CHARACTERS.has(first)) return false;
1695
- return raw.length >= MIN_QUOTED_LENGTH && raw.endsWith(first);
1696
- }
1697
- function unquote(raw) {
1698
- return is_quoted(raw) ? raw.slice(FIRST_CHARACTER_END, LAST_CHARACTER_START) : raw;
1699
- }
1700
- function assignment_value(line) {
1701
- return unquote(line.slice(line.indexOf(ASSIGNMENT_SEPARATOR) + FIRST_CHARACTER_END).trim());
1702
- }
1703
- function read_assignment(content, key) {
1704
- const line = split_lines(content).findLast((entry) => is_key_line(entry, key));
1705
- return line === void 0 ? void 0 : assignment_value(line);
1706
- }
1707
- function read_root_seed(content) {
1708
- return ports.resolve_seed({ [PORT_SEED_KEY]: read_assignment(content, PORT_SEED_KEY) });
1709
- }
1710
- function read_lane_seat(content) {
1711
- const raw = read_assignment(content, LANE_SEAT_KEY);
1712
- return raw === void 0 ? void 0 : ports.resolve_lane({ [LANE_SEAT_KEY]: raw });
1713
- }
1714
- function read_lane_ports(content) {
1715
- const environment3 = {
1716
- [PORT_SEED_KEY]: read_assignment(content, PORT_SEED_KEY),
1717
- [LANE_SEAT_KEY]: read_assignment(content, LANE_SEAT_KEY)
1718
- };
1719
- return {
1720
- development: ports.resolve_development_port(environment3),
1721
- preview: ports.resolve_preview_port(environment3)
1722
- };
1723
- }
1724
- function read_lane_output(content) {
1725
- const line = split_lines(content).findLast((entry) => is_output_line(entry));
1726
- const raw = line === void 0 ? void 0 : assignment_value(line);
1727
- return raw === void 0 || raw.length === 0 ? void 0 : raw;
1728
- }
1729
- function read_lane_profile(content) {
1730
- return agent_role_profile.parse({
1731
- provider: read_assignment(content, LANE_PROVIDER_KEY),
1732
- role: read_assignment(content, LANE_ROLE_KEY),
1733
- model: read_assignment(content, LANE_MODEL_KEY),
1734
- effort: read_assignment(content, LANE_EFFORT_KEY)
1735
- });
1736
- }
1737
- function replace_assignment(lines, keep, assignment, key) {
1738
- return lines.flatMap((entry, index) => {
1739
- if (index === keep) return [assignment];
1740
- if (is_key_line(entry, key)) return [];
1741
- return [entry];
1742
- });
1743
- }
1744
- function upsert_assignment(content, key, value) {
1745
- const assignment = `${key}${ASSIGNMENT_SEPARATOR}${value}`;
1746
- const lines = split_lines(content);
1747
- const last = lines.findLastIndex((entry) => is_key_line(entry, key));
1748
- const body = last === -1 ? [...lines, assignment] : replace_assignment(lines, last, assignment, key);
1749
- return `${body.join("\n")}
1750
- `;
1751
- }
1752
- function lane_file_content(root_content, seat) {
1753
- return upsert_assignment(root_content, LANE_SEAT_KEY, String(seat));
1754
- }
1755
- function with_lane_output(content, output, profile) {
1756
- const recorded = upsert_assignment(content, LANE_OUTPUT_KEY, `"${output}"`);
1757
- if (profile === void 0) return recorded;
1758
- const with_provider = upsert_assignment(recorded, LANE_PROVIDER_KEY, profile.provider);
1759
- const with_role = upsert_assignment(with_provider, LANE_ROLE_KEY, profile.role);
1760
- const with_model = upsert_assignment(with_role, LANE_MODEL_KEY, profile.model);
1761
- return upsert_assignment(with_model, LANE_EFFORT_KEY, profile.effort);
1762
- }
1763
- var lane_environment = {
1764
- is_seat_line,
1765
- lane_file_content,
1766
- read_lane_output,
1767
- read_lane_profile,
1768
- read_lane_ports,
1769
- read_lane_seat,
1770
- read_root_seed,
1771
- with_lane_output
1772
- };
1773
-
1774
- // scripts/lane/lane-registry.ts
1775
- var WORKTREE_PREFIX = "worktree ";
1776
- var BRANCH_PREFIX = "branch refs/heads/";
1777
- var BLOCK_SEPARATOR = "\n\n";
1778
- function line_value(lines, prefix) {
1779
- return lines.find((line) => line.startsWith(prefix))?.slice(prefix.length);
1780
- }
1781
- function seat_from_content(content) {
1782
- const seat = lane_environment.read_lane_seat(content);
1783
- if (seat === void 0) return void 0;
1784
- const port_pair = lane_environment.read_lane_ports(content);
1785
- return { seat, development_port: port_pair.development, preview_port: port_pair.preview };
1786
- }
1787
- var EMPTY_SEAT = {
1788
- seat: void 0,
1789
- development_port: void 0,
1790
- preview_port: void 0
1791
- };
1792
- function held_seat(content) {
1793
- if (content === void 0) return EMPTY_SEAT;
1794
- return seat_from_content(content) ?? EMPTY_SEAT;
1795
- }
1796
- function read_environment(directory) {
1797
- return file_reader.read_if_readable(path2.join(directory, ENV_FILE_NAME));
1798
- }
1799
- function dispatched_at(directory) {
1800
- return statSync2(path2.join(directory, ENV_FILE_NAME), { throwIfNoEntry: false })?.mtimeMs;
1801
- }
1802
- function branch_issue(branch) {
1803
- if (!branch?.endsWith(lane_paths.LANE_BRANCH_SUFFIX)) return void 0;
1804
- const issue2 = branch.slice(0, -lane_paths.LANE_BRANCH_SUFFIX.length);
1805
- return issue_number_shape.ISSUE_NUMBER_PATTERN.test(issue2) ? issue2 : void 0;
1806
- }
1807
- function is_gone(directory) {
1808
- return !existsSync2(directory);
1809
- }
1810
- function build_lane(issue2, branch, directory, is_stranded) {
1811
- const content = is_stranded ? void 0 : read_environment(directory);
1812
- const held = held_seat(content);
1813
- const output = content === void 0 ? void 0 : lane_environment.read_lane_output(content);
1814
- const profile = content === void 0 ? void 0 : lane_environment.read_lane_profile(content);
1815
- return {
1816
- issue: issue2,
1817
- branch,
1818
- directory,
1819
- seat: held.seat,
1820
- development_port: held.development_port,
1821
- preview_port: held.preview_port,
1822
- output,
1823
- profile,
1824
- dispatched_ms: is_stranded ? void 0 : dispatched_at(directory),
1825
- is_stranded
1826
- };
1827
- }
1828
- function is_lane_directory(root, issue2, directory) {
1829
- return directory === lane_paths.lane_directory(root, issue2);
1830
- }
1831
- function parse_block(block, root) {
1832
- const lines = block.split("\n");
1833
- const directory = line_value(lines, WORKTREE_PREFIX);
1834
- const branch = line_value(lines, BRANCH_PREFIX);
1835
- const issue2 = branch_issue(branch);
1836
- if (directory === void 0 || branch === void 0 || issue2 === void 0 || !is_lane_directory(root, issue2, directory)) {
1837
- return void 0;
1838
- }
1839
- return build_lane(issue2, branch, directory, is_gone(directory));
1840
- }
1841
- function is_lane(lane) {
1842
- return lane !== void 0;
1843
- }
1844
- async function worktree_blocks() {
1845
- const listing = await git_worktree.worktree_list();
1846
- return listing.split(BLOCK_SEPARATOR);
1847
- }
1848
- async function main_repository_root() {
1849
- return repo_discovery.main_worktree(await git_command.repository_root());
1850
- }
1851
- async function list_lanes() {
1852
- const root = lane_paths.lane_root(await main_repository_root());
1853
- const blocks = await worktree_blocks();
1854
- const lanes = blocks.map((block) => parse_block(block, root)).filter(is_lane);
1855
- return lanes.toSorted((left, right) => Number(left.issue) - Number(right.issue));
1856
- }
1857
- async function registered_directories() {
1858
- const blocks = await worktree_blocks();
1859
- return blocks.flatMap((block) => line_value(block.split("\n"), WORKTREE_PREFIX) ?? []);
1860
- }
1861
- async function has_lanes_in_flight() {
1862
- const lanes = await list_lanes();
1863
- return lanes.some((lane) => !lane.is_stranded);
1864
- }
1865
- function used_seats(lanes) {
1866
- return lanes.map((lane) => lane.seat).filter((seat) => seat !== void 0);
1867
- }
1868
- function unreadable_lanes(lanes) {
1869
- return lanes.filter((lane) => !lane.is_stranded && lane.seat === void 0);
1870
- }
1871
- function find_lane(lanes, issue2) {
1872
- return lanes.find((lane) => lane.issue === issue2);
1873
- }
1874
- async function find_open_lane(issue2) {
1875
- return find_lane(await list_lanes(), issue2);
1876
- }
1877
- var lane_registry = {
1878
- find_lane,
1879
- find_open_lane,
1880
- has_lanes_in_flight,
1881
- list_lanes,
1882
- main_repository_root,
1883
- parse_block,
1884
- read_environment,
1885
- registered_directories,
1886
- unreadable_lanes,
1887
- used_seats
1888
- };
1889
-
1890
- // scripts/run/run-preflight.ts
1891
- import { z as z5 } from "zod";
1892
- var CLEAN_VERDICT = "clean";
1893
- var RECLAIM_VERDICT = "reclaim";
1894
- var RESUME_VERDICT = "resume";
1895
- var PARK_VERDICT = "park";
1896
- var NO_PR = "none";
1897
- var OPEN_PR = "open";
1898
- var MERGED_PR = "merged";
1899
- var CLOSED_PR = "closed";
1900
- var NO_CHILD_WORK = { branch_name: void 0, pr_state: NO_PR };
1901
- var pr_info_schema = z5.object({ state: z5.string().optional() });
1902
- var GH_PR_STATES = /* @__PURE__ */ new Map([
1903
- ["CLOSED", CLOSED_PR],
1904
- ["MERGED", MERGED_PR],
1905
- ["OPEN", OPEN_PR]
1906
- ]);
1907
- var CLEAN_REASON = "Nothing was left behind: the tree is clean, HEAD is on the default branch, and this issue has no pull request and no branch holding work.";
1908
- var CLEAN_ADVICE = "Start the child.";
1909
- var RESUME_ADVICE = "Reuse the branch and run the whole verification gate from the start \u2014 refactor, `pnpm josh gate`, `/code-review` \u2014 never only the part the interrupted run had not reached. Nobody verified what it already committed.";
1910
- var PARK_ADVICE = "Park the child: add `needs-decision` and comment what was found. Do not delete the branch, do not reopen the pull request, and do not commit on top of it.";
1911
- var STASH_LABEL_PREFIX = "run:hold reclaimed before #";
1912
- var { require_issue_number } = issue_number_shape;
1913
- var UNREADABLE_PR_MESSAGE = "The pull request could not be read for branch ";
1914
- function needs_reclaim(tree) {
1915
- return tree.is_dirty || tree.branch !== tree.default_branch;
1916
- }
1917
- function is_pr_decided(state) {
1918
- return state === MERGED_PR || state === CLOSED_PR;
1919
- }
1920
- function has_leftover_work(child) {
1921
- return child.branch_name !== void 0 || child.pr_state === OPEN_PR;
1922
- }
1923
- function to_verdict(tree, child) {
1924
- if (needs_reclaim(tree)) return RECLAIM_VERDICT;
1925
- if (is_pr_decided(child.pr_state)) return PARK_VERDICT;
1926
- if (has_leftover_work(child)) return RESUME_VERDICT;
1927
- return CLEAN_VERDICT;
1928
- }
1929
- function reclaim_reason(tree) {
1930
- const findings = [
1931
- tree.is_dirty ? "uncommitted changes" : void 0,
1932
- tree.branch === tree.default_branch ? void 0 : `HEAD on ${tree.branch}`
1933
- ].filter((entry) => entry !== void 0);
1934
- return `An earlier run left ${findings.join(" and ")} in this working tree.`;
1935
- }
1936
- function park_reason(state) {
1937
- return `The pull request for this issue is ${state}, so whether any work is still owed is a person's call.`;
1938
- }
1939
- function resume_reason(child) {
1940
- const branch_part = child.branch_name === void 0 ? "" : ` on branch ${child.branch_name}`;
1941
- const pr_part = child.pr_state === OPEN_PR ? ", and its pull request is still open" : "";
1942
- return `An earlier run left a partial implementation${branch_part}${pr_part}.`;
1943
- }
1944
- function to_reason(verdict, tree, child) {
1945
- if (verdict === RECLAIM_VERDICT) return reclaim_reason(tree);
1946
- if (verdict === PARK_VERDICT) return park_reason(child.pr_state);
1947
- if (verdict === RESUME_VERDICT) return resume_reason(child);
1948
- return CLEAN_REASON;
1949
- }
1950
- function reclaim_steps(tree, issue2) {
1951
- if (!tree.is_dirty) return [];
1952
- return [
1953
- `git stash push -u -m "${STASH_LABEL_PREFIX}${issue2}"`,
1954
- `Record the stash on ${session_cite.issue(issue2)} \u2014 the comment is what gets it popped; nothing pops it for you.`
1955
- ];
1956
- }
1957
- function reclaim_advice(tree, issue2) {
1958
- return [
1959
- ...reclaim_steps(tree, issue2),
1960
- "pnpm josh ms",
1961
- "Then ask this command again: it is re-askable, and the clean tree gets its own answer."
1962
- ].join("\n");
1963
- }
1964
- function to_advice(verdict, issue2, tree) {
1965
- if (verdict === RECLAIM_VERDICT) return reclaim_advice(tree, issue2);
1966
- if (verdict === RESUME_VERDICT) return RESUME_ADVICE;
1967
- if (verdict === PARK_VERDICT) return PARK_ADVICE;
1968
- return CLEAN_ADVICE;
1969
- }
1970
- function decide(tree, child, issue2) {
1971
- const verdict = to_verdict(tree, child);
1972
- return {
1973
- advice: to_advice(verdict, issue2, tree),
1974
- reason: to_reason(verdict, tree, child),
1975
- verdict
1976
- };
1977
- }
1978
- function read_pr_field(raw) {
1979
- return json_value.parse_with(raw, pr_info_schema)?.state;
1980
- }
1981
- function to_pr_state2(raw) {
1982
- const state = read_pr_field(raw);
1983
- return (state === void 0 ? void 0 : GH_PR_STATES.get(state)) ?? NO_PR;
1984
- }
1985
- async function read_tree_state() {
1986
- const [is_dirty, current, default_branch] = await Promise.all([
1987
- run_hold.is_tree_dirty(),
1988
- git_command.branch(),
1989
- git_command.get_default_branch()
1990
- ]);
1991
- return { branch: current, default_branch, is_dirty };
1992
- }
1993
- async function read_pr_state(branch_name) {
1994
- if (!await git_gh_pr_read.pr_exists(branch_name)) return NO_PR;
1995
- const raw = await git_gh_pr_read.pr_view(branch_name);
1996
- if (raw === "") throw new Error(`${UNREADABLE_PR_MESSAGE}${branch_name}`);
1997
- return to_pr_state2(raw);
1998
- }
1999
- function is_pr_open(state) {
2000
- return state === OPEN_PR;
2001
- }
2002
- async function read_pr_of_branch(branch_name) {
2003
- return { branch_name, pr_state: await read_pr_state(branch_name) };
2004
- }
2005
- function pick_child_state(reads) {
2006
- const decided = reads.find((read) => is_pr_decided(read.pr_state));
2007
- const open = reads.find((read) => is_pr_open(read.pr_state));
2008
- return decided ?? open ?? { branch_name: reads[0]?.branch_name, pr_state: NO_PR };
2009
- }
2010
- var ISSUE_BRANCH_SUFFIX = "-*";
2011
- var ANY_REMOTE_PREFIX = "*/";
2012
- var REMOTE_SEPARATOR = "/";
2013
- var NOT_FOUND_INDEX = -1;
2014
- function to_head_branch(name) {
2015
- const separator_index = name.indexOf(REMOTE_SEPARATOR);
2016
- return separator_index === NOT_FOUND_INDEX ? name : name.slice(separator_index + 1);
2017
- }
2018
- function group_by_head(pairs) {
2019
- const groups = /* @__PURE__ */ new Map();
2020
- for (const [name, reference2] of pairs) groups.set(name, [...groups.get(name) ?? [], reference2]);
2021
- return groups;
2022
- }
2023
- async function read_branch_candidates(issue2) {
2024
- const pattern = `${issue2}${ISSUE_BRANCH_SUFFIX}`;
2025
- const [local, remote] = await Promise.all([
2026
- git_command.branch_names(pattern),
2027
- git_command.branch_names_remote(`${ANY_REMOTE_PREFIX}${pattern}`)
2028
- ]);
2029
- return group_by_head([
2030
- ...local.map((name) => [name, name]),
2031
- ...remote.map((reference2) => [to_head_branch(reference2), reference2])
2032
- ]);
2033
- }
2034
- async function has_commits_beyond(base, references) {
2035
- const counts = await Promise.all(
2036
- references.map(async (reference2) => await git_command.commit_count_beyond(base, reference2))
2037
- );
2038
- return counts.some((count) => count > 0);
2039
- }
2040
- async function is_held_dirty(name, lane) {
2041
- if (lane?.branch !== name || lane.is_stranded) return false;
2042
- return await run_hold.is_tree_dirty(lane.directory);
2043
- }
2044
- async function read_candidate(name, references, context) {
2045
- const state = await read_pr_of_branch(name);
2046
- if (state.pr_state !== NO_PR || await has_commits_beyond(context.base, references)) return state;
2047
- return await is_held_dirty(name, context.lane) ? state : void 0;
2048
- }
2049
- async function read_child_state(issue2) {
2050
- const candidates = await read_branch_candidates(issue2);
2051
- if (candidates.size === 0) return NO_CHILD_WORK;
2052
- const [base, lane] = await Promise.all([
2053
- git_command.default_branch_reference(),
2054
- lane_registry.find_open_lane(issue2)
2055
- ]);
2056
- const reads = await Promise.all(
2057
- [...candidates].map(
2058
- async ([name, references]) => await read_candidate(name, references, { base, lane })
2059
- )
2060
- );
2061
- return pick_child_state(reads.filter((read) => read !== void 0));
2062
- }
2063
- async function check(issue2) {
2064
- require_issue_number(issue2);
2065
- const tree = await read_tree_state();
2066
- if (needs_reclaim(tree)) return decide(tree, NO_CHILD_WORK, issue2);
2067
- return decide(tree, await read_child_state(issue2), issue2);
2068
- }
2069
- var run_preflight = {
2070
- CLEAN_VERDICT,
2071
- RESUME_ADVICE,
2072
- MERGED_PR,
2073
- STASH_LABEL_PREFIX,
2074
- check,
2075
- decide,
2076
- read_child_state,
2077
- read_pr_state,
2078
- to_pr_state: to_pr_state2
2079
- };
2080
-
2081
- // scripts/run/ship/run-ship-probe.ts
2082
- var REPOSITORY_DIRECTORY_INDEX = 1;
2083
- var REMOTE_SHA_INDEX = 0;
2084
- var REMOTE_FIELD_SEPARATOR = /\s/u;
2085
- var HEAD_REFERENCE = "HEAD";
2086
- async function or_false(is_true) {
2087
- try {
2088
- return await is_true();
2089
- } catch (error) {
2090
- error_text.trace_swallowed("run_ship_probe.or_false", error);
2091
- return false;
2092
- }
2093
- }
2094
- async function read_committed() {
2095
- if (await run_hold.is_tree_dirty()) return false;
2096
- const base = await git_command.default_branch_reference();
2097
- return await git_command.commit_count_beyond(base, HEAD_REFERENCE) > 0;
2098
- }
2099
- async function read_pushed(branch_name) {
2100
- const [remote, head] = await Promise.all([
2101
- git_worktree.ls_remote_branch(branch_name),
2102
- git_command.head_commit()
2103
- ]);
2104
- return remote.split(REMOTE_FIELD_SEPARATOR)[REMOTE_SHA_INDEX] === head;
2105
- }
2106
- async function read_merged(branch_name) {
2107
- if (await run_preflight.read_pr_state(branch_name) !== run_preflight.MERGED_PR) return false;
2108
- const base = await git_command.default_branch_reference();
2109
- return await git_command.commit_count_beyond(base, HEAD_REFERENCE) === 0;
2110
- }
2111
- var NOTHING_DONE = { is_committed: false, is_pushed: false, is_merged: false };
2112
- async function read_branch_state(branch_name) {
2113
- const [is_committed, is_pushed, is_merged2] = await Promise.all([
2114
- or_false(read_committed),
2115
- or_false(async () => await read_pushed(branch_name)),
2116
- or_false(async () => await read_merged(branch_name))
2117
- ]);
2118
- return { is_committed, is_pushed, is_merged: is_merged2 };
2119
- }
2120
- async function read_state() {
2121
- try {
2122
- return await read_branch_state(await git_command.branch());
2123
- } catch {
2124
- return NOTHING_DONE;
2125
- }
2126
- }
2127
- async function repository_directory() {
2128
- try {
2129
- const directories2 = await git_command.git_directories();
2130
- return directories2[REPOSITORY_DIRECTORY_INDEX];
2131
- } catch {
2132
- return void 0;
2133
- }
2134
- }
2135
- async function record_target(issue2) {
2136
- const repository2 = await repository_directory();
2137
- return repository2 === void 0 ? void 0 : run_ship_stage.record_path(repository2, issue2);
2138
- }
2139
- var run_ship_probe = { read_state, record_target, repository_directory };
2140
-
2141
- // scripts/run/ship/run-ship-stop-context.ts
2142
- var EXCERPT_LINE_LIMIT = 40;
2143
- var EXCERPT_LINE_WIDTH = 240;
2144
- var CHANGED_PATH_LIMIT = 30;
2145
- var OUTPUT_PREFIX = "josh-ship-stop-";
2146
- var OUTPUT_SUFFIX = ".log";
2147
- var KEY_SEPARATOR = "-";
2148
- var LINE_BREAK = "\n";
2149
- var CARRIAGE_RETURN = "\r";
2150
- var omitted_schema = z6.object({ path: z6.string().optional(), last_line: z6.number().int() }).strict();
2151
- var stop_context_schema = z6.object({
2152
- excerpt: z6.array(z6.string()).readonly(),
2153
- omitted: omitted_schema.optional(),
2154
- changed: z6.array(z6.string()).readonly().optional(),
2155
- more_changed: z6.number().int()
2156
- }).strict();
2157
- function shown_frame(line) {
2158
- return line.trimEnd().split(CARRIAGE_RETURN).at(-1) ?? "";
2159
- }
2160
- function output_lines(output) {
2161
- return stripVTControlCharacters(output).trimEnd().split(LINE_BREAK).map((line) => agent_role_profile.printable(shown_frame(line)));
2162
- }
2163
- async function keep_full_output(issue2, output) {
2164
- const repository2 = await run_ship_probe.repository_directory();
2165
- if (repository2 === void 0) return void 0;
2166
- const target = stamp_file.stamp_path(
2167
- `${OUTPUT_PREFIX}${issue2}${KEY_SEPARATOR}`,
2168
- repository2,
2169
- OUTPUT_SUFFIX
2170
- );
2171
- try {
2172
- return stamp_file.replace_text_stamp(target, output);
2173
- } catch {
2174
- return void 0;
2175
- }
2176
- }
2177
- async function omitted_range(issue2, lines) {
2178
- const path6 = await keep_full_output(issue2, lines.join(LINE_BREAK));
2179
- const last_line = lines.length - EXCERPT_LINE_LIMIT;
2180
- return path6 === void 0 ? { last_line } : { path: path6, last_line };
2181
- }
2182
- function clipped(lines) {
2183
- return lines.map((line) => line.slice(0, EXCERPT_LINE_WIDTH));
2184
- }
2185
- async function excerpt_of(issue2, output) {
2186
- const lines = output.trim() === "" ? [] : output_lines(output);
2187
- if (lines.length <= EXCERPT_LINE_LIMIT) return { excerpt: clipped(lines) };
2188
- return {
2189
- excerpt: clipped(lines.slice(-EXCERPT_LINE_LIMIT)),
2190
- omitted: await omitted_range(issue2, lines)
2191
- };
2192
- }
2193
- async function read_paths() {
2194
- try {
2195
- return await changed_paths.read_changed_paths(false);
2196
- } catch {
2197
- return void 0;
2198
- }
2199
- }
2200
- async function changed_of() {
2201
- const paths = await read_paths();
2202
- if (paths === void 0) return { more_changed: 0 };
2203
- return {
2204
- changed: paths.slice(0, CHANGED_PATH_LIMIT),
2205
- more_changed: Math.max(0, paths.length - CHANGED_PATH_LIMIT)
2206
- };
2207
- }
2208
- async function build(issue2, output) {
2209
- return { ...await excerpt_of(issue2, output), ...await changed_of() };
2210
- }
2211
- function has_excerpt(context) {
2212
- return context !== void 0 && context.excerpt.length > 0;
2213
- }
2214
- function excerpt_heading(issue2, omitted, shown) {
2215
- if (omitted === void 0) return "The failed stage output:";
2216
- const source = omitted.path ?? `the stopped report (\`${run_ship_next.COMMAND.LOG} ${issue2}\`)`;
2217
- const range = `lines 1-${String(omitted.last_line)} are in ${source}`;
2218
- return `The failed stage output (its last ${String(shown)} lines; ${range}):`;
2219
- }
2220
- function with_dropped(omitted, dropped) {
2221
- if (dropped === 0) return omitted;
2222
- return { ...omitted, last_line: (omitted?.last_line ?? 0) + dropped };
2223
- }
2224
- function excerpt_block(issue2, context, changed, dropped) {
2225
- const shown = context.excerpt.slice(dropped);
2226
- const heading = excerpt_heading(issue2, with_dropped(context.omitted, dropped), shown.length);
2227
- return [heading, ...shown, changed].join(LINE_BREAK);
2228
- }
2229
- function changed_text(context) {
2230
- if (context.changed === void 0) return "The changed files could not be read from git.";
2231
- if (context.changed.length === 0) return "No files changed against the default branch.";
2232
- const more = context.more_changed > 0 ? ` (and ${String(context.more_changed)} more)` : "";
2233
- return `Changed files on the branch: ${context.changed.join(", ")}${more}.`;
2234
- }
2235
- function describe(issue2, context, budget = agent_role_profile.MAX_VALUE_LENGTH) {
2236
- const changed = changed_text(context);
2237
- if (!has_excerpt(context)) return changed;
2238
- let dropped = 0;
2239
- let block = excerpt_block(issue2, context, changed, dropped);
2240
- while (block.length > budget && dropped < context.excerpt.length - 1) {
2241
- dropped += 1;
2242
- block = excerpt_block(issue2, context, changed, dropped);
2243
- }
2244
- return block;
2245
- }
2246
- var run_ship_stop_context = {
2247
- CHANGED_PATH_LIMIT,
2248
- EXCERPT_LINE_LIMIT,
2249
- build,
2250
- describe,
2251
- has_excerpt,
2252
- stop_context_schema
2253
- };
2254
-
2255
- // scripts/lane/lane-child-invocation.ts
2256
- var CHILD_INVOCATION = "fullrun";
2257
- var LINE_BREAK2 = "\n";
2258
- var REVIEW_INVOCATION = "the reviewer of lane";
2259
- var RESUME_GUIDE = ".claude/skills/workflow-commands/pre-gate-cut.md";
2260
- var SHIP_PROCESS = String.raw`(josh(\.[jt]s)? ship|run-ship-cli\.ts)`;
2261
- function child_invocation(issue2) {
2262
- issue_number_shape.require_issue_number(issue2);
2263
- return `${CHILD_INVOCATION} ${issue_cite.plain(issue2)}`;
2264
- }
2265
- function process_pattern(issue2) {
2266
- issue_number_shape.require_issue_number(issue2);
2267
- return `(${CHILD_INVOCATION}|${REVIEW_INVOCATION}|${SHIP_PROCESS} .*) ${issue_cite.plain(issue2)}$`;
2268
- }
2269
- function review_invocation(issue2) {
2270
- issue_number_shape.require_issue_number(issue2);
2271
- return `${REVIEW_INVOCATION} ${issue_cite.plain(issue2)}`;
2272
- }
2273
- function resume_invocation(issue2) {
2274
- const preamble = `Resuming the lane child for issue ${issue_cite.plain(issue2)} \u2014 do not re-read the workflow-commands entry documents (SKILL.md, fullrun.md). Run \`pnpm josh run:cut --resume ${issue2}\` before anything else and follow the matching verdict in ${RESUME_GUIDE}: \`resume\` goes to the gate, \`resume-impl\` continues implementation. Only on \`fresh\` proceed as an ordinary`;
2275
- return `${preamble} ${child_invocation(issue2)}`;
2276
- }
2277
- function outage_resume_invocation(issue2) {
2278
- const preamble = `Resuming the lane child for issue ${issue_cite.plain(issue2)} after an API disconnection \u2014 your session was restored with its full context, so do not re-read the workflow-commands entry documents (SKILL.md, fullrun.md). Continue the run from where it stopped: run \`pnpm josh run:step ${issue2}\` to find the next action, redoing only the last step if it did not complete.`;
2279
- return `${preamble} ${child_invocation(issue2)}`;
2280
- }
2281
- function known_stop_lines(issue2, stop, frame) {
2282
- const { context } = stop;
2283
- const is_excerpted = run_ship_stop_context.has_excerpt(context);
2284
- const next = run_ship_next.next_step(issue2, stop.stage, stop, is_excerpted);
2285
- if (context === void 0) return [next];
2286
- const fixed = [...frame, next].join(LINE_BREAK2).length + LINE_BREAK2.length;
2287
- const budget = agent_role_profile.MAX_VALUE_LENGTH - fixed;
2288
- return [next, run_ship_stop_context.describe(issue2, context, budget)];
2289
- }
2290
- function ship_stop_invocation(issue2, stop) {
2291
- const opening = `Resuming the lane child for issue ${issue_cite.plain(issue2)} after its detached ship supervisor stopped at a failed stage \u2014 do not re-read the workflow-commands entry documents (SKILL.md, fullrun.md).`;
2292
- const closing = `Do not re-plan or re-implement what is already on the branch. ${child_invocation(issue2)}`;
2293
- const middle = stop === void 0 ? [
2294
- `Run \`pnpm josh run:step ${issue2}\` and read the stopped report it names, fix what stopped the ship, then hand the region back per chain-rule.md.`
2295
- ] : known_stop_lines(issue2, stop, [opening, closing]);
2296
- return [opening, ...middle, closing].join(LINE_BREAK2);
2297
- }
2298
- var lane_child_invocation = {
2299
- child_invocation,
2300
- outage_resume_invocation,
2301
- process_pattern,
2302
- resume_invocation,
2303
- review_invocation,
2304
- ship_stop_invocation
2305
- };
2306
-
2307
- // scripts/lane/process-tools.ts
2308
- import path3 from "node:path";
2309
- var NOT_FOUND_CODE = "ENOENT";
2310
- var PACKAGE_HINT = "install the package that provides it (procps on Debian/Ubuntu: `apt-get install procps`)";
2311
- function is_not_found(error) {
2312
- return error instanceof Error && "code" in error && error.code === NOT_FOUND_CODE;
2313
- }
2314
- function missing_notice(command) {
2315
- return `\`${path3.basename(command)}\` is not installed \u2014 kit's lane commands read processes with ps and pgrep; ${PACKAGE_HINT}`;
2316
- }
2317
- function throw_if_missing(command, error) {
2318
- if (is_not_found(error)) throw new Error(missing_notice(command), { cause: error });
2319
- }
2320
- var process_tools = { missing_notice, throw_if_missing };
2321
-
2322
- // scripts/lane/lane-reap.ts
2323
- var PGREP_COMMAND = "pgrep";
2324
- var MATCH_FULL_COMMAND_LINE = "-f";
2325
- var CHILDREN_OF_FLAG = "-P";
2326
- var PS_COMMAND = "/bin/ps";
2327
- var PARENT_FORMAT = ["-o", "ppid=", "-p"];
2328
- var TERMINATE_SIGNAL = "SIGTERM";
2329
- var LOWEST_CHILD_PID = 2;
2330
- function parse_pids(printed) {
2331
- return printed.split("\n").map((line) => Number(line.trim())).filter((pid) => Number.isSafeInteger(pid) && pid >= LOWEST_CHILD_PID);
2332
- }
2333
- function run_probe(command, args) {
2334
- try {
2335
- return execFileSync2(command, [...args], {
2336
- encoding: "utf8",
2337
- timeout: PROBE_TIMEOUT_MS,
2338
- stdio: ["ignore", "pipe", "ignore"]
2339
- });
2340
- } catch (error) {
2341
- process_tools.throw_if_missing(command, error);
2342
- return "";
2343
- }
2344
- }
2345
- function parent_of(pid) {
2346
- return parse_pids(run_probe(PS_COMMAND, [...PARENT_FORMAT, String(pid)]))[0];
2347
- }
2348
- function terminate(pid) {
2349
- try {
2350
- process.kill(pid, TERMINATE_SIGNAL);
2351
- return true;
2352
- } catch {
2353
- return false;
2354
- }
2355
- }
2356
- var SYSTEM_PROBES = {
2357
- matching: (pattern) => parse_pids(run_probe(PGREP_COMMAND, [MATCH_FULL_COMMAND_LINE, pattern])),
2358
- children_of: (pid) => parse_pids(run_probe(PGREP_COMMAND, [CHILDREN_OF_FLAG, String(pid)])),
2359
- parent_of,
2360
- terminate
2361
- };
2362
- function ancestry_of(pid, probes) {
2363
- const ancestry = /* @__PURE__ */ new Set([pid]);
2364
- let current = probes.parent_of(pid);
2365
- while (current !== void 0 && !ancestry.has(current)) {
2366
- ancestry.add(current);
2367
- current = probes.parent_of(current);
2368
- }
2369
- return ancestry;
2370
- }
2371
- function own_ancestry(probes = SYSTEM_PROBES) {
2372
- return ancestry_of(process.pid, probes);
2373
- }
2374
- function tree_of(roots, probes) {
2375
- const tree = [];
2376
- const pending = [...roots];
2377
- let next = pending.shift();
2378
- while (next !== void 0) {
2379
- if (!tree.includes(next)) {
2380
- tree.push(next);
2381
- pending.push(...probes.children_of(next));
2382
- }
2383
- next = pending.shift();
2384
- }
2385
- return tree;
2386
- }
2387
- function roots_of(issue2, own2, probes) {
2388
- const pattern = lane_child_invocation.process_pattern(issue2);
2389
- return probes.matching(pattern).filter((pid) => !own2.has(pid));
2390
- }
2391
- function reap_child(issue2, probes = SYSTEM_PROBES) {
2392
- const own2 = own_ancestry(probes);
2393
- const doomed = tree_of(roots_of(issue2, own2, probes), probes).filter((pid) => !own2.has(pid));
2394
- return doomed.filter((pid) => probes.terminate(pid));
2395
- }
2396
- function is_child_running(issue2, probes = SYSTEM_PROBES) {
2397
- return roots_of(issue2, own_ancestry(probes), probes).length > 0;
2398
- }
2399
- var lane_reap = {
2400
- is_child_running,
2401
- own_ancestry,
2402
- parse_pids,
2403
- reap_child
2404
- };
2405
-
2406
- // scripts/run/run-headless.ts
2407
- var HEADLESS_ENV_KEY = "JOSH_RUN_HEADLESS";
2408
- var HEADLESS_VALUE = "1";
2409
- function environment2() {
2410
- return { [HEADLESS_ENV_KEY]: HEADLESS_VALUE };
2411
- }
2412
- function is_headless2(source = process.env) {
2413
- return source[HEADLESS_ENV_KEY] === HEADLESS_VALUE;
2414
- }
2415
- function is_headless_parent(source) {
2416
- return is_headless2(source) && lane_child_marker.marked_issue(source) === void 0;
2417
- }
2418
- function is_cut_capped(carry, source = process.env) {
2419
- return !is_headless_parent(source) && run_carry.is_at_cut_cap(carry);
2420
- }
2421
- function is_driving(read) {
2422
- return read?.kind === "carried" && read.carry.is_handed_off !== true;
2423
- }
2424
- async function read_carry_here() {
2425
- const repository2 = await run_carry.repository_directory();
2426
- return repository2 === void 0 ? void 0 : run_carry.read_carry(run_carry.carry_path(repository2));
2427
- }
2428
- async function must_keep_waiting(source = process.env) {
2429
- if (!is_headless_parent(source) || !await lane_registry.has_lanes_in_flight()) return false;
2430
- return is_driving(await read_carry_here());
2431
- }
2432
- async function current_carry() {
2433
- const read = await read_carry_here();
2434
- return read?.kind === "carried" ? read.carry : void 0;
2435
- }
2436
- function is_owned_here(carry, ancestry) {
2437
- return carry.owner_pid !== void 0 && ancestry().has(carry.owner_pid);
2438
- }
2439
- function driven_here(read, ancestry) {
2440
- if (read?.kind !== "carried" || !is_driving(read)) return void 0;
2441
- return is_owned_here(read.carry, ancestry) ? read.carry : void 0;
2442
- }
2443
- async function driving_carry(source = process.env, ancestry = lane_reap.own_ancestry) {
2444
- if (lane_child_marker.marked_issue(source) !== void 0) return void 0;
2445
- return driven_here(await read_carry_here(), ancestry);
2446
- }
2447
- async function is_backlog_parent(source = process.env, ancestry = lane_reap.own_ancestry) {
2448
- return await driving_carry(source, ancestry) !== void 0;
2449
- }
2450
- var run_headless = {
2451
- HEADLESS_ENV_KEY,
2452
- current_carry,
2453
- driven_here,
2454
- driving_carry,
2455
- environment: environment2,
2456
- is_backlog_parent,
2457
- is_cut_capped,
2458
- is_headless: is_headless2,
2459
- is_headless_parent,
2460
- is_owned_here,
2461
- must_keep_waiting
2462
- };
2463
-
2464
- // scripts/run/event/run-event-stream.ts
2465
- import { z as z7 } from "zod";
2466
- var EVENT_PREFIX = "josh-run-events-";
2467
- var EVENT_SUFFIX = ".jsonl";
2468
- var EVENT_CAP = 500;
2469
- var FIRST_POSITION = 0;
2470
- var POSITION_INCREMENT = 1;
2471
- var LINE_SEPARATOR = "\n";
2472
- var WORD_SEPARATOR2 = " ";
2473
- var STAGE_PHASE_INDEX = 2;
2474
- var LOCK_SUFFIX = ".lock";
2475
- var LOCK_WAIT_MS = 5e3;
2476
- var EVENT_KIND = {
2477
- PLAN: "plan",
2478
- CHILD_LAUNCH: "child-launch",
2479
- MERGE: "merge",
2480
- PARK: "park",
2481
- SPLIT: "split",
2482
- OUTAGE: "outage",
2483
- CUT: "cut",
2484
- // A fresh session adopted an implementation cut — `run:cut --resume` answered `resume-impl`. The
2485
- // resume clears the cut record, so without this the `cut` would stay the newest position and
2486
- // `run:step` would keep answering the resume command it had just run.
2487
- RESUME: "resume",
2488
- // A person stopped a running lane child and re-dispatched its issue in a fresh session
2489
- // (`lane:restart`). It follows the fresh dispatch's `CHILD_LAUNCH`, so it is a launch to the parent and
2490
- // the board, and — like that launch — a batch record a lane child never reads as its own position.
2491
- RESTART: "restart",
2492
- // A person withdrew a lane child — stopped it and closed its issue as not planned (`lane:withdraw`).
2493
- // It is written before the stop, so `run:merge` settles the child as withdrawn whatever GitHub says
2494
- // by the time the parent collects it, and counts it as neither a merge, a failure nor an outage.
2495
- WITHDRAW: "withdraw",
2496
- // The backlog emptied while nothing of the run's own was in flight — the drain. It marks the position
2497
- // at which the end-of-run retrospective is owed, *before* the idle watch opens, so `run:step` fires
2498
- // the retrospective at the drain rather than after the watch runs its course. It is not itself a
2499
- // stop: the run watches on once the retrospective has run, and the real `STOP` follows when the watch
2500
- // expires.
2501
- DRAIN: "drain",
2502
- STOP: "stop",
2503
- PR_OPENED: "pr-opened",
2504
- REVIEW_ROUND: "review-round",
2505
- // The end-of-run retrospective's result, recorded when the run marks the retrospective done. A
2506
- // retrospective that files zero improvements and one that never ran look
2507
- // the same from outside — no new Issue either way — so the result is put on the stream the report is
2508
- // generated from: the issues filed (or that none were), and the candidates dropped with why. It is
2509
- // emitted from the `run:carry --retrospective` close, so marking the retrospective done and recording
2510
- // what it found are one action rather than two the run could do only one of.
2511
- RETROSPECTIVE: "retrospective",
2512
- // Ready backlog work is sitting undispatched while a lane is free and nothing has dispatched for a
2513
- // while. Emitted once per stall episode by the stop-time detector, it is both the dedup marker —
2514
- // `emit_once_since` refuses a second until a `CHILD_LAUNCH` intervenes — and the line a terminal
2515
- // reader following the stream sees. `run:step` reads it as `backlog:next`, so a run that
2516
- // stalled is pointed straight at dispatching the work rather than left waiting.
2517
- STALL: "stall",
2518
- // The run's own driver is gone: the cut handed the budget off, the owner has died, and no supervisor
2519
- // is watching. Emitted once per strand episode by the stop-time detector — or by the `run:wake`
2520
- // supervisor as it fails, leaves that state behind and has warned of it —
2521
- // exactly as `STALL` is — the newest-event dedup keeps a run polled every stop from notifying more
2522
- // than once, and a terminal reader following the stream sees the line. The strand is the step before
2523
- // the stall: a stalled run still has a driver that could dispatch, a stranded one has none.
2524
- STRANDED: "stranded",
2525
- // One `josh ship` stage starting, succeeding or failing. It is a trace of the
2526
- // composite's progress rather than a position the run is at — the positions a ship leaves behind are
2527
- // the closed issue its `followup` merges, or a detached supervisor's `SHIP_LAUNCH` / `SHIP_STOP` below
2528
- // — so it is one of the `TRACE_KINDS` the last-event read skips.
2529
- SHIP_STAGE: "ship-stage",
2530
- // One progress watcher line — the `at … / next …` heartbeat `run:progress` prints. Printed only to
2531
- // the watcher's own output, a headless successor's heartbeat would be buried in its log after a cut;
2532
- // on the stream it reaches the attached session's relay. It says
2533
- // the run is alive rather than where it is, so it is a trace kind like `SHIP_STAGE`.
2534
- HEARTBEAT: "heartbeat",
2535
- // The post-implementation region handed to a detached `josh ship --detach` supervisor. Unlike a stage
2536
- // trace it is a position: the agent has ended and the
2537
- // supervisor carries the run, so `run:step` answers `wait` until it stops or the issue closes.
2538
- SHIP_LAUNCH: "ship-launch",
2539
- // The supervisor stopped at a failed stage — a red gate, a High/Medium review, a failed push, red CI
2540
- // The position that hands control back: `run:step` prints the command that
2541
- // shows the stopped report, so the agent fixes it and relaunches rather than rebuilding the context.
2542
- SHIP_STOP: "ship-stop",
2543
- // An Issue the run filed on its way, written by `issue:file`, so a run started from the command line
2544
- // still surfaces what it found — `run:board`'s findings section reads it.
2545
- FILED: "filed",
2546
- // A one-line observation short of an Issue, written with `run:event --append note` and shown in the
2547
- // same section.
2548
- NOTE: "note",
2549
- // A lane child reached a phase no other event marks — its first implementation edit, written by the
2550
- // PreToolUse hook — so `run:board` draws how far the child has got. A trace,
2551
- // like `SHIP_STAGE`: it says where the child's work is, not where the run is.
2552
- LANE_PHASE: "lane-phase",
2553
- // An issue `run:add` put into the live run. The parent's `--wait` watcher
2554
- // ends on it, so the issue takes the next free lane without waiting out the arrival probe's minute. A
2555
- // trace: it says what the run was handed, not where the run is.
2556
- ADD: "add",
2557
- // `josh lane:limit` raised a live run's lane limit. The `--wait` watcher's
2558
- // arrival probe reads it as a wake: the lanes a raise frees are new room for a pool its baseline
2559
- // already holds. A trace: it says the run gained room, not where the run is.
2560
- LANE_LIMIT: "lane-limit",
2561
- // One stage of the run's start — the session starting, the plan, the hand-off to the supervisor, a
2562
- // lane opening (`run-event-setup.ts`). `run:board` draws it while the run stands at it, so the
2563
- // minutes before one read as work rather than as a run that has stopped. A trace: it says the run is
2564
- // getting ready, not where the run is.
2565
- SETUP: "setup",
2566
- // A child's pull request checks as `josh followup` last polled them — the CI counts and CodeRabbit's
2567
- // state (`run-event-checks.ts`), written only when they change, so `run:board` draws a child waiting
2568
- // in followup without asking GitHub (joshuafolkken/kit#3770). A trace: it says how the checks stand,
2569
- // not where the run is.
2570
- PR_CHECKS: "pr-checks"
2571
- };
2572
- var EVENT_KINDS = Object.values(EVENT_KIND);
2573
- var TRACE_KINDS = /* @__PURE__ */ new Set([
2574
- EVENT_KIND.SHIP_STAGE,
2575
- EVENT_KIND.HEARTBEAT,
2576
- EVENT_KIND.FILED,
2577
- EVENT_KIND.NOTE,
2578
- EVENT_KIND.LANE_PHASE,
2579
- EVENT_KIND.ADD,
2580
- EVENT_KIND.LANE_LIMIT,
2581
- EVENT_KIND.SETUP,
2582
- EVENT_KIND.PR_CHECKS
2583
- ]);
2584
- var DISPOSABLE_KINDS = /* @__PURE__ */ new Set([
2585
- EVENT_KIND.SHIP_STAGE,
2586
- EVENT_KIND.HEARTBEAT,
2587
- EVENT_KIND.SETUP,
2588
- EVENT_KIND.PR_CHECKS
2589
- ]);
2590
- var event_schema = z7.object({
2591
- pos: z7.number(),
2592
- at: z7.string(),
2593
- kind: z7.string(),
2594
- text: z7.string()
2595
- });
2596
- function is_event_kind(value) {
2597
- return EVENT_KINDS.includes(value);
2598
- }
2599
- function target_of(repository2) {
2600
- return stamp_file.stamp_path(EVENT_PREFIX, repository2, EVENT_SUFFIX);
2601
- }
2602
- function is_present(event) {
2603
- return event !== void 0;
2604
- }
2605
- function parse_line(line) {
2606
- return event_schema.safeParse(json_value.parse_or_undefined(line)).data;
2607
- }
2608
- function read_lines(target) {
2609
- const raw = stamp_file.read_stamp_text(target);
2610
- if (raw === void 0) return [];
2611
- return raw.split(LINE_SEPARATOR).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => parse_line(line)).filter(is_present);
2612
- }
2613
- function read_events(target) {
2614
- return read_lines(target).filter((event) => is_event_kind(event.kind));
2615
- }
2616
- function last_position(events) {
2617
- return events[events.length - POSITION_INCREMENT]?.pos ?? FIRST_POSITION;
2618
- }
2619
- function issue_of(event) {
2620
- return event.text.split(WORD_SEPARATOR2)[FIRST_POSITION] ?? "";
2621
- }
2622
- function newest_by_issue(events, kind) {
2623
- const newest = /* @__PURE__ */ new Map();
2624
- for (const event of events) {
2625
- if (event.kind === kind) newest.set(issue_of(event), event);
2626
- }
2627
- return new Set(newest.values());
2628
- }
2629
- function is_stage_start(event) {
2630
- if (event.kind !== EVENT_KIND.SHIP_STAGE) return false;
2631
- return event.text.split(WORD_SEPARATOR2)[STAGE_PHASE_INDEX] === run_ship_stage.PHASE.START;
2632
- }
2633
- function drawn_lines(events) {
2634
- const setup = events.findLast((event) => event.kind === EVENT_KIND.SETUP);
2635
- return /* @__PURE__ */ new Set([
2636
- ...newest_by_issue(events, EVENT_KIND.SHIP_STAGE),
2637
- ...newest_by_issue(events, EVENT_KIND.PR_CHECKS),
2638
- ...setup === void 0 ? [] : [setup]
2639
- ]);
2640
- }
2641
- function droppable(events) {
2642
- const kept = drawn_lines(events);
2643
- const disposable = events.filter((event) => DISPOSABLE_KINDS.has(event.kind) && !kept.has(event));
2644
- return [
2645
- ...disposable.filter((event) => !is_stage_start(event)),
2646
- ...disposable.filter((event) => is_stage_start(event))
2647
- ];
2648
- }
2649
- function bounded(events) {
2650
- const excess = events.length - EVENT_CAP;
2651
- if (excess <= 0) return events;
2652
- const dropped = new Set(droppable(events).slice(0, excess));
2653
- return events.filter((event) => !dropped.has(event)).slice(-EVENT_CAP);
2654
- }
2655
- function serialize(events) {
2656
- return `${events.map((event) => JSON.stringify(event)).join(LINE_SEPARATOR)}${LINE_SEPARATOR}`;
2657
- }
2658
- function append_held(target, event) {
2659
- const position = last_position(read_lines(target)) + POSITION_INCREMENT;
2660
- const events = bounded([...read_events(target), { pos: position, ...event }]);
2661
- stamp_file.replace_text_stamp(target, serialize(events));
2662
- return position;
2663
- }
2664
- function append(target, kind, text2, at) {
2665
- if (!is_event_kind(kind)) return { appended: false, position: FIRST_POSITION };
2666
- const lock = `${target}${LOCK_SUFFIX}`;
2667
- const position = repository_lock.with_lock_sync(
2668
- () => append_held(target, { at, kind, text: text2 }),
2669
- lock,
2670
- LOCK_WAIT_MS
2671
- );
2672
- if (position === void 0) {
2673
- const message = `run event stream: gave up waiting for the lock at ${lock}`;
2674
- process.stderr.write(`${message}
2675
- `);
2676
- throw new Error(message);
2677
- }
2678
- return { appended: true, position };
2679
- }
2680
- function read_from(target, position) {
2681
- const events = read_events(target);
2682
- return {
2683
- events: events.filter((event) => event.pos > position),
2684
- next_position: last_position(events)
2685
- };
2686
- }
2687
- function read_last(target) {
2688
- return read_events(target).findLast((event) => !TRACE_KINDS.has(event.kind));
2689
- }
2690
- function has_since(events, kind, reset_kind) {
2691
- const reset_at = events.findLastIndex((event) => event.kind === reset_kind);
2692
- return events.slice(reset_at + POSITION_INCREMENT).some((event) => event.kind === kind);
2693
- }
2694
- var FIELD_SEPARATOR = " \xB7 ";
2695
- function format_event(event) {
2696
- return [event.at, event.kind, event.text].join(FIELD_SEPARATOR);
2697
- }
2698
- var run_event_stream = {
2699
- EVENT_CAP,
2700
- EVENT_KIND,
2701
- EVENT_KINDS,
2702
- TRACE_KINDS,
2703
- append,
2704
- format_event,
2705
- has_since,
2706
- is_stage_start,
2707
- read_events,
2708
- read_from,
2709
- read_last,
2710
- target_of
2711
- };
2712
-
2713
- // scripts/run/event/run-event-scope.ts
2714
- var SINCE_SCOPE = "since";
2715
- var UNKNOWN_SCOPE = "unknown";
2716
- var UNKNOWN_EVENT_SCOPE = { kind: UNKNOWN_SCOPE };
2717
- function moment_of(at) {
2718
- const parsed = Date.parse(at);
2719
- return Number.isNaN(parsed) ? void 0 : parsed;
2720
- }
2721
- function is_within(event, floor) {
2722
- const at = moment_of(event.at);
2723
- return at !== void 0 && at >= floor;
2724
- }
2725
- function scoped_events(events, scope) {
2726
- if (scope.kind === UNKNOWN_SCOPE) return void 0;
2727
- const floor = moment_of(scope.started_at);
2728
- if (floor === void 0) return void 0;
2729
- return events.filter((event) => is_within(event, floor));
2730
- }
2731
- function scope_of(read) {
2732
- if (read.kind !== "carried") return UNKNOWN_EVENT_SCOPE;
2733
- return { kind: SINCE_SCOPE, started_at: read.carry.started_at };
2734
- }
2735
- function last_scoped_event(events, scope) {
2736
- return scoped_events(events, scope)?.findLast(
2737
- (event) => !run_event_stream.TRACE_KINDS.has(event.kind)
2738
- );
2739
- }
2740
- var SHIP_POSITION_KINDS = /* @__PURE__ */ new Set([
2741
- run_event_stream.EVENT_KIND.SHIP_LAUNCH,
2742
- run_event_stream.EVENT_KIND.SHIP_STOP
2743
- ]);
2744
- var KIND = run_event_stream.EVENT_KIND;
2745
- var BATCH_RECORD_KINDS = /* @__PURE__ */ new Set([
2746
- KIND.CHILD_LAUNCH,
2747
- KIND.RESTART,
2748
- KIND.WITHDRAW,
2749
- KIND.PARK,
2750
- KIND.SPLIT,
2751
- KIND.RETROSPECTIVE,
2752
- KIND.STRANDED
2753
- ]);
2754
- var ISSUE_REFERENCE = /#(\d+)/u;
2755
- function is_foreign_ship_event(event, issue2) {
2756
- return SHIP_POSITION_KINDS.has(event.kind) && !event.text.startsWith(`${issue_cite.plain(issue2)} `);
2757
- }
2758
- function is_own_ship_event(event, issue2) {
2759
- return SHIP_POSITION_KINDS.has(event.kind) && !is_foreign_ship_event(event, issue2);
2760
- }
2761
- function issue_named(event) {
2762
- return ISSUE_REFERENCE.exec(event.text)?.[1];
2763
- }
2764
- function names_issue(event, issue2) {
2765
- return issue_named(event) === issue2;
2766
- }
2767
- function is_lane_position(event, issue2) {
2768
- return !BATCH_RECORD_KINDS.has(event.kind) && names_issue(event, issue2);
2769
- }
2770
- function since_own_launch(events, issue2) {
2771
- const launch2 = events.findLastIndex(
2772
- (event) => event.kind === KIND.CHILD_LAUNCH && names_issue(event, issue2)
2773
- );
2774
- return events.slice(launch2 + 1);
2775
- }
2776
- function is_foreign_event(event, issue2, is_lane_child) {
2777
- if (is_lane_child) return !is_lane_position(event, issue2);
2778
- return is_foreign_ship_event(event, issue2);
2779
- }
2780
- function last_issue_event(events, scope, issue2, is_lane_child) {
2781
- const attempt = is_lane_child ? since_own_launch(events, issue2) : events;
2782
- const own2 = attempt.filter((event) => !is_foreign_event(event, issue2, is_lane_child));
2783
- if (scope.kind === SINCE_SCOPE) return last_scoped_event(own2, scope);
2784
- return own2.findLast((event) => is_own_ship_event(event, issue2));
2785
- }
2786
- var LAUNCH_OR_SETTLE_KINDS = /* @__PURE__ */ new Set([
2787
- KIND.CHILD_LAUNCH,
2788
- KIND.MERGE,
2789
- KIND.PARK,
2790
- KIND.SPLIT,
2791
- KIND.WITHDRAW
2792
- ]);
2793
- function is_merge_owed(events, scope, issue2) {
2794
- const newest = (scoped_events(events, scope) ?? []).findLast(
2795
- (event) => LAUNCH_OR_SETTLE_KINDS.has(event.kind) && names_issue(event, issue2)
2796
- );
2797
- return newest?.kind === KIND.CHILD_LAUNCH;
2798
- }
2799
- function is_launch_or_withdrawal(event, issue2) {
2800
- const is_kind = event.kind === KIND.CHILD_LAUNCH || event.kind === KIND.WITHDRAW;
2801
- return is_kind && names_issue(event, issue2);
2802
- }
2803
- function is_withdrawn(events, issue2) {
2804
- const newest = events.findLast((event) => is_launch_or_withdrawal(event, issue2));
2805
- return newest?.kind === KIND.WITHDRAW;
2806
- }
2807
- var run_event_scope = {
2808
- UNKNOWN_EVENT_SCOPE,
2809
- is_merge_owed,
2810
- is_withdrawn,
2811
- issue_named,
2812
- last_issue_event,
2813
- last_scoped_event,
2814
- moment_of,
2815
- scope_of,
2816
- scoped_events,
2817
- since_own_launch
2818
- };
2819
-
2820
- // scripts/run/event/run-event-stream-emit.ts
2821
- function now_iso() {
2822
- return (/* @__PURE__ */ new Date()).toISOString();
2823
- }
2824
- async function stream_target() {
2825
- const repository2 = await run_carry.repository_directory();
2826
- return repository2 === void 0 ? void 0 : run_event_stream.target_of(repository2);
2827
- }
2828
- async function emit(kind, text2) {
2829
- try {
2830
- const target = await stream_target();
2831
- if (target === void 0) return;
2832
- run_event_stream.append(target, kind, text2, now_iso());
2833
- } catch {
2834
- }
2835
- }
2836
- async function emit_once(kind, text2) {
2837
- try {
2838
- const target = await stream_target();
2839
- if (target === void 0 || run_event_stream.read_last(target)?.kind === kind) return false;
2840
- return run_event_stream.append(target, kind, text2, now_iso()).appended;
2841
- } catch (error) {
2842
- error_text.trace_swallowed("run_event_stream_emit.emit_once", error);
2843
- return false;
2844
- }
2845
- }
2846
- function invocation_events(repository2, target) {
2847
- const events = run_event_stream.read_events(target);
2848
- const scope = run_event_scope.scope_of(run_carry.read_carry(run_carry.carry_path(repository2)));
2849
- return run_event_scope.scoped_events(events, scope) ?? events;
2850
- }
2851
- async function emit_once_since(kind, text2, reset_kind) {
2852
- try {
2853
- const repository2 = await run_carry.repository_directory();
2854
- if (repository2 === void 0) return false;
2855
- const target = run_event_stream.target_of(repository2);
2856
- if (run_event_stream.has_since(invocation_events(repository2, target), kind, reset_kind)) {
2857
- return false;
2858
- }
2859
- return run_event_stream.append(target, kind, text2, now_iso()).appended;
2860
- } catch (error) {
2861
- error_text.trace_swallowed("run_event_stream_emit.emit_once_since", error);
2862
- return false;
2863
- }
2864
- }
2865
- async function emit_heartbeat(line) {
2866
- await emit(run_event_stream.EVENT_KIND.HEARTBEAT, line);
2867
- }
2868
- async function scoped_current_events() {
2869
- try {
2870
- const repository2 = await run_carry.repository_directory();
2871
- if (repository2 === void 0) return [];
2872
- const read = run_carry.read_carry(run_carry.carry_path(repository2));
2873
- const scope = run_event_scope.scope_of(read);
2874
- const events = run_event_stream.read_events(run_event_stream.target_of(repository2));
2875
- return run_event_scope.scoped_events(events, scope);
2876
- } catch {
2877
- return void 0;
2878
- }
2879
- }
2880
- async function current_events() {
2881
- return await scoped_current_events() ?? [];
2882
- }
2883
- async function invocation_or_all_events() {
2884
- try {
2885
- const repository2 = await run_carry.repository_directory();
2886
- return repository2 === void 0 ? [] : invocation_events(repository2, run_event_stream.target_of(repository2));
2887
- } catch {
2888
- return [];
2889
- }
2890
- }
2891
- async function all_events() {
2892
- try {
2893
- const target = await stream_target();
2894
- return target === void 0 ? [] : run_event_stream.read_events(target);
2895
- } catch {
2896
- return [];
2897
- }
2898
- }
2899
- var run_event_stream_emit = {
2900
- all_events,
2901
- current_events,
2902
- emit,
2903
- emit_heartbeat,
2904
- emit_once,
2905
- emit_once_since,
2906
- invocation_or_all_events,
2907
- scoped_current_events,
2908
- stream_target
2909
- };
2910
-
2911
- // scripts/run/detached-launch.ts
2912
- import { spawn } from "node:child_process";
2913
- import { closeSync, constants, openSync, writeSync } from "node:fs";
2914
-
2915
- // scripts/agent/agent-launch-environment.ts
2916
- import { existsSync as existsSync3, lstatSync, mkdirSync, readlinkSync, symlinkSync, unlinkSync } from "node:fs";
2917
- import path5 from "node:path";
2918
-
2919
- // scripts/gh/gh-cli-token.ts
2920
- import { execaSync as execaSync2 } from "execa";
2921
- var GH_CLI_TIMEOUT_MS = 5e3;
2922
- function get() {
2923
- try {
2924
- const { stdout } = execaSync2("gh", ["auth", "token"], { timeout: GH_CLI_TIMEOUT_MS });
2925
- const token = stdout.trim();
2926
- return token.length > 0 ? token : void 0;
2927
- } catch {
2928
- return void 0;
2929
- }
2930
- }
2931
- var gh_cli_token = { get };
2932
-
2933
- // scripts/agent/codex-home-source.ts
2934
- import os from "node:os";
2935
- import path4 from "node:path";
2936
- function default_home() {
2937
- return path4.join(os.homedir(), ".codex");
2938
- }
2939
- var codex_home_source = { default_home };
2940
-
2941
- // scripts/agent/agent-launch-environment.ts
2942
- var OPENAI_PROVIDER = "openai";
2943
- var REVIEWER_HOME = ["node_modules", ".cache", "josh", "openai", "reviewer-home"];
2944
- var HOME_FILES = ["auth.json", "config.toml"];
2945
- var PRIVATE_DIRECTORY_MODE = 448;
2946
- function openai_environment() {
2947
- const token = gh_cli_token.get();
2948
- return token === void 0 ? { TMPDIR: PLATFORM_TEMP_ROOT } : { GH_TOKEN: token, TMPDIR: PLATFORM_TEMP_ROOT };
2949
- }
2950
- function remove_old_home_link(source, target) {
2951
- const current = lstatSync(target, { throwIfNoEntry: false });
2952
- if (current === void 0) return false;
2953
- if (!current.isSymbolicLink()) throw new Error(`Reviewer home file is not a link: ${target}`);
2954
- if (existsSync3(source) && readlinkSync(target) === source) return true;
2955
- unlinkSync(target);
2956
- return false;
2957
- }
2958
- function link_home_file(source_home, target_home, name) {
2959
- const source = path5.join(source_home, name);
2960
- const target = path5.join(target_home, name);
2961
- if (!remove_old_home_link(source, target) && existsSync3(source)) symlinkSync(source, target);
2962
- }
2963
- function reviewer_home(cwd, environment3) {
2964
- const source = environment3["CODEX_HOME"] ?? process.env["CODEX_HOME"] ?? codex_home_source.default_home();
2965
- const target = path5.resolve(cwd, ...REVIEWER_HOME);
2966
- mkdirSync(target, { recursive: true, mode: PRIVATE_DIRECTORY_MODE });
2967
- for (const name of HOME_FILES) link_home_file(source, target, name);
2968
- return target;
2969
- }
2970
- function build2(cwd, profile, environment3 = {}) {
2971
- if (profile === void 0) return environment3;
2972
- const marked = {
2973
- ...agent_headless.environment(),
2974
- ...agent_session_role.env_for(profile.role),
2975
- ...environment3
2976
- };
2977
- if (profile.provider !== OPENAI_PROVIDER) return marked;
2978
- const base = { ...openai_environment(), ...marked };
2979
- return profile.role === agent_role_profile.REVIEWER ? { ...base, CODEX_HOME: reviewer_home(cwd, environment3) } : base;
2980
- }
2981
- var agent_launch_environment = { build: build2 };
2982
-
2983
- // scripts/run/launch-priority.ts
2984
- import { setPriority } from "node:os";
2985
- var LANE_NICENESS = 10;
2986
- function lower(pid, set_priority = setPriority) {
2987
- if (pid === void 0) return;
2988
- try {
2989
- set_priority(pid, LANE_NICENESS);
2990
- } catch {
2991
- }
2992
- }
2993
- var launch_priority = {
2994
- LANE_NICENESS,
2995
- lower
2996
- };
2997
-
2998
- // scripts/run/detached-launch.ts
2999
- var NO_PID_NOTE = "the process started without a pid";
3000
- var UNSAFE_NOTE = "the wake command or its arguments contain characters that are not safe to execute";
3001
- var { is_safe_prompt, is_safe_value } = agent_role_profile;
3002
- var LAST = -1;
3003
- function is_safe_element(argv, value, index) {
3004
- const is_prompt = argv.ends_with_prompt === true && index === argv.args.length + LAST;
3005
- return is_prompt ? is_safe_prompt(value) : is_safe_value(value);
3006
- }
3007
- function is_safe_argv(argv) {
3008
- return is_safe_value(argv.command) && argv.args.every((value, index) => is_safe_element(argv, value, index));
3009
- }
3010
- function note_of(error) {
3011
- return error instanceof Error ? error.message : JSON.stringify(error);
3012
- }
3013
- function launched(pid) {
3014
- return { kind: "launched", pid };
3015
- }
3016
- var LOG_FLAGS = constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | constants.O_NOFOLLOW;
3017
- var LOG_MODE = 384;
3018
- function profile_suffix(profile) {
3019
- return profile === void 0 ? "" : ` \xB7 ${agent_role_profile.describe(profile)}`;
3020
- }
3021
- function log_header(argv, profile) {
3022
- const stamp = (/* @__PURE__ */ new Date()).toISOString();
3023
- return `
3024
- === ${stamp} \xB7 started by process ${String(process.pid)} \xB7 ${argv.command}${profile_suffix(profile)} ===
3025
- `;
3026
- }
3027
- function opened_log(log_path, on_error) {
3028
- const descriptor = openSync(log_path, LOG_FLAGS, LOG_MODE);
3029
- if (!stamp_file.is_own_regular_file(log_path)) {
3030
- closeSync(descriptor);
3031
- on_error(`${log_path} is not this account's own file, so nothing is kept there`);
3032
- return void 0;
3033
- }
3034
- return descriptor;
3035
- }
3036
- function stamped(descriptor, argv, profile, on_error) {
3037
- if (descriptor === void 0) return;
3038
- try {
3039
- writeSync(descriptor, log_header(argv, profile));
3040
- } catch (error) {
3041
- on_error(`the session log could not be written: ${note_of(error)}`);
3042
- }
3043
- }
3044
- function open_log(log_path, on_error) {
3045
- if (log_path === void 0) return void 0;
3046
- try {
3047
- return opened_log(log_path, on_error);
3048
- } catch (error) {
3049
- on_error(`the session log at ${log_path} could not be opened: ${note_of(error)}`);
3050
- return void 0;
3051
- }
3052
- }
3053
- function ensure_log(log_path, on_error) {
3054
- const descriptor = open_log(log_path, on_error);
3055
- if (descriptor !== void 0) closeSync(descriptor);
3056
- }
3057
- function spawn_options(cwd, log, environment3 = {}, is_detached = true) {
3058
- return {
3059
- cwd,
3060
- detached: is_detached,
3061
- stdio: log === void 0 ? "ignore" : ["ignore", log, log],
3062
- env: { ...process.env, ...agent_session_environment.removed_environment(), ...environment3 }
3063
- };
3064
- }
3065
- function notify_spawn(pid, on_spawn, on_error) {
3066
- if (pid === void 0) return;
3067
- try {
3068
- on_spawn(pid);
3069
- } catch (error) {
3070
- on_error(`the child state could not be recorded: ${note_of(error)}`);
3071
- }
3072
- }
3073
- async function attached_spawn(request, log, on_error, on_spawn) {
3074
- return await new Promise((resolve2) => {
3075
- const environment3 = agent_launch_environment.build(request.cwd, request.profile, request.env);
3076
- const child = spawn(
3077
- request.argv.command,
3078
- [...request.argv.args],
3079
- spawn_options(request.cwd, log, environment3, false)
3080
- );
3081
- child.once("error", (error) => {
3082
- on_error(note_of(error));
3083
- resolve2({ kind: "failed", note: note_of(error) });
3084
- });
3085
- child.once("exit", (exit_code) => {
3086
- resolve2({ kind: "completed", pid: child.pid ?? 0, exit_code });
3087
- });
3088
- launch_priority.lower(child.pid);
3089
- notify_spawn(child.pid, on_spawn, on_error);
3090
- });
3091
- }
3092
- function ignore_spawn(_pid) {
3093
- }
3094
- function spawned(request, log, on_error) {
3095
- const { command, args } = request.argv;
3096
- const environment3 = agent_launch_environment.build(request.cwd, request.profile, request.env);
3097
- const child = spawn(command, [...args], spawn_options(request.cwd, log, environment3));
3098
- child.on("error", (error) => {
3099
- on_error(note_of(error));
3100
- });
3101
- child.unref();
3102
- launch_priority.lower(child.pid);
3103
- return child.pid === void 0 ? { kind: "failed", note: NO_PID_NOTE } : launched(child.pid);
3104
- }
3105
- function launch(request, on_error) {
3106
- if (!is_safe_argv(request.argv)) return { kind: "failed", note: UNSAFE_NOTE };
3107
- const log = open_log(request.log_path, on_error);
3108
- try {
3109
- stamped(log, request.argv, request.profile, on_error);
3110
- return spawned(request, log, on_error);
3111
- } catch (error) {
3112
- return { kind: "failed", note: note_of(error) };
3113
- } finally {
3114
- if (log !== void 0) closeSync(log);
3115
- }
3116
- }
3117
- async function launch_attached(request, on_error, on_spawn = ignore_spawn) {
3118
- if (!is_safe_argv(request.argv)) return { kind: "failed", note: UNSAFE_NOTE };
3119
- const log = open_log(request.log_path, on_error);
3120
- try {
3121
- stamped(log, request.argv, request.profile, on_error);
3122
- return await attached_spawn(request, log, on_error, on_spawn);
3123
- } catch (error) {
3124
- return { kind: "failed", note: note_of(error) };
3125
- } finally {
3126
- if (log !== void 0) closeSync(log);
3127
- }
3128
- }
3129
- var detached_launch = {
3130
- UNSAFE_NOTE,
3131
- ensure_log,
3132
- is_safe_argv,
3133
- is_safe_value,
3134
- launch,
3135
- launch_attached,
3136
- log_header,
3137
- note_of
3138
- };
3139
-
3140
- export {
3141
- FULL_PAGE_QUERY,
3142
- git_gh_api_path,
3143
- parse_json_array_or_undefined,
3144
- read_json_listing,
3145
- parse_json_object_or_undefined,
3146
- gh_failure,
3147
- has_stderr_field,
3148
- has_stdout_field,
3149
- git_gh_exec,
3150
- git_gh_helpers,
3151
- MERGED_STATE,
3152
- to_gh_state,
3153
- repo_origin,
3154
- repo_discovery,
3155
- issue_cite,
3156
- issue_citation,
3157
- session_cite,
3158
- git_common_directory,
3159
- repository_lock,
3160
- run_event_stream,
3161
- run_event_scope,
3162
- run_event_stream_emit,
3163
- stamp_record,
3164
- git_worktree,
3165
- run_hold,
3166
- git_gh_pr_rest,
3167
- forget_pr_numbers,
3168
- require_pr_number,
3169
- read_pull,
3170
- git_gh_pr_read,
3171
- lane_registry,
3172
- run_preflight,
3173
- lane_child_invocation,
3174
- agent_headless,
3175
- detached_launch,
3176
- session_language,
3177
- process_tools,
3178
- lane_reap,
3179
- run_headless
3180
- };