@joshuafolkken/kit 1.1471.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 (895) hide show
  1. package/.claude/agents/investigator.md +1 -1
  2. package/.claude/settings.json +6 -6
  3. package/.claude/skills/epic-commands/SKILL.md +26 -77
  4. package/.claude/skills/epic-commands/epic-bundle.md +12 -6
  5. package/.claude/skills/epic-commands/execution-waves.md +1 -2
  6. package/.claude/skills/verify-ui/SKILL.md +1 -2
  7. package/.claude/skills/workflow-commands/SKILL.md +12 -14
  8. package/.claude/skills/workflow-commands/background-commands.md +8 -12
  9. package/.claude/skills/workflow-commands/backlogrun-child.md +13 -18
  10. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
  11. package/.claude/skills/workflow-commands/backlogrun-lanes.md +23 -28
  12. package/.claude/skills/workflow-commands/backlogrun-park.md +16 -31
  13. package/.claude/skills/workflow-commands/backlogrun-progress.md +12 -21
  14. package/.claude/skills/workflow-commands/backlogrun-recovery.md +12 -12
  15. package/.claude/skills/workflow-commands/backlogrun-steps.md +12 -20
  16. package/.claude/skills/workflow-commands/backlogrun.md +32 -51
  17. package/.claude/skills/workflow-commands/chain-rule.md +18 -11
  18. package/.claude/skills/workflow-commands/delegation.md +13 -8
  19. package/.claude/skills/workflow-commands/entry-sequence.md +10 -12
  20. package/.claude/skills/workflow-commands/followup.md +10 -35
  21. package/.claude/skills/workflow-commands/fullrun-steps.md +38 -49
  22. package/.claude/skills/workflow-commands/fullrun.md +6 -8
  23. package/.claude/skills/workflow-commands/halfrun.md +20 -32
  24. package/.claude/skills/workflow-commands/into-target.md +1 -2
  25. package/.claude/skills/workflow-commands/issue-comments.md +19 -15
  26. package/.claude/skills/workflow-commands/issue-scout.md +5 -4
  27. package/.claude/skills/workflow-commands/kickoff.md +24 -23
  28. package/.claude/skills/workflow-commands/latest-gate.md +9 -18
  29. package/.claude/skills/workflow-commands/needs-human-review.md +11 -19
  30. package/.claude/skills/workflow-commands/observation-filing.md +4 -50
  31. package/.claude/skills/workflow-commands/observation-ledger.md +5 -10
  32. package/.claude/skills/workflow-commands/pre-gate-cut.md +22 -44
  33. package/.claude/skills/workflow-commands/prerequisite.md +11 -18
  34. package/.claude/skills/workflow-commands/progress-watcher.md +3 -8
  35. package/.claude/skills/workflow-commands/prrun.md +6 -12
  36. package/.claude/skills/workflow-commands/retrospective.md +5 -5
  37. package/.claude/skills/workflow-commands/split-assessment.md +14 -4
  38. package/.claude/skills/workflow-commands/target-repository.md +1 -2
  39. package/.claude/skills/workflow-commands/working-tree-hold.md +11 -13
  40. package/.codex/hooks.json +6 -6
  41. package/.github/actions/setup-node/action.yml +10 -1
  42. package/.github/actions/setup-pnpm/action.yml +1 -1
  43. package/.github/dependabot.yml +16 -0
  44. package/.github/release.yml +0 -2
  45. package/.github/workflows/ci.yml +121 -11
  46. package/.github/workflows/publish.yml +10 -3
  47. package/.github/workflows/sonar-qube.yml +1 -0
  48. package/.prettierignore +2 -0
  49. package/.vscode/tasks.json +1 -2
  50. package/CLAUDE.md +4 -8
  51. package/README.md +4 -2
  52. package/SECURITY.md +1 -1
  53. package/cspell/index.yaml +7 -0
  54. package/dist/CLAUDE.md +4 -8
  55. package/dist/commands/document-read-cli.js +882 -0
  56. package/dist/commands/{document-section-cli.js → document-section-main.js} +137 -62
  57. package/dist/commands/read-set-cli.js +1867 -0
  58. package/dist/commands/run-prep-main.js +21653 -0
  59. package/dist/commands/run-step-cli.js +23880 -0
  60. package/dist/config-merge/index.js +5 -1
  61. package/dist/hooks/audit-provision.js +20 -35
  62. package/dist/hooks/{chunk-DGT54IH5.js → chunk-AZX4FGQ3.js} +63 -17
  63. package/dist/hooks/chunk-CWMBGKYW.js +6483 -0
  64. package/dist/hooks/chunk-O2YBIDSI.js +4306 -0
  65. package/dist/hooks/{chunk-AS74OU3D.js → chunk-PT5R6UJD.js} +4582 -2118
  66. package/dist/hooks/chunk-TUIFS5E7.js +72 -0
  67. package/dist/hooks/{chunk-723HKZO5.js → chunk-VWWCFGWK.js} +1 -1
  68. package/dist/hooks/{chunk-E7OIKX5Z.js → chunk-WR2KQAYZ.js} +1863 -382
  69. package/dist/hooks/{chunk-KC5AK2GF.js → chunk-XGBNSWEI.js} +248 -46
  70. package/dist/hooks/chunk-YCDOIR3I.js +3456 -0
  71. package/dist/hooks/codex-hook-adapter.js +10 -19
  72. package/dist/hooks/format-edited.js +5 -5
  73. package/dist/hooks/inputs.json +436 -257
  74. package/dist/hooks/pretool-guard.js +7 -22
  75. package/dist/hooks/session-lang.js +380 -42
  76. package/dist/hooks/stop-guard.js +8711 -782
  77. package/dist/josh.js +5263 -997
  78. package/dist/self-sync-guard/index.js +74 -10
  79. package/dist/version/index.js +115 -406
  80. package/eslint/base.js +1 -1
  81. package/lefthook/base.yml +8 -4
  82. package/package.json +17 -53
  83. package/pnpm-workspace.yaml +4 -2
  84. package/prompts/coding-standards.md +1 -1
  85. package/prompts/collaboration-workflow/file-edits.md +1 -9
  86. package/prompts/collaboration-workflow/gh-rest.md +1 -2
  87. package/prompts/collaboration-workflow/issue-citation.md +2 -4
  88. package/prompts/collaboration-workflow/issue-template.md +42 -17
  89. package/prompts/collaboration-workflow/lane-instructions.md +34 -0
  90. package/prompts/collaboration-workflow/measurement.md +37 -0
  91. package/prompts/collaboration-workflow/operating-rules.md +6 -12
  92. package/prompts/collaboration-workflow/output-bounds.md +4 -9
  93. package/prompts/collaboration-workflow/overview.md +1 -1
  94. package/prompts/collaboration-workflow/plan-comment.md +3 -42
  95. package/prompts/collaboration-workflow/principles.md +19 -8
  96. package/prompts/collaboration-workflow/report-format.md +37 -57
  97. package/prompts/collaboration-workflow/residency.md +12 -8
  98. package/prompts/collaboration-workflow/rule-delivery.md +3 -11
  99. package/prompts/collaboration-workflow/shell-body.md +8 -18
  100. package/prompts/collaboration-workflow/turn-batching.md +4 -6
  101. package/prompts/collaboration-workflow/upstream-interrupt.md +16 -6
  102. package/prompts/collaboration-workflow/wip-cap.md +7 -7
  103. package/prompts/collaboration-workflow.md +4 -7
  104. package/prompts/refactoring.md +1 -1
  105. package/prompts/review-rubric.md +1 -2
  106. package/prompts/review.md +45 -26
  107. package/prompts/testing-guide.md +10 -45
  108. package/scripts/agent/agent-argv.ts +20 -4
  109. package/scripts/agent/agent-event.ts +15 -15
  110. package/scripts/agent/agent-exit-record.ts +13 -1
  111. package/scripts/agent/agent-role-profile.ts +101 -45
  112. package/scripts/agent/agent-safe-text.ts +60 -0
  113. package/scripts/agent/api-auth.ts +41 -0
  114. package/scripts/agent/api-outage.ts +1 -1
  115. package/scripts/agent/claude-agent-argv.ts +14 -0
  116. package/scripts/agent/codex-agent-argv.ts +2 -0
  117. package/scripts/agent/lane-instructions.ts +144 -0
  118. package/scripts/auto-ok/auto-ok-cli.ts +14 -16
  119. package/scripts/auto-ok/auto-ok-judge-read.ts +12 -3
  120. package/scripts/auto-ok/auto-ok-judge-write.ts +46 -19
  121. package/scripts/auto-ok/auto-ok-judge.ts +13 -2
  122. package/scripts/auto-ok/auto-ok-main.ts +17 -0
  123. package/scripts/backlog/backlog-arrival.ts +14 -3
  124. package/scripts/backlog/backlog-budget-cli.ts +7 -33
  125. package/scripts/backlog/backlog-budget-main.ts +16 -0
  126. package/scripts/backlog/backlog-budget.ts +6 -7
  127. package/scripts/backlog/backlog-defect-priority.ts +4 -3
  128. package/scripts/backlog/backlog-drive-adopt.ts +67 -0
  129. package/scripts/backlog/backlog-drive-args.ts +4 -5
  130. package/scripts/backlog/backlog-drive-cli.ts +113 -28
  131. package/scripts/backlog/backlog-drive-hold.ts +162 -0
  132. package/scripts/backlog/backlog-drive-idle.ts +151 -0
  133. package/scripts/backlog/backlog-drive-judge.ts +25 -0
  134. package/scripts/backlog/backlog-drive-memory.ts +126 -0
  135. package/scripts/backlog/backlog-drive-named-offer.ts +5 -10
  136. package/scripts/backlog/backlog-drive-named.ts +54 -7
  137. package/scripts/backlog/backlog-drive-offer-argv.ts +3 -8
  138. package/scripts/backlog/backlog-drive-paused.ts +169 -0
  139. package/scripts/backlog/backlog-drive-restore.ts +39 -8
  140. package/scripts/backlog/backlog-drive-seats.ts +18 -8
  141. package/scripts/backlog/backlog-drive-token-handling.ts +38 -0
  142. package/scripts/backlog/backlog-drive.ts +79 -75
  143. package/scripts/backlog/backlog-next-main.ts +16 -0
  144. package/scripts/backlog/backlog-next-shared.ts +73 -0
  145. package/scripts/backlog/backlog-next.ts +48 -16
  146. package/scripts/backlog/backlog-occupied.ts +69 -0
  147. package/scripts/backlog/backlog-offer-cli.ts +6 -21
  148. package/scripts/backlog/backlog-offer-exclude.ts +15 -0
  149. package/scripts/backlog/backlog-offer-main.ts +12 -0
  150. package/scripts/backlog/backlog-offer.ts +36 -3
  151. package/scripts/backlog/backlog-overlap.ts +22 -4
  152. package/scripts/backlog/backlog-plan-read.ts +6 -2
  153. package/scripts/backlog/backlog-plan.ts +18 -4
  154. package/scripts/backlog/backlog-pool.ts +10 -10
  155. package/scripts/backlog/backlog-rank.ts +10 -2
  156. package/scripts/backlog/backlog-ready.ts +137 -18
  157. package/scripts/backlog/backlog-stalled-detect.ts +109 -36
  158. package/scripts/backlog/backlog-stalled.ts +52 -16
  159. package/scripts/backlog/backlog-wait-cause.ts +86 -0
  160. package/scripts/backlog/backlog-waves.ts +39 -13
  161. package/scripts/backlog/backlogrun-args.ts +19 -7
  162. package/scripts/backlog/backlogrun-cli.ts +19 -5
  163. package/scripts/backlog/backlogrun-launch.ts +6 -0
  164. package/scripts/backlog/backlogrun-restart.ts +97 -0
  165. package/scripts/backlog/backlogrun-stop.ts +79 -7
  166. package/scripts/behavior/behavior-cli.ts +2 -2
  167. package/scripts/behavior/behavior-rules.ts +47 -24
  168. package/scripts/build/build-bin.ts +2 -16
  169. package/scripts/build/build-claude-md.ts +0 -7
  170. package/scripts/build/build-commands.ts +0 -13
  171. package/scripts/build/build-hooks.ts +49 -48
  172. package/scripts/build/hook-bundle-stamp.ts +29 -11
  173. package/scripts/build/local-bin.ts +1 -1
  174. package/scripts/cases/cases-cli.ts +25 -13
  175. package/scripts/cases/cases-interaction-scan.ts +134 -0
  176. package/scripts/cases/cases-interaction.ts +183 -0
  177. package/scripts/cases/cases-logic.ts +39 -6
  178. package/scripts/ci/pr-classification-main.ts +18 -0
  179. package/scripts/ci/pr-classification.ts +10 -17
  180. package/scripts/clone/clone-scan.ts +1 -1
  181. package/scripts/cost-runtime/cost-blocks.ts +22 -37
  182. package/scripts/cost-runtime/cost-cli.ts +31 -14
  183. package/scripts/cost-runtime/cost-main.ts +12 -0
  184. package/scripts/cost-runtime/cost-transcript.ts +1 -0
  185. package/scripts/delegation/delegation-policy.ts +17 -4
  186. package/scripts/delegation/duplicate-read-guard.ts +2 -10
  187. package/scripts/delegation/investigation-guard.ts +15 -73
  188. package/scripts/delegation/investigation-reads.ts +3 -5
  189. package/scripts/dependabot/dependabot-cooldown.ts +194 -0
  190. package/scripts/discovery/repo-discovery.ts +24 -6
  191. package/scripts/doctor/doctor-consumer.ts +2 -5
  192. package/scripts/document/document-byte-budget.ts +9 -6
  193. package/scripts/document/document-scan.ts +1 -1
  194. package/scripts/document/document-section-cli.ts +17 -13
  195. package/scripts/document/document-section-main.ts +12 -0
  196. package/scripts/document/entry-read-budget.ts +2 -2
  197. package/scripts/document/read-set-cli.ts +4 -1
  198. package/scripts/epic/epic-audit-cli.ts +12 -6
  199. package/scripts/epic/epic-audit-orphans.ts +5 -8
  200. package/scripts/epic/epic-audit.ts +52 -1
  201. package/scripts/epic/epic-bundle-apply.ts +137 -0
  202. package/scripts/epic/epic-bundle-cli.ts +32 -121
  203. package/scripts/epic/epic-bundle-evidence.ts +49 -26
  204. package/scripts/epic/epic-bundle-format.ts +116 -0
  205. package/scripts/epic/epic-bundle-main.ts +17 -0
  206. package/scripts/epic/epic-bundle-referenced.ts +14 -3
  207. package/scripts/epic/epic-bundle.ts +17 -9
  208. package/scripts/epic/epic-busy.ts +5 -12
  209. package/scripts/epic/epic-classify.ts +24 -15
  210. package/scripts/epic/epic-cli-argv.ts +31 -0
  211. package/scripts/epic/epic-cli-decide.ts +42 -0
  212. package/scripts/epic/epic-cli.ts +6 -38
  213. package/scripts/epic/epic-close.ts +112 -55
  214. package/scripts/epic/epic-cross-repo.ts +4 -7
  215. package/scripts/epic/epic-decide.ts +119 -0
  216. package/scripts/epic/epic-decision.ts +9 -0
  217. package/scripts/epic/epic-fetch.ts +4 -0
  218. package/scripts/epic/epic-graph.ts +2 -0
  219. package/scripts/epic/epic-issue.ts +5 -1
  220. package/scripts/epic/epic-label-age.ts +1 -1
  221. package/scripts/epic/epic-lane-offer.ts +39 -4
  222. package/scripts/epic/epic-next-main.ts +24 -0
  223. package/scripts/epic/epic-next.ts +6 -24
  224. package/scripts/epic/epic-outside-blocker.ts +6 -2
  225. package/scripts/epic/epic-parse.ts +9 -3
  226. package/scripts/epic/epic-read.ts +1 -0
  227. package/scripts/epic/epic-reconcile.ts +39 -0
  228. package/scripts/epic/epic-run.ts +10 -1
  229. package/scripts/epic/epic-solo.ts +50 -14
  230. package/scripts/epic/epic.ts +41 -7
  231. package/scripts/exports/unused-members-cli.ts +2 -2
  232. package/scripts/followup/followup-checks-event.ts +8 -3
  233. package/scripts/followup/followup-coderabbit-wait.ts +82 -0
  234. package/scripts/followup/followup-review-gates.ts +81 -0
  235. package/scripts/followup/git-followup-stages.ts +13 -3
  236. package/scripts/followup/git-followup-workflow.ts +31 -60
  237. package/scripts/followup/git-pr-followup-wrapup.ts +9 -14
  238. package/scripts/followup/git-pr-followup.ts +36 -8
  239. package/scripts/fresh-machine/fresh-machine-cli.ts +1 -1
  240. package/scripts/fresh-machine/fresh-machine-run.ts +8 -8
  241. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +1 -1
  242. package/scripts/gate/busy-average.ts +58 -0
  243. package/scripts/gate/check-cpu.ts +60 -0
  244. package/scripts/gate/check-inputs.ts +73 -0
  245. package/scripts/gate/check-reuse.ts +141 -0
  246. package/scripts/gate/command-memory.ts +192 -0
  247. package/scripts/gate/core-admission.ts +218 -28
  248. package/scripts/gate/core-budget-timing.ts +37 -0
  249. package/scripts/gate/core-budget.ts +150 -119
  250. package/scripts/gate/core-wait-record.ts +48 -0
  251. package/scripts/gate/core-wait.ts +162 -0
  252. package/scripts/gate/core-weights.ts +86 -0
  253. package/scripts/gate/free-cores.ts +72 -0
  254. package/scripts/gate/gate-ledger.ts +49 -7
  255. package/scripts/gate/gate-plan.ts +44 -15
  256. package/scripts/gate/gate-report.ts +29 -4
  257. package/scripts/gate/gate-run-steps.ts +195 -0
  258. package/scripts/gate/gate-skip.ts +12 -2
  259. package/scripts/gate/gate-steps.ts +12 -1
  260. package/scripts/gate/held-mark.ts +55 -0
  261. package/scripts/gate/input-fingerprint.ts +42 -0
  262. package/scripts/gate/machine-capacity.ts +124 -31
  263. package/scripts/gate/moved-paths.ts +67 -0
  264. package/scripts/gate/pre-commit-type-check.ts +14 -1
  265. package/scripts/gate/project-checks.ts +5 -12
  266. package/scripts/gate/scoped-green.ts +12 -8
  267. package/scripts/gate/since-green.ts +62 -0
  268. package/scripts/gate/toolchain-inputs.ts +115 -0
  269. package/scripts/gate/verification-gate.ts +65 -129
  270. package/scripts/gate/verification-inputs.ts +250 -0
  271. package/scripts/gh/gh-author-association.ts +96 -9
  272. package/scripts/gh/git-ai-review-scan.ts +4 -2
  273. package/scripts/gh/git-gh-api-path.ts +15 -0
  274. package/scripts/gh/git-gh-branch-rules.ts +73 -0
  275. package/scripts/gh/git-gh-conditional.ts +5 -2
  276. package/scripts/gh/git-gh-issue-read.ts +5 -1
  277. package/scripts/gh/git-gh-issue-rest.ts +1 -0
  278. package/scripts/gh/git-gh-issue-write.ts +77 -17
  279. package/scripts/gh/git-gh-issue.ts +7 -3
  280. package/scripts/gh/git-gh-poll-read.ts +89 -0
  281. package/scripts/gh/git-gh-pr-auto-merge.ts +8 -3
  282. package/scripts/gh/git-gh-pr-rest.ts +1 -1
  283. package/scripts/gh/git-gh-pr-snapshot.ts +33 -20
  284. package/scripts/gh/git-gh-pr.ts +27 -15
  285. package/scripts/gh/git-pr-checks-eval.ts +39 -7
  286. package/scripts/gh/git-pr-checks-parse.ts +39 -9
  287. package/scripts/gh/git-pr-merge-checked.ts +80 -0
  288. package/scripts/gh/git-pr.ts +13 -1
  289. package/scripts/git/base-tree.ts +19 -2
  290. package/scripts/git/changed-file-scope.ts +6 -4
  291. package/scripts/git/changed-paths.ts +18 -1
  292. package/scripts/git/git-diff-reads.ts +27 -2
  293. package/scripts/git/git-grep-hits.ts +85 -0
  294. package/scripts/git/git-location-environment.ts +1 -1
  295. package/scripts/git/git-merge-conflicts.ts +83 -0
  296. package/scripts/git/git-preflight.ts +37 -12
  297. package/scripts/git/git-push-transport.ts +1 -2
  298. package/scripts/git/git-schemas.ts +17 -7
  299. package/scripts/git/git-spawn.ts +1 -2
  300. package/scripts/git/git-status.ts +4 -4
  301. package/scripts/git/main-merge-main.ts +12 -0
  302. package/scripts/git/main-merge-regenerate.ts +78 -0
  303. package/scripts/git/main-merge.ts +39 -14
  304. package/scripts/git/main-sync-main.ts +12 -0
  305. package/scripts/git/main-sync.ts +0 -9
  306. package/scripts/git/stash/git-stash.ts +27 -4
  307. package/scripts/git/stash/{stash-pop-args.ts → stash-args.ts} +13 -10
  308. package/scripts/git/stash/stash-pop-cli.ts +6 -12
  309. package/scripts/git/stash/stash-pop-main.ts +12 -0
  310. package/scripts/git/stash/stash-push-cli.ts +76 -0
  311. package/scripts/git/stash/stash-push-main.ts +12 -0
  312. package/scripts/hooks/batch-guard.ts +5 -16
  313. package/scripts/hooks/check-commit-message-main.ts +8 -0
  314. package/scripts/hooks/check-commit-message.ts +4 -7
  315. package/scripts/hooks/format-edited-file.ts +8 -24
  316. package/scripts/hooks/pre-commit-lint.ts +118 -0
  317. package/scripts/hooks/pre-push-unit.ts +4 -2
  318. package/scripts/hooks/pretool-guard-cli.ts +1 -8
  319. package/scripts/hooks/pretool-guard.ts +57 -69
  320. package/scripts/hooks/reserved-run.ts +67 -8
  321. package/scripts/hooks/run-hook.sh +18 -11
  322. package/scripts/hooks/shell-rules-notice.ts +37 -0
  323. package/scripts/hooks/stop-actions.ts +185 -0
  324. package/scripts/hooks/stop-guard.ts +72 -27
  325. package/scripts/init/hook-command-rewrite.ts +19 -5
  326. package/scripts/init/hook-launch.ts +15 -12
  327. package/scripts/init/init-actions.ts +0 -6
  328. package/scripts/init/init-ai-copy.ts +10 -36
  329. package/scripts/init/init-bootstrap.ts +9 -8
  330. package/scripts/init/init-dry-run-report.ts +1 -1
  331. package/scripts/init/init-dry-run.ts +1 -1
  332. package/scripts/init/init-file-action.ts +7 -9
  333. package/scripts/init/init-logic-json-merge.ts +2 -2
  334. package/scripts/init/init-logic-migrate.ts +9 -82
  335. package/scripts/init/init-logic.ts +3 -2
  336. package/scripts/init/init-main.ts +12 -0
  337. package/scripts/init/init.ts +5 -12
  338. package/scripts/init/kit-development-versions.ts +3 -7
  339. package/scripts/init/kit-written-paths.ts +2 -2
  340. package/scripts/init/project-profile.ts +5 -4
  341. package/scripts/init/tsconfig-preset-migration.ts +2 -1
  342. package/scripts/init/vscode-tasks.ts +1 -1
  343. package/scripts/issue/defect-origin-cli.ts +106 -0
  344. package/scripts/issue/defect-origin-line.ts +60 -0
  345. package/scripts/issue/defect-origin-main.ts +11 -0
  346. package/scripts/issue/defect-origin.ts +114 -0
  347. package/scripts/issue/defect-rate-cli.ts +34 -78
  348. package/scripts/issue/defect-rate.ts +0 -16
  349. package/scripts/issue/defect-report-cli.ts +128 -0
  350. package/scripts/issue/defect-report-format.ts +56 -0
  351. package/scripts/issue/defect-report-main.ts +11 -0
  352. package/scripts/issue/defect-report.ts +160 -0
  353. package/scripts/issue/expected-effect-lint.ts +60 -0
  354. package/scripts/issue/issue-already-done-cli.ts +62 -0
  355. package/scripts/issue/issue-body-or-comment.ts +40 -0
  356. package/scripts/issue/issue-cite-cli.ts +33 -22
  357. package/scripts/issue/issue-cite-main.ts +12 -0
  358. package/scripts/issue/issue-classification.ts +13 -8
  359. package/scripts/issue/issue-comment-cli.ts +10 -24
  360. package/scripts/issue/issue-comment-main.ts +12 -0
  361. package/scripts/issue/issue-evidence-exit.ts +100 -0
  362. package/scripts/issue/issue-file-cli.ts +29 -7
  363. package/scripts/issue/issue-file.ts +19 -19
  364. package/scripts/issue/issue-fold-cli.ts +2 -11
  365. package/scripts/issue/issue-fold-main.ts +12 -0
  366. package/scripts/issue/issue-labels.ts +81 -90
  367. package/scripts/issue/issue-lint-cli.ts +7 -13
  368. package/scripts/issue/issue-lint-main.ts +12 -0
  369. package/scripts/issue/issue-measured-cli.ts +56 -0
  370. package/scripts/issue/issue-merged.ts +19 -2
  371. package/scripts/issue/issue-not-before-label.ts +135 -0
  372. package/scripts/issue/issue-not-before.ts +111 -0
  373. package/scripts/issue/issue-number-shape.ts +15 -1
  374. package/scripts/issue/issue-park.ts +28 -0
  375. package/scripts/issue/issue-plan-cli.ts +151 -0
  376. package/scripts/issue/issue-priority.ts +151 -0
  377. package/scripts/issue/issue-rank.ts +7 -1
  378. package/scripts/issue/issue-read-cli.ts +3 -10
  379. package/scripts/issue/issue-read-main.ts +12 -0
  380. package/scripts/issue/issue-read.ts +29 -5
  381. package/scripts/issue/issue-release-cli.ts +0 -10
  382. package/scripts/issue/issue-release-main.ts +13 -0
  383. package/scripts/issue/issue-release.ts +7 -12
  384. package/scripts/issue/issue-sample-gate.ts +192 -0
  385. package/scripts/issue/issue-sample-source.ts +76 -0
  386. package/scripts/issue/issue-scout-cli.ts +19 -25
  387. package/scripts/issue/issue-scout-main.ts +14 -0
  388. package/scripts/issue/issue-state-cli.ts +0 -10
  389. package/scripts/issue/issue-state-main.ts +12 -0
  390. package/scripts/issue/issue-watch-diff.ts +56 -15
  391. package/scripts/issue/issue-watch.ts +2 -1
  392. package/scripts/issue/issue-wip.ts +2 -7
  393. package/scripts/issue/markdown-section.ts +19 -5
  394. package/scripts/issue/measure-rerun-cli.ts +13 -8
  395. package/scripts/issue/plan-consumers-cli.ts +39 -0
  396. package/scripts/issue/plan-consumers-main.ts +11 -0
  397. package/scripts/issue/plan-consumers-section.ts +55 -0
  398. package/scripts/issue/plan-consumers.ts +127 -0
  399. package/scripts/josh/agent-session-environment.ts +1 -1
  400. package/scripts/josh/command-usage.ts +82 -0
  401. package/scripts/josh/file-map-stamp.ts +49 -16
  402. package/scripts/josh/hook-decision.ts +32 -20
  403. package/scripts/josh/josh-command-map.ts +6 -1
  404. package/scripts/josh/josh-command-types.ts +65 -13
  405. package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
  406. package/scripts/josh/josh-commands-ai.ts +169 -157
  407. package/scripts/josh/josh-commands-backlog.ts +82 -16
  408. package/scripts/josh/josh-commands-clone.ts +1 -0
  409. package/scripts/josh/josh-commands-development.ts +111 -71
  410. package/scripts/josh/josh-commands-document.ts +43 -1
  411. package/scripts/josh/josh-commands-epic.ts +171 -0
  412. package/scripts/josh/josh-commands-hooks.ts +31 -2
  413. package/scripts/josh/josh-commands-issue-write.ts +181 -0
  414. package/scripts/josh/josh-commands-issue.ts +124 -24
  415. package/scripts/josh/josh-commands-lane.ts +112 -2
  416. package/scripts/josh/josh-commands-lint.ts +19 -8
  417. package/scripts/josh/josh-commands-maintenance.ts +112 -4
  418. package/scripts/josh/josh-commands-pause.ts +29 -0
  419. package/scripts/josh/josh-commands-progress.ts +87 -0
  420. package/scripts/josh/josh-commands-project.ts +138 -9
  421. package/scripts/josh/josh-commands-review.ts +124 -0
  422. package/scripts/josh/josh-commands-run.ts +211 -23
  423. package/scripts/josh/josh-commands-ship.ts +169 -0
  424. package/scripts/josh/josh-commands-split.ts +9 -0
  425. package/scripts/josh/josh-commands-versioning.ts +49 -2
  426. package/scripts/josh/josh-commands-workflow.ts +149 -6
  427. package/scripts/josh/josh-logic.ts +11 -27
  428. package/scripts/josh/josh.ts +14 -5
  429. package/scripts/josh/package-directory.ts +18 -0
  430. package/scripts/josh/process-identity.ts +13 -4
  431. package/scripts/josh/session-language-cli.ts +4 -8
  432. package/scripts/josh/session-language-main.ts +13 -0
  433. package/scripts/josh/session-language.ts +6 -1
  434. package/scripts/josh/shared-cache.ts +90 -0
  435. package/scripts/josh/stamp-file.ts +9 -15
  436. package/scripts/lane/lane-await.ts +51 -12
  437. package/scripts/lane/lane-cache.ts +5 -30
  438. package/scripts/lane/lane-capacity.ts +19 -22
  439. package/scripts/lane/lane-check-stats.ts +97 -0
  440. package/scripts/lane/lane-child-invocation.ts +43 -4
  441. package/scripts/lane/lane-cli.ts +15 -5
  442. package/scripts/lane/lane-close.ts +86 -18
  443. package/scripts/lane/lane-core-wait-stats.ts +66 -0
  444. package/scripts/lane/lane-dispatch.ts +27 -6
  445. package/scripts/lane/lane-gap-stats.ts +156 -0
  446. package/scripts/lane/lane-guard-policy.ts +2 -2
  447. package/scripts/lane/lane-handoff.ts +76 -1
  448. package/scripts/lane/lane-held-stats.ts +129 -0
  449. package/scripts/lane/lane-install.ts +16 -15
  450. package/scripts/lane/lane-launch-cli.ts +0 -9
  451. package/scripts/lane/lane-launch-main.ts +12 -0
  452. package/scripts/lane/lane-ledger-schema.ts +266 -0
  453. package/scripts/lane/lane-ledger.ts +108 -97
  454. package/scripts/lane/lane-limit-cli.ts +19 -9
  455. package/scripts/lane/lane-measure-cli.ts +58 -10
  456. package/scripts/lane/lane-open.ts +9 -1
  457. package/scripts/lane/lane-parked.ts +3 -3
  458. package/scripts/lane/lane-pause-cli.ts +130 -0
  459. package/scripts/lane/lane-pause.ts +158 -0
  460. package/scripts/lane/lane-preserve.ts +29 -1
  461. package/scripts/lane/lane-process-table.ts +166 -0
  462. package/scripts/lane/lane-reap-settle.ts +124 -0
  463. package/scripts/lane/lane-reap.ts +50 -15
  464. package/scripts/lane/lane-registry.ts +33 -10
  465. package/scripts/lane/lane-residents.ts +162 -0
  466. package/scripts/lane/lane-restart.ts +26 -27
  467. package/scripts/lane/lane-round-two-stats.ts +49 -0
  468. package/scripts/lane/lane-sampler.ts +4 -0
  469. package/scripts/lane/lane-session-action.ts +160 -0
  470. package/scripts/lane/lane-session-broker.ts +134 -134
  471. package/scripts/lane/lane-snapshot-trace.ts +84 -0
  472. package/scripts/lane/lane-spans.ts +51 -0
  473. package/scripts/lane/lane-spent.ts +6 -3
  474. package/scripts/lane/lane-stage-stats.ts +7 -2
  475. package/scripts/lane/lane-state.ts +302 -0
  476. package/scripts/lane/lane-stats.ts +58 -4
  477. package/scripts/lane/lane-stop-stats.ts +113 -37
  478. package/scripts/lane/lane-test-related-stats.ts +127 -0
  479. package/scripts/lane/lane-transcript-calls.ts +145 -0
  480. package/scripts/lane/lane-transcript-stats.ts +168 -0
  481. package/scripts/lane/lane-vacant.ts +13 -3
  482. package/scripts/lane/lane-withdraw-cli.ts +72 -0
  483. package/scripts/lane/lane-withdraw.ts +183 -0
  484. package/scripts/lane/process-directories.ts +70 -0
  485. package/scripts/lane/process-lane-marks.ts +94 -0
  486. package/scripts/lib/atomic-write.ts +62 -0
  487. package/scripts/lib/buffered-process.ts +12 -5
  488. package/scripts/lib/cli-flags.ts +53 -0
  489. package/scripts/lib/figure-format.ts +63 -0
  490. package/scripts/lib/json-value.ts +9 -1
  491. package/scripts/lib/package-manifest.ts +35 -0
  492. package/scripts/lib/read-file.ts +3 -1
  493. package/scripts/lib/stamped-memo.ts +63 -0
  494. package/scripts/lib/stdout-on-stderr.ts +24 -0
  495. package/scripts/lib/timeouts.ts +9 -0
  496. package/scripts/lib/transcript-record.ts +91 -0
  497. package/scripts/lines/effective-limit.ts +1 -1
  498. package/scripts/lint/eslint-cache-dependencies.ts +145 -0
  499. package/scripts/lint/eslint-daemon.ts +265 -0
  500. package/scripts/lint/format.ts +14 -5
  501. package/scripts/lint/import-graph.ts +279 -0
  502. package/scripts/lint/lint-gate-scope.ts +102 -0
  503. package/scripts/lint/lint-parallel-main.ts +19 -0
  504. package/scripts/lint/lint-parallel.ts +72 -33
  505. package/scripts/lint/lint-related-scope.ts +33 -24
  506. package/scripts/lint/lint-related.ts +38 -6
  507. package/scripts/notify/confirmation-options.ts +1 -2
  508. package/scripts/notify/telegram-notify.ts +20 -20
  509. package/scripts/notify/telegram-test-logic.ts +0 -1
  510. package/scripts/notify/telegram-test-main.ts +8 -0
  511. package/scripts/notify/telegram-test.ts +12 -11
  512. package/scripts/observations/observation-ledger.ts +13 -0
  513. package/scripts/observations/observations-flush-landing.ts +5 -3
  514. package/scripts/observations/observations-flush.ts +6 -1
  515. package/scripts/overrides/overrides-check.ts +2 -5
  516. package/scripts/overrides/overrides-files.ts +2 -1
  517. package/scripts/overrides/overrides-logic.ts +3 -6
  518. package/scripts/package/verify-optional-eslint-install.ts +8 -6
  519. package/scripts/propagate/propagate-publish.ts +2 -7
  520. package/scripts/propagate/propagate-targets.ts +4 -12
  521. package/scripts/refactor/import-graph.ts +9 -7
  522. package/scripts/release/github-release-runs.ts +17 -6
  523. package/scripts/release/release-approval-prune.ts +18 -0
  524. package/scripts/release/release-history.ts +1 -3
  525. package/scripts/release/release-progress.ts +42 -22
  526. package/scripts/release/release-publish-run.ts +39 -0
  527. package/scripts/release/release-publish.ts +6 -6
  528. package/scripts/release/release-scope-cli.ts +0 -10
  529. package/scripts/release/release-scope-main.ts +12 -0
  530. package/scripts/repo/repo-setting.ts +3 -6
  531. package/scripts/repo/required-checks-logic.ts +6 -15
  532. package/scripts/report/report-format-reference.ts +4 -0
  533. package/scripts/report/report-labels.ts +155 -0
  534. package/scripts/report/report-lint-cli.ts +3 -0
  535. package/scripts/report/report-lint.ts +85 -110
  536. package/scripts/report/report-template-cli.ts +59 -0
  537. package/scripts/report/report-template.ts +112 -0
  538. package/scripts/review/acceptance-map-check.ts +61 -0
  539. package/scripts/review/acceptance-map.ts +206 -0
  540. package/scripts/review/removed-tests-check.ts +86 -0
  541. package/scripts/review/removed-tests.ts +149 -0
  542. package/scripts/review/review-brief-cli.ts +82 -16
  543. package/scripts/review/review-brief-main.ts +12 -0
  544. package/scripts/review/review-brief.ts +31 -3
  545. package/scripts/review/review-code-tree.ts +10 -6
  546. package/scripts/review/review-comment-round.ts +26 -8
  547. package/scripts/review/review-finding-ledger.ts +30 -15
  548. package/scripts/review/review-interaction.ts +94 -0
  549. package/scripts/review/review-readers-scan.ts +163 -0
  550. package/scripts/review/review-record-cli.ts +69 -30
  551. package/scripts/review/review-record-main.ts +12 -0
  552. package/scripts/review/review-round-one-blobs.ts +221 -0
  553. package/scripts/review/review-round2-cli.ts +49 -12
  554. package/scripts/review/review-round2.ts +80 -12
  555. package/scripts/review/review-stamps.ts +19 -1
  556. package/scripts/review/review-stop-log.ts +96 -0
  557. package/scripts/review/review-stops-cli.ts +85 -0
  558. package/scripts/review/review-tree.ts +6 -17
  559. package/scripts/review/review-untouched-readers.ts +146 -0
  560. package/scripts/review/test-titles.ts +118 -0
  561. package/scripts/rules/agent-model.ts +67 -0
  562. package/scripts/rules/bash-triggers.ts +46 -3
  563. package/scripts/rules/decision-oracle-batch.ts +9 -1
  564. package/scripts/rules/decision-oracle.ts +2 -2
  565. package/scripts/rules/delivered-rules.ts +90 -3
  566. package/scripts/rules/destructive-command.ts +8 -1
  567. package/scripts/rules/direct-filing.ts +10 -2
  568. package/scripts/rules/direct-issue-comment.ts +117 -0
  569. package/scripts/rules/direct-pr-create.ts +69 -3
  570. package/scripts/rules/early-heartbeat.ts +2 -1
  571. package/scripts/rules/file-body.ts +7 -0
  572. package/scripts/rules/filing-cap.ts +8 -0
  573. package/scripts/rules/firing-point.ts +6 -5
  574. package/scripts/rules/git-argv.ts +72 -14
  575. package/scripts/rules/git-force.ts +12 -2
  576. package/scripts/rules/guard-remedy.ts +121 -0
  577. package/scripts/rules/implementation-cut-verdict.ts +1 -1
  578. package/scripts/rules/implementation-cut.ts +11 -3
  579. package/scripts/rules/index-guard.ts +8 -1
  580. package/scripts/rules/issue-comments.ts +76 -7
  581. package/scripts/rules/josh-git-bare.ts +7 -0
  582. package/scripts/rules/lane-background.ts +67 -25
  583. package/scripts/rules/lane-carry-conflict.ts +6 -0
  584. package/scripts/rules/lane-direct-tool.ts +74 -0
  585. package/scripts/rules/lane-interactive-ask.ts +9 -2
  586. package/scripts/rules/lane-park.ts +45 -23
  587. package/scripts/rules/lane-split-park.ts +10 -2
  588. package/scripts/rules/lane-switch-main.ts +7 -0
  589. package/scripts/rules/last-prompt.ts +50 -5
  590. package/scripts/rules/oracle-consulted.ts +10 -0
  591. package/scripts/rules/oracle-firing.ts +1 -0
  592. package/scripts/rules/oracle-list-cli.ts +7 -0
  593. package/scripts/rules/permission-guards.ts +3 -0
  594. package/scripts/rules/piped-verification.ts +4 -2
  595. package/scripts/rules/poll-loop.ts +7 -0
  596. package/scripts/rules/pr-merge.ts +123 -0
  597. package/scripts/rules/protected-files.ts +32 -5
  598. package/scripts/rules/raw-field-body.ts +6 -0
  599. package/scripts/rules/rule-body-guard.ts +8 -0
  600. package/scripts/rules/rule-list.ts +12 -28
  601. package/scripts/rules/rule-rewrite.ts +114 -0
  602. package/scripts/rules/rule-value-cache.ts +4 -9
  603. package/scripts/rules/rule-value-cli.ts +51 -32
  604. package/scripts/rules/rule-value.ts +8 -2
  605. package/scripts/rules/shell-segments.ts +50 -0
  606. package/scripts/rules/stop-decision.ts +77 -0
  607. package/scripts/rules/stop-rule-rows.ts +64 -0
  608. package/scripts/rules/stop-rules.ts +150 -51
  609. package/scripts/rules/tail-commands.ts +15 -1
  610. package/scripts/rules/test-declared-commit.ts +11 -1
  611. package/scripts/rules/third-party-write.ts +7 -0
  612. package/scripts/rules/timed-rerun.ts +69 -0
  613. package/scripts/rules/worktree-guard.ts +13 -3
  614. package/scripts/run/board/run-board-app-name.ts +23 -0
  615. package/scripts/run/board/run-board-cli.ts +65 -30
  616. package/scripts/run/board/run-board-closed.ts +8 -2
  617. package/scripts/run/board/run-board-earlier.ts +94 -0
  618. package/scripts/run/board/run-board-ending-reason.ts +67 -0
  619. package/scripts/run/board/run-board-estimate-schedule.ts +103 -0
  620. package/scripts/run/board/run-board-estimate.ts +98 -0
  621. package/scripts/run/board/run-board-fit.ts +153 -36
  622. package/scripts/run/board/run-board-fold.ts +123 -0
  623. package/scripts/run/board/run-board-fresh.ts +2 -2
  624. package/scripts/run/board/run-board-gather-live.ts +29 -0
  625. package/scripts/run/board/run-board-gather-thread.ts +189 -0
  626. package/scripts/run/board/run-board-gather-worker.ts +29 -0
  627. package/scripts/run/board/run-board-gather.ts +187 -0
  628. package/scripts/run/board/run-board-github.ts +119 -31
  629. package/scripts/run/board/run-board-header.ts +86 -21
  630. package/scripts/run/board/run-board-keys.ts +58 -0
  631. package/scripts/run/board/run-board-kind.ts +20 -6
  632. package/scripts/run/board/run-board-labels.ts +118 -71
  633. package/scripts/run/board/run-board-lane-state.ts +109 -0
  634. package/scripts/run/board/run-board-lane-time.ts +122 -0
  635. package/scripts/run/board/run-board-layout.ts +240 -61
  636. package/scripts/run/board/run-board-length.ts +52 -0
  637. package/scripts/run/board/run-board-machine.ts +8 -4
  638. package/scripts/run/board/run-board-main.ts +12 -0
  639. package/scripts/run/board/run-board-notes.ts +52 -31
  640. package/scripts/run/board/run-board-now.ts +1 -1
  641. package/scripts/run/board/run-board-operation.ts +15 -33
  642. package/scripts/run/board/run-board-phase.ts +1 -1
  643. package/scripts/run/board/run-board-plan-shared.ts +115 -0
  644. package/scripts/run/board/run-board-plan.ts +55 -3
  645. package/scripts/run/board/run-board-planning.ts +45 -0
  646. package/scripts/run/board/run-board-priority.ts +44 -0
  647. package/scripts/run/board/run-board-process-groups.ts +195 -0
  648. package/scripts/run/board/run-board-read.ts +153 -13
  649. package/scripts/run/board/run-board-reason.ts +238 -45
  650. package/scripts/run/board/run-board-released.ts +35 -0
  651. package/scripts/run/board/run-board-render-checks.ts +39 -5
  652. package/scripts/run/board/run-board-render-condition.ts +96 -0
  653. package/scripts/run/board/run-board-render-drawn.ts +67 -0
  654. package/scripts/run/board/run-board-render-foot.ts +59 -0
  655. package/scripts/run/board/run-board-render-icon.ts +35 -0
  656. package/scripts/run/board/run-board-render-lanes.ts +145 -0
  657. package/scripts/run/board/run-board-render-lead.ts +80 -0
  658. package/scripts/run/board/run-board-render-legend.ts +117 -47
  659. package/scripts/run/board/run-board-render-notes.ts +156 -29
  660. package/scripts/run/board/run-board-render-processes.ts +196 -0
  661. package/scripts/run/board/run-board-render-section.ts +119 -0
  662. package/scripts/run/board/run-board-render-slot.ts +3 -36
  663. package/scripts/run/board/run-board-render-tail.ts +115 -48
  664. package/scripts/run/board/run-board-render-time.ts +56 -0
  665. package/scripts/run/board/run-board-render-title.ts +117 -24
  666. package/scripts/run/board/run-board-render-waits.ts +125 -0
  667. package/scripts/run/board/run-board-render.ts +206 -259
  668. package/scripts/run/board/run-board-roots.ts +54 -0
  669. package/scripts/run/board/run-board-row-yield.ts +10 -4
  670. package/scripts/run/board/run-board-setup.ts +1 -12
  671. package/scripts/run/board/run-board-snapshot.ts +111 -0
  672. package/scripts/run/board/run-board-spin.ts +2 -2
  673. package/scripts/run/board/run-board-state.ts +23 -29
  674. package/scripts/run/board/run-board-status.ts +206 -79
  675. package/scripts/run/board/run-board-thanks-read.ts +2 -2
  676. package/scripts/run/board/run-board-tick.ts +123 -104
  677. package/scripts/run/board/run-board-usage-board.ts +78 -0
  678. package/scripts/run/board/run-board-usage-lanes.ts +113 -0
  679. package/scripts/run/board/run-board-usage-listing.ts +93 -0
  680. package/scripts/run/board/run-board-usage-read.ts +120 -150
  681. package/scripts/run/board/run-board-usage-rusage.ts +19 -7
  682. package/scripts/run/board/run-board-usage-text.ts +139 -51
  683. package/scripts/run/board/run-board-usage-top.ts +102 -0
  684. package/scripts/run/board/run-board-usage.ts +89 -72
  685. package/scripts/run/board/run-board-usual.ts +20 -9
  686. package/scripts/run/carry/run-carry-args.ts +4 -7
  687. package/scripts/run/carry/run-carry-conversation.ts +1 -1
  688. package/scripts/run/carry/run-carry.ts +9 -4
  689. package/scripts/run/cut/run-cut-cli.ts +3 -2
  690. package/scripts/run/cut/run-cut-handoff.ts +2 -2
  691. package/scripts/run/cut/run-cut-report.ts +16 -0
  692. package/scripts/run/detached-launch.ts +23 -4
  693. package/scripts/run/entry/run-entry-cli.ts +8 -1
  694. package/scripts/run/event/run-event-cli.ts +1 -5
  695. package/scripts/run/event/run-event-filed.ts +12 -6
  696. package/scripts/run/event/run-event-follow.ts +2 -3
  697. package/scripts/run/event/run-event-render.ts +7 -10
  698. package/scripts/run/event/run-event-scope.ts +20 -2
  699. package/scripts/run/event/run-event-stream-emit.ts +78 -11
  700. package/scripts/run/event/run-event-stream.ts +37 -7
  701. package/scripts/run/hold/run-hold-adopt.ts +65 -0
  702. package/scripts/run/hold/run-hold-cli.ts +93 -22
  703. package/scripts/run/hold/run-hold-main.ts +12 -0
  704. package/scripts/run/hold/run-hold-member.ts +37 -0
  705. package/scripts/run/hold/run-hold-session.ts +46 -0
  706. package/scripts/run/hold/run-hold.ts +7 -1
  707. package/scripts/run/hold/run-stop-notify.ts +183 -0
  708. package/scripts/run/launch-priority.ts +32 -0
  709. package/scripts/run/merge/run-merge-auth.ts +31 -0
  710. package/scripts/run/merge/run-merge-cli.ts +72 -107
  711. package/scripts/run/merge/run-merge-close.ts +74 -0
  712. package/scripts/run/merge/run-merge-collect.ts +6 -13
  713. package/scripts/run/merge/run-merge-driver.ts +71 -0
  714. package/scripts/run/merge/run-merge-main.ts +12 -0
  715. package/scripts/run/merge/run-merge-outcome.ts +23 -0
  716. package/scripts/run/merge/run-merge-restart.ts +39 -0
  717. package/scripts/run/merge/run-merge-ship.ts +20 -4
  718. package/scripts/run/merge/run-merge-signals.ts +123 -0
  719. package/scripts/run/merge/run-merge-steps.ts +128 -83
  720. package/scripts/run/merge/run-merge.ts +53 -40
  721. package/scripts/run/park/run-park-cli.ts +91 -0
  722. package/scripts/run/park/run-park.ts +88 -0
  723. package/scripts/run/park/run-stalled.ts +68 -0
  724. package/scripts/run/pause/run-pause-cli.ts +73 -0
  725. package/scripts/run/pause/run-pause.ts +251 -0
  726. package/scripts/run/progress/run-progress-cli.ts +4 -12
  727. package/scripts/run/progress/run-progress-clock.ts +1 -1
  728. package/scripts/run/progress/run-progress-config.ts +6 -14
  729. package/scripts/run/progress/run-progress-main.ts +12 -0
  730. package/scripts/run/progress/run-progress.ts +1 -4
  731. package/scripts/run/review/run-review.ts +2 -1
  732. package/scripts/run/run-ending.ts +1 -0
  733. package/scripts/run/run-invocation.ts +5 -6
  734. package/scripts/run/run-liveness-cli.ts +6 -8
  735. package/scripts/run/run-liveness.ts +61 -30
  736. package/scripts/run/run-next.ts +1 -1
  737. package/scripts/run/run-parent-cut-hook.ts +2 -2
  738. package/scripts/run/run-poll-hook.ts +157 -0
  739. package/scripts/run/run-preflight.ts +18 -3
  740. package/scripts/run/run-prep-cli.ts +1 -10
  741. package/scripts/run/run-prep-locate.ts +7 -50
  742. package/scripts/run/run-prep-main.ts +12 -0
  743. package/scripts/run/run-prep.ts +6 -0
  744. package/scripts/run/run-report-cli.ts +101 -13
  745. package/scripts/run/run-report-handoff.ts +114 -0
  746. package/scripts/run/run-step-cli.ts +22 -15
  747. package/scripts/run/run-step-section.ts +85 -0
  748. package/scripts/run/run-step.ts +1 -1
  749. package/scripts/run/run-stranded-detect.ts +13 -0
  750. package/scripts/run/run-watcher-guard-cli.ts +1 -1
  751. package/scripts/run/run-watcher-guard.ts +1 -1
  752. package/scripts/run/ship/run-ship-args.ts +121 -0
  753. package/scripts/run/ship/run-ship-body-draft.ts +110 -0
  754. package/scripts/run/ship/run-ship-cli.ts +67 -151
  755. package/scripts/run/ship/run-ship-detach.ts +27 -7
  756. package/scripts/run/ship/run-ship-infra-retry.ts +59 -0
  757. package/scripts/run/ship/run-ship-next.ts +27 -3
  758. package/scripts/run/ship/run-ship-overlap.ts +232 -0
  759. package/scripts/run/ship/run-ship-place.ts +96 -0
  760. package/scripts/run/ship/run-ship-pre-detach-timed.ts +43 -0
  761. package/scripts/run/ship/run-ship-pre-detach.ts +102 -27
  762. package/scripts/run/ship/run-ship-preflight.ts +161 -30
  763. package/scripts/run/ship/run-ship-probe.ts +11 -3
  764. package/scripts/run/ship/run-ship-relaunch-cap.ts +70 -0
  765. package/scripts/run/ship/run-ship-removed-rows.ts +61 -0
  766. package/scripts/run/ship/run-ship-return.ts +123 -15
  767. package/scripts/run/ship/run-ship-review-steps.ts +105 -149
  768. package/scripts/run/ship/run-ship-review.ts +73 -6
  769. package/scripts/run/ship/run-ship-reviewer.ts +207 -0
  770. package/scripts/run/ship/run-ship-stage.ts +55 -6
  771. package/scripts/run/ship/run-ship-steps.ts +46 -15
  772. package/scripts/run/ship/run-ship-stop-cause.ts +135 -0
  773. package/scripts/run/ship/run-ship-stop-context.ts +206 -0
  774. package/scripts/run/ship/run-ship-stop-text.ts +11 -6
  775. package/scripts/run/ship/run-ship-sync.ts +57 -12
  776. package/scripts/run/ship/run-ship.ts +30 -2
  777. package/scripts/run/tidy/run-tidy-cli.ts +0 -4
  778. package/scripts/run/tidy/run-tidy-lanes.ts +3 -0
  779. package/scripts/run/tidy/run-tidy-main.ts +8 -0
  780. package/scripts/run/wake/run-wake-cli.ts +119 -100
  781. package/scripts/run/wake/run-wake-code.ts +83 -0
  782. package/scripts/run/wake/run-wake-driver.ts +19 -8
  783. package/scripts/run/wake/run-wake-loop.ts +34 -3
  784. package/scripts/run/wake/run-wake-main.ts +13 -0
  785. package/scripts/run/wake/run-wake-ports.ts +90 -0
  786. package/scripts/run/wake/run-wake-takeover.ts +66 -0
  787. package/scripts/run/wake/run-wake.ts +2 -1
  788. package/scripts/safe-chain/pack-hook.ts +2 -2
  789. package/scripts/safe-chain/preinstall-command.ts +2 -1
  790. package/scripts/safe-chain/project-config.ts +3 -9
  791. package/scripts/security/security-audit-main.ts +8 -0
  792. package/scripts/security/security-audit-provision-logic.ts +0 -11
  793. package/scripts/security/security-audit-provision-main.ts +12 -0
  794. package/scripts/security/security-audit-provision.ts +11 -26
  795. package/scripts/security/security-audit.ts +6 -7
  796. package/scripts/self-sync-guard/self-sync-guard-logic.ts +6 -13
  797. package/scripts/split/split-assess-cli.ts +2 -2
  798. package/scripts/split/split-assess.ts +15 -0
  799. package/scripts/split/split-measure.ts +65 -0
  800. package/scripts/sync/claude-settings-merge.ts +8 -15
  801. package/scripts/sync/directory-copy-guard.ts +4 -9
  802. package/scripts/sync/file-content.ts +78 -8
  803. package/scripts/sync/sync-ai-files.ts +3 -5
  804. package/scripts/sync/sync-configs.ts +11 -23
  805. package/scripts/sync/sync-hook-safety.ts +4 -10
  806. package/scripts/sync/sync-main.ts +11 -0
  807. package/scripts/sync/sync.ts +25 -37
  808. package/scripts/test/test-declared-changed.ts +2 -2
  809. package/scripts/test/test-declared.ts +1 -1
  810. package/scripts/test/test-e2e-guard.ts +55 -6
  811. package/scripts/test/test-e2e-stamp.ts +38 -0
  812. package/scripts/test/test-pinned-logic.ts +145 -0
  813. package/scripts/test/test-pinned-main.ts +78 -0
  814. package/scripts/test/test-pinned.ts +100 -0
  815. package/scripts/test/test-read-map.ts +264 -0
  816. package/scripts/test/test-read-recording.ts +91 -0
  817. package/scripts/test/test-read-trace.ts +148 -0
  818. package/scripts/test/test-red-main.ts +12 -0
  819. package/scripts/test/test-red.ts +12 -30
  820. package/scripts/test/test-related-main.ts +18 -0
  821. package/scripts/test/test-related-record.ts +119 -0
  822. package/scripts/test/test-related-scope.ts +229 -43
  823. package/scripts/test/test-related.ts +300 -22
  824. package/scripts/test/test-unit-guard-main.ts +15 -0
  825. package/scripts/test/test-unit-guard.ts +54 -21
  826. package/scripts/test/unit-count-file.ts +37 -0
  827. package/scripts/test/unit-run-marker.ts +162 -0
  828. package/scripts/test/unit-setup-files.ts +51 -0
  829. package/scripts/test/unit-worker-share.ts +71 -137
  830. package/scripts/test/whole-suite-files.ts +63 -0
  831. package/scripts/time-runtime/time-background.ts +20 -2
  832. package/scripts/time-runtime/time-bundles.ts +4 -3
  833. package/scripts/time-runtime/time-density-hook.ts +8 -6
  834. package/scripts/time-runtime/time-followup-stage.ts +1 -3
  835. package/scripts/time-runtime/time-format.ts +5 -28
  836. package/scripts/time-runtime/time-markers.ts +10 -1
  837. package/scripts/time-runtime/time-shell.ts +126 -14
  838. package/scripts/time-runtime/time-spans.ts +1 -0
  839. package/scripts/time-runtime/time-tool-call.ts +7 -0
  840. package/scripts/time-runtime/time-transcript-line.ts +49 -62
  841. package/scripts/uninstall/uninstall.ts +1 -1
  842. package/scripts/version/bump-version-main.ts +12 -0
  843. package/scripts/version/bump-version.ts +25 -25
  844. package/scripts/version/effective-upstream.ts +6 -12
  845. package/scripts/version/latest-corepack.ts +17 -32
  846. package/scripts/version/latest-if-required-cli.ts +93 -0
  847. package/scripts/version/latest-lane-guard-main.ts +8 -0
  848. package/scripts/version/latest-lane-guard.ts +0 -4
  849. package/scripts/version/latest-scope-cli.ts +0 -9
  850. package/scripts/version/latest-scope-main.ts +12 -0
  851. package/scripts/version/latest-update.ts +5 -5
  852. package/scripts/version/npm-registry.ts +44 -6
  853. package/scripts/version/publishable-range-check.ts +5 -16
  854. package/scripts/version/release-age.ts +1 -1
  855. package/scripts/version/release-hold.ts +1 -1
  856. package/scripts/version/release-window.ts +38 -0
  857. package/scripts/version/running-binary.ts +1 -1
  858. package/scripts/version/safe-chain-version-update.ts +3 -8
  859. package/scripts/version/version-targets.ts +6 -28
  860. package/templates/dependabot.yml +29 -0
  861. package/templates/gitignore +10 -3
  862. package/templates/pnpm-workspace.basic.yaml +1 -1
  863. package/templates/sonar-project.properties +3 -2
  864. package/templates/workflows/ci.yml +12 -4
  865. package/templates/workflows/github-release.yml +4 -0
  866. package/tsconfig.sonar.json +1 -1
  867. package/.ncurc.json +0 -3
  868. package/dist/hooks/batch-guard.js +0 -29
  869. package/dist/hooks/chunk-43ZHT22P.js +0 -3495
  870. package/dist/hooks/chunk-CDY4NFQG.js +0 -15
  871. package/dist/hooks/chunk-EUMACUK2.js +0 -2038
  872. package/dist/hooks/chunk-H5HVWYXK.js +0 -359
  873. package/dist/hooks/chunk-IIGFYXKC.js +0 -7104
  874. package/dist/hooks/chunk-IX6TTTI6.js +0 -95
  875. package/dist/hooks/chunk-J47HU5H5.js +0 -237
  876. package/dist/hooks/chunk-K4EOONYM.js +0 -45
  877. package/dist/hooks/chunk-K4LMBQC2.js +0 -68
  878. package/dist/hooks/chunk-SHGPANFB.js +0 -56
  879. package/dist/hooks/chunk-YHBZAJSV.js +0 -79
  880. package/dist/hooks/chunk-YYPI7SJZ.js +0 -131
  881. package/dist/hooks/duplicate-read-guard.js +0 -30
  882. package/dist/hooks/investigation-guard.js +0 -32
  883. package/scripts/backlog/backlog-stalled-cli.ts +0 -30
  884. package/scripts/cost-runtime/cost-format.ts +0 -29
  885. package/scripts/init/basic-path-migration.ts +0 -24
  886. package/scripts/issue/issue-backlinks-cli.ts +0 -93
  887. package/scripts/josh/josh-commands-guard.ts +0 -38
  888. package/scripts/lint/cross-file-recheck.ts +0 -155
  889. package/scripts/registry-migration/migrate-logic.ts +0 -237
  890. package/scripts/registry-migration/migrate.ts +0 -292
  891. package/scripts/registry-migration/user-npmrc.ts +0 -15
  892. package/scripts/rules/rule-guard.ts +0 -23
  893. package/scripts/rules/rule-registry-rows.ts +0 -282
  894. package/scripts/rules/rule-registry.ts +0 -109
  895. package/scripts/run/run-stranded-cli.ts +0 -27
