@joshuafolkken/kit 1.1455.0 → 1.1514.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 (374) hide show
  1. package/.claude/settings.json +6 -6
  2. package/.claude/skills/dependency-update/SKILL.md +26 -55
  3. package/.claude/skills/epic-commands/SKILL.md +83 -156
  4. package/.claude/skills/epic-commands/epic-bundle.md +51 -79
  5. package/.claude/skills/epic-commands/execution-waves.md +43 -81
  6. package/.claude/skills/verify-ui/SKILL.md +24 -50
  7. package/.claude/skills/workflow-commands/SKILL.md +7 -9
  8. package/.claude/skills/workflow-commands/background-commands.md +31 -46
  9. package/.claude/skills/workflow-commands/backlogrun-child.md +65 -85
  10. package/.claude/skills/workflow-commands/backlogrun-lanes.md +86 -125
  11. package/.claude/skills/workflow-commands/backlogrun-park.md +68 -118
  12. package/.claude/skills/workflow-commands/backlogrun-progress.md +17 -28
  13. package/.claude/skills/workflow-commands/backlogrun-recovery.md +17 -26
  14. package/.claude/skills/workflow-commands/backlogrun-steps.md +35 -52
  15. package/.claude/skills/workflow-commands/backlogrun.md +31 -50
  16. package/.claude/skills/workflow-commands/chain-rule.md +31 -40
  17. package/.claude/skills/workflow-commands/delegation.md +12 -8
  18. package/.claude/skills/workflow-commands/entry-sequence.md +1 -3
  19. package/.claude/skills/workflow-commands/followup.md +55 -77
  20. package/.claude/skills/workflow-commands/fullrun-steps.md +3 -5
  21. package/.claude/skills/workflow-commands/fullrun.md +4 -6
  22. package/.claude/skills/workflow-commands/halfrun.md +3 -7
  23. package/.claude/skills/workflow-commands/into-target.md +1 -2
  24. package/.claude/skills/workflow-commands/issue-comments.md +43 -60
  25. package/.claude/skills/workflow-commands/issue-scout.md +3 -2
  26. package/.claude/skills/workflow-commands/kickoff.md +65 -74
  27. package/.claude/skills/workflow-commands/latest-gate.md +2 -6
  28. package/.claude/skills/workflow-commands/needs-human-review.md +2 -5
  29. package/.claude/skills/workflow-commands/observation-filing.md +59 -118
  30. package/.claude/skills/workflow-commands/observation-ledger.md +52 -112
  31. package/.claude/skills/workflow-commands/pre-gate-cut.md +88 -142
  32. package/.claude/skills/workflow-commands/prerequisite.md +11 -17
  33. package/.claude/skills/workflow-commands/progress-watcher.md +23 -33
  34. package/.claude/skills/workflow-commands/prrun.md +3 -5
  35. package/.claude/skills/workflow-commands/retrospective.md +35 -54
  36. package/.claude/skills/workflow-commands/split-assessment.md +32 -58
  37. package/.claude/skills/workflow-commands/target-repository.md +1 -2
  38. package/.claude/skills/workflow-commands/working-tree-hold.md +54 -73
  39. package/.codex/hooks.json +6 -6
  40. package/.github/actions/setup-node/action.yml +1 -1
  41. package/.github/workflows/ci.yml +1 -1
  42. package/.github/workflows/publish.yml +2 -2
  43. package/CLAUDE.md +7 -6
  44. package/cspell/index.yaml +7 -0
  45. package/dist/CLAUDE.md +7 -6
  46. package/dist/commands/document-section-cli.js +67 -34
  47. package/dist/hooks/batch-guard.js +6 -6
  48. package/dist/hooks/chunk-4KKD2UTK.js +66 -0
  49. package/dist/hooks/{chunk-GPLGZ6IC.js → chunk-6TS2JD6D.js} +14 -3
  50. package/dist/hooks/chunk-7DSBJVFH.js +50 -0
  51. package/dist/hooks/{chunk-5H4SSDSD.js → chunk-A65Y4YOR.js} +3 -3
  52. package/dist/hooks/{chunk-3C4XRYG6.js → chunk-APUO6U4J.js} +102 -19
  53. package/dist/hooks/{chunk-IX6TTTI6.js → chunk-EFXE6C37.js} +8 -22
  54. package/dist/hooks/chunk-GP4IEC4O.js +20 -0
  55. package/dist/hooks/chunk-JP45SOCJ.js +56 -0
  56. package/dist/hooks/{chunk-OLMO72ON.js → chunk-LAOV7NLM.js} +1 -1
  57. package/dist/hooks/chunk-M4HGZV7U.js +83 -0
  58. package/dist/hooks/{chunk-TBJFTSUY.js → chunk-O6GDRNJB.js} +9 -7
  59. package/dist/hooks/{chunk-HFGWYGUV.js → chunk-PF2NZL2A.js} +5 -5
  60. package/dist/hooks/{chunk-WNLVGT7E.js → chunk-PTICX4OL.js} +4 -5
  61. package/dist/hooks/{chunk-HHI6FO3R.js → chunk-RT27QRJW.js} +763 -1515
  62. package/dist/hooks/{chunk-7WQBPLUN.js → chunk-SYOTDYCI.js} +1149 -1095
  63. package/dist/hooks/{chunk-LIAFCXL7.js → chunk-TNUMY6NL.js} +1519 -1332
  64. package/dist/hooks/chunk-UPUZF3AN.js +279 -0
  65. package/dist/hooks/{chunk-Z4XI7CZS.js → chunk-WK6SMBIC.js} +1932 -784
  66. package/dist/hooks/codex-hook-adapter.js +17 -14
  67. package/dist/hooks/duplicate-read-guard.js +7 -7
  68. package/dist/hooks/format-edited.js +5 -4
  69. package/dist/hooks/inputs.json +302 -247
  70. package/dist/hooks/investigation-guard.js +8 -11
  71. package/dist/hooks/pretool-guard.js +16 -13
  72. package/dist/hooks/session-lang.js +372 -26
  73. package/dist/hooks/stop-guard.js +2593 -189
  74. package/dist/josh.js +2128 -282
  75. package/dist/managed-marker/index.js +1 -2
  76. package/dist/version/index.js +15 -12
  77. package/eslint/base.js +2 -1
  78. package/eslint/rules/unicorn.js +16 -0
  79. package/lefthook/base.yml +5 -3
  80. package/package.json +14 -12
  81. package/prompts/coding-standards.md +12 -22
  82. package/prompts/collaboration-workflow/file-edits.md +25 -45
  83. package/prompts/collaboration-workflow/gh-rest.md +19 -36
  84. package/prompts/collaboration-workflow/glossary.md +5 -7
  85. package/prompts/collaboration-workflow/issue-citation.md +6 -14
  86. package/prompts/collaboration-workflow/issue-template.md +40 -32
  87. package/prompts/collaboration-workflow/lane-instructions.md +35 -0
  88. package/prompts/collaboration-workflow/operating-rules.md +33 -46
  89. package/prompts/collaboration-workflow/output-bounds.md +15 -15
  90. package/prompts/collaboration-workflow/overview.md +14 -19
  91. package/prompts/collaboration-workflow/plan-comment.md +13 -13
  92. package/prompts/collaboration-workflow/principles.md +57 -54
  93. package/prompts/collaboration-workflow/proposal-request.md +1 -9
  94. package/prompts/collaboration-workflow/report-format.md +41 -49
  95. package/prompts/collaboration-workflow/residency.md +15 -11
  96. package/prompts/collaboration-workflow/rule-delivery.md +7 -15
  97. package/prompts/collaboration-workflow/shell-body.md +10 -20
  98. package/prompts/collaboration-workflow/turn-batching.md +8 -14
  99. package/prompts/collaboration-workflow/upstream-interrupt.md +26 -34
  100. package/prompts/collaboration-workflow/wip-cap.md +26 -32
  101. package/prompts/collaboration-workflow.md +25 -25
  102. package/prompts/refactoring.md +33 -43
  103. package/prompts/review-rubric.md +84 -129
  104. package/prompts/review.md +110 -141
  105. package/prompts/sonar-hotspot-handling.md +22 -50
  106. package/prompts/testing-guide.md +48 -99
  107. package/scripts/adopt/adopt-toolkits.ts +2 -4
  108. package/scripts/agent/agent-argv.ts +20 -4
  109. package/scripts/agent/agent-exit-record.ts +23 -1
  110. package/scripts/agent/agent-role-profile.ts +101 -45
  111. package/scripts/agent/agent-safe-text.ts +60 -0
  112. package/scripts/agent/claude-agent-argv.ts +14 -0
  113. package/scripts/agent/codex-agent-argv.ts +9 -2
  114. package/scripts/agent/lane-instructions.ts +144 -0
  115. package/scripts/backlog/backlog-budget-cli.ts +1 -2
  116. package/scripts/backlog/backlog-budget.ts +4 -4
  117. package/scripts/backlog/backlog-drive-carried.ts +26 -0
  118. package/scripts/backlog/backlog-drive-cli.ts +10 -5
  119. package/scripts/backlog/backlog-drive-named.ts +3 -5
  120. package/scripts/backlog/backlog-drive-restore.ts +28 -2
  121. package/scripts/backlog/backlog-drive-seats.ts +27 -0
  122. package/scripts/backlog/backlog-drive.ts +11 -6
  123. package/scripts/backlog/backlog-occupied.ts +56 -0
  124. package/scripts/backlog/backlog-ready.ts +59 -15
  125. package/scripts/behavior/behavior-rules.ts +3 -2
  126. package/scripts/cost-runtime/codex-usage.ts +4 -2
  127. package/scripts/cost-runtime/cost-cli.ts +1 -2
  128. package/scripts/delegation/duplicate-read-guard.ts +2 -2
  129. package/scripts/delegation/investigation-guard.ts +15 -65
  130. package/scripts/delegation/investigation-reads.ts +1 -2
  131. package/scripts/discovery/repo-discovery.ts +4 -2
  132. package/scripts/discovery/repo-origin.ts +2 -4
  133. package/scripts/doctor/doctor-logic.ts +6 -3
  134. package/scripts/document/document-byte-budget.ts +28 -27
  135. package/scripts/document/document-byte-check.ts +1 -2
  136. package/scripts/document/document-section-cli.ts +17 -5
  137. package/scripts/document/entry-read-budget.ts +3 -3
  138. package/scripts/document/read-set-cli.ts +4 -1
  139. package/scripts/epic/epic-audit-orphans.ts +5 -8
  140. package/scripts/epic/epic-audit-rationale.ts +8 -2
  141. package/scripts/epic/epic-audit.ts +52 -1
  142. package/scripts/epic/epic-bundle-cli.ts +1 -2
  143. package/scripts/epic/epic-bundle-evidence.ts +49 -26
  144. package/scripts/epic/epic-bundle-referenced.ts +14 -3
  145. package/scripts/epic/epic-bundle.ts +17 -9
  146. package/scripts/epic/epic-chains.ts +6 -2
  147. package/scripts/epic/epic-close-comment.ts +1 -2
  148. package/scripts/followup/git-followup-workflow.ts +19 -1
  149. package/scripts/gate/check-inputs.ts +129 -0
  150. package/scripts/gate/check-reuse.ts +162 -0
  151. package/scripts/gate/core-budget.ts +93 -44
  152. package/scripts/gate/core-wait.ts +130 -0
  153. package/scripts/gate/free-cores.ts +49 -0
  154. package/scripts/gate/gate-ledger.ts +17 -3
  155. package/scripts/gate/gate-plan.ts +23 -1
  156. package/scripts/gate/gate-report.ts +15 -2
  157. package/scripts/gate/gate-run-steps.ts +150 -0
  158. package/scripts/gate/held-mark.ts +55 -0
  159. package/scripts/gate/machine-capacity.ts +70 -11
  160. package/scripts/gate/pre-commit-type-check.ts +14 -1
  161. package/scripts/gate/verification-gate.ts +65 -127
  162. package/scripts/gh/git-gh-issue-rest.ts +1 -0
  163. package/scripts/gh/git-gh-issue-write.ts +24 -2
  164. package/scripts/gh/git-pr.ts +19 -3
  165. package/scripts/git/git-common-directory.ts +3 -3
  166. package/scripts/git/git-diff-reads.ts +16 -9
  167. package/scripts/git/git-execa-error.ts +1 -2
  168. package/scripts/git/main-merge-regenerate.ts +78 -0
  169. package/scripts/git/main-merge.ts +14 -5
  170. package/scripts/hooks/batch-guard.ts +5 -8
  171. package/scripts/hooks/format-edited-file.ts +10 -4
  172. package/scripts/hooks/pre-commit-lint.ts +91 -0
  173. package/scripts/hooks/pre-push-unit.ts +15 -4
  174. package/scripts/hooks/pretool-guard.ts +48 -79
  175. package/scripts/hooks/reserved-run.ts +1 -0
  176. package/scripts/hooks/run-hook.sh +10 -12
  177. package/scripts/hooks/step-zero-notice.ts +3 -2
  178. package/scripts/hooks/stop-actions.ts +204 -0
  179. package/scripts/hooks/stop-guard.ts +62 -21
  180. package/scripts/init/hook-command-rewrite.ts +6 -2
  181. package/scripts/init/hook-launch.ts +12 -7
  182. package/scripts/init/init-logic-deploy-vps.ts +4 -2
  183. package/scripts/issue/behavior-change-lint.ts +12 -6
  184. package/scripts/issue/expected-effect-lint.ts +59 -0
  185. package/scripts/issue/issue-cite-cli.ts +35 -15
  186. package/scripts/issue/issue-classification.ts +1 -1
  187. package/scripts/issue/issue-lint-cli.ts +5 -3
  188. package/scripts/issue/issue-scout-cli.ts +22 -16
  189. package/scripts/issue/markdown-section.ts +19 -5
  190. package/scripts/josh/command-usage.ts +110 -0
  191. package/scripts/josh/file-map-stamp.ts +1 -3
  192. package/scripts/josh/hook-decision.ts +17 -2
  193. package/scripts/josh/josh-command-map.ts +2 -0
  194. package/scripts/josh/josh-command-types.ts +55 -9
  195. package/scripts/josh/josh-commands-ai.ts +13 -0
  196. package/scripts/josh/josh-commands-development.ts +1 -1
  197. package/scripts/josh/josh-commands-hooks.ts +6 -0
  198. package/scripts/josh/josh-commands-lane.ts +10 -1
  199. package/scripts/josh/josh-commands-workflow.ts +5 -0
  200. package/scripts/josh/josh-logic.ts +6 -15
  201. package/scripts/josh/josh-usage-automation.ts +121 -0
  202. package/scripts/josh/josh-usage-backlog.ts +180 -0
  203. package/scripts/josh/josh-usage-developer.ts +230 -0
  204. package/scripts/josh/josh-usage-hooks.ts +38 -0
  205. package/scripts/josh/josh-usage-issue.ts +205 -0
  206. package/scripts/josh/josh-usage-review.ts +101 -0
  207. package/scripts/josh/josh-usage-run.ts +252 -0
  208. package/scripts/josh/josh-usage-session.ts +238 -0
  209. package/scripts/josh/josh-usage-workflow.ts +212 -0
  210. package/scripts/josh/josh.ts +14 -5
  211. package/scripts/josh/package-directory.ts +20 -0
  212. package/scripts/lane/lane-await.ts +3 -2
  213. package/scripts/lane/lane-capacity.ts +8 -2
  214. package/scripts/lane/lane-check-stats.ts +56 -0
  215. package/scripts/lane/lane-child-invocation.ts +49 -5
  216. package/scripts/lane/lane-dispatch.ts +3 -3
  217. package/scripts/lane/lane-guard-policy.ts +5 -5
  218. package/scripts/lane/lane-handoff.ts +8 -1
  219. package/scripts/lane/lane-install.ts +12 -4
  220. package/scripts/lane/lane-ledger.ts +52 -1
  221. package/scripts/lane/lane-limit-cli.ts +8 -9
  222. package/scripts/lane/lane-load.ts +9 -2
  223. package/scripts/lane/lane-measure-cli.ts +4 -0
  224. package/scripts/lane/lane-parked.ts +18 -0
  225. package/scripts/lane/lane-preserve.ts +29 -1
  226. package/scripts/lane/lane-process-load.ts +125 -0
  227. package/scripts/lane/lane-process-stats.ts +93 -0
  228. package/scripts/lane/lane-registry.ts +17 -10
  229. package/scripts/lane/lane-restart.ts +5 -26
  230. package/scripts/lane/lane-session-action.ts +146 -0
  231. package/scripts/lane/lane-session-broker.ts +68 -125
  232. package/scripts/lane/lane-spent.ts +14 -3
  233. package/scripts/lane/lane-stats.ts +1 -0
  234. package/scripts/lane/lane-withdraw-cli.ts +71 -0
  235. package/scripts/lane/lane-withdraw.ts +182 -0
  236. package/scripts/lint/format.ts +4 -4
  237. package/scripts/lint/lint-parallel.ts +10 -3
  238. package/scripts/lint/lint-related-scope.ts +4 -1
  239. package/scripts/managed-marker/managed-marker-logic.ts +1 -2
  240. package/scripts/notify/telegram-test.ts +10 -5
  241. package/scripts/overrides/lockfile-overrides.ts +1 -3
  242. package/scripts/propagate/propagate.ts +1 -2
  243. package/scripts/release/release-progress.ts +3 -2
  244. package/scripts/report/report-format-reference.ts +2 -0
  245. package/scripts/report/report-lint.ts +7 -4
  246. package/scripts/review/acceptance-map-check.ts +61 -0
  247. package/scripts/review/acceptance-map.ts +205 -0
  248. package/scripts/review/review-brief-cli.ts +1 -1
  249. package/scripts/review/review-record-cli.ts +6 -2
  250. package/scripts/rules/agent-model.ts +59 -0
  251. package/scripts/rules/delivered-rules.ts +11 -2
  252. package/scripts/rules/destructive-command.ts +6 -9
  253. package/scripts/rules/direct-filing.ts +3 -7
  254. package/scripts/rules/early-heartbeat.ts +7 -18
  255. package/scripts/rules/file-body.ts +6 -13
  256. package/scripts/rules/filing-cap.ts +4 -6
  257. package/scripts/rules/firing-point.ts +6 -5
  258. package/scripts/rules/git-force.ts +5 -9
  259. package/scripts/rules/guard-remedy.ts +117 -0
  260. package/scripts/rules/implementation-cut.ts +37 -35
  261. package/scripts/rules/index-guard.ts +4 -7
  262. package/scripts/rules/issue-comments.ts +67 -16
  263. package/scripts/rules/josh-git-bare.ts +3 -6
  264. package/scripts/rules/lane-background.ts +10 -21
  265. package/scripts/rules/lane-carry-conflict.ts +7 -17
  266. package/scripts/rules/lane-interactive-ask.ts +6 -11
  267. package/scripts/rules/lane-park.ts +5 -13
  268. package/scripts/rules/lane-split-park.ts +2 -7
  269. package/scripts/rules/lane-switch-main.ts +9 -12
  270. package/scripts/rules/last-prompt.ts +50 -5
  271. package/scripts/rules/oracle-consulted.ts +4 -5
  272. package/scripts/rules/oracle-list-cli.ts +7 -0
  273. package/scripts/rules/piped-verification.ts +84 -32
  274. package/scripts/rules/poll-loop.ts +7 -17
  275. package/scripts/rules/pre-gate-cut.ts +7 -21
  276. package/scripts/rules/prior-comment-read.ts +7 -5
  277. package/scripts/rules/protected-files.ts +5 -9
  278. package/scripts/rules/raw-field-body.ts +3 -7
  279. package/scripts/rules/rule-body-guard.ts +4 -11
  280. package/scripts/rules/rule-list.ts +4 -1
  281. package/scripts/rules/rule-registry-rows.ts +10 -0
  282. package/scripts/rules/rule-registry.ts +7 -4
  283. package/scripts/rules/rule-rewrite.ts +114 -0
  284. package/scripts/rules/rule-value.ts +7 -1
  285. package/scripts/rules/run-tail-rule.ts +6 -22
  286. package/scripts/rules/shell-body-trigger.ts +4 -6
  287. package/scripts/rules/shell-segments.ts +22 -0
  288. package/scripts/rules/stop-decision.ts +77 -0
  289. package/scripts/rules/stop-rules.ts +164 -77
  290. package/scripts/rules/tail-commands.ts +15 -1
  291. package/scripts/rules/test-declared-commit.ts +4 -10
  292. package/scripts/rules/third-party-write.ts +5 -10
  293. package/scripts/rules/worktree-guard.ts +5 -12
  294. package/scripts/run/board/run-board-cli.ts +2 -0
  295. package/scripts/run/board/run-board-closed.ts +8 -2
  296. package/scripts/run/board/run-board-github.ts +19 -3
  297. package/scripts/run/board/run-board-header.ts +4 -1
  298. package/scripts/run/board/run-board-idle.ts +31 -0
  299. package/scripts/run/board/run-board-labels.ts +2 -0
  300. package/scripts/run/board/run-board-layout.ts +1 -1
  301. package/scripts/run/board/run-board-read.ts +25 -12
  302. package/scripts/run/board/run-board-reason.ts +17 -4
  303. package/scripts/run/board/run-board-render-legend.ts +1 -0
  304. package/scripts/run/board/run-board-render-slot.ts +1 -1
  305. package/scripts/run/board/run-board-render-waits.ts +41 -0
  306. package/scripts/run/board/run-board-render.ts +6 -1
  307. package/scripts/run/board/run-board-row-yield.ts +1 -0
  308. package/scripts/run/board/run-board-state.ts +9 -0
  309. package/scripts/run/board/run-board-status.ts +89 -23
  310. package/scripts/run/board/run-board-thanks.ts +7 -2
  311. package/scripts/run/board/run-board-tick.ts +37 -8
  312. package/scripts/run/carry/run-carry-args.ts +1 -3
  313. package/scripts/run/carry/run-carry-conversation.ts +7 -2
  314. package/scripts/run/cut/run-cut-cli.ts +18 -22
  315. package/scripts/run/cut/run-cut-decline.ts +72 -0
  316. package/scripts/run/cut/run-cut-ready.ts +74 -0
  317. package/scripts/run/cut/run-cut-report.ts +29 -0
  318. package/scripts/run/cut/run-cut.ts +10 -1
  319. package/scripts/run/detached-launch.ts +23 -4
  320. package/scripts/run/entry/run-entry-cli.ts +8 -1
  321. package/scripts/run/event/run-event-render.ts +1 -0
  322. package/scripts/run/event/run-event-scope.ts +19 -1
  323. package/scripts/run/event/run-event-stream-emit.ts +13 -6
  324. package/scripts/run/event/run-event-stream.ts +4 -0
  325. package/scripts/run/hold/run-hold-cli.ts +14 -3
  326. package/scripts/run/hold/run-hold-session.ts +46 -0
  327. package/scripts/run/hold/run-hold.ts +13 -4
  328. package/scripts/run/launch-priority.ts +32 -0
  329. package/scripts/run/merge/run-merge-cli.ts +16 -42
  330. package/scripts/run/merge/run-merge-ship.ts +59 -1
  331. package/scripts/run/merge/run-merge-signals.ts +99 -0
  332. package/scripts/run/merge/run-merge-steps.ts +11 -1
  333. package/scripts/run/merge/run-merge.ts +22 -9
  334. package/scripts/run/run-ending.ts +31 -3
  335. package/scripts/run/run-liveness.ts +1 -1
  336. package/scripts/run/run-parent-cut-hook.ts +5 -10
  337. package/scripts/run/run-poll-hook.ts +157 -0
  338. package/scripts/run/run-preflight.ts +1 -2
  339. package/scripts/run/run-step-cli.ts +22 -15
  340. package/scripts/run/run-step-section.ts +85 -0
  341. package/scripts/run/run-stop-notify.ts +1 -2
  342. package/scripts/run/run-watcher-guard.ts +6 -3
  343. package/scripts/run/ship/run-ship-cli.ts +5 -12
  344. package/scripts/run/ship/run-ship-detach.ts +9 -0
  345. package/scripts/run/ship/run-ship-next.ts +10 -2
  346. package/scripts/run/ship/run-ship-overlap.ts +195 -0
  347. package/scripts/run/ship/run-ship-pre-detach.ts +33 -15
  348. package/scripts/run/ship/run-ship-preflight.ts +28 -2
  349. package/scripts/run/ship/run-ship-return.ts +31 -7
  350. package/scripts/run/ship/run-ship-review-steps.ts +25 -14
  351. package/scripts/run/ship/run-ship-review.ts +15 -2
  352. package/scripts/run/ship/run-ship-steps.ts +1 -1
  353. package/scripts/run/ship/run-ship-stop-context.ts +206 -0
  354. package/scripts/run/ship/run-ship-sync.ts +14 -6
  355. package/scripts/run/tidy/run-tidy-cli.ts +3 -3
  356. package/scripts/run/tidy/run-tidy-lanes.ts +3 -2
  357. package/scripts/safe-chain/project-config.ts +7 -2
  358. package/scripts/sync/sync-hook-safety.ts +8 -2
  359. package/scripts/test/test-e2e-guard.ts +30 -5
  360. package/scripts/test/test-unit-guard.ts +16 -1
  361. package/scripts/test/unit-worker-share.ts +26 -3
  362. package/scripts/time-runtime/time-batch-guard.ts +3 -3
  363. package/scripts/time-runtime/time-hook-transcript.ts +3 -2
  364. package/scripts/time-runtime/time-shell.ts +39 -4
  365. package/scripts/time-runtime/time-spans.ts +1 -0
  366. package/scripts/time-runtime/time-tool-call.ts +7 -0
  367. package/scripts/version/effective-upstream.ts +3 -4
  368. package/scripts/version/kit-version-config.ts +8 -2
  369. package/scripts/version/latest-corepack.ts +1 -2
  370. package/scripts/version/release-hold.ts +11 -4
  371. package/scripts/version/version-commands.ts +12 -4
  372. package/templates/gitignore +6 -2
  373. package/dist/hooks/chunk-D5QBTOCZ.js +0 -68
  374. package/dist/hooks/chunk-UT7YC3N2.js +0 -56
