@joshuafolkken/kit 1.1784.0 → 1.2116.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 +60 -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 +386 -360
  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 +16 -9
  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
@@ -1,6 +1,7 @@
1
1
  import path from 'node:path'
2
2
  import { fileURLToPath } from 'node:url'
3
3
  import { agent_role_profile, type AgentProfile } from '#scripts/agent/agent-role-profile'
4
+ import { agent_session_role } from '#scripts/agent/agent-session-role'
4
5
  import { bash_output_cap_reader } from '#scripts/document/bash-output-cap'
5
6
  import { scoped_green } from '#scripts/gate/scoped-green'
6
7
  import { change_base } from '#scripts/git/change-base'
@@ -15,7 +16,7 @@ import { stamp_file } from '#scripts/josh/stamp-file'
15
16
  import { lane_session_broker } from '#scripts/lane/lane-session-broker'
16
17
  import { run_ship_review } from '#scripts/run/ship/run-ship-review'
17
18
  import { removed_tests_check } from './removed-tests-check'
18
- import { review_attest } from './review-attest'
19
+ import { review_attest, type ReviewSlot } from './review-attest'
19
20
  import { review_brief } from './review-brief'
20
21
  import { review_checkout, type ReviewCheckout } from './review-checkout'
21
22
  import { review_code_tree } from './review-code-tree'
@@ -23,6 +24,7 @@ import type { DiffParts } from './review-diff-parts'
23
24
  import { review_diff_write } from './review-diff-write'
24
25
  import { review_interaction } from './review-interaction'
25
26
  import { review_level, type ReviewLevel } from './review-level'
27
+ import { review_reviewed_tree } from './review-reviewed-tree'
26
28
  import { review_round_one_blobs } from './review-round-one-blobs'
27
29
  import { review_stamps } from './review-stamps'
28
30
  import { review_tree } from './review-tree'
