@joshuafolkken/kit 1.1514.0 → 1.1784.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (858) hide show
  1. package/.claude/agents/investigator.md +1 -1
  2. package/.claude/settings.json +5 -5
  3. package/.claude/skills/epic-commands/SKILL.md +26 -65
  4. package/.claude/skills/epic-commands/epic-bundle.md +3 -1
  5. package/.claude/skills/workflow-commands/SKILL.md +5 -5
  6. package/.claude/skills/workflow-commands/background-commands.md +5 -5
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +10 -8
  8. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
  9. package/.claude/skills/workflow-commands/backlogrun-lanes.md +17 -13
  10. package/.claude/skills/workflow-commands/backlogrun-park.md +14 -23
  11. package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -2
  12. package/.claude/skills/workflow-commands/backlogrun-recovery.md +5 -5
  13. package/.claude/skills/workflow-commands/backlogrun-steps.md +10 -10
  14. package/.claude/skills/workflow-commands/backlogrun.md +1 -1
  15. package/.claude/skills/workflow-commands/chain-rule.md +13 -7
  16. package/.claude/skills/workflow-commands/delegation.md +6 -5
  17. package/.claude/skills/workflow-commands/entry-sequence.md +9 -9
  18. package/.claude/skills/workflow-commands/followup.md +9 -31
  19. package/.claude/skills/workflow-commands/fullrun-steps.md +36 -45
  20. package/.claude/skills/workflow-commands/fullrun.md +2 -2
  21. package/.claude/skills/workflow-commands/halfrun.md +17 -25
  22. package/.claude/skills/workflow-commands/issue-comments.md +16 -12
  23. package/.claude/skills/workflow-commands/issue-scout.md +2 -2
  24. package/.claude/skills/workflow-commands/kickoff.md +24 -23
  25. package/.claude/skills/workflow-commands/latest-gate.md +7 -12
  26. package/.claude/skills/workflow-commands/needs-human-review.md +9 -14
  27. package/.claude/skills/workflow-commands/observation-filing.md +4 -36
  28. package/.claude/skills/workflow-commands/observation-ledger.md +1 -1
  29. package/.claude/skills/workflow-commands/pre-gate-cut.md +13 -30
  30. package/.claude/skills/workflow-commands/prerequisite.md +10 -16
  31. package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
  32. package/.claude/skills/workflow-commands/prrun.md +3 -7
  33. package/.claude/skills/workflow-commands/retrospective.md +1 -1
  34. package/.claude/skills/workflow-commands/split-assessment.md +13 -1
  35. package/.claude/skills/workflow-commands/working-tree-hold.md +9 -9
  36. package/.codex/hooks.json +5 -5
  37. package/.github/actions/setup-node/action.yml +9 -0
  38. package/.github/actions/setup-pnpm/action.yml +1 -1
  39. package/.github/dependabot.yml +16 -0
  40. package/.github/release.yml +0 -2
  41. package/.github/workflows/ci.yml +120 -10
  42. package/.github/workflows/publish.yml +8 -1
  43. package/.github/workflows/sonar-qube.yml +1 -0
  44. package/.prettierignore +2 -0
  45. package/.vscode/tasks.json +1 -2
  46. package/CLAUDE.md +3 -7
  47. package/README.md +4 -2
  48. package/SECURITY.md +1 -1
  49. package/dist/CLAUDE.md +3 -7
  50. package/dist/commands/document-read-cli.js +882 -0
  51. package/dist/commands/{document-section-cli.js → document-section-main.js} +79 -37
  52. package/dist/commands/read-set-cli.js +1867 -0
  53. package/dist/commands/run-prep-main.js +21653 -0
  54. package/dist/commands/run-step-cli.js +23880 -0
  55. package/dist/config-merge/index.js +5 -1
  56. package/dist/hooks/audit-provision.js +20 -35
  57. package/dist/hooks/{chunk-DGT54IH5.js → chunk-AZX4FGQ3.js} +63 -17
  58. package/dist/hooks/chunk-CWMBGKYW.js +6483 -0
  59. package/dist/hooks/chunk-O2YBIDSI.js +4306 -0
  60. package/dist/hooks/{chunk-TNUMY6NL.js → chunk-PT5R6UJD.js} +4193 -1900
  61. package/dist/hooks/chunk-TUIFS5E7.js +72 -0
  62. package/dist/hooks/{chunk-723HKZO5.js → chunk-VWWCFGWK.js} +1 -1
  63. package/dist/hooks/{chunk-APUO6U4J.js → chunk-WR2KQAYZ.js} +1843 -440
  64. package/dist/hooks/{chunk-O6GDRNJB.js → chunk-XGBNSWEI.js} +248 -46
  65. package/dist/hooks/chunk-YCDOIR3I.js +3456 -0
  66. package/dist/hooks/codex-hook-adapter.js +10 -22
  67. package/dist/hooks/format-edited.js +5 -6
  68. package/dist/hooks/inputs.json +443 -317
  69. package/dist/hooks/pretool-guard.js +7 -25
  70. package/dist/hooks/session-lang.js +44 -51
  71. package/dist/hooks/stop-guard.js +7716 -2187
  72. package/dist/josh.js +6002 -3583
  73. package/dist/self-sync-guard/index.js +74 -10
  74. package/dist/version/index.js +115 -406
  75. package/eslint/base.js +1 -1
  76. package/lefthook/base.yml +3 -1
  77. package/package.json +10 -48
  78. package/pnpm-workspace.yaml +4 -2
  79. package/prompts/coding-standards.md +1 -1
  80. package/prompts/collaboration-workflow/file-edits.md +1 -7
  81. package/prompts/collaboration-workflow/issue-citation.md +1 -1
  82. package/prompts/collaboration-workflow/issue-template.md +33 -16
  83. package/prompts/collaboration-workflow/lane-instructions.md +1 -2
  84. package/prompts/collaboration-workflow/measurement.md +37 -0
  85. package/prompts/collaboration-workflow/operating-rules.md +4 -6
  86. package/prompts/collaboration-workflow/output-bounds.md +2 -7
  87. package/prompts/collaboration-workflow/plan-comment.md +3 -42
  88. package/prompts/collaboration-workflow/principles.md +5 -0
  89. package/prompts/collaboration-workflow/report-format.md +31 -60
  90. package/prompts/collaboration-workflow/residency.md +2 -2
  91. package/prompts/collaboration-workflow/shell-body.md +6 -16
  92. package/prompts/collaboration-workflow/turn-batching.md +0 -2
  93. package/prompts/collaboration-workflow/upstream-interrupt.md +14 -4
  94. package/prompts/collaboration-workflow/wip-cap.md +1 -1
  95. package/prompts/collaboration-workflow.md +3 -7
  96. package/prompts/refactoring.md +1 -1
  97. package/prompts/review-rubric.md +1 -2
  98. package/prompts/review.md +41 -21
  99. package/prompts/testing-guide.md +8 -43
  100. package/scripts/agent/agent-event.ts +15 -15
  101. package/scripts/agent/agent-exit-record.ts +13 -1
  102. package/scripts/agent/api-auth.ts +41 -0
  103. package/scripts/agent/api-outage.ts +1 -1
  104. package/scripts/auto-ok/auto-ok-cli.ts +14 -16
  105. package/scripts/auto-ok/auto-ok-judge-read.ts +12 -3
  106. package/scripts/auto-ok/auto-ok-judge-write.ts +46 -19
  107. package/scripts/auto-ok/auto-ok-judge.ts +13 -2
  108. package/scripts/auto-ok/auto-ok-main.ts +17 -0
  109. package/scripts/backlog/backlog-arrival.ts +14 -3
  110. package/scripts/backlog/backlog-budget-cli.ts +7 -33
  111. package/scripts/backlog/backlog-budget-main.ts +16 -0
  112. package/scripts/backlog/backlog-budget.ts +2 -3
  113. package/scripts/backlog/backlog-defect-priority.ts +4 -3
  114. package/scripts/backlog/backlog-drive-adopt.ts +67 -0
  115. package/scripts/backlog/backlog-drive-args.ts +4 -5
  116. package/scripts/backlog/backlog-drive-cli.ts +113 -28
  117. package/scripts/backlog/backlog-drive-hold.ts +162 -0
  118. package/scripts/backlog/backlog-drive-idle.ts +151 -0
  119. package/scripts/backlog/backlog-drive-judge.ts +25 -0
  120. package/scripts/backlog/backlog-drive-memory.ts +126 -0
  121. package/scripts/backlog/backlog-drive-named-offer.ts +5 -10
  122. package/scripts/backlog/backlog-drive-named.ts +53 -6
  123. package/scripts/backlog/backlog-drive-offer-argv.ts +3 -8
  124. package/scripts/backlog/backlog-drive-paused.ts +169 -0
  125. package/scripts/backlog/backlog-drive-restore.ts +30 -7
  126. package/scripts/backlog/backlog-drive-seats.ts +18 -8
  127. package/scripts/backlog/backlog-drive-token-handling.ts +38 -0
  128. package/scripts/backlog/backlog-drive.ts +79 -75
  129. package/scripts/backlog/backlog-next-main.ts +16 -0
  130. package/scripts/backlog/backlog-next-shared.ts +73 -0
  131. package/scripts/backlog/backlog-next.ts +48 -16
  132. package/scripts/backlog/backlog-occupied.ts +52 -39
  133. package/scripts/backlog/backlog-offer-cli.ts +6 -21
  134. package/scripts/backlog/backlog-offer-exclude.ts +15 -0
  135. package/scripts/backlog/backlog-offer-main.ts +12 -0
  136. package/scripts/backlog/backlog-offer.ts +36 -3
  137. package/scripts/backlog/backlog-overlap.ts +22 -4
  138. package/scripts/backlog/backlog-plan-read.ts +6 -2
  139. package/scripts/backlog/backlog-plan.ts +18 -4
  140. package/scripts/backlog/backlog-pool.ts +10 -10
  141. package/scripts/backlog/backlog-rank.ts +10 -2
  142. package/scripts/backlog/backlog-ready.ts +112 -30
  143. package/scripts/backlog/backlog-stalled-detect.ts +109 -36
  144. package/scripts/backlog/backlog-stalled.ts +52 -16
  145. package/scripts/backlog/backlog-wait-cause.ts +86 -0
  146. package/scripts/backlog/backlog-waves.ts +39 -13
  147. package/scripts/backlog/backlogrun-args.ts +19 -7
  148. package/scripts/backlog/backlogrun-cli.ts +19 -5
  149. package/scripts/backlog/backlogrun-launch.ts +6 -0
  150. package/scripts/backlog/backlogrun-restart.ts +97 -0
  151. package/scripts/backlog/backlogrun-stop.ts +79 -7
  152. package/scripts/behavior/behavior-cli.ts +2 -2
  153. package/scripts/behavior/behavior-rules.ts +47 -24
  154. package/scripts/build/build-bin.ts +2 -16
  155. package/scripts/build/build-claude-md.ts +0 -7
  156. package/scripts/build/build-commands.ts +0 -13
  157. package/scripts/build/build-hooks.ts +49 -48
  158. package/scripts/build/hook-bundle-stamp.ts +29 -11
  159. package/scripts/build/local-bin.ts +1 -1
  160. package/scripts/cases/cases-cli.ts +25 -13
  161. package/scripts/cases/cases-interaction-scan.ts +134 -0
  162. package/scripts/cases/cases-interaction.ts +183 -0
  163. package/scripts/cases/cases-logic.ts +39 -6
  164. package/scripts/ci/pr-classification-main.ts +18 -0
  165. package/scripts/ci/pr-classification.ts +10 -17
  166. package/scripts/clone/clone-scan.ts +1 -1
  167. package/scripts/cost-runtime/cost-blocks.ts +22 -37
  168. package/scripts/cost-runtime/cost-cli.ts +31 -14
  169. package/scripts/cost-runtime/cost-main.ts +12 -0
  170. package/scripts/cost-runtime/cost-transcript.ts +1 -0
  171. package/scripts/delegation/delegation-policy.ts +17 -4
  172. package/scripts/delegation/duplicate-read-guard.ts +0 -8
  173. package/scripts/delegation/investigation-guard.ts +0 -8
  174. package/scripts/delegation/investigation-reads.ts +3 -4
  175. package/scripts/dependabot/dependabot-cooldown.ts +194 -0
  176. package/scripts/discovery/repo-discovery.ts +24 -6
  177. package/scripts/doctor/doctor-consumer.ts +2 -5
  178. package/scripts/document/document-byte-budget.ts +8 -6
  179. package/scripts/document/document-scan.ts +1 -1
  180. package/scripts/document/document-section-cli.ts +0 -8
  181. package/scripts/document/document-section-main.ts +12 -0
  182. package/scripts/epic/epic-audit-cli.ts +12 -6
  183. package/scripts/epic/epic-bundle-apply.ts +137 -0
  184. package/scripts/epic/epic-bundle-cli.ts +32 -121
  185. package/scripts/epic/epic-bundle-format.ts +116 -0
  186. package/scripts/epic/epic-bundle-main.ts +17 -0
  187. package/scripts/epic/epic-busy.ts +5 -12
  188. package/scripts/epic/epic-classify.ts +24 -15
  189. package/scripts/epic/epic-cli-argv.ts +31 -0
  190. package/scripts/epic/epic-cli-decide.ts +42 -0
  191. package/scripts/epic/epic-cli.ts +6 -38
  192. package/scripts/epic/epic-close.ts +112 -55
  193. package/scripts/epic/epic-cross-repo.ts +4 -7
  194. package/scripts/epic/epic-decide.ts +119 -0
  195. package/scripts/epic/epic-decision.ts +9 -0
  196. package/scripts/epic/epic-fetch.ts +4 -0
  197. package/scripts/epic/epic-graph.ts +2 -0
  198. package/scripts/epic/epic-issue.ts +5 -1
  199. package/scripts/epic/epic-label-age.ts +1 -1
  200. package/scripts/epic/epic-lane-offer.ts +39 -4
  201. package/scripts/epic/epic-next-main.ts +24 -0
  202. package/scripts/epic/epic-next.ts +6 -24
  203. package/scripts/epic/epic-outside-blocker.ts +6 -2
  204. package/scripts/epic/epic-parse.ts +9 -3
  205. package/scripts/epic/epic-read.ts +1 -0
  206. package/scripts/epic/epic-reconcile.ts +39 -0
  207. package/scripts/epic/epic-run.ts +10 -1
  208. package/scripts/epic/epic-solo.ts +50 -14
  209. package/scripts/epic/epic.ts +41 -7
  210. package/scripts/exports/unused-members-cli.ts +2 -2
  211. package/scripts/followup/followup-checks-event.ts +8 -3
  212. package/scripts/followup/followup-coderabbit-wait.ts +82 -0
  213. package/scripts/followup/followup-review-gates.ts +81 -0
  214. package/scripts/followup/git-followup-stages.ts +13 -3
  215. package/scripts/followup/git-followup-workflow.ts +19 -66
  216. package/scripts/followup/git-pr-followup-wrapup.ts +9 -14
  217. package/scripts/followup/git-pr-followup.ts +36 -8
  218. package/scripts/fresh-machine/fresh-machine-cli.ts +1 -1
  219. package/scripts/fresh-machine/fresh-machine-run.ts +8 -8
  220. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +1 -1
  221. package/scripts/gate/busy-average.ts +58 -0
  222. package/scripts/gate/check-cpu.ts +60 -0
  223. package/scripts/gate/check-inputs.ts +39 -95
  224. package/scripts/gate/check-reuse.ts +33 -54
  225. package/scripts/gate/command-memory.ts +192 -0
  226. package/scripts/gate/core-admission.ts +218 -28
  227. package/scripts/gate/core-budget-timing.ts +37 -0
  228. package/scripts/gate/core-budget.ts +80 -98
  229. package/scripts/gate/core-wait-record.ts +48 -0
  230. package/scripts/gate/core-wait.ts +37 -5
  231. package/scripts/gate/core-weights.ts +86 -0
  232. package/scripts/gate/free-cores.ts +27 -4
  233. package/scripts/gate/gate-ledger.ts +32 -4
  234. package/scripts/gate/gate-plan.ts +41 -34
  235. package/scripts/gate/gate-report.ts +14 -2
  236. package/scripts/gate/gate-run-steps.ts +53 -8
  237. package/scripts/gate/gate-skip.ts +12 -2
  238. package/scripts/gate/gate-steps.ts +12 -1
  239. package/scripts/gate/input-fingerprint.ts +42 -0
  240. package/scripts/gate/machine-capacity.ts +65 -31
  241. package/scripts/gate/moved-paths.ts +67 -0
  242. package/scripts/gate/project-checks.ts +5 -12
  243. package/scripts/gate/scoped-green.ts +12 -8
  244. package/scripts/gate/since-green.ts +62 -0
  245. package/scripts/gate/toolchain-inputs.ts +115 -0
  246. package/scripts/gate/verification-gate.ts +27 -24
  247. package/scripts/gate/verification-inputs.ts +250 -0
  248. package/scripts/gh/gh-author-association.ts +96 -9
  249. package/scripts/gh/git-ai-review-scan.ts +4 -2
  250. package/scripts/gh/git-gh-api-path.ts +15 -0
  251. package/scripts/gh/git-gh-branch-rules.ts +73 -0
  252. package/scripts/gh/git-gh-conditional.ts +5 -2
  253. package/scripts/gh/git-gh-issue-read.ts +5 -1
  254. package/scripts/gh/git-gh-issue-write.ts +67 -29
  255. package/scripts/gh/git-gh-issue.ts +7 -3
  256. package/scripts/gh/git-gh-poll-read.ts +89 -0
  257. package/scripts/gh/git-gh-pr-auto-merge.ts +8 -3
  258. package/scripts/gh/git-gh-pr-rest.ts +1 -1
  259. package/scripts/gh/git-gh-pr-snapshot.ts +33 -20
  260. package/scripts/gh/git-gh-pr.ts +27 -15
  261. package/scripts/gh/git-pr-checks-eval.ts +39 -7
  262. package/scripts/gh/git-pr-checks-parse.ts +39 -9
  263. package/scripts/gh/git-pr-merge-checked.ts +80 -0
  264. package/scripts/git/base-tree.ts +19 -2
  265. package/scripts/git/changed-file-scope.ts +6 -4
  266. package/scripts/git/changed-paths.ts +18 -1
  267. package/scripts/git/git-diff-reads.ts +27 -2
  268. package/scripts/git/git-grep-hits.ts +85 -0
  269. package/scripts/git/git-location-environment.ts +1 -1
  270. package/scripts/git/git-merge-conflicts.ts +83 -0
  271. package/scripts/git/git-preflight.ts +37 -12
  272. package/scripts/git/git-push-transport.ts +1 -2
  273. package/scripts/git/git-schemas.ts +17 -7
  274. package/scripts/git/git-spawn.ts +1 -2
  275. package/scripts/git/git-status.ts +4 -4
  276. package/scripts/git/main-merge-main.ts +12 -0
  277. package/scripts/git/main-merge-regenerate.ts +2 -2
  278. package/scripts/git/main-merge.ts +25 -9
  279. package/scripts/git/main-sync-main.ts +12 -0
  280. package/scripts/git/main-sync.ts +0 -9
  281. package/scripts/git/stash/git-stash.ts +27 -4
  282. package/scripts/git/stash/{stash-pop-args.ts → stash-args.ts} +13 -10
  283. package/scripts/git/stash/stash-pop-cli.ts +6 -12
  284. package/scripts/git/stash/stash-pop-main.ts +12 -0
  285. package/scripts/git/stash/stash-push-cli.ts +76 -0
  286. package/scripts/git/stash/stash-push-main.ts +12 -0
  287. package/scripts/hooks/batch-guard.ts +0 -8
  288. package/scripts/hooks/check-commit-message-main.ts +8 -0
  289. package/scripts/hooks/check-commit-message.ts +4 -7
  290. package/scripts/hooks/format-edited-file.ts +8 -24
  291. package/scripts/hooks/pre-commit-lint.ts +30 -3
  292. package/scripts/hooks/pre-push-unit.ts +4 -2
  293. package/scripts/hooks/pretool-guard-cli.ts +1 -8
  294. package/scripts/hooks/pretool-guard.ts +32 -19
  295. package/scripts/hooks/reserved-run.ts +67 -9
  296. package/scripts/hooks/run-hook.sh +13 -4
  297. package/scripts/hooks/shell-rules-notice.ts +37 -0
  298. package/scripts/hooks/stop-actions.ts +2 -21
  299. package/scripts/hooks/stop-guard.ts +13 -9
  300. package/scripts/init/hook-command-rewrite.ts +19 -5
  301. package/scripts/init/hook-launch.ts +15 -17
  302. package/scripts/init/init-actions.ts +0 -6
  303. package/scripts/init/init-ai-copy.ts +10 -36
  304. package/scripts/init/init-bootstrap.ts +9 -8
  305. package/scripts/init/init-dry-run-report.ts +1 -1
  306. package/scripts/init/init-dry-run.ts +1 -1
  307. package/scripts/init/init-file-action.ts +7 -9
  308. package/scripts/init/init-logic-json-merge.ts +2 -2
  309. package/scripts/init/init-logic-migrate.ts +9 -82
  310. package/scripts/init/init-logic.ts +3 -2
  311. package/scripts/init/init-main.ts +12 -0
  312. package/scripts/init/init.ts +5 -12
  313. package/scripts/init/kit-development-versions.ts +3 -7
  314. package/scripts/init/kit-written-paths.ts +2 -2
  315. package/scripts/init/project-profile.ts +5 -4
  316. package/scripts/init/tsconfig-preset-migration.ts +2 -1
  317. package/scripts/init/vscode-tasks.ts +1 -1
  318. package/scripts/issue/defect-origin-cli.ts +106 -0
  319. package/scripts/issue/defect-origin-line.ts +60 -0
  320. package/scripts/issue/defect-origin-main.ts +11 -0
  321. package/scripts/issue/defect-origin.ts +114 -0
  322. package/scripts/issue/defect-rate-cli.ts +34 -78
  323. package/scripts/issue/defect-rate.ts +0 -16
  324. package/scripts/issue/defect-report-cli.ts +128 -0
  325. package/scripts/issue/defect-report-format.ts +56 -0
  326. package/scripts/issue/defect-report-main.ts +11 -0
  327. package/scripts/issue/defect-report.ts +160 -0
  328. package/scripts/issue/expected-effect-lint.ts +1 -0
  329. package/scripts/issue/issue-already-done-cli.ts +62 -0
  330. package/scripts/issue/issue-body-or-comment.ts +40 -0
  331. package/scripts/issue/issue-cite-cli.ts +0 -9
  332. package/scripts/issue/issue-cite-main.ts +12 -0
  333. package/scripts/issue/issue-classification.ts +12 -7
  334. package/scripts/issue/issue-comment-cli.ts +10 -24
  335. package/scripts/issue/issue-comment-main.ts +12 -0
  336. package/scripts/issue/issue-evidence-exit.ts +100 -0
  337. package/scripts/issue/issue-file-cli.ts +29 -7
  338. package/scripts/issue/issue-file.ts +19 -19
  339. package/scripts/issue/issue-fold-cli.ts +2 -11
  340. package/scripts/issue/issue-fold-main.ts +12 -0
  341. package/scripts/issue/issue-labels.ts +81 -90
  342. package/scripts/issue/issue-lint-cli.ts +2 -10
  343. package/scripts/issue/issue-lint-main.ts +12 -0
  344. package/scripts/issue/issue-measured-cli.ts +56 -0
  345. package/scripts/issue/issue-merged.ts +19 -2
  346. package/scripts/issue/issue-not-before-label.ts +135 -0
  347. package/scripts/issue/issue-not-before.ts +111 -0
  348. package/scripts/issue/issue-number-shape.ts +15 -1
  349. package/scripts/issue/issue-park.ts +28 -0
  350. package/scripts/issue/issue-plan-cli.ts +151 -0
  351. package/scripts/issue/issue-priority.ts +151 -0
  352. package/scripts/issue/issue-rank.ts +7 -1
  353. package/scripts/issue/issue-read-cli.ts +3 -10
  354. package/scripts/issue/issue-read-main.ts +12 -0
  355. package/scripts/issue/issue-read.ts +29 -5
  356. package/scripts/issue/issue-release-cli.ts +0 -10
  357. package/scripts/issue/issue-release-main.ts +13 -0
  358. package/scripts/issue/issue-release.ts +7 -12
  359. package/scripts/issue/issue-sample-gate.ts +192 -0
  360. package/scripts/issue/issue-sample-source.ts +76 -0
  361. package/scripts/issue/issue-scout-cli.ts +0 -11
  362. package/scripts/issue/issue-scout-main.ts +14 -0
  363. package/scripts/issue/issue-state-cli.ts +0 -10
  364. package/scripts/issue/issue-state-main.ts +12 -0
  365. package/scripts/issue/issue-watch-diff.ts +56 -15
  366. package/scripts/issue/issue-watch.ts +2 -1
  367. package/scripts/issue/issue-wip.ts +2 -7
  368. package/scripts/issue/measure-rerun-cli.ts +13 -8
  369. package/scripts/issue/plan-consumers-cli.ts +39 -0
  370. package/scripts/issue/plan-consumers-main.ts +11 -0
  371. package/scripts/issue/plan-consumers-section.ts +55 -0
  372. package/scripts/issue/plan-consumers.ts +127 -0
  373. package/scripts/josh/agent-session-environment.ts +1 -1
  374. package/scripts/josh/command-usage.ts +15 -43
  375. package/scripts/josh/file-map-stamp.ts +49 -16
  376. package/scripts/josh/hook-decision.ts +32 -20
  377. package/scripts/josh/josh-command-map.ts +4 -1
  378. package/scripts/josh/josh-command-types.ts +12 -6
  379. package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
  380. package/scripts/josh/josh-commands-ai.ts +157 -158
  381. package/scripts/josh/josh-commands-backlog.ts +82 -16
  382. package/scripts/josh/josh-commands-clone.ts +1 -0
  383. package/scripts/josh/josh-commands-development.ts +111 -71
  384. package/scripts/josh/josh-commands-document.ts +43 -1
  385. package/scripts/josh/josh-commands-epic.ts +171 -0
  386. package/scripts/josh/josh-commands-hooks.ts +25 -2
  387. package/scripts/josh/josh-commands-issue-write.ts +181 -0
  388. package/scripts/josh/josh-commands-issue.ts +124 -24
  389. package/scripts/josh/josh-commands-lane.ts +103 -2
  390. package/scripts/josh/josh-commands-lint.ts +19 -8
  391. package/scripts/josh/josh-commands-maintenance.ts +112 -4
  392. package/scripts/josh/josh-commands-pause.ts +29 -0
  393. package/scripts/josh/josh-commands-progress.ts +87 -0
  394. package/scripts/josh/josh-commands-project.ts +138 -9
  395. package/scripts/josh/josh-commands-review.ts +124 -0
  396. package/scripts/josh/josh-commands-run.ts +211 -23
  397. package/scripts/josh/josh-commands-ship.ts +169 -0
  398. package/scripts/josh/josh-commands-split.ts +9 -0
  399. package/scripts/josh/josh-commands-versioning.ts +49 -2
  400. package/scripts/josh/josh-commands-workflow.ts +144 -6
  401. package/scripts/josh/josh-logic.ts +6 -13
  402. package/scripts/josh/package-directory.ts +2 -4
  403. package/scripts/josh/process-identity.ts +13 -4
  404. package/scripts/josh/session-language-cli.ts +4 -8
  405. package/scripts/josh/session-language-main.ts +13 -0
  406. package/scripts/josh/session-language.ts +6 -1
  407. package/scripts/josh/shared-cache.ts +90 -0
  408. package/scripts/josh/stamp-file.ts +9 -15
  409. package/scripts/lane/lane-await.ts +51 -12
  410. package/scripts/lane/lane-cache.ts +5 -30
  411. package/scripts/lane/lane-capacity.ts +14 -23
  412. package/scripts/lane/lane-check-stats.ts +62 -21
  413. package/scripts/lane/lane-child-invocation.ts +8 -0
  414. package/scripts/lane/lane-cli.ts +15 -5
  415. package/scripts/lane/lane-close.ts +86 -18
  416. package/scripts/lane/lane-core-wait-stats.ts +66 -0
  417. package/scripts/lane/lane-dispatch.ts +24 -3
  418. package/scripts/lane/lane-gap-stats.ts +156 -0
  419. package/scripts/lane/lane-handoff.ts +69 -1
  420. package/scripts/lane/lane-held-stats.ts +129 -0
  421. package/scripts/lane/lane-install.ts +4 -11
  422. package/scripts/lane/lane-launch-cli.ts +0 -9
  423. package/scripts/lane/lane-launch-main.ts +12 -0
  424. package/scripts/lane/lane-ledger-schema.ts +266 -0
  425. package/scripts/lane/lane-ledger.ts +92 -123
  426. package/scripts/lane/lane-limit-cli.ts +12 -1
  427. package/scripts/lane/lane-measure-cli.ts +57 -11
  428. package/scripts/lane/lane-open.ts +9 -1
  429. package/scripts/lane/lane-parked.ts +3 -3
  430. package/scripts/lane/lane-pause-cli.ts +130 -0
  431. package/scripts/lane/lane-pause.ts +158 -0
  432. package/scripts/lane/lane-process-table.ts +166 -0
  433. package/scripts/lane/lane-reap-settle.ts +124 -0
  434. package/scripts/lane/lane-reap.ts +50 -15
  435. package/scripts/lane/lane-registry.ts +24 -3
  436. package/scripts/lane/lane-residents.ts +162 -0
  437. package/scripts/lane/lane-restart.ts +22 -2
  438. package/scripts/lane/lane-round-two-stats.ts +49 -0
  439. package/scripts/lane/lane-sampler.ts +4 -0
  440. package/scripts/lane/lane-session-action.ts +19 -5
  441. package/scripts/lane/lane-session-broker.ts +102 -21
  442. package/scripts/lane/lane-snapshot-trace.ts +84 -0
  443. package/scripts/lane/lane-spans.ts +51 -0
  444. package/scripts/lane/lane-spent.ts +6 -3
  445. package/scripts/lane/lane-stage-stats.ts +7 -2
  446. package/scripts/lane/lane-state.ts +302 -0
  447. package/scripts/lane/lane-stats.ts +58 -4
  448. package/scripts/lane/lane-stop-stats.ts +113 -37
  449. package/scripts/lane/lane-test-related-stats.ts +127 -0
  450. package/scripts/lane/lane-transcript-calls.ts +145 -0
  451. package/scripts/lane/lane-transcript-stats.ts +168 -0
  452. package/scripts/lane/lane-vacant.ts +13 -3
  453. package/scripts/lane/lane-withdraw-cli.ts +5 -4
  454. package/scripts/lane/lane-withdraw.ts +50 -49
  455. package/scripts/lane/process-directories.ts +70 -0
  456. package/scripts/lane/process-lane-marks.ts +94 -0
  457. package/scripts/lib/atomic-write.ts +62 -0
  458. package/scripts/lib/buffered-process.ts +12 -5
  459. package/scripts/lib/cli-flags.ts +53 -0
  460. package/scripts/lib/figure-format.ts +63 -0
  461. package/scripts/lib/json-value.ts +9 -1
  462. package/scripts/lib/package-manifest.ts +35 -0
  463. package/scripts/lib/read-file.ts +3 -1
  464. package/scripts/lib/stamped-memo.ts +63 -0
  465. package/scripts/lib/stdout-on-stderr.ts +24 -0
  466. package/scripts/lib/timeouts.ts +9 -0
  467. package/scripts/lib/transcript-record.ts +91 -0
  468. package/scripts/lines/effective-limit.ts +1 -1
  469. package/scripts/lint/eslint-cache-dependencies.ts +145 -0
  470. package/scripts/lint/eslint-daemon.ts +265 -0
  471. package/scripts/lint/format.ts +11 -2
  472. package/scripts/lint/import-graph.ts +279 -0
  473. package/scripts/lint/lint-gate-scope.ts +102 -0
  474. package/scripts/lint/lint-parallel-main.ts +19 -0
  475. package/scripts/lint/lint-parallel.ts +62 -30
  476. package/scripts/lint/lint-related-scope.ts +30 -24
  477. package/scripts/lint/lint-related.ts +38 -6
  478. package/scripts/notify/confirmation-options.ts +1 -2
  479. package/scripts/notify/telegram-notify.ts +20 -20
  480. package/scripts/notify/telegram-test-logic.ts +0 -1
  481. package/scripts/notify/telegram-test-main.ts +8 -0
  482. package/scripts/notify/telegram-test.ts +2 -6
  483. package/scripts/observations/observation-ledger.ts +13 -0
  484. package/scripts/observations/observations-flush-landing.ts +5 -3
  485. package/scripts/observations/observations-flush.ts +6 -1
  486. package/scripts/overrides/overrides-check.ts +2 -5
  487. package/scripts/overrides/overrides-files.ts +2 -1
  488. package/scripts/overrides/overrides-logic.ts +3 -6
  489. package/scripts/package/verify-optional-eslint-install.ts +8 -6
  490. package/scripts/propagate/propagate-publish.ts +2 -7
  491. package/scripts/propagate/propagate-targets.ts +4 -12
  492. package/scripts/refactor/import-graph.ts +9 -7
  493. package/scripts/release/github-release-runs.ts +17 -6
  494. package/scripts/release/release-approval-prune.ts +18 -0
  495. package/scripts/release/release-history.ts +1 -3
  496. package/scripts/release/release-progress.ts +42 -22
  497. package/scripts/release/release-publish-run.ts +39 -0
  498. package/scripts/release/release-publish.ts +6 -6
  499. package/scripts/release/release-scope-cli.ts +0 -10
  500. package/scripts/release/release-scope-main.ts +12 -0
  501. package/scripts/repo/repo-setting.ts +3 -6
  502. package/scripts/repo/required-checks-logic.ts +6 -15
  503. package/scripts/report/report-format-reference.ts +2 -0
  504. package/scripts/report/report-labels.ts +155 -0
  505. package/scripts/report/report-lint-cli.ts +3 -0
  506. package/scripts/report/report-lint.ts +85 -110
  507. package/scripts/report/report-template-cli.ts +59 -0
  508. package/scripts/report/report-template.ts +112 -0
  509. package/scripts/review/acceptance-map.ts +1 -0
  510. package/scripts/review/removed-tests-check.ts +86 -0
  511. package/scripts/review/removed-tests.ts +149 -0
  512. package/scripts/review/review-brief-cli.ts +81 -15
  513. package/scripts/review/review-brief-main.ts +12 -0
  514. package/scripts/review/review-brief.ts +31 -3
  515. package/scripts/review/review-code-tree.ts +10 -6
  516. package/scripts/review/review-comment-round.ts +26 -8
  517. package/scripts/review/review-finding-ledger.ts +30 -15
  518. package/scripts/review/review-interaction.ts +94 -0
  519. package/scripts/review/review-readers-scan.ts +163 -0
  520. package/scripts/review/review-record-cli.ts +69 -30
  521. package/scripts/review/review-record-main.ts +12 -0
  522. package/scripts/review/review-round-one-blobs.ts +221 -0
  523. package/scripts/review/review-round2-cli.ts +49 -12
  524. package/scripts/review/review-round2.ts +80 -12
  525. package/scripts/review/review-stamps.ts +19 -1
  526. package/scripts/review/review-stop-log.ts +96 -0
  527. package/scripts/review/review-stops-cli.ts +85 -0
  528. package/scripts/review/review-tree.ts +6 -17
  529. package/scripts/review/review-untouched-readers.ts +146 -0
  530. package/scripts/review/test-titles.ts +118 -0
  531. package/scripts/rules/agent-model.ts +8 -0
  532. package/scripts/rules/bash-triggers.ts +46 -3
  533. package/scripts/rules/decision-oracle-batch.ts +9 -1
  534. package/scripts/rules/decision-oracle.ts +2 -2
  535. package/scripts/rules/delivered-rules.ts +80 -2
  536. package/scripts/rules/destructive-command.ts +8 -1
  537. package/scripts/rules/direct-filing.ts +10 -2
  538. package/scripts/rules/direct-issue-comment.ts +117 -0
  539. package/scripts/rules/direct-pr-create.ts +69 -3
  540. package/scripts/rules/early-heartbeat.ts +2 -1
  541. package/scripts/rules/file-body.ts +7 -0
  542. package/scripts/rules/filing-cap.ts +7 -0
  543. package/scripts/rules/git-argv.ts +72 -14
  544. package/scripts/rules/git-force.ts +12 -2
  545. package/scripts/rules/guard-remedy.ts +4 -0
  546. package/scripts/rules/implementation-cut-verdict.ts +1 -1
  547. package/scripts/rules/implementation-cut.ts +11 -3
  548. package/scripts/rules/index-guard.ts +8 -1
  549. package/scripts/rules/issue-comments.ts +9 -1
  550. package/scripts/rules/josh-git-bare.ts +7 -0
  551. package/scripts/rules/lane-background.ts +67 -25
  552. package/scripts/rules/lane-carry-conflict.ts +6 -0
  553. package/scripts/rules/lane-direct-tool.ts +74 -0
  554. package/scripts/rules/lane-interactive-ask.ts +9 -2
  555. package/scripts/rules/lane-park.ts +45 -23
  556. package/scripts/rules/lane-split-park.ts +10 -2
  557. package/scripts/rules/lane-switch-main.ts +7 -0
  558. package/scripts/rules/oracle-consulted.ts +10 -0
  559. package/scripts/rules/oracle-firing.ts +1 -0
  560. package/scripts/rules/permission-guards.ts +3 -0
  561. package/scripts/rules/piped-verification.ts +1 -1
  562. package/scripts/rules/poll-loop.ts +7 -0
  563. package/scripts/rules/pr-merge.ts +123 -0
  564. package/scripts/rules/protected-files.ts +32 -5
  565. package/scripts/rules/raw-field-body.ts +6 -0
  566. package/scripts/rules/rule-body-guard.ts +8 -0
  567. package/scripts/rules/rule-list.ts +9 -28
  568. package/scripts/rules/rule-value-cache.ts +4 -9
  569. package/scripts/rules/rule-value-cli.ts +51 -32
  570. package/scripts/rules/rule-value.ts +1 -1
  571. package/scripts/rules/shell-segments.ts +35 -0
  572. package/scripts/rules/stop-rule-rows.ts +64 -0
  573. package/scripts/rules/stop-rules.ts +3 -4
  574. package/scripts/rules/test-declared-commit.ts +11 -1
  575. package/scripts/rules/third-party-write.ts +7 -0
  576. package/scripts/rules/timed-rerun.ts +69 -0
  577. package/scripts/rules/worktree-guard.ts +13 -3
  578. package/scripts/run/board/run-board-app-name.ts +23 -0
  579. package/scripts/run/board/run-board-cli.ts +65 -32
  580. package/scripts/run/board/run-board-earlier.ts +94 -0
  581. package/scripts/run/board/run-board-ending-reason.ts +67 -0
  582. package/scripts/run/board/run-board-estimate-schedule.ts +103 -0
  583. package/scripts/run/board/run-board-estimate.ts +98 -0
  584. package/scripts/run/board/run-board-fit.ts +153 -36
  585. package/scripts/run/board/run-board-fold.ts +123 -0
  586. package/scripts/run/board/run-board-fresh.ts +2 -2
  587. package/scripts/run/board/run-board-gather-live.ts +29 -0
  588. package/scripts/run/board/run-board-gather-thread.ts +189 -0
  589. package/scripts/run/board/run-board-gather-worker.ts +29 -0
  590. package/scripts/run/board/run-board-gather.ts +187 -0
  591. package/scripts/run/board/run-board-github.ts +118 -38
  592. package/scripts/run/board/run-board-header.ts +82 -20
  593. package/scripts/run/board/run-board-keys.ts +58 -0
  594. package/scripts/run/board/run-board-kind.ts +20 -6
  595. package/scripts/run/board/run-board-labels.ts +116 -71
  596. package/scripts/run/board/run-board-lane-state.ts +109 -0
  597. package/scripts/run/board/run-board-lane-time.ts +122 -0
  598. package/scripts/run/board/run-board-layout.ts +239 -60
  599. package/scripts/run/board/run-board-length.ts +52 -0
  600. package/scripts/run/board/run-board-machine.ts +8 -4
  601. package/scripts/run/board/run-board-main.ts +12 -0
  602. package/scripts/run/board/run-board-notes.ts +52 -31
  603. package/scripts/run/board/run-board-now.ts +1 -1
  604. package/scripts/run/board/run-board-operation.ts +15 -33
  605. package/scripts/run/board/run-board-phase.ts +1 -1
  606. package/scripts/run/board/run-board-plan-shared.ts +115 -0
  607. package/scripts/run/board/run-board-plan.ts +55 -3
  608. package/scripts/run/board/run-board-planning.ts +45 -0
  609. package/scripts/run/board/run-board-priority.ts +44 -0
  610. package/scripts/run/board/run-board-process-groups.ts +195 -0
  611. package/scripts/run/board/run-board-read.ts +151 -27
  612. package/scripts/run/board/run-board-reason.ts +235 -51
  613. package/scripts/run/board/run-board-released.ts +35 -0
  614. package/scripts/run/board/run-board-render-checks.ts +39 -5
  615. package/scripts/run/board/run-board-render-condition.ts +96 -0
  616. package/scripts/run/board/run-board-render-drawn.ts +67 -0
  617. package/scripts/run/board/run-board-render-foot.ts +59 -0
  618. package/scripts/run/board/run-board-render-icon.ts +35 -0
  619. package/scripts/run/board/run-board-render-lanes.ts +145 -0
  620. package/scripts/run/board/run-board-render-lead.ts +80 -0
  621. package/scripts/run/board/run-board-render-legend.ts +117 -48
  622. package/scripts/run/board/run-board-render-notes.ts +156 -29
  623. package/scripts/run/board/run-board-render-processes.ts +196 -0
  624. package/scripts/run/board/run-board-render-section.ts +119 -0
  625. package/scripts/run/board/run-board-render-slot.ts +3 -36
  626. package/scripts/run/board/run-board-render-tail.ts +115 -48
  627. package/scripts/run/board/run-board-render-time.ts +56 -0
  628. package/scripts/run/board/run-board-render-title.ts +117 -24
  629. package/scripts/run/board/run-board-render-waits.ts +104 -20
  630. package/scripts/run/board/run-board-render.ts +207 -265
  631. package/scripts/run/board/run-board-roots.ts +54 -0
  632. package/scripts/run/board/run-board-row-yield.ts +9 -4
  633. package/scripts/run/board/run-board-setup.ts +1 -12
  634. package/scripts/run/board/run-board-snapshot.ts +111 -0
  635. package/scripts/run/board/run-board-spin.ts +2 -2
  636. package/scripts/run/board/run-board-state.ts +22 -33
  637. package/scripts/run/board/run-board-status.ts +147 -71
  638. package/scripts/run/board/run-board-thanks-read.ts +2 -2
  639. package/scripts/run/board/run-board-tick.ts +122 -107
  640. package/scripts/run/board/run-board-usage-board.ts +78 -0
  641. package/scripts/run/board/run-board-usage-lanes.ts +113 -0
  642. package/scripts/run/board/run-board-usage-listing.ts +93 -0
  643. package/scripts/run/board/run-board-usage-read.ts +120 -150
  644. package/scripts/run/board/run-board-usage-rusage.ts +19 -7
  645. package/scripts/run/board/run-board-usage-text.ts +139 -51
  646. package/scripts/run/board/run-board-usage-top.ts +102 -0
  647. package/scripts/run/board/run-board-usage.ts +89 -72
  648. package/scripts/run/board/run-board-usual.ts +20 -9
  649. package/scripts/run/carry/run-carry-args.ts +4 -7
  650. package/scripts/run/carry/run-carry-conversation.ts +1 -1
  651. package/scripts/run/carry/run-carry.ts +9 -4
  652. package/scripts/run/cut/run-cut-handoff.ts +2 -2
  653. package/scripts/run/event/run-event-cli.ts +1 -5
  654. package/scripts/run/event/run-event-filed.ts +12 -6
  655. package/scripts/run/event/run-event-follow.ts +2 -3
  656. package/scripts/run/event/run-event-render.ts +6 -10
  657. package/scripts/run/event/run-event-scope.ts +2 -2
  658. package/scripts/run/event/run-event-stream-emit.ts +82 -22
  659. package/scripts/run/event/run-event-stream.ts +34 -8
  660. package/scripts/run/hold/run-hold-adopt.ts +65 -0
  661. package/scripts/run/hold/run-hold-cli.ts +93 -22
  662. package/scripts/run/hold/run-hold-main.ts +12 -0
  663. package/scripts/run/hold/run-hold-member.ts +37 -0
  664. package/scripts/run/hold/run-stop-notify.ts +183 -0
  665. package/scripts/run/merge/run-merge-auth.ts +31 -0
  666. package/scripts/run/merge/run-merge-cli.ts +62 -48
  667. package/scripts/run/merge/run-merge-close.ts +74 -0
  668. package/scripts/run/merge/run-merge-collect.ts +6 -13
  669. package/scripts/run/merge/run-merge-driver.ts +71 -0
  670. package/scripts/run/merge/run-merge-main.ts +12 -0
  671. package/scripts/run/merge/run-merge-outcome.ts +23 -0
  672. package/scripts/run/merge/run-merge-restart.ts +39 -0
  673. package/scripts/run/merge/run-merge-ship.ts +20 -4
  674. package/scripts/run/merge/run-merge-signals.ts +33 -9
  675. package/scripts/run/merge/run-merge-steps.ts +120 -85
  676. package/scripts/run/merge/run-merge.ts +38 -37
  677. package/scripts/run/park/run-park-cli.ts +91 -0
  678. package/scripts/run/park/run-park.ts +88 -0
  679. package/scripts/run/park/run-stalled.ts +68 -0
  680. package/scripts/run/pause/run-pause-cli.ts +73 -0
  681. package/scripts/run/pause/run-pause.ts +251 -0
  682. package/scripts/run/progress/run-progress-cli.ts +4 -12
  683. package/scripts/run/progress/run-progress-clock.ts +1 -1
  684. package/scripts/run/progress/run-progress-config.ts +6 -14
  685. package/scripts/run/progress/run-progress-main.ts +12 -0
  686. package/scripts/run/progress/run-progress.ts +1 -4
  687. package/scripts/run/review/run-review.ts +2 -1
  688. package/scripts/run/run-ending.ts +1 -0
  689. package/scripts/run/run-invocation.ts +5 -6
  690. package/scripts/run/run-liveness-cli.ts +6 -8
  691. package/scripts/run/run-liveness.ts +60 -29
  692. package/scripts/run/run-next.ts +1 -1
  693. package/scripts/run/run-parent-cut-hook.ts +2 -2
  694. package/scripts/run/run-preflight.ts +18 -3
  695. package/scripts/run/run-prep-cli.ts +1 -10
  696. package/scripts/run/run-prep-locate.ts +7 -50
  697. package/scripts/run/run-prep-main.ts +12 -0
  698. package/scripts/run/run-prep.ts +6 -0
  699. package/scripts/run/run-report-cli.ts +101 -13
  700. package/scripts/run/run-report-handoff.ts +114 -0
  701. package/scripts/run/run-step.ts +1 -1
  702. package/scripts/run/run-stranded-detect.ts +13 -0
  703. package/scripts/run/run-watcher-guard-cli.ts +1 -1
  704. package/scripts/run/run-watcher-guard.ts +1 -1
  705. package/scripts/run/ship/run-ship-args.ts +121 -0
  706. package/scripts/run/ship/run-ship-body-draft.ts +110 -0
  707. package/scripts/run/ship/run-ship-cli.ts +63 -140
  708. package/scripts/run/ship/run-ship-detach.ts +19 -8
  709. package/scripts/run/ship/run-ship-infra-retry.ts +59 -0
  710. package/scripts/run/ship/run-ship-next.ts +18 -2
  711. package/scripts/run/ship/run-ship-overlap.ts +42 -5
  712. package/scripts/run/ship/run-ship-place.ts +96 -0
  713. package/scripts/run/ship/run-ship-pre-detach-timed.ts +43 -0
  714. package/scripts/run/ship/run-ship-pre-detach.ts +81 -24
  715. package/scripts/run/ship/run-ship-preflight.ts +137 -32
  716. package/scripts/run/ship/run-ship-probe.ts +11 -3
  717. package/scripts/run/ship/run-ship-relaunch-cap.ts +70 -0
  718. package/scripts/run/ship/run-ship-removed-rows.ts +61 -0
  719. package/scripts/run/ship/run-ship-return.ts +107 -23
  720. package/scripts/run/ship/run-ship-review-steps.ts +105 -151
  721. package/scripts/run/ship/run-ship-review.ts +73 -6
  722. package/scripts/run/ship/run-ship-reviewer.ts +207 -0
  723. package/scripts/run/ship/run-ship-stage.ts +55 -6
  724. package/scripts/run/ship/run-ship-steps.ts +46 -15
  725. package/scripts/run/ship/run-ship-stop-cause.ts +135 -0
  726. package/scripts/run/ship/run-ship-stop-text.ts +11 -6
  727. package/scripts/run/ship/run-ship-sync.ts +43 -6
  728. package/scripts/run/ship/run-ship.ts +30 -2
  729. package/scripts/run/tidy/run-tidy-cli.ts +0 -4
  730. package/scripts/run/tidy/run-tidy-lanes.ts +3 -0
  731. package/scripts/run/tidy/run-tidy-main.ts +8 -0
  732. package/scripts/run/wake/run-wake-cli.ts +119 -100
  733. package/scripts/run/wake/run-wake-code.ts +83 -0
  734. package/scripts/run/wake/run-wake-driver.ts +19 -8
  735. package/scripts/run/wake/run-wake-loop.ts +34 -3
  736. package/scripts/run/wake/run-wake-main.ts +13 -0
  737. package/scripts/run/wake/run-wake-ports.ts +90 -0
  738. package/scripts/run/wake/run-wake-takeover.ts +66 -0
  739. package/scripts/run/wake/run-wake.ts +2 -1
  740. package/scripts/safe-chain/pack-hook.ts +2 -2
  741. package/scripts/safe-chain/preinstall-command.ts +2 -1
  742. package/scripts/safe-chain/project-config.ts +3 -9
  743. package/scripts/security/security-audit-main.ts +8 -0
  744. package/scripts/security/security-audit-provision-logic.ts +0 -11
  745. package/scripts/security/security-audit-provision-main.ts +12 -0
  746. package/scripts/security/security-audit-provision.ts +11 -26
  747. package/scripts/security/security-audit.ts +6 -7
  748. package/scripts/self-sync-guard/self-sync-guard-logic.ts +6 -13
  749. package/scripts/split/split-assess-cli.ts +2 -2
  750. package/scripts/split/split-assess.ts +15 -0
  751. package/scripts/split/split-measure.ts +65 -0
  752. package/scripts/sync/claude-settings-merge.ts +8 -15
  753. package/scripts/sync/directory-copy-guard.ts +4 -9
  754. package/scripts/sync/file-content.ts +78 -8
  755. package/scripts/sync/sync-ai-files.ts +3 -5
  756. package/scripts/sync/sync-configs.ts +11 -23
  757. package/scripts/sync/sync-hook-safety.ts +4 -10
  758. package/scripts/sync/sync-main.ts +11 -0
  759. package/scripts/sync/sync.ts +25 -37
  760. package/scripts/test/test-declared-changed.ts +2 -2
  761. package/scripts/test/test-declared.ts +1 -1
  762. package/scripts/test/test-e2e-guard.ts +25 -1
  763. package/scripts/test/test-e2e-stamp.ts +38 -0
  764. package/scripts/test/test-pinned-logic.ts +145 -0
  765. package/scripts/test/test-pinned-main.ts +78 -0
  766. package/scripts/test/test-pinned.ts +100 -0
  767. package/scripts/test/test-read-map.ts +264 -0
  768. package/scripts/test/test-read-recording.ts +91 -0
  769. package/scripts/test/test-read-trace.ts +148 -0
  770. package/scripts/test/test-red-main.ts +12 -0
  771. package/scripts/test/test-red.ts +12 -30
  772. package/scripts/test/test-related-main.ts +18 -0
  773. package/scripts/test/test-related-record.ts +119 -0
  774. package/scripts/test/test-related-scope.ts +229 -43
  775. package/scripts/test/test-related.ts +300 -22
  776. package/scripts/test/test-unit-guard-main.ts +15 -0
  777. package/scripts/test/test-unit-guard.ts +42 -24
  778. package/scripts/test/unit-count-file.ts +37 -0
  779. package/scripts/test/unit-run-marker.ts +162 -0
  780. package/scripts/test/unit-setup-files.ts +51 -0
  781. package/scripts/test/unit-worker-share.ts +61 -149
  782. package/scripts/test/whole-suite-files.ts +63 -0
  783. package/scripts/time-runtime/time-background.ts +20 -2
  784. package/scripts/time-runtime/time-bundles.ts +4 -3
  785. package/scripts/time-runtime/time-density-hook.ts +8 -6
  786. package/scripts/time-runtime/time-followup-stage.ts +1 -3
  787. package/scripts/time-runtime/time-format.ts +5 -28
  788. package/scripts/time-runtime/time-markers.ts +10 -1
  789. package/scripts/time-runtime/time-shell.ts +97 -10
  790. package/scripts/time-runtime/time-transcript-line.ts +49 -62
  791. package/scripts/uninstall/uninstall.ts +1 -1
  792. package/scripts/version/bump-version-main.ts +12 -0
  793. package/scripts/version/bump-version.ts +25 -25
  794. package/scripts/version/effective-upstream.ts +6 -12
  795. package/scripts/version/latest-corepack.ts +17 -32
  796. package/scripts/version/latest-if-required-cli.ts +93 -0
  797. package/scripts/version/latest-lane-guard-main.ts +8 -0
  798. package/scripts/version/latest-lane-guard.ts +0 -4
  799. package/scripts/version/latest-scope-cli.ts +0 -9
  800. package/scripts/version/latest-scope-main.ts +12 -0
  801. package/scripts/version/latest-update.ts +5 -5
  802. package/scripts/version/npm-registry.ts +44 -6
  803. package/scripts/version/publishable-range-check.ts +5 -16
  804. package/scripts/version/release-age.ts +1 -1
  805. package/scripts/version/release-hold.ts +1 -1
  806. package/scripts/version/release-window.ts +38 -0
  807. package/scripts/version/running-binary.ts +1 -1
  808. package/scripts/version/safe-chain-version-update.ts +3 -8
  809. package/scripts/version/version-targets.ts +6 -28
  810. package/templates/dependabot.yml +29 -0
  811. package/templates/gitignore +4 -1
  812. package/templates/pnpm-workspace.basic.yaml +1 -1
  813. package/templates/sonar-project.properties +3 -2
  814. package/templates/workflows/ci.yml +12 -4
  815. package/templates/workflows/github-release.yml +4 -0
  816. package/tsconfig.sonar.json +1 -1
  817. package/.ncurc.json +0 -3
  818. package/dist/hooks/batch-guard.js +0 -29
  819. package/dist/hooks/chunk-4KKD2UTK.js +0 -66
  820. package/dist/hooks/chunk-6TS2JD6D.js +0 -237
  821. package/dist/hooks/chunk-7DSBJVFH.js +0 -50
  822. package/dist/hooks/chunk-A65Y4YOR.js +0 -79
  823. package/dist/hooks/chunk-CDY4NFQG.js +0 -15
  824. package/dist/hooks/chunk-EFXE6C37.js +0 -81
  825. package/dist/hooks/chunk-GP4IEC4O.js +0 -20
  826. package/dist/hooks/chunk-JP45SOCJ.js +0 -56
  827. package/dist/hooks/chunk-LAOV7NLM.js +0 -45
  828. package/dist/hooks/chunk-M4HGZV7U.js +0 -83
  829. package/dist/hooks/chunk-PF2NZL2A.js +0 -131
  830. package/dist/hooks/chunk-PTICX4OL.js +0 -358
  831. package/dist/hooks/chunk-RT27QRJW.js +0 -6247
  832. package/dist/hooks/chunk-SYOTDYCI.js +0 -3533
  833. package/dist/hooks/chunk-UPUZF3AN.js +0 -279
  834. package/dist/hooks/chunk-WK6SMBIC.js +0 -3180
  835. package/dist/hooks/duplicate-read-guard.js +0 -30
  836. package/dist/hooks/investigation-guard.js +0 -29
  837. package/scripts/backlog/backlog-stalled-cli.ts +0 -30
  838. package/scripts/cost-runtime/cost-format.ts +0 -29
  839. package/scripts/init/basic-path-migration.ts +0 -24
  840. package/scripts/issue/issue-backlinks-cli.ts +0 -93
  841. package/scripts/josh/josh-commands-guard.ts +0 -38
  842. package/scripts/josh/josh-usage-automation.ts +0 -121
  843. package/scripts/josh/josh-usage-backlog.ts +0 -180
  844. package/scripts/josh/josh-usage-developer.ts +0 -230
  845. package/scripts/josh/josh-usage-hooks.ts +0 -38
  846. package/scripts/josh/josh-usage-issue.ts +0 -205
  847. package/scripts/josh/josh-usage-review.ts +0 -101
  848. package/scripts/josh/josh-usage-run.ts +0 -252
  849. package/scripts/josh/josh-usage-session.ts +0 -238
  850. package/scripts/josh/josh-usage-workflow.ts +0 -212
  851. package/scripts/lint/cross-file-recheck.ts +0 -155
  852. package/scripts/registry-migration/migrate-logic.ts +0 -237
  853. package/scripts/registry-migration/migrate.ts +0 -292
  854. package/scripts/registry-migration/user-npmrc.ts +0 -15
  855. package/scripts/rules/rule-guard.ts +0 -23
  856. package/scripts/rules/rule-registry-rows.ts +0 -292
  857. package/scripts/rules/rule-registry.ts +0 -112
  858. package/scripts/run/run-stranded-cli.ts +0 -27
