@joshuafolkken/kit 1.1514.0 → 1.1784.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 (858) hide show
  1. package/.claude/agents/investigator.md +1 -1
  2. package/.claude/settings.json +5 -5
  3. package/.claude/skills/epic-commands/SKILL.md +26 -65
  4. package/.claude/skills/epic-commands/epic-bundle.md +3 -1
  5. package/.claude/skills/workflow-commands/SKILL.md +5 -5
  6. package/.claude/skills/workflow-commands/background-commands.md +5 -5
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +10 -8
  8. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
  9. package/.claude/skills/workflow-commands/backlogrun-lanes.md +17 -13
  10. package/.claude/skills/workflow-commands/backlogrun-park.md +14 -23
  11. package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -2
  12. package/.claude/skills/workflow-commands/backlogrun-recovery.md +5 -5
  13. package/.claude/skills/workflow-commands/backlogrun-steps.md +10 -10
  14. package/.claude/skills/workflow-commands/backlogrun.md +1 -1
  15. package/.claude/skills/workflow-commands/chain-rule.md +13 -7
  16. package/.claude/skills/workflow-commands/delegation.md +6 -5
  17. package/.claude/skills/workflow-commands/entry-sequence.md +9 -9
  18. package/.claude/skills/workflow-commands/followup.md +9 -31
  19. package/.claude/skills/workflow-commands/fullrun-steps.md +36 -45
  20. package/.claude/skills/workflow-commands/fullrun.md +2 -2
  21. package/.claude/skills/workflow-commands/halfrun.md +17 -25
  22. package/.claude/skills/workflow-commands/issue-comments.md +16 -12
  23. package/.claude/skills/workflow-commands/issue-scout.md +2 -2
  24. package/.claude/skills/workflow-commands/kickoff.md +24 -23
  25. package/.claude/skills/workflow-commands/latest-gate.md +7 -12
  26. package/.claude/skills/workflow-commands/needs-human-review.md +9 -14
  27. package/.claude/skills/workflow-commands/observation-filing.md +4 -36
  28. package/.claude/skills/workflow-commands/observation-ledger.md +1 -1
  29. package/.claude/skills/workflow-commands/pre-gate-cut.md +13 -30
  30. package/.claude/skills/workflow-commands/prerequisite.md +10 -16
  31. package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
  32. package/.claude/skills/workflow-commands/prrun.md +3 -7
  33. package/.claude/skills/workflow-commands/retrospective.md +1 -1
  34. package/.claude/skills/workflow-commands/split-assessment.md +13 -1
  35. package/.claude/skills/workflow-commands/working-tree-hold.md +9 -9
  36. package/.codex/hooks.json +5 -5
  37. package/.github/actions/setup-node/action.yml +9 -0
  38. package/.github/actions/setup-pnpm/action.yml +1 -1
  39. package/.github/dependabot.yml +16 -0
  40. package/.github/release.yml +0 -2
  41. package/.github/workflows/ci.yml +120 -10
  42. package/.github/workflows/publish.yml +8 -1
  43. package/.github/workflows/sonar-qube.yml +1 -0
  44. package/.prettierignore +2 -0
  45. package/.vscode/tasks.json +1 -2
  46. package/CLAUDE.md +3 -7
  47. package/README.md +4 -2
  48. package/SECURITY.md +1 -1
  49. package/dist/CLAUDE.md +3 -7
  50. package/dist/commands/document-read-cli.js +882 -0
  51. package/dist/commands/{document-section-cli.js → document-section-main.js} +79 -37
  52. package/dist/commands/read-set-cli.js +1867 -0
  53. package/dist/commands/run-prep-main.js +21653 -0
  54. package/dist/commands/run-step-cli.js +23880 -0
  55. package/dist/config-merge/index.js +5 -1
  56. package/dist/hooks/audit-provision.js +20 -35
  57. package/dist/hooks/{chunk-DGT54IH5.js → chunk-AZX4FGQ3.js} +63 -17
  58. package/dist/hooks/chunk-CWMBGKYW.js +6483 -0
  59. package/dist/hooks/chunk-O2YBIDSI.js +4306 -0
  60. package/dist/hooks/{chunk-TNUMY6NL.js → chunk-PT5R6UJD.js} +4193 -1900
  61. package/dist/hooks/chunk-TUIFS5E7.js +72 -0
  62. package/dist/hooks/{chunk-723HKZO5.js → chunk-VWWCFGWK.js} +1 -1
  63. package/dist/hooks/{chunk-APUO6U4J.js → chunk-WR2KQAYZ.js} +1843 -440
  64. package/dist/hooks/{chunk-O6GDRNJB.js → chunk-XGBNSWEI.js} +248 -46
  65. package/dist/hooks/chunk-YCDOIR3I.js +3456 -0
  66. package/dist/hooks/codex-hook-adapter.js +10 -22
  67. package/dist/hooks/format-edited.js +5 -6
  68. package/dist/hooks/inputs.json +443 -317
  69. package/dist/hooks/pretool-guard.js +7 -25
  70. package/dist/hooks/session-lang.js +44 -51
  71. package/dist/hooks/stop-guard.js +7716 -2187
  72. package/dist/josh.js +6002 -3583
  73. package/dist/self-sync-guard/index.js +74 -10
  74. package/dist/version/index.js +115 -406
  75. package/eslint/base.js +1 -1
  76. package/lefthook/base.yml +3 -1
  77. package/package.json +10 -48
  78. package/pnpm-workspace.yaml +4 -2
  79. package/prompts/coding-standards.md +1 -1
  80. package/prompts/collaboration-workflow/file-edits.md +1 -7
  81. package/prompts/collaboration-workflow/issue-citation.md +1 -1
  82. package/prompts/collaboration-workflow/issue-template.md +33 -16
  83. package/prompts/collaboration-workflow/lane-instructions.md +1 -2
  84. package/prompts/collaboration-workflow/measurement.md +37 -0
  85. package/prompts/collaboration-workflow/operating-rules.md +4 -6
  86. package/prompts/collaboration-workflow/output-bounds.md +2 -7
  87. package/prompts/collaboration-workflow/plan-comment.md +3 -42
  88. package/prompts/collaboration-workflow/principles.md +5 -0
  89. package/prompts/collaboration-workflow/report-format.md +31 -60
  90. package/prompts/collaboration-workflow/residency.md +2 -2
  91. package/prompts/collaboration-workflow/shell-body.md +6 -16
  92. package/prompts/collaboration-workflow/turn-batching.md +0 -2
  93. package/prompts/collaboration-workflow/upstream-interrupt.md +14 -4
  94. package/prompts/collaboration-workflow/wip-cap.md +1 -1
  95. package/prompts/collaboration-workflow.md +3 -7
  96. package/prompts/refactoring.md +1 -1
  97. package/prompts/review-rubric.md +1 -2
  98. package/prompts/review.md +41 -21
  99. package/prompts/testing-guide.md +8 -43
  100. package/scripts/agent/agent-event.ts +15 -15
  101. package/scripts/agent/agent-exit-record.ts +13 -1
  102. package/scripts/agent/api-auth.ts +41 -0
  103. package/scripts/agent/api-outage.ts +1 -1
  104. package/scripts/auto-ok/auto-ok-cli.ts +14 -16
  105. package/scripts/auto-ok/auto-ok-judge-read.ts +12 -3
  106. package/scripts/auto-ok/auto-ok-judge-write.ts +46 -19
  107. package/scripts/auto-ok/auto-ok-judge.ts +13 -2
  108. package/scripts/auto-ok/auto-ok-main.ts +17 -0
  109. package/scripts/backlog/backlog-arrival.ts +14 -3
  110. package/scripts/backlog/backlog-budget-cli.ts +7 -33
  111. package/scripts/backlog/backlog-budget-main.ts +16 -0
  112. package/scripts/backlog/backlog-budget.ts +2 -3
  113. package/scripts/backlog/backlog-defect-priority.ts +4 -3
  114. package/scripts/backlog/backlog-drive-adopt.ts +67 -0
  115. package/scripts/backlog/backlog-drive-args.ts +4 -5
  116. package/scripts/backlog/backlog-drive-cli.ts +113 -28
  117. package/scripts/backlog/backlog-drive-hold.ts +162 -0
  118. package/scripts/backlog/backlog-drive-idle.ts +151 -0
  119. package/scripts/backlog/backlog-drive-judge.ts +25 -0
  120. package/scripts/backlog/backlog-drive-memory.ts +126 -0
  121. package/scripts/backlog/backlog-drive-named-offer.ts +5 -10
  122. package/scripts/backlog/backlog-drive-named.ts +53 -6
  123. package/scripts/backlog/backlog-drive-offer-argv.ts +3 -8
  124. package/scripts/backlog/backlog-drive-paused.ts +169 -0
  125. package/scripts/backlog/backlog-drive-restore.ts +30 -7
  126. package/scripts/backlog/backlog-drive-seats.ts +18 -8
  127. package/scripts/backlog/backlog-drive-token-handling.ts +38 -0
  128. package/scripts/backlog/backlog-drive.ts +79 -75
  129. package/scripts/backlog/backlog-next-main.ts +16 -0
  130. package/scripts/backlog/backlog-next-shared.ts +73 -0
  131. package/scripts/backlog/backlog-next.ts +48 -16
  132. package/scripts/backlog/backlog-occupied.ts +52 -39
  133. package/scripts/backlog/backlog-offer-cli.ts +6 -21
  134. package/scripts/backlog/backlog-offer-exclude.ts +15 -0
  135. package/scripts/backlog/backlog-offer-main.ts +12 -0
  136. package/scripts/backlog/backlog-offer.ts +36 -3
  137. package/scripts/backlog/backlog-overlap.ts +22 -4
  138. package/scripts/backlog/backlog-plan-read.ts +6 -2
  139. package/scripts/backlog/backlog-plan.ts +18 -4
  140. package/scripts/backlog/backlog-pool.ts +10 -10
  141. package/scripts/backlog/backlog-rank.ts +10 -2
  142. package/scripts/backlog/backlog-ready.ts +112 -30
  143. package/scripts/backlog/backlog-stalled-detect.ts +109 -36
  144. package/scripts/backlog/backlog-stalled.ts +52 -16
  145. package/scripts/backlog/backlog-wait-cause.ts +86 -0
  146. package/scripts/backlog/backlog-waves.ts +39 -13
  147. package/scripts/backlog/backlogrun-args.ts +19 -7
  148. package/scripts/backlog/backlogrun-cli.ts +19 -5
  149. package/scripts/backlog/backlogrun-launch.ts +6 -0
  150. package/scripts/backlog/backlogrun-restart.ts +97 -0
  151. package/scripts/backlog/backlogrun-stop.ts +79 -7
  152. package/scripts/behavior/behavior-cli.ts +2 -2
  153. package/scripts/behavior/behavior-rules.ts +47 -24
  154. package/scripts/build/build-bin.ts +2 -16
  155. package/scripts/build/build-claude-md.ts +0 -7
  156. package/scripts/build/build-commands.ts +0 -13
  157. package/scripts/build/build-hooks.ts +49 -48
  158. package/scripts/build/hook-bundle-stamp.ts +29 -11
  159. package/scripts/build/local-bin.ts +1 -1
  160. package/scripts/cases/cases-cli.ts +25 -13
  161. package/scripts/cases/cases-interaction-scan.ts +134 -0
  162. package/scripts/cases/cases-interaction.ts +183 -0
  163. package/scripts/cases/cases-logic.ts +39 -6
  164. package/scripts/ci/pr-classification-main.ts +18 -0
  165. package/scripts/ci/pr-classification.ts +10 -17
  166. package/scripts/clone/clone-scan.ts +1 -1
  167. package/scripts/cost-runtime/cost-blocks.ts +22 -37
  168. package/scripts/cost-runtime/cost-cli.ts +31 -14
  169. package/scripts/cost-runtime/cost-main.ts +12 -0
  170. package/scripts/cost-runtime/cost-transcript.ts +1 -0
  171. package/scripts/delegation/delegation-policy.ts +17 -4
  172. package/scripts/delegation/duplicate-read-guard.ts +0 -8
  173. package/scripts/delegation/investigation-guard.ts +0 -8
  174. package/scripts/delegation/investigation-reads.ts +3 -4
  175. package/scripts/dependabot/dependabot-cooldown.ts +194 -0
  176. package/scripts/discovery/repo-discovery.ts +24 -6
  177. package/scripts/doctor/doctor-consumer.ts +2 -5
  178. package/scripts/document/document-byte-budget.ts +8 -6
  179. package/scripts/document/document-scan.ts +1 -1
  180. package/scripts/document/document-section-cli.ts +0 -8
  181. package/scripts/document/document-section-main.ts +12 -0
  182. package/scripts/epic/epic-audit-cli.ts +12 -6
  183. package/scripts/epic/epic-bundle-apply.ts +137 -0
  184. package/scripts/epic/epic-bundle-cli.ts +32 -121
  185. package/scripts/epic/epic-bundle-format.ts +116 -0
  186. package/scripts/epic/epic-bundle-main.ts +17 -0
  187. package/scripts/epic/epic-busy.ts +5 -12
  188. package/scripts/epic/epic-classify.ts +24 -15
  189. package/scripts/epic/epic-cli-argv.ts +31 -0
  190. package/scripts/epic/epic-cli-decide.ts +42 -0
  191. package/scripts/epic/epic-cli.ts +6 -38
  192. package/scripts/epic/epic-close.ts +112 -55
  193. package/scripts/epic/epic-cross-repo.ts +4 -7
  194. package/scripts/epic/epic-decide.ts +119 -0
  195. package/scripts/epic/epic-decision.ts +9 -0
  196. package/scripts/epic/epic-fetch.ts +4 -0
  197. package/scripts/epic/epic-graph.ts +2 -0
  198. package/scripts/epic/epic-issue.ts +5 -1
  199. package/scripts/epic/epic-label-age.ts +1 -1
  200. package/scripts/epic/epic-lane-offer.ts +39 -4
  201. package/scripts/epic/epic-next-main.ts +24 -0
  202. package/scripts/epic/epic-next.ts +6 -24
  203. package/scripts/epic/epic-outside-blocker.ts +6 -2
  204. package/scripts/epic/epic-parse.ts +9 -3
  205. package/scripts/epic/epic-read.ts +1 -0
  206. package/scripts/epic/epic-reconcile.ts +39 -0
  207. package/scripts/epic/epic-run.ts +10 -1
  208. package/scripts/epic/epic-solo.ts +50 -14
  209. package/scripts/epic/epic.ts +41 -7
  210. package/scripts/exports/unused-members-cli.ts +2 -2
  211. package/scripts/followup/followup-checks-event.ts +8 -3
  212. package/scripts/followup/followup-coderabbit-wait.ts +82 -0
  213. package/scripts/followup/followup-review-gates.ts +81 -0
  214. package/scripts/followup/git-followup-stages.ts +13 -3
  215. package/scripts/followup/git-followup-workflow.ts +19 -66
  216. package/scripts/followup/git-pr-followup-wrapup.ts +9 -14
  217. package/scripts/followup/git-pr-followup.ts +36 -8
  218. package/scripts/fresh-machine/fresh-machine-cli.ts +1 -1
  219. package/scripts/fresh-machine/fresh-machine-run.ts +8 -8
  220. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +1 -1
  221. package/scripts/gate/busy-average.ts +58 -0
  222. package/scripts/gate/check-cpu.ts +60 -0
  223. package/scripts/gate/check-inputs.ts +39 -95
  224. package/scripts/gate/check-reuse.ts +33 -54
  225. package/scripts/gate/command-memory.ts +192 -0
  226. package/scripts/gate/core-admission.ts +218 -28
  227. package/scripts/gate/core-budget-timing.ts +37 -0
  228. package/scripts/gate/core-budget.ts +80 -98
  229. package/scripts/gate/core-wait-record.ts +48 -0
  230. package/scripts/gate/core-wait.ts +37 -5
  231. package/scripts/gate/core-weights.ts +86 -0
  232. package/scripts/gate/free-cores.ts +27 -4
  233. package/scripts/gate/gate-ledger.ts +32 -4
  234. package/scripts/gate/gate-plan.ts +41 -34
  235. package/scripts/gate/gate-report.ts +14 -2
  236. package/scripts/gate/gate-run-steps.ts +53 -8
  237. package/scripts/gate/gate-skip.ts +12 -2
  238. package/scripts/gate/gate-steps.ts +12 -1
  239. package/scripts/gate/input-fingerprint.ts +42 -0
  240. package/scripts/gate/machine-capacity.ts +65 -31
  241. package/scripts/gate/moved-paths.ts +67 -0
  242. package/scripts/gate/project-checks.ts +5 -12
  243. package/scripts/gate/scoped-green.ts +12 -8
  244. package/scripts/gate/since-green.ts +62 -0
  245. package/scripts/gate/toolchain-inputs.ts +115 -0
  246. package/scripts/gate/verification-gate.ts +27 -24
  247. package/scripts/gate/verification-inputs.ts +250 -0
  248. package/scripts/gh/gh-author-association.ts +96 -9
  249. package/scripts/gh/git-ai-review-scan.ts +4 -2
  250. package/scripts/gh/git-gh-api-path.ts +15 -0
  251. package/scripts/gh/git-gh-branch-rules.ts +73 -0
  252. package/scripts/gh/git-gh-conditional.ts +5 -2
  253. package/scripts/gh/git-gh-issue-read.ts +5 -1
  254. package/scripts/gh/git-gh-issue-write.ts +67 -29
  255. package/scripts/gh/git-gh-issue.ts +7 -3
  256. package/scripts/gh/git-gh-poll-read.ts +89 -0
  257. package/scripts/gh/git-gh-pr-auto-merge.ts +8 -3
  258. package/scripts/gh/git-gh-pr-rest.ts +1 -1
  259. package/scripts/gh/git-gh-pr-snapshot.ts +33 -20
  260. package/scripts/gh/git-gh-pr.ts +27 -15
  261. package/scripts/gh/git-pr-checks-eval.ts +39 -7
  262. package/scripts/gh/git-pr-checks-parse.ts +39 -9
  263. package/scripts/gh/git-pr-merge-checked.ts +80 -0
  264. package/scripts/git/base-tree.ts +19 -2
  265. package/scripts/git/changed-file-scope.ts +6 -4
  266. package/scripts/git/changed-paths.ts +18 -1
  267. package/scripts/git/git-diff-reads.ts +27 -2
  268. package/scripts/git/git-grep-hits.ts +85 -0
  269. package/scripts/git/git-location-environment.ts +1 -1
  270. package/scripts/git/git-merge-conflicts.ts +83 -0
  271. package/scripts/git/git-preflight.ts +37 -12
  272. package/scripts/git/git-push-transport.ts +1 -2
  273. package/scripts/git/git-schemas.ts +17 -7
  274. package/scripts/git/git-spawn.ts +1 -2
  275. package/scripts/git/git-status.ts +4 -4
  276. package/scripts/git/main-merge-main.ts +12 -0
  277. package/scripts/git/main-merge-regenerate.ts +2 -2
  278. package/scripts/git/main-merge.ts +25 -9
  279. package/scripts/git/main-sync-main.ts +12 -0
  280. package/scripts/git/main-sync.ts +0 -9
  281. package/scripts/git/stash/git-stash.ts +27 -4
  282. package/scripts/git/stash/{stash-pop-args.ts → stash-args.ts} +13 -10
  283. package/scripts/git/stash/stash-pop-cli.ts +6 -12
  284. package/scripts/git/stash/stash-pop-main.ts +12 -0
  285. package/scripts/git/stash/stash-push-cli.ts +76 -0
  286. package/scripts/git/stash/stash-push-main.ts +12 -0
  287. package/scripts/hooks/batch-guard.ts +0 -8
  288. package/scripts/hooks/check-commit-message-main.ts +8 -0
  289. package/scripts/hooks/check-commit-message.ts +4 -7
  290. package/scripts/hooks/format-edited-file.ts +8 -24
  291. package/scripts/hooks/pre-commit-lint.ts +30 -3
  292. package/scripts/hooks/pre-push-unit.ts +4 -2
  293. package/scripts/hooks/pretool-guard-cli.ts +1 -8
  294. package/scripts/hooks/pretool-guard.ts +32 -19
  295. package/scripts/hooks/reserved-run.ts +67 -9
  296. package/scripts/hooks/run-hook.sh +13 -4
  297. package/scripts/hooks/shell-rules-notice.ts +37 -0
  298. package/scripts/hooks/stop-actions.ts +2 -21
  299. package/scripts/hooks/stop-guard.ts +13 -9
  300. package/scripts/init/hook-command-rewrite.ts +19 -5
  301. package/scripts/init/hook-launch.ts +15 -17
  302. package/scripts/init/init-actions.ts +0 -6
  303. package/scripts/init/init-ai-copy.ts +10 -36
  304. package/scripts/init/init-bootstrap.ts +9 -8
  305. package/scripts/init/init-dry-run-report.ts +1 -1
  306. package/scripts/init/init-dry-run.ts +1 -1
  307. package/scripts/init/init-file-action.ts +7 -9
  308. package/scripts/init/init-logic-json-merge.ts +2 -2
  309. package/scripts/init/init-logic-migrate.ts +9 -82
  310. package/scripts/init/init-logic.ts +3 -2
  311. package/scripts/init/init-main.ts +12 -0
  312. package/scripts/init/init.ts +5 -12
  313. package/scripts/init/kit-development-versions.ts +3 -7
  314. package/scripts/init/kit-written-paths.ts +2 -2
  315. package/scripts/init/project-profile.ts +5 -4
  316. package/scripts/init/tsconfig-preset-migration.ts +2 -1
  317. package/scripts/init/vscode-tasks.ts +1 -1
  318. package/scripts/issue/defect-origin-cli.ts +106 -0
  319. package/scripts/issue/defect-origin-line.ts +60 -0
  320. package/scripts/issue/defect-origin-main.ts +11 -0
  321. package/scripts/issue/defect-origin.ts +114 -0
  322. package/scripts/issue/defect-rate-cli.ts +34 -78
  323. package/scripts/issue/defect-rate.ts +0 -16
  324. package/scripts/issue/defect-report-cli.ts +128 -0
  325. package/scripts/issue/defect-report-format.ts +56 -0
  326. package/scripts/issue/defect-report-main.ts +11 -0
  327. package/scripts/issue/defect-report.ts +160 -0
  328. package/scripts/issue/expected-effect-lint.ts +1 -0
  329. package/scripts/issue/issue-already-done-cli.ts +62 -0
  330. package/scripts/issue/issue-body-or-comment.ts +40 -0
  331. package/scripts/issue/issue-cite-cli.ts +0 -9
  332. package/scripts/issue/issue-cite-main.ts +12 -0
  333. package/scripts/issue/issue-classification.ts +12 -7
  334. package/scripts/issue/issue-comment-cli.ts +10 -24
  335. package/scripts/issue/issue-comment-main.ts +12 -0
  336. package/scripts/issue/issue-evidence-exit.ts +100 -0
  337. package/scripts/issue/issue-file-cli.ts +29 -7
  338. package/scripts/issue/issue-file.ts +19 -19
  339. package/scripts/issue/issue-fold-cli.ts +2 -11
  340. package/scripts/issue/issue-fold-main.ts +12 -0
  341. package/scripts/issue/issue-labels.ts +81 -90
  342. package/scripts/issue/issue-lint-cli.ts +2 -10
  343. package/scripts/issue/issue-lint-main.ts +12 -0
  344. package/scripts/issue/issue-measured-cli.ts +56 -0
  345. package/scripts/issue/issue-merged.ts +19 -2
  346. package/scripts/issue/issue-not-before-label.ts +135 -0
  347. package/scripts/issue/issue-not-before.ts +111 -0
  348. package/scripts/issue/issue-number-shape.ts +15 -1
  349. package/scripts/issue/issue-park.ts +28 -0
  350. package/scripts/issue/issue-plan-cli.ts +151 -0
  351. package/scripts/issue/issue-priority.ts +151 -0
  352. package/scripts/issue/issue-rank.ts +7 -1
  353. package/scripts/issue/issue-read-cli.ts +3 -10
  354. package/scripts/issue/issue-read-main.ts +12 -0
  355. package/scripts/issue/issue-read.ts +29 -5
  356. package/scripts/issue/issue-release-cli.ts +0 -10
  357. package/scripts/issue/issue-release-main.ts +13 -0
  358. package/scripts/issue/issue-release.ts +7 -12
  359. package/scripts/issue/issue-sample-gate.ts +192 -0
  360. package/scripts/issue/issue-sample-source.ts +76 -0
  361. package/scripts/issue/issue-scout-cli.ts +0 -11
  362. package/scripts/issue/issue-scout-main.ts +14 -0
  363. package/scripts/issue/issue-state-cli.ts +0 -10
  364. package/scripts/issue/issue-state-main.ts +12 -0
  365. package/scripts/issue/issue-watch-diff.ts +56 -15
  366. package/scripts/issue/issue-watch.ts +2 -1
  367. package/scripts/issue/issue-wip.ts +2 -7
  368. package/scripts/issue/measure-rerun-cli.ts +13 -8
  369. package/scripts/issue/plan-consumers-cli.ts +39 -0
  370. package/scripts/issue/plan-consumers-main.ts +11 -0
  371. package/scripts/issue/plan-consumers-section.ts +55 -0
  372. package/scripts/issue/plan-consumers.ts +127 -0
  373. package/scripts/josh/agent-session-environment.ts +1 -1
  374. package/scripts/josh/command-usage.ts +15 -43
  375. package/scripts/josh/file-map-stamp.ts +49 -16
  376. package/scripts/josh/hook-decision.ts +32 -20
  377. package/scripts/josh/josh-command-map.ts +4 -1
  378. package/scripts/josh/josh-command-types.ts +12 -6
  379. package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
  380. package/scripts/josh/josh-commands-ai.ts +157 -158
  381. package/scripts/josh/josh-commands-backlog.ts +82 -16
  382. package/scripts/josh/josh-commands-clone.ts +1 -0
  383. package/scripts/josh/josh-commands-development.ts +111 -71
  384. package/scripts/josh/josh-commands-document.ts +43 -1
  385. package/scripts/josh/josh-commands-epic.ts +171 -0
  386. package/scripts/josh/josh-commands-hooks.ts +25 -2
  387. package/scripts/josh/josh-commands-issue-write.ts +181 -0
  388. package/scripts/josh/josh-commands-issue.ts +124 -24
  389. package/scripts/josh/josh-commands-lane.ts +103 -2
  390. package/scripts/josh/josh-commands-lint.ts +19 -8
  391. package/scripts/josh/josh-commands-maintenance.ts +112 -4
  392. package/scripts/josh/josh-commands-pause.ts +29 -0
  393. package/scripts/josh/josh-commands-progress.ts +87 -0
  394. package/scripts/josh/josh-commands-project.ts +138 -9
  395. package/scripts/josh/josh-commands-review.ts +124 -0
  396. package/scripts/josh/josh-commands-run.ts +211 -23
  397. package/scripts/josh/josh-commands-ship.ts +169 -0
  398. package/scripts/josh/josh-commands-split.ts +9 -0
  399. package/scripts/josh/josh-commands-versioning.ts +49 -2
  400. package/scripts/josh/josh-commands-workflow.ts +144 -6
  401. package/scripts/josh/josh-logic.ts +6 -13
  402. package/scripts/josh/package-directory.ts +2 -4
  403. package/scripts/josh/process-identity.ts +13 -4
  404. package/scripts/josh/session-language-cli.ts +4 -8
  405. package/scripts/josh/session-language-main.ts +13 -0
  406. package/scripts/josh/session-language.ts +6 -1
  407. package/scripts/josh/shared-cache.ts +90 -0
  408. package/scripts/josh/stamp-file.ts +9 -15
  409. package/scripts/lane/lane-await.ts +51 -12
  410. package/scripts/lane/lane-cache.ts +5 -30
  411. package/scripts/lane/lane-capacity.ts +14 -23
  412. package/scripts/lane/lane-check-stats.ts +62 -21
  413. package/scripts/lane/lane-child-invocation.ts +8 -0
  414. package/scripts/lane/lane-cli.ts +15 -5
  415. package/scripts/lane/lane-close.ts +86 -18
  416. package/scripts/lane/lane-core-wait-stats.ts +66 -0
  417. package/scripts/lane/lane-dispatch.ts +24 -3
  418. package/scripts/lane/lane-gap-stats.ts +156 -0
  419. package/scripts/lane/lane-handoff.ts +69 -1
  420. package/scripts/lane/lane-held-stats.ts +129 -0
  421. package/scripts/lane/lane-install.ts +4 -11
  422. package/scripts/lane/lane-launch-cli.ts +0 -9
  423. package/scripts/lane/lane-launch-main.ts +12 -0
  424. package/scripts/lane/lane-ledger-schema.ts +266 -0
  425. package/scripts/lane/lane-ledger.ts +92 -123
  426. package/scripts/lane/lane-limit-cli.ts +12 -1
  427. package/scripts/lane/lane-measure-cli.ts +57 -11
  428. package/scripts/lane/lane-open.ts +9 -1
  429. package/scripts/lane/lane-parked.ts +3 -3
  430. package/scripts/lane/lane-pause-cli.ts +130 -0
  431. package/scripts/lane/lane-pause.ts +158 -0
  432. package/scripts/lane/lane-process-table.ts +166 -0
  433. package/scripts/lane/lane-reap-settle.ts +124 -0
  434. package/scripts/lane/lane-reap.ts +50 -15
  435. package/scripts/lane/lane-registry.ts +24 -3
  436. package/scripts/lane/lane-residents.ts +162 -0
  437. package/scripts/lane/lane-restart.ts +22 -2
  438. package/scripts/lane/lane-round-two-stats.ts +49 -0
  439. package/scripts/lane/lane-sampler.ts +4 -0
  440. package/scripts/lane/lane-session-action.ts +19 -5
  441. package/scripts/lane/lane-session-broker.ts +102 -21
  442. package/scripts/lane/lane-snapshot-trace.ts +84 -0
  443. package/scripts/lane/lane-spans.ts +51 -0
  444. package/scripts/lane/lane-spent.ts +6 -3
  445. package/scripts/lane/lane-stage-stats.ts +7 -2
  446. package/scripts/lane/lane-state.ts +302 -0
  447. package/scripts/lane/lane-stats.ts +58 -4
  448. package/scripts/lane/lane-stop-stats.ts +113 -37
  449. package/scripts/lane/lane-test-related-stats.ts +127 -0
  450. package/scripts/lane/lane-transcript-calls.ts +145 -0
  451. package/scripts/lane/lane-transcript-stats.ts +168 -0
  452. package/scripts/lane/lane-vacant.ts +13 -3
  453. package/scripts/lane/lane-withdraw-cli.ts +5 -4
  454. package/scripts/lane/lane-withdraw.ts +50 -49
  455. package/scripts/lane/process-directories.ts +70 -0
  456. package/scripts/lane/process-lane-marks.ts +94 -0
  457. package/scripts/lib/atomic-write.ts +62 -0
  458. package/scripts/lib/buffered-process.ts +12 -5
  459. package/scripts/lib/cli-flags.ts +53 -0
  460. package/scripts/lib/figure-format.ts +63 -0
  461. package/scripts/lib/json-value.ts +9 -1
  462. package/scripts/lib/package-manifest.ts +35 -0
  463. package/scripts/lib/read-file.ts +3 -1
  464. package/scripts/lib/stamped-memo.ts +63 -0
  465. package/scripts/lib/stdout-on-stderr.ts +24 -0
  466. package/scripts/lib/timeouts.ts +9 -0
  467. package/scripts/lib/transcript-record.ts +91 -0
  468. package/scripts/lines/effective-limit.ts +1 -1
  469. package/scripts/lint/eslint-cache-dependencies.ts +145 -0
  470. package/scripts/lint/eslint-daemon.ts +265 -0
  471. package/scripts/lint/format.ts +11 -2
  472. package/scripts/lint/import-graph.ts +279 -0
  473. package/scripts/lint/lint-gate-scope.ts +102 -0
  474. package/scripts/lint/lint-parallel-main.ts +19 -0
  475. package/scripts/lint/lint-parallel.ts +62 -30
  476. package/scripts/lint/lint-related-scope.ts +30 -24
  477. package/scripts/lint/lint-related.ts +38 -6
  478. package/scripts/notify/confirmation-options.ts +1 -2
  479. package/scripts/notify/telegram-notify.ts +20 -20
  480. package/scripts/notify/telegram-test-logic.ts +0 -1
  481. package/scripts/notify/telegram-test-main.ts +8 -0
  482. package/scripts/notify/telegram-test.ts +2 -6
  483. package/scripts/observations/observation-ledger.ts +13 -0
  484. package/scripts/observations/observations-flush-landing.ts +5 -3
  485. package/scripts/observations/observations-flush.ts +6 -1
  486. package/scripts/overrides/overrides-check.ts +2 -5
  487. package/scripts/overrides/overrides-files.ts +2 -1
  488. package/scripts/overrides/overrides-logic.ts +3 -6
  489. package/scripts/package/verify-optional-eslint-install.ts +8 -6
  490. package/scripts/propagate/propagate-publish.ts +2 -7
  491. package/scripts/propagate/propagate-targets.ts +4 -12
  492. package/scripts/refactor/import-graph.ts +9 -7
  493. package/scripts/release/github-release-runs.ts +17 -6
  494. package/scripts/release/release-approval-prune.ts +18 -0
  495. package/scripts/release/release-history.ts +1 -3
  496. package/scripts/release/release-progress.ts +42 -22
  497. package/scripts/release/release-publish-run.ts +39 -0
  498. package/scripts/release/release-publish.ts +6 -6
  499. package/scripts/release/release-scope-cli.ts +0 -10
  500. package/scripts/release/release-scope-main.ts +12 -0
  501. package/scripts/repo/repo-setting.ts +3 -6
  502. package/scripts/repo/required-checks-logic.ts +6 -15
  503. package/scripts/report/report-format-reference.ts +2 -0
  504. package/scripts/report/report-labels.ts +155 -0
  505. package/scripts/report/report-lint-cli.ts +3 -0
  506. package/scripts/report/report-lint.ts +85 -110
  507. package/scripts/report/report-template-cli.ts +59 -0
  508. package/scripts/report/report-template.ts +112 -0
  509. package/scripts/review/acceptance-map.ts +1 -0
  510. package/scripts/review/removed-tests-check.ts +86 -0
  511. package/scripts/review/removed-tests.ts +149 -0
  512. package/scripts/review/review-brief-cli.ts +81 -15
  513. package/scripts/review/review-brief-main.ts +12 -0
  514. package/scripts/review/review-brief.ts +31 -3
  515. package/scripts/review/review-code-tree.ts +10 -6
  516. package/scripts/review/review-comment-round.ts +26 -8
  517. package/scripts/review/review-finding-ledger.ts +30 -15
  518. package/scripts/review/review-interaction.ts +94 -0
  519. package/scripts/review/review-readers-scan.ts +163 -0
  520. package/scripts/review/review-record-cli.ts +69 -30
  521. package/scripts/review/review-record-main.ts +12 -0
  522. package/scripts/review/review-round-one-blobs.ts +221 -0
  523. package/scripts/review/review-round2-cli.ts +49 -12
  524. package/scripts/review/review-round2.ts +80 -12
  525. package/scripts/review/review-stamps.ts +19 -1
  526. package/scripts/review/review-stop-log.ts +96 -0
  527. package/scripts/review/review-stops-cli.ts +85 -0
  528. package/scripts/review/review-tree.ts +6 -17
  529. package/scripts/review/review-untouched-readers.ts +146 -0
  530. package/scripts/review/test-titles.ts +118 -0
  531. package/scripts/rules/agent-model.ts +8 -0
  532. package/scripts/rules/bash-triggers.ts +46 -3
  533. package/scripts/rules/decision-oracle-batch.ts +9 -1
  534. package/scripts/rules/decision-oracle.ts +2 -2
  535. package/scripts/rules/delivered-rules.ts +80 -2
  536. package/scripts/rules/destructive-command.ts +8 -1
  537. package/scripts/rules/direct-filing.ts +10 -2
  538. package/scripts/rules/direct-issue-comment.ts +117 -0
  539. package/scripts/rules/direct-pr-create.ts +69 -3
  540. package/scripts/rules/early-heartbeat.ts +2 -1
  541. package/scripts/rules/file-body.ts +7 -0
  542. package/scripts/rules/filing-cap.ts +7 -0
  543. package/scripts/rules/git-argv.ts +72 -14
  544. package/scripts/rules/git-force.ts +12 -2
  545. package/scripts/rules/guard-remedy.ts +4 -0
  546. package/scripts/rules/implementation-cut-verdict.ts +1 -1
  547. package/scripts/rules/implementation-cut.ts +11 -3
  548. package/scripts/rules/index-guard.ts +8 -1
  549. package/scripts/rules/issue-comments.ts +9 -1
  550. package/scripts/rules/josh-git-bare.ts +7 -0
  551. package/scripts/rules/lane-background.ts +67 -25
  552. package/scripts/rules/lane-carry-conflict.ts +6 -0
  553. package/scripts/rules/lane-direct-tool.ts +74 -0
  554. package/scripts/rules/lane-interactive-ask.ts +9 -2
  555. package/scripts/rules/lane-park.ts +45 -23
  556. package/scripts/rules/lane-split-park.ts +10 -2
  557. package/scripts/rules/lane-switch-main.ts +7 -0
  558. package/scripts/rules/oracle-consulted.ts +10 -0
  559. package/scripts/rules/oracle-firing.ts +1 -0
  560. package/scripts/rules/permission-guards.ts +3 -0
  561. package/scripts/rules/piped-verification.ts +1 -1
  562. package/scripts/rules/poll-loop.ts +7 -0
  563. package/scripts/rules/pr-merge.ts +123 -0
  564. package/scripts/rules/protected-files.ts +32 -5
  565. package/scripts/rules/raw-field-body.ts +6 -0
  566. package/scripts/rules/rule-body-guard.ts +8 -0
  567. package/scripts/rules/rule-list.ts +9 -28
  568. package/scripts/rules/rule-value-cache.ts +4 -9
  569. package/scripts/rules/rule-value-cli.ts +51 -32
  570. package/scripts/rules/rule-value.ts +1 -1
  571. package/scripts/rules/shell-segments.ts +35 -0
  572. package/scripts/rules/stop-rule-rows.ts +64 -0
  573. package/scripts/rules/stop-rules.ts +3 -4
  574. package/scripts/rules/test-declared-commit.ts +11 -1
  575. package/scripts/rules/third-party-write.ts +7 -0
  576. package/scripts/rules/timed-rerun.ts +69 -0
  577. package/scripts/rules/worktree-guard.ts +13 -3
  578. package/scripts/run/board/run-board-app-name.ts +23 -0
  579. package/scripts/run/board/run-board-cli.ts +65 -32
  580. package/scripts/run/board/run-board-earlier.ts +94 -0
  581. package/scripts/run/board/run-board-ending-reason.ts +67 -0
  582. package/scripts/run/board/run-board-estimate-schedule.ts +103 -0
  583. package/scripts/run/board/run-board-estimate.ts +98 -0
  584. package/scripts/run/board/run-board-fit.ts +153 -36
  585. package/scripts/run/board/run-board-fold.ts +123 -0
  586. package/scripts/run/board/run-board-fresh.ts +2 -2
  587. package/scripts/run/board/run-board-gather-live.ts +29 -0
  588. package/scripts/run/board/run-board-gather-thread.ts +189 -0
  589. package/scripts/run/board/run-board-gather-worker.ts +29 -0
  590. package/scripts/run/board/run-board-gather.ts +187 -0
  591. package/scripts/run/board/run-board-github.ts +118 -38
  592. package/scripts/run/board/run-board-header.ts +82 -20
  593. package/scripts/run/board/run-board-keys.ts +58 -0
  594. package/scripts/run/board/run-board-kind.ts +20 -6
  595. package/scripts/run/board/run-board-labels.ts +116 -71
  596. package/scripts/run/board/run-board-lane-state.ts +109 -0
  597. package/scripts/run/board/run-board-lane-time.ts +122 -0
  598. package/scripts/run/board/run-board-layout.ts +239 -60
  599. package/scripts/run/board/run-board-length.ts +52 -0
  600. package/scripts/run/board/run-board-machine.ts +8 -4
  601. package/scripts/run/board/run-board-main.ts +12 -0
  602. package/scripts/run/board/run-board-notes.ts +52 -31
  603. package/scripts/run/board/run-board-now.ts +1 -1
  604. package/scripts/run/board/run-board-operation.ts +15 -33
  605. package/scripts/run/board/run-board-phase.ts +1 -1
  606. package/scripts/run/board/run-board-plan-shared.ts +115 -0
  607. package/scripts/run/board/run-board-plan.ts +55 -3
  608. package/scripts/run/board/run-board-planning.ts +45 -0
  609. package/scripts/run/board/run-board-priority.ts +44 -0
  610. package/scripts/run/board/run-board-process-groups.ts +195 -0
  611. package/scripts/run/board/run-board-read.ts +151 -27
  612. package/scripts/run/board/run-board-reason.ts +235 -51
  613. package/scripts/run/board/run-board-released.ts +35 -0
  614. package/scripts/run/board/run-board-render-checks.ts +39 -5
  615. package/scripts/run/board/run-board-render-condition.ts +96 -0
  616. package/scripts/run/board/run-board-render-drawn.ts +67 -0
  617. package/scripts/run/board/run-board-render-foot.ts +59 -0
  618. package/scripts/run/board/run-board-render-icon.ts +35 -0
  619. package/scripts/run/board/run-board-render-lanes.ts +145 -0
  620. package/scripts/run/board/run-board-render-lead.ts +80 -0
  621. package/scripts/run/board/run-board-render-legend.ts +117 -48
  622. package/scripts/run/board/run-board-render-notes.ts +156 -29
  623. package/scripts/run/board/run-board-render-processes.ts +196 -0
  624. package/scripts/run/board/run-board-render-section.ts +119 -0
  625. package/scripts/run/board/run-board-render-slot.ts +3 -36
  626. package/scripts/run/board/run-board-render-tail.ts +115 -48
  627. package/scripts/run/board/run-board-render-time.ts +56 -0
  628. package/scripts/run/board/run-board-render-title.ts +117 -24
  629. package/scripts/run/board/run-board-render-waits.ts +104 -20
  630. package/scripts/run/board/run-board-render.ts +207 -265
  631. package/scripts/run/board/run-board-roots.ts +54 -0
  632. package/scripts/run/board/run-board-row-yield.ts +9 -4
  633. package/scripts/run/board/run-board-setup.ts +1 -12
  634. package/scripts/run/board/run-board-snapshot.ts +111 -0
  635. package/scripts/run/board/run-board-spin.ts +2 -2
  636. package/scripts/run/board/run-board-state.ts +22 -33
  637. package/scripts/run/board/run-board-status.ts +147 -71
  638. package/scripts/run/board/run-board-thanks-read.ts +2 -2
  639. package/scripts/run/board/run-board-tick.ts +122 -107
  640. package/scripts/run/board/run-board-usage-board.ts +78 -0
  641. package/scripts/run/board/run-board-usage-lanes.ts +113 -0
  642. package/scripts/run/board/run-board-usage-listing.ts +93 -0
  643. package/scripts/run/board/run-board-usage-read.ts +120 -150
  644. package/scripts/run/board/run-board-usage-rusage.ts +19 -7
  645. package/scripts/run/board/run-board-usage-text.ts +139 -51
  646. package/scripts/run/board/run-board-usage-top.ts +102 -0
  647. package/scripts/run/board/run-board-usage.ts +89 -72
  648. package/scripts/run/board/run-board-usual.ts +20 -9
  649. package/scripts/run/carry/run-carry-args.ts +4 -7
  650. package/scripts/run/carry/run-carry-conversation.ts +1 -1
  651. package/scripts/run/carry/run-carry.ts +9 -4
  652. package/scripts/run/cut/run-cut-handoff.ts +2 -2
  653. package/scripts/run/event/run-event-cli.ts +1 -5
  654. package/scripts/run/event/run-event-filed.ts +12 -6
  655. package/scripts/run/event/run-event-follow.ts +2 -3
  656. package/scripts/run/event/run-event-render.ts +6 -10
  657. package/scripts/run/event/run-event-scope.ts +2 -2
  658. package/scripts/run/event/run-event-stream-emit.ts +82 -22
  659. package/scripts/run/event/run-event-stream.ts +34 -8
  660. package/scripts/run/hold/run-hold-adopt.ts +65 -0
  661. package/scripts/run/hold/run-hold-cli.ts +93 -22
  662. package/scripts/run/hold/run-hold-main.ts +12 -0
  663. package/scripts/run/hold/run-hold-member.ts +37 -0
  664. package/scripts/run/hold/run-stop-notify.ts +183 -0
  665. package/scripts/run/merge/run-merge-auth.ts +31 -0
  666. package/scripts/run/merge/run-merge-cli.ts +62 -48
  667. package/scripts/run/merge/run-merge-close.ts +74 -0
  668. package/scripts/run/merge/run-merge-collect.ts +6 -13
  669. package/scripts/run/merge/run-merge-driver.ts +71 -0
  670. package/scripts/run/merge/run-merge-main.ts +12 -0
  671. package/scripts/run/merge/run-merge-outcome.ts +23 -0
  672. package/scripts/run/merge/run-merge-restart.ts +39 -0
  673. package/scripts/run/merge/run-merge-ship.ts +20 -4
  674. package/scripts/run/merge/run-merge-signals.ts +33 -9
  675. package/scripts/run/merge/run-merge-steps.ts +120 -85
  676. package/scripts/run/merge/run-merge.ts +38 -37
  677. package/scripts/run/park/run-park-cli.ts +91 -0
  678. package/scripts/run/park/run-park.ts +88 -0
  679. package/scripts/run/park/run-stalled.ts +68 -0
  680. package/scripts/run/pause/run-pause-cli.ts +73 -0
  681. package/scripts/run/pause/run-pause.ts +251 -0
  682. package/scripts/run/progress/run-progress-cli.ts +4 -12
  683. package/scripts/run/progress/run-progress-clock.ts +1 -1
  684. package/scripts/run/progress/run-progress-config.ts +6 -14
  685. package/scripts/run/progress/run-progress-main.ts +12 -0
  686. package/scripts/run/progress/run-progress.ts +1 -4
  687. package/scripts/run/review/run-review.ts +2 -1
  688. package/scripts/run/run-ending.ts +1 -0
  689. package/scripts/run/run-invocation.ts +5 -6
  690. package/scripts/run/run-liveness-cli.ts +6 -8
  691. package/scripts/run/run-liveness.ts +60 -29
  692. package/scripts/run/run-next.ts +1 -1
  693. package/scripts/run/run-parent-cut-hook.ts +2 -2
  694. package/scripts/run/run-preflight.ts +18 -3
  695. package/scripts/run/run-prep-cli.ts +1 -10
  696. package/scripts/run/run-prep-locate.ts +7 -50
  697. package/scripts/run/run-prep-main.ts +12 -0
  698. package/scripts/run/run-prep.ts +6 -0
  699. package/scripts/run/run-report-cli.ts +101 -13
  700. package/scripts/run/run-report-handoff.ts +114 -0
  701. package/scripts/run/run-step.ts +1 -1
  702. package/scripts/run/run-stranded-detect.ts +13 -0
  703. package/scripts/run/run-watcher-guard-cli.ts +1 -1
  704. package/scripts/run/run-watcher-guard.ts +1 -1
  705. package/scripts/run/ship/run-ship-args.ts +121 -0
  706. package/scripts/run/ship/run-ship-body-draft.ts +110 -0
  707. package/scripts/run/ship/run-ship-cli.ts +63 -140
  708. package/scripts/run/ship/run-ship-detach.ts +19 -8
  709. package/scripts/run/ship/run-ship-infra-retry.ts +59 -0
  710. package/scripts/run/ship/run-ship-next.ts +18 -2
  711. package/scripts/run/ship/run-ship-overlap.ts +42 -5
  712. package/scripts/run/ship/run-ship-place.ts +96 -0
  713. package/scripts/run/ship/run-ship-pre-detach-timed.ts +43 -0
  714. package/scripts/run/ship/run-ship-pre-detach.ts +81 -24
  715. package/scripts/run/ship/run-ship-preflight.ts +137 -32
  716. package/scripts/run/ship/run-ship-probe.ts +11 -3
  717. package/scripts/run/ship/run-ship-relaunch-cap.ts +70 -0
  718. package/scripts/run/ship/run-ship-removed-rows.ts +61 -0
  719. package/scripts/run/ship/run-ship-return.ts +107 -23
  720. package/scripts/run/ship/run-ship-review-steps.ts +105 -151
  721. package/scripts/run/ship/run-ship-review.ts +73 -6
  722. package/scripts/run/ship/run-ship-reviewer.ts +207 -0
  723. package/scripts/run/ship/run-ship-stage.ts +55 -6
  724. package/scripts/run/ship/run-ship-steps.ts +46 -15
  725. package/scripts/run/ship/run-ship-stop-cause.ts +135 -0
  726. package/scripts/run/ship/run-ship-stop-text.ts +11 -6
  727. package/scripts/run/ship/run-ship-sync.ts +43 -6
  728. package/scripts/run/ship/run-ship.ts +30 -2
  729. package/scripts/run/tidy/run-tidy-cli.ts +0 -4
  730. package/scripts/run/tidy/run-tidy-lanes.ts +3 -0
  731. package/scripts/run/tidy/run-tidy-main.ts +8 -0
  732. package/scripts/run/wake/run-wake-cli.ts +119 -100
  733. package/scripts/run/wake/run-wake-code.ts +83 -0
  734. package/scripts/run/wake/run-wake-driver.ts +19 -8
  735. package/scripts/run/wake/run-wake-loop.ts +34 -3
  736. package/scripts/run/wake/run-wake-main.ts +13 -0
  737. package/scripts/run/wake/run-wake-ports.ts +90 -0
  738. package/scripts/run/wake/run-wake-takeover.ts +66 -0
  739. package/scripts/run/wake/run-wake.ts +2 -1
  740. package/scripts/safe-chain/pack-hook.ts +2 -2
  741. package/scripts/safe-chain/preinstall-command.ts +2 -1
  742. package/scripts/safe-chain/project-config.ts +3 -9
  743. package/scripts/security/security-audit-main.ts +8 -0
  744. package/scripts/security/security-audit-provision-logic.ts +0 -11
  745. package/scripts/security/security-audit-provision-main.ts +12 -0
  746. package/scripts/security/security-audit-provision.ts +11 -26
  747. package/scripts/security/security-audit.ts +6 -7
  748. package/scripts/self-sync-guard/self-sync-guard-logic.ts +6 -13
  749. package/scripts/split/split-assess-cli.ts +2 -2
  750. package/scripts/split/split-assess.ts +15 -0
  751. package/scripts/split/split-measure.ts +65 -0
  752. package/scripts/sync/claude-settings-merge.ts +8 -15
  753. package/scripts/sync/directory-copy-guard.ts +4 -9
  754. package/scripts/sync/file-content.ts +78 -8
  755. package/scripts/sync/sync-ai-files.ts +3 -5
  756. package/scripts/sync/sync-configs.ts +11 -23
  757. package/scripts/sync/sync-hook-safety.ts +4 -10
  758. package/scripts/sync/sync-main.ts +11 -0
  759. package/scripts/sync/sync.ts +25 -37
  760. package/scripts/test/test-declared-changed.ts +2 -2
  761. package/scripts/test/test-declared.ts +1 -1
  762. package/scripts/test/test-e2e-guard.ts +25 -1
  763. package/scripts/test/test-e2e-stamp.ts +38 -0
  764. package/scripts/test/test-pinned-logic.ts +145 -0
  765. package/scripts/test/test-pinned-main.ts +78 -0
  766. package/scripts/test/test-pinned.ts +100 -0
  767. package/scripts/test/test-read-map.ts +264 -0
  768. package/scripts/test/test-read-recording.ts +91 -0
  769. package/scripts/test/test-read-trace.ts +148 -0
  770. package/scripts/test/test-red-main.ts +12 -0
  771. package/scripts/test/test-red.ts +12 -30
  772. package/scripts/test/test-related-main.ts +18 -0
  773. package/scripts/test/test-related-record.ts +119 -0
  774. package/scripts/test/test-related-scope.ts +229 -43
  775. package/scripts/test/test-related.ts +300 -22
  776. package/scripts/test/test-unit-guard-main.ts +15 -0
  777. package/scripts/test/test-unit-guard.ts +42 -24
  778. package/scripts/test/unit-count-file.ts +37 -0
  779. package/scripts/test/unit-run-marker.ts +162 -0
  780. package/scripts/test/unit-setup-files.ts +51 -0
  781. package/scripts/test/unit-worker-share.ts +61 -149
  782. package/scripts/test/whole-suite-files.ts +63 -0
  783. package/scripts/time-runtime/time-background.ts +20 -2
  784. package/scripts/time-runtime/time-bundles.ts +4 -3
  785. package/scripts/time-runtime/time-density-hook.ts +8 -6
  786. package/scripts/time-runtime/time-followup-stage.ts +1 -3
  787. package/scripts/time-runtime/time-format.ts +5 -28
  788. package/scripts/time-runtime/time-markers.ts +10 -1
  789. package/scripts/time-runtime/time-shell.ts +97 -10
  790. package/scripts/time-runtime/time-transcript-line.ts +49 -62
  791. package/scripts/uninstall/uninstall.ts +1 -1
  792. package/scripts/version/bump-version-main.ts +12 -0
  793. package/scripts/version/bump-version.ts +25 -25
  794. package/scripts/version/effective-upstream.ts +6 -12
  795. package/scripts/version/latest-corepack.ts +17 -32
  796. package/scripts/version/latest-if-required-cli.ts +93 -0
  797. package/scripts/version/latest-lane-guard-main.ts +8 -0
  798. package/scripts/version/latest-lane-guard.ts +0 -4
  799. package/scripts/version/latest-scope-cli.ts +0 -9
  800. package/scripts/version/latest-scope-main.ts +12 -0
  801. package/scripts/version/latest-update.ts +5 -5
  802. package/scripts/version/npm-registry.ts +44 -6
  803. package/scripts/version/publishable-range-check.ts +5 -16
  804. package/scripts/version/release-age.ts +1 -1
  805. package/scripts/version/release-hold.ts +1 -1
  806. package/scripts/version/release-window.ts +38 -0
  807. package/scripts/version/running-binary.ts +1 -1
  808. package/scripts/version/safe-chain-version-update.ts +3 -8
  809. package/scripts/version/version-targets.ts +6 -28
  810. package/templates/dependabot.yml +29 -0
  811. package/templates/gitignore +4 -1
  812. package/templates/pnpm-workspace.basic.yaml +1 -1
  813. package/templates/sonar-project.properties +3 -2
  814. package/templates/workflows/ci.yml +12 -4
  815. package/templates/workflows/github-release.yml +4 -0
  816. package/tsconfig.sonar.json +1 -1
  817. package/.ncurc.json +0 -3
  818. package/dist/hooks/batch-guard.js +0 -29
  819. package/dist/hooks/chunk-4KKD2UTK.js +0 -66
  820. package/dist/hooks/chunk-6TS2JD6D.js +0 -237
  821. package/dist/hooks/chunk-7DSBJVFH.js +0 -50
  822. package/dist/hooks/chunk-A65Y4YOR.js +0 -79
  823. package/dist/hooks/chunk-CDY4NFQG.js +0 -15
  824. package/dist/hooks/chunk-EFXE6C37.js +0 -81
  825. package/dist/hooks/chunk-GP4IEC4O.js +0 -20
  826. package/dist/hooks/chunk-JP45SOCJ.js +0 -56
  827. package/dist/hooks/chunk-LAOV7NLM.js +0 -45
  828. package/dist/hooks/chunk-M4HGZV7U.js +0 -83
  829. package/dist/hooks/chunk-PF2NZL2A.js +0 -131
  830. package/dist/hooks/chunk-PTICX4OL.js +0 -358
  831. package/dist/hooks/chunk-RT27QRJW.js +0 -6247
  832. package/dist/hooks/chunk-SYOTDYCI.js +0 -3533
  833. package/dist/hooks/chunk-UPUZF3AN.js +0 -279
  834. package/dist/hooks/chunk-WK6SMBIC.js +0 -3180
  835. package/dist/hooks/duplicate-read-guard.js +0 -30
  836. package/dist/hooks/investigation-guard.js +0 -29
  837. package/scripts/backlog/backlog-stalled-cli.ts +0 -30
  838. package/scripts/cost-runtime/cost-format.ts +0 -29
  839. package/scripts/init/basic-path-migration.ts +0 -24
  840. package/scripts/issue/issue-backlinks-cli.ts +0 -93
  841. package/scripts/josh/josh-commands-guard.ts +0 -38
  842. package/scripts/josh/josh-usage-automation.ts +0 -121
  843. package/scripts/josh/josh-usage-backlog.ts +0 -180
  844. package/scripts/josh/josh-usage-developer.ts +0 -230
  845. package/scripts/josh/josh-usage-hooks.ts +0 -38
  846. package/scripts/josh/josh-usage-issue.ts +0 -205
  847. package/scripts/josh/josh-usage-review.ts +0 -101
  848. package/scripts/josh/josh-usage-run.ts +0 -252
  849. package/scripts/josh/josh-usage-session.ts +0 -238
  850. package/scripts/josh/josh-usage-workflow.ts +0 -212
  851. package/scripts/lint/cross-file-recheck.ts +0 -155
  852. package/scripts/registry-migration/migrate-logic.ts +0 -237
  853. package/scripts/registry-migration/migrate.ts +0 -292
  854. package/scripts/registry-migration/user-npmrc.ts +0 -15
  855. package/scripts/rules/rule-guard.ts +0 -23
  856. package/scripts/rules/rule-registry-rows.ts +0 -292
  857. package/scripts/rules/rule-registry.ts +0 -112
  858. package/scripts/run/run-stranded-cli.ts +0 -27
