@joshuafolkken/kit 1.1453.0 → 1.1471.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 (224) hide show
  1. package/.claude/skills/dependency-update/SKILL.md +26 -55
  2. package/.claude/skills/epic-commands/SKILL.md +87 -148
  3. package/.claude/skills/epic-commands/epic-bundle.md +45 -77
  4. package/.claude/skills/epic-commands/execution-waves.md +44 -81
  5. package/.claude/skills/verify-ui/SKILL.md +25 -50
  6. package/.claude/skills/workflow-commands/background-commands.md +36 -47
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +72 -85
  8. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +1 -1
  9. package/.claude/skills/workflow-commands/backlogrun-lanes.md +91 -121
  10. package/.claude/skills/workflow-commands/backlogrun-park.md +73 -117
  11. package/.claude/skills/workflow-commands/backlogrun-progress.md +7 -9
  12. package/.claude/skills/workflow-commands/backlogrun-recovery.md +11 -20
  13. package/.claude/skills/workflow-commands/backlogrun-steps.md +43 -52
  14. package/.claude/skills/workflow-commands/chain-rule.md +24 -34
  15. package/.claude/skills/workflow-commands/followup.md +57 -76
  16. package/.claude/skills/workflow-commands/halfrun.md +2 -1
  17. package/.claude/skills/workflow-commands/issue-comments.md +43 -60
  18. package/.claude/skills/workflow-commands/kickoff.md +65 -74
  19. package/.claude/skills/workflow-commands/observation-filing.md +62 -107
  20. package/.claude/skills/workflow-commands/observation-ledger.md +56 -111
  21. package/.claude/skills/workflow-commands/pre-gate-cut.md +89 -138
  22. package/.claude/skills/workflow-commands/prerequisite.md +10 -15
  23. package/.claude/skills/workflow-commands/progress-watcher.md +21 -26
  24. package/.claude/skills/workflow-commands/prrun.md +2 -1
  25. package/.claude/skills/workflow-commands/retrospective.md +31 -50
  26. package/.claude/skills/workflow-commands/split-assessment.md +34 -58
  27. package/.claude/skills/workflow-commands/working-tree-hold.md +54 -71
  28. package/CLAUDE.md +7 -6
  29. package/README.md +2 -9
  30. package/dist/CLAUDE.md +7 -6
  31. package/dist/hooks/batch-guard.js +6 -6
  32. package/dist/hooks/{chunk-Y3GKIKGW.js → chunk-43ZHT22P.js} +31 -15
  33. package/dist/hooks/{chunk-MBJYQPEK.js → chunk-AS74OU3D.js} +24 -8
  34. package/dist/hooks/{chunk-3C4XRYG6.js → chunk-E7OIKX5Z.js} +17 -12
  35. package/dist/hooks/{chunk-Z4XI7CZS.js → chunk-EUMACUK2.js} +18 -12
  36. package/dist/hooks/{chunk-NO4AALP5.js → chunk-H5HVWYXK.js} +4 -4
  37. package/dist/hooks/{chunk-5C7L6FRC.js → chunk-IIGFYXKC.js} +346 -241
  38. package/dist/hooks/{chunk-W5ZKGTSY.js → chunk-J47HU5H5.js} +14 -3
  39. package/dist/hooks/{chunk-OLMO72ON.js → chunk-K4EOONYM.js} +1 -1
  40. package/dist/hooks/{chunk-LBFYEOXJ.js → chunk-K4LMBQC2.js} +4 -4
  41. package/dist/hooks/{chunk-D3NJXN5M.js → chunk-KC5AK2GF.js} +8 -6
  42. package/dist/hooks/chunk-SHGPANFB.js +56 -0
  43. package/dist/hooks/{chunk-EF5GQ6WS.js → chunk-YHBZAJSV.js} +3 -3
  44. package/dist/hooks/{chunk-SHYUQOIS.js → chunk-YYPI7SJZ.js} +5 -5
  45. package/dist/hooks/codex-hook-adapter.js +13 -13
  46. package/dist/hooks/duplicate-read-guard.js +7 -7
  47. package/dist/hooks/format-edited.js +3 -3
  48. package/dist/hooks/inputs.json +251 -247
  49. package/dist/hooks/investigation-guard.js +7 -7
  50. package/dist/hooks/pretool-guard.js +12 -12
  51. package/dist/hooks/session-lang.js +6 -5
  52. package/dist/hooks/stop-guard.js +75 -18
  53. package/dist/josh.js +6 -7
  54. package/dist/managed-marker/index.js +1 -2
  55. package/dist/version/index.js +15 -12
  56. package/eslint/base.js +2 -1
  57. package/eslint/rules/unicorn.js +16 -0
  58. package/package.json +3 -3
  59. package/prompts/coding-standards.md +12 -22
  60. package/prompts/collaboration-workflow/file-edits.md +26 -44
  61. package/prompts/collaboration-workflow/gh-rest.md +20 -36
  62. package/prompts/collaboration-workflow/glossary.md +5 -7
  63. package/prompts/collaboration-workflow/issue-citation.md +7 -13
  64. package/prompts/collaboration-workflow/issue-template.md +29 -29
  65. package/prompts/collaboration-workflow/operating-rules.md +35 -44
  66. package/prompts/collaboration-workflow/output-bounds.md +15 -15
  67. package/prompts/collaboration-workflow/overview.md +14 -19
  68. package/prompts/collaboration-workflow/plan-comment.md +13 -13
  69. package/prompts/collaboration-workflow/principles.md +50 -53
  70. package/prompts/collaboration-workflow/proposal-request.md +1 -9
  71. package/prompts/collaboration-workflow/report-format.md +32 -49
  72. package/prompts/collaboration-workflow/residency.md +10 -10
  73. package/prompts/collaboration-workflow/rule-delivery.md +9 -9
  74. package/prompts/collaboration-workflow/shell-body.md +11 -21
  75. package/prompts/collaboration-workflow/turn-batching.md +8 -14
  76. package/prompts/collaboration-workflow/upstream-interrupt.md +26 -34
  77. package/prompts/collaboration-workflow/wip-cap.md +24 -30
  78. package/prompts/collaboration-workflow.md +24 -25
  79. package/prompts/refactoring.md +33 -43
  80. package/prompts/review-rubric.md +84 -129
  81. package/prompts/review.md +111 -141
  82. package/prompts/sonar-hotspot-handling.md +22 -50
  83. package/prompts/testing-guide.md +48 -99
  84. package/scripts/adopt/adopt-toolkits.ts +2 -4
  85. package/scripts/agent/agent-exit-record.ts +23 -1
  86. package/scripts/agent/codex-agent-argv.ts +7 -2
  87. package/scripts/backlog/backlog-budget-cli.ts +1 -2
  88. package/scripts/backlog/backlog-drive-carried.ts +26 -0
  89. package/scripts/backlog/backlog-drive-cli.ts +10 -5
  90. package/scripts/backlog/backlog-drive-named.ts +2 -4
  91. package/scripts/backlog/backlog-drive-restore.ts +19 -1
  92. package/scripts/backlog/backlog-drive-seats.ts +27 -0
  93. package/scripts/backlog/backlog-drive.ts +11 -6
  94. package/scripts/backlog/backlog-ready.ts +13 -6
  95. package/scripts/behavior/behavior-rules.ts +3 -2
  96. package/scripts/cost-runtime/codex-usage.ts +4 -2
  97. package/scripts/cost-runtime/cost-cli.ts +1 -2
  98. package/scripts/delegation/investigation-guard.ts +1 -1
  99. package/scripts/delegation/investigation-reads.ts +1 -1
  100. package/scripts/discovery/repo-discovery.ts +4 -2
  101. package/scripts/discovery/repo-origin.ts +2 -4
  102. package/scripts/doctor/doctor-logic.ts +6 -3
  103. package/scripts/document/document-byte-budget.ts +27 -27
  104. package/scripts/document/document-byte-check.ts +1 -2
  105. package/scripts/document/entry-read-budget.ts +2 -2
  106. package/scripts/epic/epic-audit-rationale.ts +8 -2
  107. package/scripts/epic/epic-bundle-cli.ts +1 -2
  108. package/scripts/epic/epic-chains.ts +6 -2
  109. package/scripts/epic/epic-close-comment.ts +1 -2
  110. package/scripts/gate/verification-gate.ts +7 -2
  111. package/scripts/gh/git-pr-ai-review.ts +12 -1
  112. package/scripts/gh/git-pr-confirmation.ts +11 -7
  113. package/scripts/gh/git-pr.ts +6 -2
  114. package/scripts/git/git-common-directory.ts +3 -3
  115. package/scripts/git/git-diff-reads.ts +16 -9
  116. package/scripts/git/git-execa-error.ts +1 -2
  117. package/scripts/hooks/format-edited-file.ts +10 -4
  118. package/scripts/hooks/pre-push-unit.ts +15 -4
  119. package/scripts/hooks/pretool-guard.ts +23 -29
  120. package/scripts/hooks/step-zero-notice.ts +3 -2
  121. package/scripts/init/hook-command-rewrite.ts +6 -2
  122. package/scripts/init/init-logic-deploy-vps.ts +4 -2
  123. package/scripts/issue/behavior-change-lint.ts +12 -6
  124. package/scripts/issue/issue-scout-cli.ts +3 -2
  125. package/scripts/josh/file-map-stamp.ts +1 -3
  126. package/scripts/josh/hook-decision.ts +17 -2
  127. package/scripts/josh/josh-commands-workflow.ts +1 -1
  128. package/scripts/lane/lane-await.ts +3 -2
  129. package/scripts/lane/lane-child-invocation.ts +14 -1
  130. package/scripts/lane/lane-guard-policy.ts +4 -4
  131. package/scripts/lane/lane-ledger.ts +9 -0
  132. package/scripts/lane/lane-load.ts +9 -2
  133. package/scripts/lane/lane-measure-cli.ts +2 -0
  134. package/scripts/lane/lane-parked.ts +18 -0
  135. package/scripts/lane/lane-process-load.ts +125 -0
  136. package/scripts/lane/lane-process-stats.ts +93 -0
  137. package/scripts/lane/lane-registry.ts +8 -3
  138. package/scripts/lane/lane-session-broker.ts +29 -5
  139. package/scripts/lane/lane-spent.ts +14 -3
  140. package/scripts/lane/lane-stats.ts +1 -0
  141. package/scripts/managed-marker/managed-marker-logic.ts +1 -2
  142. package/scripts/notify/confirmation-options.ts +59 -0
  143. package/scripts/notify/notify-opt-in.ts +33 -0
  144. package/scripts/notify/telegram-notify.ts +25 -8
  145. package/scripts/notify/telegram-test-logic.ts +33 -1
  146. package/scripts/notify/telegram-test.ts +4 -2
  147. package/scripts/overrides/lockfile-overrides.ts +1 -3
  148. package/scripts/propagate/propagate.ts +1 -2
  149. package/scripts/release/release-progress.ts +3 -2
  150. package/scripts/report/report-lint.ts +7 -4
  151. package/scripts/review/review-record-cli.ts +6 -2
  152. package/scripts/rules/destructive-command.ts +6 -9
  153. package/scripts/rules/direct-filing.ts +3 -7
  154. package/scripts/rules/early-heartbeat.ts +7 -18
  155. package/scripts/rules/file-body.ts +6 -13
  156. package/scripts/rules/filing-cap.ts +3 -6
  157. package/scripts/rules/git-force.ts +5 -9
  158. package/scripts/rules/implementation-cut.ts +37 -35
  159. package/scripts/rules/index-guard.ts +4 -7
  160. package/scripts/rules/issue-comments.ts +5 -15
  161. package/scripts/rules/josh-git-bare.ts +3 -6
  162. package/scripts/rules/lane-background.ts +10 -21
  163. package/scripts/rules/lane-carry-conflict.ts +7 -17
  164. package/scripts/rules/lane-interactive-ask.ts +6 -11
  165. package/scripts/rules/lane-park.ts +5 -13
  166. package/scripts/rules/lane-split-park.ts +2 -7
  167. package/scripts/rules/lane-switch-main.ts +9 -12
  168. package/scripts/rules/oracle-consulted.ts +4 -5
  169. package/scripts/rules/piped-verification.ts +81 -31
  170. package/scripts/rules/poll-loop.ts +7 -17
  171. package/scripts/rules/pre-gate-cut.ts +7 -21
  172. package/scripts/rules/prior-comment-read.ts +7 -5
  173. package/scripts/rules/protected-files.ts +5 -9
  174. package/scripts/rules/raw-field-body.ts +3 -7
  175. package/scripts/rules/rule-body-guard.ts +4 -11
  176. package/scripts/rules/run-tail-rule.ts +6 -22
  177. package/scripts/rules/shell-body-trigger.ts +7 -8
  178. package/scripts/rules/shell-segments.ts +7 -0
  179. package/scripts/rules/stop-rules.ts +17 -29
  180. package/scripts/rules/test-declared-commit.ts +4 -10
  181. package/scripts/rules/third-party-write.ts +5 -10
  182. package/scripts/rules/worktree-guard.ts +5 -12
  183. package/scripts/run/board/run-board-github.ts +11 -3
  184. package/scripts/run/board/run-board-idle.ts +31 -0
  185. package/scripts/run/board/run-board-read.ts +9 -12
  186. package/scripts/run/board/run-board-reason.ts +7 -3
  187. package/scripts/run/board/run-board-state.ts +4 -0
  188. package/scripts/run/board/run-board-status.ts +18 -3
  189. package/scripts/run/board/run-board-thanks.ts +7 -2
  190. package/scripts/run/board/run-board-tick.ts +32 -7
  191. package/scripts/run/carry/run-carry-args.ts +1 -3
  192. package/scripts/run/carry/run-carry-conversation.ts +7 -2
  193. package/scripts/run/cut/run-cut-cli.ts +15 -20
  194. package/scripts/run/cut/run-cut-decline.ts +72 -0
  195. package/scripts/run/cut/run-cut-ready.ts +74 -0
  196. package/scripts/run/cut/run-cut-report.ts +13 -0
  197. package/scripts/run/cut/run-cut.ts +10 -1
  198. package/scripts/run/entry/run-entry-stop.ts +6 -3
  199. package/scripts/run/hold/run-hold-cli.ts +14 -3
  200. package/scripts/run/hold/run-hold.ts +6 -3
  201. package/scripts/run/merge/run-merge-cli.ts +30 -7
  202. package/scripts/run/merge/run-merge-ship.ts +59 -1
  203. package/scripts/run/merge/run-merge.ts +3 -2
  204. package/scripts/run/run-ending.ts +31 -3
  205. package/scripts/run/run-parent-cut-hook.ts +5 -10
  206. package/scripts/run/run-preflight.ts +1 -2
  207. package/scripts/run/run-stop-notify.ts +3 -2
  208. package/scripts/run/run-watcher-guard.ts +6 -3
  209. package/scripts/run/ship/run-ship-review-steps.ts +13 -4
  210. package/scripts/run/ship/run-ship-review.ts +15 -2
  211. package/scripts/run/tidy/run-tidy-cli.ts +3 -3
  212. package/scripts/run/tidy/run-tidy-lanes.ts +3 -2
  213. package/scripts/safe-chain/project-config.ts +7 -2
  214. package/scripts/sync/sync-hook-safety.ts +8 -2
  215. package/scripts/test/unit-worker-share.ts +3 -2
  216. package/scripts/time-runtime/time-batch-guard.ts +3 -3
  217. package/scripts/time-runtime/time-hook-transcript.ts +3 -2
  218. package/scripts/time-runtime/time-shell.ts +10 -0
  219. package/scripts/version/effective-upstream.ts +3 -4
  220. package/scripts/version/kit-version-config.ts +8 -2
  221. package/scripts/version/latest-corepack.ts +1 -2
  222. package/scripts/version/release-hold.ts +11 -4
  223. package/scripts/version/version-commands.ts +12 -4
  224. package/dist/hooks/chunk-UT7YC3N2.js +0 -56
