@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
@@ -13,6 +13,16 @@ import { issue_cite } from '#scripts/issue/issue-cite'
13
13
  const PREFIX = { code: '- rf:', interaction: '- ri:' } as const
14
14
  const FIELD_SEPARATOR = ' | '
15
15
  const FIELD_COUNT = 5
16
+ // **The disposition is a sixth field, written only when given** (joshuafolkken/kit#5286): a line
17
+ // written before it existed keeps its five and reads as a finding with no disposition.
18
+ const DISPOSED_FIELD_COUNT = FIELD_COUNT + 1
19
+ const ISSUE_FIELD_INDEX = FIELD_COUNT - 1
20
+ const SEVERITY_FIELD_INDEX = 1
21
+ // **A code round written to the issue's file opens with a boundary line** (joshuafolkken/kit#5359):
22
+ // the ledger is append-only, so a stopped round's unfixed lines stay, and `josh review:round2` reads
23
+ // only the lines after the issue's last boundary. Its own prefix keeps it out of every `- rf:` reader.
24
+ const ROUND_PREFIX = '- rb:'
25
+ const ROUND_ISSUE_FIELD_INDEX = 1
16
26
 
17
27
  // The nine review-rubric categories, as slugs (`prompts/review-rubric.md` → "Review categories"). A
18
28
  // finding's category must be one of these so the aggregate stays countable rather than free text.
