@joshuafolkken/kit 1.1050.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 (581) hide show
  1. package/.claude/settings.json +9 -8
  2. package/.claude/skills/epic-commands/SKILL.md +5 -7
  3. package/.claude/skills/workflow-commands/SKILL.md +19 -11
  4. package/.claude/skills/workflow-commands/background-commands.md +4 -3
  5. package/.claude/skills/workflow-commands/backlogrun-child.md +1 -1
  6. package/.claude/skills/workflow-commands/backlogrun-lanes.md +8 -6
  7. package/.claude/skills/workflow-commands/backlogrun-progress.md +1 -1
  8. package/.claude/skills/workflow-commands/backlogrun-steps.md +10 -10
  9. package/.claude/skills/workflow-commands/backlogrun.md +2 -2
  10. package/.claude/skills/workflow-commands/chain-rule.md +4 -2
  11. package/.claude/skills/workflow-commands/delegation.md +3 -3
  12. package/.claude/skills/workflow-commands/followup-reference.md +1 -1
  13. package/.claude/skills/workflow-commands/followup.md +7 -3
  14. package/.claude/skills/workflow-commands/fullrun-steps.md +3 -2
  15. package/.claude/skills/workflow-commands/fullrun.md +3 -2
  16. package/.claude/skills/workflow-commands/halfrun.md +16 -19
  17. package/.claude/skills/workflow-commands/issue-comments.md +1 -1
  18. package/.claude/skills/workflow-commands/issue-fold-existing.md +10 -10
  19. package/.claude/skills/workflow-commands/issue-scout.md +1 -1
  20. package/.claude/skills/workflow-commands/kickoff.md +9 -4
  21. package/.claude/skills/workflow-commands/latest-gate.md +1 -1
  22. package/.claude/skills/workflow-commands/needs-human-review.md +1 -1
  23. package/.claude/skills/workflow-commands/observation-filing.md +3 -3
  24. package/.claude/skills/workflow-commands/prerequisite.md +1 -1
  25. package/.claude/skills/workflow-commands/prrun.md +36 -0
  26. package/.claude/skills/workflow-commands/retrospective.md +1 -1
  27. package/.claude/skills/workflow-commands/working-tree-hold.md +22 -2
  28. package/.codex/hooks.json +16 -20
  29. package/.github/actions/setup-pnpm/action.yml +93 -0
  30. package/.github/dependabot.yml +5 -1
  31. package/.github/workflows/ci.yml +26 -128
  32. package/.github/workflows/pr-classification.yml +5 -41
  33. package/.github/workflows/publish.yml +33 -38
  34. package/.github/workflows/sonar-qube.yml +37 -4
  35. package/AGENTS.md +12 -2
  36. package/CLAUDE.md +15 -16
  37. package/GEMINI.md +14 -2
  38. package/README.md +59 -18
  39. package/SECURITY.md +36 -6
  40. package/cspell/index.yaml +2 -1
  41. package/dist/CLAUDE.md +15 -16
  42. package/dist/config-merge/index.js +15 -3
  43. package/dist/hooks/batch-guard.js +4 -4
  44. package/dist/hooks/{chunk-HJIISEAC.js → chunk-3C4YCCEF.js} +5 -13
  45. package/dist/hooks/{chunk-EJDX2TOB.js → chunk-7ZPFAVR7.js} +7 -88
  46. package/dist/hooks/{chunk-WQ4OSBSS.js → chunk-E54KGFEQ.js} +2 -2
  47. package/dist/hooks/{chunk-GQ7KP45M.js → chunk-IL27YTPH.js} +2 -2
  48. package/dist/hooks/{chunk-DMQN45FN.js → chunk-KHWHKJOM.js} +3 -3
  49. package/dist/hooks/{chunk-5BK3K7V4.js → chunk-M2XDCUKD.js} +997 -478
  50. package/dist/hooks/{chunk-7VPDUBRN.js → chunk-NKOG3XAV.js} +150 -153
  51. package/dist/hooks/{chunk-NJQOBE6L.js → chunk-O4LL4HTI.js} +2 -7
  52. package/dist/hooks/{chunk-NAS4C7GP.js → chunk-OIZUHPJI.js} +2 -2
  53. package/dist/hooks/{chunk-RLDX5SOC.js → chunk-UD24EAIL.js} +2084 -1412
  54. package/dist/hooks/codex-hook-adapter.js +10 -11
  55. package/dist/hooks/duplicate-read-guard.js +5 -5
  56. package/dist/hooks/format-edited.js +2 -2
  57. package/dist/hooks/inputs.json +279 -0
  58. package/dist/hooks/investigation-guard.js +5 -5
  59. package/dist/hooks/pretool-guard.js +9 -9
  60. package/dist/hooks/session-lang.js +0 -1
  61. package/dist/hooks/stop-guard.js +178 -324
  62. package/dist/josh.js +162 -119
  63. package/dist/managed-marker/index.js +2 -1
  64. package/dist/version/index.js +34 -58
  65. package/eslint/rules/promise.js +5 -0
  66. package/package.json +9 -4
  67. package/prompts/collaboration-workflow/issue-citation.md +5 -5
  68. package/prompts/collaboration-workflow/operating-rules.md +4 -4
  69. package/prompts/collaboration-workflow/overview.md +13 -1
  70. package/prompts/collaboration-workflow/report-format.md +1 -1
  71. package/prompts/collaboration-workflow/residency.md +3 -3
  72. package/prompts/collaboration-workflow/rule-delivery.md +1 -1
  73. package/prompts/collaboration-workflow/turn-batching.md +3 -3
  74. package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
  75. package/prompts/collaboration-workflow/wip-cap.md +25 -22
  76. package/prompts/collaboration-workflow.md +5 -8
  77. package/prompts/review-rubric.md +1 -1
  78. package/prompts/review.md +3 -3
  79. package/prompts/sonar-hotspot-handling.md +11 -3
  80. package/prompts/testing-guide.md +3 -3
  81. package/scripts/adopt/adopt-toolkits.ts +0 -2
  82. package/scripts/adopt/adopt.ts +0 -2
  83. package/scripts/agent/agent-argv.ts +0 -2
  84. package/scripts/agent/agent-diagnostics.ts +1 -1
  85. package/scripts/agent/agent-role-profile.ts +0 -7
  86. package/scripts/agent/claude-agent-argv.ts +0 -2
  87. package/scripts/agent/codex-agent-argv.ts +1 -1
  88. package/scripts/agent/codex-hooks.ts +92 -0
  89. package/scripts/agent/interactive-ask.ts +1 -1
  90. package/scripts/auto-ok/auto-ok-cli.ts +6 -16
  91. package/scripts/backlog/backlog-budget.ts +0 -2
  92. package/scripts/backlog/backlog-defect-priority.ts +2 -2
  93. package/scripts/backlog/backlog-drive-cli.ts +10 -8
  94. package/scripts/backlog/backlog-drive-named-offer.ts +16 -3
  95. package/scripts/backlog/backlog-drive-named.ts +2 -1
  96. package/scripts/backlog/backlog-drive.ts +76 -16
  97. package/scripts/backlog/backlog-named.ts +0 -3
  98. package/scripts/backlog/backlog-next.ts +9 -15
  99. package/scripts/backlog/backlog-offer-cli.ts +0 -5
  100. package/scripts/backlog/backlog-plan-cli.ts +1 -7
  101. package/scripts/backlog/backlog-plan.ts +1 -1
  102. package/scripts/backlog/backlog-pool.ts +3 -6
  103. package/scripts/backlog/backlog-rank.ts +2 -2
  104. package/scripts/backlog/backlog-ready.ts +19 -3
  105. package/scripts/backlog/backlog-scope.ts +1 -3
  106. package/scripts/backlog/backlog-stalled-detect.ts +2 -2
  107. package/scripts/backlog/backlog-stalled.ts +0 -1
  108. package/scripts/backlog/backlog-waves.ts +5 -2
  109. package/scripts/behavior/behavior-cli.ts +1 -1
  110. package/scripts/build/build-codex-hooks.ts +26 -0
  111. package/scripts/build/build-hooks.ts +85 -9
  112. package/scripts/build/hook-bundle-stamp.ts +111 -0
  113. package/scripts/cases/cases-cli.ts +1 -1
  114. package/scripts/cases/cases-logic.ts +1 -1
  115. package/scripts/ci/composite-actions.ts +30 -0
  116. package/scripts/ci/pr-classification.ts +3 -3
  117. package/scripts/claude/workflow-destination.ts +10 -1
  118. package/scripts/clone/clone-fingerprint.ts +0 -1
  119. package/scripts/clone/clone-scan-cli.ts +1 -1
  120. package/scripts/clone/clone-scan.ts +1 -1
  121. package/scripts/config-merge/json-format.ts +0 -1
  122. package/scripts/config-merge/patch-yaml-list.ts +1 -1
  123. package/scripts/cost-runtime/codex-usage.ts +2 -9
  124. package/scripts/cost-runtime/cost-attribute.ts +0 -1
  125. package/scripts/cost-runtime/cost-cli.ts +0 -3
  126. package/scripts/cost-runtime/cost-corpus.ts +0 -2
  127. package/scripts/cost-runtime/cost-format.ts +0 -3
  128. package/scripts/cost-runtime/cost-pricing.ts +0 -1
  129. package/scripts/cost-runtime/cost-tokens.ts +0 -1
  130. package/scripts/delegation/delegation-cli.ts +1 -1
  131. package/scripts/delegation/delegation-policy.ts +0 -1
  132. package/scripts/delegation/duplicate-read-guard.ts +0 -8
  133. package/scripts/delegation/fanout-cli.ts +1 -1
  134. package/scripts/delegation/fanout.ts +0 -2
  135. package/scripts/delegation/investigation-reads.ts +1 -164
  136. package/scripts/discovery/repo-map-logic.ts +0 -1
  137. package/scripts/discovery/repo-party-cli.ts +1 -1
  138. package/scripts/doctor/doctor-consumer.ts +4 -6
  139. package/scripts/doctor/doctor-logic.ts +0 -4
  140. package/scripts/doctor/doctor.ts +14 -9
  141. package/scripts/document/document-byte-budget.ts +4 -5
  142. package/scripts/document/document-byte-check.ts +0 -1
  143. package/scripts/document/document-read-cli.ts +0 -2
  144. package/scripts/document/document-section-cli.ts +1 -1
  145. package/scripts/document/document-section.ts +0 -3
  146. package/scripts/document/edit-files-cli.ts +0 -1
  147. package/scripts/document/entry-read-budget.ts +10 -2
  148. package/scripts/document/lane-child-read-set.ts +1 -6
  149. package/scripts/document/read-files-cli.ts +0 -4
  150. package/scripts/document/read-set-cli.ts +0 -2
  151. package/scripts/document/read-set-point-of-use.ts +1 -0
  152. package/scripts/document/read-set-pricing.ts +0 -1
  153. package/scripts/document/read-set-trim.ts +1 -1
  154. package/scripts/epic/epic-add.ts +1 -1
  155. package/scripts/epic/epic-audit-cli.ts +1 -4
  156. package/scripts/epic/epic-audit-orphans.ts +1 -3
  157. package/scripts/epic/epic-audit-rationale.ts +0 -1
  158. package/scripts/epic/epic-audit-report.ts +0 -2
  159. package/scripts/epic/epic-audit.ts +5 -4
  160. package/scripts/epic/epic-bundle-cli.ts +1 -1
  161. package/scripts/epic/epic-bundle-evidence.ts +0 -1
  162. package/scripts/epic/epic-bundle-referenced.ts +1 -5
  163. package/scripts/epic/epic-bundle.ts +0 -4
  164. package/scripts/epic/epic-busy.ts +4 -5
  165. package/scripts/epic/epic-candidate-confirm.ts +0 -5
  166. package/scripts/epic/epic-classify.ts +2 -2
  167. package/scripts/epic/epic-cli-argv.ts +0 -1
  168. package/scripts/epic/epic-close-comment.ts +1 -1
  169. package/scripts/epic/epic-close.ts +5 -2
  170. package/scripts/epic/epic-cross-repo.ts +2 -4
  171. package/scripts/epic/epic-decision.ts +0 -1
  172. package/scripts/epic/epic-fetch.ts +2 -2
  173. package/scripts/epic/epic-index.ts +2 -3
  174. package/scripts/epic/epic-issue.ts +1 -15
  175. package/scripts/epic/epic-lane-offer.ts +9 -8
  176. package/scripts/epic/epic-nested.ts +1 -1
  177. package/scripts/epic/epic-next-read.ts +1 -3
  178. package/scripts/epic/epic-next-views.ts +0 -1
  179. package/scripts/epic/epic-next.ts +1 -10
  180. package/scripts/epic/epic-parse.ts +0 -1
  181. package/scripts/epic/epic-promote.ts +0 -9
  182. package/scripts/epic/epic-rank.ts +2 -2
  183. package/scripts/epic/epic-read.ts +1 -2
  184. package/scripts/epic/epic-reconcile.ts +1 -1
  185. package/scripts/epic/epic-reference.ts +1 -13
  186. package/scripts/epic/epic-relation-recheck.ts +1 -1
  187. package/scripts/epic/epic-relations.ts +1 -1
  188. package/scripts/epic/epic-remove.ts +1 -1
  189. package/scripts/epic/epic-report.ts +0 -1
  190. package/scripts/epic/epic-run.ts +2 -3
  191. package/scripts/epic/epic-shape.ts +1 -1
  192. package/scripts/epic/epic-solo-stale.ts +107 -0
  193. package/scripts/epic/epic-solo.ts +3 -2
  194. package/scripts/epic/epic-triage.ts +1 -1
  195. package/scripts/epic/epic-validate.ts +1 -1
  196. package/scripts/epic/epic.ts +1 -1
  197. package/scripts/exports/unused-members-cli.ts +53 -0
  198. package/scripts/{git → followup}/followup-issue-number.ts +1 -6
  199. package/scripts/{git → followup}/git-followup-cleanup.ts +2 -1
  200. package/scripts/{git → followup}/git-followup-finish.ts +1 -3
  201. package/scripts/{git → followup}/git-followup-flush.ts +2 -2
  202. package/scripts/{git → followup}/git-followup-issue-close.ts +2 -2
  203. package/scripts/{git → followup}/git-followup-label.ts +4 -4
  204. package/scripts/followup/git-followup-merged.ts +112 -0
  205. package/scripts/{git → followup}/git-followup-pending.ts +1 -1
  206. package/scripts/{git → followup}/git-followup-workflow.ts +19 -11
  207. package/scripts/{git → followup}/git-pr-followup-wrapup.ts +9 -3
  208. package/scripts/{git → followup}/git-pr-followup.ts +53 -16
  209. package/scripts/gate/core-budget.ts +3 -9
  210. package/scripts/gate/gate-plan.ts +7 -4
  211. package/scripts/gate/gate-report.ts +0 -6
  212. package/scripts/gate/gate-tree.ts +1 -1
  213. package/scripts/gate/pre-commit-type-check.ts +0 -6
  214. package/scripts/gate/project-checks.ts +7 -8
  215. package/scripts/gate/scoped-green.ts +0 -1
  216. package/scripts/gate/type-check-step.ts +1 -1
  217. package/scripts/gate/verification-gate.ts +0 -2
  218. package/scripts/gh/fix-gh-packages.ts +15 -12
  219. package/scripts/gh/gh-spawn.ts +2 -2
  220. package/scripts/{git → gh}/git-ai-review-scan.ts +1 -5
  221. package/scripts/{git → gh}/git-gh-check.ts +2 -1
  222. package/scripts/{git → gh}/git-gh-exec.ts +1 -1
  223. package/scripts/{git → gh}/git-gh-failure.ts +1 -1
  224. package/scripts/{git → gh}/git-gh-helpers.ts +0 -1
  225. package/scripts/{git → gh}/git-gh-issue-list.ts +2 -0
  226. package/scripts/{git → gh}/git-gh-issue-read.ts +1 -1
  227. package/scripts/{git → gh}/git-gh-issue-rest.ts +6 -3
  228. package/scripts/{git → gh}/git-gh-pr-read.ts +24 -0
  229. package/scripts/{git → gh}/git-gh-pr-rest.ts +5 -2
  230. package/scripts/{git → gh}/git-gh-pr-review.ts +2 -2
  231. package/scripts/{git → gh}/git-gh-pr-rollup.ts +1 -3
  232. package/scripts/{git → gh}/git-gh-pr.ts +3 -1
  233. package/scripts/{git → gh}/git-pr-ai-review.ts +2 -5
  234. package/scripts/{git → gh}/git-pr-checks-eval.ts +0 -10
  235. package/scripts/{git → gh}/git-pr-checks-parse.ts +4 -20
  236. package/scripts/{git → gh}/git-pr-checks.ts +2 -1
  237. package/scripts/{git → gh}/git-pr-coderabbit.ts +2 -5
  238. package/scripts/{git → gh}/git-pr-confirmation.ts +1 -3
  239. package/scripts/{git → gh}/git-pr-managed-config.ts +2 -3
  240. package/scripts/{git → gh}/git-pr.ts +3 -3
  241. package/scripts/git/changed-file-scope.ts +0 -1
  242. package/scripts/git/git-branch.ts +3 -6
  243. package/scripts/git/git-commit.ts +1 -1
  244. package/scripts/git/git-common-directory.ts +80 -24
  245. package/scripts/git/git-error.ts +66 -9
  246. package/scripts/git/git-issue.ts +1 -1
  247. package/scripts/git/git-preflight.ts +2 -2
  248. package/scripts/git/git-prompt.ts +6 -31
  249. package/scripts/git/git-push.ts +1 -1
  250. package/scripts/git/git-staging.ts +1 -0
  251. package/scripts/git/git-status.ts +1 -1
  252. package/scripts/git/git-workflow.ts +1 -1
  253. package/scripts/git/gone-branch.ts +1 -0
  254. package/scripts/git/listing-cutoff.ts +1 -1
  255. package/scripts/git/main-merge.ts +1 -1
  256. package/scripts/git/main-sync.ts +19 -1
  257. package/scripts/git/parse-json-array.ts +0 -3
  258. package/scripts/git/repository-lock.ts +16 -16
  259. package/scripts/git/{git-stash.ts → stash/git-stash.ts} +1 -1
  260. package/scripts/git/{stash-pop-args.ts → stash/stash-pop-args.ts} +1 -1
  261. package/scripts/git/{stash-pop-cli.ts → stash/stash-pop-cli.ts} +0 -1
  262. package/scripts/git/{stash-sweep-lock.ts → stash/stash-sweep-lock.ts} +3 -3
  263. package/scripts/hooks/codex-hook-adapter.ts +0 -1
  264. package/scripts/hooks/edited-cspell.ts +1 -1
  265. package/scripts/hooks/format-edited-file.ts +2 -0
  266. package/scripts/hooks/pre-push-unit.ts +0 -4
  267. package/scripts/hooks/pretool-guard.ts +22 -4
  268. package/scripts/hooks/reserved-run.ts +1 -1
  269. package/scripts/hooks/step-zero-notice.ts +76 -0
  270. package/scripts/hooks/stop-guard.ts +47 -21
  271. package/scripts/init/claude-plugin-config.ts +4 -5
  272. package/scripts/init/hook-command-rewrite.ts +16 -8
  273. package/scripts/init/hook-launch.ts +41 -15
  274. package/scripts/init/init-basic.ts +2 -5
  275. package/scripts/init/init-logic.ts +7 -0
  276. package/scripts/init/init.ts +0 -3
  277. package/scripts/init/project-profile.ts +6 -11
  278. package/scripts/init/start-exec.ts +1 -1
  279. package/scripts/init/start-setup-pr.ts +6 -6
  280. package/scripts/init/start-steps.ts +1 -0
  281. package/scripts/issue/behavior-change-lint.ts +0 -1
  282. package/scripts/issue/defect-rate-cli.ts +3 -3
  283. package/scripts/issue/defect-rate.ts +1 -2
  284. package/scripts/{git → issue}/git-next-issues.ts +3 -3
  285. package/scripts/issue/issue-backlinks-cli.ts +1 -5
  286. package/scripts/issue/issue-cite-cli.ts +2 -6
  287. package/scripts/issue/issue-cite.ts +0 -2
  288. package/scripts/issue/issue-classification.ts +1 -9
  289. package/scripts/issue/issue-closing-pr.ts +4 -4
  290. package/scripts/issue/issue-comment-cli.ts +2 -2
  291. package/scripts/issue/issue-file-cli.ts +5 -5
  292. package/scripts/issue/issue-file.ts +2 -2
  293. package/scripts/issue/issue-fold-cli.ts +1 -1
  294. package/scripts/issue/issue-fold-existing-cli.ts +1 -1
  295. package/scripts/{git → issue}/issue-labels.ts +8 -0
  296. package/scripts/issue/issue-lint-cli.ts +1 -1
  297. package/scripts/issue/issue-merged.ts +2 -2
  298. package/scripts/{git → issue}/issue-rank.ts +1 -1
  299. package/scripts/issue/issue-read-cli.ts +8 -47
  300. package/scripts/issue/issue-read.ts +0 -2
  301. package/scripts/issue/issue-report-failures.ts +80 -0
  302. package/scripts/issue/issue-scout-cli.ts +1 -7
  303. package/scripts/issue/issue-scout-closed.ts +2 -2
  304. package/scripts/issue/issue-scout.ts +0 -2
  305. package/scripts/issue/issue-state-cli.ts +5 -46
  306. package/scripts/issue/issue-state.ts +1 -5
  307. package/scripts/issue/markdown-section.ts +1 -1
  308. package/scripts/issue/measure-rerun-cli.ts +1 -1
  309. package/scripts/issue/reproduction-measure.ts +1 -1
  310. package/scripts/josh/cli-body.ts +1 -1
  311. package/scripts/josh/file-map-stamp.ts +0 -3
  312. package/scripts/josh/josh-command-map.ts +2 -0
  313. package/scripts/josh/josh-commands-ai.ts +9 -102
  314. package/scripts/josh/josh-commands-backlog.ts +5 -1
  315. package/scripts/josh/josh-commands-development.ts +8 -1
  316. package/scripts/josh/josh-commands-issue.ts +2 -2
  317. package/scripts/josh/josh-commands-maintenance.ts +7 -0
  318. package/scripts/josh/josh-commands-project.ts +6 -0
  319. package/scripts/josh/josh-commands-run.ts +114 -0
  320. package/scripts/josh/josh-commands-versioning.ts +8 -0
  321. package/scripts/josh/josh-commands-workflow.ts +2 -2
  322. package/scripts/josh/path-decision.ts +0 -3
  323. package/scripts/josh/process-owner.ts +16 -0
  324. package/scripts/josh/session-language-cli.ts +0 -1
  325. package/scripts/lane/lane-await.ts +3 -6
  326. package/scripts/lane/lane-capacity.ts +6 -3
  327. package/scripts/lane/lane-child-invocation.ts +20 -7
  328. package/scripts/lane/lane-cli.ts +1 -4
  329. package/scripts/lane/lane-close.ts +1 -3
  330. package/scripts/lane/lane-dispatch.ts +3 -4
  331. package/scripts/lane/lane-environment.ts +0 -9
  332. package/scripts/lane/lane-handoff.ts +38 -0
  333. package/scripts/lane/lane-launch-cli.ts +21 -11
  334. package/scripts/lane/lane-open.ts +0 -3
  335. package/scripts/lane/lane-output.ts +0 -1
  336. package/scripts/lane/lane-registry.ts +9 -0
  337. package/scripts/lane/openai-lane-ship.ts +2 -0
  338. package/scripts/lane/openai-lane-supervisor-decision.ts +2 -1
  339. package/scripts/lane/openai-lane-supervisor.ts +6 -4
  340. package/scripts/lane/openai-review-broker.ts +3 -0
  341. package/scripts/lib/bounded-pool.ts +1 -0
  342. package/scripts/lib/json-value.ts +5 -4
  343. package/scripts/lib/poll.ts +3 -1
  344. package/scripts/lib/timed-fetch.ts +15 -0
  345. package/scripts/lib/timeouts.ts +13 -0
  346. package/scripts/{yaml → lib}/yaml-document.ts +3 -1
  347. package/scripts/{bytes → lines}/bytes-command.ts +0 -2
  348. package/scripts/lines/lines-command.ts +0 -1
  349. package/scripts/lint/lint-related-scope.ts +0 -1
  350. package/scripts/lint/lint-related.ts +1 -1
  351. package/scripts/{git → notify}/telegram-notify.ts +2 -2
  352. package/scripts/{git → notify}/telegram-test.ts +4 -4
  353. package/scripts/observations/observation-ledger-home.ts +0 -1
  354. package/scripts/observations/observation-ledger-line.ts +0 -1
  355. package/scripts/observations/observation-ledger-migrate.ts +1 -1
  356. package/scripts/observations/observations-flush-landing.ts +3 -3
  357. package/scripts/observations/observations-flush.ts +2 -2
  358. package/scripts/overrides/lockfile-overrides.ts +1 -1
  359. package/scripts/overrides/overrides-logic.ts +1 -1
  360. package/scripts/package/package-scout-cli.ts +2 -7
  361. package/scripts/package/package-scout.ts +0 -2
  362. package/scripts/propagate/propagate-git-failure.ts +0 -1
  363. package/scripts/propagate/propagate-git.ts +0 -2
  364. package/scripts/propagate/propagate-publish.ts +2 -3
  365. package/scripts/propagate/propagate-run.ts +0 -2
  366. package/scripts/propagate/propagate-steps.ts +3 -5
  367. package/scripts/propagate/propagate-targets.ts +0 -4
  368. package/scripts/propagate/propagate.ts +0 -4
  369. package/scripts/refactor/import-graph.ts +0 -1
  370. package/scripts/refactor/refactor-lint.ts +0 -2
  371. package/scripts/refactor/refactor-scan.ts +0 -1
  372. package/scripts/refactor/refactor-targets.ts +0 -1
  373. package/scripts/registry-migration/migrate-logic.ts +0 -2
  374. package/scripts/registry-migration/migrate.ts +19 -9
  375. package/scripts/release/github-release-cli.ts +8 -6
  376. package/scripts/release/github-release-environment.ts +46 -0
  377. package/scripts/release/github-release.ts +151 -94
  378. package/scripts/release/release-history.ts +0 -1
  379. package/scripts/release/release-plan.ts +0 -1
  380. package/scripts/release/release-publish.ts +2 -3
  381. package/scripts/release/release-scope-cli.ts +1 -2
  382. package/scripts/release/release-tag.ts +2 -4
  383. package/scripts/repo/auto-merge-setting-logic.ts +1 -4
  384. package/scripts/repo/repo-setting.ts +1 -1
  385. package/scripts/repo/repository-labels.ts +3 -3
  386. package/scripts/repo/required-checks-logic.ts +206 -0
  387. package/scripts/repo/required-checks-report.ts +71 -0
  388. package/scripts/repo/ruleset-check-cli.ts +53 -0
  389. package/scripts/repo/ruleset-check.ts +147 -0
  390. package/scripts/report/report-lint-cli.ts +0 -4
  391. package/scripts/review/disposition-cli.ts +1 -1
  392. package/scripts/review/live-evidence.ts +1 -1
  393. package/scripts/review/review-attest-cli.ts +0 -6
  394. package/scripts/review/review-attest.ts +4 -16
  395. package/scripts/review/review-brief-cli.ts +23 -6
  396. package/scripts/review/review-brief.ts +21 -8
  397. package/scripts/review/review-diff-parts.ts +89 -0
  398. package/scripts/review/review-diff-write.ts +97 -0
  399. package/scripts/review/review-finding-ledger.ts +0 -1
  400. package/scripts/review/review-record-cli.ts +1 -1
  401. package/scripts/review/review-record.ts +0 -1
  402. package/scripts/review/review-round2-cli.ts +1 -1
  403. package/scripts/review/review-stamps.ts +0 -3
  404. package/scripts/review/review-tree.ts +14 -2
  405. package/scripts/rules/decision-oracle-stage.ts +18 -0
  406. package/scripts/rules/decision-oracle.ts +10 -7
  407. package/scripts/rules/delivered-rules.ts +9 -1
  408. package/scripts/rules/destructive-command.ts +119 -0
  409. package/scripts/rules/direct-filing.ts +1 -1
  410. package/scripts/rules/file-body.ts +0 -3
  411. package/scripts/rules/filing-cap.ts +0 -2
  412. package/scripts/rules/gh-api.ts +7 -2
  413. package/scripts/rules/git-argv.ts +18 -7
  414. package/scripts/rules/git-force.ts +0 -2
  415. package/scripts/rules/implementation-cut.ts +0 -1
  416. package/scripts/rules/index-guard.ts +71 -0
  417. package/scripts/rules/issue-citation.ts +50 -25
  418. package/scripts/rules/lane-background.ts +15 -7
  419. package/scripts/rules/lane-park.ts +13 -6
  420. package/scripts/rules/last-prompt.ts +1 -0
  421. package/scripts/rules/oracle-consulted.ts +1 -1
  422. package/scripts/rules/oracle-firing.ts +1 -0
  423. package/scripts/rules/oracle-list-cli.ts +0 -3
  424. package/scripts/rules/permission-guards.ts +14 -0
  425. package/scripts/rules/protected-files.ts +74 -0
  426. package/scripts/rules/reply-language.ts +1 -1
  427. package/scripts/rules/rule-body-guard.ts +0 -3
  428. package/scripts/rules/rule-value-cli.ts +0 -1
  429. package/scripts/rules/shell-body-trigger.ts +0 -1
  430. package/scripts/rules/shell-segments.ts +0 -1
  431. package/scripts/rules/stop-rules.ts +13 -5
  432. package/scripts/rules/tail-commands.ts +1 -1
  433. package/scripts/rules/test-declared-commit.ts +1 -1
  434. package/scripts/rules/third-party-write.ts +0 -1
  435. package/scripts/rules/worktree-guard.ts +26 -9
  436. package/scripts/run/run-carry-cli.ts +0 -2
  437. package/scripts/run/run-carry-stash.ts +2 -2
  438. package/scripts/run/run-carry-streak.ts +1 -1
  439. package/scripts/run/run-cut-cli.ts +0 -7
  440. package/scripts/run/run-cut.ts +8 -54
  441. package/scripts/run/run-ending-cli.ts +1 -1
  442. package/scripts/run/run-ending.ts +1 -4
  443. package/scripts/run/run-entry-cli.ts +101 -24
  444. package/scripts/run/run-entry.ts +0 -1
  445. package/scripts/run/run-event-cli.ts +0 -2
  446. package/scripts/run/run-event-follow.ts +1 -0
  447. package/scripts/run/run-event-render.ts +1 -1
  448. package/scripts/run/run-event-scope.ts +53 -4
  449. package/scripts/run/run-event-stream.ts +0 -3
  450. package/scripts/run/run-event-watch.ts +1 -0
  451. package/scripts/run/run-halfrun-resume.ts +20 -7
  452. package/scripts/run/run-headless.ts +2 -2
  453. package/scripts/run/run-hold-cli.ts +33 -10
  454. package/scripts/run/run-hold.ts +25 -5
  455. package/scripts/run/run-issue-number.ts +1 -1
  456. package/scripts/run/run-liveness-cli.ts +1 -1
  457. package/scripts/run/run-liveness.ts +2 -3
  458. package/scripts/run/run-merge-cli.ts +5 -13
  459. package/scripts/run/run-merge-steps.ts +5 -5
  460. package/scripts/run/run-merge.ts +1 -1
  461. package/scripts/run/run-next-cli.ts +1 -1
  462. package/scripts/run/run-parent-cut-hook.ts +0 -1
  463. package/scripts/run/run-preflight.ts +2 -9
  464. package/scripts/run/run-prep-cli.ts +2 -2
  465. package/scripts/run/run-prep-locate.ts +1 -1
  466. package/scripts/run/run-progress-cli.ts +4 -7
  467. package/scripts/run/run-progress-clock.ts +6 -34
  468. package/scripts/run/run-progress-config.ts +0 -4
  469. package/scripts/run/run-progress-read.ts +1 -2
  470. package/scripts/run/run-progress.ts +1 -2
  471. package/scripts/run/run-prrun-resume.ts +117 -0
  472. package/scripts/run/run-report-cli.ts +1 -2
  473. package/scripts/run/run-report.ts +0 -1
  474. package/scripts/run/run-retrospective.ts +1 -1
  475. package/scripts/run/run-review-cli.ts +0 -3
  476. package/scripts/run/run-review-steps.ts +2 -0
  477. package/scripts/run/run-review.ts +0 -2
  478. package/scripts/run/run-ship-cli.ts +21 -3
  479. package/scripts/run/run-ship-detach.ts +1 -0
  480. package/scripts/run/run-ship-next.ts +106 -0
  481. package/scripts/run/run-ship-preflight.ts +1 -1
  482. package/scripts/run/run-ship-return.ts +8 -3
  483. package/scripts/run/run-ship-review-steps.ts +18 -4
  484. package/scripts/run/run-ship-review.ts +11 -0
  485. package/scripts/run/run-ship-scoped.ts +1 -0
  486. package/scripts/run/run-ship-steps.ts +1 -1
  487. package/scripts/run/run-ship.ts +0 -1
  488. package/scripts/run/run-stage-read.ts +62 -0
  489. package/scripts/run/run-stage.ts +160 -0
  490. package/scripts/run/run-status-cli.ts +1 -1
  491. package/scripts/run/run-step-cli.ts +21 -14
  492. package/scripts/run/run-step.ts +1 -1
  493. package/scripts/run/run-stop-notify.ts +1 -3
  494. package/scripts/run/run-stranded-cli.ts +0 -4
  495. package/scripts/run/run-stranded-detect.ts +2 -2
  496. package/scripts/run/run-tail-cli.ts +17 -11
  497. package/scripts/run/run-tail.ts +2 -0
  498. package/scripts/run/run-tidy-lanes.ts +2 -1
  499. package/scripts/run/run-tidy-stashes.ts +12 -12
  500. package/scripts/run/run-wake-cli.ts +2 -3
  501. package/scripts/run/run-wake-loop.ts +2 -2
  502. package/scripts/run/run-wake.ts +2 -4
  503. package/scripts/run/run-watcher-guard-cli.ts +0 -4
  504. package/scripts/run/run-watcher-guard.ts +9 -7
  505. package/scripts/run/run-watcher-hook.ts +1 -1
  506. package/scripts/safe-chain/ci-installer-pin.ts +11 -5
  507. package/scripts/safe-chain/project-config.ts +1 -1
  508. package/scripts/security/security-audit-provision-logic.ts +0 -1
  509. package/scripts/security/security-audit-provision.ts +3 -2
  510. package/scripts/security/security-audit.ts +0 -1
  511. package/scripts/security/security-updates-logic.ts +0 -1
  512. package/scripts/sonar/sonar-hotspots-cli.ts +10 -52
  513. package/scripts/sonar/sonar-hotspots.ts +0 -1
  514. package/scripts/sonar/sonar-new-code-cli.ts +150 -0
  515. package/scripts/sonar/sonar-new-code.ts +79 -0
  516. package/scripts/sonar/sonar-project.ts +97 -0
  517. package/scripts/split/split-assess-cli.ts +1 -1
  518. package/scripts/split/split-assess.ts +2 -5
  519. package/scripts/sync/managed-config-scope-cli.ts +1 -1
  520. package/scripts/sync/skill-migration.ts +0 -1
  521. package/scripts/sync/sync-hook-safety.ts +2 -3
  522. package/scripts/sync/sync.ts +1 -8
  523. package/scripts/sync/template-source-logic.ts +0 -1
  524. package/scripts/sync/workflow-pin-logic.ts +16 -28
  525. package/scripts/test/test-declared-logic.ts +0 -1
  526. package/scripts/test/test-declared.ts +0 -2
  527. package/scripts/test/test-red-commit.ts +2 -2
  528. package/scripts/test/test-red.ts +14 -7
  529. package/scripts/test/test-type-logic.ts +1 -1
  530. package/scripts/test/unit-worker-share.ts +7 -16
  531. package/scripts/time-runtime/time-batch-guard.ts +1 -2
  532. package/scripts/time-runtime/time-bundle-call.ts +0 -1
  533. package/scripts/time-runtime/time-bundles.ts +0 -4
  534. package/scripts/time-runtime/time-density-hook.ts +0 -2
  535. package/scripts/time-runtime/time-followup-stage.ts +1 -1
  536. package/scripts/time-runtime/time-format.ts +0 -73
  537. package/scripts/time-runtime/time-round-trips.ts +0 -4
  538. package/scripts/time-runtime/time-single-check.ts +1 -1
  539. package/scripts/time-runtime/time-spans.ts +1 -1
  540. package/scripts/time-runtime/time-transcript-line.ts +1 -2
  541. package/scripts/ui/ui-routes-cli.ts +0 -5
  542. package/scripts/ui/ui-routes.ts +0 -5
  543. package/scripts/version/effective-upstream.ts +2 -2
  544. package/scripts/version/latest-corepack.ts +7 -9
  545. package/scripts/version/latest-scope-cli.ts +0 -2
  546. package/scripts/version/latest-update.ts +0 -2
  547. package/scripts/version/npm-registry.ts +2 -2
  548. package/scripts/version/publishable-range-check.ts +1 -1
  549. package/scripts/version/release-hold.ts +0 -4
  550. package/scripts/version/running-binary.ts +2 -2
  551. package/scripts/version/version-check-logic.ts +0 -2
  552. package/scripts/version/version-remote.ts +3 -3
  553. package/scripts/version/version-targets.ts +4 -4
  554. package/templates/sonar-project.properties +28 -1
  555. package/templates/workflows/dependabot-auto-merge.yml +5 -3
  556. package/templates/workflows/github-release.yml +81 -0
  557. package/prompts/collaboration-workflow/cross-repo-epic.md +0 -5
  558. package/prompts/collaboration-workflow/epic-audit.md +0 -5
  559. package/prompts/collaboration-workflow/epic-bundle.md +0 -5
  560. package/scripts/init/plugin-install-hint.ts +0 -47
  561. package/scripts/version/parse-json.ts +0 -13
  562. /package/scripts/{git → followup}/git-followup-stages.ts +0 -0
  563. /package/scripts/{git → gh}/git-gh-api-path.ts +0 -0
  564. /package/scripts/{git → gh}/git-gh-command.ts +0 -0
  565. /package/scripts/{git → gh}/git-gh-issue-write.ts +0 -0
  566. /package/scripts/{git → gh}/git-gh-issue.ts +0 -0
  567. /package/scripts/{git → gh}/git-gh-pr-auto-merge.ts +0 -0
  568. /package/scripts/{git → gh}/git-gh-pr-snapshot.ts +0 -0
  569. /package/scripts/{git → gh}/git-gh-reachability.ts +0 -0
  570. /package/scripts/{git → gh}/git-gh-repo.ts +0 -0
  571. /package/scripts/{git → gh}/git-gh-rest-state.ts +0 -0
  572. /package/scripts/{git → gh}/git-pr-checks-watch.ts +0 -0
  573. /package/scripts/{git → gh}/git-pr-error.ts +0 -0
  574. /package/scripts/{git → gh}/git-pr-messages.ts +0 -0
  575. /package/scripts/{git → gh}/github-issue-url.ts +0 -0
  576. /package/scripts/git/{stash-orphans.ts → stash/stash-orphans.ts} +0 -0
  577. /package/scripts/{git → issue}/issue-reference.ts +0 -0
  578. /package/scripts/{git → lib}/animation-helpers.ts +0 -0
  579. /package/scripts/{git → lib}/git-animation.ts +0 -0
  580. /package/scripts/{git → notify}/git-notify.ts +0 -0
  581. /package/scripts/{git → notify}/telegram-test-logic.ts +0 -0
