@joshuafolkken/kit 1.1229.0 → 1.1370.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 (939) 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 +50 -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 +24 -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 +27 -16
  27. package/.claude/skills/workflow-commands/latest-gate.md +18 -29
  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/.github/workflows/publish.yml +2 -0
  42. package/.vscode/tasks.json +14 -0
  43. package/CLAUDE.md +10 -61
  44. package/README.md +38 -57
  45. package/SECURITY.md +1 -1
  46. package/dist/CLAUDE.md +10 -61
  47. package/dist/commands/document-section-cli.js +42 -10
  48. package/dist/config-merge/index.js +11 -2
  49. package/dist/hooks/audit-provision.js +2 -2
  50. package/dist/hooks/batch-guard.js +7 -7
  51. package/dist/hooks/{chunk-FIVDHQGT.js → chunk-43G45XJF.js} +18 -20
  52. package/dist/hooks/{chunk-JUDKDCDP.js → chunk-4TW4MQUL.js} +284 -362
  53. package/dist/hooks/{chunk-5VMKCCC4.js → chunk-76RK6E3H.js} +13 -11
  54. package/dist/hooks/{chunk-RNWHN5BP.js → chunk-DZWZ3DKY.js} +4 -4
  55. package/dist/hooks/{chunk-5VNDSNG3.js → chunk-FZ6FUSBM.js} +1 -1
  56. package/dist/hooks/{chunk-VC3PZPZO.js → chunk-GG72ANKI.js} +1 -1
  57. package/dist/hooks/{chunk-6HJJXRBX.js → chunk-KPM4YIIX.js} +8 -44
  58. package/dist/hooks/chunk-MXVQMLDP.js +3705 -0
  59. package/dist/hooks/{chunk-ELCN5LCH.js → chunk-NEC4AT4Z.js} +34 -12
  60. package/dist/hooks/{chunk-TQNPDZNH.js → chunk-NZBHG6FW.js} +7 -5
  61. package/dist/hooks/chunk-NZN2UFI6.js +2409 -0
  62. package/dist/hooks/{chunk-F56MFS4B.js → chunk-R6CRQEAL.js} +4 -4
  63. package/dist/hooks/chunk-SYSRHRWU.js +1589 -0
  64. package/dist/hooks/{chunk-55HHG5PX.js → chunk-TLJYAGZK.js} +799 -903
  65. package/dist/hooks/chunk-Z5TMJIPW.js +45 -0
  66. package/dist/hooks/codex-hook-adapter.js +26 -21
  67. package/dist/hooks/duplicate-read-guard.js +8 -8
  68. package/dist/hooks/format-edited.js +4 -4
  69. package/dist/hooks/inputs.json +213 -197
  70. package/dist/hooks/investigation-guard.js +8 -8
  71. package/dist/hooks/pretool-guard.js +15 -15
  72. package/dist/hooks/session-lang.js +406 -8
  73. package/dist/hooks/stop-guard.js +122 -201
  74. package/dist/josh.js +540 -137
  75. package/dist/version/index.js +15 -13
  76. package/eslint/base.js +43 -5
  77. package/eslint/rules/english-only-prose.js +3 -3
  78. package/eslint/rules/import.js +12 -0
  79. package/eslint/rules/namespace-object-export.js +2 -2
  80. package/package.json +16 -10
  81. package/pnpm-workspace.yaml +2 -4
  82. package/prompts/coding-standards.md +14 -48
  83. package/prompts/collaboration-workflow/file-edits.md +1 -1
  84. package/prompts/collaboration-workflow/issue-citation.md +1 -1
  85. package/prompts/collaboration-workflow/issue-template.md +4 -10
  86. package/prompts/collaboration-workflow/operating-rules.md +7 -8
  87. package/prompts/collaboration-workflow/output-bounds.md +1 -1
  88. package/prompts/collaboration-workflow/overview.md +1 -1
  89. package/prompts/collaboration-workflow/plan-comment.md +2 -1
  90. package/prompts/collaboration-workflow/principles.md +21 -3
  91. package/prompts/collaboration-workflow/report-format.md +16 -29
  92. package/prompts/collaboration-workflow/residency.md +1 -1
  93. package/prompts/collaboration-workflow/rule-delivery.md +7 -95
  94. package/prompts/collaboration-workflow/shell-body.md +3 -23
  95. package/prompts/collaboration-workflow/turn-batching.md +4 -13
  96. package/prompts/collaboration-workflow/wip-cap.md +5 -11
  97. package/prompts/refactoring.md +1 -1
  98. package/prompts/review-rubric.md +3 -22
  99. package/prompts/review.md +15 -38
  100. package/prompts/testing-guide.md +2 -4
  101. package/scripts/adopt/adopt-logic.ts +5 -5
  102. package/scripts/adopt/adopt-toolkits.ts +4 -5
  103. package/scripts/adopt/adopt.ts +2 -3
  104. package/scripts/agent/agent-argv.ts +7 -7
  105. package/scripts/agent/agent-diagnostics.ts +2 -2
  106. package/scripts/agent/agent-exit-record.ts +1 -1
  107. package/scripts/agent/agent-headless.ts +1 -1
  108. package/scripts/agent/agent-launch-environment.ts +6 -1
  109. package/scripts/agent/agent-role-profile.ts +49 -22
  110. package/scripts/agent/agent-session-role.ts +32 -0
  111. package/scripts/agent/api-outage.ts +1 -1
  112. package/scripts/agent/claude-agent-argv.ts +4 -4
  113. package/scripts/agent/claude-result-event.ts +4 -4
  114. package/scripts/agent/codex-hooks.ts +2 -2
  115. package/scripts/agent/interactive-ask.ts +3 -6
  116. package/scripts/auto-ok/auto-ok-cli.ts +46 -60
  117. package/scripts/backlog/backlog-arrival-added.ts +34 -0
  118. package/scripts/backlog/backlog-arrival.ts +54 -17
  119. package/scripts/backlog/backlog-budget-cli.ts +34 -6
  120. package/scripts/backlog/backlog-budget.ts +17 -24
  121. package/scripts/backlog/backlog-defect-priority.ts +1 -1
  122. package/scripts/backlog/backlog-drive-args.ts +5 -4
  123. package/scripts/backlog/backlog-drive-cli.ts +14 -10
  124. package/scripts/backlog/backlog-drive-epic.ts +85 -0
  125. package/scripts/backlog/backlog-drive-launch.ts +1 -1
  126. package/scripts/backlog/backlog-drive-named-offer.ts +60 -9
  127. package/scripts/backlog/backlog-drive-named.ts +39 -9
  128. package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
  129. package/scripts/backlog/backlog-drive-restore.ts +1 -1
  130. package/scripts/backlog/backlog-drive-retrospective.ts +2 -2
  131. package/scripts/backlog/backlog-drive.ts +43 -28
  132. package/scripts/backlog/backlog-idle.ts +88 -0
  133. package/scripts/backlog/backlog-named.ts +11 -15
  134. package/scripts/backlog/backlog-next.ts +26 -30
  135. package/scripts/backlog/backlog-offer-cli.ts +28 -23
  136. package/scripts/backlog/backlog-offer.ts +7 -7
  137. package/scripts/backlog/backlog-overlap.ts +178 -0
  138. package/scripts/backlog/backlog-plan-cli.ts +14 -90
  139. package/scripts/backlog/backlog-plan-read.ts +111 -0
  140. package/scripts/backlog/backlog-plan.ts +11 -10
  141. package/scripts/backlog/backlog-pool.ts +13 -14
  142. package/scripts/backlog/backlog-rank.ts +11 -11
  143. package/scripts/backlog/backlog-ready.ts +15 -10
  144. package/scripts/backlog/backlog-scope.ts +14 -15
  145. package/scripts/backlog/backlog-stalled-cli.ts +2 -2
  146. package/scripts/backlog/backlog-stalled-detect.ts +4 -4
  147. package/scripts/backlog/backlog-stalled.ts +5 -6
  148. package/scripts/backlog/backlog-waves.ts +4 -4
  149. package/scripts/backlog/backlogrun-args.ts +74 -0
  150. package/scripts/backlog/backlogrun-cli.ts +113 -0
  151. package/scripts/backlog/backlogrun-launch.ts +178 -0
  152. package/scripts/behavior/behavior-assertion.ts +6 -8
  153. package/scripts/behavior/behavior-cli.ts +1 -1
  154. package/scripts/behavior/behavior-rules.ts +3 -3
  155. package/scripts/build/build-claude-md.ts +4 -4
  156. package/scripts/build/build-codex-hooks.ts +2 -2
  157. package/scripts/build/build-commands.ts +1 -1
  158. package/scripts/build/build-hooks.ts +5 -5
  159. package/scripts/build/build.ts +1 -1
  160. package/scripts/build/hook-bundle-stamp.ts +109 -7
  161. package/scripts/build/local-bin.ts +2 -2
  162. package/scripts/cases/cases-cli.ts +1 -1
  163. package/scripts/cases/cases-logic.ts +2 -2
  164. package/scripts/ci/composite-actions.ts +1 -2
  165. package/scripts/ci/pr-classification.ts +2 -2
  166. package/scripts/claude/workflow-destination.ts +1 -1
  167. package/scripts/clone/clone-aggregate.ts +1 -1
  168. package/scripts/clone/clone-fingerprint.ts +1 -1
  169. package/scripts/clone/clone-scan-cli.ts +1 -1
  170. package/scripts/clone/clone-scan.ts +1 -1
  171. package/scripts/config-merge/index.ts +1 -1
  172. package/scripts/config-merge/json-format.ts +1 -3
  173. package/scripts/config-merge/patch-json-array.ts +90 -0
  174. package/scripts/config-merge/patch-json-key.ts +6 -3
  175. package/scripts/config-merge/patch-json-list.ts +1 -1
  176. package/scripts/cost-runtime/codex-usage.ts +1 -1
  177. package/scripts/cost-runtime/context-cut-payback.ts +4 -5
  178. package/scripts/cost-runtime/context-cut-threshold.ts +4 -6
  179. package/scripts/cost-runtime/cost-attribute.ts +3 -3
  180. package/scripts/cost-runtime/cost-blocks.ts +3 -4
  181. package/scripts/cost-runtime/cost-cli.ts +14 -11
  182. package/scripts/cost-runtime/cost-corpus.ts +11 -11
  183. package/scripts/cost-runtime/cost-pricing.ts +4 -4
  184. package/scripts/cost-runtime/cost-tokens.ts +1 -2
  185. package/scripts/cost-runtime/cost-transcript.ts +29 -29
  186. package/scripts/cost-runtime/cost-usage.ts +6 -7
  187. package/scripts/cost-runtime/cost-verdict.ts +10 -11
  188. package/scripts/cost-runtime/own-session.ts +1 -1
  189. package/scripts/cost-runtime/transcript-cwd.ts +2 -2
  190. package/scripts/delegation/delegation-cli.ts +4 -4
  191. package/scripts/delegation/delegation-policy.ts +13 -15
  192. package/scripts/delegation/duplicate-read-guard.ts +9 -10
  193. package/scripts/delegation/fanout-cli.ts +1 -1
  194. package/scripts/delegation/fanout.ts +1 -1
  195. package/scripts/delegation/investigation-guard.ts +18 -22
  196. package/scripts/delegation/investigation-reads.ts +48 -238
  197. package/scripts/discovery/repo-discovery.ts +1 -1
  198. package/scripts/discovery/repo-map-logic.ts +1 -2
  199. package/scripts/discovery/repo-origin.ts +3 -3
  200. package/scripts/discovery/repo-party-cli.ts +2 -2
  201. package/scripts/discovery/repo-party.ts +2 -2
  202. package/scripts/doctor/doctor-consumer.ts +1 -1
  203. package/scripts/doctor/doctor-io.ts +6 -7
  204. package/scripts/doctor/doctor-logic.ts +1 -1
  205. package/scripts/doctor/doctor-ports.ts +1 -1
  206. package/scripts/doctor/doctor.ts +8 -9
  207. package/scripts/document/backlogrun-parent-read-set.ts +5 -6
  208. package/scripts/document/bash-output-cap.ts +5 -7
  209. package/scripts/document/capped-print-part.ts +1 -1
  210. package/scripts/document/capped-print.ts +1 -1
  211. package/scripts/document/document-byte-budget.ts +33 -64
  212. package/scripts/document/document-byte-check.ts +4 -4
  213. package/scripts/document/document-reachability.ts +7 -8
  214. package/scripts/document/document-read-cli.ts +2 -2
  215. package/scripts/document/document-scan.ts +26 -2
  216. package/scripts/document/document-section-cli.ts +6 -8
  217. package/scripts/document/document-section.ts +8 -12
  218. package/scripts/document/edit-files-cli.ts +3 -4
  219. package/scripts/document/entry-read-budget.ts +8 -70
  220. package/scripts/document/entry-read-set.ts +51 -34
  221. package/scripts/document/lane-child-read-set.ts +9 -9
  222. package/scripts/document/read-files-cli.ts +1 -2
  223. package/scripts/document/read-set-cli.ts +16 -19
  224. package/scripts/document/read-set-cost.ts +4 -4
  225. package/scripts/document/read-set-point-of-use.ts +28 -38
  226. package/scripts/document/read-set-pricing.ts +1 -1
  227. package/scripts/document/read-set-trim.ts +3 -3
  228. package/scripts/document/resident-budget.ts +8 -10
  229. package/scripts/epic/epic-add-body.ts +15 -18
  230. package/scripts/epic/epic-add-plan.ts +26 -28
  231. package/scripts/epic/epic-add.ts +32 -25
  232. package/scripts/epic/epic-audit-checks.ts +27 -37
  233. package/scripts/epic/epic-audit-cli.ts +21 -22
  234. package/scripts/epic/epic-audit-orphans.ts +16 -17
  235. package/scripts/epic/epic-audit-rationale.ts +10 -15
  236. package/scripts/epic/epic-audit-report.ts +2 -5
  237. package/scripts/epic/epic-audit.ts +18 -14
  238. package/scripts/epic/epic-body.ts +10 -10
  239. package/scripts/epic/epic-bundle-cli.ts +36 -34
  240. package/scripts/epic/epic-bundle-evidence.ts +5 -5
  241. package/scripts/epic/epic-bundle-gaps.ts +6 -9
  242. package/scripts/epic/epic-bundle-poll.ts +1 -1
  243. package/scripts/epic/epic-bundle-referenced.ts +11 -14
  244. package/scripts/epic/epic-bundle.ts +19 -20
  245. package/scripts/epic/epic-busy.ts +44 -21
  246. package/scripts/epic/epic-candidate-confirm.ts +15 -18
  247. package/scripts/epic/epic-chains.ts +18 -23
  248. package/scripts/epic/epic-classify.ts +11 -12
  249. package/scripts/epic/epic-cli-argv.ts +5 -6
  250. package/scripts/epic/epic-cli-remove.ts +9 -4
  251. package/scripts/epic/epic-cli.ts +38 -26
  252. package/scripts/epic/epic-close-comment.ts +14 -15
  253. package/scripts/epic/epic-close.ts +25 -29
  254. package/scripts/epic/epic-cross-repo.ts +18 -21
  255. package/scripts/epic/epic-decision.ts +14 -18
  256. package/scripts/epic/epic-fetch.ts +25 -31
  257. package/scripts/epic/epic-graph.ts +15 -17
  258. package/scripts/epic/epic-index.ts +14 -16
  259. package/scripts/epic/epic-issue.ts +9 -11
  260. package/scripts/epic/epic-label-age.ts +74 -0
  261. package/scripts/epic/epic-lane-offer.ts +35 -24
  262. package/scripts/epic/epic-nested.ts +1 -1
  263. package/scripts/epic/epic-next-read.ts +8 -8
  264. package/scripts/epic/epic-next-views.ts +12 -12
  265. package/scripts/epic/epic-next.ts +29 -33
  266. package/scripts/epic/epic-outside-blocker.ts +11 -10
  267. package/scripts/epic/epic-parse.ts +22 -24
  268. package/scripts/epic/epic-promote.ts +3 -2
  269. package/scripts/epic/epic-rank.ts +1 -1
  270. package/scripts/epic/epic-read.ts +10 -8
  271. package/scripts/epic/epic-reconcile.ts +8 -6
  272. package/scripts/epic/epic-reference.ts +5 -4
  273. package/scripts/epic/epic-relation-recheck.ts +10 -11
  274. package/scripts/epic/epic-relations.ts +9 -8
  275. package/scripts/epic/epic-remove-plan.ts +4 -5
  276. package/scripts/epic/epic-remove.ts +7 -5
  277. package/scripts/epic/epic-report.ts +18 -20
  278. package/scripts/epic/epic-run.ts +6 -5
  279. package/scripts/epic/epic-sections.ts +2 -2
  280. package/scripts/epic/epic-shape.ts +3 -3
  281. package/scripts/epic/epic-solo-stale.ts +3 -2
  282. package/scripts/epic/epic-solo.ts +8 -8
  283. package/scripts/epic/epic-triage.ts +5 -4
  284. package/scripts/epic/epic-validate.ts +8 -7
  285. package/scripts/epic/epic.ts +5 -5
  286. package/scripts/exports/unused-members-cli.ts +1 -1
  287. package/scripts/followup/followup-issue-number.ts +1 -2
  288. package/scripts/followup/git-followup-cleanup.ts +6 -7
  289. package/scripts/followup/git-followup-finish.ts +11 -13
  290. package/scripts/followup/git-followup-flush.ts +11 -7
  291. package/scripts/followup/git-followup-issue-close.ts +16 -13
  292. package/scripts/followup/git-followup-label.ts +9 -6
  293. package/scripts/followup/git-followup-merged.ts +1 -1
  294. package/scripts/followup/git-followup-pending.ts +7 -9
  295. package/scripts/followup/git-followup-stages.ts +28 -17
  296. package/scripts/followup/git-followup-workflow.ts +19 -21
  297. package/scripts/followup/git-pr-followup-checks.ts +13 -20
  298. package/scripts/followup/git-pr-followup-wrapup.ts +7 -7
  299. package/scripts/followup/git-pr-followup.ts +18 -17
  300. package/scripts/gate/core-admission.ts +162 -0
  301. package/scripts/gate/core-budget.ts +134 -91
  302. package/scripts/gate/gate-ledger.ts +114 -0
  303. package/scripts/gate/gate-log.ts +7 -9
  304. package/scripts/gate/gate-plan.ts +103 -35
  305. package/scripts/gate/gate-report.ts +39 -21
  306. package/scripts/gate/gate-skip.ts +11 -13
  307. package/scripts/gate/gate-steps.ts +5 -1
  308. package/scripts/gate/gate-tree.ts +3 -4
  309. package/scripts/gate/hook-gate-reuse.ts +9 -9
  310. package/scripts/gate/machine-capacity.ts +313 -0
  311. package/scripts/gate/pre-commit-type-check.ts +4 -4
  312. package/scripts/gate/project-checks.ts +12 -4
  313. package/scripts/gate/scoped-green.ts +11 -18
  314. package/scripts/gate/type-check-command.ts +2 -2
  315. package/scripts/gate/type-check-step.ts +4 -4
  316. package/scripts/gate/verification-gate.ts +60 -53
  317. package/scripts/gh/gh-spawn.ts +2 -2
  318. package/scripts/gh/git-ai-review-scan.ts +3 -2
  319. package/scripts/gh/git-gh-api-path.ts +10 -11
  320. package/scripts/gh/git-gh-exec.ts +43 -48
  321. package/scripts/gh/git-gh-failure.ts +6 -9
  322. package/scripts/gh/git-gh-helpers.ts +1 -1
  323. package/scripts/gh/git-gh-issue-list.ts +15 -19
  324. package/scripts/gh/git-gh-issue-read.ts +43 -60
  325. package/scripts/gh/git-gh-issue-rest.ts +14 -15
  326. package/scripts/gh/git-gh-issue-write.ts +52 -40
  327. package/scripts/gh/git-gh-issue.ts +23 -24
  328. package/scripts/gh/git-gh-pr-auto-merge.ts +3 -3
  329. package/scripts/gh/git-gh-pr-read.ts +46 -50
  330. package/scripts/gh/git-gh-pr-rest.ts +23 -26
  331. package/scripts/gh/git-gh-pr-review.ts +2 -2
  332. package/scripts/gh/git-gh-pr-rollup.ts +4 -4
  333. package/scripts/gh/git-gh-pr-snapshot.ts +8 -10
  334. package/scripts/gh/git-gh-pr.ts +16 -16
  335. package/scripts/gh/git-gh-reachability.ts +11 -12
  336. package/scripts/gh/git-gh-repo.ts +2 -3
  337. package/scripts/gh/git-gh-rest-state.ts +1 -1
  338. package/scripts/gh/git-pr-ai-review.ts +6 -5
  339. package/scripts/gh/git-pr-checks-eval.ts +28 -30
  340. package/scripts/gh/git-pr-checks-parse.ts +14 -16
  341. package/scripts/gh/git-pr-checks-watch.ts +17 -17
  342. package/scripts/gh/git-pr-checks.ts +20 -23
  343. package/scripts/gh/git-pr-coderabbit.ts +8 -6
  344. package/scripts/gh/git-pr-confirmation.ts +5 -5
  345. package/scripts/gh/git-pr-managed-config.ts +7 -9
  346. package/scripts/gh/git-pr-messages.ts +1 -1
  347. package/scripts/gh/git-pr.ts +15 -16
  348. package/scripts/gh/github-issue-url.ts +8 -9
  349. package/scripts/git/base-tree.ts +66 -0
  350. package/scripts/git/change-base.ts +42 -2
  351. package/scripts/git/changed-file-scope.ts +5 -5
  352. package/scripts/git/changed-paths.ts +1 -2
  353. package/scripts/git/constants.ts +2 -2
  354. package/scripts/git/git-branch.ts +1 -1
  355. package/scripts/git/git-closes-keyword.ts +3 -3
  356. package/scripts/git/git-command.ts +53 -41
  357. package/scripts/git/git-common-directory.ts +3 -3
  358. package/scripts/git/git-diff-reads.ts +14 -15
  359. package/scripts/git/git-error.ts +1 -1
  360. package/scripts/git/git-execa-error.ts +1 -2
  361. package/scripts/git/git-issue.ts +10 -8
  362. package/scripts/git/git-location-environment.ts +3 -4
  363. package/scripts/git/git-ls-remote.ts +6 -8
  364. package/scripts/git/git-pre-push-hook.ts +11 -10
  365. package/scripts/git/git-preflight.ts +5 -5
  366. package/scripts/git/git-push-transport.ts +2 -2
  367. package/scripts/git/git-remote-branch.ts +1 -2
  368. package/scripts/git/git-schemas.ts +16 -23
  369. package/scripts/git/git-spawn-sync.ts +1 -1
  370. package/scripts/git/git-spawn.ts +37 -14
  371. package/scripts/git/git-ssh-keepalive.ts +12 -5
  372. package/scripts/git/git-staging.ts +7 -8
  373. package/scripts/git/git-workflow.ts +1 -1
  374. package/scripts/git/git-worktree.ts +35 -27
  375. package/scripts/git/gone-branch.ts +2 -2
  376. package/scripts/git/listing-cutoff.ts +1 -2
  377. package/scripts/git/lockfile-sync.ts +65 -0
  378. package/scripts/git/main-merge-guard.ts +1 -2
  379. package/scripts/git/main-merge.ts +7 -7
  380. package/scripts/git/main-sync.ts +23 -8
  381. package/scripts/git/parse-json-array.ts +18 -23
  382. package/scripts/git/repository-lock.ts +34 -2
  383. package/scripts/git/stash/git-stash.ts +4 -5
  384. package/scripts/git/stash/stash-orphans.ts +5 -3
  385. package/scripts/git/stash/stash-pop-args.ts +1 -1
  386. package/scripts/git/stash/stash-pop-cli.ts +3 -3
  387. package/scripts/git/stash/stash-sweep-lock.ts +2 -2
  388. package/scripts/hooks/batch-guard.ts +11 -13
  389. package/scripts/hooks/check-commit-message.ts +12 -9
  390. package/scripts/hooks/codex-hook-adapter.ts +16 -10
  391. package/scripts/hooks/edited-cspell.ts +3 -4
  392. package/scripts/hooks/format-edited-cli.ts +1 -1
  393. package/scripts/hooks/format-edited-file.ts +11 -17
  394. package/scripts/hooks/format-rewrite-notice.ts +19 -17
  395. package/scripts/hooks/pre-push-unit.ts +10 -14
  396. package/scripts/hooks/pretool-guard-cli.ts +4 -4
  397. package/scripts/hooks/pretool-guard.ts +93 -18
  398. package/scripts/hooks/reserved-run.ts +2 -2
  399. package/scripts/hooks/step-zero-notice.ts +1 -1
  400. package/scripts/hooks/stop-guard.ts +21 -10
  401. package/scripts/init/basic-path-migration.ts +2 -2
  402. package/scripts/init/claude-kit-only-settings.ts +2 -2
  403. package/scripts/init/claude-plugin-config.ts +2 -2
  404. package/scripts/init/distributed-paths.ts +4 -4
  405. package/scripts/init/hook-command-rewrite.ts +3 -3
  406. package/scripts/init/hook-launch.ts +5 -5
  407. package/scripts/init/init-actions.ts +13 -0
  408. package/scripts/init/init-ai-copy.ts +11 -11
  409. package/scripts/init/init-bootstrap.ts +3 -3
  410. package/scripts/init/init-copy-content.ts +4 -4
  411. package/scripts/init/init-logic-json-merge.ts +7 -9
  412. package/scripts/init/init-logic-migrate.ts +1 -1
  413. package/scripts/init/init-logic-templates.ts +1 -1
  414. package/scripts/init/init-logic-workspace.ts +4 -4
  415. package/scripts/init/init-logic-yaml-merge.ts +2 -2
  416. package/scripts/init/init-logic.ts +19 -22
  417. package/scripts/init/init.ts +12 -8
  418. package/scripts/init/kit-base-preset.ts +1 -1
  419. package/scripts/init/kit-setup-state.ts +1 -1
  420. package/scripts/init/kit-written-paths.ts +1 -2
  421. package/scripts/init/package-manager-pin.ts +35 -0
  422. package/scripts/init/project-profile-cli.ts +1 -1
  423. package/scripts/init/project-profile.ts +3 -3
  424. package/scripts/init/session-language-environment.ts +1 -1
  425. package/scripts/init/start-exec.ts +3 -4
  426. package/scripts/init/start-plan.ts +2 -2
  427. package/scripts/init/start-setup-pr.ts +3 -2
  428. package/scripts/init/start-steps.ts +2 -2
  429. package/scripts/init/tsconfig-preset-migration.ts +1 -1
  430. package/scripts/init/vscode-tasks.ts +62 -0
  431. package/scripts/issue/baseline-measure.ts +2 -2
  432. package/scripts/issue/behavior-change-lint.ts +2 -2
  433. package/scripts/issue/defect-rate-cli.ts +6 -7
  434. package/scripts/issue/defect-rate.ts +37 -27
  435. package/scripts/issue/git-next-issues.ts +9 -8
  436. package/scripts/issue/issue-auto-ok.ts +49 -11
  437. package/scripts/issue/issue-backlinks-cli.ts +5 -5
  438. package/scripts/issue/issue-backlinks.ts +6 -6
  439. package/scripts/issue/issue-cite-cli.ts +20 -18
  440. package/scripts/issue/issue-cite.ts +18 -8
  441. package/scripts/issue/issue-closing-pr.ts +4 -4
  442. package/scripts/issue/issue-comment-cli.ts +6 -4
  443. package/scripts/issue/issue-file-cli.ts +75 -15
  444. package/scripts/issue/issue-file-fold.ts +155 -0
  445. package/scripts/issue/issue-file.ts +14 -6
  446. package/scripts/issue/issue-fold-cli.ts +14 -9
  447. package/scripts/issue/issue-fold.ts +23 -8
  448. package/scripts/issue/issue-labels.ts +46 -37
  449. package/scripts/issue/issue-lint-cli.ts +2 -2
  450. package/scripts/issue/issue-lint.ts +1 -1
  451. package/scripts/issue/issue-merged.ts +10 -4
  452. package/scripts/issue/issue-number-shape.ts +27 -0
  453. package/scripts/issue/issue-rank.ts +1 -1
  454. package/scripts/issue/issue-read-cli.ts +4 -5
  455. package/scripts/issue/issue-read.ts +4 -5
  456. package/scripts/issue/issue-reference.ts +5 -5
  457. package/scripts/issue/issue-release-cli.ts +165 -0
  458. package/scripts/issue/issue-release.ts +58 -0
  459. package/scripts/issue/issue-report-failures.ts +7 -4
  460. package/scripts/issue/issue-scout-cli.ts +11 -11
  461. package/scripts/issue/issue-scout-closed.ts +4 -4
  462. package/scripts/issue/issue-scout.ts +4 -5
  463. package/scripts/issue/issue-state-cli.ts +17 -10
  464. package/scripts/issue/issue-state.ts +12 -13
  465. package/scripts/issue/issue-wip.ts +7 -7
  466. package/scripts/issue/markdown-section.ts +3 -3
  467. package/scripts/issue/measure-rerun-cli.ts +10 -9
  468. package/scripts/issue/reproduction-measure.ts +3 -3
  469. package/scripts/issue/session-cite.ts +56 -0
  470. package/scripts/josh/agent-session-environment.ts +10 -8
  471. package/scripts/josh/cli-body.ts +2 -2
  472. package/scripts/josh/command-suggest.ts +1 -1
  473. package/scripts/josh/file-map-stamp.ts +20 -23
  474. package/scripts/josh/hook-decision.ts +24 -28
  475. package/scripts/josh/josh-command-map.ts +4 -1
  476. package/scripts/josh/josh-command-types.ts +32 -34
  477. package/scripts/josh/josh-commands-ai.ts +6 -6
  478. package/scripts/josh/josh-commands-backlog.ts +15 -3
  479. package/scripts/josh/josh-commands-clone.ts +1 -1
  480. package/scripts/josh/josh-commands-development.ts +33 -4
  481. package/scripts/josh/josh-commands-document.ts +3 -3
  482. package/scripts/josh/josh-commands-guard.ts +3 -3
  483. package/scripts/josh/josh-commands-issue.ts +11 -5
  484. package/scripts/josh/josh-commands-lane.ts +16 -5
  485. package/scripts/josh/josh-commands-lint.ts +1 -1
  486. package/scripts/josh/josh-commands-maintenance.ts +2 -2
  487. package/scripts/josh/josh-commands-run.ts +20 -6
  488. package/scripts/josh/josh-commands-split.ts +1 -2
  489. package/scripts/josh/josh-commands-versioning.ts +5 -5
  490. package/scripts/josh/josh-commands-workflow.ts +30 -22
  491. package/scripts/josh/josh-environment-file.ts +1 -1
  492. package/scripts/josh/josh-in-process.ts +3 -3
  493. package/scripts/josh/josh-logic.ts +10 -10
  494. package/scripts/josh/josh-run.ts +3 -3
  495. package/scripts/josh/josh-verdict.ts +9 -12
  496. package/scripts/josh/josh.ts +3 -3
  497. package/scripts/josh/kit-only.ts +2 -2
  498. package/scripts/josh/path-decision.ts +3 -3
  499. package/scripts/josh/platform-temporary.ts +7 -5
  500. package/scripts/josh/process-identity.ts +24 -6
  501. package/scripts/josh/process-owner.ts +4 -4
  502. package/scripts/josh/session-language-cli.ts +53 -11
  503. package/scripts/josh/session-language.ts +1 -1
  504. package/scripts/josh/stamp-file.ts +48 -29
  505. package/scripts/josh/stamp-record.ts +57 -0
  506. package/scripts/lane/lane-await.ts +35 -11
  507. package/scripts/lane/lane-cache.ts +6 -6
  508. package/scripts/lane/lane-capacity.ts +32 -17
  509. package/scripts/lane/lane-child-invocation.ts +17 -15
  510. package/scripts/lane/lane-child-marker.ts +12 -12
  511. package/scripts/lane/lane-cli.ts +20 -13
  512. package/scripts/lane/lane-close.ts +6 -6
  513. package/scripts/lane/lane-dispatch.ts +61 -72
  514. package/scripts/lane/lane-environment.ts +5 -5
  515. package/scripts/lane/lane-guard-policy.ts +7 -21
  516. package/scripts/lane/lane-handoff.ts +2 -2
  517. package/scripts/lane/lane-install.ts +9 -10
  518. package/scripts/lane/lane-launch-cli.ts +13 -8
  519. package/scripts/lane/lane-ledger.ts +73 -11
  520. package/scripts/lane/lane-leftover.ts +44 -30
  521. package/scripts/lane/lane-limit-cli.ts +160 -0
  522. package/scripts/lane/lane-limit-override.ts +74 -0
  523. package/scripts/lane/lane-load.ts +19 -68
  524. package/scripts/lane/lane-measure-cli.ts +15 -25
  525. package/scripts/lane/lane-occupancy.ts +6 -4
  526. package/scripts/lane/lane-open.ts +25 -24
  527. package/scripts/lane/lane-output.ts +4 -3
  528. package/scripts/lane/lane-paths.ts +22 -8
  529. package/scripts/lane/lane-phase.ts +33 -0
  530. package/scripts/lane/lane-reap.ts +2 -2
  531. package/scripts/lane/lane-registry.ts +27 -15
  532. package/scripts/lane/lane-relaunch.ts +9 -9
  533. package/scripts/lane/lane-report.ts +5 -4
  534. package/scripts/lane/lane-resume.ts +2 -2
  535. package/scripts/lane/lane-sampler.ts +55 -0
  536. package/scripts/lane/lane-seed.ts +7 -7
  537. package/scripts/lane/lane-stage-stats.ts +135 -0
  538. package/scripts/lane/lane-start-point.ts +8 -11
  539. package/scripts/lane/lane-stats.ts +60 -15
  540. package/scripts/lane/lane-stray.ts +140 -0
  541. package/scripts/lane/lane-vacant.ts +1 -1
  542. package/scripts/lane/openai-lane-supervisor-decision.ts +3 -7
  543. package/scripts/lane/openai-lane-supervisor-owner.ts +3 -9
  544. package/scripts/lane/openai-review-broker.ts +2 -4
  545. package/scripts/lib/ancestor-directories.ts +1 -1
  546. package/scripts/lib/bounded-pool.ts +2 -2
  547. package/scripts/lib/buffered-process.ts +4 -6
  548. package/scripts/lib/caddy-logs.sh +0 -0
  549. package/scripts/lib/cli-flags.ts +39 -6
  550. package/scripts/lib/error-message.ts +1 -1
  551. package/scripts/lib/json-value.ts +17 -3
  552. package/scripts/lib/poll.ts +1 -1
  553. package/scripts/lib/status-icons.ts +3 -3
  554. package/scripts/lib/timed-fetch.ts +1 -1
  555. package/scripts/lib/timeouts.ts +1 -1
  556. package/scripts/lines/bytes-command.ts +3 -4
  557. package/scripts/lines/effective-limit.ts +25 -12
  558. package/scripts/lines/line-budget.ts +47 -55
  559. package/scripts/lines/line-targets.ts +6 -2
  560. package/scripts/lines/lines-command.ts +3 -3
  561. package/scripts/lint/cspell-cached.ts +1 -1
  562. package/scripts/lint/cycle-recheck.ts +122 -0
  563. package/scripts/lint/format.ts +1 -2
  564. package/scripts/lint/lint-parallel.ts +34 -19
  565. package/scripts/lint/lint-related-scope.ts +25 -15
  566. package/scripts/lint/lint-related.ts +6 -7
  567. package/scripts/managed-marker/index.ts +1 -1
  568. package/scripts/managed-marker/managed-marker-logic.ts +1 -2
  569. package/scripts/notify/git-notify.ts +9 -7
  570. package/scripts/notify/telegram-notify.ts +53 -37
  571. package/scripts/notify/telegram-test-logic.ts +3 -3
  572. package/scripts/notify/telegram-test.ts +45 -30
  573. package/scripts/observations/observation-ledger-home.ts +14 -8
  574. package/scripts/observations/observation-ledger-line.ts +3 -2
  575. package/scripts/observations/observation-ledger-migrate.ts +3 -4
  576. package/scripts/observations/observation-ledger-prepare.ts +4 -4
  577. package/scripts/observations/observation-ledger.ts +14 -15
  578. package/scripts/observations/observation-record-cli.ts +83 -0
  579. package/scripts/observations/observation-record.ts +91 -0
  580. package/scripts/observations/observations-flush-cli.ts +1 -1
  581. package/scripts/observations/observations-flush-landing.ts +7 -6
  582. package/scripts/observations/observations-flush.ts +26 -27
  583. package/scripts/overrides/overrides-check.ts +18 -8
  584. package/scripts/package/package-scout-cli.ts +1 -1
  585. package/scripts/package/package-scout-format.ts +2 -2
  586. package/scripts/package/package-scout.ts +1 -1
  587. package/scripts/propagate/propagate-git-failure.ts +1 -1
  588. package/scripts/propagate/propagate-git.ts +7 -7
  589. package/scripts/propagate/propagate-plan.ts +2 -2
  590. package/scripts/propagate/propagate-publish.ts +2 -3
  591. package/scripts/propagate/propagate-run.ts +5 -7
  592. package/scripts/propagate/propagate-select.ts +1 -1
  593. package/scripts/propagate/propagate-steps.ts +19 -20
  594. package/scripts/propagate/propagate-targets.ts +6 -10
  595. package/scripts/propagate/propagate.ts +5 -5
  596. package/scripts/refactor/import-graph.ts +1 -1
  597. package/scripts/refactor/refactor-lint.ts +4 -10
  598. package/scripts/refactor/refactor-scan-cli.ts +1 -1
  599. package/scripts/refactor/refactor-scan.ts +2 -2
  600. package/scripts/refactor/refactor-targets.ts +1 -1
  601. package/scripts/release/github-release-cli.ts +25 -3
  602. package/scripts/release/github-release-environment.ts +1 -0
  603. package/scripts/release/github-release-runs.ts +115 -0
  604. package/scripts/release/github-release.ts +13 -67
  605. package/scripts/release/release-cli.ts +21 -4
  606. package/scripts/release/release-history.ts +6 -10
  607. package/scripts/release/release-plan.ts +3 -3
  608. package/scripts/release/release-progress.ts +3 -4
  609. package/scripts/release/release-publish.ts +8 -9
  610. package/scripts/release/release-scope-cli.ts +8 -10
  611. package/scripts/release/release-tag.ts +6 -8
  612. package/scripts/release/release-worktree.ts +5 -5
  613. package/scripts/repo/auto-merge-setting-logic.ts +7 -9
  614. package/scripts/repo/auto-merge-setting.ts +1 -1
  615. package/scripts/repo/repo-setting.ts +4 -4
  616. package/scripts/repo/repository-labels.ts +1 -1
  617. package/scripts/repo/required-checks-logic.ts +3 -3
  618. package/scripts/repo/required-checks-report.ts +1 -1
  619. package/scripts/repo/ruleset-check-cli.ts +1 -1
  620. package/scripts/repo/ruleset-check.ts +1 -1
  621. package/scripts/report/report-format-reference.ts +26 -0
  622. package/scripts/report/report-lint-cli.ts +2 -2
  623. package/scripts/report/report-lint.ts +16 -2
  624. package/scripts/review/disposition-cli.ts +2 -2
  625. package/scripts/review/disposition-logic.ts +1 -1
  626. package/scripts/review/live-evidence.ts +9 -6
  627. package/scripts/review/review-attest-cli.ts +1 -2
  628. package/scripts/review/review-attest.ts +3 -3
  629. package/scripts/review/review-brief-cli.ts +19 -20
  630. package/scripts/review/review-brief.ts +29 -32
  631. package/scripts/review/review-checkout.ts +2 -2
  632. package/scripts/review/review-diff-parts.ts +3 -5
  633. package/scripts/review/review-diff-write.ts +1 -1
  634. package/scripts/review/review-finding-ledger.ts +7 -4
  635. package/scripts/review/review-findings-cli.ts +2 -2
  636. package/scripts/review/review-level.ts +4 -7
  637. package/scripts/review/review-record-cli.ts +73 -16
  638. package/scripts/review/review-record.ts +5 -4
  639. package/scripts/review/review-round2-cli.ts +2 -3
  640. package/scripts/review/review-round2.ts +13 -21
  641. package/scripts/review/review-stamps.ts +9 -71
  642. package/scripts/review/review-tree.ts +4 -5
  643. package/scripts/rules/bash-triggers.ts +4 -4
  644. package/scripts/rules/decision-oracle-batch.ts +5 -6
  645. package/scripts/rules/decision-oracle-stage.ts +1 -1
  646. package/scripts/rules/decision-oracle-tokens.ts +1 -2
  647. package/scripts/rules/decision-oracle.ts +2 -2
  648. package/scripts/rules/delivered-rules.ts +61 -406
  649. package/scripts/rules/destructive-command.ts +2 -2
  650. package/scripts/rules/direct-filing.ts +4 -4
  651. package/scripts/rules/direct-pr-create.ts +2 -2
  652. package/scripts/rules/early-heartbeat.ts +15 -19
  653. package/scripts/rules/file-body.ts +5 -6
  654. package/scripts/rules/filing-cap.ts +6 -7
  655. package/scripts/rules/filing-offer.ts +1 -1
  656. package/scripts/rules/firing-point.ts +6 -6
  657. package/scripts/rules/gh-api.ts +2 -2
  658. package/scripts/rules/git-argv.ts +3 -3
  659. package/scripts/rules/git-force.ts +2 -2
  660. package/scripts/rules/hook-context-line.ts +31 -0
  661. package/scripts/rules/implementation-cut-verdict.ts +5 -8
  662. package/scripts/rules/implementation-cut.ts +35 -32
  663. package/scripts/rules/index-guard.ts +2 -2
  664. package/scripts/rules/issue-citation.ts +7 -7
  665. package/scripts/rules/issue-comments.ts +21 -13
  666. package/scripts/rules/josh-git-bare.ts +2 -2
  667. package/scripts/rules/lane-background.ts +14 -16
  668. package/scripts/rules/lane-carry-conflict.ts +41 -5
  669. package/scripts/rules/lane-interactive-ask.ts +6 -9
  670. package/scripts/rules/lane-park.ts +12 -16
  671. package/scripts/rules/lane-split-park.ts +1 -2
  672. package/scripts/rules/lane-switch-main.ts +10 -13
  673. package/scripts/rules/last-prompt.ts +1 -1
  674. package/scripts/rules/oracle-consulted.ts +5 -5
  675. package/scripts/rules/oracle-firing.ts +6 -9
  676. package/scripts/rules/oracle-list-cli.ts +2 -2
  677. package/scripts/rules/permission-guards.ts +2 -2
  678. package/scripts/rules/piped-verification.ts +79 -9
  679. package/scripts/rules/poll-loop.ts +9 -11
  680. package/scripts/rules/pre-gate-cut.ts +33 -30
  681. package/scripts/rules/prior-comment-read.ts +3 -3
  682. package/scripts/rules/protected-files.ts +25 -13
  683. package/scripts/rules/raw-field-body.ts +3 -4
  684. package/scripts/rules/reply-language.ts +1 -1
  685. package/scripts/rules/rule-body-guard.ts +10 -12
  686. package/scripts/rules/rule-guard.ts +1 -1
  687. package/scripts/rules/rule-list.ts +51 -0
  688. package/scripts/rules/rule-registry-rows.ts +282 -0
  689. package/scripts/rules/rule-registry.ts +109 -0
  690. package/scripts/rules/rule-value-cache.ts +2 -2
  691. package/scripts/rules/rule-value-cli.ts +6 -4
  692. package/scripts/rules/rule-value.ts +61 -22
  693. package/scripts/rules/run-tail-rule.ts +11 -15
  694. package/scripts/rules/shell-body-trigger.ts +7 -7
  695. package/scripts/rules/shell-segments.ts +2 -4
  696. package/scripts/rules/stop-rules.ts +54 -41
  697. package/scripts/rules/tail-commands.ts +1 -1
  698. package/scripts/rules/test-declared-commit.ts +2 -2
  699. package/scripts/rules/third-party-write.ts +3 -3
  700. package/scripts/rules/worktree-guard.ts +12 -5
  701. package/scripts/run/add/run-add-cli.ts +165 -0
  702. package/scripts/run/add/run-add.ts +124 -0
  703. package/scripts/run/board/run-board-cli.ts +207 -0
  704. package/scripts/run/board/run-board-closed.ts +95 -0
  705. package/scripts/run/board/run-board-every.ts +60 -0
  706. package/scripts/run/board/run-board-fetch.ts +38 -0
  707. package/scripts/run/board/run-board-fit.ts +219 -0
  708. package/scripts/run/board/run-board-github.ts +162 -0
  709. package/scripts/run/board/run-board-header.ts +275 -0
  710. package/scripts/run/board/run-board-kind.ts +35 -0
  711. package/scripts/run/board/run-board-labels.ts +299 -0
  712. package/scripts/run/board/run-board-layout.ts +222 -0
  713. package/scripts/run/board/run-board-link.ts +31 -0
  714. package/scripts/run/board/run-board-machine.ts +198 -0
  715. package/scripts/run/board/run-board-notes.ts +103 -0
  716. package/scripts/run/board/run-board-phase.ts +136 -0
  717. package/scripts/run/board/run-board-plan.ts +129 -0
  718. package/scripts/run/board/run-board-read.ts +62 -0
  719. package/scripts/run/board/run-board-render-legend.ts +82 -0
  720. package/scripts/run/board/run-board-render-notes.ts +77 -0
  721. package/scripts/run/board/run-board-render-slot.ts +50 -0
  722. package/scripts/run/board/run-board-render.ts +407 -0
  723. package/scripts/run/board/run-board-scope.ts +17 -0
  724. package/scripts/run/board/run-board-screen.ts +43 -0
  725. package/scripts/run/board/run-board-span.ts +66 -0
  726. package/scripts/run/board/run-board-spin.ts +115 -0
  727. package/scripts/run/board/run-board-state.ts +113 -0
  728. package/scripts/run/board/run-board-status.ts +279 -0
  729. package/scripts/run/board/run-board-tick.ts +210 -0
  730. package/scripts/run/board/run-board-track.ts +22 -0
  731. package/scripts/run/board/run-board-usage-read.ts +255 -0
  732. package/scripts/run/board/run-board-usage-rusage.ts +124 -0
  733. package/scripts/run/board/run-board-usage-text.ts +80 -0
  734. package/scripts/run/board/run-board-usage.ts +165 -0
  735. package/scripts/run/carry/run-carry-added.ts +62 -0
  736. package/scripts/run/carry/run-carry-args.ts +25 -22
  737. package/scripts/run/carry/run-carry-change.ts +1 -1
  738. package/scripts/run/carry/run-carry-cli.ts +71 -48
  739. package/scripts/run/carry/run-carry-conversation.ts +6 -7
  740. package/scripts/run/carry/run-carry-ended.ts +85 -0
  741. package/scripts/run/carry/run-carry-reclaim.ts +1 -1
  742. package/scripts/run/carry/run-carry-stash.ts +3 -2
  743. package/scripts/run/carry/run-carry-streak.ts +8 -10
  744. package/scripts/run/carry/run-carry.ts +85 -89
  745. package/scripts/run/cut/run-cut-args.ts +7 -7
  746. package/scripts/run/cut/run-cut-cli.ts +68 -37
  747. package/scripts/run/cut/run-cut-handoff.ts +15 -15
  748. package/scripts/run/cut/run-cut-report.ts +37 -16
  749. package/scripts/run/cut/run-cut.ts +63 -77
  750. package/scripts/run/detached-launch.ts +35 -50
  751. package/scripts/run/entry/run-entry-cli.ts +48 -27
  752. package/scripts/run/entry/run-entry-stop.ts +7 -9
  753. package/scripts/run/entry/run-entry.ts +5 -6
  754. package/scripts/run/event/run-event-cli.ts +5 -6
  755. package/scripts/run/event/run-event-filed.ts +69 -0
  756. package/scripts/run/event/run-event-follow.ts +3 -3
  757. package/scripts/run/event/run-event-plan.ts +38 -0
  758. package/scripts/run/event/run-event-render.ts +10 -4
  759. package/scripts/run/event/run-event-scope.ts +47 -18
  760. package/scripts/run/event/run-event-stream-emit.ts +64 -11
  761. package/scripts/run/event/run-event-stream.ts +172 -43
  762. package/scripts/run/event/run-event-watch.ts +4 -6
  763. package/scripts/run/hold/run-hold-cli.ts +65 -62
  764. package/scripts/run/hold/run-hold.ts +88 -46
  765. package/scripts/run/merge/run-merge-cli.ts +116 -77
  766. package/scripts/run/merge/run-merge-collect.ts +107 -0
  767. package/scripts/run/merge/run-merge-steps.ts +112 -65
  768. package/scripts/run/merge/run-merge-token.ts +30 -0
  769. package/scripts/run/merge/run-merge.ts +31 -22
  770. package/scripts/run/progress/run-progress-args.ts +4 -4
  771. package/scripts/run/progress/run-progress-cli.ts +39 -50
  772. package/scripts/run/progress/run-progress-clock.ts +25 -32
  773. package/scripts/run/progress/run-progress-config.ts +6 -9
  774. package/scripts/run/progress/run-progress-read.ts +9 -10
  775. package/scripts/run/progress/run-progress.ts +48 -53
  776. package/scripts/run/review/run-review-cli.ts +6 -6
  777. package/scripts/run/review/run-review-steps.ts +6 -6
  778. package/scripts/run/review/run-review.ts +9 -11
  779. package/scripts/run/run-cli-fault.ts +29 -0
  780. package/scripts/run/run-ending-cli.ts +3 -3
  781. package/scripts/run/run-ending.ts +10 -14
  782. package/scripts/run/run-halfrun-resume.ts +6 -8
  783. package/scripts/run/run-headless.ts +25 -12
  784. package/scripts/run/run-invocation.ts +17 -22
  785. package/scripts/run/run-label.ts +7 -5
  786. package/scripts/run/run-liveness-cli.ts +19 -6
  787. package/scripts/run/run-liveness.ts +27 -38
  788. package/scripts/run/run-next-cli.ts +5 -9
  789. package/scripts/run/run-next.ts +4 -5
  790. package/scripts/run/run-parent-cut-hook.ts +10 -12
  791. package/scripts/run/run-preflight.ts +25 -29
  792. package/scripts/run/run-prep-cli.ts +17 -13
  793. package/scripts/run/run-prep-locate.ts +4 -5
  794. package/scripts/run/run-prep.ts +7 -10
  795. package/scripts/run/run-prrun-resume.ts +2 -2
  796. package/scripts/run/run-report-cli.ts +4 -4
  797. package/scripts/run/run-report.ts +9 -14
  798. package/scripts/run/run-retrospective.ts +3 -3
  799. package/scripts/run/run-section.ts +42 -0
  800. package/scripts/run/run-stage-read.ts +2 -2
  801. package/scripts/run/run-stage.ts +6 -4
  802. package/scripts/run/run-status-cli.ts +7 -5
  803. package/scripts/run/run-status.ts +6 -7
  804. package/scripts/run/run-step-cli.ts +13 -15
  805. package/scripts/run/run-step.ts +62 -48
  806. package/scripts/run/run-stop-notify.ts +7 -8
  807. package/scripts/run/run-stranded-cli.ts +1 -1
  808. package/scripts/run/run-stranded-detect.ts +4 -4
  809. package/scripts/run/run-stranded.ts +11 -13
  810. package/scripts/run/run-tail-cli.ts +15 -16
  811. package/scripts/run/run-tail.ts +14 -33
  812. package/scripts/run/run-watcher-guard-cli.ts +3 -4
  813. package/scripts/run/run-watcher-guard.ts +11 -12
  814. package/scripts/run/run-watcher-hook.ts +6 -12
  815. package/scripts/run/ship/run-ship-cli.ts +67 -33
  816. package/scripts/run/ship/run-ship-detach.ts +15 -13
  817. package/scripts/run/ship/run-ship-lock.ts +1 -1
  818. package/scripts/run/ship/run-ship-next.ts +7 -8
  819. package/scripts/run/ship/run-ship-pre-detach.ts +27 -11
  820. package/scripts/run/ship/run-ship-preflight.ts +10 -11
  821. package/scripts/run/ship/run-ship-probe.ts +4 -4
  822. package/scripts/run/ship/run-ship-return.ts +1 -1
  823. package/scripts/run/ship/run-ship-review-steps.ts +43 -24
  824. package/scripts/run/ship/run-ship-review.ts +12 -14
  825. package/scripts/run/ship/run-ship-scoped.ts +15 -6
  826. package/scripts/run/ship/run-ship-stage.ts +80 -26
  827. package/scripts/run/ship/run-ship-steps.ts +26 -16
  828. package/scripts/run/ship/run-ship-stop-text.ts +4 -2
  829. package/scripts/run/ship/run-ship-sync.ts +9 -8
  830. package/scripts/run/ship/run-ship.ts +17 -32
  831. package/scripts/run/tidy/run-tidy-cli.ts +9 -5
  832. package/scripts/run/tidy/run-tidy-lanes.ts +18 -7
  833. package/scripts/run/tidy/run-tidy-stashes.ts +8 -8
  834. package/scripts/run/tidy/run-tidy.ts +4 -3
  835. package/scripts/run/wake/run-wake-cli.ts +27 -33
  836. package/scripts/run/wake/run-wake-describe.ts +76 -29
  837. package/scripts/run/wake/run-wake-driver.ts +14 -14
  838. package/scripts/run/wake/run-wake-handoff.ts +6 -6
  839. package/scripts/run/wake/run-wake-loop.ts +13 -21
  840. package/scripts/run/wake/run-wake-restart.ts +4 -5
  841. package/scripts/run/wake/run-wake-session.ts +23 -27
  842. package/scripts/run/wake/run-wake.ts +57 -328
  843. package/scripts/safe-chain/ci-installer-pin.ts +3 -3
  844. package/scripts/safe-chain/pack-hook.ts +2 -2
  845. package/scripts/safe-chain/preinstall-command.ts +2 -2
  846. package/scripts/security/security-audit-logic.ts +1 -1
  847. package/scripts/security/security-audit-provision-logic.ts +1 -1
  848. package/scripts/security/security-audit-provision.ts +2 -2
  849. package/scripts/security/security-audit.ts +5 -5
  850. package/scripts/security/security-updates-logic.ts +2 -3
  851. package/scripts/security/security-updates.ts +2 -4
  852. package/scripts/self-sync-guard/index.ts +1 -1
  853. package/scripts/self-sync-guard/self-sync-guard-logic.ts +2 -2
  854. package/scripts/self-sync-guard/self-sync-refusal.ts +1 -1
  855. package/scripts/sonar/sonar-hotspots-cli.ts +1 -1
  856. package/scripts/sonar/sonar-hotspots.ts +1 -1
  857. package/scripts/sonar/sonar-new-code-cli.ts +1 -1
  858. package/scripts/sonar/sonar-new-code.ts +1 -1
  859. package/scripts/sonar/sonar-project.ts +1 -1
  860. package/scripts/split/split-assess-cli.ts +1 -1
  861. package/scripts/split/split-assess.ts +3 -3
  862. package/scripts/sync/directory-copy-guard.ts +2 -3
  863. package/scripts/sync/managed-config-scope-cli.ts +1 -2
  864. package/scripts/sync/managed-config-scope.ts +4 -4
  865. package/scripts/sync/plugin-skill-directories.ts +2 -2
  866. package/scripts/sync/reconcile-templates.ts +17 -8
  867. package/scripts/sync/removed-skill-manifest.ts +2 -3
  868. package/scripts/sync/sync-ai-files.ts +7 -7
  869. package/scripts/sync/sync-configs.ts +30 -3
  870. package/scripts/sync/sync-hook-safety.ts +2 -2
  871. package/scripts/sync/sync.ts +23 -10
  872. package/scripts/sync/synced-paths.ts +2 -1
  873. package/scripts/sync/workflow-pin-logic.ts +1 -1
  874. package/scripts/test/test-declared-changed.ts +4 -4
  875. package/scripts/test/test-declared-logic.ts +2 -3
  876. package/scripts/test/test-declared-match.ts +25 -4
  877. package/scripts/test/test-declared.ts +26 -9
  878. package/scripts/test/test-red-commit.ts +3 -2
  879. package/scripts/test/test-red-logic.ts +7 -14
  880. package/scripts/test/test-red.ts +12 -47
  881. package/scripts/test/test-related-scope.ts +2 -3
  882. package/scripts/test/test-related.ts +3 -3
  883. package/scripts/test/test-type-logic.ts +1 -2
  884. package/scripts/test/test-unit-guard.ts +13 -17
  885. package/scripts/test/unit-worker-share.ts +7 -8
  886. package/scripts/time-runtime/time-agent-bundles.ts +2 -4
  887. package/scripts/time-runtime/time-background.ts +17 -21
  888. package/scripts/time-runtime/time-batch-guard.ts +67 -342
  889. package/scripts/time-runtime/time-bundle-call.ts +26 -28
  890. package/scripts/time-runtime/time-bundles.ts +11 -12
  891. package/scripts/time-runtime/time-call-identity.ts +1 -1
  892. package/scripts/time-runtime/time-command-key.ts +2 -2
  893. package/scripts/time-runtime/time-density-hook.ts +8 -11
  894. package/scripts/time-runtime/time-density.ts +5 -5
  895. package/scripts/time-runtime/time-followup-stage.ts +7 -7
  896. package/scripts/time-runtime/time-format.ts +5 -5
  897. package/scripts/time-runtime/time-hook-transcript.ts +3 -3
  898. package/scripts/time-runtime/time-instant.ts +1 -1
  899. package/scripts/time-runtime/time-markers.ts +15 -19
  900. package/scripts/time-runtime/time-phase-names.ts +3 -3
  901. package/scripts/time-runtime/time-reported-failure.ts +15 -19
  902. package/scripts/time-runtime/time-round-trips.ts +20 -23
  903. package/scripts/time-runtime/time-shell.ts +8 -8
  904. package/scripts/time-runtime/time-single-check.ts +1 -2
  905. package/scripts/time-runtime/time-spans.ts +35 -40
  906. package/scripts/time-runtime/time-tool-call.ts +15 -16
  907. package/scripts/time-runtime/time-transcript-line.ts +53 -34
  908. package/scripts/time-runtime/time-writes.ts +5 -5
  909. package/scripts/ui/ui-routes-cli.ts +1 -2
  910. package/scripts/ui/ui-routes.ts +1 -2
  911. package/scripts/version/bump-version.ts +1 -1
  912. package/scripts/version/fresh-metadata-cache.ts +2 -2
  913. package/scripts/version/latest-corepack.ts +129 -98
  914. package/scripts/version/latest-lane-guard.ts +1 -1
  915. package/scripts/version/latest-scope-cli.ts +2 -2
  916. package/scripts/version/latest-stamp.ts +1 -2
  917. package/scripts/version/latest-update.ts +2 -2
  918. package/scripts/version/npm-registry.ts +2 -2
  919. package/scripts/version/package-manager-version.ts +18 -0
  920. package/scripts/version/publishable-range-check.ts +2 -1
  921. package/scripts/version/publishable-range.ts +1 -1
  922. package/scripts/version/release-age.ts +11 -11
  923. package/scripts/version/release-hold.ts +2 -2
  924. package/scripts/version/safe-chain-version-update.ts +3 -3
  925. package/scripts/version/version-check-logic.ts +2 -3
  926. package/scripts/version/version-check.ts +1 -2
  927. package/scripts/version/version-command-config.ts +2 -2
  928. package/scripts/version/version-commands.ts +3 -3
  929. package/scripts/version/version-remote.ts +4 -4
  930. package/scripts/version/version-targets.ts +2 -2
  931. package/templates/gitignore +7 -0
  932. package/templates/workflows/github-release.yml +4 -0
  933. package/dist/hooks/chunk-NV2JRZZO.js +0 -6385
  934. package/dist/hooks/chunk-RKUAD3I6.js +0 -90
  935. package/dist/hooks/chunk-WPALEIRX.js +0 -18
  936. package/scripts/backlog/backlog-restructure.ts +0 -152
  937. package/scripts/rules/issue-fold-rule.ts +0 -72
  938. package/scripts/rules/wip-cap.ts +0 -63
  939. package/scripts/run/run-issue-number.ts +0 -19