package/prompts/review.md CHANGED
@@ -1,192 +1,161 @@
1
1
  # Code Review Prompt
2
2
 
3
- This document is the review **policy**: which level a change is reviewed at, how many rounds a review
4
- runs, and what happens to a finding after the cap. Two other documents hold the rest, and this file
5
- points to them rather than restating them:
3
+ Review policy: the level, the round count, and what happens to a finding after the cap. Elsewhere:
6
4
 
7
- - The **rubric** the reviewer applies — the severity tests, the nine categories, the output format and
8
- the stop conditions — is `prompts/review-rubric.md`, handed to `/code-review` by
9
- `pnpm josh review:brief`.
10
- - The **orchestration** around a review — how the gate runs beside it, when the pull request opens, how
11
- the merge is issued — is `.claude/skills/workflow-commands/chain-rule.md` → "Orchestration facts
12
- single-sourced here".
5
+ - Rubric (severity tests, nine categories, output format, stop conditions): `prompts/review-rubric.md`,
6
+ handed to `/code-review` by `pnpm josh review:brief`.
7
+ - Orchestration (gate beside the review, when the PR opens, the merge):
8
+ `.claude/skills/workflow-commands/chain-rule.md` → "Orchestration facts single-sourced here".
13
9
 
14
10
  ---
