@joshuafolkken/kit 1.1514.0 → 1.2114.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1176) hide show
  1. package/.claude/agents/investigator.md +1 -1
  2. package/.claude/agents/reviewer-verification.md +19 -0
  3. package/.claude/agents/reviewer.md +19 -0
  4. package/.claude/settings.json +5 -6
  5. package/.claude/skills/dependency-update/SKILL.md +9 -10
  6. package/.claude/skills/epic-commands/SKILL.md +26 -65
  7. package/.claude/skills/epic-commands/epic-bundle.md +3 -1
  8. package/.claude/skills/workflow-commands/SKILL.md +11 -11
  9. package/.claude/skills/workflow-commands/background-commands.md +13 -10
  10. package/.claude/skills/workflow-commands/backlogrun-child.md +12 -8
  11. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
  12. package/.claude/skills/workflow-commands/backlogrun-lanes.md +18 -14
  13. package/.claude/skills/workflow-commands/backlogrun-park.md +18 -24
  14. package/.claude/skills/workflow-commands/backlogrun-progress.md +4 -5
  15. package/.claude/skills/workflow-commands/backlogrun-recovery.md +6 -6
  16. package/.claude/skills/workflow-commands/backlogrun-steps.md +12 -11
  17. package/.claude/skills/workflow-commands/backlogrun.md +1 -1
  18. package/.claude/skills/workflow-commands/chain-rule.md +43 -28
  19. package/.claude/skills/workflow-commands/delegation.md +11 -10
  20. package/.claude/skills/workflow-commands/entry-sequence.md +10 -10
  21. package/.claude/skills/workflow-commands/followup.md +16 -36
  22. package/.claude/skills/workflow-commands/fullrun-steps.md +38 -47
  23. package/.claude/skills/workflow-commands/fullrun.md +3 -3
  24. package/.claude/skills/workflow-commands/halfrun.md +17 -25
  25. package/.claude/skills/workflow-commands/issue-comments.md +25 -16
  26. package/.claude/skills/workflow-commands/issue-fold-existing.md +2 -1
  27. package/.claude/skills/workflow-commands/issue-scout.md +2 -2
  28. package/.claude/skills/workflow-commands/kickoff.md +24 -23
  29. package/.claude/skills/workflow-commands/latest-gate.md +7 -12
  30. package/.claude/skills/workflow-commands/needs-human-review.md +9 -14
  31. package/.claude/skills/workflow-commands/observation-filing.md +4 -36
  32. package/.claude/skills/workflow-commands/observation-ledger.md +6 -4
  33. package/.claude/skills/workflow-commands/pre-gate-cut.md +22 -37
  34. package/.claude/skills/workflow-commands/prerequisite.md +11 -16
  35. package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
  36. package/.claude/skills/workflow-commands/prrun.md +3 -7
  37. package/.claude/skills/workflow-commands/retrospective.md +2 -2
  38. package/.claude/skills/workflow-commands/split-assessment.md +15 -1
  39. package/.claude/skills/workflow-commands/working-tree-hold.md +9 -9
  40. package/.codex/hooks.json +5 -5
  41. package/.github/actions/setup-node/action.yml +9 -0
  42. package/.github/actions/setup-pnpm/action.yml +10 -17
  43. package/.github/dependabot.yml +32 -0
  44. package/.github/release.yml +0 -2
  45. package/.github/workflows/auto-tag.yml +45 -0
  46. package/.github/workflows/ci.yml +267 -17
  47. package/.github/workflows/dependabot-auto-merge.yml +63 -4
  48. package/.github/workflows/production.yml +8 -0
  49. package/.github/workflows/publish.yml +67 -46
  50. package/.github/workflows/sonar-qube.yml +1 -0
  51. package/.prettierignore +2 -0
  52. package/.vscode/settings.json +19 -0
  53. package/.vscode/tasks.json +1 -2
  54. package/CLAUDE.md +7 -18
  55. package/README.md +4 -2
  56. package/SECURITY.md +3 -3
  57. package/dist/CLAUDE.md +7 -18
  58. package/dist/commands/document-read-cli.js +883 -0
  59. package/dist/commands/{document-section-cli.js → document-section-main.js} +81 -38
  60. package/dist/commands/read-set-cli.js +1927 -0
  61. package/dist/commands/run-prep-main.js +21174 -0
  62. package/dist/commands/run-step-cli.js +27733 -0
  63. package/dist/config-merge/index.js +5 -1
  64. package/dist/hooks/audit-provision.js +39 -36
  65. package/dist/hooks/chunk-3GKE653K.js +6204 -0
  66. package/dist/hooks/chunk-45CJJOO7.js +1243 -0
  67. package/dist/hooks/chunk-5PM2JRGV.js +7780 -0
  68. package/dist/hooks/chunk-7SIUNQXK.js +3591 -0
  69. package/dist/hooks/chunk-CQD4LJE6.js +4858 -0
  70. package/dist/hooks/{chunk-723HKZO5.js → chunk-OPSRGWFU.js} +1 -1
  71. package/dist/hooks/chunk-UJ3FPMMM.js +628 -0
  72. package/dist/hooks/chunk-VVNYJWEI.js +30 -0
  73. package/dist/hooks/chunk-Z6DQJKH3.js +2806 -0
  74. package/dist/hooks/codex-hook-adapter.js +10 -22
  75. package/dist/hooks/format-edited.js +4 -6
  76. package/dist/hooks/inputs.json +460 -308
  77. package/dist/hooks/pretool-guard.js +8 -25
  78. package/dist/hooks/session-lang.js +135 -299
  79. package/dist/hooks/stop-guard.js +6496 -1799
  80. package/dist/josh.js +7412 -4228
  81. package/dist/self-sync-guard/index.js +74 -10
  82. package/dist/version/index.js +276 -407
  83. package/eslint/base.js +1 -1
  84. package/eslint/rules/comment-why-only.js +108 -0
  85. package/lefthook/base.yml +3 -1
  86. package/package.json +23 -54
  87. package/pnpm-workspace.yaml +4 -2
  88. package/prompts/coding-standards.md +2 -2
  89. package/prompts/collaboration-workflow/file-edits.md +14 -17
  90. package/prompts/collaboration-workflow/issue-citation.md +0 -4
  91. package/prompts/collaboration-workflow/issue-template.md +54 -18
  92. package/prompts/collaboration-workflow/lane-instructions.md +3 -2
  93. package/prompts/collaboration-workflow/measurement.md +44 -0
  94. package/prompts/collaboration-workflow/operating-rules.md +15 -8
  95. package/prompts/collaboration-workflow/output-bounds.md +6 -7
  96. package/prompts/collaboration-workflow/plan-comment.md +3 -42
  97. package/prompts/collaboration-workflow/principles.md +14 -0
  98. package/prompts/collaboration-workflow/report-format.md +31 -60
  99. package/prompts/collaboration-workflow/residency.md +3 -2
  100. package/prompts/collaboration-workflow/rule-delivery.md +13 -1
  101. package/prompts/collaboration-workflow/shell-body.md +6 -16
  102. package/prompts/collaboration-workflow/turn-batching.md +0 -2
  103. package/prompts/collaboration-workflow/upstream-interrupt.md +15 -5
  104. package/prompts/collaboration-workflow/wip-cap.md +4 -2
  105. package/prompts/collaboration-workflow.md +3 -7
  106. package/prompts/refactoring.md +1 -1
  107. package/prompts/review-rubric.md +9 -2
  108. package/prompts/review.md +65 -36
  109. package/prompts/testing-guide.md +9 -43
  110. package/scripts/agent/agent-argv.ts +14 -16
  111. package/scripts/agent/agent-event.ts +15 -15
  112. package/scripts/agent/agent-exit-record.ts +13 -1
  113. package/scripts/agent/agent-provider.ts +138 -0
  114. package/scripts/agent/agent-role-profile.ts +108 -156
  115. package/scripts/agent/agent-safe-text.ts +20 -5
  116. package/scripts/agent/api-auth.ts +41 -0
  117. package/scripts/agent/api-outage.ts +1 -1
  118. package/scripts/agent/api-usage-limit.ts +65 -0
  119. package/scripts/agent/claude-agent-argv.ts +19 -9
  120. package/scripts/agent/codex-agent-argv.ts +118 -22
  121. package/scripts/agent/usage-limit-reset.ts +179 -0
  122. package/scripts/auth/claude-token-output.ts +2 -2
  123. package/scripts/auto-ok/auto-ok-author.ts +53 -0
  124. package/scripts/auto-ok/auto-ok-cli.ts +25 -16
  125. package/scripts/auto-ok/auto-ok-judge-read.ts +12 -3
  126. package/scripts/auto-ok/auto-ok-judge-write.ts +46 -19
  127. package/scripts/auto-ok/auto-ok-judge.ts +13 -2
  128. package/scripts/auto-ok/auto-ok-main.ts +17 -0
  129. package/scripts/backlog/backlog-arrival.ts +14 -3
  130. package/scripts/backlog/backlog-budget-cli.ts +7 -33
  131. package/scripts/backlog/backlog-budget-main.ts +16 -0
  132. package/scripts/backlog/backlog-budget.ts +2 -3
  133. package/scripts/backlog/backlog-defect-priority.ts +5 -4
  134. package/scripts/backlog/backlog-drive-adopt.ts +67 -0
  135. package/scripts/backlog/backlog-drive-args.ts +4 -5
  136. package/scripts/backlog/backlog-drive-cli.ts +118 -28
  137. package/scripts/backlog/backlog-drive-hold.ts +162 -0
  138. package/scripts/backlog/backlog-drive-idle.ts +161 -0
  139. package/scripts/backlog/backlog-drive-judge.ts +25 -0
  140. package/scripts/backlog/backlog-drive-launch-pass.ts +90 -0
  141. package/scripts/backlog/backlog-drive-launch.ts +8 -2
  142. package/scripts/backlog/backlog-drive-memory.ts +126 -0
  143. package/scripts/backlog/backlog-drive-named-offer.ts +73 -35
  144. package/scripts/backlog/backlog-drive-named.ts +81 -13
  145. package/scripts/backlog/backlog-drive-offer-argv.ts +3 -8
  146. package/scripts/backlog/backlog-drive-paused.ts +170 -0
  147. package/scripts/backlog/backlog-drive-restore.ts +39 -8
  148. package/scripts/backlog/backlog-drive-seats.ts +18 -8
  149. package/scripts/backlog/backlog-drive-token-handling.ts +38 -0
  150. package/scripts/backlog/backlog-drive.ts +96 -131
  151. package/scripts/backlog/backlog-gate-scope.ts +61 -0
  152. package/scripts/backlog/backlog-measure-close.ts +112 -0
  153. package/scripts/backlog/backlog-next-main.ts +16 -0
  154. package/scripts/backlog/backlog-next-shared.ts +73 -0
  155. package/scripts/backlog/backlog-next.ts +78 -56
  156. package/scripts/backlog/backlog-occupied.ts +52 -39
  157. package/scripts/backlog/backlog-offer-cli.ts +6 -21
  158. package/scripts/backlog/backlog-offer-exclude.ts +15 -0
  159. package/scripts/backlog/backlog-offer-main.ts +12 -0
  160. package/scripts/backlog/backlog-offer.ts +36 -3
  161. package/scripts/backlog/backlog-overlap.ts +62 -10
  162. package/scripts/backlog/backlog-plan-cli.ts +4 -1
  163. package/scripts/backlog/backlog-plan-comment.ts +81 -0
  164. package/scripts/backlog/backlog-plan-read.ts +22 -5
  165. package/scripts/backlog/backlog-plan.ts +18 -4
  166. package/scripts/backlog/backlog-pool.ts +60 -22
  167. package/scripts/backlog/backlog-rank.ts +70 -15
  168. package/scripts/backlog/backlog-ready.ts +112 -30
  169. package/scripts/backlog/backlog-stalled-detect.ts +110 -36
  170. package/scripts/backlog/backlog-stalled.ts +52 -16
  171. package/scripts/backlog/backlog-wait-cause.ts +86 -0
  172. package/scripts/backlog/backlog-waves.ts +56 -15
  173. package/scripts/backlog/backlogrun-args.ts +19 -7
  174. package/scripts/backlog/backlogrun-cli.ts +19 -5
  175. package/scripts/backlog/backlogrun-launch.ts +13 -4
  176. package/scripts/backlog/backlogrun-restart.ts +97 -0
  177. package/scripts/backlog/backlogrun-stop.ts +79 -7
  178. package/scripts/behavior/behavior-cli.ts +2 -2
  179. package/scripts/behavior/behavior-rules.ts +47 -24
  180. package/scripts/build/build-bin.ts +2 -16
  181. package/scripts/build/build-claude-md.ts +0 -7
  182. package/scripts/build/build-commands.ts +0 -13
  183. package/scripts/build/build-hooks.ts +49 -48
  184. package/scripts/build/hook-bundle-stamp.ts +29 -11
  185. package/scripts/build/local-bin.ts +1 -1
  186. package/scripts/cases/cases-cli.ts +25 -13
  187. package/scripts/cases/cases-interaction-scan.ts +134 -0
  188. package/scripts/cases/cases-interaction.ts +183 -0
  189. package/scripts/cases/cases-logic.ts +39 -6
  190. package/scripts/ci/pr-classification-main.ts +18 -0
  191. package/scripts/ci/pr-classification.ts +10 -17
  192. package/scripts/clone/clone-scan.ts +1 -1
  193. package/scripts/cost-runtime/context-cut-payback.ts +27 -25
  194. package/scripts/cost-runtime/cost-blocks.ts +22 -37
  195. package/scripts/cost-runtime/cost-cli.ts +67 -29
  196. package/scripts/cost-runtime/cost-main.ts +12 -0
  197. package/scripts/cost-runtime/cost-pricing.ts +9 -0
  198. package/scripts/cost-runtime/cost-transcript.ts +1 -0
  199. package/scripts/cost-runtime/cost-verdict.ts +4 -1
  200. package/scripts/delegation/delegation-policy.ts +18 -5
  201. package/scripts/delegation/duplicate-read-guard.ts +1 -8
  202. package/scripts/delegation/investigation-guard.ts +12 -8
  203. package/scripts/delegation/investigation-reads.ts +48 -27
  204. package/scripts/dependabot/dependabot-cooldown.ts +195 -0
  205. package/scripts/discovery/repo-discovery.ts +24 -6
  206. package/scripts/discovery/repo-party.ts +80 -20
  207. package/scripts/discovery/session-owner-pin.ts +51 -0
  208. package/scripts/doctor/doctor-consumer.ts +2 -5
  209. package/scripts/document/capped-print.ts +1 -1
  210. package/scripts/document/command-reference-line-budget.ts +42 -0
  211. package/scripts/document/document-byte-budget.ts +18 -6
  212. package/scripts/document/document-checks.ts +20 -0
  213. package/scripts/document/document-ratchet-check.ts +101 -0
  214. package/scripts/document/document-scan.ts +1 -1
  215. package/scripts/document/document-section-cli.ts +0 -8
  216. package/scripts/document/document-section-main.ts +12 -0
  217. package/scripts/document/document-section.ts +1 -0
  218. package/scripts/document/entry-read-budget.ts +7 -3
  219. package/scripts/document/issue-citation-budget.ts +94 -0
  220. package/scripts/epic/epic-audit-cli.ts +12 -6
  221. package/scripts/epic/epic-bundle-apply.ts +137 -0
  222. package/scripts/epic/epic-bundle-cli.ts +32 -121
  223. package/scripts/epic/epic-bundle-format.ts +116 -0
  224. package/scripts/epic/epic-bundle-main.ts +17 -0
  225. package/scripts/epic/epic-busy.ts +5 -12
  226. package/scripts/epic/epic-classify.ts +24 -15
  227. package/scripts/epic/epic-cli-argv.ts +33 -2
  228. package/scripts/epic/epic-cli-decide.ts +42 -0
  229. package/scripts/epic/epic-cli.ts +6 -38
  230. package/scripts/epic/epic-close.ts +112 -55
  231. package/scripts/epic/epic-cross-repo.ts +4 -7
  232. package/scripts/epic/epic-decide.ts +119 -0
  233. package/scripts/epic/epic-decision.ts +9 -0
  234. package/scripts/epic/epic-fetch.ts +6 -0
  235. package/scripts/epic/epic-graph.ts +8 -1
  236. package/scripts/epic/epic-issue.ts +8 -2
  237. package/scripts/epic/epic-label-age.ts +1 -1
  238. package/scripts/epic/epic-lane-offer.ts +39 -4
  239. package/scripts/epic/epic-next-main.ts +24 -0
  240. package/scripts/epic/epic-next.ts +6 -24
  241. package/scripts/epic/epic-outside-blocker.ts +6 -2
  242. package/scripts/epic/epic-parse.ts +9 -3
  243. package/scripts/epic/epic-rank.ts +5 -0
  244. package/scripts/epic/epic-read.ts +1 -0
  245. package/scripts/epic/epic-reconcile.ts +39 -0
  246. package/scripts/epic/epic-run.ts +10 -1
  247. package/scripts/epic/epic-solo.ts +50 -14
  248. package/scripts/epic/epic.ts +41 -7
  249. package/scripts/exports/unused-members-check.ts +62 -0
  250. package/scripts/exports/unused-members-cli.ts +6 -51
  251. package/scripts/followup/followup-checks-event.ts +8 -3
  252. package/scripts/followup/followup-ci-path.ts +67 -0
  253. package/scripts/followup/followup-coderabbit-retrigger.ts +261 -0
  254. package/scripts/followup/followup-coderabbit-wait.ts +85 -0
  255. package/scripts/followup/followup-failed-tests.ts +160 -0
  256. package/scripts/followup/followup-job-needs.ts +100 -0
  257. package/scripts/followup/followup-job-rerun.ts +303 -0
  258. package/scripts/followup/followup-main-move.ts +113 -0
  259. package/scripts/followup/followup-review-gates.ts +81 -0
  260. package/scripts/followup/git-followup-finish.ts +43 -11
  261. package/scripts/followup/git-followup-pending.ts +3 -3
  262. package/scripts/followup/git-followup-stages.ts +52 -12
  263. package/scripts/followup/git-followup-workflow.ts +19 -66
  264. package/scripts/followup/git-pr-followup-checks.ts +55 -16
  265. package/scripts/followup/git-pr-followup-wrapup.ts +32 -18
  266. package/scripts/followup/git-pr-followup.ts +96 -33
  267. package/scripts/fresh-machine/fresh-machine-cli.ts +1 -1
  268. package/scripts/fresh-machine/fresh-machine-run.ts +8 -8
  269. package/scripts/fresh-machine/fresh-machine-script.ts +5 -9
  270. package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +2 -2
  271. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +3 -3
  272. package/scripts/gate/busy-average.ts +90 -0
  273. package/scripts/gate/check-cpu.ts +60 -0
  274. package/scripts/gate/check-inputs.ts +39 -95
  275. package/scripts/gate/check-related-pinned.ts +43 -0
  276. package/scripts/gate/check-related-reuse.ts +64 -0
  277. package/scripts/gate/check-related-section.ts +57 -0
  278. package/scripts/gate/check-related-unplanned.ts +34 -0
  279. package/scripts/gate/check-related.ts +265 -0
  280. package/scripts/gate/check-reuse.ts +33 -54
  281. package/scripts/gate/command-memory.ts +192 -0
  282. package/scripts/gate/core-admission.ts +236 -28
  283. package/scripts/gate/core-budget-timing.ts +51 -0
  284. package/scripts/gate/core-budget.ts +111 -100
  285. package/scripts/gate/core-wait-record.ts +49 -0
  286. package/scripts/gate/core-wait.ts +62 -7
  287. package/scripts/gate/core-weights.ts +94 -0
  288. package/scripts/gate/free-cores.ts +27 -4
  289. package/scripts/gate/gate-labels.ts +46 -0
  290. package/scripts/gate/gate-ledger.ts +44 -8
  291. package/scripts/gate/gate-plan.ts +130 -78
  292. package/scripts/gate/gate-report.ts +23 -9
  293. package/scripts/gate/gate-run-steps.ts +77 -9
  294. package/scripts/gate/gate-skip.ts +57 -8
  295. package/scripts/gate/gate-static-group.ts +60 -0
  296. package/scripts/gate/gate-steps.ts +14 -2
  297. package/scripts/gate/gate-tree.ts +4 -2
  298. package/scripts/gate/hook-gate-reuse.ts +19 -2
  299. package/scripts/gate/input-fingerprint.ts +42 -0
  300. package/scripts/gate/machine-capacity.ts +65 -31
  301. package/scripts/gate/metrics-totals.ts +59 -0
  302. package/scripts/gate/moved-paths.ts +67 -0
  303. package/scripts/gate/project-checks.ts +5 -12
  304. package/scripts/gate/scoped-green.ts +76 -19
  305. package/scripts/gate/since-green.ts +70 -0
  306. package/scripts/gate/structural-checks.ts +96 -0
  307. package/scripts/gate/toolchain-inputs.ts +115 -0
  308. package/scripts/gate/verification-gate.ts +70 -32
  309. package/scripts/gate/verification-inputs.ts +265 -0
  310. package/scripts/gate/verification-tail.ts +52 -0
  311. package/scripts/gh/gh-author-association.ts +117 -9
  312. package/scripts/gh/git-ai-review-scan.ts +5 -3
  313. package/scripts/gh/git-gh-api-path.ts +26 -2
  314. package/scripts/gh/git-gh-branch-rules.ts +73 -0
  315. package/scripts/gh/git-gh-comments-unreadable.ts +36 -0
  316. package/scripts/gh/git-gh-conditional.ts +5 -2
  317. package/scripts/gh/git-gh-exec.ts +32 -2
  318. package/scripts/gh/git-gh-issue-read.ts +7 -1
  319. package/scripts/gh/git-gh-issue-rest.ts +1 -0
  320. package/scripts/gh/git-gh-issue-write.ts +75 -31
  321. package/scripts/gh/git-gh-issue.ts +19 -8
  322. package/scripts/gh/git-gh-poll-read.ts +89 -0
  323. package/scripts/gh/git-gh-pr-auto-merge.ts +21 -9
  324. package/scripts/gh/git-gh-pr-graphql-state.ts +56 -0
  325. package/scripts/gh/git-gh-pr-read.ts +74 -13
  326. package/scripts/gh/git-gh-pr-rest.ts +4 -2
  327. package/scripts/gh/git-gh-pr-snapshot.ts +48 -20
  328. package/scripts/gh/git-gh-pr-too-large.ts +20 -0
  329. package/scripts/gh/git-gh-pr.ts +48 -22
  330. package/scripts/gh/git-gh-retry.ts +141 -0
  331. package/scripts/gh/git-pr-ai-review.ts +15 -6
  332. package/scripts/gh/git-pr-checks-eval.ts +42 -7
  333. package/scripts/gh/git-pr-checks-parse.ts +39 -9
  334. package/scripts/gh/git-pr-checks.ts +5 -5
  335. package/scripts/gh/git-pr-merge-checked.ts +80 -0
  336. package/scripts/git/base-tree.ts +49 -2
  337. package/scripts/git/change-base.ts +4 -10
  338. package/scripts/git/changed-file-scope.ts +6 -4
  339. package/scripts/git/changed-paths-sync.ts +63 -0
  340. package/scripts/git/changed-paths.ts +34 -2
  341. package/scripts/git/git-common-directory.ts +11 -1
  342. package/scripts/git/git-diff-reads.ts +91 -20
  343. package/scripts/git/git-error.ts +9 -2
  344. package/scripts/git/git-grep-hits.ts +85 -0
  345. package/scripts/git/git-location-environment.ts +1 -1
  346. package/scripts/git/git-merge-conflicts.ts +83 -0
  347. package/scripts/git/git-preflight.ts +37 -12
  348. package/scripts/git/git-push-transport.ts +1 -2
  349. package/scripts/git/git-schemas.ts +30 -7
  350. package/scripts/git/git-spawn.ts +1 -2
  351. package/scripts/git/git-status.ts +4 -4
  352. package/scripts/git/git-worktree.ts +13 -0
  353. package/scripts/git/gone-branch.ts +4 -1
  354. package/scripts/git/main-merge-budget-conflict.ts +89 -0
  355. package/scripts/git/main-merge-guard.ts +55 -18
  356. package/scripts/git/main-merge-main.ts +12 -0
  357. package/scripts/git/main-merge-regenerate.ts +59 -25
  358. package/scripts/git/main-merge.ts +77 -13
  359. package/scripts/git/main-sync-main.ts +12 -0
  360. package/scripts/git/main-sync.ts +0 -9
  361. package/scripts/git/no-base-checkout.ts +127 -0
  362. package/scripts/git/stash/git-stash.ts +38 -6
  363. package/scripts/git/stash/{stash-pop-args.ts → stash-args.ts} +13 -10
  364. package/scripts/git/stash/stash-pop-cli.ts +6 -12
  365. package/scripts/git/stash/stash-pop-main.ts +12 -0
  366. package/scripts/git/stash/stash-push-cli.ts +86 -0
  367. package/scripts/git/stash/stash-push-main.ts +12 -0
  368. package/scripts/hooks/batch-guard.ts +38 -27
  369. package/scripts/hooks/check-commit-message-main.ts +8 -0
  370. package/scripts/hooks/check-commit-message.ts +4 -7
  371. package/scripts/hooks/edited-cspell.ts +37 -11
  372. package/scripts/hooks/format-edited-file.ts +29 -25
  373. package/scripts/hooks/lane-plan-guard.ts +50 -0
  374. package/scripts/hooks/pre-commit-lint-switch.ts +9 -0
  375. package/scripts/hooks/pre-commit-lint.ts +44 -4
  376. package/scripts/hooks/pre-push-related-switch.ts +10 -0
  377. package/scripts/hooks/pre-push-unit.ts +77 -9
  378. package/scripts/hooks/pretool-guard-cli.ts +1 -8
  379. package/scripts/hooks/pretool-guard.ts +34 -19
  380. package/scripts/hooks/reserved-run.ts +81 -10
  381. package/scripts/hooks/run-hook.sh +30 -6
  382. package/scripts/hooks/shell-rules-notice.ts +37 -0
  383. package/scripts/hooks/step-zero-notice.ts +6 -1
  384. package/scripts/hooks/stop-actions.ts +5 -36
  385. package/scripts/hooks/stop-guard.ts +20 -15
  386. package/scripts/init/distributed-paths.ts +1 -0
  387. package/scripts/init/hook-command-rewrite.ts +23 -5
  388. package/scripts/init/hook-launch.ts +17 -17
  389. package/scripts/init/init-actions.ts +0 -6
  390. package/scripts/init/init-ai-copy.ts +10 -36
  391. package/scripts/init/init-bootstrap.ts +9 -8
  392. package/scripts/init/init-dry-run-report.ts +1 -1
  393. package/scripts/init/init-dry-run.ts +1 -1
  394. package/scripts/init/init-file-action.ts +7 -9
  395. package/scripts/init/init-logic-json-merge.ts +2 -2
  396. package/scripts/init/init-logic-migrate.ts +9 -82
  397. package/scripts/init/init-logic.ts +3 -2
  398. package/scripts/init/init-main.ts +12 -0
  399. package/scripts/init/init.ts +5 -12
  400. package/scripts/init/kit-development-versions.ts +3 -7
  401. package/scripts/init/kit-written-paths.ts +2 -2
  402. package/scripts/init/project-profile.ts +5 -4
  403. package/scripts/init/tsconfig-preset-migration.ts +2 -1
  404. package/scripts/init/vscode-tasks.ts +1 -1
  405. package/scripts/issue/aggregation-split.ts +52 -0
  406. package/scripts/issue/defect-origin-cli.ts +106 -0
  407. package/scripts/issue/defect-origin-line.ts +78 -0
  408. package/scripts/issue/defect-origin-main.ts +11 -0
  409. package/scripts/issue/defect-origin.ts +114 -0
  410. package/scripts/issue/defect-rate-cli.ts +38 -179
  411. package/scripts/issue/defect-rate.ts +0 -16
  412. package/scripts/issue/defect-report-cli.ts +128 -0
  413. package/scripts/issue/defect-report-format.ts +56 -0
  414. package/scripts/issue/defect-report-main.ts +11 -0
  415. package/scripts/issue/defect-report.ts +160 -0
  416. package/scripts/issue/effect-audit-cli.ts +178 -0
  417. package/scripts/issue/effect-audit.ts +185 -0
  418. package/scripts/issue/expected-effect-lint.ts +65 -9
  419. package/scripts/issue/git-next-issues.ts +5 -0
  420. package/scripts/issue/issue-already-done-cli.ts +62 -0
  421. package/scripts/issue/issue-body-or-comment.ts +74 -0
  422. package/scripts/issue/issue-cite-cli.ts +1 -12
  423. package/scripts/issue/issue-cite-main.ts +12 -0
  424. package/scripts/issue/issue-classification.ts +13 -7
  425. package/scripts/issue/issue-closing-pr.ts +8 -1
  426. package/scripts/issue/issue-comment-cli.ts +10 -24
  427. package/scripts/issue/issue-comment-main.ts +12 -0
  428. package/scripts/issue/issue-evidence-exit.ts +102 -0
  429. package/scripts/issue/issue-file-cap.ts +58 -0
  430. package/scripts/issue/issue-file-cli.ts +131 -36
  431. package/scripts/issue/issue-file-deferral.ts +52 -0
  432. package/scripts/issue/issue-file-fold.ts +29 -10
  433. package/scripts/issue/issue-file-interrupt.ts +85 -0
  434. package/scripts/issue/issue-file-lane-hint.ts +30 -0
  435. package/scripts/issue/issue-file.ts +56 -19
  436. package/scripts/issue/issue-fold-cli.ts +2 -11
  437. package/scripts/issue/issue-fold-main.ts +12 -0
  438. package/scripts/issue/issue-labels.ts +97 -89
  439. package/scripts/issue/issue-lint-cli.ts +29 -12
  440. package/scripts/issue/issue-lint-main.ts +12 -0
  441. package/scripts/issue/issue-measured-cli.ts +34 -0
  442. package/scripts/issue/issue-measured-close.ts +58 -0
  443. package/scripts/issue/issue-merged.ts +19 -2
  444. package/scripts/issue/issue-not-before-label.ts +135 -0
  445. package/scripts/issue/issue-not-before.ts +114 -0
  446. package/scripts/issue/issue-number-shape.ts +15 -1
  447. package/scripts/issue/issue-park.ts +28 -0
  448. package/scripts/issue/issue-plan-cli.ts +151 -0
  449. package/scripts/issue/issue-priority-cli.ts +60 -0
  450. package/scripts/issue/issue-priority-raise.ts +55 -0
  451. package/scripts/issue/issue-priority.ts +282 -0
  452. package/scripts/issue/issue-rank.ts +27 -4
  453. package/scripts/issue/issue-read-cli.ts +35 -16
  454. package/scripts/issue/issue-read-main.ts +12 -0
  455. package/scripts/issue/issue-read.ts +62 -13
  456. package/scripts/issue/issue-release-cli.ts +0 -10
  457. package/scripts/issue/issue-release-main.ts +13 -0
  458. package/scripts/issue/issue-release.ts +7 -12
  459. package/scripts/issue/issue-sample-gate.ts +213 -0
  460. package/scripts/issue/issue-sample-prime.ts +127 -0
  461. package/scripts/issue/issue-sample-required.ts +57 -0
  462. package/scripts/issue/issue-sample-source.ts +77 -0
  463. package/scripts/issue/issue-scout-cli.ts +0 -11
  464. package/scripts/issue/issue-scout-main.ts +14 -0
  465. package/scripts/issue/issue-search.ts +124 -0
  466. package/scripts/issue/issue-state-cli.ts +0 -10
  467. package/scripts/issue/issue-state-main.ts +12 -0
  468. package/scripts/issue/issue-state.ts +13 -1
  469. package/scripts/issue/issue-template-section.ts +43 -0
  470. package/scripts/issue/issue-watch-diff.ts +87 -16
  471. package/scripts/issue/issue-watch-hook.ts +11 -2
  472. package/scripts/issue/issue-watch.ts +55 -11
  473. package/scripts/issue/issue-wip.ts +2 -7
  474. package/scripts/issue/markdown-section.ts +1 -0
  475. package/scripts/issue/measure-declaration.ts +121 -0
  476. package/scripts/issue/measure-rerun-cli.ts +7 -65
  477. package/scripts/issue/plan-consumers-cli.ts +39 -0
  478. package/scripts/issue/plan-consumers-main.ts +11 -0
  479. package/scripts/issue/plan-consumers-section.ts +76 -0
  480. package/scripts/issue/plan-consumers.ts +127 -0
  481. package/scripts/issue/reproduction-measure.ts +3 -1
  482. package/scripts/issue/size-estimate.ts +90 -0
  483. package/scripts/issue/trusted-measure.ts +84 -0
  484. package/scripts/josh/agent-session-environment.ts +1 -1
  485. package/scripts/josh/command-usage.ts +17 -44
  486. package/scripts/josh/durable-state-migrate.ts +105 -0
  487. package/scripts/josh/durable-state.ts +112 -0
  488. package/scripts/josh/file-map-stamp.ts +49 -16
  489. package/scripts/josh/hook-decision.ts +32 -20
  490. package/scripts/josh/josh-aliases.ts +95 -0
  491. package/scripts/josh/josh-command-map.ts +1 -79
  492. package/scripts/josh/josh-command-types.ts +12 -6
  493. package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
  494. package/scripts/josh/josh-commands-ai.ts +160 -161
  495. package/scripts/josh/josh-commands-backlog.ts +82 -16
  496. package/scripts/josh/josh-commands-clone.ts +1 -0
  497. package/scripts/josh/josh-commands-development.ts +142 -101
  498. package/scripts/josh/josh-commands-document.ts +43 -1
  499. package/scripts/josh/josh-commands-epic.ts +171 -0
  500. package/scripts/josh/josh-commands-hooks.ts +25 -2
  501. package/scripts/josh/josh-commands-issue-write.ts +200 -0
  502. package/scripts/josh/josh-commands-issue.ts +156 -24
  503. package/scripts/josh/josh-commands-lane.ts +187 -3
  504. package/scripts/josh/josh-commands-lint.ts +34 -10
  505. package/scripts/josh/josh-commands-maintenance.ts +127 -4
  506. package/scripts/josh/josh-commands-pause.ts +29 -0
  507. package/scripts/josh/josh-commands-progress.ts +87 -0
  508. package/scripts/josh/josh-commands-project.ts +138 -9
  509. package/scripts/josh/josh-commands-review.ts +159 -0
  510. package/scripts/josh/josh-commands-run.ts +211 -23
  511. package/scripts/josh/josh-commands-ship.ts +217 -0
  512. package/scripts/josh/josh-commands-split.ts +9 -0
  513. package/scripts/josh/josh-commands-test-check.ts +80 -0
  514. package/scripts/josh/josh-commands-versioning.ts +49 -2
  515. package/scripts/josh/josh-commands-workflow.ts +144 -6
  516. package/scripts/josh/josh-environment-file.ts +43 -3
  517. package/scripts/josh/josh-in-process.ts +2 -2
  518. package/scripts/josh/josh-logic.ts +11 -16
  519. package/scripts/josh/josh-run.ts +19 -1
  520. package/scripts/josh/package-directory.ts +2 -4
  521. package/scripts/josh/process-identity.ts +13 -4
  522. package/scripts/josh/run-record-path.ts +15 -0
  523. package/scripts/josh/session-language-cli.ts +4 -8
  524. package/scripts/josh/session-language-main.ts +13 -0
  525. package/scripts/josh/session-language.ts +6 -1
  526. package/scripts/josh/shared-cache.ts +90 -0
  527. package/scripts/josh/stamp-file.ts +20 -17
  528. package/scripts/lane/lane-adopt-cli.ts +98 -0
  529. package/scripts/lane/lane-adopt.ts +208 -0
  530. package/scripts/lane/lane-await.ts +56 -20
  531. package/scripts/lane/lane-baseline.ts +123 -0
  532. package/scripts/lane/lane-breakdown-cli.ts +64 -0
  533. package/scripts/lane/lane-breakdown-implement.ts +170 -0
  534. package/scripts/lane/lane-breakdown-laps.ts +107 -0
  535. package/scripts/lane/lane-breakdown-pinned.ts +76 -0
  536. package/scripts/lane/lane-breakdown-text.ts +145 -0
  537. package/scripts/lane/lane-breakdown.ts +239 -0
  538. package/scripts/lane/lane-cache.ts +5 -30
  539. package/scripts/lane/lane-capacity.ts +14 -23
  540. package/scripts/lane/lane-check-stats.ts +84 -22
  541. package/scripts/lane/lane-child-invocation.ts +17 -2
  542. package/scripts/lane/lane-child-mark-keys.ts +12 -0
  543. package/scripts/lane/lane-child-marker.ts +20 -1
  544. package/scripts/lane/lane-ci-path-stats.ts +73 -0
  545. package/scripts/lane/lane-claim-stats.ts +84 -0
  546. package/scripts/lane/lane-cli.ts +15 -5
  547. package/scripts/lane/lane-close.ts +91 -18
  548. package/scripts/lane/lane-core-wait-stats.ts +66 -0
  549. package/scripts/lane/lane-dispatch-log.ts +3 -3
  550. package/scripts/lane/lane-dispatch.ts +26 -5
  551. package/scripts/lane/lane-gap-stats.ts +157 -0
  552. package/scripts/lane/lane-guard-policy.ts +7 -1
  553. package/scripts/lane/lane-handoff.ts +69 -1
  554. package/scripts/lane/lane-held-stats.ts +129 -0
  555. package/scripts/lane/lane-implement-stats.ts +207 -0
  556. package/scripts/lane/lane-implement-subagents.ts +90 -0
  557. package/scripts/lane/lane-install.ts +4 -11
  558. package/scripts/lane/lane-investigation-switch.ts +16 -0
  559. package/scripts/lane/lane-launch-cli.ts +0 -9
  560. package/scripts/lane/lane-launch-main.ts +12 -0
  561. package/scripts/lane/lane-ledger-kind.ts +31 -0
  562. package/scripts/lane/lane-ledger-schema-ship.ts +49 -0
  563. package/scripts/lane/lane-ledger-schema.ts +349 -0
  564. package/scripts/lane/lane-ledger-write.ts +257 -0
  565. package/scripts/lane/lane-ledger.ts +56 -233
  566. package/scripts/lane/lane-limit-cli.ts +12 -1
  567. package/scripts/lane/lane-load.ts +1 -1
  568. package/scripts/lane/lane-measure-cli.ts +193 -30
  569. package/scripts/lane/lane-net-read.ts +44 -0
  570. package/scripts/lane/lane-net-time.ts +212 -0
  571. package/scripts/lane/lane-open.ts +25 -8
  572. package/scripts/lane/lane-output.ts +2 -4
  573. package/scripts/lane/lane-overrun-prompt.ts +147 -0
  574. package/scripts/lane/lane-overrun.ts +274 -0
  575. package/scripts/lane/lane-parked.ts +3 -3
  576. package/scripts/lane/lane-paths.ts +24 -1
  577. package/scripts/lane/lane-pause-cli.ts +133 -0
  578. package/scripts/lane/lane-pause.ts +158 -0
  579. package/scripts/lane/lane-paused-spans.ts +97 -0
  580. package/scripts/lane/lane-plan-check.ts +207 -0
  581. package/scripts/lane/lane-plan-cli.ts +41 -0
  582. package/scripts/lane/lane-plan.ts +144 -0
  583. package/scripts/lane/lane-process-table.ts +166 -0
  584. package/scripts/lane/lane-reap-settle.ts +124 -0
  585. package/scripts/lane/lane-reap.ts +50 -15
  586. package/scripts/lane/lane-registry.ts +38 -4
  587. package/scripts/lane/lane-relaunch.ts +1 -1
  588. package/scripts/lane/lane-residents.ts +162 -0
  589. package/scripts/lane/lane-restart.ts +22 -2
  590. package/scripts/lane/lane-round-one-stats.ts +51 -0
  591. package/scripts/lane/lane-round-two-stats.ts +49 -0
  592. package/scripts/lane/lane-sampler.ts +26 -3
  593. package/scripts/lane/lane-session-action.ts +112 -23
  594. package/scripts/lane/lane-session-broker.ts +146 -37
  595. package/scripts/lane/lane-session-reread-main.ts +14 -0
  596. package/scripts/lane/lane-session-reread.ts +51 -0
  597. package/scripts/lane/lane-ship-lap-stats.ts +74 -0
  598. package/scripts/lane/lane-sleep.ts +58 -0
  599. package/scripts/lane/lane-snapshot-trace.ts +84 -0
  600. package/scripts/lane/lane-spans.ts +51 -0
  601. package/scripts/lane/lane-spent.ts +7 -4
  602. package/scripts/lane/lane-split-stats.ts +28 -0
  603. package/scripts/lane/lane-stage-stats.ts +20 -3
  604. package/scripts/lane/lane-state.ts +334 -0
  605. package/scripts/lane/lane-stats-tables.ts +58 -0
  606. package/scripts/lane/lane-stats.ts +74 -4
  607. package/scripts/lane/lane-stop-stats.ts +145 -37
  608. package/scripts/lane/lane-tail-stats.ts +32 -0
  609. package/scripts/lane/lane-test-related-stats.ts +127 -0
  610. package/scripts/lane/lane-transcript-calls.ts +202 -0
  611. package/scripts/lane/lane-transcript-stats.ts +200 -0
  612. package/scripts/lane/lane-vacant.ts +13 -3
  613. package/scripts/lane/lane-value-cell.ts +72 -0
  614. package/scripts/lane/lane-value.ts +118 -0
  615. package/scripts/lane/lane-withdraw-cli.ts +5 -4
  616. package/scripts/lane/lane-withdraw-closed.ts +124 -0
  617. package/scripts/lane/lane-withdraw.ts +149 -71
  618. package/scripts/lane/lane-yield.ts +85 -0
  619. package/scripts/lane/openai-lane-ship.ts +12 -11
  620. package/scripts/lane/openai-lane-supervisor-decision.ts +6 -8
  621. package/scripts/lane/openai-lane-supervisor-owner.ts +5 -8
  622. package/scripts/lane/openai-lane-supervisor.ts +5 -4
  623. package/scripts/lane/process-directories.ts +70 -0
  624. package/scripts/lane/process-lane-marks.ts +94 -0
  625. package/scripts/lib/atomic-write.ts +62 -0
  626. package/scripts/lib/buffered-process.ts +12 -5
  627. package/scripts/lib/cli-flags.ts +53 -0
  628. package/scripts/lib/figure-format.ts +63 -0
  629. package/scripts/lib/json-value.ts +9 -1
  630. package/scripts/lib/package-manifest.ts +35 -0
  631. package/scripts/lib/poll.ts +38 -9
  632. package/scripts/lib/read-file.ts +3 -1
  633. package/scripts/lib/settled-together.ts +10 -0
  634. package/scripts/lib/shell-quote.ts +21 -0
  635. package/scripts/lib/stamped-memo.ts +63 -0
  636. package/scripts/lib/stdout-on-stderr.ts +24 -0
  637. package/scripts/lib/timeouts.ts +9 -0
  638. package/scripts/lib/token-shape.ts +111 -0
  639. package/scripts/lib/transcript-record.ts +91 -0
  640. package/scripts/lines/effective-limit.ts +1 -1
  641. package/scripts/lint/eslint-cache-dependencies.ts +145 -0
  642. package/scripts/lint/eslint-daemon-sources.ts +79 -0
  643. package/scripts/lint/eslint-daemon.ts +304 -0
  644. package/scripts/lint/eslint-warm-cli.ts +7 -0
  645. package/scripts/lint/eslint-warm.ts +66 -0
  646. package/scripts/lint/format.ts +11 -2
  647. package/scripts/lint/import-graph.ts +409 -0
  648. package/scripts/lint/lint-gate-scope.ts +102 -0
  649. package/scripts/lint/lint-parallel-main.ts +19 -0
  650. package/scripts/lint/lint-parallel.ts +113 -33
  651. package/scripts/lint/lint-related-scope.ts +30 -24
  652. package/scripts/lint/lint-related.ts +183 -30
  653. package/scripts/lint/rename-cli.ts +179 -0
  654. package/scripts/lint/rename-identifier.ts +192 -0
  655. package/scripts/lint/type-only-imports.ts +58 -0
  656. package/scripts/notify/confirmation-options.ts +1 -2
  657. package/scripts/notify/telegram-notify.ts +32 -23
  658. package/scripts/notify/telegram-test-logic.ts +0 -1
  659. package/scripts/notify/telegram-test-main.ts +8 -0
  660. package/scripts/notify/telegram-test.ts +2 -6
  661. package/scripts/observations/observation-ledger.ts +13 -0
  662. package/scripts/observations/observation-record.ts +42 -16
  663. package/scripts/observations/observations-flush-landing.ts +5 -3
  664. package/scripts/observations/observations-flush.ts +38 -10
  665. package/scripts/overrides/overrides-check.ts +11 -6
  666. package/scripts/overrides/overrides-files.ts +2 -1
  667. package/scripts/overrides/overrides-logic.ts +3 -6
  668. package/scripts/package/verify-optional-eslint-install.ts +8 -6
  669. package/scripts/propagate/propagate-publish.ts +2 -7
  670. package/scripts/propagate/propagate-targets.ts +4 -12
  671. package/scripts/refactor/import-graph.ts +9 -7
  672. package/scripts/release/github-release-runs.ts +17 -6
  673. package/scripts/release/release-approval-prune.ts +24 -0
  674. package/scripts/release/release-history.ts +1 -3
  675. package/scripts/release/release-progress.ts +42 -22
  676. package/scripts/release/release-publish-run.ts +39 -0
  677. package/scripts/release/release-publish.ts +6 -6
  678. package/scripts/release/release-scope-cli.ts +0 -10
  679. package/scripts/release/release-scope-main.ts +12 -0
  680. package/scripts/repo/repo-setting.ts +3 -6
  681. package/scripts/repo/required-checks-logic.ts +10 -16
  682. package/scripts/repo/ruleset-check.ts +4 -3
  683. package/scripts/report/markdown-shape.ts +28 -0
  684. package/scripts/report/report-format-reference.ts +17 -1
  685. package/scripts/report/report-labels.ts +166 -0
  686. package/scripts/report/report-lint-child-summary.ts +94 -0
  687. package/scripts/report/report-lint-cli.ts +29 -7
  688. package/scripts/report/report-lint.ts +85 -128
  689. package/scripts/report/report-template-cli.ts +59 -0
  690. package/scripts/report/report-template.ts +112 -0
  691. package/scripts/review/acceptance-map.ts +1 -0
  692. package/scripts/review/prose-stale-cli.ts +88 -0
  693. package/scripts/review/prose-stale-scan.ts +152 -0
  694. package/scripts/review/removed-tests-check.ts +86 -0
  695. package/scripts/review/removed-tests.ts +149 -0
  696. package/scripts/review/review-attest.ts +73 -23
  697. package/scripts/review/review-brief-cli.ts +138 -23
  698. package/scripts/review/review-brief-main.ts +12 -0
  699. package/scripts/review/review-brief-paths.ts +22 -0
  700. package/scripts/review/review-brief.ts +45 -10
  701. package/scripts/review/review-code-tree.ts +10 -6
  702. package/scripts/review/review-comment-carry.ts +47 -0
  703. package/scripts/review/review-comment-round.ts +111 -30
  704. package/scripts/review/review-finding-ledger.ts +135 -18
  705. package/scripts/review/review-finding-text.ts +43 -0
  706. package/scripts/review/review-interaction.ts +105 -0
  707. package/scripts/review/review-lane-handover.ts +68 -0
  708. package/scripts/review/review-lint-cli.ts +57 -0
  709. package/scripts/review/review-lint-findings.ts +92 -0
  710. package/scripts/review/review-lint-sections.ts +80 -0
  711. package/scripts/review/review-lint.ts +221 -0
  712. package/scripts/review/review-prior-findings.ts +102 -0
  713. package/scripts/review/review-readers-scan.ts +165 -0
  714. package/scripts/review/review-record-cli.ts +236 -74
  715. package/scripts/review/review-record-code-round.ts +55 -0
  716. package/scripts/review/review-record-comment.ts +60 -0
  717. package/scripts/review/review-record-interaction.ts +35 -0
  718. package/scripts/review/review-record-main.ts +12 -0
  719. package/scripts/review/review-record-pinned.ts +108 -0
  720. package/scripts/review/review-record.ts +25 -1
  721. package/scripts/review/review-reviewed-tree.ts +307 -0
  722. package/scripts/review/review-round-one-blobs.ts +221 -0
  723. package/scripts/review/review-round-one-closure.ts +62 -0
  724. package/scripts/review/review-round-reuse.ts +106 -0
  725. package/scripts/review/review-round2-cli.ts +135 -36
  726. package/scripts/review/review-round2-skip-comment.ts +55 -0
  727. package/scripts/review/review-round2.ts +103 -19
  728. package/scripts/review/review-stamps.ts +23 -1
  729. package/scripts/review/review-stop-log.ts +110 -0
  730. package/scripts/review/review-stops-cli.ts +86 -0
  731. package/scripts/review/review-submit-cli.ts +101 -0
  732. package/scripts/review/review-tree.ts +6 -17
  733. package/scripts/review/review-untouched-readers.ts +146 -0
  734. package/scripts/review/test-titles.ts +118 -0
  735. package/scripts/rules/agent-model.ts +9 -1
  736. package/scripts/rules/bash-triggers.ts +49 -6
  737. package/scripts/rules/concise-reply.ts +88 -0
  738. package/scripts/rules/credential-body.ts +77 -0
  739. package/scripts/rules/decision-oracle-batch.ts +9 -1
  740. package/scripts/rules/decision-oracle.ts +3 -3
  741. package/scripts/rules/delivered-rules.ts +115 -18
  742. package/scripts/rules/destructive-command.ts +11 -12
  743. package/scripts/rules/direct-filing.ts +10 -2
  744. package/scripts/rules/direct-issue-comment.ts +139 -0
  745. package/scripts/rules/direct-issue-read.ts +191 -0
  746. package/scripts/rules/direct-pr-create.ts +72 -26
  747. package/scripts/rules/early-heartbeat.ts +4 -1
  748. package/scripts/rules/edit-tool.ts +27 -0
  749. package/scripts/rules/file-body.ts +7 -0
  750. package/scripts/rules/file-edit-rows.ts +17 -0
  751. package/scripts/rules/file-rewrite.ts +146 -0
  752. package/scripts/rules/firing-point.ts +3 -2
  753. package/scripts/rules/gh-api.ts +128 -7
  754. package/scripts/rules/gh-repo-selector.ts +84 -0
  755. package/scripts/rules/git-argv.ts +72 -14
  756. package/scripts/rules/git-force.ts +14 -4
  757. package/scripts/rules/guard-remedy.ts +17 -4
  758. package/scripts/rules/implementation-cut-verdict.ts +1 -1
  759. package/scripts/rules/implementation-cut.ts +68 -27
  760. package/scripts/rules/index-guard.ts +8 -1
  761. package/scripts/rules/investigator-foreground.ts +231 -0
  762. package/scripts/rules/issue-citation.ts +15 -60
  763. package/scripts/rules/issue-comments.ts +18 -5
  764. package/scripts/rules/josh-git-bare.ts +7 -0
  765. package/scripts/rules/lane-background.ts +103 -33
  766. package/scripts/rules/lane-carry-conflict.ts +6 -0
  767. package/scripts/rules/lane-direct-tool.ts +172 -0
  768. package/scripts/rules/lane-interactive-ask.ts +12 -2
  769. package/scripts/rules/lane-park.ts +49 -25
  770. package/scripts/rules/lane-spilled-read.ts +90 -0
  771. package/scripts/rules/lane-split-park.ts +11 -3
  772. package/scripts/rules/lane-switch-main.ts +11 -4
  773. package/scripts/rules/last-prompt.ts +20 -47
  774. package/scripts/rules/oracle-consulted.ts +11 -1
  775. package/scripts/rules/oracle-firing.ts +1 -0
  776. package/scripts/rules/permission-guards.ts +7 -0
  777. package/scripts/rules/piped-verification-shapes.ts +110 -0
  778. package/scripts/rules/piped-verification.ts +68 -18
  779. package/scripts/rules/poll-loop.ts +78 -8
  780. package/scripts/rules/pr-merge.ts +123 -0
  781. package/scripts/rules/pre-gate-cut.ts +3 -3
  782. package/scripts/rules/protected-files.ts +113 -22
  783. package/scripts/rules/raw-field-body.ts +6 -0
  784. package/scripts/rules/reply-language.ts +3 -17
  785. package/scripts/rules/reply-prose.ts +34 -0
  786. package/scripts/rules/repo-admin.ts +132 -0
  787. package/scripts/rules/reviewer-foreground.ts +88 -0
  788. package/scripts/rules/round-one-check-related.ts +120 -0
  789. package/scripts/rules/rule-body-guard.ts +13 -15
  790. package/scripts/rules/rule-list.ts +9 -28
  791. package/scripts/rules/rule-value-cache.ts +57 -14
  792. package/scripts/rules/rule-value-candidates.ts +84 -0
  793. package/scripts/rules/rule-value-cli.ts +106 -39
  794. package/scripts/rules/rule-value.ts +18 -5
  795. package/scripts/rules/run-tail-rule.ts +1 -1
  796. package/scripts/rules/sed-in-place.ts +196 -0
  797. package/scripts/rules/shell-segments.ts +43 -0
  798. package/scripts/rules/stop-rule-rows.ts +52 -0
  799. package/scripts/rules/stop-rules.ts +36 -62
  800. package/scripts/rules/test-declared-commit.ts +11 -1
  801. package/scripts/rules/third-party-write.ts +115 -21
  802. package/scripts/rules/timed-rerun.ts +69 -0
  803. package/scripts/rules/turn-filings.ts +90 -0
  804. package/scripts/rules/worktree-guard.ts +32 -7
  805. package/scripts/run/board/run-board-app-name.ts +23 -0
  806. package/scripts/run/board/run-board-cli.ts +65 -32
  807. package/scripts/run/board/run-board-earlier.ts +94 -0
  808. package/scripts/run/board/run-board-ending-reason.ts +71 -0
  809. package/scripts/run/board/run-board-estimate-schedule.ts +103 -0
  810. package/scripts/run/board/run-board-estimate.ts +98 -0
  811. package/scripts/run/board/run-board-fit.ts +177 -37
  812. package/scripts/run/board/run-board-fold.ts +123 -0
  813. package/scripts/run/board/run-board-found.ts +134 -0
  814. package/scripts/run/board/run-board-fresh.ts +2 -2
  815. package/scripts/run/board/run-board-gather-live.ts +29 -0
  816. package/scripts/run/board/run-board-gather-thread.ts +189 -0
  817. package/scripts/run/board/run-board-gather-worker.ts +29 -0
  818. package/scripts/run/board/run-board-gather.ts +187 -0
  819. package/scripts/run/board/run-board-github.ts +118 -38
  820. package/scripts/run/board/run-board-header.ts +90 -20
  821. package/scripts/run/board/run-board-keys.ts +58 -0
  822. package/scripts/run/board/run-board-kind.ts +20 -6
  823. package/scripts/run/board/run-board-labels.ts +126 -71
  824. package/scripts/run/board/run-board-lane-state.ts +109 -0
  825. package/scripts/run/board/run-board-lane-time.ts +123 -0
  826. package/scripts/run/board/run-board-layout.ts +239 -60
  827. package/scripts/run/board/run-board-length.ts +52 -0
  828. package/scripts/run/board/run-board-link.ts +15 -2
  829. package/scripts/run/board/run-board-machine.ts +8 -4
  830. package/scripts/run/board/run-board-main.ts +12 -0
  831. package/scripts/run/board/run-board-notes.ts +59 -32
  832. package/scripts/run/board/run-board-now.ts +1 -1
  833. package/scripts/run/board/run-board-operation.ts +19 -35
  834. package/scripts/run/board/run-board-phase.ts +3 -6
  835. package/scripts/run/board/run-board-plan-shared.ts +115 -0
  836. package/scripts/run/board/run-board-plan.ts +56 -4
  837. package/scripts/run/board/run-board-planning.ts +45 -0
  838. package/scripts/run/board/run-board-priority.ts +44 -0
  839. package/scripts/run/board/run-board-process-groups.ts +195 -0
  840. package/scripts/run/board/run-board-read.ts +197 -28
  841. package/scripts/run/board/run-board-reason.ts +247 -51
  842. package/scripts/run/board/run-board-released.ts +35 -0
  843. package/scripts/run/board/run-board-render-checks.ts +42 -7
  844. package/scripts/run/board/run-board-render-condition.ts +96 -0
  845. package/scripts/run/board/run-board-render-drawn.ts +78 -0
  846. package/scripts/run/board/run-board-render-foot.ts +59 -0
  847. package/scripts/run/board/run-board-render-found.ts +157 -0
  848. package/scripts/run/board/run-board-render-icon.ts +35 -0
  849. package/scripts/run/board/run-board-render-lanes.ts +145 -0
  850. package/scripts/run/board/run-board-render-lead.ts +89 -0
  851. package/scripts/run/board/run-board-render-legend.ts +136 -48
  852. package/scripts/run/board/run-board-render-notes.ts +156 -29
  853. package/scripts/run/board/run-board-render-processes.ts +196 -0
  854. package/scripts/run/board/run-board-render-section.ts +119 -0
  855. package/scripts/run/board/run-board-render-slot.ts +3 -36
  856. package/scripts/run/board/run-board-render-tail.ts +115 -48
  857. package/scripts/run/board/run-board-render-time.ts +56 -0
  858. package/scripts/run/board/run-board-render-title.ts +117 -24
  859. package/scripts/run/board/run-board-render-waits.ts +104 -20
  860. package/scripts/run/board/run-board-render.ts +264 -258
  861. package/scripts/run/board/run-board-roots.ts +54 -0
  862. package/scripts/run/board/run-board-row-yield.ts +9 -4
  863. package/scripts/run/board/run-board-setup.ts +1 -12
  864. package/scripts/run/board/run-board-snapshot.ts +111 -0
  865. package/scripts/run/board/run-board-spin.ts +3 -5
  866. package/scripts/run/board/run-board-state.ts +22 -33
  867. package/scripts/run/board/run-board-status.ts +149 -71
  868. package/scripts/run/board/run-board-thanks-read.ts +2 -2
  869. package/scripts/run/board/run-board-tick.ts +158 -114
  870. package/scripts/run/board/run-board-usage-board.ts +78 -0
  871. package/scripts/run/board/run-board-usage-lanes.ts +113 -0
  872. package/scripts/run/board/run-board-usage-listing.ts +93 -0
  873. package/scripts/run/board/run-board-usage-read.ts +120 -150
  874. package/scripts/run/board/run-board-usage-rusage.ts +19 -7
  875. package/scripts/run/board/run-board-usage-text.ts +139 -51
  876. package/scripts/run/board/run-board-usage-top.ts +102 -0
  877. package/scripts/run/board/run-board-usage.ts +89 -72
  878. package/scripts/run/board/run-board-usual.ts +20 -9
  879. package/scripts/run/carry/run-carry-args.ts +4 -7
  880. package/scripts/run/carry/run-carry-conversation.ts +1 -1
  881. package/scripts/run/carry/run-carry-ended.ts +3 -2
  882. package/scripts/run/carry/run-carry.ts +12 -6
  883. package/scripts/run/cut/run-cut-cli.ts +33 -133
  884. package/scripts/run/cut/run-cut-digest.ts +152 -0
  885. package/scripts/run/cut/run-cut-handoff.ts +54 -10
  886. package/scripts/run/cut/run-cut-report.ts +24 -3
  887. package/scripts/run/cut/run-cut-resume.ts +129 -0
  888. package/scripts/run/cut/run-cut-review.ts +105 -0
  889. package/scripts/run/cut/run-cut.ts +18 -7
  890. package/scripts/run/detached-launch.ts +1 -1
  891. package/scripts/run/entry/run-entry-cli.ts +88 -19
  892. package/scripts/run/entry/run-entry-spill.ts +83 -0
  893. package/scripts/run/entry/run-entry-stop.ts +5 -1
  894. package/scripts/run/entry/run-entry-trust.ts +91 -0
  895. package/scripts/run/event/run-event-baseline.ts +56 -0
  896. package/scripts/run/event/run-event-cli.ts +1 -5
  897. package/scripts/run/event/run-event-filed.ts +18 -6
  898. package/scripts/run/event/run-event-follow.ts +2 -3
  899. package/scripts/run/event/run-event-overrun.ts +197 -0
  900. package/scripts/run/event/run-event-render.ts +10 -10
  901. package/scripts/run/event/run-event-scope.ts +2 -2
  902. package/scripts/run/event/run-event-stream-emit.ts +82 -22
  903. package/scripts/run/event/run-event-stream.ts +58 -10
  904. package/scripts/run/hold/run-hold-adopt.ts +65 -0
  905. package/scripts/run/hold/run-hold-cli.ts +93 -22
  906. package/scripts/run/hold/run-hold-main.ts +12 -0
  907. package/scripts/run/hold/run-hold-member.ts +37 -0
  908. package/scripts/run/hold/run-stop-notify.ts +178 -0
  909. package/scripts/run/merge/run-merge-auth.ts +31 -0
  910. package/scripts/run/merge/run-merge-cap.ts +57 -0
  911. package/scripts/run/merge/run-merge-cli.ts +119 -62
  912. package/scripts/run/merge/run-merge-close.ts +74 -0
  913. package/scripts/run/merge/run-merge-collect.ts +6 -13
  914. package/scripts/run/merge/run-merge-driver.ts +71 -0
  915. package/scripts/run/merge/run-merge-main.ts +12 -0
  916. package/scripts/run/merge/run-merge-outcome.ts +25 -0
  917. package/scripts/run/merge/run-merge-restart.ts +39 -0
  918. package/scripts/run/merge/run-merge-ship.ts +33 -7
  919. package/scripts/run/merge/run-merge-signals.ts +66 -25
  920. package/scripts/run/merge/run-merge-steps.ts +162 -107
  921. package/scripts/run/merge/run-merge-usage-limit.ts +53 -0
  922. package/scripts/run/merge/run-merge-withdrawn.ts +53 -0
  923. package/scripts/run/merge/run-merge.ts +76 -48
  924. package/scripts/run/park/run-park-cli.ts +91 -0
  925. package/scripts/run/park/run-park.ts +88 -0
  926. package/scripts/run/park/run-stalled.ts +68 -0
  927. package/scripts/run/pause/run-pause-cli.ts +73 -0
  928. package/scripts/run/pause/run-pause.ts +251 -0
  929. package/scripts/run/progress/run-progress-cli.ts +4 -12
  930. package/scripts/run/progress/run-progress-clock.ts +1 -1
  931. package/scripts/run/progress/run-progress-config.ts +6 -14
  932. package/scripts/run/progress/run-progress-main.ts +12 -0
  933. package/scripts/run/progress/run-progress.ts +1 -4
  934. package/scripts/run/review/run-review-cli.ts +306 -20
  935. package/scripts/run/review/run-review-early-push.ts +121 -0
  936. package/scripts/run/review/run-review-join-read.ts +94 -0
  937. package/scripts/run/review/run-review-pinned-accepted.ts +126 -0
  938. package/scripts/run/review/run-review-pinned-join.ts +216 -0
  939. package/scripts/run/review/run-review-pinned-steps.ts +383 -0
  940. package/scripts/run/review/run-review-pinned-tree.ts +37 -0
  941. package/scripts/run/review/run-review-pinned.ts +53 -0
  942. package/scripts/run/review/run-review-steps.ts +70 -34
  943. package/scripts/run/review/run-review.ts +28 -7
  944. package/scripts/run/run-ending.ts +1 -0
  945. package/scripts/run/run-invocation.ts +5 -6
  946. package/scripts/run/run-liveness-cli.ts +6 -8
  947. package/scripts/run/run-liveness.ts +60 -29
  948. package/scripts/run/run-next.ts +1 -1
  949. package/scripts/run/run-parent-cut-hook.ts +3 -4
  950. package/scripts/run/run-preflight.ts +18 -3
  951. package/scripts/run/run-prep-cli.ts +1 -10
  952. package/scripts/run/run-prep-locate.ts +7 -50
  953. package/scripts/run/run-prep-main.ts +12 -0
  954. package/scripts/run/run-prep.ts +7 -0
  955. package/scripts/run/run-report-cli.ts +101 -13
  956. package/scripts/run/run-report-handoff.ts +114 -0
  957. package/scripts/run/run-stage-read.ts +2 -6
  958. package/scripts/run/run-step-cli.ts +17 -5
  959. package/scripts/run/run-step-lane-plan.ts +27 -0
  960. package/scripts/run/run-step-section.ts +26 -7
  961. package/scripts/run/run-step.ts +6 -3
  962. package/scripts/run/run-stranded-detect.ts +13 -0
  963. package/scripts/run/run-watcher-guard-cli.ts +1 -1
  964. package/scripts/run/run-watcher-guard.ts +1 -1
  965. package/scripts/run/ship/run-ship-args.ts +140 -0
  966. package/scripts/run/ship/run-ship-body-draft.ts +110 -0
  967. package/scripts/run/ship/run-ship-brokered-review.ts +106 -0
  968. package/scripts/run/ship/run-ship-cli.ts +181 -166
  969. package/scripts/run/ship/run-ship-conflict-probe.ts +59 -0
  970. package/scripts/run/ship/run-ship-detach.ts +29 -12
  971. package/scripts/run/ship/run-ship-handover.ts +106 -0
  972. package/scripts/run/ship/run-ship-infra-retry.ts +74 -0
  973. package/scripts/run/ship/run-ship-lap.ts +63 -0
  974. package/scripts/run/ship/run-ship-next.ts +44 -27
  975. package/scripts/run/ship/run-ship-overlap.ts +49 -7
  976. package/scripts/run/ship/run-ship-place.ts +103 -0
  977. package/scripts/run/ship/run-ship-planned.ts +92 -0
  978. package/scripts/run/ship/run-ship-pre-detach-pinned.ts +197 -0
  979. package/scripts/run/ship/run-ship-pre-detach-timed.ts +42 -0
  980. package/scripts/run/ship/run-ship-pre-detach.ts +144 -33
  981. package/scripts/run/ship/run-ship-preflight.ts +150 -33
  982. package/scripts/run/ship/run-ship-probe.ts +28 -6
  983. package/scripts/run/ship/run-ship-relaunch-cap.ts +106 -0
  984. package/scripts/run/ship/run-ship-relaunch.ts +51 -0
  985. package/scripts/run/ship/run-ship-removed-rows.ts +61 -0
  986. package/scripts/run/ship/run-ship-return.ts +183 -25
  987. package/scripts/run/ship/run-ship-review-reason.ts +24 -0
  988. package/scripts/run/ship/run-ship-review-steps.ts +296 -171
  989. package/scripts/run/ship/run-ship-review.ts +222 -35
  990. package/scripts/run/ship/run-ship-reviewer.ts +303 -0
  991. package/scripts/run/ship/run-ship-scoped.ts +39 -10
  992. package/scripts/run/ship/run-ship-stage.ts +101 -16
  993. package/scripts/run/ship/run-ship-steps.ts +68 -17
  994. package/scripts/run/ship/run-ship-stop-cause.ts +176 -0
  995. package/scripts/run/ship/run-ship-stop-context.ts +50 -13
  996. package/scripts/run/ship/run-ship-stop-text.ts +11 -6
  997. package/scripts/run/ship/run-ship-sync.ts +212 -34
  998. package/scripts/run/ship/run-ship-synced-scope.ts +178 -0
  999. package/scripts/run/ship/run-ship-wait-cli.ts +145 -0
  1000. package/scripts/run/ship/run-ship-waiter.ts +114 -0
  1001. package/scripts/run/ship/run-ship.ts +44 -2
  1002. package/scripts/run/tidy/run-tidy-cli.ts +0 -4
  1003. package/scripts/run/tidy/run-tidy-lanes.ts +3 -0
  1004. package/scripts/run/tidy/run-tidy-main.ts +8 -0
  1005. package/scripts/run/wake/run-wake-caffeinate.ts +48 -0
  1006. package/scripts/run/wake/run-wake-cli.ts +121 -209
  1007. package/scripts/run/wake/run-wake-code.ts +125 -0
  1008. package/scripts/run/wake/run-wake-driver.ts +22 -9
  1009. package/scripts/run/wake/run-wake-finish.ts +137 -0
  1010. package/scripts/run/wake/run-wake-loop.ts +36 -3
  1011. package/scripts/run/wake/run-wake-main.ts +13 -0
  1012. package/scripts/run/wake/run-wake-ports.ts +98 -0
  1013. package/scripts/run/wake/run-wake-session.ts +2 -0
  1014. package/scripts/run/wake/run-wake-takeover.ts +66 -0
  1015. package/scripts/run/wake/run-wake.ts +5 -3
  1016. package/scripts/safe-chain/ci-installer-pin.ts +49 -8
  1017. package/scripts/safe-chain/pack-hook.ts +2 -2
  1018. package/scripts/safe-chain/preinstall-command.ts +2 -1
  1019. package/scripts/safe-chain/project-config.ts +6 -11
  1020. package/scripts/security/secretlint-scan.ts +42 -9
  1021. package/scripts/security/security-audit-main.ts +8 -0
  1022. package/scripts/security/security-audit-provision-logic.ts +0 -11
  1023. package/scripts/security/security-audit-provision-main.ts +20 -0
  1024. package/scripts/security/security-audit-provision.ts +12 -27
  1025. package/scripts/security/security-audit.ts +27 -8
  1026. package/scripts/security/sonar-file.ts +10 -5
  1027. package/scripts/self-sync-guard/self-sync-guard-logic.ts +6 -13
  1028. package/scripts/split/split-assess-cli.ts +2 -2
  1029. package/scripts/split/split-assess.ts +25 -1
  1030. package/scripts/split/split-early-notice.ts +116 -0
  1031. package/scripts/split/split-measure.ts +83 -0
  1032. package/scripts/split/split-resolution.ts +107 -0
  1033. package/scripts/sync/claude-settings-merge.ts +8 -15
  1034. package/scripts/sync/directory-copy-guard.ts +4 -9
  1035. package/scripts/sync/file-content.ts +78 -8
  1036. package/scripts/sync/sync-ai-files.ts +3 -5
  1037. package/scripts/sync/sync-configs.ts +11 -23
  1038. package/scripts/sync/sync-hook-safety.ts +4 -10
  1039. package/scripts/sync/sync-main.ts +11 -0
  1040. package/scripts/sync/sync.ts +25 -37
  1041. package/scripts/test/direct-importers.ts +185 -0
  1042. package/scripts/test/pure-files-entries.ts +83 -0
  1043. package/scripts/test/related-heavy-tests.ts +81 -0
  1044. package/scripts/test/test-declared-changed.ts +2 -2
  1045. package/scripts/test/test-declared.ts +1 -1
  1046. package/scripts/test/test-e2e-guard.ts +25 -1
  1047. package/scripts/test/test-e2e-stamp.ts +38 -0
  1048. package/scripts/test/test-no-base.ts +88 -0
  1049. package/scripts/test/test-pinned-cache-logic.ts +363 -0
  1050. package/scripts/test/test-pinned-cache.ts +337 -0
  1051. package/scripts/test/test-pinned-emit.ts +49 -0
  1052. package/scripts/test/test-pinned-functions.ts +116 -0
  1053. package/scripts/test/test-pinned-ledger.ts +80 -0
  1054. package/scripts/test/test-pinned-logic.ts +333 -0
  1055. package/scripts/test/test-pinned-main.ts +144 -0
  1056. package/scripts/test/test-pinned-pool.ts +73 -0
  1057. package/scripts/test/test-pinned-probe.ts +254 -0
  1058. package/scripts/test/test-pinned-prune-logic.ts +118 -0
  1059. package/scripts/test/test-pinned-reach.ts +194 -0
  1060. package/scripts/test/test-pinned-record.ts +196 -0
  1061. package/scripts/test/test-pinned-rewire.ts +148 -0
  1062. package/scripts/test/test-pinned-spawn.ts +81 -0
  1063. package/scripts/test/test-pinned-stage.ts +70 -0
  1064. package/scripts/test/test-pinned.ts +311 -0
  1065. package/scripts/test/test-reach-cli.ts +61 -0
  1066. package/scripts/test/test-read-map.ts +288 -0
  1067. package/scripts/test/test-read-recording.ts +103 -0
  1068. package/scripts/test/test-read-trace.ts +166 -0
  1069. package/scripts/test/test-red-logic.ts +46 -7
  1070. package/scripts/test/test-red-main.ts +12 -0
  1071. package/scripts/test/test-red.ts +39 -37
  1072. package/scripts/test/test-related-claim.ts +37 -0
  1073. package/scripts/test/test-related-main.ts +21 -0
  1074. package/scripts/test/test-related-moved.ts +91 -0
  1075. package/scripts/test/test-related-record.ts +139 -0
  1076. package/scripts/test/test-related-scope.ts +292 -41
  1077. package/scripts/test/test-related-synced.ts +135 -0
  1078. package/scripts/test/test-related-touched.ts +84 -0
  1079. package/scripts/test/test-related.ts +381 -19
  1080. package/scripts/test/test-unit-guard-main.ts +15 -0
  1081. package/scripts/test/test-unit-guard.ts +66 -25
  1082. package/scripts/test/unit-count-file.ts +37 -0
  1083. package/scripts/test/unit-durations.ts +41 -0
  1084. package/scripts/test/unit-run-marker.ts +162 -0
  1085. package/scripts/test/unit-setup-files.ts +51 -0
  1086. package/scripts/test/unit-worker-share.ts +64 -151
  1087. package/scripts/test/vitest-cache-directory.ts +19 -0
  1088. package/scripts/test/vitest-cli-excludes.ts +14 -0
  1089. package/scripts/test/vitest-failure-summary.ts +111 -0
  1090. package/scripts/test/whole-suite-files.ts +74 -0
  1091. package/scripts/time-runtime/time-background.ts +20 -2
  1092. package/scripts/time-runtime/time-batch-guard.ts +42 -4
  1093. package/scripts/time-runtime/time-bundle-call.ts +1 -1
  1094. package/scripts/time-runtime/time-bundles.ts +40 -8
  1095. package/scripts/time-runtime/time-density-hook.ts +8 -6
  1096. package/scripts/time-runtime/time-followup-stage.ts +1 -3
  1097. package/scripts/time-runtime/time-format.ts +5 -28
  1098. package/scripts/time-runtime/time-markers.ts +12 -3
  1099. package/scripts/time-runtime/time-search-call.ts +38 -0
  1100. package/scripts/time-runtime/time-shell.ts +98 -11
  1101. package/scripts/time-runtime/time-transcript-line.ts +65 -66
  1102. package/scripts/uninstall/uninstall.ts +1 -1
  1103. package/scripts/version/bump-version-main.ts +12 -0
  1104. package/scripts/version/bump-version.ts +25 -25
  1105. package/scripts/version/development-engines-verdict.ts +124 -0
  1106. package/scripts/version/effective-upstream.ts +6 -12
  1107. package/scripts/version/latest-corepack.ts +19 -32
  1108. package/scripts/version/latest-if-required-cli.ts +93 -0
  1109. package/scripts/version/latest-lane-guard-main.ts +8 -0
  1110. package/scripts/version/latest-lane-guard.ts +0 -4
  1111. package/scripts/version/latest-scope-cli.ts +0 -9
  1112. package/scripts/version/latest-scope-main.ts +12 -0
  1113. package/scripts/version/latest-update.ts +5 -5
  1114. package/scripts/version/npm-registry.ts +44 -6
  1115. package/scripts/version/publishable-range-check.ts +5 -16
  1116. package/scripts/version/release-age.ts +1 -1
  1117. package/scripts/version/release-hold.ts +1 -1
  1118. package/scripts/version/release-window.ts +38 -0
  1119. package/scripts/version/running-binary.ts +1 -1
  1120. package/scripts/version/safe-chain-version-update.ts +3 -8
  1121. package/scripts/version/version-targets.ts +6 -28
  1122. package/templates/dependabot.yml +29 -0
  1123. package/templates/gitignore +6 -1
  1124. package/templates/pnpm-workspace.basic.yaml +1 -1
  1125. package/templates/sonar-project.properties +3 -2
  1126. package/templates/workflows/ci.yml +53 -4
  1127. package/templates/workflows/github-release.yml +4 -0
  1128. package/tsconfig.sonar.json +1 -1
  1129. package/.ncurc.json +0 -3
  1130. package/dist/hooks/batch-guard.js +0 -29
  1131. package/dist/hooks/chunk-4KKD2UTK.js +0 -66
  1132. package/dist/hooks/chunk-6TS2JD6D.js +0 -237
  1133. package/dist/hooks/chunk-7DSBJVFH.js +0 -50
  1134. package/dist/hooks/chunk-A65Y4YOR.js +0 -79
  1135. package/dist/hooks/chunk-APUO6U4J.js +0 -2451
  1136. package/dist/hooks/chunk-CDY4NFQG.js +0 -15
  1137. package/dist/hooks/chunk-DGT54IH5.js +0 -161
  1138. package/dist/hooks/chunk-EFXE6C37.js +0 -81
  1139. package/dist/hooks/chunk-GP4IEC4O.js +0 -20
  1140. package/dist/hooks/chunk-JP45SOCJ.js +0 -56
  1141. package/dist/hooks/chunk-LAOV7NLM.js +0 -45
  1142. package/dist/hooks/chunk-M4HGZV7U.js +0 -83
  1143. package/dist/hooks/chunk-O6GDRNJB.js +0 -343
  1144. package/dist/hooks/chunk-PF2NZL2A.js +0 -131
  1145. package/dist/hooks/chunk-PTICX4OL.js +0 -358
  1146. package/dist/hooks/chunk-RT27QRJW.js +0 -6247
  1147. package/dist/hooks/chunk-SYOTDYCI.js +0 -3533
  1148. package/dist/hooks/chunk-TNUMY6NL.js +0 -4838
  1149. package/dist/hooks/chunk-UPUZF3AN.js +0 -279
  1150. package/dist/hooks/chunk-WK6SMBIC.js +0 -3180
  1151. package/dist/hooks/duplicate-read-guard.js +0 -30
  1152. package/dist/hooks/investigation-guard.js +0 -29
  1153. package/scripts/backlog/backlog-stalled-cli.ts +0 -30
  1154. package/scripts/cost-runtime/context-cut-threshold.ts +0 -11
  1155. package/scripts/cost-runtime/cost-format.ts +0 -29
  1156. package/scripts/init/basic-path-migration.ts +0 -24
  1157. package/scripts/issue/issue-backlinks-cli.ts +0 -93
  1158. package/scripts/josh/josh-commands-guard.ts +0 -38
  1159. package/scripts/josh/josh-usage-automation.ts +0 -121
  1160. package/scripts/josh/josh-usage-backlog.ts +0 -180
  1161. package/scripts/josh/josh-usage-developer.ts +0 -230
  1162. package/scripts/josh/josh-usage-hooks.ts +0 -38
  1163. package/scripts/josh/josh-usage-issue.ts +0 -205
  1164. package/scripts/josh/josh-usage-review.ts +0 -101
  1165. package/scripts/josh/josh-usage-run.ts +0 -252
  1166. package/scripts/josh/josh-usage-session.ts +0 -238
  1167. package/scripts/josh/josh-usage-workflow.ts +0 -212
  1168. package/scripts/lint/cross-file-recheck.ts +0 -155
  1169. package/scripts/registry-migration/migrate-logic.ts +0 -237
  1170. package/scripts/registry-migration/migrate.ts +0 -292
  1171. package/scripts/registry-migration/user-npmrc.ts +0 -15
  1172. package/scripts/rules/filing-cap.ts +0 -132
  1173. package/scripts/rules/rule-guard.ts +0 -23
  1174. package/scripts/rules/rule-registry-rows.ts +0 -292
  1175. package/scripts/rules/rule-registry.ts +0 -112
  1176. package/scripts/run/run-stranded-cli.ts +0 -27
