@joshuafolkken/kit 1.1784.0 → 1.2114.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (690) hide show
  1. package/.claude/agents/reviewer-verification.md +19 -0
  2. package/.claude/agents/reviewer.md +19 -0
  3. package/.claude/settings.json +5 -6
  4. package/.claude/skills/dependency-update/SKILL.md +9 -10
  5. package/.claude/skills/workflow-commands/SKILL.md +6 -6
  6. package/.claude/skills/workflow-commands/background-commands.md +8 -5
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +3 -1
  8. package/.claude/skills/workflow-commands/backlogrun-lanes.md +1 -1
  9. package/.claude/skills/workflow-commands/backlogrun-park.md +5 -2
  10. package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -3
  11. package/.claude/skills/workflow-commands/backlogrun-recovery.md +1 -1
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +3 -2
  13. package/.claude/skills/workflow-commands/backlogrun.md +1 -1
  14. package/.claude/skills/workflow-commands/chain-rule.md +41 -32
  15. package/.claude/skills/workflow-commands/delegation.md +6 -6
  16. package/.claude/skills/workflow-commands/entry-sequence.md +2 -2
  17. package/.claude/skills/workflow-commands/followup.md +7 -5
  18. package/.claude/skills/workflow-commands/fullrun-steps.md +6 -6
  19. package/.claude/skills/workflow-commands/fullrun.md +1 -1
  20. package/.claude/skills/workflow-commands/issue-comments.md +9 -4
  21. package/.claude/skills/workflow-commands/issue-fold-existing.md +2 -1
  22. package/.claude/skills/workflow-commands/kickoff.md +2 -2
  23. package/.claude/skills/workflow-commands/observation-filing.md +1 -1
  24. package/.claude/skills/workflow-commands/observation-ledger.md +6 -4
  25. package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -7
  26. package/.claude/skills/workflow-commands/prerequisite.md +3 -2
  27. package/.claude/skills/workflow-commands/retrospective.md +2 -2
  28. package/.claude/skills/workflow-commands/split-assessment.md +7 -5
  29. package/.codex/hooks.json +5 -5
  30. package/.github/actions/setup-pnpm/action.yml +9 -16
  31. package/.github/dependabot.yml +16 -0
  32. package/.github/workflows/auto-tag.yml +45 -0
  33. package/.github/workflows/ci.yml +155 -15
  34. package/.github/workflows/dependabot-auto-merge.yml +63 -4
  35. package/.github/workflows/production.yml +8 -0
  36. package/.github/workflows/publish.yml +59 -45
  37. package/.vscode/settings.json +19 -0
  38. package/CLAUDE.md +5 -12
  39. package/SECURITY.md +2 -2
  40. package/dist/CLAUDE.md +5 -12
  41. package/dist/commands/document-read-cli.js +2 -1
  42. package/dist/commands/document-section-main.js +2 -1
  43. package/dist/commands/read-set-cli.js +194 -134
  44. package/dist/commands/run-prep-main.js +9694 -10173
  45. package/dist/commands/run-step-cli.js +22138 -18285
  46. package/dist/hooks/audit-provision.js +23 -5
  47. package/dist/hooks/chunk-3GKE653K.js +6204 -0
  48. package/dist/hooks/chunk-45CJJOO7.js +1243 -0
  49. package/dist/hooks/{chunk-CWMBGKYW.js → chunk-5PM2JRGV.js} +2153 -856
  50. package/dist/hooks/{chunk-WR2KQAYZ.js → chunk-7SIUNQXK.js} +1207 -1470
  51. package/dist/hooks/{chunk-O2YBIDSI.js → chunk-CQD4LJE6.js} +1682 -1130
  52. package/dist/hooks/{chunk-VWWCFGWK.js → chunk-OPSRGWFU.js} +1 -1
  53. package/dist/hooks/{chunk-XGBNSWEI.js → chunk-UJ3FPMMM.js} +132 -49
  54. package/dist/hooks/chunk-VVNYJWEI.js +30 -0
  55. package/dist/hooks/chunk-Z6DQJKH3.js +2806 -0
  56. package/dist/hooks/codex-hook-adapter.js +8 -8
  57. package/dist/hooks/format-edited.js +4 -5
  58. package/dist/hooks/inputs.json +415 -389
  59. package/dist/hooks/pretool-guard.js +7 -6
  60. package/dist/hooks/session-lang.js +101 -258
  61. package/dist/hooks/stop-guard.js +1744 -2576
  62. package/dist/josh.js +7133 -6368
  63. package/dist/version/index.js +161 -1
  64. package/eslint/rules/comment-why-only.js +108 -0
  65. package/package.json +15 -8
  66. package/prompts/coding-standards.md +1 -1
  67. package/prompts/collaboration-workflow/file-edits.md +14 -11
  68. package/prompts/collaboration-workflow/issue-citation.md +0 -4
  69. package/prompts/collaboration-workflow/issue-template.md +40 -21
  70. package/prompts/collaboration-workflow/lane-instructions.md +3 -1
  71. package/prompts/collaboration-workflow/measurement.md +8 -1
  72. package/prompts/collaboration-workflow/operating-rules.md +11 -2
  73. package/prompts/collaboration-workflow/output-bounds.md +6 -2
  74. package/prompts/collaboration-workflow/plan-comment.md +1 -1
  75. package/prompts/collaboration-workflow/principles.md +9 -0
  76. package/prompts/collaboration-workflow/residency.md +3 -2
  77. package/prompts/collaboration-workflow/rule-delivery.md +13 -1
  78. package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
  79. package/prompts/collaboration-workflow/wip-cap.md +3 -1
  80. package/prompts/review-rubric.md +8 -0
  81. package/prompts/review.md +31 -22
  82. package/prompts/testing-guide.md +1 -0
  83. package/scripts/agent/agent-argv.ts +14 -16
  84. package/scripts/agent/agent-provider.ts +138 -0
  85. package/scripts/agent/agent-role-profile.ts +108 -156
  86. package/scripts/agent/agent-safe-text.ts +20 -5
  87. package/scripts/agent/api-usage-limit.ts +65 -0
  88. package/scripts/agent/claude-agent-argv.ts +19 -9
  89. package/scripts/agent/codex-agent-argv.ts +118 -22
  90. package/scripts/agent/usage-limit-reset.ts +179 -0
  91. package/scripts/auth/claude-token-output.ts +2 -2
  92. package/scripts/auto-ok/auto-ok-author.ts +53 -0
  93. package/scripts/auto-ok/auto-ok-cli.ts +20 -9
  94. package/scripts/backlog/backlog-defect-priority.ts +1 -1
  95. package/scripts/backlog/backlog-drive-cli.ts +6 -1
  96. package/scripts/backlog/backlog-drive-hold.ts +3 -3
  97. package/scripts/backlog/backlog-drive-idle.ts +10 -0
  98. package/scripts/backlog/backlog-drive-launch-pass.ts +90 -0
  99. package/scripts/backlog/backlog-drive-launch.ts +8 -2
  100. package/scripts/backlog/backlog-drive-named-offer.ts +73 -30
  101. package/scripts/backlog/backlog-drive-named.ts +28 -7
  102. package/scripts/backlog/backlog-drive-paused.ts +5 -4
  103. package/scripts/backlog/backlog-drive-restore.ts +11 -3
  104. package/scripts/backlog/backlog-drive.ts +21 -60
  105. package/scripts/backlog/backlog-gate-scope.ts +61 -0
  106. package/scripts/backlog/backlog-measure-close.ts +112 -0
  107. package/scripts/backlog/backlog-next.ts +39 -49
  108. package/scripts/backlog/backlog-occupied.ts +2 -2
  109. package/scripts/backlog/backlog-overlap.ts +42 -8
  110. package/scripts/backlog/backlog-plan-cli.ts +4 -1
  111. package/scripts/backlog/backlog-plan-comment.ts +81 -0
  112. package/scripts/backlog/backlog-plan-read.ts +19 -6
  113. package/scripts/backlog/backlog-pool.ts +50 -12
  114. package/scripts/backlog/backlog-rank.ts +60 -13
  115. package/scripts/backlog/backlog-stalled-detect.ts +2 -1
  116. package/scripts/backlog/backlog-waves.ts +17 -2
  117. package/scripts/backlog/backlogrun-launch.ts +7 -4
  118. package/scripts/cost-runtime/context-cut-payback.ts +27 -25
  119. package/scripts/cost-runtime/cost-cli.ts +37 -16
  120. package/scripts/cost-runtime/cost-pricing.ts +9 -0
  121. package/scripts/cost-runtime/cost-verdict.ts +4 -1
  122. package/scripts/delegation/delegation-policy.ts +2 -2
  123. package/scripts/delegation/duplicate-read-guard.ts +1 -0
  124. package/scripts/delegation/investigation-guard.ts +14 -2
  125. package/scripts/delegation/investigation-reads.ts +45 -23
  126. package/scripts/dependabot/dependabot-cooldown.ts +3 -2
  127. package/scripts/discovery/repo-party.ts +80 -20
  128. package/scripts/discovery/session-owner-pin.ts +51 -0
  129. package/scripts/document/capped-print.ts +1 -1
  130. package/scripts/document/command-reference-line-budget.ts +42 -0
  131. package/scripts/document/document-byte-budget.ts +17 -7
  132. package/scripts/document/document-checks.ts +20 -0
  133. package/scripts/document/document-ratchet-check.ts +101 -0
  134. package/scripts/document/document-section.ts +1 -0
  135. package/scripts/document/entry-read-budget.ts +7 -3
  136. package/scripts/document/issue-citation-budget.ts +94 -0
  137. package/scripts/epic/epic-cli-argv.ts +2 -2
  138. package/scripts/epic/epic-fetch.ts +4 -2
  139. package/scripts/epic/epic-graph.ts +7 -2
  140. package/scripts/epic/epic-issue.ts +3 -1
  141. package/scripts/epic/epic-rank.ts +5 -0
  142. package/scripts/exports/unused-members-check.ts +62 -0
  143. package/scripts/exports/unused-members-cli.ts +6 -51
  144. package/scripts/followup/followup-ci-path.ts +67 -0
  145. package/scripts/followup/followup-coderabbit-retrigger.ts +261 -0
  146. package/scripts/followup/followup-coderabbit-wait.ts +13 -10
  147. package/scripts/followup/followup-failed-tests.ts +160 -0
  148. package/scripts/followup/followup-job-needs.ts +100 -0
  149. package/scripts/followup/followup-job-rerun.ts +303 -0
  150. package/scripts/followup/followup-main-move.ts +113 -0
  151. package/scripts/followup/git-followup-finish.ts +43 -11
  152. package/scripts/followup/git-followup-pending.ts +3 -3
  153. package/scripts/followup/git-followup-stages.ts +41 -11
  154. package/scripts/followup/git-pr-followup-checks.ts +55 -16
  155. package/scripts/followup/git-pr-followup-wrapup.ts +24 -5
  156. package/scripts/followup/git-pr-followup.ts +62 -27
  157. package/scripts/fresh-machine/fresh-machine-script.ts +5 -9
  158. package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +2 -2
  159. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +2 -2
  160. package/scripts/gate/busy-average.ts +34 -2
  161. package/scripts/gate/check-related-pinned.ts +43 -0
  162. package/scripts/gate/check-related-reuse.ts +64 -0
  163. package/scripts/gate/check-related-section.ts +57 -0
  164. package/scripts/gate/check-related-unplanned.ts +34 -0
  165. package/scripts/gate/check-related.ts +265 -0
  166. package/scripts/gate/command-memory.ts +1 -1
  167. package/scripts/gate/core-admission.ts +24 -6
  168. package/scripts/gate/core-budget-timing.ts +20 -6
  169. package/scripts/gate/core-budget.ts +40 -11
  170. package/scripts/gate/core-wait-record.ts +3 -2
  171. package/scripts/gate/core-wait.ts +25 -2
  172. package/scripts/gate/core-weights.ts +15 -7
  173. package/scripts/gate/gate-labels.ts +46 -0
  174. package/scripts/gate/gate-ledger.ts +14 -6
  175. package/scripts/gate/gate-plan.ts +103 -58
  176. package/scripts/gate/gate-report.ts +9 -7
  177. package/scripts/gate/gate-run-steps.ts +26 -3
  178. package/scripts/gate/gate-skip.ts +45 -6
  179. package/scripts/gate/gate-static-group.ts +60 -0
  180. package/scripts/gate/gate-steps.ts +2 -1
  181. package/scripts/gate/gate-tree.ts +4 -2
  182. package/scripts/gate/hook-gate-reuse.ts +19 -2
  183. package/scripts/gate/metrics-totals.ts +59 -0
  184. package/scripts/gate/scoped-green.ts +68 -15
  185. package/scripts/gate/since-green.ts +14 -6
  186. package/scripts/gate/structural-checks.ts +96 -0
  187. package/scripts/gate/verification-gate.ts +51 -16
  188. package/scripts/gate/verification-inputs.ts +21 -6
  189. package/scripts/gate/verification-tail.ts +52 -0
  190. package/scripts/gh/gh-author-association.ts +23 -2
  191. package/scripts/gh/git-ai-review-scan.ts +1 -1
  192. package/scripts/gh/git-gh-api-path.ts +12 -3
  193. package/scripts/gh/git-gh-comments-unreadable.ts +36 -0
  194. package/scripts/gh/git-gh-exec.ts +32 -2
  195. package/scripts/gh/git-gh-issue-read.ts +4 -2
  196. package/scripts/gh/git-gh-issue-rest.ts +1 -0
  197. package/scripts/gh/git-gh-issue-write.ts +8 -2
  198. package/scripts/gh/git-gh-issue.ts +12 -5
  199. package/scripts/gh/git-gh-pr-auto-merge.ts +13 -6
  200. package/scripts/gh/git-gh-pr-graphql-state.ts +56 -0
  201. package/scripts/gh/git-gh-pr-read.ts +74 -13
  202. package/scripts/gh/git-gh-pr-rest.ts +3 -1
  203. package/scripts/gh/git-gh-pr-snapshot.ts +22 -7
  204. package/scripts/gh/git-gh-pr-too-large.ts +20 -0
  205. package/scripts/gh/git-gh-pr.ts +21 -7
  206. package/scripts/gh/git-gh-retry.ts +141 -0
  207. package/scripts/gh/git-pr-ai-review.ts +15 -6
  208. package/scripts/gh/git-pr-checks-eval.ts +3 -0
  209. package/scripts/gh/git-pr-checks.ts +5 -5
  210. package/scripts/git/base-tree.ts +30 -0
  211. package/scripts/git/change-base.ts +4 -10
  212. package/scripts/git/changed-paths-sync.ts +63 -0
  213. package/scripts/git/changed-paths.ts +16 -1
  214. package/scripts/git/git-common-directory.ts +11 -1
  215. package/scripts/git/git-diff-reads.ts +66 -20
  216. package/scripts/git/git-error.ts +9 -2
  217. package/scripts/git/git-schemas.ts +13 -0
  218. package/scripts/git/git-worktree.ts +13 -0
  219. package/scripts/git/gone-branch.ts +4 -1
  220. package/scripts/git/main-merge-budget-conflict.ts +89 -0
  221. package/scripts/git/main-merge-guard.ts +55 -18
  222. package/scripts/git/main-merge-regenerate.ts +59 -25
  223. package/scripts/git/main-merge.ts +53 -5
  224. package/scripts/git/no-base-checkout.ts +127 -0
  225. package/scripts/git/stash/git-stash.ts +11 -2
  226. package/scripts/git/stash/stash-push-cli.ts +10 -0
  227. package/scripts/hooks/batch-guard.ts +40 -21
  228. package/scripts/hooks/edited-cspell.ts +37 -11
  229. package/scripts/hooks/format-edited-file.ts +22 -2
  230. package/scripts/hooks/lane-plan-guard.ts +50 -0
  231. package/scripts/hooks/pre-commit-lint-switch.ts +9 -0
  232. package/scripts/hooks/pre-commit-lint.ts +14 -1
  233. package/scripts/hooks/pre-push-related-switch.ts +10 -0
  234. package/scripts/hooks/pre-push-unit.ts +76 -10
  235. package/scripts/hooks/pretool-guard.ts +2 -0
  236. package/scripts/hooks/reserved-run.ts +14 -1
  237. package/scripts/hooks/run-hook.sh +23 -8
  238. package/scripts/hooks/step-zero-notice.ts +6 -1
  239. package/scripts/hooks/stop-actions.ts +3 -15
  240. package/scripts/hooks/stop-guard.ts +7 -6
  241. package/scripts/init/distributed-paths.ts +1 -0
  242. package/scripts/init/hook-command-rewrite.ts +5 -1
  243. package/scripts/init/hook-launch.ts +4 -2
  244. package/scripts/issue/aggregation-split.ts +52 -0
  245. package/scripts/issue/defect-origin-line.ts +19 -1
  246. package/scripts/issue/defect-rate-cli.ts +5 -102
  247. package/scripts/issue/defect-report.ts +4 -4
  248. package/scripts/issue/effect-audit-cli.ts +178 -0
  249. package/scripts/issue/effect-audit.ts +185 -0
  250. package/scripts/issue/expected-effect-lint.ts +64 -9
  251. package/scripts/issue/git-next-issues.ts +5 -0
  252. package/scripts/issue/issue-body-or-comment.ts +38 -4
  253. package/scripts/issue/issue-cite-cli.ts +1 -3
  254. package/scripts/issue/issue-classification.ts +1 -0
  255. package/scripts/issue/issue-closing-pr.ts +8 -1
  256. package/scripts/issue/issue-evidence-exit.ts +4 -2
  257. package/scripts/issue/issue-file-cap.ts +58 -0
  258. package/scripts/issue/issue-file-cli.ts +111 -38
  259. package/scripts/issue/issue-file-deferral.ts +52 -0
  260. package/scripts/issue/issue-file-fold.ts +29 -10
  261. package/scripts/issue/issue-file-interrupt.ts +85 -0
  262. package/scripts/issue/issue-file-lane-hint.ts +30 -0
  263. package/scripts/issue/issue-file.ts +43 -6
  264. package/scripts/issue/issue-labels.ts +19 -2
  265. package/scripts/issue/issue-lint-cli.ts +27 -2
  266. package/scripts/issue/issue-measured-cli.ts +13 -35
  267. package/scripts/issue/issue-measured-close.ts +58 -0
  268. package/scripts/issue/issue-not-before-label.ts +2 -2
  269. package/scripts/issue/issue-not-before.ts +4 -1
  270. package/scripts/issue/issue-priority-cli.ts +60 -0
  271. package/scripts/issue/issue-priority-raise.ts +55 -0
  272. package/scripts/issue/issue-priority.ts +174 -43
  273. package/scripts/issue/issue-rank.ts +21 -4
  274. package/scripts/issue/issue-read-cli.ts +32 -6
  275. package/scripts/issue/issue-read.ts +37 -12
  276. package/scripts/issue/issue-sample-gate.ts +95 -74
  277. package/scripts/issue/issue-sample-prime.ts +127 -0
  278. package/scripts/issue/issue-sample-required.ts +57 -0
  279. package/scripts/issue/issue-sample-source.ts +12 -11
  280. package/scripts/issue/issue-search.ts +124 -0
  281. package/scripts/issue/issue-state.ts +13 -1
  282. package/scripts/issue/issue-template-section.ts +43 -0
  283. package/scripts/issue/issue-watch-diff.ts +31 -1
  284. package/scripts/issue/issue-watch-hook.ts +11 -2
  285. package/scripts/issue/issue-watch.ts +55 -12
  286. package/scripts/issue/markdown-section.ts +1 -0
  287. package/scripts/issue/measure-declaration.ts +121 -0
  288. package/scripts/issue/measure-rerun-cli.ts +7 -70
  289. package/scripts/issue/plan-consumers-section.ts +22 -1
  290. package/scripts/issue/reproduction-measure.ts +3 -1
  291. package/scripts/issue/size-estimate.ts +90 -0
  292. package/scripts/issue/trusted-measure.ts +84 -0
  293. package/scripts/josh/command-usage.ts +3 -2
  294. package/scripts/josh/durable-state-migrate.ts +105 -0
  295. package/scripts/josh/durable-state.ts +112 -0
  296. package/scripts/josh/josh-aliases.ts +95 -0
  297. package/scripts/josh/josh-command-map.ts +1 -82
  298. package/scripts/josh/josh-commands-agent-hooks.ts +6 -6
  299. package/scripts/josh/josh-commands-ai.ts +5 -5
  300. package/scripts/josh/josh-commands-development.ts +59 -58
  301. package/scripts/josh/josh-commands-issue-write.ts +23 -4
  302. package/scripts/josh/josh-commands-issue.ts +32 -0
  303. package/scripts/josh/josh-commands-lane.ts +87 -4
  304. package/scripts/josh/josh-commands-lint.ts +16 -3
  305. package/scripts/josh/josh-commands-maintenance.ts +15 -0
  306. package/scripts/josh/josh-commands-review.ts +41 -6
  307. package/scripts/josh/josh-commands-ship.ts +56 -8
  308. package/scripts/josh/josh-commands-test-check.ts +80 -0
  309. package/scripts/josh/josh-commands-workflow.ts +1 -1
  310. package/scripts/josh/josh-environment-file.ts +43 -3
  311. package/scripts/josh/josh-in-process.ts +2 -2
  312. package/scripts/josh/josh-logic.ts +5 -3
  313. package/scripts/josh/josh-run.ts +19 -1
  314. package/scripts/josh/run-record-path.ts +15 -0
  315. package/scripts/josh/stamp-file.ts +11 -2
  316. package/scripts/lane/lane-adopt-cli.ts +98 -0
  317. package/scripts/lane/lane-adopt.ts +208 -0
  318. package/scripts/lane/lane-await.ts +5 -8
  319. package/scripts/lane/lane-baseline.ts +123 -0
  320. package/scripts/lane/lane-breakdown-cli.ts +64 -0
  321. package/scripts/lane/lane-breakdown-implement.ts +170 -0
  322. package/scripts/lane/lane-breakdown-laps.ts +107 -0
  323. package/scripts/lane/lane-breakdown-pinned.ts +76 -0
  324. package/scripts/lane/lane-breakdown-text.ts +145 -0
  325. package/scripts/lane/lane-breakdown.ts +239 -0
  326. package/scripts/lane/lane-check-stats.ts +29 -8
  327. package/scripts/lane/lane-child-invocation.ts +9 -2
  328. package/scripts/lane/lane-child-mark-keys.ts +12 -0
  329. package/scripts/lane/lane-child-marker.ts +20 -1
  330. package/scripts/lane/lane-ci-path-stats.ts +73 -0
  331. package/scripts/lane/lane-claim-stats.ts +84 -0
  332. package/scripts/lane/lane-close.ts +8 -3
  333. package/scripts/lane/lane-dispatch-log.ts +3 -3
  334. package/scripts/lane/lane-dispatch.ts +2 -2
  335. package/scripts/lane/lane-gap-stats.ts +7 -6
  336. package/scripts/lane/lane-guard-policy.ts +7 -1
  337. package/scripts/lane/lane-implement-stats.ts +207 -0
  338. package/scripts/lane/lane-implement-subagents.ts +90 -0
  339. package/scripts/lane/lane-investigation-switch.ts +16 -0
  340. package/scripts/lane/lane-ledger-kind.ts +31 -0
  341. package/scripts/lane/lane-ledger-schema-ship.ts +49 -0
  342. package/scripts/lane/lane-ledger-schema.ts +119 -36
  343. package/scripts/lane/lane-ledger-write.ts +257 -0
  344. package/scripts/lane/lane-ledger.ts +31 -177
  345. package/scripts/lane/lane-load.ts +1 -1
  346. package/scripts/lane/lane-measure-cli.ts +176 -59
  347. package/scripts/lane/lane-net-read.ts +44 -0
  348. package/scripts/lane/lane-net-time.ts +212 -0
  349. package/scripts/lane/lane-open.ts +16 -7
  350. package/scripts/lane/lane-output.ts +2 -4
  351. package/scripts/lane/lane-overrun-prompt.ts +147 -0
  352. package/scripts/lane/lane-overrun.ts +274 -0
  353. package/scripts/lane/lane-paths.ts +24 -1
  354. package/scripts/lane/lane-pause-cli.ts +4 -1
  355. package/scripts/lane/lane-paused-spans.ts +97 -0
  356. package/scripts/lane/lane-plan-check.ts +207 -0
  357. package/scripts/lane/lane-plan-cli.ts +41 -0
  358. package/scripts/lane/lane-plan.ts +144 -0
  359. package/scripts/lane/lane-registry.ts +14 -1
  360. package/scripts/lane/lane-relaunch.ts +1 -1
  361. package/scripts/lane/lane-round-one-stats.ts +51 -0
  362. package/scripts/lane/lane-sampler.ts +23 -4
  363. package/scripts/lane/lane-session-action.ts +93 -18
  364. package/scripts/lane/lane-session-broker.ts +49 -21
  365. package/scripts/lane/lane-session-reread-main.ts +14 -0
  366. package/scripts/lane/lane-session-reread.ts +51 -0
  367. package/scripts/lane/lane-ship-lap-stats.ts +74 -0
  368. package/scripts/lane/lane-sleep.ts +58 -0
  369. package/scripts/lane/lane-spent.ts +1 -1
  370. package/scripts/lane/lane-split-stats.ts +28 -0
  371. package/scripts/lane/lane-stage-stats.ts +13 -1
  372. package/scripts/lane/lane-state.ts +41 -9
  373. package/scripts/lane/lane-stats-tables.ts +58 -0
  374. package/scripts/lane/lane-stats.ts +21 -5
  375. package/scripts/lane/lane-stop-stats.ts +51 -19
  376. package/scripts/lane/lane-tail-stats.ts +32 -0
  377. package/scripts/lane/lane-transcript-calls.ts +67 -10
  378. package/scripts/lane/lane-transcript-stats.ts +44 -12
  379. package/scripts/lane/lane-value-cell.ts +72 -0
  380. package/scripts/lane/lane-value.ts +118 -0
  381. package/scripts/lane/lane-withdraw-closed.ts +124 -0
  382. package/scripts/lane/lane-withdraw.ts +108 -31
  383. package/scripts/lane/lane-yield.ts +85 -0
  384. package/scripts/lane/openai-lane-ship.ts +12 -11
  385. package/scripts/lane/openai-lane-supervisor-decision.ts +6 -8
  386. package/scripts/lane/openai-lane-supervisor-owner.ts +5 -8
  387. package/scripts/lane/openai-lane-supervisor.ts +5 -4
  388. package/scripts/lib/poll.ts +38 -9
  389. package/scripts/lib/settled-together.ts +10 -0
  390. package/scripts/lib/shell-quote.ts +21 -0
  391. package/scripts/lib/token-shape.ts +111 -0
  392. package/scripts/lint/eslint-daemon-sources.ts +79 -0
  393. package/scripts/lint/eslint-daemon.ts +45 -6
  394. package/scripts/lint/eslint-warm-cli.ts +7 -0
  395. package/scripts/lint/eslint-warm.ts +66 -0
  396. package/scripts/lint/import-graph.ts +141 -11
  397. package/scripts/lint/lint-gate-scope.ts +2 -2
  398. package/scripts/lint/lint-parallel.ts +54 -6
  399. package/scripts/lint/lint-related.ts +154 -33
  400. package/scripts/lint/rename-cli.ts +179 -0
  401. package/scripts/lint/rename-identifier.ts +192 -0
  402. package/scripts/lint/type-only-imports.ts +58 -0
  403. package/scripts/notify/telegram-notify.ts +12 -3
  404. package/scripts/observations/observation-record.ts +42 -16
  405. package/scripts/observations/observations-flush.ts +32 -9
  406. package/scripts/overrides/overrides-check.ts +9 -1
  407. package/scripts/release/release-approval-prune.ts +7 -1
  408. package/scripts/repo/required-checks-logic.ts +4 -1
  409. package/scripts/repo/ruleset-check.ts +4 -3
  410. package/scripts/report/markdown-shape.ts +28 -0
  411. package/scripts/report/report-format-reference.ts +15 -1
  412. package/scripts/report/report-labels.ts +12 -1
  413. package/scripts/report/report-lint-child-summary.ts +94 -0
  414. package/scripts/report/report-lint-cli.ts +26 -7
  415. package/scripts/report/report-lint.ts +2 -20
  416. package/scripts/review/prose-stale-cli.ts +88 -0
  417. package/scripts/review/prose-stale-scan.ts +152 -0
  418. package/scripts/review/review-attest.ts +73 -23
  419. package/scripts/review/review-brief-cli.ts +68 -19
  420. package/scripts/review/review-brief-paths.ts +22 -0
  421. package/scripts/review/review-brief.ts +14 -7
  422. package/scripts/review/review-comment-carry.ts +47 -0
  423. package/scripts/review/review-comment-round.ts +85 -22
  424. package/scripts/review/review-finding-ledger.ts +109 -7
  425. package/scripts/review/review-finding-text.ts +43 -0
  426. package/scripts/review/review-interaction.ts +11 -0
  427. package/scripts/review/review-lane-handover.ts +68 -0
  428. package/scripts/review/review-lint-cli.ts +57 -0
  429. package/scripts/review/review-lint-findings.ts +92 -0
  430. package/scripts/review/review-lint-sections.ts +80 -0
  431. package/scripts/review/review-lint.ts +221 -0
  432. package/scripts/review/review-prior-findings.ts +102 -0
  433. package/scripts/review/review-readers-scan.ts +4 -2
  434. package/scripts/review/review-record-cli.ts +177 -54
  435. package/scripts/review/review-record-code-round.ts +55 -0
  436. package/scripts/review/review-record-comment.ts +60 -0
  437. package/scripts/review/review-record-interaction.ts +35 -0
  438. package/scripts/review/review-record-pinned.ts +108 -0
  439. package/scripts/review/review-record.ts +25 -1
  440. package/scripts/review/review-reviewed-tree.ts +307 -0
  441. package/scripts/review/review-round-one-closure.ts +62 -0
  442. package/scripts/review/review-round-reuse.ts +106 -0
  443. package/scripts/review/review-round2-cli.ts +91 -29
  444. package/scripts/review/review-round2-skip-comment.ts +55 -0
  445. package/scripts/review/review-round2.ts +24 -8
  446. package/scripts/review/review-stamps.ts +7 -3
  447. package/scripts/review/review-stop-log.ts +20 -6
  448. package/scripts/review/review-stops-cli.ts +2 -1
  449. package/scripts/review/review-submit-cli.ts +101 -0
  450. package/scripts/rules/agent-model.ts +1 -1
  451. package/scripts/rules/bash-triggers.ts +3 -3
  452. package/scripts/rules/concise-reply.ts +88 -0
  453. package/scripts/rules/credential-body.ts +77 -0
  454. package/scripts/rules/decision-oracle.ts +1 -1
  455. package/scripts/rules/delivered-rules.ts +36 -17
  456. package/scripts/rules/destructive-command.ts +3 -11
  457. package/scripts/rules/direct-issue-comment.ts +34 -12
  458. package/scripts/rules/direct-issue-read.ts +191 -0
  459. package/scripts/rules/direct-pr-create.ts +4 -24
  460. package/scripts/rules/early-heartbeat.ts +2 -0
  461. package/scripts/rules/edit-tool.ts +27 -0
  462. package/scripts/rules/file-edit-rows.ts +17 -0
  463. package/scripts/rules/file-rewrite.ts +146 -0
  464. package/scripts/rules/firing-point.ts +3 -2
  465. package/scripts/rules/gh-api.ts +128 -7
  466. package/scripts/rules/gh-repo-selector.ts +84 -0
  467. package/scripts/rules/git-force.ts +2 -2
  468. package/scripts/rules/guard-remedy.ts +14 -5
  469. package/scripts/rules/implementation-cut.ts +61 -28
  470. package/scripts/rules/investigator-foreground.ts +231 -0
  471. package/scripts/rules/issue-citation.ts +15 -60
  472. package/scripts/rules/issue-comments.ts +9 -4
  473. package/scripts/rules/josh-git-bare.ts +1 -1
  474. package/scripts/rules/lane-background.ts +41 -13
  475. package/scripts/rules/lane-direct-tool.ts +107 -9
  476. package/scripts/rules/lane-interactive-ask.ts +4 -1
  477. package/scripts/rules/lane-park.ts +4 -2
  478. package/scripts/rules/lane-spilled-read.ts +90 -0
  479. package/scripts/rules/lane-split-park.ts +1 -1
  480. package/scripts/rules/lane-switch-main.ts +4 -4
  481. package/scripts/rules/last-prompt.ts +20 -47
  482. package/scripts/rules/oracle-consulted.ts +1 -1
  483. package/scripts/rules/permission-guards.ts +5 -1
  484. package/scripts/rules/piped-verification-shapes.ts +110 -0
  485. package/scripts/rules/piped-verification.ts +67 -17
  486. package/scripts/rules/poll-loop.ts +72 -9
  487. package/scripts/rules/pr-merge.ts +5 -5
  488. package/scripts/rules/pre-gate-cut.ts +3 -3
  489. package/scripts/rules/protected-files.ts +88 -24
  490. package/scripts/rules/reply-language.ts +3 -17
  491. package/scripts/rules/reply-prose.ts +34 -0
  492. package/scripts/rules/repo-admin.ts +132 -0
  493. package/scripts/rules/reviewer-foreground.ts +88 -0
  494. package/scripts/rules/round-one-check-related.ts +120 -0
  495. package/scripts/rules/rule-body-guard.ts +5 -15
  496. package/scripts/rules/rule-value-cache.ts +53 -5
  497. package/scripts/rules/rule-value-candidates.ts +84 -0
  498. package/scripts/rules/rule-value-cli.ts +59 -11
  499. package/scripts/rules/rule-value.ts +17 -4
  500. package/scripts/rules/run-tail-rule.ts +1 -1
  501. package/scripts/rules/sed-in-place.ts +196 -0
  502. package/scripts/rules/shell-segments.ts +10 -2
  503. package/scripts/rules/stop-rule-rows.ts +1 -13
  504. package/scripts/rules/stop-rules.ts +33 -58
  505. package/scripts/rules/test-declared-commit.ts +1 -1
  506. package/scripts/rules/third-party-write.ts +110 -23
  507. package/scripts/rules/timed-rerun.ts +1 -1
  508. package/scripts/rules/turn-filings.ts +90 -0
  509. package/scripts/rules/worktree-guard.ts +22 -7
  510. package/scripts/run/board/run-board-ending-reason.ts +6 -2
  511. package/scripts/run/board/run-board-fit.ts +24 -1
  512. package/scripts/run/board/run-board-found.ts +134 -0
  513. package/scripts/run/board/run-board-header.ts +8 -0
  514. package/scripts/run/board/run-board-labels.ts +11 -1
  515. package/scripts/run/board/run-board-lane-time.ts +1 -0
  516. package/scripts/run/board/run-board-link.ts +15 -2
  517. package/scripts/run/board/run-board-notes.ts +7 -1
  518. package/scripts/run/board/run-board-operation.ts +4 -2
  519. package/scripts/run/board/run-board-phase.ts +2 -5
  520. package/scripts/run/board/run-board-plan.ts +1 -1
  521. package/scripts/run/board/run-board-read.ts +46 -1
  522. package/scripts/run/board/run-board-reason.ts +20 -8
  523. package/scripts/run/board/run-board-render-checks.ts +3 -2
  524. package/scripts/run/board/run-board-render-drawn.ts +11 -0
  525. package/scripts/run/board/run-board-render-found.ts +157 -0
  526. package/scripts/run/board/run-board-render-lead.ts +9 -0
  527. package/scripts/run/board/run-board-render-legend.ts +19 -0
  528. package/scripts/run/board/run-board-render-tail.ts +1 -1
  529. package/scripts/run/board/run-board-render.ts +82 -18
  530. package/scripts/run/board/run-board-spin.ts +1 -3
  531. package/scripts/run/board/run-board-status.ts +2 -0
  532. package/scripts/run/board/run-board-tick.ts +39 -10
  533. package/scripts/run/carry/run-carry-ended.ts +3 -2
  534. package/scripts/run/carry/run-carry.ts +3 -2
  535. package/scripts/run/cut/run-cut-cli.ts +33 -133
  536. package/scripts/run/cut/run-cut-digest.ts +152 -0
  537. package/scripts/run/cut/run-cut-handoff.ts +52 -8
  538. package/scripts/run/cut/run-cut-report.ts +24 -3
  539. package/scripts/run/cut/run-cut-resume.ts +129 -0
  540. package/scripts/run/cut/run-cut-review.ts +105 -0
  541. package/scripts/run/cut/run-cut.ts +18 -7
  542. package/scripts/run/detached-launch.ts +1 -1
  543. package/scripts/run/entry/run-entry-cli.ts +88 -19
  544. package/scripts/run/entry/run-entry-spill.ts +83 -0
  545. package/scripts/run/entry/run-entry-stop.ts +5 -1
  546. package/scripts/run/entry/run-entry-trust.ts +91 -0
  547. package/scripts/run/event/run-event-baseline.ts +56 -0
  548. package/scripts/run/event/run-event-filed.ts +9 -3
  549. package/scripts/run/event/run-event-overrun.ts +197 -0
  550. package/scripts/run/event/run-event-render.ts +4 -0
  551. package/scripts/run/event/run-event-stream.ts +25 -3
  552. package/scripts/run/hold/run-stop-notify.ts +3 -8
  553. package/scripts/run/merge/run-merge-cap.ts +57 -0
  554. package/scripts/run/merge/run-merge-cli.ts +66 -23
  555. package/scripts/run/merge/run-merge-outcome.ts +2 -0
  556. package/scripts/run/merge/run-merge-ship.ts +13 -3
  557. package/scripts/run/merge/run-merge-signals.ts +40 -23
  558. package/scripts/run/merge/run-merge-steps.ts +56 -36
  559. package/scripts/run/merge/run-merge-usage-limit.ts +53 -0
  560. package/scripts/run/merge/run-merge-withdrawn.ts +53 -0
  561. package/scripts/run/merge/run-merge.ts +41 -14
  562. package/scripts/run/review/run-review-cli.ts +306 -20
  563. package/scripts/run/review/run-review-early-push.ts +121 -0
  564. package/scripts/run/review/run-review-join-read.ts +94 -0
  565. package/scripts/run/review/run-review-pinned-accepted.ts +126 -0
  566. package/scripts/run/review/run-review-pinned-join.ts +216 -0
  567. package/scripts/run/review/run-review-pinned-steps.ts +383 -0
  568. package/scripts/run/review/run-review-pinned-tree.ts +37 -0
  569. package/scripts/run/review/run-review-pinned.ts +53 -0
  570. package/scripts/run/review/run-review-steps.ts +70 -34
  571. package/scripts/run/review/run-review.ts +26 -6
  572. package/scripts/run/run-parent-cut-hook.ts +3 -4
  573. package/scripts/run/run-prep.ts +1 -0
  574. package/scripts/run/run-stage-read.ts +2 -6
  575. package/scripts/run/run-step-cli.ts +17 -5
  576. package/scripts/run/run-step-lane-plan.ts +27 -0
  577. package/scripts/run/run-step-section.ts +26 -7
  578. package/scripts/run/run-step.ts +5 -2
  579. package/scripts/run/ship/run-ship-args.ts +19 -0
  580. package/scripts/run/ship/run-ship-brokered-review.ts +106 -0
  581. package/scripts/run/ship/run-ship-cli.ts +131 -39
  582. package/scripts/run/ship/run-ship-conflict-probe.ts +59 -0
  583. package/scripts/run/ship/run-ship-detach.ts +10 -4
  584. package/scripts/run/ship/run-ship-handover.ts +106 -0
  585. package/scripts/run/ship/run-ship-infra-retry.ts +16 -1
  586. package/scripts/run/ship/run-ship-lap.ts +63 -0
  587. package/scripts/run/ship/run-ship-next.ts +27 -26
  588. package/scripts/run/ship/run-ship-overlap.ts +8 -3
  589. package/scripts/run/ship/run-ship-place.ts +9 -2
  590. package/scripts/run/ship/run-ship-planned.ts +92 -0
  591. package/scripts/run/ship/run-ship-pre-detach-pinned.ts +197 -0
  592. package/scripts/run/ship/run-ship-pre-detach-timed.ts +7 -8
  593. package/scripts/run/ship/run-ship-pre-detach.ts +77 -23
  594. package/scripts/run/ship/run-ship-preflight.ts +16 -4
  595. package/scripts/run/ship/run-ship-probe.ts +23 -9
  596. package/scripts/run/ship/run-ship-relaunch-cap.ts +43 -7
  597. package/scripts/run/ship/run-ship-relaunch.ts +51 -0
  598. package/scripts/run/ship/run-ship-return.ts +103 -29
  599. package/scripts/run/ship/run-ship-review-reason.ts +24 -0
  600. package/scripts/run/ship/run-ship-review-steps.ts +230 -59
  601. package/scripts/run/ship/run-ship-review.ts +171 -51
  602. package/scripts/run/ship/run-ship-reviewer.ts +138 -42
  603. package/scripts/run/ship/run-ship-scoped.ts +39 -10
  604. package/scripts/run/ship/run-ship-stage.ts +49 -13
  605. package/scripts/run/ship/run-ship-steps.ts +24 -4
  606. package/scripts/run/ship/run-ship-stop-cause.ts +43 -2
  607. package/scripts/run/ship/run-ship-stop-context.ts +50 -13
  608. package/scripts/run/ship/run-ship-sync.ts +171 -30
  609. package/scripts/run/ship/run-ship-synced-scope.ts +178 -0
  610. package/scripts/run/ship/run-ship-wait-cli.ts +145 -0
  611. package/scripts/run/ship/run-ship-waiter.ts +114 -0
  612. package/scripts/run/ship/run-ship.ts +16 -2
  613. package/scripts/run/wake/run-wake-caffeinate.ts +48 -0
  614. package/scripts/run/wake/run-wake-cli.ts +6 -113
  615. package/scripts/run/wake/run-wake-code.ts +53 -11
  616. package/scripts/run/wake/run-wake-driver.ts +5 -3
  617. package/scripts/run/wake/run-wake-finish.ts +137 -0
  618. package/scripts/run/wake/run-wake-loop.ts +5 -3
  619. package/scripts/run/wake/run-wake-ports.ts +11 -3
  620. package/scripts/run/wake/run-wake-session.ts +2 -0
  621. package/scripts/run/wake/run-wake.ts +3 -2
  622. package/scripts/safe-chain/ci-installer-pin.ts +49 -8
  623. package/scripts/safe-chain/project-config.ts +3 -2
  624. package/scripts/security/secretlint-scan.ts +42 -9
  625. package/scripts/security/security-audit-provision-main.ts +9 -1
  626. package/scripts/security/security-audit-provision.ts +1 -1
  627. package/scripts/security/security-audit.ts +21 -1
  628. package/scripts/security/sonar-file.ts +10 -5
  629. package/scripts/split/split-assess.ts +12 -3
  630. package/scripts/split/split-early-notice.ts +116 -0
  631. package/scripts/split/split-measure.ts +20 -2
  632. package/scripts/split/split-resolution.ts +107 -0
  633. package/scripts/test/direct-importers.ts +185 -0
  634. package/scripts/test/pure-files-entries.ts +83 -0
  635. package/scripts/test/related-heavy-tests.ts +81 -0
  636. package/scripts/test/test-no-base.ts +88 -0
  637. package/scripts/test/test-pinned-cache-logic.ts +363 -0
  638. package/scripts/test/test-pinned-cache.ts +337 -0
  639. package/scripts/test/test-pinned-emit.ts +49 -0
  640. package/scripts/test/test-pinned-functions.ts +116 -0
  641. package/scripts/test/test-pinned-ledger.ts +80 -0
  642. package/scripts/test/test-pinned-logic.ts +208 -20
  643. package/scripts/test/test-pinned-main.ts +84 -18
  644. package/scripts/test/test-pinned-pool.ts +73 -0
  645. package/scripts/test/test-pinned-probe.ts +254 -0
  646. package/scripts/test/test-pinned-prune-logic.ts +118 -0
  647. package/scripts/test/test-pinned-reach.ts +194 -0
  648. package/scripts/test/test-pinned-record.ts +196 -0
  649. package/scripts/test/test-pinned-rewire.ts +148 -0
  650. package/scripts/test/test-pinned-spawn.ts +81 -0
  651. package/scripts/test/test-pinned-stage.ts +70 -0
  652. package/scripts/test/test-pinned.ts +258 -47
  653. package/scripts/test/test-reach-cli.ts +61 -0
  654. package/scripts/test/test-read-map.ts +35 -11
  655. package/scripts/test/test-read-recording.ts +17 -5
  656. package/scripts/test/test-read-trace.ts +26 -8
  657. package/scripts/test/test-red-logic.ts +46 -7
  658. package/scripts/test/test-red.ts +34 -14
  659. package/scripts/test/test-related-claim.ts +37 -0
  660. package/scripts/test/test-related-main.ts +4 -1
  661. package/scripts/test/test-related-moved.ts +91 -0
  662. package/scripts/test/test-related-record.ts +43 -23
  663. package/scripts/test/test-related-scope.ts +99 -34
  664. package/scripts/test/test-related-synced.ts +135 -0
  665. package/scripts/test/test-related-touched.ts +84 -0
  666. package/scripts/test/test-related.ts +167 -83
  667. package/scripts/test/test-unit-guard.ts +28 -5
  668. package/scripts/test/unit-durations.ts +41 -0
  669. package/scripts/test/unit-worker-share.ts +5 -4
  670. package/scripts/test/vitest-cache-directory.ts +19 -0
  671. package/scripts/test/vitest-cli-excludes.ts +14 -0
  672. package/scripts/test/vitest-failure-summary.ts +111 -0
  673. package/scripts/test/whole-suite-files.ts +12 -1
  674. package/scripts/time-runtime/time-batch-guard.ts +42 -4
  675. package/scripts/time-runtime/time-bundle-call.ts +1 -1
  676. package/scripts/time-runtime/time-bundles.ts +36 -5
  677. package/scripts/time-runtime/time-markers.ts +2 -2
  678. package/scripts/time-runtime/time-search-call.ts +38 -0
  679. package/scripts/time-runtime/time-shell.ts +1 -1
  680. package/scripts/time-runtime/time-transcript-line.ts +17 -5
  681. package/scripts/version/development-engines-verdict.ts +124 -0
  682. package/scripts/version/latest-corepack.ts +2 -0
  683. package/templates/gitignore +2 -0
  684. package/templates/workflows/ci.yml +41 -0
  685. package/dist/hooks/chunk-AZX4FGQ3.js +0 -207
  686. package/dist/hooks/chunk-PT5R6UJD.js +0 -7131
  687. package/dist/hooks/chunk-TUIFS5E7.js +0 -72
  688. package/dist/hooks/chunk-YCDOIR3I.js +0 -3456
  689. package/scripts/cost-runtime/context-cut-threshold.ts +0 -11
  690. package/scripts/rules/filing-cap.ts +0 -139
