@joshuafolkken/kit 1.1387.0 → 1.1435.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 (236) hide show
  1. package/.claude/skills/epic-commands/SKILL.md +1 -1
  2. package/.claude/skills/epic-commands/epic-bundle.md +5 -0
  3. package/.claude/skills/workflow-commands/backlogrun-lanes.md +5 -3
  4. package/.claude/skills/workflow-commands/backlogrun-steps.md +4 -3
  5. package/.claude/skills/workflow-commands/backlogrun.md +1 -0
  6. package/.claude/skills/workflow-commands/chain-rule.md +4 -2
  7. package/.claude/skills/workflow-commands/issue-comments.md +6 -0
  8. package/.claude/skills/workflow-commands/observation-ledger.md +3 -2
  9. package/.claude/skills/workflow-commands/pre-gate-cut.md +5 -3
  10. package/README.md +25 -0
  11. package/dist/hooks/audit-provision.js +2 -2
  12. package/dist/hooks/batch-guard.js +7 -7
  13. package/dist/hooks/{chunk-IYVOLN6A.js → chunk-2G5F2YCD.js} +3 -3
  14. package/dist/hooks/{chunk-2YSW3CXH.js → chunk-3LE6VLSR.js} +17 -6
  15. package/dist/hooks/{chunk-J3KSS7II.js → chunk-4BHUPFKF.js} +1 -1
  16. package/dist/hooks/{chunk-EAQEGME7.js → chunk-5SJSSCJG.js} +1 -1
  17. package/dist/hooks/{chunk-FZ6FUSBM.js → chunk-723HKZO5.js} +1 -1
  18. package/dist/hooks/{chunk-LMWBRJIP.js → chunk-7KMN5QB5.js} +3 -3
  19. package/dist/hooks/{chunk-NEC4AT4Z.js → chunk-DGT54IH5.js} +4 -0
  20. package/dist/hooks/{chunk-STDSEPWU.js → chunk-EMB55BDF.js} +4 -4
  21. package/dist/hooks/{chunk-JBBMAPC4.js → chunk-IX6TTTI6.js} +4 -0
  22. package/dist/hooks/{chunk-GJ7JPIHN.js → chunk-JXQBK323.js} +2674 -187
  23. package/dist/hooks/{chunk-DCY2GWHC.js → chunk-MSYSUSY6.js} +5 -5
  24. package/dist/hooks/{chunk-EBSHN25W.js → chunk-MU4LJFIV.js} +4 -4
  25. package/dist/hooks/{chunk-WNFJLBXI.js → chunk-QL6QTPWN.js} +3 -3
  26. package/dist/hooks/{chunk-SL4GQ2XP.js → chunk-XER6SSIB.js} +91 -18
  27. package/dist/hooks/{chunk-U32VSRNG.js → chunk-YW452ZAX.js} +89 -34
  28. package/dist/hooks/{chunk-GNDJ7NJ7.js → chunk-YZXYOAZ3.js} +202 -55
  29. package/dist/hooks/codex-hook-adapter.js +15 -15
  30. package/dist/hooks/duplicate-read-guard.js +8 -8
  31. package/dist/hooks/format-edited.js +5 -5
  32. package/dist/hooks/inputs.json +288 -229
  33. package/dist/hooks/investigation-guard.js +8 -8
  34. package/dist/hooks/pretool-guard.js +14 -14
  35. package/dist/hooks/session-lang.js +69 -16
  36. package/dist/hooks/stop-guard.js +13 -38
  37. package/dist/josh.js +62 -9
  38. package/package.json +4 -3
  39. package/prompts/review.md +22 -0
  40. package/scripts/agent/claude-agent-argv.ts +13 -1
  41. package/scripts/auth/auth-setup-cli.ts +101 -0
  42. package/scripts/auth/claude-token-output.ts +78 -0
  43. package/scripts/auth/claude-token.ts +68 -0
  44. package/scripts/backlog/backlog-drive-epic.ts +24 -8
  45. package/scripts/backlog/backlog-drive-launch.ts +3 -0
  46. package/scripts/backlog/backlog-drive-named-offer.ts +7 -2
  47. package/scripts/backlog/backlog-drive-named.ts +4 -2
  48. package/scripts/backlog/backlog-drive-unread.ts +56 -0
  49. package/scripts/backlog/backlog-drive.ts +16 -8
  50. package/scripts/backlog/backlog-overlap.ts +22 -5
  51. package/scripts/backlog/backlog-ready.ts +1 -3
  52. package/scripts/backlog/backlogrun-args.ts +13 -2
  53. package/scripts/backlog/backlogrun-cli.ts +91 -19
  54. package/scripts/backlog/backlogrun-launch.ts +24 -0
  55. package/scripts/backlog/backlogrun-replace.ts +166 -0
  56. package/scripts/backlog/backlogrun-stop.ts +178 -0
  57. package/scripts/behavior/behavior-cli.ts +6 -1
  58. package/scripts/doctor/doctor-io.ts +60 -9
  59. package/scripts/doctor/doctor.ts +20 -1
  60. package/scripts/document/document-byte-budget.ts +3 -3
  61. package/scripts/epic/epic-bundle-cli.ts +8 -8
  62. package/scripts/epic/epic-bundle-referenced.ts +2 -5
  63. package/scripts/epic/epic-bundle.ts +39 -4
  64. package/scripts/exports/unused-members-cli.ts +2 -1
  65. package/scripts/followup/followup-checks-event.ts +82 -0
  66. package/scripts/followup/git-followup-finish.ts +16 -2
  67. package/scripts/followup/git-followup-workflow.ts +5 -2
  68. package/scripts/followup/git-pr-followup-checks.ts +18 -4
  69. package/scripts/followup/git-pr-followup-wrapup.ts +5 -0
  70. package/scripts/followup/git-pr-followup.ts +4 -1
  71. package/scripts/fresh-machine/fresh-machine-cli.ts +204 -0
  72. package/scripts/fresh-machine/fresh-machine-docker.ts +65 -0
  73. package/scripts/fresh-machine/fresh-machine-image.ts +62 -0
  74. package/scripts/fresh-machine/fresh-machine-log.ts +61 -0
  75. package/scripts/fresh-machine/fresh-machine-patterns.ts +130 -0
  76. package/scripts/fresh-machine/fresh-machine-run.ts +215 -0
  77. package/scripts/fresh-machine/fresh-machine-script.ts +45 -0
  78. package/scripts/fresh-machine/fresh-machine-spec.ts +57 -0
  79. package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +34 -0
  80. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +31 -0
  81. package/scripts/gate/gate-report.ts +70 -15
  82. package/scripts/gate/project-checks.ts +13 -2
  83. package/scripts/gate/scoped-green.ts +2 -1
  84. package/scripts/gate/verification-gate.ts +4 -3
  85. package/scripts/gh/gh-author-association.ts +14 -0
  86. package/scripts/gh/git-gh-conditional.ts +66 -0
  87. package/scripts/gh/git-gh-exec.ts +1 -1
  88. package/scripts/gh/git-gh-issue-read.ts +6 -3
  89. package/scripts/gh/git-gh-issue-write.ts +5 -1
  90. package/scripts/gh/git-gh-issue.ts +4 -1
  91. package/scripts/gh/git-pr-checks-eval.ts +13 -0
  92. package/scripts/gh/git-pr-checks-parse.ts +8 -1
  93. package/scripts/gh/git-pr-checks-watch.ts +11 -4
  94. package/scripts/gh/git-pr-checks.ts +36 -2
  95. package/scripts/git/git-command.ts +16 -4
  96. package/scripts/git/git-schemas.ts +1 -0
  97. package/scripts/git/git-spawn-sync.ts +1 -1
  98. package/scripts/hooks/pretool-guard.ts +3 -1
  99. package/scripts/init/hook-command-rewrite.ts +31 -0
  100. package/scripts/init/init-actions.ts +4 -1
  101. package/scripts/init/init-ai-copy.ts +33 -10
  102. package/scripts/init/init-basic.ts +8 -3
  103. package/scripts/init/init-logic-toolchain.ts +76 -0
  104. package/scripts/init/init-logic.ts +2 -0
  105. package/scripts/init/init.ts +5 -23
  106. package/scripts/init/project-profile.ts +36 -7
  107. package/scripts/init/start-exec.ts +27 -1
  108. package/scripts/init/start-plan.ts +15 -0
  109. package/scripts/init/start-steps.ts +46 -0
  110. package/scripts/init/start.ts +1 -0
  111. package/scripts/init/workflow-mark.ts +35 -0
  112. package/scripts/issue/issue-ack-cli.ts +84 -0
  113. package/scripts/issue/issue-labels.ts +40 -8
  114. package/scripts/issue/issue-state-cli.ts +14 -4
  115. package/scripts/issue/issue-watch-diff.ts +152 -0
  116. package/scripts/issue/issue-watch-gate.ts +81 -0
  117. package/scripts/issue/issue-watch-hook.ts +54 -0
  118. package/scripts/issue/issue-watch.ts +240 -0
  119. package/scripts/issue/measure-rerun-cli.ts +3 -4
  120. package/scripts/josh/josh-command-map.ts +4 -0
  121. package/scripts/josh/josh-commands-backlog.ts +2 -2
  122. package/scripts/josh/josh-commands-development.ts +1 -1
  123. package/scripts/josh/josh-commands-issue.ts +7 -0
  124. package/scripts/josh/josh-commands-lane.ts +11 -2
  125. package/scripts/josh/josh-commands-project.ts +24 -0
  126. package/scripts/josh/josh-verdict.ts +33 -4
  127. package/scripts/lane/claude-lane-broker.ts +142 -0
  128. package/scripts/lane/lane-await.ts +6 -2
  129. package/scripts/lane/lane-cache.ts +37 -7
  130. package/scripts/lane/lane-capacity.ts +8 -6
  131. package/scripts/lane/lane-child-invocation.ts +1 -0
  132. package/scripts/lane/lane-cli.ts +15 -1
  133. package/scripts/lane/lane-close.ts +15 -6
  134. package/scripts/lane/lane-dispatch.ts +36 -10
  135. package/scripts/lane/lane-environment.ts +1 -1
  136. package/scripts/lane/lane-launch-cli.ts +13 -4
  137. package/scripts/lane/lane-ledger.ts +21 -3
  138. package/scripts/lane/lane-measure-cli.ts +10 -2
  139. package/scripts/lane/lane-open.ts +9 -1
  140. package/scripts/lane/lane-preserve.ts +49 -0
  141. package/scripts/lane/lane-reap.ts +20 -5
  142. package/scripts/lane/lane-registry.ts +6 -0
  143. package/scripts/lane/lane-restart-cli.ts +51 -0
  144. package/scripts/lane/lane-restart.ts +175 -0
  145. package/scripts/lane/{openai-review-broker.ts → lane-session-broker.ts} +106 -28
  146. package/scripts/lane/lane-spent.ts +195 -0
  147. package/scripts/lane/lane-stage-stats.ts +27 -3
  148. package/scripts/lane/lane-stop-stats.ts +96 -0
  149. package/scripts/lane/openai-lane-supervisor.ts +2 -2
  150. package/scripts/lane/process-tools.ts +31 -0
  151. package/scripts/lib/buffered-process.ts +36 -2
  152. package/scripts/lib/pnpm-reach.ts +27 -0
  153. package/scripts/lib/status-icons.ts +5 -1
  154. package/scripts/lint/lint-parallel.ts +19 -2
  155. package/scripts/observations/observation-ledger-home.ts +1 -0
  156. package/scripts/review/review-attest-cli.ts +21 -6
  157. package/scripts/review/review-brief-cli.ts +2 -2
  158. package/scripts/review/review-comment-round.ts +114 -0
  159. package/scripts/review/review-record-cli.ts +39 -17
  160. package/scripts/rules/implementation-cut.ts +3 -3
  161. package/scripts/rules/pre-gate-cut.ts +1 -1
  162. package/scripts/run/board/run-board-checks.ts +42 -0
  163. package/scripts/run/board/run-board-cli.ts +2 -0
  164. package/scripts/run/board/run-board-every.ts +3 -1
  165. package/scripts/run/board/run-board-fit.ts +16 -5
  166. package/scripts/run/board/run-board-fresh.ts +64 -0
  167. package/scripts/run/board/run-board-header.ts +129 -53
  168. package/scripts/run/board/run-board-labels.ts +47 -4
  169. package/scripts/run/board/run-board-lane-event.ts +66 -0
  170. package/scripts/run/board/run-board-layout.ts +57 -9
  171. package/scripts/run/board/run-board-now.ts +234 -0
  172. package/scripts/run/board/run-board-operation-read.ts +75 -0
  173. package/scripts/run/board/run-board-operation.ts +150 -0
  174. package/scripts/run/board/run-board-phase.ts +26 -1
  175. package/scripts/run/board/run-board-plan.ts +4 -6
  176. package/scripts/run/board/run-board-read.ts +49 -3
  177. package/scripts/run/board/run-board-reason.ts +124 -0
  178. package/scripts/run/board/run-board-render-checks.ts +55 -0
  179. package/scripts/run/board/run-board-render-legend.ts +12 -3
  180. package/scripts/run/board/run-board-render-slot.ts +2 -2
  181. package/scripts/run/board/run-board-render-tail.ts +128 -0
  182. package/scripts/run/board/run-board-render-thanks.ts +50 -0
  183. package/scripts/run/board/run-board-render-title.ts +58 -0
  184. package/scripts/run/board/run-board-render.ts +96 -80
  185. package/scripts/run/board/run-board-row-yield.ts +32 -0
  186. package/scripts/run/board/run-board-setup.ts +61 -13
  187. package/scripts/run/board/run-board-state.ts +10 -0
  188. package/scripts/run/board/run-board-status.ts +66 -7
  189. package/scripts/run/board/run-board-thanks-csv.ts +71 -0
  190. package/scripts/run/board/run-board-thanks-read.ts +112 -0
  191. package/scripts/run/board/run-board-thanks.ts +53 -0
  192. package/scripts/run/board/run-board-tick.ts +50 -21
  193. package/scripts/run/board/run-board-usual.ts +44 -0
  194. package/scripts/run/carry/run-carry-args.ts +9 -1
  195. package/scripts/run/carry/run-carry-cli.ts +2 -45
  196. package/scripts/run/carry/run-carry-end.ts +73 -0
  197. package/scripts/run/carry/run-carry.ts +8 -1
  198. package/scripts/run/entry/run-entry-cli.ts +5 -0
  199. package/scripts/run/event/run-event-checks.ts +54 -0
  200. package/scripts/run/event/run-event-render.ts +2 -0
  201. package/scripts/run/event/run-event-scope.ts +1 -0
  202. package/scripts/run/event/run-event-setup.ts +55 -11
  203. package/scripts/run/event/run-event-stream.ts +27 -11
  204. package/scripts/run/merge/run-merge-cli.ts +7 -4
  205. package/scripts/run/merge/run-merge-ship.ts +61 -0
  206. package/scripts/run/merge/run-merge-steps.ts +7 -14
  207. package/scripts/run/merge/run-merge-token.ts +16 -2
  208. package/scripts/run/run-headless.ts +1 -0
  209. package/scripts/run/run-step.ts +2 -0
  210. package/scripts/run/ship/run-ship-cli.ts +22 -2
  211. package/scripts/run/ship/run-ship-return.ts +31 -13
  212. package/scripts/run/ship/run-ship-review-steps.ts +17 -4
  213. package/scripts/run/ship/run-ship-stage.ts +1 -0
  214. package/scripts/run/wake/run-wake-await.ts +130 -0
  215. package/scripts/run/wake/run-wake-cli.ts +60 -71
  216. package/scripts/run/wake/run-wake-describe.ts +34 -2
  217. package/scripts/run/wake/run-wake-driver.ts +11 -4
  218. package/scripts/run/wake/run-wake-session.ts +20 -3
  219. package/scripts/run/wake/run-wake-stop.ts +37 -0
  220. package/scripts/run/wake/run-wake-supervise.ts +44 -0
  221. package/scripts/sync/claude-settings-merge.ts +144 -0
  222. package/scripts/sync/sync-ai-files.ts +28 -3
  223. package/scripts/sync/sync.ts +15 -0
  224. package/scripts/test/project-test-script.ts +73 -0
  225. package/scripts/test/skip-marker.ts +14 -1
  226. package/scripts/test/test-related.ts +3 -2
  227. package/scripts/test/test-unit-guard.ts +78 -14
  228. package/scripts/time-runtime/time-reported-failure.ts +11 -3
  229. package/scripts/uninstall/distributed-files.ts +92 -0
  230. package/scripts/uninstall/uninstall-plan.ts +119 -0
  231. package/scripts/uninstall/uninstall-report.ts +61 -0
  232. package/scripts/uninstall/uninstall.ts +206 -0
  233. package/templates/AGENTS.basic.md +4 -0
  234. package/templates/GEMINI.basic.md +6 -0
  235. package/dist/hooks/chunk-6V5OPIUU.js +0 -13
  236. package/scripts/run/board/run-board-track.ts +0 -22
