@joshuafolkken/kit 1.1240.0 → 1.1373.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (934) hide show
  1. package/.claude/agents/investigator.md +1 -0
  2. package/.claude/settings.json +4 -0
  3. package/.claude/skills/dependency-update/SKILL.md +5 -3
  4. package/.claude/skills/epic-commands/SKILL.md +82 -113
  5. package/.claude/skills/epic-commands/epic-bundle.md +38 -63
  6. package/.claude/skills/epic-commands/execution-waves.md +30 -51
  7. package/.claude/skills/verify-ui/SKILL.md +13 -20
  8. package/.claude/skills/workflow-commands/SKILL.md +10 -10
  9. package/.claude/skills/workflow-commands/background-commands.md +4 -4
  10. package/.claude/skills/workflow-commands/backlogrun-child.md +30 -105
  11. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +29 -0
  12. package/.claude/skills/workflow-commands/backlogrun-lanes.md +45 -131
  13. package/.claude/skills/workflow-commands/backlogrun-park.md +36 -53
  14. package/.claude/skills/workflow-commands/backlogrun-progress.md +81 -331
  15. package/.claude/skills/workflow-commands/backlogrun-recovery.md +29 -83
  16. package/.claude/skills/workflow-commands/backlogrun-steps.md +105 -424
  17. package/.claude/skills/workflow-commands/backlogrun.md +52 -61
  18. package/.claude/skills/workflow-commands/chain-rule.md +36 -40
  19. package/.claude/skills/workflow-commands/entry-sequence.md +6 -6
  20. package/.claude/skills/workflow-commands/followup.md +19 -20
  21. package/.claude/skills/workflow-commands/fullrun-steps.md +23 -27
  22. package/.claude/skills/workflow-commands/fullrun.md +10 -10
  23. package/.claude/skills/workflow-commands/halfrun.md +9 -8
  24. package/.claude/skills/workflow-commands/into-target.md +12 -18
  25. package/.claude/skills/workflow-commands/issue-comments.md +11 -26
  26. package/.claude/skills/workflow-commands/kickoff.md +26 -16
  27. package/.claude/skills/workflow-commands/latest-gate.md +17 -28
  28. package/.claude/skills/workflow-commands/needs-human-review.md +13 -24
  29. package/.claude/skills/workflow-commands/observation-filing.md +37 -28
  30. package/.claude/skills/workflow-commands/observation-ledger.md +48 -38
  31. package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -9
  32. package/.claude/skills/workflow-commands/prerequisite.md +23 -15
  33. package/.claude/skills/workflow-commands/progress-watcher.md +17 -11
  34. package/.claude/skills/workflow-commands/prrun.md +3 -3
  35. package/.claude/skills/workflow-commands/retrospective.md +13 -18
  36. package/.claude/skills/workflow-commands/split-assessment.md +6 -4
  37. package/.claude/skills/workflow-commands/target-repository.md +25 -28
  38. package/.claude/skills/workflow-commands/working-tree-hold.md +11 -17
  39. package/.gitattributes +2 -1
  40. package/.github/workflows/ci.yml +14 -0
  41. package/.vscode/tasks.json +14 -0
  42. package/CLAUDE.md +10 -61
  43. package/README.md +23 -66
  44. package/SECURITY.md +1 -1
  45. package/dist/CLAUDE.md +10 -61
  46. package/dist/commands/document-section-cli.js +43 -11
  47. package/dist/config-merge/index.js +11 -2
  48. package/dist/hooks/audit-provision.js +2 -2
  49. package/dist/hooks/batch-guard.js +7 -7
  50. package/dist/hooks/{chunk-KHGB5S3Y.js → chunk-7UBFU3CL.js} +18 -20
  51. package/dist/hooks/{chunk-ZQGD4GBY.js → chunk-7WKYHEGU.js} +8 -44
  52. package/dist/hooks/{chunk-4TZVB44A.js → chunk-AKGCP4LX.js} +285 -363
  53. package/dist/hooks/{chunk-QVSWU24O.js → chunk-BZMPVFDY.js} +7 -5
  54. package/dist/hooks/{chunk-5VNDSNG3.js → chunk-FZ6FUSBM.js} +1 -1
  55. package/dist/hooks/{chunk-GPTFMK5E.js → chunk-GG72ANKI.js} +1 -1
  56. package/dist/hooks/{chunk-XZYKEM6J.js → chunk-JCRDBQXB.js} +13 -11
  57. package/dist/hooks/{chunk-F3ELQ2AF.js → chunk-JGW24KKM.js} +4 -4
  58. package/dist/hooks/{chunk-ELCN5LCH.js → chunk-NEC4AT4Z.js} +34 -12
  59. package/dist/hooks/chunk-NZN2UFI6.js +2409 -0
  60. package/dist/hooks/{chunk-WK2XSHSI.js → chunk-SLSFIWTX.js} +550 -875
  61. package/dist/hooks/chunk-UTHMB4O2.js +1590 -0
  62. package/dist/hooks/{chunk-KRBERBBI.js → chunk-V4TKZHER.js} +4 -4
  63. package/dist/hooks/chunk-YLBBSSTF.js +3705 -0
  64. package/dist/hooks/chunk-Z5TMJIPW.js +45 -0
  65. package/dist/hooks/codex-hook-adapter.js +26 -21
  66. package/dist/hooks/duplicate-read-guard.js +8 -8
  67. package/dist/hooks/format-edited.js +4 -4
  68. package/dist/hooks/inputs.json +195 -181
  69. package/dist/hooks/investigation-guard.js +8 -8
  70. package/dist/hooks/pretool-guard.js +15 -15
  71. package/dist/hooks/session-lang.js +406 -8
  72. package/dist/hooks/stop-guard.js +122 -187
  73. package/dist/josh.js +282 -95
  74. package/dist/version/index.js +15 -13
  75. package/eslint/base.js +43 -5
  76. package/eslint/rules/english-only-prose.js +3 -3
  77. package/eslint/rules/import.js +12 -0
  78. package/eslint/rules/namespace-object-export.js +2 -2
  79. package/package.json +17 -11
  80. package/pnpm-workspace.yaml +2 -4
  81. package/prompts/coding-standards.md +14 -48
  82. package/prompts/collaboration-workflow/file-edits.md +1 -1
  83. package/prompts/collaboration-workflow/issue-citation.md +1 -1
  84. package/prompts/collaboration-workflow/issue-template.md +3 -10
  85. package/prompts/collaboration-workflow/operating-rules.md +7 -8
  86. package/prompts/collaboration-workflow/output-bounds.md +1 -1
  87. package/prompts/collaboration-workflow/overview.md +1 -1
  88. package/prompts/collaboration-workflow/plan-comment.md +2 -1
  89. package/prompts/collaboration-workflow/principles.md +21 -3
  90. package/prompts/collaboration-workflow/report-format.md +16 -29
  91. package/prompts/collaboration-workflow/residency.md +1 -1
  92. package/prompts/collaboration-workflow/rule-delivery.md +7 -95
  93. package/prompts/collaboration-workflow/shell-body.md +3 -23
  94. package/prompts/collaboration-workflow/turn-batching.md +4 -13
  95. package/prompts/collaboration-workflow/wip-cap.md +5 -11
  96. package/prompts/refactoring.md +1 -1
  97. package/prompts/review-rubric.md +3 -22
  98. package/prompts/review.md +15 -38
  99. package/prompts/testing-guide.md +2 -4
  100. package/scripts/adopt/adopt-logic.ts +5 -5
  101. package/scripts/adopt/adopt-toolkits.ts +4 -5
  102. package/scripts/adopt/adopt.ts +2 -3
  103. package/scripts/agent/agent-argv.ts +7 -7
  104. package/scripts/agent/agent-diagnostics.ts +2 -2
  105. package/scripts/agent/agent-exit-record.ts +1 -1
  106. package/scripts/agent/agent-headless.ts +1 -1
  107. package/scripts/agent/agent-launch-environment.ts +6 -1
  108. package/scripts/agent/agent-role-profile.ts +49 -22
  109. package/scripts/agent/agent-session-role.ts +32 -0
  110. package/scripts/agent/api-outage.ts +1 -1
  111. package/scripts/agent/claude-agent-argv.ts +4 -4
  112. package/scripts/agent/claude-result-event.ts +4 -4
  113. package/scripts/agent/codex-hooks.ts +2 -2
  114. package/scripts/agent/interactive-ask.ts +3 -6
  115. package/scripts/auto-ok/auto-ok-cli.ts +46 -60
  116. package/scripts/backlog/backlog-arrival-added.ts +34 -0
  117. package/scripts/backlog/backlog-arrival.ts +54 -17
  118. package/scripts/backlog/backlog-budget-cli.ts +34 -6
  119. package/scripts/backlog/backlog-budget.ts +17 -24
  120. package/scripts/backlog/backlog-defect-priority.ts +1 -1
  121. package/scripts/backlog/backlog-drive-args.ts +5 -4
  122. package/scripts/backlog/backlog-drive-cli.ts +14 -10
  123. package/scripts/backlog/backlog-drive-epic.ts +85 -0
  124. package/scripts/backlog/backlog-drive-launch.ts +1 -1
  125. package/scripts/backlog/backlog-drive-named-offer.ts +60 -9
  126. package/scripts/backlog/backlog-drive-named.ts +39 -9
  127. package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
  128. package/scripts/backlog/backlog-drive-restore.ts +1 -1
  129. package/scripts/backlog/backlog-drive-retrospective.ts +2 -2
  130. package/scripts/backlog/backlog-drive.ts +43 -28
  131. package/scripts/backlog/backlog-idle.ts +88 -0
  132. package/scripts/backlog/backlog-named.ts +11 -15
  133. package/scripts/backlog/backlog-next.ts +26 -30
  134. package/scripts/backlog/backlog-offer-cli.ts +28 -23
  135. package/scripts/backlog/backlog-offer.ts +7 -7
  136. package/scripts/backlog/backlog-overlap.ts +178 -0
  137. package/scripts/backlog/backlog-plan-cli.ts +14 -90
  138. package/scripts/backlog/backlog-plan-read.ts +111 -0
  139. package/scripts/backlog/backlog-plan.ts +11 -10
  140. package/scripts/backlog/backlog-pool.ts +13 -14
  141. package/scripts/backlog/backlog-rank.ts +11 -11
  142. package/scripts/backlog/backlog-ready.ts +15 -10
  143. package/scripts/backlog/backlog-scope.ts +14 -15
  144. package/scripts/backlog/backlog-stalled-cli.ts +2 -2
  145. package/scripts/backlog/backlog-stalled-detect.ts +4 -4
  146. package/scripts/backlog/backlog-stalled.ts +5 -6
  147. package/scripts/backlog/backlog-waves.ts +4 -4
  148. package/scripts/backlog/backlogrun-args.ts +74 -0
  149. package/scripts/backlog/backlogrun-cli.ts +113 -0
  150. package/scripts/backlog/backlogrun-launch.ts +178 -0
  151. package/scripts/behavior/behavior-assertion.ts +6 -8
  152. package/scripts/behavior/behavior-cli.ts +1 -1
  153. package/scripts/behavior/behavior-rules.ts +3 -3
  154. package/scripts/build/build-claude-md.ts +4 -4
  155. package/scripts/build/build-codex-hooks.ts +2 -2
  156. package/scripts/build/build-commands.ts +1 -1
  157. package/scripts/build/build-hooks.ts +5 -5
  158. package/scripts/build/build.ts +1 -1
  159. package/scripts/build/hook-bundle-stamp.ts +109 -7
  160. package/scripts/build/local-bin.ts +2 -2
  161. package/scripts/cases/cases-cli.ts +1 -1
  162. package/scripts/cases/cases-logic.ts +2 -2
  163. package/scripts/ci/composite-actions.ts +1 -2
  164. package/scripts/ci/pr-classification.ts +2 -2
  165. package/scripts/claude/workflow-destination.ts +1 -1
  166. package/scripts/clone/clone-aggregate.ts +1 -1
  167. package/scripts/clone/clone-fingerprint.ts +1 -1
  168. package/scripts/clone/clone-scan-cli.ts +1 -1
  169. package/scripts/clone/clone-scan.ts +1 -1
  170. package/scripts/config-merge/index.ts +1 -1
  171. package/scripts/config-merge/json-format.ts +1 -3
  172. package/scripts/config-merge/patch-json-array.ts +90 -0
  173. package/scripts/config-merge/patch-json-key.ts +6 -3
  174. package/scripts/config-merge/patch-json-list.ts +1 -1
  175. package/scripts/cost-runtime/codex-usage.ts +1 -1
  176. package/scripts/cost-runtime/context-cut-payback.ts +4 -5
  177. package/scripts/cost-runtime/context-cut-threshold.ts +4 -6
  178. package/scripts/cost-runtime/cost-attribute.ts +3 -3
  179. package/scripts/cost-runtime/cost-blocks.ts +3 -4
  180. package/scripts/cost-runtime/cost-cli.ts +14 -11
  181. package/scripts/cost-runtime/cost-corpus.ts +11 -11
  182. package/scripts/cost-runtime/cost-pricing.ts +4 -4
  183. package/scripts/cost-runtime/cost-tokens.ts +1 -2
  184. package/scripts/cost-runtime/cost-transcript.ts +29 -29
  185. package/scripts/cost-runtime/cost-usage.ts +6 -7
  186. package/scripts/cost-runtime/cost-verdict.ts +10 -11
  187. package/scripts/cost-runtime/own-session.ts +1 -1
  188. package/scripts/cost-runtime/transcript-cwd.ts +2 -2
  189. package/scripts/delegation/delegation-cli.ts +4 -4
  190. package/scripts/delegation/delegation-policy.ts +13 -15
  191. package/scripts/delegation/duplicate-read-guard.ts +9 -10
  192. package/scripts/delegation/fanout-cli.ts +1 -1
  193. package/scripts/delegation/fanout.ts +1 -1
  194. package/scripts/delegation/investigation-guard.ts +18 -22
  195. package/scripts/delegation/investigation-reads.ts +48 -238
  196. package/scripts/discovery/repo-discovery.ts +1 -1
  197. package/scripts/discovery/repo-map-logic.ts +1 -2
  198. package/scripts/discovery/repo-origin.ts +3 -3
  199. package/scripts/discovery/repo-party-cli.ts +2 -2
  200. package/scripts/discovery/repo-party.ts +2 -2
  201. package/scripts/doctor/doctor-consumer.ts +1 -1
  202. package/scripts/doctor/doctor-io.ts +6 -7
  203. package/scripts/doctor/doctor-logic.ts +1 -1
  204. package/scripts/doctor/doctor-ports.ts +1 -1
  205. package/scripts/doctor/doctor.ts +8 -9
  206. package/scripts/document/backlogrun-parent-read-set.ts +5 -6
  207. package/scripts/document/bash-output-cap.ts +5 -7
  208. package/scripts/document/capped-print-part.ts +1 -1
  209. package/scripts/document/capped-print.ts +1 -1
  210. package/scripts/document/document-byte-budget.ts +33 -64
  211. package/scripts/document/document-byte-check.ts +4 -4
  212. package/scripts/document/document-reachability.ts +7 -8
  213. package/scripts/document/document-read-cli.ts +2 -2
  214. package/scripts/document/document-scan.ts +30 -5
  215. package/scripts/document/document-section-cli.ts +6 -8
  216. package/scripts/document/document-section.ts +8 -12
  217. package/scripts/document/edit-files-cli.ts +3 -4
  218. package/scripts/document/entry-read-budget.ts +8 -70
  219. package/scripts/document/entry-read-set.ts +51 -34
  220. package/scripts/document/lane-child-read-set.ts +9 -9
  221. package/scripts/document/read-files-cli.ts +1 -2
  222. package/scripts/document/read-set-cli.ts +16 -19
  223. package/scripts/document/read-set-cost.ts +4 -4
  224. package/scripts/document/read-set-point-of-use.ts +28 -38
  225. package/scripts/document/read-set-pricing.ts +1 -1
  226. package/scripts/document/read-set-trim.ts +3 -3
  227. package/scripts/document/resident-budget.ts +8 -10
  228. package/scripts/epic/epic-add-body.ts +15 -18
  229. package/scripts/epic/epic-add-plan.ts +26 -28
  230. package/scripts/epic/epic-add.ts +32 -25
  231. package/scripts/epic/epic-audit-checks.ts +27 -37
  232. package/scripts/epic/epic-audit-cli.ts +21 -22
  233. package/scripts/epic/epic-audit-orphans.ts +16 -17
  234. package/scripts/epic/epic-audit-rationale.ts +10 -15
  235. package/scripts/epic/epic-audit-report.ts +2 -5
  236. package/scripts/epic/epic-audit.ts +18 -14
  237. package/scripts/epic/epic-body.ts +10 -10
  238. package/scripts/epic/epic-bundle-cli.ts +36 -34
  239. package/scripts/epic/epic-bundle-evidence.ts +5 -5
  240. package/scripts/epic/epic-bundle-gaps.ts +6 -9
  241. package/scripts/epic/epic-bundle-poll.ts +1 -1
  242. package/scripts/epic/epic-bundle-referenced.ts +11 -14
  243. package/scripts/epic/epic-bundle.ts +19 -20
  244. package/scripts/epic/epic-busy.ts +44 -21
  245. package/scripts/epic/epic-candidate-confirm.ts +15 -18
  246. package/scripts/epic/epic-chains.ts +18 -23
  247. package/scripts/epic/epic-classify.ts +11 -12
  248. package/scripts/epic/epic-cli-argv.ts +5 -6
  249. package/scripts/epic/epic-cli-remove.ts +9 -4
  250. package/scripts/epic/epic-cli.ts +38 -26
  251. package/scripts/epic/epic-close-comment.ts +14 -15
  252. package/scripts/epic/epic-close.ts +25 -29
  253. package/scripts/epic/epic-cross-repo.ts +18 -21
  254. package/scripts/epic/epic-decision.ts +14 -18
  255. package/scripts/epic/epic-fetch.ts +25 -31
  256. package/scripts/epic/epic-graph.ts +15 -17
  257. package/scripts/epic/epic-index.ts +14 -16
  258. package/scripts/epic/epic-issue.ts +9 -11
  259. package/scripts/epic/epic-label-age.ts +74 -0
  260. package/scripts/epic/epic-lane-offer.ts +35 -24
  261. package/scripts/epic/epic-nested.ts +1 -1
  262. package/scripts/epic/epic-next-read.ts +8 -8
  263. package/scripts/epic/epic-next-views.ts +12 -12
  264. package/scripts/epic/epic-next.ts +29 -33
  265. package/scripts/epic/epic-outside-blocker.ts +11 -10
  266. package/scripts/epic/epic-parse.ts +22 -24
  267. package/scripts/epic/epic-promote.ts +3 -2
  268. package/scripts/epic/epic-rank.ts +1 -1
  269. package/scripts/epic/epic-read.ts +10 -8
  270. package/scripts/epic/epic-reconcile.ts +8 -6
  271. package/scripts/epic/epic-reference.ts +5 -4
  272. package/scripts/epic/epic-relation-recheck.ts +10 -11
  273. package/scripts/epic/epic-relations.ts +9 -8
  274. package/scripts/epic/epic-remove-plan.ts +4 -5
  275. package/scripts/epic/epic-remove.ts +7 -5
  276. package/scripts/epic/epic-report.ts +18 -20
  277. package/scripts/epic/epic-run.ts +6 -5
  278. package/scripts/epic/epic-sections.ts +2 -2
  279. package/scripts/epic/epic-shape.ts +3 -3
  280. package/scripts/epic/epic-solo-stale.ts +3 -2
  281. package/scripts/epic/epic-solo.ts +8 -8
  282. package/scripts/epic/epic-triage.ts +5 -4
  283. package/scripts/epic/epic-validate.ts +8 -7
  284. package/scripts/epic/epic.ts +5 -5
  285. package/scripts/exports/unused-members-cli.ts +1 -1
  286. package/scripts/followup/followup-issue-number.ts +1 -2
  287. package/scripts/followup/git-followup-cleanup.ts +6 -7
  288. package/scripts/followup/git-followup-finish.ts +11 -13
  289. package/scripts/followup/git-followup-flush.ts +11 -7
  290. package/scripts/followup/git-followup-issue-close.ts +16 -13
  291. package/scripts/followup/git-followup-label.ts +9 -6
  292. package/scripts/followup/git-followup-merged.ts +1 -1
  293. package/scripts/followup/git-followup-pending.ts +7 -9
  294. package/scripts/followup/git-followup-stages.ts +28 -17
  295. package/scripts/followup/git-followup-workflow.ts +19 -21
  296. package/scripts/followup/git-pr-followup-checks.ts +13 -20
  297. package/scripts/followup/git-pr-followup-wrapup.ts +7 -7
  298. package/scripts/followup/git-pr-followup.ts +18 -17
  299. package/scripts/gate/core-admission.ts +2 -2
  300. package/scripts/gate/core-budget.ts +15 -26
  301. package/scripts/gate/gate-ledger.ts +114 -0
  302. package/scripts/gate/gate-log.ts +7 -9
  303. package/scripts/gate/gate-plan.ts +70 -35
  304. package/scripts/gate/gate-report.ts +14 -15
  305. package/scripts/gate/gate-skip.ts +11 -13
  306. package/scripts/gate/gate-steps.ts +5 -1
  307. package/scripts/gate/gate-tree.ts +3 -4
  308. package/scripts/gate/hook-gate-reuse.ts +9 -9
  309. package/scripts/gate/machine-capacity.ts +168 -30
  310. package/scripts/gate/pre-commit-type-check.ts +4 -4
  311. package/scripts/gate/project-checks.ts +12 -4
  312. package/scripts/gate/scoped-green.ts +11 -18
  313. package/scripts/gate/type-check-command.ts +2 -2
  314. package/scripts/gate/type-check-step.ts +4 -4
  315. package/scripts/gate/verification-gate.ts +53 -51
  316. package/scripts/gh/gh-spawn.ts +2 -2
  317. package/scripts/gh/git-ai-review-scan.ts +3 -2
  318. package/scripts/gh/git-gh-api-path.ts +10 -11
  319. package/scripts/gh/git-gh-exec.ts +43 -48
  320. package/scripts/gh/git-gh-failure.ts +6 -9
  321. package/scripts/gh/git-gh-helpers.ts +1 -1
  322. package/scripts/gh/git-gh-issue-list.ts +15 -19
  323. package/scripts/gh/git-gh-issue-read.ts +43 -60
  324. package/scripts/gh/git-gh-issue-rest.ts +14 -15
  325. package/scripts/gh/git-gh-issue-write.ts +52 -40
  326. package/scripts/gh/git-gh-issue.ts +23 -24
  327. package/scripts/gh/git-gh-pr-auto-merge.ts +3 -3
  328. package/scripts/gh/git-gh-pr-read.ts +46 -50
  329. package/scripts/gh/git-gh-pr-rest.ts +23 -26
  330. package/scripts/gh/git-gh-pr-review.ts +2 -2
  331. package/scripts/gh/git-gh-pr-rollup.ts +4 -4
  332. package/scripts/gh/git-gh-pr-snapshot.ts +8 -10
  333. package/scripts/gh/git-gh-pr.ts +16 -16
  334. package/scripts/gh/git-gh-reachability.ts +11 -12
  335. package/scripts/gh/git-gh-repo.ts +2 -3
  336. package/scripts/gh/git-gh-rest-state.ts +1 -1
  337. package/scripts/gh/git-pr-ai-review.ts +6 -5
  338. package/scripts/gh/git-pr-checks-eval.ts +28 -30
  339. package/scripts/gh/git-pr-checks-parse.ts +14 -16
  340. package/scripts/gh/git-pr-checks-watch.ts +17 -17
  341. package/scripts/gh/git-pr-checks.ts +20 -23
  342. package/scripts/gh/git-pr-coderabbit.ts +8 -6
  343. package/scripts/gh/git-pr-confirmation.ts +5 -5
  344. package/scripts/gh/git-pr-managed-config.ts +7 -9
  345. package/scripts/gh/git-pr-messages.ts +1 -1
  346. package/scripts/gh/git-pr.ts +15 -16
  347. package/scripts/gh/github-issue-url.ts +8 -9
  348. package/scripts/git/base-tree.ts +66 -0
  349. package/scripts/git/change-base.ts +42 -2
  350. package/scripts/git/changed-file-scope.ts +5 -5
  351. package/scripts/git/changed-paths.ts +1 -2
  352. package/scripts/git/constants.ts +2 -2
  353. package/scripts/git/git-branch.ts +1 -1
  354. package/scripts/git/git-closes-keyword.ts +3 -3
  355. package/scripts/git/git-command.ts +53 -41
  356. package/scripts/git/git-common-directory.ts +3 -3
  357. package/scripts/git/git-diff-reads.ts +14 -15
  358. package/scripts/git/git-error.ts +1 -1
  359. package/scripts/git/git-execa-error.ts +1 -2
  360. package/scripts/git/git-issue.ts +10 -8
  361. package/scripts/git/git-location-environment.ts +3 -4
  362. package/scripts/git/git-ls-remote.ts +6 -8
  363. package/scripts/git/git-pre-push-hook.ts +11 -10
  364. package/scripts/git/git-preflight.ts +5 -5
  365. package/scripts/git/git-push-transport.ts +2 -2
  366. package/scripts/git/git-remote-branch.ts +1 -2
  367. package/scripts/git/git-schemas.ts +16 -23
  368. package/scripts/git/git-spawn-sync.ts +1 -1
  369. package/scripts/git/git-spawn.ts +37 -14
  370. package/scripts/git/git-ssh-keepalive.ts +12 -5
  371. package/scripts/git/git-staging.ts +7 -8
  372. package/scripts/git/git-workflow.ts +1 -1
  373. package/scripts/git/git-worktree.ts +35 -27
  374. package/scripts/git/gone-branch.ts +2 -2
  375. package/scripts/git/listing-cutoff.ts +1 -2
  376. package/scripts/git/lockfile-sync.ts +65 -0
  377. package/scripts/git/main-merge-guard.ts +1 -2
  378. package/scripts/git/main-merge.ts +7 -7
  379. package/scripts/git/main-sync.ts +23 -8
  380. package/scripts/git/parse-json-array.ts +18 -23
  381. package/scripts/git/repository-lock.ts +34 -2
  382. package/scripts/git/stash/git-stash.ts +4 -5
  383. package/scripts/git/stash/stash-orphans.ts +5 -3
  384. package/scripts/git/stash/stash-pop-args.ts +1 -1
  385. package/scripts/git/stash/stash-pop-cli.ts +3 -3
  386. package/scripts/git/stash/stash-sweep-lock.ts +2 -2
  387. package/scripts/hooks/batch-guard.ts +11 -13
  388. package/scripts/hooks/check-commit-message.ts +12 -9
  389. package/scripts/hooks/codex-hook-adapter.ts +16 -10
  390. package/scripts/hooks/edited-cspell.ts +3 -4
  391. package/scripts/hooks/format-edited-cli.ts +1 -1
  392. package/scripts/hooks/format-edited-file.ts +11 -17
  393. package/scripts/hooks/format-rewrite-notice.ts +19 -17
  394. package/scripts/hooks/pre-push-unit.ts +10 -14
  395. package/scripts/hooks/pretool-guard-cli.ts +4 -4
  396. package/scripts/hooks/pretool-guard.ts +93 -18
  397. package/scripts/hooks/reserved-run.ts +2 -2
  398. package/scripts/hooks/step-zero-notice.ts +1 -1
  399. package/scripts/hooks/stop-guard.ts +21 -10
  400. package/scripts/init/basic-path-migration.ts +2 -2
  401. package/scripts/init/claude-kit-only-settings.ts +2 -2
  402. package/scripts/init/claude-plugin-config.ts +2 -2
  403. package/scripts/init/distributed-paths.ts +4 -4
  404. package/scripts/init/hook-command-rewrite.ts +3 -3
  405. package/scripts/init/hook-launch.ts +5 -5
  406. package/scripts/init/init-actions.ts +13 -0
  407. package/scripts/init/init-ai-copy.ts +11 -11
  408. package/scripts/init/init-bootstrap.ts +3 -3
  409. package/scripts/init/init-copy-content.ts +4 -4
  410. package/scripts/init/init-logic-json-merge.ts +7 -9
  411. package/scripts/init/init-logic-migrate.ts +1 -1
  412. package/scripts/init/init-logic-templates.ts +1 -1
  413. package/scripts/init/init-logic-workspace.ts +4 -4
  414. package/scripts/init/init-logic-yaml-merge.ts +2 -2
  415. package/scripts/init/init-logic.ts +19 -22
  416. package/scripts/init/init.ts +7 -7
  417. package/scripts/init/kit-base-preset.ts +1 -1
  418. package/scripts/init/kit-setup-state.ts +1 -1
  419. package/scripts/init/kit-written-paths.ts +1 -2
  420. package/scripts/init/package-manager-pin.ts +1 -1
  421. package/scripts/init/project-profile-cli.ts +1 -1
  422. package/scripts/init/project-profile.ts +3 -3
  423. package/scripts/init/session-language-environment.ts +1 -1
  424. package/scripts/init/start-exec.ts +3 -4
  425. package/scripts/init/start-plan.ts +2 -2
  426. package/scripts/init/start-setup-pr.ts +3 -2
  427. package/scripts/init/start-steps.ts +2 -2
  428. package/scripts/init/tsconfig-preset-migration.ts +1 -1
  429. package/scripts/init/vscode-tasks.ts +62 -0
  430. package/scripts/issue/baseline-measure.ts +2 -2
  431. package/scripts/issue/behavior-change-lint.ts +2 -2
  432. package/scripts/issue/defect-rate-cli.ts +6 -7
  433. package/scripts/issue/defect-rate.ts +37 -27
  434. package/scripts/issue/git-next-issues.ts +9 -8
  435. package/scripts/issue/issue-auto-ok.ts +24 -11
  436. package/scripts/issue/issue-backlinks-cli.ts +5 -5
  437. package/scripts/issue/issue-backlinks.ts +6 -6
  438. package/scripts/issue/issue-cite-cli.ts +20 -18
  439. package/scripts/issue/issue-cite.ts +18 -8
  440. package/scripts/issue/issue-closing-pr.ts +4 -4
  441. package/scripts/issue/issue-comment-cli.ts +6 -4
  442. package/scripts/issue/issue-file-cli.ts +52 -15
  443. package/scripts/issue/issue-file-fold.ts +155 -0
  444. package/scripts/issue/issue-file.ts +9 -6
  445. package/scripts/issue/issue-fold-cli.ts +14 -9
  446. package/scripts/issue/issue-fold.ts +23 -8
  447. package/scripts/issue/issue-labels.ts +34 -38
  448. package/scripts/issue/issue-lint-cli.ts +2 -2
  449. package/scripts/issue/issue-lint.ts +1 -1
  450. package/scripts/issue/issue-merged.ts +10 -4
  451. package/scripts/issue/issue-number-shape.ts +27 -0
  452. package/scripts/issue/issue-rank.ts +1 -1
  453. package/scripts/issue/issue-read-cli.ts +4 -5
  454. package/scripts/issue/issue-read.ts +4 -5
  455. package/scripts/issue/issue-reference.ts +5 -5
  456. package/scripts/issue/issue-release-cli.ts +17 -7
  457. package/scripts/issue/issue-release.ts +3 -3
  458. package/scripts/issue/issue-report-failures.ts +7 -4
  459. package/scripts/issue/issue-scout-cli.ts +11 -11
  460. package/scripts/issue/issue-scout-closed.ts +4 -4
  461. package/scripts/issue/issue-scout.ts +4 -5
  462. package/scripts/issue/issue-state-cli.ts +17 -10
  463. package/scripts/issue/issue-state.ts +12 -13
  464. package/scripts/issue/issue-wip.ts +7 -7
  465. package/scripts/issue/markdown-section.ts +3 -3
  466. package/scripts/issue/measure-rerun-cli.ts +10 -9
  467. package/scripts/issue/reproduction-measure.ts +3 -3
  468. package/scripts/issue/session-cite.ts +56 -0
  469. package/scripts/josh/agent-session-environment.ts +10 -8
  470. package/scripts/josh/cli-body.ts +2 -2
  471. package/scripts/josh/command-suggest.ts +1 -1
  472. package/scripts/josh/file-map-stamp.ts +20 -23
  473. package/scripts/josh/hook-decision.ts +24 -28
  474. package/scripts/josh/josh-command-map.ts +4 -1
  475. package/scripts/josh/josh-command-types.ts +30 -35
  476. package/scripts/josh/josh-commands-ai.ts +6 -6
  477. package/scripts/josh/josh-commands-backlog.ts +15 -3
  478. package/scripts/josh/josh-commands-clone.ts +1 -1
  479. package/scripts/josh/josh-commands-development.ts +25 -4
  480. package/scripts/josh/josh-commands-document.ts +3 -3
  481. package/scripts/josh/josh-commands-guard.ts +3 -3
  482. package/scripts/josh/josh-commands-issue.ts +4 -5
  483. package/scripts/josh/josh-commands-lane.ts +14 -4
  484. package/scripts/josh/josh-commands-lint.ts +1 -1
  485. package/scripts/josh/josh-commands-run.ts +21 -7
  486. package/scripts/josh/josh-commands-split.ts +1 -2
  487. package/scripts/josh/josh-commands-versioning.ts +5 -5
  488. package/scripts/josh/josh-commands-workflow.ts +30 -22
  489. package/scripts/josh/josh-environment-file.ts +1 -1
  490. package/scripts/josh/josh-in-process.ts +3 -3
  491. package/scripts/josh/josh-logic.ts +6 -7
  492. package/scripts/josh/josh-run.ts +3 -3
  493. package/scripts/josh/josh-verdict.ts +9 -12
  494. package/scripts/josh/josh.ts +3 -3
  495. package/scripts/josh/kit-only.ts +2 -2
  496. package/scripts/josh/path-decision.ts +3 -3
  497. package/scripts/josh/platform-temporary.ts +7 -5
  498. package/scripts/josh/process-identity.ts +24 -6
  499. package/scripts/josh/process-owner.ts +4 -4
  500. package/scripts/josh/session-language-cli.ts +53 -11
  501. package/scripts/josh/session-language.ts +1 -1
  502. package/scripts/josh/stamp-file.ts +48 -29
  503. package/scripts/josh/stamp-record.ts +57 -0
  504. package/scripts/lane/lane-await.ts +35 -11
  505. package/scripts/lane/lane-cache.ts +6 -6
  506. package/scripts/lane/lane-capacity.ts +32 -17
  507. package/scripts/lane/lane-child-invocation.ts +17 -15
  508. package/scripts/lane/lane-child-marker.ts +12 -12
  509. package/scripts/lane/lane-cli.ts +12 -13
  510. package/scripts/lane/lane-close.ts +6 -6
  511. package/scripts/lane/lane-dispatch.ts +61 -72
  512. package/scripts/lane/lane-environment.ts +5 -5
  513. package/scripts/lane/lane-guard-policy.ts +7 -21
  514. package/scripts/lane/lane-handoff.ts +2 -2
  515. package/scripts/lane/lane-install.ts +9 -10
  516. package/scripts/lane/lane-launch-cli.ts +13 -8
  517. package/scripts/lane/lane-ledger.ts +73 -11
  518. package/scripts/lane/lane-leftover.ts +2 -2
  519. package/scripts/lane/lane-limit-cli.ts +160 -0
  520. package/scripts/lane/lane-limit-override.ts +74 -0
  521. package/scripts/lane/lane-load.ts +19 -68
  522. package/scripts/lane/lane-measure-cli.ts +15 -25
  523. package/scripts/lane/lane-occupancy.ts +6 -4
  524. package/scripts/lane/lane-open.ts +20 -19
  525. package/scripts/lane/lane-output.ts +4 -3
  526. package/scripts/lane/lane-paths.ts +12 -11
  527. package/scripts/lane/lane-phase.ts +33 -0
  528. package/scripts/lane/lane-reap.ts +2 -2
  529. package/scripts/lane/lane-registry.ts +16 -15
  530. package/scripts/lane/lane-relaunch.ts +9 -9
  531. package/scripts/lane/lane-report.ts +5 -4
  532. package/scripts/lane/lane-resume.ts +2 -2
  533. package/scripts/lane/lane-sampler.ts +55 -0
  534. package/scripts/lane/lane-seed.ts +7 -7
  535. package/scripts/lane/lane-stage-stats.ts +135 -0
  536. package/scripts/lane/lane-start-point.ts +8 -11
  537. package/scripts/lane/lane-stats.ts +60 -15
  538. package/scripts/lane/lane-stray.ts +1 -1
  539. package/scripts/lane/lane-vacant.ts +1 -1
  540. package/scripts/lane/openai-lane-supervisor-decision.ts +3 -7
  541. package/scripts/lane/openai-lane-supervisor-owner.ts +3 -9
  542. package/scripts/lane/openai-review-broker.ts +2 -4
  543. package/scripts/lib/ancestor-directories.ts +1 -1
  544. package/scripts/lib/bounded-pool.ts +2 -2
  545. package/scripts/lib/buffered-process.ts +4 -6
  546. package/scripts/lib/caddy-logs.sh +0 -0
  547. package/scripts/lib/cli-flags.ts +39 -6
  548. package/scripts/lib/error-message.ts +1 -1
  549. package/scripts/lib/json-value.ts +17 -3
  550. package/scripts/lib/poll.ts +1 -1
  551. package/scripts/lib/status-icons.ts +3 -3
  552. package/scripts/lib/timed-fetch.ts +1 -1
  553. package/scripts/lib/timeouts.ts +1 -1
  554. package/scripts/lines/bytes-command.ts +3 -4
  555. package/scripts/lines/effective-limit.ts +25 -12
  556. package/scripts/lines/line-budget.ts +47 -55
  557. package/scripts/lines/line-targets.ts +6 -2
  558. package/scripts/lines/lines-command.ts +3 -3
  559. package/scripts/lint/cross-file-recheck.ts +155 -0
  560. package/scripts/lint/cspell-cached.ts +1 -1
  561. package/scripts/lint/format.ts +1 -2
  562. package/scripts/lint/lint-parallel.ts +35 -19
  563. package/scripts/lint/lint-related-scope.ts +25 -15
  564. package/scripts/lint/lint-related.ts +6 -7
  565. package/scripts/managed-marker/index.ts +1 -1
  566. package/scripts/managed-marker/managed-marker-logic.ts +1 -2
  567. package/scripts/notify/git-notify.ts +9 -7
  568. package/scripts/notify/telegram-notify.ts +53 -37
  569. package/scripts/notify/telegram-test-logic.ts +3 -3
  570. package/scripts/notify/telegram-test.ts +45 -30
  571. package/scripts/observations/observation-ledger-home.ts +14 -8
  572. package/scripts/observations/observation-ledger-line.ts +3 -2
  573. package/scripts/observations/observation-ledger-migrate.ts +3 -4
  574. package/scripts/observations/observation-ledger-prepare.ts +4 -4
  575. package/scripts/observations/observation-ledger.ts +14 -15
  576. package/scripts/observations/observation-record-cli.ts +83 -0
  577. package/scripts/observations/observation-record.ts +91 -0
  578. package/scripts/observations/observations-flush-cli.ts +1 -1
  579. package/scripts/observations/observations-flush-landing.ts +7 -6
  580. package/scripts/observations/observations-flush.ts +26 -27
  581. package/scripts/overrides/overrides-check.ts +18 -8
  582. package/scripts/package/package-scout-cli.ts +1 -1
  583. package/scripts/package/package-scout-format.ts +2 -2
  584. package/scripts/package/package-scout.ts +1 -1
  585. package/scripts/propagate/propagate-git-failure.ts +1 -1
  586. package/scripts/propagate/propagate-git.ts +7 -7
  587. package/scripts/propagate/propagate-plan.ts +2 -2
  588. package/scripts/propagate/propagate-publish.ts +2 -3
  589. package/scripts/propagate/propagate-run.ts +5 -7
  590. package/scripts/propagate/propagate-select.ts +1 -1
  591. package/scripts/propagate/propagate-steps.ts +19 -20
  592. package/scripts/propagate/propagate-targets.ts +6 -10
  593. package/scripts/propagate/propagate.ts +5 -5
  594. package/scripts/refactor/import-graph.ts +1 -1
  595. package/scripts/refactor/refactor-lint.ts +4 -10
  596. package/scripts/refactor/refactor-scan-cli.ts +1 -1
  597. package/scripts/refactor/refactor-scan.ts +2 -2
  598. package/scripts/refactor/refactor-targets.ts +1 -1
  599. package/scripts/release/github-release-cli.ts +25 -3
  600. package/scripts/release/github-release-runs.ts +1 -1
  601. package/scripts/release/release-cli.ts +21 -4
  602. package/scripts/release/release-history.ts +6 -10
  603. package/scripts/release/release-plan.ts +3 -3
  604. package/scripts/release/release-progress.ts +3 -4
  605. package/scripts/release/release-publish.ts +8 -9
  606. package/scripts/release/release-scope-cli.ts +8 -10
  607. package/scripts/release/release-tag.ts +6 -8
  608. package/scripts/release/release-worktree.ts +5 -5
  609. package/scripts/repo/auto-merge-setting-logic.ts +7 -9
  610. package/scripts/repo/auto-merge-setting.ts +1 -1
  611. package/scripts/repo/repo-setting.ts +4 -4
  612. package/scripts/repo/repository-labels.ts +1 -1
  613. package/scripts/repo/required-checks-logic.ts +3 -3
  614. package/scripts/repo/required-checks-report.ts +1 -1
  615. package/scripts/repo/ruleset-check-cli.ts +1 -1
  616. package/scripts/repo/ruleset-check.ts +1 -1
  617. package/scripts/report/report-format-reference.ts +26 -0
  618. package/scripts/report/report-lint-cli.ts +2 -2
  619. package/scripts/report/report-lint.ts +16 -2
  620. package/scripts/review/disposition-cli.ts +2 -2
  621. package/scripts/review/disposition-logic.ts +1 -1
  622. package/scripts/review/live-evidence.ts +9 -6
  623. package/scripts/review/review-attest-cli.ts +1 -2
  624. package/scripts/review/review-attest.ts +3 -3
  625. package/scripts/review/review-brief-cli.ts +19 -20
  626. package/scripts/review/review-brief.ts +29 -32
  627. package/scripts/review/review-checkout.ts +2 -2
  628. package/scripts/review/review-diff-parts.ts +3 -5
  629. package/scripts/review/review-diff-write.ts +1 -1
  630. package/scripts/review/review-finding-ledger.ts +7 -4
  631. package/scripts/review/review-findings-cli.ts +2 -2
  632. package/scripts/review/review-level.ts +4 -7
  633. package/scripts/review/review-record-cli.ts +73 -16
  634. package/scripts/review/review-record.ts +5 -4
  635. package/scripts/review/review-round2-cli.ts +2 -3
  636. package/scripts/review/review-round2.ts +13 -21
  637. package/scripts/review/review-stamps.ts +9 -71
  638. package/scripts/review/review-tree.ts +4 -5
  639. package/scripts/rules/bash-triggers.ts +4 -4
  640. package/scripts/rules/decision-oracle-batch.ts +6 -7
  641. package/scripts/rules/decision-oracle-stage.ts +1 -1
  642. package/scripts/rules/decision-oracle-tokens.ts +1 -2
  643. package/scripts/rules/decision-oracle.ts +2 -2
  644. package/scripts/rules/delivered-rules.ts +61 -406
  645. package/scripts/rules/destructive-command.ts +2 -2
  646. package/scripts/rules/direct-filing.ts +4 -4
  647. package/scripts/rules/direct-pr-create.ts +2 -2
  648. package/scripts/rules/early-heartbeat.ts +15 -19
  649. package/scripts/rules/file-body.ts +5 -6
  650. package/scripts/rules/filing-cap.ts +6 -7
  651. package/scripts/rules/filing-offer.ts +1 -1
  652. package/scripts/rules/firing-point.ts +6 -6
  653. package/scripts/rules/gh-api.ts +2 -2
  654. package/scripts/rules/git-argv.ts +3 -3
  655. package/scripts/rules/git-force.ts +2 -2
  656. package/scripts/rules/hook-context-line.ts +31 -0
  657. package/scripts/rules/implementation-cut-verdict.ts +5 -8
  658. package/scripts/rules/implementation-cut.ts +35 -32
  659. package/scripts/rules/index-guard.ts +2 -2
  660. package/scripts/rules/issue-citation.ts +7 -7
  661. package/scripts/rules/issue-comments.ts +21 -13
  662. package/scripts/rules/josh-git-bare.ts +2 -2
  663. package/scripts/rules/lane-background.ts +14 -16
  664. package/scripts/rules/lane-carry-conflict.ts +41 -5
  665. package/scripts/rules/lane-interactive-ask.ts +6 -9
  666. package/scripts/rules/lane-park.ts +12 -16
  667. package/scripts/rules/lane-split-park.ts +1 -2
  668. package/scripts/rules/lane-switch-main.ts +10 -13
  669. package/scripts/rules/last-prompt.ts +1 -1
  670. package/scripts/rules/oracle-consulted.ts +5 -5
  671. package/scripts/rules/oracle-firing.ts +6 -9
  672. package/scripts/rules/oracle-list-cli.ts +2 -2
  673. package/scripts/rules/permission-guards.ts +2 -2
  674. package/scripts/rules/piped-verification.ts +79 -9
  675. package/scripts/rules/poll-loop.ts +9 -11
  676. package/scripts/rules/pre-gate-cut.ts +33 -30
  677. package/scripts/rules/prior-comment-read.ts +3 -3
  678. package/scripts/rules/protected-files.ts +25 -13
  679. package/scripts/rules/raw-field-body.ts +3 -4
  680. package/scripts/rules/reply-language.ts +1 -1
  681. package/scripts/rules/rule-body-guard.ts +10 -12
  682. package/scripts/rules/rule-guard.ts +1 -1
  683. package/scripts/rules/rule-list.ts +51 -0
  684. package/scripts/rules/rule-registry-rows.ts +282 -0
  685. package/scripts/rules/rule-registry.ts +109 -0
  686. package/scripts/rules/rule-value-cache.ts +2 -2
  687. package/scripts/rules/rule-value-cli.ts +6 -4
  688. package/scripts/rules/rule-value.ts +61 -22
  689. package/scripts/rules/run-tail-rule.ts +11 -15
  690. package/scripts/rules/shell-body-trigger.ts +7 -7
  691. package/scripts/rules/shell-segments.ts +2 -4
  692. package/scripts/rules/stop-rules.ts +54 -41
  693. package/scripts/rules/tail-commands.ts +1 -1
  694. package/scripts/rules/test-declared-commit.ts +2 -2
  695. package/scripts/rules/third-party-write.ts +3 -3
  696. package/scripts/rules/worktree-guard.ts +12 -5
  697. package/scripts/run/add/run-add-cli.ts +165 -0
  698. package/scripts/run/add/run-add.ts +124 -0
  699. package/scripts/run/board/run-board-cli.ts +207 -0
  700. package/scripts/run/board/run-board-closed.ts +95 -0
  701. package/scripts/run/board/run-board-every.ts +60 -0
  702. package/scripts/run/board/run-board-fetch.ts +38 -0
  703. package/scripts/run/board/run-board-fit.ts +219 -0
  704. package/scripts/run/board/run-board-github.ts +162 -0
  705. package/scripts/run/board/run-board-header.ts +275 -0
  706. package/scripts/run/board/run-board-kind.ts +35 -0
  707. package/scripts/run/board/run-board-labels.ts +299 -0
  708. package/scripts/run/board/run-board-layout.ts +222 -0
  709. package/scripts/run/board/run-board-link.ts +31 -0
  710. package/scripts/run/board/run-board-machine.ts +198 -0
  711. package/scripts/run/board/run-board-notes.ts +103 -0
  712. package/scripts/run/board/run-board-phase.ts +136 -0
  713. package/scripts/run/board/run-board-plan.ts +129 -0
  714. package/scripts/run/board/run-board-read.ts +62 -0
  715. package/scripts/run/board/run-board-render-legend.ts +82 -0
  716. package/scripts/run/board/run-board-render-notes.ts +77 -0
  717. package/scripts/run/board/run-board-render-slot.ts +50 -0
  718. package/scripts/run/board/run-board-render.ts +407 -0
  719. package/scripts/run/board/run-board-scope.ts +17 -0
  720. package/scripts/run/board/run-board-screen.ts +43 -0
  721. package/scripts/run/board/run-board-span.ts +66 -0
  722. package/scripts/run/board/run-board-spin.ts +115 -0
  723. package/scripts/run/board/run-board-state.ts +113 -0
  724. package/scripts/run/board/run-board-status.ts +279 -0
  725. package/scripts/run/board/run-board-tick.ts +210 -0
  726. package/scripts/run/board/run-board-track.ts +22 -0
  727. package/scripts/run/board/run-board-usage-read.ts +255 -0
  728. package/scripts/run/board/run-board-usage-rusage.ts +124 -0
  729. package/scripts/run/board/run-board-usage-text.ts +80 -0
  730. package/scripts/run/board/run-board-usage.ts +165 -0
  731. package/scripts/run/carry/run-carry-added.ts +62 -0
  732. package/scripts/run/carry/run-carry-args.ts +25 -22
  733. package/scripts/run/carry/run-carry-change.ts +1 -1
  734. package/scripts/run/carry/run-carry-cli.ts +71 -48
  735. package/scripts/run/carry/run-carry-conversation.ts +6 -7
  736. package/scripts/run/carry/run-carry-ended.ts +85 -0
  737. package/scripts/run/carry/run-carry-reclaim.ts +1 -1
  738. package/scripts/run/carry/run-carry-stash.ts +3 -2
  739. package/scripts/run/carry/run-carry-streak.ts +8 -10
  740. package/scripts/run/carry/run-carry.ts +85 -89
  741. package/scripts/run/cut/run-cut-args.ts +7 -7
  742. package/scripts/run/cut/run-cut-cli.ts +54 -36
  743. package/scripts/run/cut/run-cut-handoff.ts +15 -15
  744. package/scripts/run/cut/run-cut-report.ts +37 -16
  745. package/scripts/run/cut/run-cut.ts +63 -77
  746. package/scripts/run/detached-launch.ts +35 -50
  747. package/scripts/run/entry/run-entry-cli.ts +48 -27
  748. package/scripts/run/entry/run-entry-stop.ts +7 -9
  749. package/scripts/run/entry/run-entry.ts +5 -6
  750. package/scripts/run/event/run-event-cli.ts +5 -6
  751. package/scripts/run/event/run-event-filed.ts +69 -0
  752. package/scripts/run/event/run-event-follow.ts +3 -3
  753. package/scripts/run/event/run-event-plan.ts +38 -0
  754. package/scripts/run/event/run-event-render.ts +9 -4
  755. package/scripts/run/event/run-event-scope.ts +47 -18
  756. package/scripts/run/event/run-event-stream-emit.ts +64 -11
  757. package/scripts/run/event/run-event-stream.ts +171 -46
  758. package/scripts/run/event/run-event-watch.ts +4 -6
  759. package/scripts/run/hold/run-hold-cli.ts +65 -62
  760. package/scripts/run/hold/run-hold.ts +88 -46
  761. package/scripts/run/merge/run-merge-cli.ts +116 -77
  762. package/scripts/run/merge/run-merge-collect.ts +107 -0
  763. package/scripts/run/merge/run-merge-steps.ts +112 -65
  764. package/scripts/run/merge/run-merge-token.ts +30 -0
  765. package/scripts/run/merge/run-merge.ts +31 -22
  766. package/scripts/run/progress/run-progress-args.ts +4 -4
  767. package/scripts/run/progress/run-progress-cli.ts +39 -50
  768. package/scripts/run/progress/run-progress-clock.ts +25 -32
  769. package/scripts/run/progress/run-progress-config.ts +6 -9
  770. package/scripts/run/progress/run-progress-read.ts +9 -10
  771. package/scripts/run/progress/run-progress.ts +48 -53
  772. package/scripts/run/review/run-review-cli.ts +6 -6
  773. package/scripts/run/review/run-review-steps.ts +6 -6
  774. package/scripts/run/review/run-review.ts +9 -11
  775. package/scripts/run/run-cli-fault.ts +29 -0
  776. package/scripts/run/run-ending-cli.ts +3 -3
  777. package/scripts/run/run-ending.ts +10 -14
  778. package/scripts/run/run-halfrun-resume.ts +6 -8
  779. package/scripts/run/run-headless.ts +26 -12
  780. package/scripts/run/run-invocation.ts +17 -22
  781. package/scripts/run/run-label.ts +7 -5
  782. package/scripts/run/run-liveness-cli.ts +19 -6
  783. package/scripts/run/run-liveness.ts +27 -38
  784. package/scripts/run/run-next-cli.ts +5 -9
  785. package/scripts/run/run-next.ts +4 -5
  786. package/scripts/run/run-parent-cut-hook.ts +10 -12
  787. package/scripts/run/run-preflight.ts +25 -29
  788. package/scripts/run/run-prep-cli.ts +17 -13
  789. package/scripts/run/run-prep-locate.ts +4 -5
  790. package/scripts/run/run-prep.ts +7 -10
  791. package/scripts/run/run-prrun-resume.ts +2 -2
  792. package/scripts/run/run-report-cli.ts +4 -4
  793. package/scripts/run/run-report.ts +9 -14
  794. package/scripts/run/run-retrospective.ts +3 -3
  795. package/scripts/run/run-section.ts +42 -0
  796. package/scripts/run/run-stage-read.ts +2 -2
  797. package/scripts/run/run-stage.ts +6 -4
  798. package/scripts/run/run-status-cli.ts +7 -5
  799. package/scripts/run/run-status.ts +6 -7
  800. package/scripts/run/run-step-cli.ts +64 -18
  801. package/scripts/run/run-step.ts +107 -51
  802. package/scripts/run/run-stop-notify.ts +7 -8
  803. package/scripts/run/run-stranded-cli.ts +1 -1
  804. package/scripts/run/run-stranded-detect.ts +4 -4
  805. package/scripts/run/run-stranded.ts +11 -13
  806. package/scripts/run/run-tail-cli.ts +15 -16
  807. package/scripts/run/run-tail.ts +14 -33
  808. package/scripts/run/run-watcher-guard-cli.ts +3 -4
  809. package/scripts/run/run-watcher-guard.ts +11 -12
  810. package/scripts/run/run-watcher-hook.ts +6 -12
  811. package/scripts/run/ship/run-ship-cli.ts +67 -33
  812. package/scripts/run/ship/run-ship-detach.ts +15 -13
  813. package/scripts/run/ship/run-ship-lock.ts +1 -1
  814. package/scripts/run/ship/run-ship-next.ts +7 -8
  815. package/scripts/run/ship/run-ship-pre-detach.ts +27 -11
  816. package/scripts/run/ship/run-ship-preflight.ts +10 -11
  817. package/scripts/run/ship/run-ship-probe.ts +4 -4
  818. package/scripts/run/ship/run-ship-return.ts +1 -1
  819. package/scripts/run/ship/run-ship-review-steps.ts +43 -24
  820. package/scripts/run/ship/run-ship-review.ts +12 -14
  821. package/scripts/run/ship/run-ship-scoped.ts +15 -6
  822. package/scripts/run/ship/run-ship-stage.ts +80 -26
  823. package/scripts/run/ship/run-ship-steps.ts +26 -16
  824. package/scripts/run/ship/run-ship-stop-text.ts +4 -2
  825. package/scripts/run/ship/run-ship-sync.ts +9 -8
  826. package/scripts/run/ship/run-ship.ts +17 -32
  827. package/scripts/run/tidy/run-tidy-cli.ts +9 -5
  828. package/scripts/run/tidy/run-tidy-lanes.ts +18 -7
  829. package/scripts/run/tidy/run-tidy-stashes.ts +8 -8
  830. package/scripts/run/tidy/run-tidy.ts +4 -3
  831. package/scripts/run/wake/run-wake-cli.ts +27 -32
  832. package/scripts/run/wake/run-wake-describe.ts +24 -28
  833. package/scripts/run/wake/run-wake-driver.ts +14 -14
  834. package/scripts/run/wake/run-wake-handoff.ts +6 -6
  835. package/scripts/run/wake/run-wake-loop.ts +9 -9
  836. package/scripts/run/wake/run-wake-restart.ts +4 -5
  837. package/scripts/run/wake/run-wake-session.ts +23 -27
  838. package/scripts/run/wake/run-wake.ts +57 -279
  839. package/scripts/safe-chain/ci-installer-pin.ts +3 -3
  840. package/scripts/safe-chain/pack-hook.ts +2 -2
  841. package/scripts/safe-chain/preinstall-command.ts +2 -2
  842. package/scripts/security/security-audit-logic.ts +1 -1
  843. package/scripts/security/security-audit-provision-logic.ts +1 -1
  844. package/scripts/security/security-audit-provision.ts +2 -2
  845. package/scripts/security/security-audit.ts +5 -5
  846. package/scripts/security/security-updates-logic.ts +2 -3
  847. package/scripts/security/security-updates.ts +2 -4
  848. package/scripts/self-sync-guard/index.ts +1 -1
  849. package/scripts/self-sync-guard/self-sync-guard-logic.ts +2 -2
  850. package/scripts/self-sync-guard/self-sync-refusal.ts +1 -1
  851. package/scripts/sonar/sonar-hotspots-cli.ts +1 -1
  852. package/scripts/sonar/sonar-hotspots.ts +1 -1
  853. package/scripts/sonar/sonar-new-code-cli.ts +1 -1
  854. package/scripts/sonar/sonar-new-code.ts +1 -1
  855. package/scripts/sonar/sonar-project.ts +1 -1
  856. package/scripts/split/split-assess-cli.ts +1 -1
  857. package/scripts/split/split-assess.ts +3 -3
  858. package/scripts/sync/directory-copy-guard.ts +2 -3
  859. package/scripts/sync/managed-config-scope-cli.ts +1 -2
  860. package/scripts/sync/managed-config-scope.ts +4 -4
  861. package/scripts/sync/plugin-skill-directories.ts +2 -2
  862. package/scripts/sync/reconcile-templates.ts +17 -8
  863. package/scripts/sync/removed-skill-manifest.ts +2 -3
  864. package/scripts/sync/sync-ai-files.ts +7 -7
  865. package/scripts/sync/sync-configs.ts +30 -3
  866. package/scripts/sync/sync-hook-safety.ts +2 -2
  867. package/scripts/sync/sync.ts +23 -10
  868. package/scripts/sync/synced-paths.ts +2 -1
  869. package/scripts/sync/workflow-pin-logic.ts +1 -1
  870. package/scripts/test/test-declared-changed.ts +4 -4
  871. package/scripts/test/test-declared-logic.ts +2 -3
  872. package/scripts/test/test-declared-match.ts +25 -4
  873. package/scripts/test/test-declared.ts +26 -9
  874. package/scripts/test/test-red-commit.ts +3 -2
  875. package/scripts/test/test-red-logic.ts +7 -14
  876. package/scripts/test/test-red.ts +12 -47
  877. package/scripts/test/test-related-scope.ts +2 -3
  878. package/scripts/test/test-related.ts +3 -3
  879. package/scripts/test/test-type-logic.ts +1 -2
  880. package/scripts/test/test-unit-guard.ts +13 -17
  881. package/scripts/test/unit-worker-share.ts +7 -8
  882. package/scripts/time-runtime/time-agent-bundles.ts +2 -4
  883. package/scripts/time-runtime/time-background.ts +17 -21
  884. package/scripts/time-runtime/time-batch-guard.ts +67 -342
  885. package/scripts/time-runtime/time-bundle-call.ts +26 -28
  886. package/scripts/time-runtime/time-bundles.ts +11 -12
  887. package/scripts/time-runtime/time-call-identity.ts +1 -1
  888. package/scripts/time-runtime/time-command-key.ts +2 -2
  889. package/scripts/time-runtime/time-density-hook.ts +8 -11
  890. package/scripts/time-runtime/time-density.ts +5 -5
  891. package/scripts/time-runtime/time-followup-stage.ts +7 -7
  892. package/scripts/time-runtime/time-format.ts +5 -5
  893. package/scripts/time-runtime/time-hook-transcript.ts +3 -3
  894. package/scripts/time-runtime/time-instant.ts +1 -1
  895. package/scripts/time-runtime/time-markers.ts +15 -19
  896. package/scripts/time-runtime/time-phase-names.ts +3 -3
  897. package/scripts/time-runtime/time-reported-failure.ts +15 -19
  898. package/scripts/time-runtime/time-round-trips.ts +20 -23
  899. package/scripts/time-runtime/time-shell.ts +8 -8
  900. package/scripts/time-runtime/time-single-check.ts +1 -2
  901. package/scripts/time-runtime/time-spans.ts +35 -40
  902. package/scripts/time-runtime/time-tool-call.ts +15 -16
  903. package/scripts/time-runtime/time-transcript-line.ts +53 -34
  904. package/scripts/time-runtime/time-writes.ts +5 -5
  905. package/scripts/ui/ui-routes-cli.ts +1 -2
  906. package/scripts/ui/ui-routes.ts +1 -2
  907. package/scripts/version/bump-version.ts +1 -1
  908. package/scripts/version/fresh-metadata-cache.ts +2 -2
  909. package/scripts/version/latest-corepack.ts +26 -26
  910. package/scripts/version/latest-lane-guard.ts +1 -1
  911. package/scripts/version/latest-scope-cli.ts +2 -2
  912. package/scripts/version/latest-stamp.ts +1 -2
  913. package/scripts/version/latest-update.ts +2 -2
  914. package/scripts/version/npm-registry.ts +2 -2
  915. package/scripts/version/package-manager-version.ts +18 -0
  916. package/scripts/version/publishable-range-check.ts +2 -1
  917. package/scripts/version/publishable-range.ts +1 -1
  918. package/scripts/version/release-age.ts +11 -11
  919. package/scripts/version/release-hold.ts +2 -2
  920. package/scripts/version/safe-chain-version-update.ts +3 -3
  921. package/scripts/version/version-check-logic.ts +2 -3
  922. package/scripts/version/version-check.ts +1 -2
  923. package/scripts/version/version-command-config.ts +2 -2
  924. package/scripts/version/version-commands.ts +3 -3
  925. package/scripts/version/version-remote.ts +4 -4
  926. package/scripts/version/version-targets.ts +2 -2
  927. package/templates/gitignore +7 -0
  928. package/dist/hooks/chunk-KHX4U3BG.js +0 -6400
  929. package/dist/hooks/chunk-RKUAD3I6.js +0 -90
  930. package/dist/hooks/chunk-WPALEIRX.js +0 -18
  931. package/scripts/backlog/backlog-restructure.ts +0 -152
  932. package/scripts/rules/issue-fold-rule.ts +0 -72
  933. package/scripts/rules/wip-cap.ts +0 -63
  934. package/scripts/run/run-issue-number.ts +0 -19