15
11
 
16
12
  ## When to run
17
13
 
18
- When a review runs is `CLAUDE.md` → "Pre-commit Self-Review"; inside a workflow, round 1 runs before
19
- the commit and round 2 beside CI (`.claude/skills/workflow-commands/chain-rule.md`). Pass the
20
- `reviewer` profile's model and effort that `pnpm josh review:brief` prints to the review subagent;
21
- do not substitute the review level for effort.
14
+ When: `CLAUDE.md` → "Pre-commit Self-Review"; inside a workflow, round 1 runs before the commit and
15
+ round 2 beside CI (`.claude/skills/workflow-commands/chain-rule.md`). Pass the review subagent the
16
+ `reviewer` profile's model and effort that `pnpm josh review:brief` prints; never substitute the review
17
+ level for effort.
22
18
 
23
- Re-run after applying fixes until **no high or medium findings remain — or until the round cap below is
24
- reached, the first review included — whichever comes first.** The cap below is not optional. The second round
25
- is a verification pass over the fixes, not the first review again
19
+ Re-run after fixes until **no high or medium findings remain or the round cap below is reached** (the
20
+ first review counts), whichever comes first. Round 2 is a verification pass over the fixes
26
21
  (`prompts/review-rubric.md` → "The second round is a verification pass, not a second full review").
