leos-agent 6.3.0 → 7.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.
- package/LICENSE +21 -0
- package/README.md +14 -7
- package/adapters/cursor/agents/executor.md +1 -1
- package/adapters/cursor/agents/implementer.md +2 -2
- package/adapters/cursor/agents/review-lens.md +22 -0
- package/adapters/cursor/agents/reviewer.md +2 -2
- package/adapters/opencode/agents.json +43 -4
- package/adapters/opencode/plugin.js +325 -37
- package/config/MCP_PINS.md +17 -0
- package/config/models.json +276 -8
- package/hooks/bash-guard.py +51 -9
- package/package.json +3 -6
- package/roles/executor.md +1 -1
- package/roles/implementer.md +2 -2
- package/roles/review-lens.md +20 -0
- package/roles/reviewer.md +2 -2
- package/scripts/doctor.py +267 -31
- package/scripts/ghreview.py +7 -3
- package/scripts/jsonc_bridge.cjs +23 -0
- package/scripts/memory.py +74 -35
- package/scripts/render_adapters.py +57 -22
- package/scripts/resolve_attach_target.py +45 -13
- package/scripts/setup.py +1594 -2
- package/skills/brainstorming/SKILL.md +3 -1
- package/skills/debugging/SKILL.md +4 -2
- package/skills/delegation/SKILL.md +10 -8
- package/skills/doctor/SKILL.md +33 -14
- package/skills/executing-plans/SKILL.md +2 -1
- package/skills/finishing-a-branch/SKILL.md +4 -2
- package/skills/freshness/SKILL.md +23 -10
- package/skills/memory/SKILL.md +12 -2
- package/skills/resolve-ticket/SKILL.md +15 -9
- package/skills/review-pr/SKILL.md +26 -16
- package/skills/setup/SKILL.md +123 -9
- package/skills/setup/agents/openai.yaml +5 -0
- package/skills/test-first/SKILL.md +3 -1
- package/skills/using-leo/SKILL.md +11 -6
- package/skills/using-leo/references/claude-mapping.md +2 -1
- package/skills/using-leo/references/codex-mapping.md +4 -5
- package/skills/using-leo/references/cursor-mapping.md +2 -1
- package/skills/using-leo/references/hermes-mapping.md +2 -1
- package/skills/using-leo/references/opencode-mapping.md +6 -3
- package/skills/verification/SKILL.md +2 -1
- package/skills/visual-verification/SKILL.md +2 -1
- package/skills/watch-review/SKILL.md +17 -14
- package/skills/watch-review/agents/openai.yaml +5 -0
- package/skills/worktrees/SKILL.md +3 -1
- package/skills/writing-plans/SKILL.md +2 -1
- package/skills/writing-skills/SKILL.md +9 -2
- package/vendor/jsonc-parser-3.3.1/LICENSE.md +21 -0
- package/vendor/jsonc-parser-3.3.1/README.md +26 -0
- package/vendor/jsonc-parser-3.3.1/lib/umd/impl/edit.js +201 -0
- package/vendor/jsonc-parser-3.3.1/lib/umd/impl/format.js +275 -0
- package/vendor/jsonc-parser-3.3.1/lib/umd/impl/parser.js +682 -0
- package/vendor/jsonc-parser-3.3.1/lib/umd/impl/scanner.js +456 -0
- package/vendor/jsonc-parser-3.3.1/lib/umd/impl/string-intern.js +42 -0
- package/vendor/jsonc-parser-3.3.1/lib/umd/main.d.ts +351 -0
- package/vendor/jsonc-parser-3.3.1/lib/umd/main.js +194 -0
- package/vendor/jsonc-parser-3.3.1/package.json +37 -0
- package/workflows/cost-tiered-fix.js +32 -4
|
@@ -7,7 +7,9 @@ description: >
|
|
|
7
7
|
wide blast radius, hard to reverse, or that introduce new surface need
|
|
8
8
|
genuine, viable alternatives with trade-offs weighed before any code gets
|
|
9
9
|
written. Produces the chosen approach and its trade-offs, sized to the gate,
|
|
10
|
-
handed off to leo:writing-plans.
|
|
10
|
+
handed off to leo:writing-plans. Use when choosing an approach before
|
|
11
|
+
non-trivial code. Do not use for contained reversible tweaks, investigation,
|
|
12
|
+
or writing the plan itself.
|
|
11
13
|
when_to_use: >
|
|
12
14
|
Before starting non-trivial code: a new feature, a new integration surface,
|
|
13
15
|
a schema or data-model change, anything that's expensive or awkward to
|
|
@@ -5,7 +5,9 @@ description: >
|
|
|
5
5
|
behavior. Five named phases — Reproduce, Localize, Hypothesize, Prove, Fix —
|
|
6
6
|
each with an exit criterion, so a fix never lands before the cause is
|
|
7
7
|
pinned to file:line. Diagnosis is read-only judge work (investigator); the
|
|
8
|
-
fix happens separately, at the routed tier.
|
|
8
|
+
fix happens separately, at the routed tier. Use when a bug, failure, crash,
|
|
9
|
+
or surprising behavior needs diagnosis. Do not use for planned features,
|
|
10
|
+
reviewing a diff, or post-fix completion verification.
|
|
9
11
|
when_to_use: >
|
|
10
12
|
Any bug report, failing test, crash, stack trace, or "why does X happen"
|
|
11
13
|
before proposing a fix — used by the investigator agent and by the main
|
|
@@ -61,7 +63,7 @@ you, and go again.
|
|
|
61
63
|
|
|
62
64
|
After two failures on the same cause (two hypotheses tried and reverted, still
|
|
63
65
|
no Prove), step up one tier rather than retrying at the same one — investigator
|
|
64
|
-
|
|
66
|
+
explore findings feed a full investigator, and investigator itself steps to a
|
|
65
67
|
second, more evidence-fed pass, capped at Opus. A genuine deadlock, or two
|
|
66
68
|
Opus verdicts on the same cause that disagree → `expert`, announced in one
|
|
67
69
|
line ("escalating to expert: <question>") before it's invoked, never silent.
|
|
@@ -4,7 +4,8 @@ description: >
|
|
|
4
4
|
Operational mechanics for dispatching subagents — a single spawn or a large
|
|
5
5
|
fan-out — the companion to the policy's "Delegate the labor" section.
|
|
6
6
|
Covers brief construction, model/effort pinning, the four-state return
|
|
7
|
-
contract, and ledger-backed progress tracking for long multi-agent runs.
|
|
7
|
+
contract, and ledger-backed progress tracking for long multi-agent runs. Use
|
|
8
|
+
when dispatching any subagent or fan-out. Do not use to choose a task's tier.
|
|
8
9
|
when_to_use: >
|
|
9
10
|
Any time work is routed to a subagent (explore, investigator, executor,
|
|
10
11
|
implementer, reviewer, expert) rather than done inline — single dispatch or
|
|
@@ -36,8 +37,8 @@ version needs no follow-up question; the first invites three.
|
|
|
36
37
|
## Pin model and effort
|
|
37
38
|
|
|
38
39
|
Every dispatch pins **model AND effort** from the routing table — opus for
|
|
39
|
-
judges (reviewer, investigator), sonnet for
|
|
40
|
-
|
|
40
|
+
judges (reviewer, investigator), sonnet for normal implementation
|
|
41
|
+
(implementer), haiku for mechanical work (executor). expert
|
|
41
42
|
never appears in a fan-out — one at a time, never fanned. An unpinned call
|
|
42
43
|
silently inherits the session's tier: in an opus session that means every
|
|
43
44
|
executor spawn quietly runs at opus, and a ten-item fan-out burns
|
|
@@ -53,7 +54,7 @@ a report that hedges across two of them.
|
|
|
53
54
|
|---|---|---|
|
|
54
55
|
| `done` | Work finished, matches the brief | Verify against artifacts — see leo:verification — never take the self-report at face value |
|
|
55
56
|
| `concerns` | Finished, but flags something worth a second look | Read the concerns before accepting; they're often the real finding |
|
|
56
|
-
| `needs-context` | Blocked on missing information you can supply | Send the missing piece to the same agent (`SendMessage` on Claude Code — elsewhere see the *Follow-up to a live agent* row of your mapping, and where none is established, cold re-dispatch with the context restated is the whole mechanism) so it keeps the context it already built. Either way **once** — a second needs-context on the same gap means the brief itself is broken, escalate the tier |
|
|
57
|
+
| `needs-context` | Blocked on missing information you can supply | Send the missing piece to the same agent (`SendMessage` on Claude Code, `followup_task` on Codex — elsewhere see the *Follow-up to a live agent* row of your mapping, and where none is established, cold re-dispatch with the context restated is the whole mechanism) so it keeps the context it already built. Either way **once** — a second needs-context on the same gap means the brief itself is broken, escalate the tier |
|
|
57
58
|
| `blocked` | Blocked on something you can't hand over inline | Resolve the blocker, or escalate per the ladder — never a silent same-tier retry |
|
|
58
59
|
|
|
59
60
|
`needs-context` and `blocked` look similar; the test is whether the missing
|
|
@@ -89,10 +90,11 @@ between "agent finished" and "ledger written" is exactly the gap this
|
|
|
89
90
|
exists to close.
|
|
90
91
|
|
|
91
92
|
`${CLAUDE_PLUGIN_ROOT}` above is the Claude Code spelling of the plugin root,
|
|
92
|
-
and it is substituted into this text only there.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
and it is substituted into this text only there. Codex exposes `$PLUGIN_ROOT`
|
|
94
|
+
and Cursor `$CURSOR_PLUGIN_ROOT`. Hermes and OpenCode expose no root variable;
|
|
95
|
+
their injected policy substitutes an absolute payload path into the `state.py`
|
|
96
|
+
and `memory.py` commands, which is the discoverable source to reuse. Do not
|
|
97
|
+
invent an environment variable where the harness exposes none.
|
|
96
98
|
|
|
97
99
|
For a batch of independent, well-scoped fixes, don't hand-roll this loop —
|
|
98
100
|
the reusable workflow at `${CLAUDE_PLUGIN_ROOT}/workflows/cost-tiered-fix.js`
|
package/skills/doctor/SKILL.md
CHANGED
|
@@ -6,7 +6,9 @@ description: >
|
|
|
6
6
|
machine-local state and the memory store live, and which skills shipped
|
|
7
7
|
versus which this session can actually invoke. Disk facts come from a
|
|
8
8
|
helper script; the context facts only the running session can answer, and
|
|
9
|
-
a disagreement between the two columns is the diagnosis.
|
|
9
|
+
a disagreement between the two columns is the diagnosis. Use when Leo asks
|
|
10
|
+
about Leo's loading, routing, or skill wiring. Do not use for project health
|
|
11
|
+
checks, project-code debugging, or unprompted inspection.
|
|
10
12
|
when_to_use: >
|
|
11
13
|
Leo asks whether the policy loaded, why routing or a skill is misbehaving,
|
|
12
14
|
or invokes doctor by name after installing, updating, or switching harness.
|
|
@@ -37,14 +39,22 @@ argument, not a fault.
|
|
|
37
39
|
|
|
38
40
|
`${CLAUDE_PLUGIN_ROOT}` is the Claude Code spelling. Codex exports
|
|
39
41
|
`$PLUGIN_ROOT` and Cursor `$CURSOR_PLUGIN_ROOT`. On Hermes and OpenCode no
|
|
40
|
-
plugin-root variable exists at all —
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
plugin-root variable exists at all — the injected policy instead substitutes an
|
|
43
|
+
absolute payload path into its `state.py` and `memory.py` commands. Read that
|
|
44
|
+
command path from the policy as the discoverable source. Being unable to locate
|
|
43
45
|
the payload at all is itself the first finding: the harness is not looking where
|
|
44
46
|
the plugin was installed.
|
|
45
47
|
|
|
46
48
|
Add `--json` when you want the same facts as data.
|
|
47
49
|
|
|
50
|
+
Doctor validates the bootstrap that actually belongs to the named harness:
|
|
51
|
+
the session hook and manifest for Claude, Codex, and Cursor;
|
|
52
|
+
`config.instructions` in OpenCode's plugin; and Hermes registration plus its
|
|
53
|
+
first-tool-result fallback. It also reports the running Python version against
|
|
54
|
+
the supported 3.9+ floor. Codex hook trust is not provable from disk: review
|
|
55
|
+
the plugin in `/hooks` and confirm it is trusted before treating the on-disk
|
|
56
|
+
hook as active.
|
|
57
|
+
|
|
48
58
|
## Then answer the three it cannot
|
|
49
59
|
|
|
50
60
|
A script can prove the hook is installed and that the policy renders. It cannot
|
|
@@ -56,13 +66,17 @@ prove the policy arrived. Only you can see your own context.
|
|
|
56
66
|
then points at models that do not exist here.
|
|
57
67
|
2. **Which skills are actually invocable?** Compare your own skill list against
|
|
58
68
|
the script's shipped roster. Mind the naming rule: most harnesses namespace
|
|
59
|
-
them as `leo:<name>`, while OpenCode
|
|
60
|
-
|
|
61
|
-
|
|
69
|
+
them as `leo:<name>`, while OpenCode has no namespace and requires a
|
|
70
|
+
skill's frontmatter name to match its directory, so the plugin registers a
|
|
71
|
+
generated shadow copy with every skill renamed `leo-<name>`. A skill that
|
|
72
|
+
looks missing on OpenCode may simply be listed as `leo-<name>` rather than
|
|
73
|
+
`leo:<name>`.
|
|
62
74
|
3. **Is memory present and delivered?** The script reports whether the store
|
|
63
75
|
exists and whether each native surface received its generated copy. Whether
|
|
64
76
|
those facts are in front of you right now is something only you can confirm.
|
|
65
|
-
Report the two separately; they disagree more often than expected.
|
|
77
|
+
Report the two separately; they disagree more often than expected. Hermes's
|
|
78
|
+
projection is opt-in, so doctor reports it explicitly as disabled rather
|
|
79
|
+
than silently omitting it.
|
|
66
80
|
|
|
67
81
|
## Reading the report
|
|
68
82
|
|
|
@@ -72,10 +86,13 @@ three: **healthy**, **degraded**, or **not loaded**. Never free prose. `not
|
|
|
72
86
|
loaded` outranks everything else: if the policy did not arrive, nothing else in
|
|
73
87
|
the report describes how this session will actually behave.
|
|
74
88
|
|
|
75
|
-
**
|
|
76
|
-
the test suite drives
|
|
77
|
-
|
|
78
|
-
|
|
89
|
+
**Most breadcrumb logs are history, not a verdict.** Some older logs carry no
|
|
90
|
+
timestamps, and the test suite drives failure paths deliberately, so entries
|
|
91
|
+
can accumulate on a development machine. Quote the newest line if useful, but
|
|
92
|
+
never conclude "the hook failed this session" from history alone. The one
|
|
93
|
+
capability exception is `opencode-skills.log`: its presence means namespaced
|
|
94
|
+
OpenCode skill registration degraded and doctor reports that state until the
|
|
95
|
+
breadcrumb is cleared after the underlying problem is understood.
|
|
79
96
|
|
|
80
97
|
## Failure modes
|
|
81
98
|
|
|
@@ -83,9 +100,11 @@ useful, but never conclude "the hook failed this session" from it.
|
|
|
83
100
|
|---|---|---|
|
|
84
101
|
| Policy absent, bootstrap installed | the hook fired and failed open | read the newest breadcrumb, then confirm it describes this session before believing it |
|
|
85
102
|
| Policy present, mapping names another harness | detection resolved wrong, usually a stray plugin-root variable exported in an unrelated shell | unset it, restart the session |
|
|
86
|
-
| Harness reported as `unknown` | no `--harness`, and this harness exports no plugin-root variable | re-run with `--harness <name>` read off your mapping heading |
|
|
103
|
+
| Harness reported as `unknown` | no `--harness`, and this harness exports no plugin-root variable | degraded until re-run with `--harness <name>` read off your mapping heading; a still-unknown explicit run is invalid wiring |
|
|
104
|
+
| Codex hook is on disk but policy is absent | the new or changed hook may not be trusted | open `/hooks`, review the hook, and explicitly trust it |
|
|
105
|
+
| OpenCode reports `opencode-skills.log` | the namespaced shadow tree failed and no bare-name fallback was registered | inspect the newest breadcrumb, fix the path/permission failure, and restart OpenCode |
|
|
87
106
|
| Shipped roster exceeds what you can invoke | the harness cached an older payload, or the skills directory is not registered | update the plugin; on OpenCode check `opencode debug skill` for each skill's `location` |
|
|
88
|
-
| Skills listed
|
|
107
|
+
| Skills listed as `leo-<name>` instead of `leo:<name>` | OpenCode, working as designed | invoke them as `leo-<name>`; not a fault |
|
|
89
108
|
| Tier names resolve to models this harness cannot run | mapping and harness disagree | same as row 2 |
|
|
90
109
|
| Machine-local state not writable | the path override points somewhere unwritable | fix or unset it |
|
|
91
110
|
| A skill is genuinely absent from disk | it was never added | see leo:writing-skills |
|
|
@@ -5,7 +5,8 @@ description: >
|
|
|
5
5
|
with a check at every batch boundary, plan-intent-wins-on-architecture /
|
|
6
6
|
reality-wins-on-mechanics arbitration, and one fix-then-re-review cycle
|
|
7
7
|
before stopping to report. Used by the implementer agent, or the main loop
|
|
8
|
-
when it executes a plan directly.
|
|
8
|
+
when it executes a plan directly. Use when a written plan is about to become
|
|
9
|
+
code. Do not use for open-ended work without a plan or for reviewing a diff.
|
|
9
10
|
when_to_use: >
|
|
10
11
|
A written plan (from planner, an issue, or Leo's own outline) is about to
|
|
11
12
|
be turned into code. NOT for open-ended implementation with no plan
|
|
@@ -6,7 +6,9 @@ description: >
|
|
|
6
6
|
a closed set of next steps — merge / PR / keep / discard — routes the
|
|
7
7
|
chosen path through the right ordering (land the work before removing the
|
|
8
8
|
worktree, remove the worktree before deleting the branch), and leaves the
|
|
9
|
-
repo clean.
|
|
9
|
+
repo clean. Use when reviewed implementation on a branch/worktree needs a
|
|
10
|
+
terminal disposition. Do not use to manage a worktree mid-task or replace
|
|
11
|
+
the review cycle.
|
|
10
12
|
when_to_use: >
|
|
11
13
|
A branch or worktree has reached "implementation done" and Leo needs to
|
|
12
14
|
decide what happens to it. Fires after execute-then-review completes, or
|
|
@@ -71,7 +73,7 @@ Per option:
|
|
|
71
73
|
| Option | Sequence |
|
|
72
74
|
|---|---|
|
|
73
75
|
| merge | merge locally or `gh pr merge` → remove worktree (`leo:worktrees`) → delete local branch |
|
|
74
|
-
| PR | push branch → open PR → **stop** (worktree and branch stay; nothing is
|
|
76
|
+
| PR | push branch → open PR → **stop** (worktree and branch stay; nothing is merged yet.) |
|
|
75
77
|
| keep | do nothing destructive; leave worktree and branch as-is |
|
|
76
78
|
| discard | typed confirmation (below) → remove worktree (`leo:worktrees`) → force-delete branch |
|
|
77
79
|
|
|
@@ -6,7 +6,9 @@ description: >
|
|
|
6
6
|
committed to, its shape is confirmed against a source that reflects the
|
|
7
7
|
version this project actually runs — the installed package, the lockfile
|
|
8
8
|
pin, or documentation fetched this turn. Each check is recorded by symbol
|
|
9
|
-
and source in the report.
|
|
9
|
+
and source in the report. Use when writing, reviewing, or asserting a
|
|
10
|
+
third-party surface. Do not use for first-party code, pinned standard
|
|
11
|
+
libraries, or as a substitute for verification.
|
|
10
12
|
when_to_use: >
|
|
11
13
|
About to write, review, or assert the shape of a third-party surface — an
|
|
12
14
|
import path, an argument list, a config key, an HTTP field, an auth
|
|
@@ -46,14 +48,25 @@ Outside these five, write the code.
|
|
|
46
48
|
|
|
47
49
|
## What counts as a source
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
Two different questions — which to reach for, and which one wins.
|
|
50
52
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
**Lookup order.** Cheapest first; stop at the first that answers.
|
|
54
|
+
|
|
55
|
+
1. A documentation tool the harness exposes for that vendor (Context7 and
|
|
56
|
+
the like) — one call, cheap.
|
|
57
|
+
2. Official documentation fetched this turn — cheap.
|
|
58
|
+
3. The lockfile pin plus that version's changelog — a narrow read.
|
|
59
|
+
4. The installed package read on disk — `node_modules`, `site-packages`,
|
|
60
|
+
`vendor` — expensive; grep for the specific symbol, never read whole
|
|
61
|
+
files.
|
|
62
|
+
|
|
63
|
+
Rungs 1 and 2 answer for whichever version they happen to describe, which is
|
|
64
|
+
not always yours. Note the version each one reports and compare it to the pin;
|
|
65
|
+
a cheap answer that cannot say which version it describes has not answered.
|
|
66
|
+
|
|
67
|
+
**Authority.** When two sources disagree, the installed package wins — it
|
|
68
|
+
is the version that will execute. A cheap source that contradicts it is
|
|
69
|
+
wrong.
|
|
57
70
|
|
|
58
71
|
Not sources: your recollection; an older file in this repo calling the same API,
|
|
59
72
|
which may be the stale thing you are about to copy; a blog post; a search
|
|
@@ -97,8 +110,8 @@ to the lockfile without rerunning anything.
|
|
|
97
110
|
case where they do not is the entire reason for the step.
|
|
98
111
|
- "Another file here calls it this way" — that file may be what you are about
|
|
99
112
|
to propagate.
|
|
100
|
-
- "The typechecker will catch it" — a typechecker reads installed stubs,
|
|
101
|
-
|
|
113
|
+
- "The typechecker will catch it" — a typechecker reads installed stubs, the
|
|
114
|
+
authority source. Say so and cite it, rather than skipping and hoping.
|
|
102
115
|
- "It's one argument" — argument names are exactly what moves between majors.
|
|
103
116
|
|
|
104
117
|
## Reviewable finding
|
package/skills/memory/SKILL.md
CHANGED
|
@@ -5,7 +5,9 @@ description: >
|
|
|
5
5
|
session and every plugin update. Covers what earns a place in the store,
|
|
6
6
|
how a fact is written and revised, how to read one before acting on it,
|
|
7
7
|
and when to throw one away. The store is canonical; each harness's own
|
|
8
|
-
memory surface receives a generated copy of the global facts.
|
|
8
|
+
memory surface receives a generated copy of the global facts. Use when a
|
|
9
|
+
durable preference, repo rule, decision, or machine quirk surfaces. Do not
|
|
10
|
+
use for current-task state or facts already recorded in the repository.
|
|
9
11
|
when_to_use: >
|
|
10
12
|
A fact surfaces that will still be true next month — a stated preference,
|
|
11
13
|
a repo rule the code does not spell out, a settled decision, a machine
|
|
@@ -98,7 +100,15 @@ python3 "${CLAUDE_PLUGIN_ROOT}/scripts/memory.py" write repo convention "Generat
|
|
|
98
100
|
```
|
|
99
101
|
|
|
100
102
|
Writing the same title again revises that file in place and keeps its original
|
|
101
|
-
creation date
|
|
103
|
+
creation date only when both title and type match exactly. A slug collision with
|
|
104
|
+
a different title or type receives the next `-N` suffix; a corrupt occupied
|
|
105
|
+
slot is never overwritten. `list` shows what is stored; `read <ref>` returns
|
|
106
|
+
one fact whole.
|
|
107
|
+
|
|
108
|
+
Leo-owned memory directories use mode `0700`; fact files and the generated
|
|
109
|
+
`index.json` and `MEMORY.md` use `0600`. A newly generated projection is also
|
|
110
|
+
private, while an existing user-owned projection target retains the mode the
|
|
111
|
+
user chose.
|
|
102
112
|
|
|
103
113
|
## Read path
|
|
104
114
|
|
|
@@ -5,7 +5,8 @@ description: >
|
|
|
5
5
|
context (Confluence, Slack, GitHub), investigate and plan at Opus tier, get
|
|
6
6
|
Leo's explicit sign-off, implement on a worktree branch with sonnet/haiku
|
|
7
7
|
executors, Opus-review the diff, then push and open a DRAFT pull request in
|
|
8
|
-
the browser.
|
|
8
|
+
the browser. Use when Leo names a tracked ticket to fix or implement. Do not
|
|
9
|
+
use for ad-hoc fixes without a ticket or independent-item batches.
|
|
9
10
|
when_to_use: >
|
|
10
11
|
Leo asks to fix or implement a specific tracked ticket by ID ("fix ENG-123",
|
|
11
12
|
"/resolve-ticket PLAT-42"). NOT for ad-hoc fixes with no ticket (normal
|
|
@@ -23,6 +24,7 @@ allowed-tools:
|
|
|
23
24
|
- Bash(git fetch *)
|
|
24
25
|
- Bash(git rev-parse *)
|
|
25
26
|
- Bash(git merge-base *)
|
|
27
|
+
- Bash(git check-ignore *)
|
|
26
28
|
- Bash(git checkout *)
|
|
27
29
|
- Bash(git switch *)
|
|
28
30
|
- Bash(git add *)
|
|
@@ -137,8 +139,8 @@ Collect URLs from the ticket body, comments, attachments, and (Jira)
|
|
|
137
139
|
tell Leo explicitly** that Slack must be configured independently in the
|
|
138
140
|
current harness, then continue without it.
|
|
139
141
|
- **GitHub PR/issue/commit** → `gh` view commands.
|
|
140
|
-
- **Anything else** →
|
|
141
|
-
|
|
142
|
+
- **Anything else** → use an available connector or fetch tool once. If none
|
|
143
|
+
is connected, report that context gap to Leo; do not use a shell HTTP fallback.
|
|
142
144
|
|
|
143
145
|
Every failure or skip goes into a **context-gaps list** shown at the sign-off
|
|
144
146
|
gate — Leo sees exactly what wasn't read before approving.
|
|
@@ -182,7 +184,8 @@ Only after Approve: `git fetch origin`, then create branch
|
|
|
182
184
|
`fix/<TICKET-ID>-<slug>` off `origin/<defaultBranch>` in a worktree. Where the
|
|
183
185
|
harness has a native worktree tool (see the *Worktrees* row of your mapping),
|
|
184
186
|
use it and pair every enter with an exit. Otherwise, and on every harness that
|
|
185
|
-
does not: `git
|
|
187
|
+
does not: first prove `git check-ignore .claude/worktrees/fix-<id>` succeeds,
|
|
188
|
+
then `git worktree add -b fix/<id>-<slug> .claude/worktrees/fix-<id>
|
|
186
189
|
origin/<default>` and work by absolute paths.
|
|
187
190
|
|
|
188
191
|
Executors in Step 6 must **NOT** be given their own worktree — this is one
|
|
@@ -202,8 +205,9 @@ Per plan step:
|
|
|
202
205
|
specs, so the executor contract (do exactly this, stop on ambiguity) fits
|
|
203
206
|
better than implementer's wider latitude. Anywhere the plan is thinner than
|
|
204
207
|
that, use `implementer` as the policy says.
|
|
205
|
-
-
|
|
206
|
-
|
|
208
|
+
- Parallel spawns are read-only investigation only. All edits, test writes,
|
|
209
|
+
staging, commits, and other mutations are strictly sequential in the one
|
|
210
|
+
canonical `.claude/worktrees/fix-<id>` worktree. Executors commit as they go.
|
|
207
211
|
- This loop implements directly only for trivial diffs (< ~10 lines) where
|
|
208
212
|
writing the spec would cost more than the change.
|
|
209
213
|
- Escalate, don't struggle: an executor reporting ambiguity or failing twice →
|
|
@@ -248,9 +252,11 @@ ticket, the approved plan, and the diff scope
|
|
|
248
252
|
Same voice rules as /review-pr: no filler, no emoji, no self-praise.
|
|
249
253
|
If a PR already exists for the branch, open that one instead and say so.
|
|
250
254
|
3. `gh pr view --web` to open it in the browser.
|
|
251
|
-
4.
|
|
252
|
-
|
|
253
|
-
|
|
255
|
+
4. Retain the worktree through PR merge. After merge, hand cleanup to
|
|
256
|
+
`leo:finishing-a-branch` / `leo:worktrees`; do not remove it merely because
|
|
257
|
+
the draft PR was opened. Do **not** write back to the ticket (no comment,
|
|
258
|
+
no status transition) — deliberate non-action; Leo asks separately if he
|
|
259
|
+
wants it.
|
|
254
260
|
5. Final report: branch, PR URL, worktree path (left in place for follow-ups),
|
|
255
261
|
checks run, review rounds used, remaining non-blocking notes.
|
|
256
262
|
|
|
@@ -6,11 +6,12 @@ description: >
|
|
|
6
6
|
submitted. Handles Leo's existing reviews: a stale pending review is
|
|
7
7
|
replaced; posted threads are left, resolved, or get a staged reply.
|
|
8
8
|
Reports the staged comments and a merge verdict in chat. Requires gh,
|
|
9
|
-
installed and authenticated.
|
|
9
|
+
installed and authenticated. Use when Leo asks to review a GitHub PR. Do not
|
|
10
|
+
use for a local working diff or to submit a review.
|
|
10
11
|
when_to_use: >
|
|
11
12
|
Leo asks to review a pull request by number ("review PR 42", "/review-pr 42")
|
|
12
13
|
or "review the PR for this branch". NOT for reviewing the local working diff
|
|
13
|
-
(that is
|
|
14
|
+
(that is the local reviewer subagent) and NOT for submitting a
|
|
14
15
|
review — this only stages draft comments.
|
|
15
16
|
argument-hint: "[pr-number]"
|
|
16
17
|
allowed-tools:
|
|
@@ -26,6 +27,7 @@ allowed-tools:
|
|
|
26
27
|
- Bash(git merge-base *)
|
|
27
28
|
- Bash(git status *)
|
|
28
29
|
- Bash(python3 */ghreview.py *)
|
|
30
|
+
- Bash(python3 "*/ghreview.py" *)
|
|
29
31
|
- Agent
|
|
30
32
|
---
|
|
31
33
|
|
|
@@ -39,8 +41,8 @@ Run this at the **Opus tier** — it ends in a merge verdict, which is judge
|
|
|
39
41
|
work. Tier map: Sonnet reads (the lens agents), Opus judges (this main loop).
|
|
40
42
|
Your harness mapping names the concrete model for each, and says whether a
|
|
41
43
|
per-spawn model override exists here at all; where it does not, the lenses run
|
|
42
|
-
at whatever their registered agent runs. The staged
|
|
43
|
-
|
|
44
|
+
at whatever their registered agent runs. The staged review is created by
|
|
45
|
+
`"${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py"` in ONE API call
|
|
44
46
|
with no `event` field — that is what keeps it PENDING. Never use `gh pr review`
|
|
45
47
|
(it always submits) and never set an `event` value.
|
|
46
48
|
|
|
@@ -97,7 +99,7 @@ Two kinds of prior review state, handled differently:
|
|
|
97
99
|
it carries the script's own marker (it embeds one in everything it stages):
|
|
98
100
|
|
|
99
101
|
```
|
|
100
|
-
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py clear-pending -R OWNER/REPO -n N
|
|
102
|
+
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py" clear-pending -R OWNER/REPO -n N
|
|
101
103
|
```
|
|
102
104
|
|
|
103
105
|
If it exits 0, note what was deleted in the final report. If it exits 3, it
|
|
@@ -110,13 +112,17 @@ stage step, `--replace-pending --force`) once he confirms. Still pass
|
|
|
110
112
|
**Posted (submitted) review threads of mine** — fetch them:
|
|
111
113
|
|
|
112
114
|
```
|
|
113
|
-
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py threads -R OWNER/REPO -n N
|
|
115
|
+
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py" threads -R OWNER/REPO -n N
|
|
114
116
|
```
|
|
115
117
|
|
|
116
118
|
Returns unresolved threads whose root comment is mine (threads from pending
|
|
117
|
-
reviews are excluded automatically
|
|
119
|
+
reviews are excluded automatically). A true file-level thread has both
|
|
120
|
+
`line: null` and `original_line: null`; report it as `path:file-level`. An
|
|
121
|
+
outdated line thread can have `line: null`, `original_line: <N>`, and
|
|
122
|
+
`is_outdated: true`; report it at `path:<N>` with an `outdated` label, not as
|
|
123
|
+
file-level.
|
|
118
124
|
For each thread, judge the original comment against the **current** diff
|
|
119
|
-
(`ghreview.py extract` for that path — `is_outdated` means the nearby code
|
|
125
|
+
(`ghreview.py extract` for that path — `is_outdated: true` means the nearby code
|
|
120
126
|
changed, which is a hint, not a verdict) and pick one action, defaulting to
|
|
121
127
|
*leave* when torn:
|
|
122
128
|
|
|
@@ -132,7 +138,7 @@ adjudication is complete.
|
|
|
132
138
|
## Step 2 — Map the diff and pick a route
|
|
133
139
|
|
|
134
140
|
```
|
|
135
|
-
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py map -R OWNER/REPO -n N
|
|
141
|
+
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py" map -R OWNER/REPO -n N
|
|
136
142
|
```
|
|
137
143
|
|
|
138
144
|
Returns per-file addressable-line ranges, `generated` flags (lockfiles, dist,
|
|
@@ -149,7 +155,7 @@ the post-exclusion size:
|
|
|
149
155
|
|
|
150
156
|
Spawn three subagents at once using this harness's spawn mechanism — leo:delegation
|
|
151
157
|
and the *Subagent spawn* row of your mapping name it. Use the read-only
|
|
152
|
-
**
|
|
158
|
+
**review-lens** role, never a general-purpose agent: a lens is the agent that
|
|
153
159
|
actually ingests the attacker-authored diff, and a general-purpose agent
|
|
154
160
|
carries the full tool set including Write, Edit, and unrestricted Bash. This
|
|
155
161
|
skill's `allowed-tools` govern this loop's turn, not the agents it spawns, so
|
|
@@ -166,7 +172,7 @@ sharded review that hits the agent cap.
|
|
|
166
172
|
Do NOT ingest the full diff in this main loop on the standard
|
|
167
173
|
path — the lenses read, you judge. Each lens gets: PR number, `OWNER/REPO`,
|
|
168
174
|
title/body, its file list, and instructions to fetch its own diff slice via
|
|
169
|
-
`gh pr diff N` or `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py extract -R OWNER/REPO -n N <paths…>`
|
|
175
|
+
`gh pr diff N` or `python3 "${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py" extract -R OWNER/REPO -n N <paths…>`
|
|
170
176
|
(resolve the plugin root and pass the absolute path into the prompt — a
|
|
171
177
|
subagent does not inherit your placeholder).
|
|
172
178
|
|
|
@@ -185,8 +191,10 @@ Charters:
|
|
|
185
191
|
behavior, dead code, misleading names, genuine style nits worth a human's
|
|
186
192
|
comment.
|
|
187
193
|
|
|
188
|
-
Each lens returns
|
|
189
|
-
`
|
|
194
|
+
Each lens returns JSON only:
|
|
195
|
+
`{"status":"done"|"needs-context","findings":[{path, line, side:
|
|
196
|
+
"RIGHT"|"LEFT", severity: "blocking"|"major"|"minor"|"nit", confidence:
|
|
197
|
+
0-100, note, fix?}]}`
|
|
190
198
|
with `line` as the absolute new-file line (RIGHT) it verified against the
|
|
191
199
|
patch, and an instruction to cite the exact diff line — unverifiable findings
|
|
192
200
|
get dropped in Step 4, so guessing wastes the lens's own work.
|
|
@@ -234,7 +242,7 @@ resolutions are public and go last, only once staging has succeeded):
|
|
|
234
242
|
(`{"comments": [{path, line, side, body, start_line?, start_side?}]}`), then:
|
|
235
243
|
|
|
236
244
|
```
|
|
237
|
-
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py stage -R OWNER/REPO -n N \
|
|
245
|
+
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py" stage -R OWNER/REPO -n N \
|
|
238
246
|
--commit <headRefOid> --input comments.json --replace-pending
|
|
239
247
|
```
|
|
240
248
|
|
|
@@ -255,7 +263,7 @@ resolutions are public and go last, only once staging has succeeded):
|
|
|
255
263
|
scratchpad file:
|
|
256
264
|
|
|
257
265
|
```
|
|
258
|
-
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py reply -R OWNER/REPO -n N \
|
|
266
|
+
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py" reply -R OWNER/REPO -n N \
|
|
259
267
|
--thread-id PRRT_… --body-file reply.txt
|
|
260
268
|
```
|
|
261
269
|
|
|
@@ -266,7 +274,7 @@ resolutions are public and go last, only once staging has succeeded):
|
|
|
266
274
|
3. **Resolve stale threads** — one call per Step 1 resolve action:
|
|
267
275
|
|
|
268
276
|
```
|
|
269
|
-
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py resolve-thread -R OWNER/REPO -n N \
|
|
277
|
+
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/ghreview.py" resolve-thread -R OWNER/REPO -n N \
|
|
270
278
|
--thread-id PRRT_…
|
|
271
279
|
```
|
|
272
280
|
|
|
@@ -283,6 +291,8 @@ error.
|
|
|
283
291
|
|
|
284
292
|
1. Staged comments as a table: `path:line — comment`.
|
|
285
293
|
2. Existing threads as a table: `path:line — left / resolved / reply staged`
|
|
294
|
+
(use `path:file-level` only when both anchors are null; otherwise use
|
|
295
|
+
`path:original_line` with an `outdated` label when the current line is null)
|
|
286
296
|
(+ what was said in staged replies; note if a stale pending review was
|
|
287
297
|
replaced, and that resolutions are already live).
|
|
288
298
|
3. Unstaged findings (dropped anchors, overflow past the cap) — clearly marked.
|