@@ -3,6 +3,8 @@ import { fileURLToPath } from 'node:url'
3
3
  import { git_gh_command } from '#scripts/gh/git-gh-command'
4
4
  import { cutoff_of, type ScanCutoff } from '#scripts/git/listing-cutoff'
5
5
  import { parse_json_array_or_undefined } from '#scripts/git/parse-json-array'
6
+ import { issue_cite } from '#scripts/issue/issue-cite'
7
+ import { session_cite } from '#scripts/issue/session-cite'
6
8
  import { bounded_pool } from '#scripts/lib/bounded-pool'
7
9
  import type { PollOptions } from '#scripts/lib/poll'
8
10
  import { issue_citation } from '#scripts/rules/issue-citation'
@@ -19,10 +21,10 @@ import { epic_bundle_poll } from './epic-bundle-poll'
19
21
  import { epic_bundle_referenced, type ReferencedContext } from './epic-bundle-referenced'
20
22
  import { epic_index, epic_schema, type FetchedEpics } from './epic-index'
21
23
  import { epic_issue } from './epic-issue'
22
- import type { IssueReference } from './epic-reference'
24
+ import { format_dependency_links, type IssueReference } from './epic-reference'
23
25
 
24
26
  // `josh epic:bundle <N>` — after an issue is filed, look at the open backlog and say whether it