@@ -0,0 +1,70 @@
1
+ import { spawnSync } from 'node:child_process'
2
+ import path from 'node:path'
3
+ import { PROBE_TIMEOUT_MS } from '#scripts/lib/timeouts'
4
+ import { lane_paths } from './lane-paths'
5
+
6
+ // Each process's working directory, read with `lsof` — the one place its output is parsed.
7
+ //
8
+ // **A process belongs to a lane by its working directory first, its ancestry only after.** A process
9
+ // detached from a lane (`josh ship --detach`, a diagnostic started under `script`) is re-parented to
10
+ // pid 1, so no parent chain reaches it, while its working directory still sits under `.kit-lanes/<N>`.
11
+ // `run:board` draws such a process as a lane's or a leftover, and `lane:close` ends it
12
+ // (joshuafolkken/kit#4304); the board falls back to the ancestry where the directory names no lane
13
+ // (`run-board-usage-lanes.ts`).
14
+ // **macOS alone**, as the board reads it: elsewhere nothing is listed.
15
+
16
+ const LSOF_COMMAND = 'lsof'
17
+ // `-a` joins the conditions: the `cwd` descriptor only, in `-F` fields. The board appends `-p <pids>`.
18
+ const CWD_ARGUMENTS = ['-a', '-d', 'cwd', '-Fn']
19
+ // `lsof -F`'s field lines: `p<pid>` opens a process, `n<path>` names its directory.
20
+ const LSOF_PROCESS = /^(?=p)/mu
21
+ const LSOF_NAME = 'n'
22
+ const LISTING_PLATFORMS: ReadonlySet<NodeJS.Platform> = new Set(['darwin'])
23
+
24
+ function lsof_block(block: string): [number, string] | undefined {
25
+ const [process_line = '', ...rest] = block.trim().split('\n')
26
+ const name = rest.find((line) => line.startsWith(LSOF_NAME))
27
+
28
+ return name === undefined ? undefined : [Number(process_line.slice(1)), name.slice(1)]
29
+ }
30
+
31
+ /** Each process's working directory from `lsof -F`'s output. */
32
+ function parse(output: string): Map<number, string> {
33
+ const blocks = output.split(LSOF_PROCESS).map((block) => lsof_block(block))
34
+
35
+ return new Map(blocks.filter((block) => block !== undefined))
36
+ }
37
+
38
+ /**
39
+ * Every process's working directory, `undefined` where `lsof` could not be run or timed out — never
40
+ * read as "nothing there". `lsof` exits non-zero when one process cannot be read and still lists the
41
+ * rest, so its output is read whatever the exit status.
42
+ */
43
+ function list_all(platform: NodeJS.Platform = process.platform): Map<number, string> | undefined {
44
+ if (!LISTING_PLATFORMS.has(platform)) return new Map()
45
+
46
+ const result = spawnSync(LSOF_COMMAND, CWD_ARGUMENTS, {
47
+ encoding: 'utf8',
48
+ timeout: PROBE_TIMEOUT_MS,
49
+ stdio: ['ignore', 'pipe', 'ignore'],
50
+ })
51
+
52
+ return result.error === undefined ? parse(result.stdout) : undefined
53
+ }
54
+
55
+ /**
56
+ * The lane of `root` a directory sits under — itself or a directory above it, the outermost first.
57
+ * The one lane-membership reading: the board draws a leftover by it, and the close ends by it
58
+ * (joshuafolkken/kit#4300).
59
+ */
60
+ function lane_of(directory: string, root: string): string | undefined {
61
+ const parts = directory.split(path.sep)
62
+ const ancestors = parts.map((_, index) => parts.slice(0, index + 1).join(path.sep)).slice(1)
63
+ const environment = { [lane_paths.LANE_ROOT_KEY]: root }
64
+
65
+ return ancestors.map((ancestor) => lane_paths.lane_issue_of(ancestor, environment)).find(Boolean)
66
+ }
67
+
68
+ const process_directories = { CWD_ARGUMENTS, lane_of, list_all, parse }
69
+
70
+ export { process_directories }
@@ -0,0 +1,94 @@
1
+ import { spawnSync } from 'node:child_process'
2
+ import { PROBE_TIMEOUT_MS } from '#scripts/lib/timeouts'
3
+ import { lane_child_marker } from './lane-child-marker'
4
+
5
+ // Each process's lane mark — the `JOSH_LANE_CHILD` it inherited — read from `ps -E`
6
+ // (joshuafolkken/kit#4315).
7
+ //
8
+ // **A process belongs to a lane by its mark wherever it runs.** A lane child that measures something
9
+ // from the main checkout or `/tmp` leaves processes whose working directory is not under the lane, and
10
+ // one started under `script` or a new session has left the child's tree and group for pid 1. The
11
+ // environment survives all of that, and `lane:dispatch` puts the issue number in it
12
+ // (`lane-child-marker.ts`), so the mark names the lane a process was started from.
13
+ //
14
+ // **The mark is read from the environment, never from the arguments.** `ps -E` appends the environment
15
+ // to the command line, so the plain command line is read too and only what follows it is searched: a
16
+ // `grep JOSH_LANE_CHILD=42` carries the text without the mark.
17
+ //
18
+ // **An application bundle is never marked.** A lane that opened Docker Desktop passed its environment
19
+ // to an application the whole machine uses; it is a person's, not the lane's.
20
+ //
21
+ // **macOS alone**, as `process-directories.ts` reads it: elsewhere nothing is listed.
22
+
23
+ const PS_COMMAND = '/bin/ps'
24
+ const LISTING_ARGUMENTS = ['-A', '-ww', '-o', 'pid=,command=']
25
+ const ENVIRONMENT_FLAG = '-E'
26
+ // `ps -E` over every process runs to hundreds of kilobytes; the default 1 MiB would cut it short.
27
+ const LISTING_BUFFER_BYTES = 67_108_864
28
+ const PID_LINE = /^\s*(?<pid>\d+) (?<command>.*)$/u
29
+ const APPLICATION_BUNDLE = '.app/Contents/'
30
+ const LISTING_PLATFORMS: ReadonlySet<NodeJS.Platform> = new Set(['darwin'])
31
+ const MARK = new RegExp(String.raw`(?:^|\s)${lane_child_marker.KEY}=(?<issue>\d+)(?=\s|$)`, 'u')
32
+
33
+ function command_lines(printed: string): Map<number, string> {
34
+ const groups = printed.split('\n').map((line) => PID_LINE.exec(line)?.groups)
35
+
36
+ return new Map(
37
+ groups
38
+ .filter((group) => group !== undefined)
39
+ .map((group) => [Number(group['pid']), group['command'] ?? '']),
40
+ )
41
+ }
42
+
43
+ // What `ps -E` printed after the plain command line; `undefined` for an application bundle and for a
44
+ // process the two listings disagree on (it ended or exec'd between them).
45
+ function environment_of(command: string | undefined, with_environment: string): string | undefined {
46
+ if (command === undefined || command.includes(APPLICATION_BUNDLE)) return undefined
47
+
48
+ return with_environment.startsWith(command) ? with_environment.slice(command.length) : undefined
49
+ }
50
+
51
+ function mark_of(command: string | undefined, with_environment: string): string | undefined {
52
+ const environment = environment_of(command, with_environment)
53
+
54
+ return environment === undefined ? undefined : MARK.exec(environment)?.groups?.['issue']
55
+ }
56
+
57
+ /** Each marked process's issue, from `ps`'s plain and `-E` listings. */
58
+ function parse(plain: string, with_environment: string): Map<number, string> {
59
+ const commands = command_lines(plain)
60
+ const marks = [...command_lines(with_environment)].map(
61
+ ([pid, line]) => [pid, mark_of(commands.get(pid), line)] as const,
62
+ )
63
+
64
+ return new Map(marks.filter((pair): pair is [number, string] => pair[1] !== undefined))
65
+ }
66
+
67
+ function listing(arguments_: ReadonlyArray<string>): string | undefined {
68
+ const result = spawnSync(PS_COMMAND, arguments_, {
69
+ encoding: 'utf8',
70
+ maxBuffer: LISTING_BUFFER_BYTES,
71
+ timeout: PROBE_TIMEOUT_MS,
72
+ stdio: ['ignore', 'pipe', 'ignore'],
73
+ })
74
+
75
+ return result.error === undefined ? result.stdout : undefined
76
+ }
77
+
78
+ /**
79
+ * Every marked process's issue, `undefined` where `ps` could not be run or timed out — never read as
80
+ * "nothing marked".
81
+ */
82
+ function list_all(platform: NodeJS.Platform = process.platform): Map<number, string> | undefined {
83
+ if (!LISTING_PLATFORMS.has(platform)) return new Map()
84
+ const plain = listing(LISTING_ARGUMENTS)
85
+ const with_environment = listing([ENVIRONMENT_FLAG, ...LISTING_ARGUMENTS])
86
+
87
+ if (plain === undefined || with_environment === undefined) return undefined
88
+
89
+ return parse(plain, with_environment)
90
+ }
91
+
92
+ const process_lane_marks = { list_all, parse }
93
+
94
+ export { process_lane_marks }
@@ -0,0 +1,62 @@
1
+ import { randomUUID } from 'node:crypto'
2
+ import { chmodSync, mkdirSync, renameSync, rmSync, writeFileSync } from 'node:fs'
3
+ import path from 'node:path'
4
+
5
+ // Replacing a file so a concurrent reader sees the old content or the new, never half of either.
6
+ //
7
+ // The content is written to a staging file and renamed over the target; `rename` swaps the path
8
+ // itself, so a reader that opened the old file keeps reading it. **The staging name is unique per
9
+ // write** — process id and a random UUID — because two writers sharing one name interleave their bytes
10
+ // into the same staging file and both rename the mix into place. Create-exclusively refuses a name
11
+ // someone else already holds rather than writing through it, and the `finally` removes the staging
12
+ // file on every failing path. The `.tmp` ending keeps it out of a directory scan that matches the
13
+ // target's own extension.
14
+
15
+ const STAGING_EXTENSION = '.tmp'
16
+ const CREATE_EXCLUSIVE_FLAG = 'wx'
17
+
18
+ interface AtomicWriteOptions {
19
+ // Given to the create, so a private file is never readable at another mode in between, and
20
+ // applied again with `chmod`, so the umask cannot narrow it.
21
+ readonly mode?: number
22
+ // Where the staging file is written; the target's directory by default. It must sit on the
23
+ // target's filesystem for the rename to stay atomic.
24
+ readonly staging_directory?: string
25
+ }
26
+
27
+ function staging_path(target: string, staging_directory: string): string {
28
+ const name = `${path.basename(target)}.${String(process.pid)}.${randomUUID()}${STAGING_EXTENSION}`
29
+
30
+ return path.join(staging_directory, name)
31
+ }
32
+
33
+ function write_staged(staging: string, content: string | Uint8Array, mode?: number): void {
34
+ writeFileSync(staging, content, {
35
+ flag: CREATE_EXCLUSIVE_FLAG,
36
+ ...(mode !== undefined && { mode }),
37
+ })
38
+ if (mode !== undefined) chmodSync(staging, mode)
39
+ }
40
+
41
+ function replace_file(
42
+ target: string,
43
+ content: string | Uint8Array,
44
+ options: AtomicWriteOptions = {},
45
+ ): void {
46
+ const directory = options.staging_directory ?? path.dirname(target)
47
+ const staging = staging_path(target, directory)
48
+
49
+ mkdirSync(directory, { recursive: true })
50
+
51
+ try {
52
+ write_staged(staging, content, options.mode)
53
+ renameSync(staging, target)
54
+ } finally {
55
+ rmSync(staging, { force: true })
56
+ }
57
+ }
58
+
59
+ const atomic_write = { replace_file }
60
+
61
+ export { atomic_write }
62
+ export type { AtomicWriteOptions }
@@ -69,6 +69,16 @@ function collect_output(all: string, reason: ReadonlyArray<string>): string {
69
69
  return [all, ...reason].filter((part) => part !== '').join('\n')
70
70
  }
