@joshuafolkken/kit 1.1128.0 → 1.1166.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 (192) hide show
  1. package/.claude/agents/investigator.md +17 -0
  2. package/.claude/settings.json +5 -4
  3. package/.claude/skills/epic-commands/SKILL.md +27 -239
  4. package/.claude/skills/epic-commands/epic-bundle.md +115 -0
  5. package/.claude/skills/epic-commands/execution-waves.md +126 -0
  6. package/.claude/skills/workflow-commands/SKILL.md +48 -194
  7. package/.claude/skills/workflow-commands/background-commands.md +1 -1
  8. package/.claude/skills/workflow-commands/backlogrun-child.md +12 -123
  9. package/.claude/skills/workflow-commands/backlogrun-lanes.md +11 -60
  10. package/.claude/skills/workflow-commands/backlogrun-park.md +10 -8
  11. package/.claude/skills/workflow-commands/backlogrun-progress.md +19 -175
  12. package/.claude/skills/workflow-commands/backlogrun-recovery.md +155 -0
  13. package/.claude/skills/workflow-commands/backlogrun-steps.md +64 -144
  14. package/.claude/skills/workflow-commands/backlogrun.md +5 -4
  15. package/.claude/skills/workflow-commands/chain-rule.md +3 -2
  16. package/.claude/skills/workflow-commands/delegation.md +7 -3
  17. package/.claude/skills/workflow-commands/entry-sequence.md +62 -0
  18. package/.claude/skills/workflow-commands/followup.md +104 -181
  19. package/.claude/skills/workflow-commands/fullrun-steps.md +8 -9
  20. package/.claude/skills/workflow-commands/fullrun.md +16 -73
  21. package/.claude/skills/workflow-commands/halfrun.md +10 -36
  22. package/.claude/skills/workflow-commands/into-target.md +4 -4
  23. package/.claude/skills/workflow-commands/issue-comments.md +7 -8
  24. package/.claude/skills/workflow-commands/issue-scout.md +6 -6
  25. package/.claude/skills/workflow-commands/kickoff.md +6 -6
  26. package/.claude/skills/workflow-commands/needs-human-review.md +6 -6
  27. package/.claude/skills/workflow-commands/observation-filing.md +21 -172
  28. package/.claude/skills/workflow-commands/observation-ledger.md +150 -0
  29. package/.claude/skills/workflow-commands/pre-gate-cut.md +33 -93
  30. package/.claude/skills/workflow-commands/prerequisite.md +6 -6
  31. package/.claude/skills/workflow-commands/progress-watcher.md +90 -0
  32. package/.claude/skills/workflow-commands/prrun.md +5 -5
  33. package/.claude/skills/workflow-commands/retrospective.md +9 -9
  34. package/.claude/skills/workflow-commands/split-assessment.md +2 -2
  35. package/.claude/skills/workflow-commands/target-repository.md +2 -2
  36. package/.claude/skills/workflow-commands/working-tree-hold.md +7 -5
  37. package/.codex/hooks.json +4 -4
  38. package/AGENTS.md +1 -6
  39. package/CLAUDE.md +58 -120
  40. package/GEMINI.md +1 -6
  41. package/SECURITY.md +1 -0
  42. package/dist/CLAUDE.md +58 -120
  43. package/dist/hooks/batch-guard.js +4 -4
  44. package/dist/hooks/{chunk-MKVGBQPA.js → chunk-5KTCMCOT.js} +14 -1
  45. package/dist/hooks/{chunk-NXYMNPUQ.js → chunk-A6P7PN7P.js} +59 -21
  46. package/dist/hooks/{chunk-77J7IEQM.js → chunk-ANJ2WGFD.js} +1 -1
  47. package/dist/hooks/{chunk-4JZDP5X5.js → chunk-DYAVAM6S.js} +572 -127
  48. package/dist/hooks/{chunk-7HVB7SZG.js → chunk-ENA7P5FB.js} +4 -4
  49. package/dist/hooks/{chunk-M7QKEKWO.js → chunk-GU5MATVE.js} +214 -85
  50. package/dist/hooks/chunk-GYNGP7HI.js +56 -0
  51. package/dist/hooks/{chunk-5SD2YM7Z.js → chunk-URJA6XY4.js} +4 -4
  52. package/dist/hooks/{chunk-XYUIQOW3.js → chunk-V2BTOZHT.js} +6 -4
  53. package/dist/hooks/{chunk-AIOIOMPX.js → chunk-ZDZ555YH.js} +225 -78
  54. package/dist/hooks/codex-hook-adapter.js +10 -10
  55. package/dist/hooks/duplicate-read-guard.js +5 -5
  56. package/dist/hooks/format-edited.js +2 -2
  57. package/dist/hooks/inputs.json +186 -184
  58. package/dist/hooks/investigation-guard.js +5 -5
  59. package/dist/hooks/pretool-guard.js +11 -10
  60. package/dist/hooks/stop-guard.js +5 -5
  61. package/dist/josh.js +33 -3
  62. package/dist/version/index.js +5 -1
  63. package/package.json +7 -4
  64. package/prompts/collaboration-workflow/file-edits.md +11 -10
  65. package/prompts/collaboration-workflow/gh-rest.md +2 -4
  66. package/prompts/collaboration-workflow/glossary.md +1 -1
  67. package/prompts/collaboration-workflow/issue-citation.md +5 -9
  68. package/prompts/collaboration-workflow/issue-template.md +40 -115
  69. package/prompts/collaboration-workflow/operating-rules.md +4 -5
  70. package/prompts/collaboration-workflow/output-bounds.md +12 -78
  71. package/prompts/collaboration-workflow/overview.md +7 -13
  72. package/prompts/collaboration-workflow/plan-comment.md +11 -39
  73. package/prompts/collaboration-workflow/principles.md +3 -4
  74. package/prompts/collaboration-workflow/report-format.md +28 -74
  75. package/prompts/collaboration-workflow/residency.md +12 -109
  76. package/prompts/collaboration-workflow/rule-delivery.md +98 -97
  77. package/prompts/collaboration-workflow/shell-body.md +3 -13
  78. package/prompts/collaboration-workflow/turn-batching.md +14 -88
  79. package/prompts/collaboration-workflow/upstream-interrupt.md +12 -14
  80. package/prompts/collaboration-workflow/wip-cap.md +6 -45
  81. package/prompts/collaboration-workflow.md +1 -13
  82. package/prompts/review-rubric.md +8 -71
  83. package/prompts/review.md +25 -55
  84. package/prompts/testing-guide.md +18 -67
  85. package/scripts/agent/agent-role-profile.ts +1 -1
  86. package/scripts/agent/codex-hooks.ts +3 -12
  87. package/scripts/backlog/backlog-budget.ts +1 -1
  88. package/scripts/backlog/backlog-drive-cli.ts +4 -3
  89. package/scripts/backlog/backlog-drive-offer-argv.ts +10 -1
  90. package/scripts/backlog/backlog-offer.ts +6 -6
  91. package/scripts/behavior/behavior-rules.ts +11 -4
  92. package/scripts/delegation/delegation-policy.ts +9 -1
  93. package/scripts/delegation/investigation-guard.ts +1 -1
  94. package/scripts/delegation/investigation-reads.ts +109 -23
  95. package/scripts/discovery/repo-discovery.ts +21 -7
  96. package/scripts/discovery/repo-origin.ts +26 -0
  97. package/scripts/discovery/repo-party.ts +42 -1
  98. package/scripts/document/backlogrun-parent-read-set.ts +14 -15
  99. package/scripts/document/capped-print.ts +74 -0
  100. package/scripts/document/document-byte-budget.ts +34 -20
  101. package/scripts/document/document-section-cli.ts +4 -3
  102. package/scripts/document/entry-read-budget.ts +21 -9
  103. package/scripts/document/lane-child-read-set.ts +12 -14
  104. package/scripts/document/read-set-cli.ts +4 -4
  105. package/scripts/document/read-set-point-of-use.ts +10 -2
  106. package/scripts/document/resident-budget.ts +47 -0
  107. package/scripts/epic/epic-shape.ts +10 -13
  108. package/scripts/epic/epic-solo.ts +1 -1
  109. package/scripts/exports/unused-members-cli.ts +7 -3
  110. package/scripts/gate/scoped-green.ts +25 -14
  111. package/scripts/gh/git-gh-api-path.ts +7 -0
  112. package/scripts/hooks/pretool-guard-cli.ts +2 -2
  113. package/scripts/hooks/pretool-guard.ts +45 -2
  114. package/scripts/hooks/run-hook.sh +41 -0
  115. package/scripts/init/claude-kit-only-settings.ts +29 -0
  116. package/scripts/init/hook-command-rewrite.ts +18 -35
  117. package/scripts/init/hook-launch.ts +21 -32
  118. package/scripts/init/init-copy-content.ts +8 -2
  119. package/scripts/init/initial-commit.ts +24 -0
  120. package/scripts/init/start-exec.ts +16 -3
  121. package/scripts/init/start-steps.ts +8 -12
  122. package/scripts/issue/issue-auto-ok.ts +95 -0
  123. package/scripts/issue/issue-file-cli.ts +53 -7
  124. package/scripts/issue/issue-file.ts +28 -5
  125. package/scripts/issue/issue-labels.ts +12 -12
  126. package/scripts/issue/issue-rank.ts +1 -1
  127. package/scripts/issue/issue-read-cli.ts +4 -3
  128. package/scripts/issue/issue-read.ts +2 -2
  129. package/scripts/issue/issue-report-failures.ts +6 -2
  130. package/scripts/issue/issue-scout-cli.ts +2 -2
  131. package/scripts/issue/issue-state-cli.ts +2 -2
  132. package/scripts/issue/issue-state.ts +2 -2
  133. package/scripts/issue/issue-wip.ts +70 -0
  134. package/scripts/josh/hook-decision.ts +17 -0
  135. package/scripts/josh/josh-commands-development.ts +10 -0
  136. package/scripts/josh/josh-commands-issue.ts +2 -2
  137. package/scripts/josh/josh-commands-lane.ts +1 -1
  138. package/scripts/josh/josh-commands-project.ts +7 -0
  139. package/scripts/lane/lane-await.ts +46 -2
  140. package/scripts/lane/lane-cli.ts +11 -13
  141. package/scripts/lines/bytes-command.ts +29 -6
  142. package/scripts/observations/observation-ledger-line.ts +1 -1
  143. package/scripts/release/github-release-environment.ts +1 -0
  144. package/scripts/release/github-release.ts +103 -17
  145. package/scripts/release/release-progress.ts +167 -0
  146. package/scripts/release/release-publish.ts +19 -8
  147. package/scripts/release/release-tag.ts +22 -8
  148. package/scripts/rules/decision-oracle-stage.ts +1 -1
  149. package/scripts/rules/decision-oracle.ts +6 -6
  150. package/scripts/rules/delivered-rules.ts +11 -11
  151. package/scripts/rules/direct-pr-create.ts +110 -0
  152. package/scripts/rules/file-body.ts +98 -42
  153. package/scripts/rules/filing-cap.ts +2 -2
  154. package/scripts/rules/filing-offer.ts +1 -1
  155. package/scripts/rules/gh-api.ts +18 -1
  156. package/scripts/rules/implementation-cut.ts +3 -1
  157. package/scripts/rules/lane-background.ts +67 -10
  158. package/scripts/rules/permission-guards.ts +10 -2
  159. package/scripts/rules/stop-rules.ts +4 -4
  160. package/scripts/rules/test-declared-commit.ts +1 -1
  161. package/scripts/rules/third-party-write.ts +56 -12
  162. package/scripts/run/run-carry-cli.ts +3 -1
  163. package/scripts/run/run-carry-conversation.ts +94 -0
  164. package/scripts/run/run-carry-reclaim.ts +37 -0
  165. package/scripts/run/run-carry.ts +21 -5
  166. package/scripts/run/run-cut-handoff.ts +21 -1
  167. package/scripts/run/run-entry-cli.ts +11 -3
  168. package/scripts/run/run-hold-cli.ts +16 -2
  169. package/scripts/run/run-label.ts +50 -0
  170. package/scripts/run/run-merge-steps.ts +12 -4
  171. package/scripts/run/run-merge.ts +1 -1
  172. package/scripts/run/run-prep-cli.ts +6 -2
  173. package/scripts/run/run-prep.ts +17 -0
  174. package/scripts/run/run-ship-preflight.ts +34 -3
  175. package/scripts/run/run-ship-review-steps.ts +1 -1
  176. package/scripts/run/run-ship-review.ts +26 -5
  177. package/scripts/run/run-step-cli.ts +20 -7
  178. package/scripts/run/run-wake-driver.ts +24 -1
  179. package/scripts/run/run-wake-session.ts +2 -1
  180. package/scripts/test/test-declared-logic.ts +1 -1
  181. package/scripts/test/test-related.ts +1 -6
  182. package/scripts/test/test-unit-guard.ts +21 -7
  183. package/scripts/time-runtime/time-batch-guard.ts +52 -16
  184. package/scripts/time-runtime/time-density-hook.ts +20 -2
  185. package/scripts/time-runtime/time-density.ts +4 -3
  186. package/scripts/time-runtime/time-markers.ts +15 -4
  187. package/scripts/time-runtime/time-spans.ts +4 -0
  188. package/scripts/version/npm-registry.ts +11 -1
  189. package/templates/workflows/ci.yml +9 -1
  190. package/templates/workflows/github-release.yml +13 -25
  191. package/.claude/skills/workflow-commands/followup-reference.md +0 -118
  192. package/dist/hooks/chunk-QVLT52OV.js +0 -464