@@ -1,19 +1,16 @@
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". Reasons:
5
+ `docs/maintainers/epic-commands-rationale.md` → "Execution waves — why a wave is not a mechanism".
7
6
 
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.
7
+ **A wave is not a mechanism, and there is nothing to add for one** — the dependency declaration
8
+ already expresses it.
11
9
 
12
10
  ## The shape
13
11
 
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:
12
+ **Chain every child of the later wave to every child of the earlier one.** Wave 1 `{#A, #B, #C}` →
13
+ wave 2 `{#D}` → wave 3 `{#X, #Y, #Z}` in the epic's `## Dependencies`:
17
14
 
18
15
  ```
19
16
  #A -> #D -> #X
@@ -21,85 +18,51 @@ one.** Wave 1 `{#A, #B, #C}` → wave 2 `{#D}` → wave 3 `{#X, #Y, #Z}` is writ
21
18
  #C -> #D -> #Z
22
19
  ```
23
20
 
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.
21
+ - **#A #B #C are blocked by nobody, so they start together** — as many as there are free lanes.
22
+ - **#D is `time` until all three have closed**, then runnable.
26
23
  - **#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.
24
+ - **#D closing releases wave 3.**
25
+
26
+ **The block above is an illustration, not something to paste**: chains inside a fence read as no
27
+ declaration at all. Write the lines unfenced, with real numbers.
28
+
29
+ **Write the boundary with `pnpm josh epic --add`, not by hand** — a declared link with no recorded
30
+ `blocked-by` is a `declaration_mismatch` that stops `epic:next` and the run. **`--before <hub>` and
31
+ `--after <hub>` are both refused while the hub sits in more than one chain with nothing after it**, so
32
+ **the first child of the next wave goes into the declaration by hand**, with its `blocked-by` recorded
33
+ to match; after that, `--after <hub>` branches the rest.
34
+
35
+ **Delete a declared order with `pnpm josh epic --remove <E> <M> <N> [<N2> …]`, never a hand edit.**
36
+ Each consecutive pair is one order. **The ends are never reconnected** (`#A -> #B -> #C` minus
37
+ `#B -> #C` leaves `#A -> #B`). Deleting the last link writes the unordered sentence.
38
+ `--decision-file` records why on the epic and on both ends.
39
+
40
+ **Any number of chain lines is allowed**; only a **cycle** and a **disagreement between the
41
+ declaration and the recorded `blocked-by`** are rejected. The line count is the widest wave; when both
42
+ sides of a boundary hold several children, ask whether the boundary is real.
62
43
 
