@joshuafolkken/kit 1.1784.0 → 1.2116.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 (690) hide show
  1. package/.claude/agents/reviewer-verification.md +19 -0
  2. package/.claude/agents/reviewer.md +19 -0
  3. package/.claude/settings.json +5 -6
  4. package/.claude/skills/dependency-update/SKILL.md +9 -10
  5. package/.claude/skills/workflow-commands/SKILL.md +6 -6
  6. package/.claude/skills/workflow-commands/background-commands.md +8 -5
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +3 -1
  8. package/.claude/skills/workflow-commands/backlogrun-lanes.md +1 -1
  9. package/.claude/skills/workflow-commands/backlogrun-park.md +5 -2
  10. package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -3
  11. package/.claude/skills/workflow-commands/backlogrun-recovery.md +1 -1
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +3 -2
  13. package/.claude/skills/workflow-commands/backlogrun.md +1 -1
  14. package/.claude/skills/workflow-commands/chain-rule.md +41 -32
  15. package/.claude/skills/workflow-commands/delegation.md +6 -6
  16. package/.claude/skills/workflow-commands/entry-sequence.md +2 -2
  17. package/.claude/skills/workflow-commands/followup.md +7 -5
  18. package/.claude/skills/workflow-commands/fullrun-steps.md +6 -6
  19. package/.claude/skills/workflow-commands/fullrun.md +1 -1
  20. package/.claude/skills/workflow-commands/issue-comments.md +9 -4
  21. package/.claude/skills/workflow-commands/issue-fold-existing.md +2 -1
  22. package/.claude/skills/workflow-commands/kickoff.md +2 -2
  23. package/.claude/skills/workflow-commands/observation-filing.md +1 -1
  24. package/.claude/skills/workflow-commands/observation-ledger.md +6 -4
  25. package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -7
  26. package/.claude/skills/workflow-commands/prerequisite.md +3 -2
  27. package/.claude/skills/workflow-commands/retrospective.md +2 -2
  28. package/.claude/skills/workflow-commands/split-assessment.md +7 -5
  29. package/.codex/hooks.json +5 -5
  30. package/.github/actions/setup-pnpm/action.yml +9 -16
  31. package/.github/dependabot.yml +16 -0
  32. package/.github/workflows/auto-tag.yml +45 -0
  33. package/.github/workflows/ci.yml +155 -15
  34. package/.github/workflows/dependabot-auto-merge.yml +63 -4
  35. package/.github/workflows/production.yml +8 -0
  36. package/.github/workflows/publish.yml +60 -45
  37. package/.vscode/settings.json +19 -0
  38. package/CLAUDE.md +5 -12
  39. package/SECURITY.md +2 -2
  40. package/dist/CLAUDE.md +5 -12
  41. package/dist/commands/document-read-cli.js +2 -1
  42. package/dist/commands/document-section-main.js +2 -1
  43. package/dist/commands/read-set-cli.js +194 -134
  44. package/dist/commands/run-prep-main.js +9694 -10173
  45. package/dist/commands/run-step-cli.js +22138 -18285
  46. package/dist/hooks/audit-provision.js +23 -5
  47. package/dist/hooks/chunk-3GKE653K.js +6204 -0
  48. package/dist/hooks/chunk-45CJJOO7.js +1243 -0
  49. package/dist/hooks/{chunk-CWMBGKYW.js → chunk-5PM2JRGV.js} +2153 -856
  50. package/dist/hooks/{chunk-WR2KQAYZ.js → chunk-7SIUNQXK.js} +1207 -1470
  51. package/dist/hooks/{chunk-O2YBIDSI.js → chunk-CQD4LJE6.js} +1682 -1130
  52. package/dist/hooks/{chunk-VWWCFGWK.js → chunk-OPSRGWFU.js} +1 -1
  53. package/dist/hooks/{chunk-XGBNSWEI.js → chunk-UJ3FPMMM.js} +132 -49
  54. package/dist/hooks/chunk-VVNYJWEI.js +30 -0
  55. package/dist/hooks/chunk-Z6DQJKH3.js +2806 -0
  56. package/dist/hooks/codex-hook-adapter.js +8 -8
  57. package/dist/hooks/format-edited.js +4 -5
  58. package/dist/hooks/inputs.json +386 -360
  59. package/dist/hooks/pretool-guard.js +7 -6
  60. package/dist/hooks/session-lang.js +101 -258
  61. package/dist/hooks/stop-guard.js +1744 -2576
  62. package/dist/josh.js +7133 -6368
  63. package/dist/version/index.js +161 -1
  64. package/eslint/rules/comment-why-only.js +108 -0
  65. package/package.json +16 -9
  66. package/prompts/coding-standards.md +1 -1
  67. package/prompts/collaboration-workflow/file-edits.md +14 -11
  68. package/prompts/collaboration-workflow/issue-citation.md +0 -4
  69. package/prompts/collaboration-workflow/issue-template.md +40 -21
  70. package/prompts/collaboration-workflow/lane-instructions.md +3 -1
  71. package/prompts/collaboration-workflow/measurement.md +8 -1
  72. package/prompts/collaboration-workflow/operating-rules.md +11 -2
  73. package/prompts/collaboration-workflow/output-bounds.md +6 -2
  74. package/prompts/collaboration-workflow/plan-comment.md +1 -1
  75. package/prompts/collaboration-workflow/principles.md +9 -0
  76. package/prompts/collaboration-workflow/residency.md +3 -2
  77. package/prompts/collaboration-workflow/rule-delivery.md +13 -1
  78. package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
  79. package/prompts/collaboration-workflow/wip-cap.md +3 -1
  80. package/prompts/review-rubric.md +8 -0
  81. package/prompts/review.md +31 -22
  82. package/prompts/testing-guide.md +1 -0
  83. package/scripts/agent/agent-argv.ts +14 -16
  84. package/scripts/agent/agent-provider.ts +138 -0
  85. package/scripts/agent/agent-role-profile.ts +108 -156
  86. package/scripts/agent/agent-safe-text.ts +20 -5
  87. package/scripts/agent/api-usage-limit.ts +65 -0
  88. package/scripts/agent/claude-agent-argv.ts +19 -9
  89. package/scripts/agent/codex-agent-argv.ts +118 -22
  90. package/scripts/agent/usage-limit-reset.ts +179 -0
  91. package/scripts/auth/claude-token-output.ts +2 -2
  92. package/scripts/auto-ok/auto-ok-author.ts +53 -0
  93. package/scripts/auto-ok/auto-ok-cli.ts +20 -9
  94. package/scripts/backlog/backlog-defect-priority.ts +1 -1
  95. package/scripts/backlog/backlog-drive-cli.ts +6 -1
  96. package/scripts/backlog/backlog-drive-hold.ts +3 -3
  97. package/scripts/backlog/backlog-drive-idle.ts +10 -0
  98. package/scripts/backlog/backlog-drive-launch-pass.ts +90 -0
  99. package/scripts/backlog/backlog-drive-launch.ts +8 -2
  100. package/scripts/backlog/backlog-drive-named-offer.ts +73 -30
  101. package/scripts/backlog/backlog-drive-named.ts +28 -7
  102. package/scripts/backlog/backlog-drive-paused.ts +5 -4
  103. package/scripts/backlog/backlog-drive-restore.ts +11 -3
  104. package/scripts/backlog/backlog-drive.ts +21 -60
  105. package/scripts/backlog/backlog-gate-scope.ts +61 -0
  106. package/scripts/backlog/backlog-measure-close.ts +112 -0
  107. package/scripts/backlog/backlog-next.ts +39 -49
  108. package/scripts/backlog/backlog-occupied.ts +2 -2
  109. package/scripts/backlog/backlog-overlap.ts +42 -8
  110. package/scripts/backlog/backlog-plan-cli.ts +4 -1
  111. package/scripts/backlog/backlog-plan-comment.ts +81 -0
  112. package/scripts/backlog/backlog-plan-read.ts +19 -6
  113. package/scripts/backlog/backlog-pool.ts +50 -12
  114. package/scripts/backlog/backlog-rank.ts +60 -13
  115. package/scripts/backlog/backlog-stalled-detect.ts +2 -1
  116. package/scripts/backlog/backlog-waves.ts +17 -2
  117. package/scripts/backlog/backlogrun-launch.ts +7 -4
  118. package/scripts/cost-runtime/context-cut-payback.ts +27 -25
  119. package/scripts/cost-runtime/cost-cli.ts +37 -16
  120. package/scripts/cost-runtime/cost-pricing.ts +9 -0
  121. package/scripts/cost-runtime/cost-verdict.ts +4 -1
  122. package/scripts/delegation/delegation-policy.ts +2 -2
  123. package/scripts/delegation/duplicate-read-guard.ts +1 -0
  124. package/scripts/delegation/investigation-guard.ts +14 -2
  125. package/scripts/delegation/investigation-reads.ts +45 -23
  126. package/scripts/dependabot/dependabot-cooldown.ts +3 -2
  127. package/scripts/discovery/repo-party.ts +80 -20
  128. package/scripts/discovery/session-owner-pin.ts +51 -0
  129. package/scripts/document/capped-print.ts +1 -1
  130. package/scripts/document/command-reference-line-budget.ts +42 -0
  131. package/scripts/document/document-byte-budget.ts +17 -7
  132. package/scripts/document/document-checks.ts +20 -0
  133. package/scripts/document/document-ratchet-check.ts +101 -0
  134. package/scripts/document/document-section.ts +1 -0
  135. package/scripts/document/entry-read-budget.ts +7 -3
  136. package/scripts/document/issue-citation-budget.ts +94 -0
  137. package/scripts/epic/epic-cli-argv.ts +2 -2
  138. package/scripts/epic/epic-fetch.ts +4 -2
  139. package/scripts/epic/epic-graph.ts +7 -2
  140. package/scripts/epic/epic-issue.ts +3 -1
  141. package/scripts/epic/epic-rank.ts +5 -0
  142. package/scripts/exports/unused-members-check.ts +62 -0
  143. package/scripts/exports/unused-members-cli.ts +6 -51
  144. package/scripts/followup/followup-ci-path.ts +67 -0
  145. package/scripts/followup/followup-coderabbit-retrigger.ts +261 -0
  146. package/scripts/followup/followup-coderabbit-wait.ts +13 -10
  147. package/scripts/followup/followup-failed-tests.ts +160 -0
  148. package/scripts/followup/followup-job-needs.ts +100 -0
  149. package/scripts/followup/followup-job-rerun.ts +303 -0
  150. package/scripts/followup/followup-main-move.ts +113 -0
  151. package/scripts/followup/git-followup-finish.ts +43 -11
  152. package/scripts/followup/git-followup-pending.ts +3 -3
  153. package/scripts/followup/git-followup-stages.ts +41 -11
  154. package/scripts/followup/git-pr-followup-checks.ts +55 -16
  155. package/scripts/followup/git-pr-followup-wrapup.ts +24 -5
  156. package/scripts/followup/git-pr-followup.ts +62 -27
  157. package/scripts/fresh-machine/fresh-machine-script.ts +5 -9
  158. package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +2 -2
  159. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +2 -2
  160. package/scripts/gate/busy-average.ts +34 -2
  161. package/scripts/gate/check-related-pinned.ts +43 -0
  162. package/scripts/gate/check-related-reuse.ts +64 -0
  163. package/scripts/gate/check-related-section.ts +57 -0
  164. package/scripts/gate/check-related-unplanned.ts +34 -0
  165. package/scripts/gate/check-related.ts +265 -0
  166. package/scripts/gate/command-memory.ts +1 -1
  167. package/scripts/gate/core-admission.ts +24 -6
  168. package/scripts/gate/core-budget-timing.ts +20 -6
  169. package/scripts/gate/core-budget.ts +40 -11
  170. package/scripts/gate/core-wait-record.ts +3 -2
  171. package/scripts/gate/core-wait.ts +25 -2
  172. package/scripts/gate/core-weights.ts +15 -7
  173. package/scripts/gate/gate-labels.ts +46 -0
  174. package/scripts/gate/gate-ledger.ts +14 -6
  175. package/scripts/gate/gate-plan.ts +103 -58
  176. package/scripts/gate/gate-report.ts +9 -7
  177. package/scripts/gate/gate-run-steps.ts +26 -3
  178. package/scripts/gate/gate-skip.ts +45 -6
  179. package/scripts/gate/gate-static-group.ts +60 -0
  180. package/scripts/gate/gate-steps.ts +2 -1
  181. package/scripts/gate/gate-tree.ts +4 -2
  182. package/scripts/gate/hook-gate-reuse.ts +19 -2
  183. package/scripts/gate/metrics-totals.ts +59 -0
  184. package/scripts/gate/scoped-green.ts +68 -15
  185. package/scripts/gate/since-green.ts +14 -6
  186. package/scripts/gate/structural-checks.ts +96 -0
  187. package/scripts/gate/verification-gate.ts +51 -16
  188. package/scripts/gate/verification-inputs.ts +21 -6
  189. package/scripts/gate/verification-tail.ts +52 -0
  190. package/scripts/gh/gh-author-association.ts +23 -2
  191. package/scripts/gh/git-ai-review-scan.ts +1 -1
  192. package/scripts/gh/git-gh-api-path.ts +12 -3
  193. package/scripts/gh/git-gh-comments-unreadable.ts +36 -0
  194. package/scripts/gh/git-gh-exec.ts +32 -2
  195. package/scripts/gh/git-gh-issue-read.ts +4 -2
  196. package/scripts/gh/git-gh-issue-rest.ts +1 -0
  197. package/scripts/gh/git-gh-issue-write.ts +8 -2
  198. package/scripts/gh/git-gh-issue.ts +12 -5
  199. package/scripts/gh/git-gh-pr-auto-merge.ts +13 -6
  200. package/scripts/gh/git-gh-pr-graphql-state.ts +56 -0
  201. package/scripts/gh/git-gh-pr-read.ts +74 -13
  202. package/scripts/gh/git-gh-pr-rest.ts +3 -1
  203. package/scripts/gh/git-gh-pr-snapshot.ts +22 -7
  204. package/scripts/gh/git-gh-pr-too-large.ts +20 -0
  205. package/scripts/gh/git-gh-pr.ts +21 -7
  206. package/scripts/gh/git-gh-retry.ts +141 -0
  207. package/scripts/gh/git-pr-ai-review.ts +15 -6
  208. package/scripts/gh/git-pr-checks-eval.ts +3 -0
  209. package/scripts/gh/git-pr-checks.ts +5 -5
  210. package/scripts/git/base-tree.ts +30 -0
  211. package/scripts/git/change-base.ts +4 -10
  212. package/scripts/git/changed-paths-sync.ts +63 -0
  213. package/scripts/git/changed-paths.ts +16 -1
  214. package/scripts/git/git-common-directory.ts +11 -1
  215. package/scripts/git/git-diff-reads.ts +66 -20
  216. package/scripts/git/git-error.ts +9 -2
  217. package/scripts/git/git-schemas.ts +13 -0
  218. package/scripts/git/git-worktree.ts +13 -0
  219. package/scripts/git/gone-branch.ts +4 -1
  220. package/scripts/git/main-merge-budget-conflict.ts +89 -0
  221. package/scripts/git/main-merge-guard.ts +55 -18
  222. package/scripts/git/main-merge-regenerate.ts +59 -25
  223. package/scripts/git/main-merge.ts +53 -5
  224. package/scripts/git/no-base-checkout.ts +127 -0
  225. package/scripts/git/stash/git-stash.ts +11 -2
  226. package/scripts/git/stash/stash-push-cli.ts +10 -0
  227. package/scripts/hooks/batch-guard.ts +40 -21
  228. package/scripts/hooks/edited-cspell.ts +37 -11
  229. package/scripts/hooks/format-edited-file.ts +22 -2
  230. package/scripts/hooks/lane-plan-guard.ts +50 -0
  231. package/scripts/hooks/pre-commit-lint-switch.ts +9 -0
  232. package/scripts/hooks/pre-commit-lint.ts +14 -1
  233. package/scripts/hooks/pre-push-related-switch.ts +10 -0
  234. package/scripts/hooks/pre-push-unit.ts +76 -10
  235. package/scripts/hooks/pretool-guard.ts +2 -0
  236. package/scripts/hooks/reserved-run.ts +14 -1
  237. package/scripts/hooks/run-hook.sh +23 -8
  238. package/scripts/hooks/step-zero-notice.ts +6 -1
  239. package/scripts/hooks/stop-actions.ts +3 -15
  240. package/scripts/hooks/stop-guard.ts +7 -6
  241. package/scripts/init/distributed-paths.ts +1 -0
  242. package/scripts/init/hook-command-rewrite.ts +5 -1
  243. package/scripts/init/hook-launch.ts +4 -2
  244. package/scripts/issue/aggregation-split.ts +52 -0
  245. package/scripts/issue/defect-origin-line.ts +19 -1
  246. package/scripts/issue/defect-rate-cli.ts +5 -102
  247. package/scripts/issue/defect-report.ts +4 -4
  248. package/scripts/issue/effect-audit-cli.ts +178 -0
  249. package/scripts/issue/effect-audit.ts +185 -0
  250. package/scripts/issue/expected-effect-lint.ts +64 -9
  251. package/scripts/issue/git-next-issues.ts +5 -0
  252. package/scripts/issue/issue-body-or-comment.ts +38 -4
  253. package/scripts/issue/issue-cite-cli.ts +1 -3
  254. package/scripts/issue/issue-classification.ts +1 -0
  255. package/scripts/issue/issue-closing-pr.ts +8 -1
  256. package/scripts/issue/issue-evidence-exit.ts +4 -2
  257. package/scripts/issue/issue-file-cap.ts +58 -0
  258. package/scripts/issue/issue-file-cli.ts +111 -38
  259. package/scripts/issue/issue-file-deferral.ts +52 -0
  260. package/scripts/issue/issue-file-fold.ts +29 -10
  261. package/scripts/issue/issue-file-interrupt.ts +85 -0
  262. package/scripts/issue/issue-file-lane-hint.ts +30 -0
  263. package/scripts/issue/issue-file.ts +43 -6
  264. package/scripts/issue/issue-labels.ts +19 -2
  265. package/scripts/issue/issue-lint-cli.ts +27 -2
  266. package/scripts/issue/issue-measured-cli.ts +13 -35
  267. package/scripts/issue/issue-measured-close.ts +58 -0
  268. package/scripts/issue/issue-not-before-label.ts +2 -2
  269. package/scripts/issue/issue-not-before.ts +4 -1
  270. package/scripts/issue/issue-priority-cli.ts +60 -0
  271. package/scripts/issue/issue-priority-raise.ts +55 -0
  272. package/scripts/issue/issue-priority.ts +174 -43
  273. package/scripts/issue/issue-rank.ts +21 -4
  274. package/scripts/issue/issue-read-cli.ts +32 -6
  275. package/scripts/issue/issue-read.ts +37 -12
  276. package/scripts/issue/issue-sample-gate.ts +95 -74
  277. package/scripts/issue/issue-sample-prime.ts +127 -0
  278. package/scripts/issue/issue-sample-required.ts +57 -0
  279. package/scripts/issue/issue-sample-source.ts +12 -11
  280. package/scripts/issue/issue-search.ts +124 -0
  281. package/scripts/issue/issue-state.ts +13 -1
  282. package/scripts/issue/issue-template-section.ts +43 -0
  283. package/scripts/issue/issue-watch-diff.ts +31 -1
  284. package/scripts/issue/issue-watch-hook.ts +11 -2
  285. package/scripts/issue/issue-watch.ts +55 -12
  286. package/scripts/issue/markdown-section.ts +1 -0
  287. package/scripts/issue/measure-declaration.ts +121 -0
  288. package/scripts/issue/measure-rerun-cli.ts +7 -70
  289. package/scripts/issue/plan-consumers-section.ts +22 -1
  290. package/scripts/issue/reproduction-measure.ts +3 -1
  291. package/scripts/issue/size-estimate.ts +90 -0
  292. package/scripts/issue/trusted-measure.ts +84 -0
  293. package/scripts/josh/command-usage.ts +3 -2
  294. package/scripts/josh/durable-state-migrate.ts +105 -0
  295. package/scripts/josh/durable-state.ts +112 -0
  296. package/scripts/josh/josh-aliases.ts +95 -0
  297. package/scripts/josh/josh-command-map.ts +1 -82
  298. package/scripts/josh/josh-commands-agent-hooks.ts +6 -6
  299. package/scripts/josh/josh-commands-ai.ts +5 -5
  300. package/scripts/josh/josh-commands-development.ts +59 -58
  301. package/scripts/josh/josh-commands-issue-write.ts +23 -4
  302. package/scripts/josh/josh-commands-issue.ts +32 -0
  303. package/scripts/josh/josh-commands-lane.ts +87 -4
  304. package/scripts/josh/josh-commands-lint.ts +16 -3
  305. package/scripts/josh/josh-commands-maintenance.ts +15 -0
  306. package/scripts/josh/josh-commands-review.ts +41 -6
  307. package/scripts/josh/josh-commands-ship.ts +56 -8
  308. package/scripts/josh/josh-commands-test-check.ts +80 -0
  309. package/scripts/josh/josh-commands-workflow.ts +1 -1
  310. package/scripts/josh/josh-environment-file.ts +43 -3
  311. package/scripts/josh/josh-in-process.ts +2 -2
  312. package/scripts/josh/josh-logic.ts +5 -3
  313. package/scripts/josh/josh-run.ts +19 -1
  314. package/scripts/josh/run-record-path.ts +15 -0
  315. package/scripts/josh/stamp-file.ts +11 -2
  316. package/scripts/lane/lane-adopt-cli.ts +98 -0
  317. package/scripts/lane/lane-adopt.ts +208 -0
  318. package/scripts/lane/lane-await.ts +5 -8
  319. package/scripts/lane/lane-baseline.ts +123 -0
  320. package/scripts/lane/lane-breakdown-cli.ts +64 -0
  321. package/scripts/lane/lane-breakdown-implement.ts +170 -0
  322. package/scripts/lane/lane-breakdown-laps.ts +107 -0
  323. package/scripts/lane/lane-breakdown-pinned.ts +76 -0
  324. package/scripts/lane/lane-breakdown-text.ts +145 -0
  325. package/scripts/lane/lane-breakdown.ts +239 -0
  326. package/scripts/lane/lane-check-stats.ts +29 -8
  327. package/scripts/lane/lane-child-invocation.ts +9 -2
  328. package/scripts/lane/lane-child-mark-keys.ts +12 -0
  329. package/scripts/lane/lane-child-marker.ts +20 -1
  330. package/scripts/lane/lane-ci-path-stats.ts +73 -0
  331. package/scripts/lane/lane-claim-stats.ts +84 -0
  332. package/scripts/lane/lane-close.ts +8 -3
  333. package/scripts/lane/lane-dispatch-log.ts +3 -3
  334. package/scripts/lane/lane-dispatch.ts +2 -2
  335. package/scripts/lane/lane-gap-stats.ts +7 -6
  336. package/scripts/lane/lane-guard-policy.ts +7 -1
  337. package/scripts/lane/lane-implement-stats.ts +207 -0
  338. package/scripts/lane/lane-implement-subagents.ts +90 -0
  339. package/scripts/lane/lane-investigation-switch.ts +16 -0
  340. package/scripts/lane/lane-ledger-kind.ts +31 -0
  341. package/scripts/lane/lane-ledger-schema-ship.ts +49 -0
  342. package/scripts/lane/lane-ledger-schema.ts +119 -36
  343. package/scripts/lane/lane-ledger-write.ts +257 -0
  344. package/scripts/lane/lane-ledger.ts +31 -177
  345. package/scripts/lane/lane-load.ts +1 -1
  346. package/scripts/lane/lane-measure-cli.ts +176 -59
  347. package/scripts/lane/lane-net-read.ts +44 -0
  348. package/scripts/lane/lane-net-time.ts +212 -0
  349. package/scripts/lane/lane-open.ts +16 -7
  350. package/scripts/lane/lane-output.ts +2 -4
  351. package/scripts/lane/lane-overrun-prompt.ts +147 -0
  352. package/scripts/lane/lane-overrun.ts +274 -0
  353. package/scripts/lane/lane-paths.ts +24 -1
  354. package/scripts/lane/lane-pause-cli.ts +4 -1
  355. package/scripts/lane/lane-paused-spans.ts +97 -0
  356. package/scripts/lane/lane-plan-check.ts +207 -0
  357. package/scripts/lane/lane-plan-cli.ts +41 -0
  358. package/scripts/lane/lane-plan.ts +144 -0
  359. package/scripts/lane/lane-registry.ts +14 -1
  360. package/scripts/lane/lane-relaunch.ts +1 -1
  361. package/scripts/lane/lane-round-one-stats.ts +51 -0
  362. package/scripts/lane/lane-sampler.ts +23 -4
  363. package/scripts/lane/lane-session-action.ts +93 -18
  364. package/scripts/lane/lane-session-broker.ts +49 -21
  365. package/scripts/lane/lane-session-reread-main.ts +14 -0
  366. package/scripts/lane/lane-session-reread.ts +51 -0
  367. package/scripts/lane/lane-ship-lap-stats.ts +74 -0
  368. package/scripts/lane/lane-sleep.ts +58 -0
  369. package/scripts/lane/lane-spent.ts +1 -1
  370. package/scripts/lane/lane-split-stats.ts +28 -0
  371. package/scripts/lane/lane-stage-stats.ts +13 -1
  372. package/scripts/lane/lane-state.ts +41 -9
  373. package/scripts/lane/lane-stats-tables.ts +58 -0
  374. package/scripts/lane/lane-stats.ts +21 -5
  375. package/scripts/lane/lane-stop-stats.ts +51 -19
  376. package/scripts/lane/lane-tail-stats.ts +32 -0
  377. package/scripts/lane/lane-transcript-calls.ts +67 -10
  378. package/scripts/lane/lane-transcript-stats.ts +44 -12
  379. package/scripts/lane/lane-value-cell.ts +72 -0
  380. package/scripts/lane/lane-value.ts +118 -0
  381. package/scripts/lane/lane-withdraw-closed.ts +124 -0
  382. package/scripts/lane/lane-withdraw.ts +108 -31
  383. package/scripts/lane/lane-yield.ts +85 -0
  384. package/scripts/lane/openai-lane-ship.ts +12 -11
  385. package/scripts/lane/openai-lane-supervisor-decision.ts +6 -8
  386. package/scripts/lane/openai-lane-supervisor-owner.ts +5 -8
  387. package/scripts/lane/openai-lane-supervisor.ts +5 -4
  388. package/scripts/lib/poll.ts +38 -9
  389. package/scripts/lib/settled-together.ts +10 -0
  390. package/scripts/lib/shell-quote.ts +21 -0
  391. package/scripts/lib/token-shape.ts +111 -0
  392. package/scripts/lint/eslint-daemon-sources.ts +79 -0
  393. package/scripts/lint/eslint-daemon.ts +45 -6
  394. package/scripts/lint/eslint-warm-cli.ts +7 -0
  395. package/scripts/lint/eslint-warm.ts +66 -0
  396. package/scripts/lint/import-graph.ts +141 -11
  397. package/scripts/lint/lint-gate-scope.ts +2 -2
  398. package/scripts/lint/lint-parallel.ts +54 -6
  399. package/scripts/lint/lint-related.ts +154 -33
  400. package/scripts/lint/rename-cli.ts +179 -0
  401. package/scripts/lint/rename-identifier.ts +192 -0
  402. package/scripts/lint/type-only-imports.ts +58 -0
  403. package/scripts/notify/telegram-notify.ts +12 -3
  404. package/scripts/observations/observation-record.ts +42 -16
  405. package/scripts/observations/observations-flush.ts +32 -9
  406. package/scripts/overrides/overrides-check.ts +9 -1
  407. package/scripts/release/release-approval-prune.ts +7 -1
  408. package/scripts/repo/required-checks-logic.ts +4 -1
  409. package/scripts/repo/ruleset-check.ts +4 -3
  410. package/scripts/report/markdown-shape.ts +28 -0
  411. package/scripts/report/report-format-reference.ts +15 -1
  412. package/scripts/report/report-labels.ts +12 -1
  413. package/scripts/report/report-lint-child-summary.ts +94 -0
  414. package/scripts/report/report-lint-cli.ts +26 -7
  415. package/scripts/report/report-lint.ts +2 -20
  416. package/scripts/review/prose-stale-cli.ts +88 -0
  417. package/scripts/review/prose-stale-scan.ts +152 -0
  418. package/scripts/review/review-attest.ts +73 -23
  419. package/scripts/review/review-brief-cli.ts +68 -19
  420. package/scripts/review/review-brief-paths.ts +22 -0
  421. package/scripts/review/review-brief.ts +14 -7
  422. package/scripts/review/review-comment-carry.ts +47 -0
  423. package/scripts/review/review-comment-round.ts +85 -22
  424. package/scripts/review/review-finding-ledger.ts +109 -7
  425. package/scripts/review/review-finding-text.ts +43 -0
  426. package/scripts/review/review-interaction.ts +11 -0
  427. package/scripts/review/review-lane-handover.ts +68 -0
  428. package/scripts/review/review-lint-cli.ts +57 -0
  429. package/scripts/review/review-lint-findings.ts +92 -0
  430. package/scripts/review/review-lint-sections.ts +80 -0
  431. package/scripts/review/review-lint.ts +221 -0
  432. package/scripts/review/review-prior-findings.ts +102 -0
  433. package/scripts/review/review-readers-scan.ts +4 -2
  434. package/scripts/review/review-record-cli.ts +177 -54
  435. package/scripts/review/review-record-code-round.ts +55 -0
  436. package/scripts/review/review-record-comment.ts +60 -0
  437. package/scripts/review/review-record-interaction.ts +35 -0
  438. package/scripts/review/review-record-pinned.ts +108 -0
  439. package/scripts/review/review-record.ts +25 -1
  440. package/scripts/review/review-reviewed-tree.ts +307 -0
  441. package/scripts/review/review-round-one-closure.ts +62 -0
  442. package/scripts/review/review-round-reuse.ts +106 -0
  443. package/scripts/review/review-round2-cli.ts +91 -29
  444. package/scripts/review/review-round2-skip-comment.ts +55 -0
  445. package/scripts/review/review-round2.ts +24 -8
  446. package/scripts/review/review-stamps.ts +7 -3
  447. package/scripts/review/review-stop-log.ts +20 -6
  448. package/scripts/review/review-stops-cli.ts +2 -1
  449. package/scripts/review/review-submit-cli.ts +101 -0
  450. package/scripts/rules/agent-model.ts +1 -1
  451. package/scripts/rules/bash-triggers.ts +3 -3
  452. package/scripts/rules/concise-reply.ts +88 -0
  453. package/scripts/rules/credential-body.ts +77 -0
  454. package/scripts/rules/decision-oracle.ts +1 -1
  455. package/scripts/rules/delivered-rules.ts +36 -17
  456. package/scripts/rules/destructive-command.ts +3 -11
  457. package/scripts/rules/direct-issue-comment.ts +34 -12
  458. package/scripts/rules/direct-issue-read.ts +191 -0
  459. package/scripts/rules/direct-pr-create.ts +4 -24
  460. package/scripts/rules/early-heartbeat.ts +2 -0
  461. package/scripts/rules/edit-tool.ts +27 -0
  462. package/scripts/rules/file-edit-rows.ts +17 -0
  463. package/scripts/rules/file-rewrite.ts +146 -0
  464. package/scripts/rules/firing-point.ts +3 -2
  465. package/scripts/rules/gh-api.ts +128 -7
  466. package/scripts/rules/gh-repo-selector.ts +84 -0
  467. package/scripts/rules/git-force.ts +2 -2
  468. package/scripts/rules/guard-remedy.ts +14 -5
  469. package/scripts/rules/implementation-cut.ts +61 -28
  470. package/scripts/rules/investigator-foreground.ts +231 -0
  471. package/scripts/rules/issue-citation.ts +15 -60
  472. package/scripts/rules/issue-comments.ts +9 -4
  473. package/scripts/rules/josh-git-bare.ts +1 -1
  474. package/scripts/rules/lane-background.ts +41 -13
  475. package/scripts/rules/lane-direct-tool.ts +107 -9
  476. package/scripts/rules/lane-interactive-ask.ts +4 -1
  477. package/scripts/rules/lane-park.ts +4 -2
  478. package/scripts/rules/lane-spilled-read.ts +90 -0
  479. package/scripts/rules/lane-split-park.ts +1 -1
  480. package/scripts/rules/lane-switch-main.ts +4 -4
  481. package/scripts/rules/last-prompt.ts +20 -47
  482. package/scripts/rules/oracle-consulted.ts +1 -1
  483. package/scripts/rules/permission-guards.ts +5 -1
  484. package/scripts/rules/piped-verification-shapes.ts +110 -0
  485. package/scripts/rules/piped-verification.ts +67 -17
  486. package/scripts/rules/poll-loop.ts +72 -9
  487. package/scripts/rules/pr-merge.ts +5 -5
  488. package/scripts/rules/pre-gate-cut.ts +3 -3
  489. package/scripts/rules/protected-files.ts +88 -24
  490. package/scripts/rules/reply-language.ts +3 -17
  491. package/scripts/rules/reply-prose.ts +34 -0
  492. package/scripts/rules/repo-admin.ts +132 -0
  493. package/scripts/rules/reviewer-foreground.ts +88 -0
  494. package/scripts/rules/round-one-check-related.ts +120 -0
  495. package/scripts/rules/rule-body-guard.ts +5 -15
  496. package/scripts/rules/rule-value-cache.ts +53 -5
  497. package/scripts/rules/rule-value-candidates.ts +84 -0
  498. package/scripts/rules/rule-value-cli.ts +59 -11
  499. package/scripts/rules/rule-value.ts +17 -4
  500. package/scripts/rules/run-tail-rule.ts +1 -1
  501. package/scripts/rules/sed-in-place.ts +196 -0
  502. package/scripts/rules/shell-segments.ts +10 -2
  503. package/scripts/rules/stop-rule-rows.ts +1 -13
  504. package/scripts/rules/stop-rules.ts +33 -58
  505. package/scripts/rules/test-declared-commit.ts +1 -1
  506. package/scripts/rules/third-party-write.ts +110 -23
  507. package/scripts/rules/timed-rerun.ts +1 -1
  508. package/scripts/rules/turn-filings.ts +90 -0
  509. package/scripts/rules/worktree-guard.ts +22 -7
  510. package/scripts/run/board/run-board-ending-reason.ts +6 -2
  511. package/scripts/run/board/run-board-fit.ts +24 -1
  512. package/scripts/run/board/run-board-found.ts +134 -0
  513. package/scripts/run/board/run-board-header.ts +8 -0
  514. package/scripts/run/board/run-board-labels.ts +11 -1
  515. package/scripts/run/board/run-board-lane-time.ts +1 -0
  516. package/scripts/run/board/run-board-link.ts +15 -2
  517. package/scripts/run/board/run-board-notes.ts +7 -1
  518. package/scripts/run/board/run-board-operation.ts +4 -2
  519. package/scripts/run/board/run-board-phase.ts +2 -5
  520. package/scripts/run/board/run-board-plan.ts +1 -1
  521. package/scripts/run/board/run-board-read.ts +46 -1
  522. package/scripts/run/board/run-board-reason.ts +20 -8
  523. package/scripts/run/board/run-board-render-checks.ts +3 -2
  524. package/scripts/run/board/run-board-render-drawn.ts +11 -0
  525. package/scripts/run/board/run-board-render-found.ts +157 -0
  526. package/scripts/run/board/run-board-render-lead.ts +9 -0
  527. package/scripts/run/board/run-board-render-legend.ts +19 -0
  528. package/scripts/run/board/run-board-render-tail.ts +1 -1
  529. package/scripts/run/board/run-board-render.ts +82 -18
  530. package/scripts/run/board/run-board-spin.ts +1 -3
  531. package/scripts/run/board/run-board-status.ts +2 -0
  532. package/scripts/run/board/run-board-tick.ts +39 -10
  533. package/scripts/run/carry/run-carry-ended.ts +3 -2
  534. package/scripts/run/carry/run-carry.ts +3 -2
  535. package/scripts/run/cut/run-cut-cli.ts +33 -133
  536. package/scripts/run/cut/run-cut-digest.ts +152 -0
  537. package/scripts/run/cut/run-cut-handoff.ts +52 -8
  538. package/scripts/run/cut/run-cut-report.ts +24 -3
  539. package/scripts/run/cut/run-cut-resume.ts +129 -0
  540. package/scripts/run/cut/run-cut-review.ts +105 -0
  541. package/scripts/run/cut/run-cut.ts +18 -7
  542. package/scripts/run/detached-launch.ts +1 -1
  543. package/scripts/run/entry/run-entry-cli.ts +88 -19
  544. package/scripts/run/entry/run-entry-spill.ts +83 -0
  545. package/scripts/run/entry/run-entry-stop.ts +5 -1
  546. package/scripts/run/entry/run-entry-trust.ts +91 -0
  547. package/scripts/run/event/run-event-baseline.ts +56 -0
  548. package/scripts/run/event/run-event-filed.ts +9 -3
  549. package/scripts/run/event/run-event-overrun.ts +197 -0
  550. package/scripts/run/event/run-event-render.ts +4 -0
  551. package/scripts/run/event/run-event-stream.ts +25 -3
  552. package/scripts/run/hold/run-stop-notify.ts +3 -8
  553. package/scripts/run/merge/run-merge-cap.ts +57 -0
  554. package/scripts/run/merge/run-merge-cli.ts +66 -23
  555. package/scripts/run/merge/run-merge-outcome.ts +2 -0
  556. package/scripts/run/merge/run-merge-ship.ts +13 -3
  557. package/scripts/run/merge/run-merge-signals.ts +40 -23
  558. package/scripts/run/merge/run-merge-steps.ts +56 -36
  559. package/scripts/run/merge/run-merge-usage-limit.ts +53 -0
  560. package/scripts/run/merge/run-merge-withdrawn.ts +53 -0
  561. package/scripts/run/merge/run-merge.ts +41 -14
  562. package/scripts/run/review/run-review-cli.ts +306 -20
  563. package/scripts/run/review/run-review-early-push.ts +121 -0
  564. package/scripts/run/review/run-review-join-read.ts +94 -0
  565. package/scripts/run/review/run-review-pinned-accepted.ts +126 -0
  566. package/scripts/run/review/run-review-pinned-join.ts +216 -0
  567. package/scripts/run/review/run-review-pinned-steps.ts +383 -0
  568. package/scripts/run/review/run-review-pinned-tree.ts +37 -0
  569. package/scripts/run/review/run-review-pinned.ts +53 -0
  570. package/scripts/run/review/run-review-steps.ts +70 -34
  571. package/scripts/run/review/run-review.ts +26 -6
  572. package/scripts/run/run-parent-cut-hook.ts +3 -4
  573. package/scripts/run/run-prep.ts +1 -0
  574. package/scripts/run/run-stage-read.ts +2 -6
  575. package/scripts/run/run-step-cli.ts +17 -5
  576. package/scripts/run/run-step-lane-plan.ts +27 -0
  577. package/scripts/run/run-step-section.ts +26 -7
  578. package/scripts/run/run-step.ts +5 -2
  579. package/scripts/run/ship/run-ship-args.ts +19 -0
  580. package/scripts/run/ship/run-ship-brokered-review.ts +106 -0
  581. package/scripts/run/ship/run-ship-cli.ts +131 -39
  582. package/scripts/run/ship/run-ship-conflict-probe.ts +59 -0
  583. package/scripts/run/ship/run-ship-detach.ts +10 -4
  584. package/scripts/run/ship/run-ship-handover.ts +106 -0
  585. package/scripts/run/ship/run-ship-infra-retry.ts +16 -1
  586. package/scripts/run/ship/run-ship-lap.ts +63 -0
  587. package/scripts/run/ship/run-ship-next.ts +27 -26
  588. package/scripts/run/ship/run-ship-overlap.ts +8 -3
  589. package/scripts/run/ship/run-ship-place.ts +9 -2
  590. package/scripts/run/ship/run-ship-planned.ts +92 -0
  591. package/scripts/run/ship/run-ship-pre-detach-pinned.ts +197 -0
  592. package/scripts/run/ship/run-ship-pre-detach-timed.ts +7 -8
  593. package/scripts/run/ship/run-ship-pre-detach.ts +77 -23
  594. package/scripts/run/ship/run-ship-preflight.ts +16 -4
  595. package/scripts/run/ship/run-ship-probe.ts +23 -9
  596. package/scripts/run/ship/run-ship-relaunch-cap.ts +43 -7
  597. package/scripts/run/ship/run-ship-relaunch.ts +51 -0
  598. package/scripts/run/ship/run-ship-return.ts +103 -29
  599. package/scripts/run/ship/run-ship-review-reason.ts +24 -0
  600. package/scripts/run/ship/run-ship-review-steps.ts +230 -59
  601. package/scripts/run/ship/run-ship-review.ts +171 -51
  602. package/scripts/run/ship/run-ship-reviewer.ts +138 -42
  603. package/scripts/run/ship/run-ship-scoped.ts +39 -10
  604. package/scripts/run/ship/run-ship-stage.ts +49 -13
  605. package/scripts/run/ship/run-ship-steps.ts +24 -4
  606. package/scripts/run/ship/run-ship-stop-cause.ts +43 -2
  607. package/scripts/run/ship/run-ship-stop-context.ts +50 -13
  608. package/scripts/run/ship/run-ship-sync.ts +171 -30
  609. package/scripts/run/ship/run-ship-synced-scope.ts +178 -0
  610. package/scripts/run/ship/run-ship-wait-cli.ts +145 -0
  611. package/scripts/run/ship/run-ship-waiter.ts +114 -0
  612. package/scripts/run/ship/run-ship.ts +16 -2
  613. package/scripts/run/wake/run-wake-caffeinate.ts +48 -0
  614. package/scripts/run/wake/run-wake-cli.ts +6 -113
  615. package/scripts/run/wake/run-wake-code.ts +53 -11
  616. package/scripts/run/wake/run-wake-driver.ts +5 -3
  617. package/scripts/run/wake/run-wake-finish.ts +137 -0
  618. package/scripts/run/wake/run-wake-loop.ts +5 -3
  619. package/scripts/run/wake/run-wake-ports.ts +11 -3
  620. package/scripts/run/wake/run-wake-session.ts +2 -0
  621. package/scripts/run/wake/run-wake.ts +3 -2
  622. package/scripts/safe-chain/ci-installer-pin.ts +49 -8
  623. package/scripts/safe-chain/project-config.ts +3 -2
  624. package/scripts/security/secretlint-scan.ts +42 -9
  625. package/scripts/security/security-audit-provision-main.ts +9 -1
  626. package/scripts/security/security-audit-provision.ts +1 -1
  627. package/scripts/security/security-audit.ts +21 -1
  628. package/scripts/security/sonar-file.ts +10 -5
  629. package/scripts/split/split-assess.ts +12 -3
  630. package/scripts/split/split-early-notice.ts +116 -0
  631. package/scripts/split/split-measure.ts +20 -2
  632. package/scripts/split/split-resolution.ts +107 -0
  633. package/scripts/test/direct-importers.ts +185 -0
  634. package/scripts/test/pure-files-entries.ts +83 -0
  635. package/scripts/test/related-heavy-tests.ts +81 -0
  636. package/scripts/test/test-no-base.ts +88 -0
  637. package/scripts/test/test-pinned-cache-logic.ts +363 -0
  638. package/scripts/test/test-pinned-cache.ts +337 -0
  639. package/scripts/test/test-pinned-emit.ts +49 -0
  640. package/scripts/test/test-pinned-functions.ts +116 -0
  641. package/scripts/test/test-pinned-ledger.ts +80 -0
  642. package/scripts/test/test-pinned-logic.ts +208 -20
  643. package/scripts/test/test-pinned-main.ts +84 -18
  644. package/scripts/test/test-pinned-pool.ts +73 -0
  645. package/scripts/test/test-pinned-probe.ts +254 -0
  646. package/scripts/test/test-pinned-prune-logic.ts +118 -0
  647. package/scripts/test/test-pinned-reach.ts +194 -0
  648. package/scripts/test/test-pinned-record.ts +196 -0
  649. package/scripts/test/test-pinned-rewire.ts +148 -0
  650. package/scripts/test/test-pinned-spawn.ts +81 -0
  651. package/scripts/test/test-pinned-stage.ts +70 -0
  652. package/scripts/test/test-pinned.ts +258 -47
  653. package/scripts/test/test-reach-cli.ts +61 -0
  654. package/scripts/test/test-read-map.ts +35 -11
  655. package/scripts/test/test-read-recording.ts +17 -5
  656. package/scripts/test/test-read-trace.ts +26 -8
  657. package/scripts/test/test-red-logic.ts +46 -7
  658. package/scripts/test/test-red.ts +34 -14
  659. package/scripts/test/test-related-claim.ts +37 -0
  660. package/scripts/test/test-related-main.ts +4 -1
  661. package/scripts/test/test-related-moved.ts +91 -0
  662. package/scripts/test/test-related-record.ts +43 -23
  663. package/scripts/test/test-related-scope.ts +99 -34
  664. package/scripts/test/test-related-synced.ts +135 -0
  665. package/scripts/test/test-related-touched.ts +84 -0
  666. package/scripts/test/test-related.ts +167 -83
  667. package/scripts/test/test-unit-guard.ts +28 -5
  668. package/scripts/test/unit-durations.ts +41 -0
  669. package/scripts/test/unit-worker-share.ts +5 -4
  670. package/scripts/test/vitest-cache-directory.ts +19 -0
  671. package/scripts/test/vitest-cli-excludes.ts +14 -0
  672. package/scripts/test/vitest-failure-summary.ts +111 -0
  673. package/scripts/test/whole-suite-files.ts +12 -1
  674. package/scripts/time-runtime/time-batch-guard.ts +42 -4
  675. package/scripts/time-runtime/time-bundle-call.ts +1 -1
  676. package/scripts/time-runtime/time-bundles.ts +36 -5
  677. package/scripts/time-runtime/time-markers.ts +2 -2
  678. package/scripts/time-runtime/time-search-call.ts +38 -0
  679. package/scripts/time-runtime/time-shell.ts +1 -1
  680. package/scripts/time-runtime/time-transcript-line.ts +17 -5
  681. package/scripts/version/development-engines-verdict.ts +124 -0
  682. package/scripts/version/latest-corepack.ts +2 -0
  683. package/templates/gitignore +2 -0
  684. package/templates/workflows/ci.yml +41 -0
  685. package/dist/hooks/chunk-AZX4FGQ3.js +0 -207
  686. package/dist/hooks/chunk-PT5R6UJD.js +0 -7131
  687. package/dist/hooks/chunk-TUIFS5E7.js +0 -72
  688. package/dist/hooks/chunk-YCDOIR3I.js +0 -3456
  689. package/scripts/cost-runtime/context-cut-threshold.ts +0 -11
  690. package/scripts/rules/filing-cap.ts +0 -139
