@joshuafolkken/kit 1.1784.0 → 1.2114.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (690) hide show
  1. package/.claude/agents/reviewer-verification.md +19 -0
  2. package/.claude/agents/reviewer.md +19 -0
  3. package/.claude/settings.json +5 -6
  4. package/.claude/skills/dependency-update/SKILL.md +9 -10
  5. package/.claude/skills/workflow-commands/SKILL.md +6 -6
  6. package/.claude/skills/workflow-commands/background-commands.md +8 -5
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +3 -1
  8. package/.claude/skills/workflow-commands/backlogrun-lanes.md +1 -1
  9. package/.claude/skills/workflow-commands/backlogrun-park.md +5 -2
  10. package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -3
  11. package/.claude/skills/workflow-commands/backlogrun-recovery.md +1 -1
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +3 -2
  13. package/.claude/skills/workflow-commands/backlogrun.md +1 -1
  14. package/.claude/skills/workflow-commands/chain-rule.md +41 -32
  15. package/.claude/skills/workflow-commands/delegation.md +6 -6
  16. package/.claude/skills/workflow-commands/entry-sequence.md +2 -2
  17. package/.claude/skills/workflow-commands/followup.md +7 -5
  18. package/.claude/skills/workflow-commands/fullrun-steps.md +6 -6
  19. package/.claude/skills/workflow-commands/fullrun.md +1 -1
  20. package/.claude/skills/workflow-commands/issue-comments.md +9 -4
  21. package/.claude/skills/workflow-commands/issue-fold-existing.md +2 -1
  22. package/.claude/skills/workflow-commands/kickoff.md +2 -2
  23. package/.claude/skills/workflow-commands/observation-filing.md +1 -1
  24. package/.claude/skills/workflow-commands/observation-ledger.md +6 -4
  25. package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -7
  26. package/.claude/skills/workflow-commands/prerequisite.md +3 -2
  27. package/.claude/skills/workflow-commands/retrospective.md +2 -2
  28. package/.claude/skills/workflow-commands/split-assessment.md +7 -5
  29. package/.codex/hooks.json +5 -5
  30. package/.github/actions/setup-pnpm/action.yml +9 -16
  31. package/.github/dependabot.yml +16 -0
  32. package/.github/workflows/auto-tag.yml +45 -0
  33. package/.github/workflows/ci.yml +155 -15
  34. package/.github/workflows/dependabot-auto-merge.yml +63 -4
  35. package/.github/workflows/production.yml +8 -0
  36. package/.github/workflows/publish.yml +59 -45
  37. package/.vscode/settings.json +19 -0
  38. package/CLAUDE.md +5 -12
  39. package/SECURITY.md +2 -2
  40. package/dist/CLAUDE.md +5 -12
  41. package/dist/commands/document-read-cli.js +2 -1
  42. package/dist/commands/document-section-main.js +2 -1
  43. package/dist/commands/read-set-cli.js +194 -134
  44. package/dist/commands/run-prep-main.js +9694 -10173
  45. package/dist/commands/run-step-cli.js +22138 -18285
  46. package/dist/hooks/audit-provision.js +23 -5
  47. package/dist/hooks/chunk-3GKE653K.js +6204 -0
  48. package/dist/hooks/chunk-45CJJOO7.js +1243 -0
  49. package/dist/hooks/{chunk-CWMBGKYW.js → chunk-5PM2JRGV.js} +2153 -856
  50. package/dist/hooks/{chunk-WR2KQAYZ.js → chunk-7SIUNQXK.js} +1207 -1470
  51. package/dist/hooks/{chunk-O2YBIDSI.js → chunk-CQD4LJE6.js} +1682 -1130
  52. package/dist/hooks/{chunk-VWWCFGWK.js → chunk-OPSRGWFU.js} +1 -1
  53. package/dist/hooks/{chunk-XGBNSWEI.js → chunk-UJ3FPMMM.js} +132 -49
  54. package/dist/hooks/chunk-VVNYJWEI.js +30 -0
  55. package/dist/hooks/chunk-Z6DQJKH3.js +2806 -0
  56. package/dist/hooks/codex-hook-adapter.js +8 -8
  57. package/dist/hooks/format-edited.js +4 -5
  58. package/dist/hooks/inputs.json +415 -389
  59. package/dist/hooks/pretool-guard.js +7 -6
  60. package/dist/hooks/session-lang.js +101 -258
  61. package/dist/hooks/stop-guard.js +1744 -2576
  62. package/dist/josh.js +7133 -6368
  63. package/dist/version/index.js +161 -1
  64. package/eslint/rules/comment-why-only.js +108 -0
  65. package/package.json +15 -8
  66. package/prompts/coding-standards.md +1 -1
  67. package/prompts/collaboration-workflow/file-edits.md +14 -11
  68. package/prompts/collaboration-workflow/issue-citation.md +0 -4
  69. package/prompts/collaboration-workflow/issue-template.md +40 -21
  70. package/prompts/collaboration-workflow/lane-instructions.md +3 -1
  71. package/prompts/collaboration-workflow/measurement.md +8 -1
  72. package/prompts/collaboration-workflow/operating-rules.md +11 -2
  73. package/prompts/collaboration-workflow/output-bounds.md +6 -2
  74. package/prompts/collaboration-workflow/plan-comment.md +1 -1
  75. package/prompts/collaboration-workflow/principles.md +9 -0
  76. package/prompts/collaboration-workflow/residency.md +3 -2
  77. package/prompts/collaboration-workflow/rule-delivery.md +13 -1
  78. package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
  79. package/prompts/collaboration-workflow/wip-cap.md +3 -1
  80. package/prompts/review-rubric.md +8 -0
  81. package/prompts/review.md +31 -22
  82. package/prompts/testing-guide.md +1 -0
  83. package/scripts/agent/agent-argv.ts +14 -16
  84. package/scripts/agent/agent-provider.ts +138 -0
  85. package/scripts/agent/agent-role-profile.ts +108 -156
  86. package/scripts/agent/agent-safe-text.ts +20 -5
  87. package/scripts/agent/api-usage-limit.ts +65 -0
  88. package/scripts/agent/claude-agent-argv.ts +19 -9
  89. package/scripts/agent/codex-agent-argv.ts +118 -22
  90. package/scripts/agent/usage-limit-reset.ts +179 -0
  91. package/scripts/auth/claude-token-output.ts +2 -2
  92. package/scripts/auto-ok/auto-ok-author.ts +53 -0
  93. package/scripts/auto-ok/auto-ok-cli.ts +20 -9
  94. package/scripts/backlog/backlog-defect-priority.ts +1 -1
  95. package/scripts/backlog/backlog-drive-cli.ts +6 -1
  96. package/scripts/backlog/backlog-drive-hold.ts +3 -3
  97. package/scripts/backlog/backlog-drive-idle.ts +10 -0
  98. package/scripts/backlog/backlog-drive-launch-pass.ts +90 -0
  99. package/scripts/backlog/backlog-drive-launch.ts +8 -2
  100. package/scripts/backlog/backlog-drive-named-offer.ts +73 -30
  101. package/scripts/backlog/backlog-drive-named.ts +28 -7
  102. package/scripts/backlog/backlog-drive-paused.ts +5 -4
  103. package/scripts/backlog/backlog-drive-restore.ts +11 -3
  104. package/scripts/backlog/backlog-drive.ts +21 -60
  105. package/scripts/backlog/backlog-gate-scope.ts +61 -0
  106. package/scripts/backlog/backlog-measure-close.ts +112 -0
  107. package/scripts/backlog/backlog-next.ts +39 -49
  108. package/scripts/backlog/backlog-occupied.ts +2 -2
  109. package/scripts/backlog/backlog-overlap.ts +42 -8
  110. package/scripts/backlog/backlog-plan-cli.ts +4 -1
  111. package/scripts/backlog/backlog-plan-comment.ts +81 -0
  112. package/scripts/backlog/backlog-plan-read.ts +19 -6
  113. package/scripts/backlog/backlog-pool.ts +50 -12
  114. package/scripts/backlog/backlog-rank.ts +60 -13
  115. package/scripts/backlog/backlog-stalled-detect.ts +2 -1
  116. package/scripts/backlog/backlog-waves.ts +17 -2
  117. package/scripts/backlog/backlogrun-launch.ts +7 -4
  118. package/scripts/cost-runtime/context-cut-payback.ts +27 -25
  119. package/scripts/cost-runtime/cost-cli.ts +37 -16
  120. package/scripts/cost-runtime/cost-pricing.ts +9 -0
  121. package/scripts/cost-runtime/cost-verdict.ts +4 -1
  122. package/scripts/delegation/delegation-policy.ts +2 -2
  123. package/scripts/delegation/duplicate-read-guard.ts +1 -0
  124. package/scripts/delegation/investigation-guard.ts +14 -2
  125. package/scripts/delegation/investigation-reads.ts +45 -23
  126. package/scripts/dependabot/dependabot-cooldown.ts +3 -2
  127. package/scripts/discovery/repo-party.ts +80 -20
  128. package/scripts/discovery/session-owner-pin.ts +51 -0
  129. package/scripts/document/capped-print.ts +1 -1
  130. package/scripts/document/command-reference-line-budget.ts +42 -0
  131. package/scripts/document/document-byte-budget.ts +17 -7
  132. package/scripts/document/document-checks.ts +20 -0
  133. package/scripts/document/document-ratchet-check.ts +101 -0
  134. package/scripts/document/document-section.ts +1 -0
  135. package/scripts/document/entry-read-budget.ts +7 -3
  136. package/scripts/document/issue-citation-budget.ts +94 -0
  137. package/scripts/epic/epic-cli-argv.ts +2 -2
  138. package/scripts/epic/epic-fetch.ts +4 -2
  139. package/scripts/epic/epic-graph.ts +7 -2
  140. package/scripts/epic/epic-issue.ts +3 -1
  141. package/scripts/epic/epic-rank.ts +5 -0
  142. package/scripts/exports/unused-members-check.ts +62 -0
  143. package/scripts/exports/unused-members-cli.ts +6 -51
  144. package/scripts/followup/followup-ci-path.ts +67 -0
  145. package/scripts/followup/followup-coderabbit-retrigger.ts +261 -0
  146. package/scripts/followup/followup-coderabbit-wait.ts +13 -10
  147. package/scripts/followup/followup-failed-tests.ts +160 -0
  148. package/scripts/followup/followup-job-needs.ts +100 -0
  149. package/scripts/followup/followup-job-rerun.ts +303 -0
  150. package/scripts/followup/followup-main-move.ts +113 -0
  151. package/scripts/followup/git-followup-finish.ts +43 -11
  152. package/scripts/followup/git-followup-pending.ts +3 -3
  153. package/scripts/followup/git-followup-stages.ts +41 -11
  154. package/scripts/followup/git-pr-followup-checks.ts +55 -16
  155. package/scripts/followup/git-pr-followup-wrapup.ts +24 -5
  156. package/scripts/followup/git-pr-followup.ts +62 -27
  157. package/scripts/fresh-machine/fresh-machine-script.ts +5 -9
  158. package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +2 -2
  159. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +2 -2
  160. package/scripts/gate/busy-average.ts +34 -2
  161. package/scripts/gate/check-related-pinned.ts +43 -0
  162. package/scripts/gate/check-related-reuse.ts +64 -0
  163. package/scripts/gate/check-related-section.ts +57 -0
  164. package/scripts/gate/check-related-unplanned.ts +34 -0
  165. package/scripts/gate/check-related.ts +265 -0
  166. package/scripts/gate/command-memory.ts +1 -1
  167. package/scripts/gate/core-admission.ts +24 -6
  168. package/scripts/gate/core-budget-timing.ts +20 -6
  169. package/scripts/gate/core-budget.ts +40 -11
  170. package/scripts/gate/core-wait-record.ts +3 -2
  171. package/scripts/gate/core-wait.ts +25 -2
  172. package/scripts/gate/core-weights.ts +15 -7
  173. package/scripts/gate/gate-labels.ts +46 -0
  174. package/scripts/gate/gate-ledger.ts +14 -6
  175. package/scripts/gate/gate-plan.ts +103 -58
  176. package/scripts/gate/gate-report.ts +9 -7
  177. package/scripts/gate/gate-run-steps.ts +26 -3
  178. package/scripts/gate/gate-skip.ts +45 -6
  179. package/scripts/gate/gate-static-group.ts +60 -0
  180. package/scripts/gate/gate-steps.ts +2 -1
  181. package/scripts/gate/gate-tree.ts +4 -2
  182. package/scripts/gate/hook-gate-reuse.ts +19 -2
  183. package/scripts/gate/metrics-totals.ts +59 -0
  184. package/scripts/gate/scoped-green.ts +68 -15
  185. package/scripts/gate/since-green.ts +14 -6
  186. package/scripts/gate/structural-checks.ts +96 -0
  187. package/scripts/gate/verification-gate.ts +51 -16
  188. package/scripts/gate/verification-inputs.ts +21 -6
  189. package/scripts/gate/verification-tail.ts +52 -0
  190. package/scripts/gh/gh-author-association.ts +23 -2
  191. package/scripts/gh/git-ai-review-scan.ts +1 -1
  192. package/scripts/gh/git-gh-api-path.ts +12 -3
  193. package/scripts/gh/git-gh-comments-unreadable.ts +36 -0
  194. package/scripts/gh/git-gh-exec.ts +32 -2
  195. package/scripts/gh/git-gh-issue-read.ts +4 -2
  196. package/scripts/gh/git-gh-issue-rest.ts +1 -0
  197. package/scripts/gh/git-gh-issue-write.ts +8 -2
  198. package/scripts/gh/git-gh-issue.ts +12 -5
  199. package/scripts/gh/git-gh-pr-auto-merge.ts +13 -6
  200. package/scripts/gh/git-gh-pr-graphql-state.ts +56 -0
  201. package/scripts/gh/git-gh-pr-read.ts +74 -13
  202. package/scripts/gh/git-gh-pr-rest.ts +3 -1
  203. package/scripts/gh/git-gh-pr-snapshot.ts +22 -7
  204. package/scripts/gh/git-gh-pr-too-large.ts +20 -0
  205. package/scripts/gh/git-gh-pr.ts +21 -7
  206. package/scripts/gh/git-gh-retry.ts +141 -0
  207. package/scripts/gh/git-pr-ai-review.ts +15 -6
  208. package/scripts/gh/git-pr-checks-eval.ts +3 -0
  209. package/scripts/gh/git-pr-checks.ts +5 -5
  210. package/scripts/git/base-tree.ts +30 -0
  211. package/scripts/git/change-base.ts +4 -10
  212. package/scripts/git/changed-paths-sync.ts +63 -0
  213. package/scripts/git/changed-paths.ts +16 -1
  214. package/scripts/git/git-common-directory.ts +11 -1
  215. package/scripts/git/git-diff-reads.ts +66 -20
  216. package/scripts/git/git-error.ts +9 -2
  217. package/scripts/git/git-schemas.ts +13 -0
  218. package/scripts/git/git-worktree.ts +13 -0
  219. package/scripts/git/gone-branch.ts +4 -1
  220. package/scripts/git/main-merge-budget-conflict.ts +89 -0
  221. package/scripts/git/main-merge-guard.ts +55 -18
  222. package/scripts/git/main-merge-regenerate.ts +59 -25
  223. package/scripts/git/main-merge.ts +53 -5
  224. package/scripts/git/no-base-checkout.ts +127 -0
  225. package/scripts/git/stash/git-stash.ts +11 -2
  226. package/scripts/git/stash/stash-push-cli.ts +10 -0
  227. package/scripts/hooks/batch-guard.ts +40 -21
  228. package/scripts/hooks/edited-cspell.ts +37 -11
  229. package/scripts/hooks/format-edited-file.ts +22 -2
  230. package/scripts/hooks/lane-plan-guard.ts +50 -0
  231. package/scripts/hooks/pre-commit-lint-switch.ts +9 -0
  232. package/scripts/hooks/pre-commit-lint.ts +14 -1
  233. package/scripts/hooks/pre-push-related-switch.ts +10 -0
  234. package/scripts/hooks/pre-push-unit.ts +76 -10
  235. package/scripts/hooks/pretool-guard.ts +2 -0
  236. package/scripts/hooks/reserved-run.ts +14 -1
  237. package/scripts/hooks/run-hook.sh +23 -8
  238. package/scripts/hooks/step-zero-notice.ts +6 -1
  239. package/scripts/hooks/stop-actions.ts +3 -15
  240. package/scripts/hooks/stop-guard.ts +7 -6
  241. package/scripts/init/distributed-paths.ts +1 -0
  242. package/scripts/init/hook-command-rewrite.ts +5 -1
  243. package/scripts/init/hook-launch.ts +4 -2
  244. package/scripts/issue/aggregation-split.ts +52 -0
  245. package/scripts/issue/defect-origin-line.ts +19 -1
  246. package/scripts/issue/defect-rate-cli.ts +5 -102
  247. package/scripts/issue/defect-report.ts +4 -4
  248. package/scripts/issue/effect-audit-cli.ts +178 -0
  249. package/scripts/issue/effect-audit.ts +185 -0
  250. package/scripts/issue/expected-effect-lint.ts +64 -9
  251. package/scripts/issue/git-next-issues.ts +5 -0
  252. package/scripts/issue/issue-body-or-comment.ts +38 -4
  253. package/scripts/issue/issue-cite-cli.ts +1 -3
  254. package/scripts/issue/issue-classification.ts +1 -0
  255. package/scripts/issue/issue-closing-pr.ts +8 -1
  256. package/scripts/issue/issue-evidence-exit.ts +4 -2
  257. package/scripts/issue/issue-file-cap.ts +58 -0
  258. package/scripts/issue/issue-file-cli.ts +111 -38
  259. package/scripts/issue/issue-file-deferral.ts +52 -0
  260. package/scripts/issue/issue-file-fold.ts +29 -10
  261. package/scripts/issue/issue-file-interrupt.ts +85 -0
  262. package/scripts/issue/issue-file-lane-hint.ts +30 -0
  263. package/scripts/issue/issue-file.ts +43 -6
  264. package/scripts/issue/issue-labels.ts +19 -2
  265. package/scripts/issue/issue-lint-cli.ts +27 -2
  266. package/scripts/issue/issue-measured-cli.ts +13 -35
  267. package/scripts/issue/issue-measured-close.ts +58 -0
  268. package/scripts/issue/issue-not-before-label.ts +2 -2
  269. package/scripts/issue/issue-not-before.ts +4 -1
  270. package/scripts/issue/issue-priority-cli.ts +60 -0
  271. package/scripts/issue/issue-priority-raise.ts +55 -0
  272. package/scripts/issue/issue-priority.ts +174 -43
  273. package/scripts/issue/issue-rank.ts +21 -4
  274. package/scripts/issue/issue-read-cli.ts +32 -6
  275. package/scripts/issue/issue-read.ts +37 -12
  276. package/scripts/issue/issue-sample-gate.ts +95 -74
  277. package/scripts/issue/issue-sample-prime.ts +127 -0
  278. package/scripts/issue/issue-sample-required.ts +57 -0
  279. package/scripts/issue/issue-sample-source.ts +12 -11
  280. package/scripts/issue/issue-search.ts +124 -0
  281. package/scripts/issue/issue-state.ts +13 -1
  282. package/scripts/issue/issue-template-section.ts +43 -0
  283. package/scripts/issue/issue-watch-diff.ts +31 -1
  284. package/scripts/issue/issue-watch-hook.ts +11 -2
  285. package/scripts/issue/issue-watch.ts +55 -12
  286. package/scripts/issue/markdown-section.ts +1 -0
  287. package/scripts/issue/measure-declaration.ts +121 -0
  288. package/scripts/issue/measure-rerun-cli.ts +7 -70
  289. package/scripts/issue/plan-consumers-section.ts +22 -1
  290. package/scripts/issue/reproduction-measure.ts +3 -1
  291. package/scripts/issue/size-estimate.ts +90 -0
  292. package/scripts/issue/trusted-measure.ts +84 -0
  293. package/scripts/josh/command-usage.ts +3 -2
  294. package/scripts/josh/durable-state-migrate.ts +105 -0
  295. package/scripts/josh/durable-state.ts +112 -0
  296. package/scripts/josh/josh-aliases.ts +95 -0
  297. package/scripts/josh/josh-command-map.ts +1 -82
  298. package/scripts/josh/josh-commands-agent-hooks.ts +6 -6
  299. package/scripts/josh/josh-commands-ai.ts +5 -5
  300. package/scripts/josh/josh-commands-development.ts +59 -58
  301. package/scripts/josh/josh-commands-issue-write.ts +23 -4
  302. package/scripts/josh/josh-commands-issue.ts +32 -0
  303. package/scripts/josh/josh-commands-lane.ts +87 -4
  304. package/scripts/josh/josh-commands-lint.ts +16 -3
  305. package/scripts/josh/josh-commands-maintenance.ts +15 -0
  306. package/scripts/josh/josh-commands-review.ts +41 -6
  307. package/scripts/josh/josh-commands-ship.ts +56 -8
  308. package/scripts/josh/josh-commands-test-check.ts +80 -0
  309. package/scripts/josh/josh-commands-workflow.ts +1 -1
  310. package/scripts/josh/josh-environment-file.ts +43 -3
  311. package/scripts/josh/josh-in-process.ts +2 -2
  312. package/scripts/josh/josh-logic.ts +5 -3
  313. package/scripts/josh/josh-run.ts +19 -1
  314. package/scripts/josh/run-record-path.ts +15 -0
  315. package/scripts/josh/stamp-file.ts +11 -2
  316. package/scripts/lane/lane-adopt-cli.ts +98 -0
  317. package/scripts/lane/lane-adopt.ts +208 -0
  318. package/scripts/lane/lane-await.ts +5 -8
  319. package/scripts/lane/lane-baseline.ts +123 -0
  320. package/scripts/lane/lane-breakdown-cli.ts +64 -0
  321. package/scripts/lane/lane-breakdown-implement.ts +170 -0
  322. package/scripts/lane/lane-breakdown-laps.ts +107 -0
  323. package/scripts/lane/lane-breakdown-pinned.ts +76 -0
  324. package/scripts/lane/lane-breakdown-text.ts +145 -0
  325. package/scripts/lane/lane-breakdown.ts +239 -0
  326. package/scripts/lane/lane-check-stats.ts +29 -8
  327. package/scripts/lane/lane-child-invocation.ts +9 -2
  328. package/scripts/lane/lane-child-mark-keys.ts +12 -0
  329. package/scripts/lane/lane-child-marker.ts +20 -1
  330. package/scripts/lane/lane-ci-path-stats.ts +73 -0
  331. package/scripts/lane/lane-claim-stats.ts +84 -0
  332. package/scripts/lane/lane-close.ts +8 -3
  333. package/scripts/lane/lane-dispatch-log.ts +3 -3
  334. package/scripts/lane/lane-dispatch.ts +2 -2
  335. package/scripts/lane/lane-gap-stats.ts +7 -6
  336. package/scripts/lane/lane-guard-policy.ts +7 -1
  337. package/scripts/lane/lane-implement-stats.ts +207 -0
  338. package/scripts/lane/lane-implement-subagents.ts +90 -0
  339. package/scripts/lane/lane-investigation-switch.ts +16 -0
  340. package/scripts/lane/lane-ledger-kind.ts +31 -0
  341. package/scripts/lane/lane-ledger-schema-ship.ts +49 -0
  342. package/scripts/lane/lane-ledger-schema.ts +119 -36
  343. package/scripts/lane/lane-ledger-write.ts +257 -0
  344. package/scripts/lane/lane-ledger.ts +31 -177
  345. package/scripts/lane/lane-load.ts +1 -1
  346. package/scripts/lane/lane-measure-cli.ts +176 -59
  347. package/scripts/lane/lane-net-read.ts +44 -0
  348. package/scripts/lane/lane-net-time.ts +212 -0
  349. package/scripts/lane/lane-open.ts +16 -7
  350. package/scripts/lane/lane-output.ts +2 -4
  351. package/scripts/lane/lane-overrun-prompt.ts +147 -0
  352. package/scripts/lane/lane-overrun.ts +274 -0
  353. package/scripts/lane/lane-paths.ts +24 -1
  354. package/scripts/lane/lane-pause-cli.ts +4 -1
  355. package/scripts/lane/lane-paused-spans.ts +97 -0
  356. package/scripts/lane/lane-plan-check.ts +207 -0
  357. package/scripts/lane/lane-plan-cli.ts +41 -0
  358. package/scripts/lane/lane-plan.ts +144 -0
  359. package/scripts/lane/lane-registry.ts +14 -1
  360. package/scripts/lane/lane-relaunch.ts +1 -1
  361. package/scripts/lane/lane-round-one-stats.ts +51 -0
  362. package/scripts/lane/lane-sampler.ts +23 -4
  363. package/scripts/lane/lane-session-action.ts +93 -18
  364. package/scripts/lane/lane-session-broker.ts +49 -21
  365. package/scripts/lane/lane-session-reread-main.ts +14 -0
  366. package/scripts/lane/lane-session-reread.ts +51 -0
  367. package/scripts/lane/lane-ship-lap-stats.ts +74 -0
  368. package/scripts/lane/lane-sleep.ts +58 -0
  369. package/scripts/lane/lane-spent.ts +1 -1
  370. package/scripts/lane/lane-split-stats.ts +28 -0
  371. package/scripts/lane/lane-stage-stats.ts +13 -1
  372. package/scripts/lane/lane-state.ts +41 -9
  373. package/scripts/lane/lane-stats-tables.ts +58 -0
  374. package/scripts/lane/lane-stats.ts +21 -5
  375. package/scripts/lane/lane-stop-stats.ts +51 -19
  376. package/scripts/lane/lane-tail-stats.ts +32 -0
  377. package/scripts/lane/lane-transcript-calls.ts +67 -10
  378. package/scripts/lane/lane-transcript-stats.ts +44 -12
  379. package/scripts/lane/lane-value-cell.ts +72 -0
  380. package/scripts/lane/lane-value.ts +118 -0
  381. package/scripts/lane/lane-withdraw-closed.ts +124 -0
  382. package/scripts/lane/lane-withdraw.ts +108 -31
  383. package/scripts/lane/lane-yield.ts +85 -0
  384. package/scripts/lane/openai-lane-ship.ts +12 -11
  385. package/scripts/lane/openai-lane-supervisor-decision.ts +6 -8
  386. package/scripts/lane/openai-lane-supervisor-owner.ts +5 -8
  387. package/scripts/lane/openai-lane-supervisor.ts +5 -4
  388. package/scripts/lib/poll.ts +38 -9
  389. package/scripts/lib/settled-together.ts +10 -0
  390. package/scripts/lib/shell-quote.ts +21 -0
  391. package/scripts/lib/token-shape.ts +111 -0
  392. package/scripts/lint/eslint-daemon-sources.ts +79 -0
  393. package/scripts/lint/eslint-daemon.ts +45 -6
  394. package/scripts/lint/eslint-warm-cli.ts +7 -0
  395. package/scripts/lint/eslint-warm.ts +66 -0
  396. package/scripts/lint/import-graph.ts +141 -11
  397. package/scripts/lint/lint-gate-scope.ts +2 -2
  398. package/scripts/lint/lint-parallel.ts +54 -6
  399. package/scripts/lint/lint-related.ts +154 -33
  400. package/scripts/lint/rename-cli.ts +179 -0
  401. package/scripts/lint/rename-identifier.ts +192 -0
  402. package/scripts/lint/type-only-imports.ts +58 -0
  403. package/scripts/notify/telegram-notify.ts +12 -3
  404. package/scripts/observations/observation-record.ts +42 -16
  405. package/scripts/observations/observations-flush.ts +32 -9
  406. package/scripts/overrides/overrides-check.ts +9 -1
  407. package/scripts/release/release-approval-prune.ts +7 -1
  408. package/scripts/repo/required-checks-logic.ts +4 -1
  409. package/scripts/repo/ruleset-check.ts +4 -3
  410. package/scripts/report/markdown-shape.ts +28 -0
  411. package/scripts/report/report-format-reference.ts +15 -1
  412. package/scripts/report/report-labels.ts +12 -1
  413. package/scripts/report/report-lint-child-summary.ts +94 -0
  414. package/scripts/report/report-lint-cli.ts +26 -7
  415. package/scripts/report/report-lint.ts +2 -20
  416. package/scripts/review/prose-stale-cli.ts +88 -0
  417. package/scripts/review/prose-stale-scan.ts +152 -0
  418. package/scripts/review/review-attest.ts +73 -23
  419. package/scripts/review/review-brief-cli.ts +68 -19
  420. package/scripts/review/review-brief-paths.ts +22 -0
  421. package/scripts/review/review-brief.ts +14 -7
  422. package/scripts/review/review-comment-carry.ts +47 -0
  423. package/scripts/review/review-comment-round.ts +85 -22
  424. package/scripts/review/review-finding-ledger.ts +109 -7
  425. package/scripts/review/review-finding-text.ts +43 -0
  426. package/scripts/review/review-interaction.ts +11 -0
  427. package/scripts/review/review-lane-handover.ts +68 -0
  428. package/scripts/review/review-lint-cli.ts +57 -0
  429. package/scripts/review/review-lint-findings.ts +92 -0
  430. package/scripts/review/review-lint-sections.ts +80 -0
  431. package/scripts/review/review-lint.ts +221 -0
  432. package/scripts/review/review-prior-findings.ts +102 -0
  433. package/scripts/review/review-readers-scan.ts +4 -2
  434. package/scripts/review/review-record-cli.ts +177 -54
  435. package/scripts/review/review-record-code-round.ts +55 -0
  436. package/scripts/review/review-record-comment.ts +60 -0
  437. package/scripts/review/review-record-interaction.ts +35 -0
  438. package/scripts/review/review-record-pinned.ts +108 -0
  439. package/scripts/review/review-record.ts +25 -1
  440. package/scripts/review/review-reviewed-tree.ts +307 -0
  441. package/scripts/review/review-round-one-closure.ts +62 -0
  442. package/scripts/review/review-round-reuse.ts +106 -0
  443. package/scripts/review/review-round2-cli.ts +91 -29
  444. package/scripts/review/review-round2-skip-comment.ts +55 -0
  445. package/scripts/review/review-round2.ts +24 -8
  446. package/scripts/review/review-stamps.ts +7 -3
  447. package/scripts/review/review-stop-log.ts +20 -6
  448. package/scripts/review/review-stops-cli.ts +2 -1
  449. package/scripts/review/review-submit-cli.ts +101 -0
  450. package/scripts/rules/agent-model.ts +1 -1
  451. package/scripts/rules/bash-triggers.ts +3 -3
  452. package/scripts/rules/concise-reply.ts +88 -0
  453. package/scripts/rules/credential-body.ts +77 -0
  454. package/scripts/rules/decision-oracle.ts +1 -1
  455. package/scripts/rules/delivered-rules.ts +36 -17
  456. package/scripts/rules/destructive-command.ts +3 -11
  457. package/scripts/rules/direct-issue-comment.ts +34 -12
  458. package/scripts/rules/direct-issue-read.ts +191 -0
  459. package/scripts/rules/direct-pr-create.ts +4 -24
  460. package/scripts/rules/early-heartbeat.ts +2 -0
  461. package/scripts/rules/edit-tool.ts +27 -0
  462. package/scripts/rules/file-edit-rows.ts +17 -0
  463. package/scripts/rules/file-rewrite.ts +146 -0
  464. package/scripts/rules/firing-point.ts +3 -2
  465. package/scripts/rules/gh-api.ts +128 -7
  466. package/scripts/rules/gh-repo-selector.ts +84 -0
  467. package/scripts/rules/git-force.ts +2 -2
  468. package/scripts/rules/guard-remedy.ts +14 -5
  469. package/scripts/rules/implementation-cut.ts +61 -28
  470. package/scripts/rules/investigator-foreground.ts +231 -0
  471. package/scripts/rules/issue-citation.ts +15 -60
  472. package/scripts/rules/issue-comments.ts +9 -4
  473. package/scripts/rules/josh-git-bare.ts +1 -1
  474. package/scripts/rules/lane-background.ts +41 -13
  475. package/scripts/rules/lane-direct-tool.ts +107 -9
  476. package/scripts/rules/lane-interactive-ask.ts +4 -1
  477. package/scripts/rules/lane-park.ts +4 -2
  478. package/scripts/rules/lane-spilled-read.ts +90 -0
  479. package/scripts/rules/lane-split-park.ts +1 -1
  480. package/scripts/rules/lane-switch-main.ts +4 -4
  481. package/scripts/rules/last-prompt.ts +20 -47
  482. package/scripts/rules/oracle-consulted.ts +1 -1
  483. package/scripts/rules/permission-guards.ts +5 -1
  484. package/scripts/rules/piped-verification-shapes.ts +110 -0
  485. package/scripts/rules/piped-verification.ts +67 -17
  486. package/scripts/rules/poll-loop.ts +72 -9
  487. package/scripts/rules/pr-merge.ts +5 -5
  488. package/scripts/rules/pre-gate-cut.ts +3 -3
  489. package/scripts/rules/protected-files.ts +88 -24
  490. package/scripts/rules/reply-language.ts +3 -17
  491. package/scripts/rules/reply-prose.ts +34 -0
  492. package/scripts/rules/repo-admin.ts +132 -0
  493. package/scripts/rules/reviewer-foreground.ts +88 -0
  494. package/scripts/rules/round-one-check-related.ts +120 -0
  495. package/scripts/rules/rule-body-guard.ts +5 -15
  496. package/scripts/rules/rule-value-cache.ts +53 -5
  497. package/scripts/rules/rule-value-candidates.ts +84 -0
  498. package/scripts/rules/rule-value-cli.ts +59 -11
  499. package/scripts/rules/rule-value.ts +17 -4
  500. package/scripts/rules/run-tail-rule.ts +1 -1
  501. package/scripts/rules/sed-in-place.ts +196 -0
  502. package/scripts/rules/shell-segments.ts +10 -2
  503. package/scripts/rules/stop-rule-rows.ts +1 -13
  504. package/scripts/rules/stop-rules.ts +33 -58
  505. package/scripts/rules/test-declared-commit.ts +1 -1
  506. package/scripts/rules/third-party-write.ts +110 -23
  507. package/scripts/rules/timed-rerun.ts +1 -1
  508. package/scripts/rules/turn-filings.ts +90 -0
  509. package/scripts/rules/worktree-guard.ts +22 -7
  510. package/scripts/run/board/run-board-ending-reason.ts +6 -2
  511. package/scripts/run/board/run-board-fit.ts +24 -1
  512. package/scripts/run/board/run-board-found.ts +134 -0
  513. package/scripts/run/board/run-board-header.ts +8 -0
  514. package/scripts/run/board/run-board-labels.ts +11 -1
  515. package/scripts/run/board/run-board-lane-time.ts +1 -0
  516. package/scripts/run/board/run-board-link.ts +15 -2
  517. package/scripts/run/board/run-board-notes.ts +7 -1
  518. package/scripts/run/board/run-board-operation.ts +4 -2
  519. package/scripts/run/board/run-board-phase.ts +2 -5
  520. package/scripts/run/board/run-board-plan.ts +1 -1
  521. package/scripts/run/board/run-board-read.ts +46 -1
  522. package/scripts/run/board/run-board-reason.ts +20 -8
  523. package/scripts/run/board/run-board-render-checks.ts +3 -2
  524. package/scripts/run/board/run-board-render-drawn.ts +11 -0
  525. package/scripts/run/board/run-board-render-found.ts +157 -0
  526. package/scripts/run/board/run-board-render-lead.ts +9 -0
  527. package/scripts/run/board/run-board-render-legend.ts +19 -0
  528. package/scripts/run/board/run-board-render-tail.ts +1 -1
  529. package/scripts/run/board/run-board-render.ts +82 -18
  530. package/scripts/run/board/run-board-spin.ts +1 -3
  531. package/scripts/run/board/run-board-status.ts +2 -0
  532. package/scripts/run/board/run-board-tick.ts +39 -10
  533. package/scripts/run/carry/run-carry-ended.ts +3 -2
  534. package/scripts/run/carry/run-carry.ts +3 -2
  535. package/scripts/run/cut/run-cut-cli.ts +33 -133
  536. package/scripts/run/cut/run-cut-digest.ts +152 -0
  537. package/scripts/run/cut/run-cut-handoff.ts +52 -8
  538. package/scripts/run/cut/run-cut-report.ts +24 -3
  539. package/scripts/run/cut/run-cut-resume.ts +129 -0
  540. package/scripts/run/cut/run-cut-review.ts +105 -0
  541. package/scripts/run/cut/run-cut.ts +18 -7
  542. package/scripts/run/detached-launch.ts +1 -1
  543. package/scripts/run/entry/run-entry-cli.ts +88 -19
  544. package/scripts/run/entry/run-entry-spill.ts +83 -0
  545. package/scripts/run/entry/run-entry-stop.ts +5 -1
  546. package/scripts/run/entry/run-entry-trust.ts +91 -0
  547. package/scripts/run/event/run-event-baseline.ts +56 -0
  548. package/scripts/run/event/run-event-filed.ts +9 -3
  549. package/scripts/run/event/run-event-overrun.ts +197 -0
  550. package/scripts/run/event/run-event-render.ts +4 -0
  551. package/scripts/run/event/run-event-stream.ts +25 -3
  552. package/scripts/run/hold/run-stop-notify.ts +3 -8
  553. package/scripts/run/merge/run-merge-cap.ts +57 -0
  554. package/scripts/run/merge/run-merge-cli.ts +66 -23
  555. package/scripts/run/merge/run-merge-outcome.ts +2 -0
  556. package/scripts/run/merge/run-merge-ship.ts +13 -3
  557. package/scripts/run/merge/run-merge-signals.ts +40 -23
  558. package/scripts/run/merge/run-merge-steps.ts +56 -36
  559. package/scripts/run/merge/run-merge-usage-limit.ts +53 -0
  560. package/scripts/run/merge/run-merge-withdrawn.ts +53 -0
  561. package/scripts/run/merge/run-merge.ts +41 -14
  562. package/scripts/run/review/run-review-cli.ts +306 -20
  563. package/scripts/run/review/run-review-early-push.ts +121 -0
  564. package/scripts/run/review/run-review-join-read.ts +94 -0
  565. package/scripts/run/review/run-review-pinned-accepted.ts +126 -0
  566. package/scripts/run/review/run-review-pinned-join.ts +216 -0
  567. package/scripts/run/review/run-review-pinned-steps.ts +383 -0
  568. package/scripts/run/review/run-review-pinned-tree.ts +37 -0
  569. package/scripts/run/review/run-review-pinned.ts +53 -0
  570. package/scripts/run/review/run-review-steps.ts +70 -34
  571. package/scripts/run/review/run-review.ts +26 -6
  572. package/scripts/run/run-parent-cut-hook.ts +3 -4
  573. package/scripts/run/run-prep.ts +1 -0
  574. package/scripts/run/run-stage-read.ts +2 -6
  575. package/scripts/run/run-step-cli.ts +17 -5
  576. package/scripts/run/run-step-lane-plan.ts +27 -0
  577. package/scripts/run/run-step-section.ts +26 -7
  578. package/scripts/run/run-step.ts +5 -2
  579. package/scripts/run/ship/run-ship-args.ts +19 -0
  580. package/scripts/run/ship/run-ship-brokered-review.ts +106 -0
  581. package/scripts/run/ship/run-ship-cli.ts +131 -39
  582. package/scripts/run/ship/run-ship-conflict-probe.ts +59 -0
  583. package/scripts/run/ship/run-ship-detach.ts +10 -4
  584. package/scripts/run/ship/run-ship-handover.ts +106 -0
  585. package/scripts/run/ship/run-ship-infra-retry.ts +16 -1
  586. package/scripts/run/ship/run-ship-lap.ts +63 -0
  587. package/scripts/run/ship/run-ship-next.ts +27 -26
  588. package/scripts/run/ship/run-ship-overlap.ts +8 -3
  589. package/scripts/run/ship/run-ship-place.ts +9 -2
  590. package/scripts/run/ship/run-ship-planned.ts +92 -0
  591. package/scripts/run/ship/run-ship-pre-detach-pinned.ts +197 -0
  592. package/scripts/run/ship/run-ship-pre-detach-timed.ts +7 -8
  593. package/scripts/run/ship/run-ship-pre-detach.ts +77 -23
  594. package/scripts/run/ship/run-ship-preflight.ts +16 -4
  595. package/scripts/run/ship/run-ship-probe.ts +23 -9
  596. package/scripts/run/ship/run-ship-relaunch-cap.ts +43 -7
  597. package/scripts/run/ship/run-ship-relaunch.ts +51 -0
  598. package/scripts/run/ship/run-ship-return.ts +103 -29
  599. package/scripts/run/ship/run-ship-review-reason.ts +24 -0
  600. package/scripts/run/ship/run-ship-review-steps.ts +230 -59
  601. package/scripts/run/ship/run-ship-review.ts +171 -51
  602. package/scripts/run/ship/run-ship-reviewer.ts +138 -42
  603. package/scripts/run/ship/run-ship-scoped.ts +39 -10
  604. package/scripts/run/ship/run-ship-stage.ts +49 -13
  605. package/scripts/run/ship/run-ship-steps.ts +24 -4
  606. package/scripts/run/ship/run-ship-stop-cause.ts +43 -2
  607. package/scripts/run/ship/run-ship-stop-context.ts +50 -13
  608. package/scripts/run/ship/run-ship-sync.ts +171 -30
  609. package/scripts/run/ship/run-ship-synced-scope.ts +178 -0
  610. package/scripts/run/ship/run-ship-wait-cli.ts +145 -0
  611. package/scripts/run/ship/run-ship-waiter.ts +114 -0
  612. package/scripts/run/ship/run-ship.ts +16 -2
  613. package/scripts/run/wake/run-wake-caffeinate.ts +48 -0
  614. package/scripts/run/wake/run-wake-cli.ts +6 -113
  615. package/scripts/run/wake/run-wake-code.ts +53 -11
  616. package/scripts/run/wake/run-wake-driver.ts +5 -3
  617. package/scripts/run/wake/run-wake-finish.ts +137 -0
  618. package/scripts/run/wake/run-wake-loop.ts +5 -3
  619. package/scripts/run/wake/run-wake-ports.ts +11 -3
  620. package/scripts/run/wake/run-wake-session.ts +2 -0
  621. package/scripts/run/wake/run-wake.ts +3 -2
  622. package/scripts/safe-chain/ci-installer-pin.ts +49 -8
  623. package/scripts/safe-chain/project-config.ts +3 -2
  624. package/scripts/security/secretlint-scan.ts +42 -9
  625. package/scripts/security/security-audit-provision-main.ts +9 -1
  626. package/scripts/security/security-audit-provision.ts +1 -1
  627. package/scripts/security/security-audit.ts +21 -1
  628. package/scripts/security/sonar-file.ts +10 -5
  629. package/scripts/split/split-assess.ts +12 -3
  630. package/scripts/split/split-early-notice.ts +116 -0
  631. package/scripts/split/split-measure.ts +20 -2
  632. package/scripts/split/split-resolution.ts +107 -0
  633. package/scripts/test/direct-importers.ts +185 -0
  634. package/scripts/test/pure-files-entries.ts +83 -0
  635. package/scripts/test/related-heavy-tests.ts +81 -0
  636. package/scripts/test/test-no-base.ts +88 -0
  637. package/scripts/test/test-pinned-cache-logic.ts +363 -0
  638. package/scripts/test/test-pinned-cache.ts +337 -0
  639. package/scripts/test/test-pinned-emit.ts +49 -0
  640. package/scripts/test/test-pinned-functions.ts +116 -0
  641. package/scripts/test/test-pinned-ledger.ts +80 -0
  642. package/scripts/test/test-pinned-logic.ts +208 -20
  643. package/scripts/test/test-pinned-main.ts +84 -18
  644. package/scripts/test/test-pinned-pool.ts +73 -0
  645. package/scripts/test/test-pinned-probe.ts +254 -0
  646. package/scripts/test/test-pinned-prune-logic.ts +118 -0
  647. package/scripts/test/test-pinned-reach.ts +194 -0
  648. package/scripts/test/test-pinned-record.ts +196 -0
  649. package/scripts/test/test-pinned-rewire.ts +148 -0
  650. package/scripts/test/test-pinned-spawn.ts +81 -0
  651. package/scripts/test/test-pinned-stage.ts +70 -0
  652. package/scripts/test/test-pinned.ts +258 -47
  653. package/scripts/test/test-reach-cli.ts +61 -0
  654. package/scripts/test/test-read-map.ts +35 -11
  655. package/scripts/test/test-read-recording.ts +17 -5
  656. package/scripts/test/test-read-trace.ts +26 -8
  657. package/scripts/test/test-red-logic.ts +46 -7
  658. package/scripts/test/test-red.ts +34 -14
  659. package/scripts/test/test-related-claim.ts +37 -0
  660. package/scripts/test/test-related-main.ts +4 -1
  661. package/scripts/test/test-related-moved.ts +91 -0
  662. package/scripts/test/test-related-record.ts +43 -23
  663. package/scripts/test/test-related-scope.ts +99 -34
  664. package/scripts/test/test-related-synced.ts +135 -0
  665. package/scripts/test/test-related-touched.ts +84 -0
  666. package/scripts/test/test-related.ts +167 -83
  667. package/scripts/test/test-unit-guard.ts +28 -5
  668. package/scripts/test/unit-durations.ts +41 -0
  669. package/scripts/test/unit-worker-share.ts +5 -4
  670. package/scripts/test/vitest-cache-directory.ts +19 -0
  671. package/scripts/test/vitest-cli-excludes.ts +14 -0
  672. package/scripts/test/vitest-failure-summary.ts +111 -0
  673. package/scripts/test/whole-suite-files.ts +12 -1
  674. package/scripts/time-runtime/time-batch-guard.ts +42 -4
  675. package/scripts/time-runtime/time-bundle-call.ts +1 -1
  676. package/scripts/time-runtime/time-bundles.ts +36 -5
  677. package/scripts/time-runtime/time-markers.ts +2 -2
  678. package/scripts/time-runtime/time-search-call.ts +38 -0
  679. package/scripts/time-runtime/time-shell.ts +1 -1
  680. package/scripts/time-runtime/time-transcript-line.ts +17 -5
  681. package/scripts/version/development-engines-verdict.ts +124 -0
  682. package/scripts/version/latest-corepack.ts +2 -0
  683. package/templates/gitignore +2 -0
  684. package/templates/workflows/ci.yml +41 -0
  685. package/dist/hooks/chunk-AZX4FGQ3.js +0 -207
  686. package/dist/hooks/chunk-PT5R6UJD.js +0 -7131
  687. package/dist/hooks/chunk-TUIFS5E7.js +0 -72
  688. package/dist/hooks/chunk-YCDOIR3I.js +0 -3456
  689. package/scripts/cost-runtime/context-cut-threshold.ts +0 -11
  690. package/scripts/rules/filing-cap.ts +0 -139
