@joshuafolkken/kit 1.1035.0 → 1.1094.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 (605) hide show
  1. package/.claude/settings.json +9 -8
  2. package/.claude/skills/epic-commands/SKILL.md +5 -7
  3. package/.claude/skills/verify-ui/SKILL.md +1 -1
  4. package/.claude/skills/workflow-commands/SKILL.md +21 -13
  5. package/.claude/skills/workflow-commands/background-commands.md +5 -4
  6. package/.claude/skills/workflow-commands/backlogrun-child.md +3 -3
  7. package/.claude/skills/workflow-commands/backlogrun-lanes.md +9 -7
  8. package/.claude/skills/workflow-commands/backlogrun-park.md +6 -0
  9. package/.claude/skills/workflow-commands/backlogrun-progress.md +31 -37
  10. package/.claude/skills/workflow-commands/backlogrun-steps.md +25 -25
  11. package/.claude/skills/workflow-commands/backlogrun.md +2 -2
  12. package/.claude/skills/workflow-commands/chain-rule.md +6 -4
  13. package/.claude/skills/workflow-commands/delegation.md +3 -3
  14. package/.claude/skills/workflow-commands/followup-reference.md +3 -3
  15. package/.claude/skills/workflow-commands/followup.md +7 -3
  16. package/.claude/skills/workflow-commands/fullrun-steps.md +3 -2
  17. package/.claude/skills/workflow-commands/fullrun.md +3 -2
  18. package/.claude/skills/workflow-commands/halfrun.md +16 -19
  19. package/.claude/skills/workflow-commands/issue-comments.md +2 -2
  20. package/.claude/skills/workflow-commands/issue-fold-existing.md +10 -10
  21. package/.claude/skills/workflow-commands/issue-scout.md +1 -1
  22. package/.claude/skills/workflow-commands/kickoff.md +9 -4
  23. package/.claude/skills/workflow-commands/latest-gate.md +1 -1
  24. package/.claude/skills/workflow-commands/needs-human-review.md +1 -1
  25. package/.claude/skills/workflow-commands/observation-filing.md +44 -89
  26. package/.claude/skills/workflow-commands/pre-gate-cut.md +33 -36
  27. package/.claude/skills/workflow-commands/prerequisite.md +1 -1
  28. package/.claude/skills/workflow-commands/prrun.md +36 -0
  29. package/.claude/skills/workflow-commands/retrospective.md +1 -1
  30. package/.claude/skills/workflow-commands/working-tree-hold.md +24 -4
  31. package/.codex/hooks.json +16 -20
  32. package/.github/actions/setup-pnpm/action.yml +93 -0
  33. package/.github/dependabot.yml +5 -1
  34. package/.github/workflows/auto-tag.yml +21 -0
  35. package/.github/workflows/ci.yml +26 -128
  36. package/.github/workflows/pr-classification.yml +5 -41
  37. package/.github/workflows/publish.yml +42 -48
  38. package/.github/workflows/sonar-qube.yml +37 -4
  39. package/AGENTS.md +12 -2
  40. package/CLAUDE.md +15 -16
  41. package/GEMINI.md +14 -2
  42. package/README.md +59 -18
  43. package/SECURITY.md +36 -6
  44. package/cspell/index.yaml +2 -1
  45. package/dist/CLAUDE.md +15 -16
  46. package/dist/config-merge/index.js +15 -3
  47. package/dist/hooks/batch-guard.js +4 -4
  48. package/dist/hooks/{chunk-Y27M6A7X.js → chunk-3C4YCCEF.js} +5 -13
  49. package/dist/hooks/{chunk-D67KVGGY.js → chunk-7ZPFAVR7.js} +17 -88
  50. package/dist/hooks/{chunk-HOYJU5RM.js → chunk-E54KGFEQ.js} +11 -4
  51. package/dist/hooks/{chunk-KG6PZD72.js → chunk-IL27YTPH.js} +2 -2
  52. package/dist/hooks/{chunk-GJT4BNVE.js → chunk-KHWHKJOM.js} +3 -3
  53. package/dist/hooks/{chunk-HU66PWWL.js → chunk-M2XDCUKD.js} +1076 -509
  54. package/dist/hooks/{chunk-GLBDBJOK.js → chunk-NKOG3XAV.js} +199 -304
  55. package/dist/hooks/{chunk-ZXNE6NY3.js → chunk-O4LL4HTI.js} +2 -7
  56. package/dist/hooks/{chunk-XPLP27WA.js → chunk-OIZUHPJI.js} +5 -27
  57. package/dist/hooks/{chunk-EIFCAJRB.js → chunk-UD24EAIL.js} +2546 -1636
  58. package/dist/hooks/codex-hook-adapter.js +10 -11
  59. package/dist/hooks/duplicate-read-guard.js +5 -5
  60. package/dist/hooks/format-edited.js +15 -34
  61. package/dist/hooks/inputs.json +279 -0
  62. package/dist/hooks/investigation-guard.js +5 -5
  63. package/dist/hooks/pretool-guard.js +23 -16
  64. package/dist/hooks/session-lang.js +0 -1
  65. package/dist/hooks/stop-guard.js +188 -509
  66. package/dist/josh.js +166 -225
  67. package/dist/managed-marker/index.js +2 -1
  68. package/dist/version/index.js +412 -64
  69. package/eslint/rules/promise.js +5 -0
  70. package/package.json +13 -8
  71. package/prompts/collaboration-workflow/file-edits.md +6 -53
  72. package/prompts/collaboration-workflow/issue-citation.md +5 -5
  73. package/prompts/collaboration-workflow/operating-rules.md +4 -4
  74. package/prompts/collaboration-workflow/overview.md +13 -1
  75. package/prompts/collaboration-workflow/report-format.md +1 -1
  76. package/prompts/collaboration-workflow/residency.md +4 -4
  77. package/prompts/collaboration-workflow/rule-delivery.md +5 -36
  78. package/prompts/collaboration-workflow/shell-body.md +7 -9
  79. package/prompts/collaboration-workflow/turn-batching.md +21 -37
  80. package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
  81. package/prompts/collaboration-workflow/wip-cap.md +36 -36
  82. package/prompts/collaboration-workflow.md +5 -8
  83. package/prompts/review-rubric.md +1 -1
  84. package/prompts/review.md +3 -3
  85. package/prompts/sonar-hotspot-handling.md +12 -4
  86. package/prompts/testing-guide.md +3 -3
  87. package/scripts/adopt/adopt-toolkits.ts +2 -2
  88. package/scripts/adopt/adopt.ts +0 -2
  89. package/scripts/agent/agent-argv.ts +0 -2
  90. package/scripts/agent/agent-diagnostics.ts +1 -1
  91. package/scripts/agent/agent-role-profile.ts +0 -7
  92. package/scripts/agent/claude-agent-argv.ts +0 -2
  93. package/scripts/agent/codex-agent-argv.ts +1 -1
  94. package/scripts/agent/codex-hooks.ts +92 -0
  95. package/scripts/agent/interactive-ask.ts +1 -1
  96. package/scripts/auto-ok/auto-ok-cli.ts +15 -25
  97. package/scripts/backlog/backlog-budget.ts +0 -2
  98. package/scripts/backlog/backlog-defect-priority.ts +2 -2
  99. package/scripts/backlog/backlog-drive-cli.ts +10 -8
  100. package/scripts/backlog/backlog-drive-named-offer.ts +16 -3
  101. package/scripts/backlog/backlog-drive-named.ts +2 -1
  102. package/scripts/backlog/backlog-drive.ts +76 -16
  103. package/scripts/backlog/backlog-named.ts +0 -3
  104. package/scripts/backlog/backlog-next.ts +32 -22
  105. package/scripts/backlog/backlog-offer-cli.ts +0 -5
  106. package/scripts/backlog/backlog-plan-cli.ts +6 -8
  107. package/scripts/backlog/backlog-plan.ts +1 -1
  108. package/scripts/backlog/backlog-pool.ts +34 -17
  109. package/scripts/backlog/backlog-rank.ts +106 -0
  110. package/scripts/backlog/backlog-ready.ts +19 -3
  111. package/scripts/backlog/backlog-scope.ts +1 -3
  112. package/scripts/backlog/backlog-stalled-detect.ts +2 -2
  113. package/scripts/backlog/backlog-stalled.ts +0 -1
  114. package/scripts/backlog/backlog-waves.ts +47 -31
  115. package/scripts/behavior/behavior-cli.ts +1 -1
  116. package/scripts/build/build-codex-hooks.ts +26 -0
  117. package/scripts/build/build-hooks.ts +92 -11
  118. package/scripts/build/hook-bundle-stamp.ts +111 -0
  119. package/scripts/cases/cases-cli.ts +1 -1
  120. package/scripts/cases/cases-logic.ts +1 -1
  121. package/scripts/ci/composite-actions.ts +30 -0
  122. package/scripts/ci/pr-classification.ts +3 -3
  123. package/scripts/claude/workflow-destination.ts +10 -1
  124. package/scripts/clone/clone-fingerprint.ts +0 -1
  125. package/scripts/clone/clone-scan-cli.ts +1 -1
  126. package/scripts/clone/clone-scan.ts +1 -1
  127. package/scripts/config-merge/json-format.ts +0 -1
  128. package/scripts/config-merge/patch-yaml-list.ts +1 -1
  129. package/scripts/cost-runtime/codex-usage.ts +2 -9
  130. package/scripts/cost-runtime/cost-attribute.ts +0 -1
  131. package/scripts/cost-runtime/cost-cli.ts +0 -3
  132. package/scripts/cost-runtime/cost-corpus.ts +0 -2
  133. package/scripts/cost-runtime/cost-format.ts +0 -3
  134. package/scripts/cost-runtime/cost-pricing.ts +0 -1
  135. package/scripts/cost-runtime/cost-tokens.ts +0 -1
  136. package/scripts/delegation/delegation-cli.ts +1 -1
  137. package/scripts/delegation/delegation-policy.ts +11 -1
  138. package/scripts/delegation/duplicate-read-guard.ts +0 -8
  139. package/scripts/delegation/fanout-cli.ts +1 -1
  140. package/scripts/delegation/fanout.ts +0 -2
  141. package/scripts/delegation/investigation-reads.ts +1 -164
  142. package/scripts/discovery/repo-map-logic.ts +0 -1
  143. package/scripts/discovery/repo-party-cli.ts +1 -1
  144. package/scripts/doctor/doctor-consumer.ts +4 -6
  145. package/scripts/doctor/doctor-logic.ts +0 -4
  146. package/scripts/doctor/doctor.ts +14 -9
  147. package/scripts/document/document-byte-budget.ts +8 -9
  148. package/scripts/document/document-byte-check.ts +0 -1
  149. package/scripts/document/document-read-cli.ts +0 -2
  150. package/scripts/document/document-section-cli.ts +1 -1
  151. package/scripts/document/document-section.ts +0 -3
  152. package/scripts/document/edit-files-cli.ts +0 -1
  153. package/scripts/document/entry-read-budget.ts +13 -4
  154. package/scripts/document/lane-child-read-set.ts +1 -6
  155. package/scripts/document/read-files-cli.ts +0 -4
  156. package/scripts/document/read-set-cli.ts +0 -2
  157. package/scripts/document/read-set-point-of-use.ts +1 -0
  158. package/scripts/document/read-set-pricing.ts +0 -1
  159. package/scripts/document/read-set-trim.ts +1 -1
  160. package/scripts/epic/epic-add.ts +1 -1
  161. package/scripts/epic/epic-audit-cli.ts +1 -4
  162. package/scripts/epic/epic-audit-orphans.ts +1 -3
  163. package/scripts/epic/epic-audit-rationale.ts +0 -1
  164. package/scripts/epic/epic-audit-report.ts +0 -2
  165. package/scripts/epic/epic-audit.ts +5 -4
  166. package/scripts/epic/epic-bundle-cli.ts +1 -1
  167. package/scripts/epic/epic-bundle-evidence.ts +0 -1
  168. package/scripts/epic/epic-bundle-referenced.ts +1 -5
  169. package/scripts/epic/epic-bundle.ts +0 -4
  170. package/scripts/epic/epic-busy.ts +4 -5
  171. package/scripts/epic/epic-candidate-confirm.ts +0 -5
  172. package/scripts/epic/epic-classify.ts +2 -2
  173. package/scripts/epic/epic-cli-argv.ts +0 -1
  174. package/scripts/epic/epic-close-comment.ts +1 -1
  175. package/scripts/epic/epic-close.ts +5 -2
  176. package/scripts/epic/epic-cross-repo.ts +2 -4
  177. package/scripts/epic/epic-decision.ts +0 -1
  178. package/scripts/epic/epic-fetch.ts +2 -2
  179. package/scripts/epic/epic-index.ts +2 -3
  180. package/scripts/epic/epic-issue.ts +1 -15
  181. package/scripts/epic/epic-lane-offer.ts +20 -30
  182. package/scripts/epic/epic-nested.ts +1 -1
  183. package/scripts/epic/epic-next-read.ts +1 -3
  184. package/scripts/epic/epic-next-views.ts +0 -1
  185. package/scripts/epic/epic-next.ts +1 -10
  186. package/scripts/epic/epic-parse.ts +0 -1
  187. package/scripts/epic/epic-promote.ts +0 -9
  188. package/scripts/epic/epic-rank.ts +37 -0
  189. package/scripts/epic/epic-read.ts +1 -2
  190. package/scripts/epic/epic-reconcile.ts +1 -1
  191. package/scripts/epic/epic-reference.ts +1 -13
  192. package/scripts/epic/epic-relation-recheck.ts +1 -1
  193. package/scripts/epic/epic-relations.ts +1 -1
  194. package/scripts/epic/epic-remove.ts +1 -1
  195. package/scripts/epic/epic-report.ts +0 -1
  196. package/scripts/epic/epic-run.ts +2 -3
  197. package/scripts/epic/epic-shape.ts +1 -1
  198. package/scripts/epic/epic-solo-stale.ts +107 -0
  199. package/scripts/epic/epic-solo.ts +32 -30
  200. package/scripts/epic/epic-triage.ts +1 -1
  201. package/scripts/epic/epic-validate.ts +1 -1
  202. package/scripts/epic/epic.ts +1 -1
  203. package/scripts/exports/unused-members-cli.ts +53 -0
  204. package/scripts/{git → followup}/followup-issue-number.ts +1 -6
  205. package/scripts/{git → followup}/git-followup-cleanup.ts +2 -1
  206. package/scripts/{git → followup}/git-followup-finish.ts +1 -3
  207. package/scripts/{git → followup}/git-followup-flush.ts +2 -2
  208. package/scripts/{git → followup}/git-followup-issue-close.ts +2 -2
  209. package/scripts/{git → followup}/git-followup-label.ts +4 -4
  210. package/scripts/followup/git-followup-merged.ts +112 -0
  211. package/scripts/{git → followup}/git-followup-pending.ts +1 -1
  212. package/scripts/{git → followup}/git-followup-workflow.ts +19 -11
  213. package/scripts/{git → followup}/git-pr-followup-wrapup.ts +9 -3
  214. package/scripts/{git → followup}/git-pr-followup.ts +53 -16
  215. package/scripts/gate/core-budget.ts +3 -9
  216. package/scripts/gate/gate-plan.ts +7 -4
  217. package/scripts/gate/gate-report.ts +0 -6
  218. package/scripts/gate/gate-tree.ts +1 -1
  219. package/scripts/gate/pre-commit-type-check.ts +0 -6
  220. package/scripts/gate/project-checks.ts +7 -8
  221. package/scripts/gate/scoped-green.ts +0 -1
  222. package/scripts/gate/type-check-step.ts +1 -1
  223. package/scripts/gate/verification-gate.ts +0 -2
  224. package/scripts/gh/fix-gh-packages.ts +15 -12
  225. package/scripts/gh/gh-spawn.ts +2 -2
  226. package/scripts/{git → gh}/git-ai-review-scan.ts +1 -5
  227. package/scripts/{git → gh}/git-gh-check.ts +2 -1
  228. package/scripts/{git → gh}/git-gh-exec.ts +1 -1
  229. package/scripts/{git → gh}/git-gh-failure.ts +1 -1
  230. package/scripts/{git → gh}/git-gh-helpers.ts +0 -1
  231. package/scripts/{git → gh}/git-gh-issue-list.ts +2 -0
  232. package/scripts/{git → gh}/git-gh-issue-read.ts +1 -1
  233. package/scripts/{git → gh}/git-gh-issue-rest.ts +6 -3
  234. package/scripts/{git → gh}/git-gh-pr-read.ts +24 -0
  235. package/scripts/{git → gh}/git-gh-pr-rest.ts +5 -2
  236. package/scripts/{git → gh}/git-gh-pr-review.ts +2 -2
  237. package/scripts/{git → gh}/git-gh-pr-rollup.ts +1 -3
  238. package/scripts/{git → gh}/git-gh-pr.ts +3 -1
  239. package/scripts/{git → gh}/git-pr-ai-review.ts +2 -5
  240. package/scripts/{git → gh}/git-pr-checks-eval.ts +0 -10
  241. package/scripts/{git → gh}/git-pr-checks-parse.ts +4 -20
  242. package/scripts/{git → gh}/git-pr-checks.ts +2 -1
  243. package/scripts/{git → gh}/git-pr-coderabbit.ts +2 -5
  244. package/scripts/{git → gh}/git-pr-confirmation.ts +1 -3
  245. package/scripts/{git → gh}/git-pr-managed-config.ts +2 -3
  246. package/scripts/{git → gh}/git-pr.ts +3 -3
  247. package/scripts/git/changed-file-scope.ts +0 -1
  248. package/scripts/git/git-branch.ts +3 -6
  249. package/scripts/git/git-command.ts +1 -1
  250. package/scripts/git/git-commit.ts +1 -1
  251. package/scripts/git/git-common-directory.ts +80 -24
  252. package/scripts/git/git-error.ts +66 -9
  253. package/scripts/git/git-execa-error.ts +6 -1
  254. package/scripts/git/git-issue.ts +1 -1
  255. package/scripts/git/git-preflight.ts +24 -6
  256. package/scripts/git/git-prompt.ts +6 -31
  257. package/scripts/git/git-push-transport.ts +12 -69
  258. package/scripts/git/git-push.ts +1 -1
  259. package/scripts/git/git-spawn.ts +79 -3
  260. package/scripts/git/git-ssh-keepalive.ts +74 -0
  261. package/scripts/git/git-staging.ts +1 -0
  262. package/scripts/git/git-status.ts +1 -1
  263. package/scripts/git/git-workflow.ts +1 -1
  264. package/scripts/git/gone-branch.ts +4 -2
  265. package/scripts/git/listing-cutoff.ts +1 -1
  266. package/scripts/git/main-merge.ts +1 -1
  267. package/scripts/git/main-sync.ts +19 -1
  268. package/scripts/git/parse-json-array.ts +0 -3
  269. package/scripts/git/repository-lock.ts +16 -16
  270. package/scripts/git/{git-stash.ts → stash/git-stash.ts} +1 -1
  271. package/scripts/git/{stash-pop-args.ts → stash/stash-pop-args.ts} +1 -1
  272. package/scripts/git/{stash-pop-cli.ts → stash/stash-pop-cli.ts} +0 -1
  273. package/scripts/git/{stash-sweep-lock.ts → stash/stash-sweep-lock.ts} +3 -3
  274. package/scripts/hooks/codex-hook-adapter.ts +0 -1
  275. package/scripts/hooks/edited-cspell.ts +1 -1
  276. package/scripts/hooks/format-edited-cli.ts +15 -0
  277. package/scripts/hooks/format-edited-file.ts +4 -9
  278. package/scripts/hooks/pre-push-unit.ts +0 -4
  279. package/scripts/hooks/pretool-guard-cli.ts +21 -0
  280. package/scripts/hooks/pretool-guard.ts +36 -19
  281. package/scripts/hooks/reserved-run.ts +1 -1
  282. package/scripts/hooks/step-zero-notice.ts +76 -0
  283. package/scripts/hooks/stop-guard.ts +47 -21
  284. package/scripts/init/claude-plugin-config.ts +4 -5
  285. package/scripts/init/hook-command-rewrite.ts +16 -8
  286. package/scripts/init/hook-launch.ts +41 -15
  287. package/scripts/init/init-basic.ts +2 -5
  288. package/scripts/init/init-logic.ts +7 -0
  289. package/scripts/init/init.ts +0 -3
  290. package/scripts/init/project-profile.ts +6 -11
  291. package/scripts/init/start-exec.ts +8 -2
  292. package/scripts/init/start-plan.ts +18 -5
  293. package/scripts/init/start-setup-pr.ts +52 -25
  294. package/scripts/init/start-steps.ts +42 -9
  295. package/scripts/init/start.ts +40 -10
  296. package/scripts/issue/behavior-change-lint.ts +0 -1
  297. package/scripts/issue/defect-rate-cli.ts +3 -3
  298. package/scripts/issue/defect-rate.ts +1 -2
  299. package/scripts/{git → issue}/git-next-issues.ts +37 -8
  300. package/scripts/issue/issue-backlinks-cli.ts +1 -5
  301. package/scripts/issue/issue-cite-cli.ts +2 -6
  302. package/scripts/issue/issue-cite.ts +19 -3
  303. package/scripts/issue/issue-classification.ts +1 -9
  304. package/scripts/issue/issue-closing-pr.ts +4 -4
  305. package/scripts/issue/issue-comment-cli.ts +2 -2
  306. package/scripts/issue/issue-file-cli.ts +5 -5
  307. package/scripts/issue/issue-file.ts +2 -2
  308. package/scripts/issue/issue-fold-cli.ts +1 -1
  309. package/scripts/issue/issue-fold-existing-cli.ts +1 -1
  310. package/scripts/{git → issue}/issue-labels.ts +20 -0
  311. package/scripts/issue/issue-lint-cli.ts +1 -1
  312. package/scripts/issue/issue-merged.ts +2 -2
  313. package/scripts/issue/issue-rank.ts +89 -0
  314. package/scripts/issue/issue-read-cli.ts +8 -47
  315. package/scripts/issue/issue-read.ts +0 -2
  316. package/scripts/issue/issue-report-failures.ts +80 -0
  317. package/scripts/issue/issue-scout-cli.ts +1 -7
  318. package/scripts/issue/issue-scout-closed.ts +2 -2
  319. package/scripts/issue/issue-scout.ts +0 -2
  320. package/scripts/issue/issue-state-cli.ts +5 -46
  321. package/scripts/issue/issue-state.ts +1 -5
  322. package/scripts/issue/markdown-section.ts +1 -1
  323. package/scripts/issue/measure-rerun-cli.ts +1 -1
  324. package/scripts/issue/reproduction-measure.ts +1 -1
  325. package/scripts/josh/cli-body.ts +1 -1
  326. package/scripts/josh/file-map-stamp.ts +0 -3
  327. package/scripts/josh/josh-command-map.ts +2 -102
  328. package/scripts/josh/josh-commands-ai.ts +9 -102
  329. package/scripts/josh/josh-commands-backlog.ts +5 -1
  330. package/scripts/josh/josh-commands-development.ts +10 -3
  331. package/scripts/josh/josh-commands-issue.ts +2 -2
  332. package/scripts/josh/josh-commands-maintenance.ts +7 -0
  333. package/scripts/josh/josh-commands-project.ts +7 -1
  334. package/scripts/josh/josh-commands-run.ts +114 -0
  335. package/scripts/josh/josh-commands-versioning.ts +8 -0
  336. package/scripts/josh/josh-commands-workflow.ts +2 -2
  337. package/scripts/josh/path-decision.ts +0 -3
  338. package/scripts/josh/process-owner.ts +16 -0
  339. package/scripts/josh/session-language-cli.ts +0 -1
  340. package/scripts/lane/lane-await.ts +3 -6
  341. package/scripts/lane/lane-capacity.ts +6 -3
  342. package/scripts/lane/lane-child-invocation.ts +20 -7
  343. package/scripts/lane/lane-child-marker.ts +16 -2
  344. package/scripts/lane/lane-cli.ts +33 -18
  345. package/scripts/lane/lane-close.ts +1 -3
  346. package/scripts/lane/lane-dispatch.ts +3 -4
  347. package/scripts/lane/lane-environment.ts +0 -9
  348. package/scripts/lane/lane-handoff.ts +38 -0
  349. package/scripts/lane/lane-launch-cli.ts +21 -11
  350. package/scripts/lane/lane-open.ts +0 -3
  351. package/scripts/lane/lane-output.ts +0 -1
  352. package/scripts/lane/lane-registry.ts +9 -0
  353. package/scripts/lane/lane-report.ts +10 -4
  354. package/scripts/lane/openai-lane-ship.ts +2 -0
  355. package/scripts/lane/openai-lane-supervisor-decision.ts +2 -1
  356. package/scripts/lane/openai-lane-supervisor.ts +6 -4
  357. package/scripts/lane/openai-review-broker.ts +3 -0
  358. package/scripts/lib/bounded-pool.ts +1 -0
  359. package/scripts/lib/json-value.ts +5 -4
  360. package/scripts/lib/poll.ts +3 -1
  361. package/scripts/lib/timed-fetch.ts +15 -0
  362. package/scripts/lib/timeouts.ts +13 -0
  363. package/scripts/{yaml → lib}/yaml-document.ts +3 -1
  364. package/scripts/{bytes → lines}/bytes-command.ts +0 -2
  365. package/scripts/lines/lines-command.ts +0 -1
  366. package/scripts/lint/lint-related-scope.ts +0 -1
  367. package/scripts/lint/lint-related.ts +1 -1
  368. package/scripts/{git → notify}/telegram-notify.ts +2 -2
  369. package/scripts/{git → notify}/telegram-test.ts +4 -4
  370. package/scripts/observations/observation-ledger-home.ts +0 -1
  371. package/scripts/observations/observation-ledger-line.ts +0 -1
  372. package/scripts/observations/observation-ledger-migrate.ts +1 -1
  373. package/scripts/observations/observations-flush-landing.ts +3 -3
  374. package/scripts/observations/observations-flush.ts +2 -2
  375. package/scripts/overrides/lockfile-overrides.ts +1 -1
  376. package/scripts/overrides/overrides-logic.ts +1 -1
  377. package/scripts/package/package-scout-cli.ts +2 -7
  378. package/scripts/package/package-scout.ts +0 -2
  379. package/scripts/propagate/propagate-git-failure.ts +0 -1
  380. package/scripts/propagate/propagate-git.ts +0 -2
  381. package/scripts/propagate/propagate-plan.ts +185 -0
  382. package/scripts/propagate/propagate-publish.ts +2 -3
  383. package/scripts/propagate/propagate-run.ts +5 -3
  384. package/scripts/propagate/propagate-steps.ts +19 -6
  385. package/scripts/propagate/propagate-targets.ts +13 -6
  386. package/scripts/propagate/propagate.ts +60 -46
  387. package/scripts/refactor/import-graph.ts +0 -1
  388. package/scripts/refactor/refactor-lint.ts +0 -2
  389. package/scripts/refactor/refactor-scan.ts +0 -1
  390. package/scripts/refactor/refactor-targets.ts +0 -1
  391. package/scripts/registry-migration/migrate-logic.ts +1 -2
  392. package/scripts/registry-migration/migrate.ts +19 -9
  393. package/scripts/release/github-release-cli.ts +8 -6
  394. package/scripts/release/github-release-environment.ts +46 -0
  395. package/scripts/release/github-release.ts +151 -94
  396. package/scripts/release/release-history.ts +0 -1
  397. package/scripts/release/release-plan.ts +0 -1
  398. package/scripts/release/release-publish.ts +2 -3
  399. package/scripts/release/release-scope-cli.ts +1 -2
  400. package/scripts/release/release-tag.ts +2 -4
  401. package/scripts/repo/auto-merge-setting-logic.ts +1 -4
  402. package/scripts/repo/repo-setting.ts +1 -1
  403. package/scripts/repo/repository-labels.ts +3 -3
  404. package/scripts/repo/required-checks-logic.ts +206 -0
  405. package/scripts/repo/required-checks-report.ts +71 -0
  406. package/scripts/repo/ruleset-check-cli.ts +53 -0
  407. package/scripts/repo/ruleset-check.ts +147 -0
  408. package/scripts/report/report-lint-cli.ts +0 -4
  409. package/scripts/review/disposition-cli.ts +1 -1
  410. package/scripts/review/live-evidence.ts +1 -1
  411. package/scripts/review/review-attest-cli.ts +0 -6
  412. package/scripts/review/review-attest.ts +48 -16
  413. package/scripts/review/review-brief-cli.ts +72 -8
  414. package/scripts/review/review-brief.ts +67 -9
  415. package/scripts/review/review-diff-parts.ts +89 -0
  416. package/scripts/review/review-diff-write.ts +97 -0
  417. package/scripts/review/review-finding-ledger.ts +0 -1
  418. package/scripts/review/review-record-cli.ts +1 -1
  419. package/scripts/review/review-record.ts +0 -1
  420. package/scripts/review/review-round2-cli.ts +1 -1
  421. package/scripts/review/review-stamps.ts +6 -2
  422. package/scripts/review/review-tree.ts +14 -2
  423. package/scripts/rules/decision-oracle-stage.ts +18 -0
  424. package/scripts/rules/decision-oracle.ts +10 -7
  425. package/scripts/rules/delivered-rules.ts +9 -1
  426. package/scripts/rules/destructive-command.ts +119 -0
  427. package/scripts/rules/direct-filing.ts +1 -1
  428. package/scripts/rules/file-body.ts +0 -3
  429. package/scripts/rules/filing-cap.ts +0 -2
  430. package/scripts/rules/gh-api.ts +7 -2
  431. package/scripts/rules/git-argv.ts +18 -7
  432. package/scripts/rules/git-force.ts +0 -2
  433. package/scripts/rules/implementation-cut.ts +1 -2
  434. package/scripts/rules/index-guard.ts +71 -0
  435. package/scripts/rules/issue-citation.ts +50 -25
  436. package/scripts/rules/issue-fold.ts +1 -2
  437. package/scripts/rules/lane-background.ts +15 -7
  438. package/scripts/rules/lane-carry-conflict.ts +1 -2
  439. package/scripts/rules/lane-park.ts +14 -8
  440. package/scripts/rules/last-prompt.ts +1 -0
  441. package/scripts/rules/oracle-consulted.ts +1 -1
  442. package/scripts/rules/oracle-firing.ts +1 -0
  443. package/scripts/rules/oracle-list-cli.ts +0 -3
  444. package/scripts/rules/permission-guards.ts +14 -0
  445. package/scripts/rules/pre-gate-cut.ts +2 -2
  446. package/scripts/rules/protected-files.ts +74 -0
  447. package/scripts/rules/reply-language.ts +1 -1
  448. package/scripts/rules/rule-body-guard.ts +0 -3
  449. package/scripts/rules/rule-value-cli.ts +0 -1
  450. package/scripts/rules/shell-body-trigger.ts +0 -1
  451. package/scripts/rules/shell-segments.ts +0 -1
  452. package/scripts/rules/stop-rules.ts +13 -5
  453. package/scripts/rules/tail-commands.ts +1 -1
  454. package/scripts/rules/test-declared-commit.ts +1 -1
  455. package/scripts/rules/third-party-write.ts +0 -1
  456. package/scripts/rules/worktree-guard.ts +26 -9
  457. package/scripts/run/run-carry-cli.ts +0 -2
  458. package/scripts/run/run-carry-stash.ts +2 -2
  459. package/scripts/run/run-carry-streak.ts +1 -1
  460. package/scripts/run/run-cut-cli.ts +0 -7
  461. package/scripts/run/run-cut.ts +8 -54
  462. package/scripts/run/run-ending-cli.ts +1 -1
  463. package/scripts/run/run-ending.ts +1 -4
  464. package/scripts/run/run-entry-cli.ts +101 -24
  465. package/scripts/run/run-entry.ts +0 -1
  466. package/scripts/run/run-event-cli.ts +0 -2
  467. package/scripts/run/run-event-follow.ts +1 -0
  468. package/scripts/run/run-event-render.ts +1 -1
  469. package/scripts/run/run-event-scope.ts +53 -4
  470. package/scripts/run/run-event-stream.ts +0 -3
  471. package/scripts/run/run-event-watch.ts +1 -0
  472. package/scripts/run/run-halfrun-resume.ts +20 -7
  473. package/scripts/run/run-headless.ts +24 -8
  474. package/scripts/run/run-hold-cli.ts +33 -10
  475. package/scripts/run/run-hold.ts +25 -5
  476. package/scripts/run/run-issue-number.ts +1 -1
  477. package/scripts/run/run-liveness-cli.ts +1 -1
  478. package/scripts/run/run-liveness.ts +2 -3
  479. package/scripts/run/run-merge-cli.ts +5 -13
  480. package/scripts/run/run-merge-steps.ts +5 -5
  481. package/scripts/run/run-merge.ts +1 -1
  482. package/scripts/run/run-next-cli.ts +1 -1
  483. package/scripts/run/run-parent-cut-hook.ts +143 -0
  484. package/scripts/run/run-preflight.ts +2 -9
  485. package/scripts/run/run-prep-cli.ts +2 -2
  486. package/scripts/run/run-prep-locate.ts +1 -1
  487. package/scripts/run/run-progress-cli.ts +4 -7
  488. package/scripts/run/run-progress-clock.ts +6 -34
  489. package/scripts/run/run-progress-config.ts +0 -4
  490. package/scripts/run/run-progress-read.ts +3 -3
  491. package/scripts/run/run-progress.ts +22 -10
  492. package/scripts/run/run-prrun-resume.ts +117 -0
  493. package/scripts/run/run-report-cli.ts +1 -2
  494. package/scripts/run/run-report.ts +0 -1
  495. package/scripts/run/run-retrospective.ts +1 -1
  496. package/scripts/run/run-review-cli.ts +0 -3
  497. package/scripts/run/run-review-steps.ts +2 -0
  498. package/scripts/run/run-review.ts +0 -2
  499. package/scripts/run/run-ship-cli.ts +27 -77
  500. package/scripts/run/run-ship-detach.ts +1 -0
  501. package/scripts/run/run-ship-next.ts +106 -0
  502. package/scripts/run/run-ship-preflight.ts +87 -0
  503. package/scripts/run/run-ship-return.ts +8 -3
  504. package/scripts/run/run-ship-review-steps.ts +23 -30
  505. package/scripts/run/run-ship-review.ts +20 -0
  506. package/scripts/run/run-ship-scoped.ts +45 -0
  507. package/scripts/run/run-ship-stage.ts +5 -1
  508. package/scripts/run/run-ship-steps.ts +105 -0
  509. package/scripts/run/run-ship.ts +2 -1
  510. package/scripts/run/run-stage-read.ts +62 -0
  511. package/scripts/run/run-stage.ts +160 -0
  512. package/scripts/run/run-status-cli.ts +1 -1
  513. package/scripts/run/run-step-cli.ts +21 -14
  514. package/scripts/run/run-step.ts +1 -1
  515. package/scripts/run/run-stop-notify.ts +1 -3
  516. package/scripts/run/run-stranded-cli.ts +0 -4
  517. package/scripts/run/run-stranded-detect.ts +2 -2
  518. package/scripts/run/run-tail-cli.ts +17 -11
  519. package/scripts/run/run-tail.ts +2 -0
  520. package/scripts/run/run-tidy-lanes.ts +2 -1
  521. package/scripts/run/run-tidy-stashes.ts +12 -12
  522. package/scripts/run/run-wake-cli.ts +4 -5
  523. package/scripts/run/run-wake-describe.ts +19 -1
  524. package/scripts/run/run-wake-loop.ts +2 -2
  525. package/scripts/run/run-wake.ts +2 -4
  526. package/scripts/run/run-watcher-guard-cli.ts +0 -4
  527. package/scripts/run/run-watcher-guard.ts +9 -7
  528. package/scripts/run/run-watcher-hook.ts +1 -1
  529. package/scripts/safe-chain/ci-installer-pin.ts +11 -5
  530. package/scripts/safe-chain/project-config.ts +1 -1
  531. package/scripts/security/security-audit-provision-logic.ts +0 -1
  532. package/scripts/security/security-audit-provision.ts +3 -2
  533. package/scripts/security/security-audit.ts +0 -1
  534. package/scripts/security/security-updates-logic.ts +0 -1
  535. package/scripts/sonar/sonar-hotspots-cli.ts +10 -52
  536. package/scripts/sonar/sonar-hotspots.ts +0 -1
  537. package/scripts/sonar/sonar-new-code-cli.ts +150 -0
  538. package/scripts/sonar/sonar-new-code.ts +79 -0
  539. package/scripts/sonar/sonar-project.ts +97 -0
  540. package/scripts/split/split-assess-cli.ts +1 -1
  541. package/scripts/split/split-assess.ts +2 -5
  542. package/scripts/sync/managed-config-scope-cli.ts +1 -1
  543. package/scripts/sync/skill-migration.ts +0 -1
  544. package/scripts/sync/sync-hook-safety.ts +2 -3
  545. package/scripts/sync/sync.ts +1 -8
  546. package/scripts/sync/template-source-logic.ts +0 -1
  547. package/scripts/sync/workflow-pin-logic.ts +16 -28
  548. package/scripts/test/test-declared-logic.ts +0 -1
  549. package/scripts/test/test-declared.ts +0 -2
  550. package/scripts/test/test-red-commit.ts +2 -2
  551. package/scripts/test/test-red.ts +14 -7
  552. package/scripts/test/test-type-logic.ts +1 -1
  553. package/scripts/test/unit-worker-share.ts +7 -16
  554. package/scripts/time-runtime/time-batch-guard.ts +1 -2
  555. package/scripts/time-runtime/time-bundle-call.ts +2 -3
  556. package/scripts/time-runtime/time-bundles.ts +0 -4
  557. package/scripts/time-runtime/time-density-hook.ts +0 -2
  558. package/scripts/time-runtime/time-followup-stage.ts +1 -1
  559. package/scripts/time-runtime/time-format.ts +0 -73
  560. package/scripts/time-runtime/time-round-trips.ts +0 -4
  561. package/scripts/time-runtime/time-single-check.ts +1 -1
  562. package/scripts/time-runtime/time-spans.ts +1 -1
  563. package/scripts/time-runtime/time-transcript-line.ts +1 -2
  564. package/scripts/ui/ui-routes-cli.ts +0 -5
  565. package/scripts/ui/ui-routes.ts +0 -5
  566. package/scripts/version/effective-upstream.ts +2 -2
  567. package/scripts/version/latest-corepack.ts +7 -9
  568. package/scripts/version/latest-scope-cli.ts +0 -2
  569. package/scripts/version/latest-update.ts +0 -2
  570. package/scripts/version/npm-registry.ts +97 -0
  571. package/scripts/version/publishable-range-check.ts +1 -1
  572. package/scripts/version/release-hold.ts +0 -4
  573. package/scripts/version/running-binary.ts +2 -2
  574. package/scripts/version/version-check-logic.ts +0 -2
  575. package/scripts/version/version-commands.ts +5 -4
  576. package/scripts/version/version-remote.ts +28 -14
  577. package/scripts/version/version-targets.ts +4 -4
  578. package/templates/sonar-project.properties +28 -1
  579. package/templates/workflows/dependabot-auto-merge.yml +5 -3
  580. package/templates/workflows/github-release.yml +81 -0
  581. package/prompts/collaboration-workflow/cross-repo-epic.md +0 -5
  582. package/prompts/collaboration-workflow/epic-audit.md +0 -5
  583. package/prompts/collaboration-workflow/epic-bundle.md +0 -5
  584. package/scripts/init/plugin-install-hint.ts +0 -47
  585. package/scripts/version/parse-json.ts +0 -13
  586. /package/scripts/{git → followup}/git-followup-stages.ts +0 -0
  587. /package/scripts/{git → gh}/git-gh-api-path.ts +0 -0
  588. /package/scripts/{git → gh}/git-gh-command.ts +0 -0
  589. /package/scripts/{git → gh}/git-gh-issue-write.ts +0 -0
  590. /package/scripts/{git → gh}/git-gh-issue.ts +0 -0
  591. /package/scripts/{git → gh}/git-gh-pr-auto-merge.ts +0 -0
  592. /package/scripts/{git → gh}/git-gh-pr-snapshot.ts +0 -0
  593. /package/scripts/{git → gh}/git-gh-reachability.ts +0 -0
  594. /package/scripts/{git → gh}/git-gh-repo.ts +0 -0
  595. /package/scripts/{git → gh}/git-gh-rest-state.ts +0 -0
  596. /package/scripts/{git → gh}/git-pr-checks-watch.ts +0 -0
  597. /package/scripts/{git → gh}/git-pr-error.ts +0 -0
  598. /package/scripts/{git → gh}/git-pr-messages.ts +0 -0
  599. /package/scripts/{git → gh}/github-issue-url.ts +0 -0
  600. /package/scripts/git/{stash-orphans.ts → stash/stash-orphans.ts} +0 -0
  601. /package/scripts/{git → issue}/issue-reference.ts +0 -0
  602. /package/scripts/{git → lib}/animation-helpers.ts +0 -0
  603. /package/scripts/{git → lib}/git-animation.ts +0 -0
  604. /package/scripts/{git → notify}/git-notify.ts +0 -0
  605. /package/scripts/{git → notify}/telegram-test-logic.ts +0 -0