@@ -1,6 +1,6 @@
1
1
  import { split_assess, type SplitVerdict } from '#scripts/split/split-assess'
2
2
 
3
- // The filing-time counterpart to the split assessment (joshuafolkken/kit#2213).
3
+ // The filing-time counterpart to the split assessment.
4
4
  //
5
5
  // `split-assessment.md` → "The question" decides whether *one request* is really several
6
6
  // deliverables; this decides whether *several findings filed from one session* fold into one Issue or
@@ -11,32 +11,47 @@ import { split_assess, type SplitVerdict } from '#scripts/split/split-assess'
11
11
  //
12
12
  // **The default is `fold`.** Separability alone never separates — it is necessary, not sufficient —
13
13
  // and a size that does not clear the split guide folds however separable the findings are. That is
14
- // why an unmeasurable size is treated by the caller as under the guide: tipping the doubt toward
15
- // `separate` would reproduce the every-finding-its-own-Issue behavior this exists to end.
14
+ // why an unmeasurable size never tips to `separate`: that would reproduce the every-finding-its-own-Issue
15
+ // behavior this exists to end.
16
+ //
17
+ // **Nor does an unmeasurable size fold**. The size half is read off the working
18
+ // tree's diff, and a filing made before any implementation — `kickoff new`, a split's children — has
19
+ // no diff that says anything about the findings' size. Reading that as `single` folded every such
20
+ // filing; it answers `undetermined` instead, which leaves the size to the whole request's estimate
21
+ // (`split-assessment.md` → "The question").
16
22
 
