@joshuafolkken/kit 1.1136.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 (165) hide show
  1. package/.claude/settings.json +4 -4
  2. package/.claude/skills/epic-commands/SKILL.md +27 -239
  3. package/.claude/skills/epic-commands/epic-bundle.md +115 -0
  4. package/.claude/skills/epic-commands/execution-waves.md +126 -0
  5. package/.claude/skills/workflow-commands/SKILL.md +48 -194
  6. package/.claude/skills/workflow-commands/background-commands.md +1 -1
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +12 -123
  8. package/.claude/skills/workflow-commands/backlogrun-lanes.md +11 -60
  9. package/.claude/skills/workflow-commands/backlogrun-park.md +10 -8
  10. package/.claude/skills/workflow-commands/backlogrun-progress.md +17 -173
  11. package/.claude/skills/workflow-commands/backlogrun-recovery.md +155 -0
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +64 -144
  13. package/.claude/skills/workflow-commands/backlogrun.md +5 -4
  14. package/.claude/skills/workflow-commands/chain-rule.md +3 -2
  15. package/.claude/skills/workflow-commands/delegation.md +2 -2
  16. package/.claude/skills/workflow-commands/entry-sequence.md +62 -0
  17. package/.claude/skills/workflow-commands/followup.md +104 -181
  18. package/.claude/skills/workflow-commands/fullrun-steps.md +8 -9
  19. package/.claude/skills/workflow-commands/fullrun.md +16 -73
  20. package/.claude/skills/workflow-commands/halfrun.md +10 -36
  21. package/.claude/skills/workflow-commands/into-target.md +4 -4
  22. package/.claude/skills/workflow-commands/issue-comments.md +7 -8
  23. package/.claude/skills/workflow-commands/issue-scout.md +6 -6
  24. package/.claude/skills/workflow-commands/kickoff.md +6 -6
  25. package/.claude/skills/workflow-commands/needs-human-review.md +6 -6
  26. package/.claude/skills/workflow-commands/observation-filing.md +21 -172
  27. package/.claude/skills/workflow-commands/observation-ledger.md +150 -0
  28. package/.claude/skills/workflow-commands/pre-gate-cut.md +33 -93
  29. package/.claude/skills/workflow-commands/prerequisite.md +6 -6
  30. package/.claude/skills/workflow-commands/progress-watcher.md +90 -0
  31. package/.claude/skills/workflow-commands/prrun.md +5 -5
  32. package/.claude/skills/workflow-commands/retrospective.md +9 -9
  33. package/.claude/skills/workflow-commands/split-assessment.md +2 -2
  34. package/.claude/skills/workflow-commands/target-repository.md +2 -2
  35. package/.claude/skills/workflow-commands/working-tree-hold.md +7 -5
  36. package/.codex/hooks.json +4 -4
  37. package/AGENTS.md +1 -6
  38. package/CLAUDE.md +58 -120
  39. package/GEMINI.md +1 -6
  40. package/dist/CLAUDE.md +58 -120
  41. package/dist/hooks/batch-guard.js +4 -4
  42. package/dist/hooks/{chunk-NFZGFGOR.js → chunk-5KTCMCOT.js} +14 -1
  43. package/dist/hooks/{chunk-LJBLGHEH.js → chunk-A6P7PN7P.js} +4 -6
  44. package/dist/hooks/{chunk-FO2I7UT7.js → chunk-ANJ2WGFD.js} +1 -1
  45. package/dist/hooks/{chunk-GDU26K3J.js → chunk-DYAVAM6S.js} +563 -126
  46. package/dist/hooks/{chunk-RFWWUI5F.js → chunk-ENA7P5FB.js} +3 -3
  47. package/dist/hooks/{chunk-KBXZLMRH.js → chunk-GU5MATVE.js} +213 -65
  48. package/dist/hooks/chunk-GYNGP7HI.js +56 -0
  49. package/dist/hooks/{chunk-HBKZLITF.js → chunk-URJA6XY4.js} +4 -4
  50. package/dist/hooks/{chunk-KOKOAV6D.js → chunk-V2BTOZHT.js} +6 -4
  51. package/dist/hooks/{chunk-JKKTVDAG.js → chunk-ZDZ555YH.js} +100 -20
  52. package/dist/hooks/codex-hook-adapter.js +10 -10
  53. package/dist/hooks/duplicate-read-guard.js +5 -5
  54. package/dist/hooks/format-edited.js +2 -2
  55. package/dist/hooks/inputs.json +193 -192
  56. package/dist/hooks/investigation-guard.js +5 -5
  57. package/dist/hooks/pretool-guard.js +11 -10
  58. package/dist/hooks/stop-guard.js +5 -5
  59. package/dist/josh.js +25 -2
  60. package/dist/version/index.js +5 -1
  61. package/package.json +2 -1
  62. package/prompts/collaboration-workflow/file-edits.md +11 -10
  63. package/prompts/collaboration-workflow/gh-rest.md +2 -4
  64. package/prompts/collaboration-workflow/glossary.md +1 -1
  65. package/prompts/collaboration-workflow/issue-citation.md +5 -9
  66. package/prompts/collaboration-workflow/issue-template.md +40 -115
  67. package/prompts/collaboration-workflow/operating-rules.md +4 -5
  68. package/prompts/collaboration-workflow/output-bounds.md +12 -78
  69. package/prompts/collaboration-workflow/overview.md +7 -13
  70. package/prompts/collaboration-workflow/plan-comment.md +11 -39
  71. package/prompts/collaboration-workflow/principles.md +3 -4
  72. package/prompts/collaboration-workflow/report-format.md +28 -74
  73. package/prompts/collaboration-workflow/residency.md +12 -109
  74. package/prompts/collaboration-workflow/rule-delivery.md +98 -97
  75. package/prompts/collaboration-workflow/shell-body.md +3 -13
  76. package/prompts/collaboration-workflow/turn-batching.md +14 -88
  77. package/prompts/collaboration-workflow/upstream-interrupt.md +12 -14
  78. package/prompts/collaboration-workflow/wip-cap.md +6 -45
  79. package/prompts/collaboration-workflow.md +1 -13
  80. package/prompts/review-rubric.md +8 -71
  81. package/prompts/review.md +25 -55
  82. package/prompts/testing-guide.md +18 -67
  83. package/scripts/agent/agent-role-profile.ts +1 -1
  84. package/scripts/agent/codex-hooks.ts +3 -12
  85. package/scripts/backlog/backlog-budget.ts +1 -1
  86. package/scripts/backlog/backlog-drive-cli.ts +4 -3
  87. package/scripts/backlog/backlog-drive-offer-argv.ts +10 -1
  88. package/scripts/backlog/backlog-offer.ts +6 -6
  89. package/scripts/behavior/behavior-rules.ts +11 -4
  90. package/scripts/delegation/investigation-reads.ts +5 -5
  91. package/scripts/discovery/repo-discovery.ts +21 -7
  92. package/scripts/discovery/repo-origin.ts +26 -0
  93. package/scripts/discovery/repo-party.ts +42 -1
  94. package/scripts/document/backlogrun-parent-read-set.ts +14 -15
  95. package/scripts/document/document-byte-budget.ts +34 -20
  96. package/scripts/document/entry-read-budget.ts +21 -9
  97. package/scripts/document/lane-child-read-set.ts +12 -14
  98. package/scripts/document/read-set-cli.ts +4 -4
  99. package/scripts/document/read-set-point-of-use.ts +10 -2
  100. package/scripts/document/resident-budget.ts +47 -0
  101. package/scripts/epic/epic-shape.ts +10 -13
  102. package/scripts/epic/epic-solo.ts +1 -1
  103. package/scripts/exports/unused-members-cli.ts +7 -3
  104. package/scripts/gh/git-gh-api-path.ts +7 -0
  105. package/scripts/hooks/pretool-guard-cli.ts +2 -2
  106. package/scripts/hooks/pretool-guard.ts +45 -2
  107. package/scripts/hooks/run-hook.sh +41 -0
  108. package/scripts/init/hook-command-rewrite.ts +18 -35
  109. package/scripts/init/hook-launch.ts +21 -32
  110. package/scripts/issue/issue-auto-ok.ts +95 -0
  111. package/scripts/issue/issue-file-cli.ts +53 -7
  112. package/scripts/issue/issue-file.ts +28 -5
  113. package/scripts/issue/issue-labels.ts +12 -12
  114. package/scripts/issue/issue-rank.ts +1 -1
  115. package/scripts/issue/issue-read-cli.ts +3 -3
  116. package/scripts/issue/issue-read.ts +2 -2
  117. package/scripts/issue/issue-scout-cli.ts +2 -2
  118. package/scripts/issue/issue-state-cli.ts +1 -1
  119. package/scripts/issue/issue-state.ts +2 -2
  120. package/scripts/issue/issue-wip.ts +70 -0
  121. package/scripts/josh/hook-decision.ts +17 -0
  122. package/scripts/josh/josh-commands-development.ts +10 -0
  123. package/scripts/josh/josh-commands-issue.ts +2 -2
  124. package/scripts/lines/bytes-command.ts +29 -6
  125. package/scripts/observations/observation-ledger-line.ts +1 -1
  126. package/scripts/release/release-progress.ts +167 -0
  127. package/scripts/release/release-publish.ts +19 -8
  128. package/scripts/release/release-tag.ts +22 -8
  129. package/scripts/rules/decision-oracle-stage.ts +1 -1
  130. package/scripts/rules/decision-oracle.ts +6 -6
  131. package/scripts/rules/delivered-rules.ts +11 -11
  132. package/scripts/rules/direct-pr-create.ts +110 -0
  133. package/scripts/rules/file-body.ts +98 -42
  134. package/scripts/rules/filing-cap.ts +2 -2
  135. package/scripts/rules/filing-offer.ts +1 -1
  136. package/scripts/rules/gh-api.ts +18 -1
  137. package/scripts/rules/implementation-cut.ts +3 -1
  138. package/scripts/rules/lane-background.ts +67 -10
  139. package/scripts/rules/permission-guards.ts +10 -2
  140. package/scripts/rules/stop-rules.ts +4 -4
  141. package/scripts/rules/test-declared-commit.ts +1 -1
  142. package/scripts/rules/third-party-write.ts +56 -12
  143. package/scripts/run/run-cut-handoff.ts +21 -1
  144. package/scripts/run/run-entry-cli.ts +11 -3
  145. package/scripts/run/run-hold-cli.ts +16 -2
  146. package/scripts/run/run-label.ts +50 -0
  147. package/scripts/run/run-merge-steps.ts +8 -3
  148. package/scripts/run/run-merge.ts +1 -1
  149. package/scripts/run/run-prep-cli.ts +6 -2
  150. package/scripts/run/run-prep.ts +17 -0
  151. package/scripts/run/run-ship-preflight.ts +34 -3
  152. package/scripts/run/run-ship-review-steps.ts +1 -1
  153. package/scripts/run/run-ship-review.ts +26 -5
  154. package/scripts/run/run-step-cli.ts +20 -7
  155. package/scripts/run/run-wake-driver.ts +24 -1
  156. package/scripts/run/run-wake-session.ts +2 -1
  157. package/scripts/test/test-declared-logic.ts +1 -1
  158. package/scripts/time-runtime/time-batch-guard.ts +52 -16
  159. package/scripts/time-runtime/time-density-hook.ts +20 -2
  160. package/scripts/time-runtime/time-density.ts +4 -3
  161. package/scripts/time-runtime/time-markers.ts +15 -4
  162. package/scripts/version/npm-registry.ts +11 -1
  163. package/templates/workflows/ci.yml +9 -1
  164. package/.claude/skills/workflow-commands/followup-reference.md +0 -118
  165. package/dist/hooks/chunk-HANSKHES.js +0 -464