27
22
 
28
23
  ---
29
24
 
30
25
  ## Before round 1 — the implementer's self-check
31
26
 
32
- **Answer these five over your own diff before the scoped pair that precedes round 1.** A round-1
33
- High/Medium makes round 2 due, and most of them are of a kind the implementer clears more cheaply
34
- than a reviewer finds: in a sample of 135 round-1 High/Medium findings, about two in three fell under one of these questions. Fix what an answer turns up; the review, its
35
- severity tests and the round cap are unchanged.
36
-
37
- 1. **Tests pin the change** — for each condition, branch or call you added or changed, name the test
38
- that turns red when it is deleted or inverted, and check its fixture actually reaches that branch
39
- (no assert on a string the code never draws, no comparison against a literal copy).
40
- 2. **Prose matches the code** — grep the docs, prompts and comments for the old wording of every
41
- behavior, constant, command and heading you changed, moved or removed, `"the table above"` and
42
- rewritten sentences included.
43
- 3. **Failure is not a negative answer** — every timeout, non-zero exit or `gh` failure on a path you
44
- touched returns something a caller can tell apart from `false`, `undefined` or "nothing found".
45
- 4. **Every caller moved with it** — grep every reference to a function, list or command you changed,
46
- and update each sibling path (the other CLI, the registry, the consumer side) in the same change.
27
+ Answer these five over your own diff before the scoped pair that precedes round 1, and fix what an
28
+ answer turns up (about two in three of 135 sampled round-1 High/Medium findings fell under one). The
29
+ review, its severity tests and the round cap are unchanged.
30
+
31
+ 1. **Tests pin the change** — for each condition, branch or call added or changed, name the test that
32
+ turns red when it is deleted or inverted, and check its fixture reaches that branch (no assert on a
33
+ string the code never draws, no comparison against a literal copy).
34
+ 2. **Prose matches the code** — grep docs, prompts and comments for the old wording of every behavior,
35
+ constant, command and heading you changed, moved or removed, `"the table above"` and rewritten
36
+ sentences included.
37
+ 3. **Failure is not a negative answer** — every timeout, non-zero exit or `gh` failure on a touched
38
+ path returns something a caller can tell apart from `false`, `undefined` or "nothing found".
39
+ 4. **Every caller moved with it** — grep every reference to a changed function, list or command, and
40
+ update each sibling path (the other CLI, the registry, the consumer side) in the same change.
47
41
  5. **The Issue is met on HEAD** — the premises you relied on hold on the current tree, and each