17
- type FoldVerdict = 'fold' | 'separate' | 'no-fold-needed'
23
+ type FoldVerdict = 'fold' | 'separate' | 'no-fold-needed' | 'undetermined'
18
24
 
19
25
  const FOLD: FoldVerdict = 'fold'
20
26
  const SEPARATE: FoldVerdict = 'separate'
21
27
  const NO_FOLD_NEEDED: FoldVerdict = 'no-fold-needed'
28
+ const UNDETERMINED: FoldVerdict = 'undetermined'
22
29
 
23
30
  // One finding is nothing to fold: the question only arises once a session holds two or more.
24
31
  const MIN_CANDIDATES = 2
25
32
 
33
+ // Separable findings: the size alone decides, and a size nobody measured decides nothing.
34
+ function separable_verdict(size_verdict: SplitVerdict | undefined): FoldVerdict {
35
+ if (size_verdict === undefined) return UNDETERMINED
36
+
37
+ return size_verdict === split_assess.SPLIT_VERDICT ? SEPARATE : FOLD
38
+ }
39
+
26
40
  // The same two questions as the split assessment, in the same conjunction: `separate` only when the
27
41
  // findings are separable **and** their combined size clears the split guide. Either half alone folds,
28
- // and fewer than two candidates is not a fold question at all.
42
+ // and fewer than two candidates is not a fold question at all. An `undefined` size is one the diff
43
+ // could not measure, which decides nothing.
29
44
  function fold_verdict(
30
45
  candidate_count: number,
31
46
  is_separable: boolean,
32
- size_verdict: SplitVerdict,
47
+ size_verdict: SplitVerdict | undefined,
33
48
  ): FoldVerdict {
34
49
  if (candidate_count < MIN_CANDIDATES) return NO_FOLD_NEEDED
35
50
 
36
- return is_separable && size_verdict === split_assess.SPLIT_VERDICT ? SEPARATE : FOLD
51
+ return is_separable ? separable_verdict(size_verdict) : FOLD
37
52
  }