25
- // belongs with something already there (joshuafolkken/kit#873).
27
+ // belongs with something already there.
26
28
  //
27
29
  // The machine finds the candidates; the decision to bundle is the caller's. This command prints what
28
30
  // it found and what it recommends, and writes nothing.
@@ -37,12 +39,12 @@ const USAGE = 'Usage: josh epic:bundle <issue-number>'
37
39
  const UNKNOWN_REPO_MESSAGE =
38
40
  'Could not read this repository from `git remote`, so the backlog cannot be keyed by repository — check `gh auth status` and that this is a checkout with an `origin` remote.'
39
41
 
40
- // The backlog listing asks for the title too (joshuafolkken/kit#1252). Kept apart from the epic
42
+ // The backlog listing asks for the title too. Kept apart from the epic
41
43
  // listing's schema rather than made optional on one: the epic listing does not ask for the field, and
42
44
  // a schema that tolerates its absence everywhere would let a missing title pass unnoticed here.
43
45
  //
44
- // `blocked_by_count` is the blocker count GitHub already puts in the listing response
45
- // (joshuafolkken/kit#1736). It is **nullish rather than defaulted**, and that is the whole safety of
46
+ // `blocked_by_count` is the blocker count GitHub already puts in the listing response.
47
+ // It is **nullish rather than defaulted**, and that is the whole safety of
46
48
  // the read below: a row the listing carries no summary for must not be read as a row with no