@@ -150,7 +150,7 @@ worked form.
150
150
 
151
151
  **An `in-progress` issue occupies a lane rather than the whole repository.** The occupancy is counted
152
152
  from that repository's own `in-progress` listing — never from anything the session remembers — and
153
- what is left of `JOSH_LANE_LIMIT` (**default 6**) is what gets offered. At zero the answer is `wait`
153
+ what is left of `JOSH_LANE_LIMIT` (**default 4**) is what gets offered. At zero the answer is `wait`
154
154
  and the holders are named on standard error. A parked child releases its lane; one stopped by
155
155
  `needs-human-review` goes on holding one, because its uncommitted work is still in that checkout.
156
156
 
@@ -9,6 +9,11 @@ settle. `Nothing to bundle.` needs neither.
9
9
  already recorded between them. **A similar title never counts on its own** — "related" expands
10
10
  without limit, and the threshold is what keeps an unrelated issue out.
11
11
 
12
+ **The release issue is neither a candidate nor a subject**, like an epic. `issue:file --release` records
13
+ every change awaiting publication as its blocker, so that relation is mechanical, not a sign of shared
14
+ work. Counted as a signal, it would put the release and an unrelated change in one epic. A
15
+ `blocked-by` or a prose reference between any other two issues still counts.
16
+
12
17
  **The search is not limited to the open backlog.** Every issue number the subject's body names is read