38
53
 
39
- const issue_fold = { FOLD, SEPARATE, NO_FOLD_NEEDED, MIN_CANDIDATES, fold_verdict }
54
+ const issue_fold = { FOLD, SEPARATE, NO_FOLD_NEEDED, UNDETERMINED, MIN_CANDIDATES, fold_verdict }
40
55
 
41
56
  export type { FoldVerdict }
42
57
  export { issue_fold }
@@ -7,41 +7,41 @@ const ENHANCEMENT_LABEL = 'enhancement'
7
7
  const BREAKING_CHANGE_LABEL = 'breaking-change'
8
8
  const IN_PROGRESS_LABEL = 'in-progress'
9
9
  // Applied by `kickoff` once its plan is on the issue, so the next command's `run:entry` reads the issue
10
- // as planned and starts at the implementation rather than planning again (joshuafolkken/kit#3042).
10
+ // as planned and starts at the implementation rather than planning again.
11
11
  // Namespaced like `run:solo`: a bare `planned` is a common roadmap label a person may already apply,
12
12
  // and reading one as kickoff's mark would skip the planning that never happened.
13
13
  const PLANNED_LABEL = 'run:planned'
14
14
  // Parks a child that cannot advance without a person deciding something. `epic:next` is what reads
15
15
  // it: a parked child is why a run reports "nothing left that time will fix" rather than waiting