@@ -0,0 +1,117 @@
1
+ import { git_gh_command } from '#scripts/gh/git-gh-command'
2
+ import type { PullMergeState } from '#scripts/gh/git-gh-pr-read'
3
+ import { git_branch } from '#scripts/git/git-branch'
4
+ import { git_command } from '#scripts/git/git-command'
5
+ import { run_halfrun_resume, type StopMark } from './run-halfrun-resume'
6
+ import { run_hold, type HoldRead } from './run-hold'
7
+
8
+ // joshuafolkken/kit#3023: a `prrun` stops at a green, mergeable pull request and **keeps** its hold, so
9
+ // a person can look before anything merges. What comes next is one of three, and `run:entry` answers
10
+ // which as the resume token `fullrun #N` acts on — read, never inferred:
11
+ //
12
+ // - `prrun-merged` — the person merged it by hand. Only `followup`'s tail is left.
13
+ // - `prrun-merge` — the branch is where the stop left it, both here and on the pull request, and the
14
+ // tree is clean. What was verified is what would merge, so `followup` merges without the gate and
15
+ // the review again.
16
+ // - `prrun-gate` — the branch moved since the stop, or the tree is dirty: a person changed something,
17
+ // so the gate and the review run again before `followup`. **The pull request's own head is asked
18
+ // too**: a commit pushed on GitHub (a suggestion applied, "Update branch") moves only the remote,
19
+ // and `followup` merges the remote — an unread or moved one is never taken as untouched.
20
+ //
21
+ // **Only a marked record is adopted**, as for the `halfrun` stop (`run-halfrun-resume.ts`): the stop
22
+ // writes the commit it stopped on (`run:hold <N> --prrun-stop`), and a hold without it is a run still
23
+ // working, never one waiting for a person.
24
+
25
+ const PRRUN_MERGED = 'prrun-merged'
26
+ const PRRUN_MERGE = 'prrun-merge'
27
+ const PRRUN_GATE = 'prrun-gate'
28
+
29
+ type PrrunToken = typeof PRRUN_GATE | typeof PRRUN_MERGE | typeof PRRUN_MERGED
30
+
31
+ interface ResumeFacts {
32
+ is_merged: boolean
33
+ stop_head: string
34
+ head: string
35
+ // The commit the pull request's head is on, or `undefined` when it could not be read.
36
+ pr_head: string | undefined
37
+ is_dirty: boolean
38
+ }
39
+
40
+ function is_untouched(facts: ResumeFacts): boolean {
41
+ return facts.head === facts.stop_head && facts.pr_head === facts.stop_head && !facts.is_dirty
42
+ }
43
+
44
+ function decide(facts: ResumeFacts): PrrunToken {
45
+ if (facts.is_merged) return PRRUN_MERGED
46
+
47
+ return is_untouched(facts) ? PRRUN_MERGE : PRRUN_GATE
48
+ }
49
+
50
+ function stop_head_of(read: HoldRead, issue: string): string | undefined {
51
+ const hold = run_halfrun_resume.hold_of(read)
52
+
53
+ return hold?.issue === issue ? hold.prrun_stop_head : undefined
54
+ }
55
+
56
+ async function read_merge_state(): Promise<PullMergeState | undefined> {
57
+ return await git_gh_command.pr_get_merge_state(await git_branch.current())
58
+ }
59
+
60
+ async function read_facts(stop_head: string): Promise<ResumeFacts> {
61
+ const [state, head, is_dirty] = await Promise.all([
62
+ read_merge_state(),
63
+ git_command.head_commit(),
64
+ run_hold.is_tree_dirty(),
65
+ ])
66
+
67
+ return {
68
+ is_merged: state?.is_merged === true,
69
+ stop_head,
70
+ head,
71
+ pr_head: state?.head_sha,
72
+ is_dirty,
73
+ }
74
+ }
75
+
76
+ // Read-only, so `run:entry` can ask the session budget before it takes anything over. `undefined` is
77
+ // "no `prrun` stop for this issue here", and the ordinary claim decides the tree as before.
78
+ async function resume_token(issue: string): Promise<PrrunToken | undefined> {
79
+ const target = await run_halfrun_resume.hold_target()
80
+
81
+ if (target === undefined) return undefined
82
+
83
+ const stop_head = stop_head_of(run_hold.read_hold(target), issue)
84
+
85
+ return stop_head === undefined ? undefined : decide(await read_facts(stop_head))
86
+ }
87
+
88
+ async function adopt(issue: string): Promise<boolean> {
89
+ const target = await run_halfrun_resume.hold_target()
90
+
91
+ if (target === undefined || stop_head_of(run_hold.read_hold(target), issue) === undefined) {
92
+ return false
93
+ }
94
+
95
+ return run_halfrun_resume.take_over(target, issue)
96
+ }
97
+
98
+ // The `--prrun-stop` mark: the run's own record re-written with the commit the pull request is on.
99
+ async function mark_stop_at(target: string, issue: string): Promise<StopMark> {
100
+ const head = await git_command.head_commit()
101
+
102
+ return run_halfrun_resume.mark_stop_at(target, issue, { prrun_stop_head: head })
103
+ }
104
+
105
+ const run_prrun_resume = {
106
+ PRRUN_GATE,
107
+ PRRUN_MERGE,
108
+ PRRUN_MERGED,
109
+ adopt,
110
+ decide,
111
+ mark_stop_at,
112
+ resume_token,
113
+ stop_head_of,
114
+ }
115
+
116
+ export type { PrrunToken, ResumeFacts }
117
+ export { run_prrun_resume }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env tsx
2
2
  import { fileURLToPath } from 'node:url'