@@ -0,0 +1,30 @@
1
+ import { lane_net_read } from '#scripts/lane/lane-net-read'
2
+ import { issue_cite } from './issue-cite'
3
+ import { issue_priority } from './issue-priority'
4
+
5
+ // joshuafolkken/kit#5225: a refused `josh issue:file --found-during <N>` prints the causing-lane line
6
+ // filled from `josh lane:net <N>`, so the filer pastes it rather than running the command apart. Nothing
7
+ // is printed when the body already declares a causing lane, or the ledger holds no dispatch and merge of
8
+ // the lane yet.
9
+
10
+ async function lines_of(
11
+ found_during: string | undefined,
12
+ body: string,
13
+ ): Promise<ReadonlyArray<string>> {
14
+ if (found_during === undefined || issue_priority.lane_minutes(body) > 0) return []
15
+ const minutes = await lane_net_read.net_minutes_of(Number(found_during))
16
+
17
+ if (minutes === undefined) return []
18
+ const line = `${issue_priority.LANE_PREFIX} ${String(minutes)} 分(${issue_cite.plain(found_during)})`
19
+
20
+ return [
21
+ `↳ the causing lane from \`josh lane:net ${found_during}\`, to paste under \`## 背景\` when it caused this Issue:`,
22
+ line,
23
+ ]
24
+ }
25
+
26
+ const issue_file_lane_hint = {
27
+ lines_of,
28
+ }
29
+
30
+ export { issue_file_lane_hint }
@@ -36,6 +36,10 @@ interface FileArguments {
36
36
  labels: ReadonlyArray<string>
37
37
  repo: string | undefined
38
38
  distinct: ReadonlyArray<number>
39
+ // `--found-during <N>`: the work item the filing came from when it is not the checkout's own — a
40
+ // long lane the parent investigated, the Issue a prerequisite or an observation came out of. The
41
+ // filing cap counts per origin (`issue-file-cap.ts`); absent, the finder is read (`issue-file-fold.ts`).
42
+ found_during: string | undefined
39
43
  // `--over-cap`: the run is blocked by this filing, so the WIP cap does not hold it (`issue-wip.ts`).
40
44
  is_over_cap: boolean
41
45
  // `--no-auto-ok`: the Issue needs a person's judgement, so `auto-ok` is not applied (`issue-auto-ok.ts`).
@@ -43,6 +47,9 @@ interface FileArguments {
43
47
  // `--release`: the change reaches a consumer only once published, so the Issue is linked to the
44
48
  // repository's release Issue as a blocker (`issue-release-cli.ts`).
45
49
  is_release: boolean
50
+ // `--blocks-finder`: an interrupt the finder cannot go on without, so the finder is recorded as
51
+ // blocked by it (`issue-file-interrupt.ts`). An interrupt that blocks nobody omits it (`wip-cap.md`).
52
+ is_blocking_finder: boolean
46
53
  }
47
54
 
48
55
  const OPTIONS = {
@@ -51,9 +58,11 @@ const OPTIONS = {
51
58
  label: { type: 'string', multiple: true },
52
59
  repo: { type: 'string' },
53
60
  distinct: { type: 'string', multiple: true },
61
+ 'found-during': { type: 'string' },
54
62
  'over-cap': { type: 'boolean' },
55
63
  'no-auto-ok': { type: 'boolean' },
56
64
  release: { type: 'boolean' },
65
+ 'blocks-finder': { type: 'boolean' },
57
66
  } as const
58
67
 
59
68
  // The label a `--route` value names, or `undefined` when it names none — read against the route
@@ -95,15 +104,27 @@ function has_text(value: string | undefined): value is string {
95
104
  return value !== undefined && value.trim() !== ''
96
105
  }
97
106
 
98
- // The labelled half of the arguments, or `undefined` when a route or `--distinct` entry is not one the
99
- // command knows.
100
- function labelled_of(values: ParsedValues): Pick<FileArguments, 'route' | 'distinct'> | undefined {
107
+ // `--found-during 3423` or `#3423` → `'3423'`; `undefined` when absent, `false` when it names no single
108
+ // issue number, so a typo is refused rather than counted against no origin.
109
+ function found_during_of(value: string | undefined): string | undefined | false {
110
+ if (value === undefined) return undefined
111
+ const numbers = distinct_numbers([value])
112
+
113
+ return numbers?.length === 1 ? String(numbers[0]) : false
114
+ }
115
+
116
+ type Labelled = Pick<FileArguments, 'route' | 'distinct' | 'found_during'>
117
+
118
+ // The labelled half of the arguments, or `undefined` when a route, `--distinct` or `--found-during`
119
+ // entry is not one the command knows.
120
+ function labelled_of(values: ParsedValues): Labelled | undefined {
101
121
  const route = route_of(values)
102
122
  const distinct = distinct_numbers(values.distinct ?? [])
123
+ const found_during = found_during_of(values['found-during'])
103
124
 
104
- if (route === false || distinct === undefined) return undefined
125
+ if (route === false || distinct === undefined || found_during === false) return undefined
105
126
 
106
- return { route, distinct }
127
+ return { route, distinct, found_during }
107
128
  }
108
129
 
109
130
  function arguments_of(values: ParsedValues, title: string | undefined): FileArguments | undefined {
@@ -121,6 +142,7 @@ function arguments_of(values: ParsedValues, title: string | undefined): FileArgu
121
142
  is_over_cap: values['over-cap'] === true,
122
143
  is_auto_ok_opted_out: values['no-auto-ok'] === true,
123
144
  is_release: values.release === true,
145
+ is_blocking_finder: values['blocks-finder'] === true,
124
146
  }
125
147
  }
126
148
 
@@ -143,7 +165,7 @@ function is_undeclared_classification(label: string, body: string): boolean {
143
165
  // the body declares (`issue_classification.labels_for`, which merges case-insensitively), then any
144
166
  // extra `--label`, then `auto-ok` when the filing is judged in (`issue-auto-ok.ts`) and no `--label`
145
167
  // already named it, `not-before` while the body's start time is ahead (`issue-not-before-label.ts`), and
146
- // the declared priority's label unless a `--label` typed one (`issue-priority.ts`).
168
+ // the filed priority's label (the declaration, else its floor) unless a `--label` typed one (`issue-priority.ts`).
147
169
  // One request applies them all, so no label is a separate step to forget.
148
170
  function labels_of(args: FileArguments, body: string, is_auto_ok = false): ReadonlyArray<string> {
149
171
  const extra = args.labels.filter((label) => !is_undeclared_classification(label, body))
@@ -221,12 +243,27 @@ function unacknowledged(
221
243
  return candidates.filter((candidate) => !distinct.includes(candidate))
222
244
  }
223
245
 
246
+ // The candidates the filing has already answered: its `--distinct` numbers and, filing into this
247
+ // repository, its `--found-during` origin. The work the finding turned up during is never its duplicate,
248
+ // though a body citing it makes the scout name it (joshuafolkken/kit#4762). The origin is an Issue here,
249
+ // so in another repository the same number is an unrelated Issue the scout may rightly hold.
250
+ function acknowledged(
251
+ args: Pick<FileArguments, 'distinct' | 'found_during'>,
252
+ target: string,
253
+ current: string,
254
+ ): ReadonlyArray<number> {
255
+ if (args.found_during === undefined || !is_same_repository(target, current)) return args.distinct
256
+
257
+ return [...args.distinct, Number(args.found_during)]
258
+ }
259
+
224
260
  const issue_file = {
225
261
  parse,
226
262
  labels_of,
227
263
  origin_problem,
228
264
  triage_problem,
229
265
  unacknowledged,
266
+ acknowledged,
230
267
  is_same_repository,
231
268
  }
232
269
 
@@ -83,6 +83,9 @@ const ALREADY_DONE_LABEL = 'already-done'
83
83
  // closes such an Issue, so the merge reference a sweep reads is missing; this label is what tells the
84
84
  // run's own close from a person's, so every sweep counts it as merged (`issue-merged.ts`).
85
85
  const MEASURED_LABEL = 'measured'
86
+ // Rides beside `measured` when the measurement fell short of the expected effect it checked
87
+ // (`josh issue:measured --unmet`); `josh effect:audit` reads it as the mechanism to retire or shrink.
88
+ const MEASURED_UNMET_LABEL = 'measured:unmet'
86
89
  // Marks the Issue that tracks a repository's next release. An Issue whose
87
90
  // change reaches a consumer only once published is linked to it as a `blocked_by` blocker
88
91
  // (`josh issue:release`), so "merged but not yet released" is visible in the backlog. A run applies
@@ -255,6 +258,12 @@ const WORKFLOW_LABELS: ReadonlyArray<LabelDefinition> = [
255
258
  color: '6f42c1',
256
259
  description: 'Measurement-only — a run recorded the result and closed it',
257
260
  },
261
+ {
262
+ name: MEASURED_UNMET_LABEL,
263
+ color: '6f42c1',
264
+ description:
265
+ 'The measurement fell short of the expected effect — retire or shrink the mechanism',
266
+ },
258
267
  {
259
268
  name: DEFERRED_LABEL,
260
269
  color: 'd4c5f9',
@@ -345,9 +354,14 @@ function has_label_name(labels: ReadonlyArray<string>, wanted: string): boolean
345
354
  return label_name_of(labels, wanted) !== undefined
346
355
  }
347
356
 
348
- // Whether label names carry any park label (`PARKED_LABELS`), compared as `has_label_name` does.
357
+ // The park label (`PARKED_LABELS`) label names carry, compared as `has_label_name` does.
358
+ function parked_label_of(labels: ReadonlyArray<string>): string | undefined {
359
+ return [...PARKED_LABELS].find((label) => has_label_name(labels, label))
360
+ }
361
+
362
+ // Whether label names carry any park label (`PARKED_LABELS`).
349
363
  function has_parked_label(labels: ReadonlyArray<string>): boolean {
350
- return [...PARKED_LABELS].some((label) => has_label_name(labels, label))
364
+ return parked_label_of(labels) !== undefined
351
365
  }
352
366
 
353
367
  // Every workflow label this package manages. The label-reference scan
@@ -368,6 +382,7 @@ const ALL_LABELS: ReadonlySet<string> = new Set([
368
382
  NEEDS_HUMAN_REVIEW_LABEL,
369
383
  ALREADY_DONE_LABEL,
370
384
  MEASURED_LABEL,
385
+ MEASURED_UNMET_LABEL,
371
386
  DEFERRED_LABEL,
372
387
  PRIORITY_CRITICAL_LABEL,
373
388
  PRIORITY_HIGH_LABEL,
@@ -410,11 +425,13 @@ export {
410
425
  INTERRUPT_ROUTE_LABEL,
411
426
  label_name_of,
412
427
  MEASURED_LABEL,
428
+ MEASURED_UNMET_LABEL,
413
429
  NEEDS_DECISION_LABEL,
414
430
  NEEDS_HUMAN_REVIEW_LABEL,
415
431
  NOT_BEFORE_LABEL,
416
432
  NOT_DIRECTLY_RUNNABLE_LABELS,
417
433
  OTHER_CHANGE_LABEL,
434
+ parked_label_of,
418
435
  PARKED_LABELS,
419
436
  PLANNED_LABEL,
420
437
  PRIORITY_CRITICAL_LABEL,
@@ -1,15 +1,21 @@
1
1
  import { readFile } from 'node:fs/promises'
2
+ import { aggregation_split } from './aggregation-split'
2
3
  import { behavior_change_lint } from './behavior-change-lint'
3
4
  import { expected_effect_lint } from './expected-effect-lint'
4
5
  import { issue_classification } from './issue-classification'
5
6
  import { issue_lint } from './issue-lint'
6
7
  import { issue_not_before } from './issue-not-before'
8
+ import { issue_priority } from './issue-priority'
9
+ import { issue_template_section } from './issue-template-section'
10
+ import { measure_declaration } from './measure-declaration'
11
+ import { size_estimate } from './size-estimate'
7
12
 
8
13
  // `josh issue:lint <path>` — read an Issue body from a file and print `ok`, or every template problem
9
14
  // one per line, exiting non-zero. It reads a path rather than stdin so it can
10
15
  // lint a body written to a file before the `gh api … issues` call that files it. A body that declares
11
16
  // itself a behavior-change Issue is additionally held to the firing-point, baseline and reproduction
12
- // rules, and one that declares a run-time-shortening aim to the expected-effect estimate.
17
+ // rules, and one that declares a run-time-shortening aim to the expected-effect estimate. Every
18
+ // non-epic body declares its size estimate; the guide it is judged against is `issue:file`'s check.
13
19
 
14
20
  const SUCCESS_EXIT_CODE = 0
15
21
  const FAILURE_EXIT_CODE = 1
@@ -17,10 +23,23 @@ const OK_MESSAGE = 'ok'
17
23
  const NO_LABELS = 'none'
18
24
  const USAGE = 'Usage: josh issue:lint <path-to-issue-body>'
19
25
 
26
+ const MISSING_HEADING_PREFIX = 'missing heading: '
27
+
28
+ // A missing-heading problem followed by that section of the template, so the filer pastes it in rather
29
+ // than reopening `issue-template.md`; any other problem, or a heading the template lacks, is unchanged.
30
+ function with_template(problem: string): string {
31
+ if (!problem.startsWith(MISSING_HEADING_PREFIX)) return problem
32
+ const template = issue_template_section.section(problem.slice(MISSING_HEADING_PREFIX.length))
33
+
34
+ return template === undefined ? problem : `${problem}\n${template}`
35
+ }
36
+
20
37
  // Every problem a body has: the four base template headings it lacks, then the behavior-change and
21
38
  // expected-effect problems (each empty for an Issue that does not declare itself one).
22
39
  function problems(body: string): ReadonlyArray<string> {
23
- const missing = issue_lint.missing_headings(body).map((heading) => `missing heading: ${heading}`)
40
+ const missing = issue_lint
41
+ .missing_headings(body)
42
+ .map((heading) => `${MISSING_HEADING_PREFIX}${heading}`)
24
43
 
25
44
  return [
26
45
  ...missing,
@@ -28,7 +47,13 @@ function problems(body: string): ReadonlyArray<string> {
28
47
  ...expected_effect_lint.problems(body),
29
48
  ...issue_classification.problems(body),
30
49
  ...issue_not_before.problems(body),
50
+ ...measure_declaration.problems(body),
51
+ ...size_estimate.problems(body),
52
+ ...aggregation_split.problems(body),
53
+ issue_priority.order_problem(body),
31
54
  ]
55
+ .filter((problem) => problem !== undefined)
56
+ .map((problem) => with_template(problem))
32
57
  }
33
58
 
34
59
  function report(found: ReadonlyArray<string>, body: string): number {
@@ -1,48 +1,26 @@
1
1
  #!/usr/bin/env tsx
2
2
  import { fileURLToPath } from 'node:url'
3
- import { epic_close } from '#scripts/epic/epic-close'
4
- import { git_gh_command } from '#scripts/gh/git-gh-command'
5
3
  import { issue_evidence_exit } from '#scripts/issue/issue-evidence-exit'
6
- import { MEASURED_LABEL } from '#scripts/issue/issue-labels'
7
- import { session_cite } from '#scripts/issue/session-cite'
4
+ import { issue_measured_close } from '#scripts/issue/issue-measured-close'
8
5
 
9
6
  // `josh issue:measured <N> --evidence-file <path>` — the completion of a measurement-only Issue
10
7
  // (`issue-comments.md` → "A measurement-only Issue"): the result comment, the
11
- // `measured` label, the close and the `run:release`, in that order (`issue-evidence-exit.ts`).
12
- //
13
- // **The close is the run's own**: such an Issue changes no code, so no pull request's `closes #N`
14
- // can close it, and an OPEN child `run:merge` reads as `failed` and parks with `run:stalled`. A
15
- // CLOSED one it reads as `merged` (`run-merge.ts` → `classify_child`). The label goes on before the
16
- // close because it is what every sweep — `run:carry --end`, `run:tidy` — tells this close from a
17
- // person's by (`issue-merged.ts`); a close without it would be one they never count as merged.
8
+ // `measured` label, the close and the `run:release`, in that order (`issue-evidence-exit.ts`,
9
+ // `issue-measured-close.ts`). `--unmet` records that the measurement fell short of the expected
10
+ // effect, with the `measured:unmet` label `josh effect:audit` reads.
18
11
 
19
12
  const ARGV_OFFSET = 2
20
-
21
- async function apply_label(issue_number: string): Promise<boolean> {
22
- const write = await git_gh_command.issue_apply_label(issue_number, MEASURED_LABEL)
23
-
24
- if (!write.is_applied) console.error(`${MEASURED_LABEL} not applied: ${write.reason}`)
25
-
26
- return write.is_applied
27
- }
28
-
29
- // A closed measurement may be its epic's last child, and no `followup` runs for it — so the epic
30
- // auto-close is run here, through the one entry every child close takes (`epic-close.ts`).
31
- async function close_issue(issue_number: string): Promise<boolean> {
32
- const is_closed = await git_gh_command.issue_close(issue_number, undefined)
33
-
34
- if (is_closed) await epic_close.close_completed_epics({ issue_number, is_merged: true })
35
- else console.error(`Issue ${session_cite.issue(issue_number)} not closed`)
36
-
37
- return is_closed
38
- }
39
-
40
- async function label_and_close(issue_number: string): Promise<boolean> {
41
- return (await apply_label(issue_number)) && (await close_issue(issue_number))
42
- }
13
+ const UNMET_FLAG = '--unmet'
43
14
 
44
15
  async function run(argv: ReadonlyArray<string>): Promise<number> {
45
- return await issue_evidence_exit.run(argv, { command: 'issue:measured', finish: label_and_close })
16
+ const exit = argv.includes(UNMET_FLAG)
17
+ ? issue_measured_close.MEASURED_UNMET_EXIT
18
+ : issue_measured_close.MEASURED_EXIT
19
+
20
+ return await issue_evidence_exit.run(
21
+ argv.filter((argument) => argument !== UNMET_FLAG),
22
+ exit,
23
+ )
46
24
  }
47
25
 
48
26
  async function main(argv: ReadonlyArray<string>): Promise<void> {
@@ -0,0 +1,58 @@
1
+ import { epic_close } from '#scripts/epic/epic-close'
2
+ import { git_gh_command } from '#scripts/gh/git-gh-command'
3
+ import { issue_evidence_exit, type EvidenceExit } from '#scripts/issue/issue-evidence-exit'
4
+ import { MEASURED_LABEL, MEASURED_UNMET_LABEL } from '#scripts/issue/issue-labels'
5
+ import { session_cite } from '#scripts/issue/session-cite'
6
+
7
+ // The writes that complete a measurement-only Issue — the result comment, the `measured` label and
8
+ // the close — shared by `josh issue:measured` and `backlog:drive`'s declared measurement
9
+ // (`backlog-measure-close.ts`), out of the CLI so the drive imports no main guard.
10
+ //
11
+ // **The close is the run's own**: such an Issue changes no code, so no pull request's `closes #N`
12
+ // can close it, and an OPEN child `run:merge` reads as `failed` and parks with `run:stalled`. A
13
+ // CLOSED one it reads as `merged` (`run-merge.ts` → `classify_child`). The label goes on before the
14
+ // close because it is what every sweep — `run:carry --end`, `run:tidy` — tells this close from a
15
+ // person's by (`issue-merged.ts`); a close without it would be one they never count as merged.
16
+
17
+ async function apply_label(issue_number: string, label: string = MEASURED_LABEL): Promise<boolean> {
18
+ const write = await git_gh_command.issue_apply_label(issue_number, label)
19
+
20
+ if (!write.is_applied) console.error(`${label} not applied: ${write.reason}`)
21
+
22
+ return write.is_applied
23
+ }
24
+
25
+ // A closed measurement may be its epic's last child, and no `followup` runs for it — so the epic
26
+ // auto-close is run here, through the one entry every child close takes (`epic-close.ts`).
27
+ async function close_issue(issue_number: string): Promise<boolean> {
28
+ const is_closed = await git_gh_command.issue_close(issue_number, undefined)
29
+
30
+ if (is_closed) await epic_close.close_completed_epics({ issue_number, is_merged: true })
31
+ else console.error(`Issue ${session_cite.issue(issue_number)} not closed`)
32
+
33
+ return is_closed
34
+ }
35
+
36
+ async function label_and_close(issue_number: string): Promise<boolean> {
37
+ return (await apply_label(issue_number)) && (await close_issue(issue_number))
38
+ }
39
+
40
+ // A measurement that fell short carries `measured:unmet` too, put on first: the close is the last write.
41
+ async function mark_unmet_and_close(issue_number: string): Promise<boolean> {
42
+ return (
43
+ (await apply_label(issue_number, MEASURED_UNMET_LABEL)) && (await label_and_close(issue_number))
44
+ )
45
+ }
46
+
47
+ const COMMAND = 'issue:measured'
48
+ const MEASURED_EXIT: EvidenceExit = { command: COMMAND, finish: label_and_close }
49
+ const MEASURED_UNMET_EXIT: EvidenceExit = { command: COMMAND, finish: mark_unmet_and_close }
50
+
51
+ // The same writes for evidence composed in process, with no hold of its own to release.
52
+ async function close(issue_number: string, evidence: string): Promise<boolean> {
53
+ return await issue_evidence_exit.write({ issue_number, evidence }, MEASURED_EXIT)
54
+ }
55
+
56
+ const issue_measured_close = { MEASURED_EXIT, MEASURED_UNMET_EXIT, close }
57
+
58
+ export { issue_measured_close }
@@ -5,7 +5,7 @@ import { parse_json_array_or_undefined } from '#scripts/git/parse-json-array'
5
5
  import { error_text } from '#scripts/lib/error-message'
6
6
  import { has_label_name, NOT_BEFORE_LABEL, REPOSITORY_LABELS } from './issue-labels'
7
7
  import { issue_not_before } from './issue-not-before'
8
- import { issue_sample_gate } from './issue-sample-gate'
8
+ import { issue_sample_prime } from './issue-sample-prime'
9
9
  import { session_cite } from './session-cite'
10
10
 
11
11
  // joshuafolkken/kit#4079: the body's start-time declaration held an issue back from `backlog:next`,
@@ -126,7 +126,7 @@ async function sweep(
126
126
  const seen = new Set(scanned.map((issue) => issue.number))
127
127
  const labelled = await read_labelled()
128
128
 
129
- await issue_sample_gate.prime(labelled.map((issue) => issue.body))
129
+ await issue_sample_prime.prime(labelled.map((issue) => issue.body))
130
130
  await sync([...scanned, ...labelled.filter((issue) => !seen.has(issue.number))], now)
131
131
  }
132
132
 
@@ -13,7 +13,10 @@ const PREFIX = '- 実施可能日:'
13
13
  const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}Z$/u
14
14
  // What `toISOString` writes after the minutes the declaration spells.
15
15
  const ISO_TAIL = ':00.000Z'
16
- const MALFORMED = `\`${PREFIX}\` must be a UTC time written YYYY-MM-DDTHH:MMZ`
16
+ // The refusal ends in a line ready to paste (joshuafolkken/kit#5225); a far-future date, so the
17
+ // example never reads as already due.
18
+ const EXAMPLE = `${PREFIX} 2099-01-01T09:00Z`
19
+ const MALFORMED = `\`${PREFIX}\` must be a UTC time written YYYY-MM-DDTHH:MMZ\n${EXAMPLE}`
17
20
  const HEADING_MARKS = /^#{1,6}\s+/u
18
21
  // joshuafolkken/kit#4438: a start condition written as its own heading is never read — every reader
19
22
  // sees only the declaration line under the background heading — so the issue is offered at once.
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env tsx
2
+ import { fileURLToPath } from 'node:url'
3
+ import { issue_number_shape } from '#scripts/issue/issue-number-shape'
4
+ import { session_cite } from '#scripts/issue/session-cite'
5
+ import { issue_priority_raise, type RaiseResult } from './issue-priority-raise'
6
+
7
+ // `josh issue:priority <N>` — apply `priority:high` to an open issue whose body reached the high
8
+ // floor after filing, as a recurrence's appended cause-loss line does (joshuafolkken/kit#4960).
9
+
10
+ const SUCCESS_EXIT_CODE = 0
11
+ const FAILURE_EXIT_CODE = 1
12
+ const ARGV_OFFSET = 2
13
+ const USAGE = 'Usage: josh issue:priority <issue-number>'
14
+
15
+ const REPORTS: Readonly<Record<RaiseResult, string>> = {
16
+ raised: 'applied `priority:high` — its body reaches the high floor.',
17
+ labelled: 'already carries a priority label — left as it is.',
18
+ below: 'stays below the high floor — no label applied.',
19
+ unreadable: 'could not be read — no label applied.',
20
+ failed: 'reaches the high floor, but applying `priority:high` failed.',
21
+ }
22
+
23
+ const FAILURES: ReadonlySet<RaiseResult> = new Set(['unreadable', 'failed'])
24
+
25
+ function parse_number(argv: ReadonlyArray<string>): string | undefined {
26
+ const [first] = argv
27
+
28
+ if (first === undefined || argv.length !== 1) return undefined
29
+
30
+ return issue_number_shape.ISSUE_NUMBER_PATTERN.test(first) ? first : undefined
31
+ }
32
+
33
+ async function run(argv: ReadonlyArray<string>): Promise<number> {
34
+ const issue_number = parse_number(argv)
35
+
36
+ if (issue_number === undefined) {
37
+ console.error(USAGE)
38
+
39
+ return FAILURE_EXIT_CODE
40
+ }
41
+
42
+ const result = await issue_priority_raise.raise(issue_number)
43
+ const line = `Issue ${session_cite.issue(issue_number)} ${REPORTS[result]}`
44
+ const is_failure = FAILURES.has(result)
45
+
46
+ if (is_failure) console.error(line)
47
+ else console.info(line)
48
+
49
+ return is_failure ? FAILURE_EXIT_CODE : SUCCESS_EXIT_CODE
50
+ }
51
+
52
+ async function main(argv: ReadonlyArray<string>): Promise<void> {
53
+ process.exitCode = await run(argv)
54
+ }
55
+
56
+ const issue_priority_cli = { run }
57
+
58
+ if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
59
+
60
+ export { issue_priority_cli }
@@ -0,0 +1,55 @@
1
+ import { git_gh_command } from '#scripts/gh/git-gh-command'
2
+ import { issue_label_schema } from '#scripts/git/git-schemas'
3
+ import { parse_json_object_or_undefined } from '#scripts/git/parse-json-array'
4
+ import { z } from 'zod'
5
+ import { PRIORITY_HIGH_LABEL } from './issue-labels'
6
+ import { issue_priority } from './issue-priority'
7
+
8
+ // joshuafolkken/kit#4960: an open Issue's body can reach the high floor after it was filed — a
9
+ // recurrence appends a cause-loss line to it — and the body edit applies no label. This re-reads the
10
+ // body and applies `priority:high` once its floor is high, as `josh issue:file` would have.
11
+
12
+ type RaiseResult = 'raised' | 'labelled' | 'below' | 'unreadable' | 'failed'
13
+
14
+ const read_schema = z.object({
15
+ labels: z.array(issue_label_schema).optional(),
16
+ body: z.string().nullish(),
17
+ })
18
+
19
+ interface LabelsAndBody {
20
+ labels: ReadonlyArray<string>
21
+ body: string
22
+ }
23
+
24
+ async function read_issue(issue_number: string): Promise<LabelsAndBody | undefined> {
25
+ const raw = await git_gh_command.issue_get_labels_and_body(issue_number)
26
+ const parsed = raw === undefined ? undefined : parse_json_object_or_undefined(raw, read_schema)
27
+
28
+ if (parsed === undefined) return undefined
29
+
30
+ return { labels: (parsed.labels ?? []).map((label) => label.name), body: parsed.body ?? '' }
31
+ }
32
+
33
+ // A priority label already on the issue wins, as a typed one does at filing.
34
+ function decision(read: LabelsAndBody): RaiseResult | undefined {
35
+ if (issue_priority.is_typed(read.labels)) return 'labelled'
36
+
37
+ return issue_priority.floor_of(read.body) === 'high' ? undefined : 'below'
38
+ }
39
+
40
+ async function raise(issue_number: string): Promise<RaiseResult> {
41
+ const read = await read_issue(issue_number)
42
+
43
+ if (read === undefined) return 'unreadable'
44
+ const decided = decision(read)
45
+
46
+ if (decided !== undefined) return decided
47
+ const is_applied = await git_gh_command.issue_add_label(issue_number, PRIORITY_HIGH_LABEL)
48
+
49
+ return is_applied ? 'raised' : 'failed'
50
+ }
51
+
52
+ const issue_priority_raise = { raise }
53
+
54
+ export type { RaiseResult }
55
+ export { issue_priority_raise }