jackherd 0.0.1 → 1.0.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 (250) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +38 -0
  4. package/README.md +1121 -2
  5. package/assets/branding/README.md +62 -0
  6. package/assets/branding/jackherd-icon-256.png +0 -0
  7. package/assets/branding/jackherd-icon-512.png +0 -0
  8. package/assets/branding/jackherd-icon-64.png +0 -0
  9. package/assets/branding/jackherd-icon-small-32.png +0 -0
  10. package/assets/branding/jackherd-icon-small-64.png +0 -0
  11. package/assets/branding/jackherd-icon-small.svg +1 -0
  12. package/assets/branding/jackherd-icon.svg +1 -0
  13. package/assets/branding/jackherd-logo-1024.png +0 -0
  14. package/assets/branding/jackherd-logo-512.png +0 -0
  15. package/assets/branding/jackherd-logo-dark-1024.png +0 -0
  16. package/assets/branding/jackherd-logo-dark-512.png +0 -0
  17. package/assets/branding/jackherd-logo-dark.svg +1 -0
  18. package/assets/branding/jackherd-logo-mark-1024.png +0 -0
  19. package/assets/branding/jackherd-logo-mark-512.png +0 -0
  20. package/assets/branding/jackherd-logo-mark.svg +1 -0
  21. package/assets/branding/jackherd-logo.svg +1 -0
  22. package/dist/chunk-R6MGHCD7.js +93 -0
  23. package/dist/config.d.ts +167 -0
  24. package/dist/config.js +401 -0
  25. package/dist/plan-format.d.ts +325 -0
  26. package/dist/plan-format.js +636 -0
  27. package/docs/lanes.mmd +9 -0
  28. package/docs/lanes.svg +1 -0
  29. package/docs/skills.mmd +10 -0
  30. package/docs/skills.svg +1 -0
  31. package/docs/workflow.svg +172 -0
  32. package/herdr-plugin/herdr-plugin.toml +22 -0
  33. package/herdr-plugin/open-plans.ts +43 -0
  34. package/herdr-plugin/restore-plans.ts +107 -0
  35. package/install.sh +157 -0
  36. package/kit/hooks/hooks/git-guard/decision.ts +438 -0
  37. package/kit/hooks/hooks/git-guard/index.ts +38 -0
  38. package/kit/hooks/hooks/git-guard/shell.ts +407 -0
  39. package/kit/hooks/hooks/watch-guard/background.ts +36 -0
  40. package/kit/hooks/hooks/watch-guard/decision.ts +53 -0
  41. package/kit/hooks/hooks/watch-guard/index.ts +11 -0
  42. package/kit/hooks/hooks/watch-guard/shell-input.ts +32 -0
  43. package/kit/hooks/hooks/watch-guard/starts.ts +154 -0
  44. package/kit/hooks/hooks/watch-guard/text-fallback.ts +40 -0
  45. package/kit/hooks/hooks.json +30 -0
  46. package/kit/hooks/statusline.sh +72 -0
  47. package/kit/review/agents/devops.md +11 -0
  48. package/kit/review/agents/public-content.md +39 -0
  49. package/kit/review/agents/security-audit.md +11 -0
  50. package/kit/review/agents/uncle-bob.md +11 -0
  51. package/kit/review/skills/devops/SKILL.md +50 -0
  52. package/kit/review/skills/diagnose/SKILL.md +140 -0
  53. package/kit/review/skills/diagnose/references/feedback-loops.md +59 -0
  54. package/kit/review/skills/diagnose/scripts/hitl-loop.template.sh +71 -0
  55. package/kit/review/skills/pre-commit/SKILL.md +100 -0
  56. package/kit/review/skills/review/SKILL.md +43 -0
  57. package/kit/review/skills/security-audit/SKILL.md +65 -0
  58. package/kit/review/skills/uncle-bob/SKILL.md +43 -0
  59. package/kit/rules/rules/kit/arc42.md +89 -0
  60. package/kit/rules/rules/kit/architecture-files.md +87 -0
  61. package/kit/rules/rules/kit/code-style.md +159 -0
  62. package/kit/rules/rules/kit/pull-requests.md +59 -0
  63. package/kit/rules/rules/kit/testing.md +91 -0
  64. package/kit/rules/rules/kit/writing-for-agents.md +110 -0
  65. package/kit/workflow/agents/explore.md +25 -0
  66. package/kit/workflow/agents/implement.md +16 -0
  67. package/kit/workflow/agents/plan.md +13 -0
  68. package/kit/workflow/agents/spec-review.md +96 -0
  69. package/kit/workflow/skills/follow/SKILL.md +48 -0
  70. package/kit/workflow/skills/grill/SKILL.md +60 -0
  71. package/kit/workflow/skills/implement/SKILL.md +107 -0
  72. package/kit/workflow/skills/orchestrate/SKILL.md +565 -0
  73. package/kit/workflow/skills/orchestrate/handover/decision.ts +247 -0
  74. package/kit/workflow/skills/orchestrate/handover/index.ts +171 -0
  75. package/kit/workflow/skills/plan/SKILL.md +118 -0
  76. package/kit/workflow/skills/plan/references/template-English.md +92 -0
  77. package/kit/workflow/skills/plan/references/template-German.md +92 -0
  78. package/kit/workflow/skills/start/SKILL.md +47 -0
  79. package/package.json +63 -5
  80. package/schemas/jackherd.schema.json +601 -0
  81. package/src/check/changes.ts +45 -0
  82. package/src/check/command-line.ts +12 -0
  83. package/src/check/command.ts +136 -0
  84. package/src/check/deferral-arrows.ts +41 -0
  85. package/src/check/execute.ts +29 -0
  86. package/src/check/glob.ts +15 -0
  87. package/src/check/plan-structure-check.ts +135 -0
  88. package/src/check/plan.ts +106 -0
  89. package/src/check/public-content-check.ts +32 -0
  90. package/src/check/public-content-facts.ts +177 -0
  91. package/src/check/public-content.ts +216 -0
  92. package/src/check/report.ts +55 -0
  93. package/src/check/result.ts +42 -0
  94. package/src/check/roots.ts +36 -0
  95. package/src/check/routing.ts +22 -0
  96. package/src/check/schema.ts +83 -0
  97. package/src/check/settings.ts +44 -0
  98. package/src/claude/paths.ts +14 -0
  99. package/src/cli.ts +46 -0
  100. package/src/config/command.ts +45 -0
  101. package/src/config/detect.ts +196 -0
  102. package/src/config/index.ts +2 -0
  103. package/src/config/json-schema.ts +5 -0
  104. package/src/config/legacy-names.ts +56 -0
  105. package/src/config/link-kinds.ts +25 -0
  106. package/src/config/location.ts +46 -0
  107. package/src/config/read-config.ts +42 -0
  108. package/src/config/repository-facts.ts +19 -0
  109. package/src/config/repository-values.ts +46 -0
  110. package/src/config/schema.ts +302 -0
  111. package/src/context/command.ts +39 -0
  112. package/src/context/coordinator-name.ts +16 -0
  113. package/src/context/fill.ts +69 -0
  114. package/src/context/index.ts +10 -0
  115. package/src/context/level.ts +22 -0
  116. package/src/context/options.ts +29 -0
  117. package/src/context/report.ts +42 -0
  118. package/src/context/session-log.ts +91 -0
  119. package/src/plan-format/drift.ts +69 -0
  120. package/src/plan-format/header.ts +27 -0
  121. package/src/plan-format/index.ts +9 -0
  122. package/src/plan-format/lanes.ts +128 -0
  123. package/src/plan-format/markdown.ts +98 -0
  124. package/src/plan-format/phase-tally.ts +55 -0
  125. package/src/plan-format/phases.ts +224 -0
  126. package/src/plan-format/plan-structure.ts +150 -0
  127. package/src/plan-format/progress.ts +202 -0
  128. package/src/plan-format/sprint-document.ts +69 -0
  129. package/src/plan-format/terminal-text.ts +28 -0
  130. package/src/plans/board-choice.ts +60 -0
  131. package/src/plans/board-pick.ts +72 -0
  132. package/src/plans/board-rows.ts +62 -0
  133. package/src/plans/command.ts +60 -0
  134. package/src/plans/ensure-panes.ts +71 -0
  135. package/src/plans/error-text.ts +5 -0
  136. package/src/plans/fetch.ts +96 -0
  137. package/src/plans/git.ts +145 -0
  138. package/src/plans/github.ts +35 -0
  139. package/src/plans/lane-discovery.ts +34 -0
  140. package/src/plans/lane-plans.ts +80 -0
  141. package/src/plans/layout.ts +881 -0
  142. package/src/plans/link-chips.ts +74 -0
  143. package/src/plans/live.ts +336 -0
  144. package/src/plans/markdown-html.ts +140 -0
  145. package/src/plans/options.ts +15 -0
  146. package/src/plans/phase-source.ts +71 -0
  147. package/src/plans/plan-chips.ts +75 -0
  148. package/src/plans/plan-panes.ts +206 -0
  149. package/src/plans/planned.ts +117 -0
  150. package/src/plans/pull-requests.ts +107 -0
  151. package/src/plans/restart-decision.ts +42 -0
  152. package/src/plans/selection.ts +352 -0
  153. package/src/plans/settings.ts +68 -0
  154. package/src/plans/single-flight.ts +25 -0
  155. package/src/plans/snapshot.ts +300 -0
  156. package/src/plans/sprint-export.ts +103 -0
  157. package/src/plans/sprint-html.ts +301 -0
  158. package/src/plans/sprint-page.ts +287 -0
  159. package/src/plans/supervisor.ts +124 -0
  160. package/src/plans/symbols.ts +54 -0
  161. package/src/plans/texts.ts +103 -0
  162. package/src/plans/unlisted-lanes.ts +45 -0
  163. package/src/plans/view.ts +68 -0
  164. package/src/plans/worked-phases.ts +53 -0
  165. package/src/sync/checksum.ts +13 -0
  166. package/src/sync/choice.ts +14 -0
  167. package/src/sync/command-context.ts +113 -0
  168. package/src/sync/command.ts +94 -0
  169. package/src/sync/error-message.ts +1 -0
  170. package/src/sync/gitignore.ts +45 -0
  171. package/src/sync/global-kit.ts +176 -0
  172. package/src/sync/herdr-plugin.ts +175 -0
  173. package/src/sync/if-changed.ts +109 -0
  174. package/src/sync/init-command.ts +239 -0
  175. package/src/sync/init.ts +136 -0
  176. package/src/sync/kit-hooks.ts +18 -0
  177. package/src/sync/kit-path.ts +77 -0
  178. package/src/sync/kit-source.ts +169 -0
  179. package/src/sync/kit.ts +9 -0
  180. package/src/sync/legacy-files.ts +116 -0
  181. package/src/sync/manifest.ts +44 -0
  182. package/src/sync/next-steps.ts +42 -0
  183. package/src/sync/plan-file.ts +154 -0
  184. package/src/sync/plan-hooks.ts +165 -0
  185. package/src/sync/project-fs.ts +132 -0
  186. package/src/sync/render.ts +60 -0
  187. package/src/sync/report.ts +96 -0
  188. package/src/sync/settings-hooks.ts +90 -0
  189. package/src/sync/settings-migration.ts +94 -0
  190. package/src/sync/settings-offer.ts +168 -0
  191. package/src/sync/setup-questions.ts +70 -0
  192. package/src/sync/setup.ts +52 -0
  193. package/src/sync/sync-plan.ts +120 -0
  194. package/src/sync/sync-result.ts +9 -0
  195. package/src/sync/sync.ts +307 -0
  196. package/src/sync/tools.ts +52 -0
  197. package/src/terminal/herdr.ts +91 -0
  198. package/src/terminal/index.ts +13 -0
  199. package/src/terminal/none.ts +7 -0
  200. package/src/terminal/open.ts +39 -0
  201. package/src/terminal/text.ts +159 -0
  202. package/src/terminal/types.ts +30 -0
  203. package/src/terminal/width.ts +90 -0
  204. package/src/update/command.ts +65 -0
  205. package/src/update/package-manager.ts +56 -0
  206. package/src/update/update.ts +105 -0
  207. package/src/version/installed-version.ts +32 -0
  208. package/src/version/release.ts +22 -0
  209. package/src/version/skill-diff.ts +63 -0
  210. package/src/version/started-kit.ts +14 -0
  211. package/src/vocabulary/index.ts +132 -0
  212. package/src/watch/base-tip.ts +18 -0
  213. package/src/watch/command.ts +919 -0
  214. package/src/watch/coordinator-fill.ts +76 -0
  215. package/src/watch/feedback-read.ts +73 -0
  216. package/src/watch/feedback.ts +308 -0
  217. package/src/watch/gh.ts +22 -0
  218. package/src/watch/github-read.ts +175 -0
  219. package/src/watch/herdr.ts +11 -0
  220. package/src/watch/json-guards.ts +9 -0
  221. package/src/watch/kit-update.ts +18 -0
  222. package/src/watch/lane-fill.ts +36 -0
  223. package/src/watch/lane-message.ts +99 -0
  224. package/src/watch/lane-progress.ts +44 -0
  225. package/src/watch/lane-report-file.ts +53 -0
  226. package/src/watch/lane-report.ts +270 -0
  227. package/src/watch/lane-search.ts +41 -0
  228. package/src/watch/lane-sources.ts +46 -0
  229. package/src/watch/lane-watch.ts +121 -0
  230. package/src/watch/monitor-tool.ts +19 -0
  231. package/src/watch/options.ts +79 -0
  232. package/src/watch/plan-badges-read.ts +30 -0
  233. package/src/watch/plan-badges.ts +66 -0
  234. package/src/watch/plan-views.ts +59 -0
  235. package/src/watch/preview-read.ts +60 -0
  236. package/src/watch/previews.ts +234 -0
  237. package/src/watch/pull-requests.ts +117 -0
  238. package/src/watch/single-report.ts +15 -0
  239. package/src/watch/skill-change.ts +61 -0
  240. package/src/watch/source-dry-run-command.ts +35 -0
  241. package/src/watch/source-dry-run.ts +124 -0
  242. package/src/watch/source-fields.ts +9 -0
  243. package/src/watch/source-path.ts +40 -0
  244. package/src/watch/source-run.ts +90 -0
  245. package/src/watch/sources.ts +344 -0
  246. package/src/watch/stream-output.ts +14 -0
  247. package/src/watch/texts.ts +76 -0
  248. package/src/watch/watch-events.ts +399 -0
  249. package/src/watch/watcher-lock.ts +145 -0
  250. package/src/watch/workflow-runs.ts +96 -0
