@joshuafolkken/kit 1.1050.0 → 1.1128.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 (630) 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 +20 -12
  4. package/.claude/skills/workflow-commands/background-commands.md +36 -84
  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 +30 -33
  8. package/.claude/skills/workflow-commands/backlogrun-steps.md +12 -12
  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 +8 -6
  16. package/.claude/skills/workflow-commands/halfrun.md +19 -21
  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 +8 -16
  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/pre-gate-cut.md +4 -8
  25. package/.claude/skills/workflow-commands/prerequisite.md +1 -1
  26. package/.claude/skills/workflow-commands/prrun.md +36 -0
  27. package/.claude/skills/workflow-commands/retrospective.md +1 -1
  28. package/.claude/skills/workflow-commands/split-assessment.md +4 -18
  29. package/.claude/skills/workflow-commands/working-tree-hold.md +22 -2
  30. package/.codex/hooks.json +16 -20
  31. package/.github/actions/setup-node/action.yml +33 -0
  32. package/.github/actions/setup-pnpm/action.yml +93 -0
  33. package/.github/dependabot.yml +5 -1
  34. package/.github/workflows/auto-tag.yml +2 -3
  35. package/.github/workflows/ci.yml +31 -134
  36. package/.github/workflows/dependabot-auto-merge.yml +1 -0
  37. package/.github/workflows/pr-classification.yml +6 -44
  38. package/.github/workflows/production.yml +1 -0
  39. package/.github/workflows/publish.yml +43 -47
  40. package/.github/workflows/sonar-qube.yml +41 -4
  41. package/.pnpmfile.mjs +29 -0
  42. package/AGENTS.md +5 -2
  43. package/CLAUDE.md +33 -27
  44. package/GEMINI.md +5 -2
  45. package/README.md +66 -20
  46. package/SECURITY.md +37 -6
  47. package/cspell/index.yaml +6 -1
  48. package/dist/CLAUDE.basic.md +6 -6
  49. package/dist/CLAUDE.md +33 -27
  50. package/dist/CLAUDE.static.md +6 -6
  51. package/dist/config-merge/index.js +48 -12
  52. package/dist/hooks/batch-guard.js +4 -4
  53. package/dist/hooks/{chunk-7VPDUBRN.js → chunk-4JZDP5X5.js} +152 -155
  54. package/dist/hooks/{chunk-HJIISEAC.js → chunk-5SD2YM7Z.js} +5 -13
  55. package/dist/hooks/{chunk-NAS4C7GP.js → chunk-77J7IEQM.js} +2 -2
  56. package/dist/hooks/{chunk-DMQN45FN.js → chunk-7HVB7SZG.js} +3 -3
  57. package/dist/hooks/{chunk-RLDX5SOC.js → chunk-AIOIOMPX.js} +4413 -1970
  58. package/dist/hooks/{chunk-5BK3K7V4.js → chunk-M7QKEKWO.js} +873 -2049
  59. package/dist/hooks/{chunk-WQ4OSBSS.js → chunk-MKVGBQPA.js} +2 -2
  60. package/dist/hooks/{chunk-EJDX2TOB.js → chunk-NXYMNPUQ.js} +7 -88
  61. package/dist/hooks/{chunk-NJQOBE6L.js → chunk-QVLT52OV.js} +2 -7
  62. package/dist/hooks/{chunk-GQ7KP45M.js → chunk-XYUIQOW3.js} +2 -2
  63. package/dist/hooks/codex-hook-adapter.js +12 -48
  64. package/dist/hooks/duplicate-read-guard.js +5 -5
  65. package/dist/hooks/format-edited.js +2 -2
  66. package/dist/hooks/inputs.json +280 -0
  67. package/dist/hooks/investigation-guard.js +5 -5
  68. package/dist/hooks/pretool-guard.js +9 -9
  69. package/dist/hooks/session-lang.js +0 -1
  70. package/dist/hooks/stop-guard.js +192 -333
  71. package/dist/josh.js +240 -148
  72. package/dist/managed-marker/index.js +2 -1
  73. package/dist/version/index.js +70 -78
  74. package/eslint/rules/promise.js +5 -0
  75. package/eslint/rules/unicorn.js +3 -2
  76. package/package.json +26 -5
  77. package/pnpm-workspace.yaml +5 -7
  78. package/prompts/collaboration-workflow/glossary.md +17 -0
  79. package/prompts/collaboration-workflow/issue-citation.md +5 -5
  80. package/prompts/collaboration-workflow/issue-template.md +1 -1
  81. package/prompts/collaboration-workflow/operating-rules.md +5 -5
  82. package/prompts/collaboration-workflow/overview.md +13 -1
  83. package/prompts/collaboration-workflow/principles.md +9 -0
  84. package/prompts/collaboration-workflow/report-format.md +1 -1
  85. package/prompts/collaboration-workflow/residency.md +3 -3
  86. package/prompts/collaboration-workflow/rule-delivery.md +1 -1
  87. package/prompts/collaboration-workflow/turn-batching.md +3 -3
  88. package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
  89. package/prompts/collaboration-workflow/wip-cap.md +25 -22
  90. package/prompts/collaboration-workflow.md +6 -8
  91. package/prompts/review-rubric.md +1 -1
  92. package/prompts/review.md +3 -3
  93. package/prompts/sonar-hotspot-handling.md +11 -3
  94. package/prompts/testing-guide.md +3 -3
  95. package/scripts/adopt/adopt-toolkits.ts +0 -2
  96. package/scripts/adopt/adopt.ts +0 -2
  97. package/scripts/agent/agent-argv.ts +0 -2
  98. package/scripts/agent/agent-diagnostics.ts +1 -1
  99. package/scripts/agent/agent-role-profile.ts +0 -7
  100. package/scripts/agent/claude-agent-argv.ts +0 -2
  101. package/scripts/agent/codex-agent-argv.ts +1 -1
  102. package/scripts/agent/codex-hooks.ts +92 -0
  103. package/scripts/agent/interactive-ask.ts +1 -1
  104. package/scripts/auto-ok/auto-ok-cli.ts +6 -16
  105. package/scripts/backlog/backlog-arrival.ts +30 -10
  106. package/scripts/backlog/backlog-budget-cli.ts +15 -16
  107. package/scripts/backlog/backlog-budget.ts +0 -2
  108. package/scripts/backlog/backlog-defect-priority.ts +2 -2
  109. package/scripts/backlog/backlog-drive-cli.ts +10 -8
  110. package/scripts/backlog/backlog-drive-named-offer.ts +16 -3
  111. package/scripts/backlog/backlog-drive-named.ts +2 -1
  112. package/scripts/backlog/backlog-drive.ts +76 -16
  113. package/scripts/backlog/backlog-named.ts +0 -3
  114. package/scripts/backlog/backlog-next.ts +9 -15
  115. package/scripts/backlog/backlog-offer-cli.ts +6 -19
  116. package/scripts/backlog/backlog-plan-cli.ts +1 -7
  117. package/scripts/backlog/backlog-plan.ts +30 -19
  118. package/scripts/backlog/backlog-pool.ts +3 -6
  119. package/scripts/backlog/backlog-rank.ts +2 -2
  120. package/scripts/backlog/backlog-ready.ts +39 -10
  121. package/scripts/backlog/backlog-scope.ts +1 -3
  122. package/scripts/backlog/backlog-stalled-detect.ts +2 -2
  123. package/scripts/backlog/backlog-stalled.ts +0 -1
  124. package/scripts/backlog/backlog-waves.ts +5 -2
  125. package/scripts/behavior/behavior-cli.ts +1 -1
  126. package/scripts/build/build-codex-hooks.ts +26 -0
  127. package/scripts/build/build-hooks.ts +85 -9
  128. package/scripts/build/hook-bundle-stamp.ts +111 -0
  129. package/scripts/cases/cases-cli.ts +1 -1
  130. package/scripts/cases/cases-logic.ts +1 -1
  131. package/scripts/ci/composite-actions.ts +30 -0
  132. package/scripts/ci/pr-classification.ts +3 -3
  133. package/scripts/claude/workflow-destination.ts +10 -1
  134. package/scripts/clone/clone-fingerprint.ts +0 -1
  135. package/scripts/clone/clone-scan-cli.ts +1 -1
  136. package/scripts/clone/clone-scan.ts +1 -1
  137. package/scripts/config-merge/json-format.ts +0 -1
  138. package/scripts/config-merge/parse-jsonc.ts +33 -3
  139. package/scripts/config-merge/patch-json-key.ts +13 -6
  140. package/scripts/config-merge/patch-yaml-list.ts +1 -1
  141. package/scripts/cost-runtime/codex-usage.ts +2 -9
  142. package/scripts/cost-runtime/cost-attribute.ts +0 -1
  143. package/scripts/cost-runtime/cost-cli.ts +3 -10
  144. package/scripts/cost-runtime/cost-corpus.ts +0 -2
  145. package/scripts/cost-runtime/cost-format.ts +0 -3
  146. package/scripts/cost-runtime/cost-pricing.ts +0 -1
  147. package/scripts/cost-runtime/cost-tokens.ts +0 -1
  148. package/scripts/delegation/delegation-cli.ts +1 -1
  149. package/scripts/delegation/delegation-policy.ts +0 -1
  150. package/scripts/delegation/duplicate-read-guard.ts +0 -8
  151. package/scripts/delegation/fanout-cli.ts +1 -1
  152. package/scripts/delegation/fanout.ts +0 -2
  153. package/scripts/delegation/investigation-reads.ts +1 -164
  154. package/scripts/discovery/repo-map-logic.ts +0 -1
  155. package/scripts/discovery/repo-party-cli.ts +1 -1
  156. package/scripts/doctor/doctor-consumer.ts +6 -10
  157. package/scripts/doctor/doctor-io.ts +9 -13
  158. package/scripts/doctor/doctor-logic.ts +0 -4
  159. package/scripts/doctor/doctor.ts +14 -9
  160. package/scripts/document/backlogrun-parent-read-set.ts +12 -1
  161. package/scripts/document/document-byte-budget.ts +5 -5
  162. package/scripts/document/document-byte-check.ts +0 -1
  163. package/scripts/document/document-read-cli.ts +0 -2
  164. package/scripts/document/document-section-cli.ts +1 -1
  165. package/scripts/document/document-section.ts +0 -3
  166. package/scripts/document/edit-files-cli.ts +0 -1
  167. package/scripts/document/entry-read-budget.ts +21 -7
  168. package/scripts/document/entry-read-set.ts +32 -8
  169. package/scripts/document/lane-child-read-set.ts +8 -6
  170. package/scripts/document/read-files-cli.ts +0 -4
  171. package/scripts/document/read-set-cli.ts +0 -2
  172. package/scripts/document/read-set-point-of-use.ts +9 -3
  173. package/scripts/document/read-set-pricing.ts +0 -1
  174. package/scripts/document/read-set-trim.ts +4 -2
  175. package/scripts/epic/epic-add.ts +1 -1
  176. package/scripts/epic/epic-audit-cli.ts +1 -4
  177. package/scripts/epic/epic-audit-orphans.ts +1 -3
  178. package/scripts/epic/epic-audit-rationale.ts +0 -1
  179. package/scripts/epic/epic-audit-report.ts +0 -2
  180. package/scripts/epic/epic-audit.ts +8 -22
  181. package/scripts/epic/epic-bundle-cli.ts +1 -1
  182. package/scripts/epic/epic-bundle-evidence.ts +0 -1
  183. package/scripts/epic/epic-bundle-referenced.ts +1 -5
  184. package/scripts/epic/epic-bundle.ts +0 -4
  185. package/scripts/epic/epic-busy.ts +4 -5
  186. package/scripts/epic/epic-candidate-confirm.ts +0 -5
  187. package/scripts/epic/epic-classify.ts +2 -2
  188. package/scripts/epic/epic-cli-argv.ts +0 -1
  189. package/scripts/epic/epic-close-comment.ts +1 -1
  190. package/scripts/epic/epic-close.ts +5 -2
  191. package/scripts/epic/epic-cross-repo.ts +2 -4
  192. package/scripts/epic/epic-decision.ts +0 -1
  193. package/scripts/epic/epic-fetch.ts +2 -2
  194. package/scripts/epic/epic-index.ts +2 -3
  195. package/scripts/epic/epic-issue.ts +1 -15
  196. package/scripts/epic/epic-lane-offer.ts +9 -8
  197. package/scripts/epic/epic-nested.ts +1 -1
  198. package/scripts/epic/epic-next-read.ts +1 -3
  199. package/scripts/epic/epic-next-views.ts +0 -1
  200. package/scripts/epic/epic-next.ts +1 -10
  201. package/scripts/epic/epic-parse.ts +0 -1
  202. package/scripts/epic/epic-promote.ts +0 -9
  203. package/scripts/epic/epic-rank.ts +2 -2
  204. package/scripts/epic/epic-read.ts +1 -2
  205. package/scripts/epic/epic-reconcile.ts +1 -1
  206. package/scripts/epic/epic-reference.ts +1 -13
  207. package/scripts/epic/epic-relation-recheck.ts +1 -1
  208. package/scripts/epic/epic-relations.ts +1 -1
  209. package/scripts/epic/epic-remove.ts +1 -1
  210. package/scripts/epic/epic-report.ts +0 -1
  211. package/scripts/epic/epic-run.ts +2 -3
  212. package/scripts/epic/epic-shape.ts +1 -1
  213. package/scripts/epic/epic-solo-stale.ts +107 -0
  214. package/scripts/epic/epic-solo.ts +3 -2
  215. package/scripts/epic/epic-triage.ts +1 -1
  216. package/scripts/epic/epic-validate.ts +1 -1
  217. package/scripts/epic/epic.ts +1 -1
  218. package/scripts/exports/unused-members-cli.ts +53 -0
  219. package/scripts/{git → followup}/followup-issue-number.ts +1 -6
  220. package/scripts/{git → followup}/git-followup-cleanup.ts +2 -1
  221. package/scripts/{git → followup}/git-followup-finish.ts +1 -3
  222. package/scripts/{git → followup}/git-followup-flush.ts +2 -2
  223. package/scripts/{git → followup}/git-followup-issue-close.ts +2 -2
  224. package/scripts/{git → followup}/git-followup-label.ts +4 -4
  225. package/scripts/followup/git-followup-merged.ts +112 -0
  226. package/scripts/{git → followup}/git-followup-pending.ts +1 -1
  227. package/scripts/{git → followup}/git-followup-workflow.ts +19 -11
  228. package/scripts/{git → followup}/git-pr-followup-wrapup.ts +9 -3
  229. package/scripts/{git → followup}/git-pr-followup.ts +53 -16
  230. package/scripts/gate/core-budget.ts +3 -9
  231. package/scripts/gate/gate-plan.ts +7 -4
  232. package/scripts/gate/gate-report.ts +0 -6
  233. package/scripts/gate/gate-tree.ts +1 -1
  234. package/scripts/gate/pre-commit-type-check.ts +0 -6
  235. package/scripts/gate/project-checks.ts +7 -8
  236. package/scripts/gate/scoped-green.ts +0 -1
  237. package/scripts/gate/type-check-step.ts +1 -1
  238. package/scripts/gate/verification-gate.ts +0 -2
  239. package/scripts/gh/fix-gh-packages.ts +15 -12
  240. package/scripts/gh/gh-spawn.ts +2 -2
  241. package/scripts/{git → gh}/git-ai-review-scan.ts +1 -5
  242. package/scripts/{git → gh}/git-gh-check.ts +2 -1
  243. package/scripts/{git → gh}/git-gh-exec.ts +1 -1
  244. package/scripts/{git → gh}/git-gh-failure.ts +1 -1
  245. package/scripts/{git → gh}/git-gh-helpers.ts +0 -1
  246. package/scripts/{git → gh}/git-gh-issue-list.ts +13 -10
  247. package/scripts/{git → gh}/git-gh-issue-read.ts +1 -1
  248. package/scripts/{git → gh}/git-gh-issue-rest.ts +6 -3
  249. package/scripts/{git → gh}/git-gh-issue-write.ts +4 -1
  250. package/scripts/{git → gh}/git-gh-pr-auto-merge.ts +4 -1
  251. package/scripts/{git → gh}/git-gh-pr-read.ts +24 -0
  252. package/scripts/{git → gh}/git-gh-pr-rest.ts +5 -2
  253. package/scripts/{git → gh}/git-gh-pr-review.ts +2 -2
  254. package/scripts/{git → gh}/git-gh-pr-rollup.ts +1 -3
  255. package/scripts/{git → gh}/git-gh-pr.ts +3 -1
  256. package/scripts/{git → gh}/git-pr-ai-review.ts +2 -5
  257. package/scripts/{git → gh}/git-pr-checks-eval.ts +0 -10
  258. package/scripts/{git → gh}/git-pr-checks-parse.ts +4 -20
  259. package/scripts/{git → gh}/git-pr-checks.ts +2 -1
  260. package/scripts/{git → gh}/git-pr-coderabbit.ts +2 -5
  261. package/scripts/{git → gh}/git-pr-confirmation.ts +1 -3
  262. package/scripts/{git → gh}/git-pr-managed-config.ts +2 -3
  263. package/scripts/{git → gh}/git-pr.ts +3 -3
  264. package/scripts/git/changed-file-scope.ts +0 -1
  265. package/scripts/git/git-branch.ts +3 -6
  266. package/scripts/git/git-command.ts +6 -1
  267. package/scripts/git/git-commit.ts +1 -1
  268. package/scripts/git/git-common-directory.ts +80 -24
  269. package/scripts/git/git-error.ts +66 -9
  270. package/scripts/git/git-issue.ts +1 -1
  271. package/scripts/git/git-preflight.ts +2 -2
  272. package/scripts/git/git-prompt.ts +6 -31
  273. package/scripts/git/git-push.ts +1 -1
  274. package/scripts/git/git-spawn-sync.ts +65 -0
  275. package/scripts/git/git-spawn.ts +5 -4
  276. package/scripts/git/git-staging.ts +1 -0
  277. package/scripts/git/git-status.ts +1 -1
  278. package/scripts/git/git-workflow.ts +1 -1
  279. package/scripts/git/gone-branch.ts +1 -0
  280. package/scripts/git/listing-cutoff.ts +1 -1
  281. package/scripts/git/main-merge.ts +1 -1
  282. package/scripts/git/main-sync.ts +19 -1
  283. package/scripts/git/parse-json-array.ts +0 -3
  284. package/scripts/git/repository-lock.ts +16 -16
  285. package/scripts/git/{git-stash.ts → stash/git-stash.ts} +1 -1
  286. package/scripts/git/{stash-pop-args.ts → stash/stash-pop-args.ts} +2 -7
  287. package/scripts/git/{stash-pop-cli.ts → stash/stash-pop-cli.ts} +0 -1
  288. package/scripts/git/{stash-sweep-lock.ts → stash/stash-sweep-lock.ts} +3 -3
  289. package/scripts/hooks/codex-hook-adapter.ts +0 -1
  290. package/scripts/hooks/edited-cspell.ts +1 -1
  291. package/scripts/hooks/format-edited-file.ts +2 -0
  292. package/scripts/hooks/pre-push-unit.ts +0 -4
  293. package/scripts/hooks/pretool-guard.ts +22 -4
  294. package/scripts/hooks/reserved-run.ts +1 -1
  295. package/scripts/hooks/step-zero-notice.ts +76 -0
  296. package/scripts/hooks/stop-guard.ts +47 -21
  297. package/scripts/init/claude-plugin-config.ts +4 -5
  298. package/scripts/init/hook-command-rewrite.ts +16 -8
  299. package/scripts/init/hook-launch.ts +41 -15
  300. package/scripts/init/init-basic.ts +2 -5
  301. package/scripts/init/init-file-action.ts +54 -0
  302. package/scripts/init/init-logic-migrate.ts +35 -17
  303. package/scripts/init/init-logic-secretlint.ts +1 -1
  304. package/scripts/init/init-logic.ts +10 -19
  305. package/scripts/init/init.ts +11 -71
  306. package/scripts/init/kit-written-paths.ts +2 -0
  307. package/scripts/init/project-profile.ts +9 -17
  308. package/scripts/init/start-exec.ts +1 -1
  309. package/scripts/init/start-setup-pr.ts +6 -6
  310. package/scripts/init/start-steps.ts +3 -1
  311. package/scripts/issue/behavior-change-lint.ts +0 -1
  312. package/scripts/issue/defect-rate-cli.ts +64 -23
  313. package/scripts/issue/defect-rate.ts +1 -2
  314. package/scripts/{git → issue}/git-next-issues.ts +3 -3
  315. package/scripts/issue/issue-backlinks-cli.ts +1 -5
  316. package/scripts/issue/issue-backlinks.ts +7 -14
  317. package/scripts/issue/issue-cite-cli.ts +2 -6
  318. package/scripts/issue/issue-cite.ts +12 -8
  319. package/scripts/issue/issue-classification.ts +1 -9
  320. package/scripts/issue/issue-closing-pr.ts +4 -4
  321. package/scripts/issue/issue-comment-cli.ts +2 -2
  322. package/scripts/issue/issue-file-cli.ts +5 -5
  323. package/scripts/issue/issue-file.ts +7 -14
  324. package/scripts/issue/issue-fold-cli.ts +1 -1
  325. package/scripts/issue/issue-fold-existing-cli.ts +1 -1
  326. package/scripts/{git → issue}/issue-labels.ts +8 -0
  327. package/scripts/issue/issue-lint-cli.ts +1 -1
  328. package/scripts/issue/issue-merged.ts +2 -2
  329. package/scripts/{git → issue}/issue-rank.ts +1 -1
  330. package/scripts/issue/issue-read-cli.ts +8 -47
  331. package/scripts/issue/issue-read.ts +0 -2
  332. package/scripts/issue/issue-report-failures.ts +80 -0
  333. package/scripts/issue/issue-scout-cli.ts +1 -7
  334. package/scripts/issue/issue-scout-closed.ts +2 -2
  335. package/scripts/issue/issue-scout.ts +0 -2
  336. package/scripts/issue/issue-state-cli.ts +5 -46
  337. package/scripts/issue/issue-state.ts +1 -5
  338. package/scripts/issue/markdown-section.ts +21 -6
  339. package/scripts/issue/measure-rerun-cli.ts +74 -15
  340. package/scripts/issue/reproduction-measure.ts +1 -1
  341. package/scripts/josh/cli-body.ts +1 -1
  342. package/scripts/josh/file-map-stamp.ts +0 -3
  343. package/scripts/josh/josh-command-map.ts +2 -0
  344. package/scripts/josh/josh-commands-ai.ts +9 -102
  345. package/scripts/josh/josh-commands-backlog.ts +5 -1
  346. package/scripts/josh/josh-commands-development.ts +8 -1
  347. package/scripts/josh/josh-commands-issue.ts +2 -2
  348. package/scripts/josh/josh-commands-maintenance.ts +7 -0
  349. package/scripts/josh/josh-commands-project.ts +7 -1
  350. package/scripts/josh/josh-commands-run.ts +114 -0
  351. package/scripts/josh/josh-commands-versioning.ts +8 -0
  352. package/scripts/josh/josh-commands-workflow.ts +3 -3
  353. package/scripts/josh/path-decision.ts +0 -3
  354. package/scripts/josh/process-owner.ts +16 -0
  355. package/scripts/josh/run-github-prerequisite.ts +3 -6
  356. package/scripts/josh/session-language-cli.ts +0 -1
  357. package/scripts/lane/lane-await.ts +46 -19
  358. package/scripts/lane/lane-capacity.ts +6 -3
  359. package/scripts/lane/lane-child-invocation.ts +20 -7
  360. package/scripts/lane/lane-cli.ts +1 -4
  361. package/scripts/lane/lane-close.ts +5 -4
  362. package/scripts/lane/lane-dispatch.ts +3 -4
  363. package/scripts/lane/lane-environment.ts +0 -9
  364. package/scripts/lane/lane-handoff.ts +38 -0
  365. package/scripts/lane/lane-launch-cli.ts +31 -27
  366. package/scripts/lane/lane-open.ts +0 -3
  367. package/scripts/lane/lane-output.ts +0 -1
  368. package/scripts/lane/lane-registry.ts +9 -0
  369. package/scripts/lane/openai-lane-ship.ts +2 -0
  370. package/scripts/lane/openai-lane-supervisor-decision.ts +2 -1
  371. package/scripts/lane/openai-lane-supervisor.ts +6 -4
  372. package/scripts/lane/openai-review-broker.ts +7 -1
  373. package/scripts/lib/bounded-pool.ts +1 -0
  374. package/scripts/lib/cli-flags.ts +31 -2
  375. package/scripts/lib/error-message.ts +12 -1
  376. package/scripts/lib/json-value.ts +5 -4
  377. package/scripts/lib/poll.ts +3 -1
  378. package/scripts/lib/timed-fetch.ts +15 -0
  379. package/scripts/lib/timeouts.ts +13 -0
  380. package/scripts/{yaml → lib}/yaml-document.ts +3 -1
  381. package/scripts/{bytes → lines}/bytes-command.ts +0 -2
  382. package/scripts/lines/line-targets.ts +0 -11
  383. package/scripts/lines/lines-command.ts +5 -4
  384. package/scripts/lint/lint-related-scope.ts +0 -1
  385. package/scripts/lint/lint-related.ts +1 -1
  386. package/scripts/{git → notify}/telegram-notify.ts +2 -2
  387. package/scripts/{git → notify}/telegram-test.ts +4 -4
  388. package/scripts/observations/observation-ledger-home.ts +0 -1
  389. package/scripts/observations/observation-ledger-line.ts +0 -1
  390. package/scripts/observations/observation-ledger-migrate.ts +1 -1
  391. package/scripts/observations/observations-flush-landing.ts +3 -3
  392. package/scripts/observations/observations-flush.ts +2 -2
  393. package/scripts/overrides/lockfile-overrides.ts +1 -1
  394. package/scripts/overrides/overrides-logic.ts +1 -1
  395. package/scripts/package/package-scout-cli.ts +2 -7
  396. package/scripts/package/package-scout.ts +0 -2
  397. package/scripts/propagate/propagate-git-failure.ts +0 -1
  398. package/scripts/propagate/propagate-git.ts +3 -10
  399. package/scripts/propagate/propagate-publish.ts +2 -3
  400. package/scripts/propagate/propagate-run.ts +0 -2
  401. package/scripts/propagate/propagate-steps.ts +3 -5
  402. package/scripts/propagate/propagate-targets.ts +0 -4
  403. package/scripts/propagate/propagate.ts +0 -4
  404. package/scripts/refactor/import-graph.ts +0 -1
  405. package/scripts/refactor/refactor-lint.ts +0 -2
  406. package/scripts/refactor/refactor-scan.ts +2 -2
  407. package/scripts/refactor/refactor-targets.ts +0 -1
  408. package/scripts/registry-migration/migrate-logic.ts +28 -21
  409. package/scripts/registry-migration/migrate.ts +25 -14
  410. package/scripts/release/github-release-cli.ts +19 -6
  411. package/scripts/release/github-release-environment.ts +46 -0
  412. package/scripts/release/github-release.ts +151 -94
  413. package/scripts/release/release-history.ts +0 -1
  414. package/scripts/release/release-plan.ts +0 -1
  415. package/scripts/release/release-publish.ts +38 -5
  416. package/scripts/release/release-scope-cli.ts +1 -2
  417. package/scripts/release/release-tag.ts +2 -4
  418. package/scripts/release/release-worktree.ts +97 -2
  419. package/scripts/repo/auto-merge-setting-logic.ts +1 -4
  420. package/scripts/repo/repo-setting.ts +1 -1
  421. package/scripts/repo/repository-labels.ts +3 -3
  422. package/scripts/repo/required-checks-logic.ts +206 -0
  423. package/scripts/repo/required-checks-report.ts +71 -0
  424. package/scripts/repo/ruleset-check-cli.ts +53 -0
  425. package/scripts/repo/ruleset-check.ts +147 -0
  426. package/scripts/report/report-lint-cli.ts +0 -4
  427. package/scripts/review/disposition-cli.ts +1 -1
  428. package/scripts/review/live-evidence.ts +1 -1
  429. package/scripts/review/review-attest-cli.ts +0 -6
  430. package/scripts/review/review-attest.ts +4 -16
  431. package/scripts/review/review-brief-cli.ts +23 -6
  432. package/scripts/review/review-brief.ts +21 -8
  433. package/scripts/review/review-checkout.ts +3 -2
  434. package/scripts/review/review-diff-parts.ts +89 -0
  435. package/scripts/review/review-diff-write.ts +97 -0
  436. package/scripts/review/review-finding-ledger.ts +0 -1
  437. package/scripts/review/review-record-cli.ts +10 -17
  438. package/scripts/review/review-record.ts +0 -1
  439. package/scripts/review/review-round2-cli.ts +1 -1
  440. package/scripts/review/review-stamps.ts +0 -3
  441. package/scripts/review/review-tree.ts +14 -2
  442. package/scripts/rules/decision-oracle-stage.ts +18 -0
  443. package/scripts/rules/decision-oracle.ts +10 -7
  444. package/scripts/rules/delivered-rules.ts +9 -1
  445. package/scripts/rules/destructive-command.ts +119 -0
  446. package/scripts/rules/direct-filing.ts +1 -1
  447. package/scripts/rules/early-heartbeat.ts +4 -3
  448. package/scripts/rules/file-body.ts +0 -3
  449. package/scripts/rules/filing-cap.ts +0 -2
  450. package/scripts/rules/gh-api.ts +7 -2
  451. package/scripts/rules/git-argv.ts +18 -7
  452. package/scripts/rules/git-force.ts +0 -2
  453. package/scripts/rules/implementation-cut.ts +0 -1
  454. package/scripts/rules/index-guard.ts +71 -0
  455. package/scripts/rules/issue-citation.ts +50 -25
  456. package/scripts/rules/lane-background.ts +15 -7
  457. package/scripts/rules/lane-park.ts +22 -6
  458. package/scripts/rules/last-prompt.ts +1 -0
  459. package/scripts/rules/oracle-consulted.ts +1 -1
  460. package/scripts/rules/oracle-firing.ts +1 -0
  461. package/scripts/rules/oracle-list-cli.ts +0 -3
  462. package/scripts/rules/permission-guards.ts +14 -0
  463. package/scripts/rules/protected-files.ts +74 -0
  464. package/scripts/rules/reply-language.ts +1 -1
  465. package/scripts/rules/rule-body-guard.ts +0 -3
  466. package/scripts/rules/rule-value-cli.ts +0 -1
  467. package/scripts/rules/shell-body-trigger.ts +0 -1
  468. package/scripts/rules/shell-segments.ts +0 -1
  469. package/scripts/rules/stop-rules.ts +20 -9
  470. package/scripts/rules/tail-commands.ts +1 -1
  471. package/scripts/rules/test-declared-commit.ts +1 -1
  472. package/scripts/rules/third-party-write.ts +0 -1
  473. package/scripts/rules/worktree-guard.ts +26 -9
  474. package/scripts/run/run-carry-args.ts +8 -12
  475. package/scripts/run/run-carry-cli.ts +0 -2
  476. package/scripts/run/run-carry-stash.ts +2 -2
  477. package/scripts/run/run-carry-streak.ts +1 -1
  478. package/scripts/run/run-cut-args.ts +1 -6
  479. package/scripts/run/run-cut-cli.ts +0 -7
  480. package/scripts/run/run-cut.ts +8 -54
  481. package/scripts/run/run-ending-cli.ts +2 -6
  482. package/scripts/run/run-ending.ts +1 -4
  483. package/scripts/run/run-entry-cli.ts +133 -25
  484. package/scripts/run/run-entry-stop.ts +104 -0
  485. package/scripts/run/run-entry.ts +0 -1
  486. package/scripts/run/run-event-cli.ts +0 -2
  487. package/scripts/run/run-event-follow.ts +1 -0
  488. package/scripts/run/run-event-render.ts +1 -1
  489. package/scripts/run/run-event-scope.ts +53 -4
  490. package/scripts/run/run-event-stream-emit.ts +7 -2
  491. package/scripts/run/run-event-stream.ts +0 -3
  492. package/scripts/run/run-event-watch.ts +1 -0
  493. package/scripts/run/run-halfrun-resume.ts +20 -7
  494. package/scripts/run/run-headless.ts +2 -2
  495. package/scripts/run/run-hold-cli.ts +33 -10
  496. package/scripts/run/run-hold.ts +29 -6
  497. package/scripts/run/run-issue-number.ts +1 -1
  498. package/scripts/run/run-liveness-cli.ts +2 -6
  499. package/scripts/run/run-liveness.ts +2 -3
  500. package/scripts/run/run-merge-cli.ts +7 -23
  501. package/scripts/run/run-merge-steps.ts +5 -5
  502. package/scripts/run/run-merge.ts +1 -1
  503. package/scripts/run/run-next-cli.ts +1 -1
  504. package/scripts/run/run-parent-cut-hook.ts +4 -2
  505. package/scripts/run/run-preflight.ts +2 -9
  506. package/scripts/run/run-prep-cli.ts +6 -3
  507. package/scripts/run/run-prep-locate.ts +1 -1
  508. package/scripts/run/run-progress-args.ts +20 -4
  509. package/scripts/run/run-progress-cli.ts +35 -36
  510. package/scripts/run/run-progress-clock.ts +10 -35
  511. package/scripts/run/run-progress-config.ts +0 -4
  512. package/scripts/run/run-progress-read.ts +1 -2
  513. package/scripts/run/run-progress.ts +1 -2
  514. package/scripts/run/run-prrun-resume.ts +117 -0
  515. package/scripts/run/run-report-cli.ts +1 -2
  516. package/scripts/run/run-report.ts +0 -1
  517. package/scripts/run/run-retrospective.ts +1 -1
  518. package/scripts/run/run-review-cli.ts +0 -3
  519. package/scripts/run/run-review-steps.ts +2 -0
  520. package/scripts/run/run-review.ts +0 -2
  521. package/scripts/run/run-ship-cli.ts +29 -19
  522. package/scripts/run/run-ship-detach.ts +1 -0
  523. package/scripts/run/run-ship-next.ts +106 -0
  524. package/scripts/run/run-ship-preflight.ts +1 -1
  525. package/scripts/run/run-ship-probe.ts +4 -1
  526. package/scripts/run/run-ship-return.ts +8 -3
  527. package/scripts/run/run-ship-review-steps.ts +18 -4
  528. package/scripts/run/run-ship-review.ts +11 -0
  529. package/scripts/run/run-ship-scoped.ts +1 -0
  530. package/scripts/run/run-ship-steps.ts +1 -1
  531. package/scripts/run/run-ship.ts +0 -1
  532. package/scripts/run/run-stage-read.ts +62 -0
  533. package/scripts/run/run-stage.ts +160 -0
  534. package/scripts/run/run-status-cli.ts +3 -16
  535. package/scripts/run/run-step-cli.ts +21 -14
  536. package/scripts/run/run-step.ts +1 -1
  537. package/scripts/run/run-stop-notify.ts +1 -3
  538. package/scripts/run/run-stranded-cli.ts +0 -4
  539. package/scripts/run/run-stranded-detect.ts +2 -2
  540. package/scripts/run/run-tail-cli.ts +17 -11
  541. package/scripts/run/run-tail.ts +2 -0
  542. package/scripts/run/run-tidy-lanes.ts +6 -2
  543. package/scripts/run/run-tidy-stashes.ts +12 -12
  544. package/scripts/run/run-wake-cli.ts +4 -13
  545. package/scripts/run/run-wake-loop.ts +2 -2
  546. package/scripts/run/run-wake.ts +2 -4
  547. package/scripts/run/run-watcher-guard-cli.ts +0 -4
  548. package/scripts/run/run-watcher-guard.ts +18 -12
  549. package/scripts/run/run-watcher-hook.ts +1 -1
  550. package/scripts/safe-chain/ci-installer-pin.ts +11 -5
  551. package/scripts/safe-chain/pack-hook.ts +92 -0
  552. package/scripts/safe-chain/project-config.ts +1 -1
  553. package/scripts/security/security-audit-provision-logic.ts +0 -1
  554. package/scripts/security/security-audit-provision.ts +3 -2
  555. package/scripts/security/security-audit.ts +0 -1
  556. package/scripts/security/security-updates-logic.ts +0 -1
  557. package/scripts/sonar/sonar-hotspots-cli.ts +10 -52
  558. package/scripts/sonar/sonar-hotspots.ts +0 -1
  559. package/scripts/sonar/sonar-new-code-cli.ts +150 -0
  560. package/scripts/sonar/sonar-new-code.ts +79 -0
  561. package/scripts/sonar/sonar-project.ts +97 -0
  562. package/scripts/split/split-assess-cli.ts +1 -1
  563. package/scripts/split/split-assess.ts +2 -5
  564. package/scripts/sync/managed-config-scope-cli.ts +1 -1
  565. package/scripts/sync/skill-migration.ts +0 -1
  566. package/scripts/sync/sync-ai-files.ts +4 -0
  567. package/scripts/sync/sync-hook-safety.ts +2 -3
  568. package/scripts/sync/sync.ts +1 -8
  569. package/scripts/sync/template-source-logic.ts +0 -1
  570. package/scripts/sync/workflow-pin-logic.ts +16 -28
  571. package/scripts/test/test-declared-changed.ts +13 -16
  572. package/scripts/test/test-declared-logic.ts +0 -1
  573. package/scripts/test/test-declared.ts +3 -9
  574. package/scripts/test/test-red-commit.ts +2 -2
  575. package/scripts/test/test-red.ts +14 -7
  576. package/scripts/test/test-type-logic.ts +1 -1
  577. package/scripts/test/unit-worker-share.ts +7 -16
  578. package/scripts/time-runtime/time-batch-guard.ts +1 -2
  579. package/scripts/time-runtime/time-bundle-call.ts +0 -1
  580. package/scripts/time-runtime/time-bundles.ts +0 -4
  581. package/scripts/time-runtime/time-density-hook.ts +0 -2
  582. package/scripts/time-runtime/time-followup-stage.ts +1 -1
  583. package/scripts/time-runtime/time-format.ts +0 -73
  584. package/scripts/time-runtime/time-round-trips.ts +0 -4
  585. package/scripts/time-runtime/time-single-check.ts +1 -1
  586. package/scripts/time-runtime/time-spans.ts +1 -1
  587. package/scripts/time-runtime/time-transcript-line.ts +1 -2
  588. package/scripts/ui/ui-routes-cli.ts +0 -5
  589. package/scripts/ui/ui-routes.ts +0 -5
  590. package/scripts/version/effective-upstream.ts +2 -2
  591. package/scripts/version/latest-corepack.ts +7 -9
  592. package/scripts/version/latest-scope-cli.ts +0 -2
  593. package/scripts/version/latest-update.ts +0 -2
  594. package/scripts/version/npm-registry.ts +2 -2
  595. package/scripts/version/publishable-range-check.ts +1 -1
  596. package/scripts/version/release-hold.ts +0 -4
  597. package/scripts/version/running-binary.ts +2 -2
  598. package/scripts/version/version-check-logic.ts +0 -2
  599. package/scripts/version/version-commands.ts +11 -1
  600. package/scripts/version/version-remote.ts +3 -3
  601. package/scripts/version/version-targets.ts +4 -4
  602. package/templates/CLAUDE.basic.md +6 -6
  603. package/templates/sonar-project.properties +28 -1
  604. package/templates/workflows/ci.yml +16 -82
  605. package/templates/workflows/dependabot-auto-merge.yml +6 -3
  606. package/templates/workflows/github-release.yml +79 -0
  607. package/tsconfig.sonar.json +4 -22
  608. package/prompts/collaboration-workflow/cross-repo-epic.md +0 -5
  609. package/prompts/collaboration-workflow/epic-audit.md +0 -5
  610. package/prompts/collaboration-workflow/epic-bundle.md +0 -5
  611. package/scripts/init/plugin-install-hint.ts +0 -47
  612. package/scripts/version/parse-json.ts +0 -13
  613. /package/scripts/{git → followup}/git-followup-stages.ts +0 -0
  614. /package/scripts/{git → gh}/git-gh-api-path.ts +0 -0
  615. /package/scripts/{git → gh}/git-gh-command.ts +0 -0
  616. /package/scripts/{git → gh}/git-gh-issue.ts +0 -0
  617. /package/scripts/{git → gh}/git-gh-pr-snapshot.ts +0 -0
  618. /package/scripts/{git → gh}/git-gh-reachability.ts +0 -0
  619. /package/scripts/{git → gh}/git-gh-repo.ts +0 -0
  620. /package/scripts/{git → gh}/git-gh-rest-state.ts +0 -0
  621. /package/scripts/{git → gh}/git-pr-checks-watch.ts +0 -0
  622. /package/scripts/{git → gh}/git-pr-error.ts +0 -0
  623. /package/scripts/{git → gh}/git-pr-messages.ts +0 -0
  624. /package/scripts/{git → gh}/github-issue-url.ts +0 -0
  625. /package/scripts/git/{stash-orphans.ts → stash/stash-orphans.ts} +0 -0
  626. /package/scripts/{git → issue}/issue-reference.ts +0 -0
  627. /package/scripts/{git → lib}/animation-helpers.ts +0 -0
  628. /package/scripts/{git → lib}/git-animation.ts +0 -0
  629. /package/scripts/{git → notify}/git-notify.ts +0 -0
  630. /package/scripts/{git → notify}/telegram-test-logic.ts +0 -0
