@jagreehal/shepherd 0.0.0-stage → 0.2.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/AGENTS.md +158 -0
- package/LICENSE +21 -0
- package/README.md +445 -2
- package/THIRD_PARTY_NOTICES.md +41 -0
- package/commands/shepherd.md +18 -0
- package/examples/local-demo/baseline/src/config.ts +2 -0
- package/examples/local-demo/baseline/src/db.ts +5 -0
- package/examples/local-demo/baseline/src/notes.ts +15 -0
- package/examples/local-demo/baseline/src/users.ts +8 -0
- package/examples/local-demo/expected.json +12 -0
- package/examples/local-demo/planted/src/config.ts +2 -0
- package/examples/local-demo/planted/src/notes.ts +15 -0
- package/examples/local-demo/planted/src/search.ts +8 -0
- package/examples/local-demo/planted/src/users.ts +8 -0
- package/lenses/observability/SKILL.md +26 -0
- package/package.json +46 -4
- package/skills/ci-repair/SKILL.md +178 -0
- package/skills/code-review/SKILL.md +89 -0
- package/skills/code-review/agents/openai.yaml +3 -0
- package/skills/diagnosing-bugs/SKILL.md +138 -0
- package/skills/diagnosing-bugs/agents/openai.yaml +3 -0
- package/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +44 -0
- package/skills/garden/SKILL.md +144 -0
- package/skills/incident/SKILL.md +261 -0
- package/skills/pair/SKILL.md +111 -0
- package/skills/pr/CREDITS.md +3 -0
- package/skills/pr/SKILL.md +170 -0
- package/skills/pr/agents/openai.yaml +3 -0
- package/skills/retro/SKILL.md +44 -0
- package/skills/retro/agents/openai.yaml +5 -0
- package/skills/review-correctness/SKILL.md +80 -0
- package/skills/review-maintainability/SKILL.md +86 -0
- package/skills/review-security/SKILL.md +75 -0
- package/skills/review-simplicity/SKILL.md +87 -0
- package/skills/review-slop/SKILL.md +94 -0
- package/skills/review-spec/SKILL.md +57 -0
- package/skills/shepherd/SKILL.md +407 -0
- package/skills/shepherd/references/degradation.md +21 -0
- package/skills/shepherd/references/dispatch.md +117 -0
- package/skills/shepherd/references/formats.md +46 -0
- package/skills/shepherd/references/models.md +88 -0
- package/skills/shepherd/references/policy.md +110 -0
- package/skills/swarm/SKILL.md +521 -0
- package/skills/swarm/references/custom-lenses.md +129 -0
- package/skills/swarm/references/formats.md +91 -0
- package/skills/triage/SKILL.md +388 -0
- package/skills/writing-for-agents/SKILL-MECHANICS.md +22 -0
- package/skills/writing-for-agents/SKILL.md +81 -0
- package/skills/writing-for-agents/agents/openai.yaml +3 -0
- package/src/acceptance.ts +111 -0
- package/src/cli.ts +379 -0
- package/src/config.ts +439 -0
- package/src/doctor.ts +153 -0
- package/src/garden.ts +198 -0
- package/src/install.ts +86 -0
- package/src/lens.ts +178 -0
- package/src/local.ts +393 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Model ladder
|
|
2
|
+
|
|
3
|
+
Every runner starts as low on the ladder as its job allows. A stronger model
|
|
4
|
+
validates a result; it never replaces a test.
|
|
5
|
+
|
|
6
|
+
## Resolve the ladder before pinning anything
|
|
7
|
+
|
|
8
|
+
**The operator's choice comes first.** Take `ladder` and `models` from the
|
|
9
|
+
team policy (`policy.md`): `.shepherd/config.yml` or `.shepherd/lenses.yml`
|
|
10
|
+
and its packs, on the **default branch**, never the PR head; then from
|
|
11
|
+
`~/.config/shepherd/lenses.yml`. The repository's ladder wins; a personal
|
|
12
|
+
ladder applies only when the repository sets none. `models:` pins merge per
|
|
13
|
+
name, the repository winning. `shepherd models` prints the result.
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
ladder: [opencode-go/deepseek-v4-flash, opencode-go/glm-5.3, opencode-go/kimi-k3, opencode-go/qwen3.8-max]
|
|
17
|
+
models: # a name runs on exactly this model, whatever its rung
|
|
18
|
+
security: opencode-go/qwen3.8-max
|
|
19
|
+
router: opencode-go/deepseek-v4-flash
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Pin names: `router`, `verifier`, `validator`, `triage`, `simplify`,
|
|
23
|
+
`ci-repair`, and any lens, built-in (`correctness`, `security`, `simplicity`,
|
|
24
|
+
`maintainability`, `slop`) or custom. A model id passes to the agent tool's
|
|
25
|
+
model parameter exactly as written: `haiku` on Claude Code, `provider/model`
|
|
26
|
+
on OpenCode. Never translate one id into another provider's. A pin replaces
|
|
27
|
+
the rung for that runner only; climbing for validation starts from the pin's
|
|
28
|
+
position on the ladder, or the top rung when the pin is not on it. A pin that
|
|
29
|
+
the agent tool rejects falls back to the runner's rung, and the summary says
|
|
30
|
+
so.
|
|
31
|
+
|
|
32
|
+
**When the subagent tool has no model parameter** (OpenCode 1.x), pick the
|
|
33
|
+
model by agent instead: `shepherd opencode-agents` generates one agent per rung
|
|
34
|
+
(`shepherd-r0` is the bottom rung, `shepherd-r1` the next) and one per pin
|
|
35
|
+
(`shepherd-pin-<name>`), each fixed to its model. Dispatch the runner with that
|
|
36
|
+
agent as its type. If those agents are not listed, say so in the summary: every
|
|
37
|
+
runner then runs on the session model.
|
|
38
|
+
|
|
39
|
+
With nothing configured, use the harness's ladder:
|
|
40
|
+
|
|
41
|
+
| Harness | Ladder, cheapest first |
|
|
42
|
+
|---|---|
|
|
43
|
+
| Claude Code | `haiku` -> `sonnet` -> `opus` -> `fable` |
|
|
44
|
+
| OpenCode | none built in: list `opencode models` and take the operator's ladder; with none set, the session model is one rung |
|
|
45
|
+
| Codex | the harness's own subagent models, cheapest first; with no per-agent model choice, one rung |
|
|
46
|
+
| Anything else | whatever the agent tool accepts, cheapest first |
|
|
47
|
+
|
|
48
|
+
If you cannot tell which models the agent tool accepts, assume the Claude Code
|
|
49
|
+
ladder and fall back one rung at a time on rejection. Never let a rejected pin
|
|
50
|
+
silently land every runner on the session model: that is the costliest outcome
|
|
51
|
+
and the one this ladder exists to prevent. When a caller passes a ladder, use it
|
|
52
|
+
exactly and ignore this table.
|
|
53
|
+
|
|
54
|
+
## Roles
|
|
55
|
+
|
|
56
|
+
- **Bottom rung:** work that only reads and that a later step checks: the swarm
|
|
57
|
+
router, whose findings a verifier or lens confirms.
|
|
58
|
+
- **Second rung:** runners that edit code, push commits, or resolve threads:
|
|
59
|
+
triage, simplify, and ci-repair. In trials the bottom rung fixed code and forgot to resolve the
|
|
60
|
+
thread, committed without pushing, invented domain rules, edited code to
|
|
61
|
+
get past a gate, and a simplify pass reverted a review fix. Each slip cost a redo one rung up, so starting there is the
|
|
62
|
+
cheaper path.
|
|
63
|
+
- **One rung up:** swarm's default delegation target; the validator for a risky
|
|
64
|
+
change; swarm's verifier for a bottom-rung finding.
|
|
65
|
+
- **Two rungs up:** fallback when the rung below is unavailable.
|
|
66
|
+
- **Top rung:** a delegation the rungs below could not settle, or reviewers who
|
|
67
|
+
disagree and need a stronger read.
|
|
68
|
+
|
|
69
|
+
## Validation
|
|
70
|
+
|
|
71
|
+
1. Prefer deterministic proof: tests, typecheck, lint, the final diff, evidence
|
|
72
|
+
from GitHub or CI.
|
|
73
|
+
2. For a risky or uncertain decision, ask the next rung up with only the
|
|
74
|
+
evidence and the narrow question.
|
|
75
|
+
3. Climb one rung at a time; stop when the evidence is clear.
|
|
76
|
+
4. Record which model ran each step.
|
|
77
|
+
|
|
78
|
+
A second-model validation is **required** before an autonomous change that
|
|
79
|
+
touches authentication, permissions, billing, data deletion, migrations,
|
|
80
|
+
concurrency, a public API, or a broad shared abstraction, and whenever reviewers
|
|
81
|
+
disagree or the checks cannot prove the change safe. Mechanical work the checks
|
|
82
|
+
prove needs no stronger model.
|
|
83
|
+
|
|
84
|
+
## When nothing cheaper exists
|
|
85
|
+
|
|
86
|
+
If no rung below the session model can be dispatched, every runner costs
|
|
87
|
+
session rates. Say so in the narration and the summary, and cut the quality
|
|
88
|
+
loop's round cap to 2.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Team policy
|
|
2
|
+
|
|
3
|
+
A team sets shepherd's policy in `.shepherd/config.yml` (an older repository
|
|
4
|
+
may have only `.shepherd/lenses.yml`; it reads the same way). It can extend
|
|
5
|
+
packs, which apply first, and the repository file wins over them. Every
|
|
6
|
+
runner reads the policy the same way and holds to it.
|
|
7
|
+
|
|
8
|
+
## Load it once per run
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
git fetch -q origin <default>
|
|
12
|
+
shepherd config explain --json # or: bunx @jagreehal/shepherd config explain --json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
It reads the **default branch**, never the PR head, so a PR cannot change the
|
|
16
|
+
policy it is reviewed under. It resolves the packs, and each value carries its
|
|
17
|
+
`source`. Done when you hold the JSON.
|
|
18
|
+
|
|
19
|
+
Without the CLI, read the file yourself:
|
|
20
|
+
`git show origin/<default>:.shepherd/config.yml`, else
|
|
21
|
+
`git show origin/<default>:.shepherd/lenses.yml`. If that file has `extends`,
|
|
22
|
+
the packs are unresolved: run as `fixes.mode: suggest` (nothing edits code)
|
|
23
|
+
and say `policy packs unresolved` in the summary. Never guess a pack's
|
|
24
|
+
contents.
|
|
25
|
+
|
|
26
|
+
Personal settings (`~/.config/shepherd/lenses.yml`) are a preview: their
|
|
27
|
+
lenses print locally and never post, and their ladder and pins fill in only
|
|
28
|
+
where the team set none. They never change checks, fixes, escalation or
|
|
29
|
+
recipes.
|
|
30
|
+
|
|
31
|
+
## What each setting means
|
|
32
|
+
|
|
33
|
+
- **`checks`**: named commands. When set, swarm runs exactly these as its
|
|
34
|
+
machine checks; ci-repair looks here first for the local command behind a
|
|
35
|
+
failing job; incident runs them before calling a fix done. When empty, each
|
|
36
|
+
runner finds the commands as its own skill says.
|
|
37
|
+
- **`fixes.mode`**: how far fixing goes.
|
|
38
|
+
- `push` (default): fix, commit, push, as each skill says.
|
|
39
|
+
- `local`: fix in the working tree; never commit, push, or resolve a
|
|
40
|
+
thread. The review after a fix is `swarm --local` on the working tree,
|
|
41
|
+
which leaves the receipt `shepherd local status` checks. Report "fixes
|
|
42
|
+
left in the working tree".
|
|
43
|
+
- `suggest`: change no code. Triage, simplify, ci-repair and incident report
|
|
44
|
+
what they would fix and stop; review threads stay open for the author.
|
|
45
|
+
- **`escalate.paths`**: globs a person must decide. No runner changes a
|
|
46
|
+
matching file. A finding whose fix needs one is deferred to the author with
|
|
47
|
+
`escalate.reason` (or "team policy: a person changes <path>"); ci-repair
|
|
48
|
+
classifies it `needs-decision`; incident stops with
|
|
49
|
+
`outcome=needs_decision`. A gate or deny-list elsewhere still applies.
|
|
50
|
+
- **`lenses`**, **`ladder`**, **`models`**: as in `../../swarm/references/custom-lenses.md`
|
|
51
|
+
and `models.md`.
|
|
52
|
+
- **`recipes`**: named step lists for `/shepherd <pr> --recipe <name>`. See
|
|
53
|
+
below.
|
|
54
|
+
|
|
55
|
+
## Recipes
|
|
56
|
+
|
|
57
|
+
A recipe is an ordered list of shepherd's own steps: `swarm`, `triage`,
|
|
58
|
+
`simplify`, `ci-repair`, `stamp`, `incident`. `shepherd config validate`
|
|
59
|
+
rejects an order that cannot work (triage before any swarm, stamp anywhere
|
|
60
|
+
but last, a code change nothing reviews afterwards, a fixing step under
|
|
61
|
+
`fixes.mode: suggest`, and under `local` a fix that only stamp reviews, since
|
|
62
|
+
stamp sees the pushed head and local fixes never reach it). A built-in recipe
|
|
63
|
+
the fix mode rules out is unavailable rather than an error; `shepherd preview
|
|
64
|
+
--recipe <name>` says why. The built-in ones:
|
|
65
|
+
|
|
66
|
+
| Recipe | Steps | Runs under |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| `review` | swarm | every mode |
|
|
69
|
+
| `fix` | swarm, triage, simplify, swarm | local, push |
|
|
70
|
+
| `pr` | swarm, triage, simplify, swarm, ci-repair, stamp | push |
|
|
71
|
+
| `incident` | incident, swarm, triage, simplify, swarm, ci-repair, stamp | push |
|
|
72
|
+
|
|
73
|
+
Without `--recipe`, `/shepherd` runs the recipe its fix mode selects:
|
|
74
|
+
`review` under `suggest`, `fix` under `local`, `pr` under `push`. `pr` is
|
|
75
|
+
shepherd's own loop (`../SKILL.md`, Steps 1 to 5).
|
|
76
|
+
|
|
77
|
+
Running one:
|
|
78
|
+
|
|
79
|
+
1. Run the steps in the order listed, one at a time. Code-changing steps
|
|
80
|
+
never overlap: they share one working tree and one branch.
|
|
81
|
+
2. Each step keeps every rule of its own skill and of `AGENTS.md`.
|
|
82
|
+
3. A review step (a swarm round that finds nothing new, or a stamp approval)
|
|
83
|
+
must run **after the last change** this iteration made. Otherwise the
|
|
84
|
+
result is `pending`, naming the step that still needs to review.
|
|
85
|
+
|
|
86
|
+
## How a recipe finishes
|
|
87
|
+
|
|
88
|
+
Finishing a recipe is not the same as a PR being ready. Report exactly one of:
|
|
89
|
+
|
|
90
|
+
- **`reviewed`**: a recipe with no fixing step (`review`) finished. Findings
|
|
91
|
+
are posted for the author. It says nothing about merge readiness; never
|
|
92
|
+
call the PR ready or approved.
|
|
93
|
+
- **`fixes_uncommitted`**: under `fixes.mode: local`, the fixes sit in the
|
|
94
|
+
working tree and the last swarm reviewed the tree, not the PR head. The PR
|
|
95
|
+
is unchanged; the person commits, pushes and runs again.
|
|
96
|
+
- **`ready`**: only when all three hold on the current head: stamp approved
|
|
97
|
+
it, CI is green, and no review thread is open. A recipe without stamp can
|
|
98
|
+
reach `reviewed`, never `ready`.
|
|
99
|
+
- **`pending`**: anything short of those, naming what is missing.
|
|
100
|
+
|
|
101
|
+
## Packs and lens files
|
|
102
|
+
|
|
103
|
+
A lens in a pack pinned to a commit (`github:owner/repo/pack.yml@<sha>`) can
|
|
104
|
+
name a path in the pack's own repository (`skill: lenses/payments`). It
|
|
105
|
+
resolves at the same commit, which must be on that repository's default branch: shepherd fetches that directory once into
|
|
106
|
+
`~/.cache/shepherd/packs/`, keyed by the commit, and `config explain --json`
|
|
107
|
+
gives the lens's `path` there. A bare name (`skill: payments-rules`) is an
|
|
108
|
+
installed skill. A lens path in a pack inside this repository resolves in
|
|
109
|
+
this repository. `shepherd config validate` reports a lens skill it cannot
|
|
110
|
+
find.
|