@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,4838 +0,0 @@
1
- import {
2
- ENV_FILE_NAME,
3
- cost_transcript,
4
- json_value,
5
- lane_paths,
6
- pr_raw_schema,
7
- process_identity,
8
- process_owner_schema,
9
- run_carry,
10
- time_instant
11
- } from "./chunk-APUO6U4J.js";
12
- import {
13
- PLATFORM_TEMP_ROOT,
14
- PROBE_TIMEOUT_MS,
15
- stamp_file
16
- } from "./chunk-DGT54IH5.js";
17
-
18
- // scripts/cost-runtime/cost-blocks.ts
19
- import { z } from "zod";
20
- var CONTENT_ITEM_SCHEMA = z.object({ text: z.string().nullish() });
21
- var RESULT_CONTENT_SCHEMA = z.union([z.string(), z.array(CONTENT_ITEM_SCHEMA)]);
22
- var BLOCK_SCHEMA = z.object({
23
- type: z.string().nullish(),
24
- text: z.string().nullish(),
25
- name: z.string().nullish(),
26
- input: z.unknown().nullish(),
27
- content: RESULT_CONTENT_SCHEMA.nullish()
28
- });
29
- var LINE_CONTENT_SCHEMA = z.union([z.string(), z.array(BLOCK_SCHEMA)]);
30
- var MESSAGE_SCHEMA = z.object({ content: LINE_CONTENT_SCHEMA.nullish() });
31
- var CONTENT_LINE_SCHEMA = z.object({ type: z.string(), message: MESSAGE_SCHEMA.nullish() });
32
- var TEXT_TYPE = "text";
33
- var TOOL_USE_TYPE = "tool_use";
34
- var TOOL_RESULT_TYPE = "tool_result";
35
- var BASH_TOOL = "Bash";
36
- var COMMAND_KEY = "command";
37
- function json_of(value) {
38
- return value === void 0 || value === null ? "" : JSON.stringify(value);
39
- }
40
- function split_bash_input(input) {
41
- if (!json_value.is_record(input)) return { command: "", rest: json_of(input) };
42
- const command = input[COMMAND_KEY];
43
- const rest = Object.entries(input).filter(([key]) => key !== COMMAND_KEY);
44
- return {
45
- command: typeof command === "string" ? command : "",
46
- rest: json_of(Object.fromEntries(rest))
47
- };
48
- }
49
- function to_tool_use(block) {
50
- const tool_name = block.name ?? "";
51
- const is_bash = tool_name === BASH_TOOL;
52
- const { command, rest } = is_bash ? split_bash_input(block.input) : { command: "", rest: json_of(block.input) };
53
- return { type: TOOL_USE_TYPE, tool_name, command, text: rest };
54
- }
55
- function result_text(content) {
56
- if (typeof content === "string") return content;
57
- return content.map((item) => item.text ?? "").join("");
58
- }
59
- function to_plain_block(block) {
60
- const base = { type: block.type ?? "", tool_name: "", command: "" };
61
- const text = block.type === TOOL_RESULT_TYPE ? result_text(block.content ?? "") : block.text ?? "";
62
- return { ...base, text };
63
- }
64
- function to_block(block) {
65
- return block.type === TOOL_USE_TYPE ? to_tool_use(block) : to_plain_block(block);
66
- }
67
- function to_blocks(content) {
68
- if (typeof content === "string") {
69
- return [{ type: TEXT_TYPE, tool_name: "", command: "", text: content }];
70
- }
71
- return content.map((block) => to_block(block));
72
- }
73
- function content_of(line) {
74
- const parsed = CONTENT_LINE_SCHEMA.safeParse(json_value.parse_or_undefined(line));
75
- return parsed.success ? parsed.data.message?.content ?? void 0 : void 0;
76
- }
77
- function parse_line(line) {
78
- const content = content_of(line);
79
- return content === void 0 ? [] : to_blocks(content);
80
- }
81
- function parse_content(text) {
82
- return text.split("\n").flatMap((line) => parse_line(line));
83
- }
84
- var cost_blocks = {
85
- BASH_TOOL,
86
- TEXT_TYPE,
87
- TOOL_USE_TYPE,
88
- TOOL_RESULT_TYPE,
89
- parse_line,
90
- parse_content
91
- };
92
-
93
- // scripts/time-runtime/time-phase-names.ts
94
- var GATE_PHASE = "gate";
95
- var PR_PHASE = "pr";
96
- var MERGE_PHASE = "merge";
97
- var GATE_COMMAND = "josh gate";
98
- var COMMAND_PHASES = /* @__PURE__ */ new Map([
99
- [GATE_COMMAND, GATE_PHASE],
100
- ["josh git", PR_PHASE],
101
- ["josh pr", PR_PHASE],
102
- ["josh followup", MERGE_PHASE]
103
- ]);
104
-
105
- // scripts/gate/core-budget.ts
106
- import { randomUUID } from "node:crypto";
107
- import { readdirSync as readdirSync2 } from "node:fs";
108
- import { availableParallelism as availableParallelism3 } from "node:os";
109
- import path3 from "node:path";
110
-
111
- // scripts/test/unit-worker-share.ts
112
- import { readdirSync } from "node:fs";
113
- import { availableParallelism } from "node:os";
114
- import path from "node:path";
115
- var RUN_PREFIX = "josh-unit-running-";
116
- var WORKER_FLAG = "--maxWorkers";
117
- var WORKER_FLAGS = [WORKER_FLAG, "--max-workers"];
118
- var MIN_WORKERS = 1;
119
- var SOLO_RUNS = 1;
120
- function marker_path(pid = process.pid) {
121
- return stamp_file.stamp_path(RUN_PREFIX, String(pid));
122
- }
123
- function is_running(marker) {
124
- return process_identity.is_same_process(marker.pid, marker.process_start) !== false;
125
- }
126
- function read_marker(source) {
127
- const raw = stamp_file.read_stamp_text(source);
128
- if (raw === void 0) return void 0;
129
- const parsed = process_owner_schema.safeParse(json_value.parse_or_undefined(raw));
130
- return parsed.success ? parsed.data : void 0;
131
- }
132
- function marker_files(directory = PLATFORM_TEMP_ROOT) {
133
- try {
134
- return readdirSync(directory).filter((name) => name.startsWith(RUN_PREFIX));
135
- } catch {
136
- return [];
137
- }
138
- }
139
- function sweep_marker(source) {
140
- try {
141
- stamp_file.remove_stamp(source);
142
- } catch {
143
- }
144
- }
145
- function is_marker_live(source) {
146
- const marker = read_marker(source);
147
- if (marker === void 0) return false;
148
- if (is_running(marker)) return true;
149
- sweep_marker(source);
150
- return false;
151
- }
152
- function live_run_count(directory = PLATFORM_TEMP_ROOT) {
153
- return marker_files(directory).filter((name) => is_marker_live(path.join(directory, name))).length;
154
- }
155
- var NESTED_KEY = "JOSH_UNIT_RUN_MARKED";
156
- var NESTED_VALUE = "1";
157
- function is_nested_run() {
158
- return process.env[NESTED_KEY] === NESTED_VALUE;
159
- }
160
- function resolve_unit_workers(available_cores, runs2) {
161
- if (runs2 <= SOLO_RUNS) return void 0;
162
- return Math.max(MIN_WORKERS, Math.floor(available_cores / runs2));
163
- }
164
- function cap_to_free(workers, free_cores, available_cores) {
165
- if (free_cores === void 0 || free_cores >= (workers ?? available_cores)) return workers;
166
- return Math.max(MIN_WORKERS, Math.floor(free_cores));
167
- }
168
- function current_share(available_cores = availableParallelism(), live_runs = live_run_count(), free_cores) {
169
- const own_run2 = is_nested_run() ? 0 : SOLO_RUNS;
170
- const share = resolve_unit_workers(available_cores, live_runs + own_run2);
171
- return cap_to_free(share, free_cores, available_cores);
172
- }
173
- function is_worker_flag(argument) {
174
- return WORKER_FLAGS.some((flag) => argument === flag || argument.startsWith(`${flag}=`));
175
- }
176
- function has_worker_flag(vitest_arguments) {
177
- return vitest_arguments.some((argument) => is_worker_flag(argument));
178
- }
179
- function worker_arguments(vitest_arguments, share) {
180
- if (share === void 0 || has_worker_flag(vitest_arguments)) return [];
181
- return [`${WORKER_FLAG}=${String(share)}`];
182
- }
183
- function mark_run_started(target2) {
184
- try {
185
- stamp_file.write_stamp(target2, process_identity.own_fields());
186
- } catch {
187
- }
188
- }
189
- async function with_run_marker(run) {
190
- if (is_nested_run()) return await run();
191
- const target2 = marker_path();
192
- mark_run_started(target2);
193
- process.env[NESTED_KEY] = NESTED_VALUE;
194
- try {
195
- return await run();
196
- } finally {
197
- process.env[NESTED_KEY] = "";
198
- stamp_file.remove_stamp(target2);
199
- }
200
- }
201
- var unit_worker_share = {
202
- MIN_WORKERS,
203
- NESTED_KEY,
204
- NESTED_VALUE,
205
- RUN_PREFIX,
206
- SOLO_RUNS,
207
- cap_to_free,
208
- current_share,
209
- has_worker_flag,
210
- is_nested_run,
211
- live_run_count,
212
- marker_path,
213
- read_marker,
214
- resolve_unit_workers,
215
- with_run_marker,
216
- worker_arguments
217
- };
218
-
219
- // scripts/gate/core-budget.ts
220
- import { z as z2 } from "zod";
221
-
222
- // scripts/gate/core-admission.ts
223
- var MS_PER_SECOND = 1e3;
224
- var RAMP_UP_MS = 3e4;
225
- function compare_claim(left, right) {
226
- const by_time = left.reservation.claimed_at - right.reservation.claimed_at;
227
- return by_time === 0 ? left.key.localeCompare(right.key) : by_time;
228
- }
229
- function add_load(totals, reservation) {
230
- totals.cores += reservation.weight;
231
- totals.memory_mb += reservation.memory_mb ?? 0;
232
- }
233
- function exceeds(totals, budget) {
234
- return totals.cores > budget.cores || totals.memory_mb > budget.memory_mb;
235
- }
236
- function admitted_keys(reservations, budget, memory_budget = Infinity) {
237
- const limit = { cores: budget, memory_mb: memory_budget };
238
- const totals = { cores: 0, memory_mb: 0 };
239
- const admitted = /* @__PURE__ */ new Set();
240
- for (const [index, entry] of reservations.toSorted(compare_claim).entries()) {
241
- add_load(totals, entry.reservation);
242
- if (index !== 0 && exceeds(totals, limit)) break;
243
- admitted.add(entry.key);
244
- }
245
- return admitted;
246
- }
247
- function is_admitted(key, reservations, budget) {
248
- return admitted_keys(reservations, budget.cores, budget.memory_mb).has(key);
249
- }
250
- function sum_load(reservations) {
251
- const load = { cores: 0, memory_mb: 0 };
252
- for (const entry of reservations) add_load(load, entry.reservation);
253
- return load;
254
- }
255
- function is_ramped(reservation, now) {
256
- const { admitted_at } = reservation;
257
- return admitted_at !== void 0 && now - admitted_at >= RAMP_UP_MS;
258
- }
259
- function ledger_load(reservations, now) {
260
- const admitted = reservations.filter((entry) => entry.reservation.admitted_at !== void 0);
261
- const ramped = admitted.filter((entry) => is_ramped(entry.reservation, now));
262
- return { cores: sum_load(admitted).cores, memory_mb: sum_load(ramped).memory_mb };
263
- }
264
- function total_weight(reservations) {
265
- return sum_load(reservations).cores;
266
- }
267
- function admitted_load(reservations, budget) {
268
- const admitted = admitted_keys(reservations, budget);
269
- return total_weight(reservations.filter((entry) => admitted.has(entry.key)));
270
- }
271
- function describe_memory(ledger, budget) {
272
- if (!Number.isFinite(budget.memory_mb)) return "";
273
- return ` and ${String(Math.round(ledger.memory_mb))} MB of memory against ${String(Math.round(budget.memory_mb))} MB`;
274
- }
275
- function describe_overflow(admission) {
276
- const { overflow } = admission;
277
- if (overflow === void 0) return void 0;
278
- const { ledger, budget } = overflow;
279
- const waited = String(Math.round(overflow.waited_ms / MS_PER_SECOND));
280
- const cores = `the ledger held ${String(ledger.cores)} cores against a budget of ${String(budget.cores)}`;
281
- return `started past the core budget after ${waited}s \u2014 ${cores}${describe_memory(ledger, budget)}`;
282
- }
283
- var core_admission = {
284
- RAMP_UP_MS,
285
- admitted_keys,
286
- admitted_load,
287
- describe_overflow,
288
- is_admitted,
289
- ledger_load,
290
- sum_load
291
- };
292
-
293
- // scripts/gate/core-wait.ts
294
- import path2 from "node:path";
295
- var WAIT_REASONS = ["cores", "memory", "pressure"];
296
- var REASON_TEXT = {
297
- cores: "not enough free cores",
298
- memory: "not enough free memory",
299
- pressure: "memory under pressure"
300
- };
301
- function wait_reason(key, reservations, budget) {
302
- const cores_only = { cores: budget.cores, memory_mb: Infinity };
303
- if (!core_admission.is_admitted(key, reservations, cores_only)) return "cores";
304
- return budget.memory_pressured === true ? "pressure" : "memory";
305
- }
306
- function wait_line(command, reason) {
307
- return `\u23F3 ${command ?? "a step"} waits for the core budget \u2014 ${REASON_TEXT[reason]}`;
308
- }
309
- function lanes_root_of(checkout) {
310
- if (lane_paths.lane_issue_of(checkout) === void 0) return lane_paths.lane_root(checkout);
311
- return path2.dirname(path2.resolve(checkout));
312
- }
313
- function where_of(checkout) {
314
- return { checkout, lane: lane_paths.lane_issue_of(checkout), lanes_root: lanes_root_of(checkout) };
315
- }
316
- function place_of(marker, home_root) {
317
- const { checkout, lane, lanes_root } = marker;
318
- if (checkout === void 0 || lanes_root === void 0 || lanes_root === home_root) {
319
- return { lane, elsewhere: void 0 };
320
- }
321
- const name = lane === void 0 ? path2.basename(checkout) : `${path2.basename(lanes_root)}/${lane}`;
322
- return { lane: void 0, elsewhere: name };
323
- }
324
- function wait_of(marker, now, home_root) {
325
- const { command, wait_reason: reason } = marker;
326
- if (reason === void 0 || marker.admitted_at !== void 0) return [];
327
- return [{ command, ...place_of(marker, home_root), waited_ms: now - marker.claimed_at, reason }];
328
- }
329
- function waits_of(entries, now, home) {
330
- const home_root = lanes_root_of(home);
331
- return entries.flatMap((entry) => wait_of(entry.reservation, now, home_root)).toSorted((left, right) => right.waited_ms - left.waited_ms);
332
- }
333
- var core_wait = {
334
- REASON_TEXT,
335
- WAIT_REASONS,
336
- wait_line,
337
- wait_reason,
338
- waits_of,
339
- where_of
340
- };
341
-
342
- // scripts/gate/held-mark.ts
343
- var HELD_KEY = "JOSH_CORE_RESERVED";
344
- var HELD_VALUE = "1";
345
- var HELD_RESERVATION_KEY = "JOSH_CORE_RESERVATION";
346
- function is_held() {
347
- return process.env[HELD_KEY] === HELD_VALUE;
348
- }
349
- function held_reservation() {
350
- const key = process.env[HELD_RESERVATION_KEY] ?? "";
351
- return key === "" ? void 0 : key;
352
- }
353
- function set_held_mark(value, reservation) {
354
- process.env[HELD_KEY] = value;
355
- process.env[HELD_RESERVATION_KEY] = reservation;
356
- }
357
- async function with_held_mark(run, reservation = "") {
358
- const previous = process.env[HELD_KEY] ?? "";
359
- const previous_reservation = process.env[HELD_RESERVATION_KEY] ?? "";
360
- set_held_mark(HELD_VALUE, reservation);
361
- try {
362
- return await run();
363
- } finally {
364
- set_held_mark(previous, previous_reservation);
365
- }
366
- }
367
- var held_mark = {
368
- HELD_KEY,
369
- HELD_RESERVATION_KEY,
370
- HELD_VALUE,
371
- held_reservation,
372
- is_held,
373
- with_held_mark
374
- };
375
-
376
- // scripts/gate/machine-capacity.ts
377
- import { readFile } from "node:fs/promises";
378
- import { availableParallelism as availableParallelism2, cpus, totalmem } from "node:os";
379
- import { execa } from "execa";
380
- var SAMPLE_WINDOW_MS = 250;
381
- var BASELINE_CORES = 2;
382
- var BYTES_PER_MB = 1048576;
383
- var KB_PER_MB = 1024;
384
- var PERCENT = 100;
385
- var MEMINFO_PATH = "/proc/meminfo";
386
- var VMSTAT_PATH = "/proc/vmstat";
387
- var LINUX_AVAILABLE = /^MemAvailable:\s+(?<kb>\d+) kB/mu;
388
- var LINUX_SWAP_IN = /^pswpin (?<pages>\d+)$/mu;
389
- var LINUX_SWAP_OUT = /^pswpout (?<pages>\d+)$/mu;
390
- var PAGE_SIZE_ARGUMENTS = ["PAGESIZE"];
391
- var LEVEL_NAME = "kern.memorystatus_level";
392
- var SWAP_IN_NAME = "vm.compressor.swapper.swapins_total";
393
- var SWAP_OUT_NAME = "vm.compressor.swapper.swapouts_total";
394
- var COMPRESSED_NAME = "vm.compressor_input_bytes";
395
- var PAGE_SIZE_NAME = "hw.pagesize";
396
- var PRESSURE_NAME = "kern.memorystatus_vm_pressure_level";
397
- var PRESSURE_WARNING = 2;
398
- var SWAP_PRESSURE_MB = 16;
399
- var COMPRESSION_PRESSURE_MB = 64;
400
- var SYSCTL_ARGUMENTS = [
401
- LEVEL_NAME,
402
- SWAP_IN_NAME,
403
- SWAP_OUT_NAME,
404
- COMPRESSED_NAME,
405
- PAGE_SIZE_NAME,
406
- PRESSURE_NAME
407
- ];
408
- var SYSCTL_LINE = /^(?<name>[\w.]+): (?<value>\d+)$/gmu;
409
- function cpu_times() {
410
- let busy = 0;
411
- let idle = 0;
412
- for (const { times } of cpus()) {
413
- busy += times.user + times.nice + times.sys + times.irq;
414
- idle += times.idle;
415
- }
416
- return { busy, total: busy + idle };
417
- }
418
- function busy_share_between(before, after) {
419
- const total = after.total - before.total;
420
- if (total <= 0) return void 0;
421
- return (after.busy - before.busy) / total;
422
- }
423
- function busy_cores_between(before, after, cores) {
424
- const share = busy_share_between(before, after);
425
- return share === void 0 ? void 0 : share * cores;
426
- }
427
- function sysctl_values(output) {
428
- const values = [...output.matchAll(SYSCTL_LINE)].map(
429
- (match) => [match.groups?.["name"] ?? "", Number(match.groups?.["value"])]
430
- );
431
- return new Map(values);
432
- }
433
- function swapped_pages(pages_in, pages_out) {
434
- return pages_in === void 0 || pages_out === void 0 ? void 0 : pages_in + pages_out;
435
- }
436
- function mb_of(units, unit_bytes) {
437
- if (units === void 0 || unit_bytes === void 0) return void 0;
438
- return units * unit_bytes / BYTES_PER_MB;
439
- }
440
- function swapped_between(from, to) {
441
- if (from === void 0 || to === void 0) return void 0;
442
- return Math.max(0, to - from);
443
- }
444
- function parse_darwin_memory(output, total_bytes) {
445
- const values = sysctl_values(output);
446
- const level = values.get(LEVEL_NAME);
447
- return {
448
- available_mb: level === void 0 ? void 0 : level / PERCENT * (total_bytes / BYTES_PER_MB),
449
- swapped_mb: mb_of(
450
- swapped_pages(values.get(SWAP_IN_NAME), values.get(SWAP_OUT_NAME)),
451
- values.get(PAGE_SIZE_NAME)
452
- ),
453
- pressure_level: values.get(PRESSURE_NAME),
454
- compressed_mb: mb_of(values.get(COMPRESSED_NAME), 1)
455
- };
456
- }
457
- function parse_linux_available(meminfo) {
458
- const kb = LINUX_AVAILABLE.exec(meminfo)?.groups?.["kb"];
459
- return kb === void 0 ? void 0 : Number(kb) / KB_PER_MB;
460
- }
461
- function pages_of(pattern, vmstat) {
462
- const pages = pattern.exec(vmstat)?.groups?.["pages"];
463
- return pages === void 0 ? void 0 : Number(pages);
464
- }
465
- function parse_linux_swapped(vmstat, page_bytes) {
466
- const pages = swapped_pages(pages_of(LINUX_SWAP_IN, vmstat), pages_of(LINUX_SWAP_OUT, vmstat));
467
- return mb_of(pages, page_bytes);
468
- }
469
- async function settled(read) {
470
- try {
471
- return await read();
472
- } catch {
473
- return void 0;
474
- }
475
- }
476
- async function read_darwin_memory() {
477
- const { stdout } = await execa("sysctl", SYSCTL_ARGUMENTS, {
478
- reject: false,
479
- timeout: PROBE_TIMEOUT_MS
480
- });
481
- return parse_darwin_memory(stdout, totalmem());
482
- }
483
- async function read_page_size() {
484
- const { stdout } = await execa("getconf", PAGE_SIZE_ARGUMENTS, { timeout: PROBE_TIMEOUT_MS });
485
- return stdout;
486
- }
487
- async function read_linux_memory() {
488
- const [meminfo, vmstat, page_size] = await Promise.all([
489
- settled(async () => await readFile(MEMINFO_PATH, "utf8")),
490
- settled(async () => await readFile(VMSTAT_PATH, "utf8")),
491
- settled(read_page_size)
492
- ]);
493
- const page_bytes = page_size === void 0 ? void 0 : Number(page_size);
494
- return {
495
- available_mb: meminfo === void 0 ? void 0 : parse_linux_available(meminfo),
496
- swapped_mb: vmstat === void 0 || page_bytes === void 0 ? void 0 : parse_linux_swapped(vmstat, page_bytes),
497
- pressure_level: void 0
498
- };
499
- }
500
- var UNREAD_MEMORY = {
501
- available_mb: void 0,
502
- swapped_mb: void 0,
503
- pressure_level: void 0
504
- };
505
- async function read_memory() {
506
- if (process.platform === "darwin") return await settled(read_darwin_memory) ?? UNREAD_MEMORY;
507
- return process.platform === "linux" ? await read_linux_memory() : UNREAD_MEMORY;
508
- }
509
- function is_unquoted() {
510
- return cpus().length > 0 && cpus().length === availableParallelism2();
511
- }
512
- async function default_sleep(ms) {
513
- await new Promise((resolve) => {
514
- setTimeout(resolve, ms);
515
- });
516
- }
517
- function moved_over(from, to, limit) {
518
- return (swapped_between(from, to) ?? 0) > limit;
519
- }
520
- function is_pressured(before, after) {
521
- return (after.pressure_level ?? 0) >= PRESSURE_WARNING || moved_over(before.swapped_mb, after.swapped_mb, SWAP_PRESSURE_MB) || moved_over(before.compressed_mb, after.compressed_mb, COMPRESSION_PRESSURE_MB);
522
- }
523
- function pressured_available(before, after) {
524
- if (after.available_mb === void 0) return void 0;
525
- return is_pressured(before, after) ? 0 : after.available_mb;
526
- }
527
- async function read_machine(sleep = default_sleep) {
528
- const before = cpu_times();
529
- const [memory_before] = await Promise.all([read_memory(), sleep(SAMPLE_WINDOW_MS)]);
530
- const memory_after = await read_memory();
531
- const busy_cores = is_unquoted() ? busy_cores_between(before, cpu_times(), cpus().length) : void 0;
532
- return {
533
- busy_cores,
534
- available_mb: pressured_available(memory_before, memory_after),
535
- memory_pressured: is_pressured(memory_before, memory_after)
536
- };
537
- }
538
- async function read_sample() {
539
- return { cpu: cpu_times(), memory: await read_memory(), total_mb: totalmem() / BYTES_PER_MB };
540
- }
541
- function external_cores(busy_cores, ledger_cores) {
542
- if (busy_cores === void 0) return 0;
543
- return Math.floor(Math.max(0, busy_cores - ledger_cores - BASELINE_CORES));
544
- }
545
- function machine_budget(cores, reading, ledger) {
546
- return {
547
- cores: cores - external_cores(reading.busy_cores, ledger.cores),
548
- memory_mb: reading.available_mb === void 0 ? Infinity : reading.available_mb + ledger.memory_mb,
549
- memory_pressured: reading.memory_pressured
550
- };
551
- }
552
- var machine_capacity = {
553
- BASELINE_CORES,
554
- busy_cores_between,
555
- busy_share_between,
556
- COMPRESSION_PRESSURE_MB,
557
- external_cores,
558
- machine_budget,
559
- parse_darwin_memory,
560
- parse_linux_available,
561
- parse_linux_swapped,
562
- pressured_available,
563
- read_machine,
564
- read_memory,
565
- read_sample,
566
- SWAP_PRESSURE_MB,
567
- swapped_between
568
- };
569
-
570
- // scripts/gate/core-budget.ts
571
- var RESERVED_PREFIX = "josh-core-reserved-";
572
- var RESERVED_SUFFIX = ".json";
573
- var POLL_INTERVAL_MS = 50;
574
- var WAIT_CAP_MS = 12e4;
575
- var MIN_BUDGET = 1;
576
- var CORE_WEIGHTS = {
577
- lint: 2,
578
- type_check: 1,
579
- spell_check: 1,
580
- eslint_scan: 1,
581
- format: 1,
582
- retrospective: 1,
583
- install: 1,
584
- e2e: 2
585
- };
586
- var MEMORY_MB = {
587
- lint: 2400,
588
- type_check: 1300,
589
- spell_check: 350,
590
- eslint_scan: 2400,
591
- unit_worker: 350,
592
- format: 300,
593
- retrospective: 900,
594
- install: 100
595
- };
596
- var reservation_schema = process_owner_schema.extend({
597
- weight: z2.number(),
598
- claimed_at: z2.number(),
599
- memory_mb: z2.number().optional(),
600
- admitted_at: z2.number().optional(),
601
- command: z2.string().optional(),
602
- checkout: z2.string().optional(),
603
- lane: z2.string().optional(),
604
- lanes_root: z2.string().optional(),
605
- wait_reason: z2.enum(core_wait.WAIT_REASONS).optional()
606
- });
607
- function marker_name(key) {
608
- return `${RESERVED_PREFIX}${key}${RESERVED_SUFFIX}`;
609
- }
610
- function is_running2(reservation) {
611
- return process_identity.is_same_process(reservation.pid, reservation.process_start) !== false;
612
- }
613
- function read_reservation(source) {
614
- const raw = stamp_file.read_stamp_text(source);
615
- if (raw === void 0) return void 0;
616
- return json_value.parse_with(raw, reservation_schema);
617
- }
618
- function sweep_marker2(source) {
619
- try {
620
- stamp_file.remove_stamp(source);
621
- } catch {
622
- }
623
- }
624
- function live_reservation(source) {
625
- const reservation = read_reservation(source);
626
- if (reservation === void 0) return void 0;
627
- if (is_running2(reservation)) return reservation;
628
- sweep_marker2(source);
629
- return void 0;
630
- }
631
- function marker_files2(directory) {
632
- try {
633
- return readdirSync2(directory).filter(
634
- (name) => name.startsWith(RESERVED_PREFIX) && name.endsWith(RESERVED_SUFFIX)
635
- );
636
- } catch {
637
- return [];
638
- }
639
- }
640
- function live_reservations(directory = PLATFORM_TEMP_ROOT) {
641
- return marker_files2(directory).flatMap((name) => {
642
- const reservation = live_reservation(path3.join(directory, name));
643
- return reservation === void 0 ? [] : { key: name, reservation };
644
- });
645
- }
646
- function normalize_budget(budget) {
647
- return Number.isFinite(budget) ? Math.max(MIN_BUDGET, Math.floor(budget)) : MIN_BUDGET;
648
- }
649
- async function default_sleep2(ms) {
650
- await new Promise((resolve) => {
651
- setTimeout(resolve, ms);
652
- });
653
- }
654
- function write_reservation(target2, fields) {
655
- stamp_file.replace_stamp(target2, { ...process_identity.own_fields(), ...fields });
656
- }
657
- function report_wait(line) {
658
- process.stderr.write(`${line}
659
- `);
660
- }
661
- function resolve_timing(options) {
662
- return {
663
- now: options.now ?? Date.now,
664
- sleep: options.sleep ?? default_sleep2,
665
- poll_interval_ms: options.poll_interval_ms ?? POLL_INTERVAL_MS,
666
- wait_cap_ms: options.wait_cap_ms ?? WAIT_CAP_MS
667
- };
668
- }
669
- async function current_budget(context, reservations) {
670
- if (reservations.length <= 1) return { cores: context.budget, memory_mb: Infinity };
671
- const reading = await context.read_machine();
672
- const ledger = core_admission.ledger_load(reservations, context.now());
673
- const budget = machine_capacity.machine_budget(context.budget, reading, ledger);
674
- return { ...budget, cores: normalize_budget(budget.cores) };
675
- }
676
- function admit(context, overflow) {
677
- write_reservation(context.target, { ...context.fields, admitted_at: context.now() });
678
- return { overflow };
679
- }
680
- function overflow_of(context, reservations, budget) {
681
- return {
682
- waited_ms: context.now() - context.fields.claimed_at,
683
- ledger: core_admission.sum_load(reservations),
684
- budget
685
- };
686
- }
687
- function mark_waiting(context, reason) {
688
- const previous = context.fields.wait_reason;
689
- if (previous === reason) return;
690
- context.fields = { ...context.fields, wait_reason: reason };
691
- write_reservation(context.target, context.fields);
692
- if (previous === void 0) context.report(core_wait.wait_line(context.fields.command, reason));
693
- }
694
- async function poll_admission(context) {
695
- const reservations = live_reservations(context.directory);
696
- const budget = await current_budget(context, reservations);
697
- if (core_admission.is_admitted(context.key, reservations, budget)) return admit(context);
698
- if (context.now() >= context.deadline) {
699
- return admit(context, overflow_of(context, reservations, budget));
700
- }
701
- mark_waiting(context, core_wait.wait_reason(context.key, reservations, budget));
702
- return void 0;
703
- }
704
- async function await_admission(context) {
705
- let admission = await poll_admission(context);
706
- while (admission === void 0) {
707
- await context.sleep(context.poll_interval_ms);
708
- admission = await poll_admission(context);
709
- }
710
- return admission;
711
- }
712
- function resolve_ports(options) {
713
- return {
714
- read_machine: options.read_machine ?? machine_capacity.read_machine,
715
- report: options.report ?? report_wait
716
- };
717
- }
718
- function claim_fields(weight, claimed_at, options) {
719
- const { memory_mb, command } = options;
720
- return { weight, claimed_at, memory_mb, command, ...core_wait.where_of(process.cwd()) };
721
- }
722
- async function reserve(weight, options = {}) {
723
- const timing = resolve_timing(options);
724
- const directory = options.directory ?? PLATFORM_TEMP_ROOT;
725
- const claimed_at = timing.now();
726
- const name = marker_name(randomUUID());
727
- const target2 = path3.join(directory, name);
728
- const fields = claim_fields(weight, claimed_at, options);
729
- write_reservation(target2, fields);
730
- const admission = await await_admission({
731
- ...timing,
732
- key: name,
733
- target: target2,
734
- directory,
735
- budget: normalize_budget(options.budget ?? availableParallelism3()),
736
- deadline: claimed_at + timing.wait_cap_ms,
737
- fields,
738
- ...resolve_ports(options)
739
- });
740
- return { target: target2, admission };
741
- }
742
- function budget_waits(directory = PLATFORM_TEMP_ROOT, now = Date.now(), home = process.cwd()) {
743
- return core_wait.waits_of(live_reservations(directory), now, home);
744
- }
745
- function release(handle) {
746
- sweep_marker2(handle.target);
747
- }
748
- async function with_core_reservation(weight, run, options = {}) {
749
- const handle = await reserve(weight, options);
750
- try {
751
- return await run(handle.admission, path3.basename(handle.target));
752
- } finally {
753
- release(handle);
754
- }
755
- }
756
- async function with_command_reservation(weight, run, options = {}) {
757
- if (held_mark.is_held() || unit_worker_share.is_nested_run()) return await run();
758
- return await with_core_reservation(
759
- weight,
760
- async (_admission, key) => await held_mark.with_held_mark(run, key),
761
- options
762
- );
763
- }
764
- var core_budget = {
765
- CORE_WEIGHTS,
766
- HELD_KEY: held_mark.HELD_KEY,
767
- HELD_VALUE: held_mark.HELD_VALUE,
768
- MEMORY_MB,
769
- RESERVED_PREFIX,
770
- admitted_keys: core_admission.admitted_keys,
771
- admitted_load: core_admission.admitted_load,
772
- budget_waits,
773
- describe_overflow: core_admission.describe_overflow,
774
- is_held: held_mark.is_held,
775
- live_reservations,
776
- release,
777
- reserve,
778
- with_command_reservation,
779
- with_core_reservation,
780
- with_held_mark: held_mark.with_held_mark
781
- };
782
-
783
- // scripts/josh/josh-command-types.ts
784
- var OPTIONAL_ENV_FILE_FLAGS = [`--env-file-if-exists=${ENV_FILE_NAME}`];
785
- var GATE_COMMAND2 = "gate";
786
- var ESLINT_CACHE_FILE = ".eslintcache";
787
- var TS_BUILD_INFO_FILE = ".tsbuildinfo";
788
- var CSPELL_CACHE_FILE = ".cspellcache";
789
- var ESLINT_EDIT_CACHE_FILE = ".eslintcache.edit";
790
- var ESLINT_RELATED_CACHE_FILE = ".eslintcache.related";
791
- var PRETTIER_CACHE_FILE = ".prettiercache";
792
- var PRETTIER_RELATED_CACHE_FILE = ".prettiercache.related";
793
- var CSPELL_COMMIT_CACHE_FILE = ".cspellcache.commit";
794
- var ESLINT_COMMIT_CACHE_FILE = ".eslintcache.commit";
795
- var ROOTED_JSON_PORTABILITY = "rooted-json";
796
- var ESLINT_CACHE_SPEC = {
797
- cache_file: ESLINT_CACHE_FILE,
798
- portability: ROOTED_JSON_PORTABILITY
799
- };
800
- var TS_CACHE_SPEC = {
801
- cache_file: TS_BUILD_INFO_FILE,
802
- portability: "raw"
803
- };
804
- var CSPELL_CACHE_SPEC = {
805
- cache_file: CSPELL_CACHE_FILE,
806
- portability: "raw"
807
- };
808
- var GATE_CACHE_SPECS = [
809
- ESLINT_CACHE_SPEC,
810
- TS_CACHE_SPEC,
811
- CSPELL_CACHE_SPEC
812
- ];
813
- var GATE_CACHE_FILES = GATE_CACHE_SPECS.map((spec) => spec.cache_file);
814
- var IGNORED_CACHE_FILES = [
815
- ...GATE_CACHE_FILES,
816
- ESLINT_EDIT_CACHE_FILE,
817
- ESLINT_RELATED_CACHE_FILE,
818
- PRETTIER_CACHE_FILE,
819
- PRETTIER_RELATED_CACHE_FILE,
820
- CSPELL_COMMIT_CACHE_FILE,
821
- ESLINT_COMMIT_CACHE_FILE
822
- ];
823
- var CONTENT_CACHE_FLAGS = ["--cache", "--cache-strategy", "content"];
824
- var CACHE_LOCATION_FLAG = "--cache-location";
825
- function content_cache_flags(cache_file) {
826
- return [...CONTENT_CACHE_FLAGS, CACHE_LOCATION_FLAG, cache_file];
827
- }
828
- var ESLINT_CACHE_FLAGS = content_cache_flags(ESLINT_CACHE_FILE);
829
- var ESLINT_EDIT_CACHE_FLAGS = content_cache_flags(ESLINT_EDIT_CACHE_FILE);
830
- var ESLINT_RELATED_CACHE_FLAGS = content_cache_flags(ESLINT_RELATED_CACHE_FILE);
831
- var CSPELL_CACHE_FLAGS = content_cache_flags(CSPELL_CACHE_FILE);
832
- var PRETTIER_CACHE_FLAGS = content_cache_flags(PRETTIER_CACHE_FILE);
833
- var PRETTIER_RELATED_CACHE_FLAGS = content_cache_flags(PRETTIER_RELATED_CACHE_FILE);
834
- var CSPELL_COMMIT_CACHE_FLAGS = content_cache_flags(CSPELL_COMMIT_CACHE_FILE);
835
- var ESLINT_COMMIT_CACHE_FLAGS = content_cache_flags(ESLINT_COMMIT_CACHE_FILE);
836
-
837
- // scripts/josh/josh-commands-backlog.ts
838
- var BACKLOG_COMMANDS = {
839
- // Started from a terminal: the `backlogrun` keyword's launcher, and the board.
840
- backlogrun: {
841
- script: "scripts/backlog/backlogrun-cli.ts",
842
- description: "Start a backlogrun in the background and show its board; with one already running, only show the board, or replace it when it is idle and the invocation differs; --stop stops it",
843
- category: "AI tools",
844
- reference: [
845
- "[<n>...] [--only] [--max <n>] [--idle <minutes>] [--agent claude|codex] | --stop",
846
- "developer",
847
- ["files", "network", "processes"]
848
- ]
849
- },
850
- "backlog:next": {
851
- script: "scripts/backlog/backlog-next.ts",
852
- description: "Order the whole opted-in backlog: auto-ok issues and the descendants of auto-ok epics, transitively through nested epics",
853
- category: "AI tools",
854
- reference: ["[--exclude <n>[,<n>...]] [--repo <owner/repo>]", "automation", ["network"]]
855
- },
856
- "backlog:offer": {
857
- script: "scripts/backlog/backlog-offer-cli.ts",
858
- description: "Collapse a backlogrun loop-head event into one call: read backlog:next, ask backlog:budget, return the verdict and any issues to start",
859
- category: "AI tools",
860
- reference: ["[options]", "automation", ["files", "network", "processes"]]
861
- },
862
- "backlog:drive": {
863
- script: "scripts/backlog/backlog-drive-cli.ts",
864
- description: "Drive backlogrun through offer, launch and merge; restore this run\u2019s lanes and report when complete",
865
- category: "AI tools",
866
- reference: ["--owner <pid> [options]", "automation", ["network"]]
867
- },
868
- "backlog:plan": {
869
- script: "scripts/backlog/backlog-plan-cli.ts",
870
- description: "Print the whole backlog as a plan: ready now, waiting on what, waiting on a person, out of scope",
871
- category: "AI tools",
872
- reference: [
873
- "[issue...] [--only] [--waves] [--exclude <n>[,<n>...]]",
874
- "automation",
875
- ["network"]
876
- ]
877
- },
878
- "backlog:stalled": {
879
- script: "scripts/backlog/backlog-stalled-cli.ts",
880
- // A stall sends one Telegram warning. The `Stop` hook calls the detector
881
- // directly, so this flag costs only the manual command its in-process dispatch.
882
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
883
- description: "Report whether ready backlog work is sitting undispatched with a free lane and no recent dispatch",
884
- category: "AI tools",
885
- reference: ["", "automation", ["network"]]
886
- },
887
- "backlog:budget": {
888
- script: "scripts/backlog/backlog-budget-cli.ts",
889
- description: "Say whether a backlogrun may start more work, keep watching, or finish",
890
- category: "AI tools",
891
- reference: ["[options]", "automation", ["none"]]
892
- }
893
- };
894
-
895
- // scripts/josh/josh-commands-document.ts
896
- var DOCUMENT_COMMANDS = {
897
- "doc:section": {
898
- script: "scripts/document/document-section-cli.ts",
899
- description: 'Print one section of a markdown document, for a `file.md` \u2192 "Heading" reference',
900
- category: "AI tools",
901
- reference: ["<file> <heading>", "automation", ["none"]],
902
- is_bundled: true
903
- },
904
- "read:set": {
905
- script: "scripts/document/read-set-cli.ts",
906
- description: "Print what an entry point reads before it starts, and what that read costs",
907
- category: "AI tools",
908
- reference: ["[<entry>] [--json]", "automation", ["none"]]
909
- },
910
- "doc:read": {
911
- script: "scripts/document/document-read-cli.ts",
912
- description: "Read a whole document safely: print it, or point at the Read tool when over the Bash cap",
913
- category: "AI tools",
914
- reference: ["<file>", "automation", ["none"]]
915
- },
916
- "read:files": {
917
- script: "scripts/document/read-files-cli.ts",
918
- description: "Read several files in one call so edit targets fold into one turn",
919
- category: "AI tools",
920
- reference: ["<path> [<path> ...]", "automation", ["none"]]
921
- },
922
- "edit:files": {
923
- script: "scripts/document/edit-files-cli.ts",
924
- description: "Apply several content-addressed edits from a plan in one call",
925
- category: "AI tools",
926
- reference: ["<plan-path | ->", "automation", ["none"]]
927
- }
928
- };
929
-
930
- // scripts/josh/josh-commands-guard.ts
931
- var GUARD_COMMANDS = {
932
- "investigation:guard": {
933
- script: "scripts/delegation/investigation-guard.ts",
934
- description: "Claude Code hook: refuse a read once the unedited-read threshold is reached again (reads the tool call on stdin)",
935
- category: "AI tools",
936
- reference: ["", "automation", ["none"]]
937
- },
938
- "duplicate-read:guard": {
939
- script: "scripts/delegation/duplicate-read-guard.ts",
940
- description: "Claude Code hook: refuse a second whole-file read of a path whose content has not changed since the run last read it (reads the tool call on stdin)",
941
- category: "AI tools",
942
- reference: ["", "automation", ["none"]]
943
- },
944
- "rule:guard": {
945
- script: "scripts/rules/rule-guard.ts",
946
- description: "Claude Code hook: deliver a trigger-delivered rule at the call that binds it (reads the tool call on stdin)",
947
- category: "AI tools",
948
- reference: ["", "automation", ["none"]]
949
- }
950
- };
951
-
952
- // scripts/josh/josh-commands-issue.ts
953
- var ISSUES_WITH_REPO = "<issue...> [--repo <owner/repo>]";
954
- var ISSUE_COMMANDS = {
955
- "issue:ack": {
956
- script: "scripts/issue/issue-ack-cli.ts",
957
- description: "Record that the run read a person's update to its issue, printing the update it acknowledges",
958
- category: "AI tools",
959
- reference: ["<issue>", "automation", ["network"]]
960
- },
961
- "issue:read": {
962
- script: "scripts/issue/issue-read-cli.ts",
963
- description: "Print each issue's title, body and every comment on it, in one call",
964
- category: "AI tools",
965
- reference: ["<issue...>", "automation", ["network"]]
966
- },
967
- "issue:state": {
968
- script: "scripts/issue/issue-state-cli.ts",
969
- description: "Print each issue's state and labels, in the spelling the documents compare against",
970
- category: "AI tools",
971
- reference: [ISSUES_WITH_REPO, "automation", ["network"]]
972
- },
973
- "issue:scout": {
974
- script: "scripts/issue/issue-scout-cli.ts",
975
- description: "Before filing: say whether an issue like this exists and which epic it belongs to",
976
- category: "AI tools",
977
- reference: ["<title> [--body <summary> | --body-file <path>]", "automation", ["network"]]
978
- },
979
- "defect:rate": {
980
- script: "scripts/issue/defect-rate-cli.ts",
981
- description: "Print the defect rate of merged work: defects filed per enhancement completed",
982
- category: "AI tools",
983
- reference: ["[--days <n>]", "automation", ["network"]]
984
- },
985
- "issue:fold": {
986
- script: "scripts/issue/issue-fold-cli.ts",
987
- description: "Before a second filing: say whether findings from this session fold into one issue",
988
- category: "AI tools",
989
- reference: ["<title>... [--not-separable] [--json]", "automation", ["none"]]
990
- },
991
- "issue:fold-existing": {
992
- script: "scripts/issue/issue-fold-existing-cli.ts",
993
- description: "Assess whether a complete draft can join an unstarted issue",
994
- category: "AI tools",
995
- reference: ["<assessment.json> [--json]", "automation", ["none"]]
996
- },
997
- "issue:cite": {
998
- script: "scripts/issue/issue-cite-cli.ts",
999
- description: "Print the paste-ready number-link citation line for each issue, in one call",
1000
- category: "AI tools",
1001
- reference: [ISSUES_WITH_REPO, "automation", ["network"]]
1002
- },
1003
- "issue:comment": {
1004
- script: "scripts/issue/issue-comment-cli.ts",
1005
- description: "Post one comment to an issue from a file, so no shell expands the body",
1006
- category: "AI tools",
1007
- reference: ["<issue> --body <text> | --body-file <path>", "automation", ["network"]]
1008
- },
1009
- "issue:file": {
1010
- script: "scripts/issue/issue-file-cli.ts",
1011
- description: "File an Issue with every filing step: lint, Origin, fold, WIP cap, duplicate scout, labels, then epic:bundle",
1012
- category: "AI tools",
1013
- reference: [
1014
- "<title> --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>] [--distinct <N,\u2026>] [--over-cap] [--no-auto-ok] [--release]",
1015
- "automation",
1016
- ["network"]
1017
- ]
1018
- },
1019
- "issue:release": {
1020
- script: "scripts/issue/issue-release-cli.ts",
1021
- description: "Link an Issue to the repository's open release Issue as its blocker (or, with --wait, as waiting on it), filing one when none is open",
1022
- category: "AI tools",
1023
- reference: ["<issue> [--wait]", "automation", ["network"]]
1024
- }
1025
- };
1026
-
1027
- // scripts/josh/josh-commands-lane.ts
1028
- var LANE_SCRIPT = "scripts/lane/lane-cli.ts";
1029
- var LANE_ARGUMENTS = { script: LANE_SCRIPT, tsx_arguments: OPTIONAL_ENV_FILE_FLAGS };
1030
- var ISSUE_WITH_OPTIONS = "<issue> [options]";
1031
- var MEASURE_ARGUMENTS = {
1032
- script: "scripts/lane/lane-measure-cli.ts",
1033
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS
1034
- };
1035
- var LANE_COMMANDS = {
1036
- "lane:open": {
1037
- ...LANE_ARGUMENTS,
1038
- description: "Open a lane: a linked work tree with its own branch and its own port seed",
1039
- category: "AI tools",
1040
- reference: [ISSUE_WITH_OPTIONS, "automation", ["files", "git"]],
1041
- default_script_arguments: ["open"]
1042
- },
1043
- "lane:close": {
1044
- ...LANE_ARGUMENTS,
1045
- description: "Close a lane, leaving no work tree, branch or directory behind",
1046
- category: "AI tools",
1047
- reference: ["<issue>", "automation", ["files", "git"]],
1048
- default_script_arguments: ["close"]
1049
- },
1050
- "lane:list": {
1051
- ...LANE_ARGUMENTS,
1052
- description: "List the open lanes: which issue, which ports, and where each one is",
1053
- category: "AI tools",
1054
- reference: ["", "automation", ["none"]],
1055
- default_script_arguments: ["list"]
1056
- },
1057
- "lane:prune": {
1058
- ...LANE_ARGUMENTS,
1059
- description: "Close every lane an interruption left without its work tree and every spent lane, then sweep unregistered leftovers under the lanes root",
1060
- category: "AI tools",
1061
- reference: ["", "automation", ["files", "git"]],
1062
- default_script_arguments: ["prune"]
1063
- },
1064
- "lane:output": {
1065
- ...LANE_ARGUMENTS,
1066
- description: "Record, or read back, where the unit running a lane\u2019s child writes",
1067
- category: "AI tools",
1068
- reference: ["<issue> [path]", "automation", ["files"]],
1069
- default_script_arguments: ["output"]
1070
- },
1071
- "lane:dispatch": {
1072
- ...LANE_ARGUMENTS,
1073
- description: "Start a lane\u2019s child as a detached process that outlives this session",
1074
- category: "AI tools",
1075
- reference: ["<issue> <prompt>", "automation", ["processes"]],
1076
- default_script_arguments: ["dispatch"]
1077
- },
1078
- "lane:await": {
1079
- ...LANE_ARGUMENTS,
1080
- description: "Block until any of the named in-flight lane children completes; prints which one finished",
1081
- category: "AI tools",
1082
- reference: ["<issue> [<issue>...] [--owner <pid>]", "automation", ["files", "processes"]],
1083
- default_script_arguments: ["await"]
1084
- },
1085
- "lane:launch": {
1086
- script: "scripts/lane/lane-launch-cli.ts",
1087
- description: "Collapse a backlogrun lane-start event into one call: open the lane, pop and re-install on the first, dispatch the child",
1088
- category: "AI tools",
1089
- reference: ["<issue> [--stash <message>]", "automation", ["files", "git", "processes"]]
1090
- },
1091
- // `.env` is read for `JOSH_LANE_ROOT`, as every lane command reads it, so the lane is found.
1092
- "lane:restart": {
1093
- script: "scripts/lane/lane-restart-cli.ts",
1094
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
1095
- description: "Stop a running lane child, stash its uncommitted work and re-dispatch its issue in a fresh session \u2014 not counted as an outage or a failure",
1096
- category: "AI tools",
1097
- reference: ["<issue>", "developer", ["files", "git", "processes", "network"]]
1098
- },
1099
- // `.env` is read for `JOSH_LANE_ROOT`, as every lane command reads it, so the lane is found.
1100
- "lane:withdraw": {
1101
- script: "scripts/lane/lane-withdraw-cli.ts",
1102
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
1103
- description: "Stop a running lane child, stash its uncommitted work, close its issue as not planned and close the lane \u2014 booked withdrawn, not as an outage or a failure",
1104
- category: "AI tools",
1105
- reference: ["<issue> --reason <text>", "developer", ["files", "git", "processes", "network"]]
1106
- },
1107
- // A live run's lane limit: `.env` is read so the bare form reports the
1108
- // `JOSH_LANE_LIMIT` a person set there when no override stands.
1109
- "lane:limit": {
1110
- script: "scripts/lane/lane-limit-cli.ts",
1111
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
1112
- description: "Change a live backlogrun\u2019s lane limit without stopping it, or print the limit, lanes in use and free lanes",
1113
- category: "AI tools",
1114
- reference: ["[<limit>] [--reset]", "developer", ["files"]]
1115
- },
1116
- // The lane-limit measurement: `.env` is read so `lane:stats` labels the row
1117
- // with the `JOSH_LANE_LIMIT` a person set there.
1118
- "lane:sample": {
1119
- ...MEASURE_ARGUMENTS,
1120
- description: "Record the machine load (load average, swap, free memory, working lanes) to the lane ledger \u2014 a backlogrun samples itself, this is for a reading outside one",
1121
- category: "AI tools",
1122
- reference: ["[--every <seconds>]", "maintainer", ["files"]],
1123
- default_script_arguments: ["sample"]
1124
- },
1125
- "lane:stats": {
1126
- ...MEASURE_ARGUMENTS,
1127
- description: "Print one table row of lane throughput, gate duration and machine load over a period, the per-stage durations of a lane under it, the wait after each ship stop reason under those, and the duration and reuse count of each gate check last",
1128
- category: "AI tools",
1129
- reference: ["--period <days> [--limit <lane-limit>]", "maintainer", ["none"]],
1130
- default_script_arguments: ["stats"]
1131
- }
1132
- };
1133
-
1134
- // scripts/josh/josh-commands-run.ts
1135
- var RUN_HOLD_SCRIPT = "scripts/run/hold/run-hold-cli.ts";
1136
- var RUN_COMMANDS = {
1137
- "run:hold": {
1138
- script: RUN_HOLD_SCRIPT,
1139
- description: "Claim this working tree for a run, or say which run already holds it",
1140
- category: "AI tools",
1141
- reference: ["[<issue> [--fullrun | --halfrun-stop | --prrun-stop]]", "automation", ["files"]]
1142
- },
1143
- "run:release": {
1144
- script: RUN_HOLD_SCRIPT,
1145
- description: "Release this working tree's run record",
1146
- category: "AI tools",
1147
- reference: ["[issue|--force]", "automation", ["files"]],
1148
- default_script_arguments: ["--release"]
1149
- },
1150
- "run:tidy": {
1151
- script: "scripts/run/tidy/run-tidy-cli.ts",
1152
- description: "Close merged lanes and drop stashes whose issues are all merged",
1153
- category: "AI tools",
1154
- reference: ["", "automation", ["git", "network", "files"]]
1155
- },
1156
- "run:carry": {
1157
- script: "scripts/run/carry/run-carry-cli.ts",
1158
- // `--stopped` sends the stop confirmation, so the Telegram credentials come from `.env` as for
1159
- // `run:wake` below.
1160
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
1161
- description: "Carry one invocation\u2019s budget across its own session cuts",
1162
- category: "AI tools",
1163
- reference: ["<operation> [arguments...]", "automation", ["files"]]
1164
- },
1165
- "run:add": {
1166
- script: "scripts/run/add/run-add-cli.ts",
1167
- description: "Add issues to a live backlogrun, ahead of the queue unless --no-priority",
1168
- category: "AI tools",
1169
- reference: ["<issue...> [--no-priority]", "automation", ["network", "files"]]
1170
- },
1171
- "run:wake": {
1172
- script: "scripts/run/wake/run-wake-cli.ts",
1173
- // `.env` rather than the ambient environment:
1174
- // the failure warning needs the Telegram credentials, the same
1175
- // reasons `notify` and `followup` carry these flags.
1176
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
1177
- description: "Wake the next session of a cut backlogrun from outside the conversation",
1178
- category: "AI tools",
1179
- reference: ["[options]", "automation", ["processes", "notifications"]]
1180
- },
1181
- "run:cut": {
1182
- script: "scripts/run/cut/run-cut-cli.ts",
1183
- description: "Cut a lane child before the gate and resume a fresh process",
1184
- category: "AI tools",
1185
- reference: ["[--resume] <issue> [--impl] [--handoff <path>]", "automation", ["files"]]
1186
- },
1187
- "run:liveness": {
1188
- script: "scripts/run/run-liveness-cli.ts",
1189
- description: "Say whether a delegated unit is still working, or stopped without reporting",
1190
- category: "AI tools",
1191
- reference: ["<issue> --output <path> [options]", "automation", ["processes"]]
1192
- },
1193
- "run:ending": {
1194
- script: "scripts/run/run-ending-cli.ts",
1195
- description: "Classify how a dispatched lane child ended (merged, cut, abandoned, unreadable)",
1196
- category: "AI tools",
1197
- reference: ["<issue> --output <path> [--repo <owner/repo>]", "automation", ["network"]]
1198
- },
1199
- "run:progress": {
1200
- script: "scripts/run/progress/run-progress-cli.ts",
1201
- description: "Report an unattended run\u2019s progress once it has gone quiet for an interval",
1202
- category: "AI tools",
1203
- reference: [
1204
- "[--once | --wait] [--interval <minutes>] [--hours <hours>] [--repo <owner/repo>] [--output <path>] | --mark | --path",
1205
- "automation",
1206
- ["files"]
1207
- ]
1208
- },
1209
- "run:board": {
1210
- script: "scripts/run/board/run-board-cli.ts",
1211
- // `--every` pushes its frame as a Telegram, so the credentials come from `.env` as for `run:carry`.
1212
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
1213
- description: "Draw a live board of the running backlogrun, redrawn every second",
1214
- category: "AI tools",
1215
- reference: ["[--once | --chat | --every <minutes>]", "automation", ["files", "network"]]
1216
- },
1217
- "run:prep": {
1218
- script: "scripts/run/run-prep-cli.ts",
1219
- description: "Bundle a run\u2019s pre-edit reads: body, comments, state, dependency scope",
1220
- category: "AI tools",
1221
- reference: ["<issue>", "automation", ["network"]]
1222
- },
1223
- // The entry sequence a lane opened on, folded into one call: claim the tree,
1224
- // read the budget, gather the issue reads and decide the pre-implementation step. `run:hold`,
1225
- // `cost --cut`, `run:prep` and `run:step` were four round trips re-billing a lane's full context each.
1226
- "run:entry": {
1227
- script: "scripts/run/entry/run-entry-cli.ts",
1228
- // A `busy` hold or an `over` budget sends the stop confirmation.
1229
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
1230
- description: "Open a run in one call: claim the tree, read the budget, bundle the reads, decide the pre-implementation step",
1231
- category: "AI tools",
1232
- reference: ["<issue> [--to <command>]", "automation", ["git", "network", "files"]]
1233
- },
1234
- "run:status": {
1235
- script: "scripts/run/run-status-cli.ts",
1236
- description: "Bundle a run\u2019s read-only status: issue state, cost verdict, carry counters",
1237
- category: "AI tools",
1238
- reference: ["<issue> [--repo <owner/repo>]", "automation", ["network"]]
1239
- },
1240
- "run:next": {
1241
- script: "scripts/run/run-next-cli.ts",
1242
- description: "Print the next step a fullrun takes, computed from the run\u2019s state",
1243
- category: "AI tools",
1244
- reference: ["<issue>", "automation", ["network"]]
1245
- },
1246
- "run:step": {
1247
- script: "scripts/run/run-step-cli.ts",
1248
- description: "Print the run\u2019s next single action, computed from the event stream, carry record and issue state",
1249
- category: "AI tools",
1250
- reference: ["[<issue>]", "automation", ["network", "files"]]
1251
- }
1252
- };
1253
-
1254
- // scripts/josh/josh-commands-split.ts
1255
- var SPLIT_COMMANDS = {
1256
- "split:assess": {
1257
- script: "scripts/split/split-assess-cli.ts",
1258
- description: "Measure the branch change size (tests excluded) and answer the split assessment size question: split | single",
1259
- category: "AI tools",
1260
- reference: ["[--json]", "automation", ["none"]]
1261
- }
1262
- };
1263
-
1264
- // scripts/josh/josh-commands-ai.ts
1265
- var ISSUE_WITH_OPTIONS2 = "<issue> [options]";
1266
- var AI_COMMANDS = {
1267
- ...ISSUE_COMMANDS,
1268
- "pkg:scout": {
1269
- script: "scripts/package/package-scout-cli.ts",
1270
- description: "Rank package candidates by measured metrics so the Package-First tier decision is read, not judged",
1271
- category: "AI tools",
1272
- reference: ["<keywords> [--size <n>]", "automation", ["network"]]
1273
- },
1274
- "stash:pop": {
1275
- script: "scripts/git/stash/stash-pop-cli.ts",
1276
- description: "Pop the stash matching this message, not whichever a shared stack has on top",
1277
- category: "AI tools",
1278
- reference: ["<message>", "automation", ["git"]]
1279
- },
1280
- epic: {
1281
- script: "scripts/epic/epic.ts",
1282
- description: "Create an epic issue from its child issue numbers",
1283
- category: "AI tools",
1284
- reference: ["<title> <issue...> [--ordered]", "automation", ["network"]]
1285
- },
1286
- "epic:next": {
1287
- script: "scripts/epic/epic-next.ts",
1288
- description: "List an epic's runnable children, bundled per repository",
1289
- category: "AI tools",
1290
- reference: ["<epic>... [--repo <owner/repo>] [--lanes]", "automation", ["network"]]
1291
- },
1292
- "epic:bundle": {
1293
- script: "scripts/epic/epic-bundle-cli.ts",
1294
- description: "Say whether a newly filed issue belongs with ones already in the backlog",
1295
- category: "AI tools",
1296
- reference: ["<issue>", "automation", ["network"]]
1297
- },
1298
- "epic:audit": {
1299
- script: "scripts/epic/epic-audit-cli.ts",
1300
- description: "Audit an epic's children against each other for contradictions",
1301
- category: "AI tools",
1302
- reference: ["<epic>", "automation", ["network"]]
1303
- },
1304
- "epic:check": {
1305
- script: "scripts/epic/epic-check.ts",
1306
- description: "Check an epic issue against the tracking requirements",
1307
- category: "AI tools",
1308
- reference: ["<epic>", "automation", ["network"]]
1309
- },
1310
- "auto-ok:next": {
1311
- script: "scripts/auto-ok/auto-ok-cli.ts",
1312
- description: "Print the next opted-in issue an unattended run may pick up outside an epic",
1313
- category: "AI tools",
1314
- reference: ["[--exclude <n>[,<n>...]] [--label <name>]", "automation", ["network"]]
1315
- },
1316
- "auto-ok:judge": {
1317
- script: "scripts/auto-ok/auto-ok-judge-cli.ts",
1318
- description: "List the open issues backlogrun owes an auto-ok judgement, or record one (--apply / --decline)",
1319
- category: "AI tools",
1320
- reference: [
1321
- "[--apply <n> (--lane | --solo) | --decline <n> --reason <text>]",
1322
- "automation",
1323
- ["network"]
1324
- ]
1325
- },
1326
- ...BACKLOG_COMMANDS,
1327
- cost: {
1328
- script: "scripts/cost-runtime/cost-cli.ts",
1329
- description: "Say whether the next turn of a run crosses the context-cut threshold (--cut) or a given tokens-per-request figure (--over)",
1330
- category: "AI tools",
1331
- reference: ["(--cut | --over <tokens-per-request>) [--path <dir>]", "automation", ["none"]]
1332
- },
1333
- "cost:audit": {
1334
- script: "scripts/cost-audit/cost-audit-cli.ts",
1335
- description: "Report AI cost over a period by session kind, tool category and guard, with cost per merge and regressions against the period before",
1336
- category: "AI tools",
1337
- reference: ["[--period <days>]", "maintainer", ["none"]],
1338
- // Kit-only: it reads kit's own transcript store, like `josh retrospective`, which carries its
1339
- // summary line.
1340
- is_kit_only: true
1341
- },
1342
- ...DOCUMENT_COMMANDS,
1343
- time: {
1344
- script: "scripts/time/time-cli.ts",
1345
- description: "Report where a run's wall clock went: model wait, tool execution, human wait",
1346
- category: "AI tools",
1347
- reference: ["[options]", "maintainer", ["none"]],
1348
- // Kit-only: it measures kit's own development runs and its report modules live under the
1349
- // undistributed `scripts/time/`, so it means nothing in a consumer project and is dropped from a
1350
- // consumer's help. The runtime analysis hooks and guards rely on stays
1351
- // distributed under `scripts/time-runtime/`.
1352
- is_kit_only: true
1353
- },
1354
- // The tool-calls-per-round-trip density the batching guard is measured on, aggregated across the
1355
- // recent lane sessions. Kit-only for the same reason `time` is: it reads
1356
- // kit's own lane transcripts and means nothing in a consumer project.
1357
- "time:density": {
1358
- script: "scripts/time/time-density-cli.ts",
1359
- description: "Report tool calls per round trip across the recent lane sessions",
1360
- category: "AI tools",
1361
- reference: ["[--lanes <n>] [--path <dir>]", "maintainer", ["none"]],
1362
- is_kit_only: true
1363
- },
1364
- retrospective: {
1365
- script: "scripts/retrospective/retrospective-cli.ts",
1366
- description: "Aggregate a finished run's cost, review findings, observation ledger and events into one digest",
1367
- category: "AI tools",
1368
- reference: ["", "maintainer", ["none"]],
1369
- core_weight: core_budget.CORE_WEIGHTS.retrospective,
1370
- memory_mb: core_budget.MEMORY_MB.retrospective,
1371
- // Kit-only: it reads kit's own development run — the transcript store, the review ledger and the
1372
- // run event stream — so it means nothing in a consumer project and is dropped from a consumer's
1373
- // help, through the same declaration `josh time` uses for the same reason.
1374
- is_kit_only: true
1375
- },
1376
- "review:brief": {
1377
- script: "scripts/review/review-brief-cli.ts",
1378
- description: "Print the whole /code-review invocation: level, what the gate already proved, target (--level-only for the level alone)",
1379
- category: "AI tools",
1380
- reference: ["[--round <1|2>] | --level-only [--staged] [--json]", "automation", ["files"]]
1381
- },
1382
- "review:attest": {
1383
- script: "scripts/review/review-attest-cli.ts",
1384
- description: "Record, or verify, which checkout a /code-review actually read",
1385
- category: "AI tools",
1386
- reference: ["<nonce> | --check", "automation", ["files"]]
1387
- },
1388
- "review:round2": {
1389
- script: "scripts/review/review-round2-cli.ts",
1390
- description: "Say whether the second /code-review round is due, or may be skipped entirely",
1391
- category: "AI tools",
1392
- reference: ["[--round-1-closed] [--json]", "automation", ["none"]]
1393
- },
1394
- delegate: {
1395
- script: "scripts/delegation/delegation-cli.ts",
1396
- description: "Say whether a run step may go to a cheaper execution tier",
1397
- category: "AI tools",
1398
- reference: ["<step> | --list", "automation", ["none"]]
1399
- },
1400
- fanout: {
1401
- script: "scripts/delegation/fanout-cli.ts",
1402
- description: "Say whether proposed implementation units are file-disjoint, so they may run in parallel",
1403
- category: "AI tools",
1404
- reference: ["<unit-files> <unit-files> [<unit-files> \u2026]", "automation", ["none"]]
1405
- },
1406
- ...RUN_COMMANDS,
1407
- "repo:party": {
1408
- script: "scripts/discovery/repo-party-cli.ts",
1409
- description: "Say whether a repository is first-party or third-party by owner equality (computed, not judged)",
1410
- category: "AI tools",
1411
- reference: ["[<owner/repo>]", "automation", ["none"]]
1412
- },
1413
- "run:merge": {
1414
- script: "scripts/run/merge/run-merge-cli.ts",
1415
- description: "Collapse a backlogrun merge event into one call: confirm the child, do the post-merge steps, offer the next child",
1416
- category: "AI tools",
1417
- reference: [ISSUE_WITH_OPTIONS2, "automation", ["git", "network"]]
1418
- },
1419
- "run:review": {
1420
- script: "scripts/run/review/run-review-cli.ts",
1421
- description: "Start the gate in the background and print the /code-review brief in one call so the two overlap (--join to join the gate and check its verdict)",
1422
- category: "AI tools",
1423
- reference: ["[--join]", "automation", ["processes", "files"]]
1424
- },
1425
- // The post-merge sequence a run closed on, folded into one call: commit the
1426
- // observation ledger, read the completion citations and decide the release scope. `observations:flush`,
1427
- // `issue:cite` and `release:scope` were three round trips re-billing the run's full context each.
1428
- "run:tail": {
1429
- script: "scripts/run/run-tail-cli.ts",
1430
- description: "Close a run in one call: return to the default branch, commit the observation ledger, read the citations, decide the release scope",
1431
- category: "AI tools",
1432
- reference: ["[<issue> ...]", "automation", ["git", "network"]]
1433
- },
1434
- // The commit-to-report region a run ships a change on, folded into one call:
1435
- // the gate, the commit/push/PR (`git -y`), the CI-wait merge (`followup`) and the report bookkeeping
1436
- // (`run:tail`) were four round trips re-billing the run's full context each. It stops at the first
1437
- // failed step and names it, so the run reads only the step to fix.
1438
- ship: {
1439
- script: "scripts/run/ship/run-ship-cli.ts",
1440
- description: "Ship a change in one call: gate, commit/push/PR, the CI-wait merge and the report bookkeeping, stopping at the first failed step",
1441
- category: "AI tools",
1442
- reference: [
1443
- '"<title> #<N>" [<follow-up-N> ...] [--cite <N>] [--review] [--detach] [--body-file <path>] [--notify-message <text> | --notify-message-file <path>] | --log <N>',
1444
- "automation",
1445
- ["git", "network"]
1446
- ]
1447
- },
1448
- "run:event": {
1449
- script: "scripts/run/event/run-event-cli.ts",
1450
- description: "Append to, read or watch the run\u2019s append-only event stream (--append <kind> <text> | --from|--follow <n> | --watch [<n>] | --last)",
1451
- category: "AI tools",
1452
- reference: [
1453
- "--append <kind> <text> | --from|--follow <n> | --watch [<n>] | --last",
1454
- "automation",
1455
- ["files"]
1456
- ]
1457
- },
1458
- "run:report": {
1459
- script: "scripts/run/run-report-cli.ts",
1460
- description: "Generate the session-facing report for this invocation from the run\u2019s event stream (merges, parks, cuts) with the release tail \u2014 the same text josh notify sends",
1461
- category: "AI tools",
1462
- reference: ["", "automation", ["files", "network"]]
1463
- },
1464
- ...LANE_COMMANDS,
1465
- ...GUARD_COMMANDS,
1466
- "run:watcher:guard": {
1467
- script: "scripts/run/run-watcher-guard-cli.ts",
1468
- description: "Guard: exits non-zero when lane children are in-flight but the watcher has not pinged recently",
1469
- category: "AI tools",
1470
- reference: ["", "automation", ["none"]]
1471
- },
1472
- "run:stranded": {
1473
- script: "scripts/run/run-stranded-cli.ts",
1474
- // `.env` rather than the ambient environment: the strand notification needs the Telegram
1475
- // credentials, the same reason `run:wake` carries these flags.
1476
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
1477
- description: "Report whether the run is stranded \u2014 owner gone, no successor holding the budget, and no supervisor watching",
1478
- category: "AI tools",
1479
- reference: ["", "automation", ["processes", "notifications"]]
1480
- },
1481
- ...SPLIT_COMMANDS,
1482
- "oracle:list": {
1483
- script: "scripts/rules/oracle-list-cli.ts",
1484
- description: "Print the decision oracles \u2014 commands that answer a rule question mechanically",
1485
- category: "AI tools",
1486
- reference: ["", "automation", ["none"]]
1487
- },
1488
- eval: {
1489
- script: "scripts/eval/eval-run.ts",
1490
- description: "Run the agent rule-compliance scenarios (real Claude sessions)",
1491
- category: "AI tools",
1492
- reference: ["[scenario...]", "maintainer", ["processes", "network"]],
1493
- // Kit-only: it replays kit's own distributed rules against real Claude sessions, so it means
1494
- // nothing in a consumer project and is dropped from a consumer's help.
1495
- is_kit_only: true
1496
- }
1497
- };
1498
-
1499
- // scripts/josh/josh-commands-clone.ts
1500
- var CLONE_COMMANDS = {
1501
- "clone:scan": {
1502
- script: "scripts/clone/clone-scan-cli.ts",
1503
- description: "Count code duplication across files and first-party repositories, printing each clone as file:line pairs",
1504
- category: "AI tools",
1505
- reference: ["", "automation", ["files"]]
1506
- }
1507
- };
1508
-
1509
- // scripts/gate/gate-plan.ts
1510
- import { availableParallelism as availableParallelism4 } from "node:os";
1511
-
1512
- // scripts/lib/status-icons.ts
1513
- var FAIL_ICON = "\u2717";
1514
- var PASS_ICON = "\u2714";
1515
- var WARN_ICON = "\u26A0";
1516
- var status_icons = { FAIL_ICON, PASS_ICON, WARN_ICON };
1517
-
1518
- // scripts/josh/josh-verdict.ts
1519
- var { FAIL_ICON: FAIL_ICON2, PASS_ICON: PASS_ICON2, WARN_ICON: WARN_ICON2 } = status_icons;
1520
- var GATE_SUBJECT = "verification gate";
1521
- var GATE_PASSED_PREFIX = `${PASS_ICON2} ${GATE_SUBJECT} passed`;
1522
- var GATE_FAILED_PREFIX = `${FAIL_ICON2} ${GATE_SUBJECT} failed`;
1523
- var GATE_UNVERIFIED_PREFIX = `${WARN_ICON2} ${GATE_SUBJECT} not verified`;
1524
- var PASSED_VERDICT = "passed";
1525
- var FAILED_VERDICT = "failed";
1526
- var UNVERIFIED_VERDICT = "unverified";
1527
- function format_counts(counts) {
1528
- if (counts.skipped === 0) return `${String(counts.ran)} checks`;
1529
- return `${String(counts.ran)} ran, ${String(counts.skipped)} skipped`;
1530
- }
1531
- function format_gate_passed(counts, total) {
1532
- return `${GATE_PASSED_PREFIX} (${format_counts(counts)}) in ${total}.`;
1533
- }
1534
- function format_gate_unverified(skipped, total) {
1535
- return `${GATE_UNVERIFIED_PREFIX} (0 ran, ${String(skipped)} skipped) in ${total}.`;
1536
- }
1537
- function format_gate_failed(failed_labels, total) {
1538
- return `${GATE_FAILED_PREFIX}: ${failed_labels} (${total})`;
1539
- }
1540
- var GATE_OPENING_PREFIX = "plan: ";
1541
- var GATE_OPENING_MARK = " checks at once";
1542
- function is_gate_opening(line) {
1543
- const trimmed = line.trimStart();
1544
- return trimmed.startsWith(GATE_OPENING_PREFIX) && trimmed.includes(GATE_OPENING_MARK);
1545
- }
1546
- function read_verdict(line) {
1547
- const trimmed = line.trimStart();
1548
- if (trimmed.startsWith(GATE_FAILED_PREFIX)) return FAILED_VERDICT;
1549
- if (trimmed.startsWith(GATE_PASSED_PREFIX)) return PASSED_VERDICT;
1550
- if (trimmed.startsWith(GATE_UNVERIFIED_PREFIX)) return UNVERIFIED_VERDICT;
1551
- return void 0;
1552
- }
1553
- var josh_verdict = {
1554
- PASSED_VERDICT,
1555
- FAILED_VERDICT,
1556
- UNVERIFIED_VERDICT,
1557
- format_gate_passed,
1558
- format_gate_failed,
1559
- format_gate_unverified,
1560
- GATE_OPENING_MARK,
1561
- GATE_OPENING_PREFIX,
1562
- is_gate_opening,
1563
- read_verdict
1564
- };
1565
-
1566
- // scripts/gate/gate-plan.ts
1567
- var LINT_LABEL = "lint";
1568
- var TYPE_CHECK_LABEL = "check";
1569
- var UNIT_LABEL = "test:unit";
1570
- var BEHAVIOR_LABEL = "behavior";
1571
- var METRICS_LABEL = "metrics";
1572
- var EXPORTS_LABEL = "exports";
1573
- var WARNING_CHECKER_LABELS = [LINT_LABEL, TYPE_CHECK_LABEL];
1574
- var STATIC_CHECKS = [
1575
- {
1576
- label: LINT_LABEL,
1577
- target: "lint",
1578
- reserved_cores: core_budget.CORE_WEIGHTS.lint,
1579
- memory_mb: core_budget.MEMORY_MB.lint
1580
- },
1581
- {
1582
- label: TYPE_CHECK_LABEL,
1583
- target: "check",
1584
- reserved_cores: core_budget.CORE_WEIGHTS.type_check,
1585
- memory_mb: core_budget.MEMORY_MB.type_check
1586
- },
1587
- {
1588
- label: "cspell",
1589
- target: "cspell:dot",
1590
- reserved_cores: core_budget.CORE_WEIGHTS.spell_check,
1591
- memory_mb: core_budget.MEMORY_MB.spell_check
1592
- },
1593
- { label: BEHAVIOR_LABEL, target: BEHAVIOR_LABEL, reserved_cores: 0 },
1594
- // **The unused-member check reserves no core**: it builds one TypeScript
1595
- // program and walks it for about 5s, and it is over well before lint and the type check. A
1596
- // reservation would only take a place from the four-core CI runner's fan-out and a worker from the
1597
- // unit suite for the whole gate.
1598
- { label: EXPORTS_LABEL, target: "exports:unused", reserved_cores: 0 },
1599
- // **The metrics ratchet is kit's own**: it holds kit's repository-wide
1600
- // totals to the merge-base's. It is one in-process eslint pass with only `max-lines` enabled, over
1601
- // in a few seconds, so it reserves no core for the reason the unused-member check above does not.
1602
- // It times no startup here: beside the unit suite that reads the load, not josh.
1603
- {
1604
- label: METRICS_LABEL,
1605
- target: METRICS_LABEL,
1606
- args: ["--no-startup"],
1607
- reserved_cores: 0,
1608
- memory_mb: core_budget.MEMORY_MB.eslint_scan,
1609
- is_kit_only: true
1610
- }
1611
- ];
1612
- var GATE_CHECKS = [
1613
- ...STATIC_CHECKS,
1614
- { label: UNIT_LABEL, target: UNIT_LABEL, reserved_cores: 0 }
1615
- ];
1616
- function select_gate_checks(is_unit_included, is_kit_repository = true) {
1617
- const checks = is_unit_included ? GATE_CHECKS : STATIC_CHECKS;
1618
- return is_kit_repository ? checks : checks.filter((check) => check.is_kit_only !== true);
1619
- }
1620
- function has_unit_check(checks) {
1621
- return checks.some((check) => check.label === UNIT_LABEL);
1622
- }
1623
- var RESERVED_CORES = STATIC_CHECKS.reduce(
1624
- (total, check) => total + check.reserved_cores,
1625
- 0
1626
- );
1627
- var MEASURED_CORES = 11;
1628
- var MIN_CONCURRENCY = 1;
1629
- var MIN_SHARED_CORES = 1;
1630
- function shared_cores(available_cores, concurrent_runs) {
1631
- const runs2 = Number.isFinite(concurrent_runs) ? Math.max(unit_worker_share.SOLO_RUNS, concurrent_runs) : unit_worker_share.SOLO_RUNS;
1632
- return Math.max(MIN_SHARED_CORES, Math.floor(available_cores / runs2));
1633
- }
1634
- function resolve_concurrency(available_cores, concurrent_runs = unit_worker_share.SOLO_RUNS, checks = GATE_CHECKS) {
1635
- const share = shared_cores(available_cores, concurrent_runs);
1636
- let admitted = 0;
1637
- let reserved = 0;
1638
- for (const check of checks) {
1639
- reserved += check.reserved_cores;
1640
- if (reserved > share) break;
1641
- admitted += 1;
1642
- }
1643
- return Math.max(MIN_CONCURRENCY, admitted);
1644
- }
1645
- function resolve_unit_worker_cap(available_cores, concurrent_runs = unit_worker_share.SOLO_RUNS) {
1646
- const share = unit_worker_share.resolve_unit_workers(available_cores, concurrent_runs);
1647
- if (share !== void 0) return share;
1648
- if (available_cores < MEASURED_CORES) return void 0;
1649
- return available_cores - RESERVED_CORES;
1650
- }
1651
- function solo_unit_weight(available_cores) {
1652
- return Math.max(0, available_cores - RESERVED_CORES);
1653
- }
1654
- function check_weight(check, plan, available_cores) {
1655
- if (check.label !== UNIT_LABEL) return check.reserved_cores;
1656
- return plan.unit_worker_cap ?? solo_unit_weight(available_cores);
1657
- }
1658
- function unit_memory(workers) {
1659
- return workers * core_budget.MEMORY_MB.unit_worker;
1660
- }
1661
- function check_memory(check, plan, available_cores) {
1662
- if (check.label !== UNIT_LABEL) return check.memory_mb ?? 0;
1663
- return unit_memory(check_weight(check, plan, available_cores));
1664
- }
1665
- function direct_unit_weight(available_cores = availableParallelism4(), live_runs = unit_worker_share.live_run_count()) {
1666
- const weight = unit_worker_share.current_share(available_cores, live_runs) ?? solo_unit_weight(available_cores);
1667
- return Math.max(unit_worker_share.MIN_WORKERS, weight);
1668
- }
1669
- function direct_unit_memory() {
1670
- return unit_memory(direct_unit_weight());
1671
- }
1672
- function unit_cap_for(checks, available_cores, concurrent_runs) {
1673
- if (!has_unit_check(checks)) return void 0;
1674
- return resolve_unit_worker_cap(available_cores, concurrent_runs);
1675
- }
1676
- function plan_of(concurrency, unit_worker_cap, checks = GATE_CHECKS) {
1677
- return { checks, concurrency, unit_worker_cap };
1678
- }
1679
- function resolve_gate_plan(available_cores = availableParallelism4(), concurrent_runs = unit_worker_share.SOLO_RUNS, is_unit_included = true, is_kit_repository = true) {
1680
- const checks = select_gate_checks(is_unit_included, is_kit_repository);
1681
- return {
1682
- checks,
1683
- concurrency: resolve_concurrency(available_cores, concurrent_runs, checks),
1684
- unit_worker_cap: unit_cap_for(checks, available_cores, concurrent_runs)
1685
- };
1686
- }
1687
- function bound_by_free(plan, available_cores, free_cores) {
1688
- if (!has_unit_check(plan.checks)) return plan;
1689
- const unit_worker_cap = unit_worker_share.cap_to_free(
1690
- plan.unit_worker_cap,
1691
- free_cores,
1692
- available_cores
1693
- );
1694
- return { ...plan, unit_worker_cap };
1695
- }
1696
- function format_machine(available_cores, concurrent_runs) {
1697
- const cores = `${String(available_cores)} cores`;
1698
- if (concurrent_runs <= unit_worker_share.SOLO_RUNS) return cores;
1699
- return `${cores}, ${String(concurrent_runs)} unit runs`;
1700
- }
1701
- function format_unit_cap(plan) {
1702
- if (!has_unit_check(plan.checks)) return `${UNIT_LABEL} elsewhere`;
1703
- if (plan.unit_worker_cap === void 0) return `${UNIT_LABEL} unrestricted`;
1704
- return `${UNIT_LABEL} at ${String(plan.unit_worker_cap)} workers`;
1705
- }
1706
- function format_gate_plan(plan, available_cores = availableParallelism4(), concurrent_runs = unit_worker_share.SOLO_RUNS) {
1707
- const cap = format_unit_cap(plan);
1708
- const count = `${String(plan.concurrency)} of ${String(plan.checks.length)}`;
1709
- const width = `${count}${josh_verdict.GATE_OPENING_MARK}`;
1710
- const machine = format_machine(available_cores, concurrent_runs);
1711
- return `${josh_verdict.GATE_OPENING_PREFIX}${width}, ${cap} (${machine})`;
1712
- }
1713
- var gate_plan = {
1714
- EXPORTS_LABEL,
1715
- GATE_CHECKS,
1716
- LINT_LABEL,
1717
- MEASURED_CORES,
1718
- METRICS_LABEL,
1719
- RESERVED_CORES,
1720
- STATIC_CHECKS,
1721
- TYPE_CHECK_LABEL,
1722
- UNIT_LABEL,
1723
- WARNING_CHECKER_LABELS,
1724
- bound_by_free,
1725
- check_memory,
1726
- check_weight,
1727
- direct_unit_memory,
1728
- direct_unit_weight,
1729
- format_gate_plan,
1730
- format_machine,
1731
- has_unit_check,
1732
- plan_of,
1733
- resolve_concurrency,
1734
- resolve_gate_plan,
1735
- resolve_unit_worker_cap,
1736
- select_gate_checks
1737
- };
1738
-
1739
- // scripts/josh/josh-commands-development.ts
1740
- var FILE_ARGUMENTS = "[files...]";
1741
- var REQUIRED_FILE_ARGUMENTS = "<files...>";
1742
- var FILTER_ARGUMENTS = "[filters...]";
1743
- var MATCH_ARGUMENTS = "[--match]";
1744
- var PATH_ARGUMENTS = "<path...>";
1745
- var DEV_COMMANDS = {
1746
- "pr:classification": {
1747
- script: "scripts/ci/pr-classification.ts",
1748
- description: "Require one release classification on a pull request",
1749
- category: "Development",
1750
- reference: ["", "automation", ["none"]]
1751
- },
1752
- [GATE_COMMAND2]: {
1753
- script: "scripts/gate/verification-gate.ts",
1754
- description: "Run lint, type check, spell check and unit tests concurrently",
1755
- category: "Development",
1756
- reference: ["[--verbose|--force|--no-unit]", "developer", ["files", "processes"]]
1757
- },
1758
- lint: {
1759
- script: "scripts/lint/lint-parallel.ts",
1760
- description: "Check code with prettier and eslint (skips a tool a basic project lacks)",
1761
- category: "Development",
1762
- reference: ["", "developer", ["processes"]],
1763
- core_weight: core_budget.CORE_WEIGHTS.lint,
1764
- memory_mb: core_budget.MEMORY_MB.lint
1765
- },
1766
- "lint:related": {
1767
- script: "scripts/lint/lint-related.ts",
1768
- description: "Check only the changed files with prettier and eslint (whole tree on fallback)",
1769
- category: "Development",
1770
- reference: [FILE_ARGUMENTS, "developer", ["processes"]],
1771
- core_weight: core_budget.CORE_WEIGHTS.lint,
1772
- memory_mb: core_budget.MEMORY_MB.lint
1773
- },
1774
- lines: {
1775
- script: "scripts/lines/lines-command.ts",
1776
- description: "Print a file's code lines against the max-lines limit and the headroom left",
1777
- category: "Development",
1778
- reference: [REQUIRED_FILE_ARGUMENTS, "developer", ["none"]],
1779
- core_weight: core_budget.CORE_WEIGHTS.eslint_scan,
1780
- memory_mb: core_budget.MEMORY_MB.eslint_scan
1781
- },
1782
- metrics: {
1783
- script: "scripts/metrics/metrics-command.ts",
1784
- description: "Print repository-wide quality totals and durations, and fail when a total grew past the merge-base or a duration past its baseline",
1785
- category: "Development",
1786
- reference: [
1787
- '[--no-startup | --totals-only | --accept --reason "<why>"]',
1788
- "developer",
1789
- ["files"]
1790
- ],
1791
- core_weight: core_budget.CORE_WEIGHTS.eslint_scan,
1792
- memory_mb: core_budget.MEMORY_MB.eslint_scan,
1793
- is_kit_only: true
1794
- },
1795
- "refactor:scan": {
1796
- script: "scripts/refactor/refactor-scan-cli.ts",
1797
- description: "List refactoring candidates in the changed scope by category and answer clear/candidates",
1798
- category: "Development",
1799
- reference: ["", "automation", ["processes"]],
1800
- core_weight: core_budget.CORE_WEIGHTS.eslint_scan,
1801
- memory_mb: core_budget.MEMORY_MB.eslint_scan
1802
- },
1803
- bytes: {
1804
- script: "scripts/lines/bytes-command.ts",
1805
- description: "Print an agent-read document's byte size against its ceiling and the headroom left",
1806
- category: "Development",
1807
- reference: [REQUIRED_FILE_ARGUMENTS, "developer", ["none"]]
1808
- },
1809
- "rule:value": {
1810
- script: "scripts/rules/rule-value-cli.ts",
1811
- description: "Print each delivered rule's unaided compliance \u2014 runs reached, kept rate, refusals",
1812
- category: "AI tools",
1813
- reference: ["[--refresh]", "developer", ["files"]]
1814
- },
1815
- "rule:list": {
1816
- script: "scripts/rules/rule-list.ts",
1817
- description: "Print the trigger-delivered rules \u2014 each one's source, firing call and silent turn \u2014 from the guard rows",
1818
- category: "AI tools",
1819
- reference: ["", "automation", ["none"]]
1820
- },
1821
- format: {
1822
- script: "scripts/lint/format.ts",
1823
- description: "Format code with prettier and eslint (skips a tool a basic project lacks)",
1824
- category: "Development",
1825
- reference: ["", "developer", ["files", "processes"]]
1826
- },
1827
- "format:edited": {
1828
- script: "scripts/hooks/format-edited-cli.ts",
1829
- description: "Claude Code hook: format the file just edited (reads the tool call on stdin)",
1830
- category: "Development",
1831
- reference: ["", "automation", ["files", "processes"]]
1832
- },
1833
- "batch:guard": {
1834
- script: "scripts/hooks/batch-guard.ts",
1835
- description: "Claude Code hook: refuse a third consecutive single-call turn (reads the tool call on stdin)",
1836
- category: "Development",
1837
- reference: ["", "automation", ["none"]]
1838
- // **No `tsx_arguments`, deliberately.** `JOSH_BATCH_GUARD` is a per-machine preference kept in
1839
- // `.env`, which every other command reads through `OPTIONAL_ENV_FILE_FLAGS` — but declaring any
1840
- // `tsx_arguments` disqualifies a command from in-process dispatch (`josh-in-process.ts`), and
1841
- // this one runs before every `Bash` call, where a second ~0.16 s tsx start is not affordable.
1842
- // The script calls `process.loadEnvFile` itself instead, which is
1843
- // node's own `--env-file` parser with node's own precedence.
1844
- },
1845
- "pretool:guard": {
1846
- script: "scripts/hooks/pretool-guard-cli.ts",
1847
- description: "Claude Code hook: the batch, investigation and rule guards in one process (reads the tool call on stdin)",
1848
- category: "Development",
1849
- reference: ["", "automation", ["none"]]
1850
- // **No `tsx_arguments`, deliberately**, the same as `batch:guard` above: this is the one
1851
- // PreToolUse hook consumers run before every guarded call, so it must stay eligible for
1852
- // in-process dispatch rather than pay a second tsx start. Each guard it composes loads `.env`
1853
- // through the shared loader.
1854
- },
1855
- "stop:guard": {
1856
- script: "scripts/hooks/stop-guard.ts",
1857
- description: "Claude Code Stop hook: send the hold notify, release the hold and print the issue citations itself; block on the rules that need the model (reads the Stop payload on stdin)",
1858
- category: "Development",
1859
- reference: ["", "automation", ["none"]]
1860
- // **No `tsx_arguments`, deliberately**, the same as `pretool:guard` above: this runs at every
1861
- // turn end, so it must stay eligible for in-process dispatch rather than pay a second tsx start.
1862
- // It loads `.env` through the shared `hook-decision.ts` loader.
1863
- },
1864
- "session:lang": {
1865
- script: "scripts/josh/session-language-cli.ts",
1866
- description: "Claude Code hook: print a non-default JOSH_SESSION_LANG for the session context, and the run:board reply rule while a backlogrun is live (otherwise nothing)",
1867
- category: "Development",
1868
- reference: ["", "automation", ["none"]]
1869
- // **No `tsx_arguments`, deliberately**, the same as `batch:guard` above: this runs on every
1870
- // `UserPromptSubmit`, so it must stay eligible for in-process dispatch rather than pay a second
1871
- // tsx start each turn. It calls `process.loadEnvFile` itself through the shared loader.
1872
- },
1873
- "codex:hook-adapter": {
1874
- script: "scripts/hooks/codex-hook-adapter.ts",
1875
- description: "Codex hook: run the pretool or posttool guard on a Codex payload (reads the tool call on stdin)",
1876
- category: "Development",
1877
- reference: ["<pretool|posttool>", "automation", ["none"]]
1878
- // The live-source fallback `scripts/hooks/run-hook.sh` derives from the `codex-hook-adapter`
1879
- // bundle name. **No `tsx_arguments`**, the same as `pretool:guard`
1880
- // above: it runs before every guarded Codex call.
1881
- },
1882
- "cspell:dot": {
1883
- script: "scripts/lint/cspell-cached.ts",
1884
- description: "Run spell check including dotfiles",
1885
- category: "Development",
1886
- reference: ["", "developer", ["processes"]],
1887
- core_weight: core_budget.CORE_WEIGHTS.spell_check,
1888
- memory_mb: core_budget.MEMORY_MB.spell_check
1889
- },
1890
- behavior: {
1891
- script: "scripts/behavior/behavior-cli.ts",
1892
- description: "Check the current run's recorded transcript against the behavior assertions (no model call)",
1893
- category: "Development",
1894
- reference: ["", "developer", ["files"]]
1895
- },
1896
- "exports:unused": {
1897
- script: "scripts/exports/unused-members-cli.ts",
1898
- description: "Report exported namespace members nothing reads (kit only; a consumer project skips it)",
1899
- category: "Development",
1900
- reference: ["", "developer", ["none"]]
1901
- },
1902
- "test:unit": {
1903
- script: "scripts/test/test-unit-guard.ts",
1904
- description: "Run unit tests with Vitest (without Vitest: a basic project runs its own test script, others skip; fails when Vitest has no tests)",
1905
- category: "Development",
1906
- reference: [FILTER_ARGUMENTS, "developer", ["processes"]],
1907
- core_weight: gate_plan.direct_unit_weight,
1908
- memory_mb: gate_plan.direct_unit_memory
1909
- },
1910
- "test:related": {
1911
- script: "scripts/test/test-related.ts",
1912
- description: "Run only the unit tests related to the changed files (full suite on fallback)",
1913
- category: "Development",
1914
- reference: [FILE_ARGUMENTS, "developer", ["processes"]],
1915
- core_weight: gate_plan.direct_unit_weight,
1916
- memory_mb: gate_plan.direct_unit_memory
1917
- },
1918
- "test:declared": {
1919
- script: "scripts/test/test-declared.ts",
1920
- description: "Report whether the working-tree change needs a test (required/exempt/satisfied); --match checks Step 0 declarations on stdin",
1921
- category: "Development",
1922
- reference: [MATCH_ARGUMENTS, "developer", ["processes"]]
1923
- },
1924
- "test:red": {
1925
- script: "scripts/test/test-red.ts",
1926
- description: "Run the changed unit tests against the pre-fix tree (merge-base worktree) and report red/green/no-test/test-only",
1927
- category: "Development",
1928
- reference: ["", "developer", ["git", "processes"]]
1929
- },
1930
- disposition: {
1931
- script: "scripts/review/disposition-cli.ts",
1932
- description: "Say whether a review finding reaches a runtime path (runtime) or is inert (non-runtime)",
1933
- category: "AI tools",
1934
- reference: [PATH_ARGUMENTS, "automation", ["none"]]
1935
- },
1936
- "e2e:retry-check": {
1937
- script: "scripts/test/e2e-retry-check.ts",
1938
- description: "Report whether the preview server crashed during a failed E2E attempt (CI)",
1939
- category: "Development",
1940
- reference: ["", "automation", ["none"]]
1941
- },
1942
- "test:e2e": {
1943
- script: "scripts/test/test-e2e-guard.ts",
1944
- description: "Run E2E tests with Playwright (skips when absent or no e2e files)",
1945
- category: "Development",
1946
- reference: [FILTER_ARGUMENTS, "developer", ["processes"]]
1947
- },
1948
- test: {
1949
- shell: ["sh", "-c", "pnpm josh test:unit && pnpm josh test:e2e"],
1950
- description: "Run unit and E2E tests",
1951
- category: "Development",
1952
- reference: ["", "developer", ["processes"]],
1953
- argument_targets: ["test:unit", "test:e2e"]
1954
- },
1955
- check: {
1956
- script: "scripts/gate/type-check-command.ts",
1957
- description: "Type-check with tsc (skips a basic project with no TypeScript to check)",
1958
- category: "Development",
1959
- reference: ["[arguments...]", "developer", ["processes"]],
1960
- core_weight: core_budget.CORE_WEIGHTS.type_check,
1961
- memory_mb: core_budget.MEMORY_MB.type_check
1962
- },
1963
- port: {
1964
- script: "scripts/ports/port-command.ts",
1965
- description: "Print the PORT_SEED-resolved dev or preview port",
1966
- category: "Development",
1967
- reference: ["<dev|preview>", "developer", ["none"]]
1968
- }
1969
- };
1970
-
1971
- // scripts/josh/josh-commands-hooks.ts
1972
- var HOOKS_COMMANDS = {
1973
- "prevent-main-commit": {
1974
- script: "scripts/hooks/prevent-main-commit.ts",
1975
- description: "Git hook: block commits to main",
1976
- category: "Git hooks",
1977
- reference: ["", "automation", ["none"]]
1978
- },
1979
- "check-commit-message": {
1980
- script: "scripts/hooks/check-commit-message.ts",
1981
- description: "Git hook: validate commit message",
1982
- category: "Git hooks",
1983
- reference: ["[<message-file>]", "automation", ["none"]]
1984
- },
1985
- "secretlint-scan": {
1986
- script: "scripts/security/secretlint-scan.ts",
1987
- description: "Git hook: scan staged files for secrets",
1988
- category: "Git hooks",
1989
- reference: ["[paths...]", "automation", ["none"]]
1990
- },
1991
- "pre-commit-lint": {
1992
- script: "scripts/hooks/pre-commit-lint.ts",
1993
- description: "Git hook: run cspell, prettier or eslint over staged files from a content cache",
1994
- category: "Git hooks",
1995
- reference: ["<cspell|prettier|eslint> [paths...]", "automation", ["files"]]
1996
- },
1997
- "pre-push-unit": {
1998
- script: "scripts/hooks/pre-push-unit.ts",
1999
- description: "Git hook: run unit tests, reusing a green gate recorded on the pushed tree",
2000
- category: "Git hooks",
2001
- reference: ["", "automation", ["processes"]]
2002
- },
2003
- "reserved-run": {
2004
- script: "scripts/hooks/reserved-run.ts",
2005
- description: "Git hook: run a command while holding a place in the machine-wide core budget",
2006
- category: "Git hooks",
2007
- reference: ["<weight> -- <command...>", "automation", ["processes"]]
2008
- },
2009
- "pre-commit-type-check": {
2010
- script: "scripts/gate/pre-commit-type-check.ts",
2011
- description: "Git hook: type-check, reusing a green gate recorded on the committed tree",
2012
- category: "Git hooks",
2013
- reference: ["", "automation", ["processes"]]
2014
- }
2015
- };
2016
-
2017
- // scripts/josh/josh-commands-lint.ts
2018
- var LINT_COMMANDS = {
2019
- "issue:lint": {
2020
- script: "scripts/issue/issue-lint-cli.ts",
2021
- description: "Check an issue body file for the template's required headings",
2022
- category: "AI tools",
2023
- reference: ["<path>", "automation", ["files"]]
2024
- },
2025
- "issue:backlinks": {
2026
- script: "scripts/issue/issue-backlinks-cli.ts",
2027
- description: "Classify an origin issue\u2019s upstream backlinks: ok, missing, or wrong heading",
2028
- category: "AI tools",
2029
- reference: ["<issue>", "automation", ["network"]]
2030
- },
2031
- "report:lint": {
2032
- script: "scripts/report/report-lint-cli.ts",
2033
- description: "Check a two-layer work summary on stdin against its mechanical format rules",
2034
- category: "AI tools",
2035
- reference: ["(reads stdin)", "automation", ["none"]]
2036
- },
2037
- cases: {
2038
- script: "scripts/cases/cases-cli.ts",
2039
- description: "Read changed paths and print the I/O boundaries crossed and their mandatory abnormal cases: network | process | fs | none",
2040
- category: "AI tools",
2041
- reference: ["<path...>", "automation", ["files"]]
2042
- }
2043
- };
2044
-
2045
- // scripts/josh/josh-commands-maintenance.ts
2046
- var MAINTENANCE_COMMANDS = {
2047
- doctor: {
2048
- script: "scripts/doctor/doctor.ts",
2049
- description: "Diagnose PATH shadowing of the global josh and show the discovered repository map (--fix reclaims a stale shim)",
2050
- category: "Maintenance",
2051
- reference: ["[--fix]", "developer", ["files"]],
2052
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS
2053
- },
2054
- "ruleset:check": {
2055
- script: "scripts/repo/ruleset-check-cli.ts",
2056
- description: "Check that the default branch requires every status check kit's workflows report (--apply adds the missing ones)",
2057
- category: "Maintenance",
2058
- reference: ["[--apply]", "maintainer", ["network"]]
2059
- },
2060
- overrides: {
2061
- script: "scripts/overrides/overrides-check.ts",
2062
- description: "Check pnpm overrides for drift",
2063
- category: "Maintenance",
2064
- reference: ["[--save]", "developer", ["files"]]
2065
- },
2066
- audit: {
2067
- script: "scripts/security/security-audit.ts",
2068
- description: "Run security audit",
2069
- category: "Maintenance",
2070
- reference: ["", "developer", ["processes"]]
2071
- },
2072
- "audit:provision": {
2073
- script: "scripts/security/security-audit-provision.ts",
2074
- description: "Install the pinned osv-scanner when the audit cannot find one (no-op if present)",
2075
- category: "Maintenance",
2076
- reference: ["", "automation", ["files", "network"]]
2077
- },
2078
- "reconcile-templates": {
2079
- script: "scripts/sync/reconcile-templates.ts",
2080
- description: "Record template source hashes (--check to verify drift)",
2081
- category: "Maintenance",
2082
- reference: ["", "maintainer", ["files"]]
2083
- },
2084
- latest: {
2085
- shell: [
2086
- "sh",
2087
- "-c",
2088
- "export NODE_AUTH_TOKEN=$(gh auth token) && pnpm josh latest:guard && pnpm josh latest:update && pnpm josh ranges && pnpm josh audit && pnpm josh latest:corepack && pnpm josh latest:scope --record"
2089
- ],
2090
- description: "Update dependencies, run security audit, then update pnpm",
2091
- category: "Maintenance",
2092
- reference: ["", "developer", ["files", "network", "processes"]],
2093
- argument_targets: ["latest:corepack", "latest:update", "audit"]
2094
- },
2095
- "latest:scope": {
2096
- script: "scripts/version/latest-scope-cli.ts",
2097
- description: "Say whether this run has to update dependencies, from when josh latest last finished (--record notes a run)",
2098
- category: "Maintenance",
2099
- reference: ["[--record] [--json]", "automation", ["files"]],
2100
- // `JOSH_LATEST_MAX_AGE_HOURS` is documented as a project setting, so it has to be readable
2101
- // where the project keeps its settings — a variable that only works when exported from the
2102
- // shell is one a user follows the documentation for and gets the default from, silently.
2103
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS
2104
- },
2105
- "latest:guard": {
2106
- script: "scripts/version/latest-lane-guard.ts",
2107
- description: "Refuse josh latest inside a lane (the update stamp is keyed to the project root)",
2108
- category: "Maintenance",
2109
- reference: ["", "automation", ["files"]]
2110
- },
2111
- "latest:corepack": {
2112
- script: "scripts/version/latest-corepack.ts",
2113
- description: "Update pnpm on the current major while preserving the integrity pin",
2114
- category: "Maintenance",
2115
- reference: ["", "developer", ["files", "network"]]
2116
- },
2117
- "latest:update": {
2118
- script: "scripts/version/latest-update.ts",
2119
- description: "Update all dependencies to latest",
2120
- category: "Maintenance",
2121
- reference: ["", "developer", ["files", "network"]],
2122
- // `JOSH_PLAYWRIGHT_BROWSERS` widens the browsers a Playwright bump installs, and a project
2123
- // keeps that setting in its `.env`.
2124
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS
2125
- }
2126
- };
2127
-
2128
- // scripts/josh/josh-commands-project.ts
2129
- var PROFILE_ARGUMENTS = "[--profile basic|full]";
2130
- var PROJECT_COMMANDS = {
2131
- profile: {
2132
- script: "scripts/init/project-profile-cli.ts",
2133
- description: "Show the project profile and the reason for it",
2134
- category: "Project",
2135
- reference: [PROFILE_ARGUMENTS, "developer", ["files"]]
2136
- },
2137
- start: {
2138
- script: "scripts/init/start.ts",
2139
- description: "Set a project up for the GitHub Issue workflow, from git init to the setup PR",
2140
- category: "Project",
2141
- reference: [
2142
- `${PROFILE_ARGUMENTS} [--yes] [--github] [--public] [--dry-run] [--init-command <command>] [--push-preflight-command <command>]`,
2143
- "developer",
2144
- ["files", "git", "network", "processes"]
2145
- ]
2146
- },
2147
- "dogfood:commit": {
2148
- script: "scripts/dogfood/dogfood-commit-cli.ts",
2149
- description: "Make the first commit of a dogfood run's own kit-test-* project",
2150
- category: "Project",
2151
- reference: ["<dir>", "automation", ["files", "git"]],
2152
- is_kit_only: true
2153
- },
2154
- "fresh:run": {
2155
- script: "scripts/fresh-machine/fresh-machine-cli.ts",
2156
- description: "Run an install scenario in a Docker container of a machine with nothing installed, and keep the log",
2157
- category: "Project",
2158
- reference: [
2159
- "<pattern> | --spec <file.json> [--package-version <version>] [--log-dir <dir>] [--rebuild] | --list",
2160
- "maintainer",
2161
- ["files", "network", "processes"]
2162
- ]
2163
- },
2164
- "auth:setup": {
2165
- script: "scripts/auth/auth-setup-cli.ts",
2166
- description: "Save the long-lived Claude Code token `claude setup-token` prints in the macOS keychain, for josh fresh:run",
2167
- category: "Project",
2168
- reference: ["[--check]", "maintainer", ["network", "processes"]]
2169
- },
2170
- init: {
2171
- script: "scripts/init/init.ts",
2172
- description: "Initialize config in a new project",
2173
- category: "Project",
2174
- reference: [
2175
- `${PROFILE_ARGUMENTS} [--no-install] [--dry-run]`,
2176
- "developer",
2177
- ["files", "network", "processes"]
2178
- ]
2179
- },
2180
- sync: {
2181
- script: "scripts/sync/sync.ts",
2182
- description: "Sync config files",
2183
- category: "Project",
2184
- reference: ["", "developer", ["files"]]
2185
- },
2186
- uninstall: {
2187
- script: "scripts/uninstall/uninstall.ts",
2188
- description: "Remove what kit added to a project and list what is left to review by hand",
2189
- category: "Project",
2190
- reference: [`${PROFILE_ARGUMENTS} [--yes]`, "developer", ["files", "processes"]]
2191
- },
2192
- "registry:migrate": {
2193
- script: "scripts/registry-migration/migrate.ts",
2194
- description: "Migrate a project from GitHub Packages to public npm",
2195
- category: "Project",
2196
- reference: ["", "developer", ["files", "network", "processes"]]
2197
- },
2198
- "sync:scope": {
2199
- script: "scripts/sync/managed-config-scope-cli.ts",
2200
- description: "Say whether this change touches a file josh sync distributes",
2201
- category: "Project",
2202
- reference: ["[--staged] [--json]", "automation", ["none"]]
2203
- },
2204
- "sonar:hotspots": {
2205
- script: "scripts/sonar/sonar-hotspots-cli.ts",
2206
- description: "Fetch SonarCloud hotspots on a pull request and print each one's Step B disposition",
2207
- category: "Project",
2208
- reference: ["<PR>", "automation", ["network"]]
2209
- },
2210
- "sonar:new-code": {
2211
- script: "scripts/sonar/sonar-new-code-cli.ts",
2212
- description: "Fail when a pull request adds any new SonarCloud issue or duplicated block",
2213
- category: "Project",
2214
- reference: ["<PR>", "automation", ["network"]]
2215
- },
2216
- "ui:routes": {
2217
- script: "scripts/ui/ui-routes-cli.ts",
2218
- description: "List the screenshot-target routes the current change touches",
2219
- category: "Project",
2220
- reference: ["[--staged]", "automation", ["none"]]
2221
- },
2222
- propagate: {
2223
- script: "scripts/propagate/propagate.ts",
2224
- description: "Carry the published release into every consumer repository next to this one",
2225
- category: "Project",
2226
- reference: [
2227
- "[--dry-run] [--skip-publish-wait] [--target <repo>]",
2228
- "maintainer",
2229
- ["files", "network"]
2230
- ]
2231
- },
2232
- adopt: {
2233
- script: "scripts/adopt/adopt.ts",
2234
- description: "Upgrade the @joshuafolkken toolkits and other dependencies here, open the PR",
2235
- category: "Project",
2236
- reference: ["[--dry-run]", "developer", ["files", "git", "network", "processes"]]
2237
- }
2238
- };
2239
-
2240
- // scripts/josh/josh-commands-versioning.ts
2241
- var VERSIONING_COMMANDS = {
2242
- bump: {
2243
- script: "scripts/version/bump-version.ts",
2244
- description: "Bump package version",
2245
- category: "Versioning",
2246
- reference: ["[major|minor|patch]", "maintainer", ["files"]]
2247
- },
2248
- version: {
2249
- script: "scripts/version/version-check.ts",
2250
- description: "Show kit versions; --upgrade updates the global and project install",
2251
- category: "Versioning",
2252
- reference: ["[--upgrade]", "developer", ["files", "network", "processes"]]
2253
- },
2254
- // A `script` entry, not a shell one: script paths resolve against the kit package root, so this
2255
- // keeps working from a consumer repo where the file lives under node_modules. The registry
2256
- // probes need NODE_AUTH_TOKEN for any `@joshuafolkken/*` dependency; `josh latest` exports it
2257
- // before chaining here, exactly as it already does for `latest:update`.
2258
- ranges: {
2259
- script: "scripts/version/publishable-range-check.ts",
2260
- description: "Check that every published dependency range still resolves for a consumer and no peer range falls below an installed toolkit",
2261
- category: "Versioning",
2262
- reference: ["", "developer", ["network"]]
2263
- },
2264
- // The one place that decides a version. A `script` entry for the same
2265
- // reason `ranges` is one: script paths resolve against the kit package root, so it keeps working
2266
- // from a consumer repository where the file lives under node_modules.
2267
- release: {
2268
- script: "scripts/release/release-cli.ts",
2269
- description: "Release the merges main has taken since the version last changed",
2270
- category: "Versioning",
2271
- reference: ["[--dry-run]", "maintainer", ["git", "network", "release"]]
2272
- },
2273
- // The read-only half of the one above. `release --dry-run` cannot
2274
- // answer this question: it refuses off the default branch and on a dirty tree, which is every
2275
- // position a run asks it from. A `script` entry for the same reason `release` is one.
2276
- "release:scope": {
2277
- script: "scripts/release/release-scope-cli.ts",
2278
- description: "Say whether a release is owed, from the unreleased merges on main",
2279
- category: "Versioning",
2280
- reference: ["[--json]", "automation", ["none"]]
2281
- },
2282
- // Run by the release workflows, kit's and the one sync distributes, after a tag has published.
2283
- // Settings come from the environment, so the workflow decides them.
2284
- "release:github": {
2285
- script: "scripts/release/github-release-cli.ts",
2286
- description: "Create the GitHub Release for a published tag, with generated notes",
2287
- category: "Versioning",
2288
- reference: ["", "automation", ["network", "release"]]
2289
- }
2290
- };
2291
-
2292
- // scripts/josh/josh-commands-workflow.ts
2293
- var GIT_WORKFLOW_SCRIPT = "scripts/git/git-workflow.ts";
2294
- var GIT_MESSAGE_ARGUMENTS = "[-y] <message>";
2295
- var WORKFLOW_COMMANDS = {
2296
- git: {
2297
- script: GIT_WORKFLOW_SCRIPT,
2298
- description: "Git workflow helper",
2299
- category: "Workflow",
2300
- reference: [GIT_MESSAGE_ARGUMENTS, "developer", ["git", "network"]]
2301
- },
2302
- pr: {
2303
- script: GIT_WORKFLOW_SCRIPT,
2304
- description: "Create PR only (skip commit and push)",
2305
- category: "Workflow",
2306
- // Not `GIT_MESSAGE_ARGUMENTS`: `-y` is already in the default arguments below, so advertising
2307
- // it would document a flag that cannot change what this command does.
2308
- reference: ["<message>", "developer", ["network"]],
2309
- default_script_arguments: ["-y", "--skip-commit", "--skip-push"]
2310
- },
2311
- // **The optional form, on both**. The mandatory `--env-file=.env` is resolved by node before the
2312
- // script's first line: on a machine with no `.env` it dies as `.env: not found` with exit code 9,
2313
- // even where `TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID` exist as real environment variables — a
2314
- // cloud session, and `followup` with them the merge step of every `fullrun` there.
2315
- //
2316
- // Nothing is lost by relaxing it: both scripts already load `.env` through `josh_environment_file`
2317
- // themselves, so the file is read either way and node's precedence — an existing environment
2318
- // variable wins over the file — is node's own in both spellings.
2319
- //
2320
- // **A missing credential still fails loudly**: `telegram_notify.send` throws on missing credentials
2321
- // and on a failed send, so `josh notify` exits non-zero instead of warning and answering 0.
2322
- followup: {
2323
- script: "scripts/followup/git-followup-workflow.ts",
2324
- description: "Follow-up git workflow",
2325
- category: "Workflow",
2326
- reference: [
2327
- "<title> [--notify-message <text>]",
2328
- "automation",
2329
- ["git", "network", "notifications"]
2330
- ],
2331
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS
2332
- },
2333
- notify: {
2334
- script: "scripts/notify/telegram-test.ts",
2335
- description: "Send Telegram notification",
2336
- category: "Workflow",
2337
- reference: [
2338
- "[--task-type <type>] [--body <text> | --body-file <path>] [--issue-url <url>] [--pr-url <url>] [--issue-title <text>] [--repo-name <name>] [--recommended <text>] [--alternative <text>]...",
2339
- "automation",
2340
- ["notifications"]
2341
- ],
2342
- tsx_arguments: OPTIONAL_ENV_FILE_FLAGS
2343
- },
2344
- // One observation-ledger sighting: the key's count, the append and the second-sighting verdict,
2345
- // which a run used to type as a `cat | grep -c` and judge by hand.
2346
- "observation:record": {
2347
- script: "scripts/observations/observation-record-cli.ts",
2348
- description: "Record an observation sighting and answer whether it is now filed",
2349
- category: "Workflow",
2350
- reference: ["<key> <depth> <where> <what> [--checkout <path>]", "automation", ["files"]]
2351
- },
2352
- // The observation ledger's commit path for the lines no run's own commit carried:
2353
- // a lane's lines sit in the primary checkout, which
2354
- // its commit cannot see, and the recurrence count the promotion rule reads is a count of main.
2355
- "observations:flush": {
2356
- script: "scripts/observations/observations-flush-cli.ts",
2357
- description: "Commit the observation ledger as a pull request of its own, and merge it",
2358
- category: "Workflow",
2359
- reference: ["", "automation", ["git", "network"]]
2360
- },
2361
- // The one write path for a `/code-review` round's findings, plus the
2362
- // `--check` gate `followup` runs before it merges. It appends a `- rf:`
2363
- // line per finding — or one zero-finding line for a clean round — to the observation ledger, so
2364
- // `observations:flush` commits them and the recurrence count survives the run.
2365
- "review:record": {
2366
- script: "scripts/review/review-record-cli.ts",
2367
- description: "Record a review round\u2019s findings, or check a round was recorded",
2368
- category: "Workflow",
2369
- reference: [
2370
- "--issue <N> [--comment] [<category>:<severity>:<file> ...] | --check --issue <N>",
2371
- "automation",
2372
- ["files", "network"]
2373
- ]
2374
- },
2375
- // The reader over what `review:record` wrote: each recurring category’s
2376
- // count, and the number of zero-finding rounds that distinguishes a quiet category from an unwatched one.
2377
- "review:findings": {
2378
- script: "scripts/review/review-findings-cli.ts",
2379
- description: "Count review findings by category from the observation ledger",
2380
- category: "Workflow",
2381
- reference: ["", "developer", ["files"]]
2382
- },
2383
- // After a behavior-change Issue merges, re-run its declared baseline and print before/after; a value
2384
- // that did not move appends a refuted-premise line to the observation ledger.
2385
- "measure:rerun": {
2386
- script: "scripts/issue/measure-rerun-cli.ts",
2387
- description: "Re-run a merged issue\u2019s baseline command and print the before/after pair",
2388
- category: "Workflow",
2389
- reference: ["<issue-number>", "automation", ["network", "processes", "files"]]
2390
- },
2391
- // A script rather than an `sh -c` chain, because it has a precondition to enforce: run inside a
2392
- // linked work tree it would hijack the default branch from every other one.
2393
- "main:sync": {
2394
- script: "scripts/git/main-sync.ts",
2395
- description: "Checkout default branch, pull latest, and prune merged remote-gone branches (refuses inside a lane)",
2396
- category: "Workflow",
2397
- reference: ["", "developer", ["git", "network"]]
2398
- },
2399
- // A script rather than an `sh -c` chain, because the strategy has to be named rather than left to
2400
- // the caller's git configuration: a bare `git pull` aborts with `Need to specify how to reconcile
2401
- // divergent branches` on exactly the diverged branch the command exists for.
2402
- //
2403
- // **It declares no core weight, by measurement** (joshuafolkken/kit#3944): its own work is git, and
2404
- // the catalog it may regenerate took 0.6s of CPU. The heavy processes seen beside it are commit
2405
- // hooks — its regenerated catalog's commit runs them — which reserve themselves, and a weight here
2406
- // would set the held mark they inherit, folding the parallel hook tools into this one place.
2407
- "main:merge": {
2408
- script: "scripts/git/main-merge.ts",
2409
- description: "Merge origin default branch into the current branch",
2410
- category: "Workflow",
2411
- reference: ["", "developer", ["git", "network"]]
2412
- }
2413
- };
2414
-
2415
- // scripts/josh/josh-command-map.ts
2416
- var COMMAND_MAP = {
2417
- ...DEV_COMMANDS,
2418
- ...PROJECT_COMMANDS,
2419
- ...WORKFLOW_COMMANDS,
2420
- ...VERSIONING_COMMANDS,
2421
- ...MAINTENANCE_COMMANDS,
2422
- ...HOOKS_COMMANDS,
2423
- ...AI_COMMANDS,
2424
- ...LINT_COMMANDS,
2425
- ...CLONE_COMMANDS
2426
- };
2427
- var ALIASES = {
2428
- ga: "gate",
2429
- l: "lint",
2430
- lr: "lint:related",
2431
- ln: "lines",
2432
- by: "bytes",
2433
- mt: "metrics",
2434
- f: "format",
2435
- sd: "cspell:dot",
2436
- bh: "behavior",
2437
- eu: "exports:unused",
2438
- t: "test",
2439
- tu: "test:unit",
2440
- tr: "test:related",
2441
- td: "test:declared",
2442
- trd: "test:red",
2443
- te: "test:e2e",
2444
- c: "check",
2445
- pt: "port",
2446
- i: "init",
2447
- pf: "profile",
2448
- st: "start",
2449
- sy: "sync",
2450
- un: "uninstall",
2451
- rmi: "registry:migrate",
2452
- g: "git",
2453
- gp: "pr",
2454
- ms: "main:sync",
2455
- mm: "main:merge",
2456
- bp: "bump",
2457
- re: "release",
2458
- v: "version",
2459
- r: "ranges",
2460
- dr: "doctor",
2461
- rc: "ruleset:check",
2462
- pg: "propagate",
2463
- ad: "adopt",
2464
- ov: "overrides",
2465
- a: "audit",
2466
- rt: "reconcile-templates",
2467
- u: "latest",
2468
- lc: "latest:corepack",
2469
- lu: "latest:update",
2470
- tm: "time",
2471
- tmd: "time:density",
2472
- rtr: "retrospective",
2473
- ca: "cost:audit",
2474
- rvf: "review:findings",
2475
- ruv: "rule:value",
2476
- ev: "eval",
2477
- fr: "fresh:run",
2478
- as: "auth:setup",
2479
- lsm: "lane:sample",
2480
- lst: "lane:stats",
2481
- lli: "lane:limit",
2482
- lrs: "lane:restart",
2483
- lwd: "lane:withdraw",
2484
- blr: "backlogrun"
2485
- };
2486
- function canonical_command(name) {
2487
- if (!Object.hasOwn(ALIASES, name)) return name;
2488
- return ALIASES[name] ?? name;
2489
- }
2490
-
2491
- // scripts/time-runtime/time-shell.ts
2492
- var BASH_SEPARATOR = ": ";
2493
- var WHITESPACE_PATTERN = /\s+/u;
2494
- var SEGMENT_PATTERN = /&&|\|\||;|\|/u;
2495
- var PIPE_PATTERN = /(?<!\|)\|(?!\|)/u;
2496
- var CHAIN_PATTERN = /&&|\|\||;|\n/u;
2497
- var QUOTED_SPAN_PATTERN = /\\[\s\S]|'[^']*'|"(?:\\[\s\S]|[^"\\])*"/gu;
2498
- var HEREDOC_MARKER = /(?<!<)<<-?\s*(['"]?)(\w+)\1/u;
2499
- var HEREDOC_DELIMITER_GROUP = 2;
2500
- var LINE_BREAK = "\n";
2501
- var PIPEFAIL_PATTERN = /\bset\s+-[a-z]*o\s+pipefail\b/u;
2502
- var COMMAND_WORD_PATTERN = /^[\w./@:+][\w./@:+-]*$/u;
2503
- var ASSIGNMENT_PATTERN = /^\w+=/u;
2504
- var SUBSHELL_OPENER = "$(";
2505
- var FLAG_PREFIX = "-";
2506
- var WRAPPER_COMMANDS = /* @__PURE__ */ new Set(["time", "env", "sudo"]);
2507
- var NAVIGATION_COMMANDS = /* @__PURE__ */ new Set(["cd", "pushd", "popd", "export", "source", "set", "."]);
2508
- var JOSH_PATTERN = /^(?:pnpm\s+(?:exec\s+)?)?josh\s+([a-z][\w:-]*)/u;
2509
- var JOSH_PREFIX = "josh ";
2510
- var COMMAND_KEY2 = "command";
2511
- function bash_command(input) {
2512
- if (!json_value.is_record(input)) return "";
2513
- const command = input[COMMAND_KEY2];
2514
- return typeof command === "string" ? command : "";
2515
- }
2516
- function is_skippable(word) {
2517
- if (word.startsWith(FLAG_PREFIX)) return true;
2518
- return ASSIGNMENT_PATTERN.test(word) || WRAPPER_COMMANDS.has(word);
2519
- }
2520
- function command_words(segment) {
2521
- const words = segment.replaceAll(SUBSHELL_OPENER, " ").trim().split(WHITESPACE_PATTERN);
2522
- const start = words.findIndex((word) => !is_skippable(word));
2523
- return start === -1 ? [] : words.slice(start);
2524
- }
2525
- function segment_command(segment) {
2526
- const [head] = command_words(segment);
2527
- if (head === void 0 || NAVIGATION_COMMANDS.has(head)) return "";
2528
- return COMMAND_WORD_PATTERN.test(head) ? head : "";
2529
- }
2530
- function command_segment(command) {
2531
- return command.split(SEGMENT_PATTERN).find((segment) => segment_command(segment) !== "") ?? "";
2532
- }
2533
- function leading_word(command) {
2534
- return segment_command(command_segment(command));
2535
- }
2536
- function open_heredoc(line, kept) {
2537
- kept.push(line.replace(HEREDOC_MARKER, " "));
2538
- return HEREDOC_MARKER.exec(line)?.[HEREDOC_DELIMITER_GROUP];
2539
- }
2540
- function close_heredoc(line, delimiter) {
2541
- return line.trim() === delimiter ? void 0 : delimiter;
2542
- }
2543
- function without_heredoc_bodies(command) {
2544
- const kept = [];
2545
- const body = {};
2546
- for (const line of command.split(LINE_BREAK)) {
2547
- body.delimiter = body.delimiter === void 0 ? open_heredoc(line, kept) : close_heredoc(line, body.delimiter);
2548
- }
2549
- return kept.join(LINE_BREAK);
2550
- }
2551
- function unquoted(command) {
2552
- return without_heredoc_bodies(command).replaceAll(QUOTED_SPAN_PATTERN, " ");
2553
- }
2554
- function blanked(command) {
2555
- if (HEREDOC_MARKER.test(command)) return void 0;
2556
- return command.replaceAll(QUOTED_SPAN_PATTERN, (span) => " ".repeat(span.length));
2557
- }
2558
- function discarded_commands(command) {
2559
- const plain = unquoted(command);
2560
- if (PIPEFAIL_PATTERN.test(plain)) return [];
2561
- return plain.split(PIPE_PATTERN).slice(0, -1).map((segment) => segment.split(CHAIN_PATTERN).at(-1) ?? "");
2562
- }
2563
- function bash_label(command) {
2564
- const word = leading_word(command);
2565
- return word === "" ? cost_blocks.BASH_TOOL : `${cost_blocks.BASH_TOOL}${BASH_SEPARATOR}${word}`;
2566
- }
2567
- function josh_command_of_segment(segment) {
2568
- const name = JOSH_PATTERN.exec(command_words(segment).join(" "))?.[1];
2569
- return name === void 0 ? "" : `${JOSH_PREFIX}${canonical_command(name)}`;
2570
- }
2571
- function josh_command_of(command) {
2572
- return josh_command_of_segment(command_segment(command));
2573
- }
2574
- function josh_commands_of(command) {
2575
- return unquoted(command).split(SEGMENT_PATTERN).map((segment) => josh_command_of_segment(segment)).filter((name) => name !== "");
2576
- }
2577
- var REDIRECTION_CHARACTERS = ["<", ">"];
2578
- function is_redirection(word) {
2579
- return REDIRECTION_CHARACTERS.some((character) => word.includes(character));
2580
- }
2581
- function ends_in_redirection(word) {
2582
- return REDIRECTION_CHARACTERS.some((character) => word.endsWith(character));
2583
- }
2584
- function drop_redirections(words) {
2585
- const kept = [];
2586
- let is_target2 = false;
2587
- for (const word of words) {
2588
- const is_dropped = is_target2 || is_redirection(word);
2589
- is_target2 = ends_in_redirection(word);
2590
- if (!is_dropped) kept.push(word);
2591
- }
2592
- return kept;
2593
- }
2594
- function josh_arguments_of_segment(segment) {
2595
- const text = command_words(segment).join(" ");
2596
- const match = JOSH_PATTERN.exec(text);
2597
- if (match === null) return [];
2598
- const words = text.slice(match[0].length).split(WHITESPACE_PATTERN).filter((word) => word !== "");
2599
- return drop_redirections(words);
2600
- }
2601
- function josh_arguments(command) {
2602
- return josh_arguments_of_segment(command_segment(command));
2603
- }
2604
- function josh_signature_of_segment(segment) {
2605
- const name = josh_command_of_segment(segment);
2606
- if (name === "") return "";
2607
- return [name, ...josh_arguments_of_segment(segment)].join(" ");
2608
- }
2609
- function josh_signatures_of(command) {
2610
- return unquoted(command).split(SEGMENT_PATTERN).map((segment) => josh_signature_of_segment(segment)).filter((signature) => signature !== "");
2611
- }
2612
- var time_shell = {
2613
- JOSH_PREFIX,
2614
- bash_command,
2615
- bash_label,
2616
- blanked,
2617
- command_segment,
2618
- discarded_commands,
2619
- josh_arguments,
2620
- josh_command_of,
2621
- josh_commands_of,
2622
- josh_signatures_of,
2623
- leading_word,
2624
- unquoted
2625
- };
2626
-
2627
- // scripts/time-runtime/time-background.ts
2628
- var NO_BACKGROUND = "";
2629
- var NO_FINISH = 0;
2630
- var LAUNCH_PATTERN = /(?:running in background with ID:|moved to the background \(ID:)\s*([\w-]+)/iu;
2631
- var AGENT_LAUNCH_PATTERN = /^Async agent launched[\s\S]*?\bagentId:\s*([\w-]+)/u;
2632
- var FINISH_PATTERN = /^<task-notification>[\s\S]*?<task-id>([\w-]+)<\/task-id>/u;
2633
- var OUTPUT_PATTERN = /tasks\/([\w-]+)\.output/u;
2634
- var BASH_ID_KEY = "bash_id";
2635
- function read_id(command) {
2636
- return OUTPUT_PATTERN.exec(time_shell.unquoted(command))?.[1] ?? NO_BACKGROUND;
2637
- }
2638
- function read_id_of(input) {
2639
- if (!json_value.is_record(input)) return NO_BACKGROUND;
2640
- const id = input[BASH_ID_KEY];
2641
- return typeof id === "string" ? id : read_id(time_shell.bash_command(input));
2642
- }
2643
- function launch_id(text) {
2644
- return LAUNCH_PATTERN.exec(text)?.[1] ?? NO_BACKGROUND;
2645
- }
2646
- function agent_launch_id(text) {
2647
- return AGENT_LAUNCH_PATTERN.exec(text)?.[1] ?? NO_BACKGROUND;
2648
- }
2649
- function finished_id(text) {
2650
- return FINISH_PATTERN.exec(text)?.[1] ?? NO_BACKGROUND;
2651
- }
2652
- function finished_at(lines) {
2653
- const notices = lines.filter((one) => one.finished_background !== NO_BACKGROUND).toSorted((left, right) => right.timestamp_ms - left.timestamp_ms);
2654
- return new Map(notices.map((one) => [one.finished_background, one.timestamp_ms]));
2655
- }
2656
- function started_ms(span) {
2657
- return span.ended_ms - span.duration_ms;
2658
- }
2659
- function read_end_ms(spans, run) {
2660
- if (run.background_ended_ms === NO_FINISH) return void 0;
2661
- const found = spans.find(
2662
- (span) => span.reads_background === run.background_id && span.ended_ms >= run.background_ended_ms
2663
- );
2664
- return found?.ended_ms;
2665
- }
2666
- function to_run(spans, launch) {
2667
- const read = read_end_ms(spans, launch);
2668
- return {
2669
- id: launch.background_id,
2670
- josh_command: launch.josh_command,
2671
- started_ms: started_ms(launch),
2672
- ended_ms: read ?? launch.ended_ms,
2673
- is_read: read !== void 0
2674
- };
2675
- }
2676
- function is_launch(span) {
2677
- return span.background_id !== NO_BACKGROUND;
2678
- }
2679
- function runs(spans) {
2680
- return spans.filter((span) => is_launch(span)).map((launch) => to_run(spans, launch));
2681
- }
2682
- function is_within(span, run) {
2683
- const start = started_ms(span);
2684
- return start >= run.started_ms && start < run.ended_ms;
2685
- }
2686
- function latest_first(all) {
2687
- return all.filter((run) => run.is_read).toSorted((left, right) => right.started_ms - left.started_ms);
2688
- }
2689
- function own_run(span, all) {
2690
- return is_launch(span) ? all.find((run) => run.id === span.background_id) : void 0;
2691
- }
2692
- function placed(span, all, ordered) {
2693
- const own = own_run(span, all);
2694
- const run = own ?? ordered.find((one) => is_within(span, one));
2695
- if (run === void 0) return span;
2696
- const beside = { ...span, background_command: run.josh_command };
2697
- return own === void 0 ? beside : { ...beside, own_duration_ms: own.ended_ms - own.started_ms };
2698
- }
2699
- function positioned(spans) {
2700
- const all = runs(spans);
2701
- if (all.length === 0) return [...spans];
2702
- const ordered = latest_first(all);
2703
- return spans.map((span) => placed(span, all, ordered));
2704
- }
2705
- function unread_phases(spans) {
2706
- const names = runs(spans).filter((run) => !run.is_read).map((run) => COMMAND_PHASES.get(run.josh_command));
2707
- return new Set(names.filter((phase) => phase !== void 0));
2708
- }
2709
- var time_background = {
2710
- NO_BACKGROUND,
2711
- NO_FINISH,
2712
- launch_id,
2713
- agent_launch_id,
2714
- finished_id,
2715
- finished_at,
2716
- read_id,
2717
- read_id_of,
2718
- runs,
2719
- positioned,
2720
- unread_phases
2721
- };
2722
-
2723
- // scripts/gh/git-pr-checks-parse.ts
2724
- var CHECK_STATUS_PASS = "pass";
2725
- var CHECK_STATUS_PENDING = "pending";
2726
- var CHECK_STATUS_FAIL = "fail";
2727
- var CHECK_STATUS_MISSING = "missing";
2728
- var PASSING_CONCLUSIONS = /* @__PURE__ */ new Set(["success", "skipped", "neutral"]);
2729
- var KEY_TYPE_NAME = "__typename";
2730
- var KEY_STATE = "state";
2731
- var KEY_STATUS = "status";
2732
- var KEY_CONCLUSION = "conclusion";
2733
- var KEY_NAME = "name";
2734
- var KEY_CONTEXT = "context";
2735
- var KEY_DESCRIPTION = "description";
2736
- function read_string(value) {
2737
- if (typeof value !== "string") return void 0;
2738
- const trimmed = value.trim();
2739
- if (trimmed.length === 0) return void 0;
2740
- return trimmed;
2741
- }
2742
- var PENDING_STATUS_STATES = /* @__PURE__ */ new Set(["pending", "expected"]);
2743
- function parse_status_context(item) {
2744
- const state = read_string(item[KEY_STATE])?.toLowerCase();
2745
- if (state === "success") return CHECK_STATUS_PASS;
2746
- if (state !== void 0 && PENDING_STATUS_STATES.has(state)) return CHECK_STATUS_PENDING;
2747
- return CHECK_STATUS_FAIL;
2748
- }
2749
- function is_passing_conclusion(item) {
2750
- const conclusion = read_string(item[KEY_CONCLUSION])?.toLowerCase();
2751
- return conclusion !== void 0 && PASSING_CONCLUSIONS.has(conclusion);
2752
- }
2753
- function parse_check_run(item) {
2754
- const status = read_string(item[KEY_STATUS])?.toLowerCase();
2755
- if (status !== "completed") return CHECK_STATUS_PENDING;
2756
- return is_passing_conclusion(item) ? CHECK_STATUS_PASS : CHECK_STATUS_FAIL;
2757
- }
2758
- function parse_rollup_status(item) {
2759
- const type_name = read_string(item[KEY_TYPE_NAME]);
2760
- if (type_name === "StatusContext") return parse_status_context(item);
2761
- return parse_check_run(item);
2762
- }
2763
- function read_rollup_array(parsed) {
2764
- const result = pr_raw_schema.safeParse(parsed);
2765
- if (!result.success) return [];
2766
- return result.data.statusCheckRollup ?? [];
2767
- }
2768
- function parse_rollup_item(item) {
2769
- const name = read_string(item[KEY_NAME]) ?? read_string(item[KEY_CONTEXT]);
2770
- if (name === void 0) return void 0;
2771
- const check = { name, status: parse_rollup_status(item) };
2772
- const description = read_string(item[KEY_DESCRIPTION]);
2773
- return description === void 0 ? check : { ...check, description };
2774
- }
2775
- function parse_rollup_checks(raw_json) {
2776
- const parsed = json_value.parse_or_undefined(raw_json);
2777
- const rollup = read_rollup_array(parsed);
2778
- const checks = [];
2779
- for (const item of rollup) {
2780
- const parsed_item = parse_rollup_item(item);
2781
- if (parsed_item !== void 0) checks.push(parsed_item);
2782
- }
2783
- return checks;
2784
- }
2785
- function parse_pr_state_snapshot(raw_json) {
2786
- const parsed = json_value.parse_or_undefined(raw_json);
2787
- const result = pr_raw_schema.safeParse(parsed);
2788
- const data = result.success ? result.data : void 0;
2789
- return {
2790
- rollup: parse_rollup_checks(raw_json),
2791
- merge_state_status: read_string(data?.mergeStateStatus),
2792
- review_decision: read_string(data?.reviewDecision)
2793
- };
2794
- }
2795
-
2796
- // scripts/gh/git-pr-checks-eval.ts
2797
- var DEFAULT_REQUIRED_CHECKS = ["SonarQube"];
2798
- var CODERABBIT_CHECK_NAME = "CodeRabbit";
2799
- var REQUIRED_CHECKS_ENV_VAR = "JOSH_REQUIRED_CHECKS";
2800
- function parse_required_checks() {
2801
- const raw = process.env[REQUIRED_CHECKS_ENV_VAR];
2802
- if (!raw) return DEFAULT_REQUIRED_CHECKS;
2803
- return raw.split(",").map((check) => check.trim()).filter((check) => check.length > 0);
2804
- }
2805
- var REQUIRED_CHECKS = parse_required_checks();
2806
- var MERGE_STATE_CLEAN = "CLEAN";
2807
- var MERGE_STATE_UNSTABLE = "UNSTABLE";
2808
- var MERGE_STATE_DIRTY = "DIRTY";
2809
- var REVIEW_CHANGES_REQUESTED = "CHANGES_REQUESTED";
2810
- var CHECK_SUITE_SEPARATOR = " / ";
2811
- var FAILURE_MESSAGE_PREFIX = "PR checks failed";
2812
- var FAILURE_REASON_REVIEW = "review requested changes";
2813
- var FAILURE_REASON_CHECKS = "failed checks";
2814
- var FAILURE_REASON_CONFLICT = "merge conflict";
2815
- function is_required_match(check_name, required_name) {
2816
- if (check_name === required_name) return true;
2817
- return check_name.startsWith(`${required_name}${CHECK_SUITE_SEPARATOR}`);
2818
- }
2819
- function find_required_check(checks, required_name) {
2820
- return checks.find((check) => is_required_match(check.name, required_name));
2821
- }
2822
- function read_required_statuses(checks) {
2823
- return REQUIRED_CHECKS.map(
2824
- (name) => find_required_check(checks, name)?.status ?? CHECK_STATUS_MISSING
2825
- );
2826
- }
2827
- function is_review_blocked(review_decision) {
2828
- return review_decision === REVIEW_CHANGES_REQUESTED;
2829
- }
2830
- function is_merge_conflict(merge_state_status) {
2831
- return merge_state_status === MERGE_STATE_DIRTY;
2832
- }
2833
- function evaluate_failure_state(input) {
2834
- if (is_merge_conflict(input.merge_state_status) || is_review_blocked(input.review_decision) || input.failed_checks.length > 0) {
2835
- return "failure";
2836
- }
2837
- return void 0;
2838
- }
2839
- function is_merge_state_clean(merge_state_status) {
2840
- return merge_state_status === MERGE_STATE_CLEAN;
2841
- }
2842
- function is_every_required_passing(statuses) {
2843
- return statuses.every((status) => status === CHECK_STATUS_PASS);
2844
- }
2845
- function is_coderabbit_check(check_name) {
2846
- return is_required_match(check_name, CODERABBIT_CHECK_NAME);
2847
- }
2848
- function is_unstable_only_from_coderabbit(snapshot) {
2849
- if (snapshot.merge_state_status !== MERGE_STATE_UNSTABLE) return false;
2850
- const non_passing = snapshot.rollup.filter((check) => check.status !== CHECK_STATUS_PASS);
2851
- if (non_passing.length === 0) return false;
2852
- return non_passing.every((check) => is_coderabbit_check(check.name));
2853
- }
2854
- function is_required_check(check_name) {
2855
- return REQUIRED_CHECKS.some((required) => is_required_match(check_name, required));
2856
- }
2857
- function is_blocking_failure(check) {
2858
- if (check.status !== CHECK_STATUS_FAIL) return false;
2859
- return !is_coderabbit_check(check.name) || is_required_check(check.name);
2860
- }
2861
- function collect_blocking_failures(snapshot) {
2862
- return snapshot.rollup.filter((check) => is_blocking_failure(check)).map((check) => check.name);
2863
- }
2864
- function is_mergeable_state(snapshot) {
2865
- if (is_merge_state_clean(snapshot.merge_state_status)) return true;
2866
- return is_unstable_only_from_coderabbit(snapshot);
2867
- }
2868
- function collect_failure_reasons(snapshot) {
2869
- const reasons = [];
2870
- if (is_merge_conflict(snapshot.merge_state_status)) reasons.push(FAILURE_REASON_CONFLICT);
2871
- if (is_review_blocked(snapshot.review_decision)) reasons.push(FAILURE_REASON_REVIEW);
2872
- const failed = collect_blocking_failures(snapshot);
2873
- if (failed.length > 0) reasons.push(`${FAILURE_REASON_CHECKS}: ${failed.join(", ")}`);
2874
- return reasons;
2875
- }
2876
- function describe_pr_failure(snapshot) {
2877
- const reasons = collect_failure_reasons(snapshot);
2878
- if (reasons.length === 0) return `${FAILURE_MESSAGE_PREFIX}.`;
2879
- return `${FAILURE_MESSAGE_PREFIX} (${reasons.join("; ")}).`;
2880
- }
2881
- function evaluate_pr_state(snapshot) {
2882
- const statuses = read_required_statuses(snapshot.rollup);
2883
- const failure = evaluate_failure_state({
2884
- review_decision: snapshot.review_decision,
2885
- failed_checks: collect_blocking_failures(snapshot),
2886
- merge_state_status: snapshot.merge_state_status
2887
- });
2888
- if (failure !== void 0) return failure;
2889
- if (is_mergeable_state(snapshot) && is_every_required_passing(statuses)) return "success";
2890
- return "pending";
2891
- }
2892
- function is_review_decision_decisive(snapshot) {
2893
- return evaluate_pr_state(snapshot) !== "pending";
2894
- }
2895
- var PrConflictError = class extends Error {
2896
- name = "PrConflictError";
2897
- };
2898
-
2899
- // scripts/lane/lane-ledger.ts
2900
- import { closeSync, constants, openSync, writeSync } from "node:fs";
2901
- import { z as z3 } from "zod";
2902
- var LEDGER_PREFIX = "josh-lane-ledger-";
2903
- var LEDGER_SUFFIX = ".jsonl";
2904
- var LINE_SEPARATOR = "\n";
2905
- var CI_WAIT_STAGE = "ci-wait";
2906
- var LEDGER_FILE_MODE = 384;
2907
- var { O_APPEND, O_CREAT, O_NOFOLLOW, O_WRONLY } = constants;
2908
- var APPEND_FLAGS = O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW;
2909
- var KIND = {
2910
- MERGE: "merge",
2911
- GATE: "gate",
2912
- LOAD: "load",
2913
- DISPATCH: "dispatch",
2914
- STAGE: "stage",
2915
- STOP: "stop",
2916
- OVERLAP: "overlap"
2917
- };
2918
- var merge_schema = z3.object({ kind: z3.literal(KIND.MERGE), at: z3.string(), issue: z3.number() });
2919
- var check_schema = z3.object({
2920
- label: z3.string(),
2921
- elapsed_ms: z3.number(),
2922
- is_passed: z3.boolean(),
2923
- is_reused: z3.boolean().optional()
2924
- });
2925
- var gate_schema = z3.object({
2926
- kind: z3.literal(KIND.GATE),
2927
- at: z3.string(),
2928
- elapsed_ms: z3.number(),
2929
- is_passed: z3.boolean(),
2930
- // The unit suite's own duration, present when this gate ran it — the one
2931
- // record of a full vitest run `josh metrics` reads, so the suite is never timed twice.
2932
- unit_ms: z3.number().optional(),
2933
- // The whole cores busy outside this gate, beyond the machine's baseline, at its start or its end —
2934
- // whichever was higher. Absent when the machine could not be read.
2935
- external_cores: z3.number().optional(),
2936
- // Each check's own duration and verdict, so `josh lane:stats` can name the check a slow gate waited
2937
- // on. A reused check started no process: its row says so, and its zero is no timing.
2938
- checks: z3.array(check_schema).optional()
2939
- });
2940
- var process_kind_schema = z3.object({
2941
- kind: z3.string(),
2942
- cpu_percent: z3.number(),
2943
- rss_mb: z3.number(),
2944
- count: z3.number()
2945
- });
2946
- var load_schema = z3.object({
2947
- kind: z3.literal(KIND.LOAD),
2948
- at: z3.string(),
2949
- load: z3.number(),
2950
- available_mb: z3.number().optional(),
2951
- swapped_mb: z3.number().optional(),
2952
- lanes: z3.number().optional(),
2953
- // The heaviest process kinds at the instant of the sample (`lane-process-load.ts`), so the load the
2954
- // core budget's ledger does not explain can be read back by what made it (joshuafolkken/kit#3874).
2955
- processes: z3.array(process_kind_schema).optional()
2956
- });
2957
- var dispatch_schema = z3.object({
2958
- kind: z3.literal(KIND.DISPATCH),
2959
- at: z3.string(),
2960
- issue: z3.number()
2961
- });
2962
- var stage_schema = z3.object({
2963
- kind: z3.literal(KIND.STAGE),
2964
- at: z3.string(),
2965
- stage: z3.string(),
2966
- elapsed_ms: z3.number(),
2967
- issue: z3.number().optional()
2968
- });
2969
- var stop_schema = z3.object({
2970
- kind: z3.literal(KIND.STOP),
2971
- at: z3.string(),
2972
- issue: z3.number(),
2973
- reason: z3.string()
2974
- });
2975
- var overlap_schema = z3.object({
2976
- kind: z3.literal(KIND.OVERLAP),
2977
- at: z3.string(),
2978
- issue: z3.number(),
2979
- lanes: z3.array(z3.number()),
2980
- paths: z3.array(z3.string()),
2981
- waited_ms: z3.number(),
2982
- is_cleared: z3.boolean()
2983
- });
2984
- var entry_schema = z3.discriminatedUnion("kind", [
2985
- merge_schema,
2986
- gate_schema,
2987
- load_schema,
2988
- dispatch_schema,
2989
- stage_schema,
2990
- stop_schema,
2991
- overlap_schema
2992
- ]);
2993
- function target_of(repository) {
2994
- return stamp_file.stamp_path(LEDGER_PREFIX, repository, LEDGER_SUFFIX);
2995
- }
2996
- async function target() {
2997
- if (process.env["VITEST"] !== void 0) return void 0;
2998
- try {
2999
- const repository = await run_carry.repository_directory();
3000
- return repository === void 0 ? void 0 : target_of(repository);
3001
- } catch {
3002
- return void 0;
3003
- }
3004
- }
3005
- function append(path5, entry) {
3006
- const descriptor = openSync(path5, APPEND_FLAGS, LEDGER_FILE_MODE);
3007
- try {
3008
- if (stamp_file.is_own_regular_file(path5)) {
3009
- writeSync(descriptor, `${JSON.stringify(entry)}${LINE_SEPARATOR}`);
3010
- }
3011
- } finally {
3012
- closeSync(descriptor);
3013
- }
3014
- }
3015
- async function record(entry, path5) {
3016
- try {
3017
- const destination = path5 ?? await target();
3018
- if (destination !== void 0) append(destination, entry);
3019
- } catch {
3020
- }
3021
- }
3022
- function now_iso() {
3023
- return (/* @__PURE__ */ new Date()).toISOString();
3024
- }
3025
- async function record_gate(path5, gate) {
3026
- await record({ kind: KIND.GATE, at: now_iso(), ...gate }, path5);
3027
- }
3028
- async function record_merge(issue) {
3029
- await record({ kind: KIND.MERGE, at: now_iso(), issue });
3030
- }
3031
- async function record_dispatch(issue, path5) {
3032
- await record({ kind: KIND.DISPATCH, at: now_iso(), issue }, path5);
3033
- }
3034
- async function record_stage(stage, path5) {
3035
- await record({ kind: KIND.STAGE, at: now_iso(), ...stage }, path5);
3036
- }
3037
- async function record_stop(stop, path5) {
3038
- await record({ kind: KIND.STOP, at: now_iso(), ...stop }, path5);
3039
- }
3040
- async function record_overlap(overlap, path5) {
3041
- await record({ kind: KIND.OVERLAP, at: now_iso(), ...overlap }, path5);
3042
- }
3043
- function parse_line2(line) {
3044
- return entry_schema.safeParse(json_value.parse_or_undefined(line)).data;
3045
- }
3046
- function is_present(entry) {
3047
- return entry !== void 0;
3048
- }
3049
- function read_entries(path5) {
3050
- const raw = stamp_file.read_stamp_text(path5);
3051
- if (raw === void 0) return [];
3052
- return raw.split(LINE_SEPARATOR).map((line) => parse_line2(line.trim())).filter(is_present);
3053
- }
3054
- var lane_ledger = {
3055
- CI_WAIT_STAGE,
3056
- KIND,
3057
- append,
3058
- read_entries,
3059
- record,
3060
- record_dispatch,
3061
- record_gate,
3062
- record_merge,
3063
- record_overlap,
3064
- record_stage,
3065
- record_stop,
3066
- target,
3067
- target_of
3068
- };
3069
-
3070
- // scripts/time-runtime/time-format.ts
3071
- var MS_PER_MINUTE = 6e4;
3072
- var MS_PER_SECOND2 = 1e3;
3073
- var MINUTE_DECIMALS = 1;
3074
- var SECOND_DECIMALS = 1;
3075
- var PERCENT_SCALE = 100;
3076
- var PERCENT_DECIMALS = 1;
3077
- var LABEL_WIDTH = 24;
3078
- var MINUTES_WIDTH = 9;
3079
- var NOT_MEASURED = "not measured";
3080
- var NO_CALLS = "no tool call to divide";
3081
- var MAX_ROWS = 15;
3082
- function overflow_line(row_count) {
3083
- if (row_count <= MAX_ROWS) return [];
3084
- return [
3085
- ` \u2026 and ${String(row_count - MAX_ROWS)} more (--json carries every row this report holds)`
3086
- ];
3087
- }
3088
- function format_minutes(duration_ms) {
3089
- return `${(duration_ms / MS_PER_MINUTE).toFixed(MINUTE_DECIMALS)} min`;
3090
- }
3091
- function format_seconds(duration_ms) {
3092
- return `${(duration_ms / MS_PER_SECOND2).toFixed(SECOND_DECIMALS)} s`;
3093
- }
3094
- function format_share(part, whole) {
3095
- if (whole === 0) return "n/a";
3096
- return `${(part / whole * PERCENT_SCALE).toFixed(PERCENT_DECIMALS)}%`;
3097
- }
3098
- function usd(amount, decimals) {
3099
- return `$${amount.toFixed(decimals)}`;
3100
- }
3101
- function format_columns(label, minutes, suffix) {
3102
- return ` ${label.padEnd(LABEL_WIDTH)}${minutes.padStart(MINUTES_WIDTH)} ${suffix}`;
3103
- }
3104
- function format_row(label, duration_ms, suffix) {
3105
- return format_columns(label, format_minutes(duration_ms), suffix);
3106
- }
3107
- function unmeasured_row(label) {
3108
- return format_columns(label, "", NOT_MEASURED);
3109
- }
3110
- var time_format = {
3111
- MAX_ROWS,
3112
- NO_CALLS,
3113
- overflow_line,
3114
- format_seconds,
3115
- format_share,
3116
- usd,
3117
- format_columns,
3118
- format_row,
3119
- // `format_clock` stays private: `format_window` is its only caller, and a namespace that offers
3120
- // both invites a second renderer to join the two with its own arrow.
3121
- unmeasured_row
3122
- };
3123
-
3124
- // scripts/followup/git-followup-stages.ts
3125
- var STAGE_LINE_PREFIX = "followup stage: ";
3126
- var STAGE_TOTAL_PREFIX = "followup stages total: ";
3127
- var STAGE_NAME_WIDTH = 26;
3128
- var VALUE_COLUMN = STAGE_LINE_PREFIX.length + STAGE_NAME_WIDTH;
3129
- var NO_DURATION = 0;
3130
- var STAGE = {
3131
- closes_and_context: "closes-and-context",
3132
- checks_wait: "checks-wait",
3133
- coderabbit_comments: "coderabbit-comments",
3134
- ai_review_comments: "ai-review-comments",
3135
- telegram: "telegram",
3136
- merge: "merge",
3137
- completion_and_epic_close: "completion-and-epic-close",
3138
- // The lap that was still running when a stage threw. `followup` exits non-zero on an AI-review
3139
- // blocker and on a red check, and those are the runs whose wait is longest — reporting nothing for
3140
- // them would leave the measurement blind to exactly the invocations worth measuring.
3141
- interrupted: "interrupted",
3142
- // The interrupted lap when the wait failed on a merge conflict, so the
3143
- // stage block names the cause a resumed session would otherwise look up with `gh pr view`.
3144
- conflict: "conflict"
3145
- };
3146
- function stopped_lap(error) {
3147
- return error instanceof PrConflictError ? STAGE.conflict : STAGE.interrupted;
3148
- }
3149
- function new_log() {
3150
- return { stages: [], last_ms: performance.now() };
3151
- }
3152
- function lap(log, name) {
3153
- const now_ms = performance.now();
3154
- log.stages.push({ name, duration_ms: now_ms - log.last_ms });
3155
- log.last_ms = now_ms;
3156
- }
3157
- function total_ms(stages) {
3158
- return stages.reduce((sum, stage) => sum + stage.duration_ms, NO_DURATION);
3159
- }
3160
- function format_stage(stage) {
3161
- const name = stage.name.padEnd(STAGE_NAME_WIDTH);
3162
- return `${STAGE_LINE_PREFIX}${name}${time_format.format_seconds(stage.duration_ms)}`;
3163
- }
3164
- function format_stages(log) {
3165
- if (log.stages.length === 0) return [];
3166
- const rows = log.stages.map((stage) => format_stage(stage));
3167
- const total = time_format.format_seconds(total_ms(log.stages));
3168
- return ["", ...rows, `${STAGE_TOTAL_PREFIX.padEnd(VALUE_COLUMN)}${total}`];
3169
- }
3170
- function print_stages(log) {
3171
- for (const line of format_stages(log)) console.info(line);
3172
- }
3173
- async function record_ci_wait(log) {
3174
- const wait = log.stages.find((stage) => stage.name === STAGE.checks_wait);
3175
- if (wait === void 0) return;
3176
- await lane_ledger.record_stage({
3177
- stage: lane_ledger.CI_WAIT_STAGE,
3178
- elapsed_ms: wait.duration_ms
3179
- });
3180
- }
3181
- var git_followup_stages = {
3182
- STAGE,
3183
- STAGE_LINE_PREFIX,
3184
- STAGE_TOTAL_PREFIX,
3185
- new_log,
3186
- lap,
3187
- total_ms,
3188
- format_stages,
3189
- print_stages,
3190
- record_ci_wait,
3191
- stopped_lap
3192
- };
3193
-
3194
- // scripts/time-runtime/time-followup-stage.ts
3195
- var LINE_SEPARATOR2 = "\n";
3196
- var SECONDS_SUFFIX = " s";
3197
- var DIGIT_OR_POINT = /[\d.]/u;
3198
- var MS_PER_SECOND3 = 1e3;
3199
- var NO_STAGES = [];
3200
- function stage_body(line) {
3201
- const trimmed = line.trimStart();
3202
- if (!trimmed.startsWith(git_followup_stages.STAGE_LINE_PREFIX)) return void 0;
3203
- return trimmed.slice(git_followup_stages.STAGE_LINE_PREFIX.length);
3204
- }
3205
- function digits_start(head) {
3206
- let index = head.length;
3207
- while (index > 0 && DIGIT_OR_POINT.test(head.charAt(index - 1))) index -= 1;
3208
- return index;
3209
- }
3210
- function is_duration(digits) {
3211
- return digits !== "" && Number.isFinite(Number(digits));
3212
- }
3213
- function to_stage(body) {
3214
- const text = body.trimEnd();
3215
- if (!text.endsWith(SECONDS_SUFFIX)) return void 0;
3216
- const head = text.slice(0, -SECONDS_SUFFIX.length);
3217
- const start = digits_start(head);
3218
- const name = head.slice(0, start).trim();
3219
- const digits = head.slice(start);
3220
- if (name === "" || !is_duration(digits)) return void 0;
3221
- return { name, duration_ms: Number(digits) * MS_PER_SECOND3 };
3222
- }
3223
- function read_stages(text) {
3224
- if (!text.includes(git_followup_stages.STAGE_LINE_PREFIX)) return NO_STAGES;
3225
- return text.split(LINE_SEPARATOR2).map((line) => stage_body(line)).filter((body) => body !== void 0).map((body) => to_stage(body)).filter((stage) => stage !== void 0);
3226
- }
3227
- var time_followup_stage = { NO_STAGES, read_stages };
3228
-
3229
- // scripts/time-runtime/time-reported-failure.ts
3230
- import { z as z4 } from "zod";
3231
- var TEXT_BLOCK_SCHEMA = z4.object({ text: z4.string().nullish() });
3232
- var CONTENT_SCHEMA = z4.union([z4.string(), z4.array(z4.unknown())]);
3233
- var LINE_SEPARATOR3 = "\n";
3234
- function block_text(block) {
3235
- const parsed = TEXT_BLOCK_SCHEMA.safeParse(block);
3236
- return parsed.success ? parsed.data.text ?? "" : "";
3237
- }
3238
- function result_text2(content) {
3239
- const parsed = CONTENT_SCHEMA.safeParse(content);
3240
- if (!parsed.success) return "";
3241
- if (typeof parsed.data === "string") return parsed.data;
3242
- return parsed.data.map((block) => block_text(block)).join(LINE_SEPARATOR3);
3243
- }
3244
- function is_failure_line(line) {
3245
- return line.trimStart().startsWith(status_icons.FAIL_ICON);
3246
- }
3247
- function is_failed_verdict(line) {
3248
- return josh_verdict.read_verdict(line) === josh_verdict.FAILED_VERDICT;
3249
- }
3250
- var GREEN_VERDICTS = /* @__PURE__ */ new Set([
3251
- josh_verdict.PASSED_VERDICT,
3252
- josh_verdict.UNVERIFIED_VERDICT
3253
- ]);
3254
- function is_green_verdict(line) {
3255
- return GREEN_VERDICTS.has(josh_verdict.read_verdict(line));
3256
- }
3257
- function new_scan() {
3258
- return {
3259
- did_find: false,
3260
- has_failure_before_region: false,
3261
- has_failure_in_region: false,
3262
- is_region_open: false
3263
- };
3264
- }
3265
- function close_region(scan) {
3266
- scan.did_find ||= scan.is_region_open && scan.has_failure_before_region;
3267
- scan.has_failure_before_region = false;
3268
- scan.has_failure_in_region = false;
3269
- scan.is_region_open = false;
3270
- }
3271
- function note_failure(scan) {
3272
- if (scan.is_region_open) {
3273
- scan.has_failure_in_region = true;
3274
- return;
3275
- }
3276
- scan.has_failure_before_region = true;
3277
- }
3278
- function scan_line(scan, line) {
3279
- if (is_green_verdict(line)) {
3280
- close_region(scan);
3281
- return;
3282
- }
3283
- if (is_failure_line(line)) {
3284
- note_failure(scan);
3285
- return;
3286
- }
3287
- if (josh_verdict.is_gate_opening(line)) scan.is_region_open = true;
3288
- }
3289
- function scan_body(lines) {
3290
- const scan = new_scan();
3291
- for (const line of lines) scan_line(scan, line);
3292
- return scan;
3293
- }
3294
- function did_scan_find(scan) {
3295
- return scan.did_find || scan.has_failure_before_region || scan.has_failure_in_region;
3296
- }
3297
- function has_failure_line(content) {
3298
- const lines = result_text2(content).split(LINE_SEPARATOR3);
3299
- if (lines.some((line) => is_failed_verdict(line))) return true;
3300
- return did_scan_find(scan_body(lines));
3301
- }
3302
- function is_reported_failure(josh_command, did_print_failure) {
3303
- return josh_command !== "" && did_print_failure;
3304
- }
3305
- var time_reported_failure = { result_text: result_text2, has_failure_line, is_reported_failure };
3306
-
3307
- // scripts/time-runtime/time-bundle-call.ts
3308
- var { BASH_TOOL: BASH_TOOL2 } = cost_blocks;
3309
- var BUNDLEABLE_TOOLS = /* @__PURE__ */ new Set(["Edit", "Glob", "Grep", "Read", "WebFetch", "WebSearch", "Write"]);
3310
- var LAUNCH_TOOLS = /* @__PURE__ */ new Set(["Agent", "Task"]);
3311
- var PRIOR_REFERENCE_MARKERS = [
3312
- "previous finding",
3313
- "prior finding",
3314
- "earlier finding",
3315
- "previous result",
3316
- "prior result",
3317
- "earlier result",
3318
- "based on the previous",
3319
- "based on the earlier",
3320
- "from the previous agent",
3321
- "from the prior agent",
3322
- "the finding above",
3323
- "as found earlier",
3324
- "as found above",
3325
- "building on the previous"
3326
- ];
3327
- var READ_COMMANDS = /* @__PURE__ */ new Set([
3328
- "awk",
3329
- "basename",
3330
- "cat",
3331
- "comm",
3332
- "cut",
3333
- "diff",
3334
- "dirname",
3335
- "du",
3336
- "echo",
3337
- "file",
3338
- "find",
3339
- "gh",
3340
- "grep",
3341
- "head",
3342
- "jq",
3343
- "ls",
3344
- "nl",
3345
- "printf",
3346
- "pwd",
3347
- "realpath",
3348
- "rg",
3349
- // **`sed -i` is deliberately not excluded.** An in-place edit is what `Edit` does, and `Edit` is on
3350
- // the allow-list above — a turn may issue several of them, so rejecting the shell spelling of the
3351
- // same thing would exclude a call the tool form counts. Two in-place edits of the *same* file are
3352
- // caught by the target test instead, which is where that ordering actually lives.
3353
- "sed",
3354
- "sort",
3355
- "stat",
3356
- "tail",
3357
- "tree",
3358
- "uniq",
3359
- "wc",
3360
- "which"
3361
- ]);
3362
- var MUTATION_WORDS = /* @__PURE__ */ new Set([
3363
- "--field",
3364
- "--method",
3365
- "--raw-field",
3366
- "-F",
3367
- "-X",
3368
- "-delete",
3369
- "-exec",
3370
- "-f",
3371
- "add",
3372
- "chmod",
3373
- "chown",
3374
- "close",
3375
- "comment",
3376
- "cp",
3377
- "create",
3378
- "dd",
3379
- "delete",
3380
- "edit",
3381
- "git",
3382
- "install",
3383
- "kill",
3384
- "ln",
3385
- "merge",
3386
- "mkdir",
3387
- "mv",
3388
- "node",
3389
- "npm",
3390
- "npx",
3391
- "pkill",
3392
- "pnpm",
3393
- "remove",
3394
- "rm",
3395
- "scp",
3396
- "secret",
3397
- "set",
3398
- "ssh",
3399
- "sudo",
3400
- "tee",
3401
- "touch",
3402
- "truncate",
3403
- "tsx",
3404
- "upload",
3405
- "wget"
3406
- ]);
3407
- var READ_JOSH_SUBCOMMANDS = /* @__PURE__ */ new Set([
3408
- "backlog:budget",
3409
- "backlog:next",
3410
- "cost",
3411
- "delegate",
3412
- "epic:audit",
3413
- "epic:bundle",
3414
- "epic:check",
3415
- "epic:next",
3416
- "issue:read",
3417
- "issue:scout",
3418
- "issue:state",
3419
- "lane:list",
3420
- "latest:scope",
3421
- "release:scope",
3422
- "review:brief",
3423
- "review:round2",
3424
- "run:liveness"
3425
- ]);
3426
- var JOSH_WORD = "josh";
3427
- var JOSH_SCRIPT_SUFFIX = "josh.ts";
3428
- var COMMAND_CHAIN = /[|;&`>]|\$\(/u;
3429
- var WHITESPACE_PATTERN2 = /\s+/u;
3430
- var TARGET_FIELDS = ["file_path", "notebook_path", "path", "url"];
3431
- var TARGET_ARRAY_FIELD = "file_paths";
3432
- var MAX_TARGETS = 8;
3433
- var WORD_PATTERN = /[\s'"=(),;:|&]+/u;
3434
- var EXTENSION_PATTERN = /^[A-Za-z]+$/u;
3435
- var MAX_EXTENSION = 5;
3436
- var AFTER_DOT = 1;
3437
- var FIRST_INDEX = 0;
3438
- var CURRENT_DIRECTORY = "./";
3439
- var LAST_CHARACTER = -1;
3440
- var FLAG_PREFIX2 = "-";
3441
- var PATH_SEPARATOR = "/";
3442
- var MIN_TARGET_LENGTH = 3;
3443
- var WRITING_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "NotebookEdit"]);
3444
- var WRITING_WORDS = /* @__PURE__ */ new Set(["dd", "sed", "tee"]);
3445
- var REDIRECTION = ">";
3446
- var IN_PLACE_COMMAND = "sed";
3447
- var IN_PLACE_FLAG_PATTERN = /^--in-place\b|^-[A-Za-z]*i/u;
3448
- function not_bundleable() {
3449
- return {
3450
- is_bundleable: false,
3451
- targets: [],
3452
- is_writing: false,
3453
- may_write: false,
3454
- has_prior_reference: false
3455
- };
3456
- }
3457
- function is_launch_tool(name) {
3458
- return LAUNCH_TOOLS.has(name);
3459
- }
3460
- function words_of(command) {
3461
- return command.split(WORD_PATTERN).filter((word) => word !== "");
3462
- }
3463
- function has_mutation(command) {
3464
- return words_of(command).some((word) => MUTATION_WORDS.has(word));
3465
- }
3466
- function josh_subcommand(command) {
3467
- const tokens = command.split(WHITESPACE_PATTERN2).filter((token) => token !== "");
3468
- const josh_index = tokens.findIndex(
3469
- (token) => token === JOSH_WORD || token.endsWith(JOSH_SCRIPT_SUFFIX)
3470
- );
3471
- return josh_index < FIRST_INDEX ? void 0 : tokens[josh_index + 1];
3472
- }
3473
- function is_read_josh(command) {
3474
- if (COMMAND_CHAIN.test(command)) return false;
3475
- const subcommand = josh_subcommand(command);
3476
- if (subcommand === void 0) return false;
3477
- return READ_JOSH_SUBCOMMANDS.has(canonical_command(subcommand));
3478
- }
3479
- function may_write_command(command) {
3480
- if (command.includes(REDIRECTION)) return true;
3481
- return words_of(command).some((word) => WRITING_WORDS.has(word));
3482
- }
3483
- function write_segment(command) {
3484
- return time_shell.command_segment(time_shell.unquoted(command));
3485
- }
3486
- function is_in_place_sed(segment) {
3487
- if (time_shell.leading_word(segment) !== IN_PLACE_COMMAND) return false;
3488
- return words_of(segment).some((word) => IN_PLACE_FLAG_PATTERN.test(word));
3489
- }
3490
- function normalize(word) {
3491
- const head = word.startsWith(CURRENT_DIRECTORY) ? word.slice(CURRENT_DIRECTORY.length) : word;
3492
- return head.endsWith(PATH_SEPARATOR) ? head.slice(0, LAST_CHARACTER) : head;
3493
- }
3494
- function has_extension(word) {
3495
- const dot = word.lastIndexOf(".");
3496
- if (dot <= FIRST_INDEX) return false;
3497
- const suffix = word.slice(dot + AFTER_DOT);
3498
- return suffix.length <= MAX_EXTENSION && EXTENSION_PATTERN.test(suffix);
3499
- }
3500
- function is_target(word) {
3501
- if (word.startsWith(FLAG_PREFIX2) || word.length < MIN_TARGET_LENGTH) return false;
3502
- return word.includes(PATH_SEPARATOR) || has_extension(word);
3503
- }
3504
- function targets_in(text) {
3505
- return words_of(text).map((word) => normalize(word)).filter((word) => is_target(word)).slice(0, MAX_TARGETS);
3506
- }
3507
- function field_text(input, field) {
3508
- if (!json_value.is_record(input)) return "";
3509
- const value = input[field];
3510
- return typeof value === "string" ? value : "";
3511
- }
3512
- function field_targets(input) {
3513
- if (!json_value.is_record(input)) return [];
3514
- const value = input[TARGET_ARRAY_FIELD];
3515
- return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
3516
- }
3517
- function tool_targets(input) {
3518
- const scalar_targets = TARGET_FIELDS.map((field) => field_text(input, field));
3519
- const targets = [...scalar_targets, ...field_targets(input)].map((target2) => normalize(target2));
3520
- return [...new Set(targets)].filter((target2) => target2 !== "");
3521
- }
3522
- function prompt_references_prior(input) {
3523
- const prompt = field_text(input, "prompt").toLowerCase();
3524
- return PRIOR_REFERENCE_MARKERS.some((marker) => prompt.includes(marker));
3525
- }
3526
- function tool_facts(name, input) {
3527
- const writes = { is_writing: WRITING_TOOLS.has(name), may_write: WRITING_TOOLS.has(name) };
3528
- const has_prior_reference = LAUNCH_TOOLS.has(name) && prompt_references_prior(input);
3529
- if (!BUNDLEABLE_TOOLS.has(name)) return { ...not_bundleable(), ...writes, has_prior_reference };
3530
- return { is_bundleable: true, targets: tool_targets(input), ...writes, has_prior_reference };
3531
- }
3532
- function bash_facts(command) {
3533
- const writes = {
3534
- is_writing: is_in_place_sed(write_segment(command)),
3535
- may_write: may_write_command(command)
3536
- };
3537
- if (is_read_josh(command)) {
3538
- return {
3539
- is_bundleable: true,
3540
- targets: targets_in(time_shell.unquoted(command)),
3541
- ...writes,
3542
- has_prior_reference: false
3543
- };
3544
- }
3545
- if (!READ_COMMANDS.has(time_shell.leading_word(command)) || has_mutation(command)) {
3546
- return { ...not_bundleable(), ...writes };
3547
- }
3548
- return {
3549
- is_bundleable: true,
3550
- targets: targets_in(time_shell.unquoted(command)),
3551
- ...writes,
3552
- has_prior_reference: false
3553
- };
3554
- }
3555
- function call_facts(name, input) {
3556
- if (name !== BASH_TOOL2) return tool_facts(name, input);
3557
- return bash_facts(time_shell.bash_command(input));
3558
- }
3559
- var time_bundle_call = {
3560
- MAX_TARGETS,
3561
- not_bundleable,
3562
- bash_facts,
3563
- call_facts,
3564
- tool_facts,
3565
- // Exported for `time-agent-bundles.ts`, which asks the launch question of a
3566
- // span's `label` — the tool name for a non-Bash call — so the set lives in one place.
3567
- is_launch_tool,
3568
- // Exported for `time-writes.ts`, which asks what a call *wrote* rather
3569
- // than what it named. The extraction is the same one either way — a second copy of it would let a
3570
- // path be recognized as a target when read and missed when written.
3571
- targets_in,
3572
- tool_targets,
3573
- // Exported for the batching guard's own word scan, so the two scanners
3574
- // cannot come to disagree about where one word of a shell line ends and the next begins.
3575
- // Exported for the read-fold notice, which offers `read:files <path>` only
3576
- // over file-shaped targets — a bare directory like `scripts/` is a target here but not something
3577
- // `read:files` can read, so the notice reuses this test rather than keep a second copy that could
3578
- // drift from what counts as a file path.
3579
- has_extension,
3580
- // Exported for `time-writes.ts`, which needs the same two answers to say
3581
- // *which* files an in-place `sed` wrote. Two copies of this test disagreed in both directions at
3582
- // once — one called a piped `grep -i` a write, the other missed a bundled `sed -ni`.
3583
- write_segment,
3584
- is_in_place_sed,
3585
- // Exported for the drift test in `time-bundle-call.test.ts`, which pins that
3586
- // every name here is a real `josh` command and none of them writes.
3587
- READ_JOSH_SUBCOMMANDS
3588
- };
3589
-
3590
- // scripts/cost-runtime/cost-attribute.ts
3591
- var ISSUE_BRANCH_PATTERN = /^(\d+)-/u;
3592
- var UNATTRIBUTED_KEY = -1;
3593
- function issue_from_branch(branch) {
3594
- const matched = ISSUE_BRANCH_PATTERN.exec(branch);
3595
- return matched?.[1] === void 0 ? UNATTRIBUTED_KEY : Number(matched[1]);
3596
- }
3597
- function declared_issue(record2) {
3598
- const declared = record2.issue ?? UNATTRIBUTED_KEY;
3599
- return declared === UNATTRIBUTED_KEY ? issue_from_branch(record2.branch) : declared;
3600
- }
3601
- function fill(declared, is_reverse) {
3602
- const filled = Array.from({ length: declared.length }, () => UNATTRIBUTED_KEY);
3603
- const order = declared.map((_value, index) => is_reverse ? declared.length - 1 - index : index);
3604
- let carried = UNATTRIBUTED_KEY;
3605
- for (const index of order) {
3606
- const own = declared[index] ?? UNATTRIBUTED_KEY;
3607
- carried = own === UNATTRIBUTED_KEY ? carried : own;
3608
- filled[index] = carried;
3609
- }
3610
- return filled;
3611
- }
3612
- function is_attributed(value) {
3613
- return value !== void 0 && value !== UNATTRIBUTED_KEY;
3614
- }
3615
- function pick(own, carried, next, previous) {
3616
- if (is_attributed(own)) return own;
3617
- if (is_attributed(carried)) return carried;
3618
- if (is_attributed(next)) return next;
3619
- return previous ?? UNATTRIBUTED_KEY;
3620
- }
3621
- function announcements(records) {
3622
- return fill(
3623
- records.map((record2) => record2.issue ?? UNATTRIBUTED_KEY),
3624
- false
3625
- );
3626
- }
3627
- function attribute(records) {
3628
- const declared = records.map((record2) => declared_issue(record2));
3629
- const carried = announcements(records);
3630
- const next = fill(declared, true);
3631
- const previous = fill(declared, false);
3632
- return declared.map(
3633
- (own, index) => pick(own, carried[index] ?? UNATTRIBUTED_KEY, next[index], previous[index])
3634
- );
3635
- }
3636
- function group_by_issue(records) {
3637
- const issues = attribute(records);
3638
- const grouped = /* @__PURE__ */ new Map();
3639
- for (const [index, record2] of records.entries()) {
3640
- const bucket = grouped.get(issues[index] ?? UNATTRIBUTED_KEY) ?? [];
3641
- bucket.push(record2);
3642
- grouped.set(issues[index] ?? UNATTRIBUTED_KEY, bucket);
3643
- }
3644
- return [...grouped].toSorted(([left], [right]) => left - right).map(([issue, bucket]) => ({ issue, records: bucket }));
3645
- }
3646
- function records_for_issue(records, issue_number) {
3647
- const issues = attribute(records);
3648
- return records.filter((_record, index) => issues[index] === issue_number);
3649
- }
3650
- var cost_attribute = {
3651
- UNATTRIBUTED_KEY,
3652
- issue_from_branch,
3653
- declared_issue,
3654
- attribute,
3655
- group_by_issue,
3656
- records_for_issue
3657
- };
3658
-
3659
- // scripts/time-runtime/time-markers.ts
3660
- var NO_MARKER = "none";
3661
- var PLAN_MARKER = "plan";
3662
- var EDIT_MARKER = "edit";
3663
- var REVIEW_MARKER = "review";
3664
- var WORKFLOW_MARKER = "workflow";
3665
- var EDIT_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
3666
- var SKILL_TOOL = "Skill";
3667
- var SKILL_KEY = "skill";
3668
- var REVIEW_SKILL = "code-review";
3669
- var WORKFLOW_SKILL = "workflow-commands";
3670
- var AGENT_TOOL = "Agent";
3671
- var PROMPT_KEY = "prompt";
3672
- var REVIEW_INVOCATION = "/code-review";
3673
- var REVIEW_ATTEST = "review:attest";
3674
- var SKILL_MARKERS = /* @__PURE__ */ new Map([
3675
- [REVIEW_SKILL, REVIEW_MARKER],
3676
- [WORKFLOW_SKILL, WORKFLOW_MARKER]
3677
- ]);
3678
- var ISSUE_API_PATTERN = /repos\/\S+\/issues\/\d+/u;
3679
- var BODY_FIELD_PATTERN = /\bbody=/u;
3680
- var ISSUE_COMMENT_PATTERN = /\bgh\s+issue\s+comment\b/u;
3681
- var BODY_FLAG_PATTERN = /--body(?:-file)?\b/u;
3682
- var ISSUE_LABELS_PATTERN = /repos\/\S+\/issues\/(\d+)\/labels\b(?!\/)/u;
3683
- var IN_PROGRESS_FIELD = "labels[]=in-progress";
3684
- var RUN_ENTRY_PATTERN = /\bjosh\s+run:entry\s+(\d+)\b/u;
3685
- var NO_ISSUE = cost_attribute.UNATTRIBUTED_KEY;
3686
- function string_field(input, key) {
3687
- if (!json_value.is_record(input)) return "";
3688
- const value = input[key];
3689
- return typeof value === "string" ? value : "";
3690
- }
3691
- function skill_name(input) {
3692
- return string_field(input, SKILL_KEY);
3693
- }
3694
- function agent_marker(input) {
3695
- const prompt = string_field(input, PROMPT_KEY);
3696
- const is_review = prompt.includes(REVIEW_INVOCATION) && prompt.includes(REVIEW_ATTEST);
3697
- return is_review ? REVIEW_MARKER : NO_MARKER;
3698
- }
3699
- function tool_marker(name, input) {
3700
- if (EDIT_TOOLS.has(name)) return EDIT_MARKER;
3701
- if (name === AGENT_TOOL) return agent_marker(input);
3702
- if (name !== SKILL_TOOL) return NO_MARKER;
3703
- return SKILL_MARKERS.get(skill_name(input)) ?? NO_MARKER;
3704
- }
3705
- function is_api_body_write(command) {
3706
- return ISSUE_API_PATTERN.test(command) && BODY_FIELD_PATTERN.test(command);
3707
- }
3708
- function is_issue_comment(command) {
3709
- return ISSUE_COMMENT_PATTERN.test(command) && BODY_FLAG_PATTERN.test(command);
3710
- }
3711
- function is_in_progress_label(command) {
3712
- return ISSUE_LABELS_PATTERN.test(command) && command.includes(IN_PROGRESS_FIELD);
3713
- }
3714
- function is_run_start(command) {
3715
- return is_in_progress_label(command) || RUN_ENTRY_PATTERN.test(command);
3716
- }
3717
- var COMMAND_SEPARATOR = /&&|\|\||;/u;
3718
- function declared_issue2(part) {
3719
- const pattern = is_in_progress_label(part) ? ISSUE_LABELS_PATTERN : RUN_ENTRY_PATTERN;
3720
- const matched = pattern.exec(part);
3721
- return matched?.[1] === void 0 ? NO_ISSUE : Number(matched[1]);
3722
- }
3723
- function bash_issue(command) {
3724
- for (const part of command.split(COMMAND_SEPARATOR)) {
3725
- if (is_run_start(part)) return declared_issue2(part);
3726
- }
3727
- return NO_ISSUE;
3728
- }
3729
- function bash_marker(command) {
3730
- if (is_run_start(command)) return WORKFLOW_MARKER;
3731
- return is_api_body_write(command) || is_issue_comment(command) ? PLAN_MARKER : NO_MARKER;
3732
- }
3733
- var time_markers = {
3734
- NO_MARKER,
3735
- PLAN_MARKER,
3736
- EDIT_MARKER,
3737
- REVIEW_MARKER,
3738
- WORKFLOW_MARKER,
3739
- NO_ISSUE,
3740
- tool_marker,
3741
- bash_marker,
3742
- bash_issue
3743
- };
3744
-
3745
- // scripts/time-runtime/time-single-check.ts
3746
- var CHECK_COMMANDS = /* @__PURE__ */ new Set([
3747
- "josh check",
3748
- "josh cspell",
3749
- "josh cspell:dot",
3750
- "josh lint",
3751
- "josh lint:related",
3752
- "josh test:related",
3753
- "josh test:unit"
3754
- ]);
3755
- var NO_CHECK = "";
3756
- var KEY_SEPARATOR = " ";
3757
- function argument_key(command) {
3758
- return [...new Set(time_shell.josh_arguments(command))].toSorted(
3759
- (left, right) => left.localeCompare(right)
3760
- );
3761
- }
3762
- function check_key(josh_command, command) {
3763
- if (!CHECK_COMMANDS.has(josh_command)) return NO_CHECK;
3764
- return [josh_command, ...argument_key(command)].join(KEY_SEPARATOR);
3765
- }
3766
- var time_single_check = { NO_CHECK, check_key };
3767
-
3768
- // scripts/time-runtime/time-transcript-line.ts
3769
- import { z as z5 } from "zod";
3770
- var BLOCK_SCHEMA2 = z5.object({
3771
- type: z5.string().nullish(),
3772
- name: z5.string().nullish(),
3773
- id: z5.string().nullish(),
3774
- tool_use_id: z5.string().nullish(),
3775
- input: z5.unknown().nullish(),
3776
- // Whether the harness wrote this result back as a failure. Present on a
3777
- // `tool_result` block and on nothing else, and absent even there for the tools that never report
3778
- // one — which is why it is read as three answers rather than as a boolean with a default.
3779
- is_error: z5.boolean().nullish(),
3780
- // What the call printed. Read only to recover the outcome a pipeline threw away:
3781
- // it is kept as flattened text rather than as blocks, because that is
3782
- // the whole of what `time-reported-failure.ts` asks of it.
3783
- content: z5.unknown().nullish()
3784
- });
3785
- var CONTENT_SCHEMA2 = z5.union([z5.string(), z5.array(BLOCK_SCHEMA2)]);
3786
- var MESSAGE_SCHEMA2 = z5.object({ id: z5.string().nullish(), content: CONTENT_SCHEMA2.nullish() });
3787
- var LINE_SCHEMA = z5.object({
3788
- type: z5.string().nullish(),
3789
- timestamp: z5.string().nullish(),
3790
- // The branch the line was written on, which is where the issue number lives — `josh git` names a
3791
- // branch `<N>-<slug>`. Read here rather than re-parsed by a second reader so `josh time --issue`
3792
- // and `josh cost --issue` answer from the same field.
3793
- gitBranch: z5.string().nullish(),
3794
- // The two fields outside `message` that the harness writes an end-of-task notice on.
3795
- // **Both are read as `unknown` rather than as strings**: a schema
3796
- // insisting on a string here would reject every line whose `content` is a list of blocks — which is
3797
- // most of them — and a rejected line is dropped from the timeline entirely, so the shares would stop
3798
- // reconstructing the elapsed time. The shape is checked at the read below instead.
3799
- content: z5.unknown().nullish(),
3800
- attachment: z5.unknown().nullish(),
3801
- message: MESSAGE_SCHEMA2.nullish()
3802
- });
3803
- var UNKNOWN_BRANCH = "";
3804
- var PROMPT_KEY2 = "prompt";
3805
- var NO_MESSAGE_ID = "";
3806
- var ERROR_TEXT_LIMIT = 256;
3807
- var REFUSAL_MARKER = "\u26D4";
3808
- var HOOK_ERROR_LABEL = /^PreToolUse:\S+ hook error: /u;
3809
- var STOP_FEEDBACK_LABEL = /^Stop hook feedback:\s*/u;
3810
- var TOKEN_LINE = /^[a-z][a-z-]*$/u;
3811
- var TOKEN_LINE_LIMIT = 8;
3812
- function block_names(raw) {
3813
- return {
3814
- type: raw.type ?? "",
3815
- name: raw.name ?? "",
3816
- id: raw.id ?? "",
3817
- result_id: raw.tool_use_id ?? ""
3818
- };
3819
- }
3820
- function guard_from_refusal(text) {
3821
- const trimmed = text.trimStart().replace(HOOK_ERROR_LABEL, "");
3822
- if (!trimmed.startsWith(REFUSAL_MARKER)) return "";
3823
- const headline = trimmed.slice(REFUSAL_MARKER.length).split("\n", 1)[0]?.trimStart() ?? "";
3824
- const colon = headline.indexOf(":");
3825
- return (colon === -1 ? headline : headline.slice(0, colon)).trim();
3826
- }
3827
- function stop_guard_of(data) {
3828
- const content = data.message?.content;
3829
- if (typeof content !== "string" || !STOP_FEEDBACK_LABEL.test(content)) return "";
3830
- return guard_from_refusal(content.replace(STOP_FEEDBACK_LABEL, ""));
3831
- }
3832
- function token_lines_of(text) {
3833
- return text.split("\n").map((line) => line.trim()).filter((line) => TOKEN_LINE.test(line)).slice(0, TOKEN_LINE_LIMIT);
3834
- }
3835
- function to_block2(raw) {
3836
- const text = time_reported_failure.result_text(raw.content);
3837
- const is_error = raw.is_error ?? void 0;
3838
- return {
3839
- ...block_names(raw),
3840
- input: raw.input,
3841
- is_error,
3842
- has_failure_line: time_reported_failure.has_failure_line(text),
3843
- followup_stages: time_followup_stage.read_stages(text),
3844
- error_text: is_error === true ? text.slice(0, ERROR_TEXT_LIMIT) : "",
3845
- refusal_guard: is_error === true ? guard_from_refusal(text) : "",
3846
- token_lines: is_error === true ? [] : token_lines_of(text),
3847
- background_id: time_background.launch_id(text),
3848
- agent_id: time_background.agent_launch_id(text)
3849
- };
3850
- }
3851
- function to_blocks2(content) {
3852
- return typeof content === "string" || content === null || content === void 0 ? [] : content.map((block) => to_block2(block));
3853
- }
3854
- function message_fields(message) {
3855
- return { message_id: message?.id ?? NO_MESSAGE_ID, blocks: to_blocks2(message?.content) };
3856
- }
3857
- function notice_text(data) {
3858
- const attachment = json_value.is_record(data.attachment) ? data.attachment[PROMPT_KEY2] : void 0;
3859
- const carried = [data.message?.content, data.content, attachment];
3860
- return carried.find((one) => typeof one === "string") ?? "";
3861
- }
3862
- function to_line(data) {
3863
- const timestamp_ms = time_instant.parse_instant(data.timestamp);
3864
- if (timestamp_ms === void 0) return void 0;
3865
- return {
3866
- type: data.type ?? "",
3867
- timestamp_ms,
3868
- branch: data.gitBranch ?? UNKNOWN_BRANCH,
3869
- finished_background: time_background.finished_id(notice_text(data)),
3870
- stop_guard: stop_guard_of(data),
3871
- ...message_fields(data.message)
3872
- };
3873
- }
3874
- function parse_line3(line) {
3875
- const parsed = LINE_SCHEMA.safeParse(json_value.parse_or_undefined(line));
3876
- return parsed.success ? to_line(parsed.data) : void 0;
3877
- }
3878
- function parse_text(text) {
3879
- return text.split("\n").flatMap((line) => parse_line3(line) ?? []);
3880
- }
3881
- var time_transcript_line = {
3882
- ERROR_TEXT_LIMIT,
3883
- NO_MESSAGE_ID,
3884
- TOKEN_LINE_LIMIT,
3885
- guard_from_refusal,
3886
- parse_line: parse_line3,
3887
- parse_text
3888
- };
3889
-
3890
- // scripts/time-runtime/time-writes.ts
3891
- function bash_writes(command) {
3892
- const segment = time_bundle_call.write_segment(command);
3893
- return time_bundle_call.is_in_place_sed(segment) ? time_bundle_call.targets_in(segment) : [];
3894
- }
3895
- function tool_writes(name, input) {
3896
- if (time_markers.tool_marker(name, input) !== time_markers.EDIT_MARKER) return [];
3897
- return time_bundle_call.tool_targets(input);
3898
- }
3899
- var time_writes = {
3900
- bash_writes,
3901
- tool_writes
3902
- };
3903
-
3904
- // scripts/time-runtime/time-tool-call.ts
3905
- var { NO_MESSAGE_ID: NO_MESSAGE_ID2 } = time_transcript_line;
3906
- var UNKNOWN_TOOL = "unknown";
3907
- var NO_CALL = {
3908
- label: "",
3909
- josh_command: "",
3910
- josh_commands: [],
3911
- josh_signatures: [],
3912
- check_key: time_single_check.NO_CHECK,
3913
- marker: time_markers.NO_MARKER,
3914
- message_id: NO_MESSAGE_ID2,
3915
- writes: [],
3916
- issue: time_markers.NO_ISSUE,
3917
- reads_background: time_background.NO_BACKGROUND,
3918
- ...time_bundle_call.not_bundleable()
3919
- };
3920
- var UNKNOWN_CALL = {
3921
- label: UNKNOWN_TOOL,
3922
- josh_command: "",
3923
- josh_commands: [],
3924
- josh_signatures: [],
3925
- check_key: time_single_check.NO_CHECK,
3926
- marker: time_markers.NO_MARKER,
3927
- message_id: NO_MESSAGE_ID2,
3928
- writes: [],
3929
- issue: time_markers.NO_ISSUE,
3930
- reads_background: time_background.NO_BACKGROUND,
3931
- ...time_bundle_call.not_bundleable()
3932
- };
3933
- function non_bash_call(name, input, message_id) {
3934
- return {
3935
- label: name,
3936
- josh_command: "",
3937
- josh_commands: [],
3938
- josh_signatures: [],
3939
- check_key: time_single_check.NO_CHECK,
3940
- marker: time_markers.tool_marker(name, input),
3941
- message_id,
3942
- writes: time_writes.tool_writes(name, input),
3943
- issue: time_markers.NO_ISSUE,
3944
- // A non-Bash tool joins a backgrounded command too — `BashOutput` carries the shell id in a
3945
- // field of its own, `Monitor` names the same `…/tasks/<id>.output` path in a command — so the
3946
- // same reader is asked here rather than the field being left empty for every tool but `Bash`.
3947
- reads_background: time_background.read_id_of(input),
3948
- ...time_bundle_call.tool_facts(name, input)
3949
- };
3950
- }
3951
- function bash_call(input, message_id) {
3952
- const command = time_shell.bash_command(input);
3953
- const josh_command = time_shell.josh_command_of(command);
3954
- return {
3955
- label: time_shell.bash_label(command),
3956
- josh_command,
3957
- josh_commands: time_shell.josh_commands_of(command),
3958
- josh_signatures: time_shell.josh_signatures_of(command),
3959
- check_key: time_single_check.check_key(josh_command, command),
3960
- marker: time_markers.bash_marker(command),
3961
- message_id,
3962
- writes: time_writes.bash_writes(command),
3963
- issue: time_markers.bash_issue(command),
3964
- reads_background: time_background.read_id_of(input),
3965
- ...time_bundle_call.bash_facts(command)
3966
- };
3967
- }
3968
- function to_tool_call(name, input, message_id) {
3969
- if (name !== cost_blocks.BASH_TOOL) return non_bash_call(name, input, message_id);
3970
- return bash_call(input, message_id);
3971
- }
3972
- var time_tool_call = {
3973
- UNKNOWN_TOOL,
3974
- NO_CALL,
3975
- UNKNOWN_CALL,
3976
- to_tool_call
3977
- };
3978
-
3979
- // scripts/time-runtime/time-spans.ts
3980
- var { NO_MESSAGE_ID: NO_MESSAGE_ID3, parse_line: parse_line4 } = time_transcript_line;
3981
- var { NO_CALL: NO_CALL2, UNKNOWN_CALL: UNKNOWN_CALL2, UNKNOWN_TOOL: UNKNOWN_TOOL2, to_tool_call: to_tool_call2 } = time_tool_call;
3982
- var ASSISTANT_TYPE = "assistant";
3983
- var USER_TYPE = "user";
3984
- var MODEL_CATEGORY = "model";
3985
- var TOOL_CATEGORY = "tool";
3986
- var HUMAN_CATEGORY = "human";
3987
- var OK_OUTCOME = "ok";
3988
- var FAILED_OUTCOME = "failed";
3989
- var UNKNOWN_OUTCOME = "unknown";
3990
- var NO_RESULT = {
3991
- call_id: "",
3992
- outcome: UNKNOWN_OUTCOME,
3993
- refusal_guard: "",
3994
- background_id: time_background.NO_BACKGROUND,
3995
- followup_stages: time_followup_stage.NO_STAGES
3996
- };
3997
- function tool_use_blocks(lines) {
3998
- return lines.flatMap(
3999
- (line) => line.blocks.filter((block) => block.type === cost_blocks.TOOL_USE_TYPE && block.id !== "").map((block) => ({ block, message_id: line.message_id }))
4000
- );
4001
- }
4002
- function collect_calls(lines) {
4003
- return new Map(
4004
- tool_use_blocks(lines).map(({ block, message_id }) => [
4005
- block.id,
4006
- to_tool_call2(block.name, block.input, message_id)
4007
- ])
4008
- );
4009
- }
4010
- function result_block(line) {
4011
- return line.blocks.find((block) => block.type === cost_blocks.TOOL_RESULT_TYPE);
4012
- }
4013
- function event_of(line, category, call, result = NO_RESULT) {
4014
- return { timestamp_ms: line.timestamp_ms, branch: line.branch, category, ...result, ...call };
4015
- }
4016
- function outcome_of(result, call) {
4017
- if (time_reported_failure.is_reported_failure(call.josh_command, result.has_failure_line)) {
4018
- return FAILED_OUTCOME;
4019
- }
4020
- if (result.is_error === void 0) return UNKNOWN_OUTCOME;
4021
- return result.is_error ? FAILED_OUTCOME : OK_OUTCOME;
4022
- }
4023
- function facts_of(result, call) {
4024
- return {
4025
- call_id: result.result_id,
4026
- outcome: outcome_of(result, call),
4027
- refusal_guard: result.refusal_guard,
4028
- background_id: result.background_id,
4029
- followup_stages: result.followup_stages
4030
- };
4031
- }
4032
- function user_event(line, calls) {
4033
- const result = result_block(line);
4034
- if (result === void 0) return event_of(line, HUMAN_CATEGORY, NO_CALL2);
4035
- const call = calls.get(result.result_id) ?? UNKNOWN_CALL2;
4036
- return event_of(line, TOOL_CATEGORY, call, facts_of(result, call));
4037
- }
4038
- function to_event(line, calls) {
4039
- if (line.type === ASSISTANT_TYPE) {
4040
- return event_of(line, MODEL_CATEGORY, { ...NO_CALL2, message_id: line.message_id });
4041
- }
4042
- return line.type === USER_TYPE ? user_event(line, calls) : void 0;
4043
- }
4044
- function to_events(lines, calls) {
4045
- return lines.map((line) => to_event(line, calls)).filter((event) => event !== void 0).toSorted((left, right) => left.timestamp_ms - right.timestamp_ms);
4046
- }
4047
- function equal_durations(duration_ms) {
4048
- return { duration_ms, own_duration_ms: duration_ms };
4049
- }
4050
- function no_background() {
4051
- const none = time_background.NO_BACKGROUND;
4052
- return {
4053
- background_id: none,
4054
- reads_background: none,
4055
- background_command: none,
4056
- background_ended_ms: time_background.NO_FINISH
4057
- };
4058
- }
4059
- function background_fields(event, finished) {
4060
- return {
4061
- background_id: event.background_id,
4062
- reads_background: event.reads_background,
4063
- background_command: time_background.NO_BACKGROUND,
4064
- background_ended_ms: finished.get(event.background_id) ?? time_background.NO_FINISH
4065
- };
4066
- }
4067
- function result_facts_of(event) {
4068
- return {
4069
- call_id: event.call_id,
4070
- outcome: event.outcome,
4071
- refusal_guard: event.refusal_guard,
4072
- followup_stages: event.followup_stages
4073
- };
4074
- }
4075
- function to_spans(events, finished) {
4076
- return events.slice(1).map((event, index) => ({
4077
- category: event.category,
4078
- label: event.label,
4079
- josh_command: event.josh_command,
4080
- josh_commands: event.josh_commands,
4081
- josh_signatures: event.josh_signatures,
4082
- check_key: event.check_key,
4083
- marker: event.marker,
4084
- is_bundleable: event.is_bundleable,
4085
- targets: event.targets,
4086
- is_writing: event.is_writing,
4087
- may_write: event.may_write,
4088
- has_prior_reference: event.has_prior_reference,
4089
- writes: event.writes,
4090
- message_id: event.message_id,
4091
- issue: event.issue,
4092
- branch: event.branch,
4093
- ...result_facts_of(event),
4094
- is_continuation: false,
4095
- ...background_fields(event, finished),
4096
- ended_ms: event.timestamp_ms,
4097
- ...equal_durations(event.timestamp_ms - (events[index]?.timestamp_ms ?? event.timestamp_ms))
4098
- }));
4099
- }
4100
- function parse_timeline(text) {
4101
- const lines = text.split("\n").map((line) => parse_line4(line)).filter((line) => line !== void 0);
4102
- const events = to_events(lines, collect_calls(lines));
4103
- return {
4104
- started_ms: events[0]?.timestamp_ms ?? 0,
4105
- ended_ms: events.at(-1)?.timestamp_ms ?? 0,
4106
- // **The positioning happens here rather than in a caller**: a launch and
4107
- // the call that reads its output are in one transcript, and by the time spans have been merged
4108
- // across sessions and trimmed they are fragments rather than calls.
4109
- spans: time_background.positioned(to_spans(events, time_background.finished_at(lines)))
4110
- };
4111
- }
4112
- function has_transcript_data(span_count) {
4113
- return span_count > 0;
4114
- }
4115
- var time_spans = {
4116
- ASSISTANT_TYPE,
4117
- MODEL_CATEGORY,
4118
- TOOL_CATEGORY,
4119
- HUMAN_CATEGORY,
4120
- OK_OUTCOME,
4121
- FAILED_OUTCOME,
4122
- UNKNOWN_OUTCOME,
4123
- NO_MESSAGE_ID: NO_MESSAGE_ID3,
4124
- UNKNOWN_TOOL: UNKNOWN_TOOL2,
4125
- has_transcript_data,
4126
- equal_durations,
4127
- no_background,
4128
- // Re-exported so the suites that measure how a command is read keep asking one namespace, and so
4129
- // `time-shell.ts` moving out of this file changed no call site.
4130
- bash_label: time_shell.bash_label,
4131
- josh_command_of: time_shell.josh_command_of,
4132
- josh_commands_of: time_shell.josh_commands_of,
4133
- to_tool_call: to_tool_call2,
4134
- parse_line: parse_line4,
4135
- parse_timeline
4136
- };
4137
-
4138
- // scripts/time-runtime/time-round-trips.ts
4139
- var CALLS_PER_ROUND_TRIP_FLOOR = 1.5;
4140
- var DENSITY_DECIMALS = 2;
4141
- var NONE = 0;
4142
- function is_tool(span) {
4143
- return span.category === time_spans.TOOL_CATEGORY;
4144
- }
4145
- function is_model(span) {
4146
- return span.category === time_spans.MODEL_CATEGORY;
4147
- }
4148
- function started_ms2(span) {
4149
- return span.ended_ms - span.duration_ms;
4150
- }
4151
- function in_time_order(spans) {
4152
- return spans.toSorted((left, right) => started_ms2(left) - started_ms2(right));
4153
- }
4154
- function is_tool_at(spans, index) {
4155
- const span = spans[index];
4156
- return span !== void 0 && is_tool(span);
4157
- }
4158
- function is_call(span) {
4159
- return is_tool(span) && !span.is_continuation;
4160
- }
4161
- function count_calls(spans) {
4162
- return spans.filter((span) => is_call(span)).length;
4163
- }
4164
- function previous_break(spans, index) {
4165
- for (let back = index - 1; back >= 0; back -= 1) {
4166
- const span = spans[back];
4167
- if (span === void 0 || !is_model(span)) return span;
4168
- }
4169
- return void 0;
4170
- }
4171
- function continues_turn(spans, index, message_id) {
4172
- if (message_id === time_spans.NO_MESSAGE_ID) return false;
4173
- const earlier = previous_break(spans, index);
4174
- return earlier !== void 0 && !earlier.is_continuation && earlier.message_id === message_id;
4175
- }
4176
- function opens_round_trip(spans, index) {
4177
- const span = spans[index];
4178
- if (span === void 0 || !is_tool(span) || span.is_continuation || is_tool_at(spans, index - 1)) {
4179
- return false;
4180
- }
4181
- return !continues_turn(spans, index, span.message_id);
4182
- }
4183
- function open_trip(walk) {
4184
- walk.open = [];
4185
- walk.trips.push(walk.open);
4186
- }
4187
- function place_call(walk, span) {
4188
- if (is_call(span)) walk.open?.push(span);
4189
- }
4190
- function step_trip(walk, span, is_opener) {
4191
- if (is_opener) open_trip(walk);
4192
- if (is_tool(span)) place_call(walk, span);
4193
- else if (!is_model(span)) walk.open = void 0;
4194
- }
4195
- function group_round_trips(spans) {
4196
- const ordered = in_time_order(spans);
4197
- const walk = { trips: [], open: void 0 };
4198
- for (const [index, span] of ordered.entries()) {
4199
- step_trip(walk, span, opens_round_trip(ordered, index));
4200
- }
4201
- return walk.trips;
4202
- }
4203
- function count_round_trips(spans) {
4204
- return group_round_trips(spans).length;
4205
- }
4206
- function turn_key(span, index) {
4207
- return span.message_id === time_spans.NO_MESSAGE_ID ? `#${String(index)}` : span.message_id;
4208
- }
4209
- function count_turns(spans) {
4210
- const keys = spans.filter((span) => is_model(span)).map((span, index) => turn_key(span, index));
4211
- return new Set(keys).size;
4212
- }
4213
- function per_round_trip(total, round_trip_count) {
4214
- if (round_trip_count === NONE) return NONE;
4215
- return total / round_trip_count;
4216
- }
4217
- function format_density(density) {
4218
- return density.toFixed(DENSITY_DECIMALS);
4219
- }
4220
- function is_below_floor(density) {
4221
- return density > NONE && density < CALLS_PER_ROUND_TRIP_FLOOR;
4222
- }
4223
- var time_round_trips = {
4224
- CALLS_PER_ROUND_TRIP_FLOOR,
4225
- count_calls,
4226
- count_round_trips,
4227
- // Exported so a turn is defined in the one module that already defines a round trip rather than
4228
- // as a span filter in the report next door.
4229
- count_turns,
4230
- format_density,
4231
- // Exported so the per-tool counts are read off the very groups this module counts rather than off
4232
- // a second grouping beside them.
4233
- group_round_trips,
4234
- // Exported so the failure aggregation orders a run's spans through
4235
- // the one function that already knows why they need it — a second `toSorted` beside it would be
4236
- // the clone `CLAUDE.md` prohibits, and the seam it guards (a delegated unit's spans appended
4237
- // after the parent's) is not one a second copy would keep remembering.
4238
- in_time_order,
4239
- is_below_floor,
4240
- // Exported so callers price a round trip with the same divisor and guard rather than a private
4241
- // copy — the clone `CLAUDE.md` prohibits.
4242
- per_round_trip
4243
- };
4244
-
4245
- // scripts/time-runtime/time-agent-bundles.ts
4246
- var NONE2 = 0;
4247
- var ONE = 1;
4248
- var MIN_GROUP = 2;
4249
- function is_launch2(span) {
4250
- return span.category === time_spans.TOOL_CATEGORY && !span.is_continuation && time_bundle_call.is_launch_tool(span.label);
4251
- }
4252
- function new_walk() {
4253
- return { closed: [], open: NONE2, wrote_since: false, turn_id: time_spans.NO_MESSAGE_ID };
4254
- }
4255
- function close_group(walk) {
4256
- if (walk.open >= MIN_GROUP) walk.closed.push(walk.open);
4257
- walk.open = NONE2;
4258
- }
4259
- function is_same_turn(walk, span) {
4260
- return span.message_id !== time_spans.NO_MESSAGE_ID && span.message_id === walk.turn_id;
4261
- }
4262
- function open_turn(walk, span) {
4263
- if (walk.wrote_since || span.has_prior_reference) close_group(walk);
4264
- walk.open += ONE;
4265
- walk.turn_id = span.message_id;
4266
- walk.wrote_since = false;
4267
- }
4268
- function step(walk, span) {
4269
- if (span.is_writing) {
4270
- walk.wrote_since = true;
4271
- return;
4272
- }
4273
- if (!is_launch2(span) || is_same_turn(walk, span)) return;
4274
- open_turn(walk, span);
4275
- }
4276
- function agent_bundles(spans) {
4277
- const walk = new_walk();
4278
- for (const span of time_round_trips.in_time_order(spans)) step(walk, span);
4279
- close_group(walk);
4280
- return walk.closed;
4281
- }
4282
- var time_agent_bundles = { agent_bundles };
4283
-
4284
- // scripts/time-runtime/time-bundles.ts
4285
- var { unmeasured_row: unmeasured_row2 } = time_format;
4286
- var HEADING = "Bundling:";
4287
- var SEQUENCE_LABEL = "bundleable sequences";
4288
- var RECOVERABLE_LABEL = "recoverable round trips";
4289
- var SAVING_LABEL = "recoverable wait";
4290
- var BY_TOOL_LABEL = "recoverable by tool";
4291
- var AGENT_ROW_LABEL = "Agent";
4292
- var ROW_INDENT = " ";
4293
- var MIN_SEQUENCE = 2;
4294
- var ONE_CALL = 1;
4295
- var NONE3 = 0;
4296
- var PATH_SEPARATOR2 = "/";
4297
- var FIRST_CALL = 1;
4298
- var NO_LABEL = "";
4299
- var NO_BUNDLES = {
4300
- sequence_count: 0,
4301
- longest_sequence: 0,
4302
- recoverable_round_trips: 0,
4303
- by_tool: [],
4304
- unattributed_round_trips: 0,
4305
- is_measured: false
4306
- };
4307
- function contains_segments(whole, part) {
4308
- if (whole.startsWith(`${part}${PATH_SEPARATOR2}`)) return true;
4309
- return whole.endsWith(`${PATH_SEPARATOR2}${part}`) || whole.includes(`${PATH_SEPARATOR2}${part}${PATH_SEPARATOR2}`);
4310
- }
4311
- function is_related(left, right) {
4312
- if (left === right) return true;
4313
- return contains_segments(left, right) || contains_segments(right, left);
4314
- }
4315
- function shares_target(left, right) {
4316
- return left.some((one) => right.some((other) => is_related(one, other)));
4317
- }
4318
- function is_dependent(earlier, later) {
4319
- if (earlier.is_writing && later.is_writing) return false;
4320
- return shares_target(earlier.targets, later.targets);
4321
- }
4322
- function conflicts(span, sequence) {
4323
- return sequence.some((earlier) => is_dependent(earlier, span));
4324
- }
4325
- function is_call2(span) {
4326
- return span.category === time_spans.TOOL_CATEGORY && !span.is_continuation;
4327
- }
4328
- function is_turn_boundary(span) {
4329
- return span.category === time_spans.MODEL_CATEGORY;
4330
- }
4331
- function new_walk2() {
4332
- return { pending: [], sequence: [], closed: [] };
4333
- }
4334
- function flush(walk) {
4335
- if (walk.sequence.length >= MIN_SEQUENCE) walk.closed.push(walk.sequence);
4336
- walk.sequence = [];
4337
- }
4338
- function extend(walk, span) {
4339
- if (conflicts(span, walk.sequence)) flush(walk);
4340
- walk.sequence.push(span);
4341
- }
4342
- function close_trip(walk) {
4343
- const [only] = walk.pending;
4344
- if (walk.pending.length === ONE_CALL && only?.is_bundleable === true) extend(walk, only);
4345
- else if (walk.pending.length > NONE3) flush(walk);
4346
- walk.pending = [];
4347
- }
4348
- function is_same_turn2(span, pending) {
4349
- const [first] = pending;
4350
- if (first === void 0 || span.is_continuation || span.message_id === time_spans.NO_MESSAGE_ID) {
4351
- return false;
4352
- }
4353
- return span.message_id === first.message_id;
4354
- }
4355
- function step2(walk, span) {
4356
- if (is_call2(span)) {
4357
- walk.pending.push(span);
4358
- return;
4359
- }
4360
- if (is_same_turn2(span, walk.pending)) return;
4361
- close_trip(walk);
4362
- if (!is_turn_boundary(span)) flush(walk);
4363
- }
4364
- function longest_of(sizes) {
4365
- return sizes.length === NONE3 ? NONE3 : Math.max(...sizes);
4366
- }
4367
- function recoverable_of(sizes) {
4368
- return sizes.reduce((sum, size) => sum + size - ONE_CALL, NONE3);
4369
- }
4370
- function sizes_of(closed) {
4371
- return closed.map((sequence) => sequence.length);
4372
- }
4373
- function tally_for(tallies, label) {
4374
- const found = tallies.get(label);
4375
- if (found !== void 0) return found;
4376
- const created = { sequence_count: NONE3, recoverable_round_trips: NONE3 };
4377
- tallies.set(label, created);
4378
- return created;
4379
- }
4380
- function count_trip(tallies, counted, label) {
4381
- const tally = tally_for(tallies, label);
4382
- tally.recoverable_round_trips += ONE_CALL;
4383
- if (!counted.has(label)) tally.sequence_count += ONE_CALL;
4384
- counted.add(label);
4385
- }
4386
- function tally_sequence(tallies, sequence) {
4387
- const counted = /* @__PURE__ */ new Set();
4388
- for (const span of sequence.slice(FIRST_CALL)) {
4389
- if (span.label !== NO_LABEL) count_trip(tallies, counted, span.label);
4390
- }
4391
- }
4392
- function by_weight(left, right) {
4393
- if (left.recoverable_round_trips !== right.recoverable_round_trips) {
4394
- return right.recoverable_round_trips - left.recoverable_round_trips;
4395
- }
4396
- return left.label.localeCompare(right.label);
4397
- }
4398
- function tool_rows(closed) {
4399
- const tallies = /* @__PURE__ */ new Map();
4400
- for (const sequence of closed) tally_sequence(tallies, sequence);
4401
- return [...tallies].map(([label, tally]) => ({ label, ...tally })).toSorted(by_weight);
4402
- }
4403
- function attributed_of(rows) {
4404
- return rows.reduce((sum, row) => sum + row.recoverable_round_trips, NONE3);
4405
- }
4406
- function with_agent_row(rows, agent_sizes) {
4407
- const recoverable_round_trips = recoverable_of(agent_sizes);
4408
- if (recoverable_round_trips === NONE3) return [...rows];
4409
- const row = {
4410
- label: AGENT_ROW_LABEL,
4411
- sequence_count: agent_sizes.length,
4412
- recoverable_round_trips
4413
- };
4414
- return [...rows, row].toSorted(by_weight);
4415
- }
4416
- function build_bundles(spans) {
4417
- const walk = new_walk2();
4418
- for (const span of time_round_trips.in_time_order(spans)) step2(walk, span);
4419
- close_trip(walk);
4420
- flush(walk);
4421
- const sizes = sizes_of(walk.closed);
4422
- const agent_sizes = time_agent_bundles.agent_bundles(spans);
4423
- const by_tool = with_agent_row(tool_rows(walk.closed), agent_sizes);
4424
- const recoverable_round_trips = recoverable_of(sizes) + recoverable_of(agent_sizes);
4425
- return {
4426
- sequence_count: sizes.length + agent_sizes.length,
4427
- longest_sequence: Math.max(longest_of(sizes), longest_of(agent_sizes)),
4428
- recoverable_round_trips,
4429
- by_tool,
4430
- unattributed_round_trips: recoverable_round_trips - attributed_of(by_tool),
4431
- is_measured: time_spans.has_transcript_data(spans.length)
4432
- };
4433
- }
4434
- function open_sequence(spans) {
4435
- const walk = new_walk2();
4436
- for (const span of time_round_trips.in_time_order(spans)) step2(walk, span);
4437
- return walk.sequence;
4438
- }
4439
- function sequence_suffix(totals) {
4440
- return `longest ${String(totals.longest_sequence)} turn(s)`;
4441
- }
4442
- function recoverable_suffix(totals, round_trip_count) {
4443
- const share = time_format.format_share(totals.recoverable_round_trips, round_trip_count);
4444
- return `${share} of ${String(round_trip_count)} round trip(s)`;
4445
- }
4446
- function saving_line(totals, model_ms_per_round_trip) {
4447
- const saved_ms = totals.recoverable_round_trips * model_ms_per_round_trip;
4448
- const rate = `at ${time_format.format_seconds(model_ms_per_round_trip)} model time per round trip`;
4449
- return time_format.format_row(SAVING_LABEL, saved_ms, rate);
4450
- }
4451
- function by_tool_suffix(totals) {
4452
- const attributed = totals.recoverable_round_trips - totals.unattributed_round_trips;
4453
- return `${String(attributed)} of ${String(totals.recoverable_round_trips)} attributed`;
4454
- }
4455
- function tool_row(row) {
4456
- return time_format.format_columns(
4457
- `${ROW_INDENT}${row.label}`,
4458
- String(row.recoverable_round_trips),
4459
- `in ${String(row.sequence_count)} sequence(s)`
4460
- );
4461
- }
4462
- function by_tool_lines(totals) {
4463
- const heading = time_format.format_columns(
4464
- BY_TOOL_LABEL,
4465
- String(totals.by_tool.length),
4466
- by_tool_suffix(totals)
4467
- );
4468
- const rows = totals.by_tool.slice(NONE3, time_format.MAX_ROWS).map((row) => tool_row(row));
4469
- return [heading, ...rows, ...time_format.overflow_line(totals.by_tool.length)];
4470
- }
4471
- function measured_lines(totals, price) {
4472
- return [
4473
- time_format.format_columns(
4474
- SEQUENCE_LABEL,
4475
- String(totals.sequence_count),
4476
- sequence_suffix(totals)
4477
- ),
4478
- time_format.format_columns(
4479
- RECOVERABLE_LABEL,
4480
- String(totals.recoverable_round_trips),
4481
- recoverable_suffix(totals, price.round_trip_count)
4482
- ),
4483
- saving_line(totals, price.model_ms_per_round_trip),
4484
- ...by_tool_lines(totals)
4485
- ];
4486
- }
4487
- var LABELS = [SEQUENCE_LABEL, RECOVERABLE_LABEL, SAVING_LABEL, BY_TOOL_LABEL];
4488
- function no_divisor_lines() {
4489
- return LABELS.map((label) => time_format.format_columns(label, "", time_format.NO_CALLS));
4490
- }
4491
- function bundle_lines(totals, price) {
4492
- const heading = ["", HEADING];
4493
- if (!totals.is_measured) return [...heading, ...LABELS.map((label) => unmeasured_row2(label))];
4494
- if (price.round_trip_count === NONE3) return [...heading, ...no_divisor_lines()];
4495
- return [...heading, ...measured_lines(totals, price)];
4496
- }
4497
- var time_bundles = {
4498
- HEADING,
4499
- BY_TOOL_LABEL,
4500
- NO_BUNDLES,
4501
- build_bundles,
4502
- bundle_lines,
4503
- is_dependent,
4504
- open_sequence,
4505
- shares_target
4506
- };
4507
-
4508
- // scripts/time-runtime/time-command-key.ts
4509
- var UNNAMED_KEY = "";
4510
- function command_key(span) {
4511
- if (span.label === time_spans.UNKNOWN_TOOL) return UNNAMED_KEY;
4512
- return span.josh_command === "" ? span.label : span.josh_command;
4513
- }
4514
- var time_command_key = { UNNAMED_KEY, command_key };
4515
-
4516
- // scripts/time-runtime/time-call-identity.ts
4517
- var IDENTITY_SEPARATOR = "\0";
4518
- function identity_of(call) {
4519
- return [
4520
- time_command_key.command_key(call),
4521
- call.check_key,
4522
- [...call.targets].toSorted((left, right) => left.localeCompare(right)).join(",")
4523
- ].join(IDENTITY_SEPARATOR);
4524
- }
4525
- var time_call_identity = { identity_of };
4526
-
4527
- // scripts/time-runtime/time-batch-guard.ts
4528
- var CONSECUTIVE_LIMIT = 3;
4529
- var REFIRE_EVERY = CONSECUTIVE_LIMIT;
4530
- var ONE_TURN = 1;
4531
- var NONE4 = 0;
4532
- var NOTICE_REFIRE_EVERY = ONE_TURN;
4533
- var NAMED_CANDIDATE_COUNT = 3;
4534
- var SEQUENCE_BEFORE_LIMIT = CONSECUTIVE_LIMIT - ONE_TURN;
4535
- var RULE_POINTER = "`prompts/collaboration-workflow/turn-batching.md`";
4536
- var STREAK = `${String(CONSECUTIVE_LIMIT)} single-call turns in a row`;
4537
- var REASON = `\u26D4 batching: ${STREAK}. Reissue this with the calls that do not need its result \u2014 the test is whether a call's input needs another call's result, not what kind of call it is (edits are covered exactly as reads); it never authorizes weakening a verification gate or a review. Nothing to pair? Reissue it unchanged. ${RULE_POINTER}`;
4538
- var NOTICE = `\u{1F4A1} batching: ${STREAK}; the Write proceeds. Issue the writes that do not need its result in one turn, never by weakening a gate or a review. ${RULE_POINTER}`;
4539
- var LANE_NOTICE = `\u{1F4A1} batching: ${STREAK}; the call proceeds. Pair independent calls. ${RULE_POINTER}`;
4540
- var WHOLE_FILE_WRITE_TOOL = "Write";
4541
- var EDIT_TOOL = "Edit";
4542
- function is_guarded_call(call) {
4543
- if (call.name === WHOLE_FILE_WRITE_TOOL) return false;
4544
- return time_bundle_call.call_facts(call.name, call.input).is_bundleable;
4545
- }
4546
- function is_notice_call(call) {
4547
- return call.name === WHOLE_FILE_WRITE_TOOL;
4548
- }
4549
- function is_read_only_call(call) {
4550
- const facts = time_bundle_call.call_facts(call.name, call.input);
4551
- return facts.is_bundleable && !facts.may_write;
4552
- }
4553
- function depends_on_sequence(sequence, facts) {
4554
- return sequence.some((span) => time_bundles.shares_target(span.targets, facts.targets));
4555
- }
4556
- function sequence_started_ms(sequence) {
4557
- return sequence[0]?.ended_ms ?? NONE4;
4558
- }
4559
- function turns_since(sequence, last_fired_ms) {
4560
- return sequence.filter((span) => span.ended_ms > last_fired_ms).length;
4561
- }
4562
- function is_sequence_at_limit(sequence, facts, last_fired_ms, refire_every) {
4563
- if (sequence.length < SEQUENCE_BEFORE_LIMIT || depends_on_sequence(sequence, facts)) return false;
4564
- if (last_fired_ms < sequence_started_ms(sequence)) return true;
4565
- return turns_since(sequence, last_fired_ms) >= refire_every;
4566
- }
4567
- function is_at_limit(spans, call, last_fired_ms, refire_every) {
4568
- return is_sequence_at_limit(
4569
- time_bundles.open_sequence(spans),
4570
- time_bundle_call.call_facts(call.name, call.input),
4571
- last_fired_ms,
4572
- refire_every
4573
- );
4574
- }
4575
- var GUARD_LABEL = time_transcript_line.guard_from_refusal(REASON);
4576
- function is_reissued_refusal(spans, call) {
4577
- const identity = time_call_identity.identity_of(
4578
- time_spans.to_tool_call(call.name, call.input, time_spans.NO_MESSAGE_ID)
4579
- );
4580
- return spans.some(
4581
- (span) => span.refusal_guard === GUARD_LABEL && time_call_identity.identity_of(span) === identity
4582
- );
4583
- }
4584
- function should_block(text, call, refused_at_ms, refire_every = REFIRE_EVERY) {
4585
- if (!is_guarded_call(call)) return false;
4586
- const { spans } = time_spans.parse_timeline(text);
4587
- if (is_reissued_refusal(spans, call)) return false;
4588
- return is_at_limit(spans, call, refused_at_ms, refire_every);
4589
- }
4590
- function should_notify(text, call, notified_at_ms) {
4591
- if (!is_notice_call(call)) return false;
4592
- const { spans } = time_spans.parse_timeline(text);
4593
- return is_at_limit(spans, call, notified_at_ms, NOTICE_REFIRE_EVERY);
4594
- }
4595
- function describe_span(span) {
4596
- const target2 = span.targets[0] ?? "";
4597
- if (target2 === "" || span.label.includes(target2)) return span.label;
4598
- return `${span.label} ${target2}`;
4599
- }
4600
- var FOLD_MINIMUM = 2;
4601
- function read_targets(sequence) {
4602
- const paths = sequence.filter((span) => span.is_bundleable && !span.is_writing).map((span) => span.targets[0] ?? "").filter((path5) => path5 !== "" && time_bundle_call.has_extension(path5));
4603
- return [...new Set(paths)];
4604
- }
4605
- function read_fold_directive(sequence) {
4606
- const paths = read_targets(sequence);
4607
- if (paths.length < FOLD_MINIMUM) return "";
4608
- return ` Fold them into one call: \`pnpm josh read:files ${paths.join(" ")}\`.`;
4609
- }
4610
- function write_targets(sequence) {
4611
- const paths = sequence.filter((span) => span.label === EDIT_TOOL).map((span) => span.targets[0] ?? "").filter((path5) => path5 !== "" && time_bundle_call.has_extension(path5));
4612
- return [...new Set(paths)];
4613
- }
4614
- function write_fold_directive(sequence) {
4615
- const paths = write_targets(sequence);
4616
- if (paths.length < FOLD_MINIMUM) return "";
4617
- return ` Fold them into one \`pnpm josh edit:files\` call with a plan over: ${paths.join(" ")}.`;
4618
- }
4619
- function name_candidates(calls) {
4620
- if (calls.length === NONE4) return "";
4621
- const named = calls.map((call) => describe_span(call)).join(", ");
4622
- const folds = `${read_fold_directive(calls)}${write_fold_directive(calls)}`;
4623
- return ` Just issued one per turn, so at least these could have shared a turn: ${named}.${folds}`;
4624
- }
4625
- function recent_candidates(tail) {
4626
- return name_candidates(
4627
- time_bundles.open_sequence(time_spans.parse_timeline(tail).spans).slice(-NAMED_CANDIDATE_COUNT)
4628
- );
4629
- }
4630
- function pairing_candidates(tail, call) {
4631
- const sequence = time_bundles.open_sequence(time_spans.parse_timeline(tail).spans);
4632
- if (call === void 0 || sequence.length === NONE4) {
4633
- return name_candidates(sequence.slice(-NAMED_CANDIDATE_COUNT));
4634
- }
4635
- const facts = time_bundle_call.call_facts(call.name, call.input);
4636
- if (!facts.is_bundleable || depends_on_sequence(sequence, facts)) return "";
4637
- const current = time_spans.to_tool_call(call.name, call.input, time_spans.NO_MESSAGE_ID);
4638
- return name_candidates([...sequence.slice(ONE_TURN - NAMED_CANDIDATE_COUNT), current]);
4639
- }
4640
- var STAMP_PREFIX = "josh-batch-guard-";
4641
- var NOTICE_STAMP_PREFIX = "josh-batch-guard-notice-";
4642
- var time_batch_guard = {
4643
- CONSECUTIVE_LIMIT,
4644
- GUARD_LABEL,
4645
- LANE_NOTICE,
4646
- NOTICE,
4647
- NOTICE_REFIRE_EVERY,
4648
- NOTICE_STAMP_PREFIX,
4649
- REASON,
4650
- REFIRE_EVERY,
4651
- SEQUENCE_BEFORE_LIMIT,
4652
- STAMP_PREFIX,
4653
- is_guarded_call,
4654
- is_notice_call,
4655
- is_read_only_call,
4656
- pairing_candidates,
4657
- recent_candidates,
4658
- should_block,
4659
- should_notify
4660
- };
4661
-
4662
- // scripts/time-runtime/time-hook-transcript.ts
4663
- import path4 from "node:path";
4664
- var { TRANSCRIPT_EXTENSION } = cost_transcript;
4665
- var AGENT_PREFIX = "agent-";
4666
- var AGENT_ID_PATTERN = /^[\w-]+$/u;
4667
- function is_agent_id(value) {
4668
- return typeof value === "string" && AGENT_ID_PATTERN.test(value);
4669
- }
4670
- function fork_path(transcript_path, agent_id) {
4671
- const directory = path4.dirname(transcript_path);
4672
- const session_id = path4.basename(transcript_path, TRANSCRIPT_EXTENSION);
4673
- const file_name = `${AGENT_PREFIX}${agent_id}${TRANSCRIPT_EXTENSION}`;
4674
- return path4.join(cost_transcript.unit_directory(directory, session_id), file_name);
4675
- }
4676
- function transcript_of(transcript_path, agent_id) {
4677
- if (!is_agent_id(agent_id) || !transcript_path.endsWith(TRANSCRIPT_EXTENSION)) {
4678
- return transcript_path;
4679
- }
4680
- return fork_path(transcript_path, agent_id);
4681
- }
4682
- var time_hook_transcript = {
4683
- fork_path,
4684
- transcript_of
4685
- };
4686
-
4687
- // scripts/time-runtime/time-density-hook.ts
4688
- import { closeSync as closeSync2, fstatSync, openSync as openSync2, readSync } from "node:fs";
4689
- import { z as z6 } from "zod";
4690
-
4691
- // scripts/time-runtime/time-density.ts
4692
- var MIN_ROUND_TRIPS = 10;
4693
- var NOTICE_INTERVAL_MS = 3e5;
4694
- var ONE_CALL2 = 1;
4695
- var NONE5 = 0;
4696
- function has_whole_tail(text) {
4697
- const last = text.split("\n").findLast((line) => line.trim() !== "");
4698
- return last !== void 0 && time_spans.parse_line(last) !== void 0;
4699
- }
4700
- function assistant_lines(text) {
4701
- return text.split("\n").map((line) => time_spans.parse_line(line)).filter((line) => line?.type === time_spans.ASSISTANT_TYPE);
4702
- }
4703
- function last_turn_calls(text) {
4704
- if (!has_whole_tail(text)) return NONE5;
4705
- const lines = assistant_lines(text);
4706
- const message_id = lines.at(-1)?.message_id;
4707
- if (message_id === void 0 || message_id === time_spans.NO_MESSAGE_ID) return NONE5;
4708
- return lines.filter((line) => line.message_id === message_id).flatMap((line) => line.blocks).filter((block) => block.type === cost_blocks.TOOL_USE_TYPE).length;
4709
- }
4710
- function read_window(text) {
4711
- const { spans } = time_spans.parse_timeline(text);
4712
- const round_trip_count = time_round_trips.count_round_trips(spans);
4713
- const call_count = time_round_trips.count_calls(spans);
4714
- return {
4715
- density: time_round_trips.per_round_trip(call_count, round_trip_count),
4716
- round_trip_count,
4717
- turn_calls: last_turn_calls(text)
4718
- };
4719
- }
4720
- function is_due(reading, since_last_ms) {
4721
- if (reading.round_trip_count < MIN_ROUND_TRIPS || reading.turn_calls !== ONE_CALL2 || !time_round_trips.is_below_floor(reading.density)) {
4722
- return false;
4723
- }
4724
- return since_last_ms >= NOTICE_INTERVAL_MS;
4725
- }
4726
- function format_notice(reading, candidates = "") {
4727
- const density = time_round_trips.format_density(reading.density);
4728
- const floor = time_round_trips.format_density(time_round_trips.CALLS_PER_ROUND_TRIP_FLOOR);
4729
- return `\u26A0 batching: ${density} calls per round trip over the last ${String(reading.round_trip_count)}, under the ${floor} floor, and this turn issued one call. Independent reads, greps, gh queries and edits go out together; the criterion is whether this call's input needs another call's result, not what kind of call it is \u2014 prompts/collaboration-workflow/turn-batching.md.${candidates}`;
4730
- }
4731
- var time_density = {
4732
- MIN_ROUND_TRIPS,
4733
- NOTICE_INTERVAL_MS,
4734
- format_notice,
4735
- is_due,
4736
- last_turn_calls,
4737
- read_window
4738
- };
4739
-
4740
- // scripts/time-runtime/time-density-hook.ts
4741
- var TAIL_BYTES = 262144;
4742
- var FILE_START = 0;
4743
- var NOTICE_PREFIX = "josh-density-notice-";
4744
- var NEVER_MS = 0;
4745
- var payload_schema = z6.object({
4746
- transcript_path: z6.string().min(1).optional(),
4747
- // **`nullish`, not `optional`.** A payload spelling the absent agent as `null` has to read as "no
4748
- // fork"; rejected, it would fail `safeParse` for the whole payload and silence the line for every
4749
- // edit of the main line — the opposite of this module's stated failure direction.
4750
- agent_id: z6.string().nullish()
4751
- });
4752
- var notice_schema = z6.object({ notified_at_ms: z6.number() });
4753
- var call_schema = z6.object({ tool_name: z6.string().min(1), tool_input: z6.unknown() });
4754
- function parse_transcript_path(raw_payload) {
4755
- const parsed = payload_schema.safeParse(JSON.parse(raw_payload));
4756
- if (!parsed.success || parsed.data.transcript_path === void 0) return void 0;
4757
- return time_hook_transcript.transcript_of(parsed.data.transcript_path, parsed.data.agent_id);
4758
- }
4759
- function parse_call(raw_payload) {
4760
- const parsed = call_schema.safeParse(JSON.parse(raw_payload));
4761
- if (!parsed.success) return void 0;
4762
- return { name: parsed.data.tool_name, input: parsed.data.tool_input };
4763
- }
4764
- function read_tail(file_path, max_bytes = TAIL_BYTES) {
4765
- const descriptor = openSync2(file_path, "r");
4766
- try {
4767
- const { size } = fstatSync(descriptor);
4768
- const length = Math.min(size, max_bytes);
4769
- const buffer = Buffer.alloc(length);
4770
- const read = readSync(descriptor, buffer, FILE_START, length, size - length);
4771
- return buffer.subarray(FILE_START, read).toString("utf8");
4772
- } finally {
4773
- closeSync2(descriptor);
4774
- }
4775
- }
4776
- function notice_path(transcript_path) {
4777
- return stamp_file.stamp_path(NOTICE_PREFIX, transcript_path);
4778
- }
4779
- function last_notice_ms(source) {
4780
- const raw = stamp_file.read_stamp_text(source);
4781
- if (raw === void 0) return NEVER_MS;
4782
- return json_value.parse_with(raw, notice_schema)?.notified_at_ms ?? NEVER_MS;
4783
- }
4784
- function arm_throttle(target2, now_ms) {
4785
- try {
4786
- stamp_file.write_stamp(target2, { notified_at_ms: now_ms });
4787
- } catch {
4788
- }
4789
- }
4790
- function notice_for(raw_payload, now_ms) {
4791
- const transcript_path = parse_transcript_path(raw_payload);
4792
- if (transcript_path === void 0) return void 0;
4793
- const tail = read_tail(transcript_path);
4794
- const reading = time_density.read_window(tail);
4795
- const target2 = notice_path(transcript_path);
4796
- if (!time_density.is_due(reading, now_ms - last_notice_ms(target2))) return void 0;
4797
- const candidates = time_batch_guard.pairing_candidates(tail, parse_call(raw_payload));
4798
- if (candidates === "") return void 0;
4799
- arm_throttle(target2, now_ms);
4800
- return time_density.format_notice(reading, candidates);
4801
- }
4802
- function density_notice(raw_payload, now_ms = Date.now()) {
4803
- try {
4804
- return notice_for(raw_payload, now_ms);
4805
- } catch {
4806
- return void 0;
4807
- }
4808
- }
4809
- var time_density_hook = {
4810
- density_notice,
4811
- notice_path,
4812
- read_tail
4813
- };
4814
-
4815
- export {
4816
- cost_blocks,
4817
- ESLINT_EDIT_CACHE_FLAGS,
4818
- time_shell,
4819
- time_bundle_call,
4820
- CHECK_STATUS_PENDING,
4821
- CHECK_STATUS_FAIL,
4822
- read_string,
4823
- parse_pr_state_snapshot,
4824
- is_merge_conflict,
4825
- is_coderabbit_check,
4826
- is_required_check,
4827
- describe_pr_failure,
4828
- evaluate_pr_state,
4829
- is_review_decision_decisive,
4830
- PrConflictError,
4831
- time_reported_failure,
4832
- cost_attribute,
4833
- time_transcript_line,
4834
- time_spans,
4835
- time_batch_guard,
4836
- time_hook_transcript,
4837
- time_density_hook
4838
- };