@@ -1,6 +1,10 @@
1
1
  import { repo_party } from '#scripts/discovery/repo-party'
2
2
  import { bash_triggers } from './bash-triggers'
3
3
  import { gh_api } from './gh-api'
4
+ import { gh_repo_selector } from './gh-repo-selector'
5
+ import { git_argv } from './git-argv'
6
+ import { pr_merge } from './pr-merge'
7
+ import { repo_admin } from './repo-admin'
4
8
  import { shell_segments } from './shell-segments'
5
9
 
6
10
  // The trigger and the delivered text behind the `third-party-write` row of `delivered-rules.ts`.
@@ -70,44 +74,126 @@ function candidates_at(
70
74
  return has_moved ? unreadable_candidates : resolve_placeholder_owners
71
75
  }
72
76
 
73
- // The session owner is read only when a segment is actually a `gh api` write to a repository — so an
74
- // ordinary shell line, and every read, pays nothing for the local config read. `resolve_owner` and
77
+ // A merge or an administration write is refused by its own row whoever owns the target, and one
78
+ // refusal is what a PreToolUse hook carries — so the two readings this row added for
79
+ // joshuafolkken/kit#4659 leave those to the row that names them. Asked only of a candidate, so an
80
+ // ordinary shell line pays nothing for it.
81
+ function is_claimed_by_narrower_row(command: string): boolean {
82
+ return pr_merge.is_pr_merge(command) || repo_admin.is_repo_admin_write(command)
83
+ }
84
+
85
+ // **A GraphQL mutation names no repository this guard can read** (joshuafolkken/kit#4659): its target
86
+ // is a node id inside the body, so it is refused whoever owns the session — the disposition
87
+ // `pr-merge.ts` takes for a GraphQL body it cannot read, which that row already refuses for a body
88
+ // read from a file or computed by the shell. A query passes. The keyword is looked for in the whole
89
+ // line, because the segment cut ignores quotes and a multi-line query splits across it. A query field
90
+ // the shell expands (`query="$Q"`, or the whole argument quoted: `"query=$Q"`) hides its keyword the
91
+ // same way, so it is refused as a mutation; a single-quoted `query='query($o: String!) {…}'` is
92
+ // literal and still read. A body read from a file is `pr-merge.ts`'s, which refuses it already.
93
+ const GRAPHQL_MUTATION = /\bmutation\b/u
94
+ const EXPANDED_QUERY = /^(?:-[fF])?"?query=(?!')[\s\S]*\$/u
95
+
96
+ function is_hidden_or_mutation(command: string, args: ReadonlyArray<string>): boolean {
97
+ return GRAPHQL_MUTATION.test(command) || args.some((argument) => EXPANDED_QUERY.test(argument))
98
+ }
99
+
100
+ // The arguments of a `gh api` GraphQL call, or `undefined` when the segment is not one.
101
+ function graphql_args(segment: string): ReadonlyArray<string> | undefined {
102
+ const call = git_argv.program_of(segment)
103
+
104
+ if (call === undefined || !gh_api.is_gh_api(segment)) return undefined
105
+
106
+ return pr_merge.is_graphql_call(call.name, call.args) ? call.args : undefined
107
+ }
108
+
109
+ function is_graphql_mutation(command: string, segment: string): boolean {
110
+ const args = graphql_args(segment)
111
+
112
+ if (args === undefined) return false
113
+
114
+ return is_hidden_or_mutation(command, args) && !is_claimed_by_narrower_row(command)
115
+ }
116
+
117
+ // **A `gh <group> <action> -R <owner>/<repo>` write is judged by its selector** (kit#4659).
118
+ // A selector whose owner cannot be read (`-R "$REPO"`) is refused, like an unreadable placeholder
119
+ // candidate: it is a repository `gh` really writes to.
120
+ function is_third_party_selector_write(
121
+ command: string,
122
+ segments: ReadonlyArray<string>,
123
+ index: number,
124
+ session_owner: string | undefined,
125
+ ): boolean {
126
+ const selectors = gh_repo_selector.write_selectors(segments, index)
127
+ const is_third_party = selectors.some((selector) => {
128
+ const owner = repo_party.selector_owner(selector)
129
+
130
+ return (
131
+ owner === undefined || repo_party.classify(session_owner, owner) === repo_party.THIRD_PARTY
132
+ )
133
+ })
134
+
135
+ return is_third_party && !is_claimed_by_narrower_row(command)
136
+ }
137
+
138
+ function is_owner_dependent_write(segments: ReadonlyArray<string>, index: number): boolean {
139
+ const segment = segments[index] ?? ''
140
+
141
+ if (gh_api.is_gh_api(segment)) return gh_api.is_write(segment)
142
+
143
+ return gh_repo_selector.write_selectors(segments, index).length > 0
144
+ }
145
+
146
+ function writes_to_third_party_owner(
147
+ command: string,
148
+ segments: ReadonlyArray<string>,
149
+ resolve_owner: () => string | undefined,
150
+ resolve_placeholder_owners: () => Array<string | undefined>,
151
+ ): boolean {
152
+ if (segments.every((_segment, index) => !is_owner_dependent_write(segments, index))) return false
153
+
154
+ const session_owner = resolve_owner()
155
+
156
+ return segments.some(
157
+ (segment, index) =>
158
+ is_third_party_selector_write(command, segments, index, session_owner) ||
159
+ is_third_party_write_segment(
160
+ segment,
161
+ session_owner,
162
+ candidates_at(segments, index, resolve_placeholder_owners),
163
+ ),
164
+ )
165
+ }
166
+
167
+ // The session owner is read only when a segment is actually a repository write — so an ordinary shell
168
+ // line, and every read, pays nothing for the local config read. `resolve_owner` and
75
169
  // `resolve_placeholder_owners` are injected so the suite fixes the owners without touching the real