@@ -28,7 +28,7 @@ import { run_progress_clock } from './run-progress-clock'
28
28
  // `run-progress-clock.ts`, because the trigger-delivered rule that refuses an early heartbeat reads
29
29
  // the same record from inside a `PreToolUse` hook and cannot await the git call this file makes
30
30
  // (joshuafolkken/kit#1570). What stays here is the asynchronous way of naming the work tree.
31
- const { PROGRESS_PREFIX, mark, parse_stamp, read_last_report } = run_progress_clock
31
+ const { mark, parse_stamp, read_last_report } = run_progress_clock
32
32
 
33
33
  const FIRST_LOAD_AVERAGE = 0
34
34
 
@@ -182,7 +182,6 @@ async function read_observations(request: ObservationRequest): Promise<Observati
182
182
  }
183
183
 
184
184
  const run_progress_read = {
185
- PROGRESS_PREFIX,
186
185
  has_run_started,
187
186
  live_target,
188
187
  log_target,
@@ -257,7 +257,7 @@ interface LineTiming {
257
257
  * this is that same move for one value.
258
258
  *
259
259
  * **It is a schedule rather than an observation, and the two conditions on it are said in prose**
260
- * (`docs/josh-commands.md` → `josh run:progress`): it holds only while the silence continues, and a
260
+ * (`docs/josh-commands-automation.md` → `josh run:progress`): it holds only while the silence continues, and a
261
261
  * real report arriving first restarts the clock through `--mark` and supersedes it. The line printing
262
262
  * it is itself a report, so the clock starts at this observation.
263
263
  */
@@ -367,7 +367,6 @@ const run_progress = {
367
367
  format_line,
368
368
  format_next_line,
369
369
  format_next_report,
370
- format_record,
371
370
  format_report,
372
371
  is_due,
373
372
  minutes_from,
@@ -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 }
@@ -6,6 +6,7 @@ import { run_event_stream } from './run-event-stream'
6
6
  import { run_event_stream_emit } from './run-event-stream-emit'
7
7
  import { run_ship, type ShipSection } from './run-ship'
8
8
  import { run_ship_detach } from './run-ship-detach'
9
+ import { run_ship_next } from './run-ship-next'
9
10
  import { run_ship_probe } from './run-ship-probe'
10
11
  import { run_ship_return } from './run-ship-return'
11
12
  import { run_ship_stage, type Phase, type ShipState, type Stage } from './run-ship-stage'
@@ -255,7 +256,9 @@ async function stopped(
255
256
  args: ShipArguments,
256
257
  stage: Stage,
257
258
  ): Promise<ReadonlyArray<ShipSection>> {
258
- 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
+ }
259
262
 
260
263
  return sections
261
264
  }
@@ -268,10 +271,12 @@ async function ship(args: ShipArguments): Promise<ReadonlyArray<ShipSection>> {
268
271
  const sections: Array<ShipSection> = []
269
272
 
270
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
271
275
  const section = await run_stage(step, args, context)
272
276
 
273
277
  sections.push(section)
274
278
 
279
+ // eslint-disable-next-line no-await-in-loop -- stages run in order and the first failure stops the ship
275
280
  if (section.code !== SUCCESS_EXIT_CODE) return await stopped(sections, args, step.stage)
276
281
  }
277
282
 
@@ -324,6 +329,19 @@ function should_detach(args: ShipArguments): boolean {
324
329
  return !run_ship_detach.is_supervised() && lane_child_marker.is_child_of(process.cwd())
325
330
  }
326
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
+
327
345
  async function supervised_repository(): Promise<string | undefined> {
328
346
  return run_ship_detach.is_supervised() ? await run_ship_probe.repository_directory() : undefined
329
347
  }
@@ -346,7 +364,7 @@ async function run_ship_command(args: ShipArguments): Promise<number> {
346
364
  if (should_detach(args)) {
347
365
  if (!args.is_detach) console.error(LANE_CHILD_DETACH_NOTE)
348
366
 
349
- return await detach(args)
367
+ return await detach_after_preflight(args)
350
368
  }
351
369
 
352
370
  await claim_supervised_identity(args)
@@ -376,7 +394,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
376
394
  process.exitCode = await run(argv)
377
395
  }
378
396
 
379
- const run_ship_cli = { SUCCESS_EXIT_CODE, USAGE, main, parse, run, ship }
397
+ const run_ship_cli = { run }
380
398
 
381
399
  if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
382
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 }
@@ -1,7 +1,7 @@
1
1
  import { readFile } from 'node:fs/promises'