48
- acceptance criterion is checked off one by one against the diff.
42
+ acceptance criterion is checked against the diff.
49
43
 
50
44
  ---
51
45
 
52
46
  ## Review level (decided by `pnpm josh review:brief --level-only`, never by judgement)
53
47
 
54
- **Run `pnpm josh review:brief --level-only` and use what it prints** — `low` or `medium`, from the
55
- changed paths and nothing else, never "this one is small". `--staged` classifies the staged diff,
56
- `--json` adds the reason; inside a workflow `pnpm josh review:brief` prints the same level on its first
57
- line. A `low` change gets 1 round, a `medium` one up to 2 (the cap below). How the answer is derived —
58
- the inert paths, documentation at `medium`: `docs/maintainers/review-history.md` → "The level is
59
- decided from the changed paths".
48
+ Run `pnpm josh review:brief --level-only` and use what it prints — `low` or `medium`, from the changed
49
+ paths only, never "this one is small". `--staged` classifies the staged diff, `--json` adds the reason;
50
+ inside a workflow `pnpm josh review:brief` prints the level on its first line. `low` gets 1 round,
51
+ `medium` up to 2. A diff that touches documentation is not inert: it stays at `medium`.
60
52
 
61
53
  ```bash
62
54
  pnpm josh review:brief --level-only # the branch diff
63
55
  pnpm josh review:brief --level-only --staged # the staged diff
64
56
  ```
65
57
 
66
- **A confirmed High blocks regardless of round count**, and the round cap below does not change that.
58
+ **A confirmed High blocks regardless of round count**, whatever the cap.
67
59
 
68
60
  ---
69
61
 
70
62
  ## Review round cap (2 rounds)
71
63
 
72
- The severity rule in the rubric is not a stopping condition on its own: every fix creates new surface a
73
- further round would find something in.
74
-
75
- **Two rounds is the ceiling, not the schedule.** Whether the second one is due at all is
76
- `pnpm josh review:round2`'s answer — "When round 2 is skipped entirely, and when it is not" below is
77
- the single source of that condition.
64
+ Two rounds is the ceiling, not the schedule: every fix creates new surface a further round would find
65
+ something in. Whether round 2 is due is `pnpm josh review:round2`'s answer (below).
78
66
 
79
67
  ### A merge-conflict resolution review is not one of the two
80
68
 
81
- **When `pnpm josh followup` reports `PR checks failed (merge conflict)`, the child resolves the conflict
82
- in its own lane and reviews the resolution — and that round does not count against the cap**. The cap bounds re-reading _the change under review_; a resolution review reads
83
- a different subject — not the change, but what merging a moved `main` into it did.
84
- `.claude/skills/workflow-commands/backlogrun-recovery.md` → "Conflicts are not predicted" is the single source of
85
- the procedure and of the four conditions under which the run steps back instead of resolving.
86
- `pnpm josh review:attest --check` must answer `ok` before the merge is re-issued, and a confirmed High
87
- parks the child rather than buying it a further round.
69
+ When `pnpm josh followup` reports `PR checks failed (merge conflict)`, the child resolves the conflict
70
+ in its own lane and reviews the resolution — **that round does not count against the cap**, since it
71
+ reads what merging a moved `main` did, not the change. Procedure and the four step-back conditions:
72
+ `.claude/skills/workflow-commands/backlogrun-recovery.md` → "Conflicts are not predicted".
73
+ `pnpm josh review:attest --check` must answer `ok` before the merge is re-issued; a confirmed High parks
74
+ the child rather than buying a further round.
88
75
 
89
76
  ### When round 2 is skipped entirely, and when it is not
90
77
 
91
- **Two rounds is the ceiling; whether the second round runs at all is a command's answer, not a reading
92
- of a list**:
93
-
94
78
  ```bash
95
79
  pnpm josh review:round2 --round-1-closed # → required | skip ; the reason on stderr
96
80
  ```
97
81
 
