@joshuafolkken/kit 1.1240.0 → 1.1373.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 (934) hide show
  1. package/.claude/agents/investigator.md +1 -0
  2. package/.claude/settings.json +4 -0
  3. package/.claude/skills/dependency-update/SKILL.md +5 -3
  4. package/.claude/skills/epic-commands/SKILL.md +82 -113
  5. package/.claude/skills/epic-commands/epic-bundle.md +38 -63
  6. package/.claude/skills/epic-commands/execution-waves.md +30 -51
  7. package/.claude/skills/verify-ui/SKILL.md +13 -20
  8. package/.claude/skills/workflow-commands/SKILL.md +10 -10
  9. package/.claude/skills/workflow-commands/background-commands.md +4 -4
  10. package/.claude/skills/workflow-commands/backlogrun-child.md +30 -105
  11. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +29 -0
  12. package/.claude/skills/workflow-commands/backlogrun-lanes.md +45 -131
  13. package/.claude/skills/workflow-commands/backlogrun-park.md +36 -53
  14. package/.claude/skills/workflow-commands/backlogrun-progress.md +81 -331
  15. package/.claude/skills/workflow-commands/backlogrun-recovery.md +29 -83
  16. package/.claude/skills/workflow-commands/backlogrun-steps.md +105 -424
  17. package/.claude/skills/workflow-commands/backlogrun.md +52 -61
  18. package/.claude/skills/workflow-commands/chain-rule.md +36 -40
  19. package/.claude/skills/workflow-commands/entry-sequence.md +6 -6
  20. package/.claude/skills/workflow-commands/followup.md +19 -20
  21. package/.claude/skills/workflow-commands/fullrun-steps.md +23 -27
  22. package/.claude/skills/workflow-commands/fullrun.md +10 -10
  23. package/.claude/skills/workflow-commands/halfrun.md +9 -8
  24. package/.claude/skills/workflow-commands/into-target.md +12 -18
  25. package/.claude/skills/workflow-commands/issue-comments.md +11 -26
  26. package/.claude/skills/workflow-commands/kickoff.md +26 -16
  27. package/.claude/skills/workflow-commands/latest-gate.md +17 -28
  28. package/.claude/skills/workflow-commands/needs-human-review.md +13 -24
  29. package/.claude/skills/workflow-commands/observation-filing.md +37 -28
  30. package/.claude/skills/workflow-commands/observation-ledger.md +48 -38
  31. package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -9
  32. package/.claude/skills/workflow-commands/prerequisite.md +23 -15
  33. package/.claude/skills/workflow-commands/progress-watcher.md +17 -11
  34. package/.claude/skills/workflow-commands/prrun.md +3 -3
  35. package/.claude/skills/workflow-commands/retrospective.md +13 -18
  36. package/.claude/skills/workflow-commands/split-assessment.md +6 -4
  37. package/.claude/skills/workflow-commands/target-repository.md +25 -28
  38. package/.claude/skills/workflow-commands/working-tree-hold.md +11 -17
  39. package/.gitattributes +2 -1
  40. package/.github/workflows/ci.yml +14 -0
  41. package/.vscode/tasks.json +14 -0
  42. package/CLAUDE.md +10 -61
  43. package/README.md +23 -66
  44. package/SECURITY.md +1 -1
  45. package/dist/CLAUDE.md +10 -61
  46. package/dist/commands/document-section-cli.js +43 -11
  47. package/dist/config-merge/index.js +11 -2
  48. package/dist/hooks/audit-provision.js +2 -2
  49. package/dist/hooks/batch-guard.js +7 -7
  50. package/dist/hooks/{chunk-KHGB5S3Y.js → chunk-7UBFU3CL.js} +18 -20
  51. package/dist/hooks/{chunk-ZQGD4GBY.js → chunk-7WKYHEGU.js} +8 -44
  52. package/dist/hooks/{chunk-4TZVB44A.js → chunk-AKGCP4LX.js} +285 -363
  53. package/dist/hooks/{chunk-QVSWU24O.js → chunk-BZMPVFDY.js} +7 -5
  54. package/dist/hooks/{chunk-5VNDSNG3.js → chunk-FZ6FUSBM.js} +1 -1
  55. package/dist/hooks/{chunk-GPTFMK5E.js → chunk-GG72ANKI.js} +1 -1
  56. package/dist/hooks/{chunk-XZYKEM6J.js → chunk-JCRDBQXB.js} +13 -11
  57. package/dist/hooks/{chunk-F3ELQ2AF.js → chunk-JGW24KKM.js} +4 -4
  58. package/dist/hooks/{chunk-ELCN5LCH.js → chunk-NEC4AT4Z.js} +34 -12
  59. package/dist/hooks/chunk-NZN2UFI6.js +2409 -0
  60. package/dist/hooks/{chunk-WK2XSHSI.js → chunk-SLSFIWTX.js} +550 -875
  61. package/dist/hooks/chunk-UTHMB4O2.js +1590 -0
  62. package/dist/hooks/{chunk-KRBERBBI.js → chunk-V4TKZHER.js} +4 -4
  63. package/dist/hooks/chunk-YLBBSSTF.js +3705 -0
  64. package/dist/hooks/chunk-Z5TMJIPW.js +45 -0
  65. package/dist/hooks/codex-hook-adapter.js +26 -21
  66. package/dist/hooks/duplicate-read-guard.js +8 -8
  67. package/dist/hooks/format-edited.js +4 -4
  68. package/dist/hooks/inputs.json +195 -181
  69. package/dist/hooks/investigation-guard.js +8 -8
  70. package/dist/hooks/pretool-guard.js +15 -15
  71. package/dist/hooks/session-lang.js +406 -8
  72. package/dist/hooks/stop-guard.js +122 -187
  73. package/dist/josh.js +282 -95
  74. package/dist/version/index.js +15 -13
  75. package/eslint/base.js +43 -5
  76. package/eslint/rules/english-only-prose.js +3 -3
  77. package/eslint/rules/import.js +12 -0
  78. package/eslint/rules/namespace-object-export.js +2 -2
  79. package/package.json +17 -11
  80. package/pnpm-workspace.yaml +2 -4
  81. package/prompts/coding-standards.md +14 -48
  82. package/prompts/collaboration-workflow/file-edits.md +1 -1
  83. package/prompts/collaboration-workflow/issue-citation.md +1 -1
  84. package/prompts/collaboration-workflow/issue-template.md +3 -10
  85. package/prompts/collaboration-workflow/operating-rules.md +7 -8
  86. package/prompts/collaboration-workflow/output-bounds.md +1 -1
  87. package/prompts/collaboration-workflow/overview.md +1 -1
  88. package/prompts/collaboration-workflow/plan-comment.md +2 -1
  89. package/prompts/collaboration-workflow/principles.md +21 -3
  90. package/prompts/collaboration-workflow/report-format.md +16 -29
  91. package/prompts/collaboration-workflow/residency.md +1 -1
  92. package/prompts/collaboration-workflow/rule-delivery.md +7 -95
  93. package/prompts/collaboration-workflow/shell-body.md +3 -23
  94. package/prompts/collaboration-workflow/turn-batching.md +4 -13
  95. package/prompts/collaboration-workflow/wip-cap.md +5 -11
  96. package/prompts/refactoring.md +1 -1
  97. package/prompts/review-rubric.md +3 -22
  98. package/prompts/review.md +15 -38
  99. package/prompts/testing-guide.md +2 -4
  100. package/scripts/adopt/adopt-logic.ts +5 -5
  101. package/scripts/adopt/adopt-toolkits.ts +4 -5
  102. package/scripts/adopt/adopt.ts +2 -3
  103. package/scripts/agent/agent-argv.ts +7 -7
  104. package/scripts/agent/agent-diagnostics.ts +2 -2
  105. package/scripts/agent/agent-exit-record.ts +1 -1
  106. package/scripts/agent/agent-headless.ts +1 -1
  107. package/scripts/agent/agent-launch-environment.ts +6 -1
  108. package/scripts/agent/agent-role-profile.ts +49 -22
  109. package/scripts/agent/agent-session-role.ts +32 -0
  110. package/scripts/agent/api-outage.ts +1 -1
  111. package/scripts/agent/claude-agent-argv.ts +4 -4
  112. package/scripts/agent/claude-result-event.ts +4 -4
  113. package/scripts/agent/codex-hooks.ts +2 -2
  114. package/scripts/agent/interactive-ask.ts +3 -6
  115. package/scripts/auto-ok/auto-ok-cli.ts +46 -60
  116. package/scripts/backlog/backlog-arrival-added.ts +34 -0
  117. package/scripts/backlog/backlog-arrival.ts +54 -17
  118. package/scripts/backlog/backlog-budget-cli.ts +34 -6
  119. package/scripts/backlog/backlog-budget.ts +17 -24
  120. package/scripts/backlog/backlog-defect-priority.ts +1 -1
  121. package/scripts/backlog/backlog-drive-args.ts +5 -4
  122. package/scripts/backlog/backlog-drive-cli.ts +14 -10
  123. package/scripts/backlog/backlog-drive-epic.ts +85 -0
  124. package/scripts/backlog/backlog-drive-launch.ts +1 -1
  125. package/scripts/backlog/backlog-drive-named-offer.ts +60 -9
  126. package/scripts/backlog/backlog-drive-named.ts +39 -9
  127. package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
  128. package/scripts/backlog/backlog-drive-restore.ts +1 -1
  129. package/scripts/backlog/backlog-drive-retrospective.ts +2 -2
  130. package/scripts/backlog/backlog-drive.ts +43 -28
  131. package/scripts/backlog/backlog-idle.ts +88 -0
  132. package/scripts/backlog/backlog-named.ts +11 -15
  133. package/scripts/backlog/backlog-next.ts +26 -30
  134. package/scripts/backlog/backlog-offer-cli.ts +28 -23
  135. package/scripts/backlog/backlog-offer.ts +7 -7
  136. package/scripts/backlog/backlog-overlap.ts +178 -0
  137. package/scripts/backlog/backlog-plan-cli.ts +14 -90
  138. package/scripts/backlog/backlog-plan-read.ts +111 -0
  139. package/scripts/backlog/backlog-plan.ts +11 -10
  140. package/scripts/backlog/backlog-pool.ts +13 -14
  141. package/scripts/backlog/backlog-rank.ts +11 -11
  142. package/scripts/backlog/backlog-ready.ts +15 -10
  143. package/scripts/backlog/backlog-scope.ts +14 -15
  144. package/scripts/backlog/backlog-stalled-cli.ts +2 -2
  145. package/scripts/backlog/backlog-stalled-detect.ts +4 -4
  146. package/scripts/backlog/backlog-stalled.ts +5 -6
  147. package/scripts/backlog/backlog-waves.ts +4 -4
  148. package/scripts/backlog/backlogrun-args.ts +74 -0
  149. package/scripts/backlog/backlogrun-cli.ts +113 -0
  150. package/scripts/backlog/backlogrun-launch.ts +178 -0
  151. package/scripts/behavior/behavior-assertion.ts +6 -8
  152. package/scripts/behavior/behavior-cli.ts +1 -1
  153. package/scripts/behavior/behavior-rules.ts +3 -3
  154. package/scripts/build/build-claude-md.ts +4 -4
  155. package/scripts/build/build-codex-hooks.ts +2 -2
  156. package/scripts/build/build-commands.ts +1 -1
  157. package/scripts/build/build-hooks.ts +5 -5
  158. package/scripts/build/build.ts +1 -1
  159. package/scripts/build/hook-bundle-stamp.ts +109 -7
  160. package/scripts/build/local-bin.ts +2 -2
  161. package/scripts/cases/cases-cli.ts +1 -1
  162. package/scripts/cases/cases-logic.ts +2 -2
  163. package/scripts/ci/composite-actions.ts +1 -2
  164. package/scripts/ci/pr-classification.ts +2 -2
  165. package/scripts/claude/workflow-destination.ts +1 -1
  166. package/scripts/clone/clone-aggregate.ts +1 -1
  167. package/scripts/clone/clone-fingerprint.ts +1 -1
  168. package/scripts/clone/clone-scan-cli.ts +1 -1
  169. package/scripts/clone/clone-scan.ts +1 -1
  170. package/scripts/config-merge/index.ts +1 -1
  171. package/scripts/config-merge/json-format.ts +1 -3
  172. package/scripts/config-merge/patch-json-array.ts +90 -0
  173. package/scripts/config-merge/patch-json-key.ts +6 -3
  174. package/scripts/config-merge/patch-json-list.ts +1 -1
  175. package/scripts/cost-runtime/codex-usage.ts +1 -1
  176. package/scripts/cost-runtime/context-cut-payback.ts +4 -5
  177. package/scripts/cost-runtime/context-cut-threshold.ts +4 -6
  178. package/scripts/cost-runtime/cost-attribute.ts +3 -3
  179. package/scripts/cost-runtime/cost-blocks.ts +3 -4
  180. package/scripts/cost-runtime/cost-cli.ts +14 -11
  181. package/scripts/cost-runtime/cost-corpus.ts +11 -11
  182. package/scripts/cost-runtime/cost-pricing.ts +4 -4
  183. package/scripts/cost-runtime/cost-tokens.ts +1 -2
  184. package/scripts/cost-runtime/cost-transcript.ts +29 -29
  185. package/scripts/cost-runtime/cost-usage.ts +6 -7
  186. package/scripts/cost-runtime/cost-verdict.ts +10 -11
  187. package/scripts/cost-runtime/own-session.ts +1 -1
  188. package/scripts/cost-runtime/transcript-cwd.ts +2 -2
  189. package/scripts/delegation/delegation-cli.ts +4 -4
  190. package/scripts/delegation/delegation-policy.ts +13 -15
  191. package/scripts/delegation/duplicate-read-guard.ts +9 -10
  192. package/scripts/delegation/fanout-cli.ts +1 -1
  193. package/scripts/delegation/fanout.ts +1 -1
  194. package/scripts/delegation/investigation-guard.ts +18 -22
  195. package/scripts/delegation/investigation-reads.ts +48 -238
  196. package/scripts/discovery/repo-discovery.ts +1 -1
  197. package/scripts/discovery/repo-map-logic.ts +1 -2
  198. package/scripts/discovery/repo-origin.ts +3 -3
  199. package/scripts/discovery/repo-party-cli.ts +2 -2
  200. package/scripts/discovery/repo-party.ts +2 -2
  201. package/scripts/doctor/doctor-consumer.ts +1 -1
  202. package/scripts/doctor/doctor-io.ts +6 -7
  203. package/scripts/doctor/doctor-logic.ts +1 -1
  204. package/scripts/doctor/doctor-ports.ts +1 -1
  205. package/scripts/doctor/doctor.ts +8 -9
  206. package/scripts/document/backlogrun-parent-read-set.ts +5 -6
  207. package/scripts/document/bash-output-cap.ts +5 -7
  208. package/scripts/document/capped-print-part.ts +1 -1
  209. package/scripts/document/capped-print.ts +1 -1
  210. package/scripts/document/document-byte-budget.ts +33 -64
  211. package/scripts/document/document-byte-check.ts +4 -4
  212. package/scripts/document/document-reachability.ts +7 -8
  213. package/scripts/document/document-read-cli.ts +2 -2
  214. package/scripts/document/document-scan.ts +30 -5
  215. package/scripts/document/document-section-cli.ts +6 -8
  216. package/scripts/document/document-section.ts +8 -12
  217. package/scripts/document/edit-files-cli.ts +3 -4
  218. package/scripts/document/entry-read-budget.ts +8 -70
  219. package/scripts/document/entry-read-set.ts +51 -34
  220. package/scripts/document/lane-child-read-set.ts +9 -9
  221. package/scripts/document/read-files-cli.ts +1 -2
  222. package/scripts/document/read-set-cli.ts +16 -19
  223. package/scripts/document/read-set-cost.ts +4 -4
  224. package/scripts/document/read-set-point-of-use.ts +28 -38
  225. package/scripts/document/read-set-pricing.ts +1 -1
  226. package/scripts/document/read-set-trim.ts +3 -3
  227. package/scripts/document/resident-budget.ts +8 -10
  228. package/scripts/epic/epic-add-body.ts +15 -18
  229. package/scripts/epic/epic-add-plan.ts +26 -28
  230. package/scripts/epic/epic-add.ts +32 -25
  231. package/scripts/epic/epic-audit-checks.ts +27 -37
  232. package/scripts/epic/epic-audit-cli.ts +21 -22
  233. package/scripts/epic/epic-audit-orphans.ts +16 -17
  234. package/scripts/epic/epic-audit-rationale.ts +10 -15
  235. package/scripts/epic/epic-audit-report.ts +2 -5
  236. package/scripts/epic/epic-audit.ts +18 -14
  237. package/scripts/epic/epic-body.ts +10 -10
  238. package/scripts/epic/epic-bundle-cli.ts +36 -34
  239. package/scripts/epic/epic-bundle-evidence.ts +5 -5
  240. package/scripts/epic/epic-bundle-gaps.ts +6 -9
  241. package/scripts/epic/epic-bundle-poll.ts +1 -1
  242. package/scripts/epic/epic-bundle-referenced.ts +11 -14
  243. package/scripts/epic/epic-bundle.ts +19 -20
  244. package/scripts/epic/epic-busy.ts +44 -21
  245. package/scripts/epic/epic-candidate-confirm.ts +15 -18
  246. package/scripts/epic/epic-chains.ts +18 -23
  247. package/scripts/epic/epic-classify.ts +11 -12
  248. package/scripts/epic/epic-cli-argv.ts +5 -6
  249. package/scripts/epic/epic-cli-remove.ts +9 -4
  250. package/scripts/epic/epic-cli.ts +38 -26
  251. package/scripts/epic/epic-close-comment.ts +14 -15
  252. package/scripts/epic/epic-close.ts +25 -29
  253. package/scripts/epic/epic-cross-repo.ts +18 -21
  254. package/scripts/epic/epic-decision.ts +14 -18
  255. package/scripts/epic/epic-fetch.ts +25 -31
  256. package/scripts/epic/epic-graph.ts +15 -17
  257. package/scripts/epic/epic-index.ts +14 -16
  258. package/scripts/epic/epic-issue.ts +9 -11
  259. package/scripts/epic/epic-label-age.ts +74 -0
  260. package/scripts/epic/epic-lane-offer.ts +35 -24
  261. package/scripts/epic/epic-nested.ts +1 -1
  262. package/scripts/epic/epic-next-read.ts +8 -8
  263. package/scripts/epic/epic-next-views.ts +12 -12
  264. package/scripts/epic/epic-next.ts +29 -33
  265. package/scripts/epic/epic-outside-blocker.ts +11 -10
  266. package/scripts/epic/epic-parse.ts +22 -24
  267. package/scripts/epic/epic-promote.ts +3 -2
  268. package/scripts/epic/epic-rank.ts +1 -1
  269. package/scripts/epic/epic-read.ts +10 -8
  270. package/scripts/epic/epic-reconcile.ts +8 -6
  271. package/scripts/epic/epic-reference.ts +5 -4
  272. package/scripts/epic/epic-relation-recheck.ts +10 -11
  273. package/scripts/epic/epic-relations.ts +9 -8
  274. package/scripts/epic/epic-remove-plan.ts +4 -5
  275. package/scripts/epic/epic-remove.ts +7 -5
  276. package/scripts/epic/epic-report.ts +18 -20
  277. package/scripts/epic/epic-run.ts +6 -5
  278. package/scripts/epic/epic-sections.ts +2 -2
  279. package/scripts/epic/epic-shape.ts +3 -3
  280. package/scripts/epic/epic-solo-stale.ts +3 -2
  281. package/scripts/epic/epic-solo.ts +8 -8
  282. package/scripts/epic/epic-triage.ts +5 -4
  283. package/scripts/epic/epic-validate.ts +8 -7
  284. package/scripts/epic/epic.ts +5 -5
  285. package/scripts/exports/unused-members-cli.ts +1 -1
  286. package/scripts/followup/followup-issue-number.ts +1 -2
  287. package/scripts/followup/git-followup-cleanup.ts +6 -7
  288. package/scripts/followup/git-followup-finish.ts +11 -13
  289. package/scripts/followup/git-followup-flush.ts +11 -7
  290. package/scripts/followup/git-followup-issue-close.ts +16 -13
  291. package/scripts/followup/git-followup-label.ts +9 -6
  292. package/scripts/followup/git-followup-merged.ts +1 -1
  293. package/scripts/followup/git-followup-pending.ts +7 -9
  294. package/scripts/followup/git-followup-stages.ts +28 -17
  295. package/scripts/followup/git-followup-workflow.ts +19 -21
  296. package/scripts/followup/git-pr-followup-checks.ts +13 -20
  297. package/scripts/followup/git-pr-followup-wrapup.ts +7 -7
  298. package/scripts/followup/git-pr-followup.ts +18 -17
  299. package/scripts/gate/core-admission.ts +2 -2
  300. package/scripts/gate/core-budget.ts +15 -26
  301. package/scripts/gate/gate-ledger.ts +114 -0
  302. package/scripts/gate/gate-log.ts +7 -9
  303. package/scripts/gate/gate-plan.ts +70 -35
  304. package/scripts/gate/gate-report.ts +14 -15
  305. package/scripts/gate/gate-skip.ts +11 -13
  306. package/scripts/gate/gate-steps.ts +5 -1
  307. package/scripts/gate/gate-tree.ts +3 -4
  308. package/scripts/gate/hook-gate-reuse.ts +9 -9
  309. package/scripts/gate/machine-capacity.ts +168 -30
  310. package/scripts/gate/pre-commit-type-check.ts +4 -4
  311. package/scripts/gate/project-checks.ts +12 -4
  312. package/scripts/gate/scoped-green.ts +11 -18
  313. package/scripts/gate/type-check-command.ts +2 -2
  314. package/scripts/gate/type-check-step.ts +4 -4
  315. package/scripts/gate/verification-gate.ts +53 -51
  316. package/scripts/gh/gh-spawn.ts +2 -2
  317. package/scripts/gh/git-ai-review-scan.ts +3 -2
  318. package/scripts/gh/git-gh-api-path.ts +10 -11
  319. package/scripts/gh/git-gh-exec.ts +43 -48
  320. package/scripts/gh/git-gh-failure.ts +6 -9
  321. package/scripts/gh/git-gh-helpers.ts +1 -1
  322. package/scripts/gh/git-gh-issue-list.ts +15 -19
  323. package/scripts/gh/git-gh-issue-read.ts +43 -60
  324. package/scripts/gh/git-gh-issue-rest.ts +14 -15
  325. package/scripts/gh/git-gh-issue-write.ts +52 -40
  326. package/scripts/gh/git-gh-issue.ts +23 -24
  327. package/scripts/gh/git-gh-pr-auto-merge.ts +3 -3
  328. package/scripts/gh/git-gh-pr-read.ts +46 -50
  329. package/scripts/gh/git-gh-pr-rest.ts +23 -26
  330. package/scripts/gh/git-gh-pr-review.ts +2 -2
  331. package/scripts/gh/git-gh-pr-rollup.ts +4 -4
  332. package/scripts/gh/git-gh-pr-snapshot.ts +8 -10
  333. package/scripts/gh/git-gh-pr.ts +16 -16
  334. package/scripts/gh/git-gh-reachability.ts +11 -12
  335. package/scripts/gh/git-gh-repo.ts +2 -3
  336. package/scripts/gh/git-gh-rest-state.ts +1 -1
  337. package/scripts/gh/git-pr-ai-review.ts +6 -5
  338. package/scripts/gh/git-pr-checks-eval.ts +28 -30
  339. package/scripts/gh/git-pr-checks-parse.ts +14 -16
  340. package/scripts/gh/git-pr-checks-watch.ts +17 -17
  341. package/scripts/gh/git-pr-checks.ts +20 -23
  342. package/scripts/gh/git-pr-coderabbit.ts +8 -6
  343. package/scripts/gh/git-pr-confirmation.ts +5 -5
  344. package/scripts/gh/git-pr-managed-config.ts +7 -9
  345. package/scripts/gh/git-pr-messages.ts +1 -1
  346. package/scripts/gh/git-pr.ts +15 -16
  347. package/scripts/gh/github-issue-url.ts +8 -9
  348. package/scripts/git/base-tree.ts +66 -0
  349. package/scripts/git/change-base.ts +42 -2
  350. package/scripts/git/changed-file-scope.ts +5 -5
  351. package/scripts/git/changed-paths.ts +1 -2
  352. package/scripts/git/constants.ts +2 -2
  353. package/scripts/git/git-branch.ts +1 -1
  354. package/scripts/git/git-closes-keyword.ts +3 -3
  355. package/scripts/git/git-command.ts +53 -41
  356. package/scripts/git/git-common-directory.ts +3 -3
  357. package/scripts/git/git-diff-reads.ts +14 -15
  358. package/scripts/git/git-error.ts +1 -1
  359. package/scripts/git/git-execa-error.ts +1 -2
  360. package/scripts/git/git-issue.ts +10 -8
  361. package/scripts/git/git-location-environment.ts +3 -4
  362. package/scripts/git/git-ls-remote.ts +6 -8
  363. package/scripts/git/git-pre-push-hook.ts +11 -10
  364. package/scripts/git/git-preflight.ts +5 -5
  365. package/scripts/git/git-push-transport.ts +2 -2
  366. package/scripts/git/git-remote-branch.ts +1 -2
  367. package/scripts/git/git-schemas.ts +16 -23
  368. package/scripts/git/git-spawn-sync.ts +1 -1
  369. package/scripts/git/git-spawn.ts +37 -14
  370. package/scripts/git/git-ssh-keepalive.ts +12 -5
  371. package/scripts/git/git-staging.ts +7 -8
  372. package/scripts/git/git-workflow.ts +1 -1
  373. package/scripts/git/git-worktree.ts +35 -27
  374. package/scripts/git/gone-branch.ts +2 -2
  375. package/scripts/git/listing-cutoff.ts +1 -2
  376. package/scripts/git/lockfile-sync.ts +65 -0
  377. package/scripts/git/main-merge-guard.ts +1 -2
  378. package/scripts/git/main-merge.ts +7 -7
  379. package/scripts/git/main-sync.ts +23 -8
  380. package/scripts/git/parse-json-array.ts +18 -23
  381. package/scripts/git/repository-lock.ts +34 -2
  382. package/scripts/git/stash/git-stash.ts +4 -5
  383. package/scripts/git/stash/stash-orphans.ts +5 -3
  384. package/scripts/git/stash/stash-pop-args.ts +1 -1
  385. package/scripts/git/stash/stash-pop-cli.ts +3 -3
  386. package/scripts/git/stash/stash-sweep-lock.ts +2 -2
  387. package/scripts/hooks/batch-guard.ts +11 -13
  388. package/scripts/hooks/check-commit-message.ts +12 -9
  389. package/scripts/hooks/codex-hook-adapter.ts +16 -10
  390. package/scripts/hooks/edited-cspell.ts +3 -4
  391. package/scripts/hooks/format-edited-cli.ts +1 -1
  392. package/scripts/hooks/format-edited-file.ts +11 -17
  393. package/scripts/hooks/format-rewrite-notice.ts +19 -17
  394. package/scripts/hooks/pre-push-unit.ts +10 -14
  395. package/scripts/hooks/pretool-guard-cli.ts +4 -4
  396. package/scripts/hooks/pretool-guard.ts +93 -18
  397. package/scripts/hooks/reserved-run.ts +2 -2
  398. package/scripts/hooks/step-zero-notice.ts +1 -1
  399. package/scripts/hooks/stop-guard.ts +21 -10
  400. package/scripts/init/basic-path-migration.ts +2 -2
  401. package/scripts/init/claude-kit-only-settings.ts +2 -2
  402. package/scripts/init/claude-plugin-config.ts +2 -2
  403. package/scripts/init/distributed-paths.ts +4 -4
  404. package/scripts/init/hook-command-rewrite.ts +3 -3
  405. package/scripts/init/hook-launch.ts +5 -5
  406. package/scripts/init/init-actions.ts +13 -0
  407. package/scripts/init/init-ai-copy.ts +11 -11
  408. package/scripts/init/init-bootstrap.ts +3 -3
  409. package/scripts/init/init-copy-content.ts +4 -4
  410. package/scripts/init/init-logic-json-merge.ts +7 -9
  411. package/scripts/init/init-logic-migrate.ts +1 -1
  412. package/scripts/init/init-logic-templates.ts +1 -1
  413. package/scripts/init/init-logic-workspace.ts +4 -4
  414. package/scripts/init/init-logic-yaml-merge.ts +2 -2
  415. package/scripts/init/init-logic.ts +19 -22
  416. package/scripts/init/init.ts +7 -7
  417. package/scripts/init/kit-base-preset.ts +1 -1
  418. package/scripts/init/kit-setup-state.ts +1 -1
  419. package/scripts/init/kit-written-paths.ts +1 -2
  420. package/scripts/init/package-manager-pin.ts +1 -1
  421. package/scripts/init/project-profile-cli.ts +1 -1
  422. package/scripts/init/project-profile.ts +3 -3
  423. package/scripts/init/session-language-environment.ts +1 -1
  424. package/scripts/init/start-exec.ts +3 -4
  425. package/scripts/init/start-plan.ts +2 -2
  426. package/scripts/init/start-setup-pr.ts +3 -2
  427. package/scripts/init/start-steps.ts +2 -2
  428. package/scripts/init/tsconfig-preset-migration.ts +1 -1
  429. package/scripts/init/vscode-tasks.ts +62 -0
  430. package/scripts/issue/baseline-measure.ts +2 -2
  431. package/scripts/issue/behavior-change-lint.ts +2 -2
  432. package/scripts/issue/defect-rate-cli.ts +6 -7
  433. package/scripts/issue/defect-rate.ts +37 -27
  434. package/scripts/issue/git-next-issues.ts +9 -8
  435. package/scripts/issue/issue-auto-ok.ts +24 -11
  436. package/scripts/issue/issue-backlinks-cli.ts +5 -5
  437. package/scripts/issue/issue-backlinks.ts +6 -6
  438. package/scripts/issue/issue-cite-cli.ts +20 -18
  439. package/scripts/issue/issue-cite.ts +18 -8
  440. package/scripts/issue/issue-closing-pr.ts +4 -4
  441. package/scripts/issue/issue-comment-cli.ts +6 -4
  442. package/scripts/issue/issue-file-cli.ts +52 -15
  443. package/scripts/issue/issue-file-fold.ts +155 -0
  444. package/scripts/issue/issue-file.ts +9 -6
  445. package/scripts/issue/issue-fold-cli.ts +14 -9
  446. package/scripts/issue/issue-fold.ts +23 -8
  447. package/scripts/issue/issue-labels.ts +34 -38
  448. package/scripts/issue/issue-lint-cli.ts +2 -2
  449. package/scripts/issue/issue-lint.ts +1 -1
  450. package/scripts/issue/issue-merged.ts +10 -4
  451. package/scripts/issue/issue-number-shape.ts +27 -0
  452. package/scripts/issue/issue-rank.ts +1 -1
  453. package/scripts/issue/issue-read-cli.ts +4 -5
  454. package/scripts/issue/issue-read.ts +4 -5
  455. package/scripts/issue/issue-reference.ts +5 -5
  456. package/scripts/issue/issue-release-cli.ts +17 -7
  457. package/scripts/issue/issue-release.ts +3 -3
  458. package/scripts/issue/issue-report-failures.ts +7 -4
  459. package/scripts/issue/issue-scout-cli.ts +11 -11
  460. package/scripts/issue/issue-scout-closed.ts +4 -4
  461. package/scripts/issue/issue-scout.ts +4 -5
  462. package/scripts/issue/issue-state-cli.ts +17 -10
  463. package/scripts/issue/issue-state.ts +12 -13
  464. package/scripts/issue/issue-wip.ts +7 -7
  465. package/scripts/issue/markdown-section.ts +3 -3
  466. package/scripts/issue/measure-rerun-cli.ts +10 -9
  467. package/scripts/issue/reproduction-measure.ts +3 -3
  468. package/scripts/issue/session-cite.ts +56 -0
  469. package/scripts/josh/agent-session-environment.ts +10 -8
  470. package/scripts/josh/cli-body.ts +2 -2
  471. package/scripts/josh/command-suggest.ts +1 -1
  472. package/scripts/josh/file-map-stamp.ts +20 -23
  473. package/scripts/josh/hook-decision.ts +24 -28
  474. package/scripts/josh/josh-command-map.ts +4 -1
  475. package/scripts/josh/josh-command-types.ts +30 -35
  476. package/scripts/josh/josh-commands-ai.ts +6 -6
  477. package/scripts/josh/josh-commands-backlog.ts +15 -3
  478. package/scripts/josh/josh-commands-clone.ts +1 -1
  479. package/scripts/josh/josh-commands-development.ts +25 -4
  480. package/scripts/josh/josh-commands-document.ts +3 -3
  481. package/scripts/josh/josh-commands-guard.ts +3 -3
  482. package/scripts/josh/josh-commands-issue.ts +4 -5
  483. package/scripts/josh/josh-commands-lane.ts +14 -4
  484. package/scripts/josh/josh-commands-lint.ts +1 -1
  485. package/scripts/josh/josh-commands-run.ts +21 -7
  486. package/scripts/josh/josh-commands-split.ts +1 -2
  487. package/scripts/josh/josh-commands-versioning.ts +5 -5
  488. package/scripts/josh/josh-commands-workflow.ts +30 -22
  489. package/scripts/josh/josh-environment-file.ts +1 -1
  490. package/scripts/josh/josh-in-process.ts +3 -3
  491. package/scripts/josh/josh-logic.ts +6 -7
  492. package/scripts/josh/josh-run.ts +3 -3
  493. package/scripts/josh/josh-verdict.ts +9 -12
  494. package/scripts/josh/josh.ts +3 -3
  495. package/scripts/josh/kit-only.ts +2 -2
  496. package/scripts/josh/path-decision.ts +3 -3
  497. package/scripts/josh/platform-temporary.ts +7 -5
  498. package/scripts/josh/process-identity.ts +24 -6
  499. package/scripts/josh/process-owner.ts +4 -4
  500. package/scripts/josh/session-language-cli.ts +53 -11
  501. package/scripts/josh/session-language.ts +1 -1
  502. package/scripts/josh/stamp-file.ts +48 -29
  503. package/scripts/josh/stamp-record.ts +57 -0
  504. package/scripts/lane/lane-await.ts +35 -11
  505. package/scripts/lane/lane-cache.ts +6 -6
  506. package/scripts/lane/lane-capacity.ts +32 -17
  507. package/scripts/lane/lane-child-invocation.ts +17 -15
  508. package/scripts/lane/lane-child-marker.ts +12 -12
  509. package/scripts/lane/lane-cli.ts +12 -13
  510. package/scripts/lane/lane-close.ts +6 -6
  511. package/scripts/lane/lane-dispatch.ts +61 -72
  512. package/scripts/lane/lane-environment.ts +5 -5
  513. package/scripts/lane/lane-guard-policy.ts +7 -21
  514. package/scripts/lane/lane-handoff.ts +2 -2
  515. package/scripts/lane/lane-install.ts +9 -10
  516. package/scripts/lane/lane-launch-cli.ts +13 -8
  517. package/scripts/lane/lane-ledger.ts +73 -11
  518. package/scripts/lane/lane-leftover.ts +2 -2
  519. package/scripts/lane/lane-limit-cli.ts +160 -0
  520. package/scripts/lane/lane-limit-override.ts +74 -0
  521. package/scripts/lane/lane-load.ts +19 -68
  522. package/scripts/lane/lane-measure-cli.ts +15 -25
  523. package/scripts/lane/lane-occupancy.ts +6 -4
  524. package/scripts/lane/lane-open.ts +20 -19
  525. package/scripts/lane/lane-output.ts +4 -3
  526. package/scripts/lane/lane-paths.ts +12 -11
  527. package/scripts/lane/lane-phase.ts +33 -0
  528. package/scripts/lane/lane-reap.ts +2 -2
  529. package/scripts/lane/lane-registry.ts +16 -15
  530. package/scripts/lane/lane-relaunch.ts +9 -9
  531. package/scripts/lane/lane-report.ts +5 -4
  532. package/scripts/lane/lane-resume.ts +2 -2
  533. package/scripts/lane/lane-sampler.ts +55 -0
  534. package/scripts/lane/lane-seed.ts +7 -7
  535. package/scripts/lane/lane-stage-stats.ts +135 -0
  536. package/scripts/lane/lane-start-point.ts +8 -11
  537. package/scripts/lane/lane-stats.ts +60 -15
  538. package/scripts/lane/lane-stray.ts +1 -1
  539. package/scripts/lane/lane-vacant.ts +1 -1
  540. package/scripts/lane/openai-lane-supervisor-decision.ts +3 -7
  541. package/scripts/lane/openai-lane-supervisor-owner.ts +3 -9
  542. package/scripts/lane/openai-review-broker.ts +2 -4
  543. package/scripts/lib/ancestor-directories.ts +1 -1
  544. package/scripts/lib/bounded-pool.ts +2 -2
  545. package/scripts/lib/buffered-process.ts +4 -6
  546. package/scripts/lib/caddy-logs.sh +0 -0
  547. package/scripts/lib/cli-flags.ts +39 -6
  548. package/scripts/lib/error-message.ts +1 -1
  549. package/scripts/lib/json-value.ts +17 -3
  550. package/scripts/lib/poll.ts +1 -1
  551. package/scripts/lib/status-icons.ts +3 -3
  552. package/scripts/lib/timed-fetch.ts +1 -1
  553. package/scripts/lib/timeouts.ts +1 -1
  554. package/scripts/lines/bytes-command.ts +3 -4
  555. package/scripts/lines/effective-limit.ts +25 -12
  556. package/scripts/lines/line-budget.ts +47 -55
  557. package/scripts/lines/line-targets.ts +6 -2
  558. package/scripts/lines/lines-command.ts +3 -3
  559. package/scripts/lint/cross-file-recheck.ts +155 -0
  560. package/scripts/lint/cspell-cached.ts +1 -1
  561. package/scripts/lint/format.ts +1 -2
  562. package/scripts/lint/lint-parallel.ts +35 -19
  563. package/scripts/lint/lint-related-scope.ts +25 -15
  564. package/scripts/lint/lint-related.ts +6 -7
  565. package/scripts/managed-marker/index.ts +1 -1
  566. package/scripts/managed-marker/managed-marker-logic.ts +1 -2
  567. package/scripts/notify/git-notify.ts +9 -7
  568. package/scripts/notify/telegram-notify.ts +53 -37
  569. package/scripts/notify/telegram-test-logic.ts +3 -3
  570. package/scripts/notify/telegram-test.ts +45 -30
  571. package/scripts/observations/observation-ledger-home.ts +14 -8
  572. package/scripts/observations/observation-ledger-line.ts +3 -2
  573. package/scripts/observations/observation-ledger-migrate.ts +3 -4
  574. package/scripts/observations/observation-ledger-prepare.ts +4 -4
  575. package/scripts/observations/observation-ledger.ts +14 -15
  576. package/scripts/observations/observation-record-cli.ts +83 -0
  577. package/scripts/observations/observation-record.ts +91 -0
  578. package/scripts/observations/observations-flush-cli.ts +1 -1
  579. package/scripts/observations/observations-flush-landing.ts +7 -6
  580. package/scripts/observations/observations-flush.ts +26 -27
  581. package/scripts/overrides/overrides-check.ts +18 -8
  582. package/scripts/package/package-scout-cli.ts +1 -1
  583. package/scripts/package/package-scout-format.ts +2 -2
  584. package/scripts/package/package-scout.ts +1 -1
  585. package/scripts/propagate/propagate-git-failure.ts +1 -1
  586. package/scripts/propagate/propagate-git.ts +7 -7
  587. package/scripts/propagate/propagate-plan.ts +2 -2
  588. package/scripts/propagate/propagate-publish.ts +2 -3
  589. package/scripts/propagate/propagate-run.ts +5 -7
  590. package/scripts/propagate/propagate-select.ts +1 -1
  591. package/scripts/propagate/propagate-steps.ts +19 -20
  592. package/scripts/propagate/propagate-targets.ts +6 -10
  593. package/scripts/propagate/propagate.ts +5 -5
  594. package/scripts/refactor/import-graph.ts +1 -1
  595. package/scripts/refactor/refactor-lint.ts +4 -10
  596. package/scripts/refactor/refactor-scan-cli.ts +1 -1
  597. package/scripts/refactor/refactor-scan.ts +2 -2
  598. package/scripts/refactor/refactor-targets.ts +1 -1
  599. package/scripts/release/github-release-cli.ts +25 -3
  600. package/scripts/release/github-release-runs.ts +1 -1
  601. package/scripts/release/release-cli.ts +21 -4
  602. package/scripts/release/release-history.ts +6 -10
  603. package/scripts/release/release-plan.ts +3 -3
  604. package/scripts/release/release-progress.ts +3 -4
  605. package/scripts/release/release-publish.ts +8 -9
  606. package/scripts/release/release-scope-cli.ts +8 -10
  607. package/scripts/release/release-tag.ts +6 -8
  608. package/scripts/release/release-worktree.ts +5 -5
  609. package/scripts/repo/auto-merge-setting-logic.ts +7 -9
  610. package/scripts/repo/auto-merge-setting.ts +1 -1
  611. package/scripts/repo/repo-setting.ts +4 -4
  612. package/scripts/repo/repository-labels.ts +1 -1
  613. package/scripts/repo/required-checks-logic.ts +3 -3
  614. package/scripts/repo/required-checks-report.ts +1 -1
  615. package/scripts/repo/ruleset-check-cli.ts +1 -1
  616. package/scripts/repo/ruleset-check.ts +1 -1
  617. package/scripts/report/report-format-reference.ts +26 -0
  618. package/scripts/report/report-lint-cli.ts +2 -2
  619. package/scripts/report/report-lint.ts +16 -2
  620. package/scripts/review/disposition-cli.ts +2 -2
  621. package/scripts/review/disposition-logic.ts +1 -1
  622. package/scripts/review/live-evidence.ts +9 -6
  623. package/scripts/review/review-attest-cli.ts +1 -2
  624. package/scripts/review/review-attest.ts +3 -3
  625. package/scripts/review/review-brief-cli.ts +19 -20
  626. package/scripts/review/review-brief.ts +29 -32
  627. package/scripts/review/review-checkout.ts +2 -2
  628. package/scripts/review/review-diff-parts.ts +3 -5
  629. package/scripts/review/review-diff-write.ts +1 -1
  630. package/scripts/review/review-finding-ledger.ts +7 -4
  631. package/scripts/review/review-findings-cli.ts +2 -2
  632. package/scripts/review/review-level.ts +4 -7
  633. package/scripts/review/review-record-cli.ts +73 -16
  634. package/scripts/review/review-record.ts +5 -4
  635. package/scripts/review/review-round2-cli.ts +2 -3
  636. package/scripts/review/review-round2.ts +13 -21
  637. package/scripts/review/review-stamps.ts +9 -71
  638. package/scripts/review/review-tree.ts +4 -5
  639. package/scripts/rules/bash-triggers.ts +4 -4
  640. package/scripts/rules/decision-oracle-batch.ts +6 -7
  641. package/scripts/rules/decision-oracle-stage.ts +1 -1
  642. package/scripts/rules/decision-oracle-tokens.ts +1 -2
  643. package/scripts/rules/decision-oracle.ts +2 -2
  644. package/scripts/rules/delivered-rules.ts +61 -406
  645. package/scripts/rules/destructive-command.ts +2 -2
  646. package/scripts/rules/direct-filing.ts +4 -4
  647. package/scripts/rules/direct-pr-create.ts +2 -2
  648. package/scripts/rules/early-heartbeat.ts +15 -19
  649. package/scripts/rules/file-body.ts +5 -6
  650. package/scripts/rules/filing-cap.ts +6 -7
  651. package/scripts/rules/filing-offer.ts +1 -1
  652. package/scripts/rules/firing-point.ts +6 -6
  653. package/scripts/rules/gh-api.ts +2 -2
  654. package/scripts/rules/git-argv.ts +3 -3
  655. package/scripts/rules/git-force.ts +2 -2
  656. package/scripts/rules/hook-context-line.ts +31 -0
  657. package/scripts/rules/implementation-cut-verdict.ts +5 -8
  658. package/scripts/rules/implementation-cut.ts +35 -32
  659. package/scripts/rules/index-guard.ts +2 -2
  660. package/scripts/rules/issue-citation.ts +7 -7
  661. package/scripts/rules/issue-comments.ts +21 -13
  662. package/scripts/rules/josh-git-bare.ts +2 -2
  663. package/scripts/rules/lane-background.ts +14 -16
  664. package/scripts/rules/lane-carry-conflict.ts +41 -5
  665. package/scripts/rules/lane-interactive-ask.ts +6 -9
  666. package/scripts/rules/lane-park.ts +12 -16
  667. package/scripts/rules/lane-split-park.ts +1 -2
  668. package/scripts/rules/lane-switch-main.ts +10 -13
  669. package/scripts/rules/last-prompt.ts +1 -1
  670. package/scripts/rules/oracle-consulted.ts +5 -5
  671. package/scripts/rules/oracle-firing.ts +6 -9
  672. package/scripts/rules/oracle-list-cli.ts +2 -2
  673. package/scripts/rules/permission-guards.ts +2 -2
  674. package/scripts/rules/piped-verification.ts +79 -9
  675. package/scripts/rules/poll-loop.ts +9 -11
  676. package/scripts/rules/pre-gate-cut.ts +33 -30
  677. package/scripts/rules/prior-comment-read.ts +3 -3
  678. package/scripts/rules/protected-files.ts +25 -13
  679. package/scripts/rules/raw-field-body.ts +3 -4
  680. package/scripts/rules/reply-language.ts +1 -1
  681. package/scripts/rules/rule-body-guard.ts +10 -12
  682. package/scripts/rules/rule-guard.ts +1 -1
  683. package/scripts/rules/rule-list.ts +51 -0
  684. package/scripts/rules/rule-registry-rows.ts +282 -0
  685. package/scripts/rules/rule-registry.ts +109 -0
  686. package/scripts/rules/rule-value-cache.ts +2 -2
  687. package/scripts/rules/rule-value-cli.ts +6 -4
  688. package/scripts/rules/rule-value.ts +61 -22
  689. package/scripts/rules/run-tail-rule.ts +11 -15
  690. package/scripts/rules/shell-body-trigger.ts +7 -7
  691. package/scripts/rules/shell-segments.ts +2 -4
  692. package/scripts/rules/stop-rules.ts +54 -41
  693. package/scripts/rules/tail-commands.ts +1 -1
  694. package/scripts/rules/test-declared-commit.ts +2 -2
  695. package/scripts/rules/third-party-write.ts +3 -3
  696. package/scripts/rules/worktree-guard.ts +12 -5
  697. package/scripts/run/add/run-add-cli.ts +165 -0
  698. package/scripts/run/add/run-add.ts +124 -0
  699. package/scripts/run/board/run-board-cli.ts +207 -0
  700. package/scripts/run/board/run-board-closed.ts +95 -0
  701. package/scripts/run/board/run-board-every.ts +60 -0
  702. package/scripts/run/board/run-board-fetch.ts +38 -0
  703. package/scripts/run/board/run-board-fit.ts +219 -0
  704. package/scripts/run/board/run-board-github.ts +162 -0
  705. package/scripts/run/board/run-board-header.ts +275 -0
  706. package/scripts/run/board/run-board-kind.ts +35 -0
  707. package/scripts/run/board/run-board-labels.ts +299 -0
  708. package/scripts/run/board/run-board-layout.ts +222 -0
  709. package/scripts/run/board/run-board-link.ts +31 -0
  710. package/scripts/run/board/run-board-machine.ts +198 -0
  711. package/scripts/run/board/run-board-notes.ts +103 -0
  712. package/scripts/run/board/run-board-phase.ts +136 -0
  713. package/scripts/run/board/run-board-plan.ts +129 -0
  714. package/scripts/run/board/run-board-read.ts +62 -0
  715. package/scripts/run/board/run-board-render-legend.ts +82 -0
  716. package/scripts/run/board/run-board-render-notes.ts +77 -0
  717. package/scripts/run/board/run-board-render-slot.ts +50 -0
  718. package/scripts/run/board/run-board-render.ts +407 -0
  719. package/scripts/run/board/run-board-scope.ts +17 -0
  720. package/scripts/run/board/run-board-screen.ts +43 -0
  721. package/scripts/run/board/run-board-span.ts +66 -0
  722. package/scripts/run/board/run-board-spin.ts +115 -0
  723. package/scripts/run/board/run-board-state.ts +113 -0
  724. package/scripts/run/board/run-board-status.ts +279 -0
  725. package/scripts/run/board/run-board-tick.ts +210 -0
  726. package/scripts/run/board/run-board-track.ts +22 -0
  727. package/scripts/run/board/run-board-usage-read.ts +255 -0
  728. package/scripts/run/board/run-board-usage-rusage.ts +124 -0
  729. package/scripts/run/board/run-board-usage-text.ts +80 -0
  730. package/scripts/run/board/run-board-usage.ts +165 -0
  731. package/scripts/run/carry/run-carry-added.ts +62 -0
  732. package/scripts/run/carry/run-carry-args.ts +25 -22
  733. package/scripts/run/carry/run-carry-change.ts +1 -1
  734. package/scripts/run/carry/run-carry-cli.ts +71 -48
  735. package/scripts/run/carry/run-carry-conversation.ts +6 -7
  736. package/scripts/run/carry/run-carry-ended.ts +85 -0
  737. package/scripts/run/carry/run-carry-reclaim.ts +1 -1
  738. package/scripts/run/carry/run-carry-stash.ts +3 -2
  739. package/scripts/run/carry/run-carry-streak.ts +8 -10
  740. package/scripts/run/carry/run-carry.ts +85 -89
  741. package/scripts/run/cut/run-cut-args.ts +7 -7
  742. package/scripts/run/cut/run-cut-cli.ts +54 -36
  743. package/scripts/run/cut/run-cut-handoff.ts +15 -15
  744. package/scripts/run/cut/run-cut-report.ts +37 -16
  745. package/scripts/run/cut/run-cut.ts +63 -77
  746. package/scripts/run/detached-launch.ts +35 -50
  747. package/scripts/run/entry/run-entry-cli.ts +48 -27
  748. package/scripts/run/entry/run-entry-stop.ts +7 -9
  749. package/scripts/run/entry/run-entry.ts +5 -6
  750. package/scripts/run/event/run-event-cli.ts +5 -6
  751. package/scripts/run/event/run-event-filed.ts +69 -0
  752. package/scripts/run/event/run-event-follow.ts +3 -3
  753. package/scripts/run/event/run-event-plan.ts +38 -0
  754. package/scripts/run/event/run-event-render.ts +9 -4
  755. package/scripts/run/event/run-event-scope.ts +47 -18
  756. package/scripts/run/event/run-event-stream-emit.ts +64 -11
  757. package/scripts/run/event/run-event-stream.ts +171 -46
  758. package/scripts/run/event/run-event-watch.ts +4 -6
  759. package/scripts/run/hold/run-hold-cli.ts +65 -62
  760. package/scripts/run/hold/run-hold.ts +88 -46
  761. package/scripts/run/merge/run-merge-cli.ts +116 -77
  762. package/scripts/run/merge/run-merge-collect.ts +107 -0
  763. package/scripts/run/merge/run-merge-steps.ts +112 -65
  764. package/scripts/run/merge/run-merge-token.ts +30 -0
  765. package/scripts/run/merge/run-merge.ts +31 -22
  766. package/scripts/run/progress/run-progress-args.ts +4 -4
  767. package/scripts/run/progress/run-progress-cli.ts +39 -50
  768. package/scripts/run/progress/run-progress-clock.ts +25 -32
  769. package/scripts/run/progress/run-progress-config.ts +6 -9
  770. package/scripts/run/progress/run-progress-read.ts +9 -10
  771. package/scripts/run/progress/run-progress.ts +48 -53
  772. package/scripts/run/review/run-review-cli.ts +6 -6
  773. package/scripts/run/review/run-review-steps.ts +6 -6
  774. package/scripts/run/review/run-review.ts +9 -11
  775. package/scripts/run/run-cli-fault.ts +29 -0
  776. package/scripts/run/run-ending-cli.ts +3 -3
  777. package/scripts/run/run-ending.ts +10 -14
  778. package/scripts/run/run-halfrun-resume.ts +6 -8
  779. package/scripts/run/run-headless.ts +26 -12
  780. package/scripts/run/run-invocation.ts +17 -22
  781. package/scripts/run/run-label.ts +7 -5
  782. package/scripts/run/run-liveness-cli.ts +19 -6
  783. package/scripts/run/run-liveness.ts +27 -38
  784. package/scripts/run/run-next-cli.ts +5 -9
  785. package/scripts/run/run-next.ts +4 -5
  786. package/scripts/run/run-parent-cut-hook.ts +10 -12
  787. package/scripts/run/run-preflight.ts +25 -29
  788. package/scripts/run/run-prep-cli.ts +17 -13
  789. package/scripts/run/run-prep-locate.ts +4 -5
  790. package/scripts/run/run-prep.ts +7 -10
  791. package/scripts/run/run-prrun-resume.ts +2 -2
  792. package/scripts/run/run-report-cli.ts +4 -4
  793. package/scripts/run/run-report.ts +9 -14
  794. package/scripts/run/run-retrospective.ts +3 -3
  795. package/scripts/run/run-section.ts +42 -0
  796. package/scripts/run/run-stage-read.ts +2 -2
  797. package/scripts/run/run-stage.ts +6 -4
  798. package/scripts/run/run-status-cli.ts +7 -5
  799. package/scripts/run/run-status.ts +6 -7
  800. package/scripts/run/run-step-cli.ts +64 -18
  801. package/scripts/run/run-step.ts +107 -51
  802. package/scripts/run/run-stop-notify.ts +7 -8
  803. package/scripts/run/run-stranded-cli.ts +1 -1
  804. package/scripts/run/run-stranded-detect.ts +4 -4
  805. package/scripts/run/run-stranded.ts +11 -13
  806. package/scripts/run/run-tail-cli.ts +15 -16
  807. package/scripts/run/run-tail.ts +14 -33
  808. package/scripts/run/run-watcher-guard-cli.ts +3 -4
  809. package/scripts/run/run-watcher-guard.ts +11 -12
  810. package/scripts/run/run-watcher-hook.ts +6 -12
  811. package/scripts/run/ship/run-ship-cli.ts +67 -33
  812. package/scripts/run/ship/run-ship-detach.ts +15 -13
  813. package/scripts/run/ship/run-ship-lock.ts +1 -1
  814. package/scripts/run/ship/run-ship-next.ts +7 -8
  815. package/scripts/run/ship/run-ship-pre-detach.ts +27 -11
  816. package/scripts/run/ship/run-ship-preflight.ts +10 -11
  817. package/scripts/run/ship/run-ship-probe.ts +4 -4
  818. package/scripts/run/ship/run-ship-return.ts +1 -1
  819. package/scripts/run/ship/run-ship-review-steps.ts +43 -24
  820. package/scripts/run/ship/run-ship-review.ts +12 -14
  821. package/scripts/run/ship/run-ship-scoped.ts +15 -6
  822. package/scripts/run/ship/run-ship-stage.ts +80 -26
  823. package/scripts/run/ship/run-ship-steps.ts +26 -16
  824. package/scripts/run/ship/run-ship-stop-text.ts +4 -2
  825. package/scripts/run/ship/run-ship-sync.ts +9 -8
  826. package/scripts/run/ship/run-ship.ts +17 -32
  827. package/scripts/run/tidy/run-tidy-cli.ts +9 -5
  828. package/scripts/run/tidy/run-tidy-lanes.ts +18 -7
  829. package/scripts/run/tidy/run-tidy-stashes.ts +8 -8
  830. package/scripts/run/tidy/run-tidy.ts +4 -3
  831. package/scripts/run/wake/run-wake-cli.ts +27 -32
  832. package/scripts/run/wake/run-wake-describe.ts +24 -28
  833. package/scripts/run/wake/run-wake-driver.ts +14 -14
  834. package/scripts/run/wake/run-wake-handoff.ts +6 -6
  835. package/scripts/run/wake/run-wake-loop.ts +9 -9
  836. package/scripts/run/wake/run-wake-restart.ts +4 -5
  837. package/scripts/run/wake/run-wake-session.ts +23 -27
  838. package/scripts/run/wake/run-wake.ts +57 -279
  839. package/scripts/safe-chain/ci-installer-pin.ts +3 -3
  840. package/scripts/safe-chain/pack-hook.ts +2 -2
  841. package/scripts/safe-chain/preinstall-command.ts +2 -2
  842. package/scripts/security/security-audit-logic.ts +1 -1
  843. package/scripts/security/security-audit-provision-logic.ts +1 -1
  844. package/scripts/security/security-audit-provision.ts +2 -2
  845. package/scripts/security/security-audit.ts +5 -5
  846. package/scripts/security/security-updates-logic.ts +2 -3
  847. package/scripts/security/security-updates.ts +2 -4
  848. package/scripts/self-sync-guard/index.ts +1 -1
  849. package/scripts/self-sync-guard/self-sync-guard-logic.ts +2 -2
  850. package/scripts/self-sync-guard/self-sync-refusal.ts +1 -1
  851. package/scripts/sonar/sonar-hotspots-cli.ts +1 -1
  852. package/scripts/sonar/sonar-hotspots.ts +1 -1
  853. package/scripts/sonar/sonar-new-code-cli.ts +1 -1
  854. package/scripts/sonar/sonar-new-code.ts +1 -1
  855. package/scripts/sonar/sonar-project.ts +1 -1
  856. package/scripts/split/split-assess-cli.ts +1 -1
  857. package/scripts/split/split-assess.ts +3 -3
  858. package/scripts/sync/directory-copy-guard.ts +2 -3
  859. package/scripts/sync/managed-config-scope-cli.ts +1 -2
  860. package/scripts/sync/managed-config-scope.ts +4 -4
  861. package/scripts/sync/plugin-skill-directories.ts +2 -2
  862. package/scripts/sync/reconcile-templates.ts +17 -8
  863. package/scripts/sync/removed-skill-manifest.ts +2 -3
  864. package/scripts/sync/sync-ai-files.ts +7 -7
  865. package/scripts/sync/sync-configs.ts +30 -3
  866. package/scripts/sync/sync-hook-safety.ts +2 -2
  867. package/scripts/sync/sync.ts +23 -10
  868. package/scripts/sync/synced-paths.ts +2 -1
  869. package/scripts/sync/workflow-pin-logic.ts +1 -1
  870. package/scripts/test/test-declared-changed.ts +4 -4
  871. package/scripts/test/test-declared-logic.ts +2 -3
  872. package/scripts/test/test-declared-match.ts +25 -4
  873. package/scripts/test/test-declared.ts +26 -9
  874. package/scripts/test/test-red-commit.ts +3 -2
  875. package/scripts/test/test-red-logic.ts +7 -14
  876. package/scripts/test/test-red.ts +12 -47
  877. package/scripts/test/test-related-scope.ts +2 -3
  878. package/scripts/test/test-related.ts +3 -3
  879. package/scripts/test/test-type-logic.ts +1 -2
  880. package/scripts/test/test-unit-guard.ts +13 -17
  881. package/scripts/test/unit-worker-share.ts +7 -8
  882. package/scripts/time-runtime/time-agent-bundles.ts +2 -4
  883. package/scripts/time-runtime/time-background.ts +17 -21
  884. package/scripts/time-runtime/time-batch-guard.ts +67 -342
  885. package/scripts/time-runtime/time-bundle-call.ts +26 -28
  886. package/scripts/time-runtime/time-bundles.ts +11 -12
  887. package/scripts/time-runtime/time-call-identity.ts +1 -1
  888. package/scripts/time-runtime/time-command-key.ts +2 -2
  889. package/scripts/time-runtime/time-density-hook.ts +8 -11
  890. package/scripts/time-runtime/time-density.ts +5 -5
  891. package/scripts/time-runtime/time-followup-stage.ts +7 -7
  892. package/scripts/time-runtime/time-format.ts +5 -5
  893. package/scripts/time-runtime/time-hook-transcript.ts +3 -3
  894. package/scripts/time-runtime/time-instant.ts +1 -1
  895. package/scripts/time-runtime/time-markers.ts +15 -19
  896. package/scripts/time-runtime/time-phase-names.ts +3 -3
  897. package/scripts/time-runtime/time-reported-failure.ts +15 -19
  898. package/scripts/time-runtime/time-round-trips.ts +20 -23
  899. package/scripts/time-runtime/time-shell.ts +8 -8
  900. package/scripts/time-runtime/time-single-check.ts +1 -2
  901. package/scripts/time-runtime/time-spans.ts +35 -40
  902. package/scripts/time-runtime/time-tool-call.ts +15 -16
  903. package/scripts/time-runtime/time-transcript-line.ts +53 -34
  904. package/scripts/time-runtime/time-writes.ts +5 -5
  905. package/scripts/ui/ui-routes-cli.ts +1 -2
  906. package/scripts/ui/ui-routes.ts +1 -2
  907. package/scripts/version/bump-version.ts +1 -1
  908. package/scripts/version/fresh-metadata-cache.ts +2 -2
  909. package/scripts/version/latest-corepack.ts +26 -26
  910. package/scripts/version/latest-lane-guard.ts +1 -1
  911. package/scripts/version/latest-scope-cli.ts +2 -2
  912. package/scripts/version/latest-stamp.ts +1 -2
  913. package/scripts/version/latest-update.ts +2 -2
  914. package/scripts/version/npm-registry.ts +2 -2
  915. package/scripts/version/package-manager-version.ts +18 -0
  916. package/scripts/version/publishable-range-check.ts +2 -1
  917. package/scripts/version/publishable-range.ts +1 -1
  918. package/scripts/version/release-age.ts +11 -11
  919. package/scripts/version/release-hold.ts +2 -2
  920. package/scripts/version/safe-chain-version-update.ts +3 -3
  921. package/scripts/version/version-check-logic.ts +2 -3
  922. package/scripts/version/version-check.ts +1 -2
  923. package/scripts/version/version-command-config.ts +2 -2
  924. package/scripts/version/version-commands.ts +3 -3
  925. package/scripts/version/version-remote.ts +4 -4
  926. package/scripts/version/version-targets.ts +2 -2
  927. package/templates/gitignore +7 -0
  928. package/dist/hooks/chunk-KHX4U3BG.js +0 -6400
  929. package/dist/hooks/chunk-RKUAD3I6.js +0 -90
  930. package/dist/hooks/chunk-WPALEIRX.js +0 -18
  931. package/scripts/backlog/backlog-restructure.ts +0 -152
  932. package/scripts/rules/issue-fold-rule.ts +0 -72
  933. package/scripts/rules/wip-cap.ts +0 -63
  934. package/scripts/run/run-issue-number.ts +0 -19
