@joshuafolkken/kit 1.1455.0 → 1.1471.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/.claude/skills/dependency-update/SKILL.md +26 -55
  2. package/.claude/skills/epic-commands/SKILL.md +87 -148
  3. package/.claude/skills/epic-commands/epic-bundle.md +45 -77
  4. package/.claude/skills/epic-commands/execution-waves.md +44 -81
  5. package/.claude/skills/verify-ui/SKILL.md +25 -50
  6. package/.claude/skills/workflow-commands/background-commands.md +36 -47
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +72 -85
  8. package/.claude/skills/workflow-commands/backlogrun-lanes.md +91 -121
  9. package/.claude/skills/workflow-commands/backlogrun-park.md +73 -117
  10. package/.claude/skills/workflow-commands/backlogrun-progress.md +7 -9
  11. package/.claude/skills/workflow-commands/backlogrun-recovery.md +11 -20
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +43 -52
  13. package/.claude/skills/workflow-commands/chain-rule.md +24 -34
  14. package/.claude/skills/workflow-commands/followup.md +57 -76
  15. package/.claude/skills/workflow-commands/issue-comments.md +43 -60
  16. package/.claude/skills/workflow-commands/kickoff.md +65 -74
  17. package/.claude/skills/workflow-commands/observation-filing.md +62 -107
  18. package/.claude/skills/workflow-commands/observation-ledger.md +56 -111
  19. package/.claude/skills/workflow-commands/pre-gate-cut.md +89 -138
  20. package/.claude/skills/workflow-commands/prerequisite.md +10 -15
  21. package/.claude/skills/workflow-commands/progress-watcher.md +21 -26
  22. package/.claude/skills/workflow-commands/retrospective.md +31 -50
  23. package/.claude/skills/workflow-commands/split-assessment.md +34 -58
  24. package/.claude/skills/workflow-commands/working-tree-hold.md +54 -71
  25. package/CLAUDE.md +6 -5
  26. package/dist/CLAUDE.md +6 -5
  27. package/dist/hooks/batch-guard.js +6 -6
  28. package/dist/hooks/{chunk-7WQBPLUN.js → chunk-43ZHT22P.js} +31 -15
  29. package/dist/hooks/{chunk-LIAFCXL7.js → chunk-AS74OU3D.js} +23 -7
  30. package/dist/hooks/{chunk-3C4XRYG6.js → chunk-E7OIKX5Z.js} +17 -12
  31. package/dist/hooks/{chunk-Z4XI7CZS.js → chunk-EUMACUK2.js} +18 -12
  32. package/dist/hooks/{chunk-WNLVGT7E.js → chunk-H5HVWYXK.js} +4 -4
  33. package/dist/hooks/{chunk-HHI6FO3R.js → chunk-IIGFYXKC.js} +345 -240
  34. package/dist/hooks/{chunk-GPLGZ6IC.js → chunk-J47HU5H5.js} +14 -3
  35. package/dist/hooks/{chunk-OLMO72ON.js → chunk-K4EOONYM.js} +1 -1
  36. package/dist/hooks/{chunk-D5QBTOCZ.js → chunk-K4LMBQC2.js} +4 -4
  37. package/dist/hooks/{chunk-TBJFTSUY.js → chunk-KC5AK2GF.js} +8 -6
  38. package/dist/hooks/chunk-SHGPANFB.js +56 -0
  39. package/dist/hooks/{chunk-5H4SSDSD.js → chunk-YHBZAJSV.js} +3 -3
  40. package/dist/hooks/{chunk-HFGWYGUV.js → chunk-YYPI7SJZ.js} +5 -5
  41. package/dist/hooks/codex-hook-adapter.js +13 -13
  42. package/dist/hooks/duplicate-read-guard.js +7 -7
  43. package/dist/hooks/format-edited.js +3 -3
  44. package/dist/hooks/inputs.json +216 -214
  45. package/dist/hooks/investigation-guard.js +7 -7
  46. package/dist/hooks/pretool-guard.js +12 -12
  47. package/dist/hooks/session-lang.js +6 -5
  48. package/dist/hooks/stop-guard.js +18 -14
  49. package/dist/josh.js +5 -6
  50. package/dist/managed-marker/index.js +1 -2
  51. package/dist/version/index.js +15 -12
  52. package/eslint/base.js +2 -1
  53. package/eslint/rules/unicorn.js +16 -0
  54. package/package.json +3 -3
  55. package/prompts/coding-standards.md +12 -22
  56. package/prompts/collaboration-workflow/file-edits.md +26 -44
  57. package/prompts/collaboration-workflow/gh-rest.md +20 -36
  58. package/prompts/collaboration-workflow/glossary.md +5 -7
  59. package/prompts/collaboration-workflow/issue-citation.md +7 -13
  60. package/prompts/collaboration-workflow/issue-template.md +29 -29
  61. package/prompts/collaboration-workflow/operating-rules.md +35 -44
  62. package/prompts/collaboration-workflow/output-bounds.md +15 -15
  63. package/prompts/collaboration-workflow/overview.md +14 -19
  64. package/prompts/collaboration-workflow/plan-comment.md +13 -13
  65. package/prompts/collaboration-workflow/principles.md +50 -53
  66. package/prompts/collaboration-workflow/proposal-request.md +1 -9
  67. package/prompts/collaboration-workflow/report-format.md +32 -49
  68. package/prompts/collaboration-workflow/residency.md +10 -10
  69. package/prompts/collaboration-workflow/rule-delivery.md +9 -9
  70. package/prompts/collaboration-workflow/shell-body.md +10 -20
  71. package/prompts/collaboration-workflow/turn-batching.md +8 -14
  72. package/prompts/collaboration-workflow/upstream-interrupt.md +26 -34
  73. package/prompts/collaboration-workflow/wip-cap.md +24 -30
  74. package/prompts/collaboration-workflow.md +24 -25
  75. package/prompts/refactoring.md +33 -43
  76. package/prompts/review-rubric.md +84 -129
  77. package/prompts/review.md +111 -141
  78. package/prompts/sonar-hotspot-handling.md +22 -50
  79. package/prompts/testing-guide.md +48 -99
  80. package/scripts/adopt/adopt-toolkits.ts +2 -4
  81. package/scripts/agent/agent-exit-record.ts +23 -1
  82. package/scripts/agent/codex-agent-argv.ts +7 -2
  83. package/scripts/backlog/backlog-budget-cli.ts +1 -2
  84. package/scripts/backlog/backlog-drive-carried.ts +26 -0
  85. package/scripts/backlog/backlog-drive-cli.ts +10 -5
  86. package/scripts/backlog/backlog-drive-named.ts +2 -4
  87. package/scripts/backlog/backlog-drive-restore.ts +19 -1
  88. package/scripts/backlog/backlog-drive-seats.ts +27 -0
  89. package/scripts/backlog/backlog-drive.ts +11 -6
  90. package/scripts/backlog/backlog-ready.ts +13 -6
  91. package/scripts/behavior/behavior-rules.ts +3 -2
  92. package/scripts/cost-runtime/codex-usage.ts +4 -2
  93. package/scripts/cost-runtime/cost-cli.ts +1 -2
  94. package/scripts/delegation/investigation-guard.ts +1 -1
  95. package/scripts/delegation/investigation-reads.ts +1 -1
  96. package/scripts/discovery/repo-discovery.ts +4 -2
  97. package/scripts/discovery/repo-origin.ts +2 -4
  98. package/scripts/doctor/doctor-logic.ts +6 -3
  99. package/scripts/document/document-byte-budget.ts +27 -27
  100. package/scripts/document/document-byte-check.ts +1 -2
  101. package/scripts/document/entry-read-budget.ts +2 -2
  102. package/scripts/epic/epic-audit-rationale.ts +8 -2
  103. package/scripts/epic/epic-bundle-cli.ts +1 -2
  104. package/scripts/epic/epic-chains.ts +6 -2
  105. package/scripts/epic/epic-close-comment.ts +1 -2
  106. package/scripts/gate/verification-gate.ts +7 -2
  107. package/scripts/gh/git-pr.ts +6 -2
  108. package/scripts/git/git-common-directory.ts +3 -3
  109. package/scripts/git/git-diff-reads.ts +16 -9
  110. package/scripts/git/git-execa-error.ts +1 -2
  111. package/scripts/hooks/format-edited-file.ts +10 -4
  112. package/scripts/hooks/pre-push-unit.ts +15 -4
  113. package/scripts/hooks/pretool-guard.ts +23 -29
  114. package/scripts/hooks/step-zero-notice.ts +3 -2
  115. package/scripts/init/hook-command-rewrite.ts +6 -2
  116. package/scripts/init/init-logic-deploy-vps.ts +4 -2
  117. package/scripts/issue/behavior-change-lint.ts +12 -6
  118. package/scripts/issue/issue-scout-cli.ts +3 -2
  119. package/scripts/josh/file-map-stamp.ts +1 -3
  120. package/scripts/josh/hook-decision.ts +17 -2
  121. package/scripts/lane/lane-await.ts +3 -2
  122. package/scripts/lane/lane-child-invocation.ts +14 -1
  123. package/scripts/lane/lane-guard-policy.ts +4 -4
  124. package/scripts/lane/lane-ledger.ts +9 -0
  125. package/scripts/lane/lane-load.ts +9 -2
  126. package/scripts/lane/lane-measure-cli.ts +2 -0
  127. package/scripts/lane/lane-parked.ts +18 -0
  128. package/scripts/lane/lane-process-load.ts +125 -0
  129. package/scripts/lane/lane-process-stats.ts +93 -0
  130. package/scripts/lane/lane-registry.ts +8 -3
  131. package/scripts/lane/lane-session-broker.ts +29 -5
  132. package/scripts/lane/lane-spent.ts +14 -3
  133. package/scripts/lane/lane-stats.ts +1 -0
  134. package/scripts/managed-marker/managed-marker-logic.ts +1 -2
  135. package/scripts/overrides/lockfile-overrides.ts +1 -3
  136. package/scripts/propagate/propagate.ts +1 -2
  137. package/scripts/release/release-progress.ts +3 -2
  138. package/scripts/report/report-lint.ts +7 -4
  139. package/scripts/review/review-record-cli.ts +6 -2
  140. package/scripts/rules/destructive-command.ts +6 -9
  141. package/scripts/rules/direct-filing.ts +3 -7
  142. package/scripts/rules/early-heartbeat.ts +7 -18
  143. package/scripts/rules/file-body.ts +6 -13
  144. package/scripts/rules/filing-cap.ts +3 -6
  145. package/scripts/rules/git-force.ts +5 -9
  146. package/scripts/rules/implementation-cut.ts +37 -35
  147. package/scripts/rules/index-guard.ts +4 -7
  148. package/scripts/rules/issue-comments.ts +5 -15
  149. package/scripts/rules/josh-git-bare.ts +3 -6
  150. package/scripts/rules/lane-background.ts +10 -21
  151. package/scripts/rules/lane-carry-conflict.ts +7 -17
  152. package/scripts/rules/lane-interactive-ask.ts +6 -11
  153. package/scripts/rules/lane-park.ts +5 -13
  154. package/scripts/rules/lane-split-park.ts +2 -7
  155. package/scripts/rules/lane-switch-main.ts +9 -12
  156. package/scripts/rules/oracle-consulted.ts +4 -5
  157. package/scripts/rules/piped-verification.ts +81 -31
  158. package/scripts/rules/poll-loop.ts +7 -17
  159. package/scripts/rules/pre-gate-cut.ts +7 -21
  160. package/scripts/rules/prior-comment-read.ts +7 -5
  161. package/scripts/rules/protected-files.ts +5 -9
  162. package/scripts/rules/raw-field-body.ts +3 -7
  163. package/scripts/rules/rule-body-guard.ts +4 -11
  164. package/scripts/rules/run-tail-rule.ts +6 -22
  165. package/scripts/rules/shell-body-trigger.ts +4 -6
  166. package/scripts/rules/shell-segments.ts +7 -0
  167. package/scripts/rules/stop-rules.ts +16 -29
  168. package/scripts/rules/test-declared-commit.ts +4 -10
  169. package/scripts/rules/third-party-write.ts +5 -10
  170. package/scripts/rules/worktree-guard.ts +5 -12
  171. package/scripts/run/board/run-board-github.ts +11 -3
  172. package/scripts/run/board/run-board-idle.ts +31 -0
  173. package/scripts/run/board/run-board-read.ts +9 -12
  174. package/scripts/run/board/run-board-reason.ts +7 -3
  175. package/scripts/run/board/run-board-state.ts +4 -0
  176. package/scripts/run/board/run-board-status.ts +18 -3
  177. package/scripts/run/board/run-board-thanks.ts +7 -2
  178. package/scripts/run/board/run-board-tick.ts +32 -7
  179. package/scripts/run/carry/run-carry-args.ts +1 -3
  180. package/scripts/run/carry/run-carry-conversation.ts +7 -2
  181. package/scripts/run/cut/run-cut-cli.ts +15 -20
  182. package/scripts/run/cut/run-cut-decline.ts +72 -0
  183. package/scripts/run/cut/run-cut-ready.ts +74 -0
  184. package/scripts/run/cut/run-cut-report.ts +13 -0
  185. package/scripts/run/cut/run-cut.ts +10 -1
  186. package/scripts/run/hold/run-hold-cli.ts +14 -3
  187. package/scripts/run/hold/run-hold.ts +6 -3
  188. package/scripts/run/merge/run-merge-cli.ts +30 -7
  189. package/scripts/run/merge/run-merge-ship.ts +59 -1
  190. package/scripts/run/merge/run-merge.ts +3 -2
  191. package/scripts/run/run-ending.ts +31 -3
  192. package/scripts/run/run-parent-cut-hook.ts +5 -10
  193. package/scripts/run/run-preflight.ts +1 -2
  194. package/scripts/run/run-stop-notify.ts +1 -2
  195. package/scripts/run/run-watcher-guard.ts +6 -3
  196. package/scripts/run/ship/run-ship-review-steps.ts +13 -4
  197. package/scripts/run/ship/run-ship-review.ts +15 -2
  198. package/scripts/run/tidy/run-tidy-cli.ts +3 -3
  199. package/scripts/run/tidy/run-tidy-lanes.ts +3 -2
  200. package/scripts/safe-chain/project-config.ts +7 -2
  201. package/scripts/sync/sync-hook-safety.ts +8 -2
  202. package/scripts/test/unit-worker-share.ts +3 -2
  203. package/scripts/time-runtime/time-batch-guard.ts +3 -3
  204. package/scripts/time-runtime/time-hook-transcript.ts +3 -2
  205. package/scripts/time-runtime/time-shell.ts +10 -0
  206. package/scripts/version/effective-upstream.ts +3 -4
  207. package/scripts/version/kit-version-config.ts +8 -2
  208. package/scripts/version/latest-corepack.ts +1 -2
  209. package/scripts/version/release-hold.ts +11 -4
  210. package/scripts/version/version-commands.ts +12 -4
  211. package/dist/hooks/chunk-UT7YC3N2.js +0 -56