@@ -6,64 +6,40 @@ description: The procedures for the Issue-driven shorthand commands `kickoff`, `
6
6
  # Issue-driven workflow commands
7
7
 
8
8
  `kickoff`, `fullrun`, `halfrun`, `prrun` and `backlogrun` are the shorthand commands this
9
- package's collaboration workflow is built on. Their procedures live here rather than in `CLAUDE.md`
10
- because each one applies only while its own command is running.
11
-
12
- Each topic file under `prompts/collaboration-workflow/` sources its own rule; this skill sources the
13
- procedures. Neither restates the other.
9
+ package's collaboration workflow is built on. **This file is their manifest — triggers and pointers,
10
+ never a procedure** (joshuafolkken/kit#3174): each rule is stated once, in the file its row names.
14
11
 
15
12
  ## 0. The rule that fires before any of them — explicit invocation
16
13
 
17
14
  **Never start a `kickoff` / `halfrun` / `prrun` / `fullrun` / `backlogrun` workflow (including their
18
- `#N` and `new` variants) unless the user has typed the keyword in the current turn's prompt.** This rule is also
19
- resident in the AI documents, because it has to hold when this skill has *not* been loaded.
20
-
21
- - Conversational requests like "implement X", "fix Y", "open a PR for Z" are **NOT** implicit
22
- invocations. Even if the task clearly fits one of these workflows, do not infer authorization from
23
- the request shape.
24
- - Do **NOT** ask confirmation questions like "May I proceed with `halfrun new`?" or "Shall I run
25
- `fullrun`?". A confirmation prompt is not an acceptable substitute for explicit invocation.
26
- - Instead, **prompt the user to type the command themselves**, with the exact phrasing: "Please run
27
- \`<command>\` to start this task."
28
- - The rule applies even when the user authorized a related workflow in an earlier turn. Each
29
- invocation must be re-typed by the user in the current turn.
30
-
31
- **A session cut inside a declared budget is not a new invocation — for `backlogrun` alone**; its
32
- single source is `backlogrun-steps.md` → "The session cut is inside the invocation".
15
+ `#N` and `new` variants) unless the user has typed the keyword in the current turn's prompt.** Its
16
+ single source is `CLAUDE.md` → "Explicit invocation required (MANDATORY)", resident because it holds
17
+ when this skill is not loaded. **A session cut inside a declared budget is not a new invocation — for `backlogrun`
18
+ alone**: `backlogrun-steps.md` → "The session cut is inside the invocation".
33
19
 