@@ -100,7 +102,7 @@ function kept_note(taken_at: string): string {
100
102
  // **It is written once per run and never retaken**. Overwriting on every
101
103
  // round-1 invocation put a wrong `skip` one command away: run a bare `josh review:brief` after round
102
104
  // 1's fixes are in and the record is retaken against the fixed tree, the fix delta reads empty, and
103
- // `josh review:round2 --round-1-closed` fires arm A on unreviewed fix code. Keeping the record the
105
+ // `josh review:round2` on a closed round 1 fires arm A on unreviewed fix code. Keeping the record the
104
106
  // run already has removes that path outright — a second round-1 invocation reads it and leaves it
105
107
  // alone, so every later reading of the delta is measured from before the fixes.
106
108
  //
@@ -165,7 +167,7 @@ function record_round_one(
165
167
  // **The narrowing is measured from the tree that review was briefed on**, and only when that record
166
168
  // was written by the brief the pointer names: one left by an earlier brief is not the tree the
167
169
  // finished review read, so the resume reads the whole change instead.
168
- function attested_tree(checkout: ReviewCheckout): FileMapStamp | undefined {
170
+ function findings_tree(checkout: ReviewCheckout): FileMapStamp | undefined {
169
171
  const { findings } = lane_session_broker.review_paths(PROJECT_ROOT)
170
172
  const briefed = review_stamps.briefed_stamp.read()
171
173
 
@@ -180,18 +182,31 @@ function attested_tree(checkout: ReviewCheckout): FileMapStamp | undefined {
180
182
  return is_clean ? briefed : undefined
181
183
  }
182
184
 
183
- async function open_contract(): Promise<{
185
+ // **A recorded round narrows first**, from the tree `review:record` wrote it on — a lane's review
186
+ // before the ship writes no findings file, and its fixes are in that tree (joshuafolkken/kit#4620).
187
+ function attested_tree(checkout: ReviewCheckout): FileMapStamp | undefined {
188
+ return review_reviewed_tree.resume_point(checkout) ?? findings_tree(checkout)
189
+ }
190
+
191
+ function slot_of(interaction: ReadonlyArray<string> | undefined): ReviewSlot {
192
+ const { CODE, INTERACTION } = review_attest.REVIEW_SLOT
193
+
194
+ return interaction === undefined ? CODE : INTERACTION
195
+ }
196
+
197
+ async function open_contract(slot: ReviewSlot): Promise<{
184
198
  checkout: ReviewCheckout
185
199
  nonce: string
186
200
  resumed_from: FileMapStamp | undefined
187
201
  }> {
188
202
  const checkout = await review_checkout.read_checkout()
189
203
  const resumed_from = attested_tree(checkout)
190
-
191
204
  // Keyed on the root git just answered with, never on `process.cwd()`: the check made before the
192
205
  // merge asks git the same question, and the two hash different keys the moment one of them runs
193
206
  // from a subdirectory — a mismatch that would drop the guard with nothing printed.
194
- return { checkout, nonce: review_attest.record_target(checkout, checkout.root), resumed_from }
207
+ const nonce = review_attest.record_target(checkout, checkout.root, slot)
208
+
209
+ return { checkout, nonce, resumed_from }
195
210
  }
196
211
 
197
212
  // Retaken on every round-1 brief, after the pointer it pairs with. Swallowed:
@@ -258,7 +273,7 @@ async function read_readers(
258
273
 
259
274
  async function compose_brief(request: ComposeRequest): Promise<string> {
260
275
  const { round, paths, tree, base, profile, interaction } = request
261
- const opened = await open_contract()
276
+ const opened = await open_contract(slot_of(interaction))
262
277
  // The interaction review reads the whole change, never a resume's narrowing (joshuafolkken/kit#4276).
263
278
  const contract = interaction === undefined ? opened : { ...opened, resumed_from: undefined }
264
279
  const stamps = {
@@ -285,6 +300,7 @@ async function compose_brief(request: ComposeRequest): Promise<string> {
285
300
  readers: await read_readers(contract.checkout.root, base, paths),
286
301
  removed_tests: await read_removed_tests(),
287
302
  interaction,
303
+ high_cited: review_reviewed_tree.high_cited(),
288
304
  })
289
305
  }
290
306
 
@@ -295,7 +311,7 @@ async function compose_brief(request: ComposeRequest): Promise<string> {
295
311
  // failure it exists to prevent. Where it cannot be resolved the printed command keeps `change_base`'s
296
312
  // answer, which still runs, and the record is written without a base so the next round widens.
297
313
  async function read_bases(): Promise<{ base: string; commit: string | undefined }> {
298
- const commit = await change_base.resolved()
314
+ const commit = await change_base.resolved_through_merge()
299
315
 
300
316
  return { base: commit ?? (await git_command.change_base()), commit }
301
317
  }
@@ -344,6 +360,8 @@ interface ChangeReading {
344
360
  tree: Record<string, string>
345
361
  }
346
362
 
363
+ type Emit = (text: string) => void
364
+
347
365
  // One reading, used by every half below. Read twice, the level could describe a different change from
348
366
  // the digests printed beside it — and it would cost four git spawns to do so.
349
367
  async function read_change(): Promise<ChangeReading> {
@@ -370,6 +388,7 @@ async function record_review(
370
388
  async function run_review(
371
389
  round: number,
372
390
  reading: ChangeReading,
391
+ emit: Emit,
373
392
  interaction?: ReadonlyArray<string>,
374
393
  ): Promise<number> {
375
394
  const { base, commit, paths, tree } = reading
@@ -382,7 +401,7 @@ async function run_review(
382
401
  agent_role_profile.warn_of_default()
383
402
  const { profile } = resolved
384
403
 
385
- console.info(await compose_brief({ round, paths, tree, base, profile, interaction }))
404
+ emit(await compose_brief({ round, paths, tree, base, profile, interaction }))
386
405
  if (interaction === undefined) await record_review(round, tree, commit)
387
406
 
388
407
  return 0
@@ -391,15 +410,15 @@ async function run_review(
391
410
  // The interaction review's brief (joshuafolkken/kit#4276): `/code-review`'s round-1 brief over the
392
411
  // whole change, with the role and the run-tooling paths appended. Not due, it says so and exits 0.
393
412
  //
394
- // **An issue update taken in after round 1's brief refuses it**: minting this brief moves the pointer
395
- // `josh followup` measures that update against (`issue-watch-gate.ts`), so a round 1 that read the
396
- // earlier specification would merge without that refusal.
397
- async function run_interaction(): Promise<number> {
413
+ // **An issue update taken in after round 1's brief refuses it**: this brief is minted on its own slot
414
+ // beside round 1's (joshuafolkken/kit#4672), so it is refused here rather than briefed over an earlier
415
+ // specification round 1 read.
416
+ async function run_interaction(emit: Emit): Promise<number> {
398
417
  const reading = await read_change()
399
418
  const targets = review_interaction.due_paths(reading.paths)
400
419
 
401
420
  if (targets.length === 0) {
402
- console.info(review_interaction.NOT_DUE_LINE)
421
+ emit(review_interaction.NOT_DUE_LINE)
403
422
 
404
423
  return 0
405
424
  }
@@ -408,21 +427,48 @@ async function run_interaction(): Promise<number> {
408
427
 
409
428
  if (stale !== undefined) return report_error(stale)
410
429
 
411
- return await run_review(FIRST_ROUND, reading, targets)
430
+ return await run_review(FIRST_ROUND, reading, emit, targets)
412
431
  }
413
432
 
414
- async function run(argv: ReadonlyArray<string>): Promise<number> {
415
- if (argv[0] === LEVEL_ONLY_FLAG) return await run_level(argv.slice(1))
416
- if (argv.length === 1 && argv[0] === INTERACTION_FLAG) return await run_interaction()
433
+ // The scoped-green refusal a brief on this tree would print, read without composing one — so
434
+ // `josh run:review` refuses before it launches anything beside the brief (joshuafolkken/kit#4828).
435
+ async function scoped_refusal(): Promise<string | undefined> {
436
+ const { tree, commit } = await read_change()
437
+
438
+ return scoped_green.refusal_for(tree, commit)
439
+ }
440
+
441
+ // **A reviewer never mints a brief** (joshuafolkken/kit#5113): every brief takes a fresh nonce and drops
442
+ // the previous one's records, so a reviewer that re-briefs after attesting erases the attestation its
443
+ // supervisor is about to check, and a finished review reads as none. `--level-only` mints nothing.
444
+ const REVIEWER_REFUSAL =
445
+ 'review:brief refused: this is a reviewer session (JOSH_AGENT_ROLE=reviewer). A new brief would drop the attestation this review already left — review the brief you were handed and report.'
446
+
447
+ async function run_brief(argv: ReadonlyArray<string>, emit: Emit): Promise<number> {
448
+ if (argv.length === 1 && argv[0] === INTERACTION_FLAG) return await run_interaction(emit)
417
449
 
418
450
  const round = parse_round(argv)
419
451
 
420
452
  if (round === undefined) return report_error(USAGE)
421
453
 
422
- return await run_review(round, await read_change())
454
+ return await run_review(round, await read_change(), emit)
455
+ }
456
+
457
+ // `emit` takes the brief: `josh run:review` writes it to a file, because its two briefs together exceed
458
+ // the Bash output cap (joshuafolkken/kit#4863). `run` prints it.
459
+ async function run_to(argv: ReadonlyArray<string>, emit: Emit): Promise<number> {
460
+ if (argv[0] === LEVEL_ONLY_FLAG) return await run_level(argv.slice(1))
461
+ if (agent_session_role.is_reviewer()) return report_error(REVIEWER_REFUSAL)
462
+
463
+ return await run_brief(argv, emit)
464
+ }
465
+
466
+ async function run(argv: ReadonlyArray<string>): Promise<number> {
467
+ return await run_to(argv, console.info)
423
468
  }
424
469
 
425
470
  const review_brief_cli = {
471
+ attested_tree,
426
472
  FIRST_ROUND,
427
473
  format_reason,
428
474
  KEPT_NOTE_PREFIX,
@@ -431,6 +477,9 @@ const review_brief_cli = {
431
477
  record_round_one,
432
478
  report_error,
433
479
  run,
480
+ run_to,
481
+ scoped_refusal,
434
482
  }
435
483
 
484
+ export type { Emit }
436
485
  export { review_brief_cli }
@@ -0,0 +1,22 @@
1
+ // The path lists a review brief prints.
2
+
3
+ // Absolute, for the same reason the round-1 target carries `-C`: git prints repository-root-relative
4
+ // paths, and a forked agent sitting in another checkout resolves them against that one — where the
5
+ // same relative path names a different file, or none.
6
+ function format_paths(root: string, paths: ReadonlyArray<string>): string {
7
+ return paths.map((relative) => ` ${root}/${relative}`).join('\n')
8
+ }
9
+
10
+ // **A recorded High's fix is round 2's to verify, read whole** (joshuafolkken/kit#4941): `josh ship`
11
+ // reuses the lane's round 1 once only round 2's delta moved, so this pass is the one that reads the fix
12
+ // — and a fix can reach past the hunks the delta shows.
13
+ const HIGH_FIX_LINE =
14
+ 'These files hold the fix of a High round 1 recorded — read each whole, not only its hunks, with the fix sites the finding names:'
15
+
16
+ function high_fix_lines(root: string, cited: ReadonlyArray<string> = []): ReadonlyArray<string> {
17
+ return cited.length === 0 ? [] : [`${HIGH_FIX_LINE}\n${format_paths(root, cited)}`]
18
+ }
19
+
20
+ const review_brief_paths = { format_paths, HIGH_FIX_LINE, high_fix_lines }
21
+
22
+ export { review_brief_paths }
@@ -1,6 +1,7 @@
1
1
  import { agent_role_profile, type AgentProfile } from '#scripts/agent/agent-role-profile'
2
2
  import { file_map_stamp, type FileMapStamp } from '#scripts/josh/file-map-stamp'
3
3
  import { removed_tests } from './removed-tests'
4
+ import { review_brief_paths } from './review-brief-paths'
4
5
  import { review_checkout, type ReviewCheckout } from './review-checkout'
5
6
  import { review_diff_parts, type DiffParts } from './review-diff-parts'
6
7
  import { review_interaction } from './review-interaction'
@@ -22,6 +23,9 @@ import { review_untouched_readers, type ReadersRead } from './review-untouched-r
22
23
 
23
24
  const TEST_COMMAND_LINE =
24
25
  '- The unit suite is `pnpm josh test:unit`. Do not reach for `npx vitest`; it is not how this project runs them.'
26
+ // The self-check's question 2 ("Prose matches the code", `prompts/review.md`) as one command.
27
+ const PROSE_STALE_LINE =
28
+ '- Self-check 2, prose matches the code: `pnpm josh prose:stale` lists each removed name, command, constant or heading docs, prompts or comments still name.'
25
29
 
26
30
  // **The checkout block, and why the target below names a path instead of assuming one**.
27
31
  // `/code-review` is forked by the harness and inherits the session's
@@ -196,12 +200,7 @@ function gate_line(
196
200
  return NOT_VERIFIED_LINE
197
201
  }
198
202
 
199
- // Absolute, for the same reason the round-1 target carries `-C`: git prints repository-root-relative
200
- // paths, and a forked agent sitting in another checkout resolves them against that one — where the
201
- // same relative path names a different file, or none.
202
- function format_paths(root: string, paths: ReadonlyArray<string>): string {
203
- return paths.map((relative) => ` ${root}/${relative}`).join('\n')
204
- }
203
+ const { format_paths, high_fix_lines } = review_brief_paths
205
204
 
206
205
  // **An empty target has two readings, and only one of them is "nothing changed"**.
207
206
  // Since the delta is intersected with the change, round 1's fixes can be
@@ -414,6 +413,9 @@ interface BriefInput {
414
413
  // The tree a finished, clean review of this branch was briefed on, so round 1 is a resume.
415
414
  // Absent, round 1 reads the whole change.
416
415
  resumed_from?: FileMapStamp | undefined
416
+ // The files a recorded High cites (`review_reviewed_tree.high_cited`), named in round 2 as the
417
+ // High's fix. Absent or empty, no line.
418
+ high_cited?: ReadonlyArray<string> | undefined
417
419
  // The change written as parts under the Bash output cap. Absent when the
418
420
  // write failed, and the target line alone then names the change.
419
421
  diff?: { parts: DiffParts; cap: number } | undefined
@@ -440,7 +442,10 @@ function round_one_target(input: BriefInput): string {
440
442
  function target_block(input: BriefInput): string {
441
443
  if (input.round < SECOND_ROUND) return round_one_target(input)
442
444
 
443
- return round_two_block(input.stamps.round_one, input.tree, input.checkout.root, input.base)
445
+ const { root } = input.checkout
446
+ const block = round_two_block(input.stamps.round_one, input.tree, root, input.base)
447
+
448
+ return [block, ...high_fix_lines(root, input.high_cited)].join('\n')
444
449
  }
445
450
 
446
451
  // **Only beside a whole-change target**: each part is a path's diff against
@@ -487,6 +492,7 @@ function compose(input: BriefInput): string {
487
492
  '',
488
493
  gate_line(input.stamps, input.tree, input.base),
489
494
  TEST_COMMAND_LINE,
495
+ PROSE_STALE_LINE,
490
496
  '',
491
497
  target,
492
498
  ...diff_block(input, target),
@@ -509,6 +515,7 @@ const review_brief = {
509
515
  matching_stamp,
510
516
  no_snapshot_line,
511
517
  NOTHING_LEFT_LINE,
518
+ PROSE_STALE_LINE,
512
519
  rubric_line,
513
520
  RUBRIC_RELATIVE_PATH,
514
521
  ROUND_TWO_HEADING,
@@ -0,0 +1,47 @@
1
+ import { rmSync } from 'node:fs'
2
+ import path from 'node:path'
3
+ import { error_text } from '#scripts/lib/error-message'
4
+ import { observation_ledger } from '#scripts/observations/observation-ledger'
5
+ import { review_comment_round } from './review-comment-round'
6
+
7
+ // The carry of the closed issues' comment rounds as its two callers run it — `review:record` outside a
8
+ // lane, and `observations:flush` for the lanes (joshuafolkken/kit#5326) — so both print the same
9
+ // lines. **A carry that fails never fails its caller**: the rounds wait for the next carry, and the
10
+ // carried file is the mark, so nothing is copied twice.
11
+
12
+ const CARRIED_LINE =
13
+ 'review-finding line(s) recorded on closed issues after their pull requests opened into the ledger.'
14
+ const CARRY_FAILED_LINE =
15
+ 'Could not carry the closed issues’ comment rounds into the ledger; the next carry retries:'
16
+ const UNTRACKED_PREFIX = '?? '
17
+
18
+ // **A carried file no commit took is discarded before the default branch catches up**: left untracked
19
+ // by a flush that stopped after its carry, it would make git refuse that fast-forward on every later
20
+ // flush. Nothing is lost — the carry regenerates it from the issue's comments.
21
+ function discard_uncommitted(status_output: string, root: string): void {
22
+ const untracked = status_output.split('\n').filter((line) => line.startsWith(UNTRACKED_PREFIX))
23
+ const carried = untracked
24
+ .map((line) => observation_ledger.status_path(line))
25
+ .filter((file_path) => review_comment_round.is_carried_file(file_path))
26
+
27
+ for (const file_path of carried) rmSync(path.join(root, file_path), { force: true })
28
+ }
29
+
30
+ async function carry_reported(root: string): Promise<void> {
31
+ try {
32
+ const count = await review_comment_round.carry(root)
33
+
34
+ if (count > 0) console.info(`Carried ${String(count)} ${CARRIED_LINE}`)
35
+ } catch (error) {
36
+ console.warn(`${CARRY_FAILED_LINE} ${error_text.message_of(error)}`)
37
+ }
38
+ }
39
+
40
+ const review_comment_carry = {
41
+ CARRIED_LINE,
42
+ CARRY_FAILED_LINE,
43
+ carry_reported,
44
+ discard_uncommitted,
45
+ }
46
+
47
+ export { review_comment_carry }
@@ -1,10 +1,12 @@
1
1
  import { existsSync } from 'node:fs'
2
+ import path from 'node:path'
2
3
  import { gh_author_association } from '#scripts/gh/gh-author-association'
3
4
  import { git_gh_exec } from '#scripts/gh/git-gh-exec'
4
5
  import { git_gh_issue_read } from '#scripts/gh/git-gh-issue-read'
5
6
  import { parse_json, parse_json_array_safe } from '#scripts/git/parse-json-array'
6
7
  import { session_cite } from '#scripts/issue/session-cite'
7
8
  import { observation_ledger_home } from '#scripts/observations/observation-ledger-home'
9
+ import { observation_ledger_line } from '#scripts/observations/observation-ledger-line'
8
10
  import { z } from 'zod'
9
11
  import { review_finding_ledger } from './review-finding-ledger'
10
12
 
@@ -13,20 +15,30 @@ import { review_finding_ledger } from './review-finding-ledger'
13
15
  // a ledger line written then would be pushed onto the open pull request and restart its CI — and so
14
16
  // nothing that reads the ledger (`review:findings`, the retrospective) ever saw it.
15
17
  //
16
- // **The next run that records a round carries it.** Once an issue is closed no round is added to it,
17
- // so `review:record` copies each closed issue's comment rounds not yet carried into
18
+ // **The next run outside a lane that records a round carries it, or the next flush.** Once an issue
19
+ // is closed no round is added to it, so `review:record` copies each closed issue's comment rounds not yet carried into
18
20
  // `<issue>-comment-rounds.md` in the ledger, and the lines ride that run's own commit: the ledger stays
19
21
  // the one place a reader looks, and no push restarts any CI. **The file is the carried mark** — an
20
- // issue whose file exists is never read again, and two lanes carrying one issue write the same file,
21
- // so their pull requests merge to the same lines.
22
+ // issue whose file exists is never read again. **A lane child carries none** (joshuafolkken/kit#5326):
23
+ // parallel lanes each wrote the same file and waited and conflicted on it, so `observations:flush`
24
+ // carries for them on the default branch (`review-comment-carry.ts`).
25
+ //
26
+ // **An observation-ledger line written while the pull request is open rides the same carry**
27
+ // (joshuafolkken/kit#5197): `followup` reruns a CI job red only outside the change during its CI wait,
28
+ // after the ledger's last commit, so the sighting is posted under its own heading and carried with the
29
+ // rounds.
22
30
 
23
31
  const COMMENT_HEADING_MARK = '### '
24
32
  const COMMENT_TITLE = 'Review round recorded after the pull request opened'
25
- const COMMENT_HEADING = `${COMMENT_HEADING_MARK}${COMMENT_TITLE}`
33
+ const OBSERVATION_TITLE = 'Observation recorded while the pull request was open'
34
+ const COMMENT_TITLES = [COMMENT_TITLE, OBSERVATION_TITLE]
35
+ const COMMENT_HEADINGS = COMMENT_TITLES.map((title) => `${COMMENT_HEADING_MARK}${title}`)
26
36
  const COMMENT_NOTE =
27
37
  'Kept here rather than in the observation ledger: a line appended after the commit would be pushed onto the open pull request and restart its CI.'
28
38
  const CODE_FENCE = '```'
39
+ const OBSERVATION_LINE_MARK = '- k:'
29
40
  const CARRIED_SUFFIX = '-comment-rounds'
41
+ const CARRIED_FILE_PATTERN = new RegExp(String.raw`^\d+${CARRIED_SUFFIX}\.md$`, 'u')
30
42
  // One page of the newest closed issues: an issue leaves the search's interest once carried, so the
31
43
  // ones still to carry are the recently closed.
32
44
  const PER_PAGE = '100'
@@ -45,8 +57,33 @@ const comment_schema = z.object({
45
57
 
46
58
  type IssueComment = z.infer<typeof comment_schema>
47
59
 
60
+ function body_under(title: string, lines: ReadonlyArray<string>): string {
61
+ const heading = `${COMMENT_HEADING_MARK}${title}`
62
+
63
+ return [heading, '', COMMENT_NOTE, '', CODE_FENCE, ...lines, CODE_FENCE].join('\n')
64
+ }
65
+
48
66
  function body_of(lines: ReadonlyArray<string>): string {
49
- return [COMMENT_HEADING, '', COMMENT_NOTE, '', CODE_FENCE, ...lines, CODE_FENCE].join('\n')
67
+ return body_under(COMMENT_TITLE, lines)
68
+ }
69
+
70
+ function observation_body_of(lines: ReadonlyArray<string>): string {
71
+ return body_under(OBSERVATION_TITLE, lines)
72
+ }
73
+
74
+ function is_carried_line(line: string): boolean {
75
+ if (review_finding_ledger.is_finding_line(line)) return true
76
+
77
+ return (
78
+ line.startsWith(OBSERVATION_LINE_MARK) &&
79
+ observation_ledger_line.line_reason(line) === undefined
80
+ )
81
+ }
82
+
83
+ function is_round(comment: IssueComment): boolean {
84
+ const body = comment.body ?? ''
85
+
86
+ return COMMENT_HEADINGS.some((heading) => body.startsWith(heading))
50
87
  }
51
88
 
52
89
  // The ledger lines of every comment round among one issue's comments, oldest first; any other
@@ -67,7 +104,7 @@ async function is_trusted_comment(comment: IssueComment): Promise<boolean> {
67
104
  }
68
105
 
69
106
  async function lines_of(comments: ReadonlyArray<IssueComment>): Promise<Array<string>> {
70
- const rounds = comments.filter((comment) => (comment.body ?? '').startsWith(COMMENT_HEADING))
107
+ const rounds = comments.filter((comment) => is_round(comment))
71
108
  const trusted = await Promise.all(
72
109
  rounds.map(async (comment) => await is_trusted_comment(comment)),
73
110
  )
@@ -75,43 +112,61 @@ async function lines_of(comments: ReadonlyArray<IssueComment>): Promise<Array<st
75
112
  return rounds
76
113
  .filter((_comment, index) => trusted[index] === true)
77
114
  .flatMap((comment) => (comment.body ?? '').split('\n'))
78
- .filter((line) => review_finding_ledger.is_finding_line(line))
115
+ .filter((line) => is_carried_line(line))
79
116
  }
80
117
 
81
- function search_path(repo: string): string {
82
- const query = `repo:${repo} is:issue is:closed in:comments "${COMMENT_TITLE}"`
118
+ function search_path(repo: string, title: string): string {
119
+ const query = `repo:${repo} is:issue is:closed in:comments "${title}"`
83
120
  const parameters = new URLSearchParams({ q: query, sort: 'updated', per_page: PER_PAGE })
84
121
 
85
122
  return `search/issues?${parameters.toString()}`
86
123
  }
87
124
 
88
- // The closed issues whose comments name a comment round; a repository that cannot be named or a
89
- // search that cannot be read throws, so the run says so rather than carrying nothing in silence.
125
+ async function search(repo: string, title: string): Promise<ReadonlyArray<number>> {
126
+ const raw = await git_gh_exec.exec_gh_api({ path: search_path(repo, title) })
127
+ const page = parse_json.parse_json_object_or_undefined(raw, search_schema)
128
+
129
+ if (page === undefined) throw new Error(UNREAD_SEARCH)
130
+
131
+ return page.items.map((item) => item.number)
132
+ }
133
+
134
+ // The closed issues whose comments name a comment round of either heading; a repository that cannot be
135
+ // named or a search that cannot be read throws, so the run says so rather than carrying nothing in
136
+ // silence.
90
137
  async function closed_issues(): Promise<ReadonlyArray<number>> {
91
138
  const repo = session_cite.session_repo()
92
139
 
93
140
  if (repo === undefined) throw new Error(UNNAMED_REPOSITORY)
94
141
 
95
- const raw = await git_gh_exec.exec_gh_api({ path: search_path(repo) })
96
- const page = parse_json.parse_json_object_or_undefined(raw, search_schema)
97
-
98
- if (page === undefined) throw new Error(UNREAD_SEARCH)
142
+ const pages = await Promise.all(COMMENT_TITLES.map(async (title) => await search(repo, title)))
99
143
 
100
- return page.items.map((item) => item.number)
144
+ return [...new Set(pages.flat())]
101
145
  }
102
146
 
103
147
  function carried_path(issue: number, root: string): string {
104
148
  return observation_ledger_home.file_path(`${String(issue)}${CARRIED_SUFFIX}`, root)
105
149
  }
106
150
 
107
- // An issue whose comments could not be read writes no file, so the next run reads it again, and
108
- // throws so this one says so.
109
- async function carry_issue(issue: number, root: string): Promise<number> {
151
+ // A path this carry writes, told by its file name alone so a git status path answers it too.
152
+ function is_carried_file(file_path: string): boolean {
153
+ return CARRIED_FILE_PATTERN.test(path.basename(file_path))
154
+ }
155
+
156
+ // One issue's comment-round lines. Comments that could not be read throw, so no caller reads an
157
+ // unread issue as one without a round.
158
+ async function issue_lines(issue: number): Promise<Array<string>> {
110
159
  const raw = await git_gh_issue_read.issue_list_comments(String(issue))
111
160
 
112
161
  if (raw === undefined) throw new Error(`${UNREAD_COMMENTS} ${session_cite.issue(issue)}`)
113
162
 
114
- const lines = await lines_of(parse_json_array_safe(raw, comment_schema))
163
+ return await lines_of(parse_json_array_safe(raw, comment_schema))
164
+ }
165
+
166
+ // An issue whose comments could not be read writes no file, so the next run reads it again, and
167
+ // throws so this one says so.
168
+ async function carry_issue(issue: number, root: string): Promise<number> {
169
+ const lines = await issue_lines(issue)
115
170
 
116
171
  await observation_ledger_home.append(carried_path(issue, root), lines)
117
172
 
@@ -127,6 +182,14 @@ async function carry(root: string): Promise<number> {
127
182
  return counts.reduce((total, count) => total + count, 0)
128
183
  }
129
184
 
130
- const review_comment_round = { body_of, carried_path, carry, lines_of }
185
+ const review_comment_round = {
186
+ body_of,
187
+ carried_path,
188
+ carry,
189
+ is_carried_file,
190
+ issue_lines,
191
+ lines_of,
192
+ observation_body_of,
193
+ }
131
194
 
132
195
  export { review_comment_round }