@@ -1,39 +1,26 @@
1
1
  # The observation ledger — grammar, commit path and promotion
2
2
 
3
3
  **Read only when the depth test in `observation-filing.md` turns an observation away, or a user
4
- reports a bug** (its kind of miss, below), in the turn that appends the line.
5
- A run that files outright, or finds nothing, never reads it. This file is the single source of the ledger's grammar, its commit path and the
6
- second-sighting promotion. Provenance: `docs/maintainers/observation-ledger-rationale.md` → "Where
7
- each rule came from".
4
+ reports a bug** (its kind of miss, below), in the turn that appends the line. Single source of the
5
+ ledger's grammar, commit path and second-sighting promotion. Provenance:
6
+ `docs/maintainers/observation-ledger-rationale.md` → "Where each rule came from".
8
7
 
9
8
  ## The ledger — where an observation that cannot cite a blockage goes
10
9
 
11
- **An observation the depth test turns away is recorded in the ledger, not discarded.**
12
- Rationale: `docs/maintainers/observation-ledger-rationale.md` → "Why the
13
- ledger exists".
14
-
15
- - **The destination is the `.josh/observations/` directory in the repository the
16
- observation is about** — the same repository the Issue would have been filed into — **one file per
17
- issue**: append to `<N>.md` for the issue the run is executing (the number
18
- its branch leads with, a lane's included), or to `<YYYY-MM-DD>.md` for a line written on the
19
- default branch outside any issue's run. Parallel lanes therefore write different files, and their
20
- pull requests never conflict on the ledger. **The count and the append are both run in that
21
- repository's checkout** — in this repository, the work tree the run is in, a lane's inside a lane —
22
- resolved the way `target-repository.md` resolves any cross-repository target, and the
23
- directory is created on the first append where that repository has none. **The subject decides, never the
24
- working directory**: an observation about this package's own orchestration, seen while a run is
25
- inside a repository that consumes it, is recorded here rather than there — the append follows the
26
- subject, never the working directory. **A third-party target gets no line either** — Tier C covers
27
- the ledger exactly as it covers the Issue that would otherwise have been filed there.
28
- - **It is append-only.** A line is never edited and never deleted, because the count of lines
29
- carrying one key is what says whether an observation has recurred; a second sighting is a second
30
- line, not a rewrite of the first. **A merge conflict in it is resolved by keeping both sides** —
31
- one file per issue should keep it from arising, but a repeated key is the whole signal, so
32
- dropping either side destroys exactly what the ledger is for.
33
- - **The completion report keeps its line too.** The ledger is what the next run can read; the report
34
- is what this run's reader sees. Neither replaces the other.
35
- - **The append is not the end of it** — a line only becomes readable to anyone else once it has
36
- merged, and "The commit path" below is how it gets there.
10
+ **An observation the depth test turns away is recorded in the ledger, not discarded.** Rationale:
11
+ `docs/maintainers/observation-ledger-rationale.md` → "Why the ledger exists".
12
+
13
+ - **The destination is the `.josh/observations/` directory in the repository the observation is
14
+ about**, **one file per issue**: `<N>.md` for the issue the run is executing (its branch's number,
15
+ a lane's included), or `<YYYY-MM-DD>.md` on the default branch outside any issue's run. **The count
16
+ and the append are both run in that repository's checkout** (resolved as `target-repository.md`
17
+ resolves a target). **The subject decides, never the working directory.** **A third-party target
18
+ gets no line either** (Tier C).
19
+ - **It is append-only.** Never edit or delete a line; a second sighting is a second line. **A merge
20
+ conflict in it is resolved by keeping both sides.**
21
+ - **The completion report keeps its line too.**
22
+ - **The append is not the end of it** — → "The commit path — how an appended line reaches the
23
+ default branch" below.
37
24
 
38
25
  **One observation is one line: five fields, each separated from the next by a vertical bar with one
39
26
  space on either side.**
@@ -44,118 +31,76 @@ space on either side.**
44
31
 
45
32
  | Field | What it holds |
46
33
  | -------------- | ------------------------------------------------------------------------------------------------------------------------- |
47
- | `k:<slug>` | The identity key — lowercase letters and digits, in words joined by `-`. This is what makes a repeat machine-readable |
48
- | `d<n>` | The depth of the subject — `d1`, `d2`, or whatever deeper depth `observation-filing.md`'s depth table may one day name. **There is no `d0` line**: a depth-0 observation is filed outright and never reaches the ledger |
34
+ | `k:<slug>` | The identity key — lowercase letters and digits, in words joined by `-` |
35
+ | `d<n>` | The depth of the subject — `d1`, `d2`, or deeper. **There is no `d0` line**: depth 0 is filed outright |
49
36
  | `<YYYY-MM-DD>` | The date of **this** sighting |
50
37
  | `<where>` | One file path or one command — where the thing was seen |
51
38
  | `<what>` | The phenomenon, one sentence, carrying no vertical bar of its own |
52
39
 
53
- A sample, in the shape a real entry takes:
54
-
55
40
  ```
56
41
  - k:example | d1 | 2026-09-10 | pnpm josh run:progress | The report printed a fill-in placeholder where a clock time belonged
57
42
  ```
58
43
 
59
- **`k:example` is reserved for this sample and is never used by a real observation**, so the count
60
- below can be run over the whole ledger without the sample answering for one. **The grammar is defined
61
- here rather than in the ledger** (`docs/maintainers/observation-ledger-rationale.md` → "Why the
62
- ledger exists").
44
+ **`k:example` is reserved for this sample and is never used by a real observation.**
63
45
 
64
46
  **The identity key is the whole of the repeat test — never a similarity judgement about the prose.**
65
- Choose the key from the phenomenon rather than from the run, then record the sighting with one
66
- command — it counts what the ledger already holds for the key, appends the line and prints the
67
- verdict:
47
+ Choose it from the phenomenon, not the run, and record with one command:
68
48
 
69
49
  ```bash
70
50
  pnpm josh observation:record <slug> d<n> '<where>' '<what>' [--checkout <that repository's checkout>]
71
51
  ```
72
52
 
73
- Standard output is one token: `file` (this is the second sighting — file it, below) or `ledger` (the
74
- line is the record, nothing to file); standard error lists the earlier sightings and the file
75
- appended to. A line that breaks the grammar, or uses `k:example`, is refused with exit 1 and nothing
76
- appended. **Every
77
- file of the directory is counted**, in the named checkout rather than the working directory, because
78
- a recurrence is a recurrence whichever issue's file each sighting sits in; a missing directory is a
79
- first sighting, and the append creates it.
80
-
81
- Free-text comparison is what the key exists to replace, so two lines that read alike under different
82
- keys are two observations, and a mis-keyed entry is corrected by appending a correctly-keyed line
83
- rather than by editing the one already written.
53
+ Standard output is one token: `file` (second sighting — file it, below) or `ledger` (nothing to file);
54
+ standard error lists earlier sightings and the file appended to. A broken line, or `k:example`, exits
55
+ 1 with nothing appended. **Every file of the directory is counted**, in the named checkout. A
56
+ mis-keyed entry is corrected by appending a correctly-keyed line.
84
57
 
85
- **The depth gate is not withdrawn, and this is not a way around it.** An observation that *can* cite
86
- the depth-0 work it stopped is filed exactly as it was before — this route is only for the ones that
87
- could not.
58
+ **The depth gate is not withdrawn, and this is not a way around it** — an observation that *can* cite
59
+ blocked depth-0 work is filed as before.
88
60
 
89
61
  ## The commit path — how an appended line reaches the default branch
90
62
 
91
63
  **An append nobody commits is an append nobody can count.** Rationale:
92
64
  `docs/maintainers/observation-ledger-rationale.md` → "Why the ledger has a commit path".
93
65
 
94
- - **A run's appended lines ride its own commit.** `pnpm josh git` stages
95
- `.josh/observations/` with the run's other changes, in the one staging step every entry
96
- point goes through (`scripts/git/git-staging.ts`), so the lines are reviewed and merged with the
97
- pull request of the run that recorded them, and the run's CI is the only wait they cost.
98
- **Record before the commit, not after the merge:** a finding recorded with `pnpm josh review:record`
99
- before `pnpm josh git -y` is carried; the time while CI runs is for the records that need no CI
100
- result — filing an observation Issue, drafting the completion report.
101
- - **A line that breaks the grammar is not carried.** The staging step parses
102
- every file of the ledger first — after moving lines still on an old single-file path — and on a broken line leaves the ledger out of the
103
- commit and says so; the commit itself goes ahead.
66
+ - **A run's appended lines ride its own commit** — `pnpm josh git` stages `.josh/observations/`
67
+ (`scripts/git/git-staging.ts`). **Record before the commit, not after the merge:** a finding recorded
68
+ with `pnpm josh review:record` before `pnpm josh git -y` is carried.
69
+ - **A line that breaks the grammar is not carried** — the ledger is left out of the commit, which
70
+ goes ahead.
104
71
  - **A review round that passes after the pull request opened is recorded on the Issue, not in the
105
- ledger** — `pnpm josh review:record --issue <N> --comment` posts the same `- rf:` lines as a comment
106
- and appends nothing. That round reads only, so no commit of the run's follows it; a line in the tree
107
- would be pushed onto the open pull request and its CI would start over. `pnpm josh ship --review`
108
- does this for a passing round 2. **A round 2 that blocks records in the tree as before** — the fix it
109
- stops for is pushed anyway and carries the lines. Once the Issue is closed, the next round recorded
110
- to the ledger carries the comment's lines into `<N>-comment-rounds.md` with its own commit, so
111
- `pnpm josh review:findings` and the retrospective count them (`review-comment-round.ts`).
72
+ ledger** — `pnpm josh review:record --issue <N> --comment` (`pnpm josh ship --review` does this for a
73
+ passing round 2), so CI does not restart. **A round 2 that blocks records in the tree as before.**
74
+ Once the Issue closes, the next ledger round carries the comment's lines into
75
+ `<N>-comment-rounds.md` (`review-comment-round.ts`).
112
76
  - **`pnpm josh followup` commits any other line appended after the run's commit onto the pull request,
113
- before the merge** — the residual path, for an observation recorded between the commit and the
114
- merge. After the merge gates and before the CI wait, `followup` reads the tree and, **only when the
115
- ledger holds a pending append**, stages the ledger paths alone, commits them and pushes the branch;
116
- that push restarts the pull request's CI, and the wait that follows covers it. A broken line refuses
117
- the merge, because the line would otherwise be lost with the branch. A run whose lines rode its
118
- commit pays nothing.
119
- - **A lane carries its own lines, in its own pull request.** Its writers
120
- append to its own tree's `<N>.md`, so the two steps above take them to the default branch exactly as
121
- they do for a run in the primary checkout. **Nothing is held in the primary checkout for later.**
122
- - **`pnpm josh observations:flush` is left for a line written outside any issue's run** — the
123
- date-named file a retrospective or a hand append on the default branch writes. It stages the ledger
124
- and nothing else, commits it on a branch of its own, opens a docs-only pull request, waits on the
125
- same required checks every other pull request waits on, merges it and returns the checkout to the
126
- default branch; a single run's `run:tail` runs it after the merge. It refuses off the default branch
127
- and refuses a working tree holding anything besides the ledger, so a run in progress cannot be
128
- flushed out from under. **Nothing is committed to the default branch directly.**
129
- - **Nothing to flush is an answer, not a failure.** With the ledger matching the commit it sits on
130
- the command prints `clean` and exits 0.
77
+ before the merge** — only when the ledger holds a pending append; a broken line refuses the merge.
78
+ - **A lane carries its own lines, in its own pull request.**
79
+ **Nothing is held in the primary checkout for later.**
80
+ - **`pnpm josh observations:flush` is left for a line written outside any issue's run**: it commits the
81
+ ledger alone on its own branch, opens a docs-only pull request, waits on the required checks, merges
82
+ and returns to the default branch (a single run's `run:tail` runs it). It refuses off the default
83
+ branch or with anything besides the ledger in the tree. **Nothing is committed to the default branch
84
+ directly.**
85
+ - **Nothing to flush is an answer, not a failure** — `clean`, exit 0.
131
86
  - **The count the promotion below reads is a count of the default branch.**
132
87
 
133
88
  ## The second sighting is what files it
134
89
 
135
- **A repeat is the citation**, so the gate has a second way through, and it is counted rather than
136
- judged (rationale: `docs/maintainers/observation-ledger-rationale.md` → "Why a second sighting
137
- files"):
90
+ **A repeat is the citation** — counted, not judged (`docs/maintainers/observation-ledger-rationale.md`
91
+ → "Why a second sighting files"):
138
92
 
139
93
  - **On `observation:record` answering `file`, the observation is filed**, at depth 1 or deeper, with
140
- no depth-0 citation. It answers `file` only when exactly one earlier sighting exists — a higher
141
- count means the Issue was already opened by the sighting before. The line is appended either way,
142
- because the ledger stays append-only.
143
- - **The Issue quotes the ledger's own dates — the first sighting's and this one's**, both on the
144
- command's standard error — so the reader can check the promotion against the file instead of
145
- taking the run's word for it.
146
- - **Both ceilings still apply**, exactly as `observation-filing.md` states them: the 10-per-run cap counts a promoted
147
- filing, and the WIP cap still bites, since a promoted observation blocks nothing and is therefore
148
- still discretionary.
149
-
150
- **A third and later sighting appends a line and files nothing more.** The Issue from the second one
151
- is already open, and `pnpm josh issue:scout` is what finds it; the extra lines are evidence for that
152
- Issue, not new ones.
94
+ no depth-0 citation (only when exactly one earlier sighting exists).
95
+ - **The Issue quotes the ledger's own dates — the first sighting's and this one's.**
96
+ - **Both ceilings still apply** (`observation-filing.md`): the 10-per-run cap and the WIP cap.
97
+
98
+ **A third and later sighting appends a line and files nothing more** — `pnpm josh issue:scout` finds
99
+ the open Issue.
153
100
 
154
101
  ## A user-found bug is recorded by its kind of miss (user-found)
155
102
 
156
103
  **A user-reported bug is fixed or filed as always; this records the *kind of miss* alongside so the
157
- category never recurs as a first sighting.** The key is the **category of
158
- oversight** — `k:missed-case-worktree` — so a second bug of the same kind counts against the first.
159
- **Depth `d1`, never `d0`**: the *kind of miss* is what a run fails to enumerate, which the table puts
160
- at depth 1. Nothing else changes; the `<what>` field leads with `User-reported:`, and no second
161
- ledger, format or threshold is added.
104
+ category never recurs as a first sighting.** The key is the **category of oversight** —
105
+ `k:missed-case-worktree`. **Depth `d1`, never `d0`**. The `<what>` field leads with `User-reported:`;
106
+ nothing else changes.
@@ -1,215 +1,166 @@
1
1
  # The pre-gate cut — a lane child ends its turn before the gate
2
2
 
3
- A lane child is a detached `fullrun #<N>` process, and the thinking it accumulates while implementing
4
- rides on every later API call in the same session. The **pre-gate cut** drops that accumulation: the
5
- child ends its process the moment implementation is done, and a **fresh** process resumes the same lane
6
- from the gate onward. Rationale: `docs/maintainers/pre-gate-cut-rationale.md` → "Why the cut exists".
3
+ The **pre-gate cut**: a dispatched lane child ends its process the moment implementation is done, and a
4
+ **fresh** process resumes the same lane from the gate onward, without the implementation's accumulated
5
+ context. Rationale: `docs/maintainers/pre-gate-cut-rationale.md` → "Why the cut exists".
7
6
 
8
- This file is the single source of the boundary. `run:cut` takes it, and `run:cut --resume` is the
9
- check a fresh process makes at its own entry. **A second boundary is added below** — the
10
- implementation-phase cut, at a context threshold _during_ implementation.
11
- Everything through "What is carried" describes the pre-gate cut; the later section states only what
12
- differs.
7
+ This file is the single source of the boundary: `run:cut` takes it, `run:cut --resume` is the fresh
8
+ process's entry check. A second boundary — the implementation-phase cut, _during_ implementation — is
9
+ below; it states only what differs.
13
10
 
14
11
  ## Where the boundary is
15
12
 
16
- **After implementation and the refactor, before `pnpm josh gate`**: implementation complete, nothing
17
- committed, the gate not started. Everything after it (gate → review → commit → push → merge) is
18
- verification the fresh process runs on the tree.
19
-
20
- **A lane child first hands it to a detached supervisor** (`chain-rule.md` step 0); the cut is the fallback.
13
+ **After implementation and the refactor, before `pnpm josh gate`**: nothing committed, the gate not
14
+ started. **A lane child first hands it to a detached supervisor** (`chain-rule.md` step 0); the cut is
15
+ the fallback.
21
16
 
22
17
  ## It applies to a dispatched lane child, and to nothing else
23
18
 
24
- The cut is for a **detached** `fullrun` a lane dispatched; a person's interactive `fullrun` never
25
- relaunches itself. A dispatched child is told apart **mechanically, by a mark the dispatch sets** — never
26
- by the model reading the shape of its own prompt.
19
+ A person's interactive `fullrun` never relaunches itself. A dispatched child is told apart
20
+ **mechanically, by a mark the dispatch sets** — never by reading its own prompt.
27
21
 
28
22
  ### The dispatch mark
29
23
 
30
- `lane:dispatch` starts each child generation with the environment variable **`JOSH_LANE_CHILD`** set
31
- to the lane's issue number. `scripts/lane/lane-child-marker.ts` is its one definition.
24
+ `lane:dispatch` starts each child generation with **`JOSH_LANE_CHILD`** set to the lane's issue number
25
+ (`scripts/lane/lane-child-marker.ts`).
32
26
 
33
27
  - **Meaning**: "this session was launched for issue `<N>`, not typed by a person."
34
- - **Lifetime**: the child process — set at launch, read at the gate, never written by the run itself.
35
- - **Trust**: only where its value equals the lane's own issue. A mark that leaked in from a parent
36
- session — naming another issue, or none — is read as a person, so a leak cannot make the guard fire
37
- on a checkout it does not belong to.
38
-
39
- The name, meaning and lifetime are documented here and nowhere else.
28
+ - **Lifetime**: the child process — set at launch, never written by the run itself.
29
+ - **Trust**: only where its value equals the lane's own issue; a leaked mark naming another issue, or
30
+ none, is read as a person. An interactive `fullrun` carries no mark.
40
31
 
41
- `run:cut` decides the same fact its own way: it looks for an **open lane** for the issue, answering a
42
- checkout with none `not-a-lane`. So the command is safe to issue unconditionally — a no-op in the main
43
- checkout, a cut in a lane.
32
+ The name, meaning and lifetime are documented here and nowhere else. `run:cut` itself looks for an
33
+ **open lane** for the issue instead (`not-a-lane` otherwise), so it is safe to issue unconditionally.
44
34
 
45
35
  ## Taking the cut
46
36
 
47
- **The order is fixed in the chain**: `chain-rule.md` step 1 issues
48
- `pnpm josh run:cut <N>` after `pnpm josh main:merge`, before the scoped pair and the gate. **The command
49
- is issued unconditionally**; `run:cut` itself decides whether the cut is warranted, so a short lane with nothing to drop is answered `under-threshold` and walks on
50
- to the gate rather than relaunching.
51
-
52
- At the pre-gate boundary, issue:
37
+ `chain-rule.md` step 1 issues it after `pnpm josh main:merge`, before the scoped pair and the gate —
38
+ **unconditionally**:
53
39
 
54
40
  ```bash
55
41
  pnpm josh run:cut <N>
56
42
  ```
57
43
 
58
44
  - `cut` (0) — record written and handed to the lane's launch owner (OpenAI supervisor starts the
59
- successor after this process exits; Anthropic relaunches directly). **End the turn immediately** —
60
- the fresh process owns the run.
61
- - `under-threshold` (0) — the newest request's billed input is under the shared `CONTEXT_CUT_THRESHOLD`,
62
- so nothing was cut; **continue to the gate.**
63
- - `not-a-lane` (0) — no open lane for this issue, so not a dispatched child. **Continue to the gate.**
64
- - `unready` (1) — the tree is clean or on the default branch, nothing to carry. Continue to the gate.
65
- - `busy` (1) — a cut is already in flight for this tree (the double-cut guard). Do not relaunch.
45
+ successor after this process exits; Anthropic relaunches directly). **End the turn immediately.**
46
+ - `under-threshold` (0) — the newest request's billed input is under `CONTEXT_CUT_THRESHOLD`; **continue to the gate.**
47
+ - `not-a-lane` (0) — not a dispatched child. **Continue to the gate.**
48
+ - `unready` (1) — the tree is clean or on the default branch. Continue to the gate.
49
+ - `busy` (1) — a cut is already in flight for this tree. Do not relaunch.
66
50
  - `failed` (1) — no live OpenAI supervisor, or the Anthropic relaunch could not start. Continue.
67
51
  - `unknown` (1) — the git directory could not be read. Continue to the gate.
68
52
 
69
- **`cut` is the only verdict that ends the turn.** Every other one — `under-threshold` included — leaves
70
- the current process to carry the run on itself.
53
+ **`cut` is the only verdict that ends the turn.**
71
54
 
72
55
  ### The gate refuses until the cut has been taken
73
56
 
74
- `pnpm josh rule:guard` **refuses `pnpm josh gate`** while this checkout is a lane and no cut record is
75
- carried, handing back the command above. Rationale:
76
- `docs/maintainers/pre-gate-cut-rationale.md` → "Why the rules are guards, not prose".
57
+ `pnpm josh rule:guard` **refuses `pnpm josh gate`** in a lane with no cut record carried, handing back
58
+ the command above. Rationale: `docs/maintainers/pre-gate-cut-rationale.md` → "Why the rules are
59
+ guards, not prose".
77
60
 
78
- - **It fires for a marked child and nowhere else**: the working directory is a lane —
79
- `<lane root>/<issue number>` — **and** `JOSH_LANE_CHILD` names that same issue. An interactive
80
- `fullrun` carries no mark and runs its gate untouched. `run:cut` uses an open-lane lookup instead, so
61
+ - **It fires for a marked child and nowhere else**: the working directory is `<lane root>/<issue
62
+ number>` **and** `JOSH_LANE_CHILD` names that issue. `run:cut` uses an open-lane lookup instead, so
81
63
  the guard and the command need not agree byte for byte.
82
- - **It fires only when the current context warrants a cut**. The guard
83
- reads the same `cost_cli.session_verdict` `run:cut` reads, so an `under`-threshold lane is let through
84
- to the gate rather than refused.
85
- - **It is silent once the cut is carried**, so the resumed process goes straight to the gate.
64
+ - **It fires only when the current context warrants a cut** (`cost_cli.session_verdict`, as `run:cut`).
65
+ - **It is silent once the cut is carried**.
86
66
  - **It fires once per run.**
87
67
  - **`--resume`, `--end` and `--json` do not count as taking the cut.**
88
68
 
89
- The row, its trigger and the enumeration it joins are
90
- `prompts/collaboration-workflow/rule-delivery.md`. The suites that pin this and the three guards below:
91
- `docs/maintainers/pre-gate-cut-rationale.md` → "Which suites pin each guard".
69
+ Its row: `prompts/collaboration-workflow/rule-delivery.md`. Suites: `docs/maintainers/pre-gate-cut-rationale.md`
70
+ → "Which suites pin each guard".
92
71
 
93
72
  ## Resuming — the fresh process's entry check
94
73
 
95
- A fresh `fullrun #<N>` runs this **at its entry, before `run:hold` and the session-boundary check**,
96
- because whether it is fresh or resumed decides everything that follows:
74
+ A fresh `fullrun #<N>` runs this **at its entry, before `run:hold` and the session-boundary check**:
97
75
 
98
76
  ```bash
99
77
  pnpm josh run:cut --resume <N>
100
78
  ```
101
79
 
102
- - `fresh` (0) — no cut record, an ordinary run. Proceed with the normal entry: claim the hold, ask the
103
- session boundary, read the issue, implement.
104
- - `resume` (0) — a declared pre-gate cut whose tree matches was verified and taken over. **Skip the
105
- title, the plan, the fresh hold claim and the implementation**; re-read the issue body and comments
106
- for the plan and the recorded decisions, then go straight to `pnpm josh gate`.
107
- - `resume-impl` (0) — like `resume`, but the cut was taken **during** implementation. Skip the title, the plan, the fresh hold claim and the split assessment,
108
- re-read the plan, then **continue implementation** — do **not** go straight to the gate.
109
- - `handed-off` (0) — a successor has already adopted this cut, `is_handed_off` is spent.
110
- This process was woken **after** its own cut. **End the turn quietly and do
111
- nothing**: a benign stop, no Telegram owed.
112
- - `stale` (1) — the record does not match the tree (wrong branch, a clean tree, an expired record, or
113
- an unknown hand-off state). **A resume failure**: send a `confirmation` Telegram and stop; never gate
114
- the wrong tree.
115
- - `busy` (1) — another process already owns the resume. Send a `confirmation` Telegram and stop.
116
-
117
- **A resume is never reported as a success it did not earn**: `stale` and `busy` stop the run rather
118
- than gating.
80
+ - `fresh` (0) — an ordinary run; normal entry.
81
+ - `resume` (0) — a verified pre-gate cut. **Skip the title, the plan, the fresh hold claim and the
82
+ implementation**; re-read the issue body and comments, then go straight to `pnpm josh gate`.
83
+ - `resume-impl` (0) — the cut was taken **during** implementation. Skip the title, the plan, the
84
+ fresh hold claim and the split assessment, re-read the plan, then **continue implementation** — do
85
+ **not** go straight to the gate.
86
+ - `handed-off` (0) — a successor already adopted this cut. **End the turn quietly and do nothing**;
87
+ no Telegram owed.
88
+ - `stale` (1) — the record does not match the tree (branch, clean tree, expired, or unknown hand-off).
89
+ **A resume failure**: send a `confirmation` Telegram and stop; never gate the wrong tree.
90
+ - `busy` (1) — another process owns the resume. Send a `confirmation` Telegram and stop.
119
91
 
120
92
  ### The stage is passed to the resumed child, not reconstructed by it
121
93
 
122
- A resumed child arrives with `JOSH_LANE_CHILD` still set and `run:cut --resume` reads the record the cut
123
- left, so it learns _where to resume from_ at its entry. **Skip the entry it has already done**: do not
124
- re-read the workflow skill, repeat the split assessment or re-normalize the title; the plan and
125
- decisions are read back from the issue. Rationale:
94
+ **Skip the entry it has already done**: do not re-read the workflow skill, repeat the split assessment
95
+ or re-normalize the title; the plan and decisions are read back from the issue. Rationale:
126
96
  `docs/maintainers/pre-gate-cut-rationale.md` → "Why the resume carries what it carries".
127
97
 
128
98
  ## What is carried, and what is not
129
99
 
130
- - **The working tree is not in the record, because it never left the disk.** The record carries only
131
- what a fresh process cannot recover — the issue, the branch, the invocation, and that a **declared
132
- cut** put it here. **The conversation is not carried**; the fresh process reads the plan and
133
- auto-decisions back off GitHub.
134
- - **The hold is kept, not released** — the resumed process adopts the `run:hold` record and
135
- `pnpm josh followup` releases it at the merge.
136
- - **The dispatch mark is re-applied, not inherited**: the relaunch strips the parent's environment and
137
- sets `JOSH_LANE_CHILD` afresh from the lane's issue.
100
+ - **The working tree is not in the record, because it never left the disk.** The record carries the
101
+ issue, branch, invocation, and that a **declared cut** put it there. **The conversation is not
102
+ carried**; plan and auto-decisions are read back off GitHub.
103
+ - **The hold is kept, not released** — `pnpm josh followup` releases it at the merge.
104
+ - **The dispatch mark is re-applied, not inherited.**
138
105
 
139
106
  ## Verification, uniqueness and double-launch
140
107
 
141
- - **The resume verifies the tree against the record**: the branch matches, the tree is dirty, the
142
- issue matches, and the tree is still under the cutting run's hold. Any mismatch is `stale`.
143
- - **No owner is recorded on the cut** — the cut is the stage hand-off alone (OpenAI keeps its
144
- supervisor owner separately).
145
- - **The cut is exclusive** — `run:cut` writes the record with an exclusive create, so a second cut on
146
- the same tree is refused `busy`.
147
- - **The resume is unique.** Taking the hand-off over spends it — a second `run:cut --resume` reads a
148
- spent record and is answered `handed-off`, and the take-over is itself an
149
- exclusive create, so two resumes racing cannot both win. One lane crosses the pre-gate boundary
150
- exactly once.
108
+ - **The resume verifies the tree against the record**: branch, dirty tree, issue, and the cutting
109
+ run's hold. Any mismatch is `stale`.
110
+ - **No owner is recorded on the cut** (OpenAI keeps its supervisor owner separately).
111
+ - **The cut is exclusive** — a second cut on the same tree is `busy`.
112
+ - **The resume is unique** — a spent record answers `handed-off`, and the take-over is an exclusive
113
+ create. One lane crosses the pre-gate boundary exactly once.
151
114
 
152
115
  ## The implementation-phase cut — a lane child cuts before the gate too
153
116
 
154
- The **implementation-phase cut** caps the context accumulated _during_
155
- implementation — the child ends mid-implementation and a fresh one resumes the lane **back into
156
- implementation**.
117
+ The child ends mid-implementation and a fresh one resumes **back into implementation**.
157
118
 
158
119
  ### The measurement is the parent hand-off's, never a second one
159
120
 
160
- The guard below refuses on the same measurement the parent uses between children —
161
- `cost_verdict.per_request_cost`, read through `cost_cli.session_verdict` (the read-only form of
162
- `pnpm josh cost --cut`), single-sourced at `backlogrun-progress.md` → "The
163
- hand-off". The parent's seam and the child's `run_cut.IMPLEMENTATION_CONTEXT_THRESHOLD` share the
164
- **135_000** `CONTEXT_CUT_THRESHOLD` (aliased so the tests cannot drift). No separate measurement is
165
- built for the lane child.
121
+ Same `cost_verdict.per_request_cost` through `cost_cli.session_verdict` as `backlogrun-progress.md` →
122
+ "The hand-off"; `run_cut.IMPLEMENTATION_CONTEXT_THRESHOLD` aliases the **135_000**
123
+ `CONTEXT_CUT_THRESHOLD`.
166
124
 
167
125
  ### It is a guard, fired at the edit that crosses the threshold
168
126
 
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. **A cut
173
- that relaunches its successor owes no Telegram**, the pre-gate cut as much as this one: nobody has
174
- anything to act on, and a resume answering `stale` / `busy` sends its own. Outside a lane nothing is
175
- relaunched, so `run:cut --impl` prints the held run's instruction — on a measured `over` that run
176
- keeps the hold, sends a `confirmation` Telegram naming `fullrun #<N>` and ends the turn. The refusal states the rest — **It fires on every threshold crossing,
127
+ **The trigger**: `pnpm josh rule:guard` refuses an `Edit` / `Write` in a dispatched lane child over
128
+ threshold, handing back `pnpm josh run:cut --impl <N> --handoff <path>`. `cut` ends the turn; the
129
+ fresh process's `run:cut --resume <N>` answers `resume-impl` — **the implementation resume clears the
130
+ record**, so the cut may fire again. **A cut that relaunches its successor owes no Telegram**. Outside a
131
+ lane, `run:cut --impl` prints the held run's instruction: on `over`, keep the hold, send a
132
+ `confirmation` Telegram naming `fullrun #<N>`, end the turn. **It fires on every threshold crossing,
177
133
  not once per run**; **An edit reissued right after a refusal passes**; **An unmeasurable session
178
134
  warrants the cut**; **It is silent between a cut and its resume**. Rationale:
179
- `docs/maintainers/pre-gate-cut-rationale.md` → "Why the rules are guards, not prose";
180
- `scripts/rules/implementation-cut.ts` implements it. A child that ended without cutting is detected
181
- after the fact by `pnpm josh run:ending <N> --output <path>`.
135
+ `docs/maintainers/pre-gate-cut-rationale.md` → "Why the rules are guards, not prose"
136
+ (`scripts/rules/implementation-cut.ts`). A child that ended without cutting is detected by
137
+ `pnpm josh run:ending <N> --output <path>`.
182
138
 
183
139
  ## The threshold
184
140
 
185
- `CONTEXT_CUT_THRESHOLD` and `cost_verdict.per_request_cost` (the newest request's billed input)
186
- are computed by `scripts/cost-runtime/context-cut-payback.ts`, their
187
- single source; both cuts and the parent hand-off read the same verdict, and an unmeasurable session is
188
- always cut. Rationale: `docs/maintainers/pre-gate-cut-rationale.md` → "Why the threshold is a
189
- break-even". Both cuts end the turn **before** the gate, in the same act that starts the successor, so
190
- the push is never a turn boundary (`chain-rule.md`).
141
+ `CONTEXT_CUT_THRESHOLD` and `cost_verdict.per_request_cost` live in
142
+ `scripts/cost-runtime/context-cut-payback.ts`; both cuts and the parent hand-off read the same verdict,
143
+ and an unmeasurable session is always cut. Rationale: `docs/maintainers/pre-gate-cut-rationale.md` →
144
+ "Why the threshold is a break-even". Both cuts end the turn **before** the gate, so the push is never a
145
+ turn boundary (`chain-rule.md`).
191
146
 
192
147
  ## A lane child records its park before it stops
193
148
 
194
- **The trigger**: a dispatched lane child about to stop for a decision (a Tier B toss-up, a Tier C
195
- action, an upstream defect) parks its own Issue first — `backlogrun-park.md` → "park and
196
- continue" — so the parent's `pnpm josh run:liveness` reads it `settled`. A `needs-human-review` or `already-done` stop already carries its label.
197
- `pnpm josh rule:guard` refuses `pnpm josh notify --task-type confirmation` from a marked child until
198
- then — **It fires once per run.**, and a person's own `fullrun` is never refused
199
- (`scripts/rules/lane-park.ts`).
149
+ **The trigger**: a dispatched lane child about to stop for a decision (Tier B, Tier C, an upstream
150
+ defect) parks its own Issue first — `backlogrun-park.md` → "park and continue" — so `pnpm josh
151
+ run:liveness` reads it `settled`. A `needs-human-review` or `already-done` stop already carries its
152
+ label. `pnpm josh rule:guard` refuses `pnpm josh notify --task-type confirmation` from a marked child
153
+ until then — **It fires once per run.** (`scripts/rules/lane-park.ts`).
200
154
 
201
- **A split is not a park**: the parent reads an open Issue carrying `epic` as
202
- a split, so a child that promoted its Issue stops without `needs-decision` — `backlogrun-park.md` →
203
- "Splitting a child mid-run". `pnpm josh rule:guard` refuses a `needs-decision` write onto the epic
204
- the child promoted this run, on every occurrence (`scripts/rules/lane-split-park.ts`).
155
+ **A split is not a park**: a child that promoted its Issue to an `epic` stops without
156
+ `needs-decision` — `backlogrun-park.md` → "Splitting a child mid-run". `pnpm josh rule:guard` refuses a
157
+ `needs-decision` write onto that epic, on every occurrence (`scripts/rules/lane-split-park.ts`).
205
158
 
206
159
  ### The interactive ask is refused one call earlier
207
160
 
208
161
  **The trigger**: a headless session ends the turn on an interactive ask, so the notify guard never
209
- fires. `pnpm josh rule:guard` therefore refuses `AskUserQuestion` for a marked lane child on
210
- every occurrence — park the question instead.
211
- A child that slips past is recovered by `pnpm josh run:ending`, which lifts
212
- the refused ask into the park basis; `scripts/rules/lane-interactive-ask.ts` and the shared
213
- `scripts/agent/interactive-ask.ts` implement it.
162
+ fires; `pnpm josh rule:guard` refuses `AskUserQuestion` for a marked lane child on every occurrence — park the question instead.
163
+ `pnpm josh run:ending` lifts a slipped ask into the park basis (`scripts/rules/lane-interactive-ask.ts`,
164
+ `scripts/agent/interactive-ask.ts`).
214
165
 
215
166
  Provenance of each rule: `docs/maintainers/pre-gate-cut-rationale.md` → "Where each rule came from".
@@ -34,10 +34,8 @@ open), then stash, comment and `pnpm josh run:release <M>` as for a prerequisite
34
34
  `halfrun` stop, `backlogrun` continues. Closing the release Issue once a person has published it hands
35
35
  `<M>` back to `backlog:next` (`docs/josh-commands-backlog.md` → `josh issue:release`).
36
36
 
37
- **File the prerequisite with the `route:tier-a` label**, so a Tier A filing made during implementation
38
- stays countable by filing route afterwards. **This paragraph belongs to the prerequisite row, not to
39
- the table** — the label means a filing the run is *blocked by*, so the observation row carries no
40
- `route:` label of its own (`observation-filing.md`):
37
+ **File the prerequisite with the `route:tier-a` label** — it means a filing the run is *blocked by*,
38
+ so the observation row carries no `route:` label (`observation-filing.md`):
41
39
 
42
40
  ```bash
43
41
  pnpm josh issue:file "<title>" --body-file <body-file> --depth <n> --route tier-a
@@ -47,9 +45,9 @@ The command lints the body against `prompts/collaboration-workflow/issue-templat
47
45
  classification labels it declares, and runs the duplicate scan and `epic:bundle` itself
48
46
  (`docs/josh-commands-backlog.md` → `josh issue:file`).
49
47
 
50
- Every *file the prerequisite* step below means that labelled filing, and it always happens **first**: the
51
- steps after it name a number that does not exist until it is. **Its duplicate scan is read exactly as
52
- it is for a `new` entry** (`issue-scout.md`): a filing made mid-run is the one most likely to duplicate something.
48
+ Every *file the prerequisite* step below means that filing, and it always happens **first** — the
49
+ later steps name its number. **Its duplicate scan is read exactly as it is for a `new` entry**
50
+ (`issue-scout.md`).
53
51
 
54
52
  **Each entry point's own branch stays in that entry's file:**
55
53
 
@@ -63,16 +61,13 @@ it is for a `new` entry** (`issue-scout.md`): a filing made mid-run is the one m
63
61
  command to type (`fullrun.md` / `halfrun.md`). Typing `fullrun` approved implementing **one** Issue;
64
62
  a batch is a different authorization, so the stop stays.
65
63
 
66
- **Two steps every entry's procedure turns on**, both load-bearing rather than tidy-up:
64
+ **Two steps every entry's procedure turns on:**
67
65
 
68
66
  - **`git stash push -u` — the `-u` is not optional.** The work in progress almost always includes a
69
- new `*.test.ts`, which is untracked, and a stash without `-u` leaves exactly those files in the tree
70
- for the next child's `pnpm josh ms` to refuse.
71
- - **The Issue comment is what gets the stash popped, not the Telegram.** The run that later picks the
72
- paused Issue up reads that comment and pops before implementing — **by message,
73
- `pnpm josh stash:pop "<the -m message>"`, never a positional `git stash pop`**, because the stash is
74
- a repository-wide stack every lane shares and a positional pop takes whichever lane last pushed. Say
75
- it in the Telegram too — the comment is the record.
67
+ new, untracked `*.test.ts`, which a stash without `-u` leaves for the next `pnpm josh ms` to refuse.
68
+ - **The Issue comment is what gets the stash popped, not the Telegram.** The run that picks the Issue up
69
+ reads it and pops before implementing — **by message, `pnpm josh stash:pop "<the -m message>"`, never
70
+ a positional `git stash pop`** (the stack is shared by every lane). Say it in the Telegram too.
76
71
 
77
72
  **Automatic filing is capped at 10 Issues per run** at every entry point; `pnpm josh rule:guard`
78
73
  refuses the eleventh filing (`prompts/collaboration-workflow/rule-delivery.md`). On reaching it, stop