@@ -45,6 +45,9 @@ interface StopContext {
45
45
  hold_present: boolean
46
46
  // `git status --porcelain` came back empty.
47
47
  tree_clean: boolean
48
+ // That record carries a `prrun` stop mark (joshuafolkken/kit#3023): the run stopped at a green pull
49
+ // request and keeps the hold over a clean tree on purpose, so a person can look before it merges.
50
+ prrun_stopped: boolean
48
51
  // A `confirmation` notify is on this run's transcript tail.
49
52
  notified: boolean
50
53
  // The turn's session-facing reply text.
@@ -75,6 +78,9 @@ interface StopContext {
75
78
  // A backgrounded subagent this run launched has not finished — `lane_background.pending_agent_ids`
76
79
  // (joshuafolkken/kit#2774). Apart from `background_pending`, since only a subagent is sure to end.
77
80
  agent_pending: boolean
81
+ // This lane child handed its region to a running detached ship — `lane_handoff.is_handed_off`
82
+ // (joshuafolkken/kit#2962). The supervisor notifies on its own outcome, so nobody waits on this stop.
83
+ handed_off: boolean
78
84
  // The resolved `JOSH_SESSION_LANG` — `session_language.resolve_session_lang` (joshuafolkken/kit#2470).
79
85
  session_lang: string
80
86
  }
@@ -105,8 +111,8 @@ const HOLD_RELEASE_REASON =
105
111
  'place, so the next run here runs `git switch main && git pull` believing the tree is free while ' +
106
112
  'you hold it. `.claude/skills/workflow-commands/SKILL.md` → §2f: a stop that leaves the tree clean ' +
107
113
  'releases the hold with `pnpm josh run:release <N>` (bare for a `new` entry). A `halfrun` ' +
108
- 'pre-commit stop and a `needs-human-review` stop keep the hold because their tree is dirty — this ' +
109
- 'row is silent there. Release it, then end with a one-line confirmation that it was released — do ' +
114
+ 'pre-commit stop and a `needs-human-review` stop keep the hold because their tree is dirty, and a ' +
115
+ '`prrun` stop keeps it by its stop mark — this row is silent there. Release it, then end with a one-line confirmation that it was released — do ' +
110
116
  'not repeat your previous reply.'
111
117
 
112
118
  // **A refusal that corrects rather than advises** (joshuafolkken/kit#2247). The bare `#N` is already
@@ -156,15 +162,18 @@ const HEADLESS_WAIT_MARKER = '⛔ headless parent:'
156
162
  const HEADLESS_REFUSAL_CAP = 3
157
163
 
158
164
  // The foreground waits as they appear in a transcript's tool-call input — the JSON `command` field, so
159
- // the refusal's own prose, which names the same commands, never matches.
160
- const HEADLESS_WAIT_CALLS = ['"command":"pnpm josh lane:await', '"command":"pnpm josh run:progress']
165
+ // the refusal's own prose, which names the same commands, never matches. `run:progress --wait` is not
166
+ // one (joshuafolkken/kit#3102): it streams its reports and runs until work arrives, so it is started in
167
+ // the background, where it lives as long as the turn the foreground wait keeps open.
168
+ const HEADLESS_WAIT_CALLS = ['"command":"pnpm josh lane:await']
161
169
 
162
170
  const HEADLESS_WAIT_BODY =
163
171
  ' this is a `claude -p` `backlogrun` parent (`JOSH_RUN_HEADLESS`) with lanes still ' +
164
172
  'in flight, and ending this turn ends the process — its background waits are killed with it and the ' +
165
173
  'lanes are left without a parent. Wait in the foreground instead: run `pnpm josh lane:await <N...>` ' +
166
- 'for the in-flight lanes (and `pnpm josh run:progress --wait` for the heartbeat) as foreground ' +
167
- 'commands within the tool timeout, act on what they report, and continue the loop. End the turn only ' +
174
+ 'for the in-flight lanes as a foreground command within the tool timeout (with ' +
175
+ '`pnpm josh run:progress --wait` in the background for the heartbeat, which streams its reports ' +
176
+ 'itself and lives while this turn does), act on what it reports, and continue the loop. End the turn only ' +
168
177
  'after `pnpm josh run:carry --cut` or `--end` (`backlogrun-progress.md` → "The parent keeps no clock ' +
169
178
  'of its own").'
170
179
 
@@ -232,8 +241,11 @@ function needs_filing(context: StopContext): boolean {
232
241
  // notify there says "nothing needed" and dilutes the ones that do. A backgrounded command does not
233
242
  // count: a dev server never ends, and a stop behind it would leave a person silently waiting. A lane
234
243
  // child never reaches this with a task running: `needs_background_wait` answers it first.
244
+ //
245
+ // **A lane handed to the detached ship stands them down too** (joshuafolkken/kit#2962): the hold now
246
+ // belongs to the supervisor driving the merge, and the person hears from that supervisor's own notify.
235
247
  function is_held_idle(context: StopContext): boolean {
236
- return context.hold_present && !context.agent_pending
248
+ return context.hold_present && !context.agent_pending && !context.handed_off
237
249
  }
238
250
 
239
251
  function needs_notify(context: StopContext): boolean {
@@ -241,7 +253,7 @@ function needs_notify(context: StopContext): boolean {
241
253
  }
242
254
 
243
255
  function needs_release(context: StopContext): boolean {
244
- return is_held_idle(context) && context.tree_clean
256
+ return is_held_idle(context) && context.tree_clean && !context.prrun_stopped
245
257
  }
246
258
 
247
259
  function citation_reason(context: StopContext): string | undefined {
@@ -345,7 +357,6 @@ const stop_rules = {
345
357
  STOP_NOTIFY_REASON,
346
358
  SWITCH_ENV_KEY,
347
359
  block_envelope,
348
- block_reason,
349
360
  build_language_reason,
350
361
  count_headless_refusals,
351
362
  is_enabled,
@@ -30,6 +30,6 @@ function prior_bash_commands(tail: string): ReadonlyArray<string> {
30
30
  return tail.split('\n').flatMap((line) => bash_commands_of(line))
31
31
  }
32
32
 
33
- const tail_commands = { bash_commands_of, is_bash_use, prior_bash_commands }
33
+ const tail_commands = { is_bash_use, prior_bash_commands }
34
34
 
35
35
  export { tail_commands }
@@ -46,6 +46,6 @@ const REASON =
46
46
  // reason above.
47
47
  const ROW = { id: 'test-declared', is_trigger: is_untested_commit, reason: REASON }
48
48
 
49
- const test_declared_commit = { REASON, ROW, is_untested_commit }
49
+ const test_declared_commit = { REASON, ROW }
50
50
 
51
51
  export { test_declared_commit }
@@ -83,7 +83,6 @@ const ROW = {
83
83
  const third_party_write = {
84
84
  ROW,
85
85
  THIRD_PARTY_WRITE_REASON,
86
- is_third_party_write_segment,
87
86
  writes_third_party,
88
87
  }
89
88
 
@@ -36,8 +36,8 @@ function is_worktree_checkout(args: ReadonlyArray<string>): boolean {
36
36
  }
37
37
 
38
38
  // `git restore <path>` discards working-tree changes. `--staged` / `-S` alone is an index restore —
39
- // that is the deny list's territory (`git restore --staged*` / `-S*`), so a pure index restore is not
40
- // refused twice. Anything touching the worktree (the default, or an explicit `--worktree` / `-W`) is.
39
+ // that is the `index-mutation` row's (`index-guard.ts`), so a pure index restore is not claimed by two
40
+ // rows. Anything touching the worktree (the default, or an explicit `--worktree` / `-W`) is this row's.
41
41
  const STAGED_LONG = '--staged'
42
42
  const STAGED_LETTER = 'S'
43
43
  const WORKTREE_LONG = '--worktree'
@@ -83,14 +83,33 @@ function is_unauthorized_stash(args: ReadonlyArray<string>): boolean {
83
83
  return true
84
84
  }
85
85
 
86
+ // `git clean` deletes untracked files, which no commit can bring back (joshuafolkken/kit#2983). It
87
+ // refuses to act without a force (`clean.requireForce`), so a force — `--force`, or a cluster carrying
88
+ // `f` — is what marks the destructive call; `git clean -n` is a dry run and passes.
89
+ const CLEAN_SUBCOMMAND = 'clean'
90
+ const FORCE_LONG = '--force'
91
+ const FORCE_LETTER = 'f'
92
+
93
+ function is_forced_clean(args: ReadonlyArray<string>): boolean {
94
+ return args.some(
95
+ (argument) => argument === FORCE_LONG || git_argv.short_cluster_has(argument, FORCE_LETTER),
96
+ )
97
+ }
98
+
99
+ // Each subcommand this row judges, with the predicate that reads its arguments.
100
+ const JUDGED_SUBCOMMANDS: ReadonlyMap<string, (args: ReadonlyArray<string>) => boolean> = new Map([
101
+ [CHECKOUT_SUBCOMMAND, is_worktree_checkout],
102
+ [RESTORE_SUBCOMMAND, touches_worktree],
103
+ [CLEAN_SUBCOMMAND, is_forced_clean],
104
+ [STASH_SUBCOMMAND, is_unauthorized_stash],
105
+ ])
106
+
86
107
  function is_unauthorized_segment(segment: string): boolean {
87
108
  const call = git_argv.parse(segment)
88
109
 
89
110
  if (call === undefined) return false
90
- if (call.subcommand === CHECKOUT_SUBCOMMAND) return is_worktree_checkout(call.args)
91
- if (call.subcommand === RESTORE_SUBCOMMAND) return touches_worktree(call.args)
92
111
 
93
- return call.subcommand === STASH_SUBCOMMAND && is_unauthorized_stash(call.args)
112
+ return JUDGED_SUBCOMMANDS.get(call.subcommand ?? '')?.(call.args) === true
94
113
  }
95
114
 
96
115
  function is_unauthorized_worktree_change(command: string): boolean {
@@ -101,8 +120,8 @@ function is_unauthorized_worktree_change(command: string): boolean {
101
120
  // and — for a stash — the message form that is allowed. `pnpm josh git` and `pnpm josh stash:pop` are
102
121
  // invisible to this trigger, so a run that uses them is never refused.
103
122
  const WORKTREE_MUTATION_REASON =
104
- '⛔ unauthorized working-tree change: `git checkout -- <path>`, `git restore <path>` and an ' +
105
- 'unauthorized `git stash` mutate the working tree or the repository-wide stash every work tree ' +
123
+ '⛔ unauthorized working-tree change: `git checkout -- <path>`, `git restore <path>`, a forced ' +
124
+ '`git clean` and an unauthorized `git stash` discard work or mutate the repository-wide stash every work tree ' +
106
125
  'shares, and none is on the `.claude/settings.json` deny list (`operating-rules.md`). Do not run ' +
107
126
  'them on your own judgement. A commit goes through `pnpm josh git`; a stash pop goes through `pnpm ' +
108
127
  'josh stash:pop "<message>"`, never a positional `git stash pop` a shared stack lets another lane ' +
@@ -121,9 +140,7 @@ const ROW = {
121
140
  const worktree_guard = {
122
141
  ROW,
123
142
  WORKTREE_MUTATION_REASON,
124
- is_unauthorized_stash,
125
143
  is_unauthorized_worktree_change,
126
- is_worktree_checkout,
127
144
  touches_worktree,
128
145
  }
129
146
 
@@ -76,17 +76,13 @@ type Request =
76
76
  const READ_REQUEST: Request = { kind: 'read' }
77
77
 
78
78
  function read_arguments(argv: ReadonlyArray<string>): ParsedValues | undefined {
79
- return cli_flags.parse_or_undefined({ args: [...argv], options: OPTIONS, strict: true })?.values
80
- }
81
-
82
- function text_of(value: OptionValue): string | undefined {
83
- return typeof value === 'string' ? value : undefined
79
+ return cli_flags.values_of(argv, OPTIONS)
84
80
  }
85
81
 
86
82
  // Absent is zero; present but not a count is `undefined`, which invalidates the whole invocation
87
83
  // rather than quietly counting nothing.
88
84
  function to_count(value: OptionValue): number | undefined {
89
- const text = text_of(value)
85
+ const text = cli_flags.string_of(value)
90
86
 
91
87
  if (text === undefined) return NO_INCREMENT
92
88
 
@@ -99,7 +95,7 @@ function to_count(value: OptionValue): number | undefined {
99
95
  // than a zero: there is no issue to record, which is a different fact from recording issue zero. A
100
96
  // present-but-malformed value invalidates the whole invocation, exactly as a bad `--merged` does.
101
97
  function to_done(value: OptionValue): Pick<CarryChange, 'done'> | undefined {
102
- const text = text_of(value)
98
+ const text = cli_flags.string_of(value)
103
99
 
104
100
  if (text === undefined) return {}
105
101
 
@@ -165,7 +161,7 @@ function group_count(values: ParsedValues): number {
165
161
  // the record simply declares no owner and every standing record reads as not provably live, which
166
162
  // refuses rather than resumes.
167
163
  function to_owner(value: OptionValue): CarryOwner | undefined {
168
- const text = text_of(value)
164
+ const text = cli_flags.string_of(value)
169
165
 
170
166
  if (text === undefined) return run_carry.NO_OWNER
171
167
 
@@ -179,7 +175,7 @@ function to_owner(value: OptionValue): CarryOwner | undefined {
179
175
  // A non-empty `--summary`, or nothing. An empty string is nothing here, so it reads as absent and the
180
176
  // pairing check below refuses it against `--retrospective`.
181
177
  function summary_text(values: ParsedValues): string | undefined {
182
- const summary = text_of(values.summary)
178
+ const summary = cli_flags.string_of(values.summary)
183
179
 
184
180
  return summary === undefined || summary === '' ? undefined : summary
185
181
  }
@@ -220,17 +216,17 @@ function to_claim_request(
220
216
  }
221
217
 
222
218
  function to_other_request(values: ParsedValues, owner: CarryOwner): Request | undefined {
223
- if (values.end === true) return { kind: 'end', stopped: text_of(values.stopped) }
219
+ if (values.end === true) return { kind: 'end', stopped: cli_flags.string_of(values.stopped) }
224
220
 
225
221
  return has_count(values) ? to_count_request(values, owner) : READ_REQUEST
226
222
  }
227
223
 
228
224
  function to_named_request(values: ParsedValues, owner: CarryOwner): Request | undefined {
229
- const begun = text_of(values.begin)
225
+ const begun = cli_flags.string_of(values.begin)
230
226
 
231
227
  if (begun !== undefined) return to_claim_request(begun, owner, false)
232
228
 
233
- const adopted = text_of(values.resume)
229
+ const adopted = cli_flags.string_of(values.resume)
234
230
 
235
231
  if (adopted !== undefined) return to_claim_request(adopted, owner, true)
236
232
 
@@ -447,11 +447,9 @@ const run_carry_cli = {
447
447
  RESUMED_VERDICT,
448
448
  STANDING_VERDICT,
449
449
  UNKNOWN_VERDICT,
450
- UNREADABLE_VERDICT,
451
450
  // Re-exported rather than restated: the usage line belongs to the half that parses, and a second
452
451
  // copy of it here would drift from the flags it describes.
453
452
  USAGE: run_carry_args.USAGE,
454
- main,
455
453
  run,
456
454
  }
457
455
 
@@ -1,5 +1,5 @@
1
- import { git_stash } from '#scripts/git/git-stash'
2
- import { stash_orphans } from '#scripts/git/stash-orphans'
1
+ import { git_stash } from '#scripts/git/stash/git-stash'
2
+ import { stash_orphans } from '#scripts/git/stash/stash-orphans'
3
3
  import { issue_state_cli } from '#scripts/issue/issue-state-cli'
4
4
  import { bounded_pool } from '#scripts/lib/bounded-pool'
5
5
 
@@ -107,7 +107,7 @@ function next_state(carry: StreakCarry, change: StreakChange, now: Date): Streak
107
107
  }
108
108
  }
109
109
 
110
- const run_carry_streak = { OUTAGE_FOLD_WINDOW_MS, next_state }
110
+ const run_carry_streak = { next_state }
111
111
 
112
112
  export type { StreakCarry, StreakChange, StreakState }
113
113
  export { run_carry_streak }
@@ -47,12 +47,7 @@ type Request =
47
47
  | { kind: 'end' }
48
48
 
49
49
  function read_arguments(argv: ReadonlyArray<string>): ParsedValues | undefined {
50
- return cli_flags.parse_or_undefined({
51
- args: [...argv],
52
- options: OPTIONS,
53
- strict: true,
54
- allowPositionals: true,
55
- })
50
+ return cli_flags.arguments_of(argv, OPTIONS)
56
51
  }
57
52
 
58
53
  // The issue is the sole positional, and it must be a real issue number: a cut relaunches
@@ -45,8 +45,6 @@ const {
45
45
  STALE_VERDICT,
46
46
  SUCCESS_EXIT_CODE,
47
47
  UNDER_THRESHOLD_VERDICT,
48
- UNKNOWN_VERDICT,
49
- UNREADABLE_VERDICT,
50
48
  UNREADY_VERDICT,
51
49
  refuse_unready,
52
50
  report,
@@ -423,18 +421,13 @@ const run_cut_cli = {
423
421
  FAILED_VERDICT,
424
422
  FRESH_VERDICT,
425
423
  HANDED_OFF_VERDICT,
426
- INCOMPLETE_VERDICT,
427
424
  NOT_A_LANE_VERDICT,
428
425
  OVER_VERDICT,
429
426
  RESUME_IMPL_VERDICT,
430
427
  RESUME_VERDICT,
431
428
  STALE_VERDICT,
432
429
  UNDER_THRESHOLD_VERDICT,
433
- UNKNOWN_VERDICT,
434
- UNREADABLE_VERDICT,
435
430
  UNREADY_VERDICT,
436
- USAGE: run_cut_args.USAGE,
437
- main,
438
431
  run,
439
432
  }
440
433
 
@@ -1,10 +1,8 @@
1
- import { execFileSync } from 'node:child_process'
2
1
  import { agent_role_profile } from '#scripts/agent/agent-role-profile'
3
2
  import { backlog_budget } from '#scripts/backlog/backlog-budget'
4
3
  import { CONTEXT_CUT_THRESHOLD } from '#scripts/cost-runtime/context-cut-threshold'
5
- import { git_utilities } from '#scripts/git/constants'
6
4
  import { git_command } from '#scripts/git/git-command'
7
- import { git_location_environment } from '#scripts/git/git-location-environment'
5
+ import { git_common_directory } from '#scripts/git/git-common-directory'
8
6
  import { stamp_file } from '#scripts/josh/stamp-file'
9
7
  import { lane_child_invocation } from '#scripts/lane/lane-child-invocation'
10
8
  import { z } from 'zod'
@@ -60,14 +58,6 @@ const IMPLEMENTATION_CONTEXT_THRESHOLD = CONTEXT_CUT_THRESHOLD
60
58
  const CUT_MAX_AGE_MS = backlog_budget.WHOLE_RUN_BUDGET_MS
61
59
  const CUT_MAX_AGE_HOURS = backlog_budget.WHOLE_RUN_BUDGET_HOURS
62
60
 
63
- // The synchronous git read runs inside a `PreToolUse` hook, which holds the tool call for as long as
64
- // it takes; `rev-parse` takes no lock, so anything past a second is a fault rather than slow work.
65
- const GIT_READ_TIMEOUT_MS = 5000
66
-
67
- // The two lines `GIT_DIRECTORY_ARGUMENTS` prints, in order: the work tree's own git directory, then the
68
- // common one every lane of a repository shares. `git_directories` reads the same two asynchronously.
69
- const WORKTREE_DIRECTORY_INDEX = 0
70
-
71
61
  const END_COMMAND = 'pnpm josh run:cut --end'
72
62
  const READ_COMMAND = 'pnpm josh run:cut --json'
73
63
 
@@ -224,10 +214,10 @@ function read_cut(target: string, now: Date = new Date()): CutRead {
224
214
 
225
215
  // **The same read as `read_cut(cut_path(await worktree_directory()))`, taken synchronously**
226
216
  // (joshuafolkken/kit#1864). The pre-gate cut is enforced from a `PreToolUse` guard, and a guard
227
- // answers synchronously or not at all — so the one git call the path derivation needs is made here
228
- // with `git_command.GIT_DIRECTORY_ARGUMENTS`, the same argument list the asynchronous reader uses,
229
- // rather than a second spelling of it. Everything after the path is already shared: `cut_path` keys
230
- // the record and `classify` parses and expires it.
217
+ // answers synchronously or not at all — so the one git call the path derivation needs is
218
+ // `git_common_directory.own()`, the synchronous twin of the asynchronous reader, rather than a second
219
+ // spelling of it. Everything after the path is already shared: `cut_path` keys the record and
220
+ // `classify` parses and expires it.
231
221
  //
232
222
  // **A fault reads as "no cut was taken", and that direction is deliberate rather than fail-open.** A
233
223
  // checkout git cannot describe, a record that will not parse and an expired one all come back
@@ -235,47 +225,11 @@ function read_cut(target: string, now: Date = new Date()): CutRead {
235
225
  // The alternative errs the other way: a read fault would be taken for "already cut" and the guard
236
226
  // would go quiet on exactly the run it exists for. The cost of this direction is one refusal a lane
237
227
  // can answer by reissuing, since that row is delivered once per run.
238
- function git_directories_sync(cwd?: string): ReadonlyArray<string> {
239
- try {
240
- // The binary is resolved through `git_utilities` exactly as `git-spawn.ts` resolves it, so this
241
- // call does not answer to whatever `PATH` happens to hold. It runs the binary directly with an
242
- // argument array and no `shell` option, and both are internally controlled, never untrusted
243
- // input.
244
- const output = execFileSync(
245
- git_utilities.get_git_command_for_spawn(),
246
- [...git_command.GIT_DIRECTORY_ARGUMENTS],
247
- // git's own diagnostics are discarded: a checkout it cannot describe is already the
248
- // `undefined` below, and a hook that let `fatal: not a git repository` through would print it
249
- // in front of a tool call that is about to be allowed.
250
- // A `PreToolUse` hook holds the tool call while it runs, so the read is bounded rather than
251
- // left to whatever git does.
252
- // `cwd` is set only by `lane_cut_sync`, which reads another lane's record from the parent.
253
- // With a `cwd`, the git location variables are cleared so it is what git answers for: a hook
254
- // exports `GIT_DIR`, which beats `cwd` and would name the hook's checkout instead
255
- // (joshuafolkken/kit#2515). Without one the environment is kept, so this read resolves the same
256
- // checkout as the asynchronous `git_directories` that writes the record.
257
- {
258
- cwd,
259
- env:
260
- cwd === undefined
261
- ? process.env
262
- : { ...process.env, ...git_location_environment.location_free_environment() },
263
- encoding: 'utf8',
264
- stdio: ['ignore', 'pipe', 'ignore'],
265
- timeout: GIT_READ_TIMEOUT_MS,
266
- },
267
- ) // NOSONAR
268
-
269
- return output.split('\n').filter((line) => line !== '')
270
- } catch {
271
- return []
272
- }
273
- }
274
-
228
+ //
275
229
  // The work tree's own git directory (index 0), the same read `git_directories` makes asynchronously —
276
230
  // the record and the pre-gate guard both key on it.
277
231
  function worktree_git_directory_sync(): string | undefined {
278
- return git_directories_sync()[WORKTREE_DIRECTORY_INDEX]
232
+ return git_common_directory.own()
279
233
  }
280
234
 
281
235
  // **The directory is injectable so a test never has to write to the live record.** Keyed to the work
@@ -297,7 +251,7 @@ function carried_cut_sync(
297
251
  // lane's own git directory, so the parent — standing in the main checkout — resolves that directory
298
252
  // from the lane's path rather than its own, and gets the record path back to mark it.
299
253
  function lane_cut_sync(lane_directory: string): { target: string; cut: RunCut } | undefined {
300
- const directory = git_directories_sync(lane_directory)[WORKTREE_DIRECTORY_INDEX]
254
+ const directory = git_common_directory.own(lane_directory)
301
255
 
302
256
  if (directory === undefined) return undefined
303
257
 
@@ -56,10 +56,6 @@ interface ParsedArguments {
56
56
  values: ParsedValues
57
57
  }
58
58
 
59
- function read_arguments(argv: ReadonlyArray<string>): ParsedArguments | undefined {
60
- return cli_flags.parse_or_undefined({ args: [...argv], options: OPTIONS, allowPositionals: true })
61
- }
62
-
63
59
  function is_valid(parsed: ParsedArguments): boolean {
64
60
  return (
65
61
  parsed.positionals.length === 1 &&
@@ -78,7 +74,7 @@ function to_request(parsed: ParsedArguments): EndingRequest {
78
74
  }
79
75
 
80
76
  function parse_request(argv: ReadonlyArray<string>): EndingRequest | undefined {
81
- const parsed = read_arguments(argv)
77
+ const parsed = cli_flags.arguments_of(argv, OPTIONS)
82
78
 
83
79
  if (parsed === undefined || !is_valid(parsed)) return undefined
84
80
 
@@ -101,7 +97,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
101
97
  process.exitCode = await run(argv)
102
98
  }
103
99
 
104
- const run_ending_cli = { USAGE, main, parse_request, run }
100
+ const run_ending_cli = { USAGE, parse_request, run }
105
101
 
106
102
  if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
107
103
 
@@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs'
2
2
  import { agent_exit_record } from '#scripts/agent/agent-exit-record'
3
3
  import { api_outage } from '#scripts/agent/api-outage'
4
4
  import type { ClaudeResultEvent } from '#scripts/agent/claude-result-event'
5
- import { git_gh_issue_read } from '#scripts/git/git-gh-issue-read'
5
+ import { git_gh_issue_read } from '#scripts/gh/git-gh-issue-read'
6
6
  import { issue_state } from '#scripts/issue/issue-state'
7
7
  import { run_cut } from './run-cut'
8
8
  import { run_hold } from './run-hold'
@@ -222,9 +222,6 @@ async function check(request: EndingRequest): Promise<EndingDecision> {
222
222
  const run_ending = {
223
223
  check,
224
224
  decide,
225
- describe_exit,
226
- read_child_closed,
227
- read_cut_taken,
228
225
  read_exit,
229
226
  }
230
227