13
18
  on its own, whatever its state. A **closed** reference counts only when an open epic already tracks
14
19
  it, since the answer worth recovering is `add_to_epic`; an epic created over a closed issue has
@@ -113,9 +113,10 @@ The bullets below describe that dispatch:
113
113
  trace alone**, because its log will never grow.
114
114
  - **The child is started as `fullrun #<N>` with the lane as its working directory.** The batch a
115
115
  person approved by typing `backlogrun` covers the child.
116
- - **It does not pass `--dangerously-skip-permissions`.** What the child may do is the checkout's own
117
- `.claude/settings.json` to decide; a headless child reaches `gh` and merges through `pnpm josh
118
- followup` without the flag, and the run reports what stopped rather than loosening it.
116
+ - **It passes `--permission-mode bypassPermissions`, never `--dangerously-skip-permissions`.** A
117
+ current Claude Code ignores the mode `.claude/settings.json` declares, and a new lane worktree is
118
+ never a trusted workspace; that file's `deny` list still refuses what it names, so the run reports
119
+ what stopped rather than loosening it.
119
120
 
120
121
  **Start each child without blocking on it, and poll them all** — a silent one is
121
122
  `backlogrun-recovery.md` → "A delegated unit that stopped without reporting", read in that child's
@@ -142,6 +143,7 @@ conflict.
142
143
  | The child stopped on **`needs-human-review`** | **Left open and untouched** | The uncommitted work *is* the artifact a person has to look at. Name the lane directory in the stop report and in the Telegram |