@@ -1,24 +1,17 @@
1
1
  import {
2
- ENV_FILE_NAME
3
- } from "./chunk-RKUAD3I6.js";
2
+ ENV_FILE_NAME,
3
+ cost_transcript,
4
+ json_value,
5
+ process_identity,
6
+ process_owner_schema,
7
+ run_carry,
8
+ time_instant
9
+ } from "./chunk-NZN2UFI6.js";
4
10
  import {
5
11
  PLATFORM_TEMP_ROOT,
6
12
  PROBE_TIMEOUT_MS,
7
13
  stamp_file
8
- } from "./chunk-ELCN5LCH.js";
9
-
10
- // scripts/lib/json-value.ts
11
- function parse_or_undefined(text) {
12
- try {
13
- return JSON.parse(text);
14
- } catch {
15
- return void 0;
16
- }
17
- }
18
- function is_record(value) {
19
- return typeof value === "object" && value !== null && !Array.isArray(value);
20
- }
21
- var json_value = { parse_or_undefined, is_record };
14
+ } from "./chunk-NEC4AT4Z.js";
22
15
 
23
16
  // scripts/cost-runtime/cost-blocks.ts
24
17
  import { z } from "zod";
@@ -151,6 +144,17 @@ var CSPELL_CACHE_FLAGS = content_cache_flags(CSPELL_CACHE_FILE);
151
144
 