2
+ import { git_gh_command } from '#scripts/gh/git-gh-command'
2
3
  import { changed_paths } from '#scripts/git/changed-paths'
3
4
  import { git_branch } from '#scripts/git/git-branch'
4
- import { git_gh_command } from '#scripts/git/git-gh-command'
5
5
  import { git_preflight } from '#scripts/git/git-preflight'
6
6
  import type { JoshResult } from '#scripts/josh/josh-run'
7
7
  import { error_text } from '#scripts/lib/error-message'
@@ -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 }
@@ -5,6 +5,7 @@ import { josh_command, type JoshResult } from '#scripts/josh/josh-run'
5
5
  import { stamp_file } from '#scripts/josh/stamp-file'
6
6
  import { lane_child_marker } from '#scripts/lane/lane-child-marker'
7
7
  import { openai_review_broker } from '#scripts/lane/openai-review-broker'
8
+ import { review_record } from '#scripts/review/review-record'
8
9
  import { detached_launch } from './detached-launch'
9
10
  import { run_ship_review, type RoundOutcome, type ScoredVerdict } from './run-ship-review'
10
11
  import { run_ship_scoped, type Phase } from './run-ship-scoped'
@@ -43,8 +44,10 @@ const ROUND_TWO_DECISION = ['review:round2', '--round-1-closed']
43
44
  const ROUND_TWO_BRIEF = ['review:brief', '--round', '2']