143
144
  | The child **failed** | Whichever of the two parked rows applies, plus the consecutive-failure count | Same reasoning; only the counter differs. **A merge conflict is not this row** — it takes the row above, and it is not counted |
144
145
  | **`lane:open` failed on the install** | `pnpm josh lane:close <N>`, then park the child | A lane exists that no `pnpm josh …` runs in and the next `lane:open` answers `already-open`. Closing frees the seat; parking is right because the cause is one a person fixes. Carry pnpm's reason into the park note |
146
+ | The lane is **spent** — no child working in it, its Issue closed, not one this run launched and has not collected with `run:merge`, a clean tree, no commit that is on no remote | Nothing to do — `pnpm josh lane:prune` closes it | Nothing in it is wanted, so no one has to type the close. Any other lane is kept and `lane:prune` says why on standard error |
145
147
  | The run was **interrupted** | Nothing to do — the work tree survives on disk | The next session's `pnpm josh lane:prune` closes what git no longer has a tree for. **Park that child**, naming the lane and `pnpm josh lane:close <N>` as the way out |
146
148
 
147
149
  **A lane closed after a push is reopened by `pnpm josh lane:open <N>`**, which attaches to a local
@@ -61,7 +61,7 @@ resumed session runs `remaining` from `--json`. The contract is `docs/josh-comma
61
61
  ```bash