3
- import { git_followup_pending } from '#scripts/git/git-followup-pending'
3
+ import { git_followup_pending } from '#scripts/followup/git-followup-pending'
4
4
  import { release_scope_cli } from '#scripts/release/release-scope-cli'
5
5
  import { run_carry } from './run-carry'
6
6
  import { run_event_scope, type EventScope } from './run-event-scope'
@@ -62,7 +62,6 @@ async function main(): Promise<void> {
62
62
  }
63
63
 
64
64
  const run_report_cli = {
65
- main,
66
65
  run,
67
66
  }
68
67
 
@@ -71,7 +71,6 @@ function build_report(input: ReportInput): string {
71
71
  const run_report = {
72
72
  UNKNOWN_SCOPE_NOTICE,
73
73
  build_report,
74
- release_tail,
75
74
  }
76
75
 
77
76
  export type { ReportInput }
@@ -28,7 +28,7 @@ function is_owed(facts: RetrospectiveFacts): boolean {
28
28
  return !facts.is_lane_child && !facts.is_retrospective_done && !facts.is_consumer
29
29
  }
30
30
 
31
- const run_retrospective = { RETROSPECTIVE_ENV_KEY, is_enabled, is_owed }
31
+ const run_retrospective = { is_enabled, is_owed }
32
32
 
33
33
  export type { RetrospectiveFacts }
34
34
  export { run_retrospective }
@@ -118,10 +118,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
118
118
  }