71
71
 
72
+ // A buffered child writes to a pipe, so it is told to keep its colors unless the caller opted out.
73
+ // Exported for the eslint daemon route (`eslint-daemon.ts`), which buffers the same way.
74
+ function child_environment(): NodeJS.ProcessEnv {
75
+ const environment = { ...process.env }
76
+ if (environment['NO_COLOR'] === undefined) environment['FORCE_COLOR'] = FORCE_COLOR
77
+ else delete environment['FORCE_COLOR']
78
+
79
+ return environment
80
+ }
81
+
72
82
  async function run_buffered_process(
73
83
  command_args: ReadonlyArray<string>,
74
84
  options: BufferedProcessOptions = {},
@@ -76,14 +86,11 @@ async function run_buffered_process(
76
86
  // `performance.now()` rather than `Date.now()`: it is monotonic, so a system clock adjusted
77
87
  // mid-check cannot produce a negative or wildly inflated duration.
78
88
  const started_at = performance.now()
79
- const environment = { ...process.env }
80
- if (environment['NO_COLOR'] === undefined) environment['FORCE_COLOR'] = FORCE_COLOR
81
- else delete environment['FORCE_COLOR']
82
89
  // `cwd` is spread in rather than assigned: `exactOptionalPropertyTypes` refuses an explicit
83
90
  // `undefined` for an optional `string`, and passing one anyway breaks execa's overload
84
91
  // resolution — which silently widens `result.all` back to `string | undefined`.
85
92
  const result = await execa(PNPM, [...command_args], {
86
- env: environment,
93
+ env: child_environment(),
87
94
  extendEnv: false,
88
95
  all: true,
89
96
  reject: false,
@@ -104,7 +111,7 @@ function is_process_failed(result: Pick<BufferedProcessResult, 'exit_code'>): bo
104
111
  return result.exit_code !== 0
105
112
  }
106
113
 
107
- const buffered_process = { is_process_failed, run_buffered_process }
114
+ const buffered_process = { child_environment, is_process_failed, run_buffered_process }
108
115
 
109
116
  export type { BufferedProcessResult }
110
117
  export { buffered_process, FAIL_EXIT_CODE }
@@ -152,7 +152,59 @@ function attach_values(
152
152
  return attached
153
153
  }
154
154
 
155
+ // Digits and nothing else. `Number('')`, `Number(' ')` and `Number('0x10')` are all safe integers, so a
156
+ // check that only asked `Number.isSafeInteger` would read an unset shell variable — `--max
157
+ // "$max_issues"` — as zero. The magnitude check is separate because the pattern bounds nothing: a
158
+ // number past the safe range would be read as a different number.
159
+ const COUNT_PATTERN = /^\d+$/u
160
+ // Whole and positive: `0`, a sign, a decimal point and anything not a digit are refused.
161
+ const POSITIVE_PATTERN = /^[1-9]\d*$/u
162
+
163
+ // The value a positive-integer setting answers, or why it could not be read. A problem rather than a
164
+ // throw: the caller decides whether a bad setting ends the command or is reported and worked around.
165
+ type PositiveSetting = { kind: 'limit'; limit: number } | { kind: 'problem'; problem: string }
166
+
167
+ function to_integer(raw: string | undefined, pattern: RegExp): number | undefined {
168
+ if (raw === undefined || !pattern.test(raw)) return undefined
169
+
170
+ const parsed = Number(raw)
171
+
172
+ return Number.isSafeInteger(parsed) ? parsed : undefined
173
+ }
174
+
175
+ // A count flag's value — zero or more — or `undefined` when it is absent or not a count.
176
+ function to_count(raw: string | undefined): number | undefined {
177
+ return to_integer(raw, COUNT_PATTERN)
178
+ }
179
+
180
+ // A value that must be one or more, or `undefined` when it is absent or not.
181
+ function to_positive(raw: string | undefined): number | undefined {
182
+ return to_integer(raw, POSITIVE_PATTERN)
183
+ }
184
+
185
+ // A positive-integer setting read from the environment or an argument. Blank is unset, not invalid — an
186
+ // `.env` line left as `KEY=` is a setting nobody configured — and answers `fallback`. Anything else that
187
+ // is not a positive integer is a problem naming `name`, never a silent fall back to the default: a typo
188
+ // that quietly became the default is a number nobody chose.
189
+ function read_positive_setting(
190
+ raw: string | undefined,
191
+ name: string,
192
+ fallback: number,
193
+ ): PositiveSetting {
194
+ const trimmed = raw?.trim() ?? ''
195
+
196
+ if (trimmed === '') return { kind: 'limit', limit: fallback }
197
+
198
+ const limit = to_positive(trimmed)
199
+ if (limit !== undefined) return { kind: 'limit', limit }
200
+
201
+ return { kind: 'problem', problem: `${name} must be a positive integer, not "${trimmed}"` }
202
+ }
203
+
155
204
  const cli_flags = {
205
+ to_count,
206
+ to_positive,
207
+ read_positive_setting,
156
208
  attach_values,
157
209
  usage_line,
158
210
  refuse_unknown_flags,
@@ -167,3 +219,4 @@ const cli_flags = {
167
219
  }
168
220
 
169
221
  export { cli_flags }
222
+ export type { PositiveSetting }
@@ -0,0 +1,63 @@
1
+ import { MS_PER_MINUTE } from '#scripts/lib/timeouts'
2
+
3
+ // The figures the reports print — a dollar amount, a token count, a percentage share, a duration in
4
+ // minutes and a local wall clock — and the precision each uses. The cost reports, `josh time`'s
5
+ // reports, `run:board` and the run event pane all render these, so each is written once here.
6
+
7
+ const USD_DECIMALS = 4
8
+ const PERCENT_SCALE = 100
9
+ const PERCENT_DECIMALS = 1
10
+ const MINUTE_DECIMALS = 1
11
+ const CLOCK_WIDTH = 2
12
+ const CLOCK_PAD = '0'
13
+
14
+ // The caller names the decimals where its figure rounds to another place — a run total to the cent.
15
+ function format_usd(usd: number, decimals: number = USD_DECIMALS): string {
16
+ return `$${usd.toFixed(decimals)}`
17
+ }
18
+
19
+ function format_tokens(count: number): string {
20
+ return count.toLocaleString('en-US')
21
+ }
22
+
23
+ function format_share(part: number, whole: number): string {
24
+ if (whole === 0) return 'n/a'
25
+
26
+ return `${((part / whole) * PERCENT_SCALE).toFixed(PERCENT_DECIMALS)}%`
27
+ }
28
+
29
+ function format_minutes(duration_ms: number): string {
30
+ return `${(duration_ms / MS_PER_MINUTE).toFixed(MINUTE_DECIMALS)} min`
31
+ }
32
+
33
+ function two_digits(value: number): string {
34
+ return String(value).padStart(CLOCK_WIDTH, CLOCK_PAD)
35
+ }
36
+
37
+ // The local wall-clock `HH:MM:SS` of a moment.
38
+ function clock_of(ms: number): string {
39
+ const date = new Date(ms)
40
+
41
+ return [date.getHours(), date.getMinutes(), date.getSeconds()]
42
+ .map((value) => two_digits(value))
43
+ .join(':')
44
+ }
45
+
46
+ // The local wall-clock `HH:MM` of a moment, for one a person reads to the minute.
47
+ function minute_of(ms: number): string {
48
+ const date = new Date(ms)
49
+
50
+ return [date.getHours(), date.getMinutes()].map((value) => two_digits(value)).join(':')
51
+ }
52
+
53
+ const figure_format = {
54
+ format_usd,
55
+ format_tokens,
56
+ format_share,
57
+ format_minutes,
58
+ two_digits,
59
+ clock_of,
60
+ minute_of,
61
+ }
62
+
63
+ export { figure_format }
@@ -28,12 +28,20 @@ function parse_with<T>(text: string, schema: z.ZodType<T>): T | undefined {
28
28
  return parsed.success ? parsed.data : undefined
29
29
  }
30
30
 
31
+ // The read a listing wants: text that is not JSON and JSON that is not an array both answer
32
+ // `undefined`, so a caller can keep "unreadable" apart from an empty listing.
33
+ function parse_array(text: string): Array<unknown> | undefined {
34
+ const value = parse_or_undefined(text)
35
+
36
+ return Array.isArray(value) ? value : undefined
37
+ }
38
+
31
39
  // A plain object, as opposed to an array or a primitive. `typeof null` is `'object'`, and an array
32
40
  // answers `'object'` too, so both have to be excluded by hand before a key lookup means anything.
33
41
  function is_record(value: unknown): value is Record<string, unknown> {
34
42
  return typeof value === 'object' && value !== null && !Array.isArray(value)
35
43
  }
36
44
 
37
- const json_value = { parse_or_undefined, parse_with, is_record }
45
+ const json_value = { parse_or_undefined, parse_with, parse_array, is_record }
38
46
 
39
47
  export { json_value }
@@ -0,0 +1,35 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import path from 'node:path'
3
+ import type { z } from 'zod'
4
+ import { json_value } from './json-value'
5
+ import { file_reader } from './read-file'
6
+
7
+ // The one place a `package.json` is named and read. Readers across `scripts/` had each spelled the
8
+ // file name and written their own read-then-parse; they now ask here, and choose only how a manifest
9
+ // that cannot be read answers.
10
+ const PACKAGE_JSON = 'package.json'
11
+
12
+ function manifest_path(directory: string): string {
13
+ return path.join(directory, PACKAGE_JSON)
14
+ }
15
+
16
+ // For a manifest that must exist: a missing file, text that is not JSON and a shape the schema
17
+ // rejects all throw, so the defect surfaces where it was met.
18
+ function read_manifest<T>(directory: string, schema: z.ZodType<T>): T {
19
+ const text = readFileSync(manifest_path(directory), 'utf8')
20
+
21
+ return schema.parse(JSON.parse(text))
22
+ }
23
+
24
+ // For a manifest that may be absent or broken without that being this reader's failure: every one of
25
+ // those answers `undefined`.
26
+ function read_manifest_if_valid<T>(directory: string, schema: z.ZodType<T>): T | undefined {
27
+ const text = file_reader.read_if_readable(manifest_path(directory))
28
+ if (text === undefined) return undefined
29
+
30
+ return json_value.parse_with(text, schema)
31
+ }
32
+
33
+ const package_manifest = { manifest_path, read_manifest, read_manifest_if_valid }
34
+
35
+ export { PACKAGE_JSON, package_manifest }
@@ -2,6 +2,8 @@ import { readFileSync } from 'node:fs'
2
2
 
3
3
  const ABSENT_CODE = 'ENOENT'
4
4
 
5
+ // Whether a filesystem error says "there is nothing here" — ENOENT and nothing else. A permission
6
+ // error or ENOTDIR says something is there, so neither reads as absent.
5
7
  function is_absent(error: unknown): boolean {
6
8
  return error instanceof Error && 'code' in error && error.code === ABSENT_CODE
7
9
  }
@@ -35,6 +37,6 @@ function read_if_readable(path: string): string | undefined {
35
37
  }
36
38
  }
37
39
 
38
- const file_reader = { read_optional, read_file_or_empty, read_if_readable }
40
+ const file_reader = { is_absent, read_optional, read_file_or_empty, read_if_readable }
39
41
 
40
42
  export { file_reader }
@@ -0,0 +1,63 @@
1
+ import { lstatSync } from 'node:fs'
2
+
3
+ // An answer remembered per key, recomputed only when the key's stamp changes (joshuafolkken/kit#4263).
4
+ //
5
+ // **`run:board` redraws every second, and most of what it reads has not changed since the last
6
+ // redraw.** A process's app name, a ledger's parsed lines and a work tree's git config were computed
7
+ // again on every pass, and on a saturated machine those passes stopped the spinner for 45–200ms. The
8
+ // stamp is what says "this has changed": a file's `file_stamp`, or a constant where the key alone
9
+ // decides the answer.
10
+
11
+ const NO_STAMP = ''
12
+ const STAMP_SEPARATOR = ':'
13
+
14
+ interface Remembered<Value> {
15
+ stamp: string
16
+ value: Value
17
+ }
18
+
19
+ interface StampedMemo<Value> {
20
+ // `compute`'s answer for `key`, run only when `key` was never seen or its stamp moved since.
21
+ of: (key: string, stamp: string, compute: () => Value) => Value
22
+ // Forget every key outside `keys` — a process gone from the table, so the memo cannot grow unbounded.
23
+ keep: (keys: ReadonlySet<string>) => void
24
+ }
25
+
26
+ function create<Value>(): StampedMemo<Value> {
27
+ const answers = new Map<string, Remembered<Value>>()
28
+
29
+ return {
30
+ of(key, stamp, compute) {
31
+ const known = answers.get(key)
32
+
33
+ if (known?.stamp === stamp) return known.value
34
+
35
+ const value = compute()
36
+
37
+ answers.set(key, { stamp, value })
38
+
39
+ return value
40
+ },
41
+ keep(keys) {
42
+ for (const key of answers.keys()) if (!keys.has(key)) answers.delete(key)
43
+ },
44
+ }
45
+ }
46
+
47
+ // What changes when a file is rewritten, appended to, replaced or re-owned: its inode, its modification
48
+ // and change times and its size. An absent or unreadable file is `NO_STAMP`, so it reads again once
49
+ // it appears.
50
+ function file_stamp(file: string): string {
51
+ try {
52
+ const status = lstatSync(file)
53
+
54
+ return [status.ino, status.mtimeMs, status.ctimeMs, status.size].join(STAMP_SEPARATOR)
55
+ } catch {
56
+ return NO_STAMP
57
+ }
58
+ }
59
+
60
+ const stamped_memo = { NO_STAMP, create, file_stamp }
61
+
62
+ export { stamped_memo }
63
+ export type { StampedMemo }
@@ -0,0 +1,24 @@
1
+ // Runs work whose own reports go to stdout with stdout pointed at stderr, for a caller whose stdout is
2
+ // a contract: the `Stop` hook's decision envelope, and `josh run:hold`'s single verdict token.
3
+
4
+ type StreamWrite = typeof process.stdout.write
5
+
6
+ function set_stdout_write(stream_write: StreamWrite): void {
7
+ process.stdout.write = stream_write
8
+ }
9
+
10
+ async function run<T>(work: () => Promise<T>): Promise<T> {
11
+ const saved = { write: process.stdout.write.bind(process.stdout) }
12
+
13
+ set_stdout_write(process.stderr.write.bind(process.stderr))
14
+
15
+ try {
16
+ return await work()
17
+ } finally {
18
+ set_stdout_write(saved.write)
19
+ }
20
+ }
21
+
22
+ const stdout_on_stderr = { run }
23
+
24
+ export { stdout_on_stderr }
@@ -3,6 +3,12 @@
3
3
  // limit stays stuck where it stopped and never comes back, so every such
4
4
  // call takes one of these, and a value used in more than one place is named once here.
5
5
 
6
+ // The unit conversions every duration is read and printed through. They sit beside the limits because a
7
+ // limit is the most common thing they convert; a second copy in a caller is a clone of these two lines.
8
+ const MS_PER_SECOND = 1000
9
+ const SECONDS_PER_MINUTE = 60
10
+ const MS_PER_MINUTE = MS_PER_SECOND * SECONDS_PER_MINUTE
11
+
6
12
  // A probe that only asks the local machine (`ps`, `lsof`, `git config`) on a path something else is
7
13
  // waiting on. Failing answers "cannot tell", which every caller handles, so anything slower is a fault.
8
14
  const PROBE_TIMEOUT_MS = 2000
@@ -41,6 +47,9 @@ export {
41
47
  HOOK_PROCESS_TIMEOUT_MS,
42
48
  INSTALL_TIMEOUT_MS,
43
49
  LINT_TIMEOUT_MS,
50
+ MS_PER_MINUTE,
51
+ MS_PER_SECOND,
44
52
  PROBE_TIMEOUT_MS,
53
+ SECONDS_PER_MINUTE,
45
54
  SUITE_TIMEOUT_MS,
46
55
  }
@@ -0,0 +1,91 @@
1
+ import { z } from 'zod'
2
+ import { json_value } from './json-value'
3
+
4
+ // One line of a Claude Code JSONL log — a session transcript, or the `stream-json` output of
5
+ // `claude -p`, which writes the same `{ type, message: { id, content } }` shape. Every reader of those
6
+ // lines parses through these schemas and takes what it needs from the record; a fix to the shape
7
+ // reaches all of them at once.
8
+ //
9
+ // **Every field is optional, including `type`.** A required field would make one unexpected block
10
+ // fail the whole array it sits in, and with it every other block on that line — an entire assistant
11
+ // turn dropped because one tool wrote a shape no reader had seen. A block that parses to nothing
12
+ // contributes nothing.
13
+
14
+ const TEXT_TYPE = 'text'
15
+ const TOOL_USE_TYPE = 'tool_use'
16
+ const TOOL_RESULT_TYPE = 'tool_result'
17
+
18
+ const BLOCK_SCHEMA = z.object({
19
+ type: z.string().nullish(),
20
+ text: z.string().nullish(),
21
+ name: z.string().nullish(),
22
+ id: z.string().nullish(),
23
+ tool_use_id: z.string().nullish(),
24
+ input: z.unknown().nullish(),
25
+ // Whether the harness wrote a `tool_result` back as a failure — absent on every other block, and
26
+ // on the results of tools that never report one.
27
+ is_error: z.boolean().nullish(),
28
+ // A result's body: a string or a list of blocks. Read as `unknown` because each reader flattens it
29
+ // its own way, and a narrower type here would drop the whole line over one odd item.
30
+ content: z.unknown().nullish(),
31
+ })
32
+
33
+ const CONTENT_SCHEMA = z.union([z.string(), z.array(BLOCK_SCHEMA)])
34
+ // `id` is the assistant *message* the line belongs to; Claude Code writes one line per content block,
35
+ // so a turn that issued two calls is several lines carrying one id.
36
+ const MESSAGE_SCHEMA = z.object({ id: z.string().nullish(), content: CONTENT_SCHEMA.nullish() })
37
+
38
+ const LINE_SCHEMA = z.object({
39
+ type: z.string().nullish(),
40
+ timestamp: z.string().nullish(),
41
+ gitBranch: z.string().nullish(),
42
+ // The two fields outside `message` the harness writes an end-of-task notice on. `unknown`, since a
43
+ // string here would reject every line whose `content` is a list of blocks.
44
+ content: z.unknown().nullish(),
45
+ attachment: z.unknown().nullish(),
46
+ message: MESSAGE_SCHEMA.nullish(),
47
+ })
48
+
49
+ type TranscriptBlock = z.infer<typeof BLOCK_SCHEMA>
50
+ type TranscriptContent = z.infer<typeof CONTENT_SCHEMA>
51
+ type TranscriptMessage = z.infer<typeof MESSAGE_SCHEMA>
52
+ type TranscriptRecord = z.infer<typeof LINE_SCHEMA>
53
+ type ToolCallBlock = TranscriptBlock & { name: string }
54
+
55
+ function read(value: unknown): TranscriptRecord | undefined {
56
+ return LINE_SCHEMA.safeParse(value).data
57
+ }
58
+
59
+ // A blank line, a line that is not JSON and a line of another shape are one answer: `undefined`.
60
+ function parse(line: string): TranscriptRecord | undefined {
61
+ return read(json_value.parse_or_undefined(line))
62
+ }
63
+
64
+ // The line's blocks. A message written as a bare string — a prompt — carries none.
65
+ function blocks_of(record: TranscriptRecord): ReadonlyArray<TranscriptBlock> {
66
+ const content = record.message?.content
67
+
68
+ return Array.isArray(content) ? content : []
69
+ }
70
+
71
+ function is_tool_call(block: TranscriptBlock): block is ToolCallBlock {
72
+ return block.type === TOOL_USE_TYPE && typeof block.name === 'string'
73
+ }
74
+
75
+ // The calls a line made, in order. A `tool_use` block without a name is not a call anything can name.
76
+ function tool_calls_of(record: TranscriptRecord): Array<ToolCallBlock> {
77
+ return blocks_of(record).filter((block) => is_tool_call(block))
78
+ }
79
+
80
+ const transcript_record = {
81
+ TEXT_TYPE,
82
+ TOOL_USE_TYPE,
83
+ TOOL_RESULT_TYPE,
84
+ read,
85
+ parse,
86
+ blocks_of,
87
+ tool_calls_of,
88
+ }
89
+
90
+ export type { TranscriptBlock, TranscriptContent, TranscriptMessage, TranscriptRecord }
91
+ export { transcript_record }