@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
@@ -2,7 +2,7 @@ import { spawnSync } from 'node:child_process'
2
2
  import { setTimeout as sleep } from 'node:timers/promises'
3
3
  import { parseArgs } from 'node:util'
4
4
  import { issue_number_shape } from '#scripts/issue/issue-number-shape'
5
- import { PROBE_TIMEOUT_MS } from '#scripts/lib/timeouts'
5
+ import { MS_PER_SECOND, PROBE_TIMEOUT_MS } from '#scripts/lib/timeouts'
6
6
  import {
7
7
  PROCESS_ALIVE,
8
8
  PROCESS_NONE,
@@ -28,7 +28,6 @@ import { process_tools } from './process-tools'
28
28
  const RECONFIRM_MS = 15_000
29
29
  const DEFAULT_POLL_MS = 5000
30
30
  const NEVER_APPEARED_TIMEOUT_MS = 600_000
31
- const MS_PER_SECOND = 1000
32
31
  const PROCESS_FOUND = 0
33
32
  const PROCESS_NOT_FOUND = 1
34
33
  const PGREP_COMMAND = 'pgrep'
@@ -36,8 +35,14 @@ const PGREP_COMMAND = 'pgrep'
36
35
  // `is_settled` is read once, when the wait starts: a child that ended between two `lane:await` calls
37
36
  // never appears in the second one, and only its settled issue tells it apart from one not yet
38
37
  // launched.
38
+ //
39
+ // `alive_since` is when this run of the child was first seen alive: a ship it launched is no older, so
40
+ // a ship record launched earlier is a past dispatch's (joshuafolkken/kit#4395). A child already alive
41
+ // when the watch began gets the first poll's time, so a ship it launched before that is not read as
42
+ // its own and its disappearance waits out the re-confirm window.
39
43
  interface AwaitState {
40
44
  appeared: boolean
45
+ alive_since?: number | undefined
41
46
  disappeared_at: number | undefined
42
47
  first_polled_at: number | undefined
43
48
  is_settled?: boolean
@@ -56,6 +61,7 @@ interface RawAwaitArguments {
56
61
  // Injectable for testing -- the CLI never overrides these.
57
62
  interface AwaitOptions {
58
63
  is_running?: (issue: string) => boolean
64
+ is_shipped?: (issue: string, since_ms: number) => boolean
59
65
  is_settled?: (issue: string) => Promise<boolean>
60
66
  poll_ms?: number
61
67
  reconfirm_ms?: number
@@ -64,8 +70,11 @@ interface AwaitOptions {
64
70
  sleep?: (ms: number) => Promise<void>
65
71
  }
66
72
 
73
+ // `is_shipped` is the one disappearance the re-confirm window never has to cover: a ship that ended in
74
+ // success merged the child's work, so no cut hand-off can follow it (joshuafolkken/kit#4395).
67
75
  interface CheckConfig {
68
76
  is_running: (issue: string) => boolean
77
+ is_shipped?: (issue: string, since_ms: number) => boolean
69
78
  reconfirm_ms: number
70
79
  never_appeared_timeout_ms: number
71
80
  }
@@ -100,6 +109,10 @@ function is_process_running_default(issue: string): boolean {
100
109
  return process_trace_default(issue) === PROCESS_ALIVE
101
110
  }
102
111
 
112
+ function is_shipped_default(issue: string, since_ms: number): boolean {
113
+ return lane_handoff.is_ship_succeeded(issue, process.cwd(), since_ms)
114
+ }
115
+
103
116
  // The same positive evidence `run:liveness` answers `settled` on: the issue closed, or it was parked.
104
117
  async function is_settled_default(issue: string): Promise<boolean> {
105
118
  return (await run_liveness.read_child_settled(issue)) === true
@@ -164,9 +177,16 @@ function resolve_timing(
164
177
  }
165
178
  }
166
179
 
167
- function resolve_options(options: AwaitOptions): RunConfig {
180
+ function resolve_probes(options: AwaitOptions): Pick<RunConfig, 'is_running' | 'is_shipped'> {
168
181
  return {
169
182
  is_running: options.is_running ?? is_process_running_default,
183
+ is_shipped: options.is_shipped ?? is_shipped_default,
184
+ }
185
+ }
186
+
187
+ function resolve_options(options: AwaitOptions): RunConfig {
188
+ return {
189
+ ...resolve_probes(options),
170
190
  is_settled: options.is_settled ?? is_settled_default,
171
191
  now: options.now ?? Date.now,
172
192
  sleep: options.sleep ?? sleep,
@@ -174,9 +194,11 @@ function resolve_options(options: AwaitOptions): RunConfig {
174
194
  }
175
195
  }
176
196
 
177
- function update_liveness(state: AwaitState, is_live: boolean): void {
197
+ function update_liveness(state: AwaitState, is_live: boolean, now_ms: number): void {
178
198
  if (!is_live) return
179
199
 
200
+ if (!state.appeared || state.disappeared_at !== undefined) state.alive_since = now_ms
201
+
180
202
  state.appeared = true
181
203
  state.disappeared_at = undefined
182
204
  }
@@ -203,6 +225,28 @@ function check_not_appeared(
203
225
  return undefined
204
226
  }
205
227
 
228
+ // The ship this run of the child launched succeeded.
229
+ function is_own_ship_done(issue: string, state: AwaitState, config: CheckConfig): boolean {
230
+ const { alive_since } = state
231
+
232
+ return alive_since !== undefined && config.is_shipped?.(issue, alive_since) === true
233
+ }
234
+
235
+ // A child that appeared and is gone: done at once when its ship succeeded, else once it stayed gone
236
+ // past the re-confirm window.
237
+ function check_gone(
238
+ issue: string,
239
+ state: AwaitState,
240
+ now_ms: number,
241
+ config: CheckConfig,
242
+ ): string | undefined {
243
+ if (is_own_ship_done(issue, state, config)) return issue
244
+
245
+ state.disappeared_at ??= now_ms
246
+
247
+ return now_ms - state.disappeared_at >= config.reconfirm_ms ? issue : undefined
248
+ }
249
+
206
250
  // Returns the issue that has confirmed-completed this tick, `undefined` if none yet.
207
251
  // The `appeared` guard prevents a process that never showed up from being declared done, unless its
208
252
  // issue had already settled when the wait started.
@@ -214,7 +258,7 @@ function check_issue(
214
258
  ): string | undefined {
215
259
  const is_live = config.is_running(issue)
216
260
 
217
- update_liveness(state, is_live)
261
+ update_liveness(state, is_live, now_ms)
218
262
 
219
263
  if (is_live) return undefined
220
264
 
@@ -222,13 +266,7 @@ function check_issue(
222
266
  return check_not_appeared(issue, state, now_ms, config.never_appeared_timeout_ms)
223
267
  }
224
268
 
225
- if (state.disappeared_at === undefined) {
226
- state.disappeared_at = now_ms
227
-
228
- return undefined
229
- }
230
-
231
- return now_ms - state.disappeared_at >= config.reconfirm_ms ? issue : undefined
269
+ return check_gone(issue, state, now_ms, config)
232
270
  }
233
271
 
234
272
  function check_any(
@@ -267,6 +305,7 @@ const lane_await = {
267
305
  RECONFIRM_MS,
268
306
  check_issue,
269
307
  is_process_running_default,
308
+ is_shipped_default,
270
309
  parse_arguments,
271
310
  process_trace_default,
272
311
  wait_for_any,
@@ -1,13 +1,4 @@
1
- import { randomUUID } from 'node:crypto'
2
- import {
3
- cpSync,
4
- existsSync,
5
- mkdirSync,
6
- readFileSync,
7
- renameSync,
8
- rmSync,
9
- writeFileSync,
10
- } from 'node:fs'
1
+ import { cpSync, existsSync, readFileSync } from 'node:fs'
11
2
  import path from 'node:path'
12
3
  import { hook_launch } from '#scripts/init/hook-launch'
13
4
  import {
@@ -15,6 +6,7 @@ import {
15
6
  SHARED_CACHE_SPECS,
16
7
  type GateCacheSpec,
17
8
  } from '#scripts/josh/josh-command-types'
9
+ import { atomic_write } from '#scripts/lib/atomic-write'
18
10
 
19
11
  // Warming a fresh lane's verification caches from the main checkout.
20
12
  //
@@ -75,30 +67,13 @@ function portable_content(
75
67
  // runs in parallel with the tool whose cache is being copied, and a temporary name in the checkout
76
68
  // root is listed by its tree walk and gone by the time it is read (#3763). `node_modules` is skipped
77
69
  // by every tree scan and sits on the checkout's own filesystem, so the rename stays atomic.
78
- function stage_path(destination_root: string, cache_file: string): string {
79
- const staging_directory = path.join(destination_root, ...STAGING_SEGMENTS)
80
-
81
- mkdirSync(staging_directory, { recursive: true })
82
-
83
- return path.join(staging_directory, `${cache_file}.${String(process.pid)}.${randomUUID()}.tmp`)
84
- }
85
-
86
- function publish_staged(temporary_path: string, destination_path: string, content: string): void {
87
- try {
88
- writeFileSync(temporary_path, content, { flag: 'wx' })
89
- renameSync(temporary_path, destination_path)
90
- } finally {
91
- rmSync(temporary_path, { force: true })
92
- }
93
- }
94
-
95
70
  function write_atomically(destination_root: string, cache_file: string, content: string): void {
96
71
  if (!existsSync(destination_root)) return
97
72
 
98
73
  try {
99
- const temporary_path = stage_path(destination_root, cache_file)
100
-
101
- publish_staged(temporary_path, path.join(destination_root, cache_file), content)
74
+ atomic_write.replace_file(path.join(destination_root, cache_file), content, {
75
+ staging_directory: path.join(destination_root, ...STAGING_SEGMENTS),
76
+ })
102
77
  } catch {
103
78
  // Best-effort: a cache that could not be published simply leaves the destination unchanged.
104
79
  }
@@ -1,3 +1,4 @@
1
+ import { cli_flags, type PositiveSetting } from '#scripts/lib/cli-flags'
1
2
  import { lane_limit_override } from './lane-limit-override'
2
3
  import type { LaneEnvironment } from './lane-paths'
3
4
  import { lane_seed_policy } from './lane-seed'
@@ -21,32 +22,16 @@ import { lane_seed_policy } from './lane-seed'
21
22
  // the swap peak, the slowest gates and most of the gate and commit failures.
22
23
  const DEFAULT_LANE_LIMIT = 4
23
24
  const LANE_LIMIT_KEY = 'JOSH_LANE_LIMIT'
24
- const POSITIVE_INTEGER = /^[1-9]\d*$/u
25
25
  const NO_LANES = 0
26
26
 
27
- // The limit, or why it could not be read. A problem rather than a throw, for the reason
28
- // `eval-runner.ts` records for `JOSH_EVAL_CONCURRENCY`: the caller decides whether a bad setting
29
- // ends the command or is reported and worked around, and only it knows which.
30
- type LimitChoice = { kind: 'limit'; limit: number } | { kind: 'problem'; problem: string }
27
+ // The limit, or why it could not be read.
28
+ type LimitChoice = PositiveSetting
31
29
 
32
30
  // **An invalid value is a hard error, never a silent fall back to the default** — the rule
33
- // `PORT_SEED` already holds to. A typo that quietly becomes 4 is a limit nobody set, and the whole
34
- // point of the setting is that the number is the one a person chose.
35
- //
36
- // Blank is unset, not invalid: an `.env` line left as `JOSH_LANE_LIMIT=` is a variable nobody
37
- // configured, exactly as `lane_paths.lane_root` reads a blank root.
38
- //
39
- // `name` is what the problem names: `josh lane:limit` reads its argument by the same rule.
31
+ // `PORT_SEED` already holds to. `name` is what the problem names: `josh lane:limit` reads its argument
32
+ // by the same rule.
40
33
  function read_limit(raw: string | undefined, name: string): LimitChoice {
41
- const trimmed = raw?.trim() ?? ''
42
-
43
- if (trimmed === '') return { kind: 'limit', limit: DEFAULT_LANE_LIMIT }
44
-
45
- if (!POSITIVE_INTEGER.test(trimmed)) {
46
- return { kind: 'problem', problem: `${name} must be a positive integer, not "${trimmed}"` }
47
- }
48
-
49
- return { kind: 'limit', limit: Number(trimmed) }
34
+ return cli_flags.read_positive_setting(raw, name, DEFAULT_LANE_LIMIT)
50
35
  }
51
36
 
52
37
  // **A live run's `lane:limit` override outranks the environment**: a running
@@ -76,17 +61,23 @@ function seated_limit(limit: number): number {
76
61
  //
77
62
  // **A lane that holds no place under the limit still holds its port seat** (joshuafolkken/kit#3967):
78
63
  // `seated` counts every open lane, so the free count never offers more launches than seats are left.
64
+ // The places left under the limit, port seats aside: what resuming a lane that keeps its seat is
65
+ // weighed against (joshuafolkken/kit#4107).
66
+ function limit_room(limit: number, occupied: number): number {
67
+ return Math.max(NO_LANES, seated_limit(limit) - occupied)
68
+ }
69
+
79
70
  function free_lanes(limit: number, occupied: number, seated = occupied): number {
80
- const by_limit = seated_limit(limit) - occupied
81
71
  const by_seats = lane_seed_policy.LAST_LANE_SEAT - seated
82
72
 
83
- return Math.max(NO_LANES, Math.min(by_limit, by_seats))
73
+ return Math.max(NO_LANES, Math.min(limit_room(limit, occupied), by_seats))
84
74
  }
85
75
 
86
76
  const lane_capacity = {
87
77
  LANE_LIMIT_KEY,
88
78
  free_lanes,
89
79
  lane_limit,
80
+ limit_room,
90
81
  read_limit,
91
82
  seated_limit,
92
83
  }
@@ -1,17 +1,26 @@
1
+ import { MS_PER_SECOND } from '#scripts/lib/timeouts'
1
2
  import { lane_ledger, type GateCheckRecord, type GateEntry, type LedgerEntry } from './lane-ledger'
2
3
  import { lane_stage_stats } from './lane-stage-stats'
3
4
  import { lane_stats, type StatsWindow } from './lane-stats'
4
5
 
5
- // Which check a gate waited on: the ledger's per-check rows of one period reduced to one row per check
6
- // — median, maximum, how many runs and how many were reused — printed last by `josh lane:stats`. The
7
- // rows are in the order the checks first appear.
6
+ // Which check a gate waited on: one period's per-check rows reduced to one row per check — median,
7
+ // maximum, runs, reuses, no-ops and whole-suite fallbacks — printed last by `josh lane:stats`.
8
+ //
9
+ // The whole gate is the first row, since its reuse started no check (joshuafolkken/kit#4397); the
10
+ // checks follow in the order they first appear.
8
11
  //
9
12
  // **A reused check is counted, never timed.** It started no process, so its zero would pull the median
10
- // toward a check that never ran; a check with only reused rows prints `not measured`.
13
+ // toward a check that never ran; a check with only reused rows prints `not measured`. **The unit leg's
14
+ // since-green no-op is counted the same way** (joshuafolkken/kit#4457): it ran no test, so its second
15
+ // would stand for a run that tested nothing.
16
+ //
17
+ // **The fallbacks are broken down by why** in a second table, one row per reason kind, so a slow unit
18
+ // leg can be read as the full suite it ran and the reason it had to.
11
19
 
12
- const MS_PER_SECOND = 1000
13
20
  const DECIMALS = 1
14
- const COLUMNS = ['check', 'median (s)', 'max (s)', 'runs', 'reused'] as const
21
+ const WHOLE_GATE_LABEL = 'gate (whole)'
22
+ const COLUMNS = ['check', 'median (s)', 'max (s)', 'runs', 'reused', 'no-op', 'fallback'] as const
23
+ const FALLBACK_COLUMNS = ['fallback reason', 'runs'] as const
15
24
 
16
25
  function is_gate(entry: LedgerEntry): entry is GateEntry {
17
26
  return entry.kind === lane_ledger.KIND.GATE
@@ -23,34 +32,66 @@ function cell(milliseconds: number | undefined): string {
23
32
  : (milliseconds / MS_PER_SECOND).toFixed(DECIMALS)
24
33
  }
25
34
 
35
+ function header(columns: ReadonlyArray<string>): Array<string> {
36
+ return [lane_stats.to_row(columns), lane_stats.to_row(columns.map(() => '---'))]
37
+ }
38
+
39
+ function count(
40
+ runs: ReadonlyArray<GateCheckRecord>,
41
+ is_counted: (check: GateCheckRecord) => boolean,
42
+ ): string {
43
+ return String(runs.filter((check) => is_counted(check)).length)
44
+ }
45
+
26
46
  function check_row(label: string, checks: ReadonlyArray<GateCheckRecord>): string {
27
47
  const runs = checks.filter((check) => check.label === label)
28
- const timed = runs.filter((check) => check.is_reused !== true).map((check) => check.elapsed_ms)
48
+ const timed = runs.filter((check) => check.is_reused !== true && check.is_unmoved !== true)
49
+ const elapsed = timed.map((check) => check.elapsed_ms)
29
50
 
30
51
  return lane_stats.to_row([
31
52
  label,
32
- cell(lane_stats.median(timed)),
33
- cell(lane_stats.peak(timed)),
53
+ cell(lane_stats.median(elapsed)),
54
+ cell(lane_stats.peak(elapsed)),
34
55
  String(runs.length),
35
- String(runs.length - timed.length),
56
+ count(runs, (check) => check.is_reused === true),
57
+ count(runs, (check) => check.is_unmoved === true),
58
+ count(runs, (check) => check.fallback !== undefined),
36
59
  ])
37
60
  }
38
61
 
39
- // The period's table: `entries` is the whole ledger, filtered here to `window`.
62
+ // The whole gate read as one more check, so its reuse is counted the way a check's is.
63
+ function whole_gate(gate: GateEntry): GateCheckRecord {
64
+ return {
65
+ label: WHOLE_GATE_LABEL,
66
+ elapsed_ms: gate.elapsed_ms,
67
+ is_passed: gate.is_passed,
68
+ is_reused: gate.is_reused,
69
+ }
70
+ }
71
+
72
+ function fallback_table(checks: ReadonlyArray<GateCheckRecord>): string {
73
+ const reasons = checks.map((check) => check.fallback).filter((reason) => reason !== undefined)
74
+ const kinds = [...new Set(reasons)]
75
+ const rows = kinds.map((kind) =>
76
+ lane_stats.to_row([kind, String(reasons.filter((reason) => reason === kind).length)]),
77
+ )
78
+
79
+ return [...header(FALLBACK_COLUMNS), ...rows].join('\n')
80
+ }
81
+
82
+ // The period's tables: `entries` is the whole ledger, filtered here to `window`.
40
83
  function table(entries: ReadonlyArray<LedgerEntry>, window: StatsWindow): string {
41
- const checks = lane_stats
42
- .in_window(entries, window)
43
- .filter(is_gate)
44
- .flatMap((gate) => gate.checks ?? [])
45
- const labels = [...new Set(checks.map((check) => check.label))]
84
+ const gates = lane_stats.in_window(entries, window).filter(is_gate)
85
+ const checks = gates.flatMap((gate) => gate.checks ?? [])
86
+ const rows = [...gates.map((gate) => whole_gate(gate)), ...checks]
87
+ const labels = [...new Set(rows.map((row) => row.label))]
46
88
 
47
89
  return [
48
- lane_stats.to_row(COLUMNS),
49
- lane_stats.to_row(COLUMNS.map(() => '---')),
50
- ...labels.map((label) => check_row(label, checks)),
51
- ].join('\n')
90
+ [...header(COLUMNS), ...labels.map((label) => check_row(label, rows))].join('\n'),
91
+ fallback_table(checks),
92
+ ].join('\n\n')
52
93
  }
53
94
 
54
- const lane_check_stats = { table }
95
+ const lane_check_stats = { WHOLE_GATE_LABEL, table }
55
96
 
56
97
  export { lane_check_stats }
@@ -47,6 +47,13 @@ function process_pattern(issue: string): string {
47
47
  return `(${CHILD_INVOCATION}|${REVIEW_INVOCATION}|${SHIP_PROCESS} .*) ${issue_cite.plain(issue)}$`
48
48
  }
49
49
 
50
+ // The `pgrep -f` pattern that finds the detached ship supervisor of `issue` alone.
51
+ function ship_pattern(issue: string): string {
52
+ issue_number_shape.require_issue_number(issue)
53
+
54
+ return `${SHIP_PROCESS} .* ${issue_cite.plain(issue)}$`
55
+ }
56
+
50
57
  function review_invocation(issue: string): string {
51
58
  issue_number_shape.require_issue_number(issue)
52
59
 
@@ -126,6 +133,7 @@ const lane_child_invocation = {
126
133
  process_pattern,
127
134
  resume_invocation,
128
135
  review_invocation,
136
+ ship_pattern,
129
137
  ship_stop_invocation,
130
138
  }
131
139
 
@@ -17,6 +17,7 @@ import { lane_open, type OpenOutcome } from './lane-open'
17
17
  import { lane_output, type ReadOutcome, type RecordOutcome } from './lane-output'
18
18
  import { lane_registry, type LaneInfo } from './lane-registry'
19
19
  import { lane_report } from './lane-report'
20
+ import { lane_residents } from './lane-residents'
20
21
  import { lane_seed_policy } from './lane-seed'
21
22
  import type { KeptLane } from './lane-spent'
22
23
  import { lane_stray } from './lane-stray'
@@ -111,16 +112,25 @@ function report_issues(issues: ReadonlyArray<string>): number {
111
112
  return SUCCESS_EXIT_CODE
112
113
  }
113
114
 
114
- // A close that left something behind exits non-zero and names it. Reported as a success, it would
115
- // send the caller to the next `lane:open`, which then fails on git's own message about a branch that
116
- // still exists.
117
- function report_close(outcome: CloseOutcome): number {
115
+ // What the close terminated: the lane child that had not ended, and what else ran from the checkout.
116
+ function report_terminated(outcome: CloseOutcome): void {
117
+ const cited = session_cite.issue(outcome.issue)
118
+
118
119
  if (outcome.reaped.length > 0) {
119
120
  console.error(
120
- `Terminated the lane child for ${session_cite.issue(outcome.issue)} that had not ended by itself: process ${outcome.reaped.join(', ')}.`,
121
+ `Terminated the lane child for ${cited} that had not ended by itself: process ${outcome.reaped.join(', ')}.`,
121
122
  )
122
123
  }
123
124
 
125
+ lane_residents.report(outcome.residents, cited)
126
+ }
127
+
128
+ // A close that left something behind exits non-zero and names it. Reported as a success, it would
129
+ // send the caller to the next `lane:open`, which then fails on git's own message about a branch that
130
+ // still exists.
131
+ function report_close(outcome: CloseOutcome): number {
132
+ report_terminated(outcome)
133
+
124
134
  if (outcome.kind !== 'incomplete') {
125
135
  return report_issues(outcome.kind === 'closed' ? [outcome.issue] : [])
126
136
  }
@@ -4,8 +4,11 @@ import { git_worktree } from '#scripts/git/git-worktree'
4
4
  import { error_text } from '#scripts/lib/error-message'
5
5
  import { lane_paths } from './lane-paths'
6
6
  import { lane_reap } from './lane-reap'
7
+ import { lane_reap_settle } from './lane-reap-settle'
7
8
  import { lane_registry, type LaneInfo } from './lane-registry'
9
+ import { lane_residents } from './lane-residents'
8
10
  import { lane_spent, type KeptLane } from './lane-spent'
11
+ import { lane_state } from './lane-state'
9
12
 
10
13
  // Closing a lane: no work tree, no branch, no directory.
11
14
  //
@@ -13,7 +16,8 @@ import { lane_spent, type KeptLane } from './lane-spent'
13
16
  // every step here is written to run over a subject that is already gone or that still holds
14
17
  // uncommitted work. A close that refused either would leave exactly the debris it exists to remove,
15
18
  // and the next lane for that issue would then fail on a directory nobody could account for. There
16
- // is no ledger entry to remove: the lane's seat lived in the `.env` that goes with the work tree.
19
+ // is no ledger entry to remove: the lane's seat lived in the `.env` that goes with the work tree. The
20
+ // lane's state record outlives it, marked `ended`, so its last state stays readable.
17
21
 
18
22
  interface LaneTargets {
19
23
  directory: string
@@ -36,6 +40,9 @@ interface CloseOutcome {
36
40
  left_behind: Array<string>
37
41
  // The lane child's processes this close terminated — empty for a child that ended by itself.
38
42
  reaped: Array<number>
43
+ // What else still ran from the lane's checkout or carried its mark and this close terminated
44
+ // (`lane-residents.ts`); `undefined` where the processes could not be read.
45
+ residents: Array<number> | undefined
39
46
  }
40
47
 
41
48
  interface SweepOutcome {
@@ -112,39 +119,72 @@ function close_kind(did_exist: boolean, left_behind: ReadonlyArray<string>): Clo
112
119
  return did_exist ? 'closed' : 'none'
113
120
  }
114
121
 
115
- // The main work tree's root, not this one's — the same reading `list_lanes` uses, so the fallback
116
- // directory an unregistered lane is closed by is the one `lane:open` would have created.
117
- // Derived here from the current work tree, a close run inside a lane
118
- // reports `none` over a directory that is still on disk.
119
- async function lane_root_directory(): Promise<string> {
120
- return lane_paths.lane_root(await lane_registry.main_repository_root())
121
- }
122
-
122
+ // The lane root is the main work tree's (`lane_root_directory`), so the fallback directory an
123
+ // unregistered lane is closed by is the one `lane:open` would have created.
123
124
  /**
124
125
  * Close the lane for `issue`. `none` means there was nothing there, which is not a failure: a caller
125
126
  * cleaning up after an interruption cannot know whether the lane was ever opened. `incomplete` means
126
127
  * something survived the removal, and `left_behind` names it.
127
128
  */
128
129
  async function resolve_lane(issue: string): Promise<ResolvedLane> {
129
- const root = await lane_root_directory()
130
+ const root = await lane_registry.lane_root_directory()
130
131
  const existing = lane_registry.find_lane(await lane_registry.list_lanes(), issue)
131
132
 
132
133
  return { existing, targets: lane_targets(root, issue, existing) }
133
134
  }
134
135
 
136
+ // A lane closed before is `none` on a retry, and ends there once its record says it is not over —
137
+ // an issue never opened is not given a record.
138
+ async function is_ending(issue: string, kind: CloseKind): Promise<boolean> {
139
+ if (kind !== 'none') return kind === 'closed'
140
+
141
+ const record = await lane_state.read_state(issue)
142
+
143
+ return record !== undefined && record.state !== 'ended'
144
+ }
145
+
146
+ // The lane's processes, settled after the removal so the processes have had the work tree's deletion
147
+ // to exit in too; what outlived the SIGKILL replaces what the lane's record noted for `run:board`.
148
+ async function survivors_of(issue: string, directory: string): Promise<Array<string>> {
149
+ const survivors = await lane_reap_settle.settle({ issue, directory })
150
+
151
+ if (survivors !== undefined) await lane_state.record_stuck(issue, survivors)
152
+
153
+ return lane_reap_settle.survivor_texts(survivors)
154
+ }
155
+
156
+ // Whatever the removal left: the checkout's residue, then the processes that outlived it.
157
+ async function left_behind_of(issue: string, targets: LaneTargets): Promise<Array<string>> {
158
+ const survivors = await survivors_of(issue, targets.directory)
159
+
160
+ return [...(await residue(targets)), ...survivors]
161
+ }
162
+
135
163
  async function close_lane(issue: string): Promise<CloseOutcome> {
136
164
  const { existing, targets } = await resolve_lane(issue)
137
165
  const did_exist = existing !== undefined || existsSync(targets.directory)
138
166
  // Before the removal, not after: a child still running in the tree would keep writing into a
139
167
  // directory being deleted, and a process outliving its lane is a half-discarded state — the work
140
- // tree gone, the child still answering `alive`.
141
- const reaped = lane_reap.reap_child(issue)
168
+ // tree gone, the child still answering `alive`. What else still runs from the checkout goes too.
169
+ const reaped = lane_reap.reap_child({ issue, directory: targets.directory })
170
+ const residents = lane_residents.end_residents({ issue, directory: targets.directory }, reaped)
142
171
 
143
172
  await remove_lane(targets)
144
173
 
145
- const left_behind = await residue(targets)
174
+ const left_behind = await left_behind_of(issue, targets)
175
+ const kind = close_kind(did_exist, left_behind)
176
+
177
+ if (await is_ending(issue, kind)) {
178
+ await lane_state.record_change({ issue, state: 'ended', command: 'lane:close' })
179
+ }
180
+
181
+ return { issue, kind, left_behind, reaped, residents }
182
+ }
183
+
184
+ type DuePredicate = (issue: string) => Promise<boolean>
146
185
 
147
- return { issue, kind: close_kind(did_exist, left_behind), left_behind, reaped }
186
+ async function always_due(): Promise<boolean> {
187
+ return true
148
188
  }
149
189
 
150
190
  // A lane that could not be closed is recorded rather than thrown: a sweep has to attempt every lane,
@@ -163,14 +203,24 @@ async function try_close(issue: string): Promise<boolean> {
163
203
 
164
204
  // Sequential on purpose: two `git worktree` writes at once contend for the same registration
165
205
  // directory, and the whole point of the command is that nothing is left half-removed.
166
- async function close_each(issues: ReadonlyArray<string>): Promise<SweepOutcome> {
206
+ async function close_into(sweep: SweepOutcome, issue: string, is_due: DuePredicate): Promise<void> {
207
+ if (!(await is_due(issue))) return
208
+ const bucket = (await try_close(issue)) ? sweep.closed : sweep.failed
209
+
210
+ bucket.push(issue)
211
+ }
212
+
213
+ // `is_due` is asked right before each close, not for every issue up front: a close can wait out the
214
+ // grace window, and a lane opened again meanwhile is no longer one to close.
215
+ async function close_each(
216
+ issues: ReadonlyArray<string>,
217
+ is_due: DuePredicate = always_due,
218
+ ): Promise<SweepOutcome> {
167
219
  const sweep: SweepOutcome = { closed: [], failed: [] }
168
220
 
169
221
  for (const issue of issues) {
170
222
  // eslint-disable-next-line no-await-in-loop -- worktree writes contend for the same registration directory
171
- const bucket = (await try_close(issue)) ? sweep.closed : sweep.failed
172
-
173
- bucket.push(issue)
223
+ await close_into(sweep, issue, is_due)
174
224
  }
175
225
 
176
226
  return sweep
@@ -196,11 +246,29 @@ async function close_all_lanes(): Promise<SweepOutcome> {
196
246
  return await close_each(lanes.map((lane) => lane.issue))
197
247
  }
198
248
 
249
+ async function is_unfinished(issue: string): Promise<boolean> {
250
+ const { targets } = await resolve_lane(issue)
251
+
252
+ return !existsSync(targets.directory)
253
+ }
254
+
255
+ /**
256
+ * Close again every lane whose work tree is gone but whose record is not `ended` — a close a process
257
+ * outlived. The supervisor runs it each pass, so a lane ends once its last process does.
258
+ */
259
+ async function retry_closes(): Promise<SweepOutcome> {
260
+ const records = await lane_state.read_records()
261
+ const issues = records.filter((record) => record.state !== 'ended').map(({ issue }) => issue)
262
+
263
+ return await close_each(issues, is_unfinished)
264
+ }
265
+
199
266
  const lane_close = {
200
267
  close_all_lanes,
201
268
  close_lane,
202
269
  prune_lanes,
203
270
  resolve_lane,
271
+ retry_closes,
204
272
  }
205
273
 
206
274
  export type { CloseKind, CloseOutcome, PruneOutcome, ResolvedLane, SweepOutcome }