34
20
  ## 1. Which file to read
35
21
 
36
- Read this file, then the one for the command that was typed. The command file is a **manifest** — the
37
- ordered steps as terse triggers and pointers; `pnpm josh run:step <N>` prints the run's next single
38
- action — computed from the event stream, the carry record and the issue state, never the conversation
39
- (`run:next` is its pre-implementation degenerate form) — and each step's detail is read on demand from
40
- the file its pointer names (for `fullrun`, the step lists are `fullrun-steps.md`).
22
+ Read this file, then the files the typed command's row names. A command file is a **manifest** of
23
+ terse triggers and pointers; `pnpm josh run:step <N>` prints the run's next single action, computed
24
+ from the event stream, the carry record and the issue state, never the conversation.
41
25
 
42
26
  | Typed keyword | Read |
43
27
  | ---------------------------------------- | ------------------------------------------- |
44
28
  | `kickoff` / `kickoff #N` / `kickoff new` | `kickoff.md` |
45
- | `fullrun` / `fullrun #N` / `fullrun new` | `fullrun.md` |
46
- | `halfrun` / `halfrun #N` / `halfrun new` | `halfrun.md` |
47
- | `prrun` / `prrun #N` / `prrun new` | `prrun.md` — the difference over `fullrun.md`, read with it |
29
+ | `fullrun` / `fullrun #N` / `fullrun new` | `fullrun.md` + `entry-sequence.md` |
30
+ | `halfrun` / `halfrun #N` / `halfrun new` | `halfrun.md` + `entry-sequence.md` |
31
+ | `prrun` / `prrun #N` / `prrun new` | `prrun.md` — the difference over `fullrun.md`, read with it and `entry-sequence.md` |
48
32
  | `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 |
49
33
 
50
- Each command manifest cites `split-assessment.md` → "The question" — the split decision, read at the
51
- entry as a section; the split-handling detail (what each entry does with the answer, promote or create
52
- an epic) is read on demand only when a split is found (joshuafolkken/kit#2189). `backlogrun`'s row
53
- lists `backlogrun.md` alone: its parent orchestrates and never implements, so `fullrun.md` and
54
- `split-assessment.md` are read by a dispatched child in its own delegated unit (`backlogrun-child.md`).
55
- Every procedure for *running* a `backlogrun` item — lanes (`backlogrun-lanes.md`), park-and-continue,
56
- the guards — stays `backlogrun.md`'s. The on-demand sections `into-target.md` (an `into` suffix) and `target-repository.md`
57
- (an `owner/repo#` prefix) are read only when their trigger is typed, and §3's residency procedure lives
58
- in `prompts/collaboration-workflow/residency.md`, reached only when a rule is placed, moved or retired.
34
+ `entry-sequence.md` holds the entry sequence and stop branches `fullrun`, `halfrun` and `prrun` share;
35
+ each manifest carries only its difference. `split-assessment.md` → "The question" is read at the
36
+ entry as a section, its split-handling detail only when a split is found.
59
37
 
60
38
  ### The fetch is one `Read` call per file
61
39
 
62
- **Fetch each file above with one `Read` call of its own — never `cat`, and never two of them in one
63
- command.** The distributed `.claude/settings.json` caps a Bash result at `BASH_MAX_OUTPUT_LENGTH`
64
- characters, and every document over it is handed back by `cat` as a middle-truncated preview, then
65
- read a second time. `pnpm josh read:set [<keyword>]` prints the cap and marks every file that exceeds
66
- it; `pnpm josh doc:read <file>` is the Bash-cap-safe whole-file read.
40
+ **Fetch each file above with one `Read` call of its own — never `cat`, never two in one command.** A
41
+ Bash result is capped at `BASH_MAX_OUTPUT_LENGTH` characters and truncates a longer document;
42
+ `pnpm josh doc:read <file>` is the cap-safe whole-file read.
67
43
 
68
44
  ### Four documents are read at the point of use, not at the entry
69
45
 
@@ -74,19 +50,13 @@ Each is fetched at its named scope, in the same turn, by the named command that
74
50
  | ----------------------- | ------------------------------------------------------------------------------ |
75
51
  | `latest-gate.md` | `pnpm josh latest:scope` answers `required` — before `josh latest` runs |
76
52
  | `followup.md` → "Run `pnpm josh followup`" | Before issuing `pnpm josh followup`, in that same turn |
77
- | `chain-rule.md` → "Run the review-to-merge chain" | Before the first `pnpm josh gate` launch (`fullrun` / `backlogrun`) — the section is how the gate starts, overlapped with the review, so it is read before the gate rather than before the `/code-review` step |
53
+ | `chain-rule.md` → "Run the review-to-merge chain" | Before the first `pnpm josh gate` launch (`fullrun` / `backlogrun`) — the gate starts overlapped with the review, so the section is read before the gate |
78
54
  | `background-commands.md` → "Background the gate and push" | Before backgrounding `pnpm josh gate` — the first long-running command a run detaches (`fullrun` / `halfrun` / `backlogrun`) |
79
55
 