62
62
  pnpm josh run:carry --begin "backlogrun --max 5 --idle 30" --owner "$PPID"
63
63
  pnpm josh run:carry --json # read it back in a resumed session
64
- pnpm josh run:wake --start # same turn as --begin
64
+ pnpm josh run:wake --start # same turn as --begin; `running` under `josh backlogrun`
65
65
  ```
66
66
 
67
67
  **Always pass `--owner "$PPID"`**, and ask it before the plan, in the same turn as the first `pnpm josh
@@ -85,7 +85,8 @@ named epic's children", never the root as a standalone `fullrun`, then ask `pnpm
85
85
  a child number or `complete` continues; only `stop` or a failure records `pnpm josh run:carry --done <E>
86
86
  --owner "$PPID"`.
87
87
 
88
- **A person keeps control of the supervisor** — `pnpm josh run:wake --list` / `--stop`.
88
+ **A person keeps control of the run** — `pnpm josh run:wake --list` reads it, `pnpm josh backlogrun
89
+ --stop` stops it (`docs/josh-commands.md` → "`josh backlogrun`").
89
90
 
90
91
  Rationale: `docs/maintainers/backlogrun-steps-rationale.md` → "Why a session cut does not end the run"
91
92
 
@@ -129,7 +130,7 @@ section the row names:
129
130
  | Handed back | What the session does | Read |
130
131
  | --- | --- | --- |
131
132
  | `triage` | Label each issue stderr names `run:solo` or `run:lane` (`blocked-by` where one must land first) | "Resolve what the plan can resolve, before starting" above |
132
- | `offer` | Report what stderr printed; **never pick an issue by hand** | — |
133
+ | `offer` | Report what stderr printed — a failed offer, or a named issue whose state stayed unreadable; **never pick an issue by hand** | — |
133
134
  | `launch #N` | Read the lane's log and park `#N` | `backlogrun-park.md` → "park and continue" |
134
135
  | `merge [<token>] #N` | `environment` ends the run; the others re-read the child | `backlogrun-progress.md` → "Running a named epic's children" |
135
136
  | `epic #N` | A named epic's turn | "The session cut is inside the invocation" above |