47
49
  // blockers, because that reading is what would silently drop a relation instead of costing a
48
50
  // request. Nothing in today's pipeline is expected to arrive without one — the response carries the
@@ -56,8 +58,7 @@ const backlog_schema = epic_schema.extend({
56
58
 
57
59
  type BacklogRow = z.infer<typeof backlog_schema>
58
60
 
59
- // The epic index is `epic-index.ts`'s, shared with the `auto-ok` pickup since
60
- // joshuafolkken/kit#1633: both commands ask which epic tracks an issue, and a second copy of the
61
+ // The epic index is `epic-index.ts`'s, shared with the `auto-ok` pickup: both commands ask which epic tracks an issue, and a second copy of the
61
62
  // task-list read would answer differently the first time that shape moved.
62
63
  const { build_epic_index } = epic_index
63
64
 
@@ -80,21 +81,19 @@ async function epic_issue_relations(
80
81
 
81
82
  // One read per backlog issue *that has blockers*, a few at a time.
82
83
  //
83
- // Since joshuafolkken/kit#1024 a read is `gh api`: one REST request for the issue, and a second to
84
- // its `dependencies/blocked_by` endpoint unless the issue's own dependency summary reports exactly
85
- // zero blockers. That second request was already skipped on a zero; the first one was not, so the
86
- // command still paid one request for every open issue in the repository — a cost that grows with the
87
- // backlog and made the command heavier exactly as more issues made it more useful
88
- // (joshuafolkken/kit#1736). The listing that produced these rows already carries that same summary,
89
- // so the zero is known *before* the read rather than inside it, and the read is skipped outright.
84
+ // A read is `gh api`: one REST request for the issue, and a second to its `dependencies/blocked_by`
85
+ // endpoint unless the issue's own dependency summary reports exactly zero blockers. The listing that
86
+ // produced these rows already carries that same summary, so the zero is known *before* the read
87
+ // rather than inside it, and the read is skipped outright — otherwise the command would pay one
88
+ // request for every open issue in the repository, a cost that grows with the backlog.
90
89
  //
91
90
  // One read would do if `gh` exposed the reverse of `blockedBy`, but it does not (`blocks` is not a
92
91
  // JSON field), so a dependency declared on the *other* issue is only visible by asking that issue.
93
92
  // Spawning all of them at once is what turns a rate limit into a wrong answer: a refused read becomes
94
93
  // an empty relation list, and a bundle that should have been proposed is reported as "no strong
95
94
  // signal" instead. Batching bounds the burst; the `unreadable` list below is what keeps a refused
96
- // read from passing as an answer (joshuafolkken/kit#873). The pool itself is `bounded-pool.ts`,
97
- // shared with the reference reads below it and with the eval suite (joshuafolkken/kit#1144).
95
+ // read from passing as an answer. The pool itself is `bounded-pool.ts`,
96
+ // shared with the reference reads below it and with the eval suite.
98
97
  const RELATION_CONCURRENCY = 8
99
98
  const NO_BLOCKERS = 0
100
99
 
@@ -124,8 +123,8 @@ interface FetchedBacklog {
124
123
  issues: Array<BacklogIssue>
125
124
  unreadable: Array<number>
126
125
  is_readable: boolean
127
- // Why the backlog listing stopped short, or that it did not. A `ScanCutoff` rather than a flag
128
- // since joshuafolkken/kit#1067: the page ceiling now bounds this listing too, and the two cutoffs
126
+ // Why the backlog listing stopped short, or that it did not. A `ScanCutoff` rather than a flag:
127
+ // the page ceiling bounds this listing too, and the two cutoffs
129
128
  // cite different numbers.
130
129
  cutoff?: ScanCutoff
131
130
  has_epic_list?: boolean
@@ -158,7 +157,7 @@ function to_backlog_issue(
158
157
  // What a caller does not need read for it. `issue:scout` asks about an issue that does not exist yet:
159
158
  // it has no number, so no recorded dependency can name it and it declares none of its own — the
160
159
  // relation reads cannot change its answer, and skipping them takes one request per open issue off the
161
- // command a run makes before every filing (joshuafolkken/kit#1252). `epic:bundle` leaves it unset and
160
+ // command a run makes before every filing. `epic:bundle` leaves it unset and
162
161
  // reads them exactly as before.
163
162
  interface BacklogOptions {
164
163
  include_relations?: boolean
@@ -212,7 +211,7 @@ const ACTION_LINES: Readonly<Record<string, string>> = {
212
211
 
213
212
  // `Nothing to bundle.` is right when nothing was found, and wrong when an epic already tracks the
214
213
  // issue — there the answer is actionable: a caller looking for somewhere to put a prerequisite adds
215
- // it to *that* epic rather than creating a second one (joshuafolkken/kit#943).
214
+ // it to *that* epic rather than creating a second one.
216
215
  const ALREADY_TRACKED_LINE = 'Already in an epic — add to that one, do not create a second.'
217
216
 
218
217
  function headline(decision: BundleDecision): string {
@@ -223,22 +222,21 @@ function headline(decision: BundleDecision): string {
223
222
 
224
223
  // The epics currently open, at this command's own listing limit. A failed read stays `undefined` and
225
224
  // is reported: without the list, an issue an epic already tracks is told to create a second one —
226
- // confidently, and with exit 0 (joshuafolkken/kit#950).
225
+ // confidently, and with exit 0.
227
226
  async function fetch_epics(): Promise<FetchedEpics | undefined> {
228
227
  return await epic_index.fetch_epics(BACKLOG_LIMIT)
229
228
  }
230
229
 
231
230
  function format_numbers(numbers: ReadonlyArray<number>): string {
232
- return numbers.map((issue_number) => `#${String(issue_number)}`).join(', ')
231
+ return numbers.map((issue_number) => issue_cite.plain(issue_number)).join(', ')
233
232
  }
234
233
 
235
234
  // The order to record alongside the bundle. Bundling without it records the batch and loses the
236
235
  // reason it is a batch, so the recommendation carries it rather than leaving it to be remembered.
237
236
  function format_links(links: ReadonlyArray<{ blocker: number; blocked: number }>): string {
238
237
  if (links.length === 0) return ' Order: none declared — do not invent one'
239
- const arrows = links.map((link) => `#${String(link.blocker)} -> #${String(link.blocked)}`)
240
238
 
241
- return ` Order: ${arrows.join(', ')}`
239
+ return ` Order: ${format_dependency_links(links)}`
242
240
  }
243
241
 
244
242
  function format_order(
@@ -251,7 +249,7 @@ function format_order(
251
249
  const children = epic_bundle.bundle_children(subject, members)
252
250
 
253
251
  // The evidence goes under the order rather than beside the verdict: what it explains is the
254
- // order, and a reader checking one reads straight on into the other (joshuafolkken/kit#1737).
252
+ // order, and a reader checking one reads straight on into the other.
255
253
  return [
256
254
  ` Children: ${format_numbers(children)}`,
257
255
  format_links(epic_bundle.bundle_dependency_links(subject, members)),
@@ -261,7 +259,7 @@ function format_order(
261
259
 
262
260
  // The verdicts that put the subject into an epic. Each one asserts that no epic already tracks it —
263
261
  // `create_epic` asserts as much about the candidates too — and that negative is exactly what a cut
264
- // epic listing cannot establish (joshuafolkken/kit#1697). `none` is absent on purpose: it either
262
+ // epic listing cannot establish. `none` is absent on purpose: it either
265
263
  // names the epic it *found* tracking the subject, which a cut cannot unseat, or reports no candidate
266
264
  // at all, which says nothing about epics.
267
265
  const PLACING_ACTIONS: ReadonlySet<BundleAction> = new Set<BundleAction>([
@@ -306,7 +304,7 @@ async function read_backlog(repo: string, options?: BacklogOptions): Promise<Fet
306
304
  const epics = build_epic_index(open_epics.epics)
307
305
  // From the epic list itself, not from the index's values: an epic tracking no child yet has no
308
306
  // entry in the index, and would enter the backlog as an ordinary issue that its own children then
309
- // propose bundling with (joshuafolkken/kit#873).
307
+ // propose bundling with.
310
308
  const epic_numbers = new Set(open_epics.epics.map((epic) => epic.number))
311
309
 
312
310
  return {
@@ -319,7 +317,7 @@ async function read_backlog(repo: string, options?: BacklogOptions): Promise<Fet
319
317
 
320
318
  // The backlog the decision is made from: the open listing, plus the referenced issues it could not
321
319
  // show. Without the second half the command answers about a window that closes minutes after the
322
- // follow-up issue is filed (joshuafolkken/kit#947).
320
+ // follow-up issue is filed.
323
321
  async function widen_with_referenced(
324
322
  subject: BacklogIssue,
325
323
  backlog: FetchedBacklog,
@@ -360,7 +358,9 @@ function warn_cutoff(message: string | undefined): void {
360
358
  // wording of each gap is `epic-bundle-gaps.ts`'s; what stays here is which gaps this command has.
361
359
  function warn_about_gaps(backlog: FetchedBacklog): void {
362
360
  if (backlog.unreadable.length > 0) {
363
- console.error(`⚠ Could not read ${format_numbers(backlog.unreadable)}.`)
361
+ const unreadable = backlog.unreadable.map((issue_number) => session_cite.issue(issue_number))
362
+
363
+ console.error(`⚠ Could not read ${unreadable.join(', ')}.`)
364
364
  }
365
365
 
366
366
  warn_cutoff(epic_bundle_gaps.backlog_gap(backlog.cutoff ?? NO_CUTOFF, BACKLOG_LIMIT))
@@ -373,7 +373,7 @@ function report_decision(subject: BacklogIssue, backlog: FetchedBacklog, repo: s
373
373
  const decision = epic_bundle.decide_bundle(subject, others)
374
374
 
375
375
  // The `Related:` / `Children:` listings name issues as `#N`; linkified here so the recommendation a
376
- // run copies into its reply carries clickable references rather than bare ones (joshuafolkken/kit#2329).
376
+ // run copies into its reply carries clickable references rather than bare ones.
377
377
  const report = format_decision(decision, subject, others, is_established)
378
378
 
379
379
  console.info(issue_citation.linkify(report, repo))
@@ -417,7 +417,9 @@ async function report_for(
417
417
  const subject = backlog.issues.find((issue) => issue.number === issue_number)
418
418
 
419
419
  if (subject === undefined) {
420
- console.error(`#${String(issue_number)} is not an open issue in ${repo}.`)
420
+ console.error(
421
+ `${session_cite.issue(issue_number, undefined, repo)} is not an open issue in ${repo}.`,
422
+ )
421
423
 
422
424
  return FAILURE_EXIT_CODE
423
425
  }
@@ -436,8 +438,8 @@ async function run(argv: ReadonlyArray<string>): Promise<number> {
436
438
 
437
439
  const repo = await git_gh_command.repo_get_name_with_owner()
438
440
 
439
- // A repository that could not be read is refused rather than stood in for. Since
440
- // joshuafolkken/kit#1130 the members are keyed by repository and the blockers carry their own, so a
441
+ // A repository that could not be read is refused rather than stood in for. The members are keyed
442
+ // by repository and the blockers carry their own, so a
441
443
  // placeholder matches nothing: every recorded dependency would vanish and the command would answer
442
444
  // `Nothing to bundle.` with exit 0 — a confident verdict built on a read that failed, on the
443
445
  // command a run consults before deciding an issue belongs nowhere.
@@ -453,7 +455,7 @@ async function run(argv: ReadonlyArray<string>): Promise<number> {
453
455
  // `process.exitCode` rather than `process.exit()`: the answer goes to standard output and a write to
454
456
  // a pipe is asynchronous on macOS, so exiting can tear the process down before it drains. This
455
457
  // command's answer is what a workflow reads and acts on, which is exactly that pipe. The same shape
456
- // is in `scripts/cost-runtime/cost-cli.ts`, which met the truncation first (joshuafolkken/kit#1005).
458
+ // is in `scripts/cost-runtime/cost-cli.ts`, which met the truncation first.
457
459
  async function main(argv: ReadonlyArray<string>): Promise<void> {
458
460
  process.exitCode = await run(argv)
459
461
  }
@@ -1,7 +1,7 @@
1
+ import { issue_cite } from '#scripts/issue/issue-cite'
1
2
  import { epic_bundle, type BacklogIssue } from './epic-bundle'
2
3
 
3
- // The facts the bundle decision was already made from, printed beside the order it prints
4
- // (joshuafolkken/kit#1737).
4
+ // The facts the bundle decision was already made from, printed beside the order it prints.
5
5
  //
6
6
  // `is_strong_signal` reads exactly two things — whether a body names the other issue's number, and
7
7
  // whether a `blocked-by` is already recorded in either direction — and neither ever reached the
@@ -75,7 +75,7 @@ function member_pairs(
75
75
  //
76
76
  // The repository filter is the one `bundle_dependency_links` applies: a bare number declared in a
77
77
  // member elsewhere would be resolved against this repository by the epic body, naming a different
78
- // issue entirely (joshuafolkken/kit#1130).
78
+ // issue entirely.
79
79
  function ordering_evidence(
80
80
  subject: BacklogIssue,
81
81
  candidates: ReadonlyArray<BacklogIssue>,
@@ -118,8 +118,8 @@ const EVIDENCE_INDENT = ' '.repeat(EVIDENCE_INDENT_WIDTH)
118
118
 
119
119
  function format_one(item: OrderingEvidence): string {
120
120
  const { verb, where, order_prefix, order_suffix } = EVIDENCE_WORDING[item.kind]
121
- const first = `#${String(item.first)}`
122
- const second = `#${String(item.second)}`
121
+ const first = issue_cite.plain(item.first)
122
+ const second = issue_cite.plain(item.second)
123
123
  const order = `${order_prefix}${first}${order_suffix}`
124
124
 
125
125
  return `${EVIDENCE_INDENT}${second} ${verb} ${first}${where} — ${order}`
@@ -1,8 +1,7 @@
1
1
  import { cutoff_cause, type ScanCutoff } from '#scripts/git/listing-cutoff'
2
2
 
3
- // What `epic:bundle` could not see, said in the `⚠ … cap` shape joshuafolkken/kit#1033 settled on
4
- // for `epic:audit`. Split out of `epic-bundle-cli.ts` because the wording carries more explanation
5
- // than the command it warns from (joshuafolkken/kit#1067).
3
+ // What `epic:bundle` could not see, said in the `⚠ … cap` shape `epic:audit` uses. Split out of
4
+ // `epic-bundle-cli.ts` because the wording carries more explanation than the command it warns from.
6
5
  //
7
6
  // **Two listings, and two cuts each.** The listing decides *what* is hidden — a backlog issue, or
8
7
  // the epic that tracks one — and the cut decides *which number to cite*, because a reader who wants
@@ -21,7 +20,7 @@ function backlog_gap(cutoff: ScanCutoff, limit: number): string | undefined {
21
20
 
22
21
  // Named separately from the backlog's. What this one hides is *which epic tracks a candidate*, so
23
22
  // `Nothing to bundle.` under it may mean "the epic was past the cut" rather than "no epic tracks
24
- // it" — and acting on the second reading creates the duplicate epic (joshuafolkken/kit#950).
23
+ // it" — and acting on the second reading creates the duplicate epic.
25
24
  function epic_gap(cutoff: ScanCutoff, limit: number): string | undefined {
26
25
  const cause = cutoff_cause(cutoff, `hit its ${String(limit)}-epic cap`)
27
26
  if (cause === undefined) return undefined
@@ -36,8 +35,7 @@ function epic_gap(cutoff: ScanCutoff, limit: number): string | undefined {
36
35
  // the assertion is only as good as the epic listing it was read from: an epic past the cut tracks its
37
36
  // children invisibly, so each of them reads as tracked by nothing. Acted on as Tier A, that absence
38
37
  // puts a **second** epic over an issue one already tracks — the state `fullrun.md` forbids, because
39
- // the auto-close then has two task lists to disagree about and `epic:next` answers from two graphs
40
- // (joshuafolkken/kit#943).
38
+ // the auto-close then has two task lists to disagree about and `epic:next` answers from two graphs.
41
39
  //
42
40
  // A membership that *was* found is untouched, and that is the whole of what survives a cut: `none`
43
41
  // reporting `#E already tracks this issue` read the epic it names, and more epics past the cut cannot
@@ -46,12 +44,11 @@ function epic_gap(cutoff: ScanCutoff, limit: number): string | undefined {
46
44
  // The cut is the whole condition, and deliberately so. An epic the listing answered without a body
47
45
  // would hide its children the same way, but it cannot arrive: the listing mapping coerces a REST
48
46
  // `null` body to `''` before this module's caller ever parses one (`git-gh-issue-rest.ts`,
49
- // `to_gh_field_value`), so a gate arm for it would be code no input can reach
50
- // (joshuafolkken/kit#1697).
47
+ // `to_gh_field_value`), so a gate arm for it would be code no input can reach.
51
48
  //
52
49
  // The cutoff is optional because the fetched backlog carries it that way: a listing nothing capped
53
50
  // records no cut at all, which is the same answer as `none`. Defaulted here rather than at each call
54
- // site, so a caller holding the optional field cannot forget the coercion (joshuafolkken/kit#1703).
51
+ // site, so a caller holding the optional field cannot forget the coercion.
55
52
  function is_membership_established(cutoff: ScanCutoff = 'none'): boolean {
56
53
  return cutoff === 'none'
57
54
  }
@@ -1,6 +1,6 @@
1
1
  import { poll, type PollOptions } from '#scripts/lib/poll'
2
2
 
3
- // **The open listing trails the create call** (joshuafolkken/kit#3332): `issue:file` asks
3
+ // **The open listing trails the create call**: `issue:file` asks
4
4
  // `epic:bundle` about the issue it has just filed, and the list endpoint had not shown it yet on every
5
5
  // filing of one run, so the placement was skipped each time. A caller that knows the issue is fresh
6
6
  // passes a poll and the listing is read again until it shows the issue. An unreadable listing is
@@ -6,22 +6,20 @@ import { epic_issue, type EpicIssue } from './epic-issue'
6
6
 
7
7
  // Candidates the open backlog cannot show, read from the subject's own prose.
8
8
  //
9
- // `epic:bundle` searched open issues only, which left a window of minutes in which it could answer
10
- // correctly: a follow-up issue names its parent, and the parent's pull request merges right after —
11
- // on joshuafolkken/kit#943 the gap between filing and the parent closing was about three minutes.
12
- // Past it the command reported `Nothing to bundle.` with exit 0, asserting there was no relation
13
- // rather than that it had not looked (joshuafolkken/kit#947).
9
+ // The open backlog alone cannot answer: a follow-up issue names its parent, and the parent's pull
10
+ // request often merges minutes later. Searching open issues only would then report
11
+ // `Nothing to bundle.` with exit 0, asserting there was no relation rather than that it had not looked.
14
12
  //
15
- // The numbers a body names are information the command already holds; the open listing was never
16
- // what supplied them. Only the *reading* of those issues needs a request, and this module decides
13
+ // The numbers a body names are information the command already holds; the open listing is not
14
+ // what supplies them. Only the *reading* of those issues needs a request, and this module decides
17
15
  // which ones are worth one and which of the answers count.
18
16
 
19
17
  // One read each, so the count is what bounds the cost. Chosen an order of magnitude above the
20
- // references a real issue body carries — kit#946's body names five — so the cap is a runaway guard
18
+ // handful of references a real issue body carries, so the cap is a runaway guard
21
19
  // rather than something an ordinary issue reaches. A body naming more than this is prose about the
22
20
  // backlog, not an issue with twenty prerequisites.
23
21
  //
24
- // Since joshuafolkken/kit#1024 a read is `gh api`, and one reference costs one REST request in the
22
+ // A read is `gh api`, and one reference costs one REST request in the
25
23
  // common case. Three cases cost two. The `dependencies/blocked_by` endpoint is asked unless the
26
24
  // issue's own dependency summary reports exactly zero blockers, so an issue that declares one pays
27
25
  // for it. So does a pull request, which the issue endpoint serves as readily as an issue and which
@@ -88,7 +86,7 @@ function to_backlog_issue(issue: EpicIssue, context: ReferencedContext): Backlog
88
86
  function is_usable_candidate(issue: BacklogIssue, read: EpicIssue): boolean {
89
87
  // The issue endpoint answers for a pull request too, and a body citing "the fix landed in #952"
90
88
  // is ordinary prose. Without this, a merged PR reads as an open issue in no epic and the command
91
- // proposes creating an epic with a pull request among its children (joshuafolkken/kit#947).
89
+ // proposes creating an epic with a pull request among its children.
92
90
  if (issue.is_epic === true || epic_issue.is_pull_request(read)) return false
93
91
 
94
92
  return epic_issue.is_open(read.state) || issue.epic !== undefined
@@ -96,8 +94,7 @@ function is_usable_candidate(issue: BacklogIssue, read: EpicIssue): boolean {
96
94
 
97
95
  // How one referenced number came back. `missing` is GitHub resolving it to nothing — a typo, or a
98
96
  // number belonging to another repository quoted in prose — which is an answer, not a gap: there is
99
- // no candidate and nothing was lost. `unreadable` is the gap, and it is the only one reported
100
- // (joshuafolkken/kit#957).
97
+ // no candidate and nothing was lost. `unreadable` is the gap, and it is the only one reported.
101
98
  interface ReferencedRead {
102
99
  number: number
103
100
  result: EpicIssue | 'missing' | 'unreadable'
@@ -113,7 +110,7 @@ interface ReferencedResult {
113
110
  // The ones whose read failed, and the ones the cap never reached. Both are gaps rather than
114
111
  // answers: folded into "no relation found" they become the confident wrong verdict this whole
115
112
  // module exists to remove. A number that resolves to nothing is **not** here — reporting it as a
116
- // gap stops an unattended run over a reference that never existed (joshuafolkken/kit#957).
113
+ // gap stops an unattended run over a reference that never existed.
117
114
  unreadable: Array<number>
118
115
  }
119
116
 
@@ -156,7 +153,7 @@ async function read_one(number: number): Promise<ReferencedRead> {
156
153
 
157
154
  // The pool is shared with the eval suite rather than spelled out again here: this was written as
158
155
  // waves — slice, `Promise.all`, next slice — which holds every finished read's slot until the whole
159
- // slice returns (joshuafolkken/kit#1144).
156
+ // slice returns.
160
157
  async function fetch_referenced(numbers: ReadonlyArray<number>): Promise<Array<ReferencedRead>> {
161
158
  return await bounded_pool.bounded_map(
162
159
  numbers,
@@ -1,3 +1,4 @@
1
+ import { issue_cite } from '#scripts/issue/issue-cite'
1
2
  import { epic_audit_logic } from './epic-audit'
2
3
  import { epic_graph } from './epic-graph'
3
4
  import type { DependencyLink } from './epic-parse'
@@ -7,11 +8,10 @@ import type { IssueReference } from './epic-reference'
7
8
  //
8
9
  // "Two or more always means an epic" already holds when one request is split on the spot. It does
9
10
  // not reach the other way in: two issues filed days apart that turn out to be the front and back of
10
- // one job are executed separately, in whatever order, with the reasoning recorded nowhere
11
- // (joshuafolkken/kit#873).
11
+ // one job are executed separately, in whatever order, with the reasoning recorded nowhere.
12
12
  //
13
- // The candidate search reads issue references out of prose — the same reading joshuafolkken/kit#870
14
- // does inside one epic. That analysis is imported rather than written a second time; the only
13
+ // The candidate search reads issue references out of prose — the same reading `epic:audit` does
14
+ // inside one epic. That analysis is imported rather than written a second time; the only
15
15
  // difference is what it is pointed at.
16
16
 
17
17
  // An open issue as the search sees it.
@@ -21,17 +21,17 @@ interface BacklogIssue {
21
21
  body: string
22
22
  // Optional because nothing in this module reads it: the strong signals below are references and
23
23
  // recorded dependencies, and a title resemblance is deliberately not one of them. It rides on the
24
- // same listing for `issue:scout`, whose duplicate search is the one thing that does compare titles
25
- // (joshuafolkken/kit#1252), and is absent on an issue read one at a time by reference.
24
+ // same listing for `issue:scout`, whose duplicate search is the one thing that does compare titles,
25
+ // and is absent on an issue read one at a time by reference.
26
26
  title?: string
27
27
  // The epic tracking it, when one does. An issue belongs to at most one epic, because that is what
28
28
  // a task list can express.
29
29
  epic?: number
30
30
  // Whether this issue *is* an epic. An epic is a container, not a sibling: every child names it as
31
31
  // its parent, so without this every child would find its own epic as a candidate and be told to
32
- // bundle with it (joshuafolkken/kit#873, found by running the command on a real backlog).
32
+ // bundle with it.
33
33
  is_epic?: boolean
34
- // Repository-qualified, not bare numbers (joshuafolkken/kit#1130). Issue numbers are unique per
34
+ // Repository-qualified, not bare numbers. Issue numbers are unique per
35
35
  // repository, so a blocker read as `40` alone matched any candidate numbered 40 — including one in
36
36
  // a different repository entirely. That produced a bundle nobody's data supported, and, through
37
37
  // `bundle_dependency_links`, a `blocked-by` relation recorded onto the wrong issue: a write, not
@@ -55,8 +55,7 @@ interface BundleDecision {
55
55
 
56
56
  // Whether `from`'s body names `to`. One direction of the citation test, because which direction it
57
57
  // was is what `epic-bundle-evidence.ts` reports — and the read is single-sourced here rather than
58
- // written a second time there, so the candidate search and the evidence beside it cannot drift apart
59
- // (joshuafolkken/kit#1737).
58
+ // written a second time there, so the candidate search and the evidence beside it cannot drift apart.
60
59
  function names_in_body(from: BacklogIssue, to: BacklogIssue): boolean {
61
60
  return epic_audit_logic.parse_references(from.body, from.repo).includes(to.number)
62
61
  }
@@ -117,10 +116,10 @@ const NO_SIGNAL_REASON = 'no existing issue shares a reference or a dependency w
117
116
 
118
117
  // Names the epic, rather than only reporting that one exists. The number is what the caller does
119
118
  // something with: the prerequisite procedure inserts into that epic instead of creating a second one,
120
- // and an issue tracked by two epics gives the auto-close two task lists to disagree about
121
- // (joshuafolkken/kit#943). The decision already carried the number; only this sentence dropped it.
119
+ // and an issue tracked by two epics gives the auto-close two task lists to disagree about.
120
+ // The decision already carried the number; only this sentence dropped it.
122
121
  function already_tracked_reason(epic: number): string {
123
- return `#${String(epic)} already tracks this issue`
122
+ return `${issue_cite.plain(epic)} already tracks this issue`
124
123
  }
125
124
 
126
125
  const SPREAD_REASON =
@@ -132,13 +131,13 @@ function to_numbers(candidates: ReadonlyArray<BacklogIssue>): Array<number> {
132
131
 
133
132
  function create_decision(subject: BacklogIssue, numbers: ReadonlyArray<number>): BundleDecision {
134
133
  const count = String(numbers.length)
135
- const reason = `#${String(subject.number)} and ${count} related issue(s) belong to no epic`
134
+ const reason = `${issue_cite.plain(subject.number)} and ${count} related issue(s) belong to no epic`
136
135
 
137
136
  return { action: 'create_epic', epics: [], candidates: numbers, reason }
138
137
  }
139
138
 
140
139
  // Which epic each issue is itself tracked by. An epic is a row of the backlog like any other, so a
141
- // nested one carries its own parent here and no second read is needed (joshuafolkken/kit#1079).
140
+ // nested one carries its own parent here and no second read is needed.
142
141
  // The repository filter is defensive: every caller stamps one repository onto the whole listing
143
142
  // today, and the filter is what keeps a bare epic number naming the subject's repository if one ever
144
143
  // assembles two.
@@ -181,8 +180,8 @@ function is_cyclic(
181
180
  }
182
181
 
183
182
  // Nested epics are not two peers to choose between: the parent already contains the child, so an
184
- // issue related to both belongs in the child and no merge is on the table. Asking anyway is the
185
- // false positive joshuafolkken/kit#1079 recorded three times, one of which stopped a whole batch.
183
+ // issue related to both belongs in the child and no merge is on the table. Asking anyway is a false
184
+ // positive that can stop a whole batch.
186
185
  function narrow_to_innermost(
187
186
  epics: ReadonlyArray<number>,
188
187
  parents: ReadonlyMap<number, number>,
@@ -200,7 +199,7 @@ function narrow_to_innermost(
200
199
  // reported without narrowing above, so a lone survivor of two or more means the graph was acyclic,
201
200
  // and there every dropped epic is a transitive parent of the one left.
202
201
  function tracks_reason(epic: number, involved: ReadonlyArray<number>): string {
203
- const tracks = `#${String(epic)} already tracks a related issue`
202
+ const tracks = `${issue_cite.plain(epic)} already tracks a related issue`
204
203
  if (involved.length === 1) return tracks
205
204
 
206
205
  return `${tracks}; the other epics the candidates sit in are its own parents`
@@ -256,7 +255,7 @@ function decide_bundle(
256
255
 
257
256
  // The dependency links a bundle should record, from what the candidates already declare. Bundling
258
257
  // without the order records the batch and loses the reason it is a batch — an issue that must follow
259
- // another is exactly the case this exists to catch (joshuafolkken/kit#873).
258
+ // another is exactly the case this exists to catch.
260
259
  //
261
260
  // Only relations already declared are carried over; an order nobody stated is not invented here.
262
261
  function bundle_dependency_links(
@@ -269,7 +268,7 @@ function bundle_dependency_links(
269
268
  // rather than from each member: comparing a blocker against its *own* member's repository would
270
269
  // let two members elsewhere emit a link between them, and the epic body would then resolve those
271
270
  // bare numbers against this repository — a different pair of issues. `epic_graph.child_links`
272
- // guards the identical case the identical way (joshuafolkken/kit#1130).
271
+ // guards the identical case the identical way.
273
272
  const declared_repo = subject.repo
274
273
 
275
274
  return members
@@ -7,21 +7,19 @@ import {
7
7
  IN_PROGRESS_LABEL,
8
8
  NEEDS_DECISION_LABEL,
9
9
  } from '#scripts/issue/issue-labels'
10
+ import { session_cite } from '#scripts/issue/session-cite'
10
11
 
11
12
  // How much of a repository's parallelism is already spoken for — asked of the *repository*, never of
12
- // the epic (joshuafolkken/kit#925), and counted rather than treated as a yes/no since
13
- // joshuafolkken/kit#1491.
13
+ // the epic, and counted rather than treated as a yes/no.
14
14
  //
15
15
  // `epic-classify.ts` sorts only the children the epic tracks, so an `in-progress` issue belonging to
16
16
  // a *different* epic is invisible to it: start two `epicrun`s and both answer "nothing of mine is in
17
17
  // progress". This read is what closes that gap, and it is deliberately outside the classification —
18
18
  // the question is not about the graph.
19
19
  //
20
- // **What an `in-progress` issue holds is one lane, not the repository.** Until joshuafolkken/kit#1490
21
- // the contended resource really was one working tree, one `main` and one `pnpm-lock.yaml`, so one
22
- // holder excluded everything. A lane is its own checkout with its own branch and its own ports, so
23
- // the question stopped being "is anything running" and became "how many are running" — and the
24
- // answer is a count the caller compares against `lane_capacity`'s limit.
20
+ // **What an `in-progress` issue holds is one lane, not the repository.** A lane is its own checkout
21
+ // with its own branch and its own ports, so the question is not "is anything running" but "how many
22
+ // are running" — and the answer is a count the caller compares against `lane_capacity`'s limit.
25
23
  //
26
24
  // **The count is read from GitHub, never kept in the session.** Two `epicrun`s counting to six in
27
25
  // their own memory give twelve lanes; the label on an open issue is the one record both of them
@@ -37,14 +35,14 @@ const LISTING_LIMIT = 100
37
35
  // `issue-labels.ts` records: GitHub keeps the spelling a label was created with.
38
36
  //
39
37
  // `already-done` joins `needs-decision` here for the same reason it joins it in
40
- // `epic_classify.local_category` (joshuafolkken/kit#1679): the run that applied it committed
38
+ // `epic_classify.local_category`: the run that applied it committed
41
39
  // nothing, so the checkout it ran in is clean and there is no uncommitted work for the next child to
42
40
  // start on top of. That is exactly what separates both from `needs-human-review`, which is
43
41
  // deliberately not parked because its work is still sitting in the tree.
44
42
  const PARKED_LABELS: ReadonlySet<string> = new Set([NEEDS_DECISION_LABEL, ALREADY_DONE_LABEL])
45
43
 
46
- // What one repository answered. `unreadable` is kept apart from `idle` for the reason
47
- // joshuafolkken/kit#950 records: reading a failed read as an empty listing is a confident absence
44
+ // What one repository answered. `unreadable` is kept apart from `idle` because reading a failed
45
+ // read as an empty listing is a confident absence
48
46
  // built on a response nobody parsed — and here that absence *starts* work, which is the one
49
47
  // direction a guard must never fail in.
50
48
  //
@@ -55,12 +53,14 @@ const PARKED_LABELS: ReadonlySet<string> = new Set([NEEDS_DECISION_LABEL, ALREAD
55
53
  // children are read first, and one that could not be read is already an anomaly that exits 1. What
56
54
  // is left at this line is transient, and `wait` self-heals where an exit needs a person.
57
55
  //
58
- // **`truncated` is kept apart from `idle` for the same reason, one step further in**
59
- // (joshuafolkken/kit#1067). Since the page ceiling applies to every listing, a listing can now come
56
+ // **`truncated` is kept apart from `idle` for the same reason, one step further in**.
57
+ // Since the page ceiling applies to every listing, a listing can now come
60
58
  // back well-formed, short, and missing the very issue that holds this repository — and "no holder in
61
59
  // the rows I was given" is not "no holder". It is grouped with `unreadable` rather than with `idle`
62
60
  // because what it authorizes is identical: nothing. It gets its own kind only so the message names
63
61
  // the real cause — `unreadable_message` sends a reader to `gh auth status`, which is green here.
62
+ const NO_AGES: ReadonlyMap<number, string> = new Map()
63
+
64
64
  type BusyRead =
65
65
  | { kind: 'idle' }
66
66
  | { kind: 'busy'; issues: ReadonlyArray<OpenIssueData> }
@@ -69,9 +69,25 @@ type BusyRead =
69
69
 
70
70
  // Named so the reader can go and look at them: the stale-label rule is what keeps an abandoned
71
71
  // `in-progress` from holding a repository forever, and it cannot be applied to an issue nobody was
72
- // told about.
73
- function format_holders(issues: ReadonlyArray<OpenIssueData>): string {
74
- return issues.map((issue) => `#${String(issue.number)} ${issue.title}`).join(', ')
72
+ // told about. Each holder's label age is printed beside it when the caller read one,
73
+ // since the age is what that rule is applied against.
74
+ function format_holder(
75
+ issue: OpenIssueData,
76
+ repo: string,
77
+ ages: ReadonlyMap<number, string>,
78
+ ): string {
79
+ const cite = session_cite.issue(issue.number, issue.title, repo)
80
+ const age = ages.get(issue.number)
81
+
82
+ return age === undefined ? cite : `${cite} (${age})`
83
+ }
84
+
85
+ function format_holders(
86
+ issues: ReadonlyArray<OpenIssueData>,
87
+ repo: string,
88
+ ages: ReadonlyMap<number, string>,
89
+ ): string {
90
+ return issues.map((issue) => format_holder(issue, repo, ages)).join(', ')
75
91
  }
76
92
 
77
93
  // How many lanes this read shows occupied. Every kind but `busy` is zero, and the two that could not
@@ -87,8 +103,9 @@ function occupancy_message(
87
103
  issues: ReadonlyArray<OpenIssueData>,
88
104
  repo: string,
89
105
  limit: number,
106
+ ages: ReadonlyMap<number, string> = NO_AGES,
90
107
  ): string {
91
- return `${String(issues.length)} of ${String(limit)} lanes in use in ${repo}: ${format_holders(issues)}.`
108
+ return `${String(issues.length)} of ${String(limit)} lanes in use in ${repo}: ${format_holders(issues, repo, ages)}.`
92
109
  }
93
110
 
94
111
  // The occupancy said once, with the consequence appended — rather than a second sentence that
@@ -97,15 +114,16 @@ function lanes_full_message(
97
114
  issues: ReadonlyArray<OpenIssueData>,
98
115
  repo: string,
99
116
  limit: number,
117
+ ages: ReadonlyMap<number, string> = NO_AGES,
100
118
  ): string {
101
- return `${occupancy_message(issues, repo, limit)} No lane is free, so nothing is offered here. A lane is released when its child merges or is parked; if a label is stale, remove it and ask again, and \`JOSH_LANE_LIMIT\` is what raises the ceiling.`
119
+ return `${occupancy_message(issues, repo, limit, ages)} No lane is free, so nothing is offered here. A lane is released when its child merges or is parked; if a label is stale, remove it and ask again, and \`JOSH_LANE_LIMIT\` is what raises the ceiling.`
102
120
  }
103
121
 
104
122
  function unreadable_message(repo: string): string {
105
123
  return `Could not read the \`${IN_PROGRESS_LABEL}\` listing for ${repo}. That is not "nothing is running" — check \`gh auth status\` and ask again.`
106
124
  }
107
125
 
108
- // Said in the `⚠ … cap` shape joshuafolkken/kit#1033 settled on, because it is the same kind of
126
+ // Said in the shared `⚠ … cap` shape, because it is the same kind of
109
127
  // statement: the read happened and covered less than the whole listing. What it means here is
110
128
  // stronger than elsewhere, so the message says the consequence out loud rather than leaving a reader
111
129
  // to infer it from a warning marker.
@@ -129,8 +147,13 @@ const BUSY_REASONS: Readonly<
129
147
  truncated: truncated_message,
130
148
  }
131
149
 
132
- function busy_reason(read: BusyRead, repo: string, limit: number): string {
133
- if (read.kind === 'busy') return lanes_full_message(read.issues, repo, limit)
150
+ function busy_reason(
151
+ read: BusyRead,
152
+ repo: string,
153
+ limit: number,
154
+ ages: ReadonlyMap<number, string> = NO_AGES,
155
+ ): string {
156
+ if (read.kind === 'busy') return lanes_full_message(read.issues, repo, limit, ages)
134
157
  if (read.kind === 'idle') return ''
135
158
 
136
159
  return BUSY_REASONS[read.kind](repo)
@@ -141,7 +164,7 @@ function busy_reason(read: BusyRead, repo: string, limit: number): string {
141
164
  // `in-progress` and so calls a parked child `human` rather than `time`. Two readings of one issue
142
165
  // have to agree, and without this they do not — nothing removes `in-progress` when a child is
143
166
  // parked, so `park and continue` would spend a lane on the very child it just set aside, and with
144
- // one lane the run would poll instead of continuing (joshuafolkken/kit#925). A child stopped by
167
+ // one lane the run would poll instead of continuing. A child stopped by
145
168
  // `needs-human-review` is deliberately not parked and goes on holding its lane: its uncommitted work
146
169
  // is still sitting in that checkout.
147
170
  function is_parked(issue: OpenIssueData): boolean {