44
45
  const ROUND_TWO_REQUIRED = 'required'
45
46
  const FIXED_JOIN_NOTE =
46
- 'the round-1 gate read the tree before the review fixes — drained, not judged; the gate stage re-runs it.'
47
+ 'the round-1 gate read the tree before the review fixes — drained, not judged; the gate re-runs once the tree is fixed.'
47
48
  const ROUND_TWO_SKIPPED_NOTE = 'round 2 not due — nothing left to verify; shipping on.'
49
+ const ROUND_ONE_RECORDED_NOTE =
50
+ 'round 1 already recorded for this issue — not reviewed again; the gate reads the fixed tree and round 2 decides after the commit.'
48
51
 
49
52
  // The scoped pair's precondition, met by the supervisor itself rather than stopped on
50
53
  // (joshuafolkken/kit#2500), single-sourced with the preflight and gate stages (joshuafolkken/kit#2946).
@@ -125,12 +128,14 @@ function current_verdict(): ReturnType<typeof run_ship_review.read_verdict> {
125
128
 
126
129
  // A red join blocks unless the reviewer fixed findings in place: the background gate then read the
127
130
  // tree before the fixes, so its verdict describes a tree that no longer exists. The join still ran to
128
- // its end, so the gate stage that follows never races it.
131
+ // its end, so the gate stage that follows never races it. Any fix drains it, not only a round whose
132
+ // every finding was fixed — a partial fix moved the tree just the same, and the round then stops on its
133
+ // unfixed finding at the record rather than on a `Gate RED` the gate never earned (joshuafolkken/kit#2961).
129
134
  async function join_gate(): Promise<JoshResult> {
130
135
  const joined = await josh([RUN_REVIEW, '--join'])
131
136
 
132
137
  if (joined.code === SUCCESS_EXIT_CODE) return joined
133
- if (current_verdict().kind !== run_ship_review.VERDICT.FIXED) return joined
138
+ if (!run_ship_review.has_fixes(stamp_file.read_stamp_text(paths().findings))) return joined
134
139
 
135
140
  note(FIXED_JOIN_NOTE)
136
141
 
@@ -191,7 +196,16 @@ async function round_one_record(issue: string): Promise<JoshResult> {
191
196
 
192
197
  // The round-1 review, beside the gate: scoped pair → open → review → join → attest → record, stopping
193
198
  // at the first that did not pass.
199
+ //
200
+ // **A recorded round 1 is not run again** (joshuafolkken/kit#2964). A ship relaunched with `--review`
201
+ // after a round-1 stop would otherwise review the whole change a second time as round 1 — a new Medium
202
+ // there stops it again, and round 2 after the commit makes a third. The fix delta is round 2's to
203
+ // verify, and `round_two_stage` asks whether it is due after the commit.
194
204
  async function review_stage(issue: string): Promise<JoshResult> {
205
+ const recorded = await review_record.check(Number(issue))
206
+
207
+ if (recorded.status === 'ok') return { code: SUCCESS_EXIT_CODE, out: ROUND_ONE_RECORDED_NOTE }
208
+
195
209
  return await run_phases([
196
210
  scoped_pair,
197
211
  ...reviewed([RUN_REVIEW], run_ship_review.reviewer_prompt, issue, '1'),
@@ -221,6 +235,6 @@ async function round_two_stage(issue: string): Promise<JoshResult> {
221
235
  ])
222
236
  }
223
237
 
224
- const run_ship_review_steps = { paths, review_stage, round_two_stage }
238
+ const run_ship_review_steps = { review_stage, round_two_stage }
225
239
 
226
240
  export { run_ship_review_steps }
@@ -162,6 +162,16 @@ function is_clean_round_one(text: string | undefined): boolean {
162
162
  return read_verdict(text).kind === VERDICT.CLEAN
163
163
  }
164
164
 
165
+ // Whether the reviewer edited the tree — any finding marked fixed, whether or not another one still
166
+ // blocks (joshuafolkken/kit#2961). A partial fix moves the tree the background gate read as surely as a
167
+ // full one, so the join reads it red either way; keyed off the verdict kind instead, a round that fixed
168
+ // one Medium and left another stopped at a misleading `Gate RED` before its own blocking note.
169
+ function has_fixes(text: string | undefined): boolean {
170
+ if (text === undefined) return false
171
+
172
+ return spec_findings(text).some((finding) => finding.is_fixed)
173
+ }
174
+
165
175
  // Round 2 is final and reads only, so it passes clean or Low-only alone — a fix it made would itself be
166
176
  // unreviewed.
167
177
  function round_two_outcome(verdict: ScoredVerdict): RoundOutcome {
@@ -174,6 +184,7 @@ const run_ship_review = {
174
184
  FIXED_PREFIX,
175
185
  UNVERIFIED_OUTCOME,
176
186
  VERDICT,
187
+ has_fixes,
177
188
  is_clean_round_one,
178
189
  read_verdict,
179
190
  reviewer_prompt,
@@ -16,6 +16,7 @@ async function run_phases(phases: ReadonlyArray<Phase>): Promise<JoshResult> {
16
16
  let last: JoshResult = { code: SUCCESS_EXIT_CODE, out: '' }
17
17
 
18
18
  for (const phase of phases) {
19
+ // eslint-disable-next-line no-await-in-loop -- phases run in order and the first failure stops the rest
19
20
  last = await phase()
20
21
  if (last.code !== SUCCESS_EXIT_CODE) return last
21
22
  }
@@ -99,7 +99,7 @@ function steps(args: ShipArguments): ReadonlyArray<Step> {
99
99
  return [PREFLIGHT_STEP, REVIEW_STEP, ...COMMIT_STEPS, ROUND_TWO_STEP, ...MERGE_STEPS]
100
100
  }
101
101
 
102
- const run_ship_steps = { steps }
102
+ const run_ship_steps = { PREFLIGHT_STEP, steps }
103
103
 
104
104
  export type { ShipArguments, Step }
105
105
  export { run_ship_steps }
@@ -70,7 +70,6 @@ const run_ship = {
70
70
  ROUND_TWO_HEADER,
71
71
  SKIPPED_BODY,
72
72
  STOPPED_PREFIX,
73
- SUCCESS_EXIT_CODE,
74
73
  exit_code,
75
74
  failed_section,
76
75
  format_report,
@@ -0,0 +1,62 @@
1
+ import { has_label_name, PLANNED_LABEL } from '#scripts/issue/issue-labels'
2
+ import { issue_state_cli, type StateRead } from '#scripts/issue/issue-state-cli'
3
+ import { run_halfrun_resume } from './run-halfrun-resume'
4
+ import { run_prrun_resume, type PrrunToken } from './run-prrun-resume'
5
+ import { run_stage, type StageState } from './run-stage'
6
+
7
+ // The reading half of the stage ladder (joshuafolkken/kit#3042): the facts `run_stage.state_of` folds
8
+ // into one state, each read from where the stage that produced it left it — never from the
9
+ // conversation. A closed issue and the `run:planned` label come from GitHub; a `halfrun` stop and a `prrun`
10
+ // stop come from the stop's own mark on the tree's hold (`run-halfrun-resume.ts`,
11
+ // `run-prrun-resume.ts`).
12
+
13
+ const CLOSED = 'CLOSED'
14
+
15
+ interface StageRead {
16
+ state: StageState
17
+ // The `prrun` stop's resume token, kept so the entry acts on it without reading the pull request
18
+ // again; `undefined` when no `prrun` stop is recorded for the issue.
19
+ prrun_token: PrrunToken | undefined
20
+ }
21
+
22
+ function is_closed(read: StateRead): boolean {
23
+ return read.kind === 'state' && read.state.state === CLOSED
24
+ }
25
+
26
+ function is_planned(read: StateRead): boolean {
27
+ return read.kind === 'state' && has_label_name(read.state.labels, PLANNED_LABEL)
28
+ }
29
+
30
+ // The two stops are one hold record, so at most one is present; the `prrun` one is asked only when the
31
+ // `halfrun` one is not, which spares its pull-request read.
32
+ async function read_stop(
33
+ issue: string,
34
+ ): Promise<{ is_halfrun_stopped: boolean; prrun_token: PrrunToken | undefined }> {
35
+ if (await run_halfrun_resume.is_pending(issue)) {
36
+ return { is_halfrun_stopped: true, prrun_token: undefined }
37
+ }
38
+
39
+ return { is_halfrun_stopped: false, prrun_token: await run_prrun_resume.resume_token(issue) }
40
+ }
41
+
42
+ // An unreadable issue reads as neither closed nor planned: the ordinary entry that follows reads it
43
+ // again and answers `unknown` for it, exactly as before the ladder existed.
44
+ async function read_stage(issue: string): Promise<StageRead> {
45
+ const [issue_read, stop] = await Promise.all([
46
+ issue_state_cli.read_issue(issue),
47
+ read_stop(issue),
48
+ ])
49
+ const state = run_stage.state_of({
50
+ is_closed: is_closed(issue_read),
51
+ is_prrun_stopped: stop.prrun_token !== undefined,
52
+ is_halfrun_stopped: stop.is_halfrun_stopped,
53
+ is_planned: is_planned(issue_read),
54
+ })
55
+
56
+ return { state, prrun_token: stop.prrun_token }
57
+ }
58
+
59
+ const run_stage_read = { read_stage }
60
+
61
+ export type { StageRead }
62
+ export { run_stage_read }