@@ -0,0 +1,183 @@
1
+ import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
2
+ import { issue_cite } from '#scripts/issue/issue-cite'
3
+ import { issue_number_shape } from '#scripts/issue/issue-number-shape'
4
+ import { issue_state_cli } from '#scripts/issue/issue-state-cli'
5
+ import { session_cite } from '#scripts/issue/session-cite'
6
+ import { run_event_stream } from '#scripts/run/event/run-event-stream'
7
+ import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
8
+ import { run_label } from '#scripts/run/run-label'
9
+ import { lane_close, type CloseKind } from './lane-close'
10
+ import { lane_preserve, type KeptWork } from './lane-preserve'
11
+ import { lane_reap } from './lane-reap'
12
+ import { lane_registry, type LaneInfo } from './lane-registry'
13
+ import { lane_residents } from './lane-residents'
14
+ import { lane_state } from './lane-state'
15
+
16
+ // `josh lane:withdraw <N> --reason <text>` — a person takes a running lane child's issue out of the
17
+ // current run: the child is stopped, its work stashed and the lane closed. **The Issue stays open** —
18
+ // a withdrawal ends this run's attempt, not the work — so a later run offers it again; this run does
19
+ // not (`backlog-drive-restore.ts` → `offer_exclude`, and the drive's own exclusion).
20
+ //
21
+ // **The `withdraw` event is written first, before anything is stopped.** Killing the child alone would
22
+ // let `lane:await` book it stopped and `run:merge` classify it from GitHub — an open issue resumed as an
23
+ // `outage` or parked `run:stalled`. `run:merge` reads the event stream before GitHub, so a child whose
24
+ // newest launch-or-withdraw event is a withdraw is booked `withdrawn` whatever the Issue's state reads.
25
+ //
26
+ // A tree that could not be stashed is left in place: closing the lane would delete the work, and the
27
+ // person decides what to keep.
28
+
29
+ const WITHDRAW_OCCASION = 'lane withdraw'
30
+ const WITHDRAW_CAUSE = 'a person withdrew it with `lane:withdraw`'
31
+ const CLOSED_STATE = 'CLOSED'
32
+ const CLOSED_KIND = 'closed'
33
+ const NO_LANE_KIND = 'no-lane'
34
+ const UNREADABLE_KIND = 'unreadable'
35
+
36
+ type Unsaved = Extract<KeptWork, { kind: 'unsaved' }>
37
+
38
+ interface Withdrawn {
39
+ kind: 'withdrawn'
40
+ // How many of the child's processes the withdrawal stopped — 0 for a child that had already ended.
41
+ reaped: number
42
+ stash: string | undefined
43
+ // Whether the comment saying the issue stays open reached it.
44
+ is_noted: boolean
45
+ lane: CloseKind
46
+ // What else the close ended from the checkout; `undefined` where it could not be read.
47
+ residents: ReadonlyArray<number> | undefined
48
+ }
49
+
50
+ type Refused =
51
+ { kind: typeof CLOSED_KIND } | { kind: typeof NO_LANE_KIND } | { kind: typeof UNREADABLE_KIND }
52
+ type WithdrawOutcome = Withdrawn | Unsaved | Refused
53
+
54
+ function withdraw_comment(reason: string): string {
55
+ return [
56
+ 'Withdrawn from the current run by a person with `pnpm josh lane:withdraw`.',
57
+ 'Its lane child was stopped and the lane closed. The Issue stays open: this run does not resume it, and the next run offers it again.',
58
+ `- Why: ${reason}`,
59
+ ].join('\n')
60
+ }
61
+
62
+ async function record_withdraw(issue: string, reason: string): Promise<void> {
63
+ await run_event_stream_emit.emit(
64
+ run_event_stream.EVENT_KIND.WITHDRAW,
65
+ `${issue_cite.plain(issue)} withdrawn by a person: ${reason}`,
66
+ )
67
+ }
68
+
69
+ // A closed issue has nothing to withdraw, and an unread one might be: neither writes anything.
70
+ async function refusal_of(issue: string): Promise<Refused | undefined> {
71
+ const read = await issue_state_cli.read_issue(issue)
72
+
73
+ if (read.kind !== 'state') return { kind: UNREADABLE_KIND }
74
+ if (read.state.state.toUpperCase() === CLOSED_STATE) return { kind: CLOSED_KIND }
75
+
76
+ return undefined
77
+ }
78
+
79
+ async function note_issue(
80
+ issue: string,
81
+ reason: string,
82
+ stash: string | undefined,
83
+ ): Promise<boolean> {
84
+ const is_noted = await git_gh_issue_write.issue_try_comment(issue, withdraw_comment(reason))
85
+
86
+ if (stash !== undefined) await lane_preserve.announce(issue, stash, WITHDRAW_CAUSE)
87
+ await run_label.unmark(issue)
88
+
89
+ return is_noted
90
+ }
91
+
92
+ async function stop_and_close(lane: LaneInfo, reason: string): Promise<WithdrawOutcome> {
93
+ await record_withdraw(lane.issue, reason)
94
+ const reaped = lane_reap.reap_child(lane).length
95
+ const saved = await lane_preserve.keep_work(lane.issue, lane.directory, WITHDRAW_OCCASION)
96
+
97
+ if (saved.kind === 'unsaved') return saved
98
+ const is_noted = await note_issue(lane.issue, reason, saved.stash)
99
+ const closed = await lane_close.close_lane(lane.issue)
100
+
101
+ // After the close, so the record names the withdrawal rather than the close it ran. An `incomplete`
102
+ // close is not `ended`: the supervisor closes the lane again until its last process is gone.
103
+ if (closed.kind !== 'incomplete') {
104
+ await lane_state.record_change({ issue: lane.issue, state: 'ended', command: 'lane:withdraw' })
105
+ }
106
+
107
+ return {
108
+ kind: 'withdrawn',
109
+ reaped,
110
+ stash: saved.stash,
111
+ is_noted,
112
+ lane: closed.kind,
113
+ residents: closed.residents,
114
+ }
115
+ }
116
+
117
+ /** Stop `#<N>`'s lane child, stash its work and close the lane, leaving the Issue open. */
118
+ async function withdraw(issue: string, reason: string): Promise<WithdrawOutcome> {
119
+ issue_number_shape.require_issue_number(issue)
120
+ const refusal = await refusal_of(issue)
121
+
122
+ if (refusal !== undefined) return refusal
123
+ const lane = await lane_registry.find_open_lane(issue)
124
+
125
+ if (lane === undefined) return { kind: NO_LANE_KIND }
126
+
127
+ return await stop_and_close(lane, reason)
128
+ }
129
+
130
+ function stash_sentence(stash: string | undefined): string {
131
+ if (stash === undefined) return 'The lane held no uncommitted work.'
132
+
133
+ return `Its uncommitted work was stashed — recover with \`pnpm josh stash:pop "${stash}"\`.`
134
+ }
135
+
136
+ // What the lane's close left or ended, as a suffix.
137
+ function lane_suffix(outcome: Withdrawn, cited: string): string {
138
+ const removed = outcome.lane === 'incomplete' ? ' The lane could not be fully removed.' : ''
139
+ const residents = lane_residents.residents_sentence(outcome.residents, cited)
140
+
141
+ return residents === undefined ? removed : `${removed} ${residents}`
142
+ }
143
+
144
+ function withdrawn_text(outcome: Withdrawn, issue: string): string {
145
+ const cited = session_cite.issue(issue)
146
+ const stopped = outcome.reaped === 0 ? 'Its child had already ended.' : 'Stopped its child.'
147
+ const head = `Withdrew ${cited}. ${stopped} ${stash_sentence(outcome.stash)}`
148
+ const lane = lane_suffix(outcome, cited)
149
+ const noted = outcome.is_noted ? '' : ' The comment saying so could not be posted.'
150
+
151
+ return `${head} The Issue stays open: this run does not offer it again, the next run does.${noted}${lane}`
152
+ }
153
+
154
+ function unsaved_text(outcome: Unsaved, issue: string): string {
155
+ return `The child for ${session_cite.issue(issue)} was stopped, but its uncommitted work could not be stashed (${outcome.reason}), so the lane is left at ${outcome.directory}; \`run:merge\` books it withdrawn.`
156
+ }
157
+
158
+ function refused_text(outcome: Refused, issue: string): string {
159
+ const cited = session_cite.issue(issue)
160
+
161
+ if (outcome.kind === CLOSED_KIND) {
162
+ return `${cited} is already closed, so there is nothing to withdraw.`
163
+ }
164
+
165
+ if (outcome.kind === NO_LANE_KIND) {
166
+ return `No lane is open for ${cited}, so there is no child to withdraw.`
167
+ }
168
+
169
+ return `The state of ${cited} could not be read, so nothing was stopped or closed — try again.`
170
+ }
171
+
172
+ function describe(outcome: WithdrawOutcome, issue: string): string {
173
+ if (outcome.kind === 'unsaved') return unsaved_text(outcome, issue)
174
+
175
+ return outcome.kind === 'withdrawn'
176
+ ? withdrawn_text(outcome, issue)
177
+ : refused_text(outcome, issue)
178
+ }
179
+
180
+ const lane_withdraw = { describe, withdraw }
181
+
182
+ export type { WithdrawOutcome }
183
+ export { lane_withdraw }
@@ -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 }