16
- // forever (joshuafolkken/kit#860).
16
+ // forever.
17
17
  const NEEDS_DECISION_LABEL = 'needs-decision'
18
- // Marks an issue whose defect reaches the verification path, so it runs with nothing beside it
19
- // (joshuafolkken/kit#2776). A run applies it from the verification-path enumeration in `backlogrun-lanes.md`;
18
+ // Marks an issue whose defect reaches the verification path, so it runs with nothing beside it.
19
+ // A run applies it from the verification-path enumeration in `backlogrun-lanes.md`;
20
20
  // `backlog:next` enforces it (`backlog-solo.ts`), so the rule no longer rests on a judgement at
21
21
  // dispatch time.
22
22
  const RUN_SOLO_LABEL = 'run:solo'
23
- // The other half of the same judgement: an issue a run read and found safe to run beside others
24
- // (joshuafolkken/kit#2779). Without it an issue lacking `run:solo` could mean "judged parallel" or
23
+ // The other half of the same judgement: an issue a run read and found safe to run beside others.
24
+ // Without it an issue lacking `run:solo` could mean "judged parallel" or
25
25
  // "never judged", and `backlog:next` withholds the second (`epic-triage.ts`).
26
26
  const RUN_LANE_LABEL = 'run:lane'
27
- // Puts an issue at the head of the backlog's ranking (joshuafolkken/kit#2928). A person or a run may
27
+ // Puts an issue at the head of the backlog's ranking. A person or a run may
28
28
  // apply it — a run only where it can cite a deadline or a stated urgency, or a policy a person wrote