@@ -1,3533 +0,0 @@
1
- import {
2
- FULL_PAGE_QUERY,
3
- MERGED_STATE,
4
- detached_launch,
5
- forget_pr_numbers,
6
- gh_failure,
7
- git_common_directory,
8
- git_gh_api_path,
9
- git_gh_exec,
10
- git_gh_helpers,
11
- git_gh_pr_read,
12
- git_gh_pr_rest,
13
- issue_cite,
14
- lane_child_invocation,
15
- parse_json_array_or_undefined,
16
- parse_json_object_or_undefined,
17
- read_json_listing,
18
- read_pull,
19
- repo_discovery,
20
- repo_origin,
21
- require_pr_number,
22
- run_event_stream,
23
- run_event_stream_emit,
24
- run_hold,
25
- session_cite,
26
- stamp_record,
27
- to_gh_state
28
- } from "./chunk-WK6SMBIC.js";
29
- import {
30
- error_text
31
- } from "./chunk-CDY4NFQG.js";
32
- import {
33
- agent_role_profile,
34
- agent_session_role
35
- } from "./chunk-UPUZF3AN.js";
36
- import {
37
- CHECK_STATUS_FAIL,
38
- CHECK_STATUS_PENDING,
39
- PrConflictError,
40
- cost_attribute,
41
- cost_blocks,
42
- describe_pr_failure,
43
- evaluate_pr_state,
44
- is_coderabbit_check,
45
- is_merge_conflict,
46
- is_required_check,
47
- is_review_decision_decisive,
48
- parse_pr_state_snapshot,
49
- read_string,
50
- time_density_hook,
51
- time_shell,
52
- time_transcript_line
53
- } from "./chunk-TNUMY6NL.js";
54
- import {
55
- lane_child_marker
56
- } from "./chunk-LAOV7NLM.js";
57
- import {
58
- backlog_budget,
59
- blocking_issue_schema,
60
- cli_flags,
61
- cost_transcript,
62
- cost_usage,
63
- git_command,
64
- issue_number_shape,
65
- json_value,
66
- lane_paths,
67
- own_session,
68
- process_identity
69
- } from "./chunk-APUO6U4J.js";
70
- import {
71
- PLATFORM_TEMP_ROOT,
72
- PROJECT_ROOT,
73
- stamp_file
74
- } from "./chunk-DGT54IH5.js";
75
-
76
- // scripts/lib/bounded-pool.ts
77
- function pool_width(limit, total) {
78
- if (!Number.isFinite(limit)) return 1;
79
- return Math.max(1, Math.min(Math.floor(limit), total));
80
- }
81
- function throw_first_failure(failures) {
82
- if (failures.length === 0) return;
83
- const [first] = failures;
84
- throw first;
85
- }
86
- async function drain(pool, worker) {
87
- for (let entry = pool.queue.shift(); entry !== void 0 && pool.failures.length === 0; entry = pool.queue.shift()) {
88
- const [index, item] = entry;
89
- try {
90
- pool.results.push({ index, value: await worker(item, index) });
91
- } catch (error) {
92
- pool.failures.push(error);
93
- }
94
- }
95
- }
96
- async function bounded_map(items, limit, worker) {
97
- const pool = {
98
- failures: [],
99
- queue: items.map((item, index) => [index, item]),
100
- results: []
101
- };
102
- const consumers = Array.from({ length: pool_width(limit, items.length) }, async () => {
103
- await drain(pool, worker);
104
- });
105
- await Promise.all(consumers);
106
- throw_first_failure(pool.failures);
107
- return pool.results.toSorted((left, right) => left.index - right.index).map((result) => result.value);
108
- }
109
- var bounded_pool = { bounded_map, pool_width };
110
-
111
- // scripts/rules/tail-commands.ts
112
- function is_bash_use(block) {
113
- return block.type === cost_blocks.TOOL_USE_TYPE && block.name === cost_blocks.BASH_TOOL;
114
- }
115
- function bash_commands_of(line) {
116
- const parsed = time_transcript_line.parse_line(line);
117
- if (parsed === void 0) return [];
118
- return parsed.blocks.filter((block) => is_bash_use(block)).map((block) => time_shell.bash_command(block.input));
119
- }
120
- function prior_bash_commands(tail) {
121
- return tail.split("\n").flatMap((line) => bash_commands_of(line));
122
- }
123
- function answered(text, is_call, token) {
124
- const blocks = time_transcript_line.parse_text(text).flatMap((line) => line.blocks);
125
- const call_ids = new Set(
126
- blocks.filter((block) => is_call(time_shell.bash_command(block.input))).map((block) => block.id)
127
- );
128
- return blocks.some((block) => call_ids.has(block.result_id) && block.token_lines.includes(token));
129
- }
130
- var tail_commands = { answered, is_bash_use, prior_bash_commands };
131
-
132
- // scripts/rules/shell-segments.ts
133
- var SEGMENT_SEPARATOR = /&&|\|\||;|\n/u;
134
- var SEGMENT_PARTS = new RegExp(`(${SEGMENT_SEPARATOR.source})`, "u");
135
- function segments_of(command) {
136
- return command.split(SEGMENT_SEPARATOR).map((segment) => segment.trim());
137
- }
138
- function parts_of(command) {
139
- return command.split(SEGMENT_PARTS);
140
- }
141
- function first_of(command) {
142
- const plain = time_shell.blanked(command);
143
- if (plain === void 0) return void 0;
144
- const cut = plain.search(SEGMENT_SEPARATOR);
145
- return (cut === -1 ? command : command.slice(0, cut)).trim();
146
- }
147
- function is_josh_command(segment, names) {
148
- const named = time_shell.josh_command_of(segment);
149
- if (!named.startsWith(time_shell.JOSH_PREFIX)) return false;
150
- return names.has(named.slice(time_shell.JOSH_PREFIX.length));
151
- }
152
- var shell_segments = {
153
- first_of,
154
- is_josh_command,
155
- parts_of,
156
- segments_of
157
- };
158
-
159
- // scripts/rules/bash-triggers.ts
160
- function on_bash_command(is_match) {
161
- return function is_trigger(call) {
162
- if (call.name !== cost_blocks.BASH_TOOL) return false;
163
- return is_match(time_shell.bash_command(call.input));
164
- };
165
- }
166
- var ISSUE_CREATE_COMMAND = /\bgh\s+(?:\S+\s+)*?issue\s+create\b/u;
167
- var ISSUES_ENDPOINT = /repos\/[^\s'"]*\/issues(?=$|["'\s])/u;
168
- var TITLE_FIELD = /(?:-f|-F|--field|--raw-field)\s*'?title=/u;
169
- function is_direct_filing(command) {
170
- if (ISSUE_CREATE_COMMAND.test(command)) return true;
171
- return ISSUES_ENDPOINT.test(command) && TITLE_FIELD.test(command);
172
- }
173
- var FILING_NAMES = /* @__PURE__ */ new Set(["issue:file"]);
174
- function is_issue_filing(command) {
175
- return shell_segments.segments_of(command).some((segment) => shell_segments.is_josh_command(segment, FILING_NAMES));
176
- }
177
- var bash_triggers = { is_direct_filing, is_issue_filing, on_bash_command };
178
-
179
- // scripts/rules/filing-cap.ts
180
- var FILING_CAP = 10;
181
- var CAP_REACHED = FILING_CAP;
182
- function is_filing_use(block) {
183
- if (!tail_commands.is_bash_use(block)) return false;
184
- return bash_triggers.is_issue_filing(time_shell.bash_command(block.input));
185
- }
186
- function collect_block(block, found) {
187
- if (block.result_id !== "" && block.is_error === true) found.failures.add(block.result_id);
188
- if (is_filing_use(block)) found.filing_ids.push(block.id);
189
- }
190
- function collect_line(line, found) {
191
- const parsed = time_transcript_line.parse_line(line);
192
- if (parsed === void 0) return;
193
- for (const block of parsed.blocks) collect_block(block, found);
194
- }
195
- function scan_tail(tail) {
196
- const found = { filing_ids: [], failures: /* @__PURE__ */ new Set() };
197
- for (const line of tail.split("\n")) collect_line(line, found);
198
- return found;
199
- }
200
- function prior_filing_count(tail) {
201
- const { filing_ids, failures } = scan_tail(tail);
202
- return filing_ids.filter((id) => !failures.has(id)).length;
203
- }
204
- function is_prompt_line(line) {
205
- const parsed = time_transcript_line.parse_line(line);
206
- if (parsed?.type !== "user") return false;
207
- return parsed.blocks.every((block) => block.result_id === "");
208
- }
209
- function current_turn(tail) {
210
- const lines = tail.split("\n");
211
- const start = lines.findLastIndex((line) => is_prompt_line(line));
212
- return lines.slice(Math.max(start, 0)).join("\n");
213
- }
214
- function turn_filing_count(tail) {
215
- return prior_filing_count(current_turn(tail));
216
- }
217
- function decide(_call, run2) {
218
- return prior_filing_count(time_density_hook.read_tail(run2.transcript)) >= CAP_REACHED;
219
- }
220
- var FILING_CAP_REASON = `\u26D4 filing cap: this run has already filed ${String(FILING_CAP)} Issues, the per-run ceiling. Stop filing and report; a further Issue is a person's call. It fires on every occurrence (\`.claude/skills/workflow-commands/observation-filing.md\`).`;
221
- var ROW = {
222
- id: "filing-cap",
223
- is_trigger: bash_triggers.on_bash_command(bash_triggers.is_issue_filing),
224
- reason: FILING_CAP_REASON,
225
- decide
226
- };
227
- var filing_cap = {
228
- FILING_CAP,
229
- FILING_CAP_REASON,
230
- ROW,
231
- current_turn,
232
- is_prompt_line,
233
- prior_filing_count,
234
- turn_filing_count
235
- };
236
-
237
- // scripts/cost-runtime/cost-pricing.ts
238
- var CACHE_WRITE_5M_MULTIPLIER = 1.25;
239
- var CACHE_WRITE_1H_MULTIPLIER = 2;
240
- var DEFAULT_CACHE_READ_MULTIPLIER = 0.1;
241
- var HALVED_CACHE_READ_MULTIPLIER = 0.05;
242
- var QUARTERED_CACHE_READ_MULTIPLIER = 0.025;
243
- var TOKENS_PER_MILLION = 1e6;
244
- var LONG_PROMPT_SUFFIX = ":long-prompt";
245
- var LONG_PROMPT_THRESHOLD = 1e5;
246
- var MODEL_PRICES = {
247
- "claude-fable-5-1": {
248
- input: 10,
249
- output: 50,
250
- cache_read_multiplier: QUARTERED_CACHE_READ_MULTIPLIER
251
- },
252
- "claude-mythos-5-1": {
253
- input: 10,
254
- output: 50,
255
- cache_read_multiplier: QUARTERED_CACHE_READ_MULTIPLIER
256
- },
257
- "claude-fable-5": { input: 10, output: 50 },
258
- "claude-mythos-5": { input: 10, output: 50 },
259
- "claude-opus-5-5": { input: 4, output: 20, cache_read_multiplier: HALVED_CACHE_READ_MULTIPLIER },
260
- "claude-opus-5": { input: 5, output: 25 },
261
- "claude-opus-4-8": { input: 5, output: 25 },
262
- "claude-opus-4-7": { input: 5, output: 25 },
263
- "claude-opus-4-6": { input: 5, output: 25 },
264
- "claude-sonnet-5-5": {
265
- input: 2,
266
- output: 10,
267
- cache_read_multiplier: HALVED_CACHE_READ_MULTIPLIER
268
- },
269
- "claude-sonnet-5": { input: 2, output: 10 },
270
- "claude-sonnet-4-6": { input: 3, output: 15 },
271
- "claude-haiku-5-5": { input: 0.1, output: 0.5 },
272
- [`claude-haiku-5-5${LONG_PROMPT_SUFFIX}`]: { input: 0.5, output: 2.5 },
273
- "claude-haiku-4-5": { input: 1, output: 5 }
274
- };
275
- var CONTEXT_MARKER = "[";
276
- var DATE_SUFFIX = /-\d{8}$/u;
277
- function known_id(model) {
278
- const base = model.split(CONTEXT_MARKER)[0] ?? model;
279
- return [base, base.replace(DATE_SUFFIX, "")].find((id) => Object.hasOwn(MODEL_PRICES, id));
280
- }
281
- function resolve_price(model) {
282
- const id = known_id(model);
283
- return id === void 0 ? void 0 : MODEL_PRICES[id];
284
- }
285
- function cache_read_multiplier(price) {
286
- return price.cache_read_multiplier ?? DEFAULT_CACHE_READ_MULTIPLIER;
287
- }
288
- function estimate_cost(totals, price) {
289
- const weighted_input = totals.input_tokens + totals.cache_write_5m_tokens * CACHE_WRITE_5M_MULTIPLIER + totals.cache_write_1h_tokens * CACHE_WRITE_1H_MULTIPLIER + totals.cache_read_tokens * cache_read_multiplier(price);
290
- return (weighted_input * price.input + totals.output_tokens * price.output) / TOKENS_PER_MILLION;
291
- }
292
- function priced(tokens, rate) {
293
- return tokens * rate / TOKENS_PER_MILLION;
294
- }
295
- function estimate_composition(totals, price) {
296
- return {
297
- input_usd: priced(totals.input_tokens, price.input),
298
- cache_write_5m_usd: priced(
299
- totals.cache_write_5m_tokens * CACHE_WRITE_5M_MULTIPLIER,
300
- price.input
301
- ),
302
- cache_write_1h_usd: priced(
303
- totals.cache_write_1h_tokens * CACHE_WRITE_1H_MULTIPLIER,
304
- price.input
305
- ),
306
- cache_read_usd: priced(totals.cache_read_tokens * cache_read_multiplier(price), price.input),
307
- output_usd: priced(totals.output_tokens, price.output)
308
- };
309
- }
310
- function to_model_cost(model, totals) {
311
- const price = resolve_price(model);
312
- if (price === void 0) return { model, totals };
313
- return { model, totals, cost_usd: estimate_cost(totals, price) };
314
- }
315
- function billed_model(usage) {
316
- const long_id = `${known_id(usage.model) ?? usage.model}${LONG_PROMPT_SUFFIX}`;
317
- const is_long = cost_usage.billed_input(usage.totals) > LONG_PROMPT_THRESHOLD;
318
- return is_long && Object.hasOwn(MODEL_PRICES, long_id) ? long_id : usage.model;
319
- }
320
- function cost_by_model(records) {
321
- const grouped = /* @__PURE__ */ new Map();
322
- for (const record of records) {
323
- const model = billed_model(record);
324
- const running = grouped.get(model) ?? cost_usage.EMPTY_TOTALS;
325
- grouped.set(model, cost_usage.add_totals(running, record.totals));
326
- }
327
- return [...grouped].map(([model, totals]) => to_model_cost(model, totals));
328
- }
329
- function total_cost(costs) {
330
- return {
331
- usd: costs.reduce((sum, entry) => sum + (entry.cost_usd ?? 0), 0),
332
- unpriced: costs.filter((entry) => entry.cost_usd === void 0).map((entry) => entry.model)
333
- };
334
- }
335
- function cost_of(records) {
336
- return total_cost(cost_by_model(records)).usd;
337
- }
338
- var cost_pricing = {
339
- CACHE_WRITE_5M_MULTIPLIER,
340
- CACHE_WRITE_1H_MULTIPLIER,
341
- DEFAULT_CACHE_READ_MULTIPLIER,
342
- LONG_PROMPT_THRESHOLD,
343
- resolve_price,
344
- estimate_cost,
345
- estimate_composition,
346
- cost_by_model,
347
- total_cost,
348
- cost_of
349
- };
350
-
351
- // scripts/cost-runtime/context-cut-payback.ts
352
- var POST_CUT_CONTEXT = 6e4;
353
- var EXPECTED_REMAINING_REQUESTS = 10;
354
- function write_over_read() {
355
- return cost_pricing.CACHE_WRITE_5M_MULTIPLIER / cost_pricing.DEFAULT_CACHE_READ_MULTIPLIER;
356
- }
357
- function break_even_context(remaining = EXPECTED_REMAINING_REQUESTS) {
358
- if (remaining <= 0) return Infinity;
359
- return Math.round(POST_CUT_CONTEXT * (1 + write_over_read() / remaining));
360
- }
361
- function break_even_requests(current_context) {
362
- const saved_per_request = current_context - POST_CUT_CONTEXT;
363
- if (saved_per_request <= 0) return Infinity;
364
- return POST_CUT_CONTEXT * write_over_read() / saved_per_request;
365
- }
366
- function pays_back(current_context, remaining = EXPECTED_REMAINING_REQUESTS) {
367
- return current_context > break_even_context(remaining);
368
- }
369
- var context_cut_payback = {
370
- POST_CUT_CONTEXT,
371
- EXPECTED_REMAINING_REQUESTS,
372
- break_even_context,
373
- break_even_requests,
374
- pays_back
375
- };
376
-
377
- // scripts/cost-runtime/context-cut-threshold.ts
378
- var CONTEXT_CUT_THRESHOLD = context_cut_payback.break_even_context();
379
-
380
- // scripts/run/cut/run-cut.ts
381
- import { z as z2 } from "zod";
382
-
383
- // scripts/run/cut/run-cut-handoff.ts
384
- import { readFileSync } from "node:fs";
385
- import { z } from "zod";
386
- var handoff_schema = z.object({
387
- instruction: z.string(),
388
- completed: z.array(z.string()),
389
- remaining: z.array(z.string()),
390
- untouched: z.array(z.string())
391
- });
392
- var COMPLETED_LABEL = "Completed";
393
- var REMAINING_LABEL = "Remaining";
394
- var UNTOUCHED_LABEL = "Deliberately untouched";
395
- var INSTRUCTION_LABEL = "Instruction (verbatim)";
396
- var EMPTY_LIST_NOTE = "(none)";
397
- function describe_key(key2) {
398
- const value = handoff_schema.shape[key2] instanceof z.ZodArray ? '["\u2026"]' : '"\u2026"';
399
- return `"${key2}": ${value}`;
400
- }
401
- var HANDOFF_FORMAT = `a JSON object {${handoff_schema.keyof().options.map((key2) => describe_key(key2)).join(", ")}}`;
402
- function parse_handoff(raw) {
403
- return json_value.parse_with(raw, handoff_schema);
404
- }
405
- function read_handoff_file(handoff_path) {
406
- try {
407
- return parse_handoff(readFileSync(handoff_path, "utf8"));
408
- } catch {
409
- return void 0;
410
- }
411
- }
412
- function is_complete_handoff(handoff) {
413
- return handoff !== void 0 && handoff.instruction.trim() !== "";
414
- }
415
- function is_within_bound(handoff, max_bytes) {
416
- return Buffer.byteLength(JSON.stringify(handoff), "utf8") <= max_bytes;
417
- }
418
- function load_handoff(handoff_path, max_bytes) {
419
- if (handoff_path === void 0) return { kind: "ok", handoff: void 0 };
420
- const handoff = read_handoff_file(handoff_path);
421
- if (handoff === void 0) {
422
- return {
423
- kind: "bad",
424
- note: `--handoff ${handoff_path} is not a readable handoff file \u2014 write ${HANDOFF_FORMAT}`
425
- };
426
- }
427
- if (!is_within_bound(handoff, max_bytes)) {
428
- return { kind: "bad", note: `--handoff ${handoff_path} is too large to carry across the cut` };
429
- }
430
- return { kind: "ok", handoff };
431
- }
432
- function describe_list(label, items) {
433
- if (items.length === 0) return `${label}: ${EMPTY_LIST_NOTE}`;
434
- const bullets = items.map((item) => ` - ${item}`).join("\n");
435
- return `${label}:
436
- ${bullets}`;
437
- }
438
- function describe_handoff(handoff) {
439
- return [
440
- `${INSTRUCTION_LABEL}:
441
- ${handoff.instruction}`,
442
- describe_list(COMPLETED_LABEL, handoff.completed),
443
- describe_list(REMAINING_LABEL, handoff.remaining),
444
- describe_list(UNTOUCHED_LABEL, handoff.untouched)
445
- ].join("\n\n");
446
- }
447
- var HANDOFF_PATH = ".claude/tmp/handoff-<N>.json";
448
- var run_cut_handoff = {
449
- HANDOFF_FORMAT,
450
- HANDOFF_PATH,
451
- describe_handoff,
452
- handoff_schema,
453
- is_complete_handoff,
454
- load_handoff,
455
- parse_handoff,
456
- read_handoff_file
457
- };
458
-
459
- // scripts/run/cut/run-cut.ts
460
- var CUT_PREFIX = "josh-run-cut-";
461
- var { PRE_GATE_PHASE, IMPLEMENTATION_PHASE } = agent_role_profile;
462
- var IMPLEMENTATION_CONTEXT_THRESHOLD = CONTEXT_CUT_THRESHOLD;
463
- var CUT_MAX_AGE_MS = backlog_budget.DEFAULT_IDLE_MS;
464
- var CUT_MAX_AGE_HOURS = backlog_budget.IDLE_WAIT_HOURS;
465
- var END_COMMAND = "pnpm josh run:cut --end";
466
- var READ_COMMAND = "pnpm josh run:cut --json";
467
- var MAX_HANDOFF_BYTES = 8192;
468
- var run_cut_schema = z2.object({
469
- invocation: z2.string(),
470
- issue: z2.string(),
471
- branch: z2.string(),
472
- phase: z2.string(),
473
- cut_at: z2.string(),
474
- is_handed_off: z2.boolean().optional(),
475
- handoff: run_cut_handoff.handoff_schema.optional(),
476
- is_merge_relaunched: z2.boolean().optional()
477
- });
478
- function cut_path(git_directory) {
479
- return stamp_file.stamp_path(CUT_PREFIX, git_directory);
480
- }
481
- var { worktree_directory } = run_hold;
482
- function invocation_for(issue) {
483
- return lane_child_invocation.child_invocation(issue);
484
- }
485
- function parse_cut(raw) {
486
- return json_value.parse_with(raw, run_cut_schema);
487
- }
488
- function cut_at_of(cut) {
489
- return cut.cut_at;
490
- }
491
- var CUT_SPEC = {
492
- parse: parse_cut,
493
- timestamp_of: cut_at_of,
494
- max_age_ms: CUT_MAX_AGE_MS
495
- };
496
- function is_expired(cut, now) {
497
- return stamp_record.is_older_than(cut_at_of(cut), CUT_MAX_AGE_MS, now);
498
- }
499
- function classify(raw, now) {
500
- const read2 = stamp_record.classify(raw, CUT_SPEC, now);
501
- if (!("record" in read2)) return read2;
502
- return { kind: read2.kind, cut: read2.record };
503
- }
504
- function read_cut(target, now = /* @__PURE__ */ new Date()) {
505
- return classify(stamp_file.read_stamp_text(target), now);
506
- }
507
- function worktree_git_directory_sync() {
508
- return git_common_directory.own();
509
- }
510
- function carried_cut_sync(now = /* @__PURE__ */ new Date(), directory = worktree_git_directory_sync()) {
511
- if (directory === void 0) return void 0;
512
- const read2 = read_cut(cut_path(directory), now);
513
- return read2.kind === "carried" ? read2.cut : void 0;
514
- }
515
- function lane_cut_sync(lane_directory) {
516
- const directory = git_common_directory.own(lane_directory);
517
- if (directory === void 0) return void 0;
518
- const cut = carried_cut_sync(/* @__PURE__ */ new Date(), directory);
519
- return cut === void 0 ? void 0 : { target: cut_path(directory), cut };
520
- }
521
- function fresh_cut(spec, now) {
522
- return {
523
- invocation: invocation_for(spec.issue),
524
- issue: spec.issue,
525
- branch: spec.branch,
526
- phase: spec.phase,
527
- cut_at: now.toISOString(),
528
- is_handed_off: true,
529
- handoff: spec.handoff
530
- };
531
- }
532
- function resumes_into_implementation(phase) {
533
- return phase === IMPLEMENTATION_PHASE;
534
- }
535
- function within_handoff_bound(cut) {
536
- return Buffer.byteLength(JSON.stringify(cut), "utf8") <= MAX_HANDOFF_BYTES;
537
- }
538
- function record_within_bound(spec, now = /* @__PURE__ */ new Date()) {
539
- return within_handoff_bound(fresh_cut(spec, now));
540
- }
541
- function begin_cut(target, spec, now = /* @__PURE__ */ new Date()) {
542
- const cut = fresh_cut(spec, now);
543
- if (!within_handoff_bound(cut)) return void 0;
544
- return stamp_file.create_stamp(target, cut) ? cut : void 0;
545
- }
546
- function is_declared_cut(cut, issue) {
547
- return cut.is_handed_off === true && cut.invocation === invocation_for(issue);
548
- }
549
- function matches_state(cut, request) {
550
- return cut.branch === request.current_branch && cut.issue === request.issue && request.is_dirty && request.is_held;
551
- }
552
- function is_adopted_cut(cut, issue) {
553
- return cut.is_handed_off === false && cut.invocation === invocation_for(issue);
554
- }
555
- function has_required_handoff(cut) {
556
- return !resumes_into_implementation(cut.phase) || run_cut_handoff.is_complete_handoff(cut.handoff);
557
- }
558
- function is_relaunchable(cut, issue) {
559
- return is_declared_cut(cut, issue) && has_required_handoff(cut) && cut.is_merge_relaunched !== true;
560
- }
561
- function mark_merge_relaunched(target, cut) {
562
- stamp_file.remove_stamp(target);
563
- return stamp_file.create_stamp(target, { ...cut, is_merge_relaunched: true });
564
- }
565
- function classify_resume(cut, request) {
566
- if (is_adopted_cut(cut, request.issue)) return "handed-off";
567
- if (!is_declared_cut(cut, request.issue) || !matches_state(cut, request)) return "stale";
568
- return has_required_handoff(cut) ? "resume" : "incomplete";
569
- }
570
- function adopt_cut(target, cut) {
571
- const next = { ...cut, is_handed_off: false };
572
- stamp_file.remove_stamp(target);
573
- return stamp_file.create_stamp(target, next) ? next : void 0;
574
- }
575
- function end_cut(target) {
576
- stamp_file.remove_stamp(target);
577
- }
578
- function hold_of(directory) {
579
- if (directory === void 0) return void 0;
580
- const read2 = run_hold.read_hold(run_hold.hold_path(directory));
581
- return read2.kind === "held" || read2.kind === "stale" ? read2.hold : void 0;
582
- }
583
- function fullrun_issue(hold) {
584
- return hold?.is_fullrun === true ? hold.issue : void 0;
585
- }
586
- function held_issue_sync() {
587
- return fullrun_issue(hold_of(worktree_git_directory_sync()));
588
- }
589
- async function current_state() {
590
- const branch = await git_command.branch();
591
- const is_dirty = await run_hold.is_tree_dirty();
592
- const hold = hold_of(await worktree_directory());
593
- return {
594
- branch,
595
- is_dirty,
596
- is_held: hold !== void 0,
597
- held_issue: fullrun_issue(hold),
598
- hold_taken_at: hold?.taken_at
599
- };
600
- }
601
- function describe_cut(cut) {
602
- return `${cut.invocation} cut at ${cut.cut_at} on ${cut.branch} (${cut.phase})`;
603
- }
604
- function busy_message(cut) {
605
- return `Another process already resumed this cut \u2014 ${describe_cut(cut)}. Nothing was resumed here; a double launch was detected.`;
606
- }
607
- function handed_off_message(cut) {
608
- return `This cut was already handed off to a successor \u2014 ${describe_cut(cut)}. Nothing was resumed here; the run is being carried on by the process that adopted it, so this one has nothing to do.`;
609
- }
610
- function stale_message(cut) {
611
- return `This cut does not match the current tree \u2014 ${describe_cut(cut)}. Resume failed; verify the branch and the uncommitted work, then clear it with \`${END_COMMAND}\` if the run is over.`;
612
- }
613
- function incomplete_message(cut) {
614
- return `This cut carries no instruction to resume on \u2014 ${describe_cut(cut)}. Resume was refused rather than continuing without it; recover the run's instruction and work state before implementing, and clear the record with \`${END_COMMAND}\` if the run is over.`;
615
- }
616
- function unreadable_message() {
617
- return `A cut record is here but could not be read; clear it with \`${END_COMMAND}\` once you know no run is using it. Read it with \`${READ_COMMAND}\`.`;
618
- }
619
- function unknown_message() {
620
- return "This working tree\u2019s git directory could not be read, so no cut record was acted on.";
621
- }
622
- var run_cut = {
623
- CUT_MAX_AGE_HOURS,
624
- CUT_MAX_AGE_MS,
625
- END_COMMAND,
626
- IMPLEMENTATION_CONTEXT_THRESHOLD,
627
- IMPLEMENTATION_PHASE,
628
- MAX_HANDOFF_BYTES,
629
- PRE_GATE_PHASE,
630
- adopt_cut,
631
- begin_cut,
632
- busy_message,
633
- carried_cut_sync,
634
- classify,
635
- classify_resume,
636
- current_state,
637
- cut_path,
638
- describe_cut,
639
- end_cut,
640
- fresh_cut,
641
- fullrun_issue,
642
- handed_off_message,
643
- has_required_handoff,
644
- held_issue_sync,
645
- hold_of,
646
- incomplete_message,
647
- invocation_for,
648
- is_expired,
649
- is_relaunchable,
650
- lane_cut_sync,
651
- mark_merge_relaunched,
652
- read_cut,
653
- record_within_bound,
654
- resumes_into_implementation,
655
- stale_message,
656
- unknown_message,
657
- unreadable_message,
658
- within_handoff_bound,
659
- worktree_directory,
660
- worktree_git_directory_sync
661
- };
662
-
663
- // scripts/rules/run-tail-rule.ts
664
- var SEGMENT_PREFIX = String.raw`(?:\(\s*)?(?:[A-Za-z_][A-Za-z0-9_]*=\S*\s+)*(?:npx\s+|pnpm\s+(?:exec\s+|run\s+)?)?`;
665
- var WORD_END = String.raw`(?=\s|$|\))`;
666
- var PUSH_STEP_SEGMENT = new RegExp(String.raw`^${SEGMENT_PREFIX}josh\s+(?:git|g)${WORD_END}`, "u");
667
- var CONFIRMED_FLAG = new RegExp(String.raw`(?:^|\s)(?:-y|--yes)${WORD_END}`, "u");
668
- var SKIPS_THE_PUSH = new RegExp(String.raw`(?:^|\s)--skip-push${WORD_END}`, "u");
669
- var BACKGROUND_KEY = "run_in_background";
670
- var QUOTED_SPAN = /"[^"]*"|'[^']*'/gu;
671
- function flags_of(segment) {
672
- return segment.replaceAll(QUOTED_SPAN, " ");
673
- }
674
- function is_push_step_segment(segment) {
675
- if (!PUSH_STEP_SEGMENT.test(segment)) return false;
676
- const flags = flags_of(segment);
677
- if (SKIPS_THE_PUSH.test(flags)) return false;
678
- return CONFIRMED_FLAG.test(flags);
679
- }
680
- function is_push_step(command) {
681
- return shell_segments.segments_of(command).some((segment) => is_push_step_segment(segment));
682
- }
683
- function is_backgrounded(input) {
684
- if (!json_value.is_record(input)) return false;
685
- return input[BACKGROUND_KEY] === true;
686
- }
687
- function is_push_step_call(call) {
688
- if (call.name !== cost_blocks.BASH_TOOL) return false;
689
- return is_push_step(time_shell.bash_command(call.input));
690
- }
691
- function is_backgrounded_push_step(call) {
692
- if (!is_backgrounded(call.input)) return false;
693
- return is_push_step_call(call);
694
- }
695
- function is_foreground_push_step(call) {
696
- if (is_backgrounded(call.input)) return false;
697
- return is_push_step_call(call);
698
- }
699
- function decide2() {
700
- return true;
701
- }
702
- var RUN_TAIL_REASON = "\u26D4 run tail: this issues the commit-push-PR step in the foreground, where the harness decides when to stop waiting. Reissue it with `run_in_background` set; when it exits, go straight on to `pnpm josh followup` in the foreground \u2014 the turn never ends at the push (`.claude/skills/workflow-commands/background-commands.md`). It fires on every foreground push, not once per run.";
703
- var run_tail_rule = {
704
- RUN_TAIL_REASON,
705
- decide: decide2,
706
- is_backgrounded_push_step,
707
- is_foreground_push_step,
708
- is_push_step,
709
- is_push_step_call
710
- };
711
-
712
- // scripts/rules/lane-background.ts
713
- var SHIP_COMMAND = `${time_shell.JOSH_PREFIX}ship`;
714
- var LONG_RUNNING_COMMANDS = /* @__PURE__ */ new Set([
715
- ...["gate", "git", "followup"].map((name) => `${time_shell.JOSH_PREFIX}${name}`),
716
- SHIP_COMMAND
717
- ]);
718
- var BACKGROUND_KEY2 = "run_in_background";
719
- var TIMEOUT_KEY = "timeout";
720
- var FOREGROUND_TIMEOUT_MS = 6e5;
721
- function is_backgrounded2(input) {
722
- return json_value.is_record(input) && input[BACKGROUND_KEY2] === true;
723
- }
724
- function long_commands_of(command) {
725
- return time_shell.josh_commands_of(command).filter((name) => LONG_RUNNING_COMMANDS.has(name));
726
- }
727
- function ships_alone(command) {
728
- const names = long_commands_of(command);
729
- return names.length > 0 && names.every((name) => name === SHIP_COMMAND);
730
- }
731
- function backgrounded_bash_command(call) {
732
- if (call.name !== cost_blocks.BASH_TOOL || !is_backgrounded2(call.input)) return void 0;
733
- return time_shell.bash_command(call.input);
734
- }
735
- function is_backgrounded_ship(call) {
736
- const command = backgrounded_bash_command(call);
737
- return command !== void 0 && ships_alone(command);
738
- }
739
- function is_candidate(call) {
740
- if (run_tail_rule.is_push_step_call(call)) return true;
741
- const command = backgrounded_bash_command(call);
742
- if (command === void 0 || is_backgrounded_ship(call)) return false;
743
- return long_commands_of(command).length > 0;
744
- }
745
- function is_background_long_run(call, is_lane_child = () => lane_child_marker.is_child_of(process.cwd())) {
746
- return is_candidate(call) && is_lane_child();
747
- }
748
- function foreground_input(call, is_lane_child = () => lane_child_marker.is_child_of(process.cwd())) {
749
- if (!is_backgrounded_ship(call) || !json_value.is_record(call.input) || !is_lane_child()) {
750
- return void 0;
751
- }
752
- return { ...call.input, [BACKGROUND_KEY2]: false, [TIMEOUT_KEY]: FOREGROUND_TIMEOUT_MS };
753
- }
754
- var FOREGROUND_NOTE = "lane background: this lane child backgrounded `josh ship`, which would die with the headless turn before its supervisor exists \u2014 so it was run in the foreground instead, where it detaches itself after the preflight. End the turn on `launched` / `busy`.";
755
- function unfinished_ids(tail, launched_ids) {
756
- const lines = tail.split("\n").map((line) => time_transcript_line.parse_line(line));
757
- const finished = new Set(lines.map((line) => line?.finished_background ?? ""));
758
- const blocks = lines.flatMap((line) => line?.blocks ?? []);
759
- const launched = blocks.flatMap((block) => launched_ids(block));
760
- return launched.filter((id) => id !== "" && !finished.has(id));
761
- }
762
- function pending_background_ids(tail) {
763
- return unfinished_ids(tail, (block) => [block.background_id, block.agent_id]);
764
- }
765
- function pending_agent_ids(tail) {
766
- return unfinished_ids(tail, (block) => [block.agent_id]);
767
- }
768
- var LANE_BACKGROUND_REASON = '\u26D4 lane background: this session is a dispatched lane child (`JOSH_LANE_CHILD`), a headless process whose background tasks die when the turn ends. Hand over to `pnpm josh ship --detach --review "<title> #<N>"`, issued in the foreground, then end the turn on `launched` / `busy`. It fires on every occurrence (`.claude/skills/workflow-commands/chain-rule.md` step 0).';
769
- var LANE_BACKGROUND_STOP_REASON = "\u26D4 lane background stop: this is a dispatched lane child (`JOSH_LANE_CHILD`) and a background task it launched has not finished, and ending this turn kills it. Wait for it in the foreground, or re-issue the work through `pnpm josh ship --detach` \u2014 do not notify, stop or repeat your reply.";
770
- var ROW2 = {
771
- id: "lane-background",
772
- is_trigger: (call) => is_background_long_run(call),
773
- reason: LANE_BACKGROUND_REASON,
774
- decide: () => true
775
- };
776
- var lane_background = {
777
- FOREGROUND_NOTE,
778
- LANE_BACKGROUND_REASON,
779
- LANE_BACKGROUND_STOP_REASON,
780
- ROW: ROW2,
781
- foreground_input,
782
- is_background_long_run,
783
- pending_agent_ids,
784
- pending_background_ids
785
- };
786
-
787
- // scripts/run/ship/run-ship-detach.ts
788
- import { randomUUID } from "node:crypto";
789
- import { setTimeout as sleep } from "node:timers/promises";
790
- import { z as z3 } from "zod";
791
- var LOG_PREFIX = "josh-ship-log-";
792
- var PID_PREFIX = "josh-ship-pid-";
793
- var BODY_PREFIX = "josh-ship-notify-";
794
- var KEY_SEPARATOR = "-";
795
- var LOG_SUFFIX = ".log";
796
- var BODY_SUFFIX = ".txt";
797
- var PNPM = "pnpm";
798
- var INLINE_NOTIFY = "--notify-message";
799
- var FILE_NOTIFY = "--notify-message-file";
800
- var NOTIFY_VALUE_INDEX = 1;
801
- var SUPERVISED_KEY = "JOSH_SHIP_SUPERVISED";
802
- var LAUNCH_ID_KEY = "JOSH_SHIP_LAUNCH_ID";
803
- var SUPERVISED_VALUE = "1";
804
- var LAUNCHED = "launched";
805
- var BUSY = "busy";
806
- var FAILED = "failed";
807
- var RESULT_PREFIX = "josh-ship-result-";
808
- var RECORD_POLL_MS = 25;
809
- var RECORD_WAIT_ATTEMPTS = 200;
810
- var CLAIM_WINDOW_MS = 12e4;
811
- var ship_record_schema = z3.object({
812
- pid: z3.number().int().positive().optional(),
813
- process_start: z3.string().optional(),
814
- launched_at: z3.number().optional(),
815
- launcher_pid: z3.number().int().positive().optional(),
816
- launcher_start: z3.string().optional(),
817
- launch_id: z3.string(),
818
- result: z3.enum(["success", "failed"]).optional()
819
- });
820
- var LAUNCH_MARK = " \xB7 started by process ";
821
- var HEADER_START = "\n";
822
- function key(prefix, request) {
823
- return stamp_file.stamp_path(`${prefix}${request.number}${KEY_SEPARATOR}`, request.repository);
824
- }
825
- function log_path(repository, number) {
826
- return stamp_file.stamp_path(`${LOG_PREFIX}${number}${KEY_SEPARATOR}`, repository, LOG_SUFFIX);
827
- }
828
- function result_path(repository, number) {
829
- return stamp_file.stamp_path(`${RESULT_PREFIX}${number}${KEY_SEPARATOR}`, repository);
830
- }
831
- function read_record(repository, number) {
832
- try {
833
- const raw = stamp_file.read_stamp_text(result_path(repository, number));
834
- return raw === void 0 ? void 0 : json_value.parse_with(raw, ship_record_schema);
835
- } catch {
836
- return void 0;
837
- }
838
- }
839
- function record_launch(request, pid, launch_id) {
840
- stamp_file.write_text_stamp(key(PID_PREFIX, request), String(pid));
841
- const process_start = process_identity.read_start(pid);
842
- stamp_file.replace_stamp(result_path(request.repository, request.number), {
843
- pid,
844
- launch_id,
845
- launched_at: Date.now(),
846
- ...process_start !== void 0 && { process_start }
847
- });
848
- }
849
- function supervisor_environment(launch_id) {
850
- return {
851
- ...agent_role_profile.handoff_environment(),
852
- [SUPERVISED_KEY]: SUPERVISED_VALUE,
853
- [LAUNCH_ID_KEY]: launch_id
854
- };
855
- }
856
- function is_within_claim_window(record) {
857
- return record.launched_at !== void 0 && Date.now() - record.launched_at < CLAIM_WINDOW_MS;
858
- }
859
- function has_live_identity(pid, record) {
860
- if (record.process_start === void 0) {
861
- return is_within_claim_window(record) && process_identity.is_live_pid(pid);
862
- }
863
- return process_identity.is_same_process(pid, record.process_start) !== false;
864
- }
865
- function result_of(record) {
866
- if (record.pid === void 0) {
867
- const is_launcher = process_identity.is_same_process(record.launcher_pid, record.launcher_start);
868
- return is_launcher === false ? "abnormal" : "running";
869
- }
870
- if (has_live_identity(record.pid, record)) return "running";
871
- return record.result ?? "abnormal";
872
- }
873
- function read_result(repository, number) {
874
- const record = read_record(repository, number);
875
- return record === void 0 ? void 0 : { launch_id: record.launch_id, result: result_of(record) };
876
- }
877
- function current_record(repository, number) {
878
- const record = read_record(repository, number);
879
- return record?.launch_id === process.env[LAUNCH_ID_KEY] ? record : void 0;
880
- }
881
- function running_since(repository, number) {
882
- const record = read_record(repository, number);
883
- return record !== void 0 && result_of(record) === "running" ? record.launched_at : void 0;
884
- }
885
- function is_pending(record) {
886
- return record !== void 0 && record.pid === void 0;
887
- }
888
- async function ready_record(repository, number) {
889
- let record = current_record(repository, number);
890
- for (let attempt = 0; attempt < RECORD_WAIT_ATTEMPTS; attempt += 1) {
891
- if (!is_pending(record)) return record;
892
- await sleep(RECORD_POLL_MS);
893
- record = current_record(repository, number);
894
- }
895
- return void 0;
896
- }
897
- async function update_record(repository, number, fields) {
898
- const record = await ready_record(repository, number);
899
- if (record === void 0) return;
900
- stamp_file.replace_stamp(result_path(repository, number), { ...record, ...fields });
901
- }
902
- async function mark_result(repository, number, code) {
903
- await update_record(repository, number, { result: code === 0 ? "success" : "failed" });
904
- }
905
- async function claim_identity(repository, number) {
906
- const own = process_identity.own_fields();
907
- if (own.process_start === void 0) return;
908
- await update_record(repository, number, own);
909
- }
910
- function failed_launch(request, note) {
911
- stamp_file.remove_stamp(result_path(request.repository, request.number));
912
- return { verdict: FAILED, note };
913
- }
914
- function notify_arguments(request) {
915
- const [flag, value] = [request.notify[0], request.notify[NOTIFY_VALUE_INDEX]];
916
- if (flag !== INLINE_NOTIFY || value === void 0) return request.notify;
917
- const body_path = stamp_file.stamp_path(
918
- `${BODY_PREFIX}${request.number}${KEY_SEPARATOR}`,
919
- request.repository,
920
- BODY_SUFFIX
921
- );
922
- stamp_file.write_text_stamp(body_path, value);
923
- return [FILE_NOTIFY, body_path];
924
- }
925
- function supervisor_argv(request) {
926
- const review = request.is_review ? ["--review"] : [];
927
- const cites = request.cites.flatMap((cite) => ["--cite", cite]);
928
- return {
929
- command: PNPM,
930
- args: [
931
- "josh",
932
- "ship",
933
- ...review,
934
- ...notify_arguments(request),
935
- ...request.body,
936
- ...cites,
937
- request.title
938
- ]
939
- };
940
- }
941
- function prepare_launch(request) {
942
- const launch_id = randomUUID();
943
- const launcher = process_identity.own_fields();
944
- stamp_file.replace_stamp(result_path(request.repository, request.number), {
945
- launch_id,
946
- launcher_pid: launcher.pid,
947
- ...launcher.process_start !== void 0 && { launcher_start: launcher.process_start }
948
- });
949
- return launch_id;
950
- }
951
- function launch(request) {
952
- const notes = [];
953
- const log = log_path(request.repository, request.number);
954
- const launch_id = prepare_launch(request);
955
- const result = detached_launch.launch(
956
- {
957
- argv: supervisor_argv(request),
958
- cwd: request.cwd,
959
- log_path: log,
960
- // The provider travels as a mark because the launch strips the session keys that name it, and
961
- // `ship --review` resolves its reviewer from it.
962
- env: supervisor_environment(launch_id)
963
- },
964
- (note) => {
965
- notes.push(note);
966
- }
967
- );
968
- agent_role_profile.warn_of_default();
969
- if (result.kind === "failed") return failed_launch(request, result.note);
970
- record_launch(request, result.pid, launch_id);
971
- return {
972
- verdict: LAUNCHED,
973
- note: [`supervisor ${String(result.pid)} \u2014 log: ${log}`, ...notes].join("\n")
974
- };
975
- }
976
- async function detach(request) {
977
- if (read_result(request.repository, request.number)?.result === "running") {
978
- return {
979
- verdict: BUSY,
980
- note: `a ship supervisor for ${session_cite.issue(request.number)} is already running`
981
- };
982
- }
983
- const result = launch(request);
984
- if (result.verdict === LAUNCHED) {
985
- await run_event_stream_emit.emit(
986
- run_event_stream.EVENT_KIND.SHIP_LAUNCH,
987
- `${issue_cite.plain(request.number)} ship supervisor launched`
988
- );
989
- }
990
- return result;
991
- }
992
- function last_launch(text) {
993
- const mark = text.lastIndexOf(LAUNCH_MARK);
994
- if (mark === -1) return text;
995
- return text.slice(text.lastIndexOf(HEADER_START, mark) + HEADER_START.length);
996
- }
997
- function read_log(repository, number) {
998
- const text = stamp_file.read_stamp_text(log_path(repository, number));
999
- return text === void 0 ? void 0 : last_launch(text);
1000
- }
1001
- function is_supervised(source = process.env) {
1002
- return source[SUPERVISED_KEY] === SUPERVISED_VALUE;
1003
- }
1004
- var run_ship_detach = {
1005
- BUSY,
1006
- FAILED,
1007
- LAUNCHED,
1008
- LAUNCH_ID_KEY,
1009
- claim_identity,
1010
- mark_result,
1011
- read_result,
1012
- SUPERVISED_KEY,
1013
- detach,
1014
- is_supervised,
1015
- last_launch,
1016
- log_path,
1017
- read_log,
1018
- running_since,
1019
- supervisor_argv
1020
- };
1021
-
1022
- // scripts/lane/lane-handoff.ts
1023
- function is_ship_running(issue, directory) {
1024
- const repository = git_common_directory.repository(directory);
1025
- return repository !== void 0 && run_ship_detach.read_result(repository, issue)?.result === "running";
1026
- }
1027
- function ship_running_since(issue, directory) {
1028
- const repository = git_common_directory.repository(directory);
1029
- return repository === void 0 ? void 0 : run_ship_detach.running_since(repository, issue);
1030
- }
1031
- function is_handed_off(directory, source = process.env) {
1032
- const issue = lane_child_marker.marked_issue(source);
1033
- if (issue === void 0 || !lane_child_marker.is_child_of(directory, source)) return false;
1034
- return is_ship_running(issue, directory);
1035
- }
1036
- var lane_handoff = { is_handed_off, is_ship_running, ship_running_since };
1037
-
1038
- // scripts/issue/issue-labels.ts
1039
- var EPIC_LABEL = "epic";
1040
- var BUG_LABEL = "bug";
1041
- var ENHANCEMENT_LABEL = "enhancement";
1042
- var BREAKING_CHANGE_LABEL = "breaking-change";
1043
- var IN_PROGRESS_LABEL = "in-progress";
1044
- var PLANNED_LABEL = "run:planned";
1045
- var NEEDS_DECISION_LABEL = "needs-decision";
1046
- var RUN_SOLO_LABEL = "run:solo";
1047
- var RUN_LANE_LABEL = "run:lane";
1048
- var PRIORITY_HIGH_LABEL = "priority:high";
1049
- var AUTO_OK_LABEL = "auto-ok";
1050
- var NEEDS_HUMAN_REVIEW_LABEL = "needs-human-review";
1051
- var ALREADY_DONE_LABEL = "already-done";
1052
- var RELEASE_LABEL = "release";
1053
- var REVIEW_ROUND2_SKIPPED_LABEL = "review-round2-skipped";
1054
- var INTERRUPT_ROUTE_LABEL = "route:interrupt";
1055
- var REVIEW_CAP_ROUTE_LABEL = "route:review-cap";
1056
- var SPLIT_ROUTE_LABEL = "route:split";
1057
- var TIER_A_ROUTE_LABEL = "route:tier-a";
1058
- var FILING_ROUTE_LABELS = [
1059
- {
1060
- name: INTERRUPT_ROUTE_LABEL,
1061
- // Not `5319e7`, which is the `epic` label's purple: in a listing an interrupt would render as
1062
- // an epic, and the two are read at a glance rather than by name.
1063
- color: "1d76db",
1064
- // Keyed to the tests rather than to severity. "A serious defect" is the self-assessment
1065
- // `wip-cap.md` bans as a criterion, and this string is what a person reads in `gh label list`.
1066
- description: "Filed past the WIP cap \u2014 meets one of the three interrupt tests (wip-cap.md)"
1067
- },
1068
- {
1069
- name: REVIEW_CAP_ROUTE_LABEL,
1070
- color: "eab308",
1071
- description: "Filed by the review round cap's carry-forward (prompts/review.md \u2192 Review round cap)"
1072
- },
1073
- {
1074
- name: SPLIT_ROUTE_LABEL,
1075
- color: "0e8a16",
1076
- description: "A child issue created by a split (split-assessment.md)"
1077
- },
1078
- {
1079
- name: TIER_A_ROUTE_LABEL,
1080
- color: "d93f0b",
1081
- description: "Filed Tier A during implementation \u2014 an upstream defect or a prerequisite"
1082
- }
1083
- ];
1084
- var DEPTH_0_LABEL = "depth:0";
1085
- var DEPTH_1_LABEL = "depth:1";
1086
- var DEPTH_2_LABEL = "depth:2";
1087
- var DEPTH_LABELS = [
1088
- {
1089
- name: DEPTH_0_LABEL,
1090
- color: "0e8a16",
1091
- description: "Depth 0 \u2014 what a consumer of this package touches (observation-filing.md)"
1092
- },
1093
- {
1094
- name: DEPTH_1_LABEL,
1095
- color: "fbc02d",
1096
- description: "Depth 1 \u2014 the run orchestration that executes an Issue (observation-filing.md)"
1097
- },
1098
- {
1099
- name: DEPTH_2_LABEL,
1100
- color: "c5def5",
1101
- description: "Depth 2 \u2014 what measures a run (observation-filing.md)"
1102
- }
1103
- ];
1104
- var WORKFLOW_LABELS = [
1105
- {
1106
- name: EPIC_LABEL,
1107
- color: "5319e7",
1108
- description: "Tracks a batch of child issues from one split"
1109
- },
1110
- { name: IN_PROGRESS_LABEL, color: "0075ca", description: "Work is actively in progress" },
1111
- { name: PLANNED_LABEL, color: "c2e0c6", description: "kickoff posted the plan" },
1112
- {
1113
- name: RUN_SOLO_LABEL,
1114
- color: "b60205",
1115
- description: "Runs alone in a backlogrun: nothing starts beside it"
1116
- },
1117
- {
1118
- name: RUN_LANE_LABEL,
1119
- color: "0e8a16",
1120
- description: "Judged safe to run beside others in a backlogrun"
1121
- },
1122
- {
1123
- name: PRIORITY_HIGH_LABEL,
1124
- color: "e99695",
1125
- description: "Offered first in a backlogrun; only a person removes it"
1126
- },
1127
- {
1128
- name: RELEASE_LABEL,
1129
- color: "fef2c0",
1130
- description: "Tracks the next release; its blockers are the merged work it publishes"
1131
- },
1132
- {
1133
- name: AUTO_OK_LABEL,
1134
- color: "0e8a16",
1135
- description: "Opted in to unattended execution outside an epic"
1136
- },
1137
- {
1138
- name: NEEDS_DECISION_LABEL,
1139
- color: "d93f0b",
1140
- description: "Parked: needs a decision before it can run"
1141
- },
1142
- {
1143
- name: NEEDS_HUMAN_REVIEW_LABEL,
1144
- color: "d93f0b",
1145
- description: "Implement and verify, but stop before committing so a person can look"
1146
- },
1147
- {
1148
- name: ALREADY_DONE_LABEL,
1149
- color: "6f42c1",
1150
- description: "Verified already merged \u2014 a person closes it"
1151
- },
1152
- {
1153
- name: REVIEW_ROUND2_SKIPPED_LABEL,
1154
- color: "c5def5",
1155
- description: "Review round 2 was skipped under the condition in prompts/review.md"
1156
- },
1157
- { name: BUG_LABEL, color: "d73a4a", description: "Something isn't working" },
1158
- ...FILING_ROUTE_LABELS,
1159
- ...DEPTH_LABELS
1160
- ];
1161
- var BUGFIX_LABEL = "bugfix";
1162
- var OTHER_CHANGE_LABEL = "other-change";
1163
- var IGNORE_FOR_RELEASE_LABEL = "ignore-for-release";
1164
- var RELEASE_CLASSIFICATION_NAMES = [
1165
- BREAKING_CHANGE_LABEL,
1166
- ENHANCEMENT_LABEL,
1167
- BUGFIX_LABEL,
1168
- OTHER_CHANGE_LABEL,
1169
- IGNORE_FOR_RELEASE_LABEL
1170
- ];
1171
- var RELEASE_CLASSIFICATION_METADATA = {
1172
- [BREAKING_CHANGE_LABEL]: { color: "d93f0b", description: "Release: a breaking change (major)" },
1173
- [ENHANCEMENT_LABEL]: { color: "84b6eb", description: "Release: a new feature (minor)" },
1174
- [BUGFIX_LABEL]: { color: "d73a4a", description: "Release: a bug fix (patch)" },
1175
- [OTHER_CHANGE_LABEL]: { color: "c2e0c6", description: "Release: any other change (patch)" },
1176
- [IGNORE_FOR_RELEASE_LABEL]: { color: "cfd3d7", description: "Release: left out of the notes" }
1177
- };
1178
- var RELEASE_CLASSIFICATION_LABELS = RELEASE_CLASSIFICATION_NAMES.map((name) => ({ name, ...RELEASE_CLASSIFICATION_METADATA[name] }));
1179
- var REPOSITORY_LABELS = [
1180
- ...WORKFLOW_LABELS,
1181
- ...RELEASE_CLASSIFICATION_LABELS
1182
- ];
1183
- function has_any_label(labels, wanted) {
1184
- return (labels ?? []).some((label) => wanted.has(label.name.toLowerCase()));
1185
- }
1186
- function label_name_of(labels, wanted) {
1187
- const target = wanted.toLowerCase();
1188
- return labels.find((label) => label.toLowerCase() === target);
1189
- }
1190
- function has_label_name(labels, wanted) {
1191
- return label_name_of(labels, wanted) !== void 0;
1192
- }
1193
-
1194
- // scripts/rules/lane-park.ts
1195
- var NOTIFY_COMMANDS = /* @__PURE__ */ new Set(["notify"]);
1196
- var CONFIRMATION_TASK_TYPE = /(?:^|\s)--task-type[=\s]+["']?confirmation\b/u;
1197
- function is_confirmation_notify(command) {
1198
- return shell_segments.segments_of(command).some(
1199
- (segment) => shell_segments.is_josh_command(segment, NOTIFY_COMMANDS) && CONFIRMATION_TASK_TYPE.test(segment)
1200
- );
1201
- }
1202
- var NOTIFY_INVOCATION = /josh\s+(?:notify|nf)\b/u;
1203
- var COMMAND_NOTIFY_MARKER = "stop notified: a confirmation Telegram was sent by this command";
1204
- function mentions_confirmation_notify(text) {
1205
- if (text.includes(COMMAND_NOTIFY_MARKER)) return true;
1206
- return NOTIFY_INVOCATION.test(text) && CONFIRMATION_TASK_TYPE.test(text);
1207
- }
1208
- function is_parking_child(directory = process.cwd()) {
1209
- return lane_child_marker.is_child_of(directory) && !lane_handoff.is_handed_off(directory);
1210
- }
1211
- function is_unparked_stop(command, is_child = is_parking_child) {
1212
- if (!is_confirmation_notify(command)) return false;
1213
- return is_child();
1214
- }
1215
- var APPLIES_NEEDS_DECISION = new RegExp(
1216
- String.raw`(?:labels\[\]=|--add-label[= ]'?)${NEEDS_DECISION_LABEL}\b`,
1217
- "u"
1218
- );
1219
- function records_the_park(command) {
1220
- return APPLIES_NEEDS_DECISION.test(command);
1221
- }
1222
- var LANE_PARK_REASON = "\u26D4 lane child park: this session is a dispatched lane child, so a stop for a person parks first: `gh api repos/{owner}/{repo}/issues/<N>/labels -f 'labels[]=needs-decision'`; `pnpm josh issue:comment <N> --body-file <path>` (question, options, stash); a `needs-human-review` / `already-done` stop already is. Reissue this notify, once per run (`.claude/skills/workflow-commands/pre-gate-cut.md`).";
1223
- var ROW3 = {
1224
- id: "lane-park",
1225
- is_trigger: bash_triggers.on_bash_command(is_unparked_stop),
1226
- reason: LANE_PARK_REASON,
1227
- keeps: bash_triggers.on_bash_command(records_the_park)
1228
- };
1229
- var lane_park = {
1230
- COMMAND_NOTIFY_MARKER,
1231
- LANE_PARK_REASON,
1232
- ROW: ROW3,
1233
- is_confirmation_notify,
1234
- is_parking_child,
1235
- is_unparked_stop,
1236
- mentions_confirmation_notify,
1237
- records_the_park
1238
- };
1239
-
1240
- // scripts/cost-runtime/cost-cli.ts
1241
- import { fileURLToPath } from "node:url";
1242
-
1243
- // scripts/cost-runtime/codex-usage.ts
1244
- import { globSync, readFileSync as readFileSync2 } from "node:fs";
1245
- import path from "node:path";
1246
- import { z as z4 } from "zod";
1247
- var THREAD_ID_PATTERN = /^[A-Za-z0-9-]+$/u;
1248
- var SESSION_META_SCHEMA = z4.looseObject({
1249
- type: z4.literal("session_meta"),
1250
- payload: z4.looseObject({ id: z4.string(), cwd: z4.string() })
1251
- });
1252
- var TOTAL_USAGE_SCHEMA = z4.looseObject({ input_tokens: z4.number().nonnegative() });
1253
- var TOKEN_COUNT_SCHEMA = z4.looseObject({
1254
- type: z4.literal("event_msg"),
1255
- payload: z4.looseObject({
1256
- type: z4.literal("token_count"),
1257
- info: z4.looseObject({
1258
- total_token_usage: TOTAL_USAGE_SCHEMA,
1259
- last_token_usage: TOTAL_USAGE_SCHEMA
1260
- })
1261
- })
1262
- });
1263
- function same_project(cwd, target) {
1264
- return cost_transcript.session_cwd(cwd) === cost_transcript.session_cwd(target);
1265
- }
1266
- function billed_per_request(usages) {
1267
- return usages.map((usage) => usage.last_token_usage.input_tokens);
1268
- }
1269
- function measurement_from(content, target, thread_id) {
1270
- const values = content.split("\n").map((line) => json_value.parse_or_undefined(line));
1271
- const metadata = values.flatMap((value) => {
1272
- const parsed = SESSION_META_SCHEMA.safeParse(value);
1273
- return parsed.success ? [parsed.data] : [];
1274
- });
1275
- const usages = values.flatMap((value) => {
1276
- const parsed = TOKEN_COUNT_SCHEMA.safeParse(value);
1277
- return parsed.success ? [parsed.data.payload.info] : [];
1278
- });
1279
- const session = metadata.find((entry) => entry.payload.id === thread_id);
1280
- if (session === void 0 || usages.length === 0 || !same_project(session.payload.cwd, target)) {
1281
- return void 0;
1282
- }
1283
- return { billed_input_per_request: billed_per_request(usages) };
1284
- }
1285
- function rollout_files(home, thread_id) {
1286
- if (!THREAD_ID_PATTERN.test(thread_id)) return [];
1287
- return globSync(`sessions/**/*${thread_id}.jsonl`, { cwd: home }).map(
1288
- (file) => path.join(home, file)
1289
- );
1290
- }
1291
- function read_measurement(file, target, thread_id) {
1292
- try {
1293
- return measurement_from(readFileSync2(file, "utf8"), target, thread_id);
1294
- } catch {
1295
- return void 0;
1296
- }
1297
- }
1298
- function latest_measurement(files, target, thread_id) {
1299
- for (const file of files.toReversed()) {
1300
- const measured = read_measurement(file, target, thread_id);
1301
- if (measured !== void 0) return measured;
1302
- }
1303
- return void 0;
1304
- }
1305
- function measurement(target, default_home, environment = process.env) {
1306
- const thread_id = environment["CODEX_THREAD_ID"];
1307
- if (thread_id === void 0) return void 0;
1308
- const home = environment["CODEX_HOME"] ?? path.join(default_home, ".codex");
1309
- return latest_measurement(rollout_files(home, thread_id), target, thread_id);
1310
- }
1311
- var codex_usage = { measurement };
1312
-
1313
- // scripts/cost-runtime/cost-corpus.ts
1314
- function accumulate_missing(sessions) {
1315
- return {
1316
- no_usage_lines: sessions.reduce((sum, session) => sum + session.no_usage_lines, 0),
1317
- malformed_lines: sessions.reduce((sum, session) => sum + session.malformed_lines, 0),
1318
- unreadable_sessions: sessions.filter((session) => !session.is_readable).length,
1319
- // Filled by the attribution, which is the only step that knows a unit could not follow its
1320
- // parent; a per-session tally cannot see it, so it is zero here and set for an issue scope below.
1321
- unattributed_sessions: 0
1322
- };
1323
- }
1324
- function load_corpus(cwd) {
1325
- const files = cost_transcript.list_sessions_across(cost_transcript.transcript_directories(cwd));
1326
- const sessions = files.map((file) => cost_transcript.read_session(file));
1327
- return { sessions, files, missing: accumulate_missing(sessions) };
1328
- }
1329
- function session_meta(corpus) {
1330
- return new Map(
1331
- corpus.files.map((file) => [
1332
- file.session_id,
1333
- { is_delegated: file.is_delegated, owner: cost_transcript.owning_session_id(file) }
1334
- ])
1335
- );
1336
- }
1337
- function issue_set(records) {
1338
- const issues = cost_attribute.group_by_issue(records).map((group) => group.issue).filter((issue) => issue !== cost_attribute.UNATTRIBUTED_KEY);
1339
- return new Set(issues);
1340
- }
1341
- function sole_of(issues) {
1342
- if (issues.size !== 1) return cost_attribute.UNATTRIBUTED_KEY;
1343
- return [...issues][0] ?? cost_attribute.UNATTRIBUTED_KEY;
1344
- }
1345
- function owner_sets(corpus, meta) {
1346
- const own = corpus.sessions.filter(
1347
- (session) => meta.get(session.session_id)?.is_delegated !== true
1348
- );
1349
- return new Map(own.map((session) => [session.session_id, issue_set(session.records)]));
1350
- }
1351
- function pairs_with_inherited(session, inherited, is_delegated) {
1352
- return cost_attribute.group_by_issue(session.records).flatMap(
1353
- (group) => group.records.map((record) => ({
1354
- record,
1355
- issue: group.issue === cost_attribute.UNATTRIBUTED_KEY ? inherited : group.issue,
1356
- baseline_tokens: session.baseline_tokens,
1357
- session_id: session.session_id,
1358
- is_delegated
1359
- }))
1360
- );
1361
- }
1362
- var NO_ISSUES = /* @__PURE__ */ new Set();
1363
- function parent_issues(session, meta, owners) {
1364
- const entry = meta.get(session.session_id);
1365
- if (entry?.is_delegated !== true) return NO_ISSUES;
1366
- return owners.get(entry.owner) ?? NO_ISSUES;
1367
- }
1368
- function pairs_of_session(session, meta, owners) {
1369
- const is_delegated = meta.get(session.session_id)?.is_delegated === true;
1370
- const candidates = parent_issues(session, meta, owners);
1371
- const inherited = is_delegated ? sole_of(candidates) : cost_attribute.UNATTRIBUTED_KEY;
1372
- const pairs = pairs_with_inherited(session, inherited, is_delegated);
1373
- const has_unattributed = pairs.some((pair) => pair.issue === cost_attribute.UNATTRIBUTED_KEY);
1374
- if (!is_delegated || !has_unattributed) return { pairs };
1375
- return { pairs, unattributed_candidates: candidates };
1376
- }
1377
- function attribute_corpus(corpus) {
1378
- const meta = session_meta(corpus);
1379
- const owners = owner_sets(corpus, meta);
1380
- const per_session = corpus.sessions.map((session) => pairs_of_session(session, meta, owners));
1381
- return {
1382
- pairs: per_session.flatMap((one) => one.pairs),
1383
- unattributed: per_session.flatMap(
1384
- (one) => one.unattributed_candidates === void 0 ? [] : [one.unattributed_candidates]
1385
- )
1386
- };
1387
- }
1388
- function floor_for_issue(unattributed, issue_number) {
1389
- return unattributed.filter((set) => set.size === 0 || set.has(issue_number)).length;
1390
- }
1391
- function is_better(candidate, existing) {
1392
- const { UNATTRIBUTED_KEY } = cost_attribute;
1393
- return existing.issue === UNATTRIBUTED_KEY && candidate.issue !== UNATTRIBUTED_KEY;
1394
- }
1395
- function values_of(best) {
1396
- const collected = [];
1397
- for (const [, pair] of best) collected.push(pair);
1398
- return collected;
1399
- }
1400
- function dedupe_across_sessions(pairs) {
1401
- const best = /* @__PURE__ */ new Map();
1402
- for (const pair of pairs) {
1403
- const existing = best.get(pair.record.request_id);
1404
- if (existing === void 0 || is_better(pair, existing)) {
1405
- best.set(pair.record.request_id, pair);
1406
- }
1407
- }
1408
- return values_of(best);
1409
- }
1410
- function attributed(corpus) {
1411
- return dedupe_across_sessions(attribute_corpus(corpus).pairs);
1412
- }
1413
- function mainline_records(pairs) {
1414
- const groups = /* @__PURE__ */ new Map();
1415
- for (const pair of pairs) {
1416
- if (pair.is_delegated) continue;
1417
- groups.set(pair.session_id, [...groups.get(pair.session_id) ?? [], pair.record]);
1418
- }
1419
- return [...groups.values()];
1420
- }
1421
- var cost_corpus = {
1422
- load_corpus,
1423
- attribute_corpus,
1424
- floor_for_issue,
1425
- attributed,
1426
- mainline_records
1427
- };
1428
-
1429
- // scripts/cost-runtime/cost-verdict.ts
1430
- var FAILURE_EXIT_CODE = 1;
1431
- var OVER_VERDICT = "over";
1432
- var UNDER_VERDICT = "under";
1433
- function per_request_cost(measurement2) {
1434
- return measurement2.billed_input_per_request.at(-1) ?? 0;
1435
- }
1436
- function classify2(measurement2, limit) {
1437
- return per_request_cost(measurement2) > limit ? OVER_VERDICT : UNDER_VERDICT;
1438
- }
1439
- function over_summary(measurement2, limit) {
1440
- const total = measurement2.billed_input_per_request.length;
1441
- return `${String(per_request_cost(measurement2))} billed input tokens per request, on the newest of ${String(total)} request(s); limit ${String(limit)}`;
1442
- }
1443
- function report_over(measurement2, limit) {
1444
- if (measurement2 === void 0 || measurement2.billed_input_per_request.length === 0) {
1445
- console.error("No requests in this session; there is nothing to hand off.");
1446
- return FAILURE_EXIT_CODE;
1447
- }
1448
- console.info(classify2(measurement2, limit));
1449
- console.error(over_summary(measurement2, limit));
1450
- return 0;
1451
- }
1452
- var cost_verdict = {
1453
- OVER_VERDICT,
1454
- UNDER_VERDICT,
1455
- classify: classify2,
1456
- per_request_cost,
1457
- report_over
1458
- };
1459
-
1460
- // scripts/cost-runtime/transcript-cwd.ts
1461
- import path2 from "node:path";
1462
- function resolve(target, cwd) {
1463
- return target === void 0 ? cwd : path2.resolve(target);
1464
- }
1465
- var transcript_cwd = { resolve };
1466
-
1467
- // scripts/cost-runtime/cost-cli.ts
1468
- var ARGV_OFFSET = 2;
1469
- var FAILURE_EXIT_CODE2 = 1;
1470
- var USAGE = "Usage: josh cost (--cut | --over <tokens-per-request>) [--path <dir>]";
1471
- var UNMEASURABLE_VERDICT = "unmeasurable";
1472
- function to_threshold(raw) {
1473
- if (raw === void 0 || raw.trim() === "") return void 0;
1474
- const parsed = Number(raw);
1475
- return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : void 0;
1476
- }
1477
- function is_unparsed(raw, parsed) {
1478
- return parsed === void 0 && raw !== void 0;
1479
- }
1480
- function selected_threshold(values) {
1481
- if (values.cut === true) return CONTEXT_CUT_THRESHOLD;
1482
- return to_threshold(values.over);
1483
- }
1484
- function threshold_option(over) {
1485
- return over === void 0 ? {} : { over };
1486
- }
1487
- function path_option(path4) {
1488
- return path4 === void 0 ? {} : { path: path4 };
1489
- }
1490
- function to_options(values) {
1491
- if (values.cut === true && values.over !== void 0) return void 0;
1492
- const over = selected_threshold(values);
1493
- if (is_unparsed(values.over, over)) return void 0;
1494
- return { ...threshold_option(over), ...path_option(values.path) };
1495
- }
1496
- var PARSE_ARGS_OPTIONS = {
1497
- cut: { type: "boolean" },
1498
- over: { type: "string" },
1499
- path: { type: "string" }
1500
- };
1501
- function parse_options(argv) {
1502
- const values = cli_flags.values_of(argv, PARSE_ARGS_OPTIONS);
1503
- return values === void 0 ? void 0 : to_options(values);
1504
- }
1505
- function report_empty(cwd, session_id) {
1506
- const searched = cost_transcript.searched_directories(cost_transcript.transcript_directories(cwd));
1507
- for (const line of cost_transcript.missing_message(searched, session_id)) console.error(line);
1508
- return FAILURE_EXIT_CODE2;
1509
- }
1510
- function provider_of(environment) {
1511
- const resolved = agent_role_profile.resolve_provider(environment);
1512
- if (resolved.kind !== "provider" || resolved.is_default === true) return void 0;
1513
- return resolved.provider;
1514
- }
1515
- function measurement_of(session) {
1516
- return {
1517
- billed_input_per_request: session.records.map(
1518
- (record) => cost_usage.billed_input(record.totals)
1519
- )
1520
- };
1521
- }
1522
- function anthropic_own(target, environment) {
1523
- const corpus = cost_corpus.load_corpus(target);
1524
- const selection = own_session.select_own_session(corpus.files, environment);
1525
- if (selection.kind === "absent") return { kind: "absent", session_id: selection.session_id };
1526
- const session = corpus.sessions[selection.index];
1527
- if (session === void 0) return { kind: "empty" };
1528
- return { kind: "measured", measurement: measurement_of(session) };
1529
- }
1530
- function anthropic_measurement(target, environment) {
1531
- const own = anthropic_own(target, environment);
1532
- return own.kind === "measured" ? own.measurement : void 0;
1533
- }
1534
- function same_openai_project(target, cwd) {
1535
- return cost_transcript.session_cwd(target) === cost_transcript.session_cwd(cwd);
1536
- }
1537
- function reject_openai_cross_project(context, target, cwd) {
1538
- if (context.provider !== "openai" || context.path === void 0 || same_openai_project(target, cwd)) {
1539
- return false;
1540
- }
1541
- console.error(
1542
- "OpenAI --path cannot select a thread from another project; run josh cost in that project."
1543
- );
1544
- return true;
1545
- }
1546
- function measure(target, provider, environment) {
1547
- return provider === "openai" ? codex_usage.measurement(target, cost_transcript.home_directory(), environment) : anthropic_measurement(target, environment);
1548
- }
1549
- function run_over_anthropic(own, target, limit) {
1550
- if (own.kind === "measured") return cost_verdict.report_over(own.measurement, limit);
1551
- return report_empty(target, own.kind === "absent" ? own.session_id : void 0);
1552
- }
1553
- function run_over_codex(target, limit, environment) {
1554
- const measurement2 = measure(target, "openai", environment);
1555
- if (measurement2 !== void 0) return cost_verdict.report_over(measurement2, limit);
1556
- console.error(`No Codex usage found for the current OpenAI thread under ${target}.`);
1557
- return FAILURE_EXIT_CODE2;
1558
- }
1559
- function run_over(target, limit, provider, environment) {
1560
- if (provider === "anthropic") {
1561
- return run_over_anthropic(anthropic_own(target, environment), target, limit);
1562
- }
1563
- return run_over_codex(target, limit, environment);
1564
- }
1565
- function verdict_of(measurement2) {
1566
- if (measurement2 === void 0 || measurement2.billed_input_per_request.length === 0) {
1567
- return UNMEASURABLE_VERDICT;
1568
- }
1569
- return cost_verdict.classify(measurement2, CONTEXT_CUT_THRESHOLD);
1570
- }
1571
- function session_verdict(cwd = process.cwd(), environment = process.env) {
1572
- const provider = provider_of(environment);
1573
- if (provider === void 0) return UNMEASURABLE_VERDICT;
1574
- return verdict_of(measure(cwd, provider, environment));
1575
- }
1576
- function run_context(argv, environment) {
1577
- const options = parse_options(argv);
1578
- if (options?.over === void 0) return void 0;
1579
- const provider = provider_of(environment);
1580
- if (provider === void 0) return void 0;
1581
- return { over: options.over, path: options.path, provider };
1582
- }
1583
- function run(argv, cwd = process.cwd(), environment = process.env) {
1584
- const context = run_context(argv, environment);
1585
- if (context === void 0) {
1586
- console.error(USAGE);
1587
- return FAILURE_EXIT_CODE2;
1588
- }
1589
- const target = transcript_cwd.resolve(context.path, cwd);
1590
- if (reject_openai_cross_project(context, target, cwd)) return FAILURE_EXIT_CODE2;
1591
- return run_over(target, context.over, context.provider, environment);
1592
- }
1593
- function main(argv) {
1594
- process.exitCode = run(argv);
1595
- }
1596
- var cost_cli = {
1597
- UNMEASURABLE_VERDICT,
1598
- USAGE,
1599
- parse_options,
1600
- to_threshold,
1601
- run,
1602
- session_verdict
1603
- };
1604
- if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET));
1605
-
1606
- // scripts/rules/pre-gate-cut.ts
1607
- var GATE_COMMANDS = /* @__PURE__ */ new Set(["gate"]);
1608
- var CUT_COMMANDS = /* @__PURE__ */ new Set(["run:cut"]);
1609
- var CUT_MODE_FLAG = /(?:^|\s)--(?:resume|end|json)(?:[=\s]|$)/u;
1610
- var HOLD_COMMANDS = /* @__PURE__ */ new Set(["run:hold"]);
1611
- var HOLD_MODE_FLAG = /(?:^|\s)--release(?:[=\s]|$)/u;
1612
- function invokes_josh(command, names, mode_flag) {
1613
- return shell_segments.segments_of(command).some(
1614
- (segment) => shell_segments.is_josh_command(segment, names) && mode_flag?.test(segment) !== true
1615
- );
1616
- }
1617
- function runs_the_gate(command) {
1618
- return invokes_josh(command, GATE_COMMANDS);
1619
- }
1620
- function takes_the_cut(command) {
1621
- return invokes_josh(command, CUT_COMMANDS, CUT_MODE_FLAG);
1622
- }
1623
- function claims_the_hold(command) {
1624
- return invokes_josh(command, HOLD_COMMANDS, HOLD_MODE_FLAG);
1625
- }
1626
- function asks_about_the_cut(command) {
1627
- return invokes_josh(command, CUT_COMMANDS);
1628
- }
1629
- function current_state2() {
1630
- return {
1631
- directory: process.cwd(),
1632
- carried: run_cut.carried_cut_sync,
1633
- marked_issue: lane_child_marker.marked_issue(),
1634
- is_reviewer: agent_session_role.is_reviewer(),
1635
- context_verdict: cost_cli.session_verdict
1636
- };
1637
- }
1638
- function dispatched_issue(state) {
1639
- return state.is_reviewer ? void 0 : state.marked_issue;
1640
- }
1641
- function uncut_lane_issue(state) {
1642
- const issue = lane_paths.lane_issue_of(state.directory);
1643
- if (issue === void 0 || dispatched_issue(state) !== issue) return void 0;
1644
- return state.carried()?.issue === issue ? void 0 : issue;
1645
- }
1646
- function warrants_the_cut(verdict) {
1647
- return verdict !== cost_verdict.UNDER_VERDICT;
1648
- }
1649
- function is_uncut_gate(command, state = current_state2()) {
1650
- if (!runs_the_gate(command) || uncut_lane_issue(state) === void 0) return false;
1651
- return warrants_the_cut(state.context_verdict());
1652
- }
1653
- var PRE_GATE_CUT_REASON = "\u26D4 pre-gate cut: this checkout is a lane dispatched for this issue and the gate is the boundary to cut at. Issue `pnpm josh run:cut <N>`: on `cut`, end the turn immediately \u2014 no Telegram is owed; on any other verdict (`not-a-lane`, `busy`, \u2026), reissue the gate \u2014 this fires once per run (`.claude/skills/workflow-commands/pre-gate-cut.md`).";
1654
- function reaches_the_pre_gate_boundary(call, _turn, run2) {
1655
- if (!bash_triggers.on_bash_command(asks_about_the_cut)(call)) return false;
1656
- return run2.some((issued) => bash_triggers.on_bash_command(claims_the_hold)(issued));
1657
- }
1658
- var pre_gate_cut = {
1659
- PRE_GATE_CUT_REASON,
1660
- asks_about_the_cut,
1661
- claims_the_hold,
1662
- is_uncut_gate,
1663
- reaches_the_pre_gate_boundary,
1664
- runs_the_gate,
1665
- takes_the_cut,
1666
- uncut_lane_issue
1667
- };
1668
-
1669
- // scripts/discovery/repo-party.ts
1670
- var FIRST_PARTY = "first-party";
1671
- var THIRD_PARTY = "third-party";
1672
- var UNKNOWN = "unknown";
1673
- var GH_REPO_ENV_KEY = "GH_REPO";
1674
- var GH_REPO_PATH_SEGMENTS = 2;
1675
- function classify3(session_owner, target) {
1676
- if (session_owner === void 0 || target === void 0) return UNKNOWN;
1677
- return session_owner.toLowerCase() === target.toLowerCase() ? FIRST_PARTY : THIRD_PARTY;
1678
- }
1679
- function target_owner(owner_repo) {
1680
- return repo_origin.parse_origin_url(`https://${repo_origin.GITHUB_HOST}/${owner_repo}`)?.owner;
1681
- }
1682
- function current_owner(repository_path = process.cwd()) {
1683
- return repo_discovery.resolve_current_owner(repository_path);
1684
- }
1685
- function gh_repo_owners(gh_repo) {
1686
- return [target_owner(gh_repo.split("/").slice(-GH_REPO_PATH_SEGMENTS).join("/"))];
1687
- }
1688
- function remote_owners(repository_path) {
1689
- return repo_discovery.read_remote_urls(repository_path).map((url) => repo_origin.parse_origin_url(url)?.owner);
1690
- }
1691
- function placeholder_owners(repository_path = process.cwd(), environment = process.env) {
1692
- const gh_repo = environment[GH_REPO_ENV_KEY];
1693
- return gh_repo === void 0 || gh_repo === "" ? remote_owners(repository_path) : gh_repo_owners(gh_repo);
1694
- }
1695
- var repo_party = {
1696
- FIRST_PARTY,
1697
- THIRD_PARTY,
1698
- UNKNOWN,
1699
- classify: classify3,
1700
- current_owner,
1701
- placeholder_owners,
1702
- target_owner
1703
- };
1704
-
1705
- // scripts/gh/git-gh-repo.ts
1706
- async function repo_get_name_with_owner() {
1707
- try {
1708
- const result = await git_gh_exec.exec_gh_api({
1709
- path: git_gh_api_path.repo_api_path(),
1710
- jq_filter: ".full_name"
1711
- });
1712
- return git_gh_helpers.parse_pr_state_string(result);
1713
- } catch {
1714
- return void 0;
1715
- }
1716
- }
1717
- var git_gh_repo = {
1718
- repo_get_name_with_owner
1719
- };
1720
-
1721
- // scripts/gh/git-gh-issue-rest.ts
1722
- import { z as z5 } from "zod";
1723
- var rest_issue_schema = z5.looseObject({
1724
- number: z5.number(),
1725
- issue_dependencies_summary: z5.looseObject({ total_blocked_by: z5.number().optional() }).nullish(),
1726
- // Present only on a pull request, which this endpoint serves as readily as an issue.
1727
- pull_request: z5.looseObject({ merged_at: z5.string().nullish() }).nullish()
1728
- });
1729
- var REPOSITORY_URL = /\/repos\/([\w.-]+\/[\w.-]+)$/u;
1730
- var REPOSITORY_URL_GROUP = 1;
1731
- var BLOCKED_BY_FIELD = "blockedBy";
1732
- var BLOCKED_BY_COUNT_FIELD = "blocked_by_count";
1733
- var STATE_FIELD = "state";
1734
- var BODY_FIELD = "body";
1735
- var FIELD_SEPARATOR = ",";
1736
- var EMPTY_BODY = "";
1737
- var REST_FIELD_NAMES = /* @__PURE__ */ new Map([
1738
- ["url", "html_url"],
1739
- ["createdAt", "created_at"],
1740
- ["closedAt", "closed_at"],
1741
- ["stateReason", "state_reason"],
1742
- ["updatedAt", "updated_at"]
1743
- ]);
1744
- var NOT_AN_ISSUE_MESSAGE = "gh api answered something other than an issue object";
1745
- var NOT_AN_ISSUE_LISTING_MESSAGE = "gh api answered something other than an issue listing";
1746
- var NOT_A_BLOCKER_LISTING_MESSAGE = "gh api answered something other than a blocked-by listing";
1747
- function rest_field_name(field) {
1748
- return REST_FIELD_NAMES.get(field) ?? field;
1749
- }
1750
- function split_fields(fields) {
1751
- return fields.split(FIELD_SEPARATOR).map((field) => field.trim()).filter((field) => field.length > 0);
1752
- }
1753
- function to_issue_state(rest, value) {
1754
- if (typeof rest.pull_request?.merged_at === "string") return MERGED_STATE;
1755
- return typeof value === "string" ? to_gh_state(value) : value;
1756
- }
1757
- function total_blocked_by(rest) {
1758
- return rest.issue_dependencies_summary?.total_blocked_by;
1759
- }
1760
- function to_gh_field_value(field, rest) {
1761
- if (field === BLOCKED_BY_COUNT_FIELD) return total_blocked_by(rest);
1762
- const value = rest[rest_field_name(field)];
1763
- if (field === STATE_FIELD) return to_issue_state(rest, value);
1764
- return field === BODY_FIELD ? value ?? EMPTY_BODY : value;
1765
- }
1766
- function parse_rest_issue(rest_json) {
1767
- const parsed = parse_json_object_or_undefined(rest_json, rest_issue_schema);
1768
- if (parsed === void 0) throw new Error(NOT_AN_ISSUE_MESSAGE);
1769
- return parsed;
1770
- }
1771
- function is_pull_request(rest) {
1772
- return rest.pull_request !== void 0 && rest.pull_request !== null;
1773
- }
1774
- function parse_rest_issues(rest_json) {
1775
- const parsed = parse_json_array_or_undefined(rest_json, rest_issue_schema);
1776
- if (parsed === void 0) throw new Error(NOT_AN_ISSUE_LISTING_MESSAGE);
1777
- return parsed;
1778
- }
1779
- function empty_blocked_by() {
1780
- return { nodes: [], totalCount: 0 };
1781
- }
1782
- function repo_of_url(repository_url = "") {
1783
- const match = REPOSITORY_URL.exec(repository_url);
1784
- return match?.[REPOSITORY_URL_GROUP];
1785
- }
1786
- function to_blocked_by(blockers_json, exact_total) {
1787
- const parsed = parse_json_array_or_undefined(blockers_json, blocking_issue_schema);
1788
- if (parsed === void 0) throw new Error(NOT_A_BLOCKER_LISTING_MESSAGE);
1789
- const nodes = parsed.map((blocker) => ({ ...blocker, state: to_gh_state(blocker.state) }));
1790
- return { nodes, totalCount: exact_total ?? nodes.length };
1791
- }
1792
- function to_gh_issue(rest, fields, blocked_by) {
1793
- return Object.fromEntries(
1794
- fields.map((field) => [
1795
- field,
1796
- field === BLOCKED_BY_FIELD ? blocked_by : to_gh_field_value(field, rest)
1797
- ])
1798
- );
1799
- }
1800
- function to_field_text(value) {
1801
- if (typeof value === "string") return value;
1802
- return value === void 0 || value === null ? EMPTY_BODY : JSON.stringify(value);
1803
- }
1804
- var CLOSED = "CLOSED";
1805
- function reference_of_blocker(node, fallback_repo) {
1806
- const repo = repo_of_url(node.repository_url) ?? fallback_repo;
1807
- if (node.state === void 0) return { repo, number: node.number };
1808
- return { repo, number: node.number, state: node.state.toUpperCase() === CLOSED ? CLOSED : "OPEN" };
1809
- }
1810
- var git_gh_issue_rest = {
1811
- empty_blocked_by,
1812
- repo_of_url,
1813
- reference_of_blocker,
1814
- split_fields,
1815
- is_pull_request,
1816
- parse_rest_issue,
1817
- parse_rest_issues,
1818
- total_blocked_by,
1819
- to_blocked_by,
1820
- to_gh_issue,
1821
- to_field_text
1822
- };
1823
-
1824
- // scripts/gh/git-gh-reachability.ts
1825
- var RATE_LIMITED_STATUS = 429;
1826
- var SERVER_ERROR_FLOOR = 500;
1827
- function is_retryable_status(status) {
1828
- if (status >= SERVER_ERROR_FLOOR) return true;
1829
- return status === RATE_LIMITED_STATUS;
1830
- }
1831
- function classify_status(status) {
1832
- if (status === void 0) return "unreachable";
1833
- return is_retryable_status(status) ? "unreachable" : "reachable";
1834
- }
1835
- var gh_reachability = { classify_status };
1836
-
1837
- // scripts/gh/git-gh-issue-read.ts
1838
- async function read_blocked_by_listing(issue_number, repo, exact_total) {
1839
- const json = await git_gh_exec.exec_gh_api({
1840
- path: `${git_gh_api_path.blocked_by_api_path(issue_number, repo)}${git_gh_api_path.FULL_PAGE_QUERY}`
1841
- });
1842
- return git_gh_issue_rest.to_blocked_by(json, exact_total);
1843
- }
1844
- async function read_blocked_by(issue_number, rest, repo) {
1845
- if (git_gh_issue_rest.is_pull_request(rest)) return git_gh_issue_rest.empty_blocked_by();
1846
- const exact_total = git_gh_issue_rest.total_blocked_by(rest);
1847
- if (exact_total === 0) return git_gh_issue_rest.empty_blocked_by();
1848
- return await read_blocked_by_listing(issue_number, repo, exact_total);
1849
- }
1850
- function mark_followup(error) {
1851
- if (!(error instanceof Error)) return error;
1852
- const failure = gh_failure.failure_of(error);
1853
- if (failure === void 0) return error;
1854
- return gh_failure.attach(error, { ...failure, is_followup: true });
1855
- }
1856
- async function read_relations(issue_number, rest, repo) {
1857
- try {
1858
- return await read_blocked_by(issue_number, rest, repo);
1859
- } catch (error) {
1860
- throw mark_followup(error);
1861
- }
1862
- }
1863
- async function read_issue_fields(issue_number, fields, repo) {
1864
- const rest = git_gh_issue_rest.parse_rest_issue(
1865
- await git_gh_exec.exec_gh_api({ path: git_gh_api_path.issue_api_path(issue_number, repo) })
1866
- );
1867
- const requested = git_gh_issue_rest.split_fields(fields);
1868
- const blocked_by = requested.includes(BLOCKED_BY_FIELD) ? await read_relations(issue_number, rest, repo) : void 0;
1869
- return git_gh_issue_rest.to_gh_issue(rest, requested, blocked_by);
1870
- }
1871
- var NOT_FOUND_STATUS = 404;
1872
- function is_number_unresolved(failure) {
1873
- return failure.status === NOT_FOUND_STATUS && failure.is_followup !== true;
1874
- }
1875
- function to_unreadable_reason(status) {
1876
- return gh_reachability.classify_status(status) === "unreachable" ? "unreachable" : "rejected";
1877
- }
1878
- function to_read_failure(error) {
1879
- const failure = gh_failure.failure_of(error);
1880
- if (failure === void 0) return { kind: "unreadable", reason: "malformed", status: void 0 };
1881
- if (is_number_unresolved(failure)) return { kind: "missing" };
1882
- return {
1883
- kind: "unreadable",
1884
- reason: to_unreadable_reason(failure.status),
1885
- status: failure.status
1886
- };
1887
- }
1888
- async function issue_view_json_classified(issue_number, fields, repo) {
1889
- try {
1890
- const issue = await read_issue_fields(issue_number, fields, repo);
1891
- return { kind: "read", json: JSON.stringify(issue) };
1892
- } catch (error) {
1893
- return to_read_failure(error);
1894
- }
1895
- }
1896
- async function issue_view_field_classified(issue_number, field, repo) {
1897
- try {
1898
- const issue = await read_issue_fields(issue_number, field, repo);
1899
- return { kind: "read", text: git_gh_issue_rest.to_field_text(issue[field]) };
1900
- } catch (error) {
1901
- return to_read_failure(error);
1902
- }
1903
- }
1904
- async function issue_view_field(issue_number, field, repo) {
1905
- const read2 = await issue_view_field_classified(issue_number, field, repo);
1906
- return read2.kind === "read" ? read2.text : void 0;
1907
- }
1908
- async function issue_get_title(issue_number, repo) {
1909
- const result = await issue_view_field(issue_number, "title", repo);
1910
- return result === void 0 ? void 0 : git_gh_helpers.parse_pr_state_string(result);
1911
- }
1912
- async function issue_get_body(issue_number, repo) {
1913
- return await issue_view_field(issue_number, "body", repo);
1914
- }
1915
- async function issue_get_body_classified(issue_number, repo) {
1916
- return await issue_view_field_classified(issue_number, "body", repo);
1917
- }
1918
- async function issue_view_json(issue_number, fields, repo) {
1919
- const read2 = await issue_view_json_classified(issue_number, fields, repo);
1920
- return read2.kind === "read" ? read2.json : void 0;
1921
- }
1922
- var STATE_AND_RELATIONS_FIELDS = "number,state,labels,blockedBy";
1923
- async function issue_get_state_and_relations(issue_number, repo) {
1924
- return await issue_view_json(issue_number, STATE_AND_RELATIONS_FIELDS, repo);
1925
- }
1926
- async function issue_get_state_and_relations_classified(issue_number, repo) {
1927
- return await issue_view_json_classified(issue_number, STATE_AND_RELATIONS_FIELDS, repo);
1928
- }
1929
- function is_unreachable_read(failure) {
1930
- return failure.kind === "unreadable" && failure.reason === "unreachable";
1931
- }
1932
- var PLAN_FIELDS = "number,title,body,state,url,labels,blockedBy";
1933
- async function issue_get_plan_fields(issue_number) {
1934
- return await issue_view_json(issue_number, PLAN_FIELDS);
1935
- }
1936
- async function issue_get_plan_fields_classified(issue_number) {
1937
- return await issue_view_json_classified(issue_number, PLAN_FIELDS);
1938
- }
1939
- async function issue_get_labels_and_body(issue_number) {
1940
- return await issue_view_json(issue_number, "number,state,labels,body");
1941
- }
1942
- async function issue_list_comments(issue_number, timeout_ms) {
1943
- const path4 = `${git_gh_api_path.issue_comments_api_path(issue_number)}${git_gh_api_path.FULL_PAGE_QUERY}`;
1944
- try {
1945
- return await git_gh_exec.exec_gh_api({ path: path4, should_paginate: true, timeout_ms });
1946
- } catch {
1947
- return void 0;
1948
- }
1949
- }
1950
- async function has_no_relations_endpoint(issue_number, repo) {
1951
- const status = await git_gh_exec.exec_gh_api_status(
1952
- git_gh_api_path.blocked_by_api_path(issue_number, repo)
1953
- );
1954
- return status === NOT_FOUND_STATUS;
1955
- }
1956
- async function issue_blocked_by_references(issue_number, own_repo, repo) {
1957
- try {
1958
- const listing = await read_blocked_by_listing(issue_number, repo);
1959
- return listing.nodes.map((blocker) => git_gh_issue_rest.reference_of_blocker(blocker, own_repo));
1960
- } catch (error) {
1961
- if (await has_no_relations_endpoint(issue_number, repo)) return [];
1962
- throw error;
1963
- }
1964
- }
1965
- async function issue_blocked_by_numbers(issue_number, repo) {
1966
- const references = await issue_blocked_by_references(issue_number, "", repo);
1967
- return references.map((blocker) => blocker.number);
1968
- }
1969
- var git_gh_issue_read = {
1970
- issue_blocked_by_numbers,
1971
- issue_blocked_by_references,
1972
- issue_get_title,
1973
- issue_get_body,
1974
- issue_get_body_classified,
1975
- issue_view_json,
1976
- issue_view_json_classified,
1977
- issue_get_state_and_relations,
1978
- issue_get_state_and_relations_classified,
1979
- is_unreachable_read,
1980
- issue_get_plan_fields,
1981
- issue_get_plan_fields_classified,
1982
- issue_get_labels_and_body,
1983
- issue_list_comments
1984
- };
1985
-
1986
- // scripts/gh/git-gh-issue-list.ts
1987
- var PER_PAGE = 100;
1988
- var FIRST_PAGE = 1;
1989
- var DEFAULT_STATE = "open";
1990
- var DEFAULT_SORT = "created";
1991
- var LISTING_DIRECTION = "direction=desc";
1992
- function listing_query(request) {
1993
- const state = request.state ?? DEFAULT_STATE;
1994
- const sort = request.sort ?? DEFAULT_SORT;
1995
- return `state=${state}&sort=${sort}&${LISTING_DIRECTION}`;
1996
- }
1997
- function listing_path(request, page) {
1998
- const label = request.label === void 0 ? "" : `&labels=${encodeURIComponent(request.label)}`;
1999
- const paging = `&per_page=${String(PER_PAGE)}&page=${String(page)}`;
2000
- return `${git_gh_api_path.issues_api_path(request.repo)}?${listing_query(request)}${label}${paging}`;
2001
- }
2002
- var DIGIT_PATTERN = /\d/u;
2003
- function has_token_occurrence(body, term) {
2004
- let index = body.indexOf(term);
2005
- while (index !== -1) {
2006
- if (!DIGIT_PATTERN.test(body.charAt(index + term.length))) return true;
2007
- index = body.indexOf(term, index + 1);
2008
- }
2009
- return false;
2010
- }
2011
- function matches_body(rest, term) {
2012
- if (term === void 0) return true;
2013
- const { body } = rest;
2014
- return typeof body === "string" && has_token_occurrence(body, term);
2015
- }
2016
- function is_selected(rest, request) {
2017
- return !git_gh_issue_rest.is_pull_request(rest) && matches_body(rest, request.body_term);
2018
- }
2019
- async function fetch_page(request, page) {
2020
- const path4 = listing_path(request, page);
2021
- const rows = git_gh_issue_rest.parse_rest_issues(await git_gh_exec.exec_gh_api({ path: path4 }));
2022
- return {
2023
- selected: rows.filter((row) => is_selected(row, request)),
2024
- is_full: rows.length >= PER_PAGE
2025
- };
2026
- }
2027
- var MAX_PAGES = 5;
2028
- var MAX_SCANNED = MAX_PAGES * PER_PAGE;
2029
- function wants_more(has_more, selected_count, limit) {
2030
- return has_more && selected_count < limit;
2031
- }
2032
- async function fetch_selected(request) {
2033
- const selected = [];
2034
- let page = FIRST_PAGE;
2035
- let has_more = true;
2036
- while (page <= MAX_PAGES && wants_more(has_more, selected.length, request.limit)) {
2037
- const result = await fetch_page(request, page);
2038
- selected.push(...result.selected);
2039
- has_more = result.is_full;
2040
- page += 1;
2041
- }
2042
- return {
2043
- rows: selected.slice(0, request.limit),
2044
- is_capped: wants_more(has_more, selected.length, request.limit)
2045
- };
2046
- }
2047
- var RELATION_CONCURRENCY = 8;
2048
- async function read_relations2(rows, repo) {
2049
- return await bounded_pool.bounded_map(
2050
- rows,
2051
- RELATION_CONCURRENCY,
2052
- async (row) => await read_blocked_by(String(row.number), row, repo)
2053
- );
2054
- }
2055
- async function issue_list(request) {
2056
- try {
2057
- const { rows, is_capped } = await fetch_selected(request);
2058
- const fields = git_gh_issue_rest.split_fields(request.json_fields);
2059
- const relations = fields.includes(BLOCKED_BY_FIELD) ? await read_relations2(rows, request.repo) : void 0;
2060
- const mapped = rows.map(
2061
- (row, index) => git_gh_issue_rest.to_gh_issue(row, fields, relations?.[index])
2062
- );
2063
- return { json: JSON.stringify(mapped), is_capped };
2064
- } catch {
2065
- return { json: void 0, is_capped: false };
2066
- }
2067
- }
2068
- var git_gh_issue_list = {
2069
- issue_list
2070
- };
2071
-
2072
- // scripts/issue/issue-watch-diff.ts
2073
- import { z as z6 } from "zod";
2074
- var RUN_MARKER = "<!-- josh:run -->";
2075
- var BOT_TYPE = "Bot";
2076
- var BOT_SUFFIX = "[bot]";
2077
- var NO_COMMENT_ID = 0;
2078
- var UNKNOWN_AUTHOR = "(unknown)";
2079
- var UNKNOWN_TIME = "(undated)";
2080
- var BODY_HEADING = "Body edited:";
2081
- var REMOVED_PREFIX = "- ";
2082
- var ADDED_PREFIX = "+ ";
2083
- var COMMENT_HEADING = "New comment by ";
2084
- var AT = " at ";
2085
- var SECTION_SEPARATOR = "\n\n";
2086
- var LINE_SEPARATOR = "\n";
2087
- var CRLF = "\r\n";
2088
- var comment_schema = z6.looseObject({
2089
- id: z6.number(),
2090
- user: z6.looseObject({ login: z6.string(), type: z6.string().optional() }).nullish(),
2091
- created_at: z6.string().optional(),
2092
- body: z6.string().nullish()
2093
- });
2094
- function is_bot(user) {
2095
- return user?.type === BOT_TYPE || (user?.login.endsWith(BOT_SUFFIX) ?? false);
2096
- }
2097
- function is_automated(user, body) {
2098
- return is_bot(user) || body.includes(RUN_MARKER);
2099
- }
2100
- function to_comment(raw) {
2101
- const body = raw.body ?? "";
2102
- const author = raw.user?.login ?? UNKNOWN_AUTHOR;
2103
- const created_at = raw.created_at ?? UNKNOWN_TIME;
2104
- return { id: raw.id, author, is_automated: is_automated(raw.user, body), created_at, body };
2105
- }
2106
- function parse_comments(json) {
2107
- if (json === void 0) return void 0;
2108
- const listing = read_json_listing(json, comment_schema);
2109
- return listing.kind === "read" ? listing.rows.map((row) => to_comment(row)) : void 0;
2110
- }
2111
- function last_comment_id(comments) {
2112
- return Math.max(NO_COMMENT_ID, ...comments.map((comment) => comment.id));
2113
- }
2114
- function baseline_of(snapshot) {
2115
- return { body: snapshot.body, last_comment_id: last_comment_id(snapshot.comments) };
2116
- }
2117
- function lines_missing_from(source, other) {
2118
- const present = new Set(other.split(LINE_SEPARATOR));
2119
- return source.split(LINE_SEPARATOR).filter((line) => line.trim() !== "" && !present.has(line));
2120
- }
2121
- function to_lf(body) {
2122
- return body.split(CRLF).join(LINE_SEPARATOR);
2123
- }
2124
- function body_section(previous_raw, current_raw) {
2125
- const previous = to_lf(previous_raw);
2126
- const current = to_lf(current_raw);
2127
- if (previous === current) return void 0;
2128
- const removed = lines_missing_from(previous, current).map((line) => `${REMOVED_PREFIX}${line}`);
2129
- const added = lines_missing_from(current, previous).map((line) => `${ADDED_PREFIX}${line}`);
2130
- return [BODY_HEADING, ...removed, ...added].join(LINE_SEPARATOR);
2131
- }
2132
- function comment_section(comment) {
2133
- return `${COMMENT_HEADING}${comment.author}${AT}${comment.created_at}${LINE_SEPARATOR}${comment.body}`;
2134
- }
2135
- function new_person_comments(baseline, snapshot) {
2136
- return snapshot.comments.filter(
2137
- (comment) => comment.id > baseline.last_comment_id && !comment.is_automated
2138
- );
2139
- }
2140
- function unread_diff(baseline, snapshot) {
2141
- const body = body_section(baseline.body, snapshot.body);
2142
- const comments = new_person_comments(baseline, snapshot).map(
2143
- (comment) => comment_section(comment)
2144
- );
2145
- const sections = [...body === void 0 ? [] : [body], ...comments];
2146
- return sections.length === 0 ? void 0 : sections.join(SECTION_SEPARATOR);
2147
- }
2148
- var issue_watch_diff = {
2149
- RUN_MARKER,
2150
- baseline_of,
2151
- parse_comments,
2152
- unread_diff
2153
- };
2154
-
2155
- // scripts/gh/git-gh-issue-write.ts
2156
- var PATCH_METHOD = "PATCH";
2157
- var DELETE_METHOD = "DELETE";
2158
- var HTML_URL_FILTER = ".html_url";
2159
- var ID_FILTER = ".id";
2160
- var LABEL_NAMES_FILTER = ".[].name";
2161
- var LABELS_SEGMENT = "/labels";
2162
- var COMMENTS_SEGMENT = "/comments";
2163
- var CLOSED_STATE = "closed";
2164
- var NOT_PLANNED_REASON = "not_planned";
2165
- var COLOR_HASH = "#";
2166
- var UNPROCESSABLE_STATUS = 422;
2167
- var ALREADY_EXISTS_CODE = "already_exists";
2168
- async function did_write_succeed(write) {
2169
- try {
2170
- await write();
2171
- return true;
2172
- } catch (error) {
2173
- error_text.trace_swallowed("git_gh_issue_write.did_write_succeed", error);
2174
- return false;
2175
- }
2176
- }
2177
- async function issue_edit_body(issue_number, body) {
2178
- return await git_gh_exec.exec_gh_api({
2179
- path: git_gh_api_path.issue_api_path(issue_number),
2180
- method: PATCH_METHOD,
2181
- body: JSON.stringify({ body }),
2182
- jq_filter: HTML_URL_FILTER
2183
- });
2184
- }
2185
- async function issue_comment(issue_number, body) {
2186
- return await git_gh_exec.exec_gh_api({
2187
- path: `${git_gh_api_path.issue_api_path(issue_number)}${COMMENTS_SEGMENT}`,
2188
- body: JSON.stringify({ body: `${body}
2189
-
2190
- ${issue_watch_diff.RUN_MARKER}` }),
2191
- jq_filter: HTML_URL_FILTER
2192
- });
2193
- }
2194
- async function issue_try_comment(issue_number, body) {
2195
- return await did_write_succeed(async () => await issue_comment(issue_number, body));
2196
- }
2197
- async function close_with(issue_number, comment, state) {
2198
- return await did_write_succeed(async () => {
2199
- if (comment !== void 0) await issue_comment(issue_number, comment);
2200
- await git_gh_exec.exec_gh_api({
2201
- path: git_gh_api_path.issue_api_path(issue_number),
2202
- method: PATCH_METHOD,
2203
- body: JSON.stringify(state)
2204
- });
2205
- });
2206
- }
2207
- async function issue_close(issue_number, comment) {
2208
- return await close_with(issue_number, comment, { state: CLOSED_STATE });
2209
- }
2210
- async function issue_close_not_planned(issue_number, comment) {
2211
- return await close_with(issue_number, comment, {
2212
- state: CLOSED_STATE,
2213
- state_reason: NOT_PLANNED_REASON
2214
- });
2215
- }
2216
- function to_label_color(color) {
2217
- return color.startsWith(COLOR_HASH) ? color.slice(COLOR_HASH.length) : color;
2218
- }
2219
- function is_label_already_exists(error) {
2220
- if (gh_failure.failure_of(error)?.status !== UNPROCESSABLE_STATUS) return false;
2221
- return error_text.message_of(error).includes(ALREADY_EXISTS_CODE);
2222
- }
2223
- async function label_ensure(input) {
2224
- try {
2225
- await git_gh_exec.exec_gh_api({
2226
- path: `${git_gh_api_path.repo_api_path()}${LABELS_SEGMENT}`,
2227
- body: JSON.stringify({
2228
- name: input.name,
2229
- color: to_label_color(input.color),
2230
- description: input.description
2231
- })
2232
- });
2233
- } catch (error) {
2234
- if (is_label_already_exists(error)) return;
2235
- const [gist = ""] = error_text.message_of(error).split("\n", 1);
2236
- console.warn(`\u26A0 could not create the \`${input.name}\` label \u2014 ${gist}`);
2237
- }
2238
- }
2239
- function issue_create_request(input) {
2240
- const { labels } = input;
2241
- return {
2242
- path: git_gh_api_path.issues_api_path(input.repo),
2243
- body: JSON.stringify({
2244
- title: input.title,
2245
- ...labels !== void 0 && { labels },
2246
- body: input.body
2247
- }),
2248
- jq_filter: HTML_URL_FILTER
2249
- };
2250
- }
2251
- async function issue_create_with_label(input) {
2252
- return await git_gh_exec.exec_gh_api(
2253
- issue_create_request({ title: input.title, body: input.body, labels: [input.label] })
2254
- );
2255
- }
2256
- async function read_label_names(issue_number) {
2257
- try {
2258
- const raw = await git_gh_exec.exec_gh_api({
2259
- path: `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`,
2260
- should_paginate: true,
2261
- jq_filter: LABEL_NAMES_FILTER
2262
- });
2263
- return raw.split("\n").map((name) => name.trim());
2264
- } catch (error) {
2265
- error_text.trace_swallowed("git_gh_issue_write.read_label_names", error);
2266
- return void 0;
2267
- }
2268
- }
2269
- async function issue_apply_label(issue_number, label) {
2270
- const labels_path = `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`;
2271
- try {
2272
- await git_gh_exec.exec_gh_api({ path: labels_path, body: JSON.stringify({ labels: [label] }) });
2273
- return { is_applied: true };
2274
- } catch (error) {
2275
- const names = await read_label_names(issue_number);
2276
- if (names?.includes(label) === true) return { is_applied: true };
2277
- error_text.trace_swallowed("git_gh_issue_write.issue_apply_label", error);
2278
- const [gist = ""] = error_text.message_of(error).split("\n", 1);
2279
- return { is_applied: false, reason: gist };
2280
- }
2281
- }
2282
- async function issue_add_label(issue_number, label) {
2283
- const write = await issue_apply_label(issue_number, label);
2284
- return write.is_applied;
2285
- }
2286
- async function issue_remove_label(issue_number, label) {
2287
- const labels_path = `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`;
2288
- await git_gh_exec.exec_gh_api({
2289
- path: `${labels_path}/${encodeURIComponent(label)}`,
2290
- method: DELETE_METHOD
2291
- });
2292
- }
2293
- async function read_issue_id(issue_number) {
2294
- const raw = await git_gh_exec.exec_gh_api({
2295
- path: git_gh_api_path.issue_api_path(issue_number),
2296
- jq_filter: ID_FILTER
2297
- });
2298
- const issue_id = Number(raw.trim());
2299
- if (!Number.isSafeInteger(issue_id) || issue_id <= 0) {
2300
- throw new Error(`gh api answered no database id for issue ${session_cite.issue(issue_number)}`);
2301
- }
2302
- return issue_id;
2303
- }
2304
- async function issue_add_blocked_by(issue_number, blocker) {
2305
- return await did_write_succeed(async () => {
2306
- const issue_id = await read_issue_id(blocker);
2307
- await git_gh_exec.exec_gh_api({
2308
- path: git_gh_api_path.blocked_by_api_path(issue_number),
2309
- body: JSON.stringify({ issue_id })
2310
- });
2311
- });
2312
- }
2313
- async function issue_remove_blocked_by(issue_number, blocker) {
2314
- return await did_write_succeed(async () => {
2315
- const issue_id = await read_issue_id(blocker);
2316
- const relations_path = git_gh_api_path.blocked_by_api_path(issue_number);
2317
- await git_gh_exec.exec_gh_api({
2318
- path: `${relations_path}/${String(issue_id)}`,
2319
- method: DELETE_METHOD
2320
- });
2321
- });
2322
- }
2323
- var git_gh_issue_write = {
2324
- issue_edit_body,
2325
- issue_comment,
2326
- issue_try_comment,
2327
- issue_close,
2328
- issue_close_not_planned,
2329
- label_ensure,
2330
- issue_create_request,
2331
- issue_create_with_label,
2332
- issue_apply_label,
2333
- issue_add_label,
2334
- issue_remove_label,
2335
- issue_add_blocked_by,
2336
- issue_remove_blocked_by
2337
- };
2338
-
2339
- // scripts/gh/git-gh-issue.ts
2340
- var NUMBER_AND_BODY_FIELDS = "number,body";
2341
- var BACKLOG_SCAN_FIELDS = `number,title,body,labels,${BLOCKED_BY_COUNT_FIELD}`;
2342
- var NUMBER_TITLE_AND_LABELS_FIELDS = "number,title,labels";
2343
- var SUMMARY_FIELDS = "number,title,labels,createdAt";
2344
- var PICKUP_FIELDS = `${SUMMARY_FIELDS},blockedBy,body`;
2345
- var { issue_list: issue_list2 } = git_gh_issue_list;
2346
- async function issue_list_recent(limit) {
2347
- return await issue_list2({ json_fields: SUMMARY_FIELDS, limit });
2348
- }
2349
- async function issue_list_open_bodies(limit) {
2350
- return await issue_list2({ json_fields: BACKLOG_SCAN_FIELDS, limit });
2351
- }
2352
- async function issue_list_recently_closed(limit) {
2353
- return await issue_list2({
2354
- json_fields: NUMBER_TITLE_AND_LABELS_FIELDS,
2355
- limit,
2356
- state: "closed",
2357
- sort: "updated"
2358
- });
2359
- }
2360
- async function issue_search_body(term, limit) {
2361
- return await issue_list2({
2362
- json_fields: NUMBER_AND_BODY_FIELDS,
2363
- limit,
2364
- body_term: term
2365
- });
2366
- }
2367
- async function issue_list_by_label(label, limit) {
2368
- return await issue_list2({ json_fields: NUMBER_AND_BODY_FIELDS, limit, label });
2369
- }
2370
- async function issue_list_by_label_summary(label, limit, options) {
2371
- return await issue_list2({
2372
- json_fields: options?.json_fields ?? PICKUP_FIELDS,
2373
- limit,
2374
- label
2375
- });
2376
- }
2377
- async function issue_list_by_label_in_repo(label, limit, repo) {
2378
- return await issue_list2({ json_fields: SUMMARY_FIELDS, limit, label, repo });
2379
- }
2380
- var JUDGEMENT_FIELDS = "number,title,body,labels,updatedAt";
2381
- async function issue_list_open_for_judgement(limit) {
2382
- return await issue_list2({ json_fields: JUDGEMENT_FIELDS, limit });
2383
- }
2384
- var git_gh_issue = {
2385
- ...git_gh_issue_read,
2386
- ...git_gh_issue_write,
2387
- issue_list_recent,
2388
- issue_list_by_label,
2389
- issue_list_by_label_in_repo,
2390
- issue_list_by_label_summary,
2391
- issue_search_body,
2392
- issue_list_open_bodies,
2393
- issue_list_open_for_judgement,
2394
- issue_list_recently_closed
2395
- };
2396
-
2397
- // scripts/ci/pr-classification.ts
2398
- import { readFileSync as readFileSync3 } from "node:fs";
2399
- import { fileURLToPath as fileURLToPath2 } from "node:url";
2400
- import { z as z7 } from "zod";
2401
- var CLASSIFICATION_SET = new Set(RELEASE_CLASSIFICATION_NAMES);
2402
- var ISSUE_BUG_LABEL = "bug";
2403
- var DECLARATION_PREFIX = "- \u30EA\u30EA\u30FC\u30B9\u5206\u985E: ";
2404
- var DECLARATION = new RegExp(`^${DECLARATION_PREFIX}(.+)$`, "gmu");
2405
- var LEGACY_LABELS = /* @__PURE__ */ new Set(["semver-major", "semver-minor"]);
2406
- var LABEL = z7.object({ name: z7.string() });
2407
- var USER = z7.object({ login: z7.string() });
2408
- var PULL_REQUEST = z7.object({ number: z7.number(), user: USER });
2409
- var EVENT = z7.object({
2410
- pull_request: PULL_REQUEST,
2411
- repository: z7.object({ full_name: z7.string() })
2412
- });
2413
- function classification_error(labels, author) {
2414
- const legacy = labels.filter((label) => LEGACY_LABELS.has(label.toLowerCase()));
2415
- if (legacy.length > 0) return `Remove legacy release labels: ${legacy.join(", ")}`;
2416
- const selected = labels.filter((label) => CLASSIFICATION_SET.has(label.toLowerCase()));
2417
- if (selected.length > 1) {
2418
- return `Choose exactly one release classification; found: ${selected.join(", ")}`;
2419
- }
2420
- if (selected.length === 1 || author.endsWith("[bot]")) return void 0;
2421
- return `Choose one release classification: ${RELEASE_CLASSIFICATION_NAMES.join(", ")}`;
2422
- }
2423
- function declaration(label) {
2424
- return `${DECLARATION_PREFIX}${label}`;
2425
- }
2426
- function is_classification(value) {
2427
- return CLASSIFICATION_SET.has(value);
2428
- }
2429
- function release_candidates(candidates) {
2430
- if (!candidates.includes(BREAKING_CHANGE_LABEL)) return candidates;
2431
- return candidates.filter((candidate) => candidate !== ENHANCEMENT_LABEL);
2432
- }
2433
- function issue_candidates(issue_json) {
2434
- const issue = z7.object({ labels: z7.array(LABEL), body: z7.string().nullable() }).parse(JSON.parse(issue_json));
2435
- const names = issue.labels.map((label) => label.name.toLowerCase());
2436
- const declared = [...(issue.body ?? "").matchAll(DECLARATION)].map((match) => match[1] ?? "");
2437
- const candidates = [...release_candidates([...names, ...declared].filter(is_classification))];
2438
- const unknown = declared.filter((value) => !is_classification(value));
2439
- if (unknown.length > 0) throw new Error(`Unknown release classification: ${unknown.join(", ")}`);
2440
- if (names.includes(ISSUE_BUG_LABEL) && !candidates.includes(BREAKING_CHANGE_LABEL)) {
2441
- candidates.push(BUGFIX_LABEL);
2442
- }
2443
- return candidates;
2444
- }
2445
- function select_issue_classification(issue_json) {
2446
- const candidates = issue_candidates(issue_json);
2447
- const selected = [...new Set(candidates)];
2448
- const [label] = selected;
2449
- if (label === void 0 || selected.length > 1) {
2450
- throw new Error(
2451
- `Choose one release classification before opening the PR: ${RELEASE_CLASSIFICATION_NAMES.join(", ")}; found: ${selected.join(", ") || "none"}. Add "${DECLARATION_PREFIX}<label>" to the Issue body.`
2452
- );
2453
- }
2454
- return label;
2455
- }
2456
- function fetch_current_labels(repository, pull_number) {
2457
- const path4 = `repos/${repository}/issues/${String(pull_number)}/labels`;
2458
- try {
2459
- const names = git_gh_exec.exec_gh_api_sync({ path: path4, jq_filter: ".[].name" });
2460
- return names.split("\n").filter((name) => name !== "");
2461
- } catch (error) {
2462
- const detail = error_text.message_of(error);
2463
- throw new Error(`Could not read the pull request labels: ${detail}`, { cause: error });
2464
- }
2465
- }
2466
- function check_event(event_path, read_labels = fetch_current_labels) {
2467
- const event = EVENT.parse(JSON.parse(readFileSync3(event_path, "utf8")));
2468
- const labels = read_labels(event.repository.full_name, event.pull_request.number);
2469
- return classification_error(labels, event.pull_request.user.login);
2470
- }
2471
- if (process.argv[1] === fileURLToPath2(import.meta.url)) {
2472
- const event_path = process.env["GITHUB_EVENT_PATH"];
2473
- if (!event_path) throw new Error("GITHUB_EVENT_PATH is required");
2474
- const error = check_event(event_path);
2475
- if (error) {
2476
- console.error(`::error::${error}`);
2477
- process.exitCode = 1;
2478
- }
2479
- }
2480
- var pr_classification = {
2481
- classification_error,
2482
- check_event,
2483
- fetch_current_labels,
2484
- declaration,
2485
- is_classification,
2486
- select_issue_classification
2487
- };
2488
-
2489
- // scripts/lib/poll.ts
2490
- async function sleep2(duration_ms) {
2491
- await new Promise((resolve2) => {
2492
- setTimeout(resolve2, duration_ms);
2493
- });
2494
- }
2495
- async function wait_between(wait, interval_ms, attempt, attempts) {
2496
- if (attempt < attempts - 1) await wait(interval_ms);
2497
- }
2498
- async function poll_until(is_done, options) {
2499
- const wait = options.sleeper ?? sleep2;
2500
- for (let attempt = 0; attempt < options.attempts; attempt += 1) {
2501
- if (await is_done()) return true;
2502
- await wait_between(wait, options.interval_ms, attempt, options.attempts);
2503
- }
2504
- return false;
2505
- }
2506
- var poll = { poll_until, sleep: sleep2 };
2507
-
2508
- // scripts/gh/git-gh-pr.ts
2509
- import { z as z10 } from "zod";
2510
-
2511
- // scripts/gh/git-gh-pr-review.ts
2512
- import { z as z8 } from "zod";
2513
- var REVIEW_APPROVED = "APPROVED";
2514
- var REVIEW_CHANGES_REQUESTED = "CHANGES_REQUESTED";
2515
- var REVIEW_NONE = "";
2516
- var STATE_CHANGING_REVIEWS = /* @__PURE__ */ new Set([REVIEW_APPROVED, REVIEW_CHANGES_REQUESTED]);
2517
- var rest_review_schema = z8.looseObject({
2518
- state: z8.string().optional(),
2519
- user: z8.looseObject({ login: z8.string().optional() }).nullish()
2520
- });
2521
- var NOT_A_REVIEW_LISTING = "gh api answered something other than a review listing";
2522
- function parse_rest_reviews(reviews_json) {
2523
- const parsed = parse_json_array_or_undefined(reviews_json, rest_review_schema);
2524
- if (parsed === void 0) throw new Error(NOT_A_REVIEW_LISTING);
2525
- return parsed;
2526
- }
2527
- var UNATTRIBUTED_REVIEWER = "(no author)";
2528
- function read_reviewer(review) {
2529
- const login = review.user?.login;
2530
- return typeof login === "string" && login.length > 0 ? login : UNATTRIBUTED_REVIEWER;
2531
- }
2532
- function read_state_changing(review) {
2533
- const state = review.state?.toUpperCase();
2534
- return state !== void 0 && STATE_CHANGING_REVIEWS.has(state) ? state : void 0;
2535
- }
2536
- function fold_latest_states(reviews) {
2537
- const latest = /* @__PURE__ */ new Map();
2538
- for (const review of reviews) {
2539
- const state = read_state_changing(review);
2540
- if (state !== void 0) latest.set(read_reviewer(review), state);
2541
- }
2542
- return latest;
2543
- }
2544
- function to_review_decision(reviews_json) {
2545
- const latest = new Set(fold_latest_states(parse_rest_reviews(reviews_json)).values());
2546
- if (latest.has(REVIEW_CHANGES_REQUESTED)) return REVIEW_CHANGES_REQUESTED;
2547
- return latest.has(REVIEW_APPROVED) ? REVIEW_APPROVED : REVIEW_NONE;
2548
- }
2549
- var git_gh_pr_review = { to_review_decision };
2550
-
2551
- // scripts/gh/git-gh-pr-rollup.ts
2552
- import { z as z9 } from "zod";
2553
- var STATUS_CONTEXT_TYPE_NAME = "StatusContext";
2554
- var TYPE_NAME_KEY = "__typename";
2555
- var rollup_element_schema = z9.looseObject({});
2556
- var check_runs_page_schema = z9.looseObject({
2557
- // Required, not optional: GitHub always names the key, and accepting a page without one would
2558
- // answer an empty rollup — which `git-pr-followup.ts` reports as "this branch has no checks".
2559
- check_runs: z9.array(rollup_element_schema)
2560
- });
2561
- var id_holder_schema = z9.object({ id: z9.number() });
2562
- var status_page_schema = z9.looseObject({
2563
- statuses: z9.array(rollup_element_schema)
2564
- });
2565
- var NOT_A_CHECK_RUNS_LISTING = "gh api answered something other than a check run listing";
2566
- var NOT_A_STATUS_LISTING = "gh api answered something other than a commit status listing";
2567
- function read_pages(raw_json, schema, message) {
2568
- const pages = parse_json_array_or_undefined(raw_json, schema);
2569
- if (pages === void 0) throw new Error(message);
2570
- return pages;
2571
- }
2572
- var NO_SUITE = -1;
2573
- function read_id(value) {
2574
- const parsed = id_holder_schema.safeParse(value);
2575
- return parsed.success ? parsed.data.id : void 0;
2576
- }
2577
- function check_run_group_key(run2) {
2578
- const { name, app } = run2;
2579
- if (typeof name !== "string") return void 0;
2580
- return JSON.stringify([name, read_id(app)]);
2581
- }
2582
- function read_rank(run2) {
2583
- const id = read_id(run2);
2584
- if (id === void 0) return void 0;
2585
- return { suite: read_id(run2["check_suite"]) ?? NO_SUITE, run: id };
2586
- }
2587
- function is_ranked_above(candidate, current) {
2588
- if (candidate.suite !== current.suite) return candidate.suite > current.suite;
2589
- return candidate.run > current.run;
2590
- }
2591
- function should_replace(previous, rank) {
2592
- const previous_rank = previous === void 0 ? void 0 : read_rank(previous);
2593
- return previous_rank === void 0 || is_ranked_above(rank, previous_rank);
2594
- }
2595
- function remember_newest_run(run2, newest) {
2596
- const key2 = check_run_group_key(run2);
2597
- const rank = read_rank(run2);
2598
- if (key2 === void 0 || rank === void 0) return;
2599
- if (should_replace(newest.get(key2), rank)) newest.set(key2, run2);
2600
- }
2601
- function is_newest_run(run2, newest) {
2602
- const key2 = check_run_group_key(run2);
2603
- if (key2 === void 0 || read_rank(run2) === void 0) return true;
2604
- return newest.get(key2) === run2;
2605
- }
2606
- function to_check_run_items(check_runs_json) {
2607
- const pages = read_pages(check_runs_json, check_runs_page_schema, NOT_A_CHECK_RUNS_LISTING);
2608
- const runs = pages.flatMap((page) => page.check_runs);
2609
- const newest = /* @__PURE__ */ new Map();
2610
- for (const run2 of runs) remember_newest_run(run2, newest);
2611
- return runs.filter((run2) => is_newest_run(run2, newest));
2612
- }
2613
- function to_status_context_items(status_json) {
2614
- const pages = read_pages(status_json, status_page_schema, NOT_A_STATUS_LISTING);
2615
- return pages.flatMap((page) => page.statuses).map((status) => ({ ...status, [TYPE_NAME_KEY]: STATUS_CONTEXT_TYPE_NAME }));
2616
- }
2617
- function to_status_check_rollup(input) {
2618
- return [
2619
- ...to_check_run_items(input.check_runs_json),
2620
- ...to_status_context_items(input.status_json)
2621
- ];
2622
- }
2623
- var git_gh_pr_rollup = {
2624
- to_status_check_rollup
2625
- };
2626
-
2627
- // scripts/gh/git-gh-pr-snapshot.ts
2628
- var NO_HEAD_SHA_MESSAGE = "gh api answered a pull request with no head commit";
2629
- async function read_object_pages(path4) {
2630
- return await git_gh_exec.exec_gh_api({
2631
- path: `${path4}${FULL_PAGE_QUERY}`,
2632
- should_paginate: true,
2633
- should_slurp: true
2634
- });
2635
- }
2636
- async function read_array_pages(path4) {
2637
- return await git_gh_exec.exec_gh_api({
2638
- path: `${path4}${FULL_PAGE_QUERY}`,
2639
- should_paginate: true
2640
- });
2641
- }
2642
- function read_head_sha(pull) {
2643
- const sha = pull.head?.sha;
2644
- if (sha === void 0) throw new Error(NO_HEAD_SHA_MESSAGE);
2645
- return sha;
2646
- }
2647
- async function read_status_check_rollup(commit_sha) {
2648
- const [check_runs_json, status_json] = await Promise.all([
2649
- read_object_pages(git_gh_api_path.commit_check_runs_api_path(commit_sha)),
2650
- read_object_pages(git_gh_api_path.commit_status_api_path(commit_sha))
2651
- ]);
2652
- return git_gh_pr_rollup.to_status_check_rollup({ check_runs_json, status_json });
2653
- }
2654
- async function pr_get_review_decision(pr_number) {
2655
- const path4 = git_gh_api_path.pull_reviews_api_path(String(pr_number));
2656
- return git_gh_pr_review.to_review_decision(await read_array_pages(path4));
2657
- }
2658
- async function build_checks_fields(pull) {
2659
- return {
2660
- statusCheckRollup: await read_status_check_rollup(read_head_sha(pull)),
2661
- mergeStateStatus: to_gh_state(pull.mergeable_state)
2662
- };
2663
- }
2664
- async function resolve_pull(branch_name) {
2665
- const pr_number = await require_pr_number(branch_name);
2666
- return { pr_number, pull: await read_pull(pr_number) };
2667
- }
2668
- async function pr_get_checks_snapshot(branch_name) {
2669
- const { pr_number, pull } = await resolve_pull(branch_name);
2670
- return { pr_number, snapshot_json: JSON.stringify(await build_checks_fields(pull)) };
2671
- }
2672
- async function pr_get_state_snapshot(branch_name) {
2673
- const { pr_number, pull } = await resolve_pull(branch_name);
2674
- const [fields, review_decision] = await Promise.all([
2675
- build_checks_fields(pull),
2676
- pr_get_review_decision(pr_number)
2677
- ]);
2678
- return JSON.stringify({ ...fields, reviewDecision: review_decision });
2679
- }
2680
- var git_gh_pr_snapshot = {
2681
- pr_get_state_snapshot,
2682
- pr_get_checks_snapshot,
2683
- pr_get_review_decision
2684
- };
2685
-
2686
- // scripts/gh/git-gh-pr.ts
2687
- var HTML_URL_FILTER2 = ".html_url";
2688
- var PUT_METHOD = "PUT";
2689
- var PATCH_METHOD2 = "PATCH";
2690
- var MERGE_COMMIT_METHOD = "merge";
2691
- var MERGE_REQUEST_TIMEOUT_MS = 18e4;
2692
- var MERGE_UNCONFIRMED_MESSAGE = "gh api could not read the pull request back after the merge request failed";
2693
- var MERGE_READ_BACK_ATTEMPTS = 3;
2694
- var MERGE_READ_BACK_INTERVAL_MS = 1e3;
2695
- var PR_NUMBER_PATTERN = /\/pull\/([1-9]\d*)$/u;
2696
- var LABELS_SEGMENT2 = "/labels";
2697
- var PR_LABELS = z10.array(z10.object({ name: z10.string() }));
2698
- async function add_pr_classification(number, label) {
2699
- await git_gh_exec.exec_gh_api({
2700
- path: `${git_gh_api_path.issue_api_path(number)}${LABELS_SEGMENT2}`,
2701
- body: JSON.stringify({ labels: [label] })
2702
- });
2703
- }
2704
- async function pr_get_classification(branch_name) {
2705
- const number = await require_pr_number(branch_name);
2706
- const response = await git_gh_exec.exec_gh_api({
2707
- path: `${git_gh_api_path.issue_api_path(String(number))}${LABELS_SEGMENT2}`
2708
- });
2709
- const names = PR_LABELS.parse(JSON.parse(response)).map((label) => label.name.toLowerCase());
2710
- const selected = names.filter((name) => pr_classification.is_classification(name));
2711
- if (selected.length === 0) return void 0;
2712
- const error = pr_classification.classification_error(names, "human");
2713
- if (error !== void 0) throw new Error(error);
2714
- return selected[0];
2715
- }
2716
- async function pr_ensure_classification(branch_name, label) {
2717
- if (await pr_get_classification(branch_name) !== void 0) return;
2718
- const number = await require_pr_number(branch_name);
2719
- await add_pr_classification(String(number), label);
2720
- }
2721
- async function post_pull_request(title, body) {
2722
- const base = await git_command.get_default_branch();
2723
- const head = await git_command.branch();
2724
- forget_pr_numbers();
2725
- try {
2726
- return await git_gh_exec.exec_gh_api({
2727
- path: git_gh_api_path.pulls_api_path(),
2728
- body: JSON.stringify({ title, body, head, base }),
2729
- jq_filter: HTML_URL_FILTER2
2730
- });
2731
- } catch (error) {
2732
- return git_gh_helpers.handle_pr_create_error(error);
2733
- }
2734
- }
2735
- async function pr_create(title, body, label) {
2736
- const classification_error2 = pr_classification.classification_error([label], "human");
2737
- if (classification_error2 !== void 0) throw new Error(classification_error2);
2738
- const url = await post_pull_request(title, body);
2739
- const number = PR_NUMBER_PATTERN.exec(url)?.[1];
2740
- if (number === void 0) throw new Error(`Could not identify the created pull request: ${url}`);
2741
- await add_pr_classification(number, label);
2742
- return url;
2743
- }
2744
- async function pr_comment(branch_name, body) {
2745
- const pr_number = await require_pr_number(branch_name);
2746
- return await git_gh_issue_write.issue_comment(String(pr_number), body);
2747
- }
2748
- async function pr_update_body(branch_name, body) {
2749
- const pr_number = await require_pr_number(branch_name);
2750
- forget_pr_numbers();
2751
- await git_gh_exec.exec_gh_api({
2752
- path: git_gh_api_path.pull_api_path(String(pr_number)),
2753
- method: PATCH_METHOD2,
2754
- body: JSON.stringify({ body })
2755
- });
2756
- }
2757
- async function put_merge(pr_number) {
2758
- forget_pr_numbers();
2759
- await git_gh_exec.exec_gh_api({
2760
- path: git_gh_api_path.pull_merge_api_path(String(pr_number)),
2761
- method: PUT_METHOD,
2762
- body: JSON.stringify({ merge_method: MERGE_COMMIT_METHOD }),
2763
- timeout_ms: MERGE_REQUEST_TIMEOUT_MS
2764
- });
2765
- }
2766
- async function read_merge_state(pr_number) {
2767
- try {
2768
- return git_gh_pr_rest.is_merged(await read_pull(pr_number));
2769
- } catch (error) {
2770
- console.warn(`Could not read the pull request back: ${String(error)}`);
2771
- return void 0;
2772
- }
2773
- }
2774
- async function sleep_between_read_backs(attempt) {
2775
- if (attempt < MERGE_READ_BACK_ATTEMPTS - 1) await poll.sleep(MERGE_READ_BACK_INTERVAL_MS);
2776
- }
2777
- async function has_merge_landed(pr_number, merge_error) {
2778
- for (let attempt = 0; attempt < MERGE_READ_BACK_ATTEMPTS; attempt += 1) {
2779
- const is_merged = await read_merge_state(pr_number);
2780
- if (is_merged !== void 0) return is_merged;
2781
- await sleep_between_read_backs(attempt);
2782
- }
2783
- throw new Error(MERGE_UNCONFIRMED_MESSAGE, { cause: merge_error });
2784
- }
2785
- async function pr_merge(branch_name) {
2786
- const pr_number = await require_pr_number(branch_name);
2787
- try {
2788
- await put_merge(pr_number);
2789
- } catch (error) {
2790
- if (!await has_merge_landed(pr_number, error)) throw error;
2791
- }
2792
- }
2793
- var git_gh_pr = {
2794
- ...git_gh_pr_read,
2795
- ...git_gh_pr_snapshot,
2796
- pr_create,
2797
- pr_get_classification,
2798
- pr_ensure_classification,
2799
- pr_comment,
2800
- pr_merge,
2801
- pr_update_body
2802
- };
2803
-
2804
- // scripts/gh/git-gh-pr-auto-merge.ts
2805
- var GRAPHQL_PATH = "graphql";
2806
- var OPEN_PULLS_QUERY = `${git_gh_api_path.FULL_PAGE_QUERY}&state=open`;
2807
- var MISSING_NODE_ID_MESSAGE = "gh api answered a pull request without a node_id";
2808
- var ENABLE_AUTO_MERGE_MUTATION = "mutation($id: ID!) { enablePullRequestAutoMerge(input: { pullRequestId: $id, mergeMethod: MERGE }) { clientMutationId } }";
2809
- async function pr_enable_auto_merge(branch_name) {
2810
- const pull = await read_pull(await require_pr_number(branch_name));
2811
- if (pull.node_id === void 0) throw new Error(MISSING_NODE_ID_MESSAGE);
2812
- await git_gh_exec.exec_gh_api({
2813
- path: GRAPHQL_PATH,
2814
- body: JSON.stringify({ query: ENABLE_AUTO_MERGE_MUTATION, variables: { id: pull.node_id } })
2815
- });
2816
- }
2817
- async function pr_is_merged(branch_name) {
2818
- try {
2819
- return git_gh_pr_rest.is_merged(await read_pull(await require_pr_number(branch_name)));
2820
- } catch (error) {
2821
- error_text.trace_swallowed("git_gh_pr_auto_merge.pr_is_merged", error);
2822
- return false;
2823
- }
2824
- }
2825
- function head_reference_of(pull) {
2826
- return pull.head?.ref ?? "";
2827
- }
2828
- function has_head_prefix(pull, prefix) {
2829
- return git_gh_pr_rest.is_same_repository_head(pull) && head_reference_of(pull).startsWith(prefix);
2830
- }
2831
- function to_open_pull(pull) {
2832
- return {
2833
- number: pull.number,
2834
- head_ref: head_reference_of(pull),
2835
- has_auto_merge: pull.auto_merge !== null && pull.auto_merge !== void 0
2836
- };
2837
- }
2838
- async function pr_list_open_with_head_prefix(prefix) {
2839
- const json = await git_gh_exec.exec_gh_api({
2840
- path: `${git_gh_api_path.pulls_api_path()}${OPEN_PULLS_QUERY}`,
2841
- should_paginate: true
2842
- });
2843
- return git_gh_pr_rest.parse_rest_pulls(json).filter((pull) => has_head_prefix(pull, prefix)).map((pull) => to_open_pull(pull));
2844
- }
2845
- var git_gh_pr_auto_merge = {
2846
- pr_enable_auto_merge,
2847
- pr_is_merged,
2848
- pr_list_open_with_head_prefix
2849
- };
2850
-
2851
- // scripts/gh/git-pr-checks.ts
2852
- var SECONDS_TO_MS = 1e3;
2853
- var CHECK_WAIT_INTERVAL_MS = 1e4;
2854
- var DEFAULT_TIMEOUT_SECONDS = 1920;
2855
- function compute_max_attempts(timeout_seconds, interval_ms) {
2856
- return Math.ceil(timeout_seconds / (interval_ms / SECONDS_TO_MS)) + 1;
2857
- }
2858
- var DEFAULT_MAX_ATTEMPTS = compute_max_attempts(DEFAULT_TIMEOUT_SECONDS, CHECK_WAIT_INTERVAL_MS);
2859
- function get_configured_max_attempts() {
2860
- const environment_seconds = Number(process.env["JOSH_CI_TIMEOUT_SECONDS"]);
2861
- return Number.isFinite(environment_seconds) && environment_seconds > 0 ? compute_max_attempts(environment_seconds, CHECK_WAIT_INTERVAL_MS) : DEFAULT_MAX_ATTEMPTS;
2862
- }
2863
- var CHECK_MAX_ATTEMPTS = get_configured_max_attempts();
2864
- var DEFAULT_STABLE_READS = 2;
2865
- var MAX_CONSECUTIVE_READ_FAILURES = 3;
2866
- var PR_CHECKS_TIMEOUT_MESSAGE = "Timed out while waiting for PR checks to complete.";
2867
- function is_pr_checks_timeout(error) {
2868
- return error instanceof Error && error.message === PR_CHECKS_TIMEOUT_MESSAGE;
2869
- }
2870
- function should_always_read_review_decision() {
2871
- return true;
2872
- }
2873
- var MERGE_GATE_EVALUATOR = {
2874
- evaluate: evaluate_pr_state,
2875
- describe: describe_pr_failure,
2876
- should_read_review_decision: is_review_decision_decisive
2877
- };
2878
- function advance_stable_count(previous, state) {
2879
- return state === "success" ? previous + 1 : 0;
2880
- }
2881
- function failure_error(message, snapshot) {
2882
- return is_merge_conflict(snapshot.merge_state_status) ? new PrConflictError(message) : new Error(message);
2883
- }
2884
- function classify_poll_result(input) {
2885
- const state = input.evaluator.evaluate(input.snapshot);
2886
- if (state === "failure") {
2887
- throw failure_error(input.evaluator.describe(input.snapshot), input.snapshot);
2888
- }
2889
- const next_stable_count = advance_stable_count(input.stable_count, state);
2890
- return {
2891
- is_done: next_stable_count >= input.required_stable_reads,
2892
- next_stable_count
2893
- };
2894
- }
2895
- async function read_pr_state(input, evaluator) {
2896
- try {
2897
- const snapshot = await input.options.fetcher(
2898
- input.options.branch_name,
2899
- evaluator.should_read_review_decision ?? should_always_read_review_decision
2900
- );
2901
- return { kind: "read", snapshot };
2902
- } catch (error) {
2903
- return { kind: "unreadable", cause: error };
2904
- }
2905
- }
2906
- async function sleep_before_next_attempt(input) {
2907
- if (input.attempt < input.options.max_attempts - 1) {
2908
- await poll.sleep(input.options.interval_ms);
2909
- }
2910
- }
2911
- async function retry_after_unreadable(input, cause) {
2912
- const next_failure_count = input.failure_count + 1;
2913
- if (next_failure_count >= MAX_CONSECUTIVE_READ_FAILURES) throw cause;
2914
- console.warn(
2915
- `Could not read the PR state (${String(next_failure_count)}/${String(MAX_CONSECUTIVE_READ_FAILURES)}); asking again on the next poll: ${String(cause)}`
2916
- );
2917
- await sleep_before_next_attempt(input);
2918
- return { next_stable_count: 0, next_failure_count, read_failure: cause };
2919
- }
2920
- function to_exhaustion_error(last_read_failure) {
2921
- return last_read_failure ?? new Error(PR_CHECKS_TIMEOUT_MESSAGE);
2922
- }
2923
- async function attempt_pr_success_poll(input) {
2924
- const evaluator = input.options.evaluator ?? MERGE_GATE_EVALUATOR;
2925
- const read2 = await read_pr_state(input, evaluator);
2926
- if (read2.kind === "unreadable") return await retry_after_unreadable(input, read2.cause);
2927
- const classification = classify_poll_result({
2928
- snapshot: read2.snapshot,
2929
- stable_count: input.stable_count,
2930
- required_stable_reads: input.options.required_stable_reads,
2931
- evaluator
2932
- });
2933
- if (classification.is_done) {
2934
- return { snapshot: read2.snapshot, next_stable_count: 0, next_failure_count: 0 };
2935
- }
2936
- await sleep_before_next_attempt(input);
2937
- return { next_stable_count: classification.next_stable_count, next_failure_count: 0 };
2938
- }
2939
- async function wait_for_pr_success(options) {
2940
- let carried = { next_stable_count: 0, next_failure_count: 0 };
2941
- for (let attempt = 0; attempt < options.max_attempts; attempt += 1) {
2942
- console.info(`Checking PR status\u2026 (${String(attempt + 1)}/${String(options.max_attempts)})`);
2943
- await options.before_poll?.();
2944
- carried = await attempt_pr_success_poll({
2945
- options,
2946
- stable_count: carried.next_stable_count,
2947
- failure_count: carried.next_failure_count,
2948
- attempt
2949
- });
2950
- if (carried.snapshot !== void 0) return carried.snapshot;
2951
- }
2952
- throw to_exhaustion_error(carried.read_failure);
2953
- }
2954
- async function default_fetch_pr_state(branch_name, should_read_review_decision = should_always_read_review_decision) {
2955
- const checks = await git_gh_pr_snapshot.pr_get_checks_snapshot(branch_name);
2956
- const snapshot = parse_pr_state_snapshot(checks.snapshot_json);
2957
- if (!should_read_review_decision(snapshot)) return snapshot;
2958
- const decision = await git_gh_pr_snapshot.pr_get_review_decision(checks.pr_number);
2959
- return { ...snapshot, review_decision: read_string(decision) };
2960
- }
2961
- function observed_fetcher(observe) {
2962
- if (observe === void 0) return default_fetch_pr_state;
2963
- return async function fetch_observed(branch_name, should_read_review_decision) {
2964
- const snapshot = await default_fetch_pr_state(branch_name, should_read_review_decision);
2965
- await observe(snapshot);
2966
- return snapshot;
2967
- };
2968
- }
2969
-
2970
- // scripts/gh/git-pr-checks-watch.ts
2971
- var PR_CHECKS_WATCH_TIMEOUT_MS = 12e4;
2972
- var WATCH_TIMED_OUT_NOTE = "\u23F1\uFE0F pr checks --watch timed out.";
2973
- var NO_CHECKS_MESSAGE = "gh api reported no checks on the branch";
2974
- var CHECKS_FAILED_MESSAGE = "gh api reported a failing check on the branch";
2975
- function is_awaited_check(check2) {
2976
- return !is_coderabbit_check(check2.name) || is_required_check(check2.name);
2977
- }
2978
- function evaluate_checks_settled(snapshot) {
2979
- const awaited = snapshot.rollup.filter((check2) => is_awaited_check(check2));
2980
- const considered = awaited.length === 0 ? snapshot.rollup : awaited;
2981
- if (considered.length === 0 || considered.some((check2) => check2.status === CHECK_STATUS_PENDING)) {
2982
- return "pending";
2983
- }
2984
- return snapshot.rollup.some((check2) => check2.status === CHECK_STATUS_FAIL) ? "failure" : "success";
2985
- }
2986
- function describe_checks_failure(snapshot) {
2987
- const failed = snapshot.rollup.filter((check2) => check2.status === CHECK_STATUS_FAIL);
2988
- return `${CHECKS_FAILED_MESSAGE}: ${failed.map((check2) => check2.name).join(", ")}`;
2989
- }
2990
- function should_never_read_review_decision() {
2991
- return false;
2992
- }
2993
- var CHECKS_SETTLED_EVALUATOR = {
2994
- evaluate: evaluate_checks_settled,
2995
- describe: describe_checks_failure,
2996
- should_read_review_decision: should_never_read_review_decision
2997
- };
2998
- async function watch_until_settled(branch_name, observe) {
2999
- await wait_for_pr_success({
3000
- branch_name,
3001
- fetcher: observed_fetcher(observe),
3002
- interval_ms: CHECK_WAIT_INTERVAL_MS,
3003
- max_attempts: compute_max_attempts(
3004
- PR_CHECKS_WATCH_TIMEOUT_MS / SECONDS_TO_MS,
3005
- CHECK_WAIT_INTERVAL_MS
3006
- ),
3007
- required_stable_reads: DEFAULT_STABLE_READS,
3008
- evaluator: CHECKS_SETTLED_EVALUATOR
3009
- });
3010
- }
3011
- async function fail_when_no_checks(branch_name) {
3012
- const snapshot = await default_fetch_pr_state(branch_name, should_never_read_review_decision);
3013
- if (snapshot.rollup.length === 0) throw new Error(NO_CHECKS_MESSAGE);
3014
- }
3015
- async function pr_checks_watch(branch_name, observe) {
3016
- try {
3017
- await watch_until_settled(branch_name, observe);
3018
- return { timed_out: false };
3019
- } catch (error) {
3020
- if (!is_pr_checks_timeout(error)) throw error;
3021
- await fail_when_no_checks(branch_name);
3022
- console.info(WATCH_TIMED_OUT_NOTE);
3023
- return { timed_out: true };
3024
- }
3025
- }
3026
- var git_pr_checks_watch = { pr_checks_watch };
3027
-
3028
- // scripts/gh/git-gh-command.ts
3029
- var git_gh_command = {
3030
- ...git_gh_pr,
3031
- ...git_gh_pr_auto_merge,
3032
- pr_checks_watch: git_pr_checks_watch.pr_checks_watch,
3033
- ...git_gh_issue,
3034
- ...git_gh_repo
3035
- };
3036
-
3037
- // scripts/gh/gh-spawn.ts
3038
- var NO_BUDGET = 0;
3039
- function fetch_repo_name(timeout_ms) {
3040
- const stdout = git_gh_exec.read_gh_api_sync({
3041
- path: git_gh_api_path.repo_api_path(),
3042
- jq_filter: ".full_name",
3043
- cwd: PROJECT_ROOT,
3044
- timeout_ms: timeout_ms ?? NO_BUDGET
3045
- });
3046
- const name = stdout?.trim();
3047
- return name === "" ? void 0 : name;
3048
- }
3049
- function get_repo_name_with_owner() {
3050
- return fetch_repo_name(void 0);
3051
- }
3052
- function get_repo_name_with_owner_within(timeout_ms) {
3053
- return fetch_repo_name(timeout_ms);
3054
- }
3055
- var gh_spawn = { get_repo_name_with_owner, get_repo_name_with_owner_within };
3056
-
3057
- // scripts/issue/issue-state.ts
3058
- import { z as z11 } from "zod";
3059
- var NO_LABELS = "(none)";
3060
- var LABEL_SEPARATOR = ", ";
3061
- var STATE_LABEL = "state: ";
3062
- var LABELS_LABEL = "labels: ";
3063
- var HUMAN_REVIEW_LABEL_LINE = "human_review: ";
3064
- var YES = "yes";
3065
- var NO = "no";
3066
- var ISSUE_LABEL = "issue: ";
3067
- var HUMAN_REVIEW_LABELS = /* @__PURE__ */ new Set([NEEDS_HUMAN_REVIEW_LABEL]);
3068
- var label_schema = z11.looseObject({ name: z11.string() });
3069
- var issue_state_schema = z11.looseObject({
3070
- state: z11.string(),
3071
- labels: label_schema.array().optional()
3072
- });
3073
- function parse_issue_state(json) {
3074
- try {
3075
- const parsed = parse_json_object_or_undefined(json, issue_state_schema);
3076
- if (parsed === void 0) return void 0;
3077
- const labels = parsed.labels ?? [];
3078
- return {
3079
- state: parsed.state,
3080
- labels: labels.map((label) => label.name),
3081
- is_human_review: has_any_label(labels, HUMAN_REVIEW_LABELS)
3082
- };
3083
- } catch {
3084
- return void 0;
3085
- }
3086
- }
3087
- function format_labels(labels) {
3088
- return labels.length === 0 ? NO_LABELS : labels.join(LABEL_SEPARATOR);
3089
- }
3090
- function format_issue_state(state) {
3091
- const human_review = `${HUMAN_REVIEW_LABEL_LINE}${state.is_human_review ? YES : NO}`;
3092
- return `${STATE_LABEL}${state.state}
3093
- ${LABELS_LABEL}${format_labels(state.labels)}
3094
- ${human_review}`;
3095
- }
3096
- function format_attributed_issue_state(issue_number, state) {
3097
- return `${ISSUE_LABEL}${issue_number}
3098
- ${format_issue_state(state)}`;
3099
- }
3100
- var issue_state = {
3101
- NO_LABELS,
3102
- parse_issue_state,
3103
- format_issue_state,
3104
- format_attributed_issue_state
3105
- };
3106
-
3107
- // scripts/run/run-liveness.ts
3108
- import { readFileSync as readFileSync4, realpathSync, statSync } from "node:fs";
3109
- import { homedir, tmpdir } from "node:os";
3110
- import path3 from "node:path";
3111
- import { setTimeout as sleep3 } from "node:timers/promises";
3112
-
3113
- // scripts/agent/agent-event.ts
3114
- import { z as z14 } from "zod";
3115
-
3116
- // scripts/agent/claude-result-event.ts
3117
- import { z as z13 } from "zod";
3118
-
3119
- // scripts/agent/interactive-ask.ts
3120
- import { z as z12 } from "zod";
3121
- var INTERACTIVE_TOOLS = /* @__PURE__ */ new Set(["AskUserQuestion"]);
3122
- function is_interactive_tool(name) {
3123
- return INTERACTIVE_TOOLS.has(name);
3124
- }
3125
- var OPTION_SCHEMA = z12.looseObject({ label: z12.string().optional() });
3126
- var QUESTION_SCHEMA = z12.looseObject({
3127
- question: z12.string().optional(),
3128
- options: z12.array(OPTION_SCHEMA).optional()
3129
- });
3130
- var ASK_INPUT_SCHEMA = z12.looseObject({ questions: z12.array(QUESTION_SCHEMA).optional() });
3131
- var DENIAL_SCHEMA = z12.looseObject({
3132
- tool_name: z12.string().optional(),
3133
- tool_input: z12.unknown().optional()
3134
- });
3135
- var UNKNOWN_QUESTION = "(question text unavailable)";
3136
- var OPTION_SEPARATOR = " / ";
3137
- var QUESTION_SEPARATOR = "; ";
3138
- function labels_of(question) {
3139
- return (question.options ?? []).map((option) => option.label ?? "").filter((label) => label !== "");
3140
- }
3141
- function render_question(question) {
3142
- const labels = labels_of(question);
3143
- const text = question.question ?? UNKNOWN_QUESTION;
3144
- return labels.length === 0 ? text : `${text} [${labels.join(OPTION_SEPARATOR)}]`;
3145
- }
3146
- function interactive_input(raw) {
3147
- const denial = DENIAL_SCHEMA.safeParse(raw);
3148
- if (!denial.success || !is_interactive_tool(denial.data.tool_name ?? "")) return void 0;
3149
- const input = ASK_INPUT_SCHEMA.safeParse(denial.data.tool_input);
3150
- return input.success ? input.data : void 0;
3151
- }
3152
- function refused_ask_of(permission_denials) {
3153
- if (!Array.isArray(permission_denials)) return void 0;
3154
- const input = permission_denials.map((raw) => interactive_input(raw)).find((one) => one !== void 0);
3155
- const questions = input?.questions ?? [];
3156
- if (questions.length === 0) return void 0;
3157
- return questions.map((question) => render_question(question)).join(QUESTION_SEPARATOR);
3158
- }
3159
- var interactive_ask = { is_interactive_tool, refused_ask_of };
3160
-
3161
- // scripts/agent/claude-result-event.ts
3162
- var RESULT_EVENT_SCHEMA = z13.looseObject({
3163
- type: z13.literal("result"),
3164
- is_error: z13.unknown().optional(),
3165
- subtype: z13.unknown().optional(),
3166
- num_turns: z13.unknown().optional(),
3167
- permission_denials: z13.unknown().optional(),
3168
- result: z13.unknown().optional(),
3169
- session_id: z13.unknown().optional(),
3170
- usage: z13.unknown().optional()
3171
- });
3172
- var USAGE_SCHEMA = z13.looseObject({
3173
- input_tokens: z13.unknown().optional(),
3174
- cache_read_input_tokens: z13.unknown().optional(),
3175
- output_tokens: z13.unknown().optional()
3176
- });
3177
- function usable_reason(value) {
3178
- return typeof value === "string" && value.trim() !== "" ? value : void 0;
3179
- }
3180
- function numeric_value(value) {
3181
- return typeof value === "number" ? value : void 0;
3182
- }
3183
- function denial_count(value) {
3184
- return Array.isArray(value) ? value.length : 0;
3185
- }
3186
- function usage_of(value) {
3187
- const parsed = USAGE_SCHEMA.safeParse(value);
3188
- if (!parsed.success) return void 0;
3189
- const usage = {
3190
- input_tokens: numeric_value(parsed.data.input_tokens),
3191
- cached_input_tokens: numeric_value(parsed.data.cache_read_input_tokens),
3192
- output_tokens: numeric_value(parsed.data.output_tokens)
3193
- };
3194
- return Object.values(usage).some((count) => count !== void 0) ? usage : void 0;
3195
- }
3196
- function decode(value) {
3197
- const parsed = RESULT_EVENT_SCHEMA.safeParse(value);
3198
- if (!parsed.success) return void 0;
3199
- const is_error = parsed.data.is_error === true;
3200
- return {
3201
- is_error,
3202
- subtype: usable_reason(parsed.data.subtype),
3203
- num_turns: numeric_value(parsed.data.num_turns),
3204
- permission_denials: denial_count(parsed.data.permission_denials),
3205
- refused_ask: interactive_ask.refused_ask_of(parsed.data.permission_denials),
3206
- reason: is_error ? usable_reason(parsed.data.result) ?? usable_reason(parsed.data.subtype) : void 0,
3207
- session_id: usable_reason(parsed.data.session_id),
3208
- usage: usage_of(parsed.data.usage)
3209
- };
3210
- }
3211
- var claude_result_event = { decode };
3212
-
3213
- // scripts/agent/agent-event.ts
3214
- var TEXT_BLOCK_SCHEMA = z14.looseObject({ type: z14.literal("text"), text: z14.string() });
3215
- var CLAUDE_MESSAGE_SCHEMA = z14.looseObject({ content: z14.array(z14.unknown()).optional() });
3216
- var CLAUDE_INIT_SCHEMA = z14.looseObject({ type: z14.literal("system"), subtype: z14.literal("init") });
3217
- var CLAUDE_ASSISTANT_SCHEMA = z14.looseObject({
3218
- type: z14.literal("assistant"),
3219
- message: CLAUDE_MESSAGE_SCHEMA
3220
- });
3221
- var USAGE_SCHEMA2 = z14.looseObject({
3222
- input_tokens: z14.number().optional(),
3223
- cached_input_tokens: z14.number().optional(),
3224
- output_tokens: z14.number().optional()
3225
- });
3226
- var CODEX_START_SCHEMA = z14.looseObject({ type: z14.enum(["thread.started", "turn.started"]) });
3227
- var CODEX_PROGRESS_SCHEMA = z14.looseObject({
3228
- type: z14.enum(["item.started", "item.updated", "item.completed"]),
3229
- item: z14.looseObject({ type: z14.string(), text: z14.string().optional() }).optional()
3230
- });
3231
- var CODEX_COMPLETE_SCHEMA = z14.looseObject({
3232
- type: z14.literal("turn.completed"),
3233
- usage: USAGE_SCHEMA2.optional()
3234
- });
3235
- var CODEX_FAILURE_SCHEMA = z14.looseObject({
3236
- type: z14.enum(["turn.failed", "error"]),
3237
- error: z14.looseObject({ message: z14.string().optional() }).optional(),
3238
- message: z14.string().optional()
3239
- });
3240
- var EMPTY_STATE = {
3241
- provider: void 0,
3242
- launch: "pending",
3243
- progress: void 0,
3244
- result: "running",
3245
- reason: void 0,
3246
- usage: void 0
3247
- };
3248
- var LAUNCH_HEADER_PREFIX = "=== ";
3249
- var LAUNCH_HEADER_MARKER = " \xB7 started by process ";
3250
- function usable_text(value) {
3251
- return typeof value === "string" && value.trim() !== "" ? value : void 0;
3252
- }
3253
- function claude_progress(content) {
3254
- return content.map((block) => TEXT_BLOCK_SCHEMA.safeParse(block)).filter((parsed) => parsed.success).map((parsed) => parsed.data.text).findLast((text) => text.trim() !== "");
3255
- }
3256
- function claude_result(value, state) {
3257
- const result = claude_result_event.decode(value);
3258
- if (result === void 0) return void 0;
3259
- return {
3260
- ...state,
3261
- provider: "anthropic",
3262
- result: result.is_error ? "failed" : "completed",
3263
- reason: result.is_error ? result.reason ?? state.reason : state.reason,
3264
- usage: result.usage
3265
- };
3266
- }
3267
- function claude_assistant(value, state) {
3268
- const assistant = CLAUDE_ASSISTANT_SCHEMA.safeParse(value);
3269
- if (!assistant.success) return void 0;
3270
- const progress = claude_progress(assistant.data.message.content ?? []) ?? state.progress;
3271
- return { ...state, provider: "anthropic", progress };
3272
- }
3273
- function claude_terminal(value, state) {
3274
- return claude_result(value, state);
3275
- }
3276
- function claude_event(value, state) {
3277
- if (CLAUDE_INIT_SCHEMA.safeParse(value).success) {
3278
- return { ...state, provider: "anthropic", launch: "started" };
3279
- }
3280
- return claude_assistant(value, state) ?? claude_terminal(value, state);
3281
- }
3282
- function codex_progress(value, state) {
3283
- const parsed = CODEX_PROGRESS_SCHEMA.safeParse(value);
3284
- if (!parsed.success) return void 0;
3285
- const progress = usable_text(parsed.data.item?.text) ?? state.progress;
3286
- return { ...state, provider: "openai", progress };
3287
- }
3288
- function codex_completed(value, state) {
3289
- const completed = CODEX_COMPLETE_SCHEMA.safeParse(value);
3290
- if (!completed.success) return void 0;
3291
- return { ...state, provider: "openai", result: "completed", usage: completed.data.usage };
3292
- }
3293
- function codex_failed(value, state) {
3294
- const failed = CODEX_FAILURE_SCHEMA.safeParse(value);
3295
- if (!failed.success) return void 0;
3296
- const reason = usable_text(failed.data.error?.message) ?? usable_text(failed.data.message);
3297
- return { ...state, provider: "openai", result: "failed", reason: reason ?? state.reason };
3298
- }
3299
- function codex_terminal(value, state) {
3300
- return codex_completed(value, state) ?? codex_failed(value, state);
3301
- }
3302
- function codex_event(value, state) {
3303
- if (CODEX_START_SCHEMA.safeParse(value).success) {
3304
- return { ...state, provider: "openai", launch: "started" };
3305
- }
3306
- return codex_progress(value, state) ?? codex_terminal(value, state);
3307
- }
3308
- function normalized(value, state) {
3309
- return claude_event(value, state) ?? codex_event(value, state) ?? state;
3310
- }
3311
- function next_state(line, state) {
3312
- const is_header = line.startsWith(LAUNCH_HEADER_PREFIX) && line.includes(LAUNCH_HEADER_MARKER);
3313
- if (is_header) return EMPTY_STATE;
3314
- return normalized(json_value.parse_or_undefined(line), state);
3315
- }
3316
- function read(transcript) {
3317
- let state = EMPTY_STATE;
3318
- for (const line of transcript.split("\n")) state = next_state(line, state);
3319
- return state;
3320
- }
3321
- function describe(state) {
3322
- const progress = state.progress === void 0 ? "" : ` progress=${state.progress}`;
3323
- const reason = state.reason === void 0 ? "" : ` reason=${state.reason}`;
3324
- return `launch=${state.launch} result=${state.result}${progress}${reason}`;
3325
- }
3326
- var agent_event = { describe, read };
3327
-
3328
- // scripts/run/run-liveness.ts
3329
- var ALIVE_VERDICT = "alive";
3330
- var SETTLED_VERDICT = "settled";
3331
- var STOPPED_VERDICT = "stopped";
3332
- var UNDETERMINED_VERDICT = "undetermined";
3333
- var PROCESS_ALIVE = "alive";
3334
- var PROCESS_NONE = "none";
3335
- var PROCESS_UNKNOWN = "unknown";
3336
- var DEFAULT_SILENT_MINUTES = 30;
3337
- var DEFAULT_GAP_SECONDS = 5;
3338
- var MS_PER_MINUTE = 6e4;
3339
- var MS_PER_SECOND = 1e3;
3340
- var OPEN_STATE = "OPEN";
3341
- var STATE_FIELDS = "state,labels";
3342
- var REASONS = {
3343
- [ALIVE_VERDICT]: "The unit is still working: its output moved, or a process of the child is alive.",
3344
- [SETTLED_VERDICT]: "The child is closed, parked with `needs-decision`, or marked `already-done`, so there is nothing here to recover.",
3345
- [STOPPED_VERDICT]: "The output has been frozen past the silent window and no process of the child is alive in that checkout.",
3346
- [UNDETERMINED_VERDICT]: "A trace could not be read, so this says nothing about the unit. A trace that could not be read answers `undetermined`, never `stopped`."
3347
- };
3348
- var ALIVE_ADVICE = "Keep waiting on `pnpm josh lane:await`; do not touch the child.";
3349
- var SETTLED_ADVICE = "Read the child with `pnpm josh issue:state <N>` and take the branch its state says.";
3350
- var STOPPED_CLEAN_ADVICE = 'The unit ended \u2014 classify how before booking it. Run `pnpm josh run:merge <N> --output <path>` (add `--epic <E> --repo <owner/repo> --owner "$PPID"` for a named epic): it reads the child\'s exit record without waiting for the unit to return, re-dispatches a child that could not reach the API (counting the outage; a run of them trips the environment guard and stops the run), and parks an abandoned child with `needs-decision` against the consecutive-failure guard. The checkout is clean, so there is nothing to stash.';
3351
- var STOPPED_DIRTY_ADVICE = 'Stash the half-finished work with `git stash push -u -m "backlogrun: stopped unit for #<N>"` and record it on the Issue, then classify how the unit ended with `pnpm josh run:merge <N> --output <path>` (add `--epic <E> --repo <owner/repo> --owner "$PPID"` for a named epic): it re-dispatches an API-outage child (counting the outage; a run of them trips the environment guard) and parks an abandoned child with `needs-decision` against the consecutive-failure guard, without waiting for the unit to return.';
3352
- var UNDETERMINED_ADVICE = "Read the trace that failed and ask again. Where the process trace was given as `unknown`, leave `--process` out so the command reads it. Two of these in a row is a fault in the check itself rather than a slow unit: stop polling and report it.";
3353
- function is_output_moving(traces) {
3354
- return traces.is_output_frozen === false;
3355
- }
3356
- function is_agent_state_finished(state) {
3357
- return state?.result === "completed" || state?.result === "failed";
3358
- }
3359
- function is_agent_finished(traces) {
3360
- return is_agent_state_finished(traces.agent_state);
3361
- }
3362
- function definitive_verdict(traces) {
3363
- if (traces.is_child_settled === true) return SETTLED_VERDICT;
3364
- if (is_agent_finished(traces)) return STOPPED_VERDICT;
3365
- if (is_output_moving(traces)) return ALIVE_VERDICT;
3366
- return void 0;
3367
- }
3368
- function is_check_running(traces) {
3369
- return traces.process_trace === PROCESS_ALIVE;
3370
- }
3371
- function has_unreadable_trace(traces) {
3372
- return traces.is_child_settled === void 0 || traces.is_output_frozen === void 0 || traces.process_trace === PROCESS_UNKNOWN;
3373
- }
3374
- function to_verdict(traces) {
3375
- const definitive = definitive_verdict(traces);
3376
- if (definitive !== void 0) return definitive;
3377
- if (has_unreadable_trace(traces)) return UNDETERMINED_VERDICT;
3378
- return is_check_running(traces) ? ALIVE_VERDICT : STOPPED_VERDICT;
3379
- }
3380
- function to_advice(verdict, has_work_to_stash) {
3381
- if (verdict === ALIVE_VERDICT) return ALIVE_ADVICE;
3382
- if (verdict === SETTLED_VERDICT) return SETTLED_ADVICE;
3383
- if (verdict === UNDETERMINED_VERDICT) return UNDETERMINED_ADVICE;
3384
- return has_work_to_stash ? STOPPED_DIRTY_ADVICE : STOPPED_CLEAN_ADVICE;
3385
- }
3386
- function decide3(traces) {
3387
- const verdict = to_verdict(traces);
3388
- const has_work_to_stash = verdict === STOPPED_VERDICT && traces.is_tree_dirty;
3389
- return {
3390
- advice: to_advice(verdict, has_work_to_stash),
3391
- has_work_to_stash,
3392
- reason: traces.agent_state?.reason ?? REASONS[verdict],
3393
- verdict
3394
- };
3395
- }
3396
- function to_resolved_root(root) {
3397
- try {
3398
- return realpathSync(root);
3399
- } catch {
3400
- return root;
3401
- }
3402
- }
3403
- var ALLOWED_ROOTS = [
3404
- ...new Set(
3405
- [homedir(), tmpdir(), PLATFORM_TEMP_ROOT].flatMap((root) => [root, to_resolved_root(root)])
3406
- )
3407
- ];
3408
- function is_within(candidate, root) {
3409
- const relative = path3.relative(root, candidate);
3410
- return relative !== "" && !relative.startsWith("..") && !path3.isAbsolute(relative);
3411
- }
3412
- function to_safe_path(output_path) {
3413
- const normalized2 = path3.normalize(output_path);
3414
- if (!path3.isAbsolute(normalized2)) return void 0;
3415
- return ALLOWED_ROOTS.some((root) => is_within(normalized2, root)) ? normalized2 : void 0;
3416
- }
3417
- function sample_output(output_path) {
3418
- const safe_path = to_safe_path(output_path);
3419
- if (safe_path === void 0) return void 0;
3420
- const stats = statSync(safe_path, { throwIfNoEntry: false });
3421
- if (!stats?.isFile()) return void 0;
3422
- return { mtime_ms: stats.mtimeMs, size: stats.size };
3423
- }
3424
- function read_agent_state(output_path) {
3425
- const safe_path = to_safe_path(output_path);
3426
- if (safe_path === void 0) return void 0;
3427
- try {
3428
- const state = agent_event.read(readFileSync4(safe_path, "utf8"));
3429
- return state.provider === void 0 ? void 0 : state;
3430
- } catch {
3431
- return void 0;
3432
- }
3433
- }
3434
- function describe_agent_state(output_path) {
3435
- const state = read_agent_state(output_path);
3436
- return state === void 0 ? void 0 : `agent: ${state.provider ?? "unknown"} ${agent_event.describe(state)}`;
3437
- }
3438
- async function read_output_frozen(request) {
3439
- const first = sample_output(request.output_path);
3440
- if (first === void 0) return void 0;
3441
- if (request.now_ms - first.mtime_ms < request.silent_window_ms) return false;
3442
- await sleep3(request.gap_ms);
3443
- const second = sample_output(request.output_path);
3444
- if (second === void 0) return void 0;
3445
- return second.mtime_ms === first.mtime_ms && second.size === first.size;
3446
- }
3447
- function carries_label(labels, wanted) {
3448
- return labels.some((label) => label.toLowerCase() === wanted);
3449
- }
3450
- var SETTLED_LABELS = [NEEDS_DECISION_LABEL, ALREADY_DONE_LABEL];
3451
- function carries_settled_label(labels) {
3452
- return SETTLED_LABELS.some((label) => carries_label(labels, label));
3453
- }
3454
- async function read_child_settled(issue, repo) {
3455
- const json = await git_gh_issue_read.issue_view_json(issue, STATE_FIELDS, repo);
3456
- if (json === void 0) return void 0;
3457
- const state = issue_state.parse_issue_state(json);
3458
- if (state === void 0) return void 0;
3459
- return state.state !== OPEN_STATE || carries_settled_label(state.labels);
3460
- }
3461
- async function read_traces(request) {
3462
- const [is_initial_child_settled, is_output_frozen, is_tree_dirty] = await Promise.all([
3463
- read_child_settled(request.issue, request.repo),
3464
- read_output_frozen({
3465
- gap_ms: request.gap_ms ?? DEFAULT_GAP_SECONDS * MS_PER_SECOND,
3466
- now_ms: Date.now(),
3467
- output_path: request.output_path,
3468
- silent_window_ms: request.silent_window_ms ?? DEFAULT_SILENT_MINUTES * MS_PER_MINUTE
3469
- }),
3470
- run_hold.is_tree_dirty()
3471
- ]);
3472
- const agent_state = read_agent_state(request.output_path);
3473
- const is_latest_child_settled = is_agent_state_finished(agent_state) ? await read_child_settled(request.issue, request.repo) : void 0;
3474
- const is_child_settled = is_latest_child_settled ?? is_initial_child_settled;
3475
- return {
3476
- agent_state,
3477
- is_child_settled,
3478
- is_output_frozen,
3479
- is_tree_dirty,
3480
- process_trace: request.process_trace
3481
- };
3482
- }
3483
- async function check(request) {
3484
- issue_number_shape.require_issue_number(request.issue);
3485
- return decide3(await read_traces(request));
3486
- }
3487
- var run_liveness = {
3488
- check,
3489
- decide: decide3,
3490
- describe_agent_state,
3491
- read_child_settled,
3492
- read_output_frozen,
3493
- sample_output,
3494
- to_safe_path
3495
- };
3496
-
3497
- export {
3498
- bounded_pool,
3499
- git_gh_issue_read,
3500
- issue_watch_diff,
3501
- shell_segments,
3502
- bash_triggers,
3503
- tail_commands,
3504
- filing_cap,
3505
- CONTEXT_CUT_THRESHOLD,
3506
- cost_verdict,
3507
- cost_cli,
3508
- run_cut_handoff,
3509
- run_cut,
3510
- run_tail_rule,
3511
- lane_background,
3512
- interactive_ask,
3513
- IN_PROGRESS_LABEL,
3514
- NEEDS_DECISION_LABEL,
3515
- RUN_SOLO_LABEL,
3516
- RUN_LANE_LABEL,
3517
- ALREADY_DONE_LABEL,
3518
- has_any_label,
3519
- label_name_of,
3520
- has_label_name,
3521
- lane_handoff,
3522
- lane_park,
3523
- pre_gate_cut,
3524
- gh_spawn,
3525
- repo_party,
3526
- git_gh_repo,
3527
- git_gh_command,
3528
- issue_state,
3529
- PROCESS_ALIVE,
3530
- PROCESS_NONE,
3531
- PROCESS_UNKNOWN,
3532
- run_liveness
3533
- };