@@ -46,6 +46,7 @@ is still that one invocation (`backlogrun-steps.md` → "The session cut is insi
46
46
  session only when it needs judgment.
47
47
  7. **End the record when the run ends** — `run:report`, then `run:carry --end` (or `--end --stopped
48
48
  "<reason>"`) and `run:wake --stop`. An empty plan is not that end; the driver's idle watch decides it.
49
+ A person stops a run from the terminal with `pnpm josh backlogrun --stop`, which makes both calls.
49
50
 
50
51
  ## The route table
51
52
 
@@ -5,7 +5,8 @@
5
5
  This is the execution contract for `fullrun` and `backlogrun`, and for `prrun` up to the pull request: a `prrun` never issues `pnpm josh ship` or a merging `pnpm josh followup` — it opens the pull request with `pnpm josh git -y` and ends by `prrun.md` → "The difference — the end of the run". The record below is reference only.
6
6
  Review results and successful pushes are never turn boundaries.
7
7
 
8
- 0. **A lane child**: `pnpm josh main:merge`, the scoped pair, `pnpm josh ship --detach --review
8
+ 0. **A lane child**: `pnpm josh main:merge`, the self-check (`prompts/review.md` → "Before round 1 —
9
+ the implementer's self-check"), the scoped pair, `pnpm josh ship --detach --review
9
10
  "<title> #<N>"` (`--cite <N>`), then **end the turn** on `launched`/`busy`. A stop relaunches a child
10
11
  whose prompt names `pnpm josh ship --log <N>` and (Anthropic lane) the re-detach to run after
11
12
  the fix — `pnpm josh ship --detach`, `--review` only if the stopped ship carried it and stopped before
@@ -13,7 +14,8 @@ Review results and successful pushes are never turn boundaries.
13
14
  `failed` → step 1. A backgrounded `ship` issued alone is moved to the foreground by the hook
14
15
  rather than refused.
15
16
  1. Run `pnpm josh main:merge`. **Then issue `pnpm josh run:cut <N>` alone, before the scoped pair and
16
- the gate** — the pre-gate cut (a no-op outside a lane). Then run the final scoped lint/test pair and
17
+ the gate** — the pre-gate cut (a no-op outside a lane). Then answer the self-check
18
+ (`prompts/review.md` → "Before round 1 — the implementer's self-check"), run the final scoped lint/test pair and
17
19
  `pnpm josh run:review`: it starts `pnpm josh gate` in the background and prints the `/code-review`
18
20
  brief in one call, so the two overlap. Launch the `/code-review` subagent as the `general-purpose`
19
21
  agent type with that brief (every tool, so `--fix` applies; never a guessed type name).
@@ -91,3 +91,9 @@ never the comment text.
91
91
  **`pnpm josh rule:guard` refuses the body-only read** and hands over the reissue and the conflict rule
92
92
  at the moment they bind (`prompts/collaboration-workflow/rule-delivery.md`). **This file is the rule,
93
93
  not the hook** — a session that runs no hooks still owes the read.
94
+
95
+ ## A person's update mid-run
96
+
97
+ When the hook, `review:attest --check` or `followup` shows an Issue update, read it as above — the
98
+ later text is in force — fix what it changes, then `pnpm josh issue:ack <N>`. The watch and what it
99
+ does not catch: `docs/josh-commands-backlog.md` → "`josh issue:ack`".
@@ -106,8 +106,9 @@ could not.
106
106
  and appends nothing. That round reads only, so no commit of the run's follows it; a line in the tree
107
107
  would be pushed onto the open pull request and its CI would start over. `pnpm josh ship --review`
108
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. The comment's lines are outside the count
110
- `pnpm josh review:findings` and the retrospective read.
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`).
111
112
  - **`pnpm josh followup` commits any other line appended after the run's commit onto the pull request,
112
113
  before the merge** — the residual path, for an observation recorded between the commit and the
113
114
  merge. After the merge gates and before the CI wait, `followup` reads the tree and, **only when the
@@ -169,9 +169,11 @@ built for the lane child.
169
169
  **The trigger**: `pnpm josh rule:guard` refuses an `Edit` / `Write` in a dispatched lane child whose
170
170
  recent-context cost is over threshold, handing back `pnpm josh run:cut --impl <N> --handoff <path>`.
171
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,
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,
175
177
  not once per run**; **An edit reissued right after a refusal passes**; **An unmeasurable session
176
178
  warrants the cut**; **It is silent between a cut and its resume**. Rationale:
177
179
  `docs/maintainers/pre-gate-cut-rationale.md` → "Why the rules are guards, not prose";
package/README.md CHANGED
@@ -35,6 +35,16 @@ pnpm exec josh start
35
35
 
36
36
  Next: [tutorial](./docs/tutorial.md)
37
37
 
38
+ ### Your first backlogrun
39
+
40
+ Tell the agent the change you want, then type `kickoff new auto ok` to it (or add the `auto-ok` label to an existing Issue).
41
+
42
+ ```bash
43
+ pnpm josh backlogrun
44
+ ```
45
+
46
+ Details: [Run the backlog unattended](./docs/how-to/run-backlog.md)
47
+
38
48
  ### AI assistant only — no GitHub account needed
39
49
 
40
50
  Requires [Node.js and pnpm](./docs/setup/prerequisites.md).
@@ -45,6 +55,21 @@ pnpm --allow-build=esbuild dlx @joshuafolkken/kit init
45
55
 