29
29
  // (`backlogrun-steps.md`) — and **only a person removes it**: a run that could clear it could undo
30
30
  // the person's ordering. Read by `issue-rank.ts`, the one place the ranking keys are decided.
31
31
  const PRIORITY_HIGH_LABEL = 'priority:high'
32
- // Opts one issue outside any epic into unattended execution (joshuafolkken/kit#906). **Only a
32
+ // Opts one issue outside any epic into unattended execution. **Only a
33
33
  // person applies it.** `epicrun #<E>` approves the merges inside `#<E>`; this label is the only way
34
34
  // a person extends that approval past the epic's edge, so a label an AI could apply to itself would
35
35
  // let an unattended run widen its own authorization — which is not a guard at all.
36
36
  const AUTO_OK_LABEL = 'auto-ok'
37
37
  // Degrades one issue's run to a `halfrun`-shaped stop: it is implemented and taken through the
38
- // verification gate, and then nothing is committed, pushed, opened as a pull request or merged
39
- // (joshuafolkken/kit#1125). **Only a person applies it** — a mark a run could clear for itself is not
38
+ // verification gate, and then nothing is committed, pushed, opened as a pull request or merged.
39
+ // **Only a person applies it** — a mark a run could clear for itself is not
40
40
  // a mark.
41
41
  //
42
42
  // It is the opposite of `auto-ok` in what it does: one widens unattended execution past an epic's
43
43
  // edge, the other withholds the last step of it. Unlike `auto-ok`, which `issue:file` applies by
44
- // default to work found by opted-in work (joshuafolkken/kit#3213), no run ever applies it. `auto-ok`
44
+ // default to work found by opted-in work, no run ever applies it. `auto-ok`
45
45
  // answers "may this run at all", this one answers "may its result ship without a person looking".
46
46
  //
47
47
  // **Not `needs-decision`, and the difference is what the two sets below encode.** A parked issue is
@@ -51,10 +51,9 @@ const AUTO_OK_LABEL = 'auto-ok'
51
51
  // checkout and must go on holding the repository. Read as parked in either place, the next child
52
52
  // would start on top of that work.
53
53
  const NEEDS_HUMAN_REVIEW_LABEL = 'needs-human-review'
54
- // Marks an issue whose work a run verified is **already merged** (joshuafolkken/kit#1679). Closing
55
- // an Issue is Tier C, so a run that reaches that conclusion may not act on it — and before this
56
- // label there was no exit that was not Tier C: `fullrun #1656` verified the work was already in
57
- // `main` from joshuafolkken/kit#1623 and closed the Issue itself.
54
+ // Marks an issue whose work a run verified is **already merged**. Closing
55
+ // an Issue is Tier C, so a run that reaches that conclusion may not act on it — this label is its
56
+ // exit that is not Tier C.
58
57
  //
59
58
  // **It is not `needs-decision`, and the difference is the whole reason it exists.** A parked issue
60
59
  // waits for an answer nobody has given; this one has its answer already — the work is done, and all
@@ -65,6 +64,12 @@ const NEEDS_HUMAN_REVIEW_LABEL = 'needs-human-review'
65
64
  // takes it off, because taking it off asserts the work is *not* done, which is the same claim in
66
65
  // reverse and is no more a run's to make.
67
66
  const ALREADY_DONE_LABEL = 'already-done'
67
+ // Marks the Issue that tracks a repository's next release. An Issue whose
68
+ // change reaches a consumer only once published is linked to it as a `blocked_by` blocker
69
+ // (`josh issue:release`), so "merged but not yet released" is visible in the backlog. A run applies
70
+ // it; **`auto-ok` never rides on it** — `issue-auto-ok.ts` refuses the default for it on every path,
71
+ // since a release is Tier C — and only a person opts it into unattended execution.
72
+ const RELEASE_LABEL = 'release'
68
73
 
69
74
  // The four labels that mean an open issue must not be handed to a run as it stands: an `epic`
70
75
  // tracks a batch and is never run directly (its children are), `in-progress` is already claimed by
@@ -84,20 +89,19 @@ const NOT_DIRECTLY_RUNNABLE_LABELS: ReadonlySet<string> = new Set([
84
89
  ALREADY_DONE_LABEL,
85
90
  ])
86
91
 
87
- // joshuafolkken/kit#1083: filing-route labels, applied at filing time so the backlog's composition —
88
- // a review-cap carry-forward vs a split child vs a Tier A in-implementation filing — is countable
89
- // with `gh api "repos/{owner}/{repo}/issues?labels=<route>"` instead of grepping issue bodies by
90
- // hand, which is how the 2026-08-30 breakdown was produced and why it did not reproduce. Purely
92
+ // Filing-route labels, applied at filing time so the backlog's composition — a review-cap
93
+ // carry-forward vs a split child vs a Tier A in-implementation filing — is countable with
94
+ // `gh api "repos/{owner}/{repo}/issues?labels=<route>"` instead of grepping issue bodies by hand,
95
+ // which does not reproduce. Purely
91
96
  // informational: unlike the three above, a route label says nothing about whether an issue may run,
92
97
  // so none of them joins NOT_DIRECTLY_RUNNABLE_LABELS. The names are duplicated as literals in the
93
98
  // filing procedures (prose cannot import this module); `scripts/rules/filing-route-label.test.ts` keys the
94
99
  // docs to these constants so a filing command that drops the label fails rather than drifting.
95
100
  //
96
- // joshuafolkken/kit#1518 added a fourth: an interrupt is a defect found in *this* repository that
97
- // does not block the run that found it, and which the WIP cap would otherwise push into the
98
- // discretionary exit — the route joshuafolkken/kit#1517 took, surviving only as a comment on another
99
- // issue. It is not `route:tier-a`: that one is a filing the run is blocked by (an upstream defect or
100
- // a prerequisite), and reading the two as one is what lost #1517.
101
+ // `route:interrupt` is a defect found in *this* repository that does not block the run that found
102
+ // it, and which the WIP cap would otherwise push into the discretionary exit, surviving only as a
103
+ // comment on another issue. It is not `route:tier-a`: that one is a filing the run is blocked by (an
104
+ // upstream defect or a prerequisite), and reading the two as one loses the interrupt.
101
105
  const INTERRUPT_ROUTE_LABEL = 'route:interrupt'
102
106
  const REVIEW_CAP_ROUTE_LABEL = 'route:review-cap'
103
107
  const SPLIT_ROUTE_LABEL = 'route:split'
@@ -139,7 +143,7 @@ const FILING_ROUTE_LABELS: ReadonlyArray<{
139
143
  },
140
144
  ]
141
145
 
142
- // joshuafolkken/kit#1729: the depth of an issue's subject, recorded as a label at filing time.
146
+ // The depth of an issue's subject, recorded as a label at filing time.
143
147
  //
144
148
  // **The definition is not here.** `.claude/skills/workflow-commands/observation-filing.md` → "The depth test",
145
149
  // is the single source: depth 0 is what a consumer of this package touches, depth 1 the run