98
- **Ask it once round 1's fixes are in and before the commit.** Pass `--round-1-closed` only where every
99
- round-1 High/Medium finding actually closed — by a fix in this working tree, or as a verified false
100
- positive — and none was filed or deferred. **Without the flag the answer is `required`**, which is also
101
- what the command answers to every uncertainty it meets, a missing round-1 snapshot included.
82
+ Ask once round 1's fixes are in, before the commit. Pass `--round-1-closed` only when every round-1
83
+ High/Medium closed — fixed in this working tree or verified false positive — and none was filed or
84
+ deferred. Without the flag, and on any uncertainty (a missing round-1 snapshot included), the answer is
85
+ `required`.
86
+
87
+ `skip` has exactly two arms, and the reason line names which fired:
88
+
89
+ - **A** — the fix delta is empty.
90
+ - **B** — every path in the fix delta is inert by the review-level classification above:
91
+ `docs/**/*.md`, the root `README.md`, under `prompts/`, or a `.ts` / `.js` / `.svelte` file outside
92
+ `.claude/` changed only in comments (a lint, type-check, coverage or bundler directive comment counts
93
+ as code).
102
94
 
103
- **`skip` has exactly two arms** — **A** (no fix code: the fix delta is empty) and **B** (a fix that
104
- leaves what executes unchanged: every path in the fix delta is inert by the review-level classification
105
- above, `docs/**/*.md`, the root `README.md`, under `prompts/`, or a `.ts` / `.js` / `.svelte` file
106
- outside `.claude/` whose only change is in comments, a directive comment — lint, type-check, coverage
107
- or bundler — counting as code); the reason line names which fired. **One path
108
- outside that set makes the round `required`** — `.claude/**`, `CLAUDE.md`, a test, configuration, a
109
- code line, or a source file whose comment-free text cannot be read. Why neither arm weakens the
110
- standard: `docs/maintainers/review-history.md` → "The two skip arms".
95
+ One path outside that set makes it `required` — `.claude/**`, `CLAUDE.md`, a test, configuration, a
96
+ code line, or a source file whose comment-free text cannot be read.
111
97
 
112
- **A skipped round is recorded on the Issue**, so the condition stays auditable and can be withdrawn if
113
- a defect is later traced to a skipped delta:
98
+ Record a skipped round on the Issue:
114
99
 
115
100
  1. Label the Issue `review-round2-skipped`, created once per repository:
116
101
  `gh api repos/{owner}/{repo}/labels -f name=review-round2-skipped -f color=c5def5 -f description="Review round 2 was skipped under the condition in prompts/review.md" --silent 2>/dev/null || true`,
117
102
  then `gh api repos/{owner}/{repo}/issues/<N>/labels -f 'labels[]=review-round2-skipped'`.
118
- 2. Post an Issue comment under the heading `## Round 2 skipped`, naming **which arm fired** and quoting
119
- **the reason line the command printed**, verbatim.
103
+ 2. Comment under `## Round 2 skipped`, naming which arm fired and quoting the command's reason line
104
+ verbatim.
120
105
 
121
106
  ### Three-way disposition after the cap
122
107
 