@@ -0,0 +1,94 @@
1
+ import { project_checks } from '#scripts/gate/project-checks'
2
+ import { changed_paths } from '#scripts/git/changed-paths'
3
+ import { session_cite } from '#scripts/issue/session-cite'
4
+ import { observation_ledger_home } from '#scripts/observations/observation-ledger-home'
5
+ import { review_finding_ledger } from './review-finding-ledger'
6
+
7
+ // The interaction review — one adversarial pass after `/code-review`, over a change to the run
8
+ // tooling (joshuafolkken/kit#4276).
9
+ //
10
+ // **`/code-review` reads the diff for its own correctness, and the defects came from elsewhere**: most
11
+ // of them were a new mechanism meeting an existing one — a pause meeting the next run, a count meeting
12
+ // the per-second repaint. This pass is given one role, to find the existing features the change
13
+ // breaks, and is due only where those meetings happen: the four directories below, in the kit
14
+ // repository alone — a consumer's own `scripts/run/` is not kit's run tooling.
15
+ //
16
+ // **Its round is its own ledger line, `- ri:`**, so the merge gate tells it apart from `/code-review`'s
17
+ // and `josh followup` refuses a due change that has none. The verdicts mirror `review_record.check`'s:
18
+ // `not-required` covers both a change outside the directories and a checkout that keeps no ledger.
19
+
20
+ const TARGET_DIRECTORIES = ['scripts/run/', 'scripts/lane/', 'scripts/backlog/', 'scripts/hooks/']
21
+
22
+ const NOT_DUE_LINE =
23
+ 'Interaction review not due: this is not the kit repository, or the change touches none of scripts/run/, scripts/lane/, scripts/backlog/ or scripts/hooks/.'
24
+
25
+ const ROLE_LINES = [
26
+ '## Interaction review',
27
+ 'This pass is not a second `/code-review`: do not hunt for bugs inside the diff — the round before it did. Your role is to find three existing features this change breaks. Check only these three:',
28
+ '1. Every state, command, label, file or process this change adds or gives a new meaning to — who else reads or writes it? Search the repository outside the diff for each. Where the plan has a `### 影響を受ける既存の利用者` section, check it names them all.',
29
+ '2. Does each of those readers and writers still behave correctly when the new state or value reaches it (for example, a paused lane counted as running)?',
30
+ '3. Does the change add heavy or synchronous work to a path called repeatedly — every second, every Bash call, every edit?',
31
+ "Report each break with the reader's `file:line` and the change's, rated by the rubric's severities; it is disposed of by `prompts/review.md` → \"Interaction review\".",
32
+ ]
33
+
34
+ type InteractionStatus = 'ok' | 'missing' | 'not-required'
35
+
36
+ function due_paths(
37
+ paths: ReadonlyArray<string>,
38
+ checkout: string = process.cwd(),
39
+ ): ReadonlyArray<string> {
40
+ if (!project_checks.is_kit_repository(checkout)) return []
41
+
42
+ return paths.filter((file) => TARGET_DIRECTORIES.some((directory) => file.startsWith(directory)))
43
+ }
44
+
45
+ function brief_block(targets: ReadonlyArray<string>): string {
46
+ const listed = targets.map((file) => `- ${file}`)
47
+
48
+ return [...ROLE_LINES, 'Changed in the run tooling:', ...listed].join('\n')
49
+ }
50
+
51
+ async function status_of(
52
+ issue: number,
53
+ paths: ReadonlyArray<string>,
54
+ root: string = observation_ledger_home.ledger_root(),
55
+ ): Promise<InteractionStatus> {
56
+ const content = due_paths(paths).length > 0 ? await observation_ledger_home.read(root) : undefined
57
+
58
+ if (content === undefined) return 'not-required'
59
+
60
+ return review_finding_ledger.has_issue_record(content, issue, 'interaction') ? 'ok' : 'missing'
61
+ }
62
+
63
+ // The status over this checkout's change — the reading `review:brief` takes.
64
+ async function status(issue: number, root?: string): Promise<InteractionStatus> {
65
+ return await status_of(issue, await changed_paths.read_changed_paths(false), root)
66
+ }
67
+
68
+ const MISSING_REASON =
69
+ '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
+
71
+ const REMEDY =
72
+ 'Run it from `pnpm josh review:brief --interaction`, then record it with `pnpm josh review:record --interaction --issue <N> [<category>:<severity>:<file> ...]` — a clean pass is a call with no findings — and reissue the merge.'
73
+
74
+ function refusal_message(issue: number): string {
75
+ return [MISSING_REASON, `Issue: ${session_cite.issue(issue)}`, REMEDY].join('\n')
76
+ }
77
+
78
+ // The merge gate's half: the refusal for a due change with no recorded pass, else `undefined`.
79
+ async function refusal(issue: number, root?: string): Promise<string | undefined> {
80
+ return (await status(issue, root)) === 'missing' ? refusal_message(issue) : undefined
81
+ }
82
+
83
+ const review_interaction = {
84
+ brief_block,
85
+ due_paths,
86
+ NOT_DUE_LINE,
87
+ refusal,
88
+ refusal_message,
89
+ status,
90
+ status_of,
91
+ }
92
+
93
+ export type { InteractionStatus }
94
+ export { review_interaction }
@@ -0,0 +1,163 @@
1
+ // The exported names a diff edits, read from one file's `git diff -U0` and its new text
2
+ // (joshuafolkken/kit#4515). Pure: `review-untouched-readers.ts` reads the diff and searches each name.
3
+ //
4
+ // **A name is edited when a changed line falls inside its top-level declaration** — from the
5
+ // declaration's first line to the line before the next one. Only a name another module can reach is
6
+ // returned, spelled the way a reader writes it: a direct export as itself, a member of an exported
7
+ // namespace object (`export { issue_merged }`) as `issue_merged.read_merged`. The namespace object
8
+ // itself is skipped — a member added to it changes none of its readers.
9
+
10
+ const HUNK_HEADER = /^@@ -\d+(?:,\d+)? \+(?<start>\d+)(?:,(?<count>\d+))? @@/u
11
+ const DECLARATION =
12
+ /^(?:export\s+)?(?:async\s+)?(?:function\*?|const|let|class|type|interface|enum)\s+(?<name>\w+)/u
13
+ const EXPORT_LIST = /^export\s+(?:type\s+)?\{(?<names>[^}]*)\}/gmu
14
+ const IDENTIFIER = /^(?:type\s+)?(?<name>\w+)/u
15
+ const DIRECT_EXPORT = /^export\s/u
16
+ const LIST_SEPARATOR = ','
17
+ // A blank line or a comment line — `//`, `/*`, or a block comment's ` *` continuation.
18
+ const PREAMBLE = /^(?:\s*$|\s*\/[/*]|\s+\*)/u
19
+ // From a 1-based line number to the index of the line above it.
20
+ const TWO = 2
21
+
22
+ interface Declaration {
23
+ name: string
24
+ line: number
25
+ is_exported: boolean
26
+ }
27
+
28
+ interface Edited {
29
+ // The spelling a reader uses — `name` or `namespace.member`.
30
+ target: string
31
+ line: number
32
+ }
33
+
34
+ function to_range(start: number, count: number): Array<number> {
35
+ return Array.from({ length: count }, (_unused, offset) => start + offset)
36
+ }
37
+
38
+ // A pure deletion (`+c,0`) is placed on the line before it, which still lies inside the declaration
39
+ // it was cut from.
40
+ function hunk_lines(header: string): Array<number> {
41
+ const groups = HUNK_HEADER.exec(header)?.groups
42
+
43
+ if (groups === undefined) return []
44
+
45
+ const start = Number(groups['start'])
46
+ const count = groups['count'] === undefined ? 1 : Number(groups['count'])
47
+
48
+ return count === 0 ? [start] : to_range(start, count)
49
+ }
50
+
51
+ function changed_lines(diff: string): Array<number> {
52
+ return diff.split('\n').flatMap((line) => hunk_lines(line))
53
+ }
54
+
55
+ function to_declaration(text: string, index: number): Declaration | undefined {
56
+ const name = DECLARATION.exec(text)?.groups?.['name']
57
+
58
+ if (name === undefined) return undefined
59
+
60
+ return { name, line: index + 1, is_exported: DIRECT_EXPORT.test(text) }
61
+ }
62
+
63
+ function declarations(source: string): Array<Declaration> {
64
+ const found = source.split('\n').map((text, index) => to_declaration(text, index))
65
+
66
+ return found.filter((entry): entry is Declaration => entry !== undefined)
67
+ }
68
+
69
+ function first_identifier(entry: string): string | undefined {
70
+ return IDENTIFIER.exec(entry.trim())?.groups?.['name']
71
+ }
72
+
73
+ function list_names(list: string): Array<string> {
74
+ const names = list.split(LIST_SEPARATOR).map((entry) => first_identifier(entry))
75
+
76
+ return names.filter((name): name is string => name !== undefined)
77
+ }
78
+
79
+ function exported_names(source: string): Set<string> {
80
+ const lists = [...source.matchAll(EXPORT_LIST)].map((match) => match.groups?.['names'] ?? '')
81
+
82
+ return new Set(lists.flatMap((list) => list_names(list)))
83
+ }
84
+
85
+ // The members of `const <name> = { … }`, or `undefined` where `name` is not an object literal. `name`
86
+ // is a `\w+` match, so it carries no pattern syntax.
87
+ function namespace_members(source: string, name: string): Array<string> | undefined {
88
+ const literal = new RegExp(String.raw`^const\s+${name}\s*=\s*\{(?<body>[^}]*)\}`, 'mu')
89
+ const body = literal.exec(source)?.groups?.['body']
90
+
91
+ return body === undefined ? undefined : list_names(body)
92
+ }
93
+
94
+ function namespaces(source: string, exported: ReadonlySet<string>): Map<string, Array<string>> {
95
+ const entries = [...exported].map((name) => [name, namespace_members(source, name)] as const)
96
+
97
+ return new Map(
98
+ entries.filter((entry): entry is [string, Array<string>] => entry[1] !== undefined),
99
+ )
100
+ }
101
+
102
+ // The line after a declaration's own text: the next declaration's line, moved back past the blank and
103
+ // comment lines that introduce it — a comment edited above `b` edits `b`, not the `a` before it.
104
+ function range_end(texts: ReadonlyArray<string>, next: number | undefined): number {
105
+ if (next === undefined) return Infinity
106
+
107
+ let end = next
108
+
109
+ while (end > 1 && PREAMBLE.test(texts[end - TWO] ?? '')) end -= 1
110
+
111
+ return end
112
+ }
113
+
114
+ function touched(source: string, lines: ReadonlySet<number>): Array<Declaration> {
115
+ const found = declarations(source)
116
+ const texts = source.split('\n')
117
+
118
+ return found.filter((declaration, index) => {
119
+ const end = range_end(texts, found[index + 1]?.line)
120
+
121
+ return [...lines].some((line) => line >= declaration.line && line < end)
122
+ })
123
+ }
124
+
125
+ function namespace_of(
126
+ name: string,
127
+ spaces: ReadonlyMap<string, ReadonlyArray<string>>,
128
+ ): string | undefined {
129
+ return [...spaces].find(([, members]) => members.includes(name))?.[0]
130
+ }
131
+
132
+ interface ExportView {
133
+ exported: ReadonlySet<string>
134
+ spaces: ReadonlyMap<string, ReadonlyArray<string>>
135
+ }
136
+
137
+ function target_of(declaration: Declaration, view: ExportView): string | undefined {
138
+ const { name } = declaration
139
+
140
+ if (view.spaces.has(name)) return undefined
141
+ if (declaration.is_exported || view.exported.has(name)) return name
142
+
143
+ const space = namespace_of(name, view.spaces)
144
+
145
+ return space === undefined ? undefined : `${space}.${name}`
146
+ }
147
+
148
+ function edited(source: string, diff: string): Array<Edited> {
149
+ const exported = exported_names(source)
150
+ const view = { exported, spaces: namespaces(source, exported) }
151
+ const edited_declarations = touched(source, new Set(changed_lines(diff)))
152
+ const found_targets = edited_declarations.map((declaration) => ({
153
+ target: target_of(declaration, view),
154
+ line: declaration.line,
155
+ }))
156
+
157
+ return found_targets.filter((entry): entry is Edited => entry.target !== undefined)
158
+ }
159
+
160
+ const review_readers_scan = { changed_lines, edited }
161
+
162
+ export type { Edited }
163
+ export { review_readers_scan }
@@ -1,11 +1,10 @@
1
- #!/usr/bin/env tsx
2
- import { fileURLToPath } from 'node:url'
3
1
  import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
4
2
  import { issue_number_shape } from '#scripts/issue/issue-number-shape'
5
3
  import { cli_flags } from '#scripts/lib/cli-flags'
6
4
  import { observation_ledger_home } from '#scripts/observations/observation-ledger-home'
7
5
  import { review_comment_round } from './review-comment-round'
8
- import { review_finding_ledger, type Finding } from './review-finding-ledger'
6
+ import { review_finding_ledger, type Finding, type LineKind } from './review-finding-ledger'
7
+ import { review_interaction } from './review-interaction'
9
8
  import { review_record, type RecordVerdict } from './review-record'
10
9
 
11
10
  // `josh review:record --issue <N> [<category>:<severity>:<file> ...]` — the one write path for a
@@ -23,16 +22,21 @@ import { review_record, type RecordVerdict } from './review-record'
23
22
  // `josh review:record --check --issue <N>` is the read half `pnpm josh followup` runs before it
24
23
  // merges: `ok` / `not-required` exit zero, `missing` exits non-zero so the
25
24
  // merge is refused until the round is recorded. It mirrors `josh review:attest --check`.
25
+ //
26
+ // **`--interaction` records and checks the interaction review's pass instead** (`review-interaction.ts`):
27
+ // the same grammar under `- ri:`. It takes no `--comment` — the pass runs before the pull request, and
28
+ // a pass kept only on the issue would leave the merge gate reading it as missing.
26
29
 
27
- const ARGV_OFFSET = 2
28
30
  const FAILURE_EXIT_CODE = 1
29
31
  const USAGE =
30
- 'Usage: josh review:record --issue <N> [--comment] [<category>:<severity>:<file> ...] | josh review:record --check --issue <N>'
32
+ 'Usage: josh review:record --issue <N> [--comment | --interaction] [<category>:<severity>:<file> ...] | josh review:record --check [--interaction] --issue <N>'
31
33
  const FILE_HINT = ' <file>: the cited path, optionally with :line'
32
- const CHECK_USAGE = 'Usage: josh review:record --check --issue <N>'
34
+ const CHECK_USAGE = 'Usage: josh review:record --check [--interaction] --issue <N>'
33
35
  const RECORDED_LINE = 'Recorded: the review round for this issue is in the ledger.'
34
36
  const NOT_REQUIRED_LINE =
35
37
  'No review-finding ledger is kept in this checkout, so there is nothing to check.'
38
+ const INTERACTION_NOT_REQUIRED_LINE =
39
+ 'No interaction review is due: the change touches no run tooling, or this checkout keeps no ledger.'
36
40
  const CARRIED_LINE =
37
41
  'review-finding line(s) recorded on closed issues after their pull requests opened into the ledger.'
38
42
  const CARRY_FAILED_LINE =
@@ -41,6 +45,7 @@ const OPTIONS = {
41
45
  issue: { type: 'string' },
42
46
  check: { type: 'boolean' },
43
47
  comment: { type: 'boolean' },
48
+ interaction: { type: 'boolean' },
44
49
  } as const
45
50
 
46
51
  interface Request {
@@ -51,6 +56,7 @@ interface Request {
51
56
  interface Parsed {
52
57
  check: boolean
53
58
  comment: boolean
59
+ interaction: boolean
54
60
  issue: string | undefined
55
61
  positionals: ReadonlyArray<string>
56
62
  }
@@ -99,6 +105,7 @@ function parse_argv(argv: ReadonlyArray<string>): Parsed | undefined {
99
105
  return {
100
106
  check: parsed.values.check === true,
101
107
  comment: parsed.values.comment === true,
108
+ interaction: parsed.values.interaction === true,
102
109
  issue: parsed.values.issue,
103
110
  positionals: parsed.positionals,
104
111
  }
@@ -129,13 +136,17 @@ function usage_text(): string {
129
136
  ].join('\n')
130
137
  }
131
138
 
132
- function build_lines(request: Request, date: string): ReadonlyArray<string> {
139
+ function build_lines(
140
+ request: Request,
141
+ date: string,
142
+ kind: LineKind = 'code',
143
+ ): ReadonlyArray<string> {
133
144
  if (request.findings.length === 0) {
134
- return [review_finding_ledger.zero_round_line(date, request.issue)]
145
+ return [review_finding_ledger.zero_round_line(date, request.issue, kind)]
135
146
  }
136
147
 
137
148
  return request.findings.map((finding) =>
138
- review_finding_ledger.finding_line(finding, date, request.issue),
149
+ review_finding_ledger.finding_line(finding, date, request.issue, kind),
139
150
  )
140
151
  }
141
152
 
@@ -143,28 +154,62 @@ function confirmation(count: number, ledger_path: string): string {
143
154
  return `Recorded ${String(count)} review-finding line(s) in ${ledger_path}.`
144
155
  }
145
156
 
146
- function check_line(verdict: RecordVerdict): string {
147
- return verdict.status === 'ok' ? RECORDED_LINE : NOT_REQUIRED_LINE
157
+ type CheckStatus = RecordVerdict['status']
158
+
159
+ interface CheckMode {
160
+ status: (issue: number, root: string) => Promise<CheckStatus>
161
+ refusal: (issue: number) => string
162
+ not_required: string
148
163
  }
149
164
 
150
- async function run_check(issue: string | undefined, root: string): Promise<number> {
151
- if (issue === undefined || !issue_number_shape.ISSUE_NUMBER_PATTERN.test(issue)) {
152
- console.error(CHECK_USAGE)
165
+ async function code_status(issue: number, root: string): Promise<CheckStatus> {
166
+ const verdict = await review_record.check(issue, root)
167
+
168
+ return verdict.status
169
+ }
170
+
171
+ // The two rounds a check reads, each with its own ledger line, refusal and quiet answer.
172
+ const CHECK_MODES: Record<LineKind, CheckMode> = {
173
+ code: {
174
+ status: code_status,
175
+ refusal: review_record.refusal_message,
176
+ not_required: NOT_REQUIRED_LINE,
177
+ },
178
+ interaction: {
179
+ status: review_interaction.status,
180
+ refusal: review_interaction.refusal_message,
181
+ not_required: INTERACTION_NOT_REQUIRED_LINE,
182
+ },
183
+ }
184
+
185
+ function kind_of(parsed: Parsed): LineKind {
186
+ return parsed.interaction ? 'interaction' : 'code'
187
+ }
188
+
189
+ async function report_check(issue: number, mode: CheckMode, root: string): Promise<number> {
190
+ const status = await mode.status(issue, root)
191
+
192
+ if (status === 'missing') {
193
+ console.error(mode.refusal(issue))
153
194
 
154
195
  return FAILURE_EXIT_CODE
155
196
  }
156
197
 
157
- const verdict = await review_record.check(Number(issue), root)
198
+ console.info(status === 'ok' ? RECORDED_LINE : mode.not_required)
158
199
 
159
- if (verdict.status === 'ok' || verdict.status === 'not-required') {
160
- console.info(check_line(verdict))
200
+ return 0
201
+ }
161
202
 
162
- return 0
163
- }
203
+ async function run_check(parsed: Parsed, root: string): Promise<number> {
204
+ const { issue } = parsed
205
+
206
+ if (issue === undefined || !issue_number_shape.ISSUE_NUMBER_PATTERN.test(issue)) {
207
+ console.error(CHECK_USAGE)
164
208
 
165
- console.error(review_record.refusal_message(Number(issue)))
209
+ return FAILURE_EXIT_CODE
210
+ }
166
211
 
167
- return FAILURE_EXIT_CODE
212
+ return await report_check(Number(issue), CHECK_MODES[kind_of(parsed)], root)
168
213
  }
169
214
 
170
215
  // **A comment that could not be posted fails the record**: it is the round's only copy, so a
@@ -216,7 +261,7 @@ async function append_round(
216
261
  }
217
262
 
218
263
  async function run_record(parsed: Parsed, now: Date, root: string): Promise<number> {
219
- const request = to_request(parsed)
264
+ const request = parsed.comment && parsed.interaction ? undefined : to_request(parsed)
220
265
 
221
266
  if (request === undefined) {
222
267
  console.error(usage_text())
@@ -224,7 +269,7 @@ async function run_record(parsed: Parsed, now: Date, root: string): Promise<numb
224
269
  return FAILURE_EXIT_CODE
225
270
  }
226
271
 
227
- const lines = build_lines(request, observation_ledger_home.ledger_date(now))
272
+ const lines = build_lines(request, observation_ledger_home.ledger_date(now), kind_of(parsed))
228
273
 
229
274
  if (parsed.comment) return await post_comment(request.issue, lines)
230
275
 
@@ -247,15 +292,11 @@ async function run(
247
292
  return FAILURE_EXIT_CODE
248
293
  }
249
294
 
250
- if (parsed.check) return await run_check(parsed.issue, root)
295
+ if (parsed.check) return await run_check(parsed, root)
251
296
 
252
297
  return await run_record(parsed, now, root)
253
298
  }
254
299
 
255
- async function main(argv: ReadonlyArray<string>): Promise<void> {
256
- process.exitCode = await run(argv, new Date())
257
- }
258
-
259
300
  const review_record_cli = {
260
301
  accepted_values,
261
302
  build_lines,
@@ -264,6 +305,4 @@ const review_record_cli = {
264
305
  usage_text,
265
306
  }
266
307
 
267
- if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
268
-
269
308
  export { review_record_cli }
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env tsx
2
+ import { fileURLToPath } from 'node:url'
3
+ import { review_record_cli } from './review-record-cli'
4
+
5
+ // The `josh review:record` entry, kept apart from `review-record-cli.ts` because `run-ship-review.ts`
6
+ // imports that one: a bundle is one file, so a main guard there would fire for every command that
7
+ // carries it (joshuafolkken/kit#4186).
8
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
9
+ const ARGV_OFFSET = 2
10
+
11
+ process.exitCode = await review_record_cli.run(process.argv.slice(ARGV_OFFSET), new Date())
12
+ }
@@ -0,0 +1,221 @@
1
+ import { existsSync } from 'node:fs'
2
+ import path from 'node:path'
3
+ import { git_spawn_sync } from '#scripts/git/git-spawn-sync'
4
+ import { review_tree } from './review-tree'
5
+
6
+ // Round 1's files as git blobs, so round 2 can still name the fix delta after the change base moved
7
+ // (joshuafolkken/kit#4165).
8
+ //
9
+ // **A lane merges the default branch between the rounds**, which moves the base, and the round-1 file
10
+ // map then covers a different set of paths from the one read now. Its digests cannot be carried onto
11
+ // the new base; blobs can. `capture` writes each round-1 path into the object store — nothing else:
12
+ // no index, no commit, no ref. `carried_delta` then carries each path three ways — the old base, round
13
+ // 1, the new base — and names the paths whose carried content differs from the working tree now. A
14
+ // path the default branch alone changed carries to exactly what the merge left, so it drops out; what
15
+ // is left is round 1's fixes.
16
+ //
17
+ // **Every failure answers `undefined`**, which round 2 reads as the moved-base refusal it gave before:
18
+ // no recorded blobs, a carry that conflicts, or a git that cannot run one of the reads.
19
+
20
+ // A path the working tree or a commit does not hold.
21
+ const ABSENT = review_tree.ABSENT_DIGEST
22
+ const SUCCESS_EXIT_CODE = 0
23
+ const NUL = '\0'
24
+ const NEWLINE = '\n'
25
+ const TAB = '\t'
26
+ const SPACE = ' '
27
+ const OID_FIELD = 2
28
+ const WRITE_FLAGS: ReadonlyArray<string> = ['-w']
29
+ const READ_FLAGS: ReadonlyArray<string> = []
30
+
31
+ interface Move {
32
+ // The base round 1 was read against, and the base now.
33
+ from: string | undefined
34
+ to: string | undefined
35
+ // The paths to read: for a carry, those changed against the base now.
36
+ paths: ReadonlyArray<string>
37
+ }
38
+
39
+ interface CarryInput extends Move {
40
+ // Round 1's blobs, from the snapshot.
41
+ blobs: Record<string, string> | undefined
42
+ }
43
+
44
+ interface Carry {
45
+ blobs: Record<string, string>
46
+ from: string
47
+ to: string
48
+ paths: ReadonlyArray<string>
49
+ }
50
+
51
+ interface Readings {
52
+ blobs: Record<string, string>
53
+ before: Record<string, string>
54
+ after: Record<string, string>
55
+ now: Record<string, string>
56
+ }
57
+
58
+ interface Sides {
59
+ base: string
60
+ round_one: string
61
+ moved: string
62
+ }
63
+
64
+ // git's paths are root-relative, so every command runs from the root rather than the caller's cwd.
65
+ function repository_root(): string | undefined {
66
+ return git_spawn_sync.read(['rev-parse', '--show-toplevel'])
67
+ }
68
+
69
+ function hash_paths(
70
+ root: string,
71
+ paths: ReadonlyArray<string>,
72
+ flags: ReadonlyArray<string>,
73
+ ): Record<string, string> | undefined {
74
+ const present = paths.filter((relative) => existsSync(path.join(root, relative)))
75
+ const output =
76
+ present.length === 0
77
+ ? ''
78
+ : git_spawn_sync.read(['hash-object', ...flags, '--', ...present], { cwd: root })
79
+
80
+ if (output === undefined) return undefined
81
+
82
+ const hashes = output.split(NEWLINE)
83
+ const hashed = new Map(present.map((relative, index) => [relative, hashes[index] ?? ABSENT]))
84
+
85
+ return Object.fromEntries(paths.map((relative) => [relative, hashed.get(relative) ?? ABSENT]))
86
+ }
87
+
88
+ // `<mode> <type> <oid>\t<path>`.
89
+ function parse_entry(entry: string): [string, string] {
90
+ const tab = entry.indexOf(TAB)
91
+
92
+ return [entry.slice(tab + 1), entry.slice(0, tab).split(SPACE)[OID_FIELD] ?? ABSENT]
93
+ }
94
+
95
+ function blobs_at(
96
+ commit: string,
97
+ paths: ReadonlyArray<string>,
98
+ root: string,
99
+ ): Record<string, string> | undefined {
100
+ const result = git_spawn_sync.run(['ls-tree', '-r', '-z', commit, '--', ...paths], { cwd: root })
101
+
102
+ if (result.exit_code !== SUCCESS_EXIT_CODE) return undefined
103
+
104
+ return Object.fromEntries(
105
+ result.stdout
106
+ .split(NUL)
107
+ .filter((entry) => entry !== '')
108
+ .map((entry) => parse_entry(entry)),
109
+ )
110
+ }
111
+
112
+ // `git merge-file` exits with the number of conflicts, so only a clean merge answers an oid.
113
+ function merged_blob({ base, round_one, moved }: Sides, root: string): string | undefined {
114
+ if ([base, round_one, moved].includes(ABSENT)) return undefined
115
+
116
+ return git_spawn_sync.read(['merge-file', '--object-id', round_one, base, moved], { cwd: root })
117
+ }
118
+
119
+ function carried_blob(sides: Sides, root: string): string | undefined {
120
+ if (sides.round_one === sides.base) return sides.moved
121
+ if (sides.moved === sides.base || sides.moved === sides.round_one) return sides.round_one
122
+
123
+ return merged_blob(sides, root)
124
+ }
125
+
126
+ // A path round 1 did not list was unchanged against its base, so round 1 held the base's blob.
127
+ function sides_of(relative: string, readings: Readings): Sides {
128
+ const base = readings.before[relative] ?? ABSENT
129
+
130
+ return {
131
+ base,
132
+ round_one: readings.blobs[relative] ?? base,
133
+ moved: readings.after[relative] ?? ABSENT,
134
+ }
135
+ }
136
+
137
+ function differing(
138
+ paths: ReadonlyArray<string>,
139
+ readings: Readings,
140
+ root: string,
141
+ ): ReadonlyArray<string> | undefined {
142
+ const carried = paths.map((relative) => carried_blob(sides_of(relative, readings), root))
143
+
144
+ if (carried.includes(undefined)) return undefined
145
+
146
+ return paths.filter((relative, index) => carried[index] !== readings.now[relative])
147
+ }
148
+
149
+ function read_readings(
150
+ input: Carry,
151
+ paths: ReadonlyArray<string>,
152
+ root: string,
153
+ ): Readings | undefined {
154
+ const before = blobs_at(input.from, paths, root)
155
+ const after = blobs_at(input.to, paths, root)
156
+ const now = hash_paths(root, paths, READ_FLAGS)
157
+
158
+ if (before === undefined || after === undefined || now === undefined) return undefined
159
+
160
+ return { blobs: input.blobs, before, after, now }
161
+ }
162
+
163
+ // No paths at all is an empty delta: `ls-tree` given none would list the whole tree.
164
+ function delta_of(input: Carry, root: string): ReadonlyArray<string> | undefined {
165
+ const paths = [...new Set([...Object.keys(input.blobs), ...input.paths])].toSorted(
166
+ (left, right) => left.localeCompare(right),
167
+ )
168
+ const readings = paths.length === 0 ? undefined : read_readings(input, paths, root)
169
+
170
+ if (paths.length === 0) return []
171
+
172
+ return readings === undefined ? undefined : differing(paths, readings, root)
173
+ }
174
+
175
+ function carried_delta(input: CarryInput): ReadonlyArray<string> | undefined {
176
+ const { blobs, from, to } = input
177
+ const root = repository_root()
178
+
179
+ if (root === undefined || blobs === undefined || from === undefined || to === undefined) {
180
+ return undefined
181
+ }
182
+
183
+ return delta_of({ blobs, from, to, paths: input.paths }, root)
184
+ }
185
+
186
+ function unmoved_between(
187
+ from: string,
188
+ to: string,
189
+ paths: ReadonlyArray<string>,
190
+ root: string,
191
+ ): ReadonlyArray<string> | undefined {
192
+ if (from === to || paths.length === 0) return paths
193
+ const before = blobs_at(from, paths, root)
194
+ const after = blobs_at(to, paths, root)
195
+
196
+ if (before === undefined || after === undefined) return undefined
197
+
198
+ return paths.filter((relative) => (before[relative] ?? ABSENT) === (after[relative] ?? ABSENT))
199
+ }
200
+
201
+ // The paths the base move left alone: there the carry reproduces round 1's file, so the fix delta on
202
+ // them is round 1 against the working tree, as on an unmoved base. `undefined` when git cannot say.
203
+ function unmoved({ from, to, paths }: Move): ReadonlyArray<string> | undefined {
204
+ const root = repository_root()
205
+
206
+ if (root === undefined || from === undefined || to === undefined) return undefined
207
+
208
+ return unmoved_between(from, to, paths, root)
209
+ }
210
+
211
+ // Each path's blob, written into the object store so a later carry can merge it; `undefined` when git
212
+ // cannot answer, which the record then omits.
213
+ function capture(paths: ReadonlyArray<string>): Record<string, string> | undefined {
214
+ const root = repository_root()
215
+
216
+ return root === undefined ? undefined : hash_paths(root, paths, WRITE_FLAGS)
217
+ }
218
+
219
+ const review_round_one_blobs = { capture, carried_delta, unmoved }
220
+
221
+ export { review_round_one_blobs }