119
119
 
120
120
  const run_review_cli = {
121
- JOIN_FLAG,
122
- USAGE,
123
121
  join_exit_code,
124
- main,
125
122
  run,
126
123
  }
127
124
 
@@ -94,7 +94,9 @@ async function wait_for_gate_finish(now: Clock = () => Date.now()): Promise<Gate
94
94
  let state = await read_gate_state()
95
95
 
96
96
  while (!run_review.is_gate_settled(state) && now() - started < MAX_JOIN_WAIT_MS) {
97
+ // eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
97
98
  await sleep(POLL_INTERVAL_MS)
99
+ // eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
98
100
  state = await read_gate_state()
99
101
  }
100
102
 
@@ -105,12 +105,10 @@ const run_review = {
105
105
  GATE_RED,
106
106
  GATE_RUNNING,
107
107
  adopt_verdict,
108
- format_seconds,
109
108
  format_timing,
110
109
  gate_state,
111
110
  is_gate_settled,
112
111
  overlap_seconds,
113
- span_seconds,
114
112
  }
115
113
 
116
114
  export type { AdoptVerdict, GateState, ReviewTiming, TimingStart }
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env tsx
2
2
  import { fileURLToPath } from 'node:url'
3
3
  import { parseArgs } from 'node:util'
4
- import { josh_command, type JoshResult } from '#scripts/josh/josh-run'
5
4
  import { lane_child_marker } from '#scripts/lane/lane-child-marker'