152
145
  // scripts/josh/josh-commands-backlog.ts
153
146
  var BACKLOG_COMMANDS = {
147
+ // Started from a terminal: the `backlogrun` keyword's launcher, and the board.
148
+ backlogrun: {
149
+ script: "scripts/backlog/backlogrun-cli.ts",
150
+ description: "Start a backlogrun in the background and show its board; with one already running, only show the board",
151
+ category: "AI tools",
152
+ reference: [
153
+ "[#<n>...] [--only] [--max <n>] [--idle <minutes>] [--agent claude|codex]",
154
+ "developer",
155
+ ["files", "network", "processes"]
156
+ ]
157
+ },
154
158
  "backlog:next": {
155
159
  script: "scripts/backlog/backlog-next.ts",
156
160
  description: "Order the whole opted-in backlog: auto-ok issues and the descendants of auto-ok epics, transitively through nested epics",
@@ -181,7 +185,7 @@ var BACKLOG_COMMANDS = {
181
185
  },
182
186
  "backlog:stalled": {
183
187
  script: "scripts/backlog/backlog-stalled-cli.ts",
184
- // A stall sends one Telegram warning (joshuafolkken/kit#3357). The `Stop` hook calls the detector
188
+ // A stall sends one Telegram warning. The `Stop` hook calls the detector
185
189
  // directly, so this flag costs only the manual command its in-process dispatch.
186
190
  tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
187
191
  description: "Report whether ready backlog work is sitting undispatched with a free lane and no recent dispatch",
@@ -276,7 +280,7 @@ var ISSUE_COMMANDS = {
276
280
  },
277
281
  "defect:rate": {
278
282
  script: "scripts/issue/defect-rate-cli.ts",
279
- description: "Print the defect rate of merged work: defects filed per behavior change completed",
283
+ description: "Print the defect rate of merged work: defects filed per enhancement completed",
280
284
  category: "AI tools",
281
285
  reference: ["[--days <n>]", "automation", ["network"]]
282
286
  },
@@ -306,10 +310,10 @@ var ISSUE_COMMANDS = {
306
310
  },
307
311
  "issue:file": {
308
312
  script: "scripts/issue/issue-file-cli.ts",
309
- description: "File an Issue with every filing step: lint, Origin, WIP cap, duplicate scout, labels, then epic:bundle",
313
+ description: "File an Issue with every filing step: lint, Origin, fold, WIP cap, duplicate scout, labels, then epic:bundle",
310
314
  category: "AI tools",
311
315
  reference: [
312
- "<title> --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>] [--distinct <N,\u2026>] [--over-cap] [--no-auto-ok] [--release]",
316
+ "<title> --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>] [--distinct <N,\u2026>] [--over-cap] [--no-auto-ok] [--requested] [--release]",
313
317
  "automation",
314
318
  ["network"]
315
319
  ]
@@ -386,18 +390,27 @@ var LANE_COMMANDS = {
386
390
  category: "AI tools",
387
391
  reference: ["<issue> [--stash <message>]", "automation", ["files", "git", "processes"]]
388
392
  },
389
- // The lane-limit measurement (joshuafolkken/kit#3355): `.env` is read so `lane:stats` labels the row
393
+ // A live run's lane limit: `.env` is read so the bare form reports the
394
+ // `JOSH_LANE_LIMIT` a person set there when no override stands.
395
+ "lane:limit": {
396
+ script: "scripts/lane/lane-limit-cli.ts",
397
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
398
+ description: "Change a live backlogrun\u2019s lane limit without stopping it, or print the limit, lanes in use and free lanes",
399
+ category: "AI tools",
400
+ reference: ["[<limit>] [--reset]", "developer", ["files"]]
401
+ },
402
+ // The lane-limit measurement: `.env` is read so `lane:stats` labels the row
390
403
  // with the `JOSH_LANE_LIMIT` a person set there.
391
404
  "lane:sample": {
392
405
  ...MEASURE_ARGUMENTS,
393
- description: "Record the machine load (load average, swap, free memory, working lanes) to the lane ledger",
406
+ 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",
394
407
  category: "AI tools",
395
408
  reference: ["[--every <seconds>]", "maintainer", ["files"]],
396
409
  default_script_arguments: ["sample"]
397
410
  },
398
411
  "lane:stats": {
399
412
  ...MEASURE_ARGUMENTS,
400
- description: "Print one table row of lane throughput, gate duration and machine load over a period",
413
+ description: "Print one table row of lane throughput, gate duration and machine load over a period, and the per-stage durations of a lane under it",
401
414
  category: "AI tools",
402
415
  reference: ["--period <days> [--limit <lane-limit>]", "maintainer", ["none"]],
403
416
  default_script_arguments: ["stats"]
@@ -429,12 +442,18 @@ var RUN_COMMANDS = {
429
442
  "run:carry": {
430
443
  script: "scripts/run/carry/run-carry-cli.ts",
431
444
  // `--stopped` sends the stop confirmation, so the Telegram credentials come from `.env` as for
432
- // `run:wake` below (joshuafolkken/kit#3357).
445
+ // `run:wake` below.
433
446
  tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
434
447
  description: "Carry one invocation\u2019s budget across its own session cuts",
435
448
  category: "AI tools",
436
449
  reference: ["<operation> [arguments...]", "automation", ["files"]]
437
450
  },
451
+ "run:add": {
452
+ script: "scripts/run/add/run-add-cli.ts",
453
+ description: "Add issues to a live backlogrun, ahead of the queue unless --no-priority",
454
+ category: "AI tools",
455
+ reference: ["<issue...> [--no-priority]", "automation", ["network", "files"]]
456
+ },
438
457
  "run:wake": {
439
458
  script: "scripts/run/wake/run-wake-cli.ts",
440
459
  // `.env` rather than the ambient environment:
@@ -473,18 +492,26 @@ var RUN_COMMANDS = {
473
492
  ["files"]
474
493
  ]
475
494
  },
495
+ "run:board": {
496
+ script: "scripts/run/board/run-board-cli.ts",
497
+ // `--every` pushes its frame as a Telegram, so the credentials come from `.env` as for `run:carry`.
498
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
499
+ description: "Draw a live board of the running backlogrun, redrawn every second",
500
+ category: "AI tools",
501
+ reference: ["[--once | --chat | --every <minutes>]", "automation", ["files", "network"]]
502
+ },
476
503
  "run:prep": {
477
504
  script: "scripts/run/run-prep-cli.ts",
478
505
  description: "Bundle a run\u2019s pre-edit reads: body, comments, state, dependency scope",
479
506
  category: "AI tools",
480
507
  reference: ["<issue>", "automation", ["network"]]
481
508
  },
482
- // The entry sequence a lane opened on, folded into one call (joshuafolkken/kit#2372): claim the tree,
509
+ // The entry sequence a lane opened on, folded into one call: claim the tree,
483
510
  // read the budget, gather the issue reads and decide the pre-implementation step. `run:hold`,
484
511
  // `cost --cut`, `run:prep` and `run:step` were four round trips re-billing a lane's full context each.
485
512
  "run:entry": {
486
513
  script: "scripts/run/entry/run-entry-cli.ts",
487
- // A `busy` hold or an `over` budget sends the stop confirmation (joshuafolkken/kit#3357).
514
+ // A `busy` hold or an `over` budget sends the stop confirmation.
488
515
  tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
489
516
  description: "Open a run in one call: claim the tree, read the budget, bundle the reads, decide the pre-implementation step",
490
517
  category: "AI tools",
@@ -506,7 +533,7 @@ var RUN_COMMANDS = {
506
533
  script: "scripts/run/run-step-cli.ts",
507
534
  description: "Print the run\u2019s next single action, computed from the event stream, carry record and issue state",
508
535
  category: "AI tools",
509
- reference: ["<issue>", "automation", ["network", "files"]]
536
+ reference: ["[<issue>]", "automation", ["network", "files"]]
510
537
  }
511
538
  };
512
539
 
@@ -587,12 +614,12 @@ var AI_COMMANDS = {
587
614
  reference: ["[options]", "maintainer", ["none"]],
588
615
  // Kit-only: it measures kit's own development runs and its report modules live under the
589
616
  // undistributed `scripts/time/`, so it means nothing in a consumer project and is dropped from a
590
- // consumer's help (joshuafolkken/kit#1997). The runtime analysis hooks and guards rely on stays
617
+ // consumer's help. The runtime analysis hooks and guards rely on stays
591
618
  // distributed under `scripts/time-runtime/`.
592
619
  is_kit_only: true
593
620
  },
594
621
  // The tool-calls-per-round-trip density the batching guard is measured on, aggregated across the
595
- // recent lane sessions (joshuafolkken/kit#2405). Kit-only for the same reason `time` is: it reads
622
+ // recent lane sessions. Kit-only for the same reason `time` is: it reads
596
623
  // kit's own lane transcripts and means nothing in a consumer project.
597
624
  "time:density": {
598
625
  script: "scripts/time/time-density-cli.ts",
@@ -608,7 +635,7 @@ var AI_COMMANDS = {
608
635
  reference: ["", "maintainer", ["none"]],
609
636
  // Kit-only: it reads kit's own development run — the transcript store, the review ledger and the
610
637
  // run event stream — so it means nothing in a consumer project and is dropped from a consumer's
611
- // help (joshuafolkken/kit#2328), through the same declaration `josh time` uses for the same reason.
638
+ // help, through the same declaration `josh time` uses for the same reason.
612
639
  is_kit_only: true
613
640
  },
614
641
  "review:brief": {
@@ -660,7 +687,7 @@ var AI_COMMANDS = {
660
687
  category: "AI tools",
661
688
  reference: ["[--join]", "automation", ["processes", "files"]]
662
689
  },
663
- // The post-merge sequence a run closed on, folded into one call (joshuafolkken/kit#2372): commit the
690
+ // The post-merge sequence a run closed on, folded into one call: commit the
664
691
  // observation ledger, read the completion citations and decide the release scope. `observations:flush`,
665
692
  // `issue:cite` and `release:scope` were three round trips re-billing the run's full context each.
666
693
  "run:tail": {
@@ -669,7 +696,7 @@ var AI_COMMANDS = {
669
696
  category: "AI tools",
670
697
  reference: ["[<issue> ...]", "automation", ["git", "network"]]
671
698
  },
672
- // The commit-to-report region a run ships a change on, folded into one call (joshuafolkken/kit#2398):
699
+ // The commit-to-report region a run ships a change on, folded into one call:
673
700
  // the gate, the commit/push/PR (`git -y`), the CI-wait merge (`followup`) and the report bookkeeping
674
701
  // (`run:tail`) were four round trips re-billing the run's full context each. It stops at the first
675
702
  // failed step and names it, so the run reads only the step to fix.
@@ -729,7 +756,7 @@ var AI_COMMANDS = {
729
756
  category: "AI tools",
730
757
  reference: ["[scenario...]", "maintainer", ["processes", "network"]],
731
758
  // Kit-only: it replays kit's own distributed rules against real Claude sessions, so it means
732
- // nothing in a consumer project and is dropped from a consumer's help (joshuafolkken/kit#1988).
759
+ // nothing in a consumer project and is dropped from a consumer's help.
733
760
  is_kit_only: true
734
761
  }
735
762
  };
@@ -745,186 +772,15 @@ var CLONE_COMMANDS = {
745
772
  };
746
773
 
747
774
  // scripts/gate/core-budget.ts
748
- import { randomUUID as randomUUID2 } from "node:crypto";
775
+ import { randomUUID } from "node:crypto";
749
776
  import { readdirSync as readdirSync2 } from "node:fs";
750
777
  import { availableParallelism as availableParallelism3 } from "node:os";
751
- import path3 from "node:path";
752
-
753
- // scripts/josh/process-identity.ts
754
- import { execFileSync, spawnSync } from "node:child_process";
755
- import { randomUUID } from "node:crypto";
756
- import { readFileSync, rmSync } from "node:fs";
757
- import { createServer } from "node:net";
758
- import path from "node:path";
759
- var PS_COMMAND = "/bin/ps";
760
- var FORMAT_FLAG = "-o";
761
- var START_TIME_FORMAT = "lstart=";
762
- var PID_FLAG = "-p";
763
- var PROBE_ENVIRONMENT = { TZ: "UTC", LC_ALL: "C" };
764
- var LIVENESS_SIGNAL = 0;
765
- var LOWEST_REAL_PID = 1;
766
- var PROC_START_FIELD_INDEX = 19;
767
- var BEACON_SCHEME = "socket:";
768
- var BEACON_SUFFIX = ".sock";
769
- var BEACON_PREFIX = `josh-process-identity-${String(process.getuid?.() ?? "")}-`;
770
- var BEACON_ID_LENGTH = 36;
771
- var BEACON_ID_PATTERN = /^[\da-f-]+$/u;
772
- var WINDOWS_PLATFORM = "win32";
773
- var SOCKET_PROBE_SOURCE = "const net=require('node:net');const socket=net.createConnection(process.argv[1]);socket.once('connect',()=>process.exit(0));socket.once('error',()=>process.exit(1));socket.setTimeout(1000,()=>process.exit(1));";
774
- var beacons = /* @__PURE__ */ new Map();
775
- var exit_cleanup = { is_registered: false };
776
- function is_live_pid(pid) {
777
- if (pid < LOWEST_REAL_PID) return false;
778
- try {
779
- process.kill(pid, LIVENESS_SIGNAL);
780
- return true;
781
- } catch {
782
- return false;
783
- }
784
- }
785
- function read_proc_start(pid) {
786
- try {
787
- const stat = readFileSync(`/proc/${String(pid)}/stat`, "utf8");
788
- const fields = stat.slice(stat.lastIndexOf(")") + 1).trim().split(/\s+/u);
789
- const start = fields[PROC_START_FIELD_INDEX];
790
- return start === void 0 ? void 0 : `proc:${start}`;
791
- } catch {
792
- return void 0;
793
- }
794
- }
795
- function read_ps_start(pid) {
796
- try {
797
- const printed = execFileSync(
798
- PS_COMMAND,
799
- [FORMAT_FLAG, START_TIME_FORMAT, PID_FLAG, String(pid)],
800
- {
801
- encoding: "utf8",
802
- timeout: PROBE_TIMEOUT_MS,
803
- stdio: ["ignore", "pipe", "ignore"],
804
- env: PROBE_ENVIRONMENT
805
- }
806
- ).trim();
807
- return printed.length > 0 ? printed : void 0;
808
- } catch {
809
- return void 0;
810
- }
811
- }
812
- var START_PROBES = { read_proc_start, read_ps_start };
813
- function safe_probe(probe, pid) {
814
- try {
815
- return probe(pid);
816
- } catch {
817
- return void 0;
818
- }
819
- }
820
- function read_start(pid, probes = START_PROBES) {
821
- return safe_probe(probes.read_proc_start, pid) ?? safe_probe(probes.read_ps_start, pid);
822
- }
823
- function close_beacon(token) {
824
- const server = beacons.get(token);
825
- if (server === void 0) return;
826
- beacons.delete(token);
827
- server.close();
828
- rmSync(token.slice(BEACON_SCHEME.length), { force: true });
829
- }
830
- function close_beacons() {
831
- for (const token of beacons.keys()) close_beacon(token);
832
- }
833
- function ensure_exit_cleanup() {
834
- if (exit_cleanup.is_registered) return;
835
- exit_cleanup.is_registered = true;
836
- process.once("exit", close_beacons);
837
- }
838
- function ignore_beacon_error() {
839
- }
840
- function bind_beacon(target) {
841
- return createServer().on("error", ignore_beacon_error).listen(target);
842
- }
843
- function try_bind_beacon(bind, target) {
844
- try {
845
- const server = bind(target);
846
- return server.listening ? server : void 0;
847
- } catch {
848
- return void 0;
849
- }
850
- }
851
- function open_beacon(bind = bind_beacon) {
852
- const target = path.join(PLATFORM_TEMP_ROOT, `${BEACON_PREFIX}${randomUUID()}${BEACON_SUFFIX}`);
853
- const token = `${BEACON_SCHEME}${target}`;
854
- const server = try_bind_beacon(bind, target);
855
- if (server === void 0) return void 0;
856
- server.unref();
857
- beacons.set(token, server);
858
- ensure_exit_cleanup();
859
- return token;
860
- }
861
- function resolve_own_start(probes = START_PROBES, platform = process.platform) {
862
- const start = read_start(process.pid, probes);
863
- if (start !== void 0 || platform === WINDOWS_PLATFORM) return start;
864
- return open_beacon();
865
- }
866
- function is_valid_beacon_name(name) {
867
- if (!name.startsWith(BEACON_PREFIX) || !name.endsWith(BEACON_SUFFIX)) return false;
868
- const id = name.slice(BEACON_PREFIX.length, -BEACON_SUFFIX.length);
869
- return id.length === BEACON_ID_LENGTH && BEACON_ID_PATTERN.test(id);
870
- }
871
- function beacon_target(token) {
872
- if (!token.startsWith(BEACON_SCHEME)) return void 0;
873
- const target = token.slice(BEACON_SCHEME.length);
874
- if (path.dirname(target) !== PLATFORM_TEMP_ROOT) return void 0;
875
- return is_valid_beacon_name(path.basename(target)) ? target : void 0;
876
- }
877
- function is_live_beacon(target) {
878
- return spawnSync(process.execPath, ["-e", SOCKET_PROBE_SOURCE, target], {
879
- stdio: "ignore",
880
- timeout: PROBE_TIMEOUT_MS
881
- }).status === 0;
882
- }
883
- function has_matching_start(pid, recorded_start, read) {
884
- const observed = read(pid);
885
- return observed === void 0 ? void 0 : observed === recorded_start;
886
- }
887
- function matches_recorded_start(pid, recorded_start, read) {
888
- const target = beacon_target(recorded_start);
889
- return target === void 0 ? has_matching_start(pid, recorded_start, read) : is_live_beacon(target);
890
- }
891
- var own_probe = /* @__PURE__ */ new Map();
892
- function own_start() {
893
- if (!own_probe.has(process.pid)) own_probe.set(process.pid, resolve_own_start());
894
- return own_probe.get(process.pid);
895
- }
896
- function own_fields() {
897
- const start = own_start();
898
- return { pid: process.pid, ...start !== void 0 && { process_start: start } };
899
- }
900
- function is_same_process(pid, recorded_start, read = read_start) {
901
- if (pid === void 0 || !is_live_pid(pid)) return false;
902
- if (recorded_start === void 0) return void 0;
903
- return matches_recorded_start(pid, recorded_start, read);
904
- }
905
- function is_own_process(pid, recorded_start) {
906
- return pid === process.pid && recorded_start === own_start();
907
- }
908
- var process_identity = {
909
- close_beacon,
910
- is_live_pid,
911
- is_own_process,
912
- is_same_process,
913
- open_beacon,
914
- own_fields,
915
- own_start,
916
- read_start,
917
- resolve_own_start
918
- };
919
-
920
- // scripts/josh/process-owner.ts
921
- import { z as z2 } from "zod";
922
- var process_owner_schema = z2.object({ pid: z2.number(), process_start: z2.string().optional() });
778
+ import path2 from "node:path";
923
779
 
924
780
  // scripts/test/unit-worker-share.ts
925
781
  import { readdirSync } from "node:fs";
926
782
  import { availableParallelism } from "node:os";
927
- import path2 from "node:path";
783
+ import path from "node:path";
928
784
  var RUN_PREFIX = "josh-unit-running-";
929
785
  var WORKER_FLAG = "--maxWorkers";
930
786
  var WORKER_FLAGS = [WORKER_FLAG, "--max-workers"];
@@ -963,7 +819,7 @@ function is_marker_live(source) {
963
819
  return false;
964
820
  }
965
821
  function live_run_count(directory = PLATFORM_TEMP_ROOT) {
966
- return marker_files(directory).filter((name) => is_marker_live(path2.join(directory, name))).length;
822
+ return marker_files(directory).filter((name) => is_marker_live(path.join(directory, name))).length;
967
823
  }
968
824
  var NESTED_KEY = "JOSH_UNIT_RUN_MARKED";
969
825
  var NESTED_VALUE = "1";
@@ -986,22 +842,22 @@ function worker_arguments(vitest_arguments, share) {
986
842
  if (vitest_arguments.some((argument) => is_worker_flag(argument))) return [];
987
843
  return [`${WORKER_FLAG}=${String(share)}`];
988
844
  }
989
- function mark_run_started(target) {
845
+ function mark_run_started(target2) {
990
846
  try {
991
- stamp_file.write_stamp(target, process_identity.own_fields());
847
+ stamp_file.write_stamp(target2, process_identity.own_fields());
992
848
  } catch {
993
849
  }
994
850
  }
995
851
  async function with_run_marker(run) {
996
852
  if (is_nested_run()) return await run();
997
- const target = marker_path();
998
- mark_run_started(target);
853
+ const target2 = marker_path();
854
+ mark_run_started(target2);
999
855
  process.env[NESTED_KEY] = NESTED_VALUE;
1000
856
  try {
1001
857
  return await run();
1002
858
  } finally {
1003
859
  process.env[NESTED_KEY] = "";
1004
- stamp_file.remove_stamp(target);
860
+ stamp_file.remove_stamp(target2);
1005
861
  }
1006
862
  }
1007
863
  var unit_worker_share = {
@@ -1021,7 +877,7 @@ var unit_worker_share = {
1021
877
  };
1022
878
 
1023
879
  // scripts/gate/core-budget.ts
1024
- import { z as z3 } from "zod";
880
+ import { z as z2 } from "zod";
1025
881
 
1026
882
  // scripts/gate/core-admission.ts
1027
883
  var MS_PER_SECOND = 1e3;
@@ -1104,9 +960,18 @@ var BYTES_PER_MB = 1048576;
1104
960
  var KB_PER_MB = 1024;
1105
961
  var PERCENT = 100;
1106
962
  var MEMINFO_PATH = "/proc/meminfo";
963
+ var VMSTAT_PATH = "/proc/vmstat";
1107
964
  var LINUX_AVAILABLE = /^MemAvailable:\s+(?<kb>\d+) kB/mu;
1108
- var PRESSURE_ARGUMENTS = ["-n", "kern.memorystatus_level"];
1109
- var PRESSURE_LEVEL = /^\s*(?<level>\d+)\s*$/u;
965
+ var LINUX_SWAP_IN = /^pswpin (?<pages>\d+)$/mu;
966
+ var LINUX_SWAP_OUT = /^pswpout (?<pages>\d+)$/mu;
967
+ var PAGE_SIZE_ARGUMENTS = ["PAGESIZE"];
968
+ var LEVEL_NAME = "kern.memorystatus_level";
969
+ var SWAP_IN_NAME = "vm.compressor.swapper.swapins_total";
970
+ var SWAP_OUT_NAME = "vm.compressor.swapper.swapouts_total";
971
+ var PAGE_SIZE_NAME = "hw.pagesize";
972
+ var PRESSURE_NAME = "kern.memorystatus_vm_pressure_level";
973
+ var SYSCTL_ARGUMENTS = [LEVEL_NAME, SWAP_IN_NAME, SWAP_OUT_NAME, PAGE_SIZE_NAME, PRESSURE_NAME];
974
+ var SYSCTL_LINE = /^(?<name>[\w.]+): (?<value>\d+)$/gmu;
1110
975
  function cpu_times() {
1111
976
  let busy = 0;
1112
977
  let idle = 0;
@@ -1116,31 +981,96 @@ function cpu_times() {
1116
981
  }
1117
982
  return { busy, total: busy + idle };
1118
983
  }
1119
- function busy_cores_between(before, after, cores) {
984
+ function busy_share_between(before, after) {
1120
985
  const total = after.total - before.total;
1121
986
  if (total <= 0) return void 0;
1122
- return (after.busy - before.busy) / total * cores;
987
+ return (after.busy - before.busy) / total;
988
+ }
989
+ function busy_cores_between(before, after, cores) {
990
+ const share = busy_share_between(before, after);
991
+ return share === void 0 ? void 0 : share * cores;
992
+ }
993
+ function sysctl_values(output) {
994
+ const values = [...output.matchAll(SYSCTL_LINE)].map(
995
+ (match) => [match.groups?.["name"] ?? "", Number(match.groups?.["value"])]
996
+ );
997
+ return new Map(values);
998
+ }
999
+ function swapped_pages(pages_in, pages_out) {
1000
+ return pages_in === void 0 || pages_out === void 0 ? void 0 : pages_in + pages_out;
1001
+ }
1002
+ function swapped_mb(pages, page_bytes) {
1003
+ if (pages === void 0 || page_bytes === void 0) return void 0;
1004
+ return pages * page_bytes / BYTES_PER_MB;
1123
1005
  }
1124
- function parse_darwin_pressure(output, total_bytes) {
1125
- const level = PRESSURE_LEVEL.exec(output)?.groups?.["level"];
1126
- if (level === void 0) return void 0;
1127
- return Number(level) / PERCENT * (total_bytes / BYTES_PER_MB);
1006
+ function swapped_between(from, to) {
1007
+ if (from === void 0 || to === void 0) return void 0;
1008
+ return Math.max(0, to - from);
1009
+ }
1010
+ function parse_darwin_memory(output, total_bytes) {
1011
+ const values = sysctl_values(output);
1012
+ const level = values.get(LEVEL_NAME);
1013
+ return {
1014
+ available_mb: level === void 0 ? void 0 : level / PERCENT * (total_bytes / BYTES_PER_MB),
1015
+ swapped_mb: swapped_mb(
1016
+ swapped_pages(values.get(SWAP_IN_NAME), values.get(SWAP_OUT_NAME)),
1017
+ values.get(PAGE_SIZE_NAME)
1018
+ ),
1019
+ pressure_level: values.get(PRESSURE_NAME)
1020
+ };
1128
1021
  }
1129
1022
  function parse_linux_available(meminfo) {
1130
1023
  const kb = LINUX_AVAILABLE.exec(meminfo)?.groups?.["kb"];
1131
1024
  return kb === void 0 ? void 0 : Number(kb) / KB_PER_MB;
1132
1025
  }
1133
- async function read_available_mb(platform = process.platform) {
1026
+ function pages_of(pattern, vmstat) {
1027
+ const pages = pattern.exec(vmstat)?.groups?.["pages"];
1028
+ return pages === void 0 ? void 0 : Number(pages);
1029
+ }
1030
+ function parse_linux_swapped(vmstat, page_bytes) {
1031
+ const pages = swapped_pages(pages_of(LINUX_SWAP_IN, vmstat), pages_of(LINUX_SWAP_OUT, vmstat));
1032
+ return swapped_mb(pages, page_bytes);
1033
+ }
1034
+ async function settled(read) {
1134
1035
  try {
1135
- if (platform === "darwin") {
1136
- const { stdout } = await execa("sysctl", PRESSURE_ARGUMENTS);
1137
- return parse_darwin_pressure(stdout, totalmem());
1138
- }
1139
- return platform === "linux" ? parse_linux_available(await readFile(MEMINFO_PATH, "utf8")) : void 0;
1036
+ return await read();
1140
1037
  } catch {
1141
1038
  return void 0;
1142
1039
  }
1143
1040
  }
1041
+ async function read_darwin_memory() {
1042
+ const { stdout } = await execa("sysctl", SYSCTL_ARGUMENTS, {
1043
+ reject: false,
1044
+ timeout: PROBE_TIMEOUT_MS
1045
+ });
1046
+ return parse_darwin_memory(stdout, totalmem());
1047
+ }
1048
+ async function read_page_size() {
1049
+ const { stdout } = await execa("getconf", PAGE_SIZE_ARGUMENTS, { timeout: PROBE_TIMEOUT_MS });
1050
+ return stdout;
1051
+ }
1052
+ async function read_linux_memory() {
1053
+ const [meminfo, vmstat, page_size] = await Promise.all([
1054
+ settled(async () => await readFile(MEMINFO_PATH, "utf8")),
1055
+ settled(async () => await readFile(VMSTAT_PATH, "utf8")),
1056
+ settled(read_page_size)
1057
+ ]);
1058
+ const page_bytes = page_size === void 0 ? void 0 : Number(page_size);
1059
+ return {
1060
+ available_mb: meminfo === void 0 ? void 0 : parse_linux_available(meminfo),
1061
+ swapped_mb: vmstat === void 0 || page_bytes === void 0 ? void 0 : parse_linux_swapped(vmstat, page_bytes),
1062
+ pressure_level: void 0
1063
+ };
1064
+ }
1065
+ var UNREAD_MEMORY = {
1066
+ available_mb: void 0,
1067
+ swapped_mb: void 0,
1068
+ pressure_level: void 0
1069
+ };
1070
+ async function read_memory() {
1071
+ if (process.platform === "darwin") return await settled(read_darwin_memory) ?? UNREAD_MEMORY;
1072
+ return process.platform === "linux" ? await read_linux_memory() : UNREAD_MEMORY;
1073
+ }
1144
1074
  function is_unquoted() {
1145
1075
  return cpus().length > 0 && cpus().length === availableParallelism2();
1146
1076
  }
@@ -1151,9 +1081,12 @@ async function default_sleep(ms) {
1151
1081
  }
1152
1082
  async function read_machine(sleep = default_sleep) {
1153
1083
  const before = cpu_times();
1154
- const [available_mb] = await Promise.all([read_available_mb(), sleep(SAMPLE_WINDOW_MS)]);
1084
+ const [memory] = await Promise.all([read_memory(), sleep(SAMPLE_WINDOW_MS)]);
1155
1085
  const busy_cores = is_unquoted() ? busy_cores_between(before, cpu_times(), cpus().length) : void 0;
1156
- return { busy_cores, available_mb };
1086
+ return { busy_cores, available_mb: memory.available_mb };
1087
+ }
1088
+ async function read_sample() {
1089
+ return { cpu: cpu_times(), memory: await read_memory(), total_mb: totalmem() / BYTES_PER_MB };
1157
1090
  }
1158
1091
  function external_cores(busy_cores, ledger_cores) {
1159
1092
  if (busy_cores === void 0) return 0;
@@ -1168,10 +1101,16 @@ function machine_budget(cores, reading, ledger) {
1168
1101
  var machine_capacity = {
1169
1102
  BASELINE_CORES,
1170
1103
  busy_cores_between,
1104
+ busy_share_between,
1105
+ external_cores,
1171
1106
  machine_budget,
1172
- parse_darwin_pressure,
1107
+ parse_darwin_memory,
1173
1108
  parse_linux_available,
1174
- read_machine
1109
+ parse_linux_swapped,
1110
+ read_machine,
1111
+ read_memory,
1112
+ read_sample,
1113
+ swapped_between
1175
1114
  };
1176
1115
 
1177
1116
  // scripts/gate/core-budget.ts
@@ -1196,10 +1135,10 @@ var MEMORY_MB = {
1196
1135
  var HELD_KEY = "JOSH_CORE_RESERVED";
1197
1136
  var HELD_VALUE = "1";
1198
1137
  var reservation_schema = process_owner_schema.extend({
1199
- weight: z3.number(),
1200
- claimed_at: z3.number(),
1201
- memory_mb: z3.number().optional(),
1202
- admitted_at: z3.number().optional()
1138
+ weight: z2.number(),
1139
+ claimed_at: z2.number(),
1140
+ memory_mb: z2.number().optional(),
1141
+ admitted_at: z2.number().optional()
1203
1142
  });
1204
1143
  function marker_name(key) {
1205
1144
  return `${RESERVED_PREFIX}${key}${RESERVED_SUFFIX}`;
@@ -1210,12 +1149,7 @@ function is_running2(reservation) {
1210
1149
  function read_reservation(source) {
1211
1150
  const raw = stamp_file.read_stamp_text(source);
1212
1151
  if (raw === void 0) return void 0;
1213
- try {
1214
- const parsed = reservation_schema.safeParse(JSON.parse(raw));
1215
- return parsed.success ? parsed.data : void 0;
1216
- } catch {
1217
- return void 0;
1218
- }
1152
+ return json_value.parse_with(raw, reservation_schema);
1219
1153
  }
1220
1154
  function sweep_marker2(source) {
1221
1155
  try {
@@ -1241,7 +1175,7 @@ function marker_files2(directory) {
1241
1175
  }
1242
1176
  function live_reservations(directory = PLATFORM_TEMP_ROOT) {
1243
1177
  return marker_files2(directory).flatMap((name) => {
1244
- const reservation = live_reservation(path3.join(directory, name));
1178
+ const reservation = live_reservation(path2.join(directory, name));
1245
1179
  return reservation === void 0 ? [] : { key: name, reservation };
1246
1180
  });
1247
1181
  }
@@ -1253,8 +1187,8 @@ async function default_sleep2(ms) {
1253
1187
  setTimeout(resolve, ms);
1254
1188
  });
1255
1189
  }
1256
- function write_reservation(target, fields) {
1257
- stamp_file.replace_stamp(target, { ...process_identity.own_fields(), ...fields });
1190
+ function write_reservation(target2, fields) {
1191
+ stamp_file.replace_stamp(target2, { ...process_identity.own_fields(), ...fields });
1258
1192
  }
1259
1193
  function resolve_timing(options) {
1260
1194
  return {
@@ -1303,21 +1237,21 @@ async function reserve(weight, options = {}) {
1303
1237
  const timing = resolve_timing(options);
1304
1238
  const directory = options.directory ?? PLATFORM_TEMP_ROOT;
1305
1239
  const claimed_at = timing.now();
1306
- const name = marker_name(randomUUID2());
1307
- const target = path3.join(directory, name);
1240
+ const name = marker_name(randomUUID());
1241
+ const target2 = path2.join(directory, name);
1308
1242
  const fields = { weight, claimed_at, memory_mb: options.memory_mb };
1309
- write_reservation(target, fields);
1243
+ write_reservation(target2, fields);
1310
1244
  const admission = await await_admission({
1311
1245
  ...timing,
1312
1246
  key: name,
1313
- target,
1247
+ target: target2,
1314
1248
  directory,
1315
1249
  budget: normalize_budget(options.budget ?? availableParallelism3()),
1316
1250
  deadline: claimed_at + timing.wait_cap_ms,
1317
1251
  fields,
1318
1252
  read_machine: options.read_machine ?? machine_capacity.read_machine
1319
1253
  });
1320
- return { target, admission };
1254
+ return { target: target2, admission };
1321
1255
  }
1322
1256
  function release(handle) {
1323
1257
  sweep_marker2(handle.target);
@@ -1416,6 +1350,7 @@ var LINT_LABEL = "lint";
1416
1350
  var TYPE_CHECK_LABEL = "check";
1417
1351
  var UNIT_LABEL = "test:unit";
1418
1352
  var BEHAVIOR_LABEL = "behavior";
1353
+ var METRICS_LABEL = "metrics";
1419
1354
  var WARNING_CHECKER_LABELS = [LINT_LABEL, TYPE_CHECK_LABEL];
1420
1355
  var STATIC_CHECKS = [
1421
1356
  {
@@ -1437,18 +1372,31 @@ var STATIC_CHECKS = [
1437
1372
  memory_mb: core_budget.MEMORY_MB.spell_check
1438
1373
  },
1439
1374
  { label: BEHAVIOR_LABEL, target: BEHAVIOR_LABEL, reserved_cores: 0 },
1440
- // **The unused-member check reserves no core** (joshuafolkken/kit#2987): it builds one TypeScript
1375
+ // **The unused-member check reserves no core**: it builds one TypeScript
1441
1376
  // program and walks it for about 5s, and it is over well before lint and the type check. A
1442
1377
  // reservation would only take a place from the four-core CI runner's fan-out and a worker from the
1443
1378
  // unit suite for the whole gate.
1444
- { label: "exports", target: "exports:unused", reserved_cores: 0 }
1379
+ { label: "exports", target: "exports:unused", reserved_cores: 0 },
1380
+ // **The metrics ratchet is kit's own**: it holds kit's repository-wide
1381
+ // totals to the merge-base's. It is one in-process eslint pass with only `max-lines` enabled, over
1382
+ // in a few seconds, so it reserves no core for the reason the unused-member check above does not.
1383
+ // It times no startup here: beside the unit suite that reads the load, not josh.
1384
+ {
1385
+ label: METRICS_LABEL,
1386
+ target: METRICS_LABEL,
1387
+ args: ["--no-startup"],
1388
+ reserved_cores: 0,
1389
+ memory_mb: core_budget.MEMORY_MB.eslint_scan,
1390
+ is_kit_only: true
1391
+ }
1445
1392
  ];
1446
1393
  var GATE_CHECKS = [
1447
1394
  ...STATIC_CHECKS,
1448
1395
  { label: UNIT_LABEL, target: UNIT_LABEL, reserved_cores: 0 }
1449
1396
  ];
1450
- function select_gate_checks(is_unit_included) {
1451
- return is_unit_included ? GATE_CHECKS : STATIC_CHECKS;
1397
+ function select_gate_checks(is_unit_included, is_kit_repository = true) {
1398
+ const checks = is_unit_included ? GATE_CHECKS : STATIC_CHECKS;
1399
+ return is_kit_repository ? checks : checks.filter((check) => check.is_kit_only !== true);
1452
1400
  }
1453
1401
  function has_unit_check(checks) {
1454
1402
  return checks.some((check) => check.label === UNIT_LABEL);
@@ -1502,15 +1450,19 @@ function direct_unit_weight(available_cores = availableParallelism4(), live_runs
1502
1450
  function direct_unit_memory() {
1503
1451
  return unit_memory(direct_unit_weight());
1504
1452
  }
1453
+ function unit_cap_for(checks, available_cores, concurrent_runs) {
1454
+ if (!has_unit_check(checks)) return void 0;
1455
+ return resolve_unit_worker_cap(available_cores, concurrent_runs);
1456
+ }
1505
1457
  function plan_of(concurrency, unit_worker_cap, checks = GATE_CHECKS) {
1506
1458
  return { checks, concurrency, unit_worker_cap };
1507
1459
  }
1508
- function resolve_gate_plan(available_cores = availableParallelism4(), concurrent_runs = unit_worker_share.SOLO_RUNS, is_unit_included = true) {
1509
- const checks = select_gate_checks(is_unit_included);
1460
+ function resolve_gate_plan(available_cores = availableParallelism4(), concurrent_runs = unit_worker_share.SOLO_RUNS, is_unit_included = true, is_kit_repository = true) {
1461
+ const checks = select_gate_checks(is_unit_included, is_kit_repository);
1510
1462
  return {
1511
1463
  checks,
1512
1464
  concurrency: resolve_concurrency(available_cores, concurrent_runs, checks),
1513
- unit_worker_cap: is_unit_included ? resolve_unit_worker_cap(available_cores, concurrent_runs) : void 0
1465
+ unit_worker_cap: unit_cap_for(checks, available_cores, concurrent_runs)
1514
1466
  };
1515
1467
  }
1516
1468
  function format_machine(available_cores, concurrent_runs) {
@@ -1534,6 +1486,7 @@ var gate_plan = {
1534
1486
  GATE_CHECKS,
1535
1487
  LINT_LABEL,
1536
1488
  MEASURED_CORES,
1489
+ METRICS_LABEL,
1537
1490
  RESERVED_CORES,
1538
1491
  STATIC_CHECKS,
1539
1492
  TYPE_CHECK_LABEL,
@@ -1596,6 +1549,19 @@ var DEV_COMMANDS = {
1596
1549
  core_weight: core_budget.CORE_WEIGHTS.eslint_scan,
1597
1550
  memory_mb: core_budget.MEMORY_MB.eslint_scan
1598
1551
  },
1552
+ metrics: {
1553
+ script: "scripts/metrics/metrics-command.ts",
1554
+ description: "Print repository-wide quality totals and durations, and fail when a total grew past the merge-base or a duration past its baseline",
1555
+ category: "Development",
1556
+ reference: [
1557
+ '[--no-startup | --totals-only | --accept --reason "<why>"]',
1558
+ "developer",
1559
+ ["files"]
1560
+ ],
1561
+ core_weight: core_budget.CORE_WEIGHTS.eslint_scan,
1562
+ memory_mb: core_budget.MEMORY_MB.eslint_scan,
1563
+ is_kit_only: true
1564
+ },
1599
1565
  "refactor:scan": {
1600
1566
  script: "scripts/refactor/refactor-scan-cli.ts",
1601
1567
  description: "List refactoring candidates in the changed scope by category and answer clear/candidates",
@@ -1616,6 +1582,12 @@ var DEV_COMMANDS = {
1616
1582
  category: "AI tools",
1617
1583
  reference: ["[--refresh]", "developer", ["files"]]
1618
1584
  },
1585
+ "rule:list": {
1586
+ script: "scripts/rules/rule-list.ts",
1587
+ description: "Print the trigger-delivered rules \u2014 each one's source, firing call and silent turn \u2014 from the guard rows",
1588
+ category: "AI tools",
1589
+ reference: ["", "automation", ["none"]]
1590
+ },
1619
1591
  format: {
1620
1592
  script: "scripts/lint/format.ts",
1621
1593
  description: "Format code with prettier and eslint (skips a tool a basic project lacks)",
@@ -1636,8 +1608,8 @@ var DEV_COMMANDS = {
1636
1608
  // **No `tsx_arguments`, deliberately.** `JOSH_BATCH_GUARD` is a per-machine preference kept in
1637
1609
  // `.env`, which every other command reads through `OPTIONAL_ENV_FILE_FLAGS` — but declaring any
1638
1610
  // `tsx_arguments` disqualifies a command from in-process dispatch (`josh-in-process.ts`), and
1639
- // this one runs before every `Bash` call. That is the hot path joshuafolkken/kit#1342 took a
1640
- // second ~0.16 s tsx start off. The script calls `process.loadEnvFile` itself instead, which is
1611
+ // this one runs before every `Bash` call, where a second ~0.16 s tsx start is not affordable.
1612
+ // The script calls `process.loadEnvFile` itself instead, which is
1641
1613
  // node's own `--env-file` parser with node's own precedence.
1642
1614
  },
1643
1615
  "pretool:guard": {
@@ -1661,7 +1633,7 @@ var DEV_COMMANDS = {
1661
1633
  },
1662
1634
  "session:lang": {
1663
1635
  script: "scripts/josh/session-language-cli.ts",
1664
- description: "Claude Code hook: print the resolved JOSH_SESSION_LANG (defaults to ja) for the session context",
1636
+ 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)",
1665
1637
  category: "Development",
1666
1638
  reference: ["", "automation", ["none"]]
1667
1639
  // **No `tsx_arguments`, deliberately**, the same as `batch:guard` above: this runs on every
@@ -1674,7 +1646,7 @@ var DEV_COMMANDS = {
1674
1646
  category: "Development",
1675
1647
  reference: ["<pretool|posttool>", "automation", ["none"]]
1676
1648
  // The live-source fallback `scripts/hooks/run-hook.sh` derives from the `codex-hook-adapter`
1677
- // bundle name (joshuafolkken/kit#3184). **No `tsx_arguments`**, the same as `pretool:guard`
1649
+ // bundle name. **No `tsx_arguments`**, the same as `pretool:guard`
1678
1650
  // above: it runs before every guarded Codex call.
1679
1651
  },
1680
1652
  "cspell:dot": {
@@ -2028,16 +2000,16 @@ var VERSIONING_COMMANDS = {
2028
2000
  category: "Versioning",
2029
2001
  reference: ["", "developer", ["network"]]
2030
2002
  },
2031
- // The one place that decides a version (joshuafolkken/kit#1169). A `script` entry for the same
2003
+ // The one place that decides a version. A `script` entry for the same
2032
2004
  // reason `ranges` is one: script paths resolve against the kit package root, so it keeps working
2033
2005
  // from a consumer repository where the file lives under node_modules.
2034
2006
  release: {
2035
2007
  script: "scripts/release/release-cli.ts",
2036
2008
  description: "Release the merges main has taken since the version last changed",
2037
2009
  category: "Versioning",
2038
- reference: ["[version]", "maintainer", ["git", "network", "release"]]
2010
+ reference: ["[--dry-run]", "maintainer", ["git", "network", "release"]]
2039
2011
  },
2040
- // The read-only half of the one above (joshuafolkken/kit#1582). `release --dry-run` cannot
2012
+ // The read-only half of the one above. `release --dry-run` cannot
2041
2013
  // answer this question: it refuses off the default branch and on a dirty tree, which is every
2042
2014
  // position a run asks it from. A `script` entry for the same reason `release` is one.
2043
2015
  "release:scope": {
@@ -2046,8 +2018,8 @@ var VERSIONING_COMMANDS = {
2046
2018
  category: "Versioning",
2047
2019
  reference: ["[--json]", "automation", ["none"]]
2048
2020
  },
2049
- // Run by the release workflows, kit's and the one sync distributes, after a tag has published
2050
- // (joshuafolkken/kit#3007). Settings come from the environment, so the workflow decides them.
2021
+ // Run by the release workflows, kit's and the one sync distributes, after a tag has published.
2022
+ // Settings come from the environment, so the workflow decides them.
2051
2023
  "release:github": {
2052
2024
  script: "scripts/release/github-release-cli.ts",
2053
2025
  description: "Create the GitHub Release for a published tag, with generated notes",
@@ -2075,20 +2047,17 @@ var WORKFLOW_COMMANDS = {
2075
2047
  reference: ["<message>", "developer", ["network"]],
2076
2048
  default_script_arguments: ["-y", "--skip-commit", "--skip-push"]
2077
2049
  },
2078
- // **The optional form, on both** (joshuafolkken/kit#1564). These two were the last commands
2079
- // passing the mandatory `--env-file=.env`, which node resolves before the script's first line: on
2080
- // a machine with no `.env` they died as `.env: not found` with exit code 9, even where
2081
- // `TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID` existed as real environment variables — a cloud
2082
- // session, and `followup` with them the merge step of every `fullrun` there. `doctor` was moved to
2083
- // this form for the same reason in joshuafolkken/kit#869.
2050
+ // **The optional form, on both**. The mandatory `--env-file=.env` is resolved by node before the
2051
+ // script's first line: on a machine with no `.env` it dies as `.env: not found` with exit code 9,
2052
+ // even where `TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID` exist as real environment variables — a
2053
+ // cloud session, and `followup` with them the merge step of every `fullrun` there.
2084
2054
  //
2085
2055
  // Nothing is lost by relaxing it: both scripts already load `.env` through `josh_environment_file`
2086
2056
  // themselves, so the file is read either way and node's precedence — an existing environment
2087
2057
  // variable wins over the file — is node's own in both spellings.
2088
2058
  //
2089
- // **What the mandatory flag was accidentally providing was noise**, and that is replaced rather
2090
- // than dropped: `telegram_notify.send` now throws on missing credentials and on a failed send, so
2091
- // `josh notify` exits non-zero instead of warning and answering 0.
2059
+ // **A missing credential still fails loudly**: `telegram_notify.send` throws on missing credentials
2060
+ // and on a failed send, so `josh notify` exits non-zero instead of warning and answering 0.
2092
2061
  followup: {
2093
2062
  script: "scripts/followup/git-followup-workflow.ts",
2094
2063
  description: "Follow-up git workflow",
@@ -2104,11 +2073,23 @@ var WORKFLOW_COMMANDS = {
2104
2073
  script: "scripts/notify/telegram-test.ts",
2105
2074
  description: "Send Telegram notification",
2106
2075
  category: "Workflow",
2107
- reference: ["--task-type <type> --body <text>", "automation", ["notifications"]],
2076
+ reference: [
2077
+ "[--task-type <type>] [--body <text> | --body-file <path>] [--issue-url <url>] [--pr-url <url>] [--issue-title <text>] [--repo-name <name>]",
2078
+ "automation",
2079
+ ["notifications"]
2080
+ ],
2108
2081
  tsx_arguments: OPTIONAL_ENV_FILE_FLAGS
2109
2082
  },
2110
- // The observation ledger's commit path for the lines no run's own commit carried
2111
- // (joshuafolkken/kit#1756, joshuafolkken/kit#2763): a lane's lines sit in the primary checkout, which
2083
+ // One observation-ledger sighting: the key's count, the append and the second-sighting verdict,
2084
+ // which a run used to type as a `cat | grep -c` and judge by hand.
2085
+ "observation:record": {
2086
+ script: "scripts/observations/observation-record-cli.ts",
2087
+ description: "Record an observation sighting and answer whether it is now filed",
2088
+ category: "Workflow",
2089
+ reference: ["<key> <depth> <where> <what> [--checkout <path>]", "automation", ["files"]]
2090
+ },
2091
+ // The observation ledger's commit path for the lines no run's own commit carried:
2092
+ // a lane's lines sit in the primary checkout, which
2112
2093
  // its commit cannot see, and the recurrence count the promotion rule reads is a count of main.
2113
2094
  "observations:flush": {
2114
2095
  script: "scripts/observations/observations-flush-cli.ts",
@@ -2116,8 +2097,8 @@ var WORKFLOW_COMMANDS = {
2116
2097
  category: "Workflow",
2117
2098
  reference: ["", "automation", ["git", "network"]]
2118
2099
  },
2119
- // The one write path for a `/code-review` round's findings (joshuafolkken/kit#2325), plus the
2120
- // `--check` gate `followup` runs before it merges (joshuafolkken/kit#2343). It appends a `- rf:`
2100
+ // The one write path for a `/code-review` round's findings, plus the
2101
+ // `--check` gate `followup` runs before it merges. It appends a `- rf:`
2121
2102
  // line per finding — or one zero-finding line for a clean round — to the observation ledger, so
2122
2103
  // `observations:flush` commits them and the recurrence count survives the run.
2123
2104
  "review:record": {
@@ -2125,12 +2106,12 @@ var WORKFLOW_COMMANDS = {
2125
2106
  description: "Record a review round\u2019s findings, or check a round was recorded",
2126
2107
  category: "Workflow",
2127
2108
  reference: [
2128
- "--issue <N> [<category>:<severity>:<file> ...] | --check --issue <N>",
2109
+ "--issue <N> [--comment] [<category>:<severity>:<file> ...] | --check --issue <N>",
2129
2110
  "automation",
2130
- ["files"]
2111
+ ["files", "network"]
2131
2112
  ]
2132
2113
  },
2133
- // The reader over what `review:record` wrote (joshuafolkken/kit#2325): each recurring category’s
2114
+ // The reader over what `review:record` wrote: each recurring category’s
2134
2115
  // count, and the number of zero-finding rounds that distinguishes a quiet category from an unwatched one.
2135
2116
  "review:findings": {
2136
2117
  script: "scripts/review/review-findings-cli.ts",
@@ -2139,7 +2120,7 @@ var WORKFLOW_COMMANDS = {
2139
2120
  reference: ["", "developer", ["files"]]
2140
2121
  },
2141
2122
  // After a behavior-change Issue merges, re-run its declared baseline and print before/after; a value
2142
- // that did not move appends a refuted-premise line to the observation ledger (joshuafolkken/kit#2212).
2123
+ // that did not move appends a refuted-premise line to the observation ledger.
2143
2124
  "measure:rerun": {
2144
2125
  script: "scripts/issue/measure-rerun-cli.ts",
2145
2126
  description: "Re-run a merged issue\u2019s baseline command and print the before/after pair",
@@ -2147,7 +2128,7 @@ var WORKFLOW_COMMANDS = {
2147
2128
  reference: ["<issue-number>", "automation", ["network", "processes", "files"]]
2148
2129
  },
2149
2130
  // A script rather than an `sh -c` chain, because it has a precondition to enforce: run inside a
2150
- // linked work tree it would hijack the default branch from every other one (joshuafolkken/kit#1535).
2131
+ // linked work tree it would hijack the default branch from every other one.
2151
2132
  "main:sync": {
2152
2133
  script: "scripts/git/main-sync.ts",
2153
2134
  description: "Checkout default branch, pull latest, and prune merged remote-gone branches (refuses inside a lane)",
@@ -2155,9 +2136,8 @@ var WORKFLOW_COMMANDS = {
2155
2136
  reference: ["", "developer", ["git", "network"]]
2156
2137
  },
2157
2138
  // A script rather than an `sh -c` chain, because the strategy has to be named rather than left to
2158
- // the caller's git configuration: the `git pull` this replaced aborted with `Need to specify how
2159
- // to reconcile divergent branches` on exactly the diverged branch the command exists for
2160
- // (joshuafolkken/kit#1659).
2139
+ // the caller's git configuration: a bare `git pull` aborts with `Need to specify how to reconcile
2140
+ // divergent branches` on exactly the diverged branch the command exists for.
2161
2141
  "main:merge": {
2162
2142
  script: "scripts/git/main-merge.ts",
2163
2143
  description: "Merge origin default branch into the current branch",
@@ -2184,6 +2164,7 @@ var ALIASES = {
2184
2164
  lr: "lint:related",
2185
2165
  ln: "lines",
2186
2166
  by: "bytes",
2167
+ mt: "metrics",
2187
2168
  f: "format",
2188
2169
  sd: "cspell:dot",
2189
2170
  bh: "behavior",
@@ -2226,7 +2207,9 @@ var ALIASES = {
2226
2207
  ruv: "rule:value",
2227
2208
  ev: "eval",
2228
2209
  lsm: "lane:sample",
2229
- lst: "lane:stats"
2210
+ lst: "lane:stats",
2211
+ lli: "lane:limit",
2212
+ blr: "backlogrun"
2230
2213
  };
2231
2214
  function canonical_command(name) {
2232
2215
  if (!Object.hasOwn(ALIASES, name)) return name;
@@ -2449,74 +2432,74 @@ var time_background = {
2449
2432
  };
2450
2433
 
2451
2434
  // scripts/git/git-schemas.ts
2452
- import { z as z4 } from "zod";
2453
- var package_name_schema = z4.object({ name: z4.string().min(1) });
2454
- var rollup_item_schema = z4.looseObject({
2435
+ import { z as z3 } from "zod";
2436
+ var package_name_schema = z3.object({ name: z3.string().min(1) });
2437
+ var rollup_item_schema = z3.looseObject({
2455
2438
  // eslint-disable-next-line @typescript-eslint/naming-convention -- GraphQL field name from GitHub API
2456
- __typename: z4.string().optional(),
2457
- state: z4.string().optional(),
2458
- status: z4.string().optional(),
2459
- conclusion: z4.string().optional(),
2460
- name: z4.string().optional(),
2461
- context: z4.string().optional()
2439
+ __typename: z3.string().optional(),
2440
+ state: z3.string().optional(),
2441
+ status: z3.string().optional(),
2442
+ conclusion: z3.string().optional(),
2443
+ name: z3.string().optional(),
2444
+ context: z3.string().optional()
2462
2445
  });
2463
- var pr_raw_schema = z4.object({
2464
- statusCheckRollup: z4.array(rollup_item_schema).optional(),
2465
- mergeStateStatus: z4.string().optional(),
2466
- reviewDecision: z4.string().optional()
2446
+ var pr_raw_schema = z3.object({
2447
+ statusCheckRollup: z3.array(rollup_item_schema).optional(),
2448
+ mergeStateStatus: z3.string().optional(),
2449
+ reviewDecision: z3.string().optional()
2467
2450
  });
2468
- var pull_comment_schema = z4.object({
2469
- body: z4.string().optional(),
2470
- html_url: z4.string().optional(),
2471
- user: z4.object({ login: z4.string().optional() }).optional()
2451
+ var pull_comment_schema = z3.object({
2452
+ body: z3.string().optional(),
2453
+ html_url: z3.string().optional(),
2454
+ user: z3.object({ login: z3.string().optional() }).optional()
2472
2455
  });
2473
- var ai_review_pull_comment_schema = z4.object({
2474
- body: z4.string().optional(),
2475
- url: z4.string().optional(),
2476
- author: z4.object({ login: z4.string().optional() }).optional()
2456
+ var ai_review_pull_comment_schema = z3.object({
2457
+ body: z3.string().optional(),
2458
+ url: z3.string().optional(),
2459
+ author: z3.object({ login: z3.string().optional() }).optional()
2477
2460
  });
2478
- var pr_info_schema = z4.object({
2479
- mergeable: z4.union([z4.boolean(), z4.string()]).nullable().optional(),
2480
- mergeStateStatus: z4.string().nullable().optional(),
2481
- state: z4.string().optional()
2461
+ var pr_info_schema = z3.object({
2462
+ mergeable: z3.union([z3.boolean(), z3.string()]).nullable().optional(),
2463
+ mergeStateStatus: z3.string().nullable().optional(),
2464
+ state: z3.string().optional()
2482
2465
  });
2483
- var epic_issue_schema = z4.object({
2484
- number: z4.number(),
2485
- body: z4.string().optional()
2466
+ var epic_issue_schema = z3.object({
2467
+ number: z3.number(),
2468
+ body: z3.string().optional()
2486
2469
  });
2487
- var blocking_issue_schema = z4.object({
2488
- number: z4.number(),
2489
- state: z4.string().optional(),
2490
- repository_url: z4.string().optional()
2470
+ var blocking_issue_schema = z3.object({
2471
+ number: z3.number(),
2472
+ state: z3.string().optional(),
2473
+ repository_url: z3.string().optional()
2491
2474
  });
2492
- var blocked_by_schema = z4.object({
2493
- nodes: z4.array(blocking_issue_schema).default([]),
2494
- totalCount: z4.number().optional()
2475
+ var blocked_by_schema = z3.object({
2476
+ nodes: z3.array(blocking_issue_schema).default([]),
2477
+ totalCount: z3.number().optional()
2495
2478
  }).optional();
2496
- var epic_child_schema = z4.object({
2497
- state: z4.string().optional(),
2479
+ var epic_child_schema = z3.object({
2480
+ state: z3.string().optional(),
2498
2481
  blockedBy: blocked_by_schema
2499
2482
  });
2500
- var rest_comment_schema = z4.looseObject({
2501
- body: z4.string().nullish(),
2502
- html_url: z4.string().optional(),
2503
- user: z4.looseObject({ login: z4.string().optional() }).nullish()
2483
+ var rest_comment_schema = z3.looseObject({
2484
+ body: z3.string().nullish(),
2485
+ html_url: z3.string().optional(),
2486
+ user: z3.looseObject({ login: z3.string().optional() }).nullish()
2504
2487
  });
2505
- var issue_label_schema = z4.object({ name: z4.string() });
2506
- var epic_subject_schema = z4.object({
2507
- number: z4.number(),
2508
- state: z4.string().optional(),
2509
- labels: z4.array(issue_label_schema).optional(),
2510
- body: z4.string().optional()
2488
+ var issue_label_schema = z3.object({ name: z3.string() });
2489
+ var epic_subject_schema = z3.object({
2490
+ number: z3.number(),
2491
+ state: z3.string().optional(),
2492
+ labels: z3.array(issue_label_schema).optional(),
2493
+ body: z3.string().optional()
2511
2494
  });
2512
- var open_issue_schema = z4.object({
2513
- number: z4.number(),
2514
- title: z4.string(),
2515
- labels: z4.array(issue_label_schema).optional(),
2516
- createdAt: z4.string(),
2495
+ var open_issue_schema = z3.object({
2496
+ number: z3.number(),
2497
+ title: z3.string(),
2498
+ labels: z3.array(issue_label_schema).optional(),
2499
+ createdAt: z3.string(),
2517
2500
  blockedBy: blocked_by_schema,
2518
- // Present only on the pickup listing, which reads it for the restructures each issue declares.
2519
- body: z4.string().optional()
2501
+ // Present only on the pickup listing, which reads it for the paths each issue declares.
2502
+ body: z3.string().optional()
2520
2503
  });
2521
2504
 
2522
2505
  // scripts/gh/git-pr-checks-parse.ts
@@ -2692,6 +2675,132 @@ var PrConflictError = class extends Error {
2692
2675
  name = "PrConflictError";
2693
2676
  };
2694
2677
 
2678
+ // scripts/lane/lane-ledger.ts
2679
+ import { closeSync, constants, openSync, writeSync } from "node:fs";
2680
+ import { z as z4 } from "zod";
2681
+ var LEDGER_PREFIX = "josh-lane-ledger-";
2682
+ var LEDGER_SUFFIX = ".jsonl";
2683
+ var LINE_SEPARATOR = "\n";
2684
+ var CI_WAIT_STAGE = "ci-wait";
2685
+ var LEDGER_FILE_MODE = 384;
2686
+ var { O_APPEND, O_CREAT, O_NOFOLLOW, O_WRONLY } = constants;
2687
+ var APPEND_FLAGS = O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW;
2688
+ var KIND = {
2689
+ MERGE: "merge",
2690
+ GATE: "gate",
2691
+ LOAD: "load",
2692
+ DISPATCH: "dispatch",
2693
+ STAGE: "stage"
2694
+ };
2695
+ var merge_schema = z4.object({ kind: z4.literal(KIND.MERGE), at: z4.string(), issue: z4.number() });
2696
+ var gate_schema = z4.object({
2697
+ kind: z4.literal(KIND.GATE),
2698
+ at: z4.string(),
2699
+ elapsed_ms: z4.number(),
2700
+ is_passed: z4.boolean(),
2701
+ // The unit suite's own duration, present when this gate ran it — the one
2702
+ // record of a full vitest run `josh metrics` reads, so the suite is never timed twice.
2703
+ unit_ms: z4.number().optional(),
2704
+ // The whole cores busy outside this gate, beyond the machine's baseline, at its start or its end —
2705
+ // whichever was higher. Absent when the machine could not be read.
2706
+ external_cores: z4.number().optional()
2707
+ });
2708
+ var load_schema = z4.object({
2709
+ kind: z4.literal(KIND.LOAD),
2710
+ at: z4.string(),
2711
+ load: z4.number(),
2712
+ available_mb: z4.number().optional(),
2713
+ swapped_mb: z4.number().optional(),
2714
+ lanes: z4.number().optional()
2715
+ });
2716
+ var dispatch_schema = z4.object({
2717
+ kind: z4.literal(KIND.DISPATCH),
2718
+ at: z4.string(),
2719
+ issue: z4.number()
2720
+ });
2721
+ var stage_schema = z4.object({
2722
+ kind: z4.literal(KIND.STAGE),
2723
+ at: z4.string(),
2724
+ stage: z4.string(),
2725
+ elapsed_ms: z4.number(),
2726
+ issue: z4.number().optional()
2727
+ });
2728
+ var entry_schema = z4.discriminatedUnion("kind", [
2729
+ merge_schema,
2730
+ gate_schema,
2731
+ load_schema,
2732
+ dispatch_schema,
2733
+ stage_schema
2734
+ ]);
2735
+ function target_of(repository) {
2736
+ return stamp_file.stamp_path(LEDGER_PREFIX, repository, LEDGER_SUFFIX);
2737
+ }
2738
+ async function target() {
2739
+ if (process.env["VITEST"] !== void 0) return void 0;
2740
+ try {
2741
+ const repository = await run_carry.repository_directory();
2742
+ return repository === void 0 ? void 0 : target_of(repository);
2743
+ } catch {
2744
+ return void 0;
2745
+ }
2746
+ }
2747
+ function append(path4, entry) {
2748
+ const descriptor = openSync(path4, APPEND_FLAGS, LEDGER_FILE_MODE);
2749
+ try {
2750
+ if (stamp_file.is_own_regular_file(path4)) {
2751
+ writeSync(descriptor, `${JSON.stringify(entry)}${LINE_SEPARATOR}`);
2752
+ }
2753
+ } finally {
2754
+ closeSync(descriptor);
2755
+ }
2756
+ }
2757
+ async function record(entry, path4) {
2758
+ try {
2759
+ const destination = path4 ?? await target();
2760
+ if (destination !== void 0) append(destination, entry);
2761
+ } catch {
2762
+ }
2763
+ }
2764
+ function now_iso() {
2765
+ return (/* @__PURE__ */ new Date()).toISOString();
2766
+ }
2767
+ async function record_gate(path4, gate) {
2768
+ await record({ kind: KIND.GATE, at: now_iso(), ...gate }, path4);
2769
+ }
2770
+ async function record_merge(issue) {
2771
+ await record({ kind: KIND.MERGE, at: now_iso(), issue });
2772
+ }
2773
+ async function record_dispatch(issue, path4) {
2774
+ await record({ kind: KIND.DISPATCH, at: now_iso(), issue }, path4);
2775
+ }
2776
+ async function record_stage(stage, path4) {
2777
+ await record({ kind: KIND.STAGE, at: now_iso(), ...stage }, path4);
2778
+ }
2779
+ function parse_line2(line) {
2780
+ return entry_schema.safeParse(json_value.parse_or_undefined(line)).data;
2781
+ }
2782
+ function is_present(entry) {
2783
+ return entry !== void 0;
2784
+ }
2785
+ function read_entries(path4) {
2786
+ const raw = stamp_file.read_stamp_text(path4);
2787
+ if (raw === void 0) return [];
2788
+ return raw.split(LINE_SEPARATOR).map((line) => parse_line2(line.trim())).filter(is_present);
2789
+ }
2790
+ var lane_ledger = {
2791
+ CI_WAIT_STAGE,
2792
+ KIND,
2793
+ append,
2794
+ read_entries,
2795
+ record,
2796
+ record_dispatch,
2797
+ record_gate,
2798
+ record_merge,
2799
+ record_stage,
2800
+ target,
2801
+ target_of
2802
+ };
2803
+
2695
2804
  // scripts/time-runtime/time-format.ts
2696
2805
  var MS_PER_MINUTE = 6e4;
2697
2806
  var MS_PER_SECOND2 = 1e3;
@@ -2764,8 +2873,8 @@ var STAGE = {
2764
2873
  // blocker and on a red check, and those are the runs whose wait is longest — reporting nothing for
2765
2874
  // them would leave the measurement blind to exactly the invocations worth measuring.
2766
2875
  interrupted: "interrupted",
2767
- // The interrupted lap when the wait failed on a merge conflict (joshuafolkken/kit#3221), so the
2768
- // stage block names the cause a resumed session used to look up with `gh pr view`.
2876
+ // The interrupted lap when the wait failed on a merge conflict, so the
2877
+ // stage block names the cause a resumed session would otherwise look up with `gh pr view`.
2769
2878
  conflict: "conflict"
2770
2879
  };
2771
2880
  function stopped_lap(error) {
@@ -2795,6 +2904,14 @@ function format_stages(log) {
2795
2904
  function print_stages(log) {
2796
2905
  for (const line of format_stages(log)) console.info(line);
2797
2906
  }
2907
+ async function record_ci_wait(log) {
2908
+ const wait = log.stages.find((stage) => stage.name === STAGE.checks_wait);
2909
+ if (wait === void 0) return;
2910
+ await lane_ledger.record_stage({
2911
+ stage: lane_ledger.CI_WAIT_STAGE,
2912
+ elapsed_ms: wait.duration_ms
2913
+ });
2914
+ }
2798
2915
  var git_followup_stages = {
2799
2916
  STAGE,
2800
2917
  STAGE_LINE_PREFIX,
@@ -2804,11 +2921,12 @@ var git_followup_stages = {
2804
2921
  total_ms,
2805
2922
  format_stages,
2806
2923
  print_stages,
2924
+ record_ci_wait,
2807
2925
  stopped_lap
2808
2926
  };
2809
2927
 
2810
2928
  // scripts/time-runtime/time-followup-stage.ts
2811
- var LINE_SEPARATOR = "\n";
2929
+ var LINE_SEPARATOR2 = "\n";
2812
2930
  var SECONDS_SUFFIX = " s";
2813
2931
  var DIGIT_OR_POINT = /[\d.]/u;
2814
2932
  var MS_PER_SECOND3 = 1e3;
@@ -2838,7 +2956,7 @@ function to_stage(body) {
2838
2956
  }
2839
2957
  function read_stages(text) {
2840
2958
  if (!text.includes(git_followup_stages.STAGE_LINE_PREFIX)) return NO_STAGES;
2841
- return text.split(LINE_SEPARATOR).map((line) => stage_body(line)).filter((body) => body !== void 0).map((body) => to_stage(body)).filter((stage) => stage !== void 0);
2959
+ 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);
2842
2960
  }
2843
2961
  var time_followup_stage = { NO_STAGES, read_stages };
2844
2962
 
@@ -2846,7 +2964,7 @@ var time_followup_stage = { NO_STAGES, read_stages };
2846
2964
  import { z as z5 } from "zod";
2847
2965
  var TEXT_BLOCK_SCHEMA = z5.object({ text: z5.string().nullish() });
2848
2966
  var CONTENT_SCHEMA = z5.union([z5.string(), z5.array(z5.unknown())]);
2849
- var LINE_SEPARATOR2 = "\n";
2967
+ var LINE_SEPARATOR3 = "\n";
2850
2968
  function block_text(block) {
2851
2969
  const parsed = TEXT_BLOCK_SCHEMA.safeParse(block);
2852
2970
  return parsed.success ? parsed.data.text ?? "" : "";
@@ -2855,7 +2973,7 @@ function result_text2(content) {
2855
2973
  const parsed = CONTENT_SCHEMA.safeParse(content);
2856
2974
  if (!parsed.success) return "";
2857
2975
  if (typeof parsed.data === "string") return parsed.data;
2858
- return parsed.data.map((block) => block_text(block)).join(LINE_SEPARATOR2);
2976
+ return parsed.data.map((block) => block_text(block)).join(LINE_SEPARATOR3);
2859
2977
  }
2860
2978
  function is_failure_line(line) {
2861
2979
  return line.trimStart().startsWith(status_icons.FAIL_ICON);
@@ -2907,7 +3025,7 @@ function did_scan_find(scan) {
2907
3025
  return scan.did_find || scan.has_failure_before_region || scan.has_failure_in_region;
2908
3026
  }
2909
3027
  function has_failure_line(content) {
2910
- const lines = result_text2(content).split(LINE_SEPARATOR2);
3028
+ const lines = result_text2(content).split(LINE_SEPARATOR3);
2911
3029
  if (lines.some((line) => is_failed_verdict(line))) return true;
2912
3030
  return did_scan_find(scan_body(lines));
2913
3031
  }
@@ -3128,8 +3246,8 @@ function field_targets(input) {
3128
3246
  }
3129
3247
  function tool_targets(input) {
3130
3248
  const scalar_targets = TARGET_FIELDS.map((field) => field_text(input, field));
3131
- const targets = [...scalar_targets, ...field_targets(input)].map((target) => normalize(target));
3132
- return [...new Set(targets)].filter((target) => target !== "");
3249
+ const targets = [...scalar_targets, ...field_targets(input)].map((target2) => normalize(target2));
3250
+ return [...new Set(targets)].filter((target2) => target2 !== "");
3133
3251
  }
3134
3252
  function prompt_references_prior(input) {
3135
3253
  const prompt = field_text(input, "prompt").toLowerCase();
@@ -3174,27 +3292,27 @@ var time_bundle_call = {
3174
3292
  bash_facts,
3175
3293
  call_facts,
3176
3294
  tool_facts,
3177
- // Exported for `time-agent-bundles.ts` (joshuafolkken/kit#1854), which asks the launch question of a
3295
+ // Exported for `time-agent-bundles.ts`, which asks the launch question of a
3178
3296
  // span's `label` — the tool name for a non-Bash call — so the set lives in one place.
3179
3297
  is_launch_tool,
3180
- // Exported for `time-writes.ts` (joshuafolkken/kit#1472), which asks what a call *wrote* rather
3298
+ // Exported for `time-writes.ts`, which asks what a call *wrote* rather
3181
3299
  // than what it named. The extraction is the same one either way — a second copy of it would let a
3182
3300
  // path be recognized as a target when read and missed when written.
3183
3301
  targets_in,
3184
3302
  tool_targets,
3185
- // Exported for the batching guard's own word scan (joshuafolkken/kit#1390), so the two scanners
3303
+ // Exported for the batching guard's own word scan, so the two scanners
3186
3304
  // cannot come to disagree about where one word of a shell line ends and the next begins.
3187
- // Exported for the read-fold notice (joshuafolkken/kit#2311), which offers `read:files <path>` only
3305
+ // Exported for the read-fold notice, which offers `read:files <path>` only
3188
3306
  // over file-shaped targets — a bare directory like `scripts/` is a target here but not something
3189
3307
  // `read:files` can read, so the notice reuses this test rather than keep a second copy that could
3190
3308
  // drift from what counts as a file path.
3191
3309
  has_extension,
3192
- // Exported for `time-writes.ts` (joshuafolkken/kit#1509), which needs the same two answers to say
3310
+ // Exported for `time-writes.ts`, which needs the same two answers to say
3193
3311
  // *which* files an in-place `sed` wrote. Two copies of this test disagreed in both directions at
3194
3312
  // once — one called a piped `grep -i` a write, the other missed a bundled `sed -ni`.
3195
3313
  write_segment,
3196
3314
  is_in_place_sed,
3197
- // Exported for the drift test in `time-bundle-call.test.ts` (joshuafolkken/kit#1875), which pins that
3315
+ // Exported for the drift test in `time-bundle-call.test.ts`, which pins that
3198
3316
  // every name here is a real `josh` command and none of them writes.
3199
3317
  READ_JOSH_SUBCOMMANDS
3200
3318
  };
@@ -3206,9 +3324,9 @@ function issue_from_branch(branch) {
3206
3324
  const matched = ISSUE_BRANCH_PATTERN.exec(branch);
3207
3325
  return matched?.[1] === void 0 ? UNATTRIBUTED_KEY : Number(matched[1]);
3208
3326
  }
3209
- function declared_issue(record) {
3210
- const declared = record.issue ?? UNATTRIBUTED_KEY;
3211
- return declared === UNATTRIBUTED_KEY ? issue_from_branch(record.branch) : declared;
3327
+ function declared_issue(record2) {
3328
+ const declared = record2.issue ?? UNATTRIBUTED_KEY;
3329
+ return declared === UNATTRIBUTED_KEY ? issue_from_branch(record2.branch) : declared;
3212
3330
  }
3213
3331
  function fill(declared, is_reverse) {
3214
3332
  const filled = Array.from({ length: declared.length }, () => UNATTRIBUTED_KEY);
@@ -3232,12 +3350,12 @@ function pick(own, carried, next, previous) {
3232
3350
  }
3233
3351
  function announcements(records) {
3234
3352
  return fill(
3235
- records.map((record) => record.issue ?? UNATTRIBUTED_KEY),
3353
+ records.map((record2) => record2.issue ?? UNATTRIBUTED_KEY),
3236
3354
  false
3237
3355
  );
3238
3356
  }
3239
3357
  function attribute(records) {
3240
- const declared = records.map((record) => declared_issue(record));
3358
+ const declared = records.map((record2) => declared_issue(record2));
3241
3359
  const carried = announcements(records);
3242
3360
  const next = fill(declared, true);
3243
3361
  const previous = fill(declared, false);
@@ -3248,9 +3366,9 @@ function attribute(records) {
3248
3366
  function group_by_issue(records) {
3249
3367
  const issues = attribute(records);
3250
3368
  const grouped = /* @__PURE__ */ new Map();
3251
- for (const [index, record] of records.entries()) {
3369
+ for (const [index, record2] of records.entries()) {
3252
3370
  const bucket = grouped.get(issues[index] ?? UNATTRIBUTED_KEY) ?? [];
3253
- bucket.push(record);
3371
+ bucket.push(record2);
3254
3372
  grouped.set(issues[index] ?? UNATTRIBUTED_KEY, bucket);
3255
3373
  }
3256
3374
  return [...grouped].toSorted(([left], [right]) => left - right).map(([issue, bucket]) => ({ issue, records: bucket }));
@@ -3379,28 +3497,18 @@ var time_single_check = { NO_CHECK, check_key };
3379
3497
 
3380
3498
  // scripts/time-runtime/time-transcript-line.ts
3381
3499
  import { z as z6 } from "zod";
3382
-
3383
- // scripts/time-runtime/time-instant.ts
3384
- function parse_instant(raw) {
3385
- if (raw === null || raw === void 0) return void 0;
3386
- const parsed = Date.parse(raw);
3387
- return Number.isNaN(parsed) ? void 0 : parsed;
3388
- }
3389
- var time_instant = { parse_instant };
3390
-
3391
- // scripts/time-runtime/time-transcript-line.ts
3392
3500
  var BLOCK_SCHEMA2 = z6.object({
3393
3501
  type: z6.string().nullish(),
3394
3502
  name: z6.string().nullish(),
3395
3503
  id: z6.string().nullish(),
3396
3504
  tool_use_id: z6.string().nullish(),
3397
3505
  input: z6.unknown().nullish(),
3398
- // Whether the harness wrote this result back as a failure (joshuafolkken/kit#1309). Present on a
3506
+ // Whether the harness wrote this result back as a failure. Present on a
3399
3507
  // `tool_result` block and on nothing else, and absent even there for the tools that never report
3400
3508
  // one — which is why it is read as three answers rather than as a boolean with a default.
3401
3509
  is_error: z6.boolean().nullish(),
3402
- // What the call printed. Read only to recover the outcome a pipeline threw away
3403
- // (joshuafolkken/kit#1361): it is kept as flattened text rather than as blocks, because that is
3510
+ // What the call printed. Read only to recover the outcome a pipeline threw away:
3511
+ // it is kept as flattened text rather than as blocks, because that is
3404
3512
  // the whole of what `time-reported-failure.ts` asks of it.
3405
3513
  content: z6.unknown().nullish()
3406
3514
  });
@@ -3411,10 +3519,10 @@ var LINE_SCHEMA = z6.object({
3411
3519
  timestamp: z6.string().nullish(),
3412
3520
  // The branch the line was written on, which is where the issue number lives — `josh git` names a
3413
3521
  // branch `<N>-<slug>`. Read here rather than re-parsed by a second reader so `josh time --issue`
3414
- // and `josh cost --issue` answer from the same field (joshuafolkken/kit#1268).
3522
+ // and `josh cost --issue` answer from the same field.
3415
3523
  gitBranch: z6.string().nullish(),
3416
- // The two fields outside `message` that the harness writes an end-of-task notice on
3417
- // (joshuafolkken/kit#1696). **Both are read as `unknown` rather than as strings**: a schema
3524
+ // The two fields outside `message` that the harness writes an end-of-task notice on.
3525
+ // **Both are read as `unknown` rather than as strings**: a schema
3418
3526
  // insisting on a string here would reject every line whose `content` is a list of blocks — which is
3419
3527
  // most of them — and a rejected line is dropped from the timeline entirely, so the shares would stop
3420
3528
  // reconstructing the elapsed time. The shape is checked at the read below instead.
@@ -3428,6 +3536,7 @@ var NO_MESSAGE_ID = "";
3428
3536
  var ERROR_TEXT_LIMIT = 256;
3429
3537
  var REFUSAL_MARKER = "\u26D4";
3430
3538
  var HOOK_ERROR_LABEL = /^PreToolUse:\S+ hook error: /u;
3539
+ var STOP_FEEDBACK_LABEL = /^Stop hook feedback:\s*/u;
3431
3540
  var TOKEN_LINE = /^[a-z][a-z-]*$/u;
3432
3541
  var TOKEN_LINE_LIMIT = 8;
3433
3542
  function block_names(raw) {
@@ -3445,6 +3554,11 @@ function guard_from_refusal(text) {
3445
3554
  const colon = headline.indexOf(":");
3446
3555
  return (colon === -1 ? headline : headline.slice(0, colon)).trim();
3447
3556
  }
3557
+ function stop_guard_of(data) {
3558
+ const content = data.message?.content;
3559
+ if (typeof content !== "string" || !STOP_FEEDBACK_LABEL.test(content)) return "";
3560
+ return guard_from_refusal(content.replace(STOP_FEEDBACK_LABEL, ""));
3561
+ }
3448
3562
  function token_lines_of(text) {
3449
3563
  return text.split("\n").map((line) => line.trim()).filter((line) => TOKEN_LINE.test(line)).slice(0, TOKEN_LINE_LIMIT);
3450
3564
  }
@@ -3483,19 +3597,24 @@ function to_line(data) {
3483
3597
  timestamp_ms,
3484
3598
  branch: data.gitBranch ?? UNKNOWN_BRANCH,
3485
3599
  finished_background: time_background.finished_id(notice_text(data)),
3600
+ stop_guard: stop_guard_of(data),
3486
3601
  ...message_fields(data.message)
3487
3602
  };
3488
3603
  }
3489
- function parse_line2(line) {
3604
+ function parse_line3(line) {
3490
3605
  const parsed = LINE_SCHEMA.safeParse(json_value.parse_or_undefined(line));
3491
3606
  return parsed.success ? to_line(parsed.data) : void 0;
3492
3607
  }
3608
+ function parse_text(text) {
3609
+ return text.split("\n").flatMap((line) => parse_line3(line) ?? []);
3610
+ }
3493
3611
  var time_transcript_line = {
3494
3612
  ERROR_TEXT_LIMIT,
3495
3613
  NO_MESSAGE_ID,
3496
3614
  TOKEN_LINE_LIMIT,
3497
3615
  guard_from_refusal,
3498
- parse_line: parse_line2
3616
+ parse_line: parse_line3,
3617
+ parse_text
3499
3618
  };
3500
3619
 
3501
3620
  // scripts/time-runtime/time-writes.ts
@@ -3584,7 +3703,7 @@ var time_tool_call = {
3584
3703
  };
3585
3704
 
3586
3705
  // scripts/time-runtime/time-spans.ts
3587
- var { NO_MESSAGE_ID: NO_MESSAGE_ID3, parse_line: parse_line3 } = time_transcript_line;
3706
+ var { NO_MESSAGE_ID: NO_MESSAGE_ID3, parse_line: parse_line4 } = time_transcript_line;
3588
3707
  var { NO_CALL: NO_CALL2, UNKNOWN_CALL: UNKNOWN_CALL2, UNKNOWN_TOOL: UNKNOWN_TOOL2, to_tool_call: to_tool_call2 } = time_tool_call;
3589
3708
  var ASSISTANT_TYPE = "assistant";
3590
3709
  var USER_TYPE = "user";
@@ -3704,12 +3823,12 @@ function to_spans(events, finished) {
3704
3823
  }));
3705
3824
  }
3706
3825
  function parse_timeline(text) {
3707
- const lines = text.split("\n").map((line) => parse_line3(line)).filter((line) => line !== void 0);
3826
+ const lines = text.split("\n").map((line) => parse_line4(line)).filter((line) => line !== void 0);
3708
3827
  const events = to_events(lines, collect_calls(lines));
3709
3828
  return {
3710
3829
  started_ms: events[0]?.timestamp_ms ?? 0,
3711
3830
  ended_ms: events.at(-1)?.timestamp_ms ?? 0,
3712
- // **The positioning happens here rather than in a caller** (joshuafolkken/kit#1662): a launch and
3831
+ // **The positioning happens here rather than in a caller**: a launch and
3713
3832
  // the call that reads its output are in one transcript, and by the time spans have been merged
3714
3833
  // across sessions and trimmed they are fragments rather than calls.
3715
3834
  spans: time_background.positioned(to_spans(events, time_background.finished_at(lines)))
@@ -3732,12 +3851,12 @@ var time_spans = {
3732
3851
  equal_durations,
3733
3852
  no_background,
3734
3853
  // Re-exported so the suites that measure how a command is read keep asking one namespace, and so
3735
- // `time-shell.ts` moving out of this file changed no call site (joshuafolkken/kit#1344).
3854
+ // `time-shell.ts` moving out of this file changed no call site.
3736
3855
  bash_label: time_shell.bash_label,
3737
3856
  josh_command_of: time_shell.josh_command_of,
3738
3857
  josh_commands_of: time_shell.josh_commands_of,
3739
3858
  to_tool_call: to_tool_call2,
3740
- parse_line: parse_line3,
3859
+ parse_line: parse_line4,
3741
3860
  parse_timeline
3742
3861
  };
3743
3862
 
@@ -3830,23 +3949,21 @@ var time_round_trips = {
3830
3949
  CALLS_PER_ROUND_TRIP_FLOOR,
3831
3950
  count_calls,
3832
3951
  count_round_trips,
3833
- // Exported since joshuafolkken/kit#1406, so a turn is defined in the one module that already
3834
- // defines a round trip rather than as a span filter in the report next door.
3952
+ // Exported so a turn is defined in the one module that already defines a round trip rather than
3953
+ // as a span filter in the report next door.
3835
3954
  count_turns,
3836
3955
  format_density,
3837
- // Exported since joshuafolkken/kit#1385, so the per-tool counts are read off the very groups this
3838
- // module counts rather than off a second grouping beside them.
3956
+ // Exported so the per-tool counts are read off the very groups this module counts rather than off
3957
+ // a second grouping beside them.
3839
3958
  group_round_trips,
3840
- // Exported since joshuafolkken/kit#1309, so the failure aggregation orders a run's spans through
3959
+ // Exported so the failure aggregation orders a run's spans through
3841
3960
  // the one function that already knows why they need it — a second `toSorted` beside it would be
3842
3961
  // the clone `CLAUDE.md` prohibits, and the seam it guards (a delegated unit's spans appended
3843
3962
  // after the parent's) is not one a second copy would keep remembering.
3844
3963
  in_time_order,
3845
3964
  is_below_floor,
3846
- // The four below are exported since joshuafolkken/kit#1406, when the model-gap walk moved to
3847
- // `time-model-gaps.ts` and needed the same predicates and the same opener test this walk uses. A
3848
- // private copy there would be the clone `CLAUDE.md` prohibits, in the one place a drift would have
3849
- // the distribution and the count disagreeing about what a round trip is.
3965
+ // Exported so callers price a round trip with the same divisor and guard rather than a private
3966
+ // copy — the clone `CLAUDE.md` prohibits.
3850
3967
  per_round_trip
3851
3968
  };
3852
3969
 
@@ -3986,9 +4103,9 @@ function tally_for(tallies, label) {
3986
4103
  return created;
3987
4104
  }
3988
4105
  function count_trip(tallies, counted, label) {
3989
- const tally2 = tally_for(tallies, label);
3990
- tally2.recoverable_round_trips += ONE_CALL;
3991
- if (!counted.has(label)) tally2.sequence_count += ONE_CALL;
4106
+ const tally = tally_for(tallies, label);
4107
+ tally.recoverable_round_trips += ONE_CALL;
4108
+ if (!counted.has(label)) tally.sequence_count += ONE_CALL;
3992
4109
  counted.add(label);
3993
4110
  }
3994
4111
  function tally_sequence(tallies, sequence) {
@@ -4006,7 +4123,7 @@ function by_weight(left, right) {
4006
4123
  function tool_rows(closed) {
4007
4124
  const tallies = /* @__PURE__ */ new Map();
4008
4125
  for (const sequence of closed) tally_sequence(tallies, sequence);
4009
- return [...tallies].map(([label, tally2]) => ({ label, ...tally2 })).toSorted(by_weight);
4126
+ return [...tallies].map(([label, tally]) => ({ label, ...tally })).toSorted(by_weight);
4010
4127
  }
4011
4128
  function attributed_of(rows) {
4012
4129
  return rows.reduce((sum, row) => sum + row.recoverable_round_trips, NONE3);
@@ -4140,9 +4257,11 @@ var NONE4 = 0;
4140
4257
  var NOTICE_REFIRE_EVERY = ONE_TURN;
4141
4258
  var NAMED_CANDIDATE_COUNT = 3;
4142
4259
  var SEQUENCE_BEFORE_LIMIT = CONSECUTIVE_LIMIT - ONE_TURN;
4143
- var REASON = `\u26D4 batching: the last ${String(SEQUENCE_BEFORE_LIMIT)} turns each issued a single tool call, so this one would make ${String(CONSECUTIVE_LIMIT)} in a row. Reissue it in one turn together with the calls meant to follow it that do not need its result. **The criterion is whether this call's input needs another call's result, not what kind of call it is** \u2014 edits are covered exactly as reads are, and it never authorizes weakening a verification gate or a review: fewer turns, never less work. The rule, and where its measured cost and rejected mechanisms are, is in \`prompts/collaboration-workflow/turn-batching.md\`. If this turn was already batching, or the call genuinely has nothing to go beside it, reissue it as it was: this fires once per run of single-call turns and cannot repeat on the call in hand.`;
4144
- var NOTICE = `\u{1F4A1} batching: the last ${String(SEQUENCE_BEFORE_LIMIT)} turns each issued a single tool call, so this Write makes ${String(CONSECUTIVE_LIMIT)} in a row. This is a notice, not a refusal \u2014 the write proceeds. Where the writes meant to follow it do not need its result, issue them in one turn together. **The criterion is whether a call's input needs another call's result, not what kind of call it is** \u2014 it never authorizes weakening a verification gate or a review: fewer turns, never less work. The rule, and where its measured cost and rejected mechanisms are, is in \`prompts/collaboration-workflow/turn-batching.md\`. If this run was already batching, or the write genuinely has nothing to go beside it, carry on: this recurs every ${String(NOTICE_REFIRE_EVERY)} further single-call turn(s).`;
4145
- var LANE_NOTICE = `\u{1F4A1} batching: the last ${String(SEQUENCE_BEFORE_LIMIT)} turns each issued a single tool call, so this one makes ${String(CONSECUTIVE_LIMIT)} in a row. This is a notice, not a refusal \u2014 the call proceeds, because a dispatched lane child ends its turn on a denial. Where the calls meant to follow it do not need its result, issue them in one turn together. **The criterion is whether a call's input needs another call's result, not what kind of call it is** \u2014 it never authorizes weakening a verification gate or a review: fewer turns, never less work. The rule, and where its measured cost and rejected mechanisms are, is in \`prompts/collaboration-workflow/turn-batching.md\`. If this run was already batching, or the call genuinely has nothing to go beside it, carry on: this recurs every ${String(NOTICE_REFIRE_EVERY)} further single-call turn(s).`;
4260
+ var RULE_POINTER = "`prompts/collaboration-workflow/turn-batching.md`";
4261
+ var STREAK = `${String(CONSECUTIVE_LIMIT)} single-call turns in a row`;
4262
+ 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), and it never authorizes weakening a verification gate or a review. Already batching, or nothing to pair? Reissue it unchanged; this fires once per streak. ${RULE_POINTER}`;
4263
+ 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}`;
4264
+ var LANE_NOTICE = `\u{1F4A1} batching: ${STREAK}; the call proceeds. Pair independent calls. ${RULE_POINTER}`;
4146
4265
  var WHOLE_FILE_WRITE_TOOL = "Write";
4147
4266
  var EDIT_TOOL = "Edit";
4148
4267
  function is_guarded_call(call) {
@@ -4199,13 +4318,13 @@ function should_notify(text, call, notified_at_ms) {
4199
4318
  return is_at_limit(spans, call, notified_at_ms, NOTICE_REFIRE_EVERY);
4200
4319
  }
4201
4320
  function describe_span(span) {
4202
- const target = span.targets[0] ?? "";
4203
- if (target === "" || span.label.includes(target)) return span.label;
4204
- return `${span.label} ${target}`;
4321
+ const target2 = span.targets[0] ?? "";
4322
+ if (target2 === "" || span.label.includes(target2)) return span.label;
4323
+ return `${span.label} ${target2}`;
4205
4324
  }
4206
4325
  var FOLD_MINIMUM = 2;
4207
4326
  function read_targets(sequence) {
4208
- const paths = sequence.filter((span) => span.is_bundleable && !span.is_writing).map((span) => span.targets[0] ?? "").filter((path7) => path7 !== "" && time_bundle_call.has_extension(path7));
4327
+ const paths = sequence.filter((span) => span.is_bundleable && !span.is_writing).map((span) => span.targets[0] ?? "").filter((path4) => path4 !== "" && time_bundle_call.has_extension(path4));
4209
4328
  return [...new Set(paths)];
4210
4329
  }
4211
4330
  function read_fold_directive(sequence) {
@@ -4214,7 +4333,7 @@ function read_fold_directive(sequence) {
4214
4333
  return ` Fold them into one call: \`pnpm josh read:files ${paths.join(" ")}\`.`;
4215
4334
  }
4216
4335
  function write_targets(sequence) {
4217
- const paths = sequence.filter((span) => span.label === EDIT_TOOL).map((span) => span.targets[0] ?? "").filter((path7) => path7 !== "" && time_bundle_call.has_extension(path7));
4336
+ const paths = sequence.filter((span) => span.label === EDIT_TOOL).map((span) => span.targets[0] ?? "").filter((path4) => path4 !== "" && time_bundle_call.has_extension(path4));
4218
4337
  return [...new Set(paths)];
4219
4338
  }
4220
4339
  function write_fold_directive(sequence) {
@@ -4266,455 +4385,22 @@ var time_batch_guard = {
4266
4385
  };
4267
4386
 
4268
4387
  // scripts/time-runtime/time-hook-transcript.ts
4269
- import path6 from "node:path";
4270
-
4271
- // scripts/cost-runtime/cost-transcript.ts
4272
- import { readdirSync as readdirSync3, readFileSync as readFileSync3, statSync } from "node:fs";
4273
- import { homedir } from "node:os";
4274
- import path5 from "node:path";
4275
-
4276
- // scripts/lane/lane-paths.ts
4277
- import path4 from "node:path";
4278
- var LANE_ROOT_KEY = "JOSH_LANE_ROOT";
4279
- var LANE_DIRECTORY_SUFFIX = "-lanes";
4280
- var LANE_BRANCH_SUFFIX = "-lane";
4281
- function default_lane_root(repository_root) {
4282
- const name = path4.basename(repository_root);
4283
- return path4.join(path4.dirname(repository_root), `.${name}${LANE_DIRECTORY_SUFFIX}`);
4284
- }
4285
- function lane_root(repository_root, environment = process.env) {
4286
- const configured = environment[LANE_ROOT_KEY]?.trim() ?? "";
4287
- return configured.length === 0 ? default_lane_root(repository_root) : path4.resolve(configured);
4288
- }
4289
- function lane_directory(root, issue) {
4290
- return path4.join(root, issue);
4291
- }
4292
- var LANE_ISSUE_PATTERN = /^\d+$/u;
4293
- var DEFAULT_LANE_ROOT_PATTERN = new RegExp(String.raw`^\..+${LANE_DIRECTORY_SUFFIX}$`, "u");
4294
- function is_lane_root(directory, environment) {
4295
- const configured = environment[LANE_ROOT_KEY]?.trim() ?? "";
4296
- if (configured.length > 0) return path4.resolve(configured) === directory;
4297
- return DEFAULT_LANE_ROOT_PATTERN.test(path4.basename(directory));
4298
- }
4299
- function lane_issue_of(directory, environment = process.env) {
4300
- const resolved = path4.resolve(directory);
4301
- const issue = path4.basename(resolved);
4302
- if (!LANE_ISSUE_PATTERN.test(issue)) return void 0;
4303
- return is_lane_root(path4.dirname(resolved), environment) ? issue : void 0;
4304
- }
4305
- function lane_branch(issue) {
4306
- return `${issue}${LANE_BRANCH_SUFFIX}`;
4307
- }
4308
- var SEAT_LOCK_DIR = ".seat-locks";
4309
- function is_lane_entry(name) {
4310
- return LANE_ISSUE_PATTERN.test(name) || DEFAULT_LANE_ROOT_PATTERN.test(name);
4311
- }
4312
- var lane_paths = {
4313
- LANE_BRANCH_SUFFIX,
4314
- LANE_ROOT_KEY,
4315
- SEAT_LOCK_DIR,
4316
- default_lane_root,
4317
- is_lane_entry,
4318
- lane_branch,
4319
- lane_directory,
4320
- lane_issue_of,
4321
- lane_root
4322
- };
4323
-
4324
- // scripts/lib/read-file.ts
4325
- import { readFileSync as readFileSync2 } from "node:fs";
4326
- var ABSENT_CODE = "ENOENT";
4327
- function is_absent(error) {
4328
- return error instanceof Error && "code" in error && error.code === ABSENT_CODE;
4329
- }
4330
- function read_optional(path7) {
4331
- try {
4332
- return readFileSync2(path7, "utf8");
4333
- } catch (error) {
4334
- if (is_absent(error)) return void 0;
4335
- throw error;
4336
- }
4337
- }
4338
- function read_file_or_empty(path7) {
4339
- return read_optional(path7) ?? "";
4340
- }
4341
- function read_if_readable(path7) {
4342
- try {
4343
- return readFileSync2(path7, "utf8");
4344
- } catch {
4345
- return void 0;
4346
- }
4347
- }
4348
- var file_reader = { read_optional, read_file_or_empty, read_if_readable };
4349
-
4350
- // scripts/cost-runtime/cost-usage.ts
4351
- import { z as z7 } from "zod";
4352
- var CACHE_CREATION_SCHEMA = z7.object({
4353
- ephemeral_1h_input_tokens: z7.number().nullish(),
4354
- ephemeral_5m_input_tokens: z7.number().nullish()
4355
- });
4356
- var USAGE_SCHEMA = z7.object({
4357
- input_tokens: z7.number(),
4358
- cache_creation_input_tokens: z7.number().nullish(),
4359
- cache_read_input_tokens: z7.number().nullish(),
4360
- output_tokens: z7.number(),
4361
- output_tokens_details: z7.object({ thinking_tokens: z7.number().nullish() }).nullish(),
4362
- cache_creation: CACHE_CREATION_SCHEMA.nullish()
4363
- });
4364
- var MESSAGE_SCHEMA3 = z7.object({
4365
- id: z7.string().nullish(),
4366
- model: z7.string().nullish(),
4367
- usage: USAGE_SCHEMA.nullish()
4368
- });
4369
- var LINE_SCHEMA2 = z7.object({
4370
- type: z7.string(),
4371
- requestId: z7.string().nullish(),
4372
- uuid: z7.string().nullish(),
4373
- gitBranch: z7.string().nullish(),
4374
- timestamp: z7.string().nullish(),
4375
- message: MESSAGE_SCHEMA3.nullish()
4376
- });
4377
- var SYNTHETIC_MODEL = "<synthetic>";
4378
- var EMPTY_TOTALS = {
4379
- input_tokens: 0,
4380
- cache_write_5m_tokens: 0,
4381
- cache_write_1h_tokens: 0,
4382
- cache_read_tokens: 0,
4383
- output_tokens: 0,
4384
- thinking_tokens: 0,
4385
- thinking_measured: false
4386
- };
4387
- var UNKNOWN_MODEL = "unknown";
4388
- var UNKNOWN_BRANCH2 = "";
4389
- function split_cache_write(usage) {
4390
- const total = usage.cache_creation_input_tokens ?? 0;
4391
- const detail = usage.cache_creation;
4392
- if (!detail) return { write_5m: total, write_1h: 0 };
4393
- const write_1h = detail.ephemeral_1h_input_tokens ?? 0;
4394
- return { write_5m: detail.ephemeral_5m_input_tokens ?? total - write_1h, write_1h };
4395
- }
4396
- function thinking_usage(usage) {
4397
- const raw = usage.output_tokens_details?.thinking_tokens;
4398
- return { tokens: raw ?? 0, measured: raw !== null && raw !== void 0 };
4399
- }
4400
- function to_totals(usage) {
4401
- const { write_5m, write_1h } = split_cache_write(usage);
4402
- const thinking = thinking_usage(usage);
4403
- return {
4404
- input_tokens: usage.input_tokens,
4405
- cache_write_5m_tokens: write_5m,
4406
- cache_write_1h_tokens: write_1h,
4407
- cache_read_tokens: usage.cache_read_input_tokens ?? 0,
4408
- output_tokens: usage.output_tokens,
4409
- thinking_tokens: thinking.tokens,
4410
- thinking_measured: thinking.measured
4411
- };
4412
- }
4413
- function declared_id(data) {
4414
- return data.requestId ?? data.message?.id ?? data.uuid ?? void 0;
4415
- }
4416
- function request_id_of(data, usage) {
4417
- const fallback = `${data.timestamp ?? ""}-${String(usage.output_tokens)}`;
4418
- return declared_id(data) ?? fallback;
4419
- }
4420
- function to_record(data, usage) {
4421
- return {
4422
- request_id: request_id_of(data, usage),
4423
- model: data.message?.model ?? UNKNOWN_MODEL,
4424
- branch: data.gitBranch ?? UNKNOWN_BRANCH2,
4425
- at_ms: time_instant.parse_instant(data.timestamp),
4426
- totals: to_totals(usage)
4427
- };
4428
- }
4429
- var ASSISTANT_TYPE2 = "assistant";
4430
- function is_priced_line(data) {
4431
- return data.type === ASSISTANT_TYPE2 && data.message?.model !== SYNTHETIC_MODEL;
4432
- }
4433
- function classify(data) {
4434
- if (!is_priced_line(data)) return { kind: "skipped" };
4435
- const usage = data.message?.usage;
4436
- return usage ? { kind: "record", record: to_record(data, usage) } : { kind: "no_usage" };
4437
- }
4438
- function parse_line4(line) {
4439
- if (line.trim() === "") return { kind: "skipped" };
4440
- const parsed = LINE_SCHEMA2.safeParse(json_value.parse_or_undefined(line));
4441
- return parsed.success ? classify(parsed.data) : { kind: "malformed" };
4442
- }
4443
- function later_instant(left, right) {
4444
- if (left === void 0) return right;
4445
- if (right === void 0) return left;
4446
- return Math.max(left, right);
4447
- }
4448
- function dedupe(records) {
4449
- const by_id = /* @__PURE__ */ new Map();
4450
- for (const record of records) {
4451
- const seen = by_id.get(record.request_id);
4452
- const at_ms = later_instant(seen?.at_ms, record.at_ms);
4453
- by_id.set(record.request_id, { ...seen ?? record, at_ms });
4454
- }
4455
- return [...by_id.values()];
4456
- }
4457
- function add_totals(left, right) {
4458
- return {
4459
- input_tokens: left.input_tokens + right.input_tokens,
4460
- cache_write_5m_tokens: left.cache_write_5m_tokens + right.cache_write_5m_tokens,
4461
- cache_write_1h_tokens: left.cache_write_1h_tokens + right.cache_write_1h_tokens,
4462
- cache_read_tokens: left.cache_read_tokens + right.cache_read_tokens,
4463
- output_tokens: left.output_tokens + right.output_tokens,
4464
- thinking_tokens: left.thinking_tokens + right.thinking_tokens,
4465
- thinking_measured: left.thinking_measured || right.thinking_measured
4466
- };
4467
- }
4468
- function sum_totals(records) {
4469
- let total = EMPTY_TOTALS;
4470
- for (const record of records) total = add_totals(total, record.totals);
4471
- return total;
4472
- }
4473
- function billed_input(totals) {
4474
- return totals.input_tokens + totals.cache_write_5m_tokens + totals.cache_write_1h_tokens + totals.cache_read_tokens;
4475
- }
4476
- var cost_usage = {
4477
- EMPTY_TOTALS,
4478
- UNKNOWN_MODEL,
4479
- SYNTHETIC_MODEL,
4480
- parse_line: parse_line4,
4481
- dedupe,
4482
- add_totals,
4483
- sum_totals,
4484
- billed_input
4485
- };
4486
-
4487
- // scripts/cost-runtime/cost-transcript.ts
4488
- var TRANSCRIPT_ROOT = path5.join(".claude", "projects");
4489
- var TRANSCRIPT_EXTENSION = ".jsonl";
4490
- var SLUG_PATTERN = /[^a-zA-Z0-9-]/gu;
4491
- var UNIT_DIRECTORY = "subagents";
4492
- var UNIT_ID_SEPARATOR = "/";
4493
- function project_slug(cwd) {
4494
- return cwd.replaceAll(SLUG_PATTERN, "-");
4495
- }
4496
- function transcript_directory(cwd, home = homedir()) {
4497
- return path5.join(home, TRANSCRIPT_ROOT, project_slug(cwd));
4498
- }
4499
- var GIT_ENTRY = ".git";
4500
- var GITDIR_PREFIX = "gitdir:";
4501
- var WORKTREE_SEGMENT = `/${GIT_ENTRY}/worktrees/`;
4502
- var NOT_FOUND = -1;
4503
- function linked_worktree_gitdir(cwd) {
4504
- try {
4505
- const contents = readFileSync3(path5.join(cwd, GIT_ENTRY), "utf8").trim();
4506
- return contents.startsWith(GITDIR_PREFIX) ? contents.slice(GITDIR_PREFIX.length).trim() : "";
4507
- } catch {
4508
- return "";
4509
- }
4510
- }
4511
- function session_cwd(cwd) {
4512
- const gitdir = linked_worktree_gitdir(cwd);
4513
- const absolute = gitdir === "" ? "" : path5.resolve(cwd, gitdir);
4514
- const segment = absolute.indexOf(WORKTREE_SEGMENT);
4515
- return segment === NOT_FOUND ? cwd : absolute.slice(0, segment);
4516
- }
4517
- function read_directory(directory) {
4518
- try {
4519
- return readdirSync3(directory);
4520
- } catch {
4521
- return [];
4522
- }
4523
- }
4524
- var LANE_ISSUE_SLUG = /^\d+$/u;
4525
- function lane_transcript_directories(main_cwd, home) {
4526
- const projects = path5.join(home, TRANSCRIPT_ROOT);
4527
- const prefix = `${project_slug(lane_paths.lane_root(main_cwd))}-`;
4528
- return read_directory(projects).filter((name) => name.startsWith(prefix) && LANE_ISSUE_SLUG.test(name.slice(prefix.length))).map((name) => path5.join(projects, name));
4529
- }
4530
- function transcript_directories(cwd, home = homedir()) {
4531
- const own = transcript_directory(cwd, home);
4532
- const lanes = session_cwd(cwd) === cwd ? lane_transcript_directories(cwd, home) : [];
4533
- return [.../* @__PURE__ */ new Set([own, ...lanes])];
4534
- }
4535
- var OWN_DEPTH = 0;
4536
- function home_directory() {
4537
- return homedir();
4538
- }
4539
- function to_session_file(full_path, session_id, depth) {
4540
- try {
4541
- return {
4542
- session_id,
4543
- path: full_path,
4544
- modified_ms: statSync(full_path).mtimeMs,
4545
- is_delegated: depth > OWN_DEPTH,
4546
- depth
4547
- };
4548
- } catch {
4549
- return void 0;
4550
- }
4551
- }
4552
- function is_transcript(name) {
4553
- return name.endsWith(TRANSCRIPT_EXTENSION);
4554
- }
4555
- function without_extension(name) {
4556
- return name.slice(0, -TRANSCRIPT_EXTENSION.length);
4557
- }
4558
- function own_files(directory, names) {
4559
- return names.filter((name) => is_transcript(name)).map((name) => to_session_file(path5.join(directory, name), without_extension(name), OWN_DEPTH)).filter((file) => file !== void 0);
4560
- }
4561
- function unit_directory(directory, session_id) {
4562
- return path5.join(directory, session_id, UNIT_DIRECTORY);
4563
- }
4564
- var UNIT_DEPTH = 1;
4565
- function level_units(subagents_directory, prefix, depth) {
4566
- return read_directory(subagents_directory).filter((name) => is_transcript(name)).map(
4567
- (name) => to_session_file(
4568
- path5.join(subagents_directory, name),
4569
- `${prefix}${UNIT_ID_SEPARATOR}${without_extension(name)}`,
4570
- depth
4571
- )
4572
- ).filter((file) => file !== void 0);
4573
- }
4574
- function collect_units(subagents_directory, prefix, depth) {
4575
- const nested = read_directory(subagents_directory).filter((name) => !is_transcript(name)).flatMap(
4576
- (name) => collect_units(
4577
- unit_directory(subagents_directory, name),
4578
- `${prefix}${UNIT_ID_SEPARATOR}${name}`,
4579
- depth + 1
4580
- )
4581
- );
4582
- return [...level_units(subagents_directory, prefix, depth), ...nested];
4583
- }
4584
- function unit_files(directory, session_name) {
4585
- return collect_units(unit_directory(directory, session_name), session_name, UNIT_DEPTH);
4586
- }
4587
- function list_sessions(directory) {
4588
- const names = read_directory(directory);
4589
- const units = names.filter((name) => !is_transcript(name)).flatMap((name) => unit_files(directory, name));
4590
- return [...own_files(directory, names), ...units].toSorted(
4591
- (left, right) => right.modified_ms - left.modified_ms
4592
- );
4593
- }
4594
- function list_sessions_across(directories) {
4595
- const seen = /* @__PURE__ */ new Set();
4596
- const merged = directories.flatMap((directory) => list_sessions(directory));
4597
- const newest_first = merged.toSorted((left, right) => right.modified_ms - left.modified_ms);
4598
- const kept = [];
4599
- for (const file of newest_first) {
4600
- if (seen.has(file.session_id)) continue;
4601
- seen.add(file.session_id);
4602
- kept.push(file);
4603
- }
4604
- return kept;
4605
- }
4606
- function owning_session_id(file) {
4607
- const [owner] = file.session_id.split(UNIT_ID_SEPARATOR);
4608
- return owner ?? file.session_id;
4609
- }
4610
- function parent_session_id(file) {
4611
- const separator = file.session_id.lastIndexOf(UNIT_ID_SEPARATOR);
4612
- return separator === NOT_FOUND ? file.session_id : file.session_id.slice(0, separator);
4613
- }
4614
- function latest_own_index(files) {
4615
- const index = files.findIndex((file) => !file.is_delegated);
4616
- return index === -1 ? 0 : index;
4617
- }
4618
- function empty_session() {
4619
- return {
4620
- records: [],
4621
- no_usage_lines: 0,
4622
- malformed_lines: 0,
4623
- is_readable: false,
4624
- baseline_tokens: 0
4625
- };
4626
- }
4627
- function tally(content) {
4628
- const outcomes = content.split("\n").map((line) => cost_usage.parse_line(line));
4629
- const records = outcomes.flatMap(
4630
- (outcome) => outcome.kind === "record" ? [outcome.record] : []
4631
- );
4632
- const unique = cost_usage.dedupe(records);
4633
- const [first] = unique;
4634
- return {
4635
- records: unique,
4636
- no_usage_lines: outcomes.filter((outcome) => outcome.kind === "no_usage").length,
4637
- malformed_lines: outcomes.filter((outcome) => outcome.kind === "malformed").length,
4638
- is_readable: true,
4639
- baseline_tokens: first === void 0 ? 0 : cost_usage.billed_input(first.totals)
4640
- };
4641
- }
4642
- function read_session(file) {
4643
- const content = file_reader.read_if_readable(file.path);
4644
- if (content === void 0) return { session_id: file.session_id, ...empty_session() };
4645
- return { session_id: file.session_id, ...tally(content) };
4646
- }
4647
- function read_raw(file) {
4648
- return file_reader.read_if_readable(file.path) ?? "";
4649
- }
4650
- function read_optional2(file) {
4651
- return file_reader.read_if_readable(file.path);
4652
- }
4653
- function directory_exists(directory) {
4654
- try {
4655
- return statSync(directory).isDirectory();
4656
- } catch {
4657
- return false;
4658
- }
4659
- }
4660
- function searched_directories(directories) {
4661
- return directories.map((directory) => ({
4662
- path: directory,
4663
- exists: directory_exists(directory)
4664
- }));
4665
- }
4666
- function describe_searched(directory) {
4667
- return ` ${directory.path} \u2014 ${directory.exists ? "no transcripts here" : "no such directory"}`;
4668
- }
4669
- function missing_message(searched, session_id) {
4670
- const lead = session_id === void 0 ? "No transcripts found. Searched:" : `No transcript named ${session_id}. Searched:`;
4671
- const listed = searched.map((directory) => describe_searched(directory));
4672
- if (session_id !== void 0) return [lead, ...listed];
4673
- return [
4674
- lead,
4675
- ...listed,
4676
- "Claude Code writes them per project; run this from the project it ran in."
4677
- ];
4678
- }
4679
- var cost_transcript = {
4680
- TRANSCRIPT_EXTENSION,
4681
- TRANSCRIPT_ROOT,
4682
- UNIT_DIRECTORY,
4683
- project_slug,
4684
- transcript_directory,
4685
- transcript_directories,
4686
- session_cwd,
4687
- unit_directory,
4688
- list_sessions,
4689
- list_sessions_across,
4690
- searched_directories,
4691
- owning_session_id,
4692
- parent_session_id,
4693
- latest_own_index,
4694
- tally,
4695
- read_session,
4696
- read_raw,
4697
- read_optional: read_optional2,
4698
- missing_message,
4699
- home_directory
4700
- };
4701
-
4702
- // scripts/time-runtime/time-hook-transcript.ts
4703
- var { TRANSCRIPT_EXTENSION: TRANSCRIPT_EXTENSION2 } = cost_transcript;
4388
+ import path3 from "node:path";
4389
+ var { TRANSCRIPT_EXTENSION } = cost_transcript;
4704
4390
  var AGENT_PREFIX = "agent-";
4705
4391
  var AGENT_ID_PATTERN = /^[\w-]+$/u;
4706
4392
  function is_agent_id(value) {
4707
4393
  return typeof value === "string" && AGENT_ID_PATTERN.test(value);
4708
4394
  }
4709
4395
  function fork_path(transcript_path, agent_id) {
4710
- const directory = path6.dirname(transcript_path);
4711
- const session_id = path6.basename(transcript_path, TRANSCRIPT_EXTENSION2);
4712
- const file_name = `${AGENT_PREFIX}${agent_id}${TRANSCRIPT_EXTENSION2}`;
4713
- return path6.join(cost_transcript.unit_directory(directory, session_id), file_name);
4396
+ const directory = path3.dirname(transcript_path);
4397
+ const session_id = path3.basename(transcript_path, TRANSCRIPT_EXTENSION);
4398
+ const file_name = `${AGENT_PREFIX}${agent_id}${TRANSCRIPT_EXTENSION}`;
4399
+ return path3.join(cost_transcript.unit_directory(directory, session_id), file_name);
4714
4400
  }
4715
4401
  function transcript_of(transcript_path, agent_id) {
4716
4402
  if (!is_agent_id(agent_id)) return transcript_path;
4717
- if (!transcript_path.endsWith(TRANSCRIPT_EXTENSION2)) return transcript_path;
4403
+ if (!transcript_path.endsWith(TRANSCRIPT_EXTENSION)) return transcript_path;
4718
4404
  return fork_path(transcript_path, agent_id);
4719
4405
  }
4720
4406
  var time_hook_transcript = {
@@ -4723,8 +4409,8 @@ var time_hook_transcript = {
4723
4409
  };
4724
4410
 
4725
4411
  // scripts/time-runtime/time-density-hook.ts
4726
- import { closeSync, fstatSync, openSync, readSync } from "node:fs";
4727
- import { z as z8 } from "zod";
4412
+ import { closeSync as closeSync2, fstatSync, openSync as openSync2, readSync } from "node:fs";
4413
+ import { z as z7 } from "zod";
4728
4414
 
4729
4415
  // scripts/time-runtime/time-density.ts
4730
4416
  var MIN_ROUND_TRIPS = 10;
@@ -4780,15 +4466,15 @@ var TAIL_BYTES = 262144;
4780
4466
  var FILE_START = 0;
4781
4467
  var NOTICE_PREFIX = "josh-density-notice-";
4782
4468
  var NEVER_MS = 0;
4783
- var payload_schema = z8.object({
4784
- transcript_path: z8.string().min(1).optional(),
4469
+ var payload_schema = z7.object({
4470
+ transcript_path: z7.string().min(1).optional(),
4785
4471
  // **`nullish`, not `optional`.** A payload spelling the absent agent as `null` has to read as "no
4786
4472
  // fork"; rejected, it would fail `safeParse` for the whole payload and silence the line for every
4787
4473
  // edit of the main line — the opposite of this module's stated failure direction.
4788
- agent_id: z8.string().nullish()
4474
+ agent_id: z7.string().nullish()
4789
4475
  });
4790
- var notice_schema = z8.object({ notified_at_ms: z8.number() });
4791
- var call_schema = z8.object({ tool_name: z8.string().min(1), tool_input: z8.unknown() });
4476
+ var notice_schema = z7.object({ notified_at_ms: z7.number() });
4477
+ var call_schema = z7.object({ tool_name: z7.string().min(1), tool_input: z7.unknown() });
4792
4478
  function parse_transcript_path(raw_payload) {
4793
4479
  const parsed = payload_schema.safeParse(JSON.parse(raw_payload));
4794
4480
  if (!parsed.success || parsed.data.transcript_path === void 0) return void 0;
@@ -4800,7 +4486,7 @@ function parse_call(raw_payload) {
4800
4486
  return { name: parsed.data.tool_name, input: parsed.data.tool_input };
4801
4487
  }
4802
4488
  function read_tail(file_path, max_bytes = TAIL_BYTES) {
4803
- const descriptor = openSync(file_path, "r");
4489
+ const descriptor = openSync2(file_path, "r");
4804
4490
  try {
4805
4491
  const { size } = fstatSync(descriptor);
4806
4492
  const length = Math.min(size, max_bytes);
@@ -4808,7 +4494,7 @@ function read_tail(file_path, max_bytes = TAIL_BYTES) {
4808
4494
  const read = readSync(descriptor, buffer, FILE_START, length, size - length);
4809
4495
  return buffer.subarray(FILE_START, read).toString("utf8");
4810
4496
  } finally {
4811
- closeSync(descriptor);
4497
+ closeSync2(descriptor);
4812
4498
  }
4813
4499
  }
4814
4500
  function notice_path(transcript_path) {
@@ -4817,15 +4503,11 @@ function notice_path(transcript_path) {
4817
4503
  function last_notice_ms(source) {
4818
4504
  const raw = stamp_file.read_stamp_text(source);
4819
4505
  if (raw === void 0) return NEVER_MS;
4820
- try {
4821
- return notice_schema.parse(JSON.parse(raw)).notified_at_ms;
4822
- } catch {
4823
- return NEVER_MS;
4824
- }
4506
+ return json_value.parse_with(raw, notice_schema)?.notified_at_ms ?? NEVER_MS;
4825
4507
  }
4826
- function arm_throttle(target, now_ms) {
4508
+ function arm_throttle(target2, now_ms) {
4827
4509
  try {
4828
- stamp_file.write_stamp(target, { notified_at_ms: now_ms });
4510
+ stamp_file.write_stamp(target2, { notified_at_ms: now_ms });
4829
4511
  } catch {
4830
4512
  }
4831
4513
  }
@@ -4834,11 +4516,11 @@ function notice_for(raw_payload, now_ms) {
4834
4516
  if (transcript_path === void 0) return void 0;
4835
4517
  const tail = read_tail(transcript_path);
4836
4518
  const reading = time_density.read_window(tail);
4837
- const target = notice_path(transcript_path);
4838
- if (!time_density.is_due(reading, now_ms - last_notice_ms(target))) return void 0;
4519
+ const target2 = notice_path(transcript_path);
4520
+ if (!time_density.is_due(reading, now_ms - last_notice_ms(target2))) return void 0;
4839
4521
  const candidates = time_batch_guard.pairing_candidates(tail, parse_call(raw_payload));
4840
4522
  if (candidates === "") return void 0;
4841
- arm_throttle(target, now_ms);
4523
+ arm_throttle(target2, now_ms);
4842
4524
  return time_density.format_notice(reading, candidates);
4843
4525
  }
4844
4526
  function density_notice(raw_payload, now_ms = Date.now()) {
@@ -4855,11 +4537,8 @@ var time_density_hook = {
4855
4537
  };
4856
4538
 
4857
4539
  export {
4858
- json_value,
4859
4540
  cost_blocks,
4860
4541
  ESLINT_EDIT_CACHE_FLAGS,
4861
- process_identity,
4862
- process_owner_schema,
4863
4542
  time_shell,
4864
4543
  time_bundle_call,
4865
4544
  blocking_issue_schema,
@@ -4881,10 +4560,6 @@ export {
4881
4560
  time_transcript_line,
4882
4561
  time_spans,
4883
4562
  time_batch_guard,
4884
- lane_paths,
4885
- file_reader,
4886
- cost_usage,
4887
- cost_transcript,
4888
4563
  time_hook_transcript,
4889
4564
  time_density_hook
4890
4565
  };