@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
@@ -1,44 +1,34 @@
1
1
  # `epic:bundle` — the detail behind the answer
2
2
 
3
- **Read this when a filing's `epic:bundle` answer places the issue** — `add_to_epic`, `create_epic`,
4
- or a choice between epics — or when the answer is one the summary in the `epic-commands` skill
5
- (`SKILL.md` → "`josh epic:bundle <N>` — does this new issue belong with one already filed?") does not
6
- settle. `Nothing to bundle.` needs neither.
7
-
8
- **Only two things count as a signal**: the issues referring to each other in prose, or a `blocked-by`
9
- already recorded between them. **A similar title never counts on its own** — "related" expands
10
- without limit, and the threshold is what keeps an unrelated issue out.
11
-
12
- **The release issue is neither a candidate nor a subject**, like an epic. `issue:file --release` records
13
- every change awaiting publication as its blocker, so that relation is mechanical, not a sign of shared
14
- work. Counted as a signal, it would put the release and an unrelated change in one epic. A
15
- `blocked-by` or a prose reference between any other two issues still counts.
16
-
17
- **The search is not limited to the open backlog.** Every issue number the subject's body names is read
18
- on its own, whatever its state. A **closed** reference counts only when an open epic already tracks
19
- it, since the answer worth recovering is `add_to_epic`; an epic created over a closed issue has
20
- nothing left to run. An **open** reference counts either way. A read that fails — and a reference the
21
- per-issue cap never reached — is reported as a gap, never folded into "no strong signal". A number
22
- that answers with a **pull request** is not a candidate at all: `repos/{owner}/{repo}/issues/<N>`
23
- serves one too, and a merged PR does not report `CLOSED`.
24
-
25
- **A number that does not exist is not a gap.** A typo, or another repository's number quoted in
26
- prose, is dropped in silence — neither a candidate nor something the command reports it could not
27
- read. **The two are told apart by HTTP status, never by `gh`'s wording**: 404 is nothing at that
28
- number, 403 and 429 are a rate limit. The referenced-number reads are capped at twenty, and **only
29
- the subject's own body is followed**.
30
-
31
- **`none` is a legitimate answer** — a self-review outside any workflow has no current issue to point
32
- at, so the issue stays in the backlog: what the procedure requires is running the command and
33
- following its answer, not landing every issue in an epic. The review-cap follow-up's filing and the
34
- answer table it acts on are `prompts/review.md` → "Three-way disposition after the cap".
35
-
36
- **Every row that *places* the issue asserts a negative, so a cut epic listing withholds all of them.**
37
- "No epic already tracks this issue" — which `create_epic` asserts about the candidates too — is only
38
- as good as the listing it was read from, and an epic past the cut tracks its children invisibly.
39
- **`add_to_epic` rests on it as much as `create_epic` does**: adding the issue to the epic a
40
- *candidate* sits in, while an unseen epic already tracks the issue itself, is the same duplicate by
41
- another route. The verdict says so itself:
3
+ Read this when a filing's `epic:bundle` answer places the issue (`add_to_epic`, `create_epic`, or a
4
+ choice between epics), or when `SKILL.md` → "`josh epic:bundle <N>` — does this new issue belong with
5
+ one already filed?" does not settle it. `Nothing to bundle.` needs neither.
6
+
7
+ **Only two things count as a signal**: one issue naming the other in its acceptance criteria
8
+ (`## 受け入れ条件` / `## Acceptance criteria`) or its `parent: #N` / `親: #N` line, or a `blocked-by`
9
+ recorded between them. A reference elsewhere, or a similar title, never counts; the evidence line
10
+ names the section.
11
+
12
+ **A placing answer you do not follow** — check it against both issues first; record the reason as an
13
+ `Auto-decided:` line on the issue.
14
+
15
+ **The release issue is neither a candidate nor a subject**, like an epic — its `blocked-by` relations
16
+ are mechanical. Any other `blocked-by` or counted reference still counts.
17
+
18
+ **The search is not limited to the open backlog.** Every number the subject's own body names is read
19
+ (capped at twenty), whatever its state:
20
+
21
+ - A **closed** reference counts only when an open epic already tracks it; an **open** one counts either way.
22
+ - A **pull request** number is not a candidate.
23
+ - A failed read, or a reference past the cap, is reported as a gap — never folded into "no strong signal".
24
+ - **A number that does not exist is not a gap** — dropped in silence. Told apart **by HTTP status,
25
+ never by `gh`'s wording**: 404 is nothing there; 403 and 429 are a rate limit.
26
+
27
+ **`none` is a legitimate answer** — the issue stays in the backlog. The review-cap follow-up's filing:
28
+ `prompts/review.md` → "Three-way disposition after the cap".
29
+
30
+ **A cut epic listing withholds every placing row**, `add_to_epic` as much as `create_epic` — an unseen
31
+ epic may already track the issue. The verdict says so, and the exit code stays `0`:
42
32
 