@@ -0,0 +1,59 @@
1
+ # Pull Requests
2
+
3
+ How an agent opens a pull request so every PR reads consistently and is review- and deploy-ready. Applies whenever you run `gh pr create` or edit a PR body.
4
+
5
+ ## Preconditions
6
+
7
+ - **Open a PR only when the user asks.** Same rule as commit and push.
8
+ - **Base = `{{kit.baseBranch}}`** unless the user names another.
9
+ - **Work on a branch.** If the working branch is `{{kit.baseBranch}}`, branch first.
10
+ - **Push before creating, with the user's go-ahead for the push.** The head branch must be on the remote so `gh pr create` has a target.
11
+ - **Check for an existing PR first** (`gh pr view <branch>`). If a prior PR for the same branch is already **merged**, the new one is a continuation — mark it in the title.
12
+
13
+ ## Title
14
+
15
+ Conventional-commit shape, imperative, lower-case summary, no trailing period:
16
+
17
+ ```
18
+ type(scope): short imperative summary
19
+ ```
20
+
21
+ - `type` ∈ `feat | fix | refactor | perf | docs | test | chore | build | ci`. Pick the type of the PR's **dominant** change, not the first commit.
22
+ - `scope` = the primary package, app or service.
23
+ - **Continuation of a merged PR on the same branch:** append `(PART N)`.
24
+
25
+ ## Body structure
26
+
27
+ Fixed sections, in this order. Omit a section only when it has no content — never leave a placeholder.
28
+
29
+ 1. **Context** — one or two lines: link the plan (`{{kit.planDirectory}}/…`), the predecessor PR, or the issue. State which phase or slice this is.
30
+ 2. **Changes** — grouped **by theme**, not commit by commit. Use `###` subheadings or a table when the PR spans several areas. A reviewer must grasp the shape without reading the diff.
31
+ 3. **Verification** — the checks you actually ran, with their numbers, and the review gates with their verdicts. Only checks you ran.
32
+ 4. **Deploy checklist** — required whenever the PR touches **database migrations, secrets, message or mail templates, or a new or changed service**. Order the steps **causally**: database → secrets → templates → services (consumer before publisher) → apps. Use `- [ ]` so it doubles as a runbook. Flag any migration already applied to an environment and which ones still need it.
33
+ 5. **Out of scope / follow-ups** — what was deliberately deferred, so reviewers don't ask.
34
+
35
+ ## Diagrams (Mermaid)
36
+
37
+ Add a fenced ` ```mermaid ` block **when it removes reader effort**:
38
+
39
+ - a **new service** or a multi-hop **data flow** (who reads what, who publishes to whom),
40
+ - a **state machine** or transition set,
41
+ - a **security or replication mechanism** where the failure mode is the point.
42
+
43
+ Keep each diagram to one idea; two small diagrams beat one dense one. Small or single-file PRs need none.
44
+
45
+ ## Review order (large PRs)
46
+
47
+ When a PR spans many files, add a short **suggested review order** — **pure/domain logic first, adapters next, UI and wiring last**. A `| # | Area | Start here | Why first |` table works well.
48
+
49
+ ## Language
50
+
51
+ PR **title and body are English**, whatever language the conversation runs in, so the history reads the same for every reader.
52
+
53
+ ## Anti-patterns
54
+
55
+ - Pasting the raw commit log as the body — group by theme instead.
56
+ - A deploy section out of causal order (a deploy before its migration).
57
+ - Claiming tests or reviews that did not run.
58
+ - Secrets, tokens or full connection strings anywhere in the body.
59
+ - A diagram that restates the title without adding structure.
@@ -0,0 +1,91 @@
1
+ # Testing
2
+
3
+ The kit's core. The project's own rules beside `.claude/rules/kit/` add how this project verifies in a browser, which fixtures exist and which environments a test may touch.
4
+
5
+ All new or changed code **must** have tests.
6
+
7
+ ## Runner & File Placement
8
+
9
+ | Setting | Value |
10
+ | ------------ | ---------------------------------------------- |
11
+ | Runner | `{{kit.command.test}}` |
12
+ | File naming | `*.test.ts` co-located next to the source file |
13
+ | E2E runner | Playwright |
14
+
15
+ ### `EMFILE` / `ProcessFdQuotaExceeded` while dev servers run
16
+
17
+ With watch processes active, `bun test` from the **workspace root** can fail before running a single test with `EMFILE` / `ProcessFdQuotaExceeded` (`Cannot read file ".../tsconfig.json": EMFILE`). The watchers exhaust the kernel's global descriptor table, so Bun cannot open its config. **This is an environment condition, not a test failure** — the run reports `0 pass / 1 error`. Raising `ulimit -n` does not help; the exhaustion is system-wide.
18
+
19
+ **Workaround: `cd` into the package or module directory and run the tests there.** From a narrow directory Bun scans only that subtree. Leave the user's dev servers running; for a full-suite run that genuinely needs the root, stop them with the user's consent.
20
+
21
+ ### Run from the package root, not below it
22
+
23
+ Bun resolves `tsconfig.json` from the **working directory**, and that is where it reads `jsxImportSource`. Descend below a package root and any `.tsx` a test pulls in compiles against React's JSX runtime. The failure does not name JSX:
24
+
25
+ ```
26
+ error: Cannot find module 'react/jsx-dev-runtime' from '.../components/area-chart/index.tsx'
27
+ ```
28
+
29
+ **Read the failure before calling it a broken test.** It arrives as an "unhandled error between tests" with a module-resolution message, so it reads like a missing dependency in code nobody touched. Re-run from the package root first. Re-running the same wrong invocation with the changes stashed reproduces it identically and proves nothing.
30
+
31
+ ## What to Test (decision tree)
32
+
33
+ ```
34
+ Does it compute money, an identifier, or a state transition?
35
+ → YES: test first — write it, run it, see it red, then implement. Then 100% coverage.
36
+ → NO: ↓
37
+
38
+ Is it a pure function or utility?
39
+ → YES: 100% coverage. Test every branch.
40
+ → NO: ↓
41
+
42
+ Is it a bug fix?
43
+ → YES: Write a regression test that fails without the fix.
44
+ → NO: ↓
45
+
46
+ Is it new business logic (use-case, handler)?
47
+ → YES: Minimum 80% coverage. Test happy path + error paths.
48
+ → NO: ↓
49
+
50
+ Is it an adapter or integration?
51
+ → YES: Test error paths and edge cases.
52
+ → NO: ↓
53
+
54
+ Is it a new user-facing feature?
55
+ → Add an E2E placeholder ticket. Implement when explicitly requested.
56
+ ```
57
+
58
+ ### Test-first: money, identifiers, state
59
+
60
+ The coverage target is the same either way. The **order** is what buys something: a test that has to pass before the code exists cannot be satisfied by logic buried inside a server function with a database call in it. Writing it first forces a seam — the random values or the clock arrive as an argument, so the logic is a pure function a unit test reaches directly. See `code-style.md` → Generated identifiers carry entropy, never a clock.
61
+
62
+ ## Test Priority Order
63
+
64
+ Write tests in this order — stop when coverage expectations are met:
65
+
66
+ 1. **Unit tests** — pure functions, validators, mappers
67
+ 2. **Integration tests** — service interactions, database operations
68
+ 3. **E2E tests** — user flows via Playwright (only when requested)
69
+
70
+ ## `mock.module()` replaces a module for the whole file
71
+
72
+ `mock.module()` replaces the module **globally for the entire test file** — every import, including transitive ones.
73
+
74
+ **Mock only the lowest-level dependency** (adapters, repositories). The use-case logic still runs; only I/O is stubbed. Mocking an intermediate module (a use-case in a handler test) breaks every other test in that file that imports it.
75
+
76
+ ```typescript
77
+ // ✅ Mock only the adapter
78
+ mock.module('../adapters', () => ({
79
+ auditRepo: { insert: mock(() => Promise.resolve()) },
80
+ }))
81
+ ```
82
+
83
+ ## Before every commit
84
+
85
+ `/pre-commit` runs `bunx jackherd check`, which measures types, lint, tests, staged build artifacts and the project's own checks. Beyond that, the judgement points:
86
+
87
+ 1. No unused imports left over from refactoring
88
+ 2. Version bumped if the change affects a published package (minor = feature, patch = fix)
89
+ 3. Code follows the order types → pure functions → higher-order functions, without section-label comments
90
+ 4. The design review in `code-style.md` passed
91
+ 5. No dead code: unused exports, unreachable branches, commented-out code removed from every changed file
@@ -0,0 +1,110 @@
1
+ ---
2
+ paths:
3
+ - ".claude/rules/**"
4
+ - ".claude/skills/**"
5
+ - ".claude/agents/**"
6
+ - ".claude/project/**"
7
+ - "CLAUDE.md"
8
+ ---
9
+
10
+ <!--
11
+ Adapted from https://github.com/mattpocock/skills (skills/productivity/writing-for-agents),
12
+ commit 8b78b53, MIT License, Copyright (c) 2026 Matt Pocock. See NOTICE in jackherd.
13
+ The levers are his; the kit mechanics and the worked examples are the kit's.
14
+ -->
15
+
16
+ # Writing for Agents
17
+
18
+ Applies to every document an agent reads: a rule, a skill, an agent, a project supplement, `CLAUDE.md`. The packaging differs, the writing does not. The goal is a **predictable process** — the agent taking the same route every run — not identical output.
19
+
20
+ ## Where documents live
21
+
22
+ | You are writing | It loads | Its pointer is |
23
+ | --------------- | -------- | -------------- |
24
+ | `.claude/rules/**/*.md` with `paths:` | when a file matching one of the globs is touched | the `paths:` globs |
25
+ | `.claude/rules/**/*.md` without `paths:` | **every session, unconditionally** | none — it always loads |
26
+ | `.claude/skills/<name>/SKILL.md` | when the model invokes it, or the user types `/name` | the `description` |
27
+ | … with `disable-model-invocation: true` | only when the user types `/name` | none — the `description` is a listing label |
28
+ | `.claude/agents/<name>.md` | when an orchestrator dispatches it | the `description` plus the reviewer routes in `.jackherd/config.json` |
29
+ | `.claude/project/<skill>.md` | when the kit skill of that name runs; it reads the file first | the skill's first instruction |
30
+ | `CLAUDE.md` | **every turn, always** | none — it is the root |
31
+
32
+ ## Kit files and project files
33
+
34
+ Files that came from `jackherd` are listed in `.jackherd/lock.json` and are updated by `jh sync`. A local edit to one survives the next sync — the new kit version lands beside it as `<file>.kit-new` — but every later kit change then has to be merged by hand.
35
+
36
+ **Put project knowledge into project files instead:** a project rule beside `.claude/rules/kit/`, or a supplement in `.claude/project/<skill>.md` for a kit skill. The kit file stays untouched and keeps updating cleanly, and the project layer stays visibly the project's.
37
+
38
+ ## Where a skill and an agent share a name
39
+
40
+ Several reviewers exist in both forms, because a human types `/uncle-bob` and `/pre-commit` dispatches `uncle-bob`. Two files, one behaviour, and nothing compares them: a drift bug with a delay fuse. Copies maintained at different times drift apart even when nobody changes a rule twice — one keeps a check the other lost, one loses the model gate the other carries.
41
+
42
+ **The `SKILL.md` holds the content. The agent file is a pointer to it** and carries only what is genuinely agent-shaped: the `model`, the `tools` grant, and whatever changes because the run is dispatched rather than typed. A dispatched agent reads the skill as its first action, so both entry points execute the same document.
43
+
44
+ The direction matters. Point the other way and the human path returns a subagent's report, which the caller has to relay; this way the typed command loads the full text inline and the dispatched run reaches the same text through one `Read`.
45
+
46
+ Agents dispatched only, never typed (`explore`, `spec-review`), stay whole files.
47
+
48
+ `CLAUDE.md` is the one document with no pointer of its own, so every line costs on every turn forever. Put a line there only when it must be true before the agent knows what it is working on. Everything else gets `paths:`.
49
+
50
+ A rule **without** `paths:` is the same always-on cost as `CLAUDE.md`, just filed elsewhere. Rules that bind regardless of which file is open earn it (code style, testing, pull requests); any other needs a real argument, not a preference.
51
+
52
+ ## Context pointers
53
+
54
+ A **context pointer** names material that is out of context and encodes the condition for reaching it: a skill `description`, a `paths:` glob, a line in `CLAUDE.md` naming a doc. **The pointer's wording, not its target, decides whether the material is reached.** Good material behind a weak pointer is a variance bug — sharpen the wording first, inline the material only if sharpening fails.
55
+
56
+ - **Front-load the trigger.** The pointer does its work in the first few words.
57
+ - **One trigger per branch.** Synonyms renaming one branch are that branch written twice.
58
+ - **Cut what the body already carries.** A pointer says when to come, not what is inside.
59
+ - **Every trigger names something its loader can honour.** A skill with `disable-model-invocation: true` describes what it is for, since the user picks it; a `paths:` list names globs the repository actually has. Check both against reality — a trigger nothing can fire is a line paid for on every load and never earned back.
60
+
61
+ ## The two loads
62
+
63
+ Every document spends one of two budgets:
64
+
65
+ - **Context load** — always-loaded material on the window: a `CLAUDE.md` line, a description, anything present whether or not it fires.
66
+ - **Cognitive load** — the cost on the human: which documents exist and when to reach for which. Not a cost to minimise. It is the price of human agency; spend it where judgement matters, remove it where it does not.
67
+
68
+ Material behind a pointer escapes context load at the price of the pointer's own line. Material with no pointer rides entirely on cognitive load.
69
+
70
+ ## Information hierarchy
71
+
72
+ Documents are built from **steps** (ordered actions) and **reference** (facts consulted on demand), and they mix freely. The decision is where each piece sits:
73
+
74
+ 1. **In-file step** — what the agent does, in order.
75
+ 2. **In-file reference** — consulted on demand. A flat peer set is fine: every rule of a review on one rung is the right arrangement.
76
+ 3. **Disclosed reference** — a separate file behind a pointer, loaded only when the pointer fires.
77
+
78
+ **Progressive disclosure** is the move down that ladder. The test is branching: inline what every branch needs, disclose what only some branches reach. `/diagnose` is the worked example — the six phases are steps every run takes, the loop recipes are in `references/feedback-loops.md` because a browser bug reaches one recipe and a service bug another.
79
+
80
+ Reference that should be disclosed but is not **buries the steps**, and attending to them becomes a coin flip. That is a variance lever, not just a legibility one.
81
+
82
+ **Sprawl** is the failure mode: a document simply too long, even when every line is live. Attention thins across the excess. The cure is the ladder, plus splitting by branch or sequence so each path carries only what it needs.
83
+
84
+ **Co-location** decides what sits beside a piece once its rung is fixed: keep a concept's definition, rules and caveats under one heading rather than scattered. Scattering fragments one meaning across many places; duplication repeats one meaning in two. Both are bugs, with different fixes.
85
+
86
+ ## Completion criteria
87
+
88
+ Every step ends on a condition telling the agent it is done. Two properties make it a lever:
89
+
90
+ - **Clarity** — can the agent tell done from not-done? A vague bound ("understanding reached") invites **premature completion**, the pull of the visible later steps overrunning the current one. Sharpen the bound first; only if it is irreducibly fuzzy *and* you observe the rush, split the sequence so the later steps are out of view — and that only works across a real context boundary, a hand-off or a subagent, never an inline call.
91
+ - **Demand** — how much it requires. "Every changed model accounted for" forces work that "produce a change list" does not. Demand is not step-bound: "every rule applied" binds a flat body of reference the same way.
92
+
93
+ `/diagnose` Phase 1 is the pattern: four checkable properties and a named command that must already have run. Compare "build a good repro" — same intent, no bound, no resistance.
94
+
95
+ ## Leading words
96
+
97
+ A **leading word** is a compact concept the model already holds from pretraining, repeated as a token and never as a sentence: *tight*, *red*, *frontier*, *fog of war*. It accumulates a distributed definition and anchors a region of behaviour in very few tokens. Coining your own works if you define it, but a made-up word recruits no priors — you pay in definition tokens what a pretrained word gives free.
98
+
99
+ It anchors twice: in the body the agent reaches for the same behaviour every time the word appears; in a pointer, shared language between your prompts and your docs makes the material easier to reach.
100
+
101
+ Hunt for passages that collapse into one token. "Fast, deterministic, low-overhead" becomes *tight*. "A loop you believe in" becomes *red* — a fuzzy gate turned into a binary observable state.
102
+
103
+ **Negation is the failure mode beside this lever.** Steering by prohibition drags the forbidden behaviour into context and makes it *more* available. Prompt the **positive**: state the target so the banned behaviour is never spoken. A prohibition earns its place only as a hard guardrail you cannot phrase positively — and even then, pair it with the positive target.
104
+
105
+ ## Pruning
106
+
107
+ - **One meaning, one place.** Changing a behaviour should be a one-place edit. Duplication costs maintenance and tokens and inflates a meaning's apparent rank.
108
+ - **The environment is a source of truth too.** `package.json` scripts, config files, the directory layout, `--help` output. A document restating them is a **cache**, and a cache earns its load only when the lookup is expensive. Cache the unwritten convention, the reason behind a choice, the gotcha no config confesses. Leave one-command lookups to the environment, where they cannot go stale.
109
+ - **Check every line for relevance.** A line loses it by never bearing on the task, or by going stale as the world it describes changes. Without pruning the default fate is **sediment**: layers that settle because adding feels safe and removing feels risky.
110
+ - **Hunt no-ops.** Does this sentence change behaviour versus the default? The test is model-relative, not reader-relative — two people disagreeing about a no-op disagree about the default, and settle it by running the document, not by arguing. When a sentence fails, delete the sentence rather than trim its words. The test also grades leading words: a word too weak to beat the default is a no-op, and the fix is a stronger word, not a different technique.
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: explore
3
+ description: 'Fast read-only codebase exploration and Q&A. Use when: searching for code patterns, understanding architecture, finding file locations, tracing dependencies, answering "where is X?" questions.'
4
+ model: {{kit.model.explore}}
5
+ tools: Read, Grep, Glob
6
+ user-invocable: false
7
+ ---
8
+
9
+ You are a fast, focused codebase explorer. You find and summarise; the files stay exactly as they are.
10
+
11
+ ## Approach
12
+
13
+ 1. Search with `Grep` and `Glob` to locate the relevant code.
14
+ 2. Read the key files to understand the patterns.
15
+ 3. Return a concise, structured answer with file paths and line references.
16
+
17
+ Suggest changes only when the prompt asks for them.
18
+
19
+ ## Output Format
20
+
21
+ A brief structured report:
22
+
23
+ - File locations, with line numbers where relevant
24
+ - Key patterns or conventions observed
25
+ - Relevant code snippets, kept short
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: implement
3
+ description: 'Implementer — explore, build, test, commit. Use when: building new features, refactoring, fixing bugs, adding components. Searches for existing code before writing new code, writes tests, runs pre-commit.'
4
+ model: {{kit.model.implement}}
5
+ user-invocable: false
6
+ ---
7
+
8
+ Read [`.claude/skills/implement/SKILL.md`](../skills/implement/SKILL.md) and follow it. It carries the golden rules, the explore/implement/verify/test sequence, the plan hygiene and the review-gate binding, and it is the single source of truth for all of them — this file only fixes the default model and states what changes when the process runs as a dispatched subagent rather than in the chat.
9
+
10
+ **Skip Step 0 and Step 0b, the model and parallel gates.** The caller read the plan's tables, set your model and chose which phases run beside yours. Applying them a second time would dispatch subagents inside this one.
11
+
12
+ **When the prompt names a write set, edit only inside it and leave the plan document to the caller.** Other phases run in the same checkout at the same time; the caller ticks the plan and walks the gates from your report.
13
+
14
+ **You have no channel to the user.** Everywhere the skill puts a question to them — the arc42 check, the `ARCHITECTURE.md` check, the commit confirmation in `/pre-commit` — carry the work up to that point, leave it uncommitted, and return the open questions in your final report. The caller has the channel and asks on your behalf. A commit is the user's decision and stays theirs even when the work was delegated.
15
+
16
+ Everything else in the skill applies unchanged, including the plan hygiene when you run alone (no write set in the prompt): tick a task off in the plan document the moment it is done, and treat the phase's review gate as binding.
@@ -0,0 +1,13 @@
1
+ ---
2
+ name: plan
3
+ description: 'Create structured concept/plan documents for {{kit.planDirectory}}/. Use when planning new features or architectural changes.'
4
+ model: {{kit.model.plan}}
5
+ tools: Read, Grep, Glob, Write, Edit
6
+ user-invocable: false
7
+ ---
8
+
9
+ Read [`.claude/skills/plan/SKILL.md`](../skills/plan/SKILL.md) and follow it. It carries the pre-scan, the document template with its verbatim headings, the model table, the review-gate block and the quality checks, and it is the single source of truth for all of them — this file only fixes the model and the tool grant, and states what changes when the process runs as a dispatched subagent rather than in the chat.
10
+
11
+ The headings are verbatim for a reason: the plan parser, `/implement` and `spec-review` find `## {{kit.heading.decisions}}` and `## {{kit.heading.documentation}}` by those exact names.
12
+
13
+ **You have no channel to the user.** Where the skill asks them something — the `/grill` recommendation in step 0, the arc42 check and the `ARCHITECTURE.md` check after the document exists — write the plan as far as it goes and return the open questions in your final report. The caller has the channel and asks on your behalf. Decisions you could not get answered belong in the plan as open questions; the `## {{kit.heading.decisions}}` table holds only answered ones.
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: spec-review
3
+ description: 'Spec Review: does the diff implement what the originating plan in {{kit.planDirectory}}/ asked for? Checks for missing requirements, scope creep, requirements implemented wrongly, and a plan retro-fitted to the code. Use when: reviewing a branch, a commit, or staged changes that belong to a plan document.'
4
+ model: {{kit.model.review}}
5
+ tools: Read, Grep, Glob, Bash
6
+ user-invocable: false
7
+ ---
8
+
9
+ <!--
10
+ The two-axis idea (Standards vs. Spec) is adapted from
11
+ https://github.com/mattpocock/skills (skills/engineering/code-review), commit 8b78b53,
12
+ MIT License, Copyright (c) 2026 Matt Pocock. See NOTICE in jackherd. Only the Spec
13
+ axis is used here — the Standards axis is covered by /review and /uncle-bob.
14
+ -->
15
+
16
+ If `.claude/project/spec-review.md` exists, read it first. It extends this agent for this project and wins where the two disagree.
17
+
18
+ You review **one axis only: does the change do what was asked?** Whether the code is well written is `/review`'s and `/uncle-bob`'s job; your report stays on the spec axis. The two axes stay separate so neither masks the other: code can follow every convention and still implement the wrong thing.
19
+
20
+ You receive a git diff and a commit list. Your `git` access is **read-only** — `show`, `log`, `diff`, `rev-parse`.
21
+
22
+ ## 1. Find the plan
23
+
24
+ In this order, stop at the first hit:
25
+
26
+ 1. A path the caller passed as an argument.
27
+ 2. **A `{{kit.planDirectory}}/**` file in the diff itself.** `/implement` ticks tasks off in the same commit as the work, so a changed plan is the strongest and cheapest signal there is.
28
+ 3. A plan path named in a commit message.
29
+ 4. A document under `{{kit.planDirectory}}/**` whose title or `**{{kit.heading.scope}}:**` line matches the changed paths or the branch name, sub-directories included.
30
+
31
+ **Found nothing? Report `N/A — no plan document found`, name where you looked, and stop.** A review against an inferred intent produces findings nobody can act on.
32
+
33
+ ## 2. Read the plan as it stood BEFORE the change
34
+
35
+ The plan is usually **inside the diff you are reviewing**. The worktree version is the one the author already reconciled with their own code — every box ticked, every unplanned piece of work written in after the fact. Against that document, scope creep is invisible by construction.
36
+
37
+ So read the plan **at its pre-image**:
38
+
39
+ ```bash
40
+ git show <first-commit-under-review>~1:<plan-path> # for a commit range
41
+ git show HEAD:<plan-path> # for staged / uncommitted work
42
+ ```
43
+
44
+ That version is the requirement list. The worktree version is a **claim about the work**, and the difference between the two is itself reviewable:
45
+
46
+ - Tasks flipped `[ ]` → `[x]` — is each one actually in the diff?
47
+ - Task lines **added** in this change — work the plan did not ask for, written in afterwards. Report it as scope creep even though the current plan text now covers it.
48
+ - Statements added about the code ("fixed", "taken over") — check them against the diff. A plan that claims a fix the diff does not contain is a wrongly-implemented finding.
49
+
50
+ If the pre-image does not exist (the plan was created in this very change), say so: the plan is a record, not a specification, and drift checks do not apply.
51
+
52
+ ## 3. Read the requirements
53
+
54
+ Four places carry them:
55
+
56
+ - **`## {{kit.heading.implementation}}` → the phase you are reviewing.** It opens with the model table and holds one sub-section per phase. Find the phase the diff belongs to and take its checkboxes as the requirements. `[ ]` open, `[x]` done, `[~]` partially done.
57
+ - **The phase's review gate block.** This is where tests and verifications live; it also carries the admissions: an item left open with a written reason, a verification deferred with the user's consent.
58
+ - **`## {{kit.heading.decisions}}`** — the table holds the global decisions. **Phase-specific decisions often sit inline in the phase's own checklist** and never appear in the table. Read both.
59
+ - **`**{{kit.heading.scope}}:**`** in the header — the path list you quote when reporting scope creep.
60
+
61
+ ## 4. Report
62
+
63
+ Categories, most severe first. Every finding names its evidence: a quoted plan line, or the scope line for creep.
64
+
65
+ - **Missing / incomplete** — the plan asks for it, the diff does not deliver it (or only partly).
66
+ - **Implemented wrongly** — the requirement looks implemented, but misses what the plan meant. Quote the plan and the hunk.
67
+ - **Plan drift** — the plan's claim and the diff disagree: a box ticked without the work, work without a box, or a written statement the code does not support.
68
+ - **Not asked for (scope creep)** — the diff does something outside the scope and outside the phase's list. This is a finding even when the code is good.
69
+
70
+ Five rules that keep the report honest:
71
+
72
+ - **A range that does not end at `HEAD` needs a staleness check.** `git log <range-end>..HEAD -- <file>` tells you whether a later commit already fixed the finding; drop it or report it as resolved, naming the commit.
73
+ - **Say what was delivered.** Open with one or two sentences naming the requirements the diff does satisfy.
74
+ - **A line the plan itself marks "not planned" is still reported** under scope creep, noting that the plan admits it. The user decides whether it stays.
75
+ - **Generated files are not scope creep.** Files a generator owns (`check.generatorOwned` in `.jackherd/config.json`, or files the project supplement names) land in the diff without the author touching them — **unless** the generated file appears without the source it was derived from, which is a real finding. Files under `.claude/` are hand-edited sources and are reviewed like any other.
76
+ - **A deliberately open gate item is not a defect.** Where the plan documents why an item stays open and the user agreed, list it under the verdict, not as a finding.
77
+
78
+ ## Output Format
79
+
80
+ Write the report in {{kit.responseLanguage}}.
81
+
82
+ ```
83
+ ### Spec: PASS / PASS WITH NOTES / FAIL / N/A
84
+
85
+ Plan: <path> — {{kit.heading.phase}} <n> (pre-image: <ref>)
86
+ Delivered: <one or two sentences on what the diff does satisfy>
87
+
88
+ [CATEGORY] <one sentence>
89
+ Plan: "<quoted plan line, or the scope line for creep>"
90
+ Diff: <file:line or hunk>
91
+ → <what is missing or wrong>
92
+
93
+ Open: <gate items deliberately left open, with the plan's reason>
94
+ ```
95
+
96
+ Verdict: **FAIL** when a required item is missing or a decision was contradicted. **PASS WITH NOTES** for scope creep, plan drift, or an open gate item alone. **PASS** when the phase is delivered as written. Keep the report under 400 words — it is aggregated with the other reviewers. Where a plan line is too long to quote whole, quote the clause that carries the requirement.
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: follow
3
+ description: 'Have the watcher report changes of something outside GitHub (a ticket, an issue, an error, a status page): pick a recipe, check the tool and its login read only, dry-run the source, write it to `watch.sources` after approval. Use when the user asks to follow or be told about such an item, e.g. "/follow PROJ-123".'
4
+ argument-hint: 'What to follow, e.g. a ticket key, an issue or a query'
5
+ ---
6
+
7
+ If `.claude/project/follow.md` exists, read it first. It extends this skill for this project and wins where the two disagree.
8
+
9
+ You add one entry to `watch.sources`, so that `jh watch` reports a new or changed entry of an external service as `=== source <name> …`. You run only reading commands; the one file you write is the project's `.jackherd/config.json` in the main checkout, and only after the user approved the entry. How sources work, their fields and limits: the kit's README, section **Source reports** and **Recipes**, in the installed package (`"$(dirname "$(readlink -f "$(command -v jh)")")/../README.md"`). Read those two sections; do not copy a recipe from memory.
10
+
11
+ ## 1. Ask
12
+
13
+ One `AskUserQuestion` round in {{kit.responseLanguage}}, only for what the argument and the conversation leave open, each with the recommended option first:
14
+
15
+ - **Service:** the recipes the README lists, and "another command that prints JSON".
16
+ - **What to follow:** the item the argument names (its comments, recommended) or a query over several items.
17
+ - **Lane:** the lane the reports name, from the board's lanes table, or none.
18
+ - **What reports:** a change of what the user reads (title, body, the latest comment; recommended), or a change of named fields such as a status (`reportOn` with those fields, mapped in `map`).
19
+ - **Own changes:** ignore the user's own account on that service (`ignoreAuthors`, needs an author in the map), or report everything.
20
+
21
+ ## 2. Check, read only
22
+
23
+ - The tool: `command -v <tool>` for the recipe's program (`curl`, the service's CLI).
24
+ - The login: the tool's own status command where it has one. For a token in an environment variable only whether it is set: `test -n "$<VARIABLE>" && echo set || echo missing`. Never print, echo or pass on a token's value, and never read a file that holds one.
25
+
26
+ Anything missing goes to the user as the command to run themselves (`! <command>`); wait until they did, then check again.
27
+
28
+ ## 3. Fill and dry-run
29
+
30
+ Before filling, read the help of the installed CLI version for every command the recipe calls (`acli jira workitem search --help` and `workitem view --help`, `gh issue list --help`) and confirm that the fields and options the entry needs exist there. Read the provider's web documentation only when the help leaves it open or no recipe fits. A recipe is a starting point; the installed version decides.
31
+
32
+ Fill the recipe with the item or query and the answers from step 1: a `name` of letters, digits, `.`, `_` and `-` that says what is followed, `lane` and `ignoreAuthors` where chosen. A recipe that needs a script (a token handed on stdin, or one call per item): write it to the scratchpad first, never into the repository before step 4.
33
+
34
+ Write the entry as one JSON object to a draft file in the scratchpad and run, from the main checkout:
35
+
36
+ ```bash
37
+ jh watch source <draft.json> --dry-run
38
+ ```
39
+
40
+ It runs the command once and shows the entries and the report the watcher would print, without touching the watcher's state. Exit code 1 means the run failed or a `map` field is empty in every entry (`map.<field>: in … entries empty (<path>)`): never write such an entry, correct the path or drop the field. When the run fails or the entries look wrong, run it again with `--raw` to see the command's output, correct `items` or a path of `map`, and try again; after two failed corrections, show the user the reason and the output's first lines and ask how to go on. Show the user the dry run's list and report, not the raw output.
41
+
42
+ ## 4. Write after approval
43
+
44
+ Ask through `AskUserQuestion`: write the entry (recommended), change it, or drop it. Say in the question that the source runs for everyone who starts the watcher in this repository, and that the watcher cannot keep a command from writing, so the command only reads.
45
+
46
+ On approval add the entry to `watch.sources` in `.jackherd/config.json` of the main checkout (create the array if missing), and a script from step 3 under the path the entry names. Then run `jh config`, which fails on an invalid config, and `jh watch source <name> --dry-run` once more against the written entry.
47
+
48
+ End with one line: the watcher takes the source over at its next start, so a running watcher (the coordinator's stream) has to be started again. The new file and the changed config are part of the repository and follow its commit rules.
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: grill
3
+ description: 'Interrogate a loose idea in rounds until the decisions are settled — the clarification step before /plan. Invoked by the user when they want an idea stress-tested.'
4
+ disable-model-invocation: true
5
+ argument-hint: 'Describe the idea, feature or change you want stress-tested'
6
+ ---
7
+
8
+ <!--
9
+ Adapted from https://github.com/mattpocock/skills (skills/productivity/grilling),
10
+ commit 8b78b53, MIT License, Copyright (c) 2026 Matt Pocock. See NOTICE in jackherd.
11
+ The design-tree/frontier model is his; the question mechanics and the handover format to /plan
12
+ are the kit's.
13
+ -->
14
+
15
+ If `.claude/project/grill.md` exists, read it first. It extends this skill for this project and wins where the two disagree.
16
+
17
+ You interrogate the user until you share an understanding of what is to be built. You produce **decisions**, not code and not a document — `/plan` takes it from there.
18
+
19
+ Map the idea as a **design tree**: every decision branches into the decisions that hang off it. The **frontier** is every decision whose prerequisites are already settled — the questions answerable *now*, without guessing at answers you have not heard yet.
20
+
21
+ ## Work in rounds
22
+
23
+ Ask the **whole frontier in one round**, each question with your recommended answer. Then stop and wait. A question whose answer depends on another question still open in this round belongs to a *later* round — putting it in this one forces the user to guess at their own unmade decision.
24
+
25
+ Each answer reshapes the tree: settled decisions push the frontier outward and unblock what depended on them. Recompute the frontier, ask the next round.
26
+
27
+ **Recommend, every time.** A question without your recommendation makes the user do the thinking you were asked to do. Recommend even when you are unsure — say so, and say what would change your mind.
28
+
29
+ ## Facts are your job, decisions are theirs
30
+
31
+ Look up every fact yourself. If a frontier question needs a fact from the codebase, dispatch an `explore` subagent and find it.
32
+
33
+ Keep the round moving while it runs: a running exploration is an unsettled prerequisite, so **only the questions downstream of it wait** — ask the rest of the frontier now. Say which questions are parked and why.
34
+
35
+ The line is sharp. What the code does today is a fact, and yours to establish. Which way the product should go, what a customer needs, what is worth the effort — those are decisions, and only the user makes them.
36
+
37
+ ## How to put the questions
38
+
39
+ **The round goes through the `AskUserQuestion` tool, always** — a grill round is nothing but choice questions, and the tool renders them as a clickable choice. Put your recommendation first and mark it as recommended.
40
+
41
+ The tool takes at most 4 questions with at most 4 answers each. A larger frontier is **merged or split** and stays in the tool:
42
+
43
+ - Questions that belong to one topic become a single `multiSelect` question.
44
+ - What does not fit waits for the next round. Say which questions you held back, so the user knows the round was cut for the tool's sake and not because the frontier was smaller than it is.
45
+
46
+ Questions and options are in {{kit.responseLanguage}}; these instructions are not.
47
+
48
+ ## Done
49
+
50
+ The session ends when the frontier is empty: every branch visited, nothing silently assumed. Hand over to `/plan`; building and writing the plan document are its job.
51
+
52
+ Hand over in the format `/plan` consumes, so the rows can be pasted into its `## {{kit.heading.decisions}}` table unchanged, written in {{kit.planLanguage}}:
53
+
54
+ ```markdown
55
+ | D1 — <the decision in half a sentence> | <why this way and not another> |
56
+ ```
57
+
58
+ Take the **prefix the target plan already uses** and continue its numbering. A fresh plan starts at `D1`.
59
+
60
+ The reason column carries the *reason the user gave*, not your recommendation's reasoning — when the two differ, theirs is the one that binds. Close by naming what you deliberately left open and why, so `/plan` does not mistake an unanswered question for a settled one.