76
170
  // remotes, the way `file-body.ts` injects `has_file`. Each segment is judged on its own, so a `gh api`
77
171
  // write quoted inside another command's argument is read as the write it is not, exactly as every
78
- // other trigger here reads its own.
172
+ // other trigger here reads its own. The cut is by program — a pipe and a background `&` cut too, a
173
+ // quoted one does not — after joining backslash-continued lines, so `echo hi | gh pr comment …` and a
174
+ // `gh api graphql \⏎ -f query=…` are each read as the one `gh` call they launch.
79
175
  function writes_third_party(
80
176
  command: string,
81
177
  resolve_owner: () => string | undefined = repo_party.current_owner,
82
178
  resolve_placeholder_owners: () => Array<string | undefined> = repo_party.placeholder_owners,
83
179
  ): boolean {
84
- const segments = shell_segments.segments_of(command)
85
- const has_write = segments.some(
86
- (segment) => gh_api.is_gh_api(segment) && gh_api.is_write(segment),
180
+ const segments = shell_segments.quote_aware_commands_of(
181
+ shell_segments.joined_continuations(command),
87
182
  )
88
183
 
89
- if (!has_write) return false
90
-
91
- const session_owner = resolve_owner()
184
+ if (segments.some((segment) => is_graphql_mutation(command, segment))) return true
92
185
 
93
- return segments.some((segment, index) =>
94
- is_third_party_write_segment(
95
- segment,
96
- session_owner,
97
- candidates_at(segments, index, resolve_placeholder_owners),
98
- ),
99
- )
186
+ return writes_to_third_party_owner(command, segments, resolve_owner, resolve_placeholder_owners)
100
187
  }
101
188
 
102
189
  // The instruction in the shape a refusal can carry: what the command does, why it is Tier C, and what
103
190
  // to do instead. The command that computes the party is handed over, because the whole point of this
104
191
  // Issue is that the test is computed rather than judged.
105
192
  const THIRD_PARTY_WRITE_REASON =
106
- '⛔ third-party write: this `gh api` call writes to a repository whose owner is not this session, ' +
107
- 'which is Tier C and needs explicit current-turn user instruction. Check with ' +
108
- '`pnpm josh repo:party <owner/repo>`, then record the finding on our own Issue and draft the ' +
109
- 'artifact for a person to post. This rule fires on every occurrence ' +
110
- '(`prompts/collaboration-workflow/upstream-interrupt.md`).'
193
+ "⛔ third-party write: this `gh` call writes to another owner's repository, or one it cannot " +
194
+ 'read (a GraphQL mutation, an unreadable `-R`) — Tier C. Check `pnpm josh repo:party ' +
195
+ '<owner/repo>`; first-party, use a REST `repos/<owner>/<repo>` path. Else record it on our ' +
196
+ 'Issue and draft it for a person to post. Fires on every occurrence (`upstream-interrupt.md`).'
111
197
 
112
198
  // `decide` returns true so it refuses every occurrence; it declares no `keeps` — not writing to
113
199
  // another owner's tracker is the absence of a call, not a call, so the row is reported unmeasured
@@ -121,8 +207,9 @@ const ROW = {
121
207
  title: 'Third-party write',
122
208
  topic: '`upstream-interrupt.md`',
123
209
  fires:
124
- 'a `gh api` write (field flag or a write method) to a repository whose owner is not this session. Every occurrence',
125
- quiet: 'a read, or a first-party owner (`pnpm josh repo:party`)',
210
+ 'a `gh api` write (field flag or a write method) or a `gh <group> <action>` write selected by `-R` / `GH_REPO` to a repository whose owner is not this session, or a `gh api graphql` call whose line names `mutation` or whose query the shell expands, outside the merge and administration rows. Every occurrence',
211
+ quiet:
212
+ 'a read, a GraphQL query, or a first-party owner (pinned at session start, `pnpm josh repo:party`)',
126
213
  },
127
214
  }
