jackherd 1.8.1 → 1.10.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 (261) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/INSTALL.md +3 -1
  3. package/README.md +75 -64
  4. package/dist/{chunk-OU2KALXP.js → chunk-5MQBCUQ5.js} +24 -4
  5. package/dist/config.d.ts +45 -4
  6. package/dist/config.js +84 -27
  7. package/dist/plan-format.d.ts +63 -7
  8. package/dist/plan-format.js +66 -12
  9. package/docs/workflow-dark.svg +67 -63
  10. package/docs/workflow.svg +67 -63
  11. package/herdr-plugin/herdr-plugin.toml +1 -1
  12. package/install.sh +1 -1
  13. package/kit/hooks/ask-rules.json +15 -0
  14. package/kit/hooks/hooks/approval-gate/index.ts +22 -4
  15. package/kit/hooks/hooks/approval-gate/run.ts +29 -6
  16. package/kit/hooks/hooks/approval-gate/subagent.ts +18 -0
  17. package/kit/hooks/hooks/ask-hint/decision.ts +82 -14
  18. package/kit/hooks/hooks/ask-hint/index.ts +15 -19
  19. package/kit/hooks/hooks/ask-hint/settings.ts +3 -18
  20. package/kit/hooks/hooks/git-guard/decision.ts +50 -102
  21. package/kit/hooks/hooks/merge-guard/always-ask.ts +63 -0
  22. package/kit/hooks/hooks/merge-guard/{plan-approval-settings.ts → board-settings.ts} +21 -67
  23. package/kit/hooks/hooks/merge-guard/check-free.ts +20 -0
  24. package/kit/hooks/hooks/merge-guard/decision.ts +127 -140
  25. package/kit/hooks/hooks/merge-guard/index.ts +6 -3
  26. package/kit/hooks/hooks/merge-guard/lane-plan.ts +79 -0
  27. package/kit/hooks/hooks/merge-guard/run.ts +59 -54
  28. package/kit/hooks/hooks/merge-guard/settings.ts +13 -1
  29. package/kit/hooks/hooks/merge-guard/standing-approval.ts +142 -0
  30. package/kit/hooks/hooks/open-question/index.ts +26 -0
  31. package/kit/hooks/hooks/open-question/record.ts +135 -0
  32. package/kit/hooks/hooks/open-question/run.ts +52 -0
  33. package/kit/hooks/hooks/open-question/store.ts +39 -0
  34. package/kit/hooks/hooks/sent-file/index.ts +19 -0
  35. package/kit/hooks/hooks/sent-file/record.ts +128 -0
  36. package/kit/hooks/hooks/sent-file/run.ts +48 -0
  37. package/kit/hooks/hooks/sent-file/store.ts +9 -0
  38. package/kit/hooks/hooks/shared/board-lanes.ts +15 -2
  39. package/kit/hooks/hooks/shared/config.ts +7 -0
  40. package/kit/hooks/hooks/shared/dialog-answers.ts +9 -9
  41. package/kit/hooks/hooks/shared/files.ts +7 -0
  42. package/kit/hooks/hooks/shared/lane.ts +1 -1
  43. package/kit/hooks/hooks/shared/newest-verdict.ts +10 -0
  44. package/kit/hooks/hooks/shared/private-directory.ts +56 -9
  45. package/kit/hooks/hooks/shared/program-position.ts +2 -75
  46. package/kit/hooks/hooks/shared/shell-aliases.ts +1 -71
  47. package/kit/hooks/hooks/{ask-hint → shared}/transcript.ts +37 -6
  48. package/kit/hooks/hooks/{merge-guard → shared}/xargs-program.ts +10 -8
  49. package/kit/hooks/hooks/task-hint/decision.ts +49 -0
  50. package/kit/hooks/hooks/task-hint/index.ts +79 -0
  51. package/kit/hooks/hooks/task-hint/run.ts +62 -0
  52. package/kit/hooks/hooks/task-hint/store.ts +51 -0
  53. package/kit/hooks/hooks.json +21 -4
  54. package/kit/hooks/statusline.sh +1 -1
  55. package/kit/review/agents/skill-review.md +34 -0
  56. package/kit/review/skills/pre-commit/SKILL.md +1 -1
  57. package/kit/workflow/skills/follow/SKILL.md +1 -8
  58. package/kit/workflow/skills/implement/SKILL.md +10 -6
  59. package/kit/workflow/skills/orchestrate/SKILL.md +213 -412
  60. package/kit/workflow/skills/orchestrate/handover/decision.ts +43 -8
  61. package/kit/workflow/skills/orchestrate/handover/index.ts +32 -4
  62. package/kit/workflow/skills/orchestrate/handover/standing-approval.ts +84 -0
  63. package/kit/workflow/skills/orchestrate/references/acceptance.md +15 -0
  64. package/kit/workflow/skills/orchestrate/references/close-lane.md +17 -0
  65. package/kit/workflow/skills/orchestrate/references/coordinator-handover.md +43 -17
  66. package/kit/workflow/skills/orchestrate/references/draft-review.md +19 -0
  67. package/kit/workflow/skills/orchestrate/references/events.md +86 -0
  68. package/kit/workflow/skills/orchestrate/references/herd.md +6 -6
  69. package/kit/workflow/skills/orchestrate/references/lane-handover.md +18 -0
  70. package/kit/workflow/skills/orchestrate/references/lane-session.md +25 -0
  71. package/kit/workflow/skills/orchestrate/references/lane-setup.md +37 -0
  72. package/kit/workflow/skills/orchestrate/references/plan-commit.md +22 -10
  73. package/kit/workflow/skills/orchestrate/references/sensitive-input.md +5 -7
  74. package/kit/workflow/skills/plan/SKILL.md +6 -5
  75. package/kit/workflow/skills/plan/references/template-English.md +4 -4
  76. package/kit/workflow/skills/plan/references/template-German.md +4 -4
  77. package/package.json +4 -1
  78. package/recipes/README.md +2 -1
  79. package/recipes/sources.md +1 -1
  80. package/schemas/jackherd.schema.json +85 -7
  81. package/src/check/agent-text-reviewers.ts +23 -0
  82. package/src/check/command.ts +2 -0
  83. package/src/check/plan-structure-check.ts +49 -2
  84. package/src/check/plan.ts +8 -1
  85. package/src/check/schema.ts +9 -0
  86. package/src/check/skill-budget-defaults.ts +55 -0
  87. package/src/check/skill-budgets.ts +185 -0
  88. package/src/cli.ts +4 -0
  89. package/src/config/auto-window.ts +8 -0
  90. package/src/config/link-kinds.ts +7 -1
  91. package/src/config/schema.ts +80 -26
  92. package/src/context/fill.ts +12 -0
  93. package/src/context/session-log.ts +43 -1
  94. package/src/lane/close-board.ts +106 -0
  95. package/src/lane/close-check.ts +183 -0
  96. package/src/lane/close-command-line.ts +11 -0
  97. package/src/lane/close-command.ts +217 -0
  98. package/src/lane/close-options.ts +43 -0
  99. package/src/lane/close-survey.ts +83 -0
  100. package/src/lane/close.ts +141 -0
  101. package/src/lane/command.ts +13 -0
  102. package/src/lane-prompt/build.ts +74 -0
  103. package/src/lane-prompt/command.ts +87 -0
  104. package/src/lane-prompt/input.ts +116 -0
  105. package/src/lane-prompt/options.ts +68 -0
  106. package/src/lane-prompt/texts.ts +101 -0
  107. package/src/plan-format/clock.ts +12 -0
  108. package/src/plan-format/dependencies.ts +9 -9
  109. package/src/plan-format/index.ts +1 -0
  110. package/src/plan-format/lanes.ts +30 -5
  111. package/src/plan-format/short-names.ts +71 -0
  112. package/src/plan-format/terminal-text.ts +4 -0
  113. package/src/plan-format/waiting.ts +53 -0
  114. package/src/plans/active-tasks.ts +60 -0
  115. package/src/plans/appointment-rows.ts +59 -0
  116. package/src/plans/ask-coordinator.ts +77 -0
  117. package/src/plans/ask-target.ts +25 -0
  118. package/src/plans/child-stop.ts +51 -0
  119. package/src/plans/closable-records.ts +34 -0
  120. package/src/plans/command.ts +3 -2
  121. package/src/plans/current-phase.ts +17 -7
  122. package/src/plans/current-task.ts +63 -5
  123. package/src/plans/fetch.ts +26 -3
  124. package/src/plans/git.ts +19 -5
  125. package/src/plans/herd-claim.ts +173 -0
  126. package/src/plans/herd-memory.ts +36 -25
  127. package/src/plans/lane-plans.ts +44 -13
  128. package/src/plans/lane-standing.ts +9 -4
  129. package/src/plans/lane-summary.ts +367 -92
  130. package/src/plans/lane-tickets.ts +15 -0
  131. package/src/plans/layout-phase.ts +80 -19
  132. package/src/plans/layout-summary.ts +163 -74
  133. package/src/plans/layout.ts +472 -114
  134. package/src/plans/link-chips.ts +1 -0
  135. package/src/plans/live.ts +119 -10
  136. package/src/plans/phase-ids.ts +8 -0
  137. package/src/plans/phase-models.ts +1 -1
  138. package/src/plans/phase-ranges.ts +45 -0
  139. package/src/plans/phase-source.ts +15 -0
  140. package/src/plans/plan-cache.ts +28 -0
  141. package/src/plans/plan-heads.ts +54 -0
  142. package/src/plans/pull-requests.ts +23 -2
  143. package/src/plans/question-records.ts +48 -0
  144. package/src/plans/questions-read.ts +13 -0
  145. package/src/plans/read-cache.ts +8 -0
  146. package/src/plans/record-id.ts +4 -0
  147. package/src/plans/restart-decision.ts +13 -4
  148. package/src/plans/selection.ts +117 -34
  149. package/src/plans/sent-files-read.ts +13 -0
  150. package/src/plans/sent-files.ts +114 -0
  151. package/src/plans/settings.ts +2 -1
  152. package/src/plans/signalled-phase.ts +42 -0
  153. package/src/plans/signals-read.ts +62 -0
  154. package/src/plans/snapshot.ts +279 -60
  155. package/src/plans/sprint-export.ts +11 -11
  156. package/src/plans/sprint-page.ts +5 -5
  157. package/src/plans/subagent-phases.ts +95 -0
  158. package/src/plans/subagent-tasks.ts +51 -0
  159. package/src/plans/subagents-read.ts +131 -0
  160. package/src/plans/subagents.ts +190 -0
  161. package/src/plans/supervisor.ts +14 -4
  162. package/src/plans/symbols.ts +3 -0
  163. package/src/plans/task-name.ts +34 -0
  164. package/src/plans/texts.ts +36 -14
  165. package/src/plans/unlisted-lanes.ts +10 -5
  166. package/src/plans/view.ts +20 -12
  167. package/src/plans/waiting-click.ts +231 -0
  168. package/src/plans/waiting-records.ts +39 -0
  169. package/src/plans/waiting-window.ts +8 -0
  170. package/src/preview/command.ts +105 -0
  171. package/src/preview/embed.ts +209 -0
  172. package/src/preview/images.ts +89 -0
  173. package/src/preview/open.ts +12 -0
  174. package/src/preview/options.ts +32 -0
  175. package/src/preview/page.ts +89 -0
  176. package/src/preview/render.ts +41 -0
  177. package/src/settled/board-row.ts +1 -2
  178. package/src/shared/is-record.ts +2 -0
  179. package/src/shared/private-location.ts +89 -0
  180. package/src/shared/private-records.ts +48 -0
  181. package/src/shared/stat-cache.ts +48 -0
  182. package/src/sync/kit-source.ts +29 -10
  183. package/src/sync/kit.ts +2 -0
  184. package/src/sync/manifest.ts +2 -0
  185. package/src/sync/plan-ask-rules.ts +94 -0
  186. package/src/sync/plan-hooks.ts +2 -0
  187. package/src/sync/render.ts +3 -3
  188. package/src/sync/settings-hooks.ts +4 -1
  189. package/src/sync/sync-plan.ts +1 -0
  190. package/src/sync/sync.ts +24 -3
  191. package/src/task-signals/agent.ts +15 -0
  192. package/src/task-signals/claude-read.ts +89 -0
  193. package/src/task-signals/claude-signals.ts +112 -0
  194. package/src/task-signals/command.ts +71 -0
  195. package/src/task-signals/fixtures/session.jsonl +7 -0
  196. package/src/task-signals/matcher.ts +96 -0
  197. package/src/task-signals/record-store.ts +40 -0
  198. package/src/task-signals/record.ts +68 -0
  199. package/src/task-signals/text.ts +13 -0
  200. package/src/task-signals/types.ts +14 -0
  201. package/src/terminal/open.ts +13 -6
  202. package/src/terminal/text.ts +16 -4
  203. package/src/terminal/width.ts +2 -1
  204. package/src/version/skill-diff.ts +46 -0
  205. package/src/vocabulary/index.ts +44 -6
  206. package/src/waiting/command.ts +50 -0
  207. package/src/watch/appointments.ts +2 -4
  208. package/src/watch/approvals.ts +2 -2
  209. package/src/watch/asking-lanes.ts +40 -0
  210. package/src/watch/base-tip.ts +11 -0
  211. package/src/watch/command.ts +401 -90
  212. package/src/watch/failed-tests.ts +56 -10
  213. package/src/watch/failure-read.ts +18 -6
  214. package/src/watch/failures.ts +29 -5
  215. package/src/watch/feedback.ts +1 -1
  216. package/src/watch/gh-process.ts +9 -3
  217. package/src/watch/heartbeat-progress.ts +6 -18
  218. package/src/watch/json-guards.ts +0 -3
  219. package/src/watch/kit-update.ts +28 -9
  220. package/src/watch/lane-fill.ts +1 -1
  221. package/src/watch/lane-model.ts +1 -1
  222. package/src/watch/lane-name.ts +6 -0
  223. package/src/watch/lane-parallel.ts +1 -1
  224. package/src/watch/lane-progress.ts +58 -14
  225. package/src/watch/lane-report-file.ts +20 -5
  226. package/src/watch/lane-report.ts +37 -5
  227. package/src/watch/lane-rest.ts +28 -0
  228. package/src/watch/lane-sources.ts +31 -3
  229. package/src/watch/main-checkout.ts +34 -0
  230. package/src/watch/plan-badges-read.ts +13 -7
  231. package/src/watch/plan-badges.ts +9 -2
  232. package/src/watch/previews.ts +1 -1
  233. package/src/watch/pull-requests.ts +8 -3
  234. package/src/watch/reference-paths.ts +87 -0
  235. package/src/watch/running-subagents.ts +43 -0
  236. package/src/watch/skill-change.ts +124 -32
  237. package/src/watch/source-change.ts +48 -0
  238. package/src/watch/source-path.ts +1 -1
  239. package/src/watch/sources.ts +7 -4
  240. package/src/watch/stream-output.ts +14 -8
  241. package/src/watch/task-parallel-auto.ts +208 -0
  242. package/src/watch/task-parallel-data-paths.ts +46 -0
  243. package/src/watch/task-parallel-input.ts +108 -0
  244. package/src/watch/task-parallel-read.ts +151 -0
  245. package/src/watch/task-parallel-touched.ts +39 -0
  246. package/src/watch/task-parallel.ts +235 -0
  247. package/src/watch/task-signal-missing.ts +69 -0
  248. package/src/watch/task-signal-read.ts +29 -0
  249. package/src/watch/texts.ts +10 -0
  250. package/src/watch/update-available.ts +6 -3
  251. package/src/watch/waiting-line.ts +19 -0
  252. package/src/watch/watch-events.ts +36 -1
  253. package/src/watch/watcher-lock.ts +25 -29
  254. package/src/watch/workflow-runs.ts +2 -1
  255. package/kit/hooks/hooks/merge-guard/plan-approval-record.ts +0 -23
  256. package/kit/hooks/hooks/merge-guard/plan-approval-sources.ts +0 -196
  257. package/kit/hooks/hooks/merge-guard/plan-approval.ts +0 -168
  258. package/kit/hooks/hooks/merge-guard/plan-growth.ts +0 -40
  259. package/kit/hooks/hooks/merge-guard/plan-pointers.ts +0 -194
  260. package/kit/hooks/hooks/shared/command-text-runners.ts +0 -71
  261. package/kit/hooks/hooks/shared/plan-open-phases.ts +0 -114