63
44
  ## Running one child alone is a wave of one
64
45
 
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.
46
+ **There is no `solo` mechanism.** Chain into it every child that must not overlap it, and out of it
47
+ every child that must not precede it.
68
48
 
69
49
  ## When a wave may be declared
70
50
 
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.
51
+ **Only where the later wave needs the earlier wave's artifact.**
90
52
 
91
- ## What a jam does, and how it is cleared
53
+ - **A preference of order is not a dependency** — use task-list order: `--order-before <M>` /
54
+ `--order-after <M>` move the row and declare nothing. They do not help at a wave boundary.
55
+ - **Two children editing the same file are not a dependency** — run them in parallel; conflicts
56
+ resolve in the lane (`pnpm josh main:merge`; `backlogrun-recovery.md` → "Conflicts are not
57
+ predicted"; `backlogrun-lanes.md` → "Lanes — running more than one child at a time").
58
+ - **Two children that would each build the same mechanism are a dependency.**
59
+ - **No reason to wait means no declaration** — say so in prose and leave the graph empty.
92
60
 
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".
61
+ ## What a jam does, and how it is cleared
96
62
 
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.
63
+ **One stuck child in an earlier wave stops every wave behind it**: a `needs-decision` child makes
64
+ every child behind it "waiting on a person" (`from_blockers` in `scripts/epic/epic-classify.ts`).
65
+ `backlogrun` parks it and runs the rest of the wave; the session stops once nothing is runnable.
66
+ **Clear it by removing that child's `needs-decision`** once the decision is recorded.
103
67
 
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.**
68
+ **A wave is declared for a real wait and removed when the wait ends.**
@@ -6,84 +6,59 @@ 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. Rationale: `docs/maintainers/verify-ui-rationale.md` → "Why the skill
11
+ reads as it does".
12
12
 
13
13
  ## 1. Decide which routes to capture
14
14
 
15
- In order:
16
-
17
15
  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.
16
+ 2. Otherwise `pnpm josh ui:routes` (branch diff, or `--staged`) lists the routes the change touches;
17
+ **pick the ones a reader would notice**.
18
+ 3. If it derives none, ask which screen to look at. Do not guess.
24
19
 
25
- State the list before capturing, so a wrong route is caught before the build.
20
+ State the list before capturing.
26
21
 
27
22
  ## 2. Find this project's screenshot command
28
23
 
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:
24
+ Stop at the first hit:
31
25
 
32
26
  1. `pnpm josh-app shot` — the SvelteKit application toolkit (`@joshuafolkken/app-kit`).
33
27
  2. `pnpm josh-game shot` — the game toolkit (`@joshuafolkken/game-kit`).
34
28
  3. A project-local script named `shot`, `screenshot` or `verify:ui` in `package.json`.
35
29
 
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
30
+ Option 1 exists since app-kit 0.86.0; game-kit carries no `shot` yet —
38
31
  the version a project has installed is the only thing that decides.
39
32
 
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.
33
+ **Decide by the printed command list, not by whether the toolkit is installed.** Run the toolkit with
34
+ no subcommand (`pnpm josh-app`) and read its usage line; an absent toolkit and one without `shot` both
35
+ exit non-zero.
45
36
 
46
37
  ### When there is no screenshot command
47
38
 
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:
39
+ **Capture through the project's own E2E suite**: add `await page.screenshot({ path: … })` to the
40
+ Playwright spec covering the screen (or a new spec) and run it.
55
41
 
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.
42
+ **Otherwise stop and say so**, in the session language: what you looked for, that the UI verification
43
+ gate is **not** closed by this run, and ask the user to look at the screen.
60
44
 
61
45
  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.
46
+ it from a throwaway script. A project that should have the command and does not is an issue against
47
+ the application toolkit.
64
48
 
65
49
  ## 3. Capture
66
50
 
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.
51
+ Run the command once for every route (`pnpm josh-app shot / /blog`) and note the output directory (on
52
+ the E2E fallback, the `path` option). A non-zero exit is the result. A failed capture is not a passed gate.
72
53
 
73
54
  ## 4. Look at the images
74
55
 
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.
56
+ Read every produced image with the Read tool — capturing without opening does not close the gate.
57
+ Check the change's intent: element present, placed, sized, spaced, colored and worded as intended;
58
+ nothing else disappeared or moved; the layout holds at the captured viewport.
81
59
 
82
60
  ## 5. Report
83
61
 
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.
62
+ - **Matches the intent**: route by route, what you checked, with the image paths.
63
+ - **Does not match**: route, intended result, what the image shows, image path. Fix and capture again.
89
64
  - **Could not capture**: the report from step 2 or step 3, unchanged. This is not a pass.
@@ -21,69 +21,58 @@ Where each rule came from: `docs/maintainers/background-commands-rationale.md`
21
21
 
22
22
  ## How the wait ends — the task's exit, never a regex over its output
23
23
 
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.
29
-
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".
35
-
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`.
24
+ **Background it from the first, then end the turn.** A `run_in_background` command re-invokes the run
25
+ when it *exits* — that completion notification is what ends the wait, not a regex match or the block
26
+ limit.
27
+
28
+ **Never hand-write a `while`/`until` … `sleep` loop over the output file** — a regex that never matches
29
+ waits to the block limit, one that matches a mid-run line exits early. `pnpm josh rule:guard` refuses it
30
+ (`prompts/collaboration-workflow/rule-delivery.md`; `docs/maintainers/background-commands-rationale.md`
31
+ → "Why a poll loop is refused").
32
+
33
+ **To glance at interim output, `Read` the output file once**, never in a sleep loop. CI is waited on by
34
+ `pnpm josh followup`; a progress heartbeat is `run:progress --wait`'s job (`early-heartbeat` refuses a
35
+ hand-armed timer).
40
36
 
41
37
  ## The tail and what overlaps each wait
42
38
 
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".
39
+ **Never give a foreground call a timeout above the harness cap** — a larger number detaches it without
40
+ the completion notification (`docs/maintainers/background-commands-rationale.md` → "Why the tail
41
+ collects idle time").
46
42
 
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
43
+ **The tail is emptied before `followup` is issued.** Each step is asked one question: **does it read the
49
44
  merge result?**
50
45
 
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:
46
+ - **It does — it stays after `followup`**: `pnpm josh ms`, `pnpm josh issue:state <N>`,
47
+ `pnpm josh epic:next`, `pnpm josh backlog:next --exclude <N>`, `pnpm josh lane:close` /
48
+ `pnpm josh lane:list`. **De-duplicating a step is not removing it** — none is dropped or answered
49
+ from memory.
50
+ - **It does not — it is composed in the turn that issues `followup`**: the epic progress counter
51
+ *values* and the completion report body. **Only the write follows the merge.**
52
+ - **`pnpm josh cost --cut` stays after the merge**, though it reads nothing from it (`backlogrun-progress.md`
53
+ → "The check is asked at every merge").
54
+
55
+ **Beside a backgrounded command runs only work that writes nothing to the working tree**:
65
56
 
66
57
  | While this runs | Do this beside it |
67
58
  | --------------- | ----------------- |
68
59
  | `pnpm josh gate` | a subagent running `/code-review` with the brief `pnpm josh review:brief` prints |
69
60
  | `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
61
  | 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` |
62
+ | `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
63
 
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".
64
+ **The turn never ends at the push.** The `pnpm josh git -y` completion resumes the run, and that turn
65
+ goes straight through any branch-2 filing and `pnpm josh epic:bundle` to `pnpm josh followup`. `pnpm
66
+ josh rule:guard` refuses the foreground push (`prompts/collaboration-workflow/rule-delivery.md`); the
67
+ push reissued detached is not refused again (`docs/maintainers/background-commands-rationale.md` → "Why
68
+ the push is guarded").
79
69
 
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.
70
+ **One turn does end before the push: a dispatched lane child's pre-gate cut** — `pre-gate-cut.md` →
71
+ "Taking the cut".
83
72
 
84
73
  **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
74
+ hold: its background Bash tasks are killed when its turn ends.** It hands the gate-to-merge region to a
75
+ foreground `pnpm josh ship --detach` (`chain-rule.md` step 0); `pnpm josh rule:guard` refuses a
87
76
  backgrounded `josh gate` / `git` / `followup` / `ship` there, and the `Stop` hook sends a child with a
88
77
  task still running back to wait.
89
78
 
@@ -1,113 +1,106 @@
1
1
  # `backlogrun` — running a child (shared mechanics, delegation, liveness, session setup)
2
2
 
3
- Point-of-use, read one section at a time from `backlogrun.md` → "The route table" (rationale: `docs/maintainers/backlogrun-child-rationale.md` → "Why the file is read by section").
3
+ Point-of-use, read one section at a time from `backlogrun.md` → "The route table". Reasons:
4
+
5
+ - `docs/maintainers/backlogrun-child-rationale.md` → "Why the file is read by section"
6
+ - `docs/maintainers/backlogrun-child-rationale.md` → "Why a bare Issue promotes itself under `backlogrun` but not under `fullrun`"
7
+ - `docs/maintainers/backlogrun-child-rationale.md` → "Why each child runs in a delegated unit"
8
+ - `docs/maintainers/backlogrun-child-rationale.md` → "Why the summary is bounded the way it is"
9
+ - `docs/maintainers/backlogrun-child-rationale.md` → "Why the audit runs before the first child"
10
+ - `docs/maintainers/backlogrun-child-rationale.md` → "Why `josh latest` is hoisted to the session"
11
+ - `docs/maintainers/backlogrun-child-rationale.md` → "Why the preflight is part of the claim"
4
12
 
5
13
  ## Running a child — the shared mechanics
6
14
 
7
- Everything below runs **one child** — of a named epic, or of the opted-in backlog. A single-issue named item, a named epic's child and a bare backlog child all run the same `fullrun` in the same way, and this part is the single source of how. A named epic runs these mechanics over its own children until every one is processed, then the run advances to the next named item.
15
+ This file is the single source of how **one child** runs — a named single-issue item, a named epic's
16
+ child and a bare backlog child all run the same `fullrun`. A named epic runs these mechanics over its
17
+ children until every one is processed, then the run advances to the next named item.
8
18
 
9
19
  ## When `#N` is not an epic
10
20
 
11
- `backlogrun` accepts an ordinary Issue as well as an epic. `backlogrun #<N>` on an Issue with no task list
12
- runs `#<N>` as a `fullrun` and then finishes. Inside `backlogrun #<N>`, a prerequisite or a split found
13
- mid-run does **not** stop the run (rationale: `docs/maintainers/backlogrun-child-rationale.md` → "Why a
14
- bare Issue promotes itself under `backlogrun` but not under `fullrun`"):
15
-
16
- 1. File the new Issue(s) with the matching route label — `route:split` for a split, `route:tier-a`
17
- for a prerequisite — no confirmation.
18
- 2. **Stash the work in progress and remove `in-progress` from `#<N>`**, exactly as steps 2 and 4 of
19
- "A prerequisite discovered mid-run" do — `git stash push -u -m "..."` with the `-u`, the
20
- `gh api repos/{owner}/{repo}/issues/<N>/comments` post that records the stash, and
21
- `pnpm josh run:release <N>`, which removes the label with the hold.
21
+ `backlogrun #<N>` on an Issue with no task list runs `#<N>` as a `fullrun` and finishes. A prerequisite
22
+ or a split found mid-run does **not** stop it:
23
+
24
+ 1. File the new Issue(s) — `route:split` for a split, `route:tier-a` for a prerequisite — no
25
+ confirmation.
26
+ 2. **Stash and remove `in-progress`**, as steps 2 and 4 of "A prerequisite discovered mid-run" do:
27
+ `git stash push -u -m "..."`, a `gh api repos/{owner}/{repo}/issues/<N>/comments` post recording the
28
+ stash, and `pnpm josh run:release <N>`.
22
29
  3. **Ask `pnpm josh epic:bundle <N>` whether an epic already tracks `#<N>` before creating one.**
23
30
 
24
31
  | Answer | What to do |
25
32
  | --- | --- |
26
- | An epic `#<E>` already tracks `#<N>` | `pnpm josh epic --add <E> <P> --before <N>` for a prerequisite, or `--add <E> <N1> ...` for a split. **Do not create a second epic.** Continue the loop against `#<E>` |
27
- | No epic tracks it | Create one — the command depends on what was found (table below) |
28
- | **The command could not answer** — a non-zero exit, `Could not confirm which epic already tracks these — do not place this issue in one.`, or a ⚠ warning about a truncated listing (beginning `⚠ The epic listing …`, in either form `hit its …-epic cap` / `stopped at the …-issue page ceiling`) above a `Nothing to bundle.` verdict; `⚠ Could not read #N.` is one failed relation read and voids nothing, and a definitive answer stands even beside a warning | Park `#<N>` with `needs-decision` and report. "Could not tell" is not "no epic tracks it" |
33
+ | An epic `#<E>` already tracks `#<N>` | `pnpm josh epic --add <E> <P> --before <N>` (prerequisite) or `--add <E> <N1> ...` (split). **Do not create a second epic**; continue against `#<E>` |
34
+ | No epic tracks it | Create one (table below) |
35
+ | **The command could not answer** | Park `#<N>` with `needs-decision` and report — "could not tell" is not "no epic" |
36
+
37
+ "Could not answer" is a non-zero exit, `Could not confirm which epic already tracks these — do not
38
+ place this issue in one.`, or a `⚠ The epic listing …` truncation warning (`hit its …-epic cap` /
39
+ `stopped at the …-issue page ceiling`) above `Nothing to bundle.`. `⚠ Could not read #N.` voids
40
+ nothing, and a definitive answer stands beside a warning.
29
41
 
30
- When creating one, `#<N>` is itself one of the deliverables — this path always takes the
31
- keep-as-a-child arm of `split-assessment.md`'s promote-or-create branch. Which command depends on
32
- what was found, because `--ordered` makes the argument order the dependency chain:
42
+ `#<N>` is itself one of the deliverables (the keep-as-a-child arm of `split-assessment.md`).
43
+ `--ordered` makes the argument order the dependency chain:
33
44
 
34
45
  | Found | Command |
35
46
  | --- | --- |
36
- | A prerequisite `<P>` | `pnpm josh epic "<title>" <P> <N> --ordered` — the prerequisite comes **first** |
47
+ | A prerequisite `<P>` | `pnpm josh epic "<title>" <P> <N> --ordered` — the prerequisite **first** |
37
48
  | A split into independent children | `pnpm josh epic "<title>" <N> <N1> ...` — **no `--ordered`** |
38
- | A split whose children do have an order | `pnpm josh epic "<title>" ... --ordered`, arguments in that order |
39
-
40
- 4. **Run `pnpm josh epic:audit <E>` now**, not earlier — there is no epic to audit until step 3.
41
- 5. **Do not stop.** Continue into the loop below against the new epic `#<E>`.
42
-
43
- **Nothing found means no epic.** If `#<N>` reaches its merge without a prerequisite or a split turning
44
- up, the run finishes there. An epic is created only when there is a second child to put in it.
49
+ | A split whose children do have an order | `pnpm josh epic "<title>" ... --ordered`, in that order |
45
50
 
46
- **Every guard below applies on this path unchanged** — 30 children, 10 Issues filed, 3 consecutive
47
- failures.
51
+ 4. **Run `pnpm josh epic:audit <E>` now** — there is no epic to audit before step 3.
52
+ 5. **Do not stop.** Continue into the loop against `#<E>`.
48
53
 
49
- **This does not let `fullrun` promote itself.** A `fullrun` that discovered a split still files the
50
- children and the epic and then **stops** (`split-assessment.md` → "Finding a split mid-run stops the
51
- run").
54
+ - **Nothing found means no epic** — the run finishes at `#<N>`'s merge.
55
+ - **Every guard applies unchanged** — 30 children, 10 Issues filed, 3 consecutive failures.
56
+ - **`fullrun` does not promote itself** — it files and **stops** (`split-assessment.md` → "Finding a
57
+ split mid-run stops the run"). `josh epic:next` still refuses an Issue with no task list.
58
+ - **A bare Issue named beside an epic is a mistyped command.** Named alone, the refusal is the answer;
59
+ among several, it is **skipped** — `backlogrun #<E> --only #<N>` exits 0, notes the skip on stderr
60
+ and **never runs `#<N>`**. To do both, type `backlogrun #<N>` after the epic.
52
61
 
53
- **`josh epic:next` is not changed by any of this.** It still refuses an Issue with no task list; the
54
- acceptance of a bare Issue belongs to `backlogrun`.
55
-
56
- **Naming a bare Issue beside an epic is a mistyped command rather than a second entry.** Where one
57
- reference is named, the refusal is the whole answer. Where several are, a task-listless reference is
58
- **skipped** so the other epics keep running — `backlogrun #<E> --only #<N>` with `#<N>` an ordinary Issue exits
59
- 0, notes the skip on standard error, and **never runs `#<N>`**. A run that means to do both types
60
- `backlogrun #<N>` on its own after the epic.
61
62
  ## Each child runs in a delegated unit
62
63
 
63
- **A child is not run in the parent loop's context** — **whatever offers a child — the loop, or a
64
- person clearing a label — the child is handed to a lane, never to the parent.** `pnpm josh delegate
65
- epic-child` answers `delegate`; in a lane the unit is a detached process started by `pnpm josh
66
- lane:launch` (`backlogrun-lanes.md` → "Opening one lane and dispatching its child"), with the invoking
67
- CLI's `worker` profile — Claude Code defaults to Anthropic `claude-opus-5-5` / `medium`
68
- (`docs/josh-commands-run.md` → "`josh lane:dispatch`", the single source).
69
- Where no isolated unit exists, run the child in the parent's context; the hand-off is still asked at
70
- every merge. Rationale: `docs/maintainers/backlogrun-child-rationale.md` → "Why each child runs in a
71
- delegated unit".
72
-
73
- **The parent reads GitHub, never the summary** — `pnpm josh issue:state <N>` (or `run:merge`) is the
74
- verifier; **never advance the loop on the summary alone**.
64
+ **Whatever offers a child — the loop, or a person clearing a label — the child is handed to a lane,
65
+ never run in the parent's context.** `pnpm josh delegate epic-child` answers `delegate`; the unit is a
66
+ detached process from `pnpm josh lane:launch` (`backlogrun-lanes.md` → "Opening one lane and
67
+ dispatching its child") with the CLI's `worker` profile — Claude Code defaults to Anthropic
68
+ `claude-opus-5-5` / `medium` (`docs/josh-commands-run.md` → "`josh lane:dispatch`"). With no isolated
69
+ unit, run the child in the parent's context and still ask the hand-off at every merge.
75
70
 
76
- **The brief names the invocation it descends from** — e.g. `backlogrun #<E> --only`, the child number,
77
- and that the child runs as `fullrun #<N>` under that authorization; the unit refuses a brief without it.
71
+ - **The parent reads GitHub, never the summary** — `pnpm josh issue:state <N>` (or `run:merge`)
72
+ verifies; **never advance the loop on the summary alone**.
73
+ - **The brief names the invocation it descends from** — e.g. `backlogrun #<E> --only`, the child
74
+ number, and that it runs as `fullrun #<N>` under that authorization; the unit refuses a brief without
75
+ it.
78
76
 
79
77
  ### What the summary carries, and how long it may be
80
78
 
81
- **The summary carries only what GitHub does not, in at most 25 lines; the brief states the bound.**
82
- Rationale: `docs/maintainers/backlogrun-child-rationale.md` → "Why the summary is bounded the way it is".
79
+ **Only what GitHub does not, in at most 25 lines; the brief states the bound.**
83
80
 
84
- - **Kept**: `Cause` / `Fix` / `Result`; every verification result not closed the ordinary way, named
85
- as such; observations that could bite later — **the only route a child's discretionary observation
86
- has** (`observation-filing.md` → "A delegated child does not take this route"); decisions not already
87
- logged; what was left undone, and under whose authority.
88
- - **Cut**: the changed-file list, per-round review detail, and restated rules.
81
+ - **Kept**: `Cause` / `Fix` / `Result`; every verification not closed the ordinary way, named as such;
82
+ observations that could bite later — **a child's only route for one** (`observation-filing.md` → "A
83
+ delegated child does not take this route"); decisions not yet logged; what was left undone, on whose
84
+ authority.
85
+ - **Cut**: the changed-file list, per-round review detail, restated rules.
89
86
 
90
87
  The person-facing report (`prompts/collaboration-workflow/report-format.md` → 「完了報告(セッション向け)」)
91
88
  is unchanged.
92
89
 
93
90
  ## A delegated unit that stopped without reporting
94
91
 
95
- **Hand the child to the unit without blocking on its return, and poll** — a stopped unit leaves no
96
- notification behind. Once its output has been unchanged for the silent-unit window, read
97
- `backlogrun-recovery.md` → "A delegated unit that stopped without reporting" and ask
98
- `pnpm josh run:liveness`.
92
+ **Hand the child off without blocking, and poll** — a stopped unit leaves no notification. Once its
93
+ output is unchanged for the silent-unit window, read `backlogrun-recovery.md` → "A delegated unit that
94
+ stopped without reporting" and ask `pnpm josh run:liveness`.
99
95
 
100
96
  ## Audit before the first child
101
97
 
102
- Run `pnpm josh epic:audit <E>` before step 1 below. **When the run began from a bare Issue there is
103
- nothing to audit yet** — that path runs the audit at the moment it creates the epic instead. Errors
104
- stop the run; warnings are read and carried on past. Fixing what it finds is Tier A. Rationale:
105
- `docs/maintainers/backlogrun-child-rationale.md` → "Why the audit runs before the first child".
98
+ Run `pnpm josh epic:audit <E>` before the first child; a run begun from a bare Issue audits when it
99
+ creates the epic. Errors stop the run; warnings are read and passed. Fixing a finding is Tier A.
106
100
 
107
101
  ## `josh latest` runs once per session, not once per child
108
102
 
109
- `josh latest` belongs to the **session**, not to a child. Ask once, the first time the loop below hands
110
- back a child number — before implementing that child — and never again:
103
+ Ask once, the first time the loop hands back a child number, before implementing it:
111
104
 
112
105
  ```bash
113
106
  pnpm josh latest:scope # → required | skip ; the reason on stderr
@@ -117,20 +110,14 @@ pnpm josh latest # on `required` only
117
110
  pnpm josh stash:pop "backlogrun: josh latest #<N>" # only if you stashed above — by message, not a positional pop
118
111
  ```
119
112
 
120
- On `required`, load the `dependency-update` skill; `latest-gate.md` is the single source. **Session,
121
- not run** — each session updates its own checkout, and a resumed `backlogrun` asks again. **The lock
122
- file lands with the first child's `pnpm josh git -y`**; fix a failing bump forward. **`josh latest` is
123
- never run inside a lane** (`pnpm josh latest:guard` refuses it) — with lanes the parent runs it in the
124
- primary checkout (`backlogrun-lanes.md` → "Once per repository, before the first lane opens").
125
-
126
- Rationale: `docs/maintainers/backlogrun-child-rationale.md` → "Why `josh latest` is hoisted to the
127
- session".
113
+ On `required`, load the `dependency-update` skill; `latest-gate.md` is the single source. A resumed
114
+ `backlogrun` asks again. **The lock file lands with the first child's `pnpm josh git -y`**; fix a
115
+ failing bump forward. **Never inside a lane** (`pnpm josh latest:guard` refuses) — the parent runs it
116
+ in the primary checkout (`backlogrun-lanes.md` → "Once per repository, before the first lane opens").
128
117
 
129
118
  ## Preflight — the child's claim asks it
130
119
 
131
- `pnpm josh run:hold <N>`, the first call of the child's `fullrun`, checks for an interrupted run's
132
- leftovers before it claims the tree, and prints the step for each answer (`reclaim` / `resume` /
133
- `park`) on stderr — follow it, and report a reclaim or resume with its stash reference. The answers are
134
- `docs/josh-commands-run.md` → "`josh run:hold`"; rationale:
135
- `docs/maintainers/backlogrun-child-rationale.md` → "Why the preflight is part of the claim".
136
-
120
+ `pnpm josh run:hold <N>`, the child's first call, checks for an interrupted run's leftovers before
121
+ claiming the tree and prints the step for each answer (`reclaim` / `resume` / `park`) on stderr —
122
+ follow it, and report a reclaim or resume with its stash reference (`docs/josh-commands-run.md` →
123
+ "`josh run:hold`").