128
215
 
@@ -12,7 +12,7 @@ import { shell_segments } from './shell-segments'
12
12
  //
13
13
  // **Once per run.** The rule allows one re-run when the record cannot answer, so the reissue goes
14
14
  // through. On that reissue `lane-direct-tool` still refuses a lane child's `time`-prefixed heavy tool
15
- // (`git_argv` skips the timer) and points it at `pnpm josh reserved-run`, the overlap
15
+ // (`git_argv` skips the timer), never wrapping it, and points it at `pnpm josh reserved-run`, the overlap
16
16
  // `delivered-rules.ts` admits. A `hyperfine "<command>"` carries the tool inside a quoted argument,
17
17
  // which `lane-direct-tool` does not read, so in a lane that reissue is not budgeted.
18
18
 
@@ -0,0 +1,90 @@
1
+ import { time_shell } from '#scripts/time-runtime/time-shell'
2
+ import { time_transcript_line, type Block } from '#scripts/time-runtime/time-transcript-line'
3
+ import { bash_triggers } from './bash-triggers'
4
+ import { tail_commands } from './tail-commands'
5
+
6
+ // The filings a turn made, read off the session transcript for the `Stop` hook's offer to file
7
+ // (`stop-guard.ts`). **No new predicate**: the filing is `bash_triggers.is_issue_filing`, reused
8
+ // verbatim. The filing cap is not this count — it is `issue:file`'s own step, per originating work item
9
+ // (`scripts/issue/issue-file-cap.ts`, joshuafolkken/kit#4750).
10
+ //
11
+ // **A guard-refused filing does not count.** Claude Code writes a denied call to the transcript as a
12
+ // `tool_use` block with an errored `tool_result` — the same exclusion `investigation-reads.ts` makes
13
+ // for a refused read. **Nor does one `issue:file` held itself**: a lint problem or an unacknowledged
14
+ // duplicate exits non-zero having filed nothing. The filing is counted only where its result did not
15
+ // fail.
16
+
17
+ interface TailFilings {
18
+ // The `tool_use` id of every filing on the tail.
19
+ filing_ids: Array<string>
20
+ // The id of every result that came back as a failure — a guard refusal, or `issue:file` holding the
21
+ // filing itself (a lint problem, an unacknowledged duplicate), which files nothing either.
22
+ failures: Set<string>
23
+ }
24
+
25
+ function is_filing_use(block: Block): boolean {
26
+ if (!tail_commands.is_bash_use(block)) return false
27
+
28
+ return bash_triggers.is_issue_filing(time_shell.bash_command(block.input))
29
+ }
30
+
31
+ function collect_block(block: Block, found: TailFilings): void {
32
+ if (block.result_id !== '' && block.is_error === true) found.failures.add(block.result_id)
33
+ if (is_filing_use(block)) found.filing_ids.push(block.id)
34
+ }
35
+
36
+ function collect_line(line: string, found: TailFilings): void {
37
+ const parsed = time_transcript_line.parse_line(line)
38
+
39
+ if (parsed === undefined) return
40
+
41
+ for (const block of parsed.blocks) collect_block(block, found)
42
+ }
43
+
44
+ function scan_tail(tail: string): TailFilings {
45
+ const found: TailFilings = { filing_ids: [], failures: new Set<string>() }
46
+
47
+ for (const line of tail.split('\n')) collect_line(line, found)
48
+
49
+ return found
50
+ }
51
+
52
+ // How many Issues the tail filed, counting only filings whose result did not fail.
53
+ function filing_count(tail: string): number {
54
+ const { filing_ids, failures } = scan_tail(tail)
55
+
56
+ return filing_ids.filter((id) => !failures.has(id)).length
57
+ }
58
+
59
+ // A person's prompt: a `user` line carrying no tool result. Tool results ride `user` lines too, so the
60
+ // absence of one is what marks the line as typed rather than returned.
61
+ function is_prompt_line(line: string): boolean {
62
+ const parsed = time_transcript_line.parse_line(line)
63
+
64
+ if (parsed?.type !== 'user') return false
65
+
66
+ return parsed.blocks.every((block) => block.result_id === '')
67
+ }
68
+
69
+ // The tail from the last prompt on, so a filing an earlier turn made does not answer for this one.
70
+ // A tail with no prompt on it is returned whole.
71
+ function current_turn(tail: string): string {
72
+ const lines = tail.split('\n')
73
+ const start = lines.findLastIndex((line) => is_prompt_line(line))
74
+
75
+ return lines.slice(Math.max(start, 0)).join('\n')
76
+ }
77
+
78
+ // How many Issues this turn has filed — `filing_count` read over `current_turn`.
79
+ function turn_filing_count(tail: string): number {
80
+ return filing_count(current_turn(tail))
81
+ }
82
+
83
+ const turn_filings = {
84
+ current_turn,
85
+ filing_count,
86
+ is_prompt_line,
87
+ turn_filing_count,
88
+ }
89
+
90
+ export { turn_filings }
@@ -25,6 +25,14 @@ import { shell_segments } from './shell-segments'
25
25
  // stash with `git stash apply`, and the lane parked on how to apply it instead of popping by message;