46
56
  Next: [tutorial](./docs/tutorial.md#without-github-one-change-checked-locally)
47
57
 
58
+ ## Claude Code in a fresh-machine run
59
+
60
+ A [`josh fresh:run`](./docs/maintainers/fresh-machine.md) scenario that runs Claude Code needs a sign-in, saved once:
61
+
62
+ 1. In a terminal at the kit repository, run:
63
+
64
+ ```bash
65
+ pnpm josh auth:setup
66
+ ```
67
+
68
+ 2. A browser opens: sign in with your Claude account and press "Authorize".
69
+ 3. Done when the terminal prints `saved: CLAUDE_CODE_OAUTH_TOKEN (macOS keychain)`. There is no token to copy or write into a file.
70
+ 4. To check, run `pnpm josh auth:setup --check`: it prints `ok` and the day it was saved.
71
+ 5. When the token expires, Claude Code in the container fails to sign in — start again from step 1.
72
+
48
73
  ## Docs
49
74
 
50
75
  [How-to](./docs/how-to.md) · [All docs](./docs/overview.md)
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env tsx
2
2
  import {
3
3
  timed_fetch
4
- } from "./chunk-FZ6FUSBM.js";
4
+ } from "./chunk-723HKZO5.js";
5
5
  import {
6
6
  error_text
7
7
  } from "./chunk-CDY4NFQG.js";
8
8
  import {
9
9
  PROJECT_ROOT,
10
10
  stamp_file
11
- } from "./chunk-NEC4AT4Z.js";
11
+ } from "./chunk-DGT54IH5.js";
12
12
 
13
13
  // scripts/security/security-audit-provision.ts
14
14
  import { chmodSync, mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
@@ -9,13 +9,13 @@ import {
9
9
  load_environment_file,
10
10
  notice_refusal_path,
11
11
  refusal_path
12
- } from "./chunk-LMWBRJIP.js";
13
- import "./chunk-EAQEGME7.js";
14
- import "./chunk-EBSHN25W.js";
15
- import "./chunk-SL4GQ2XP.js";
16
- import "./chunk-J3KSS7II.js";
17
- import "./chunk-2YSW3CXH.js";
18
- import "./chunk-NEC4AT4Z.js";
12
+ } from "./chunk-7KMN5QB5.js";
13
+ import "./chunk-5SJSSCJG.js";
14
+ import "./chunk-MU4LJFIV.js";
15
+ import "./chunk-XER6SSIB.js";
16
+ import "./chunk-4BHUPFKF.js";
17
+ import "./chunk-3LE6VLSR.js";
18
+ import "./chunk-DGT54IH5.js";
19
19
  export {
20
20
  DISABLED_VALUES,
21
21
  SWITCH_ENV_KEY,
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  investigation_reads
3
- } from "./chunk-WNFJLBXI.js";
3
+ } from "./chunk-QL6QTPWN.js";
4
4
  import {
5
5
  lane_guard_policy
6
- } from "./chunk-EAQEGME7.js";
6
+ } from "./chunk-5SJSSCJG.js";
7
7
  import {
8
8
  hook_decision
9
- } from "./chunk-EBSHN25W.js";
9
+ } from "./chunk-MU4LJFIV.js";
10
10
 
11
11
  // scripts/delegation/investigation-guard.ts
12
12
  import { text } from "node:stream/consumers";
@@ -4,7 +4,7 @@ import {
4
4
  PROBE_TIMEOUT_MS,
5
5
  SUITE_TIMEOUT_MS,
6
6
  stamp_file
7
- } from "./chunk-NEC4AT4Z.js";
7
+ } from "./chunk-DGT54IH5.js";
8
8
 
9
9
  // scripts/lib/json-value.ts