package/CHANGELOG.md CHANGED
@@ -2,6 +2,66 @@
2
2
 
3
3
  What changed for people who use jackherd, newest first.
4
4
 
5
+ ## 1.10.0
6
+
7
+ - **`jh sync` writes the ask rules the merge guard left behind.** A project sync adds `permissions.ask` rules for `gh run rerun` and the `gh api` writes that merge, write a file, dispatch or rerun a workflow, or move a ref; it records them in the lock, removes one only when the kit drops it and only if a kit shipped it, and leaves your own rules alone. Claude Code applies a matching ask rule even when a hook answers `allow`.
8
+ - **A standing approval replaces the plan approval.** The coordinator asks once per plan with an end time, at most 24 hours ahead; until then the merge guard lets the plan's lane pull requests merge on green checks, except workflows, migrations, env files and the guards' own files (hooks, settings, the jackherd config, git hooks). It lives in that chat only: after a hand-over the new chat asks again. The plan approval, its hook and its pointers under `.jackherd/approvals/plans/` are gone.
9
+ - **`guard.planApproval` is now `guard.alwaysAsk` and `guard.requiredChecks`.** The old key is still read until 2.0.0, so your config keeps working.
10
+ - **A lane that works without reporting its task is noticed.** A new `PostToolUse` hook `task-hint` reminds a lane once per task to run `jh task start` (off with `hints.taskSignal: false`); the watcher reports `lane <name> no task signal (P<n>)` once per lane and phase after `watch.taskSignalMinutes` (default 10) of work. The herd takes the current phase from the lane's newest reported task, else from its branch name, and a phase with a signal never reads `next`.
11
+ - **The herd and the watcher read ticked boxes from open pull requests.** A phase whose pull request ticks it further shows that count, not the one from the base branch; `jh lane prompt` reads the plan from the lane's worktree and leaves out a phase finished in either copy. Pull request heads are fetched into `refs/jackherd/pr/<n>`, apart from your branches.
12
+ - **`jh lane close <lane> [--dry-run]` closes a finished lane in one run.** It first checks that nothing is lost and lists every reason it refuses: the board does not name the lane, its branch has no merged pull request whose merge commit holds the same tree, the worktree holds anything beyond `node_modules`, the `.worktreeinclude` files and known build output, the hand-over directory is not empty, an agent still works in it, or the command runs inside it. Then it exits the agent, checks again, removes the worktree (never forced) and the herdr workspace, deletes the branch at the checked head and marks the board rows with a history row. `--dry-run` only checks. `jh sync` adds ask rules, so Claude Code asks before every call, `--dry-run` included. The watcher's `plan finished` line names the dry run, and the orchestrate skill shrinks its closing steps to the command.
13
+ - **The herd shows a lane's subagents on their task.** A lane's own review ran as a subagent the herd never listed. Now the subagents of the lane's worktree count in the heartbeat, a review sits on the gate item that names its type (or shows `▶ Subagent: <description>`), and a subagent whose description starts with an open task's short name sits on that task. `task-hint` also reminds of the task signal when a subagent starts. An opened task shows its short name once.
14
+ - **The watcher reminds you when the main checkout is out of date.** While it lags behind `origin/<base>` or has another branch or a detached head checked out, every report and heartbeat carries a line (`main checkout behind origin/<base> by <n> (git merge --ff-only origin/<base>)`, `main checkout on <branch>, not <base>`). A watcher run from source ends with `kit updated … (source changed)` when its sources change, so the herd restarts on the new code.
15
+ - **A question from a working lane is reported at once.** A lane waiting on background subagents ends no turn, so its question waited for them. The watcher now reports a changed questions section of a working lane as `report … questions: <n>`, once per change and not again after a restart. The `open-question` hook treats "noch nicht" and "not yet" as putting a question off.
16
+ - **A source keeps its interval over a restart of the watcher.** Each `watch.sources` entry remembers when it last ran, so a restart no longer runs every source at once.
17
+
18
+ - **No mandatory rule is lost when a skill gets shorter.** The kit's own test holds the 67 rules the coordinator and the lanes must follow and finds each in its skill or in a reference the skill links, so a cut that drops one turns red.
19
+ - **`jh check` measures what an agent loads, in words.** Every installed kit skill, reference, agent and always-loaded kit rule, each project supplement (`.claude/project/<skill>.md`, 800 words) and each skill of your own (2000 words) is counted against a word budget: a warning above it, an error above it plus 10 %. Set your own under `check.skillBudgets` in `.jackherd/config.json`, by path or glob; a key joining two paths with ` + ` budgets what loads together. The kit's test reads the same budgets, which now sit at the measured size plus at most 10 %, and every budget names a file the kit ships.
20
+ - **A rare watcher line names the file that handles it.** A rare event ends in `· read <skill directory>/references/<file>`, so the coordinator reads that procedure when it is needed instead of carrying it in every session; a kit update reports changed, new and deleted references like the skill. The heartbeat names the tick count of every working lane and its running subagents (`P12 7/12, 3 subagents`).
21
+ - **The herd shows what waits for you and the board's appointments as blocks of their own.** `Waiting for you` lists the board's open questions, the files sent to you and the dialog questions you left open (a new stop hook `open-question` records them); a click sends the coordinator a fixed line with the question's id. `Appointments` lists the open rows of the board's appointments section. Both fold together. A lane row shows the task's short name, a running reviewer makes its phase active, finished phases read `done P1–P2` beside `next P4–P5`, and the clock is `HH:MM`. One herd runs per terminal: a new one stops the older on the same tty (Linux). The herd reads session logs and plans through a cache and redraws only a changed frame.
22
+ - **`jh lane prompt <lane>` writes a lane's first prompt** from its board row and the plan's dependency table, in the plan's language (`--board`, `--out`, `--handover` for a restart). It tells the lane its phases, its write set, that it may tick its own tasks, and that code and tests go through Write and Edit, never a here-document in Bash.
23
+ - **The orchestrate skill is about a third shorter.** The coordinator loads about 7400 words instead of 11400; rare steps (setting up and closing a lane, the rare events, a draft for review, an acceptance, a lane's hand-over) moved to references under `references/` that name their section and trigger. Sections and step numbers stay.
24
+ - **Every file jackherd keeps outside the repository lies in a private directory it checks first.** The board page, `jh preview`'s page, the watcher's lock and state, skill diffs and the herd's lane memory go below `$XDG_RUNTIME_DIR` (when it is the user's own and closed to others) or `<tmp>/jackherd-<uid>`, written through a temporary file. The herd reads the watcher's files only from a private directory and only regular files.
25
+ - **The implement, plan and follow skills are shorter, and every task has a short name.** A plan task starts with `- [ ] **Name**: …`, at most 40 characters; the plan templates use it, and the herd shows it. `/follow` reads the rules every recipe follows from the recipe index.
26
+ - **`skill-review` reviews changed agent texts.** `jh check` routes a change to Markdown under `skills/`, `agents/`, `rules/`, `.claude/project/` and to `CLAUDE.md`/`AGENTS.md` to the new kit agent, which judges it against `writing-for-agents.md`: no-op, the same rule twice, the wrong rung, a late trigger, a negation, an open step. `jh check` warns about a new plan task without a short name or with one over 40 characters, and about a phase title over 50.
27
+ - **The coordinator may start parallel tasks without asking, inside a window you set.** `watch.parallelTasks.auto: { "since": "<date>", "until": "<date>" }`, at most seven days, off by default. Inside it, a `parallel tasks` proposal ends in `· auto until <day>` when every limit holds: running work in the lane, at most two extra subagents, cost under `watch.parallelTasks.maxTokens`, no path that always asks (nor a migration or env file below a written directory), read from the plan at the base branch. Otherwise it ends in `· asks: <limit>` and the coordinator asks as before. The end of the window is reported once.
28
+ - **The merge guard and the git guard read only the parsed script.** They count a command at a program position (past options, chains, subshells, substitutions, `env`/`sudo`/`xargs`, `sh -c`, `eval`, aliases and functions), and no longer search interpreter code, here-document data or quoted text for command words, which caused most of their false alarms. A call that only reads passes (`--help`, `gh … view`, `gh … list`), and a script the parser cannot read asks only when `gh` stands where a command starts. Deliberately accepted: `subprocess.run(['gh', 'pr', 'merge', …])` in an interpreter no longer asks.
29
+ - **The merge guard guards only `gh pr merge` and `gh workflow run` by default.** `gh run rerun` and the `gh api` writes left `guard.commands`; `jh sync` now writes them as ask rules (first entry above).
30
+ - **`merge.withoutChecks` no longer merges a file on a path that always asks** (workflows, migrations, lockfiles, env files, agent instructions, `guard.alwaysAsk`), besides `package.json` and changelogs.
31
+ - **A coordinator hand-over carries your standing approvals.** The hand-over script takes `--board <board> --approval "<line> <DD.MM.> <HH:MM>"` and quotes that board row word for word into the new chat's first input, so a commit you already approved is not refused there. It refuses a row without your dated mark, an end the row does not name, and an approval that has ended.
32
+ - **npm finds jackherd under `plan-driven` and `multi-agent` too**, beside `orchestration` and the other keywords.
33
+ - **The README says what jackherd adds to Claude Code** after a check against the code and the Claude Code docs, recommends herdr and names who it is for. `INSTALL.md` lists all eleven project hooks, and `/orchestrate` sends migrations and writes against a shared environment to you every time.
34
+
35
+ ## 1.9.0
36
+
37
+ - **An open lane in the herd takes fewer lines, and a red pull request says what failed where.** A failed test hangs under its check as `└ ✗ <package> · <test>`, the package read from the log (the monorepo task header, else the test file), the test path dim with `›`; a cut name unfolds on a click and folds on the next. The pull request title stays on one line, a lane's only link chip moves onto its session line, and the finished phases are ranges (`✓ P1–P7, P10–P15`). The label column (SESSION, PR, NOW, NEXT, LATER, DONE, LINKS) is gone: the tree lines and each row's mark (`⎇`, `↗`, `▶`/`▷`, `✓`) say what it is, and every row under a lane gains the 9 columns the labels took. Each running phase is a branch of its own, and the other open phases share one line, `next P18–P25` (ranges, the other plans by name after them). A reported task in other words still finds its plan task, and a lane that reports a task shows no guessed `▷`. The progress column is calmer: no `◐`, the `🥣` cell on a folded lane only from `warn`, and a hidden cell keeps its width, so no bar moves; the checkbox count stands on every lane line. A folded lane's title line in a narrow pane starts in the column of the lane's name, where an open lane's branches start too. A click on a for-you row now also lands right while `now:` lines stand above it.
38
+ - **A lane in the herd shows only the phases its board rows name.** It showed every phase of its plan, so phases another lane had just written stood under the lane's NOW while its own phase waited; the tally (`n/m`, `n/m ph`) counts the named phases too, a sub-phase (`P10c`) belonging to the phase a row names. A board row's range (`P17–P25`) names every phase it spans, where before only its first counted. A phase runs while some of its tasks are ticked and others open, while one of its boxes was ticked in the last 20 minutes, or while an agent reports it; task lines written into a phase, or a new phase without a tick, no longer make it run, and a phase with only its review gate open waits.
39
+ - **The herd's teal is the brand colour.** The teal accents (the working lane's dot, `▶`/`▷`, `↑n`) are exactly `#03B5BD`, as true colour where `COLORTERM` is `truecolor` or `24bit`, and 256-colour 37 elsewhere.
40
+ - **`jh watch` proposes open plan tasks that could run in parallel at a heartbeat** (`parallel tasks <lane>: …`): disjoint paths, none touched or reported by running agents (the coordinator's subagents in the lane's worktree included), extra agents costing less than `watch.parallelTasks.maxTokens` (default 100000, the baseline is the first answer of a session log). One free task beside a running agent counts; a lane with no active work gets no proposal; once per changed situation; nothing starts by itself.
41
+ - **The merge guard no longer asks for an interpreter script whose text merely contains the command words apart** (a path segment `workflow` and a `run` elsewhere): where the program is hidden, the words count only as adjacent whole tokens, with quotes, commas, brackets and gh options between them. An option value that brackets or braces cut into several tokens (`-R "${REPO}"`, `REPOS[0]`, `os.environ["GH_REPO"]`, an f-string) no longer hides the words after it, so those calls ask again.
42
+ - **`jh preview` is hardened.** An image is embedded only when its answer carries a plain `image/<subtype>` type, an image address is escaped before it goes into the page (also the one behind GitHub's image proxy) and read back unescaped before it is fetched, so a badge address with `&` in it fetches the right image, and a local image is read only when it is a regular file whose real path, links followed, lies inside the package. `jh watch` reads the task signals of subagent logs written within the activity window only, and the writes of at most the 20 newest subagent logs of a session.
43
+ - **The herd's arrow follows the task an agent works on.** It stood on the first open task of a phase; now the open task whose words the lane's agent (or a subagent working in its worktree) used most in its last 40 log entries gets the arrow, when it clearly leads (at least 3 of its distinctive words and 40 %); otherwise the first open task, as before.
44
+ - **`jh task start "<text>"` and `jh task done` report the task an agent works on.** One record per agent in `.jackherd/tasks/` (a new `start` replaces the agent's task); the kit skills `/implement` and `/orchestrate` tell every building agent to report. `jh task done` without an open task is silent and exits 0, so a second call is no error; with text that names another task than the open one it exits 1.
45
+ - **The herd's arrow comes from what agents report, in every case.** It reads Claude Code's task list (`TaskCreate`/`TaskUpdate`, `TodoWrite`) from the logs of the sessions and subagents of every worktree and of the coordinator, and the records of `jh task`, and matches them to open plan tasks. Every active task carries its own `▶`, a phase with an active task runs, so a lane may show several active phases; the agent's name stands dim after the title only while more than one agent is active in the lane. A report that matches no open task shows as `now: <text>` under its lane, under the title when no lane fits (also without herdr). A `jh task` record counts only while it is younger than the lane's last tick; agent text is cleaned of control characters. Without any report the word guess stays, drawn as a dim `▷` with a plain title.
46
+ - **The herd's arrow is teal, not yellow.** `▶` on a task is teal with a bold title, as the working lane's dot is; yellow stays for what is blocked or waits on you. The legend (`?`) names `▶` and `▷`.
47
+ - **The open lane's tree names each thing once.** An open lane no longer repeats its phase on the lane line; a folded lane names it compactly, `P3 Search API +1 · 12/20` (`+n` more active phases). The running phases stand by number, never by recency, each with its age, its count and `· gate` while only the review gate is open, without an arrow on the phase row; arrows stand before tasks only, and an agent's name stands dim at the right edge of its task, only while more than one agent is active. An open lane shows per active phase only its active tasks; a click on the phase row shows the other open ones and the next click folds them. Only you change a fold; a new active task adds its own row.
48
+ - **Files sent to you and published artifacts stay in sight.** The new kit hook `sent-file` (PostToolUse on `SendUserFile` and `Artifact`) records each send with time and caption in `.jackherd/sent/`. `jh herd` shows the files as `📎` badges among the link chips of the lane they belong to (linked by their `file:` address; an artifact by its URL), the sends nobody closed wait on you next to the board's rows (top of the herd, heartbeat, status line), and `jh waiting close <id>` (or `--all`) closes them after your answer; `jh waiting` lists them.
49
+ - **A draft for review is published as one Artifact.** `/orchestrate` names the `Artifact` tool: with it, and unless `preview.publish` is `false` in `.jackherd/config.json`, the coordinator publishes the `jh preview` page as a private Artifact and updates the same URL each round; without it, a file card or `jh preview --open`. `jh preview` embeds external images (badges) as data addresses so the page is complete where it may load nothing from outside, and warns once for an image it could not fetch. It fetches only `https` images from public hosts (no loopback, private or link-local address, also after a redirect) and at most 5 MB each.
50
+ - **`jh herd` stays calm.** The lanes keep the order of the board, whatever their states are (the order by urgency is gone; the state shows in the symbol and colour of each line, and what waits on you sits on top). A lane opens by itself only when it first appears; a change of status no longer opens or closes it, so a lane you folded stays folded.
51
+ - **A click on a `📎` row opens it.** In `jh herd` a plain left click on a file or Artifact in the block of what waits on you opens it with the platform's opener (`xdg-open`, `open`); a `?` row opens nothing and a failure shows in the footer. `jh preview --open` shares the opener (`src/terminal/open.ts`).
52
+ - **The herd's lane line names the state only for `blocked`.** The symbol at the row start carries working, idle, done, unknown and no agent (colour unchanged); a blocked lane writes `blocked` in front of its own phase title (no column, so no other row moves). The legend names every symbol; the watcher and the heartbeat keep their words.
53
+ - **Long for-you rows expand by click.** A `📎`/`?` row wider than the pane expands on a click (wrapped over several lines); a question folds on the next click, a file or Artifact opens on it. A row that fits opens its file at once.
54
+ - **The coordinator's hand-over thresholds default to 350 000 / 500 000 tokens** (`plans.context.coordinator`, were 200 000 / 300 000), since a fresh coordinator chat already starts near 200 000; the 60 % / 85 % cap of a smaller window stays. The `statusline.sh` template follows.
55
+ - **`jh preview --open` works on Windows again** through the shared opener (`rundll32 url.dll,FileProtocolHandler`, which hands the target over without a shell).
56
+ - **`jh preview` renders long documents and answers `--help`.** The Markdown went to `gh api /markdown` as an argument and failed with `E2BIG` for a long plan; it goes through standard input now. `jh preview --help` (and `-h`) prints the usage and exits 0.
57
+ - **A question or a waiting agent no longer sinks in the coordinator's pane.** `jh herd` shows a subagent of the coordinator that builds in a worktree as `working` (and as `blocked` while the approval gate holds a request of it), also when the worktree has no row in the board; the row carries the subagent's description and the branch. The approval gate holds a permission request of such a subagent like a lane's, under the name `subagent-<type>-<id>`, so the watcher reports `approval …` instead of the dialog sitting in the coordinator's pane. The heartbeat and each status line name what a resting (`idle`, `done`) lane waits on, from the questions in its report: `a idle: waits on: <first question>, 2 open questions`.
58
+ - **What waits on you stays in sight.** A board section `## Wartet auf dich` (German) or `## Waiting for you` (English), one row `Seit | Punkt | Herkunft | Stand`, lists a preview sent, a question put to you or a report to accept. `jh herd` shows every open row on top as one line per item (a dim `▌`, then `📎 file` or `? question` in bold, `▌ +n` after five), closed by a rule labelled `woof`, and the watcher repeats them in each heartbeat and status until the row is closed in its status cell. `/orchestrate` says when Jack enters and closes a row.
59
+ - **The README is shorter and keeps each point once.** The section "Human on the loop" is gone; what it said sits where it belongs, in the intro (you decide, Jack asks only what the plan does not settle), in "What Jack does on his own, and what waits for you" and in "Guarded commands and merges", which now also names the refusal of a push to the base branch and the limit of the guards. Planning and building are told apart from the parts that need herdr, the quickstart is five bare steps, and the lines on lanes, boards, worktrees, the watcher and the fresh start say what they mean. `jh preview` is in the command list.
60
+ - **The feature icons load from a marked address.** Every icon in the README is `…/assets/icons/<name>.svg?v=2`. GitHub's image proxy keeps an unmarked address for a year, so npm kept showing the 1.8.0 icons, a few pixels too high. A test holds the mark in one place (`assets/icons/version.ts`) and compares the icon files with stored digests, so a changed icon without a new mark turns red.
61
+ - **`jh preview <markdown-file>`** renders a Markdown file through the GitHub API into a page that shows it in GitHub and npm style, light and dark, and at phone width (`--out`, `--open`).
62
+ - **`jh herd` shows a small fix as active.** It listed a lane as "no agent" when the board held a cleaned-up row and a newer open row of the same name, or when a cleaned-up lane had uncommitted changes in its worktree. A newer row without the mark now reopens the lane, and uncommitted changes make it active.
63
+ - **An open lane in `jh herd` keeps its tree.** Its pull requests hang on the tree as `PR`, behind the SESSION line, the chips row is labelled `LINKS`, and a pull request title no longer repeats the lane's ticket key.
64
+
5
65
  ## 1.8.1
6
66
 
7
67
  - **The README reads on npm in a dark browser.** npm wraps every image in a link, so a `<picture>` never switched to its dark source, and npm has no dark theme of its own; a phone in dark mode showed the light logo on black. Every image is now one version that works on white and on black: the logo is the dark one with a light outline around Jack, the letters, the lanes and the nodes (`assets/branding/jackherd-logo-outline.svg`), the terminal diagrams are always the dark ones, and the feature icons are mid-grey and teal. Each of the six points has its icon on the line of the bold title and its text below, so nothing wraps under an icon on a phone or on a desktop and the gaps are equal.
package/INSTALL.md CHANGED
@@ -54,7 +54,7 @@ When `init` creates a new config, it asks:
54
54
  | Use it when | the team shares the kit through the repository | the repository must stay untouched, not even untracked files |
55
55
  | Lives in | the project's `.claude/` | `~/.claude/` |
56
56
  | Skill names | `/plan`, `/implement`, `/orchestrate`, … | `/jh-plan`, `/jh-implement`, `/jh-orchestrate`, … |
57
- | Hooks | `git-guard`, `watch-guard`, `merge-guard`, `approval-gate`, `ask-hint`, `format-on-edit` | none; `init --global` offers only a `SessionStart` update notice |
57
+ | Hooks | `git-guard`, `watch-guard`, `merge-guard`, `approval-gate`, `model-gate`, `model-log`, `ask-hint`, `open-question`, `sent-file`, `format-on-edit` | none; `init --global` offers only a `SessionStart` update notice |
58
58
  | Config | `.jackherd/config.json` | `~/.jackherd/config.json`, used where a repository has none |
59
59
  | Update | `jh sync` | `jh update` |
60
60
 
@@ -69,6 +69,8 @@ bunx jackherd sync # later: updates the kit files
69
69
 
70
70
  `init` writes what it [detected](#detected-per-repository) into the new config, so the project sees it. It asks whether to enter the status line (README, *Status line*) in `.claude/settings.json`; `--yes` or `--no` answer every question without asking.
71
71
 
72
+ **Everyone on the team needs Bun.** The project hooks run as `bun .claude/hooks/…`, and without Bun the guard hooks block the commands they check.
73
+
72
74
  **Name clashes.** A project that already has a skill or agent of a kit name (`implement`, `plan`, …): `init` names the clash and offers the prefix `jh-`, so the kit's copies sit beside yours and call each other, not yours. Any project can set `skillPrefix` in `.jackherd/config.json`; `sync` then renames, and removes the unprefixed kit files you never edited, with the directories they leave empty. A directory that holds a file of yours stays, and `sync` names it.
73
75
 
74
76
  **Your edits survive.** `sync` leaves files you have edited alone. When the kit changed one of them too, its version lands beside yours as `<file>.kit-new`: merge it, or take the kit version with `sync --accept <path>`. A kit file you deleted stays deleted. Project-specific additions go into `.claude/project/<skill>.md` (read first by the skill of that name) or a rule beside `.claude/rules/kit/`, so the kit files stay updatable.
package/README.md CHANGED
@@ -3,35 +3,41 @@
3
3
  <br>
4
4
  </p>
5
5
 
6
- [![npm](https://img.shields.io/npm/v/jackherd)](https://www.npmjs.com/package/jackherd) [![license: MIT](https://img.shields.io/npm/l/jackherd)](https://www.npmjs.com/package/jackherd) [![2 dependencies](https://img.shields.io/badge/dependencies-2-brightgreen)](https://www.npmjs.com/package/jackherd?activeTab=dependencies)<br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd/assets/icons/space.svg">
6
+ [![npm](https://img.shields.io/npm/v/jackherd)](https://www.npmjs.com/package/jackherd) [![license: MIT](https://img.shields.io/npm/l/jackherd)](https://www.npmjs.com/package/jackherd) [![2 dependencies](https://img.shields.io/badge/dependencies-2-brightgreen)](https://www.npmjs.com/package/jackherd?activeTab=dependencies)<br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd/assets/icons/space.svg?v=2">
7
7
 
8
- **Let AI do the work. Stay in control.** Build several features in parallel with Claude Code. Each runs in its own branch; you only answer the questions that need a human. Jack, the coordinator (the Shih Tzu in the logo, who herds anyway), handles the rest. In a project install, hooks hold merges and releases that touch risky paths until you approve, and refuse a push to your base branch.
8
+ # Your agents write code. Jack keeps the work moving.
9
9
 
10
- Install with one command, run `/jh-start` in a repository, and it offers your first plan: [Quickstart](#quickstart).<br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd/assets/icons/space.svg">
10
+ **Let AI do the work. Stay in control.** jackherd orchestrates your coding agents, alone or as a team. You plan once, in your repository; Jack, the coordinator, runs it in parallel lanes.
11
+
12
+ He settles the small questions himself and asks only what needs you. What's running, blocked or waiting for you sits on one screen.
13
+
14
+ For developers who'd rather make the calls than babysit their agents.
15
+
16
+ **We recommend [herdr](https://herdr.dev), a terminal for coding agents:** Jack, the lanes and the watcher run there; without it, one Claude Code session plans and builds, with independent phases as parallel subagents.
17
+
18
+ Install with one command, run `/jh-start` in a repository, and it offers your first plan: [Quickstart](#quickstart).<br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd/assets/icons/space.svg?v=2">
11
19
 
12
20
  <p>
13
21
  <img src="https://unpkg.com/jackherd/docs/workflow-dark.svg" width="720" alt="jackherd in herdr: a lane hits a question, Jack asks you as a choice, you pick, and the lane works on while the herd view counts its progress.">
14
22
  <br>
15
- <sub>Parallel mode in herdr (optional). Planning and building work without it.</sub><br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd/assets/icons/space.svg">
23
+ <sub>Jack and parallel lanes in herdr (recommended).</sub><br><img width="1" height="8" alt="" src="https://unpkg.com/jackherd/assets/icons/space.svg?v=2">
16
24
  </p>
17
25
 
18
- <p><img src="https://unpkg.com/jackherd/assets/icons/plan.svg" width="24" height="34" align="middle" alt=""> <b>Plans live in your repository.</b><br>Markdown phases, a model each, ticked off as they are built.</p>
26
+ <p><img src="https://unpkg.com/jackherd/assets/icons/decide.svg?v=2" width="24" height="34" align="middle" alt=""> <b>You make the calls that matter.</b><br>Jack answers what the plan or a rule already settles and records each answer on the board, where you can check it. The rest reaches you as a short choice. Approve a plan once, and its pull requests merge on green checks, except on paths you marked to always ask.</p>
19
27
 
20
- <p><img src="https://unpkg.com/jackherd/assets/icons/lanes.svg" width="24" height="34" align="middle" alt=""> <b>Lanes stay apart.</b><br>A lane is one phase of a plan in its own git worktree and session, side by side in herdr, the terminal that holds the parallel sessions.</p>
28
+ <p><img src="https://unpkg.com/jackherd/assets/icons/bark.svg?v=2" width="24" height="34" align="middle" alt=""> <b>Jack barks when something moves.</b><br>One view of the whole herd: each lane's progress, pull request and checks, and on top whatever waits for your answer. In herdr it also shows what each agent is doing and every new review comment. You stop hopping between terminals and holding the state in your head.</p>
21
29
 
22
- <p><img src="https://unpkg.com/jackherd/assets/icons/decide.svg" width="24" height="34" align="middle" alt=""> <b>You decide. Jack takes care of the lanes.</b><br>He answers what the plan settles and asks you the rest.</p>
30
+ <p><img src="https://unpkg.com/jackherd/assets/icons/ear.svg?v=2" width="24" height="34" align="middle" alt=""> <b>Jack listens, on GitHub and beyond.</b><br>A review comment, from a teammate or a bot, goes to its lane, which fixes it with a test and answers in the thread; a judgement call comes to you. <code>/jh-follow</code> follows any tool with a CLI or an API, with recipes for Jira, Linear, Sentry and status pages as a head start, and Jack reports changes. Runs in herdr.</p>
23
31
 
24
- <p><img src="https://unpkg.com/jackherd/assets/icons/bark.svg" width="24" height="34" align="middle" alt=""> <b>Jack barks when something moves.</b><br>One live view of the herd, all your lanes: state, pull request, checks, feedback.</p>
32
+ <p><img src="https://unpkg.com/jackherd/assets/icons/lanes.svg?v=2" width="24" height="34" align="middle" alt=""> <b>Parallel where it pays.</b><br>The plan says what each phase writes and waits for, and jackherd works out what can run side by side: independent phases as subagents in one session, bigger ones in a lane of their own in herdr, with its own branch and worktree. Where more could run in parallel at little cost, Jack suggests it. He keeps the merge order and has the others rebase after each merge.</p>
25
33
 
26
- <p><img src="https://unpkg.com/jackherd/assets/icons/ear.svg" width="24" height="34" align="middle" alt=""> <b>Jack listens beyond GitHub.</b><br><code>/jh-follow</code> Jira, Linear, Sentry or a status page. Reports need herdr.</p>
34
+ <p><img src="https://unpkg.com/jackherd/assets/icons/plan.svg?v=2" width="24" height="34" align="middle" alt=""> <b>One workflow, solo or team.</b><br>Plans, boards and Jack's decisions live in your repository, so everyone sees what was planned, what was settled and what comes next, and workflow changes go through your usual review. <code>jh init</code> adds the skills, rules and guard hooks through Claude Code's own project settings.</p>
27
35
 
28
- <p><img src="https://unpkg.com/jackherd/assets/icons/bowl.svg" width="24" height="34" align="middle" alt=""> <b>Long sessions get a fresh start.</b><br>At a phase boundary, a lane whose context is filling up moves to a new chat.</p>
36
+ <p><img src="https://unpkg.com/jackherd/assets/icons/bowl.svg?v=2" width="24" height="34" align="middle" alt=""> <b>Pick up where you left off.</b><br>The ticked-off plan and the board carry the state, not the chat. A lane whose context runs high continues in a fresh chat at the end of its phase; Jack hands himself over the same way.</p>
29
37
 
30
38
  ## Quickstart
31
39
 
32
- Planning and building work without herdr; parallel lanes need it.
33
-
34
- 1. **Install** (Linux and macOS; needs Claude Code and git). It asks a few setup questions and leaves your repositories alone. → [INSTALL.md](https://unpkg.com/jackherd/INSTALL.md)
40
+ 1. **Install** (Linux and macOS; needs Claude Code and git). → [INSTALL.md](https://unpkg.com/jackherd/INSTALL.md)
35
41
 
36
42
  ```bash
37
43
  curl -fsSL https://unpkg.com/jackherd/install.sh | sh
@@ -40,24 +46,24 @@ Planning and building work without herdr; parallel lanes need it.
40
46
  Already in a coding agent? Paste this instead:
41
47
 
42
48
  ```text
43
- Install jackherd by following https://unpkg.com/jackherd/INSTALL.md. Ask me the setup questions it lists; herdr is optional.
49
+ Install jackherd by following https://unpkg.com/jackherd/INSTALL.md. Ask me the setup questions it lists; herdr is recommended, not required.
44
50
  ```
45
- 2. **Start Claude Code in a repository.** It checks the setup and offers your first plan.
51
+ 2. **Start Claude Code in a repository.**
46
52
 
47
53
  ```text
48
54
  /jh-start
49
55
  ```
50
- 3. **Plan.** Phases, tasks and a model for each, written to `docs/plans/`.
56
+ 3. **Create your first plan.** It lands in `docs/plans/`, and for parallel lanes `/jh-plan` offers to write a board.
51
57
 
52
58
  ```text
53
59
  /jh-plan Add product search
54
60
  ```
55
- 4. **Build,** one phase at a time, ticked off in the plan. No herdr needed.
61
+ 4. **Build the first phase.**
56
62
 
57
63
  ```text
58
64
  /jh-implement docs/plans/<plan>.md phase 1
59
65
  ```
60
- 5. **Or let Jack run the herd.** Inside [herdr](https://herdr.dev), one lane per phase, with the live herd view beside him (`jh herd` anywhere else).
66
+ 5. **Run phases in parallel with herdr (recommended).** Lanes, the full herd view, review-comment fixes and ticket reports need it. In Claude Code inside herdr, hand Jack the board:
61
67
 
62
68
  ```text
63
69
  /jh-orchestrate docs/plans/board-<name>/board.md
@@ -65,9 +71,7 @@ Planning and building work without herdr; parallel lanes need it.
65
71
 
66
72
  By hand (Bun 1.3+): `bun add -g jackherd` or `npm install -g jackherd`, then `jh init --global` for yourself, or `jh init` in a repository to give your team the same skills and guard hooks. → [INSTALL.md](https://unpkg.com/jackherd/INSTALL.md)
67
73
 
68
- ## Human on the loop
69
-
70
- You decide every open question, commit and push, once per pull request. Jack answers on his own what the plan already settles, never money, auth, secrets, a migration or a release. Once you've approved a plan and a pull request, he merges it on green checks and tells you in one line. The guards catch mistakes, not an agent set on getting around them; only branch protection stops that. A pull request that touches a workflow, a migration, a lockfile or `package.json` still asks, and so does every release. Prefer to see every merge? Approve per pull request instead.
74
+ ## In detail
71
75
 
72
76
  <details>
73
77
  <summary><b>What Jack does on his own, and what waits for you</b></summary>
@@ -78,36 +82,32 @@ You decide every open question, commit and push, once per pull request. Jack ans
78
82
  | --- | --- | --- |
79
83
  | Starting a ready phase in a lane | Commits, push and pull request, once per pull request | Writing lane code himself |
80
84
  | Answering what the plan or a rule settles, on record in the board | Every other decision a lane raises | Merging a pull request on a path that always asks, without asking you |
81
- | Merging a pull request of an approved plan on green checks | A plan approval, once per plan | Storing a permission on your behalf |
82
- | Rebasing the lanes after a merge | Migrations and writes against a shared environment | |
83
- | Handing a session over to a fresh chat before its context fills up | Closing a lane | |
85
+ | Merging a plan's pull requests on green checks for a while | A standing approval, until a time you pick | Storing a permission on your behalf |
86
+ | Having the lanes rebase after a merge | Migrations and writes against a shared environment | |
87
+ | Handing a lane over to a fresh chat at the end of a phase, once its context runs high | Closing a lane | |
84
88
 
85
89
  </details>
86
90
 
87
91
  <details>
88
92
  <summary><b>Guarded commands and merges</b></summary>
89
93
 
90
- In a project install, the `merge-guard` hook asks you before `gh pr merge`, `gh workflow run`, `gh run rerun` and a `gh api` write that merges, writes a file, dispatches or reruns a workflow, or moves a ref, also behind a chain, a wrapper or `sh -c`. The `git-guard` hook refuses a git command that hides a commit, push, rebase, reset, checkout or merge from your permission rules (`git -C … push`, `sh -c "…"`), and every force push, skipped hook and hard reset.
94
+ A project install adds two hooks to Claude Code's [permission rules](https://code.claude.com/docs/en/permissions):
91
95
 
92
- A merge passes without a question only on an answer from your own dialog: self-merge for that pull request, or the approval of its plan, with green checks and no file on a path that always asks (workflows, migrations, lockfiles, `package.json`, env files, agent instructions, and your own list). `merge.withoutChecks` lets a pull request that only touches such paths as docs merge without waiting for checks.
96
+ - **`merge-guard`** asks before `gh pr merge` and `gh workflow run`, also behind options, a chain or `sh -c`. Calls that only read pass.
97
+ - **`git-guard`** refuses hidden commits and pushes (`git -C … push`), pushes to the base branch, force pushes without lease, skipped hooks and hard resets.
93
98
 
94
- ```json
95
- {
96
- "guard": { "planApproval": { "exceptPaths": ["src/billing/**", "src/auth/**"] } },
97
- "merge": { "withoutChecks": ["docs/**/*.md"] }
98
- }
99
- ```
99
+ `jh sync` also adds ask rules for check reruns and `gh api` writes.
100
100
 
101
- A global install ships no hooks, and the skills ask on their own.
101
+ A merge passes without a question on green checks after self-merge, or under a standing approval: one plan's lanes until a time you pick, at most 24 hours; workflows, migrations, env files and the guards' own files still ask. A pull request whose files all match `merge.withoutChecks`, such as docs only, skips question and checks, unless a file lies on a path that always asks.
102
102
 
103
- </details>
103
+ The guards catch mistakes, not intent; for that, use branch protection. The hooks need Bun; a global install ships none.
104
104
 
105
- ## In detail
105
+ </details>
106
106
 
107
107
  <details>
108
108
  <summary><b>Plans, boards and the skills</b></summary>
109
109
 
110
- A **plan** is Markdown with phases, checkbox tasks, a model and a review gate per phase. A **board** lists the lanes: which phases each one works on, on which model, after what. A **lane** is one agent session in its own git worktree, and **Jack** is the session in the main checkout that runs `/jh-orchestrate`.
110
+ A **plan** is Markdown with phases, checkbox tasks, a model and a review gate per phase. A **board** lists the lanes of one or more plans: which phases each lane builds, on which model, after what. A **lane** is one agent session in its own git worktree (a second checkout of your repository), and **Jack** is the session in the main checkout that runs `/jh-orchestrate` on a board.
111
111
 
112
112
  <img src="https://unpkg.com/jackherd/docs/skills-dark.svg" alt="/jh-grill hands decisions to /jh-plan; /jh-plan feeds /jh-orchestrate or a single /jh-implement; /jh-implement ends in /jh-pre-commit, which runs the reviewers; /jh-diagnose hands a red command to /jh-implement.">
113
113
 
@@ -119,8 +119,8 @@ A **plan** is Markdown with phases, checkbox tasks, a model and a review gate pe
119
119
  | `/jh-implement` | builds and tests one phase and ticks it off; independent phases run as parallel subagents |
120
120
  | `/jh-orchestrate` | runs a board's lanes in herdr, as Jack |
121
121
  | `/jh-pre-commit` | runs `jh check` and the reviewers, proposes the commit message and asks before committing |
122
- | `/jh-follow` | follows a ticket or a status page outside GitHub |
123
- | `/jh-diagnose` | turns a bug into a failing command, then hands the fix on |
122
+ | `/jh-follow` | follows something outside GitHub: a ticket, error logs, a status page |
123
+ | `/jh-diagnose` | turns a bug into a failing command, fixes it with a regression test |
124
124
 
125
125
  The global install names the skills with a `jh-` prefix; a project install uses none, unless the project already has skills of the same names.
126
126
 
@@ -129,51 +129,53 @@ The global install names the skills with a `jh-` prefix; a project install uses
129
129
  <details>
130
130
  <summary><b>Which model runs each phase</b></summary>
131
131
 
132
- Each phase in the plan names its model: the planning model (Opus by default) where a mistake is expensive, such as data, security or a migration, and the cheaper implementation model (Sonnet by default) for everything else. `/jh-implement` and Jack start each phase on its model, and in a project install a hook stops a phase handed to a weaker one. Set the models per role under `models` in the config.
132
+ Each phase in the plan names its model: the planning model (Opus by default) where a mistake is expensive, such as data, security or a migration, and the cheaper implementation model (Sonnet by default) for everything else. `/jh-implement` and Jack start each phase on its model. In a project install, a hook stops a phase's subagent started on a weaker one, and the watcher tells Jack about a lane that runs on one. Set the models per role under `models` in the config.
133
133
 
134
134
  </details>
135
135
 
136
136
  <details>
137
- <summary><b>The watcher and tickets outside GitHub</b></summary>
137
+ <summary><b>The watcher and sources outside GitHub</b></summary>
138
138
 
139
- Jack doesn't watch the terminals himself. `jh watch`, which he starts himself, wakes him when a lane is blocked or done, a check turns red, a pull request gets feedback, a lane's context fills up or a lane waits for an approval; deploys and previews too, when configured.
139
+ Jack doesn't watch the terminals himself. `jh watch`, which he starts, wakes him when a lane is blocked or done, a check turns red, a pull request gets feedback, a lane's context fills up, a lane waits for an approval or works for ten minutes without reporting its task; deploys and previews too, when configured.
140
140
 
141
- `/jh-follow PROJ-123` adds a ticket, an issue or a status page: it checks the tool and its login, shows you a dry run and writes the source to `watch.sources` after your yes. The [recipes](https://unpkg.com/jackherd/recipes/README.md) cover Jira, Linear, GitHub issues and Projects, Sentry and status pages. The reports need herdr; a source can be set up and dry-run without it.
141
+ `/jh-follow PROJ-123` adds anything a command can print as JSON: a ticket, an issue, error logs, a status page. It checks the tool and its login, shows you a dry run and writes the source to `watch.sources` after your yes. A token stays in the environment, read by a small Bun script, never in an argument. Each source runs on its own interval, kept across a restart of the watcher. The [recipes](https://unpkg.com/jackherd/recipes/README.md) cover Jira, Linear, GitHub issues and Projects, Sentry and status pages. The reports need herdr; a source can be set up and dry-run without it.
142
142
 
143
143
  </details>
144
144
 
145
145
  <details>
146
146
  <summary><b>The herd view</b></summary>
147
147
 
148
- `jh herd` shows every lane of a board: agent state, plan progress, pull request, checks and context fill. It only reads.
148
+ `jh herd` shows every lane of a board: plan progress, pull request and checks, and with herdr agent state and context fill. It changes nothing in your repository.
149
+
150
+ On top, **Waiting for you** lists what needs your answer: a file or Artifact sent to you (`📎`) and open questions from the board or a session's dialog (`?`). **Appointments** below it shows the dated rows of the board's appointments section. A click folds either block.
149
151
 
150
152
  ```text
151
153
  🐾 Board 01 11:38
154
+ ▾ Waiting for you · 2 ──────────────────────────────────────────────────────────
155
+ ▌ 📎 search-box-mockup.html
156
+ ▌ ? Ship the fee change before Friday? [ask]
157
+ ▾ Appointments · 1 ─────────────────────────────────────────────────────────────
158
+ ▌ ◷ Mo 09:00 Release 1.4 to production
152
159
  ────────────────────────────────────────────────────────────────────────────────
153
- ▾ ◆ search-ui blocked 🥣 62 % │ ██████░░░░ ◐ 6/9
154
- ⎇ feat/search-ui ↑1 ±4
155
- │
156
- └─ Product search
157
- ├─ 📎 📄 Plan 📡 PROJ-123 · In Progress ✦ Mockup ◈ Search box
158
- │
159
- ├─ ✓ P2 Search box 4/4
160
- ├─ ▸ P3 Docs docs open
161
- │ └─ ▶ Docs updated (README)
162
- └─ ▸ P4 Review 0/2
160
+ ▾ ◆ search-ui blocked ██████░░░░ 6/9
161
+ ├─ Search box docs ⎇ feat/search-ui ↑1 ±4 🥣 62 %
162
+ ├─ 📄 Plan 📡 PROJ-123 · In Progress ✦ Mockup ◈ Search box
163
+ ├─ P3 Docs · 4 min ago · gate 2/3
164
+ │ ▶ Review gate
165
+ ├─ next P4
166
+ └─ ✓ P2
163
167
  ────────────────────────────────────────────────────────────────────────────────
164
- ▸ ◉ checkout-fee done ↗ #42 💬 2 🥣 48 % │ ██████████ ◐ 6/6
168
+ ▸ ◉ checkout-fee ↗ #42 💬 2 ██████████ 6/6
165
169
  ────────────────────────────────────────────────────────────────────────────────
166
- ▾ ● search-index working 🥣 34 % │ ████████░░ ◐ 4/5
167
- ⎇ feat/search-index ↑3 ±2
168
- ↗ #41 … checks 🌐 preview 💬 1 new Search index
169
- │
170
- └─ Product search
171
- └─ ▸ P1 Index 4/5
172
- └─ ▶ /jh-uncle-bob
170
+ ▾ ● search-index ████████░░ 4/5
171
+ ├─ Search index ⎇ feat/search-index ↑3 ±2 🥣 34 %
172
+ ├─ ↗ #41 … checks 🌐 preview 💬 1 new Search index
173
+ └─ P1 Index · just now 4/5
174
+ ▶ /jh-uncle-bob
173
175
  ────────────────────────────────────────────────────────────────────────────────
174
176
  · no agent (1) docs-site 1/3
175
177
  ────────────────────────────────────────────────────────────────────────────────
176
- ↑↓ select →← open a show ticked s html q quit ? help
178
+ ↑↓ select →← open a ticked tasks s html q quit ? help
177
179
  ```
178
180
 
179
181
  </details>
@@ -189,20 +191,29 @@ Jack doesn't watch the terminals himself. `jh watch`, which he starts himself, w
189
191
  | `jh check` | types, lint and tests of what you touched, plus the plan and board checks (`--skip-slow`, `--parallel <plan>`) |
190
192
  | `jh herd` | the live view (`--once`, `--lane <name>`) |
191
193
  | `jh watch` | the watcher Jack runs |
194
+ | `jh lane prompt <lane>` | writes a lane's first prompt from its board row and its plan (`--out`, `--handover`) |
195
+ | `jh lane close <lane>` | removes a finished lane: agent, worktree, herdr workspace and branch, and marks the board; first checks that nothing is lost, and refuses with every reason; `--dry-run` only checks. Claude Code asks before each call |
196
+ | `jh preview <file>` | renders a Markdown file through the GitHub API into a preview in GitHub and npm style |
197
+ | `jh waiting` | the files and Artifacts sent to you that you have not answered yet (`close <id>…` or `close --all` once you have) |
192
198
  | `jh context` | how full an agent's context is, as JSON |
193
199
  | `jh config` | the commands and the base branch the repository uses |
194
200
 
195
- Without a global install, run them as `bunx jackherd <command>`. The config is `.jackherd/config.json` in a project and `~/.jackherd/config.json` globally, checked against [one schema](https://unpkg.com/jackherd/schemas/jackherd.schema.json) your editor completes. What usually needs setting:
201
+ Without a global install, run them as `bunx jackherd <command>`. The config is `.jackherd/config.json` in a project and `~/.jackherd/config.json` globally, checked against [one schema](https://unpkg.com/jackherd/schemas/jackherd.schema.json), which your editor completes in the project config. What usually needs setting:
196
202
 
197
203
  ```json
198
204
  {
199
205
  "responseLanguage": "de",
200
206
  "terminal": { "adapter": "herdr" },
201
207
  "lanes": { "copy": ["apps/web/.env"] },
202
- "check": { "reviewerRoutes": [{ "reviewer": "jh-uncle-bob", "globs": ["src/**/*.ts"], "why": "Code" }] }
208
+ "check": {
209
+ "reviewerRoutes": [{ "reviewer": "jh-uncle-bob", "globs": ["src/**/*.ts"], "why": "Code" }],
210
+ "skillBudgets": { ".claude/skills/release/SKILL.md": 1200 }
211
+ }
203
212
  }
204
213
  ```
205
214
 
215
+ `jh check` counts the words of every skill, agent and always-loaded rule an agent reads, and warns above its budget; `check.skillBudgets` sets your own, by path or glob. `watch.parallelTasks.auto` (`since`, `until`, at most seven days) lets Jack start up to two extra subagents in a running lane without asking, under the cost limit and away from paths that always ask; he switches it on only after asking you.
216
+
206
217
  </details>
207
218
 
208
219
  <details>
@@ -19,9 +19,13 @@ var SELF_MERGE_LABEL = {
19
19
  [PLAN_LANGUAGE.en]: "Approve, and merge it yourself after green checks",
20
20
  [PLAN_LANGUAGE.de]: "Freigeben, und nach gr\xFCnen Checks selbst mergen"
21
21
  };
22
- var PLAN_APPROVAL_LABELS = {
23
- [PLAN_LANGUAGE.en]: { approve: "Approve the plan", revoke: "Revoke the plan approval" },
24
- [PLAN_LANGUAGE.de]: { approve: "Plan freigeben", revoke: "Plan-Freigabe widerrufen" }
22
+ var STANDING_APPROVAL_TEXTS = {
23
+ [PLAN_LANGUAGE.en]: { approve: "Approve standing", until: "until" },
24
+ [PLAN_LANGUAGE.de]: { approve: "Stehend freigeben", until: "bis" }
25
+ };
26
+ var LANE_PROMPT_OPENING = {
27
+ [PLAN_LANGUAGE.en]: "You are the lane",
28
+ [PLAN_LANGUAGE.de]: "Du bist die Spur"
25
29
  };
26
30
  var APPROVAL_REASONS = {
27
31
  pending: "Approval pending with the coordinator; retry the same call once it is approved.",
@@ -45,6 +49,20 @@ var APPOINTMENT_VOCABULARY = {
45
49
  open: ["open"]
46
50
  }
47
51
  };
52
+ var WAITING_VOCABULARY = {
53
+ [PLAN_LANGUAGE.de]: {
54
+ heading: "Wartet auf dich",
55
+ columns: { since: "Seit", item: "Punkt", origin: "Herkunft", status: "Stand" },
56
+ statusAlso: ["Status"],
57
+ open: ["offen"]
58
+ },
59
+ [PLAN_LANGUAGE.en]: {
60
+ heading: "Waiting for you",
61
+ columns: { since: "Since", item: "Item", origin: "Origin", status: "Status" },
62
+ statusAlso: [],
63
+ open: ["open"]
64
+ }
65
+ };
48
66
  var isPlanLanguage = (value) => Object.values(PLAN_LANGUAGE).includes(value);
49
67
  var PLAN_STATUS = {
50
68
  done: "done",
@@ -142,9 +160,11 @@ export {
142
160
  RESPONSE_ADDRESS,
143
161
  ADDRESS_FORM,
144
162
  SELF_MERGE_LABEL,
145
- PLAN_APPROVAL_LABELS,
163
+ STANDING_APPROVAL_TEXTS,
164
+ LANE_PROMPT_OPENING,
146
165
  APPROVAL_TEXTS,
147
166
  APPOINTMENT_VOCABULARY,
167
+ WAITING_VOCABULARY,
148
168
  isPlanLanguage,
149
169
  PLAN_STATUS,
150
170
  PLAN_VOCABULARY,
package/dist/config.d.ts CHANGED
@@ -90,6 +90,9 @@ declare const jackherdConfigSchema: z.ZodObject<{
90
90
  herdr: "herdr";
91
91
  }>>;
92
92
  }, z.core.$strict>>;
93
+ preview: z.ZodPrefault<z.ZodObject<{
94
+ publish: z.ZodDefault<z.ZodBoolean>;
95
+ }, z.core.$strict>>;
93
96
  plans: z.ZodPrefault<z.ZodObject<{
94
97
  fetchIntervalMinutes: z.ZodDefault<z.ZodNumber>;
95
98
  linkKinds: z.ZodDefault<z.ZodArray<z.ZodObject<{
@@ -120,6 +123,14 @@ declare const jackherdConfigSchema: z.ZodObject<{
120
123
  checks: z.ZodPrefault<z.ZodObject<{
121
124
  failedTestPattern: z.ZodDefault<z.ZodString>;
122
125
  }, z.core.$strict>>;
126
+ parallelTasks: z.ZodPrefault<z.ZodObject<{
127
+ maxTokens: z.ZodDefault<z.ZodNumber>;
128
+ auto: z.ZodOptional<z.ZodObject<{
129
+ since: z.ZodISODate;
130
+ until: z.ZodISODate;
131
+ }, z.core.$strict>>;
132
+ }, z.core.$strict>>;
133
+ taskSignalMinutes: z.ZodDefault<z.ZodNumber>;
123
134
  previews: z.ZodOptional<z.ZodObject<{
124
135
  deployments: z.ZodDefault<z.ZodBoolean>;
125
136
  authors: z.ZodDefault<z.ZodArray<z.ZodString>>;
@@ -146,7 +157,7 @@ declare const jackherdConfigSchema: z.ZodObject<{
146
157
  reportOn: z.ZodOptional<z.ZodArray<z.ZodString>>;
147
158
  }, z.core.$strict>>>;
148
159
  }, z.core.$strict>>;
149
- guard: z.ZodPrefault<z.ZodObject<{
160
+ guard: z.ZodPrefault<z.ZodPipe<z.ZodObject<{
150
161
  commands: z.ZodDefault<z.ZodArray<z.ZodString>>;
151
162
  selfMerge: z.ZodPrefault<z.ZodObject<{
152
163
  offer: z.ZodDefault<z.ZodBoolean>;
@@ -155,16 +166,45 @@ declare const jackherdConfigSchema: z.ZodObject<{
155
166
  approvals: z.ZodPrefault<z.ZodObject<{
156
167
  waitMinutes: z.ZodDefault<z.ZodNumber>;
157
168
  }, z.core.$strict>>;
158
- planApproval: z.ZodPrefault<z.ZodObject<{
159
- exceptPaths: z.ZodDefault<z.ZodArray<z.ZodString>>;
169
+ alwaysAsk: z.ZodDefault<z.ZodArray<z.ZodString>>;
170
+ requiredChecks: z.ZodOptional<z.ZodArray<z.ZodString>>;
171
+ planApproval: z.ZodOptional<z.ZodObject<{
172
+ exceptPaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
160
173
  requiredChecks: z.ZodOptional<z.ZodArray<z.ZodString>>;
161
174
  }, z.core.$strict>>;
162
- }, z.core.$strict>>;
175
+ }, z.core.$strict>, z.ZodTransform<{
176
+ requiredChecks?: string[] | undefined;
177
+ alwaysAsk: string[];
178
+ commands: string[];
179
+ selfMerge: {
180
+ offer: boolean;
181
+ approvalMinutes: number;
182
+ };
183
+ approvals: {
184
+ waitMinutes: number;
185
+ };
186
+ }, {
187
+ commands: string[];
188
+ selfMerge: {
189
+ offer: boolean;
190
+ approvalMinutes: number;
191
+ };
192
+ approvals: {
193
+ waitMinutes: number;
194
+ };
195
+ alwaysAsk: string[];
196
+ requiredChecks?: string[] | undefined;
197
+ planApproval?: {
198
+ exceptPaths?: string[] | undefined;
199
+ requiredChecks?: string[] | undefined;
200
+ } | undefined;
201
+ }>>>;
163
202
  merge: z.ZodPrefault<z.ZodObject<{
164
203
  withoutChecks: z.ZodDefault<z.ZodArray<z.ZodString>>;
165
204
  }, z.core.$strict>>;
166
205
  hints: z.ZodPrefault<z.ZodObject<{
167
206
  askUserQuestion: z.ZodDefault<z.ZodBoolean>;
207
+ taskSignal: z.ZodDefault<z.ZodBoolean>;
168
208
  }, z.core.$strict>>;
169
209
  check: z.ZodOptional<z.ZodObject<{
170
210
  lintFilesCommand: z.ZodDefault<z.ZodString>;
@@ -188,6 +228,7 @@ declare const jackherdConfigSchema: z.ZodObject<{
188
228
  exclude: z.ZodDefault<z.ZodArray<z.ZodString>>;
189
229
  reviewer: z.ZodDefault<z.ZodString>;
190
230
  }, z.core.$strict>>;
231
+ skillBudgets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
191
232
  looseTests: z.ZodDefault<z.ZodBoolean>;
192
233
  }, z.core.$strict>>;
193
234
  }, z.core.$strict>;