26
26
  // the reason now says the substitution is the run's own to make (joshuafolkken/kit#3648).
27
27
  //
28
+ // **The refusal names the way back for a single file.** A lane that refused `git checkout -- <file>`
29
+ // reverted its own edit by hand with `Edit` and left a line behind, so a green record landed on the
30
+ // wrong tree (joshuafolkken/kit#4988). The named restore writes HEAD's bytes over that one file, carries
31
+ // no body inline (`file-edits.md`), and no row refuses it. It reverses the file's unstaged diff, so a
32
+ // staged change (the user's) stays, `<path>` is read from the shell's directory like any pathspec,
33
+ // nothing is emptied before git runs (a `git show HEAD:<path> > <path>` redirect is), and an untracked
34
+ // path has no diff to reverse.
35
+ //
28
36
  // **It fires on every occurrence**, for the reason `git-force.ts` does: discarding the working tree is
29
37
  // destructive each time it is issued.
30
38
 
@@ -122,33 +130,40 @@ function is_unauthorized_worktree_change(command: string): boolean {
122
130
  return shell_segments.commands_of(command).some((segment) => is_unauthorized_segment(segment))
123
131
  }
124
132
 
125
- // The instruction in the shape a refusal can carry: what the command touches, the authorized route,
126
- // and — for a stash — the message form that is allowed. `pnpm josh git` and `pnpm josh stash:pop` are
127
- // invisible to this trigger, so a run that uses them is never refused.
133
+ // The instruction in the shape a refusal can carry: the authorized route — for one file, the restore,
134
+ // limited to this run's own edit (another's uncommitted change is never discarded); for a stash, the
135
+ // message form that is allowed. The refused command is the caller's own, so it is not listed back.
136
+ // The `headline:` opening is what `time-transcript-line.ts` names the guard by. `pnpm josh git` and
137
+ // `pnpm josh stash:pop` are invisible to this trigger, so a run that uses them is never refused.
138
+ const SINGLE_FILE_RESTORE = 'git diff -- <path> | git apply -R'
128
139
  const WORKTREE_MUTATION_REASON =