10
10
  function parse_or_undefined(text) {
@@ -511,12 +511,19 @@ async function commit(message) {
511
511
  async function delete_branch(branch_name) {
512
512
  await git_spawn.read(["branch", "-d", branch_name]);
513
513
  }
514
- async function commit_count_beyond(base, tip) {
515
- const range = `${base}..${tip}`;
516
- const output = await git_spawn.read(["rev-list", "--count", range]);
514
+ async function read_commit_count(revisions) {
515
+ const output = await git_spawn.read(["rev-list", "--count", ...revisions]);
517
516
  const parsed = Number(output);
518
517
  if (output.length > 0 && Number.isFinite(parsed)) return parsed;
519
- throw new Error(`\`git rev-list --count ${range}\` printed \`${output}\` rather than a count`);
518
+ throw new Error(
519
+ `\`git rev-list --count ${revisions.join(" ")}\` printed \`${output}\` rather than a count`
520
+ );
521
+ }
522
+ async function commit_count_beyond(base, tip) {
523
+ return await read_commit_count([`${base}..${tip}`]);
524
+ }
525
+ async function commit_count_unpushed(branch_name) {
526
+ return await read_commit_count([branch_name, "--not", "--remotes"]);
520
527
  }
521
528
  function is_exit_code_128(cause) {
522
529
  return typeof cause === "object" && cause !== null && "exit_code" in cause && cause.exit_code === "128";
@@ -633,6 +640,7 @@ var git_command = {
633
640
  checkout,
634
641
  commit,
635
642
  commit_count_beyond,
643
+ commit_count_unpushed,
636
644
  delete_branch,
637
645
  push: push2,
638
646
  pull_fast_forward,
@@ -2049,6 +2057,7 @@ var run_carry_schema = z2.object({
2049
2057
  owner_pid: z2.number().optional(),
2050
2058
  owner_start: z2.string().optional(),
2051
2059
  owner_transcript: z2.string().optional(),
2060
+ is_owner_headless: z2.boolean().optional(),
2052
2061
  is_handed_off: z2.boolean().optional(),
2053
2062
  done: z2.array(z2.number()).optional(),
2054
2063
  retrospective: z2.boolean().optional(),
@@ -2090,7 +2099,8 @@ function fresh_carry(invocation, owner, now) {
2090
2099
  outages: NO_INCREMENT3,
2091
2100
  owner_pid: owner.pid,
2092
2101
  owner_start: owner.start,
2093
- owner_transcript: owner.transcript
2102
+ owner_transcript: owner.transcript,
2103
+ is_owner_headless: owner.is_headless
2094
2104
  };
2095
2105
  }
2096
2106
  function begin_carry(target, invocation, owner = NO_OWNER, now = /* @__PURE__ */ new Date()) {
@@ -2103,6 +2113,7 @@ function adopt_carry(target, carry, owner = NO_OWNER) {
2103
2113
  owner_pid: owner.pid,
2104
2114
  owner_start: owner.start,
2105
2115
  owner_transcript: owner.transcript,
2116
+ is_owner_headless: owner.is_headless,
2106
2117
  is_handed_off: false
2107
2118
  };
2108
2119
  stamp_file.remove_stamp(target);
@@ -2,7 +2,7 @@ import {
2
2
  ENV_FILE_NAME,
3
3
  issue_number_shape,
4
4
  lane_paths
5
- } from "./chunk-2YSW3CXH.js";
5
+ } from "./chunk-3LE6VLSR.js";
6
6
 
7
7
  // scripts/josh/josh-environment-file.ts
8
8
  function load_environment_file() {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  lane_child_marker
3
- } from "./chunk-J3KSS7II.js";
3
+ } from "./chunk-4BHUPFKF.js";
4
4
 
5
5
  // scripts/lane/lane-guard-policy.ts
6
6
  var DEFAULT_MODE = "refuse";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  FETCH_TIMEOUT_MS
3
- } from "./chunk-NEC4AT4Z.js";
3
+ } from "./chunk-DGT54IH5.js";
4
4
 
5
5
  // scripts/lib/timed-fetch.ts
6
6
  async function timed_fetch(url, init = {}, timeout_ms = FETCH_TIMEOUT_MS) {
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  lane_guard_policy
3
- } from "./chunk-EAQEGME7.js";
3
+ } from "./chunk-5SJSSCJG.js";
4
4
  import {
5
5
  hook_decision
6
- } from "./chunk-EBSHN25W.js";
6
+ } from "./chunk-MU4LJFIV.js";
7
7
  import {
8
8
  time_batch_guard
9
- } from "./chunk-SL4GQ2XP.js";
9
+ } from "./chunk-XER6SSIB.js";
10
10
 
11
11
  // scripts/hooks/batch-guard.ts
12
12
  import { text } from "node:stream/consumers";
@@ -3,6 +3,9 @@ import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  var PACKAGE_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
5
5
  var PROJECT_ROOT = process.cwd();
6
+ function package_path(relative_path) {
7
+ return path.join(PACKAGE_DIR, relative_path);
8
+ }
6
9
 
7
10
  // scripts/josh/stamp-file.ts
8
11
  import { createHash, randomUUID } from "node:crypto";
@@ -144,6 +147,7 @@ var SUITE_TIMEOUT_MS = 18e5;
144
147
 
145
148
  export {
146
149
  PROJECT_ROOT,
150
+ package_path,
147
151
  PLATFORM_TEMP_ROOT,
148
152
  platform_temporary,
149
153
  stamp_file,
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  resolve_local_bin,
3
3
  resolve_package_bin
4
- } from "./chunk-JBBMAPC4.js";
4
+ } from "./chunk-IX6TTTI6.js";
5
5
  import {
6
6
  ESLINT_EDIT_CACHE_FLAGS,
7
7
  time_density_hook
8
- } from "./chunk-SL4GQ2XP.js";
8
+ } from "./chunk-XER6SSIB.js";
9
9
  import {
10
10
  file_reader,
11
11
  json_value
12
- } from "./chunk-2YSW3CXH.js";
12
+ } from "./chunk-3LE6VLSR.js";
13
13
  import {
14
14
  HOOK_PROCESS_TIMEOUT_MS
15
- } from "./chunk-NEC4AT4Z.js";
15
+ } from "./chunk-DGT54IH5.js";
16
16
 
17
17
  // scripts/hooks/format-edited-file.ts
18
18
  import { existsSync as existsSync2 } from "node:fs";
@@ -85,6 +85,10 @@ function resolve_package_bin(base_directory, package_name, bin_name) {
85
85
 
86
86
  export {
87
87
  ancestor_directories,
88
+ vscode_settings_schema,
89
+ json_object_schema,
90
+ string_array_schema,
91
+ string_record_schema,
88
92
  resolve_local_bin,
89
93
  find_local_bin_upwards,
90
94
  resolve_package_bin