@@ -166,103 +166,43 @@ built for the lane child.
166
166
 
167
167
  ### It is a guard, fired at the edit that crosses the threshold
168
168
 
169
- Rationale: `docs/maintainers/pre-gate-cut-rationale.md` → "Why the rules are guards, not prose".
170
- `pnpm josh rule:guard` **refuses an `Edit` / `Write`** while this checkout is a dispatched lane child
171
- whose recent-context cost is over threshold, handing back `pnpm josh run:cut --impl <N> --handoff <path>` — the
172
- refusal lands _before_ the edit. `cut` ends the turn, the rest leave this process implementing; a fresh
173
- process's `pnpm josh run:cut --resume <N>` then answers **`resume-impl`**, so it **skips the title, plan,
174
- hold claim and split assessment** and **continues implementation** rather than gating. Unlike the
175
- pre-gate cut, **the implementation resume clears the record** — it may fire again, unlike the
176
- once-per-lane pre-gate cut (joshuafolkken/kit#1935); `begin_cut`'s exclusive create still gives each
177
- crossing one successor.
178
-
179
- - **It fires for a marked child, or a run held outside a lane on a measured `over`**
180
- (joshuafolkken/kit#2760); a person's tree holds no run. Outside a lane `cut` relaunches nothing: keep
181
- the hold, send a `confirmation` Telegram naming `fullrun #<N>`, end the turn.
182
- - **It fires on every threshold crossing, not once per run** — it re-asks on
183
- each over-threshold edit, including after a `busy` / `failed` / `unready` verdict.
184
- - **An edit reissued right after a refusal passes** — so a `busy` / `failed` cut cannot wedge the run:
185
- the reissue lands inside a short window and goes through, a genuinely new crossing past it refuses
186
- again.
187
- - **An unmeasurable session warrants the cut** in a lane, as the pre-gate cut's does.
188
- - **It is silent between a cut and its resume** — a carried record naming this issue keeps it quiet; the
189
- resume clears it, and the fresh process reads its own transcript under threshold.
190
- - **The verdict read is reused over a short window** — cached per checkout for a few seconds, so a
191
- turn's burst of edits shares one read.
192
-
193
- `scripts/rules/implementation-cut.ts` implements the trigger, and the row joins
194
- `prompts/collaboration-workflow/rule-delivery.md`. **A child that ended
195
- without cutting is still detected after the fact by `pnpm josh run:ending <N> --output <path>`**
196
- (joshuafolkken/kit#2139). **A single check (`lint:related` / `test:related`) is run after a batch of
197
- edits, not after each one.**
198
-
199
- ## The threshold, and the statistic it is measured against
200
-
201
- **`CONTEXT_CUT_THRESHOLD` (135_000) is one value, and `cost_verdict.per_request_cost` — the one
202
- statistic the parent and the lane child both read — averages the most recent `RECENT_REQUEST_WINDOW`
203
- (10) requests, not the whole session**. The value is computed by
204
- `scripts/cost-runtime/context-cut-payback.ts`, its single source.
205
-
206
- **The cut is conditional**: taken only when the recent-window per-request cost
207
- is over `CONTEXT_CUT_THRESHOLD` — the same statistic and threshold the implementation-phase cut reads, so
208
- no second threshold exists. Below it `run:cut` answers `under-threshold` and the gate runs uncut; the
209
- guard reads the same verdict and stays silent. An **unmeasurable** session is always cut.
210
- Rationale: `docs/maintainers/pre-gate-cut-rationale.md` → "Why the threshold is a break-even".
211
-
212
- ## Consistency with the chain rule
213
-
214
- The chain forbids ending a turn at the push, with CI in flight and nothing set to resume. **The pre-gate
215
- cut and the detached hand-off end it _before_ the gate** and start what carries the run on in the same
216
- act — a fresh process, or the supervisor — so the push is never a turn boundary. The implementation-phase
217
- cut is the same pattern one boundary earlier.
169
+ **The trigger**: `pnpm josh rule:guard` refuses an `Edit` / `Write` in a dispatched lane child whose
170
+ recent-context cost is over threshold, handing back `pnpm josh run:cut --impl <N> --handoff <path>`.
171
+ `cut` ends the turn; a fresh process's `run:cut --resume <N>` answers `resume-impl` and continues
172
+ implementation — **the implementation resume clears the record**, so the cut may fire again. Outside
173
+ a lane, a held run on a measured `over` keeps the hold, sends a `confirmation` Telegram naming
174
+ `fullrun #<N>` and ends the turn. The refusal states the rest — **It fires on every threshold crossing,
175
+ not once per run**; **An edit reissued right after a refusal passes**; **An unmeasurable session
176
+ warrants the cut**; **It is silent between a cut and its resume**. Rationale:
177
+ `docs/maintainers/pre-gate-cut-rationale.md` → "Why the rules are guards, not prose";
178
+ `scripts/rules/implementation-cut.ts` implements it. A child that ended without cutting is detected
179
+ after the fact by `pnpm josh run:ending <N> --output <path>` (joshuafolkken/kit#2139).
180
+
181
+ ## The threshold
182
+
183
+ `CONTEXT_CUT_THRESHOLD` and the recent-window `cost_verdict.per_request_cost` (the last
184
+ `RECENT_REQUEST_WINDOW` requests) are computed by `scripts/cost-runtime/context-cut-payback.ts`, their
185
+ single source; both cuts and the parent hand-off read the same verdict, and an unmeasurable session is
186
+ always cut. Rationale: `docs/maintainers/pre-gate-cut-rationale.md` → "Why the threshold is a
187
+ break-even". Both cuts end the turn **before** the gate, in the same act that starts the successor, so
188
+ the push is never a turn boundary (`chain-rule.md`).
218
189
 
219
190
  ## A lane child records its park before it stops
220
191
 
221
- **A dispatched lane child records its park on the Issue before it stops for a decision**
222
- (joshuafolkken/kit#2034). A headless child's only route to ask a person is to park the Issue (#2012,
223
- #2011). Rationale:
224
- `docs/maintainers/pre-gate-cut-rationale.md` → "Why the rules are guards, not prose".
225
-
226
- **The record, before the Telegram, is the park procedure exactly** — `needs-decision` plus a comment
227
- carrying the question, the options, and whether work was stashed. Its single source is
228
- `backlogrun-park.md` → "park and continue", followed against the child's own Issue before the
229
- `confirmation` notify; with the label on the Issue, the parent's `pnpm josh run:liveness` reads the
230
- child as `settled`.
231
-
232
- **A `needs-human-review` or `already-done` stop needs nothing added** — those labels are already on the
233
- Issue. It is only a decision-stop (a Tier B toss-up, a Tier C action, an upstream defect, a split) that
234
- would otherwise leave the Issue bare.
235
-
236
- ### The stop notify refuses until the park is recorded
237
-
238
- `pnpm josh rule:guard` **refuses `pnpm josh notify --task-type confirmation`** while this checkout is a
239
- lane child — the mark `JOSH_LANE_CHILD` names this lane's own issue — handing back the park commands.
240
-
241
- - **It fires for a marked child and nowhere else.** A person's own `fullrun` carries no mark and sends
242
- its stop notify untouched.
243
- - **It fires once per run.** The child records the park and reissues the same notify; a
244
- `needs-human-review` or `already-done` stop reissues after the one delivery, its label already on the
245
- Issue.
246
- - **The park state is not readable synchronously**, so the delivery is a checklist — one wasted reissue
247
- on the compliant path is safe.
248
-
249
- This section is the single source of the lane-child park rule; `scripts/rules/lane-park.ts` implements
250
- the trigger, and the row joins the enumeration in
251
- `prompts/collaboration-workflow/rule-delivery.md`.
192
+ **The trigger**: a dispatched lane child about to stop for a decision (a Tier B toss-up, a Tier C
193
+ action, an upstream defect, a split) parks its own Issue first — `backlogrun-park.md` → "park and
194
+ continue" — so the parent's `pnpm josh run:liveness` reads it `settled` (joshuafolkken/kit#2034),
195
+ after #2012 and #2011. A `needs-human-review` or `already-done` stop already carries its label.
196
+ `pnpm josh rule:guard` refuses `pnpm josh notify --task-type confirmation` from a marked child until
197
+ then — **It fires once per run.**, and a person's own `fullrun` is never refused
198
+ (`scripts/rules/lane-park.ts`).
252
199
 
253
200
  ### The interactive ask is refused one call earlier
254
201
 
255
- (joshuafolkken/kit#2201) The harness refuses an interactive ask in a headless session by **ending the
256
- turn**, so the notify guard never fires (#2178 — the failure joshuafolkken/kit#2034 set out to prevent,
257
- one call upstream). So `pnpm josh rule:guard` **refuses `AskUserQuestion` for a marked lane child**; the
258
- deny returns to the model, and the instruction is to park the question. It fires on **every occurrence**
259
- and stays silent for a person working in a lane. Rationale:
260
- `docs/maintainers/pre-gate-cut-rationale.md` → "Why the rules are guards, not prose".
261
-
262
- **A child that slips past it is still recoverable** — `pnpm josh run:ending` lifts the refused ask out
263
- of the exit record's `permission_denials` into the `abandoned` verdict's park basis, so the parent puts
264
- it into the park comment. `scripts/rules/lane-interactive-ask.ts` implements the trigger, and
265
- `scripts/agent/interactive-ask.ts` is the
266
- shared extractor the guard and `run:ending` both read.
202
+ **The trigger**: a headless session ends the turn on an interactive ask, so the notify guard never
203
+ fires (#2178). `pnpm josh rule:guard` therefore refuses `AskUserQuestion` for a marked lane child on
204
+ every occurrence — park the question instead (joshuafolkken/kit#2201), completing
205
+ joshuafolkken/kit#2034. A child that slips past is recovered by `pnpm josh run:ending`, which lifts
206
+ the refused ask into the park basis; `scripts/rules/lane-interactive-ask.ts` and the shared
207
+ `scripts/agent/interactive-ask.ts` implement it.
267
208
 
268
- This file is the single source of the rule.
@@ -1,8 +1,8 @@
1
1
  # A prerequisite discovered mid-run — a dependency, not a park
2
2
 
3
- **This is the body of `SKILL.md` §2d, relocated here so the entry read carries the trigger and the
4
- pointer, not the procedure** (joshuafolkken/kit#2189). `SKILL.md` §2d is the resident stub, and each
5
- entry file (`fullrun.md` / `halfrun.md` / `backlogrun-park.md`) routes here for the definition. It is
3
+ **This file is the single source, so the entry read carries the trigger and the pointer, not the
4
+ procedure** (joshuafolkken/kit#2189). `SKILL.md` → §2's table keeps the trigger, and each entry file
5
+ (`entry-sequence.md` / `backlogrun-park.md`) routes here for the definition. It is
6
6
  read at its point of use — the moment a run discovers that another Issue in this repository has to
7
7
  land first.
8
8
 
@@ -18,12 +18,12 @@ another is the failure this section exists to prevent:
18
18
  | A defect originating in **another package** | File the upstream Issue and **stop** — Tier A for a first-party target; a third-party one is Tier C, recorded and drafted rather than filed (`CLAUDE.md` → "Cross-package problems"; `prompts/collaboration-workflow/upstream-interrupt.md`) |
19
19
  | This Issue was really **several** (a split) | File the children and the epic and **stop** — except under `backlogrun`, whose authorization already covers a batch, so the children are filed and run through (`split-assessment.md`) |
20
20
  | Another Issue in **this** repository has to land first (**a prerequisite**) | This section |
21
- | Something worth filing that is **none of the three** (**an observation**) | File it **without asking** — Tier A for a first-party target — and **carry the run straight on**: nothing is stashed, nothing is parked (§2i). **A delegated child does not file here**, and a filing at depth 1 or deeper cites the depth-0 work it blocked; one that cannot cite it goes to the run's own `docs/maintainers/observations/<N>.md` and is filed on its second sighting — all of them §2i's |
21
+ | Something worth filing that is **none of the three** (**an observation**) | File it **without asking** — Tier A for a first-party target — and **carry the run straight on**: nothing is stashed, nothing is parked (`observation-filing.md`). **A delegated child does not file here**, and a filing at depth 1 or deeper cites the depth-0 work it blocked; one that cannot cite it goes to the run's own `docs/maintainers/observations/<N>.md` and is filed on its second sighting — all of them `observation-filing.md`'s |
22
22
 
23
23
  **File the prerequisite with the `route:tier-a` label**, so a Tier A filing made during implementation
24
24
  stays countable by filing route afterwards. **This paragraph belongs to the prerequisite row, not to
25
25
  the table** — the label means a filing the run is *blocked by*, so the observation row carries no
26
- `route:` label of its own (§2i):
26
+ `route:` label of its own (`observation-filing.md`):
27
27
 
28
28
  ```bash
29
29
  pnpm josh issue:file "<title>" --body-file <body-file> --depth <n> --route tier-a
@@ -35,7 +35,7 @@ classification labels it declares, and runs the duplicate scan and `epic:bundle`
35
35
 
36
36
  Every "file the prerequisite" below means that labelled filing, and it always happens **first**: the
37
37
  steps after it name a number that does not exist until it is. **Its duplicate scan is read exactly as
38
- it is for a `new` entry** (§2e): a filing made mid-run is the one most likely to duplicate something.
38
+ it is for a `new` entry** (`issue-scout.md`): a filing made mid-run is the one most likely to duplicate something.
39
39
 
40
40
  **Each entry point's own branch stays in that entry's file:**
41
41
 
@@ -0,0 +1,90 @@
1
+ # The progress watcher — every implementing run
2
+
3
+ **Read this file in full when the run's hold is claimed, before the watcher starts.** It is a
4
+ point-of-use document, never an entry read, and the single source of the heartbeat for `fullrun`,
5
+ `halfrun`, `prrun` and the `backlogrun` parent alike (joshuafolkken/kit#3172). `kickoff` starts none.
6
+
7
+ ## Progress while the run is quiet
8
+
9
+ **Start the progress step without being asked** — in a single-issue run immediately after
10
+ `pnpm josh run:hold` succeeds, in a `backlogrun` before step 1 of its loop.
11
+
12
+ ```bash
13
+ pnpm josh run:progress --wait --output <the transcript path of each delegated unit> # in the background
14
+ ```
15
+
16
+ **Start it once; it reports by itself** (joshuafolkken/kit#3102). Each silence interval appends the
17
+ five labelled lines to the run's event stream as a heartbeat and to the ambient log, prints nothing to
18
+ standard output and keeps running — so a scheduled report never wakes the session, and the session
19
+ relays none. **It exits only on one of three, and the command computes which:**
20
+
21
+ | Exit | What the session does |
22
+ | ------------------------------------------------------- | ---------------------------------------------------------------------- |
23
+ | Newly runnable backlog work (the `ready #N` line) | Read the ready line, act on it, and restart the watcher in that turn |
24
+ | `pnpm josh followup` removed the run's life record | Nothing — the run has ended |
25
+ | `--hours` elapsed (8 by default for `--wait`) | Restart the watcher in that turn |
26
+
27
+ **A report is not an exit, and neither is a decline** — with no run recorded it keeps waiting, and the
28
+ `--hours` exit says so on standard error.
29
+
30
+ **`pnpm josh run:watcher:guard` detects a missed restart** (joshuafolkken/kit#2113): wired into
31
+ `pretool-guard` (joshuafolkken/kit#2353), it refuses the next tool call while lane children are in
32
+ flight and the watcher's life record has gone stale — once per run, so the restart is not blocked.
33
+
34
+ **`--mark` at every real report.** Whenever the run reports something of its own, run
35
+ `pnpm josh run:progress --mark` in the same turn to restart the silence clock. The clock is silence,
36
+ never a timer (`docs/josh-commands-automation.md` → "`josh run:progress`").
37
+
38
+ **Do not keep a progress clock of your own** — the hook refuses the arm rather than asking
39
+ (`scripts/rules/early-heartbeat.ts` → `decide`), though a single correctly-spaced arm is allowed.
40
+ `--wait` is not a wait timer.
41
+
42
+ **The default interval is twenty minutes, overridable — by the person, not the run.**
43
+ `JOSH_PROGRESS_INTERVAL_MINUTES` moves both sides (the guard reads it through the watcher's reader);
44
+ `josh` → `progress_interval_minutes` in `package.json` sits one step below the variable. **`--interval`
45
+ moves the watcher alone** — it makes the watcher quieter than the floor, never the guard stricter.
46
+ Rationale: `docs/maintainers/progress-watcher-rationale.md` → "Why the heartbeat reads as it does".
47
+
48
+ ### What a report says
49
+
50
+ **Every unscheduled progress statement is answered by `pnpm josh run:progress --once`** — the reply to
51
+ an explicit ask and the note just after a run starts alike; it is exempt from the interval and records
52
+ the report itself, so no `--mark` beside it. **Relay its five field lines verbatim** — round, rephrase
53
+ or re-label nothing, and **never write a clock time the command did not print**; where a field is
54
+ missing, say so. **A field's empty value is an observation, never a state** (`record unread` is not
55
+ *not stalled*), and **nothing in the lines is a verification result** — no gate, CI or check rollup.
56
+
57
+ **The heartbeat is ambient, never a Telegram.** `pnpm josh run:event --watch` is its reader, in a pane
58
+ of the person's own; **no session relays the stream** — name the watch command once, at the first cut
59
+ or when asked. `pnpm josh run:wake --list` is the one-line read for a person who types for it.
60
+
61
+ **A stop is the only interrupt** (joshuafolkken/kit#2136): a `backlogrun` that has stopped ends with
62
+ `pnpm josh run:carry --end --stopped "<reason>"`, which sends one ⏸️ confirmation; a parked child sends
63
+ its own (`backlogrun-park.md`). Rationale: `docs/maintainers/progress-watcher-rationale.md` → "Why the
64
+ signal tiers are split this way".
65
+
66
+ ### Who starts it, and what counts as a report
67
+
68
+ **One watcher per run, and the outermost invocation is the one that starts it.** `fullrun`, `halfrun`,
69
+ `prrun` and `backlogrun` start the same watcher under these rules. A `fullrun` running as a
70
+ `backlogrun` named issue or child starts none. **A dispatched lane child is refused a watcher by its
71
+ `JOSH_LANE_CHILD` mark** — it still runs `--mark` for the parent's clock, but every reporting form
72
+ (`--wait`, `--once`, the default watch) exits at once with a notice.
73
+
74
+ **It is started in the target repository's checkout, and `--mark` is run there too.** A heartbeat is
75
+ emitted from the moment a run has started — a registered lane, a held work tree or a carried budget —
76
+ even before any child carries `in-progress`; only a checkout with no run recorded stays silent.
77
+
78
+ **In a single-issue run, a real report is any turn that puts a progress statement in front of the
79
+ person** — four of them, `--mark` run in the same turn as each: **the Step 0 work summary, the pull
80
+ request opening, each review round's verdict, and any `confirmation` / `failure` / `completion`
81
+ notification or stop.** **A tool result only you read is not one** — a gate run, a `gh` read, an edit.
82
+ `--output` is omitted there, and `record` reads `unread`. In a `backlogrun`, a child merged, parked or
83
+ stopped is the report.
84
+
85
+ **A run that merges needs no teardown; a run that stops has to end the reporting itself.** A stop
86
+ keeps the `in-progress` label on purpose, so **no further `--wait` is started** after the stop
87
+ notification, and the running `--wait` is stopped in the same turn, since no report ends it. That
88
+ covers `halfrun`'s stop before commit, a `needs-human-review` stop, a split or prerequisite stop, and a
89
+ `backlogrun` named issue's failure stop. Rationale: `docs/maintainers/progress-watcher-rationale.md` →
90
+ "Why the watcher runs where it does".
@@ -2,16 +2,16 @@
2
2
 
3
3
  `prrun` sits between `halfrun` (stop before commit) and `fullrun` (auto-merge). It runs `fullrun`
4
4
  up to a green, mergeable pull request and **stops before the merge**, so a person merges by hand
5
- (joshuafolkken/kit#3023). **Read `fullrun.md` for every step** — the entry sequence, the step lists,
6
- the gate, the review and the stop branches are `fullrun`'s, unchanged. This file names only the
7
- difference, never a second copy of the procedure.
5
+ (joshuafolkken/kit#3023). **Read `fullrun.md` and `entry-sequence.md` for every step** — the entry
6
+ sequence, the step lists, the gate, the review and the stop branches are `fullrun`'s, unchanged. This
7
+ file names only the difference, never a second copy of the procedure.
8
8
 
9
9
  ## The difference — the entry
10
10
 
11
11
  `prrun #<N>` opens with `pnpm josh run:entry <N> --to prrun` where `fullrun` passes no `--to`
12
- (`SKILL.md` → §2k): a planned Issue starts at the implementation, a `halfrun` stop is adopted and
12
+ (`docs/how-to/run-issues.md`): a planned Issue starts at the implementation, a `halfrun` stop is adopted and
13
13
  resumes at the gate, and an Issue already stopped by a `prrun` is reached — report the stage line and
14
- stop. A merged Issue is reached too, but the `entry #<N>` line after the stage line answers it (§2k).
14
+ stop. A merged Issue is reached too, but the `entry #<N>` line after the stage line answers it.
15
15
 
16
16
  ## The difference — the end of the run
17
17
 
@@ -1,10 +1,10 @@
1
- # The end-of-run retrospective — `SKILL.md` §2j's body
1
+ # The end-of-run retrospective
2
2
 
3
- **This is `SKILL.md` → §2j's procedure, and it is read when `run:step` prints the retrospective step —
4
- not at the entry** (joshuafolkken/kit#2328). §2j keeps the rule itself: run what `run:step` prints once,
3
+ **This is the retrospective's procedure, and it is read when `run:step` prints the retrospective step —
4
+ not at the entry** (joshuafolkken/kit#2328). `SKILL.md` → §2's table keeps the rule itself: run what `run:step` prints once,
5
5
  file the improvements worth carrying into the next run, stack the rest, and mark the step done.
6
6
  Everything that decides *how* — what the four sections mean, how the top two are chosen rather than
7
- rationed, the exclusions, and the `auto-ok` carve-out that lets the next run pick them up — is here,
7
+ rationed, the exclusions, and the `auto-ok` default that lets the next run pick them up — is here,
8
8
  because none of it binds until a run has actually drained its backlog. A run that never empties its pool
9
9
  never reads it; the one that does reads it in full, in the same turn, before it files.
10
10
 
@@ -53,7 +53,7 @@ ceiling on what may be recorded. **File nothing when nothing passes** — a run
53
53
  improvement worth carrying files zero Issues, and that is what makes the "file → drain → file again"
54
54
  loop converge.
55
55
 
56
- **Exclude what is already filed or already done, through the existing scout** (`SKILL.md` → §2e). File
56
+ **Exclude what is already filed or already done, through the existing scout** (`issue-scout.md`). File
57
57
  each with `pnpm josh issue:file`, which runs the scout before creating anything: an **open** candidate
58
58
  covering the same work means do not file it, and a `(closed)` candidate covering it means the work is
59
59
  already merged. Neither exclusion is a new mechanism. The same call runs `epic:bundle` on each new
@@ -61,10 +61,10 @@ Issue, as after any filing.
61
61
 
62
62
  ## `auto-ok`, and closing the step
63
63
 
64
- **A retrospective may apply `auto-ok` to what it files** — the one path on which a run labels its own
65
- input, so the next run picks the improvements up without waiting for a person. **`backlogrun-steps.md` →
66
- "What one invocation approves" is that carve-out's single source**; it is written there, beside the
67
- brakes that bound it, rather than restated here. Every brake still counts a retrospective's filings: the
64
+ **What a retrospective files carries `auto-ok`** — it files while the carry record is live, so
65
+ `issue:file`'s default applies the label and the next run picks the improvements up without waiting
66
+ for a person. **`backlogrun-steps.md` → "What one invocation approves" is that default's single
67
+ source**; it is written there, beside the brakes that bound it, rather than restated here. Every brake still counts a retrospective's filings: the
68
68
  ten-per-invocation ceiling, the WIP cap, `--max`, the 150,000-token session budget and the 8-hour
69
69
  whole-run bound.
70
70
 
@@ -29,7 +29,7 @@ whether *several findings from one session* are one Issue — and reads the **sa
29
29
  same conjunction**: separability, and whether the whole clearly exceeds one gate.
30
30
  `pnpm josh issue:fold "<title>" …` answers `fold` / `separate` / `no-fold-needed`; its size half is
31
31
  `pnpm josh split:assess`, called not recomputed, and `separate` needs both halves exactly as `split`
32
- does. **There is no second criterion.** §2i's observation, the review round cap's branch 2 and §2d's
32
+ does. **There is no second criterion.** `observation-filing.md`'s observation, the review round cap's branch 2 and `prerequisite.md`'s
33
33
  prerequisite each route a second filing through it, delivered by `pnpm josh rule:guard` at the run's
34
34
  second `pnpm josh issue:file` call, never the first.
35
35
 
@@ -60,7 +60,7 @@ why a `split` from this command is the size condition met, not a decision to div
60
60
 
61
61
  "This needs something else done first" is a different answer from "this is really several things". A
62
62
  split means the request in hand contains two or more deliverables; a prerequisite means it is still
63
- **one** deliverable that has another one in front of it. The prerequisite rule is `SKILL.md` → §2d, its
63
+ **one** deliverable that has another one in front of it. The prerequisite rule is `prerequisite.md`, its
64
64
  single source; each entry's own branch is in `backlogrun-park.md` → "A prerequisite discovered mid-run" and, for
65
65
  the stopping entry points, in `fullrun.md` / `halfrun.md`.
66
66
 
@@ -1,9 +1,9 @@
1
1
  # The `owner/repo#` prefix — which repository the run acts on
2
2
 
3
- **This is `SKILL.md` → §2c's body, read at its point of use — the moment an entry is typed with an
3
+ **This file is the prefix's single source, read at its point of use — the moment an entry is typed with an
4
4
  `owner/repo#` prefix (or a short `repo#` name), not at any entry** (joshuafolkken/kit#2161). A run
5
5
  given a bare `#N` or `new` targets the session's own repository and never reaches it, so it costs a
6
- workflow entry nothing to leave it here. `SKILL.md` → §2c keeps the trigger and points here.
6
+ workflow entry nothing to leave it here. `SKILL.md` → §2's table keeps the trigger and points here.
7
7
 
8
8
  Every entry point takes the target repository in front of the Issue reference. Without it the target
9
9
  is the repository the session runs in.
@@ -1,8 +1,8 @@
1
1
  # The working-tree hold — one run per tree
2
2
 
3
- **This is the body of `SKILL.md` §2f, relocated here so the entry read carries the trigger and the
4
- pointer, not the procedure** (joshuafolkken/kit#2189). `SKILL.md` §2f is the resident stub, and
5
- `fullrun.md` / `halfrun.md` route here for the definition. It is read at its point of use — the moment
3
+ **This file is the single source, so the entry read carries the trigger and the pointer, not the
4
+ procedure** (joshuafolkken/kit#2189). `SKILL.md` → §2's table keeps the trigger, and
5
+ `entry-sequence.md` routes here for the definition. It is read at its point of use — the moment
6
6
  a run is about to claim or release the tree.
7
7
 
8
8
  **Ask `pnpm josh run:hold` before anything else, and obey what it answers.** It is the first call of
@@ -47,12 +47,14 @@ ordinary one.
47
47
  **Release what the claim recorded, which is not always the Issue number.** A `#N` entry claimed `<N>`
48
48
  and releases `<N>`; a **`new` entry claimed before its Issue existed**, so it releases with the
49
49
  **bare** form however many numbers the run has acquired since — so a `fullrun new` that stops on a
50
- split types `pnpm josh run:release`, not `pnpm josh run:release <N>`.
50
+ split types `pnpm josh run:release`, not `pnpm josh run:release <N>`. The bare form removes no
51
+ label, so every `new` stop that releases — a split, a prerequisite or a third-party target — also runs `gh api -X DELETE repos/{owner}/{repo}/issues/<N>/labels/in-progress
52
+ 2>/dev/null || true`.
51
53
 
52
54
  **Releasing is the run's, not a person's memory.** `pnpm josh followup` releases the hold on a merged
53
55
  run, and a record abandoned by a crashed session expires after 8 hours. **A stop that leaves the tree
54
56
  clean releases it explicitly**: a `fullrun` / `halfrun` that stops on a split, a prerequisite or a
55
- third-party target ends with `pnpm josh run:release <N>` (bare where that run entered as `new`).
57
+ third-party target ends with `pnpm josh run:release <N>` (bare where that run entered as `new`, followed by the label DELETE above).
56
58
  **`halfrun`'s stop before commit keeps the hold**, and so does a `needs-human-review` stop: the
57
59
  uncommitted work still in the tree is exactly what a second run would trample, so the release command
58
60
  goes in the stop report and the Telegram for the person to type. **`fullrun #<N>` of the same issue
package/.codex/hooks.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "hooks": [
18
18
  {
19
19
  "type": "command",
20
- "command": "if project_root=\"$(env -u GIT_ALTERNATE_OBJECT_DIRECTORIES -u GIT_COMMON_DIR -u GIT_DIR -u GIT_INDEX_FILE -u GIT_NAMESPACE -u GIT_OBJECT_DIRECTORY -u GIT_WORK_TREE git rev-parse --show-toplevel 2>/dev/null)\"; then unset GIT_ALTERNATE_OBJECT_DIRECTORIES GIT_COMMON_DIR GIT_DIR GIT_INDEX_FILE GIT_NAMESPACE GIT_OBJECT_DIRECTORY GIT_WORK_TREE; else project_root=\"$(git rev-parse --show-toplevel)\" || exit 1; fi; cd \"$project_root\" && if node --disable-warning=ExperimentalWarning scripts/hooks/hook-bundle-ready.ts; then node dist/hooks/session-lang.js; else pnpm josh session:lang; fi",
20
+ "command": "project_root=\"$(env -u GIT_ALTERNATE_OBJECT_DIRECTORIES -u GIT_COMMON_DIR -u GIT_DIR -u GIT_INDEX_FILE -u GIT_NAMESPACE -u GIT_OBJECT_DIRECTORY -u GIT_WORK_TREE git rev-parse --show-toplevel 2>/dev/null || git rev-parse --show-toplevel)\" && cd \"$project_root\" && sh scripts/hooks/run-hook.sh session-lang",
21
21
  "timeout": 10
22
22
  }
23
23
  ]
@@ -29,7 +29,7 @@
29
29
  "hooks": [
30
30
  {
31
31
  "type": "command",
32
- "command": "if project_root=\"$(env -u GIT_ALTERNATE_OBJECT_DIRECTORIES -u GIT_COMMON_DIR -u GIT_DIR -u GIT_INDEX_FILE -u GIT_NAMESPACE -u GIT_OBJECT_DIRECTORY -u GIT_WORK_TREE git rev-parse --show-toplevel 2>/dev/null)\"; then unset GIT_ALTERNATE_OBJECT_DIRECTORIES GIT_COMMON_DIR GIT_DIR GIT_INDEX_FILE GIT_NAMESPACE GIT_OBJECT_DIRECTORY GIT_WORK_TREE; else project_root=\"$(git rev-parse --show-toplevel)\" || exit 1; fi; cd \"$project_root\" && if node --disable-warning=ExperimentalWarning scripts/hooks/hook-bundle-ready.ts; then node dist/hooks/codex-hook-adapter.js pretool; else pnpm exec tsx scripts/hooks/codex-hook-adapter.ts pretool; fi",
32
+ "command": "project_root=\"$(env -u GIT_ALTERNATE_OBJECT_DIRECTORIES -u GIT_COMMON_DIR -u GIT_DIR -u GIT_INDEX_FILE -u GIT_NAMESPACE -u GIT_OBJECT_DIRECTORY -u GIT_WORK_TREE git rev-parse --show-toplevel 2>/dev/null || git rev-parse --show-toplevel)\" && cd \"$project_root\" && sh scripts/hooks/run-hook.sh codex-hook-adapter pretool",
33
33
  "timeout": 20
34
34
  }
35
35
  ]
@@ -41,7 +41,7 @@
41
41
  "hooks": [
42
42
  {
43
43
  "type": "command",
44
- "command": "if project_root=\"$(env -u GIT_ALTERNATE_OBJECT_DIRECTORIES -u GIT_COMMON_DIR -u GIT_DIR -u GIT_INDEX_FILE -u GIT_NAMESPACE -u GIT_OBJECT_DIRECTORY -u GIT_WORK_TREE git rev-parse --show-toplevel 2>/dev/null)\"; then unset GIT_ALTERNATE_OBJECT_DIRECTORIES GIT_COMMON_DIR GIT_DIR GIT_INDEX_FILE GIT_NAMESPACE GIT_OBJECT_DIRECTORY GIT_WORK_TREE; else project_root=\"$(git rev-parse --show-toplevel)\" || exit 1; fi; cd \"$project_root\" && if node --disable-warning=ExperimentalWarning scripts/hooks/hook-bundle-ready.ts; then node dist/hooks/codex-hook-adapter.js posttool; else pnpm exec tsx scripts/hooks/codex-hook-adapter.ts posttool; fi",
44
+ "command": "project_root=\"$(env -u GIT_ALTERNATE_OBJECT_DIRECTORIES -u GIT_COMMON_DIR -u GIT_DIR -u GIT_INDEX_FILE -u GIT_NAMESPACE -u GIT_OBJECT_DIRECTORY -u GIT_WORK_TREE git rev-parse --show-toplevel 2>/dev/null || git rev-parse --show-toplevel)\" && cd \"$project_root\" && sh scripts/hooks/run-hook.sh codex-hook-adapter posttool",
45
45
  "timeout": 90
46
46
  }
47
47
  ]
@@ -53,7 +53,7 @@
53
53
  "hooks": [
54
54
  {
55
55
  "type": "command",
56
- "command": "if project_root=\"$(env -u GIT_ALTERNATE_OBJECT_DIRECTORIES -u GIT_COMMON_DIR -u GIT_DIR -u GIT_INDEX_FILE -u GIT_NAMESPACE -u GIT_OBJECT_DIRECTORY -u GIT_WORK_TREE git rev-parse --show-toplevel 2>/dev/null)\"; then unset GIT_ALTERNATE_OBJECT_DIRECTORIES GIT_COMMON_DIR GIT_DIR GIT_INDEX_FILE GIT_NAMESPACE GIT_OBJECT_DIRECTORY GIT_WORK_TREE; else project_root=\"$(git rev-parse --show-toplevel)\" || exit 1; fi; cd \"$project_root\" && if node --disable-warning=ExperimentalWarning scripts/hooks/hook-bundle-ready.ts; then node dist/hooks/stop-guard.js; else pnpm josh stop:guard; fi",
56
+ "command": "project_root=\"$(env -u GIT_ALTERNATE_OBJECT_DIRECTORIES -u GIT_COMMON_DIR -u GIT_DIR -u GIT_INDEX_FILE -u GIT_NAMESPACE -u GIT_OBJECT_DIRECTORY -u GIT_WORK_TREE git rev-parse --show-toplevel 2>/dev/null || git rev-parse --show-toplevel)\" && cd \"$project_root\" && sh scripts/hooks/run-hook.sh stop-guard",
57
57
  "timeout": 20
58
58
  }
59
59
  ]
package/AGENTS.md CHANGED
@@ -3,9 +3,4 @@
3
3
  > **All rules for this repository live in [`CLAUDE.md`](./CLAUDE.md). Read it in full before doing
4
4
  > any work here, and follow every rule in it.** This file exists only to point at it.
5
5
 
6
- **Codex runs the same hooks from `.codex/hooks.json`**, generated from `.claude/settings.json`; where
7
- it does not show a hook's output, apply that rule yourself. How to read `CLAUDE.md`'s Claude Code
8
- features here is `prompts/collaboration-workflow/principles.md` → "Claude Code 以外のエージェントでの読み替え".
9
-
10
- **Do not copy rules back into this file.** Every change to how agents work in this repository belongs
11
- in `CLAUDE.md`.
6
+ **Codex runs the same hooks from `.codex/hooks.json`** (generated from `.claude/settings.json`) — apply any rule whose hook output you do not see yourself, per `prompts/collaboration-workflow/principles.md` → "Claude Code 以外のエージェントでの読み替え". Do not copy rules back into this file.