129
- '⛔ unauthorized working-tree change: `git checkout --`, `git restore`, `git clean -f`, ' +
130
- '`git stash`. A documented flow stashes with `pnpm josh stash:push "<message>"`; a handed-over ' +
140
+ "⛔ unauthorized working-tree change: undo only this run's edit: " +
141
+ `\`${SINGLE_FILE_RESTORE}\`. A documented flow stashes with ` +
142
+ '`pnpm josh stash:push "<message>"`; a handed-over ' +
131
143
  'stash is `pnpm josh stash:pop "<message>"`; record the substitution on the Issue (Tier A) unless ' +
132
144
  'the plan says why the owner keeps the stash: then stop and confirm. It fires on every occurrence ' +
133
145
  '(`operating-rules.md`).'
146
+ // The opening before joshuafolkken/kit#4988, so `rule-value.ts` still credits a refusal it delivered.
147
+ const FORMER_OPENING = '⛔ unauthorized working-tree change: `git checkout --`, `git restore`'
134
148
 
135
149
  const ROW = {
136
150
  id: 'worktree-mutation',
137
151
  is_trigger: bash_triggers.on_bash_command(is_unauthorized_worktree_change),
138
152
  reason: WORKTREE_MUTATION_REASON,
153
+ former_reasons: [FORMER_OPENING],
139
154
  decide: (): boolean => true,
140
155
  about: {
141
156
  title: 'Unauthorized work-tree mutation',
142
157
  topic: '`operating-rules.md`',
143
158
  fires:
144
159
  '`git checkout -- <path>` / `git restore <path>` / forced `git clean -f` / an unauthorized `git stash` (bare, push without a message, positional pop). Every occurrence',
145
- quiet:
146
- '`git stash push -m`, `git stash list`, `pnpm josh git`, `pnpm josh stash:push`, `pnpm josh stash:pop`',
160
+ quiet: `\`git stash push -m\`, \`git stash list\`, \`pnpm josh git\`, \`pnpm josh stash:push\`, \`pnpm josh stash:pop\`, \`${SINGLE_FILE_RESTORE}\``,
147
161
  },
148
162
  }