@@ -30,6 +40,12 @@ const CATEGORIES = [
30
40
 
31
41
  const SEVERITIES = ['high', 'medium', 'low'] as const
32
42
 
43
+ // What became of a finding: fixed in this tree, a verified false positive, or left to another issue.
44
+ // Only the first two close it for `josh review:round2`.
45
+ const CLOSING_DISPOSITIONS = ['fixed', 'false-positive'] as const
46
+ const DISPOSITION_PATTERN = /^(?:fixed|false-positive|(?:filed|deferred):#[1-9]\d*)$/u
47
+ const DISPOSITION_SEPARATOR = ' '
48
+
33
49
  // The sentinel a zero-finding round writes, so "a round ran and found nothing" is a recorded line
34
50
  // rather than an absent one — the count's denominator survives.
35
51
  const NONE = 'none'
@@ -43,6 +59,12 @@ interface Finding {
43
59
  category: Category
44
60
  severity: Severity
45
61
  file: string
62
+ disposition?: string
63
+ }
64
+
65
+ interface DisposedSpec {
66
+ disposition: string | undefined
67
+ spec: string
46
68
  }
47
69
 
48
70
  interface CategoryCount {
@@ -65,6 +87,25 @@ function is_valid_file(file: string): boolean {
65
87
  return file.length > 0 && !file.includes(FIELD_SEPARATOR)
66
88
  }
67
89
 
90
+ function is_disposition(value: string): boolean {
91
+ return DISPOSITION_PATTERN.test(value)
92
+ }
93
+
94
+ function is_closing(disposition: string | undefined): boolean {
95
+ return (CLOSING_DISPOSITIONS as ReadonlyArray<string | undefined>).includes(disposition)
96
+ }
97
+
98
+ // A positional's leading disposition — `fixed <spec>`, `filed:#12 <spec>` — split from the spec it
99
+ // marks. The token the reviewer already writes before a finding it fixed, so one grammar serves both.
100
+ function split_disposition(positional: string): DisposedSpec {
101
+ const end = positional.indexOf(DISPOSITION_SEPARATOR)
102
+ const head = end === -1 ? '' : positional.slice(0, end)
103
+
104
+ if (!is_disposition(head)) return { disposition: undefined, spec: positional }
105
+
106
+ return { disposition: head, spec: positional.slice(end + DISPOSITION_SEPARATOR.length) }
107
+ }
108
+
68
109
  function issue_field(issue: number): string {
69
110
  return issue_cite.plain(issue)
70
111
  }
@@ -79,7 +120,12 @@ function finding_line(
79
120
  issue: number,
80
121
  kind: LineKind = 'code',
81
122
  ): string {
82
- return line_of([finding.category, finding.severity, finding.file, date, issue_field(issue)], kind)
123
+ const fields = [finding.category, finding.severity, finding.file, date, issue_field(issue)]
124
+
125
+ return line_of(
126
+ finding.disposition === undefined ? fields : [...fields, finding.disposition],
127
+ kind,
128
+ )
83
129
  }
84
130
 
85
131
  // **A zero-finding round records `none`, not nothing.** Reading its absence as "no findings" would
@@ -97,10 +143,20 @@ function fields_of(line: string, kind: LineKind = 'code'): ReadonlyArray<string>
97
143
  return line.trimStart().slice(PREFIX[kind].length).split(FIELD_SEPARATOR)
98
144
  }
99
145
 
100
- function category_of(line: string): string | undefined {
101
- const fields = fields_of(line)
146
+ // The line's fields, or `undefined` for a malformed one — five, or six with a disposition.
147
+ function well_formed_fields(
148
+ line: string,
149
+ kind: LineKind = 'code',
150
+ ): ReadonlyArray<string> | undefined {
151
+ const fields = fields_of(line, kind)
102
152
 
103
- return fields.length === FIELD_COUNT ? fields[0] : undefined
153
+ return fields.length === FIELD_COUNT || fields.length === DISPOSED_FIELD_COUNT
154
+ ? fields
155
+ : undefined
156
+ }
157
+
158
+ function category_of(line: string): string | undefined {
159
+ return well_formed_fields(line)?.[0]
104
160
  }
105
161
 
106
162
  function increment(counts: Map<string, number>, category: string): void {
@@ -149,9 +205,50 @@ function zero_round_count(content: string): number {
149
205
  // non-finding or malformed line. The record check reads this to ask whether a given issue's round was
150
206
  // recorded at all.
151
207
  function issue_of(line: string, kind: LineKind): string | undefined {
152
- const fields = fields_of(line, kind)
208
+ return well_formed_fields(line, kind)?.[ISSUE_FIELD_INDEX]
209
+ }
210
+
211
+ interface DisposedLine {
212
+ severity: string
213
+ disposition: string | undefined
214
+ }
215
+
216
+ // One issue's `- rf:` lines, each with its severity and disposition — `undefined` disposition for a
217
+ // line written without one. `josh review:round2` reads round 1's closure from this.
218
+ function issue_dispositions(content: string, issue: number): ReadonlyArray<DisposedLine> {
219
+ const target = issue_field(issue)
220
+
221
+ return content
222
+ .split('\n')
223
+ .filter((line) => is_finding_line(line) && issue_of(line, 'code') === target)
224
+ .map((line) => well_formed_fields(line) ?? [])
225
+ .map((fields) => ({
226
+ severity: fields[SEVERITY_FIELD_INDEX] ?? NONE,
227
+ disposition: fields[FIELD_COUNT],
228
+ }))
229
+ }
230
+
231
+ function round_line(date: string, issue: number): string {
232
+ return `${ROUND_PREFIX}${[date, issue_field(issue)].join(FIELD_SEPARATOR)}`
233
+ }
234
+
235
+ function is_round_line(line: string, target: string): boolean {
236
+ const trimmed = line.trimStart()
237
+
238
+ if (!trimmed.startsWith(ROUND_PREFIX)) return false
239
+
240
+ const fields = trimmed.slice(ROUND_PREFIX.length).split(FIELD_SEPARATOR)
241
+
242
+ return fields[ROUND_ISSUE_FIELD_INDEX] === target
243
+ }
244
+
245
+ // The content after the issue's last round boundary — the whole content when it has none, as a ledger
246
+ // written before the boundary existed does.
247
+ function latest_round(content: string, issue: number): string {
248
+ const target = issue_field(issue)
249
+ const lines = content.split('\n')
153
250
 
154
- return fields.length === FIELD_COUNT ? fields[FIELD_COUNT - 1] : undefined
251
+ return lines.slice(lines.findLastIndex((line) => is_round_line(line, target)) + 1).join('\n')
155
252
  }
156
253
 
157
254
  // **A `none` zero-round line counts as recorded, exactly like a real finding line does.** The gate
@@ -172,13 +269,18 @@ const review_finding_ledger = {
172
269
  finding_line,
173
270
  has_issue_record,
174
271
  is_category,
272
+ is_closing,
175
273
  is_finding_line,
176
274
  is_severity,
177
275
  is_valid_file,
276
+ issue_dispositions,
277
+ latest_round,
278
+ round_line,
178
279
  SEVERITIES,
280
+ split_disposition,
179
281
  zero_round_count,
180
282
  zero_round_line,
181
283
  }
182
284
 
183
- export type { CategoryCount, Finding, LineKind }
285
+ export type { CategoryCount, DisposedLine, Finding, LineKind }
184
286
  export { review_finding_ledger }
@@ -0,0 +1,43 @@
1
+ // A finding written in the `review:record` grammar with its reason after it — `<spec> — <sentence>` —
2
+ // split into the two halves, the one place both its writers read it: a ship reviewer's findings file
3
+ // (`run-ship-review.ts`) and an agent's own `review:record` round (`review-record-cli.ts`). The spec is
4
+ // what the ledger keeps; the first sentence of the reason is what the durable stop log keeps.
5
+
6
+ // What a finding line carries after its spec: one sentence saying what is wrong, so a stopped ship's
7
+ // log tells the resumed lane child the defect rather than only its location.
8
+ const DESCRIPTION_SEPARATOR = ' — '
9
+ // Where the spec ends on read: a reviewer that types the dash as `-`, `--` or `–` still ends it there,
10
+ // so its sentence never lands in the ledger's file field.
11
+ const DESCRIPTION_BOUNDARY = / [—–-]{1,2} /u
12
+ // Where a description's first sentence ends, and the cap that keeps a run-on one a line. Japanese
13
+ // sets no space after `。`, so it ends a sentence on its own.
14
+ const SENTENCE_END = /(?<=[.!?])\s|(?<=。)/u
15
+ const SENTENCE_LIMIT = 200
16
+ const ELLIPSIS = '…'
17
+
18
+ function split_description(unmarked: string): { spec: string; description: string } {
19
+ const boundary = DESCRIPTION_BOUNDARY.exec(unmarked)
20
+
21
+ if (boundary === null) return { spec: unmarked.trim(), description: '' }
22
+
23
+ const rest = unmarked.slice(boundary.index + boundary[0].length)
24
+
25
+ return { spec: unmarked.slice(0, boundary.index).trim(), description: rest.trim() }
26
+ }
27
+
28
+ function first_sentence(description: string): string {
29
+ const [sentence = ''] = description.split(SENTENCE_END, 1)
30
+
31
+ if (sentence.length <= SENTENCE_LIMIT) return sentence
32
+
33
+ return `${sentence.slice(0, SENTENCE_LIMIT - ELLIPSIS.length)}${ELLIPSIS}`
34
+ }
35
+
36
+ const review_finding_text = {
37
+ DESCRIPTION_SEPARATOR,
38
+ SENTENCE_LIMIT,
39
+ first_sentence,
40
+ split_description,
41
+ }
42
+
43
+ export { review_finding_text }
@@ -2,6 +2,7 @@ import { project_checks } from '#scripts/gate/project-checks'
2
2
  import { changed_paths } from '#scripts/git/changed-paths'
3
3
  import { session_cite } from '#scripts/issue/session-cite'
4
4
  import { observation_ledger_home } from '#scripts/observations/observation-ledger-home'
5
+ import { review_attest, type ReviewSlot } from './review-attest'
5
6
  import { review_finding_ledger } from './review-finding-ledger'
6
7
 
7
8
  // The interaction review — one adversarial pass after `/code-review`, over a change to the run
@@ -65,6 +66,15 @@ async function status(issue: number, root?: string): Promise<InteractionStatus>
65
66
  return await status_of(issue, await changed_paths.read_changed_paths(false), root)
66
67
  }
67
68
 
69
+ // **Round 1's slots — the interaction review beside `/code-review`'s where it is due and not yet
70
+ // recorded** (joshuafolkken/kit#4672, joshuafolkken/kit#4802), so it takes round 1's wait and stop.
71
+ // `josh ship` and `josh run:review` both open round 1 from it.
72
+ function round_one_slots(answer: InteractionStatus | undefined): ReadonlyArray<ReviewSlot> {
73
+ const { CODE, INTERACTION } = review_attest.REVIEW_SLOT
74
+
75
+ return answer === 'missing' ? [CODE, INTERACTION] : [CODE]
76
+ }
77
+
68
78
  const MISSING_REASON =
69
79
  'This change touches the run tooling, and no interaction review is recorded for its issue — the pass that looks for the existing features a change breaks, which `/code-review` does not (joshuafolkken/kit#4276).'
70
80
 
@@ -86,6 +96,7 @@ const review_interaction = {
86
96
  NOT_DUE_LINE,
87
97
  refusal,
88
98
  refusal_message,
99
+ round_one_slots,
89
100
  status,
90
101
  status_of,
91
102
  }
@@ -0,0 +1,68 @@
1
+ import { PROJECT_ROOT } from '#scripts/init/init-paths'
2
+ import { session_cite } from '#scripts/issue/session-cite'
3
+ import { lane_child_marker } from '#scripts/lane/lane-child-marker'
4
+ import { error_text } from '#scripts/lib/error-message'
5
+ import { review_round_reuse, type ReuseAnswer } from './review-round-reuse'
6
+
7
+ // joshuafolkken/kit#4850: once a lane child has recorded round 1 on a tree `josh ship` reuses, round 2
8
+ // is the ship's. The rule stood in `chain-rule.md` step 0 as prose alone (joshuafolkken/kit#4830), and
9
+ // the next lane reopened `run:review` after reading it, running a round 2 the ship then ran again. So
10
+ // `run:review` refuses that reopen and `review:record` names the ship as the next step.
11
+ //
12
+ // **A round the ship would review again is not handed over**: `review:record --check` then tells the
13
+ // lane to run round 1 itself, so `run:review` stays open for it.
14
+
15
+ const SHIP_STEP = 'pnpm josh ship --detach --review "<title> #<N>"'
16
+ const NEXT_STEP_LINE = `Next: hand over to \`${SHIP_STEP}\` — round 2 is the ship's; never reopen \`run:review\` (chain-rule.md step 0).`
17
+
18
+ // A reuse question git could not answer reads as not reused: the lane then reviews the round itself,
19
+ // which costs one review, rather than leaving it to a ship that may review it again detached.
20
+ // The stale read inside it fails open in `review_round_reuse.is_stale_here`, as the ship's probe reads it.
21
+ const UNANSWERED_CAUSE = 'git could not answer the reuse question'
22
+
23
+ async function answer_here(issue: number): Promise<ReuseAnswer> {
24
+ try {
25
+ return await review_round_reuse.answer_here(issue)
26
+ } catch (error) {
27
+ error_text.trace_swallowed('review_lane_handover.answer_here', error)
28
+
29
+ return { reuse: review_round_reuse.REUSE.AGAIN, cause: UNANSWERED_CAUSE }
30
+ }
31
+ }
32
+
33
+ async function is_reused_here(issue: number): Promise<boolean> {
34
+ const answer = await answer_here(issue)
35
+
36
+ return answer.reuse !== review_round_reuse.REUSE.AGAIN
37
+ }
38
+
39
+ // The mark must name this issue as well as this checkout, so a person's run — or a branch whose issue
40
+ // is not the lane's — is never refused.
41
+ function is_lane_child_of(issue: number): boolean {
42
+ if (lane_child_marker.marked_issue() !== String(issue)) return false
43
+
44
+ return lane_child_marker.is_child_of(PROJECT_ROOT)
45
+ }
46
+
47
+ // Reuse already requires the recorded round (`review_round_reuse.is_reusable`), so it answers both.
48
+ async function is_handed_over(issue: number): Promise<boolean> {
49
+ if (!is_lane_child_of(issue)) return false
50
+
51
+ return await is_reused_here(issue)
52
+ }
53
+
54
+ function refusal(issue: number): string {
55
+ return (
56
+ `⛔ run:review: round 1 of ${session_cite.issue(issue)} is recorded and josh ship reuses it, and this is a ` +
57
+ `dispatched lane child (\`${lane_child_marker.KEY}\`), so no brief is minted. ${NEXT_STEP_LINE}`
58
+ )
59
+ }
60
+
61
+ const review_lane_handover = {
62
+ NEXT_STEP_LINE,
63
+ answer_here,
64
+ is_handed_over,
65
+ refusal,
66
+ }
67
+
68
+ export { review_lane_handover }
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env tsx
2
+ import { text } from 'node:stream/consumers'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { review_brief_cli } from './review-brief-cli'
5
+ import { review_lint } from './review-lint'
6
+
7
+ // `josh review:lint` — read a review's markdown from stdin and print `ok`, or the rubric's format
8
+ // violations one per line, exiting non-zero so the reviewer runs it before returning its findings.
9
+ // `--round 2` checks the verification pass's shape instead of the full template.
10
+
11
+ const SUCCESS_EXIT_CODE = 0
12
+ const FAILURE_EXIT_CODE = 1
13
+ const OK_MESSAGE = 'ok'
14
+ const ARGV_OFFSET = 2
15
+ const USAGE = 'Usage: josh review:lint [--round <1|2>] < review.md'
16
+ const NO_INPUT_MESSAGE =
17
+ '✖ nothing on stdin — pipe the review in, e.g. `pnpm josh review:lint < review.md`'
18
+
19
+ // The lines to print on failure — a usage error, no input, or the violations — empty on a pass.
20
+ function failure_lines(review: string, argv: ReadonlyArray<string>): ReadonlyArray<string> {
21
+ const round = review_brief_cli.parse_round(argv)
22
+ if (round === undefined) return [USAGE]
23
+ if (review.trim().length === 0) return [NO_INPUT_MESSAGE]
24
+
25
+ return review_lint.with_reference(review_lint.lint_review(review, round), round)
26
+ }
27
+
28
+ function run(review: string, argv: ReadonlyArray<string>): number {
29
+ const failures = failure_lines(review, argv)
30
+
31
+ if (failures.length > 0) {
32
+ console.error(failures.join('\n'))
33
+
34
+ return FAILURE_EXIT_CODE
35
+ }
36
+
37
+ console.info(OK_MESSAGE)
38
+
39
+ return SUCCESS_EXIT_CODE
40
+ }
41
+
42
+ async function read_and_run(): Promise<number> {
43
+ const argv = process.argv.slice(ARGV_OFFSET)
44
+ if (process.stdin.isTTY) return run('', argv)
45
+
46
+ return run(await text(process.stdin), argv)
47
+ }
48
+
49
+ async function main(): Promise<void> {
50
+ process.exitCode = await read_and_run()
51
+ }
52
+
53
+ const review_lint_cli = { run }
54
+
55
+ if (process.argv[1] === fileURLToPath(import.meta.url)) await main()
56
+
57
+ export { review_lint_cli }
@@ -0,0 +1,92 @@
1
+ import { review_lint_sections, type ReviewSection } from './review-lint-sections'
2
+
3
+ // The finding-line checks of `review:lint` (`prompts/review-rubric.md` → "Review output format"): every
4
+ // finding cites `file_path:line_number` and a severity, and a `low` carries its
5
+ // `no failure scenario — <what you tried>` line. A round-2 first-round line cites the severity it
6
+ // had (`(was high)`) and its resolution instead.
7
+
8
+ interface ItemRule {
9
+ readonly holds: (block: string) => boolean
10
+ readonly message: string
11
+ }
12
+
13
+ const FILE_LINE = /`[^`\s]+:\d+(?:-\d+)?`/u
14
+ const SEVERITY = /\((?:high|medium|low)\)/u
15
+ const LOW_MARKER = '(low)'
16
+ const NO_FAILURE_SCENARIO = 'no failure scenario —'
17
+ const PRIOR_SEVERITY = /\(was (?:high|medium|low)\)/u
18
+ const RESOLUTION = /\bresolved\b/u
19
+ // An item that is a trace, a `No issues` proof or an empty section's `None` is the verdict, not a finding.
20
+ const VERDICT_ITEM = /^(?:Traced\b|No issues|None\b)/u
21
+
22
+ function cites_file_line(block: string): boolean {
23
+ return FILE_LINE.test(block)
24
+ }
25
+
26
+ function states_severity(block: string): boolean {
27
+ return SEVERITY.test(block)
28
+ }
29
+
30
+ // The finding's own severity is its first one; a `(low)` later in its prose is not a severity.
31
+ function low_has_scenario_line(block: string): boolean {
32
+ return SEVERITY.exec(block)?.[0] !== LOW_MARKER || block.includes(NO_FAILURE_SCENARIO)
33
+ }
34
+
35
+ function states_prior_severity(block: string): boolean {
36
+ return PRIOR_SEVERITY.test(block)
37
+ }
38
+
39
+ function states_resolution(block: string): boolean {
40
+ return RESOLUTION.test(block)
41
+ }
42
+
43
+ const FINDING_RULES: ReadonlyArray<ItemRule> = [
44
+ { holds: cites_file_line, message: 'finding without a `file:line` citation' },
45
+ { holds: states_severity, message: 'finding without a severity (high|medium|low)' },
46
+ {
47
+ holds: low_has_scenario_line,
48
+ message: `low finding without "${NO_FAILURE_SCENARIO} <what you tried>"`,
49
+ },
50
+ ]
51
+
52
+ const FIRST_ROUND_RULES: ReadonlyArray<ItemRule> = [
53
+ { holds: cites_file_line, message: 'first-round line without a `file:line` citation' },
54
+ { holds: states_prior_severity, message: 'first-round line without "(was <severity>)"' },
55
+ { holds: states_resolution, message: 'first-round line without "resolved" or "not resolved"' },
56
+ ]
57
+
58
+ function first_line(block: string): string {
59
+ return block.split('\n', 1)[0]?.trim() ?? ''
60
+ }
61
+
62
+ function rule_violations(
63
+ block: string,
64
+ heading: string,
65
+ rules: ReadonlyArray<ItemRule>,
66
+ ): ReadonlyArray<string> {
67
+ const where = `under ### ${heading}: ${first_line(block)}`
68
+
69
+ return rules.filter((rule) => !rule.holds(block)).map((rule) => `✖ ${rule.message} ${where}`)
70
+ }
71
+
72
+ function finding_blocks(section: ReviewSection): ReadonlyArray<string> {
73
+ return review_lint_sections
74
+ .item_blocks(section.lines)
75
+ .filter((block) => !VERDICT_ITEM.test(review_lint_sections.item_text(block)))
76
+ }
77
+
78
+ function finding_violations(section: ReviewSection): ReadonlyArray<string> {
79
+ return finding_blocks(section).flatMap((block) =>
80
+ rule_violations(block, section.heading, FINDING_RULES),
81
+ )
82
+ }
83
+
84
+ function first_round_violations(section: ReviewSection): ReadonlyArray<string> {
85
+ return review_lint_sections
86
+ .item_blocks(section.lines)
87
+ .flatMap((block) => rule_violations(block, section.heading, FIRST_ROUND_RULES))
88
+ }
89
+
90
+ const review_lint_findings = { finding_blocks, finding_violations, first_round_violations }
91
+
92
+ export { review_lint_findings }
@@ -0,0 +1,80 @@
1
+ import { document_section } from '#scripts/document/document-section'
2
+
3
+ // The parsing half of `review:lint`: a review's markdown split into its `###` sections, and a
4
+ // section's list items grouped with their indented continuation lines. The checks live in
5
+ // `review-lint.ts` and `review-lint-findings.ts`; nothing here judges what it reads.
6
+
7
+ interface ReviewSection {
8
+ readonly heading: string
9
+ readonly lines: ReadonlyArray<string>
10
+ }
11
+
12
+ const HEADING_PREFIX = '### '
13
+ // `### 1. Bug risks & logic errors` and `### Project conventions (`CLAUDE.md`)` are the rubric's own
14
+ // category headings, so the number and a trailing parenthetical are dropped before the name is read.
15
+ const NUMBER_PREFIX = /^\d+\.\s+/u
16
+ const TRAILING_NOTE = / \([^)]*\)$/u
17
+ // A list item at column 0; an indented one is a continuation of the item above it.
18
+ const TOP_LEVEL_ITEM = /^(?:[-*]|\d+\.)\s+/u
19
+ const CONTINUATION = /^\s+\S/u
20
+
21
+ function heading_name(line: string): string {
22
+ return line
23
+ .slice(HEADING_PREFIX.length)
24
+ .trim()
25
+ .replace(NUMBER_PREFIX, '')
26
+ .replace(TRAILING_NOTE, '')
27
+ .trim()
28
+ }
29
+
30
+ // Lines before the first heading belong to no section and are not read; a `###` line inside a code
31
+ // fence is quoted text, not a heading.
32
+ function parse_sections(review: string): ReadonlyArray<ReviewSection> {
33
+ const lines = review.split('\n')
34
+ const fenced = document_section.fenced_flags(lines)
35
+ const heading_flags = lines.map(
36
+ (line, index) => fenced[index] !== true && line.startsWith(HEADING_PREFIX),
37
+ )
38
+ const sections: Array<{ heading: string; lines: Array<string> }> = []
39
+
40
+ for (const [index, line] of lines.entries()) {
41
+ if (heading_flags[index] === true) sections.push({ heading: heading_name(line), lines: [] })
42
+ else sections.at(-1)?.lines.push(line)
43
+ }
44
+
45
+ return sections
46
+ }
47
+
48
+ function has_content(section: ReviewSection): boolean {
49
+ return section.lines.some((line) => line.trim().length > 0)
50
+ }
51
+
52
+ function body_text(section: ReviewSection): string {
53
+ return section.lines.join('\n').trim()
54
+ }
55
+
56
+ // A line extends the block above it only when indented; any other non-blank line opens a new block —
57
+ // an item's own, or a closed one for prose, which closes the item above it and takes no continuation.
58
+ function add_line(blocks: Array<Array<string> | undefined>, line: string): void {
59
+ if (CONTINUATION.test(line)) blocks.at(-1)?.push(line)
60
+ else if (line.trim().length > 0) blocks.push(TOP_LEVEL_ITEM.test(line) ? [line] : undefined)
61
+ }
62
+
63
+ // Each top-level item with its indented continuation lines, joined; a sentence after a list is never
64
+ // read as part of its last item.
65
+ function item_blocks(lines: ReadonlyArray<string>): ReadonlyArray<string> {
66
+ const blocks: Array<Array<string> | undefined> = []
67
+
68
+ for (const line of lines) add_line(blocks, line)
69
+
70
+ return blocks.filter((block) => block !== undefined).map((block) => block.join('\n'))
71
+ }
72
+
73
+ function item_text(block: string): string {
74
+ return block.replace(TOP_LEVEL_ITEM, '')
75
+ }
76
+
77
+ const review_lint_sections = { parse_sections, has_content, body_text, item_blocks, item_text }
78
+
79
+ export type { ReviewSection }
80
+ export { review_lint_sections }