6
5
  import { run_event_stream } from './run-event-stream'
7
6
  import { run_event_stream_emit } from './run-event-stream-emit'
8
7
  import { run_ship, type ShipSection } from './run-ship'
9
8
  import { run_ship_detach } from './run-ship-detach'
9
+ import { run_ship_next } from './run-ship-next'
10
10
  import { run_ship_probe } from './run-ship-probe'
11
11
  import { run_ship_return } from './run-ship-return'
12
- import { run_ship_review_steps } from './run-ship-review-steps'
13
12
  import { run_ship_stage, type Phase, type ShipState, type Stage } from './run-ship-stage'
13
+ import { run_ship_steps, type ShipArguments, type Step } from './run-ship-steps'
14
14
 
15
15
  // `josh ship "<title> #<N>"` — one call for the fixed commit-to-report region a run ships a change on
16
16
  // (joshuafolkken/kit#2398). The loop used to spend a round trip each on `gate`, `git -y`, `followup`
@@ -67,7 +67,6 @@ const USAGE =
67
67
  const NO_LOG_NOTE = 'no detached ship supervisor log for this issue'
68
68
  const LANE_CHILD_DETACH_NOTE =
69
69
  'lane child: shipping through the detached supervisor (--detach implied), so the end of this turn cannot kill it'