149
163
 
150
164
  const worktree_guard = {
151
165
  ROW,
166
+ SINGLE_FILE_RESTORE,
152
167
  WORKTREE_MUTATION_REASON,
153
168
  is_unauthorized_worktree_change,
154
169
  touches_worktree,
@@ -1,3 +1,4 @@
1
+ import { lane_withdraw } from '#scripts/lane/lane-withdraw'
1
2
  import { run_event_scope } from '#scripts/run/event/run-event-scope'
2
3
  import { run_event_stream, type RunEvent } from '#scripts/run/event/run-event-stream'
3
4
  import { run_stalled } from '#scripts/run/park/run-stalled'
@@ -10,8 +11,11 @@ const KIND = run_event_stream.EVENT_KIND
10
11
  // waiting park does not name its issue twice.
11
12
  const PARK_PREFIX = /^#\d+ (?:parked\s*)?/u
12
13
  const PARENTHESES = /^\((?<inner>.*)\)$/u
13
- // `#<N> withdrawn by a person: <reason>` (`lane-withdraw.ts`).
14
- const WITHDRAW_PREFIX = /^#\d+ withdrawn by a person:\s*/u
14
+ // `#<N> withdrawn by <who>: <reason>` — every withdrawer `lane-withdraw.ts` names.
15
+ const WITHDRAW_PREFIX = new RegExp(
16
+ String.raw`^#\d+ withdrawn by (?:${lane_withdraw.WITHDRAWER_NAMES.join('|')}):\s*`,
17
+ 'u',
18
+ )
15
19
 
16
20
  // `#<N> parked (needs-decision)` reads as the reason `needs-decision`; a bare park has none.
17
21
  function park_reason(event: RunEvent): string {
@@ -107,9 +107,32 @@ const NO_CUT: Cut = {
107
107
  rows: new Set(),
108
108
  }
109
109
 
110
+ // A line of printable ASCII alone takes a column a character, so `string-width` is spared it.
111
+ const PRINTABLE_ASCII = /^[ -~]*$/u
112
+
113
+ // The widths measured so far. A fit weighs a frame for every cut of its order, each repeating most of
114
+ // the last one's lines, and the next redraw draws nearly the same lines and cells again, so each is
115
+ // measured once (joshuafolkken/kit#5185). Let go whole once it holds `WIDTHS_KEPT`, so a long-running
116
+ // board does not keep every line it stopped drawing.
117
+ const WIDTHS_KEPT = 10_000
118
+ const widths = new Map<string, number>()
119
+
120
+ function measured(plain: string): number {
121
+ return PRINTABLE_ASCII.test(plain) ? plain.length : string_width(plain)
122
+ }
123
+
110
124
  // The columns a line takes on screen: its color escapes take none, an emoji two.
111
125
  function width_of(line: string): number {
112
- return string_width(stripVTControlCharacters(line))
126
+ const known = widths.get(line)
127
+
128
+ if (known !== undefined) return known
129
+ if (widths.size >= WIDTHS_KEPT) widths.clear()
130
+
131
+ const width = measured(stripVTControlCharacters(line))
132
+
133
+ widths.set(line, width)
134
+
135
+ return width
113
136
  }
114
137
 
115
138
  function height_of(line: string, columns: number): number {
@@ -0,0 +1,134 @@
1
+ import { process_identity } from '#scripts/josh/process-identity'
2
+ import { lane_process_table, type TableRead } from '#scripts/lane/lane-process-table'
3
+ import { run_event_filed } from '#scripts/run/event/run-event-filed'
4
+ import {
5
+ run_event_overrun,
6
+ type Longest,
7
+ type OverrunNote,
8
+ } from '#scripts/run/event/run-event-overrun'
9
+ import { run_event_stream, type RunEvent } from '#scripts/run/event/run-event-stream'
10
+
11
+ // What a done row says after its time (joshuafolkken/kit#4772, joshuafolkken/kit#4818): the Issues
12
+ // filed during its child's work, its lane's net minutes and what its overrun investigation came to —
13
+ // read off the stream's `filed` events and the overrun notes (`run-event-overrun.ts`). The child's own
14
+ // filings and the investigation's are kept apart by the event's recorded mark (joshuafolkken/kit#4880).
15
+
16
+ interface Found {
17
+ // Each filing of the child's own session as `header.link` takes it: `4768`, or `owner/repo#12` for
18
+ // one filed elsewhere. An event with no overrun mark is the child's.
19
+ filed: ReadonlyArray<string>
20
+ // Each filing of the lane's overrun investigation, read off its mark (joshuafolkken/kit#4880).
21
+ overrun_filed: ReadonlyArray<string>
22
+ // The lane's net minutes, from the notes; `undefined` where none said them.
23
+ minutes: number | undefined
24
+ // The child's latest overrun note.
25
+ overrun: OverrunNote | undefined
26
+ // The longest stage the overrun's start note carried (joshuafolkken/kit#4995), kept past its end note.
27
+ longest: Longest | undefined
28
+ // The latest note is the investigation's start and its session is alive; `undefined` where its start
29
+ // token could not be read, so neither its life nor its death is known.
30
+ is_investigating: boolean | undefined
31
+ }
32
+
33
+ // By the child's number.
34
+ type FoundOf = ReadonlyMap<number, Found>
35
+
36
+ // Whether the process a start note names — its pid and start token — is still there, one this reader
37
+ // may not signal included, `undefined` where the note carries no start token; injected, so a test never
38
+ // probes one.
39
+ type IsLive = (pid: number, start: string | undefined) => boolean | undefined
40
+
41
+ const KIND = run_event_stream.EVENT_KIND
42
+ const NONE: Found = {
43
+ filed: [],
44
+ overrun_filed: [],
45
+ minutes: undefined,
46
+ overrun: undefined,
47
+ longest: undefined,
48
+ is_investigating: false,
49
+ }
50
+
51
+ // The child a filing was found during, the reference the board draws, and whether the overrun filed it.
52
+ type FiledEntry = readonly [number, string, boolean]
53
+
54
+ function filed_entry(event: RunEvent): ReadonlyArray<FiledEntry> {
55
+ const filed = event.kind === KIND.FILED ? run_event_filed.parse(event.text) : undefined
56
+
57
+ if (filed?.found_during === undefined) return []
58
+
59
+ return [
60
+ [Number(filed.found_during), filed.reference.replace(/^#/u, ''), filed.is_overrun === true],
61
+ ]
62
+ }
63
+
64
+ function with_filed(known: Found, reference: string, is_overrun: boolean): Found {
65
+ if (is_overrun) return { ...known, overrun_filed: [...known.overrun_filed, reference] }
66
+
67
+ return { ...known, filed: [...known.filed, reference] }
68
+ }
69
+
70
+ function overrun_note(event: RunEvent): OverrunNote | undefined {
71
+ return event.kind === KIND.NOTE ? run_event_overrun.parse(event.text) : undefined
72
+ }
73
+
74
+ // The minutes a note carries, else the ones an earlier note did: an end note carries none.
75
+ function minutes_of(note: OverrunNote, known: number | undefined): number | undefined {
76
+ return 'minutes' in note ? (note.minutes ?? known) : known
77
+ }
78
+
79
+ // A session that died before its end note turns no spinner, nor does a later process given its pid.
80
+ function noted(found: Found, note: OverrunNote, is_live: IsLive): Found {
81
+ return {
82
+ ...found,
83
+ minutes: minutes_of(note, found.minutes),
84
+ overrun: note,
85
+ longest: note.kind === 'started' ? note.longest : found.longest,
86
+ is_investigating: note.kind === 'started' ? is_live(note.pid, note.start) : false,
87
+ }
88
+ }
89
+
90
+ function add_filed(found: Map<number, Found>, events: ReadonlyArray<RunEvent>): void {
91
+ const entries = events.flatMap((event) => filed_entry(event))
92
+
93
+ for (const [issue, reference, is_overrun] of entries) {
94
+ found.set(issue, with_filed(found.get(issue) ?? NONE, reference, is_overrun))
95
+ }
96
+ }
97
+
98
+ // Each child's latest overrun note decides what its row says.
99
+ function add_overrun(
100
+ found: Map<number, Found>,
101
+ events: ReadonlyArray<RunEvent>,
102
+ is_live: IsLive,
103
+ ): void {
104
+ const notes = events.flatMap((event) => overrun_note(event) ?? [])
105
+
106
+ for (const note of notes) {
107
+ found.set(note.issue, noted(found.get(note.issue) ?? NONE, note, is_live))
108
+ }
109
+ }
110
+
111
+ function found_of(events: ReadonlyArray<RunEvent>, is_live: IsLive): FoundOf {
112
+ const found = new Map<number, Found>()
113
+
114
+ add_filed(found, events)
115
+ add_overrun(found, events, is_live)
116
+
117
+ return found
118
+ }
119
+
120
+ // The board's own probe, each start time answered from the read's own `ps` snapshot, so neither the
121
+ // read nor a redraw runs a `ps` of its own per note (joshuafolkken/kit#4263). The pid alone reads a
122
+ // later process given that pid as the session, so the start token decides; a note without one — a
123
+ // platform that could not read it — is known dead only once its pid is gone.
124
+ async function live_in(table: TableRead | undefined): Promise<IsLive> {
125
+ const rows = table === undefined ? undefined : await table()
126
+ const read = lane_process_table.start_reader(rows ?? [])
127
+
128
+ return (pid, start) => process_identity.is_present_process(pid, start, read)
129
+ }
130
+
131
+ const run_board_found = { found_of, live_in }
132
+
133
+ export { run_board_found }
134
+ export type { Found, FoundOf, IsLive }
@@ -3,6 +3,7 @@ import type { BudgetWait } from '#scripts/gate/core-wait'
3
3
  import { MS_PER_MINUTE } from '#scripts/lib/timeouts'
4
4
  import { run_board_estimate } from './run-board-estimate'
5
5
  import { run_board_fit } from './run-board-fit'
6
+ import type { FoundOf } from './run-board-found'
6
7
  import { run_board_fresh } from './run-board-fresh'
7
8
  import { run_board_labels } from './run-board-labels'
8
9
  import { run_board_layout, type BoardLayout, type BoardRow } from './run-board-layout'
@@ -92,6 +93,11 @@ interface BoardHeader {
92
93
  usual?: UsualTimes | undefined
93
94
  // How many lanes the run may hold at once, which the estimated finish stacks the waiting children on.
94
95
  lane_limit?: number | undefined
96
+ // What each done row says after its time (`run-board-found.ts`); none where nothing was read.
97
+ found?: FoundOf | undefined
98
+ // Whether `JOSH_LANE_INVESTIGATION` is on; off, a merged row hides its minutes and investigation
99
+ // (joshuafolkken/kit#5132, joshuafolkken/kit#5194).
100
+ is_investigation_on: boolean
95
101
  // The spinner's frame a running run and a running row turn, `undefined` where the output is not a
96
102
  // terminal and they draw their still icons.
97
103
  spinner: string | undefined
@@ -101,6 +107,8 @@ interface BoardHeader {
101
107
  // An issue reference as the board draws it — `3450` or `owner/repo#12` — made a link where the
102
108
  // terminal opens one.
103
109
  link: (reference: string) => string
110
+ // A pull request's number, made a link to it where the terminal opens one (joshuafolkken/kit#4625).
111
+ pull_link: (number: number) => string
104
112
  }
105
113
 
106
114
  interface BoardCounts {
@@ -62,6 +62,7 @@ const WORDS = {
62
62
  named: 'named order',
63
63
  held: 'held by triage',
64
64
  headroom: 'memory headroom',
65
+ usage_limit: 'usage limit',
65
66
  untriaged: 'untriaged',
66
67
  solo: 'runs alone',
67
68
  solo_ahead: 'behind solo',
@@ -95,6 +96,7 @@ const WORDS = {
95
96
  park: 'park',
96
97
  note: 'note',
97
98
  found_during: ' (found during {n})',
99
+ overrun: 'overrun investigation',
98
100
  // What the run is doing now, where no stage of its own says it.
99
101
  watching: 'watching',
100
102
  pool_empty: 'pool empty',
@@ -188,6 +190,10 @@ const NOTES_ICON = '📌'
188
190
  // A plan row the run filed leads its title with it, in place of a findings line naming it again
189
191
  // (joshuafolkken/kit#4099).
190
192
  const FILED_RUN_MARK = '✚'
193
+ // A merged row whose overrun investigation is running ends on it where no spinner turns
194
+ // (joshuafolkken/kit#4772), and leads its result once it ended (joshuafolkken/kit#4818): the
195
+ // investigate phase's own icon, for the same work.
196
+ const OVERRUN_MARK = PHASE_ICONS.investigate
191
197
  const NOTE_ICONS: Readonly<Record<BoardNote['kind'], string>> = {
192
198
  filed: '🆕',
193
199
  park: STATE_ICONS.parked,
@@ -252,8 +258,10 @@ const STAGE_ICONS: Readonly<Partial<Record<string, string>>> = {
252
258
  // running issue holds, 📋 the declared order, ✋ a pool held for a judgment, ❓ an issue nobody has
253
259
  // judged, 🧍 a `run:solo` issue waiting for the running lanes, 🙅 a row behind it (#4294; 🚧 is a
254
260
  // held check's) and 🔒 a row a running `run:solo` issue holds (#4391), chosen on the same rule as
255
- // every row icon. The rest are the board's own, shared rather than copied.
261
+ // every row icon, and 🪫 the account's Claude usage limit until it resets (#4796). The rest are the
262
+ // board's own, shared rather than copied.
256
263
  const WAIT_ICONS = {
264
+ usage_limit: '🪫',
257
265
  path: '📂',
258
266
  named: '📋',
259
267
  held: '✋',
@@ -280,6 +288,7 @@ const WAIT_WORDS: ReadonlyArray<readonly [icon: string, word: keyof Words]> = [
280
288
  [WAIT_ICONS.solo, 'solo'],
281
289
  [WAIT_ICONS.solo_ahead, 'solo_ahead'],
282
290
  [WAIT_ICONS.solo_running, 'solo_running'],
291
+ [WAIT_ICONS.usage_limit, 'usage_limit'],
283
292
  [WAIT_ICONS.memory, 'headroom'],
284
293
  [WAIT_ICONS.untriaged, 'untriaged'],
285
294
  [WAIT_ICONS.blocker, 'waits'],
@@ -366,6 +375,7 @@ const run_board_labels = {
366
375
  NOTES_ICON,
367
376
  NOTE_ICONS,
368
377
  NOW_ICONS,
378
+ OVERRUN_MARK,
369
379
  PHASE_ICONS,
370
380
  PHASE_WORDS,
371
381
  SPINNER_INTERVAL_MS,
@@ -16,6 +16,7 @@ const OFF_LANE_KINDS: ReadonlySet<string> = new Set([
16
16
  KIND.PARK,
17
17
  KIND.WITHDRAW,
18
18
  KIND.OUTAGE,
19
+ KIND.USAGE_LIMIT,
19
20
  KIND.SPLIT,
20
21
  KIND.STOP,
21
22
  ])
@@ -1,7 +1,8 @@
1
1
  // The issue numbers on `run:board` open their GitHub issue: each is wrapped in
2
2
  // an OSC 8 terminal hyperlink, so VSCode's terminal opens it on Cmd+click while the visible text stays
3
3
  // the number. A reference is drawn the way the plan names it — `3450` for this repository's issue,
4
- // `owner/repo#12` for one elsewhere — and links to the repository it names.
4
+ // `owner/repo#12` for one elsewhere — and links to the repository it names. A followup row's pull
5
+ // request number opens its pull request the same way (joshuafolkken/kit#4625).
5
6
  //
6
7
  // The columns are padded on the text before it is linked: the escape draws nothing, but `padEnd`
7
8
  // counts it. Whether a terminal gets the escape at all is the `link` port's answer.
@@ -18,6 +19,11 @@ function issue_url(reference: string, repo: string): string {
18
19
  return `${GITHUB_URL_PREFIX}${target}/issues/${number}`
19
20
  }
20
21
 
22
+ // A pull request of `repo` (joshuafolkken/kit#4625).
23
+ function pull_url(number: number, repo: string): string {
24
+ return `${GITHUB_URL_PREFIX}${repo}/pull/${String(number)}`
25
+ }
26
+
21
27
  // A board with no plan read yet knows no repository, so its references stay plain text.
22
28
  function linker(repo: string | undefined, link: Link): (reference: string) => string {
23
29
  if (repo === undefined) return (reference) => reference
@@ -25,7 +31,14 @@ function linker(repo: string | undefined, link: Link): (reference: string) => st
25
31
  return (reference) => link(reference, issue_url(reference, repo))
26
32
  }
27
33
 
28
- const run_board_link = { issue_url, linker }
34
+ // A pull request's number linked to it, plain text on the same rule as `linker`.
35
+ function pull_linker(repo: string | undefined, link: Link): (number: number) => string {
36
+ if (repo === undefined) return String
37
+
38
+ return (number) => link(String(number), pull_url(number, repo))
39
+ }
40
+
41
+ const run_board_link = { issue_url, linker, pull_linker, pull_url }
29
42
 
30
43
  export { run_board_link }
31
44
  export type { Link }