43
33
  ```text
44
34
  Could not confirm which epic already tracks these — do not place this issue in one.
@@ -46,50 +36,32 @@ Could not confirm which epic already tracks these — do not place this issue in
46
36
  Related: #<N>
47
37
  ```
48
38
 
49
- **The children and the order are deliberately absent** — they are the recipe for the placement that
50
- line says not to make. The exit code stays `0`, as it does for every other "do nothing" answer. **What
51
- survives the cut is a membership that *was* found**: the table's first row names the epic it read
52
- tracking the issue, and epics past the cut cannot unseat it.
53
-
54
- **Placing an issue is not merging epics.** Bundling is reversible — one `epic --add` moves an issue
55
- to a different epic — so choosing between two candidate epics is Tier A: take the one you recommend,
56
- and write the decision (what was taken, what was rejected, why, and the date) on **both** the issue
57
- and the epic's `## Decisions`. **Merging two epics is a different action, and nothing here proposes
58
- it.**
39
+ It prints no children or order. What survives the cut is a membership that *was* found (the table's
40
+ first row).
59
41
 
60
- **An epic and its own parent do not produce the spread verdict at all.** The parent already contains
61
- the child, so the pair is narrowed to the inner epic and the issue is added there. **The narrowing
62
- drops parents, never peers**: one unrelated epic beside a nested chain still asks, and so does a
63
- cyclic declaration, where there is no inner epic to pick. Stop only where the epics left are
64
- genuinely too close to separate, which is the toss-up Tier B is for and is rare.
42
+ **Placing an issue is not merging epics.** Choosing between two candidate epics is Tier A: take the one
43
+ you recommend and write the decision (taken, rejected, why, date) on **both** the issue and the epic's
44
+ `## Decisions`. **Merging two epics is a different action, and nothing here proposes it.**
65
45
 
66
- **The decision record is what pays for the autonomy** — without it the run has taken a decision
67
- nobody can find afterwards.
46
+ **An epic and its own parent do not produce the spread verdict** — the issue goes to the inner epic.
47
+ **The narrowing drops parents, never peers**: an unrelated epic beside a nested chain, or a cyclic
48
+ declaration, still asks. Stop (Tier B) only where the epics left are genuinely too close to separate.
68
49
 
69
50
  **Write both halves in the one call that places the issue: `pnpm josh epic --add <E> <N...>
70
- --decision-file <path|->`.** It appends the record to the epic's `## Decisions` inside the body edit
71
- the insertion already makes, and posts the same text as a comment on each child added. **Never
72
- hand-edit the epic body to add the entry** — that is the operation `--add` exists to remove. Two
73
- constraints on the record's own text, both refused before anything is written:
74
-
75
- - **No line that is *nothing but* a `#A -> #B` chain.** Such a line is read as part of the epic's
76
- declaration wherever it sits in the body, so the record would declare an order nobody decided. Quote
77
- the order inside backticks, or put it in a fenced block; either is accepted.
78
- - **The record must say something, and the path must be readable.** An empty file is refused, and so is
79
- `--decision-file` with no usable path — otherwise the insertion lands, no record is written anywhere,
80
- and the command still exits 0.
81
-
82
- Answers about children the epic already tracks cannot use this flag; `SKILL.md` → "Recording a
83
- decision" says what to do instead.
84
-
85
- **Its sibling runs before the filing, not after it: `pnpm josh issue:scout "<title>"`.** That command
86
- answers the same epic question for an issue that does not exist yet — this decision, called rather
87
- than restated — and beside it the one thing this one deliberately refuses: whether the work has
88
- already been filed, from a title comparison. **Both run**, and neither replaces the other:
89
- `pnpm josh issue:file` runs the scout before it creates the issue, and `epic:bundle` afterwards, from
90
- the real number and the relations recorded against it. Full behavior:
51
+ --decision-file <path|->`.** It appends to the epic's `## Decisions` and comments the same text on
52
+ each child added. **Never hand-edit the epic body to add the entry.** Refused before anything is
53
+ written:
54
+
55
+ - **A line that is *nothing but* a `#A -> #B` chain** — it would be read as a declaration. Quote the
56
+ order in backticks or a fenced block.
57
+ - **An empty record, or `--decision-file` with no usable path.**
58
+
59
+ For children the epic already tracks: `SKILL.md` → "Recording a decision".
60
+
61
+ **Its sibling runs before the filing: `pnpm josh issue:scout "<title>"`** — the same epic question for
62
+ an issue not yet filed, plus whether the work is already filed. **Both run**: `pnpm josh issue:file`
63
+ runs the scout before creating the issue and `epic:bundle` after. Full behavior:
91
64
  `docs/josh-commands-backlog.md` → "`josh issue:file`".