@@ -0,0 +1,152 @@
1
+ import path from 'node:path'
2
+ import { cost_transcript } from '#scripts/cost-runtime/cost-transcript'
3
+ import { own_session } from '#scripts/cost-runtime/own-session'
4
+ import { duplicate_reads } from '#scripts/delegation/duplicate-read-guard'
5
+ import { json_value } from '#scripts/lib/json-value'
6
+ import { transcript_record, type TranscriptRecord } from '#scripts/lib/transcript-record'
7
+ import { time_spans } from '#scripts/time-runtime/time-spans'
8
+ import { z } from 'zod'
9
+
10
+ // What the cut session already read and decided, derived from its own transcript so the resumed
11
+ // process does not spend minutes re-reading to rebuild it (joshuafolkken/kit#5040).
12
+ //
13
+ // **Derived, not written by the agent.** The reads are tool calls and the decisions are the
14
+ // `Auto-decided:` lines the session already logs (`CLAUDE.md` → "Decision autonomy") — in its reply,
15
+ // or in the Issue comment a tool call posts — so the cut takes both from the transcript: nothing to
16
+ // forget, and no handoff key the refusal has to spell out.
17
+
18
+ interface SessionDigest {
19
+ read: ReadonlyArray<string>
20
+ decisions: ReadonlyArray<string>
21
+ }
22
+
23
+ const session_digest_schema = z.object({
24
+ read: z.array(z.string()),
25
+ decisions: z.array(z.string()),
26
+ })
27
+
28
+ // The newest entries are kept: the record has a byte bound, and the last reads are the ones the
29
+ // resumed work continues from.
30
+ const MAX_READ_ENTRIES = 40
31
+ const MAX_DECISIONS = 12
32
+ const MAX_DECISION_CHARS = 240
33
+ const DECISION_PREFIX = 'Auto-decided:'
34
+ // A logged decision wherever it starts a line or follows a quote or `body=`; the space after the colon
35
+ // keeps out the bare prefix a source file spells.
36
+ const DECISION_LINE = /(?:^|[\s'"=])(Auto-decided: [^\n]+)/gu
37
+ // The quote closing a `body='…'` argument.
38
+ const TRAILING_QUOTES = /['"]$/u
39
+ const ASSISTANT = 'assistant'
40
+ const READ_LABEL = 'Already read before the cut — re-read only the lines you need'
41
+ const DECISIONS_LABEL = 'Decided before the cut — do not reopen'
42
+
43
+ function shown_path(target: string, cwd: string): string {
44
+ const relative = path.relative(cwd, path.resolve(cwd, target))
45
+
46
+ return relative.startsWith('..') ? target : relative
47
+ }
48
+
49
+ function newest_unique(entries: ReadonlyArray<string>, limit: number): Array<string> {
50
+ const unique = [...new Set(entries.toReversed())].toReversed()
51
+
52
+ return unique.slice(-limit)
53
+ }
54
+
55
+ function read_files_of(text: string, cwd: string): Array<string> {
56
+ const reads = time_spans
57
+ .parse_timeline(text)
58
+ .spans.filter((span) => duplicate_reads.is_successful_read(span))
59
+ .flatMap((span) => span.targets.map((target) => shown_path(target, cwd)))
60
+
61
+ return newest_unique(reads, MAX_READ_ENTRIES)
62
+ }
63
+
64
+ // Where a tool call carries an Issue comment: the Bash command posting it, or the body file a `Write`
65
+ // prepared for it. An `Edit`'s strings are source text, so they are not read.
66
+ const COMMENT_INPUT_KEYS = ['command', 'content']
67
+
68
+ function input_strings(input: unknown): Array<string> {
69
+ if (!json_value.is_record(input)) return []
70
+
71
+ return COMMENT_INPUT_KEYS.map((key) => input[key]).filter((value) => typeof value === 'string')
72
+ }
73
+
74
+ // What the session wrote: its reply text and the inputs of its tool calls, where an Issue workflow's
75
+ // decision comment travels.
76
+ function assistant_texts(record: TranscriptRecord | undefined): Array<string> {
77
+ if (record?.type !== ASSISTANT) return []
78
+
79
+ return transcript_record
80
+ .blocks_of(record)
81
+ .flatMap((block) => [block.text ?? '', ...input_strings(block.input)])
82
+ }
83
+
84
+ function decisions_of(text: string): Array<string> {
85
+ const decisions = text
86
+ .split('\n')
87
+ .flatMap((line) => assistant_texts(transcript_record.parse(line)))
88
+ .flatMap((written) => [...written.matchAll(DECISION_LINE)].map((match) => match[1] ?? ''))
89
+ .map((line) => line.replace(TRAILING_QUOTES, '').slice(0, MAX_DECISION_CHARS))
90
+
91
+ return newest_unique(decisions, MAX_DECISIONS)
92
+ }
93
+
94
+ function digest_of(text: string, cwd: string): SessionDigest {
95
+ return { read: read_files_of(text, cwd), decisions: decisions_of(text) }
96
+ }
97
+
98
+ // The running session's own transcript, or `undefined`. Only a session that names itself is read: the
99
+ // newest-file fallback could pick another session filed under the checkout (a Codex lane's reviewer).
100
+ function own_transcript(cwd: string, environment: NodeJS.ProcessEnv): string | undefined {
101
+ if (own_session.session_id_of(environment) === undefined) return undefined
102
+
103
+ const files = cost_transcript.list_sessions_across(cost_transcript.transcript_directories(cwd))
104
+ const selection = own_session.select_own_session(files, environment)
105
+ if (selection.kind === 'absent') return undefined
106
+
107
+ const file = files[selection.index]
108
+
109
+ return file === undefined ? undefined : cost_transcript.read_optional(file)
110
+ }
111
+
112
+ // The running session's own digest, or `undefined` when its transcript cannot be found — a cut is
113
+ // never refused for want of one.
114
+ function own_digest(
115
+ cwd: string = process.cwd(),
116
+ environment: NodeJS.ProcessEnv = process.env,
117
+ ): SessionDigest | undefined {
118
+ const text = own_transcript(cwd, environment)
119
+
120
+ return text === undefined ? undefined : digest_of(text, cwd)
121
+ }
122
+
123
+ function describe_list(label: string, entries: ReadonlyArray<string>): Array<string> {
124
+ if (entries.length === 0) return []
125
+
126
+ const bullets = entries.map((entry) => ` - ${entry}`).join('\n')
127
+
128
+ return [`${label}:\n${bullets}`]
129
+ }
130
+
131
+ // The block the resume prints; nothing for a digest with neither list.
132
+ function describe_digest(digest: SessionDigest | undefined): string | undefined {
133
+ if (digest === undefined) return undefined
134
+
135
+ const blocks = [
136
+ ...describe_list(READ_LABEL, digest.read),
137
+ ...describe_list(DECISIONS_LABEL, digest.decisions),
138
+ ]
139
+
140
+ return blocks.length === 0 ? undefined : blocks.join('\n\n')
141
+ }
142
+
143
+ const run_cut_digest = {
144
+ DECISION_PREFIX,
145
+ describe_digest,
146
+ digest_of,
147
+ own_digest,
148
+ session_digest_schema,
149
+ }
150
+
151
+ export type { SessionDigest }
152
+ export { run_cut_digest }
@@ -25,6 +25,9 @@ interface Handoff {
25
25
  completed: ReadonlyArray<string>
26
26
  remaining: ReadonlyArray<string>
27
27
  untouched: ReadonlyArray<string>
28
+ // An attested review round's findings not yet `review:record`ed — the conversation that held them is
29
+ // what the cut drops, so without this the resumed run reruns round 1 (joshuafolkken/kit#4868).
30
+ findings?: ReadonlyArray<string> | undefined
28
31
  }
29
32
 
30
33
  const handoff_schema = z.object({
@@ -32,6 +35,7 @@ const handoff_schema = z.object({
32
35
  completed: z.array(z.string()),
33
36
  remaining: z.array(z.string()),
34
37
  untouched: z.array(z.string()),
38
+ findings: z.array(z.string()).optional(),
35
39
  })
36
40
 
37
41
  // The label each list is printed under when the handoff is shown to the resumed session, kept beside
@@ -40,23 +44,34 @@ const COMPLETED_LABEL = 'Completed'
40
44
  const REMAINING_LABEL = 'Remaining'
41
45
  const UNTOUCHED_LABEL = 'Deliberately untouched'
42
46
  const INSTRUCTION_LABEL = 'Instruction (verbatim)'
47
+ const FINDINGS_LABEL =
48
+ 'Round-1 findings, attested but not recorded — do not rerun round 1: fix them, then record them with `pnpm josh review:record --issue <N>`'
43
49
  const EMPTY_LIST_NOTE = '(none)'
44
50
 
45
51
  type HandoffKey = keyof Handoff
46
52
 
47
- function describe_key(key: HandoffKey): string {
48
- const value = handoff_schema.shape[key] instanceof z.ZodArray ? '["…"]' : '"…"'
49
-
50
- return `"${key}": ${value}`
53
+ // The placeholders each example value is drawn with; `findings`' says which round it carries. They
54
+ // parse, so a copied example is read as entries — `carried_findings` drops them, or a copied
55
+ // `findings` would pass the unrecorded-round refusal.
56
+ const PLACEHOLDER = '…'
57
+ const FINDINGS_PLACEHOLDER = 'unrecorded'
58
+ const EXAMPLE_LIST = `["${PLACEHOLDER}"]`
59
+
60
+ const EXAMPLE_VALUES: Readonly<Record<HandoffKey, string>> = {
61
+ instruction: `"${PLACEHOLDER}"`,
62
+ completed: EXAMPLE_LIST,
63
+ remaining: EXAMPLE_LIST,
64
+ untouched: EXAMPLE_LIST,
65
+ findings: `["${FINDINGS_PLACEHOLDER}"]`,
51
66
  }
52
67
 
53
- // The shape a handoff file must have, derived from `handoff_schema` so the refusal that asks for the file
68
+ // The shape a handoff file must have, keyed from `handoff_schema` so the refusal that asks for the file
54
69
  // and the error that rejects it can never name a key the parser does not read — a refusal listing the
55
70
  // items in prose invites Markdown, which `parse_handoff` rejects.
56
- const HANDOFF_FORMAT = `a JSON object {${handoff_schema
71
+ const HANDOFF_FORMAT = `{${handoff_schema
57
72
  .keyof()
58
- .options.map((key) => describe_key(key))
59
- .join(', ')}}`
73
+ .options.map((key) => `"${key}":${EXAMPLE_VALUES[key]}`)
74
+ .join(',')}}`
60
75
 
61
76
  function parse_handoff(raw: string): Handoff | undefined {
62
77
  return json_value.parse_with(raw, handoff_schema)
@@ -115,6 +130,25 @@ function describe_list(label: string, items: ReadonlyArray<string>): string {
115
130
  return `${label}:\n${bullets}`
116
131
  }
117
132
 
133
+ // The findings a handoff really carries: a blank entry or an example placeholder is no finding.
134
+ function carried_findings(handoff: Handoff | undefined): ReadonlyArray<string> {
135
+ const findings = handoff?.findings ?? []
136
+
137
+ return findings.filter(
138
+ (finding) => ![PLACEHOLDER, FINDINGS_PLACEHOLDER, ''].includes(finding.trim()),
139
+ )
140
+ }
141
+
142
+ // Carried findings are printed only when there are some — a handoff cut before any review says nothing
143
+ // about one.
144
+ function describe_findings(handoff: Handoff): ReadonlyArray<string> {
145
+ const findings = carried_findings(handoff)
146
+
147
+ if (findings.length === 0) return []
148
+
149
+ return [describe_list(FINDINGS_LABEL, findings)]
150
+ }
151
+
118
152
  // The block the resume prints to standard error so the fresh process continues on the original
119
153
  // instruction rather than the tree alone.
120
154
  function describe_handoff(handoff: Handoff): string {
@@ -123,6 +157,7 @@ function describe_handoff(handoff: Handoff): string {
123
157
  describe_list(COMPLETED_LABEL, handoff.completed),
124
158
  describe_list(REMAINING_LABEL, handoff.remaining),
125
159
  describe_list(UNTOUCHED_LABEL, handoff.untouched),
160
+ ...describe_findings(handoff),
126
161
  ].join('\n\n')
127
162
  }
128
163
 
@@ -130,10 +165,19 @@ function describe_handoff(handoff: Handoff): string {
130
165
  // untracked non-ignored file, cannot commit the note with the code. A refusal that asked for "a file"
131
166
  // and named no place got one written beside the code and committed (joshuafolkken/kit#3603).
132
167
  const HANDOFF_PATH = '.josh/tmp/handoff-<N>.json'
168
+ const ISSUE_PLACEHOLDER = '<N>'
169
+
170
+ // The handoff path for one issue, relative to the checkout — the path `HANDOFF_PATH` tells the run
171
+ // to write, so the implementation-cut guard can let that one write through.
172
+ function handoff_path_of(issue: string): string {
173
+ return HANDOFF_PATH.replace(ISSUE_PLACEHOLDER, () => issue)
174
+ }
133
175
 
134
176
  const run_cut_handoff = {
135
177
  HANDOFF_FORMAT,
136
178
  HANDOFF_PATH,
179
+ handoff_path_of,
180
+ carried_findings,
137
181
  describe_handoff,
138
182
  handoff_schema,
139
183
  is_complete_handoff,
@@ -38,6 +38,7 @@ const UNKNOWN_VERDICT = 'unknown'
38
38
  // The asking session is over the shared context-cut threshold, so an implementation cut was not
39
39
  // resumed into it — the same refusal `run:carry` answers `over` with.
40
40
  const OVER_VERDICT = 'over'
41
+ const SPLIT_UNRESOLVED_VERDICT = 'split-unresolved'
41
42
 
42
43
  function report(verdict: string, code: number): number {
43
44
  console.info(verdict)
@@ -127,12 +128,13 @@ function report_under_threshold(): number {
127
128
  }
128
129
 
129
130
  // **A ship reviewer takes no cut, of either phase** (joshuafolkken/kit#3623). Its supervisor is waiting
130
- // on the findings file it has yet to write, so a relaunch would stand a second child in the lane beside
131
+ // on the findings it has yet to submit, so a relaunch would stand a second child in the lane beside
131
132
  // the one the supervisor repairs with. Answered `not-a-lane`, the verdict that already means "nothing
132
- // was cut and this process carries on".
133
+ // was cut and this process carries on". The message names no sink: its review prompt says whether it
134
+ // submits through `review:submit` or, on a lane that predates it, writes a path (joshuafolkken/kit#4799).
133
135
  function report_reviewer(): number {
134
136
  console.error(
135
- 'This session is a ship reviewer, which its supervisor is waiting on, so nothing was cut and nothing was relaunched. Write the findings file and finish the review in this process.',
137
+ 'This session is a ship reviewer, which its supervisor is waiting on, so nothing was cut and nothing was relaunched. Finish the review in this process and submit its findings the way your review prompt says.',
136
138
  )
137
139
 
138
140
  return report(NOT_A_LANE_VERDICT, SUCCESS_EXIT_CODE)
@@ -174,6 +176,22 @@ function report_over(): number {
174
176
  return report(OVER_VERDICT, FAILURE_EXIT_CODE)
175
177
  }
176
178
 
179
+ function report_missing_supervisor(issue: string): number {
180
+ console.error(
181
+ `The OpenAI supervisor for ${session_cite.issue(issue)} is not live, so this nested process was not cut and can continue. Re-dispatch the lane to recover the supervisor.`,
182
+ )
183
+
184
+ return report(FAILED_VERDICT, FAILURE_EXIT_CODE)
185
+ }
186
+
187
+ // The lane got the split notice and has answered it neither way, so nothing was cut and the run does
188
+ // not go on to the gate until it does (joshuafolkken/kit#4695). `note` says which answers it takes.
189
+ function report_split_unresolved(note: string): number {
190
+ console.error(note)
191
+
192
+ return report(SPLIT_UNRESOLVED_VERDICT, FAILURE_EXIT_CODE)
193
+ }
194
+
177
195
  const run_cut_report = {
178
196
  BAD_HANDOFF_VERDICT,
179
197
  BUSY_VERDICT,
@@ -191,6 +209,7 @@ const run_cut_report = {
191
209
  RELAUNCHED_CUT_MARKER,
192
210
  RESUME_IMPL_VERDICT,
193
211
  RESUME_VERDICT,
212
+ SPLIT_UNRESOLVED_VERDICT,
194
213
  STALE_VERDICT,
195
214
  SUCCESS_EXIT_CODE,
196
215
  UNDER_THRESHOLD_VERDICT,
@@ -205,9 +224,11 @@ const run_cut_report = {
205
224
  report_handed_off,
206
225
  report_held_cut,
207
226
  report_incomplete,
227
+ report_missing_supervisor,
208
228
  report_over,
209
229
  report_relaunched_cut,
210
230
  report_reviewer,
231
+ report_split_unresolved,
211
232
  report_stale,
212
233
  report_under_threshold,
213
234
  report_unknown,
@@ -0,0 +1,129 @@
1
+ import { cost_cli } from '#scripts/cost-runtime/cost-cli'
2
+ import { cost_verdict } from '#scripts/cost-runtime/cost-verdict'
3
+ import { issue_cite } from '#scripts/issue/issue-cite'
4
+ import { run_event_stream } from '#scripts/run/event/run-event-stream'
5
+ import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
6
+ import { run_cut, type RunCut } from './run-cut'
7
+ import { run_cut_report } from './run-cut-report'
8
+ import { run_cut_review } from './run-cut-review'
9
+
10
+ // `josh run:cut --resume <N>` — a fresh process asking whether it resumes a cut: it verifies the tree
11
+ // against the record and adopts it, answering which phase it resumes into. Taking a cut is
12
+ // `run-cut-cli.ts`'s.
13
+
14
+ const {
15
+ FRESH_VERDICT,
16
+ HANDED_OFF_VERDICT,
17
+ INCOMPLETE_VERDICT,
18
+ RESUME_IMPL_VERDICT,
19
+ RESUME_VERDICT,
20
+ SUCCESS_EXIT_CODE,
21
+ report,
22
+ report_busy,
23
+ report_handed_off,
24
+ report_incomplete,
25
+ report_over,
26
+ report_stale,
27
+ report_unreadable,
28
+ } = run_cut_report
29
+
30
+ // **The adoption is the resume-uniqueness guarantee**: it removes and creates exclusively, so of two
31
+ // racing resumes only one wins the create and the loser is answered `busy`.
32
+ // An implementation cut resumes back into implementation; a pre-gate one into the gate. The resuming
33
+ // child is told which by the verdict rather than reconstructing it from the record.
34
+ function resume_verdict_for(cut_record: RunCut): string {
35
+ return run_cut.resumes_into_implementation(cut_record.phase)
36
+ ? RESUME_IMPL_VERDICT
37
+ : RESUME_VERDICT
38
+ }
39
+
40
+ // **An implementation resume removes the record; a pre-gate one marks it handed off**.
41
+ // The cuts have different multiplicities sharing one record: the pre-gate cut fires once per lane, so
42
+ // its record must survive to answer a second resume `handed-off`; the implementation cut is guarded by the run's
43
+ // event stream rather than the cut record, so its record is cleared on resume — a lingering record
44
+ // would keep the pre-gate guard, which reads `carried_cut_sync`, silent for the rest of the run. A double
45
+ // cut stays impossible either way: `begin_cut`'s exclusive create is what prevents it.
46
+ function take_over(target: string, cut_record: RunCut): RunCut | undefined {
47
+ if (!run_cut.resumes_into_implementation(cut_record.phase)) {
48
+ return run_cut.adopt_cut(target, cut_record)
49
+ }
50
+
51
+ run_cut.end_cut(target)
52
+
53
+ return cut_record
54
+ }
55
+
56
+ // **An implementation resume appends a `resume` event**. It clears the record
57
+ // the `cut` event stood for, so the stream is what moves `run:step` back to implementation; a pre-gate
58
+ // resume keeps its record and appends nothing. Best-effort, as the cut's own append is.
59
+ async function emit_resume_event(issue: string, verdict: string): Promise<void> {
60
+ if (verdict !== RESUME_IMPL_VERDICT) return
61
+
62
+ await run_event_stream_emit.emit(
63
+ run_event_stream.EVENT_KIND.RESUME,
64
+ `${issue_cite.plain(issue)} resumed`,
65
+ )
66
+ }
67
+
68
+ async function adopt(target: string, cut_record: RunCut): Promise<number> {
69
+ const taken = take_over(target, cut_record)
70
+
71
+ if (taken === undefined) return report_busy(cut_record)
72
+
73
+ const verdict = resume_verdict_for(cut_record)
74
+
75
+ await run_cut_review.announce_resume(cut_record, verdict === RESUME_IMPL_VERDICT)
76
+ await emit_resume_event(cut_record.issue, verdict)
77
+
78
+ return report(verdict, SUCCESS_EXIT_CODE)
79
+ }
80
+
81
+ // A relaunched lane child and a fresh session both measure `under`, so only the session that took an
82
+ // implementation cut resumes over the threshold; unmeasurable is not refused.
83
+ function is_over_threshold_resume(cut_record: RunCut): boolean {
84
+ if (!run_cut.resumes_into_implementation(cut_record.phase)) return false
85
+
86
+ return cost_cli.session_verdict() === cost_verdict.OVER_VERDICT
87
+ }
88
+
89
+ async function verify_and_adopt(
90
+ target: string,
91
+ cut_record: RunCut,
92
+ issue: string,
93
+ ): Promise<number> {
94
+ const state = await run_cut.current_state()
95
+ const verdict = run_cut.classify_resume(cut_record, {
96
+ issue,
97
+ current_branch: state.branch,
98
+ is_dirty: state.is_dirty,
99
+ is_held: state.is_held,
100
+ })
101
+
102
+ if (verdict === HANDED_OFF_VERDICT) return report_handed_off(cut_record)
103
+
104
+ if (verdict === 'stale') return report_stale(cut_record)
105
+
106
+ if (verdict === INCOMPLETE_VERDICT) return report_incomplete(cut_record)
107
+
108
+ if (is_over_threshold_resume(cut_record)) return report_over()
109
+
110
+ return await adopt(target, cut_record)
111
+ }
112
+
113
+ async function resume(target: string, issue: string): Promise<number> {
114
+ const read = run_cut.read_cut(target)
115
+
116
+ if (read.kind === 'none') return report(FRESH_VERDICT, SUCCESS_EXIT_CODE)
117
+
118
+ if (read.kind === 'unreadable') return report_unreadable()
119
+
120
+ if (read.kind === 'expired') return report_stale(read.cut)
121
+
122
+ return await verify_and_adopt(target, read.cut, issue)
123
+ }
124
+
125
+ const run_cut_resume = {
126
+ resume,
127
+ }
128
+
129
+ export { run_cut_resume }
@@ -0,0 +1,105 @@
1
+ import { git_command } from '#scripts/git/git-command'
2
+ import { review_attest } from '#scripts/review/review-attest'
3
+ import { review_prior_findings } from '#scripts/review/review-prior-findings'
4
+ import { review_record } from '#scripts/review/review-record'
5
+ import { run_cut, type RunCut } from './run-cut'
6
+ import { run_cut_digest } from './run-cut-digest'
7
+ import { run_cut_handoff, type Handoff } from './run-cut-handoff'
8
+
9
+ // The review round an implementation cut has to carry across the process boundary
10
+ // (joshuafolkken/kit#4868). A lane child's in-session reviewer returns its findings into the
11
+ // conversation, and `review:record` is run after the fixes — so a cut between the two dropped the
12
+ // findings with the conversation, and the resumed child reran round 1 in full. The cut is refused
13
+ // until the round is recorded or its findings ride in the handoff, and the resume prints a recorded
14
+ // round back so it is continued, not rerun.
15
+
16
+ function unrecorded_note(issue: string): string {
17
+ return (
18
+ 'a review round is attested on this branch but not recorded, and the handoff carries no ' +
19
+ `"findings" — run \`pnpm josh review:record --issue ${issue} [<finding> ...]\` before the cut, ` +
20
+ 'or list the round\'s findings under "findings" in the handoff, so the resumed run does not ' +
21
+ 'rerun round 1'
22
+ )
23
+ }
24
+
25
+ const RECORDED_ROUND_HEADING =
26
+ 'Round 1 is recorded for this issue — do not rerun it; continue the fixes, then the ship, ' +
27
+ 'which reviews only what moved since:'
28
+
29
+ interface CutScope {
30
+ issue: string
31
+ branch: string
32
+ phase: string
33
+ }
34
+
35
+ // Attested on this branch, with no `review:record` line for the issue — the round the cut would lose.
36
+ async function has_unrecorded_round(issue: string, branch: string): Promise<boolean> {
37
+ const root = await git_command.repository_root()
38
+
39
+ if (!review_attest.is_attested_on({ branch }, root)) return false
40
+
41
+ const recorded = await review_record.check(Number(issue))
42
+
43
+ return recorded.status === 'missing'
44
+ }
45
+
46
+ // Only an implementation cut without carried findings can lose a round: a pre-gate cut is taken
47
+ // before any review.
48
+ function may_drop_round(scope: CutScope, handoff: Handoff | undefined): boolean {
49
+ if (!run_cut.resumes_into_implementation(scope.phase)) return false
50
+
51
+ return run_cut_handoff.carried_findings(handoff).length === 0
52
+ }
53
+
54
+ // The note an implementation cut is refused with when it would drop an unrecorded round, else
55
+ // `undefined`.
56
+ async function unrecorded_refusal(
57
+ scope: CutScope,
58
+ handoff: Handoff | undefined,
59
+ ): Promise<string | undefined> {
60
+ if (!may_drop_round(scope, handoff)) return undefined
61
+
62
+ const is_unrecorded = await has_unrecorded_round(scope.issue, scope.branch)
63
+
64
+ return is_unrecorded ? unrecorded_note(scope.issue) : undefined
65
+ }
66
+
67
+ // What an implementation resume prints about a round recorded before the cut: the heading and the
68
+ // findings the stop log kept with their reasons; nothing when no round is recorded.
69
+ async function recorded_round_lines(issue: string): Promise<ReadonlyArray<string>> {
70
+ const recorded = await review_record.check(Number(issue))
71
+
72
+ if (recorded.status !== 'ok') return []
73
+
74
+ const findings = review_prior_findings.latest(issue, () => true)
75
+
76
+ return [RECORDED_ROUND_HEADING, ...findings.map((finding) => ` - ${finding}`)]
77
+ }
78
+
79
+ // The carried instruction and work state, printed to standard error so the resumed session continues
80
+ // on what the run was told to do rather than on the tree alone — and, for an implementation resume,
81
+ // the round recorded before the cut. The record is cleared on adoption, so this is where it reaches
82
+ // the fresh process.
83
+ async function announce_resume(cut_record: RunCut, is_implementation: boolean): Promise<void> {
84
+ if (cut_record.handoff !== undefined) {
85
+ console.error(run_cut_handoff.describe_handoff(cut_record.handoff))
86
+ }
87
+
88
+ const digest = run_cut_digest.describe_digest(cut_record.digest)
89
+
90
+ if (digest !== undefined) console.error(digest)
91
+
92
+ if (!is_implementation) return
93
+
94
+ const lines = await recorded_round_lines(cut_record.issue)
95
+
96
+ if (lines.length > 0) console.error(lines.join('\n'))
97
+ }
98
+
99
+ const run_cut_review = {
100
+ RECORDED_ROUND_HEADING,
101
+ announce_resume,
102
+ unrecorded_refusal,
103
+ }
104
+
105
+ export { run_cut_review }
@@ -1,6 +1,5 @@
1
1
  import { agent_role_profile } from '#scripts/agent/agent-role-profile'
2
2
  import { backlog_budget } from '#scripts/backlog/backlog-budget'
3
- import { CONTEXT_CUT_THRESHOLD } from '#scripts/cost-runtime/context-cut-threshold'
4
3
  import { git_command } from '#scripts/git/git-command'
5
4
  import { git_common_directory } from '#scripts/git/git-common-directory'
6
5
  import { stamp_file } from '#scripts/josh/stamp-file'
@@ -9,6 +8,7 @@ import { lane_child_invocation } from '#scripts/lane/lane-child-invocation'
9
8
  import { json_value } from '#scripts/lib/json-value'
10
9
  import { run_hold, type RunHold } from '#scripts/run/hold/run-hold'
11
10
  import { z } from 'zod'
11
+ import { run_cut_digest, type SessionDigest } from './run-cut-digest'
12
12
  import { run_cut_handoff, type Handoff } from './run-cut-handoff'
13
13
 
14
14
  // A lane child is a detached `fullrun #<N>` process, and the thinking it accumulates while
@@ -45,11 +45,6 @@ const CUT_PREFIX = 'josh-run-cut-'
45
45
  // `IMPLEMENTATION_PHASE` drops the thinking accumulated *during* implementation and resumes back into
46
46
  // implementation (`resumes_into_implementation`); only the pre-gate cut resumes into the gate.
47
47
  const { PRE_GATE_PHASE, IMPLEMENTATION_PHASE } = agent_role_profile
48
- // **The measurement is the parent hand-off's, never a second one.** The lane child decides whether
49
- // to take this cut with `pnpm josh cost --cut` — the same per-request billed-input measurement (`cost_verdict.per_request_cost`) the parent's
50
- // `pnpm josh cost --cut` hand-off uses (`backlogrun-progress.md` → "The hand-off"). The shared
51
- // threshold prevents the scheduler and worker boundaries from drifting apart.
52
- const IMPLEMENTATION_CONTEXT_THRESHOLD = CONTEXT_CUT_THRESHOLD
53
48
  // **The bound is `backlog-budget.ts`'s idle wait, imported rather than restated**, so the eight hours
54
49
  // stay written once. A resume is expected within seconds of the cut, so this age is only a backstop
55
50
  // against a fresh process that never started; an expired record is cleared and replaced by the next
@@ -92,6 +87,8 @@ interface RunCut {
92
87
  // record of the scalar fields alone parses, while a resume into implementation refuses to continue without it (`classify_resume`
93
88
  // → `incomplete`), so a session is never silently continued lacking the instruction it needs.
94
89
  handoff?: Handoff | undefined
90
+ // What the cut session read and decided, printed on the resume (joshuafolkken/kit#5040).
91
+ digest?: SessionDigest | undefined
95
92
  // Set when `run:merge` found this cut still unadopted after every process of the lane had gone and
96
93
  // relaunched its successor itself. The fallback fires once per cut: a
97
94
  // successor that dies again before adopting is not relaunched a second time, so a lane that keeps
@@ -121,6 +118,8 @@ interface CutSpec {
121
118
  // The instruction and work state to carry, absent for a pre-gate cut that resumes into the gate
122
119
  // rather than into implementation.
123
120
  handoff?: Handoff | undefined
121
+ // What the cut session read and decided, derived from its transcript (`run-cut-digest.ts`).
122
+ digest?: SessionDigest | undefined
124
123
  }
125
124
 
126
125
  // What the resume classifier is asked about, gathered from the fresh process's own git state so the
@@ -155,6 +154,7 @@ const run_cut_schema = z.object({
155
154
  cut_at: z.string(),
156
155
  is_handed_off: z.boolean().optional(),
157
156
  handoff: run_cut_handoff.handoff_schema.optional(),
157
+ digest: run_cut_digest.session_digest_schema.optional(),
158
158
  is_merge_relaunched: z.boolean().optional(),
159
159
  })
160
160
 
@@ -261,6 +261,7 @@ function fresh_cut(spec: CutSpec, now: Date): RunCut {
261
261
  cut_at: now.toISOString(),
262
262
  is_handed_off: true,
263
263
  handoff: spec.handoff,
264
+ digest: spec.digest,
264
265
  }
265
266
  }
266
267
 
@@ -285,6 +286,16 @@ function record_within_bound(spec: CutSpec, now: Date = new Date()): boolean {
285
286
  return within_handoff_bound(fresh_cut(spec, now))
286
287
  }
287
288
 
289
+ // An implementation cut carries what the session read and decided (`run-cut-digest.ts`); a digest the
290
+ // bound cannot hold is dropped, so a cut is never refused for it, and a pre-gate cut never derives one.
291
+ function with_digest(spec: CutSpec, digest_of: () => SessionDigest | undefined): CutSpec {
292
+ if (spec.handoff === undefined) return spec
293
+
294
+ const digested = { ...spec, digest: digest_of() }
295
+
296
+ return record_within_bound(digested) ? digested : spec
297
+ }
298
+
288
299
  // **Create-exclusively, exactly as `run-hold.ts` claims a tree.** A record already here means a cut is
289
300
  // already in flight for this tree, so `undefined` is "do not launch a second one" rather than an
290
301
  // error — the exclusive create is what makes a double cut, and so a double relaunch, impossible. A
@@ -455,7 +466,6 @@ const run_cut = {
455
466
  CUT_MAX_AGE_HOURS,
456
467
  CUT_MAX_AGE_MS,
457
468
  END_COMMAND,
458
- IMPLEMENTATION_CONTEXT_THRESHOLD,
459
469
  IMPLEMENTATION_PHASE,
460
470
  MAX_HANDOFF_BYTES,
461
471
  PRE_GATE_PHASE,
@@ -466,6 +476,7 @@ const run_cut = {
466
476
  classify,
467
477
  classify_resume,
468
478
  current_state,
479
+ with_digest,
469
480
  cut_path,
470
481
  describe_cut,
471
482
  end_cut,
@@ -21,7 +21,7 @@ import { launch_priority } from '#scripts/run/launch-priority'
21
21
 
22
22
  const NO_PID_NOTE = 'the process started without a pid'
23
23
  const UNSAFE_NOTE =
24
- 'the wake command or its arguments contain characters that are not safe to execute'
24
+ 'the wake command or its arguments are empty, over length, or contain characters that are not safe to execute'
25
25
 
26
26
  // Provider-specific commands and flags are composed before this boundary. This module accepts only
27
27
  // an argv vector and never infers policy from it; role/model/effort arrive separately as log metadata.