80
- A `skip` answer from `latest:scope` reads nothing; `latest-gate.md` remains a whole-file read, while
81
- the other three fetch only the operational section named above. The trigger sentence for each is
82
- resident in §2 and in the command's manifest, so a run that never opens these documents still calls
83
- the right command at the right moment. `followup.md`'s post-execution reference is in
84
- `followup-reference.md`, reached through a section pointer from `followup.md`.
85
-
86
- **A lane child that parks reads `backlogrun-park.md` → "park and continue" at that point of use**, so
87
- the pointer names that heading rather than the whole file: the entry read is charged for the park
88
- procedure alone, and the rest of `backlogrun-park.md` is read only when it is reached
89
- (joshuafolkken/kit#2189).
56
+ A `skip` answer from `latest:scope` reads nothing. **A lane child that parks reads
57
+ `backlogrun-park.md` → "park and continue" at that point of use**, and **every implementing run reads
58
+ `progress-watcher.md` → "Progress while the run is quiet"** before starting `pnpm josh run:progress
59
+ --wait` once its hold is claimed (joshuafolkken/kit#3172).
90
60
 
91
61
  ### A section reference is read as a section
92
62
 
@@ -97,162 +67,46 @@ pnpm josh doc:section <file.md> "<heading>" # the section, verbatim
97
67
  pnpm josh read:set [<keyword>] # what an entry reads, and what it costs
98
68
  ```
99
69
 
100
- The section is fetched in the same turn, printed verbatim with its subsections; **a heading that does
101
- not resolve is refused, with the file's own headings listed**, as is an ambiguous prefix. The set is
102
- derived from the table above and the documents themselves, not transcribed;
103
- `scripts/document/entry-read-set.test.ts` pins the derivation and
104
- `scripts/rules/entry-read-set-document-rule.test.ts` pins this rule.
70
+ A heading that does not resolve is refused, with the file's own headings listed. The set is derived
71
+ from the table above and the documents themselves, never transcribed.
105
72
 
106
73
  ## 2. What every one of them shares
107
74
 
108
75
  Each shared rule is a **trigger, a one-line action, and the single source** the procedure is read
109
- from. The single source is where the rule is stated in full — this list is the manifest, not the
110
- procedure.
76
+ from — read at that trigger, never restated here.
111
77
 
112
78
  | Trigger | Action | Single source |
113
79
  | --- | --- | --- |
80
+ | First call of any entry | `#N`: `pnpm josh run:entry <N> --to <command>` (claims the tree, except `kickoff`); `new` (not `kickoff`): `pnpm josh run:hold`; `busy` / `unknown` stop | `working-tree-hold.md` |
81
+ | `run:entry` prints its stage line | The command sets how far a run goes, the Issue where it starts; **`start: reached` redoes nothing** — stop (at `merged`, the next line answers) | `docs/how-to/run-issues.md` |
82
+ | Same turn as the hold (not a dispatched child, not `kickoff`) | `pnpm josh cost --cut`; `under` continues, `over` stops — `run:entry` notifies and runs `run:release` (by hand for `new`) | `backlogrun-progress.md` → "The hand-off" (shared 135,000 threshold) |
83
+ | An entry typed with an `owner/repo#` prefix or a short `repo#` name | Resolve the target and its checkout; an explicit foreign owner stops the run | `target-repository.md` |
84
+ | A `new` entry typed with an `into <target>` suffix | Insert the artifact into the named epic with `pnpm josh epic --add <E> <N>` | `into-target.md` |
85
+ | Before any work starts (every entry) | The split assessment; the default is not to split — separability **and** a scope clearly over one gate must hold together; a `fullrun` / `halfrun` that finds a split files the epic and **stops** | `split-assessment.md` → "The question" |
86
+ | Before implementing (every `#N` entry) | `pnpm josh issue:read <N>` — the body and the comments; the later of a body and a comment wins | `issue-comments.md` |
87
+ | `pnpm josh issue:state <N>` answers `human_review: yes` | Implement and gate, then stop before the commit; the label is applied only by a person | `needs-human-review.md` |
114
88
  | Before implementing (every implementing entry) | `pnpm josh latest:scope`; on `required` read the doc and run `josh latest`, then load the `dependency-update` skill; `kickoff` never reaches it | `latest-gate.md` (read whole, only on `required`) |
115
- | Implementation is done | The verification gate: refactor → `pnpm josh main:merge` → `pnpm josh gate` started beside a subagent `/code-review` and joined before the commit → the two-round cap → PR opened between the rounds → merge; `kickoff` never reaches it | `chain-rule.md` → "Run the review-to-merge chain" |
116
- | While implementing | Re-run one check by name, not the whole gate — `pnpm josh lint:related`, `pnpm josh cspell:dot`, `pnpm josh test:related`; the last pair runs in front of the gate, and `pnpm josh review:brief` refuses a brief on a tree neither was green on | `chain-rule.md` |
89
+ | Before delegating any run step | `pnpm josh delegate <step>` decides eligibility, never you | `delegation.md` |
90
+ | The pre-implementation reading reaches 3 unedited files | Delegate the unread investigation; a file this run will edit is read in the main line | `delegation.md` → "The pre-implementation reading" |
91
+ | Immediately before implementation | Present the two-layer work summary (once per Issue); `kickoff` posts a plan instead | `prompts/collaboration-workflow/report-format.md` |
92
+ | While implementing | Re-run one check by name, not the whole gate — `pnpm josh lint:related`, `pnpm josh cspell:dot`, `pnpm josh test:related`; `pnpm josh review:brief` refuses a brief on a tree the last two were not green on | `chain-rule.md` |
93
+ | Implementation is done | Refactor → `pnpm josh main:merge` → `pnpm josh gate` beside a subagent `/code-review`, joined before the commit → round cap → PR → merge | `chain-rule.md` → "Run the review-to-merge chain" |
117
94
  | A review has run | Its verdict counts only once `pnpm josh review:attest --check` answers `ok`; `missing` / `mismatch` are refusals `pnpm josh followup` blocks the merge on | `chain-rule.md` → "The brief names the checkout, and a review that read another one is refused" |
95
+ | A command can take minutes | Issue it in the background; the turn never ends at the push (`pnpm josh followup` stays foreground) | `background-commands.md` → "Background the gate and push" |
118
96
  | E2E gate | The CI E2E job where the command ends in a PR (`fullrun` / `backlogrun`, enforced by `pnpm josh followup`); you run `pnpm josh test:e2e` yourself where it does not (`halfrun`) | `prompts/testing-guide.md` → "Closing the E2E gate without a human run" |
119
- | A defect in kit's own verification turns up | It runs alone, and a batch resumes only once it has merged, when three conditions all hold (a defect, in kit's own verification, making unrelated PRs answer wrongly on `main` now) — never from how serious it looks | `prompts/collaboration-workflow/wip-cap.md` → 「実行のしかた」 |
120
- | A command can take minutes | Issue it in the background; the turn never ends at the push (`pnpm josh followup` stays foreground) | §2h → `background-commands.md` → "Background the gate and push" |
121
- | `pnpm josh issue:state <N>` answers `human_review: yes` | Implement and gate, then stop before the commit | §2z → `needs-human-review.md` |
97
+ | Filing any new Issue | `pnpm josh issue:file` — it runs the `issue:scout` scan first; read its duplicate and epic answers | `issue-scout.md` |
98
+ | Another Issue here must land first | A prerequisite is a dependency, not a park — file it, stash, record the dependency; `fullrun` / `halfrun` stop, `backlogrun` continues | `prerequisite.md` |
99
+ | Something worth filing, none of the three | File it without asking (Tier A, first-party) and carry on; a delegated child returns it to the parent instead | `observation-filing.md` |
100
+ | A defect in kit's own verification turns up | It runs alone when all three conditions hold; a batch resumes once it merges | `backlogrun-lanes.md` → "Lanes — running more than one child at a time" |
122
101
  | Under `backlogrun`, a stop that would end a batch, or a named non-epic item | Park one child and continue; run a named non-epic item as a `fullrun` | `backlogrun-park.md` → "park and continue"; `backlogrun-child.md` → "When `#N` is not an epic" |
123
102
  | `backlogrun`'s authorization | The whole `auto-ok` opted-in pool as well as its named items; `pnpm josh backlog:next` offers them | `backlogrun.md` |
124
- | First call of any entry | `#N`: `pnpm josh run:entry <N> --to <command>` (claims the tree, except `kickoff`); `new` (not `kickoff`): `pnpm josh run:hold` | §2k; §2f → `working-tree-hold.md` |
125
- | Same turn as the hold (not a dispatched child, not `kickoff`) | `pnpm josh cost --cut`; `under` continues, `over` stops — `run:entry` notifies and runs `run:release` (by hand for `new`) | `backlogrun-progress.md` → "The hand-off" (shared 135,000 threshold) |
126
- | Before any work starts (every entry) | The split assessment; the default is not to split — separability **and** a scope clearly over one gate must hold together; a `fullrun` / `halfrun` that finds a split files the epic and **stops** | `split-assessment.md` → "The question" |
127
- | Another Issue here must land first | A prerequisite is a dependency, not a park (the third of four mid-run discoveries) | §2d → `prerequisite.md` |
128
- | Something worth filing, none of the three | File it without asking (Tier A, first-party) and carry on; a delegated child returns it to the parent instead | §2i → `observation-filing.md` |
129
- | `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` | §2j → `retrospective.md` |
130
- | The pre-implementation reading reaches 3 unedited files | Delegate it; a file this run will edit is read in the main line | §2b → "The pre-implementation reading" |
131
- | Before implementing (every `#N` entry) | Read the Issue's comments — the later of a body and a comment wins | §2g → `issue-comments.md` |
132
- | Immediately before implementation | Present the two-layer work summary (once per Issue); `kickoff` posts a plan instead | `prompts/collaboration-workflow/report-format.md` |
103
+ | `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` |
133
104
  | Any artifact prose (Issue bodies, comments, Telegram) | Session language (`JOSH_SESSION_LANG`, default `ja`); Issue/PR titles stay English | `prompts/collaboration-workflow/overview.md` |
134
105
  | Any mid-workflow stop | Send a `confirmation` Telegram first, so the user is alerted off-screen | `CLAUDE.md` → "Mid-workflow stop notification" |
135
106
 
136
- ## 2z. `needs-human-review` — the child that stops before its commit
137
-
138
- **Trigger:** `pnpm josh issue:state <N>` answers `human_review: yes` — asked once, before implementing.
139
- **Then:** implement and run the verification gate normally, but commit nothing — leave the tree
140
- uncommitted and unstashed, send a `confirmation` Telegram with the resume command, and stop the whole
141
- run (inside a `backlogrun` this is the one child stop that is *not* park-and-continue). **The label is
142
- applied only by a person; never apply or remove it.** The full procedure — why it stops the *end* not
143
- the *start*, why the repository stays held, and the resume — is `needs-human-review.md`, its single
144
- source, read at that trigger.
145
-
146
- ## 2a. The `into <target>` suffix — where the new Issue lands
147
-
148
- **The suffix and its procedure are `into-target.md`, read at its point of use — the moment a `new`
149
- entry (`kickoff new` / `fullrun new` / `halfrun new`) is typed with an `into <target>` suffix.** It
150
- names the epic the run's artifact joins, inserts it with `pnpm josh epic --add <E> <N>` as soon as the
151
- artifact exists, and refuses a target that is not an epic. A run given a `#N` or a bare `new` never
152
- reaches it. `into-target.md` is the single source.
153
-
154
- ## 2b. Delegating a step to a cheaper tier
155
-
156
- **Before delegating any run step, ask `pnpm josh delegate <step>`; never decide eligibility yourself.**
157
- Read `delegation.md` at the first delegation decision for its units and verification rules. An item
158
- absent from the enumeration stays in the main line. A dispatched `epic-child` that returns open with
159
- `human_review: yes` is an authorized stop, not a failed child (§2z).
160
-
161
- ### The pre-implementation reading — what goes to a unit, and from which file
162
-
163
- **When the next pre-implementation read would reach 3 files this run will not edit, delegate the
164
- unread investigation before that read.** Keep edit-target reads in the main line. The full procedure
165
- and the `file:line` verification are in `delegation.md` → "The pre-implementation reading"; the
166
- threshold is counted by `pnpm josh investigation:guard`.
167
-
168
- ## 2c. The `owner/repo#` prefix — which repository the run acts on
169
-
170
- **The prefix and its procedure are `target-repository.md`, read at its point of use — the moment an
171
- entry is typed with an `owner/repo#` prefix or a short `repo#` name.** It names the repository the run
172
- acts on; a short name expands by the session owner and is first-party by construction, an explicit
173
- foreign owner is a third-party target that stops the run, and an implementing entry resolves that
174
- repository's checkout from `pnpm josh doctor` rather than cloning. No prefix leaves the target as the
175
- session's own repository, so a run without one never reaches it. `target-repository.md` is the single
176
- source.
177
-
178
- ## 2d. A prerequisite discovered mid-run — a dependency, not a park
179
-
180
- **Trigger:** a run finds that another Issue in *this* repository has to land first. **Then:** it is
181
- still one deliverable with another in front of it — file the prerequisite with the `route:tier-a` label
182
- (scouted first, §2e), stash the work in progress with `git stash push -u` and record it on the Issue,
183
- record the dependency in the epic, and — under `fullrun` / `halfrun` — **stop**, or — under
184
- `backlogrun` — **continue** (`backlogrun-park.md` → "A prerequisite discovered mid-run"). It is the
185
- third of four mid-run discoveries, distinct from an upstream defect, a split (`split-assessment.md`)
186
- and an observation (§2i). The full table, the filing command, the `-u`/`stash:pop` steps and the
187
- 10-per-run cap are `prerequisite.md`, its single source, read at that trigger. **When the prerequisite
188
- is the run's second filing, `pnpm josh issue:fold` runs first** (§2e), and `pnpm josh rule:guard`
189
- refuses the second `pnpm josh issue:file` call until it has.
190
-
191
- ## 2e. Before filing a new Issue — `pnpm josh issue:scout`
192
-
193
- **Every new Issue is filed with `pnpm josh issue:file`, which runs the `issue:scout` scan first — read
194
- its duplicate and epic answers.** This applies inside every workflow, including observations and review
195
- follow-ups. The guard refuses any other filing call. Read `issue-scout.md` at that point for the
196
- duplicate, closed-Issue and epic decisions and for `--distinct`; `issue-fold-existing.md` handles a
197
- compatible duplicate. `docs/josh-commands-automation.md` → "`josh issue:file`" defines the command.
198
-
199
- ## 2f. The working-tree hold — one run per tree
200
-
201
- **Trigger:** the first call of `fullrun` and `halfrun` alike — before the title is normalized, before
202
- `git switch main`, and before a `new` entry files its Issue. **Then:** a `#N` entry first runs
203
- `pnpm josh run:entry <N> --to <command>` (§2k, the tree claim included); `new` runs bare
204
- `pnpm josh run:hold`. `hold` continues; `busy` and `unknown` stop with a `confirmation` Telegram
205
- carrying what stderr printed. **`kickoff` is exempt** (it edits nothing). A stop that leaves the tree
206
- clean releases explicitly with `pnpm josh run:release [<N>]`; a `halfrun` or `needs-human-review` stop
207
- keeps the hold; `pnpm josh followup` releases a merged run. The answer table, the per-child rule and
208
- the `--force` spelling are `working-tree-hold.md`, its single source, read at that trigger.
209
-
210
- ## 2g. An Issue's comments are part of the Issue
211
-
212
- **Trigger:** before implementing at every `#N` entry point (`fullrun`, `halfrun`, `kickoff`, and each
213
- `backlogrun` child in its own unit). **Then:** `pnpm josh issue:read <N> [<N> ...]` reads the body and
214
- the comments in one call — a decision recorded after the body was written lives only in a comment, and
215
- of a body and a comment that disagree the later text wins. Two comment kinds are not the run's to act
216
- on blindly — a scope reassigned to another Issue, and an Issue already merged (the `already-done`
217
- exit) — and both, the long-thread delegation and why `pnpm josh rule:guard` refuses the body-only read,
218
- are `issue-comments.md`, its single source, read at that trigger.
219
-
220
- ## 2h. A command that can take minutes is issued in the background
221
-
222
- **Trigger:** before backgrounding the first long-running command (`pnpm josh gate`). **Then:** issue
223
- `pnpm josh git -y`, `pnpm josh gate` and the CI wait detached while `pnpm josh followup` stays in the
224
- foreground — the turn never ends at the push, bar a dispatched lane child's pre-gate cut
225
- (`pre-gate-cut.md`). A parent waiting on its children is the same rule at the batch's scale: a
226
- background command's completion re-invokes the session, so the `backlogrun` loop starts no sleep of
227
- its own. The single source is `background-commands.md` → "Background the gate and push", with the
228
- parent-wake half at `backlogrun-progress.md` → "The parent keeps no clock of its own".
229
-
230
- ## 2i. An observation worth filing is filed without asking
231
-
232
- **When a first-party observation is worth filing, file it without asking and continue the run.**
233
- Read `observation-filing.md` in full before filing: it decides the depth test, filing ceilings, labels,
234
- second-filing fold, ledger fallback and delegated-child handoff. Use `pnpm josh repo:party` to decide
235
- first-party status, then file with `pnpm josh issue:file` (§2e). A third-party target remains
236
- Tier C (`CLAUDE.md`).
237
-
238
- ## 2j. The end-of-run retrospective — read when `run:step` prints it
239
-
240
- **When `pnpm josh run:step` prints the retrospective step, read `retrospective.md` in full and run the
241
- digest it names once.** File up to two worthwhile improvements through `issue:file` (scout and
242
- `epic:bundle` included), stack the rest in the observation ledger, and close the step with the command described
243
- there. A dispatched lane child never runs the retrospective.
244
-
245
- ## 2k. The stage ladder
246
-
247
- `kickoff` → `halfrun` → `prrun` → `fullrun` (joshuafolkken/kit#3042): the command sets how far a run
248
- goes, the Issue where it starts. `run:entry <N> --to <command>` prints `stage #<N> — at: … · start:
249
- …`; **`start: reached` redoes nothing — stop** (at `merged`, the next line answers). A
250
- stop's `Next:` line names the commands further up. Table: `docs/how-to/run-issues.md`.
251
-
252
107
  ## 3. What stays resident, and what is read from here
253
108
 
254
109
  **The residency criterion is `prompts/collaboration-workflow/residency.md`, its single source — read
255
- only when a rule is being placed, moved or retired, never at any entry and never during a run.** Its
256
- questions are asked there in order — question 0 (`pnpm josh oracle:list`), the ordering question
257
- (`pnpm josh run:step`), the first and the second — beside how much of a resident rule stays and the
258
- retirement route; none is restated here.
110
+ only when a rule is placed, moved or retired, never during a run.** Its questions — question 0
111
+ (`pnpm josh oracle:list`), the ordering question (`pnpm josh run:step`), the first and the second —
112
+ are asked there in order; none is restated here.
@@ -88,4 +88,4 @@ backgrounded `josh gate` / `git` / `followup` / `ship` there, and the `Stop` hoo
88
88
  task still running back to wait.
89
89
 
90
90
  The operational section above is the single source of the rule. `followup.md`, `chain-rule.md` and
91
- `backlogrun-progress.md` → "Progress while the run is quiet" route here for it rather than restating it.
91
+ `progress-watcher.md` → "Progress while the run is quiet" route here for it rather than restating it.
@@ -24,7 +24,7 @@ bare Issue promotes itself under `backlogrun` but not under `fullrun`"):
24
24
  2. **Stash the work in progress and remove `in-progress` from `#<N>`**, exactly as steps 2 and 4 of
25
25
  "A prerequisite discovered mid-run" do — `git stash push -u -m "..."` with the `-u`, the
26
26
  `gh api repos/{owner}/{repo}/issues/<N>/comments` post that records the stash, and
27
- `gh api -X DELETE repos/{owner}/{repo}/issues/<N>/labels/in-progress 2>/dev/null || true`.
27
+ `pnpm josh run:release <N>`, which removes the label with the hold.
28
28
  3. **Ask `pnpm josh epic:bundle <N>` whether an epic already tracks `#<N>` before creating one.**
29
29
 
30
30
  | Answer | What to do |
@@ -115,7 +115,7 @@ summary is bounded the way it is".
115
115
  3. **Observations that could bite later** — something noticed and not filed, a flaky check, a
116
116
  surprising diff, work a later child will collide with. **This is the only route a child's
117
117
  discretionary observation has**: a child files `route:tier-a` and `route:interrupt` only, and the
118
- parent files what survives — `SKILL.md` → §2i, the single source. **What the parent does with the
118
+ parent files what survives — `observation-filing.md`, the single source. **What the parent does with the
119
119
  rest is append it, not drop it**: an observation that cannot cite the depth-0 work it blocked
120
120
  becomes one line in the observation ledger, and a second line under the same key files it. **A
121
121
  child appends only to its own issue's file, `docs/maintainers/observations/<N>.md`, in its own
@@ -148,92 +148,10 @@ asked at every merge; delegation is not an alternative to it.
148
148
 
149
149
  ## A delegated unit that stopped without reporting
150
150
 
151
- **A unit can be stopped from outside, and a stop leaves no notification behind** — and a stopped unit
152
- trips none of this file's guards, which all assume it is running. **So the parent checks rather than
153
- waiting — which means it must not be waiting.** **Hand the child to the unit without blocking on its
154
- return, and poll** at the loop's polling interval; ask once the unit's output has been unchanged for
155
- the silent-unit window (`| Silent delegated unit | 30 min |` in `backlogrun-progress.md`).
156
-
157
- **Note where the unit writes at hand-off; the modification time is read from the file, not carried.**
158
- **Where the child runs in a lane, that note goes into the lane rather than the conversation** —
159
- `pnpm josh lane:output <N> <path>`, in the same turn as the dispatch, so it comes back from
160
- `pnpm josh lane:output <N>` in any session.
161
-
162
- **Ask the command rather than combining the traces yourself.** Traces are read **in the checkout the
163
- unit was given** — this session's own unless the unit was handed a separate work tree, and the stash in
164
- the recovery below is taken there too.
165
-
166
- ```bash
167
- pnpm josh run:liveness <N> --output <path> --process none
168
- pnpm josh run:liveness <N> --output <path> --process alive
169
- pnpm josh run:liveness <N> --output <path> --process none --window 45 --repo <owner/repo>
170
- ```
171
-
172
- | Answer | What it found | What the parent does |
173
- | --- | --- | --- |
174
- | `alive` | The output moved, or a process of the child is running | Keep polling; touch nothing |
175
- | `stopped` | The output has been frozen past the window and no process of the child is alive | The recovery below |
176
- | `settled` | The child closed, or the unit parked it with `needs-decision` | Re-read it with `pnpm josh run:status <N>` — one read-only call whose state section says which branch and whose carry counters beside it feed the failure-streak decision — and take the branch its state section says |
177
- | `undetermined` | A trace could not be read | Read the trace that failed and ask again — and see the two-in-a-row rule below |
178
-
179
- **Two `undetermined` answers in a row is a fault in the check, not a slow unit.** The second
180
- consecutive `undetermined` on the same child ends the polling: send a `confirmation` Telegram naming
181
- the trace that failed, and stop. **It is never escalated to a `stopped`** — nothing was read.
182
-
183
- **Silence and no process together — never either one alone.** **A trace that could not be read answers
184
- `undetermined`, never `stopped`**, and a process trace nobody gave is an unasked question rather than
185
- "no process". **Output that moved answers `alive` on its own; a live process is weighed only once every
186
- trace has answered.** Rationale: `docs/maintainers/backlogrun-child-rationale.md` → "Why liveness needs
187
- silence and no process together".
188
-
189
- **The path passed to `--output` is absolute** — the command refuses a relative one. **The process
190
- trace is the one the command does not read for itself**: run it in the unit's checkout and read the
191
- command lines rather than the names — `pgrep -laf 'josh gate'` etc. — looking for one naming **that
192
- checkout's path**, since several kit projects may run at once. **Read the file the path points at, not
193
- the link**: a transcript path is a symlink whose own modification time never changes, so a `stat` typed
194
- by hand needs `-L` (`run:liveness` follows the link itself).
195
-
196
- **A clean checkout is not evidence that the unit is alive** — a stop can come while the unit is still
197
- reading the skill and the issue. The checkout is read only for whether there is work to stash before
198
- the child is parked; **"nothing was ever opened for the child" is `pnpm josh run:hold`'s preflight check
199
- at the start of the next child, not this one's.**
200
-
201
- **What follows is what a failed child already gets.** Re-read the child first with
202
- `pnpm josh run:status <N>` — its state section carries the same `state:` / `labels:` /
203
- `human_review:` lines `issue:state` prints, and folds in the carry counters this recovery reads
204
- anyway; then, while it is still `state: OPEN` and not carrying `needs-decision`.
205
- **A re-read carrying `needs-decision`** means the unit parked the child and then stopped, so fall
206
- through to the loop's park branch: leave the label on, count nothing against the consecutive-failure
207
- guard, and go back to step 1.
208
-
209
- 1. **Stash the half-finished work** — `git stash push -u -m "backlogrun: stopped unit for #<N>"` — and
210
- record it on the Issue. `-u` is not optional, and the comment is what gets the stash popped — by
211
- message, `pnpm josh stash:pop "backlogrun: stopped unit for #<N>"`, never a positional
212
- `git stash pop` that a shared stack lets another lane divert.
213
- 2. **Classify how the child ended and act, in one call** — `pnpm josh run:merge <N> --output <path>`
214
- (add `--epic <E> --repo <owner/repo> --owner "$PPID"` for a named epic). **It is the same composite a
215
- returned child takes** (`backlogrun-progress.md` → "Running a named epic's children"), reached here
216
- from the poll rather than from a return — **one** decision, never a second copy of it. It **reads the
217
- child's exit record without waiting for the unit to return**, telling an `outage` — a child that
218
- could not reach the API — apart from an `abandoned` one that stopped mid-implementation, and it drops
219
- the stale `in-progress` itself, so there is no separate label-removal step:
220
- - **outage** — the child never reached the API, so it is counted into its own outage streak and
221
- **re-dispatched in the same run** by being offered again, **not** parked with `needs-decision` and
222
- **not** counted against the consecutive-failure guard. **The re-dispatch resumes the child's
223
- session**: `lane:dispatch` reads the `session_id` off the exit record and relaunches with
224
- `--resume`; with no session id it falls back to a fresh `fullrun`, and the report says which path
225
- it took. **Outages inside a two-minute window count once** toward the streak. The re-dispatch is
226
- bounded by `CONSECUTIVE_OUTAGE_LIMIT` in `scripts/run/run-merge.ts`: *distinct* outages trip the
227
- separate outage guard, at which point the command prints `environment` and the run stops. It never
228
- re-dispatches into a dead API forever.
229
- - **abandoned** — counted against the consecutive-failure guard and parked with `needs-decision`,
230
- exactly as a failed child. Never retried silently.
231
- 3. **Read the token it printed and take that branch** — a next child number to run (the re-dispatched
232
- outage child among them), `environment` / `stop` to end the run, or `busy` / `retry` to re-read —
233
- the same tokens the merge event reads (`backlogrun-progress.md` → "Running a named epic's children").
234
- Then go back to step 1 of the loop.
235
-
236
- Rationale: `docs/maintainers/backlogrun-child-rationale.md` → "Why the poll routes through `run:merge`".
151
+ **Hand the child to the unit without blocking on its return, and poll** — a stopped unit leaves no
152
+ notification behind. Once its output has been unchanged for the silent-unit window, read
153
+ `backlogrun-recovery.md` → "A delegated unit that stopped without reporting" and ask
154
+ `pnpm josh run:liveness`.
237
155
 
238
156
  ## Audit before the first child
239
157
 
@@ -281,40 +199,11 @@ This is the same rule `latest-gate.md` is the single source of.
281
199
  Rationale: `docs/maintainers/backlogrun-child-rationale.md` → "Why `josh latest` is hoisted to the
282
200
  session".
283
201
 
284
- ## Preflight — reclaim what an interrupted run left, before the next child starts
285
-
286
- **The child's claim is what asks it.** `pnpm josh run:hold <N>` — the first call of the child's
287
- `fullrun` procedure — runs the preflight check before it takes the tree: it hands back a hold **only on
288
- a clean tree**, and returns `reclaim` / `resume` / `park` without claiming otherwise. There is no
289
- separate command to ask first. Rationale: `docs/maintainers/backlogrun-child-rationale.md` → "Why the
290
- preflight is part of the claim".
202
+ ## Preflight — the child's claim asks it
291
203
 
292
- ```bash
293
- answer=$(pnpm josh run:hold 926) # one token on stdout, prose on stderr
294
- ```
204
+ `pnpm josh run:hold <N>`, the first call of the child's `fullrun`, checks for an interrupted run's
205
+ leftovers before it claims the tree, and prints the step for each answer (`reclaim` / `resume` /
206
+ `park`) on stderr — follow it, and report a reclaim or resume with its stash reference. The answers are
207
+ `docs/josh-commands-automation.md` → "`josh run:hold`"; rationale:
208
+ `docs/maintainers/backlogrun-child-rationale.md` → "Why the preflight is part of the claim".
295
209
 
296
- | Answer | What it found | What to do |
297
- | --- | --- | --- |
298
- | `hold` | Nothing left behind; the tree is claimed | Start the child. This is the ordinary answer. |
299
- | `reclaim` | Uncommitted changes, or HEAD off the default branch | Run what stderr printed: `git stash push -u -m "run:hold reclaimed before #<N>"`, then `git switch <default> && git pull`. **`-u` is not optional** (a new `*.test.ts` is untracked). **Then record the stash on `#<N>` as a comment, and ask `run:hold` again** — the check is re-askable. |
300
- | `resume` | An open PR, or a `#<N>` branch with commits or a dirty lane | **Reuse it and run the whole verification gate from the start** — never only the part the interrupted run had not reached. The tools are idempotent; what was missing was that **nobody had verified what the dead run already committed**. |
301
- | `park` | The pull request for `#<N>` is **merged** or **closed** | **Park the child** — `needs-decision` plus a comment naming what was found — and continue. Carrying on over a merged PR duplicates work; over a closed one revives rejected work. Do not delete the branch, reopen the PR, or commit on top of it. |
302
- | `busy` | Another **live** run holds this tree | Stop before filing anything — `run:hold`'s own answer, unchanged. |
303
- | `unknown` | The tree could not be read | Stop the session and report. It is not "the tree is clean". |
304
-
305
- **The rule answers, so the run does not judge.**
306
-
307
- **The `git stash` above is one of the flows that authorizes automatic stashing**
308
- (`prompts/collaboration-workflow/operating-rules.md` → the `git stash` bullet). **It is the one entry
309
- there not followed by a pop**: what is stashed belongs to a run that is gone, so **the Issue comment is
310
- the only thing that can bring it back** — recovered by message, `pnpm josh stash:pop "run:hold
311
- reclaimed before #<N>"`, never a positional `git stash pop` a shared stash stack lets another lane
312
- divert.
313
-
314
- **Report what was reclaimed** — a child that started from a `reclaim` or a `resume` says so, with the
315
- stash reference where there was one.
316
-
317
- **It is not asked in a lane** — `run:hold` claimed inside a lane skips the check, and `lane:open`'s own
318
- answer covers an interrupted lane instead. **Asked in the primary checkout while a lane for that child
319
- is open, `run:hold` reads `resume` only if `<N>-lane` has a commit or a dirty tree** — a clean one
320
- at the default branch reads `hold`. The loop never gets there, because `epic:next` does not offer a child already carrying `in-progress`.
@@ -84,8 +84,12 @@ it a defect (not an improvement, refactor, removal or feature)? Is it in kit's o
84
84
  checks — not a consumer repository's CI or template? Does it, on `main` now, make unrelated PRs
85
85
  answer wrongly (a false green or a false red)? All three, and the issue carries `run:solo`; any one
86
86
  missing, and it carries `run:lane` and fills a lane like any other child. `backlog:next` and `epic:next --lanes` enforce both (joshuafolkken/kit#2776,
87
- #2779). The rule is
88
- `prompts/collaboration-workflow/wip-cap.md` → 「実行のしかた」, its single source.
87
+ #2779), and an issue a run files (an interrupt, a split child, a prerequisite) carries one of the
88
+ two from its filing, because an issue with neither answers `triage` and nothing starts. **It stops
89
+ the other lanes for one reason only: a batch run on broken verification leaves nobody's result
90
+ trustworthy** — that the issue's own verification sits under the defect is the issue's own concern,
91
+ checked by the verification after the fix. This paragraph is the rule's single source; rationale:
92
+ `docs/maintainers/wip-cap-rationale.md` → 「単独実行の理由と由来」.
89
93
 
90
94
  **A lane's review does not inherit the lane, and `pnpm josh review:brief` is what closes that.**
91
95
  `pnpm josh review:brief` prints the lane's absolute root, branch and HEAD, hands over targets written
@@ -103,7 +107,7 @@ isolation. So `epic:next` is asked **with** `--lanes`, and everything below runs
103
107
  switched".
104
108
 
105
109
  **Report the throughput gain only with its merge-race cost** — every overlap that becomes a conflict
106
- costs a resolution, a re-run gate and a review ("Conflicts are not predicted" below). Rationale:
110
+ costs a resolution, a re-run gate and a review (`backlogrun-recovery.md` → "Conflicts are not predicted"). Rationale:
107
111
  `docs/maintainers/backlogrun-lanes-rationale.md` → "Why lanes cost as well as buy throughput".
108
112
 
109
113
  ### Once per repository, before the first lane opens
@@ -205,62 +209,9 @@ lane is cut from.
205
209
 
206
210
  ### Conflicts are not predicted
207
211
 
208
- **The child merges `origin/main` into its lane before its gate now, so this path is the fallback rather
209
- than the first line.** Every `fullrun` runs `pnpm josh main:merge` ahead of the gate
210
- (`chain-rule.md` → "origin/main is merged in before the gate", the single source), so an overlap
211
- already on `main` is resolved before the gate reads the tree. What this section covers is an overlap
212
- that lands on `main` *after* it, which `followup` still reports as a conflict.
213
-
214
- **Nothing here forecasts which children will overlap.** The overlap surfaces where GitHub already
215
- reports it: a pull request that conflicts with its base comes back `mergeStateStatus: DIRTY`, which
216
- `git-pr-checks-eval.ts` reads as a **failure** rather than polling through it — so `pnpm josh followup`
217
- ends that child with a named conflict in about ten seconds.
218
-
219
- **That child does not stop: it resolves the conflict in its own lane.** It is **not** counted against
220
- the consecutive-failure guard either way.
221
-
222
- **The merge direction is `origin/main` into the lane's branch, never a rebase**, and no step below
223
- rewrites a pushed commit. Rationale: `docs/maintainers/backlogrun-lanes-rationale.md` → "Why a conflict
224
- is resolved in the lane rather than handed to a person".
225
-
226
- 1. **Resolve in the lane.** `git fetch origin main`, merge `origin/main` into the lane's branch, resolve
227
- in place. Do not close the lane, open another, or switch its branch.
228
- 2. **Re-run the whole gate.** The tree changed, so the green recorded before the conflict is void:
229
- `pnpm josh lint:related` and `pnpm josh test:related`, then `pnpm josh gate`.
230
- 3. **Review the resolution, one round.** Brief it with `pnpm josh review:brief` and run `/code-review`
231
- over the resolution diff, then require `pnpm josh review:attest --check` to answer `ok`. That round
232
- is a different subject and does not spend one of the two the cap allows — `prompts/review.md` →
233
- "Review round cap" carries the exception.
234
- 4. **Conclude the merge and push it, with `pnpm josh git -y`** — the only sanctioned way; without it
235
- nothing changes on `origin` and condition 3 parks the child for good. **Record the resolution on the
236
- Issue in this same step** — a comment naming the conflicting paths — because condition 3 counts
237
- resolutions off the Issue comments, not off memory.
238
- 5. **Merge**, by re-running `pnpm josh followup` exactly as before.
239
-
240
- **The safeguard is the re-run verification, not who holds the pen** — a conflict the run can resolve is
241
- not routed to a person.
242
-
243
- **The run steps back under these four conditions, and under no others. The list is exhaustive and
244
- carries no judgement.**
245
-
246
- 1. **The resolution requires deleting the other side's change.** That decides intended behavior, not
247
- text. It goes to the user as a **specification** question — "behavior A or behavior B" — never as a
248
- diff.
249
- 2. **Both sides rewrote the same lines** — overlapping, not adjacent. Read off the structure of the
250
- conflict hunks, so it needs no interpretation.
251
- 3. **A second conflict on the same child.** One resolution per child; the count is read off the Issue
252
- comments step 4 writes, so it survives an interrupt.
253
- 4. **The re-run gate did not come back green, or the resolution review returned a High.** Not only a
254
- High: a lint error, a failing test or a spell-check hit that merging a moved `main` introduced is
255
- this condition too.
256
-
257
- Meeting any of the four, the child is parked — `needs-decision` plus a comment naming which of the four
258
- it was — and its lane is **kept**, because the pushed branch is the resume path (the table below).
259
-
260
- **Leave the tree clean before parking: `git merge --abort` precedes a park under conditions 1, 2 or 4.**
261
- Conditions 1 and 2 are read mid-merge with conflict markers still in the tree, condition 4 after a merge
262
- that is resolved but not committed; condition 3 fires before any merge is started, so there is nothing
263
- to abort.
212
+ **A child whose pull request conflicts with `main` resolves it in its own lane rather than stopping** —
213
+ read `backlogrun-recovery.md` → "Conflicts are not predicted" when `pnpm josh followup` reports the
214
+ conflict.
264
215
 
265
216
  ### What happens to a lane
266
217
 
@@ -269,7 +220,7 @@ to abort.
269
220
  | The child **merged** | `pnpm josh lane:close <N>` | `followup` released the hold and the branch is on `main`; nothing in that tree is wanted |
270
221
  | The child was **parked before its commit** | `git -C <dir> stash push -u -m "backlogrun: parked #<N>"`, record it on the Issue, then `pnpm josh lane:close <N>` | The stash is a repository-level ref, so it outlives the work tree — and `lane:close` is a **forced** removal that would otherwise take the work. `epic:next` counts a parked child's lane as released, so a lane left open holds a seat the count believes is free |
271
222
  | The child was **parked after its commit and push** | **Left open**, its directory and held seat recorded on the Issue | The stash step is a **no-op** (tree clean because committed). What `lane:close` would take is the **local branch**, which is the resume path |
272
- | The child hit a **merge conflict** | **Left open** — the resolution happens in it | The child resolves in place ("Conflicts are not predicted"). A park under that section's four conditions takes the row above |
223
+ | The child hit a **merge conflict** | **Left open** — the resolution happens in it | The child resolves in place (`backlogrun-recovery.md` → "Conflicts are not predicted"). A park under that section's four conditions takes the row above |
273
224
  | The child stopped on **`needs-human-review`** | **Left open and untouched** | The uncommitted work *is* the artifact a person has to look at. Name the lane directory in the stop report and in the Telegram |
274
225
  | The child **failed** | Whichever of the two parked rows applies, plus the consecutive-failure count | Same reasoning; only the counter differs. **A merge conflict is not this row** — it takes the row above, and it is not counted |
275
226
  | **`lane:open` failed on the install** | `pnpm josh lane:close <N>`, then park the child | A lane exists that no `pnpm josh …` runs in and the next `lane:open` answers `already-open`. Closing frees the seat; parking is right because the cause is one a person fixes. Carry pnpm's reason into the park note |