jackherd 1.17.0 → 1.18.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.
- package/CHANGELOG.md +6 -0
- package/README.md +25 -30
- package/herdr-plugin/herdr-plugin.toml +1 -1
- package/install.sh +1 -1
- package/kit/review/skills/pre-commit/SKILL.md +16 -22
- package/kit/rules/rules/kit/code-style.md +22 -50
- package/kit/rules/rules/kit/pull-requests.md +17 -40
- package/kit/rules/rules/kit/testing.md +6 -12
- package/kit/workflow/skills/implement/SKILL.md +27 -42
- package/kit/workflow/skills/orchestrate/SKILL.md +157 -235
- package/kit/workflow/skills/orchestrate/references/approvals.md +23 -0
- package/kit/workflow/skills/orchestrate/references/plan-commit.md +2 -1
- package/kit/workflow/skills/plan/SKILL.md +27 -47
- package/package.json +1 -1
- package/src/check/skill-budget-defaults.ts +20 -13
- package/src/check/skill-budgets.ts +42 -12
|
@@ -9,81 +9,68 @@ You are the **Implementer**. Your job is to carry tasks through completely: expl
|
|
|
9
9
|
|
|
10
10
|
## Golden Rules
|
|
11
11
|
|
|
12
|
-
1. **Tool calls before text.**
|
|
12
|
+
1. **Tool calls before text.** Every plan you state in prose is followed by the tool call that carries it out.
|
|
13
13
|
2. **A commit or push waits for the user's explicit confirmation.** `/pre-commit` obtains it via `AskUserQuestion`.
|
|
14
14
|
3. **Change only what was asked for.** Unasked refactorings and extra abstractions stay out.
|
|
15
15
|
4. **A bug fix starts from a command that goes red on it.** Before you edit a line, name that command. If you cannot, run `/diagnose` — it builds the command first and hands the fix back here.
|
|
16
16
|
|
|
17
17
|
## Step 0: Model Gate (plans with a `{{kit.heading.modelRecommendations}}` table)
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
Compare the model the table recommends for the phase with the model your run is on:
|
|
20
|
+
|
|
21
|
+
- **Same model** → continue with step 1.
|
|
22
|
+
- **Any other model, stronger or weaker** (the recommendation is a choice, not a floor) → delegate the phase to `Agent(subagent_type: 'implement', model: <recommended>, description: …, prompt: …)`, the `description` as in Step 0b item 3. Hand it what you already know (files located, decisions made, the phase's review gate). The prompt names the phase as `Phase P<n>` and the plan by its path from the repository root, so `model-gate` stops a start on a weaker model and `model-log` records the model for the herd. It ticks its phase's tasks itself (Plan Hygiene). You stay the orchestrator: the review gate, the arc42 and architecture checks and `/pre-commit` stay with you.
|
|
23
23
|
|
|
24
24
|
## Step 0b: Parallel Gate (plans with a `{{kit.heading.dependencies}}` table)
|
|
25
25
|
|
|
26
26
|
When the user asks for more than one phase:
|
|
27
27
|
|
|
28
|
-
1. **Read the computed waves:**
|
|
29
|
-
2. **Batch:** the requested phases in wave 1. A requested phase in a later wave waits, naming the phase it collides with. One in no wave is not ready
|
|
30
|
-
3. **Dispatch the batch in one message**, one `Agent(subagent_type: 'implement', model: <from the model table>, description: …, prompt: …)` per phase, in the same checkout
|
|
31
|
-
4. **When the batch returns:** check each report against its set (`git diff --stat`; an edit outside the set
|
|
28
|
+
1. **Read the computed waves:** `jh check --parallel <plan>` prints one line per wave of phases that can run side by side (`wave 1: P19 ∥ P20`), then `critical path: …` and `in no wave: …`. Wave 1 can start now, each later wave once the waves before it are done. A phase is ready once every `{{kit.heading.dependsOn}}` entry is ticked off with its review gate; one with an external gate (`User: …`) never is. Two phases share a wave only with no overlapping path under `{{kit.heading.writes}}`, no shared `{{kit.heading.serialMarker}}` and no release of the same package: a marker `Release <package> <version>`, or the package's `CHANGELOG.md` or `package.json` under `{{kit.heading.writes}}`. `no dependency table`: the phases run one after the other. `no phase is ready`: every open phase waits, is done, or is in no wave.
|
|
29
|
+
2. **Batch:** the requested phases in wave 1. A requested phase in a later wave waits, naming the phase it collides with. One in no wave is not ready (an external gate, an unknown or cyclic `like N`, a `{{kit.heading.writes}}` cell without a backticked path, or a dependency on such a phase); say which, and ask whether an external gate holds. The command checks paths, markers and releases only: two phases that collide in content you serialise yourself.
|
|
30
|
+
3. **Dispatch the batch in one message**, one `Agent(subagent_type: 'implement', model: <from the model table>, description: …, prompt: …)` per phase, in the same checkout. The `description` is `<Name> · P<n>`, with the short name of the first open task of its phase (the herd puts its `●` there), or the phase alone. Each prompt names its phase as in Step 0 and its `{{kit.heading.writes}}` set as the **only** paths it may edit besides its own phase's task lines, and states that it ticks the task checkboxes of its own phase as it finishes each one; the review gate, commits and `/pre-commit` stay with you, and it reports changed files, test results and the gate items it ran. They may run in the background; a hand-over (Step 7) waits until all are back.
|
|
31
|
+
4. **When the batch returns:** check each report against its set (`git diff --stat`; an edit outside the set, or a tick outside its own phase, is a finding), tick what it left open, walk each review gate. Gate items that write outside a phase's set (documentation, a changelog entry, plan synchronisation) are yours, at the wave's end. Then re-run `jh check --parallel` and dispatch the next batch.
|
|
32
32
|
5. **Commits stay serial and with you:** one `/pre-commit` per finished phase, in phase order; in a lane under `/orchestrate`, one per pull request (orchestrate skill § 5).
|
|
33
33
|
|
|
34
34
|
## Plan Hygiene (when implementing from a plan in `{{kit.planDirectory}}/`)
|
|
35
35
|
|
|
36
|
-
- **Tick off tasks as you go
|
|
37
|
-
- **A subagent ticks only its own phase,** and only with `Edit` on the exact task line (enough of it to be unique
|
|
36
|
+
- **Tick off tasks as you go:** `- [ ]` → `- [x]` the moment a task is done, so the herd shows progress while the phase runs.
|
|
37
|
+
- **A subagent ticks only its own phase,** and only with `Edit` on the exact task line (enough of it to be unique). Never `Write` the plan or rewrite it with a script: a whole-file write from an older read erases the ticks parallel subagents made. A line that is not unique, and every review-gate item, stays with the caller.
|
|
38
38
|
- **A task you add, or one the user adds later,** takes the form of `/plan` step 2: `- [ ] **Name**: …`.
|
|
39
|
-
- **The review gate is binding.** A phase is finished once its review gate has been walked through completely and ticked off; only then comes the next phase or `/pre-commit`.
|
|
39
|
+
- **The review gate is binding.** A phase is finished once its review gate has been walked through completely and ticked off; only then comes the next phase or `/pre-commit`. A gate item that names a skill is ticked after the skill has actually run.
|
|
40
40
|
|
|
41
41
|
## Step 1: Explore
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
0. A phase not yet in the plan gets its skeleton there first (heading, origin, tasks, review gate), before any research, so the herd never shows it as missing.
|
|
46
|
-
1. Search with `Grep` / `Glob` / `Read` for existing utilities, components and domain types that cover 80%+ of the need. For deeper research dispatch an `explore` subagent.
|
|
43
|
+
0. A phase not yet in the plan gets its skeleton there first (heading, origin, tasks, review gate), so the herd never shows it as missing.
|
|
44
|
+
1. Search for existing utilities, components and domain types that cover 80%+ of the need; for deeper research dispatch an `explore` subagent.
|
|
47
45
|
2. Run the generator for a generated file instead of editing it (`.claude/rules/kit/code-style.md` → Generators).
|
|
48
46
|
|
|
49
47
|
## Step 2: Implement
|
|
50
48
|
|
|
51
|
-
**Report each task before you start it
|
|
49
|
+
**Report each task before you start it**: in your own task list, or without one `jh task start "<task text>"` and `jh task done` when it is finished. The herd shows the task you work on from that signal.
|
|
52
50
|
|
|
53
|
-
**Money, identifiers, state transitions: the test comes first**
|
|
54
|
-
|
|
55
|
-
Follow `.claude/rules/kit/code-style.md`: types → pure functions → higher-order functions, names that reveal intent, no section-label comments.
|
|
51
|
+
**Money, identifiers, state transitions: the test comes first** (`.claude/rules/kit/testing.md` → Test-first).
|
|
56
52
|
|
|
57
53
|
Write code and tests with Write and Edit, never through a here-document or a script in Bash: such a call shows the reviewer no diff, and an unquoted or unreadable one can stop at a guard.
|
|
58
54
|
|
|
59
55
|
## Step 3: Verify
|
|
60
56
|
|
|
61
|
-
After each changed file:
|
|
62
|
-
|
|
63
|
-
1. Types and lint clean: `{{kit.command.typecheck}}` in the package, `{{kit.command.lint}}`.
|
|
64
|
-
2. No unused imports, no dead code, no commented-out leftovers.
|
|
57
|
+
After each changed file: `{{kit.command.typecheck}}` in the package and `{{kit.command.lint}}` clean, no dead code.
|
|
65
58
|
|
|
66
59
|
## Step 4: Write Tests
|
|
67
60
|
|
|
68
|
-
Follow the decision tree in `.claude/rules/kit/testing.md
|
|
61
|
+
Follow the decision tree in `.claude/rules/kit/testing.md`; run the tests with `{{kit.command.test}}`. For a change in a shared package, also run the tests of the packages that consume it.
|
|
69
62
|
|
|
70
63
|
## Step 4b: Look at It
|
|
71
64
|
|
|
72
|
-
A change a user sees
|
|
65
|
+
A change a user sees (a page, a route, a redirect, a printed document) is looked at in the running app before `/pre-commit`: unit tests prove the pieces, only the running app proves they meet. Use a temporary end-to-end spec or the browser, a screenshot per state, and report what each shows; delete the temporary spec before the commit unless the plan asks for one. No visible change → skip, and say so in the report.
|
|
73
66
|
|
|
74
|
-
|
|
67
|
+
## Step 5: arc42 and Architecture
|
|
75
68
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
Before `/pre-commit`: apply the filter in `.claude/rules/kit/arc42.md` and, on a hit, **ask the user concretely** whether the architecture documentation should be extended. No hit (bug fix, styling, small tweak) → skip without asking.
|
|
79
|
-
|
|
80
|
-
## Step 5b: Architecture Check
|
|
81
|
-
|
|
82
|
-
If the change touched a service, a domain package or a data layer: apply the filter in `.claude/rules/kit/architecture-files.md` and, on a hit, **ask the user concretely** whether the unit's `ARCHITECTURE.md` needs a new invariant, ownership entry or accepted risk.
|
|
69
|
+
Before `/pre-commit`: apply the filter in `.claude/rules/kit/arc42.md`, and for a service, a domain package or a data layer the one in `.claude/rules/kit/architecture-files.md`. On a hit, **ask the user concretely**; no hit (bug fix, styling, small tweak) → skip without asking.
|
|
83
70
|
|
|
84
71
|
## Step 6: Pre-Commit
|
|
85
72
|
|
|
86
|
-
Once
|
|
73
|
+
Once tests are green, types clean, the change looked at and Step 5 done: call `/pre-commit`. It routes to the reviewers and obtains the commit confirmation.
|
|
87
74
|
|
|
88
75
|
Ask every question with a fixed set of answers through the `AskUserQuestion` tool, in {{kit.responseLanguage}}.
|
|
89
76
|
|
|
@@ -91,20 +78,18 @@ The report at the end is short: one line of diff stat, one line per check with i
|
|
|
91
78
|
|
|
92
79
|
### Git commands run one at a time
|
|
93
80
|
|
|
94
|
-
`git add`, `git commit`, `git fetch`, `git rebase` and `git push` each run as a Bash command of their own, with
|
|
95
|
-
|
|
96
|
-
Why: a chained command cannot be approved as one (Claude Code docs, "Configure permissions", section "Compound commands").
|
|
81
|
+
`git add`, `git commit`, `git fetch`, `git rebase` and `git push` each run as a Bash command of their own, with nothing joined by `&&`, `||`, `;`, a pipe or a line break: a chained command cannot be approved as one (Claude Code docs, "Configure permissions", section "Compound commands"). The order is: checks, commit, fetch, rebase, checks again, push. Push only once the checks after the rebase are green. The checks again run where the rebase brought in changes to your package roots or plans, all of them when in doubt (orchestrate skill § 6).
|
|
97
82
|
|
|
98
83
|
## Step 7: Phase Boundary
|
|
99
84
|
|
|
100
85
|
Runs once the phase's review gate is ticked off, committed or not (a lane under `/orchestrate` commits only when its pull request is ready), and only then — never in the middle of a task.
|
|
101
86
|
|
|
102
|
-
1. Read the fill of your own context
|
|
87
|
+
1. Read the fill of your own context from the log, not from memory:
|
|
103
88
|
|
|
104
89
|
```bash
|
|
105
90
|
bunx jackherd context
|
|
106
91
|
```
|
|
107
92
|
|
|
108
|
-
`null` or `level` `ok` → continue with the next phase in this chat, and say nothing about it. A line on stderr that the auto-compact window is not above `plans.context.alertTokens`
|
|
109
|
-
2. `warn` or `alert`, and a next phase exists → the next phase runs in a new chat, without a question: go on with step 3
|
|
110
|
-
3. Write the hand-over to `.claude/handover/<lane>.md` (`<lane>` is the
|
|
93
|
+
`null` or `level` `ok` → continue with the next phase in this chat, and say nothing about it. A line on stderr that the auto-compact window is not above `plans.context.alertTokens` goes into your report in one line.
|
|
94
|
+
2. `warn` or `alert`, and a next phase exists → the next phase runs in a new chat, without a question: go on with step 3 once every subagent you started is back, no dialog of yours is open and no question of yours waits for an answer. The same holds when Jack, the coordinator, asked for the hand-over.
|
|
95
|
+
3. Write the hand-over to `.claude/handover/<lane>.md` (`<lane>` is the worktree directory's name; the directory stays out of every commit) and end your turn with its path. It holds, in this order: the line `{{kit.word.openSubagents}}: 0`, which the coordinator requires, the state (branch, commits or uncommitted changes, what is merged), the open points, the next step (after a wave, the state of each of its phases), the traps you ran into, and links to the plan and the files that matter. Jack starts a fresh agent in the same worktree with it; without a coordinator, the last line names the fill and tells the user to start a new chat with that file.
|