123
- **After the second round, place every remaining non-High finding in exactly one of three exits, decided
124
- from what the finding is rather than from the filer's discretion**. **The
125
- default exit is branch 3, and branch 2 has to be earned**. Read them in order — branch 1 where the fix is
126
- trivial and local, branch 2 only where the finding clears the bar it names, branch 3 for everything
127
- left, which is most of them. "It might matter later" is branch 3.
128
-
129
- 1. **Fix it in place.** The finding closes in a few lines inside a file the diff already touches, with
130
- no design judgement — a stale comment, a name, an unused export. **A fix-in-place never starts a new
131
- review round**: the fix widens the diff, so a naive re-review would re-open the loop the cap just
132
- closed. The fix must stay **inside a file the diff already changed** and carry **no design decision**;
133
- a finding that cannot close under both limits is filed, not fixed in place.
134
- 2. **File it as an Issue.** The finding is a **confirmed defect that reaches a runtime code path** —
135
- both halves, and neither on its own. Confirmed means the failure scenario is stated in concrete
136
- inputs and state. **Reaching is read exactly as the rubric's Severity test 1 reads it** — a runtime
137
- code path, a distributed artifact a consumer reads, or the verification that guards either — so in a
138
- repository whose product is its distributed documents, a defect in one of those is a branch-2 finding
139
- like any other. **The reaching half is not a judgement**: `pnpm josh disposition <path>` answers
140
- `runtime` / `non-runtime` from the finding's paths, sharing the same inert set the review level uses,
141
- so only "is the defect confirmed" is left to decide. **"It needs a decision" is no longer a branch-2
142
- condition on its own**: a design question with no defect under it takes branch 3.
143
- 3. **Drop it with a one-line note in the PR body.** **This is the default, and it takes everything the
144
- other two branches did not**: a Low that does not reach the user, and every remaining finding that is
145
- neither closable in place nor a confirmed runtime defect — a design preference or an unproven
146
- suspicion included. **The note is not optional**: one line naming the finding and why it was dropped
147
- is what keeps a dropped finding auditable rather than invisible.
148
-
149
- **Findings that reduce to one root judgement are filed as one Issue, not several** — a single follow-up
150
- Issue with a section per symptom (`## 現象 1` / `## 現象 2`).
151
-
152
- Only branch 2 files an Issue. What follows applies to that branch.
153
-
154
- - **A finding routed to branch 2 is filed as a follow-up Issue referencing the current one, and the
155
- current Issue completes.** (A confirmed High is not a branch-2 finding: it blocks the merge rather
156
- than being deferred — see below.)
157
- - **Filing does not end at the Issue.** `epic:next` only ever offers a child the task list of an epic
158
- names, so an Issue in no epic is never handed to a running `backlogrun` — the deferred finding is parked
159
- forever, which reads the same from the backlog. **The steps run inside the CI wait, not before
160
- the commit.** Where the run opens a pull request — `fullrun`, `backlogrun` — they go after
161
- `pnpm josh git -y` and before `pnpm josh followup`; where it does not — `halfrun`, or a standalone
162
- pre-commit self-review — they run as soon as the disposition is decided. **The chain may run in a
163
- delegated unit** — `pnpm josh delegate followup-filing`.
164
- - **A second follow-up from one round folds into the first by default.** Several findings from one
165
- review fold into one Issue — the filing-time counterpart to the split assessment, reading the same
166
- two questions (`.claude/skills/workflow-commands/split-assessment.md` → "The same two questions
167
- decide the filing-time fold"). `pnpm josh issue:file` asks the fold question itself on the run's
168
- second filing and holds a `fold`; the first filing asks nothing.
169
-
170
- 1. File the follow-up Issue referencing the current one, tagged `route:review-cap` — **before the current Issue closes.**
171
- `pnpm josh issue:file "<title>" --body-file <body-file> --depth <n> --route review-cap`.
172
- The command lints the body, applies the classification labels it declares, runs the duplicate scan
173
- and then `epic:bundle` on the new Issue (`docs/josh-commands-backlog.md` → `josh issue:file`). The
174
- `epic:bundle` candidate search reads open issues only, so once the parent has closed it answers
175
- `none` permanently.
176
- 2. Act on the `epic:bundle` answer it prints. **`epic:bundle` recommends and writes nothing**, so acting means running the
177
- write command yourself — never a hand edit of the epic body, which leaves the task list and the
178
- `blocked-by` relations disagreeing and `epic:next` returning `error`.
179
-
180
- | Answer | Do | Tier |
181
- | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
182
- | `add_to_epic` | `pnpm josh epic --add <E> <new>` — add `--before <M>` / `--after <M>` when the relation carries an order | **A — no confirmation** |
183
- | `create_epic` | `pnpm josh epic "<title>" <new> <other> [--ordered]` | **A — no confirmation** |
184
- | `ask` — candidates spread across two or more epics | **Choose the epic you recommend, run its write command, and record the decision** — what was taken, what was rejected, why — on both the new Issue and that epic's `## Decisions`. This does not stop a run and does not park a child; stop only where the two epics are genuinely too close to separate | **A — no confirmation** |
185
- | `none` | Nothing | — |
186
- | **The command could not answer** — non-zero exit, or **any** ⚠ warning above `Nothing to bundle.` | Stop and report, naming what it said. **A `none` printed after such a warning is not "nothing to bundle"** — the search was incomplete | — |
187
-
188
- - **A confirmed High is never deferred.** A real defect does not ship because a round counter ran out,
189
- so a standing High blocks the merge — never fixed-in-place, filed, or dropped as one of the three
190
- exits. If a High is still standing after the second round, do not start a third: stop, send a
191
- `confirmation` Telegram, and put the scope back to the user, where splitting the Issue is usually the
192
- answer.
108
+ After round 2, place every remaining non-High finding in exactly one exit, decided by what the finding
109
+ is. **The default exit is branch 3, and branch 2 has to be earned**. "It might matter later" is branch 3.
110
+
111
+ 1. **Fix it in place** — it closes in a few lines inside a file the diff already changed, with no
112
+ design decision (a stale comment, a name, an unused export). A fix-in-place never starts a new
113
+ review round. A finding that cannot close under both limits is filed, not fixed in place.
114
+ 2. **File it as an Issue** — a **confirmed defect that reaches a runtime code path** — both halves, and neither on its own.
115
+ Confirmed: the failure scenario is stated in concrete inputs and state.
116
+ **Reaching is read exactly as the rubric's Severity test 1 reads it** (a runtime code path, a
117
+ distributed artifact a consumer reads, or the verification that guards either), so a defect in a
118
+ distributed document is branch 2. `pnpm josh disposition <path>` answers `runtime` / `non-runtime`
119
+ from the finding's paths (the review level's inert set). **"It needs a decision" is no longer a branch-2 condition on its own**:
120
+ a design question with no defect under it takes branch 3.
121
+ 3. **Drop it with a one-line note in the PR body** — **This is the default, and it takes everything the other two branches did not**:
122
+ a Low that does not reach the user, a design preference, an unproven suspicion. **The note is not optional**:
123
+ one line naming the finding and why it was dropped.
124
+
125
+ Findings that reduce to one root judgement are filed as one Issue with a section per symptom
126
+ (`## 現象 1` / `## 現象 2`).
127
+
128
+ Branch 2 only:
129
+
130
+ - File a follow-up Issue whose `parent: #N` line names the current one — a mention in its background
131
+ is not read by `epic:bundle`; the current Issue completes.
132
+ - An Issue in no epic is never offered by `epic:next`, so filing continues to the epic. Run these steps
133
+ inside the CI wait: in `fullrun` / `backlogrun` after `pnpm josh git -y` and before
134
+ `pnpm josh followup`; in `halfrun` or a standalone pre-commit self-review as soon as the disposition
135
+ is decided. They may run delegated — `pnpm josh delegate followup-filing`.
136
+ - A second follow-up from one round folds into the first by default
137
+ (`.claude/skills/workflow-commands/split-assessment.md` → "The same two questions decide the
138
+ filing-time fold"). `pnpm josh issue:file` asks the fold question on the run's second filing and holds
139
+ a `fold`; the first filing asks nothing.
140
+
141
+ 1. Before the current Issue closes, file it tagged `route:review-cap`:
142
+ `pnpm josh issue:file "<title>" --body-file <body-file> --depth <n> --route review-cap`. It lints
143
+ the body, applies the declared labels, runs the duplicate scan and `epic:bundle`
144
+ (`docs/josh-commands-backlog.md` → `josh issue:file`). `epic:bundle` reads open issues only, so
145
+ after the parent closes it answers `none` permanently.
146
+ 2. Act on the printed `epic:bundle` answer by running the write command yourself — `epic:bundle`
147
+ writes nothing, and a hand edit of the epic body leaves the task list and `blocked-by` relations
148
+ disagreeing (`epic:next` returns `error`). Tier A, no confirmation:
149
+ - `add_to_epic` → `pnpm josh epic --add <E> <new>`, with `--before <M>` / `--after <M>` when the
150
+ relation carries an order.
151
+ - `create_epic` → `pnpm josh epic "<title>" <new> <other> [--ordered]`.
152
+ - `ask` (candidates across two or more epics) → run the recommended epic's write command and record
153
+ what was taken, what was rejected and why on the new Issue and that epic's `## Decisions`. Stop
154
+ only where the two epics are genuinely too close to separate.
155
+ - `none` → nothing.
156
+ - Non-zero exit, or any ⚠ warning above `Nothing to bundle.` → stop and report what it said; a
157
+ `none` after such a warning is not "nothing to bundle".
158
+
159
+ **A confirmed High is never deferred** — it blocks the merge, never fixed-in-place, filed or dropped.
160
+ If one still stands after round 2, do not start a third: stop, send a `confirmation` Telegram, and put
161
+ the scope back to the user (usually: split the Issue).
@@ -2,50 +2,26 @@
2
2
 
3
3
  <!-- cspell:words hotspot Hotspot hotspots Hotspots NOSONAR -->
4
4
 
5
- This guide extends the collaboration workflow with a project-local procedure for handling SonarCloud Security Hotspots. It is kept out of the upstream-synced `prompts/collaboration-workflow/` topics so those stay identical across the projects that consume them.
6
-
7
- AI tools cannot perform OAuth browser login to SonarCloud, so this guide assumes public-API and config-based actions as the primary path.
5
+ Project-local procedure for SonarCloud Security Hotspots, kept out of the upstream-synced `prompts/collaboration-workflow/`. AI tools cannot do SonarCloud's OAuth browser login, so the primary path is the public API and config.
8
6
 
9
7
  ## Quality Gate enforcement (CI blocks PRs)
10
8
 
11
- The distributed `.github/workflows/sonar-qube.yml` runs the SonarCloud scan with
12
- `-Dsonar.qualitygate.wait=true`, so the `SonarQube` job — a required PR check — fails when the
13
- Quality Gate is red. **The gate alone is not enough**: `Sonar way` judges ratings and ratios, so a
14
- few MINOR code smells keep the maintainability rating at A and a small copied block stays under the
15
- duplication threshold. On a pull request the job therefore ends with `pnpm josh sonar:new-code <PR>`,
16
- which **fails on a single new issue of any type or severity, or a single new duplicated block**
17
- (joshuafolkken/kit#3045). An issue resolved in SonarCloud as accepted or a false positive is not
18
- counted — that resolution is the route for a deliberate exception. This job is the single enforcement point:
19
- `josh followup` does **not** scan SonarCloud findings (it only scans CodeRabbit / Claude Review
20
- comments), but it **does** wait on the required `SonarQube` CI check, so a red gate also blocks the
21
- `followup` merge. Consumers pick the workflow up verbatim via `josh sync`; do not re-implement the
22
- gate per consumer.
23
-
24
- **A run that cannot see `SONAR_TOKEN` skips the scan and passes**, printing one line that names the
25
- missing token (joshuafolkken/kit#2815) — a consumer that does not use SonarCloud is never blocked by
26
- it. The same holds for any run GitHub withholds secrets from (a fork pull request, or a Dependabot
27
- run without the secret in the Dependabot store), so a repository that relies on this gate keeps
28
- `SONAR_TOKEN` in both secret stores.
9
+ The distributed `.github/workflows/sonar-qube.yml` scans with `-Dsonar.qualitygate.wait=true`, so the required `SonarQube` PR check fails on a red Quality Gate. On a pull request the job then runs `pnpm josh sonar:new-code <PR>`, which **fails on a single new issue of any type or severity, or a single new duplicated block** (joshuafolkken/kit#3045) — `Sonar way` judges ratings and ratios, so a few MINOR smells or a small copied block would otherwise pass. An issue resolved in SonarCloud as accepted or a false positive is not counted; that resolution is the route for a deliberate exception.
10
+
11
+ This job is the single enforcement point: `josh followup` does not scan SonarCloud findings but waits on the required `SonarQube` check, so a red gate blocks its merge too. Consumers get the workflow verbatim via `josh sync`; do not re-implement the gate per consumer.
12
+
13
+ A run that cannot see `SONAR_TOKEN` skips the scan and passes, printing one line naming the missing token (joshuafolkken/kit#2815). GitHub withholds secrets from fork pull requests and from Dependabot runs without the secret in the Dependabot store, so a repository relying on this gate keeps `SONAR_TOKEN` in both secret stores.
29
14
 
30
15
  ### New Code vs Overall Code semantics
31
16
 
32
- The scan passes `package.json`'s `version` as `sonar.projectVersion`, so New Code — "since the
33
- previous version" — restarts at every `josh bump` that reaches main instead of growing from the
34
- first analysis on.
17
+ The scan passes `package.json`'s `version` as `sonar.projectVersion`, so New Code ("since the previous version") restarts at every `josh bump` that reaches main.
35
18
 
36
- SonarCloud's default **Sonar way** Quality Gate evaluates **New Code only** — conditions
37
- (new bugs, new code smells above the Maintainability rating, new coverage/duplication) apply to
38
- lines changed in the PR's New Code period, not the whole codebase. Consequences:
19
+ The default Sonar way gate evaluates New Code only — lines changed in the PR's New Code period:
39
20
 
40
- - A PR is blocked when it **introduces or modifies** code that trips a condition — this is what
41
- catches the recurring Maintainability `0 -> 1` regression that motivated this gate.
42
- - Pre-existing Overall-Code findings on untouched files do **not** fail an unrelated PR. To make
43
- the gate enforce Overall Code as well, add Overall conditions to the gate in the SonarCloud
44
- project settings (Quality Gates UI) — that is a SonarCloud-side configuration, not a repo file.
21
+ - A PR that introduces or modifies code tripping a condition is blocked (e.g. a Maintainability `0 -> 1` regression).
22
+ - Pre-existing Overall-Code findings on untouched files do not fail an unrelated PR. Enforcing Overall Code needs Overall conditions added in the SonarCloud Quality Gates UI, not a repo file.
45
23
 
46
- When triaging a red gate, confirm via the PR analysis whether the failing condition is a **New
47
- Code** condition (caused by this PR — fix it) or an **Overall** condition (pre-existing — handle
48
- per the table below, and do not let it silently block an unrelated change).
24
+ Red gate → check in the PR analysis: a New Code condition is this PR's (fix it); an Overall one is pre-existing (handle per the table below, never silently blocking an unrelated change).
49
25
 
50
26
  ## Step A / Step B: fetch the hotspots and read each one's disposition
51
27
 
@@ -53,11 +29,7 @@ per the table below, and do not let it silently block an unrelated change).
53
29
  pnpm josh sonar:hotspots <PR>
54
30
  ```
55
31
 
56
- The command fetches the hotspots on the pull request from SonarCloud's public API (no auth), reading
57
- the project key from `sonar-project.properties`, and prints per hotspot its `status`, `component`,
58
- `line`, `ruleKey` and the Step B branch it falls into. The one branch key that used to be walked by
59
- eye — "is this path upstream-synced?" — is answered by calling `josh sync:scope`'s own detection, so
60
- no distribution path list is duplicated. The four branches:
32
+ Reads the PR's hotspots from SonarCloud's public API (no auth; project key from `sonar-project.properties`) and prints each one's `status`, `component`, `line`, `ruleKey` and Step B branch; upstream-synced paths come from `josh sync:scope`'s detection.
61
33
 
62
34
  | Branch | Meaning |
63
35
  | ---------- | ---------------------------------------------------------------------------------------------------------- |
@@ -66,15 +38,15 @@ no distribution path list is duplicated. The four branches:
66
38
  | `fix` | A reviewed-and-fixed hotspot — the real issue was fixed |
67
39
  | `defer` | A reviewed hotspot set aside — out of scope for this PR |
68
40
 
69
- A read that failed (rate-limit, network) prints `unreadable: <reason>`, told apart from a success
70
- that found no hotspots. `pnpm josh oracle:list` carries the same vocabulary. **The only judgement
71
- left to you is whether a `TO_REVIEW` hotspot is really a false positive** — if it is, apply its
72
- `excluded` / `local` branch; if it is instead a real issue fix the code and add a regression test,
73
- and if it is out of scope mention it in the completion comment and open a follow-up Issue.
41
+ A failed read (rate-limit, network) prints `unreadable: <reason>`, distinct from finding none. `pnpm josh oracle:list` uses the same vocabulary. **Your only judgement: is a `TO_REVIEW` hotspot really a false positive?**
42
+
43
+ - False positive → apply its `excluded` / `local` branch.
44
+ - Real issue → fix the code and add a regression test.
45
+ - Out of scope → mention it in the completion comment and open a follow-up Issue.
74
46
 
75
47
  ## Step C: optional — mark SAFE via API if a token is available
76
48
 
77
- If `SONAR_TOKEN` is exported (SonarCloud user token with write scope):
49
+ With `SONAR_TOKEN` exported (SonarCloud user token with write scope):
78
50
 
79
51
  ```bash
80
52
  curl -sS -u "$SONAR_TOKEN:" -X POST \
@@ -82,10 +54,10 @@ curl -sS -u "$SONAR_TOKEN:" -X POST \
82
54
  -d "hotspot=<hotspot-key>&status=REVIEWED&resolution=SAFE&comment=<reason>"
83
55
  ```
84
56
 
85
- Without a token, prefer Step B's config-based approach — that change is reviewable in the PR diff, whereas API-side state changes are not.
57
+ Without a token, prefer Step B's config-based approach — it is reviewable in the PR diff; API-side state changes are not.
86
58
 
87
59
  ## Reporting rules
88
60
 
89
- - List every outstanding hotspot in the completion comment (never hide a failing SonarCloud analysis).
90
- - State which action you took (excluded / marked SAFE / fixed / deferred) and why.
91
- - If you deferred, include a link to the follow-up Issue.
61
+ - List every outstanding hotspot in the completion comment; never hide a failing SonarCloud analysis.
62
+ - State the action taken (excluded / marked SAFE / fixed / deferred) and why.
63
+ - Link the follow-up Issue for a deferral.