70
- const should_forward_stderr = true
71
70
 
72
71
  type NotifyValues = Partial<Record<(typeof NOTIFY_OPTIONS)[number], string>>
73
72
 
@@ -84,24 +83,8 @@ const OPTIONS = {
84
83
  cite: { type: 'string', multiple: true },
85
84
  } as const
86
85
 
87
- interface ShipArguments {
88
- title: string
89
- number: string
90
- notify: ReadonlyArray<string>
91
- body: ReadonlyArray<string>
92
- cites: ReadonlyArray<string>
93
- is_review: boolean
94
- is_detach: boolean
95
- }
96
-
97
86
  type ShipCommand = { kind: 'ship'; args: ShipArguments } | { kind: 'log'; number: string }
98
87
 
99
- interface Step {
100
- stage: Stage
101
- header: string
102
- run: (args: ShipArguments, state: ShipState) => Promise<JoshResult>
103
- }
104
-
105
88
  // What a resumed ship knows before its first stage: the record's path (absent outside a repository),
106
89
  // the stages it says completed, and the repository's actual state (`run-ship-stage.ts` decides from it).
107
90
  interface ShipContext {
@@ -124,58 +107,7 @@ function body_arguments(path: string | undefined): ReadonlyArray<string> {
124
107
  return path === undefined ? [] : [`--${BODY_FILE_OPTION}`, path]
125
108
  }
126
109
 
127
- const { STAGE, PHASE } = run_ship_stage
128
-
129
- // The four steps in the order a change ships: the gate before the commit, the commit/push/PR before
130
- // the merge, the merge before the report bookkeeping. The commit step carries the `--skip-*` flags a
131
- // resumed ship needs, so an existing commit or push is never made twice.
132
- async function josh(argv: ReadonlyArray<string>): Promise<JoshResult> {
133
- return await josh_command.josh_run(argv, should_forward_stderr)
134
- }
135
-
136
- const COMMIT_STEPS: ReadonlyArray<Step> = [
137
- { stage: STAGE.GATE, header: run_ship.GATE_HEADER, run: async () => await josh(['gate']) },
138
- {
139
- stage: STAGE.COMMIT,
140
- header: run_ship.COMMIT_HEADER,
141
- run: async (args, state) =>
142
- await josh(['git', '-y', ...run_ship_stage.commit_flags(state), ...args.body, args.title]),
143
- },
144
- ]
145
-
146
- const MERGE_STEPS: ReadonlyArray<Step> = [
147
- {
148
- stage: STAGE.FOLLOWUP,
149
- header: run_ship.FOLLOWUP_HEADER,
150
- run: async (args) => await josh(['followup', args.title, ...args.notify]),
151
- },
152
- {
153
- stage: STAGE.REPORT,
154
- header: run_ship.REPORT_HEADER,
155
- run: async (args) => await josh(['run:tail', args.number, ...args.cites]),
156
- },
157
- ]
158
-
159
- // `--review` (joshuafolkken/kit#2427) puts the supervised round-1 review in front of the gate: it
160
- // launches the gate itself, so the gate stage that follows reuses that tree's green record. It also
161
- // puts the round-2 pass between the commit and the followup (joshuafolkken/kit#2489), so the PR opens
162
- // between the rounds and round 2 runs beside CI — a no-op when round 1 left no fix delta.
163
- const REVIEW_STEP: Step = {
164
- stage: STAGE.REVIEW,
165
- header: run_ship.REVIEW_HEADER,
166
- run: async (args) => await run_ship_review_steps.review_stage(args.number),
167
- }
168
- const ROUND_TWO_STEP: Step = {
169
- stage: STAGE.ROUND_TWO,
170
- header: run_ship.ROUND_TWO_HEADER,
171
- run: async (args) => await run_ship_review_steps.round_two_stage(args.number),
172
- }
173
-
174
- function steps(args: ShipArguments): ReadonlyArray<Step> {
175
- if (!args.is_review) return [...COMMIT_STEPS, ...MERGE_STEPS]
176
-
177
- return [REVIEW_STEP, ...COMMIT_STEPS, ROUND_TWO_STEP, ...MERGE_STEPS]
178
- }
110
+ const { PHASE } = run_ship_stage
179
111
 
180
112
  function issue_number(title: string): string | undefined {
181
113
  return TRAILING_ISSUE_PATTERN.exec(title)?.[NUMBER_GROUP]
@@ -211,6 +143,7 @@ function ship_args(
211
143
  number,
212
144
  notify: notify_arguments(values),
213
145
  body: body_arguments(values[BODY_FILE_OPTION]),
146
+ body_path: values[BODY_FILE_OPTION],
214
147
  cites,
215
148
  is_review: values.review === true,
216
149
  is_detach: values.detach === true,
@@ -323,23 +256,27 @@ async function stopped(
323
256
  args: ShipArguments,
324
257
  stage: Stage,
325
258
  ): Promise<ReadonlyArray<ShipSection>> {
326
- if (run_ship_detach.is_supervised()) await run_ship_return.return_control(args.number, stage)
259
+ if (run_ship_detach.is_supervised()) {
260
+ await run_ship_return.return_control(args.number, stage, run_ship_next.resume_of(args))
261
+ }
327
262
 
328
263
  return sections
329
264
  }
330
265
 
331
- // Run the four in order, stopping at the first that failed: a red gate never reaches the commit, so
266
+ // Run the stages in order, stopping at the first that failed: a red gate never reaches the commit, so
332
267
  // the returned sections end at the failure the report names. A ship that reached the end clears its
333
- // record, so the next ship of the same issue starts from the gate.
268
+ // record, so the next ship of the same issue starts from the preflight.
334
269
  async function ship(args: ShipArguments): Promise<ReadonlyArray<ShipSection>> {
335
270
  const context = await open_context(args)
336
271
  const sections: Array<ShipSection> = []
337
272
 
338
- for (const step of steps(args)) {
273
+ for (const step of run_ship_steps.steps(args)) {
274
+ // eslint-disable-next-line no-await-in-loop -- stages run in order and the first failure stops the ship
339
275
  const section = await run_stage(step, args, context)
340
276
 
341
277
  sections.push(section)
342
278
 
279
+ // eslint-disable-next-line no-await-in-loop -- stages run in order and the first failure stops the ship
343
280
  if (section.code !== SUCCESS_EXIT_CODE) return await stopped(sections, args, step.stage)
344
281
  }
345
282
 
@@ -392,6 +329,19 @@ function should_detach(args: ShipArguments): boolean {
392
329
  return !run_ship_detach.is_supervised() && lane_child_marker.is_child_of(process.cwd())
393
330
  }
394
331
 
332
+ // joshuafolkken/kit#2966: the preflight is deterministic and fast, so it runs here, in the agent's own
333
+ // turn, before the hand-off — a stop it finds is fixed by the same session instead of relaunching one
334
+ // from the supervisor. Only the slow stages go to the supervisor, which re-asks the preflight itself.
335
+ async function detach_after_preflight(args: ShipArguments): Promise<number> {
336
+ const section = await run_stage(run_ship_steps.PREFLIGHT_STEP, args, await open_context(args))
337
+
338
+ if (section.code === SUCCESS_EXIT_CODE) return await detach(args)
339
+
340
+ console.info(run_ship.format_report([section]))
341
+
342
+ return run_ship.exit_code([section])
343
+ }
344
+
395
345
  async function supervised_repository(): Promise<string | undefined> {
396
346
  return run_ship_detach.is_supervised() ? await run_ship_probe.repository_directory() : undefined
397
347
  }
@@ -414,7 +364,7 @@ async function run_ship_command(args: ShipArguments): Promise<number> {
414
364
  if (should_detach(args)) {
415
365
  if (!args.is_detach) console.error(LANE_CHILD_DETACH_NOTE)
416
366
 
417
- return await detach(args)
367
+ return await detach_after_preflight(args)
418
368
  }
419
369
 
420
370
  await claim_supervised_identity(args)
@@ -444,7 +394,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
444
394
  process.exitCode = await run(argv)
445
395
  }
446
396
 
447
- const run_ship_cli = { SUCCESS_EXIT_CODE, USAGE, main, parse, run, ship }
397
+ const run_ship_cli = { run }
448
398
 
449
399
  if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
450
400
 
@@ -195,6 +195,7 @@ async function ready_record(repository: string, number: string): Promise<ShipRec
195
195
  for (let attempt = 0; attempt < RECORD_WAIT_ATTEMPTS; attempt += 1) {
196
196
  if (!is_pending(record)) return record
197
197
 
198
+ // eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
198
199
  await sleep(RECORD_POLL_MS)
199
200
  record = current_record(repository, number)
200
201
  }
@@ -0,0 +1,106 @@
1
+ import { run_ship_stage, type Stage } from './run-ship-stage'
2
+ import type { ShipArguments } from './run-ship-steps'
3
+
4
+ // The command a relaunched lane child runs once it has fixed what stopped its detached ship
5
+ // (joshuafolkken/kit#2964). The ship-stop prompt used to say only "hand the region back per
6
+ // chain-rule.md", so every relaunched session searched that document and re-derived the next command
7
+ // — 179 reads of it in one run. The stopped stage decides the command mechanically, so it is decided
8
+ // here, once, and the prompt carries it. `chain-rule.md` step 0 stays the single source of the
9
+ // procedure; `ship-stop-prompt-document-rule.test.ts` holds every command below to it.
10
+ //
11
+ // The fix is left uncommitted on purpose: a dirty tree reads as not committed
12
+ // (`run-ship-probe.ts`), so a re-detached ship runs the gate and the commit again on the fixed tree
13
+ // instead of passing over them.
14
+ //
15
+ // **Every route is a re-detach.** The prompt only ever reaches a lane child, and a lane child's commit
16
+ // and push belong to the detached ship (`scripts/rules/lane-background.ts`), so a `josh git -y` here could never
17
+ // run. The rounds are the supervisor's too: under `--review` it skips a round 1 already recorded for the
18
+ // issue and asks `review:round2` itself after the commit (`run-ship-review-steps.ts`), so the fix delta
19
+ // is verified as round 2 rather than reviewed again as round 1.
20
+ //
21
+ // **The re-run carries the stopped ship's own options.** A preflight that stopped on missing live
22
+ // evidence asks for `--body-file`, and `followup` delivers the body from it; a command naming only
23
+ // the title would stop on the same evidence again, and drop the `--cite` follow-ups `run:tail` reads.
24
+
25
+ const { STAGE } = run_ship_stage
26
+
27
+ const COMMAND = {
28
+ LOG: 'pnpm josh ship --log',
29
+ DETACH: 'pnpm josh ship --detach',
30
+ DETACH_REVIEW: 'pnpm josh ship --detach --review',
31
+ } as const
32
+
33
+ // A single quote cannot appear inside single quotes, so it closes the quote, escapes one, and reopens.
34
+ const ESCAPED_QUOTE = String.raw`'\''`
35
+
36
+ // A token of only these characters means the same to the shell quoted or not, so it is left bare.
37
+ const BARE_WORD = /^[\w%+,./:=@-]+$/u
38
+
39
+ // What a stopped ship is re-run with: its title, every option it was started with, and whether it
40
+ // carried `--review` — the one option a route decides rather than repeats.
41
+ interface ShipResume {
42
+ title: string
43
+ flags: ReadonlyArray<string>
44
+ is_review: boolean
45
+ }
46
+
47
+ // Single quotes, so a `$` or a backtick in a title is never expanded by the shell that runs it.
48
+ function quoted(title: string): string {
49
+ return `'${title.split("'").join(ESCAPED_QUOTE)}'`
50
+ }
51
+
52
+ function shell_word(token: string): string {
53
+ return BARE_WORD.test(token) ? token : quoted(token)
54
+ }
55
+
56
+ // A supervised ship's notify tail is already file-form (`run-ship-detach.ts`), so every flag is a path
57
+ // or an issue number and fits the prompt.
58
+ function resume_of(args: ShipArguments): ShipResume {
59
+ const cites = args.cites.flatMap((cite) => ['--cite', cite])
60
+
61
+ return {
62
+ title: args.title,
63
+ flags: [...args.notify, ...args.body, ...cites],
64
+ is_review: args.is_review,
65
+ }
66
+ }
67
+
68
+ // The command prefix stays as written; only the stopped ship's own tokens are quoted where needed.
69
+ function ship_command(command: string, resume: ShipResume): string {
70
+ const words = [...resume.flags, resume.title].map((token) => shell_word(token))
71
+
72
+ return [command, ...words].join(' ')
73
+ }
74
+
75
+ // After the merge-side stages, or after round 2 — which is final — the re-detach reviews nothing.
76
+ function detach_again(resume: ShipResume): string {
77
+ return `leave the fix uncommitted and run \`${ship_command(COMMAND.DETACH, resume)}\`.`
78
+ }
79
+
80
+ // Before round 2 the re-run takes the stopped ship's own shape: `--review` only when it carried it. A
81
+ // reviewing ship skips its recorded round 1 and decides round 2 after the commit; a ship started
82
+ // without `--review` was re-detached after round 2, which is final, so it reviews nothing.
83
+ function detach_as_started(resume: ShipResume): string {
84
+ const command = resume.is_review ? COMMAND.DETACH_REVIEW : COMMAND.DETACH
85
+
86
+ return `leave the fix uncommitted and run \`${ship_command(command, resume)}\`.`
87
+ }
88
+
89
+ const AFTER_FIX: Record<Stage, (resume: ShipResume) => string> = {
90
+ [STAGE.PREFLIGHT]: detach_as_started,
91
+ [STAGE.REVIEW]: detach_as_started,
92
+ [STAGE.GATE]: detach_as_started,
93
+ [STAGE.COMMIT]: detach_as_started,
94
+ [STAGE.ROUND_TWO]: detach_again,
95
+ [STAGE.FOLLOWUP]: detach_again,
96
+ [STAGE.REPORT]: detach_again,
97
+ }
98
+
99
+ // Two lines' worth: read the stopped report, then the one command that resumes after the fix.
100
+ function next_step(issue: string, stage: Stage, resume: ShipResume): string {
101
+ return `Read the stopped report with \`${COMMAND.LOG} ${issue}\`, fix the ${stage} failure, then ${AFTER_FIX[stage](resume)}`
102
+ }
103
+
104
+ const run_ship_next = { COMMAND, next_step, quoted, resume_of }
105
+
106
+ export { run_ship_next, type ShipResume }
@@ -0,0 +1,87 @@
1
+ import { readFile } from 'node:fs/promises'
2
+ import { git_gh_command } from '#scripts/gh/git-gh-command'
3
+ import { changed_paths } from '#scripts/git/changed-paths'
4
+ import { git_branch } from '#scripts/git/git-branch'
5
+ import { git_preflight } from '#scripts/git/git-preflight'
6
+ import type { JoshResult } from '#scripts/josh/josh-run'
7
+ import { error_text } from '#scripts/lib/error-message'
8
+ import { live_evidence } from '#scripts/review/live-evidence'
9
+ import { run_ship_scoped } from './run-ship-scoped'
10
+
11
+ // `josh ship`'s first stage (joshuafolkken/kit#2946). A detached ship used to meet the pull request's
12
+ // preconditions only at the commit stage — `git -y`'s preflight — or at the merge — `followup`'s
13
+ // live-evidence refusal — each after the review and the gate had already run, so every such stop
14
+ // relaunched a session to repeat them. **Every precondition decidable before the review is asked here,
15
+ // and all of them are reported at once.** No check is new: the classification, issue and branch answers
16
+ // are `git_preflight.problems_of`, and the evidence answer is `live_evidence.verdict_for` over the same
17
+ // changed paths and the body this ship will deliver — `--body-file` when given, else the open PR's.
18
+ //
19
+ // The scoped pair runs last, met rather than stopped on (`run-ship-scoped.ts`), so the review and the
20
+ // gate start on a tree both checks are green on.
21
+
22
+ const SUCCESS_EXIT_CODE = 0
23
+ const FAILURE_EXIT_CODE = 1
24
+ const EVIDENCE_PROBLEM = `This change touches runtime code, but the PR body has no ${live_evidence.EVIDENCE_HEADING} section: run the acceptance criteria for real and pass the body with --body-file <path>.`
25
+
26
+ interface PreflightRequest {
27
+ title: string
28
+ body_path: string | undefined
29
+ }
30
+
31
+ async function body_text(body_path: string | undefined): Promise<string | undefined> {
32
+ if (body_path !== undefined) return await readFile(body_path, 'utf8')
33
+
34
+ return await git_gh_command.pr_get_body(await git_branch.current())
35
+ }
36
+
37
+ async function evidence_problems(body_path: string | undefined): Promise<Array<string>> {
38
+ const [paths, body] = await Promise.all([
39
+ changed_paths.read_changed_paths(false),
40
+ body_text(body_path),
41
+ ])
42
+
43
+ return live_evidence.verdict_for(paths, body) === 'required' ? [EVIDENCE_PROBLEM] : []
44
+ }
45
+
46
+ function refusal(problems: ReadonlyArray<string>): JoshResult {
47
+ const lines = problems.map((problem) => ` - ${problem}`)
48
+ const head = `${String(problems.length)} pull-request precondition(s) unmet before the review and the gate:`
49
+
50
+ return { code: FAILURE_EXIT_CODE, out: [head, ...lines].join('\n') }
51
+ }
52
+
53
+ // The reads here run in the ship's own process, where the commit stage's ran in a `git -y` child: a
54
+ // throw — a `--body-file` path that does not exist, a git read that failed — would escape `ship()`
55
+ // past the stop a supervised ship hands back on, so it is reported as one more unmet precondition.
56
+ // Each side is caught on its own, so one side's failed read never hides what the other side found.
57
+ async function caught(problems: Promise<Array<string>>): Promise<Array<string>> {
58
+ try {
59
+ return await problems
60
+ } catch (error) {
61
+ return [error_text.message_of(error)]
62
+ }
63
+ }
64
+
65
+ async function asked_problems(request: PreflightRequest): Promise<Array<string>> {
66
+ const [preflight, evidence] = await Promise.all([
67
+ caught(git_preflight.problems_of({ cli_input: request.title, will_open_pr: true })),
68
+ caught(evidence_problems(request.body_path)),
69
+ ])
70
+
71
+ return [...preflight, ...evidence]
72
+ }
73
+
74
+ async function stage(request: PreflightRequest): Promise<JoshResult> {
75
+ const problems = await asked_problems(request)
76
+
77
+ if (problems.length > 0) return refusal(problems)
78
+
79
+ const scoped = await run_ship_scoped.scoped_pair()
80
+
81
+ return scoped.code === SUCCESS_EXIT_CODE ? { code: SUCCESS_EXIT_CODE, out: 'ready' } : scoped
82
+ }
83
+
84
+ const run_ship_preflight = { EVIDENCE_PROBLEM, stage }
85
+
86
+ export type { PreflightRequest }
87
+ export { run_ship_preflight }
@@ -5,6 +5,7 @@ import { lane_registry, type LaneInfo } from '#scripts/lane/lane-registry'
5
5
  import { lane_relaunch } from '#scripts/lane/lane-relaunch'
6
6
  import { run_event_stream } from './run-event-stream'
7
7
  import { run_event_stream_emit } from './run-event-stream-emit'
8
+ import type { ShipResume } from './run-ship-next'
8
9
  import type { Stage } from './run-ship-stage'
9
10
 
10
11
  // How a detached `josh ship` supervisor hands a stopped stage back (joshuafolkken/kit#2428). The agent
@@ -47,14 +48,18 @@ function note(text: string): void {
47
48
  process.stderr.write(`${text}\n`)
48
49
  }
49
50
 
50
- async function return_control(issue: string, stage: Stage): Promise<ReturnOutcome> {
51
+ async function return_control(
52
+ issue: string,
53
+ stage: Stage,
54
+ resume: ShipResume,
55
+ ): Promise<ReturnOutcome> {
51
56
  await run_event_stream_emit.emit(run_event_stream.EVENT_KIND.SHIP_STOP, stop_text(issue, stage))
52
57
 
53
58
  const lane = await lane_to_relaunch(issue)
54
59
 
55
60
  if (lane === undefined) return 'recorded'
56
61
 
57
- const invocation = lane_child_invocation.ship_stop_invocation(issue)
62
+ const invocation = lane_child_invocation.ship_stop_invocation(issue, { stage, ...resume })
58
63
  const result = lane_relaunch.relaunch(
59
64
  lane,
60
65
  invocation,
@@ -69,7 +74,7 @@ async function return_control(issue: string, stage: Stage): Promise<ReturnOutcom
69
74
  return 'recorded'
70
75
  }
71
76
 
72
- const run_ship_return = { return_control, stop_text }
77
+ const run_ship_return = { return_control }
73
78
 
74
79
  export type { ReturnOutcome }
75
80
  export { run_ship_return }