92
65
 
93
66
  **When the relation carries an order, record it** in `blocked-by` and in the epic's `Dependencies` —
94
- on an addition as much as on a new epic. Without it the batch survives and the reason for it does
95
- not. An order **nobody declared is not invented**.
67
+ on an addition as much as on a new epic. An order **nobody declared is not invented**.
@@ -1,19 +1,15 @@
1
1
  # Execution waves — parallel, then one alone, then the rest
2
2
 
3
- **Read this when an epic's children need an order between groups** — a wave boundary, or one child
4
- that must run alone. It is a reference of the `epic-commands` skill (`SKILL.md`), which carries the
5
- commands themselves; the dependency declaration this file builds on is `SKILL.md` → "`josh epic:next
6
- <E…>` — what is runnable".
3
+ Read this when an epic's children need an order between groups — a wave boundary, or one child that
4
+ must run alone. It builds on `SKILL.md` → "`josh epic:next <E…>` — what is runnable".
7
5
 
8
- **A wave is not a mechanism, and there is nothing to add for one.** "Run #A, #B and #C together, then
9
- #D by itself, then the rest together" is already expressible with the dependency declaration
10
- `SKILL.md` describes.
6
+ **A wave is not a mechanism, and there is nothing to add for one** — the dependency declaration
7
+ already expresses it.
11
8
 
12
9
  ## The shape
13
10
 
14
- **A wave boundary is drawn by chaining every child of the later wave to every child of the earlier
15
- one.** Wave 1 `{#A, #B, #C}` → wave 2 `{#D}` → wave 3 `{#X, #Y, #Z}` is written in the epic's
16
- `## Dependencies` as three chain lines:
11
+ **Chain every child of the later wave to every child of the earlier one.** Wave 1 `{#A, #B, #C}` →
12
+ wave 2 `{#D}` → wave 3 `{#X, #Y, #Z}` in the epic's `## Dependencies`:
17
13
 
18
14
  ```
19
15
  #A -> #D -> #X
@@ -21,85 +17,51 @@ one.** Wave 1 `{#A, #B, #C}` → wave 2 `{#D}` → wave 3 `{#X, #Y, #Z}` is writ
21
17
  #C -> #D -> #Z
22
18
  ```
23
19
 
24
- - **#A #B #C are blocked by nobody, so they start together** — as many at once as there are free lanes.
25
- - **#D is `time` until all three have closed**, and becomes runnable the moment the last one does.
20
+ - **#A #B #C are blocked by nobody, so they start together** — as many as there are free lanes.
21
+ - **#D is `time` until all three have closed**, then runnable.
26
22
  - **#X #Y #Z are blocked by #D, so #D necessarily runs alone.**
27
- - **#D closing releases wave 3**, which again runs as wide as the lanes allow.
28
-
29
- **The block above is an illustration, not something to paste.** `parse_dependency_chains` strips
30
- fenced blocks before it matches, so a `## Dependencies` section whose chains sit inside a fence reads
31
- as **no declaration at all** rather than as an error — and `#A` / `#B` are not issue numbers anyway.
32
- The lines go into the epic body unfenced, with real numbers.
33
-
34
- **Deleting a declared order is `pnpm josh epic --remove <E> <M> <N> [<N2> …]`, and never a hand edit
35
- either.** The arguments are a path, so each consecutive pair is one order and a whole chain goes in
36
- one call; the body's declaration and the `blocked-by` relations are written from that one input,
37
- exactly as `--add` writes them. **The ends are never reconnected** — `#A -> #B -> #C` minus
38
- `#B -> #C` leaves `#A -> #B`, and taking out a middle child's two links leaves `#A` and `#C`
39
- unordered rather than declaring `#A -> #C`. Deleting the last link writes the unordered sentence, so
40
- the section never ends up with no machine-readable declaration. Pass `--decision-file` to record why;
41
- the record lands on the epic's `## Decisions` and on both ends of every deleted order. Doing either
42
- half by hand is the `declaration_mismatch` below, arrived at from the other direction.
43
-
44
- **Write the boundary with `pnpm josh epic --add`, not by hand.** A declared link with no recorded
45
- `blocked-by` relation is the `declaration_mismatch` that `find_anomalies` reports, and it stops
46
- `epic:next` and the run that consumes it outright; the rule `epic-bundle.md` ends on — record the order in `blocked-by` **and**
47
- in `Dependencies` — is what a wave has to satisfy, and editing the body alone satisfies half of it.
48
- **`--before <hub>` and `--after <hub>` are both refused while the hub sits in more than one chain
49
- with nothing after it** — which is exactly what a hub is the moment the earlier wave has been chained
50
- into it. **The first child of the next wave therefore goes into the declaration by hand**, with its
51
- `blocked-by` recorded to match. Once the hub has a successor, `--after <hub>` branches a new line and
52
- the rest of that wave goes in with it.
53
-
54
- **Any number of chain lines is allowed, and one child may be an endpoint of several of them.** The
55
- consistency check rejects exactly two things, a **cycle** and a **disagreement between the
56
- declaration and the recorded `blocked-by`**; a fan-in and a fan-out are neither.
57
-
58
- **The number of lines is the size of the widest wave**, because a one-child wave is a hub and the
59
- chains through it collapse into one line each. Where both sides of a boundary hold several children
60
- the count grows — and that is the moment to ask whether the boundary is real, rather than to go
61
- looking for a shorter notation.
23
+ - **#D closing releases wave 3.**
24
+
25
+ **The block above is an illustration, not something to paste**: chains inside a fence read as no
26
+ declaration at all. Write the lines unfenced, with real numbers.
27
+
28
+ **Write the boundary with `pnpm josh epic --add`, not by hand** — a declared link with no recorded
29
+ `blocked-by` is a `declaration_mismatch` that stops `epic:next` and the run. **`--before <hub>` and
30
+ `--after <hub>` are both refused while the hub sits in more than one chain with nothing after it**, so
31
+ **the first child of the next wave goes into the declaration by hand**, with its `blocked-by` recorded
32
+ to match; after that, `--after <hub>` branches the rest.
33
+
34
+ **Delete a declared order with `pnpm josh epic --remove <E> <M> <N> [<N2> …]`, never a hand edit.**
35
+ Each consecutive pair is one order. **The ends are never reconnected** (`#A -> #B -> #C` minus
36
+ `#B -> #C` leaves `#A -> #B`). Deleting the last link writes the unordered sentence.
37
+ `--decision-file` records why on the epic and on both ends.
38
+
39
+ **Any number of chain lines is allowed**; only a **cycle** and a **disagreement between the
40
+ declaration and the recorded `blocked-by`** are rejected. The line count is the widest wave; when both
41
+ sides of a boundary hold several children, ask whether the boundary is real.
62
42
 
63
43
  ## Running one child alone is a wave of one
64
44
 
65
- **There is no `solo` mechanism, and none is needed.** "This one must not run beside anything" is the
66
- shape above with a wave of size one: chain into it every child that must not overlap it, and out of
67
- it every child that must not precede it.
45
+ **There is no `solo` mechanism.** Chain into it every child that must not overlap it, and out of it
46
+ every child that must not precede it.
68
47
 
69
48
  ## When a wave may be declared
70
49
 
71
- **Declare a boundary only where the later wave needs the earlier wave's artifact.** That is the whole
72
- condition, and it is narrower than it sounds:
73
-
74
- - **A mere preference of order is not a dependency.** Wanting one child to go first — to see its
75
- result early, to get the risky one out of the way — is presentation order, and the task-list order
76
- is where that belongs. Substituting a dependency for it buys the order and pays with the stall below.
77
- **Write it with `--order-before <M>` / `--order-after <M>`**, which move the task-list row and
78
- declare nothing; `--before` / `--after` are for an order that really is a dependency. Neither of the
79
- order-only flags helps at a **wave boundary**, which is a dependency by definition — the hub case
80
- above stays what it is.
81
- - **Two children that merely edit the same file are not a dependency.** A textual conflict resolves
82
- inside the lane: every run merges `origin/main` before its gate (`pnpm josh main:merge`), and an
83
- overlap that lands after it is resolved where it surfaces (`backlogrun-recovery.md` → "Conflicts are
84
- not predicted"). Run them in parallel; the per-conflict price is `backlogrun-lanes.md` → "Lanes —
85
- running more than one child at a time".
86
- - **Two children that would each build the same mechanism are a dependency.** No merge reconciles two
87
- implementations of one thing — the later child must build on the earlier one's, so the boundary stays.
88
- - **No reason to wait means no declaration.** An epic whose children are mostly independent says so in
89
- prose and leaves the graph empty.
50
+ **Only where the later wave needs the earlier wave's artifact.**
90
51
 
91
- ## What a jam does, and how it is cleared
52
+ - **A preference of order is not a dependency** — use task-list order: `--order-before <M>` /
53
+ `--order-after <M>` move the row and declare nothing. They do not help at a wave boundary.
54
+ - **Two children editing the same file are not a dependency** — run them in parallel; conflicts
55
+ resolve in the lane (`pnpm josh main:merge`; `backlogrun-recovery.md` → "Conflicts are not
56
+ predicted"; `backlogrun-lanes.md` → "Lanes — running more than one child at a time").
57
+ - **Two children that would each build the same mechanism are a dependency.**
58
+ - **No reason to wait means no declaration** — say so in prose and leave the graph empty.
92
59
 
93
- **Declare a boundary and one stuck child in the earlier wave stops every wave behind it.**
94
- `from_blockers` in `scripts/epic/epic-classify.ts` propagates `human`: a wave-1 child labelled
95
- `needs-decision` makes every child behind it "waiting on a person" rather than "waiting on time".
60
+ ## What a jam does, and how it is cleared
96
61
 
97
- **The park itself is not the halt.** `backlogrun` parks that child and goes on running the rest of
98
- wave 1 exactly as it always does; the session stops once those close and nothing is runnable,
99
- because every later wave has been classified `human`. So a boundary is paid for at the *end* of the
100
- wave rather than at the moment one child parks. **Clearing it is removing that child's
101
- `needs-decision`** once the decision has been recorded — the removal recording a decision already
102
- requires — after which the waves behind it become runnable on the next round.
62
+ **One stuck child in an earlier wave stops every wave behind it**: a `needs-decision` child makes
63
+ every child behind it "waiting on a person" (`from_blockers` in `scripts/epic/epic-classify.ts`).
64
+ `backlogrun` parks it and runs the rest of the wave; the session stops once nothing is runnable.
65
+ **Clear it by removing that child's `needs-decision`** once the decision is recorded.
103
66
 
104
- **A wave is declared for a real wait and removed when the wait ends; it is not the standing shape of
105
- an epic.**
67
+ **A wave is declared for a real wait and removed when the wait ends.**
@@ -6,84 +6,58 @@ argument-hint: '[route] [route...]'
6
6
 
7
7
  # Verify the rendered screen
8
8
 
9
- The completion gate in `CLAUDE.md` says a change that affects the rendered UI is not done until
10
- someone has looked at the rendered result; passing unit and E2E tests are not that look. This skill is
11
- the look. Rationale: `docs/maintainers/verify-ui-rationale.md` → "Why the skill reads as it does".
9
+ A rendered-UI change is not done until someone has looked at it (`CLAUDE.md` → completion gate);
10
+ passing tests are not that look.
12
11
 
13
12
  ## 1. Decide which routes to capture
14
13
 
15
- In order:
16
-
17
14
  1. The routes given as arguments (`/verify-ui / /blog`).
18
- 2. Otherwise, derive the candidates with `pnpm josh ui:routes`: it reads the
19
- change (the branch diff, or the staged diff with `--staged`) and lists the routes it touches,
20
- tracing a changed shared component to the routes that render it. From that list **pick the ones a
21
- reader would notice** — that narrowing is the judgement the command leaves to you.
22
- 3. If it derives no route — it prints that plainly rather than guessing — ask which screen to look
23
- at. Do not guess.
15
+ 2. Otherwise `pnpm josh ui:routes` (branch diff, or `--staged`) lists the routes the change touches;
16
+ **pick the ones a reader would notice**.
17
+ 3. If it derives none, ask which screen to look at. Do not guess.
24
18
 
25
- State the list before capturing, so a wrong route is caught before the build.
19
+ State the list before capturing.
26
20
 
27
21
  ## 2. Find this project's screenshot command
28
22
 
29
- The command belongs to the application layer, not to this package, and it differs per project type.
30
- Look for it in this order and stop at the first hit:
23
+ Stop at the first hit:
31
24
 
32
25
  1. `pnpm josh-app shot` — the SvelteKit application toolkit (`@joshuafolkken/app-kit`).
33
26
  2. `pnpm josh-game shot` — the game toolkit (`@joshuafolkken/game-kit`).
34
27
  3. A project-local script named `shot`, `screenshot` or `verify:ui` in `package.json`.
35
28
 
36
- Option 1 exists since app-kit 0.86.0; game-kit carries no `shot` yet, so a game project lands on
37
- option 3 or the fallback below. Both are true of a version, and
29
+ Option 1 exists since app-kit 0.86.0; game-kit carries no `shot` yet —
38
30
  the version a project has installed is the only thing that decides.
39
31
 
40
- **Decide by the printed command list, not by whether the toolkit is installed.** Run the toolkit
41
- with no subcommand (`pnpm josh-app`) and read the usage line it prints; `shot` exists only if that
42
- list names it. An unknown subcommand exits non-zero with the same usage line, so a toolkit that is
43
- present but has no `shot` command and a toolkit that is absent are told apart by reading the list,
44
- not by whether the invocation succeeded.
32
+ **Decide by the printed command list, not by whether the toolkit is installed.** Run the toolkit with
33
+ no subcommand (`pnpm josh-app`) and read its usage line; an absent toolkit and one without `shot` both
34
+ exit non-zero.
45
35
 
46
36
  ### When there is no screenshot command
47
37
 
48
- The gate still has to be met, so fall back in this order.
49
-
50
- **Capture through the project's own E2E suite.** If it has Playwright specs, add a
51
- `await page.screenshot({ path: … })` to the spec that already covers the affected screen — or a new
52
- spec if none does — and run it.
53
-
54
- **Otherwise stop and say so.** Report, in the session language:
38
+ **Capture through the project's own E2E suite**: add `await page.screenshot({ path: … })` to the
39
+ Playwright spec covering the screen (or a new spec) and run it.
55
40
 
56
- - that this project has neither a screenshot command nor an E2E suite to capture through, naming
57
- what you looked for;
58
- - that the UI verification gate is therefore **not** closed by this run;
59
- - that the change needs a human to look at the screen, and ask the user to do it.
41
+ **Otherwise stop and say so**, in the session language: what you looked for, that the UI verification
42
+ gate is **not** closed by this run, and ask the user to look at the screen.
60
43
 
61
44
  Never report the gate as satisfied on tests alone. Never stand up a preview server by hand and drive
62
- it from a throwaway script left outside the repository. If the project should have the command and
63
- does not, that is an issue to file against the application toolkit.
45
+ it from a throwaway script. A project that should have the command and does not is an issue against
46
+ the application toolkit.
64
47
 
65
48
  ## 3. Capture
66
49
 
67
- Run the command once for every route in a single invocation (`pnpm josh-app shot / /blog`). Wait for
68
- it to finish and note the output directory it prints. On the E2E fallback, run the spec and note where its
69
- `path` option wrote the images.
70
-
71
- If it exits non-zero, report the failure as the result. A failed capture is not a passed gate.
50
+ Run the command once for every route (`pnpm josh-app shot / /blog`) and note the output directory (on
51
+ the E2E fallback, the `path` option). A non-zero exit is the result. A failed capture is not a passed gate.
72
52
 
73
53
  ## 4. Look at the images
74
54
 
75
- Read every produced image with the Read tool. Actually look at each one — capturing files without
76
- opening them does not close the gate.
77
-
78
- Check what the change was supposed to do to the screen: the element is present, in the right place,
79
- at the right size, with the intended spacing, color and text; nothing that used to be there has
80
- disappeared or moved; the layout is not broken at the captured viewport.
55
+ Read every produced image with the Read tool — capturing without opening does not close the gate.
56
+ Check the change's intent: element present, placed, sized, spaced, colored and worded as intended;
57
+ nothing else disappeared or moved; the layout holds at the captured viewport.
81
58
 
82
59
  ## 5. Report
83
60
 
84
- - **Matches the intent**: say what you looked at, route by route, and what you checked on each. Name
85
- the image paths so the user can open the same files.
86
- - **Does not match**: for each mismatch give the route, what the change was supposed to produce,
87
- what the image actually shows, and the image path. Then fix and capture again. Do not report the
88
- work as done with a known mismatch outstanding.
61
+ - **Matches the intent**: route by route, what you checked, with the image paths.
62
+ - **Does not match**: route, intended result, what the image shows, image path. Fix and capture again.
89
63
  - **Could not capture**: the report from step 2 or step 3, unchanged. This is not a pass.
@@ -5,10 +5,7 @@ description: Procedures for `kickoff`, `fullrun`, `halfrun`, `prrun` and `backlo
5
5
 
6
6
  # Issue-driven workflow commands
7
7
 
8
- `kickoff`, `fullrun`, `halfrun`, `prrun` and `backlogrun` are the shorthand commands this
9
- package's collaboration workflow is built on. **This file is their manifest — triggers and pointers,
10
- never a procedure**: each rule is stated once, in the file its row names. History:
11
- `docs/maintainers/workflow-commands-rationale.md` → "Where each rule came from".
8
+ Each rule is stated once, in the file its row names.
12
9
 
13
10
  ## 0. The rule that fires before any of them — explicit invocation
14
11
 
@@ -19,8 +16,9 @@ alone**: `backlogrun-steps.md` → "The session cut is inside the invocation".
19
16
  ## 1. Which file to read
20
17
 
21
18
  Read this file, then the files the typed command's row names. A command file is a **manifest** of
22
- terse triggers and pointers; `pnpm josh run:step <N>` prints the run's next single action, computed
23
- from the event stream, the carry record and the issue state, never the conversation.
19
+ terse triggers and pointers; `pnpm josh run:step <N>` prints the run's next single action and the
20
+ section that governs it, computed from the event stream, the carry record and the issue state, never
21
+ the conversation; a section it prints is not fetched again.
24
22
 
25
23
  | Typed keyword | Read |
26
24
  | ---------------------------------------- | ------------------------------------------- |
@@ -31,8 +29,8 @@ from the event stream, the carry record and the issue state, never the conversat
31
29
  | `backlogrun` / `backlogrun #N…` / `backlogrun #E…` | `backlogrun.md` — its dispatched child reads `fullrun.md` + `split-assessment.md` in its own unit, not the parent at entry |
32
30
 
33
31
  `entry-sequence.md` holds the entry sequence and stop branches `fullrun`, `halfrun` and `prrun` share;
34
- each manifest carries only its difference. `split-assessment.md` → "The question" is read at the
35
- entry as a section, its split-handling detail only when a split is found.
32
+ each manifest carries only its difference. `split-assessment.md` → "The question" is printed by
33
+ `pnpm josh run:entry` at the entry, its split-handling detail read only when a split is found.
36
34
 
37
35
  ### The fetch is one `Read` call per file
38
36
 
@@ -100,7 +98,7 @@ from — read at that trigger, never restated here.
100
98
  | `backlogrun`'s authorization | The whole `auto-ok` opted-in pool as well as its named items; `pnpm josh backlog:next` offers them | `backlogrun.md` |
101
99
  | `run:step` prints the retrospective step (a run drained its backlog and stopped, not a lane child) | Run what it prints once, file 0–2 improvements, then `pnpm josh run:carry --retrospective` | `retrospective.md` |
102
100
  | Any artifact prose (Issue bodies, comments, Telegram) | Session language (`JOSH_SESSION_LANG`, default `ja`); Issue/PR titles stay English | `prompts/collaboration-workflow/overview.md` |
103
- | Any mid-workflow stop | Send a `confirmation` Telegram first, so the user is alerted off-screen | `CLAUDE.md` → "Mid-workflow stop notification" |
101
+ | Any mid-workflow stop | `stop:guard` sends the `confirmation` Telegram; on its refusal, send it | `CLAUDE.md` → "Mid-workflow stop notification" |
104
102
 
105
103
  ## 3. What stays resident, and what is read from here
106
104
 
@@ -17,73 +17,58 @@
17
17
  - A lane child's hand-off or pre-gate cut is the sole turn boundary before the push (`chain-rule.md`).
18
18
 
19
19
  Use harness detachment so completion returns to the run. Foreground timeouts stay within the cap.
20
- Where each rule came from: `docs/maintainers/background-commands-rationale.md` → "Where each rule came from".
21
20
 
22
21
  ## How the wait ends — the task's exit, never a regex over its output
23
22
 
24
- **Background it from the first, then end the turn.** A command issued with `run_in_background` set
25
- re-invokes the run when it exits, and that completion notification is what ends the wait — on the
26
- task's *exit*, not on a regex match and not on the harness block limit. So the moment you background
27
- a long command there is nothing to wait *on*: end the turn, and the wake-up brings you back with the
28
- command finished.
23
+ **Background it from the first, then end the turn.** A `run_in_background` command re-invokes the run
24
+ when it *exits* — that completion notification is what ends the wait, not a regex match or the block
25
+ limit.
29
26
 
30
- **Never hand-write a `while`/`until` … `sleep` loop over the output file.** The loop does not know
31
- when the command finished: a regex that never matches waits to the block limit, and one that matches
32
- a mid-run line exits too early. `pnpm josh rule:guard` refuses the poll loop and hands back this route
33
- (`prompts/collaboration-workflow/rule-delivery.md`). Rationale:
34
- `docs/maintainers/background-commands-rationale.md` → "Why a poll loop is refused".
27
+ **Never hand-write a `while`/`until` … `sleep` loop over the output file** — a regex that never matches
28
+ waits to the block limit, one that matches a mid-run line exits early. `pnpm josh rule:guard` refuses it
29
+ (`prompts/collaboration-workflow/rule-delivery.md`).
35
30
 
36
- **To glance at interim output, `Read` the output file once** — the notification names its path — and
37
- never in a sleep loop. If what you are waiting on is CI, `pnpm josh followup` waits on it for you in
38
- the foreground; a bare `sleep` that arms a progress heartbeat is `run:progress --wait`'s job, refused
39
- in front of a hand-armed timer by `early-heartbeat`.
31
+ **To glance at interim output, `Read` the output file once**, never in a sleep loop. CI is waited on by
32
+ `pnpm josh followup`; a progress heartbeat is `run:progress --wait`'s job (`early-heartbeat` refuses a
33
+ hand-armed timer).
40
34
 
41
35
  ## The tail and what overlaps each wait
42
36
 
43
- **Never give a foreground call a timeout above the harness cap** — the cap decides how long a
44
- foreground call waits, so a larger number detaches the call without the completion notification.
45
- Rationale: `docs/maintainers/background-commands-rationale.md` → "Why the tail collects idle time".
37
+ **Never give a foreground call a timeout above the harness cap** — a larger number detaches it without
38
+ the completion notification.
46
39
 
47
- **The tail is emptied before `followup` is issued, rather than worked through after it returns.**
48
- One question decides each step, and it is asked of the step rather than judged: **does it read the
40
+ **The tail is emptied before `followup` is issued.** Each step is asked one question: **does it read the
49
41
  merge result?**
50
42
 
51
- - **It does — the step stays after `followup`.** `pnpm josh ms`, `pnpm josh issue:state <N>`,
52
- `pnpm josh epic:next`, `pnpm josh backlog:next --exclude <N>`, and `pnpm josh lane:close` /
53
- `pnpm josh lane:list`. **De-duplicating a step is not removing it**: none of these may be dropped or
54
- answered from memory.
55
- - **It does not — the step is composed in the turn that issues `followup`.** The epic progress
56
- comment's counter *values* and the completion report body (placed beside `pnpm josh git -y` in the
57
- table below). **Only the write follows the merge.**
58
- - **`pnpm josh cost --cut` stays after the merge, and reads nothing from it** — its answer grows with
59
- the session, so it keeps its documented seam (`backlogrun-progress.md` → "The check is asked at
60
- every merge").
61
-
62
- **What runs beside a backgrounded command is the work that writes nothing to the working tree** — a
63
- step that edits makes the background command's result stale. Applied to the three waits a run
64
- actually has:
43
+ - **It does — it stays after `followup`**: `pnpm josh ms`, `pnpm josh issue:state <N>`,
44
+ `pnpm josh epic:next`, `pnpm josh backlog:next --exclude <N>`, `pnpm josh lane:close` /
45
+ `pnpm josh lane:list`. **De-duplicating a step is not removing it** — none is dropped or answered
46
+ from memory.
47
+ - **It does not — it is composed in the turn that issues `followup`**: the epic progress counter
48
+ *values* and the completion report body. **Only the write follows the merge.**
49
+ - **`pnpm josh cost --cut` stays after the merge**, though it reads nothing from it (`backlogrun-progress.md`
50
+ → "The check is asked at every merge").
51
+
52
+ **Beside a backgrounded command runs only work that writes nothing to the working tree**:
65
53
 
66
54
  | While this runs | Do this beside it |
67
55
  | --------------- | ----------------- |
68
56
  | `pnpm josh gate` | a subagent running `/code-review` with the brief `pnpm josh review:brief` prints |
69
57
  | `pnpm josh git -y` | Write the completion notification body to a file for `--notify-message-file`, and settle the three-way disposition of any remaining non-High finding |
70
58
  | CI, after the push | The second review round where one is due, the branch-2 filing through `pnpm josh issue:file`, which runs `epic:bundle` itself (`prompts/review.md` → "Review round cap") |
71
- | `pnpm josh followup` | Nothing — it is foreground and holds the session. **The post-merge tail is what overlaps here, and it is taken before the call rather than beside it**: compose the epic progress counters first, and leave after the merge only the steps that read its result, plus `pnpm josh cost --cut` |
59
+ | `pnpm josh followup` | Nothing — it is foreground. **The post-merge tail is taken before the call**: compose the epic progress counters first, and leave after the merge only the steps that read its result, plus `pnpm josh cost --cut` |
72
60
 
73
- **The turn never ends at the push.** The completion notification for `pnpm josh git -y` is what
74
- resumes the run, and the turn that reads it goes straight through any branch-2 filing and
75
- `pnpm josh epic:bundle` to `pnpm josh followup`. `pnpm josh rule:guard` refuses the foreground push
76
- step and states both halves at that call (`prompts/collaboration-workflow/rule-delivery.md`); the push
77
- reissued detached is not refused again. Rationale: `docs/maintainers/background-commands-rationale.md`
78
- → "Why the push is guarded".
61
+ **The turn never ends at the push.** The `pnpm josh git -y` completion resumes the run, and that turn
62
+ goes straight through any branch-2 filing and `pnpm josh epic:bundle` to `pnpm josh followup`. `pnpm
63
+ josh rule:guard` refuses the foreground push (`prompts/collaboration-workflow/rule-delivery.md`); the
64
+ push reissued detached is not refused again.
79
65
 
80
- **One turn does end before the push, and only one: a dispatched lane child's pre-gate cut.** It ends
81
- the turn before the gate and relaunches a fresh process in the same act — `pre-gate-cut.md` → "Taking
82
- the cut" is its single source.
66
+ **One turn does end before the push: a dispatched lane child's pre-gate cut** — `pre-gate-cut.md` →
67
+ "Taking the cut".
83
68
 
84
69
  **A headless lane child (`claude -p`) is where "a background command re-invokes the run" does not
85
- hold: its background Bash tasks are killed when its turn ends.** It hands the gate-to-merge region to
86
- a foreground `pnpm josh ship --detach` instead (`chain-rule.md` step 0); `pnpm josh rule:guard` refuses a
70
+ hold: its background Bash tasks are killed when its turn ends.** It hands the gate-to-merge region to a
71
+ foreground `pnpm josh ship --detach` (`chain-rule.md` step 0); `pnpm josh rule:guard` refuses a
87
72
  backgrounded `josh gate` / `git` / `followup` / `ship` there, and the `Stop` hook sends a child with a
88
73
  task still running back to wait.
89
74