@@ -148,10 +152,9 @@ const FILING_ROUTE_LABELS: ReadonlyArray<{
148
152
  // would be the clone `CLAUDE.md` prohibits, and the descriptions below therefore name the section
149
153
  // rather than paraphrase it.
150
154
  //
151
- // **Why a label at all.** joshuafolkken/kit#1698 set a measurable target — the share of open issues
152
- // at depth 0 — and left nothing that records a depth, so the share could only be obtained by reading
153
- // every open issue's body by hand. Two hand counts a day apart disagreed on the denominator and were
154
- // therefore not comparable, which is the failure a recorded label removes.
155
+ // **Why a label at all.** The share of open issues at depth 0 is a measured target, and without a
156
+ // recorded depth it could only be obtained by reading every open issue's body by hand — hand counts
157
+ // disagree on the denominator and are not comparable, which is the failure a recorded label removes.
155
158
  //
156
159
  // **The depth is read off the subject, so a run applies it.** Unlike `auto-ok` and
157
160
  // `needs-human-review` this is not a person's judgement about authorization; it is the same reading
@@ -163,8 +166,7 @@ const DEPTH_2_LABEL = 'depth:2'
163
166
 
164
167
  // Ordered shallowest first, which is what makes `depth_label_of` deterministic: an issue carrying
165
168
  // more than one depth label counts as the **lowest** depth present, the one closest to the consumer.
166
- // Without a fixed tie-break the same listing measured twice could answer differently, which is the
167
- // whole defect joshuafolkken/kit#1729 was filed for.
169
+ // Without a fixed tie-break the same listing measured twice could answer differently.
168
170
  const DEPTH_LABEL_ORDER: ReadonlyArray<string> = [DEPTH_0_LABEL, DEPTH_1_LABEL, DEPTH_2_LABEL]
169
171
 
170
172
  // The metadata `gh api ... labels` needs, in the shape `FILING_ROUTE_LABELS` above uses and for the
@@ -173,7 +175,7 @@ const DEPTH_LABEL_ORDER: ReadonlyArray<string> = [DEPTH_0_LABEL, DEPTH_1_LABEL,
173
175
  // Green, amber and pale blue, so the consumer-facing depth is the one that stands out in a listing.
174
176
  //
175
177
  // **`josh issue:file` provisions them** through `repository_labels.ensure_labels` before its create
176
- // call (joshuafolkken/kit#3176), so no document carries a creation command to keep in step.
178
+ // call, so no document carries a creation command to keep in step.
177
179
  const DEPTH_LABELS: ReadonlyArray<{
178
180
  name: string
179
181
  color: string
@@ -203,7 +205,7 @@ interface LabelDefinition {
203
205
  }
204
206
 
205
207
  // What `josh start` provisions on a new repository so the first `kickoff` finds every label a run
206
- // applies with its intended color (joshuafolkken/kit#2197). The `epic` and `in-progress` metadata is
208
+ // applies with its intended color. The `epic` and `in-progress` metadata is
207
209
  // the one the workflow documents create them with; the labels only a person applies are left out.
208
210
  const WORKFLOW_LABELS: ReadonlyArray<LabelDefinition> = [
209
211
  {
@@ -228,12 +230,17 @@ const WORKFLOW_LABELS: ReadonlyArray<LabelDefinition> = [
228
230
  color: 'e99695',
229
231
  description: 'Offered first in a backlogrun; only a person removes it',
230
232
  },
233
+ {
234
+ name: RELEASE_LABEL,
235
+ color: 'fef2c0',
236
+ description: 'Tracks the next release; its blockers are the merged work it publishes',
237
+ },
231
238
  ...FILING_ROUTE_LABELS,
232
239
  ...DEPTH_LABELS,
233
240
  ]
234
241
 
235
- // The pull request release classifications `pr-classification.yml` requires exactly one of
236
- // (joshuafolkken/kit#2797). The check is distributed by `josh sync`, so the labels it asks for are
242
+ // The pull request release classifications `pr-classification.yml` requires exactly one of.
243
+ // The check is distributed by `josh sync`, so the labels it asks for are
237
244
  // provisioned from this same list — a repository that never had them would otherwise fail the check
238
245
  // on every pull request that is not an `enhancement`.
239
246
  const BUGFIX_LABEL = 'bugfix'
@@ -289,7 +296,7 @@ function has_any_label(
289
296
  // A membership test answers whether the label is there; a *removal* has to name it, and
290
297
  // `DELETE …/issues/<N>/labels/<name>` names it in the path. Lowercasing the wanted name and sending
291
298
  // that would be a second comparison — GitHub's, on a spelling we did not read — so the removal reads
292
- // the stored one and sends it back (joshuafolkken/kit#1794).
299
+ // the stored one and sends it back.
293
300
  function label_name_of(labels: ReadonlyArray<string>, wanted: string): string | undefined {
294
301
  const target = wanted.toLowerCase()
295
302
 
@@ -318,7 +325,7 @@ function depth_label_of(labels: ReadonlyArray<LabelReference> | undefined): stri
318
325
  }
319
326
 
320
327
  // Every workflow label this package manages. The label-reference scan
321
- // (`scripts/document/label-reference.test.ts`, joshuafolkken/kit#1923) reads this to check that no
328
+ // (`scripts/document/label-reference.test.ts`) reads this to check that no
322
329
  // document operates on a label name that does not exist here — a stale or mistyped `labels[]=…`
323
330
  // otherwise fails silently at run time. One source, so a label added above joins the scan without a
324
331
  // second edit.
@@ -340,6 +347,7 @@ const ALL_LABELS: ReadonlySet<string> = new Set([
340
347
  NEEDS_HUMAN_REVIEW_LABEL,
341
348
  ALREADY_DONE_LABEL,
342
349
  PRIORITY_HIGH_LABEL,
350
+ RELEASE_LABEL,
343
351
  INTERRUPT_ROUTE_LABEL,
344
352
  REVIEW_CAP_ROUTE_LABEL,
345
353
  REVIEW_ROUND2_SKIPPED_LABEL,
@@ -386,6 +394,7 @@ export {
386
394
  PRIORITY_HIGH_LABEL,
387
395
  RELEASE_CLASSIFICATION_LABELS,
388
396
  RELEASE_CLASSIFICATION_NAMES,
397
+ RELEASE_LABEL,
389
398
  REPOSITORY_LABELS,
390
399
  REVIEW_CAP_ROUTE_LABEL,
391
400
  REVIEW_ROUND2_SKIPPED_LABEL,
@@ -6,10 +6,10 @@ import { issue_classification } from './issue-classification'
6
6
  import { issue_lint } from './issue-lint'
7
7
 
8
8
  // `josh issue:lint <path>` — read an Issue body from a file and print `ok`, or every template problem
9
- // one per line, exiting non-zero (joshuafolkken/kit#2123). It reads a path rather than stdin so it can
9
+ // one per line, exiting non-zero. It reads a path rather than stdin so it can
10
10
  // lint a body written to a file before the `gh api … issues` call that files it. A body that declares
11
11
  // itself a behavior-change Issue is additionally held to the firing-point, baseline and reproduction
12
- // rules (joshuafolkken/kit#2212, joshuafolkken/kit#2353).
12
+ // rules.
13
13
 
14
14
  const SUCCESS_EXIT_CODE = 0
15
15
  const FAILURE_EXIT_CODE = 1
@@ -2,7 +2,7 @@ import { markdown_section } from './markdown-section'
2
2
 
3
3
  // The Issue body template's four headings (`prompts/collaboration-workflow/issue-template.md`) are a
4
4
  // fixed shape, but unlike an epic — which `josh epic:check` verifies — nothing checks that a filed
5
- // Issue carries them. This reports the ones a body is missing (joshuafolkken/kit#2123). The headings
5
+ // Issue carries them. This reports the ones a body is missing. The headings
6
6
  // are the single source's, and the document test pins that these match it.
7
7
  const REQUIRED_HEADINGS: ReadonlyArray<string> = [
8
8
  '## 背景',
@@ -1,7 +1,7 @@
1
1
  import { git_gh_api_path } from '#scripts/gh/git-gh-api-path'
2
2
  import { git_gh_exec } from '#scripts/gh/git-gh-exec'
3
3
 
4
- // Whether an issue was closed by a merge, read from its REST timeline (joshuafolkken/kit#2701). The
4
+ // Whether an issue was closed by a merge, read from its REST timeline. The
5
5
  // issue's own `state_reason` cannot tell: a pull request's `closes #N` and a person's "Close as
6
6
  // completed" both answer `completed`. What only a merge leaves is a merged pull request referencing
7
7
  // the issue, so the answer is the conjunction — closed now, as completed, and referenced by a merged
@@ -55,7 +55,9 @@ function is_merged_close(rows: ReadonlyArray<TimelineRow>): boolean {
55
55
  return rows.some((row) => row.event === MERGED_REFERENCE)
56
56
  }
57
57
 
58
- async function read_merged(issue: string): Promise<boolean> {
58
+ // `undefined` when the timeline could not be read, so a caller that keeps the answer can tell "not
59
+ // merged" from "ask again".
60
+ async function read_merge_state(issue: string): Promise<boolean | undefined> {
59
61
  try {
60
62
  const raw = await git_gh_exec.exec_gh_api({
61
63
  path: `${git_gh_api_path.issue_api_path(issue)}/timeline?per_page=100`,
@@ -65,11 +67,15 @@ async function read_merged(issue: string): Promise<boolean> {
65
67
 
66
68
  return is_merged_close(parse_rows(raw))
67
69
  } catch {
68
- return false
70
+ return undefined
69
71
  }
70
72
  }
71
73
 
72
- const issue_merged = { is_merged_close, parse_rows, read_merged }
74
+ async function read_merged(issue: string): Promise<boolean> {
75
+ return (await read_merge_state(issue)) ?? false
76
+ }
77
+
78
+ const issue_merged = { is_merged_close, parse_rows, read_merge_state, read_merged }
73
79
 
74
80
  export type { TimelineRow }
75
81
  export { issue_merged }
@@ -0,0 +1,27 @@
1
+ // The shape an issue number may take, and the refusal when it does not — the one declaration every
2
+ // command reads.
3
+ //
4
+ // It sits in its own module because a rule copied into two files is a rule kept correct in one: a
5
+ // copy that read `/^\d+$/u` accepted issue `0` and a leading zero where every other command refused
6
+ // them. A command that interpolates the number into a shell command a caller is told to paste, a
7
+ // GitHub path, a branch or a lane directory refuses before the interpolation rather than leaving the
8
+ // check to whichever entry point remembered.
9
+ //
10
+ // `ISSUE_NUMBER_PATTERN` stays exported beside `is_issue_number`: a taint analyzer credits a literal
11
+ // pattern test in the expression that returns the value as a sanitizer, but not one reached through a
12
+ // call (`run-merge-cli.ts`).
13
+
14
+ const ISSUE_NUMBER_PATTERN = /^[1-9]\d*$/u
15
+ const BAD_ISSUE_MESSAGE = 'Not an issue number: '
16
+
17
+ function is_issue_number(value: string): boolean {
18
+ return ISSUE_NUMBER_PATTERN.test(value)
19
+ }
20
+
21
+ function require_issue_number(issue: string): void {
22
+ if (!is_issue_number(issue)) throw new Error(`${BAD_ISSUE_MESSAGE}${issue}`)
23
+ }
24
+
25
+ const issue_number_shape = { ISSUE_NUMBER_PATTERN, is_issue_number, require_issue_number }
26
+
27
+ export { issue_number_shape }
@@ -6,7 +6,7 @@ import {
6
6
  RUN_SOLO_LABEL,
7
7
  } from './issue-labels'
8
8
 
9
- // The keys that decide which open issue is offered first (joshuafolkken/kit#2928), defined once for
9
+ // The keys that decide which open issue is offered first, defined once for
10
10
  // every ranking that asks: the `🗒 Next issues` display, the `auto-ok` pickup and `backlog:next`.
11
11
  //
12
12
  // In order: `priority:high`, then a defect on the verification path (`bug` with `run:solo`, or
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env tsx
2
2
  import { fileURLToPath } from 'node:url'
3
3
  import { git_gh_command } from '#scripts/gh/git-gh-command'
4
+ import { issue_number_shape } from '#scripts/issue/issue-number-shape'
4
5
  import { bounded_pool } from '#scripts/lib/bounded-pool'
5
6
  import { issue_read, type IssueComment, type IssueFields } from './issue-read'
6
7
  import { issue_report_failures, type ReadFailureKind } from './issue-report-failures'
7
8
 
8
- // `josh issue:read <N> [<N> ...]` — the body *and* the comments of every issue named, in one call
9
- // (joshuafolkken/kit#1715).
9
+ // `josh issue:read <N> [<N> ...]` — the body *and* the comments of every issue named, in one call.
10
10
  //
11
11
  // It replaces the two `gh api` reads `.claude/skills/workflow-commands/issue-comments.md` tells an agent
12
12
  // to type per issue. Measured over four recorded `backlogrun` parents, `issue bookkeeping` was the
@@ -28,7 +28,6 @@ import { issue_report_failures, type ReadFailureKind } from './issue-report-fail
28
28
 
29
29
  const FAILURE_EXIT_CODE = 1
30
30
  const ARGV_OFFSET = 2
31
- const ISSUE_NUMBER_PATTERN = /^[1-9]\d*$/u
32
31
  const USAGE = 'Usage: josh issue:read <issue-number> [<issue-number> ...]'
33
32
  const BLOCK_SEPARATOR = '\n\n---\n\n'
34
33
  // The same bound `issue:state` puts on its batch read, for the same reason: every read is a `gh`
@@ -45,7 +44,7 @@ interface IssueContent {
45
44
  type NumberResult = { kind: 'issue'; content: IssueContent } | { kind: ReadFailureKind }
46
45
 
47
46
  // The formatted block for one issue, or the failure kind — what `run:prep` bundles beside the state
48
- // and the dependency-update scope (joshuafolkken/kit#1978). It reuses this file's read and the shared
47
+ // and the dependency-update scope. It reuses this file's read and the shared
49
48
  // `format_issue` rather than reproducing either, so the two `gh` reads and the block shape stay
50
49
  // single-sourced here.
51
50
  type BlockRead = { kind: 'ok'; block: string } | { kind: ReadFailureKind }
@@ -59,7 +58,7 @@ interface IssueReport {
59
58
  // Dropping it answers fewer numbers than were asked for and still exits zero — and nothing in the
60
59
  // output then says a number went unanswered. `#1262` copied out of a table is exactly that token.
61
60
  function parse_numbers(argv: ReadonlyArray<string>): ReadonlyArray<string> | undefined {
62
- const numbers = argv.filter((argument) => ISSUE_NUMBER_PATTERN.test(argument))
61
+ const numbers = argv.filter((argument) => issue_number_shape.is_issue_number(argument))
63
62
 
64
63
  if (numbers.length === 0 || numbers.length !== argv.length) return undefined
65
64
 
@@ -1,9 +1,8 @@
1
- import { parse_json_object_safe, read_json_listing } from '#scripts/git/parse-json-array'
1
+ import { parse_json_object_or_undefined, read_json_listing } from '#scripts/git/parse-json-array'
2
2
  import { z } from 'zod'
3
3
 
4
4
  // The block `josh issue:read` prints for one issue, kept apart from the reading and the printing so
5
- // the shape of the report is decided by one pure function — the seam `issue-state.ts` already has
6
- // (joshuafolkken/kit#1715).
5
+ // the shape of the report is decided by one pure function — the seam `issue-state.ts` already has.
7
6
  //
8
7
  // **It exists because reading one issue costs a parent two turns.** `.claude/skills/workflow-commands/SKILL.md`
9
8
  // `issue-comments.md` requires the body *and* the comments, since a decision recorded after the body was written
@@ -11,7 +10,7 @@ import { z } from 'zod'
11
10
  // `gh api repos/{owner}/{repo}/issues/<N>/comments`. Measured over four recorded `backlogrun`
12
11
  // parents, `issue bookkeeping` was the single largest contributor to the parent's turn count — 110 of
13
12
  // 414 turns, 26.6% — and one-issue-at-a-time `gh api` reads were its dominant shape. A parent's cost
14
- // grows as n²/2 in its own request count (joshuafolkken/kit#1567), so those turns are the
13
+ // grows as n²/2 in its own request count, so those turns are the
15
14
  // distribution this collapses.
16
15
  //
17
16
  // **The comments are never silently absent.** A listing that could not be read prints a line saying
@@ -65,7 +64,7 @@ const UNKNOWN_TIME = '(undated)'
65
64
  // parse.
66
65
  function parse_issue_fields(json: string): IssueFields | undefined {
67
66
  try {
68
- const parsed = parse_json_object_safe(json, issue_fields_schema)
67
+ const parsed = parse_json_object_or_undefined(json, issue_fields_schema)
69
68
 
70
69
  if (parsed === undefined) return undefined
71
70
 
@@ -1,14 +1,14 @@
1
1
  // An issue named from outside any one graph — a task-list row, a citation in prose, a blocker
2
2
  // relation, a child that could not be read. Repository **and** number, because a number alone cannot
3
3
  // identify one: issue numbers are unique per repository, so the same `#40` names two different issues
4
- // depending on who wrote it (joshuafolkken/kit#1014).
4
+ // depending on who wrote it.
5
5
  //
6
6
  // It lives in the git layer because the `blocked-by` relations are read here and carry a repository
7
- // of their own (joshuafolkken/kit#1126); the epic domain builds on this layer, never the other way
8
- // round (joshuafolkken/kit#2904). `epic-reference` re-exports it, so every epic importer is unchanged.
7
+ // of their own; the epic domain builds on this layer, never the other way
8
+ // round. `epic-reference` re-exports it, so every epic importer is unchanged.
9
9
  //
10
- // `state` is present only on a reference read from a `blocked-by` relation whose response carried it
11
- // (joshuafolkken/kit#1943). The classifier needs it for a blocker no named graph tracks, where there is
10
+ // `state` is present only on a reference read from a `blocked-by` relation whose response carried it.
11
+ // The classifier needs it for a blocker no named graph tracks, where there is
12
12
  // no child record to read the state from; every other reference leaves it out.
13
13
  interface IssueReference {
14
14
  repo: string
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env tsx
2
+ import { fileURLToPath } from 'node:url'
3
+ import { git_gh_command } from '#scripts/gh/git-gh-command'
4
+ import { git_gh_exec } from '#scripts/gh/git-gh-exec'
5
+ import { git_gh_issue_list, MAX_SCANNED } from '#scripts/gh/git-gh-issue-list'
6
+ import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
7
+ import { github_issue_url } from '#scripts/gh/github-issue-url'
8
+ import { issue_number_shape } from '#scripts/issue/issue-number-shape'
9
+ import { cli_flags } from '#scripts/lib/cli-flags'
10
+ import { error_text } from '#scripts/lib/error-message'
11
+ import { repository_labels } from '#scripts/repo/repository-labels'
12
+ import { RELEASE_LABEL } from './issue-labels'
13
+ import { issue_release } from './issue-release'
14
+ import { session_cite } from './session-cite'
15
+
16
+ // `josh issue:release <N>` — link Issue `<N>` to its repository's release Issue as a `blocked_by`
17
+ // blocker, filing the release Issue when none is open. `josh issue:file
18
+ // --release` calls the same `link` once its Issue exists, so a new and an existing Issue are linked
19
+ // by one body of code.
20
+ //
21
+ // The relation is written through `issue_add_blocked_by`, which addresses the repository `gh`
22
+ // resolves — the current one, or the target a cross-repository `issue:file` has pointed `GH_REPO` at.
23
+
24
+ const SUCCESS_EXIT_CODE = 0
25
+ const FAILURE_EXIT_CODE = 1
26
+ const ARGV_OFFSET = 2
27
+ const USAGE = 'Usage: josh issue:release <issue-number>'
28
+ const NONE = 'none'
29
+ const UNKNOWN_REPO_MESSAGE =
30
+ 'Could not read this repository from `git remote` — check `gh auth status`.'
31
+
32
+ interface ReleaseIssue {
33
+ issue_number: number
34
+ // Filed by this call, rather than found open.
35
+ is_filed: boolean
36
+ }
37
+
38
+ // `undefined` when the listing is unreadable, `NONE` when it reads and names no open release Issue.
39
+ async function find_open(target: string): Promise<number | typeof NONE | undefined> {
40
+ const outcome = await git_gh_issue_list.issue_list({
41
+ json_fields: 'number',
42
+ limit: MAX_SCANNED,
43
+ label: RELEASE_LABEL,
44
+ repo: target,
45
+ })
46
+
47
+ if (outcome.json === undefined) return undefined
48
+
49
+ return issue_release.open_release_of(outcome.json) ?? NONE
50
+ }
51
+
52
+ // The new release Issue's number, or `undefined` when the create call failed. Never `auto-ok`: the
53
+ // labels are `RELEASE_LABELS`, decided here rather than by `issue_auto_ok`, which refuses the label too.
54
+ async function file_release(target: string): Promise<number | undefined> {
55
+ repository_labels.ensure_labels(target)
56
+ const request = git_gh_issue_write.issue_create_request({
57
+ title: issue_release.title_of(target),
58
+ body: issue_release.body_of(target),
59
+ labels: issue_release.RELEASE_LABELS,
60
+ repo: target,
61
+ })
62
+
63
+ try {
64
+ const url = await git_gh_exec.exec_gh_api(request)
65
+ const issue_number = Number(github_issue_url.parse(url)?.issue_number) || undefined
66
+
67
+ if (issue_number === undefined) console.error(`✖ the release number is unreadable: ${url}`)
68
+
69
+ return issue_number
70
+ } catch (error) {
71
+ console.error(`✖ the release Issue could not be filed: ${error_text.message_of(error)}`)
72
+
73
+ return undefined
74
+ }
75
+ }
76
+
77
+ // An unreadable listing files nothing: a second release Issue beside one the listing failed to show
78
+ // would split the blockers between two releases.
79
+ async function release_of(target: string): Promise<ReleaseIssue | undefined> {
80
+ const open = await find_open(target)
81
+
82
+ if (open === undefined) {
83
+ console.error(`✖ the open ${RELEASE_LABEL} Issues of ${target} could not be listed`)
84
+
85
+ return undefined
86
+ }
87
+
88
+ if (open !== NONE) return { issue_number: open, is_filed: false }
89
+ const filed = await file_release(target)
90
+
91
+ return filed === undefined ? undefined : { issue_number: filed, is_filed: true }
92
+ }
93
+
94
+ function linked_line(release: ReleaseIssue, issue_number: number, target: string): string {
95
+ const how = release.is_filed ? 'filed' : 'open'
96
+ const release_cite = session_cite.issue(release.issue_number, undefined, target)
97
+
98
+ return `release: ${release_cite} (${how}) is blocked by ${session_cite.issue(issue_number, undefined, target)}`
99
+ }
100
+
101
+ function unlinked_line(issue_number: number, blocked: string, target: string): string {
102
+ const blocker = session_cite.issue(issue_number, undefined, target)
103
+
104
+ return `✖ ${blocker} could not be recorded as a blocker of ${session_cite.issue(blocked, undefined, target)}`
105
+ }
106
+
107
+ // Whether Issue `issue_number` of `target` now blocks the release Issue. Every outcome is printed.
108
+ async function link(issue_number: number, target: string): Promise<boolean> {
109
+ const release = await release_of(target)
110
+
111
+ if (release === undefined) return false
112
+ const blocked = String(release.issue_number)
113
+ const is_linked = await git_gh_issue_write.issue_add_blocked_by(blocked, String(issue_number))
114
+
115
+ if (is_linked) console.info(linked_line(release, issue_number, target))
116
+ else console.error(unlinked_line(issue_number, blocked, target))
117
+
118
+ return is_linked
119
+ }
120
+
121
+ // An unknown flag parses to no positionals, so it refuses the call like a missing number.
122
+ function positionals_of(argv: ReadonlyArray<string>): ReadonlyArray<string> {
123
+ return cli_flags.arguments_of(argv, {})?.positionals ?? []
124
+ }
125
+
126
+ // The number is the one positional: a missing, malformed or second one refuses the whole call.
127
+ function issue_number_of(argv: ReadonlyArray<string>): number | undefined {
128
+ const [issue_number, ...rest] = positionals_of(argv)
129
+ const is_single = rest.length === 0 && issue_number !== undefined
130
+
131
+ return is_single && issue_number_shape.ISSUE_NUMBER_PATTERN.test(issue_number)
132
+ ? Number(issue_number)
133
+ : undefined
134
+ }
135
+
136
+ async function run(argv: ReadonlyArray<string>): Promise<number> {
137
+ const issue_number = issue_number_of(argv)
138
+
139
+ if (issue_number === undefined) {
140
+ console.error(USAGE)
141
+
142
+ return FAILURE_EXIT_CODE
143
+ }
144
+
145
+ const current = await git_gh_command.repo_get_name_with_owner()
146
+
147
+ if (current === undefined) {
148
+ console.error(UNKNOWN_REPO_MESSAGE)
149
+
150
+ return FAILURE_EXIT_CODE
151
+ }
152
+
153
+ return (await link(issue_number, current)) ? SUCCESS_EXIT_CODE : FAILURE_EXIT_CODE
154
+ }
155
+
156
+ // `process.exitCode` rather than `process.exit()`, so the report on standard output drains first.
157
+ async function main(argv: ReadonlyArray<string>): Promise<void> {
158
+ process.exitCode = await run(argv)
159
+ }
160
+
161
+ const issue_release_cli = { link, run }
162
+
163
+ if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
164
+
165
+ export { issue_release_cli }