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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +14 -7
  3. package/adapters/cursor/agents/executor.md +1 -1
  4. package/adapters/cursor/agents/implementer.md +2 -2
  5. package/adapters/cursor/agents/review-lens.md +22 -0
  6. package/adapters/cursor/agents/reviewer.md +2 -2
  7. package/adapters/opencode/agents.json +43 -4
  8. package/adapters/opencode/plugin.js +325 -37
  9. package/config/MCP_PINS.md +17 -0
  10. package/config/models.json +276 -8
  11. package/hooks/bash-guard.py +51 -9
  12. package/package.json +3 -6
  13. package/roles/executor.md +1 -1
  14. package/roles/implementer.md +2 -2
  15. package/roles/review-lens.md +20 -0
  16. package/roles/reviewer.md +2 -2
  17. package/scripts/doctor.py +267 -31
  18. package/scripts/ghreview.py +7 -3
  19. package/scripts/jsonc_bridge.cjs +23 -0
  20. package/scripts/memory.py +74 -35
  21. package/scripts/render_adapters.py +57 -22
  22. package/scripts/resolve_attach_target.py +45 -13
  23. package/scripts/setup.py +1594 -2
  24. package/skills/brainstorming/SKILL.md +3 -1
  25. package/skills/debugging/SKILL.md +4 -2
  26. package/skills/delegation/SKILL.md +10 -8
  27. package/skills/doctor/SKILL.md +33 -14
  28. package/skills/executing-plans/SKILL.md +2 -1
  29. package/skills/finishing-a-branch/SKILL.md +4 -2
  30. package/skills/freshness/SKILL.md +23 -10
  31. package/skills/memory/SKILL.md +12 -2
  32. package/skills/resolve-ticket/SKILL.md +15 -9
  33. package/skills/review-pr/SKILL.md +26 -16
  34. package/skills/setup/SKILL.md +123 -9
  35. package/skills/setup/agents/openai.yaml +5 -0
  36. package/skills/test-first/SKILL.md +3 -1
  37. package/skills/using-leo/SKILL.md +11 -6
  38. package/skills/using-leo/references/claude-mapping.md +2 -1
  39. package/skills/using-leo/references/codex-mapping.md +4 -5
  40. package/skills/using-leo/references/cursor-mapping.md +2 -1
  41. package/skills/using-leo/references/hermes-mapping.md +2 -1
  42. package/skills/using-leo/references/opencode-mapping.md +6 -3
  43. package/skills/verification/SKILL.md +2 -1
  44. package/skills/visual-verification/SKILL.md +2 -1
  45. package/skills/watch-review/SKILL.md +17 -14
  46. package/skills/watch-review/agents/openai.yaml +5 -0
  47. package/skills/worktrees/SKILL.md +3 -1
  48. package/skills/writing-plans/SKILL.md +2 -1
  49. package/skills/writing-skills/SKILL.md +9 -2
  50. package/vendor/jsonc-parser-3.3.1/LICENSE.md +21 -0
  51. package/vendor/jsonc-parser-3.3.1/README.md +26 -0
  52. package/vendor/jsonc-parser-3.3.1/lib/umd/impl/edit.js +201 -0
  53. package/vendor/jsonc-parser-3.3.1/lib/umd/impl/format.js +275 -0
  54. package/vendor/jsonc-parser-3.3.1/lib/umd/impl/parser.js +682 -0
  55. package/vendor/jsonc-parser-3.3.1/lib/umd/impl/scanner.js +456 -0
  56. package/vendor/jsonc-parser-3.3.1/lib/umd/impl/string-intern.js +42 -0
  57. package/vendor/jsonc-parser-3.3.1/lib/umd/main.d.ts +351 -0
  58. package/vendor/jsonc-parser-3.3.1/lib/umd/main.js +194 -0
  59. package/vendor/jsonc-parser-3.3.1/package.json +37 -0
  60. package/workflows/cost-tiered-fix.js +32 -4
@@ -5,7 +5,10 @@ description: >
5
5
  Every harness installs Leo through its own plugin system, and none of them
6
6
  offers an install-time hook, so anything that writes into a file the user
7
7
  already owns is asked for once, here, and recorded in machine-local state.
8
- Idempotent and reversible: running it twice changes nothing the second time.
8
+ Idempotent, but not generally reversible: running it twice changes nothing
9
+ the second time, while removal is harness-specific and manual. Use when Leo
10
+ explicitly requests opt-in setup after installation. Do not use for
11
+ diagnosis or unprompted writes outside the repository.
9
12
  when_to_use: >
10
13
  Leo asks to enable Hermes memory projection, or invokes setup by name after
11
14
  installing on a new machine. NOT for diagnosing whether the plugin loaded
@@ -29,9 +32,9 @@ python3 "${CLAUDE_PLUGIN_ROOT}/scripts/setup.py"
29
32
 
30
33
  `${CLAUDE_PLUGIN_ROOT}` is the Claude Code spelling of the plugin root; Codex
31
34
  exports `$PLUGIN_ROOT`, Cursor `$CURSOR_PLUGIN_ROOT`, and on Hermes and
32
- OpenCode no such variable exists — read the absolute path out of the
33
- machine-local state paragraph in the policy already in your context, which had
34
- its placeholders substituted before injection.
35
+ OpenCode no such variable exists — read the absolute payload path from the
36
+ injected policy's `state.py` or `memory.py` command, which was substituted
37
+ before injection.
35
38
 
36
39
  With no arguments it reports what is on, what is available, and what each
37
40
  feature would actually do right now. It changes nothing. Add `--json` for the
@@ -45,6 +48,113 @@ python3 "${CLAUDE_PLUGIN_ROOT}/scripts/setup.py" disable hermes-memory
45
48
  Enabling something already on prints that and exits 0 — re-running is always
46
49
  safe, and never a reason to check first.
47
50
 
51
+ ## `apply`: bootstrap this harness's MCP servers
52
+
53
+ ```sh
54
+ python3 "${CLAUDE_PLUGIN_ROOT}/scripts/setup.py" apply
55
+ python3 "${CLAUDE_PLUGIN_ROOT}/scripts/setup.py" apply --dry-run
56
+ ```
57
+
58
+ Idempotent, and read-modify-write: `config/models.json`'s `mcp.core` list names
59
+ the servers each harness gets, `apply` detects which harness is actually
60
+ running this script (the same detection `doctor.py` already does —
61
+ never a second, divergent copy of it) and writes only that harness's own
62
+ config, never another one's, even when another harness's config file also
63
+ exists on the machine. `--dry-run` prints the exact commands or diffs and
64
+ touches nothing. An unsupported or undetectable harness refuses outright —
65
+ nothing is touched, and the exit code is non-zero.
66
+
67
+ "Already installed" is always answered by re-reading the harness's own
68
+ config, never by a flag Leo remembers — so removing a server by hand and
69
+ re-running `apply` sees the removal, and running `apply` twice in a row
70
+ writes nothing the second time either way. OpenCode edits are lossless JSONC
71
+ additions: comments, trailing commas, indentation, symlinks and modes survive;
72
+ existing `opencode.jsonc` and `opencode.json` together make setup refuse rather
73
+ than choose. `OPENCODE_CONFIG` wins, otherwise the sole existing global file
74
+ wins, otherwise a new `.jsonc` is used.
75
+
76
+ `apply` is idempotent, **not generally reversible**. It never removes an MCP
77
+ server or tool gate. Remove an automatic CLI registration with the command for
78
+ the harness that owns it:
79
+
80
+ ```sh
81
+ claude mcp remove <name> --scope user
82
+ codex mcp remove <name>
83
+ hermes mcp remove <name>
84
+ ```
85
+
86
+ Cursor has no setup-owned removal command: remove the `mcpServers.<name>` key
87
+ from `~/.cursor/mcp.json`. OpenCode likewise has no MCP removal command: remove
88
+ the `mcp.<name>` key from the resolved `opencode.jsonc` or `opencode.json`, and
89
+ remove any unwanted setup-owned tool gates there. A `.leo-backup` is one
90
+ pre-first-write snapshot, not a conflict-aware restore, transaction log, or
91
+ promise that a later user edit can be undone.
92
+
93
+ `apply` also reports (never flips) two Codex toggles: its `computer_use`
94
+ feature flag and `web_search` mode (offering, never forcing, the upgrade to
95
+ `"live"`), plus one manual Claude in Chrome toggle, which has no config key.
96
+
97
+ Vendor connectors (Slack, Sentry, Linear, ...) live in the same `mcp` config
98
+ under `connectors` — `apply` never installs those; that is the next section.
99
+ Core executable packages are exact reviewed pins. Their maintainer update
100
+ procedure is recorded in `config/MCP_PINS.md`; never substitute `@latest`, a
101
+ range, or an unqualified package name during setup.
102
+
103
+ ## Vendor connectors: `connectors` and `connect`
104
+
105
+ `config/models.json`'s `mcp.connectors` names eleven vendor MCP servers
106
+ (Slack, Sentry, Honeycomb, Snowflake, LaunchDarkly, Linear, Jira +
107
+ Confluence, Gmail, Google Drive, Granola, Vercel) — every one OAuth, every
108
+ one remote HTTP. Unlike `apply`'s core servers, these are never installed
109
+ without a name chosen explicitly. After `apply`, run:
110
+
111
+ ```sh
112
+ python3 "${CLAUDE_PLUGIN_ROOT}/scripts/setup.py" connectors --json
113
+ ```
114
+
115
+ Read-only, and it exits 0 even on a harness `apply` would refuse — it just
116
+ has nothing installable to report. Each entry's `installed` is answered by
117
+ re-reading the harness's own config the same way `apply` does — matching the
118
+ endpoint URL first, a name second, because a claude.ai connector such as
119
+ Gmail or Vercel is registered against the account and never written to
120
+ `~/.claude.json` at all. Never offer one already `installed: true`.
121
+
122
+ For every connector still `installed: false`, see the *Structured question
123
+ to the user* row of your mapping:
124
+
125
+ - **A question tool** (Claude Code, OpenCode): present the not-installed
126
+ connectors as a multi-select, one entry per `label`, and install only what
127
+ is chosen:
128
+
129
+ ```sh
130
+ python3 "${CLAUDE_PLUGIN_ROOT}/scripts/setup.py" connect <key> [<key> ...]
131
+ ```
132
+
133
+ - **No question tool** (Codex, Cursor, Hermes): list them in plain text —
134
+ `key`, `label`, and `authNote` — and **install nothing** unless the user
135
+ names one or more by key in reply. The same default as everywhere else in
136
+ this skill: asking is never itself consent.
137
+
138
+ `snowflake` always needs `needsUrl: true` handled first — its endpoint
139
+ embeds org, account, database and schema, and cannot be guessed from
140
+ anything on the machine. Ask for the account-specific URL before offering it
141
+ in the multi-select (or before accepting it in a plain-text reply), then:
142
+
143
+ ```sh
144
+ python3 "${CLAUDE_PLUGIN_ROOT}/scripts/setup.py" connect snowflake --url <URL>
145
+ ```
146
+
147
+ `connect` refuses outright, writing nothing, on an unsupported harness, an
148
+ unknown registry state, or on `snowflake` with no URL on hand. Slack, Gmail,
149
+ Google Drive, and account-specific providers are manual-only: report their
150
+ prerequisites and never attempt dynamic registration. On Hermes, providers
151
+ that support dynamic registration use `hermes mcp add <key> --url <url> --auth oauth`
152
+ followed by `hermes mcp login <key>`; providers without it remain manual.
153
+ Every successful install reports
154
+ `needs-auth`: setup registers the endpoint and stops there — it never
155
+ handles a credential. Report back to the user, by `label`, which connectors
156
+ now need them to complete a browser OAuth flow on first use.
157
+
48
158
  ## Features
49
159
 
50
160
  ### `hermes-memory`
@@ -78,8 +188,12 @@ Leo's markers.
78
188
 
79
189
  ## What setup never does
80
190
 
81
- It does not install, update, or repair the plugin, and it does not diagnose —
82
- if the question is "did the policy load" or "why can't I invoke this skill",
83
- that is leo:doctor, which reads and never writes. setup only records consent
84
- and flips flags; the projection itself happens at the next session start,
85
- through the same `memory.py` helper every harness already uses.
191
+ It does not install, update, or repair the plugin, handle credentials, or
192
+ diagnose — if the question is "did the policy load" or "why can't I invoke
193
+ this skill", that is leo:doctor, which reads and never writes. Its write
194
+ boundary is explicit consent state, the current harness's automatic core MCP
195
+ registration/config additions, and an explicitly named automatic connector;
196
+ manual providers only print their prerequisites. Hermes projection is applied
197
+ at the next session start through `memory.py`; removing Leo's balanced marker
198
+ block is the only safely reversible projection action. Config additions and
199
+ their one-time backups are not a general rollback mechanism.
@@ -0,0 +1,5 @@
1
+ interface:
2
+ display_name: "Set Up Leo"
3
+ short_description: "Configure Leo's opt-in wiring and MCP services"
4
+ policy:
5
+ allow_implicit_invocation: false
@@ -6,7 +6,9 @@ description: >
6
6
  it fail, then make it pass with the change — the red-to-green transition is
7
7
  the evidence a real guard exists, not a rubber stamp added after the fact.
8
8
  Applies to implementer and executor during implementation; reviewer checks
9
- the resulting coverage as a rubric line.
9
+ the resulting coverage as a rubric line. Use when an implementation changes
10
+ runtime behavior. Do not use for throwaway spikes, docs/config/dependency
11
+ work, or pure UI copy and styling.
10
12
  when_to_use: >
11
13
  Any implementation task that changes runtime behavior — fix, feature,
12
14
  refactor with observable effect — routed through implementer or executor.
@@ -10,7 +10,12 @@ description: >
10
10
 
11
11
  # Leo's global agent directives
12
12
 
13
- These apply in every session on every machine and every harness. Canonical copy: `skills/using-leo/SKILL.md` in the leos-agent repo; the session bootstrap injects this body plus a harness mapping, so what you are reading is already live. Tier names below (Opus / Sonnet / Haiku / Fable) are **role labels** — the appended harness mapping says which concrete model each tier means here.
13
+ These apply in every session on every machine and every harness. Canonical copy: [`plugins/leo/skills/using-leo/SKILL.md`](https://github.com/foxhatleo/leos-agent/blob/main/plugins/leo/skills/using-leo/SKILL.md); the session bootstrap injects this body plus a harness mapping, so what you are reading is already live. Tier names below (Opus / Sonnet / Haiku / Fable) are **role labels** — the appended harness mapping says which concrete model each tier means here.
14
+
15
+ Claude Code's `allowed-tools` are Claude grants only; they do not enforce
16
+ anything on another harness. Portable safety rules therefore belong in role and
17
+ skill prompts, generated adapters, and each harness's native permissions — not
18
+ in a Claude-only allowlist treated as a cross-harness sandbox.
14
19
 
15
20
  ## Model routing
16
21
 
@@ -20,7 +25,7 @@ Tier every task by the kind of work, not per session. When a request spans phase
20
25
  |---|---|---|---|
21
26
  | Investigation | investigate, diagnose, debug, root-cause, "why does…" | Opus | the `investigator` role |
22
27
  | Planning / design | plan, design, architect, decide | Opus | the `planner` role (or the harness's native plan flow at the Opus tier) |
23
- | Implementation | implement, fix, build, refactor, execute | Sonnet | main loop if the session runs at the Sonnet tier, else the `implementer` role |
28
+ | Implementation | implement, fix, build, refactor, execute | Sonnet | the `implementer` role |
24
29
  | Mechanical | rename, codemod, apply known pattern, boilerplate, format | Haiku | the `executor` role |
25
30
  | Review / verification | review, verify, audit, judge | Opus | the `reviewer` role on the real diff |
26
31
  | Hardest problems / arbitration | "use expert", "deep thinking", "deep investigate", Fable by name | Fable | the `expert` role |
@@ -35,7 +40,7 @@ Every implementation request — "fix", "implement", "execute the plan", anythin
35
40
 
36
41
  1. Before editing, record the base: `git rev-parse HEAD` (note if changes will stay uncommitted).
37
42
  2. Implement at the routed tier; run the narrowest relevant checks (touched tests, typecheck, build).
38
- 3. Have the `reviewer` role judge the actual diff, passing the base ref (or "uncommitted working tree") and the original request/plan text. Never self-review instead. Review runs at the Opus tier by default. Downscale to a Sonnet-tier review ONLY for a clearly-trivial diff — ALL of: ≤ 2 files, ≤ ~60 changed lines, mechanical/boilerplate class (rename, format, comment, constant/string tweak, dependency-version bump, test-data edit), and no risky-path match (auth, payments/billing, crypto/secrets, DB migration or schema, CI/CD config, access control). If any condition fails or you are unsure, keep the full Opus-tier review — the default bucket is today's behavior. Never skip review because the change "is small". Only exemptions (no review at all): docs/comment-only diffs, and edits Leo dictated verbatim — and "verbatim" means I gave you the literal text or the literal command, so claiming this exemption requires quoting what I said back in the done report. A paraphrase, an interpretation, or "this is what he meant" is not dictation and gets the normal review.
43
+ 3. Have the `reviewer` role judge the actual diff, passing the base ref (or "uncommitted working tree") and the original request/plan text. Never self-review instead. Review runs at the Opus tier by default. Downscale to a Sonnet-tier review ONLY for a clearly-trivial diff — ALL of: ≤ 2 files, ≤ ~60 changed lines, mechanical/boilerplate class (rename, format, comment, constant/string tweak, dependency-version bump, test-data edit), and no risky-path match (auth, payments/billing, crypto/secrets, DB migration or schema, CI/CD config, access control). This downscale is available only on Codex, where each spawn can select the model and effort; on other harnesses keep the full Opus-tier review. If any condition fails or you are unsure, keep the full Opus-tier review — the default bucket is today's behavior. Never skip review because the change "is small". Only exemptions (no review at all): docs/comment-only diffs, and edits Leo dictated verbatim — and "verbatim" means I gave you the literal text or the literal command, so claiming this exemption requires quoting what I said back in the done report. A paraphrase, an interpretation, or "this is what he meant" is not dictation and gets the normal review.
39
44
  4. Blocking findings: fix at the executing tier, re-review the fix only. ONE cycle — if the second review still blocks, stop and report the findings to Leo instead of looping, offering `expert` arbitration as one of the options (where the Fable rung exists).
40
45
  5. Report done as three lines: what changed / checks run / review verdict.
41
46
 
@@ -46,7 +51,7 @@ The main loop orchestrates; delegated roles do the volume. In an expensive-tier
46
51
  - Locating code, mapping structure → `explore` (Haiku tier), in parallel when questions are independent.
47
52
  - Diagnosis needing a verdict → `investigator` (Opus tier) — ONE per question, fed by cheap exploration; distinct questions may run in parallel, but never fan the same question across multiple Opus-tier agents.
48
53
  - Mechanical edits → `executor` (Haiku tier), fanned across independent items.
49
- - Executing a written plan → `implementer` (Sonnet tier).
54
+ - Normal implementation and executing a written plan → `implementer` (Sonnet tier); `executor` is mechanical work only.
50
55
  - Judging a diff → `reviewer` (Opus tier).
51
56
  - Hardest verdicts and deadlocks → `expert` (Fable tier) — one at a time, never fanned out, never implements; hand it the outcome wanted, the raw artifact paths, and the full failure history (it reads sources itself — don't pre-digest for a stronger model).
52
57
 
@@ -70,7 +75,7 @@ Durable facts are a different thing and do not belong in those JSON files: a pre
70
75
 
71
76
  ## Cost discipline
72
77
 
73
- Spend expensive tokens on planning, verification, and synthesis (low volume, high leverage); spend cheap tokens on execution volume. When dispatching delegated work, pin the tier per task — the `executor` role runs at the Haiku tier for mechanical and boilerplate work and at the Sonnet tier at low effort for ordinary implementation, judges/verifiers at the Opus tier. The Fable tier is the most expensive per call and cheap as a policy only because it fires rarely and only on verdicts — batch fan-outs never auto-use it (that is exactly where a Fable jump silently multiplies cost).
78
+ Spend expensive tokens on planning, verification, and synthesis (low volume, high leverage); spend cheap tokens on mechanical execution volume. When dispatching delegated work, pin the tier per task — `implementer` runs normal implementation at Sonnet, `executor` runs only mechanical and boilerplate work at Haiku, and judges/verifiers run at Opus. The Fable tier is the most expensive per call and cheap as a policy only because it fires rarely and only on verdicts — batch fan-outs never auto-use it (that is exactly where a Fable jump silently multiplies cost).
74
79
 
75
80
  ## Skill index
76
81
 
@@ -93,4 +98,4 @@ Reach for the matching skill at the decision point — each one encodes the mech
93
98
  | Policy or harness wiring in doubt | leo:doctor |
94
99
  | Authoring or editing a skill | leo:writing-skills |
95
100
 
96
- Four operational skills `leo:resolve-ticket`, `leo:review-pr`, `leo:watch-review`, `leo:setup` are invoked by name rather than reached from the table above. One more, `leo:attach-pr`, is Claude Code only and is not registered on any other harness (the harness mapping appended below says so explicitly, and names what else differs here).
101
+ Four operational skills in the canonical roster (`config/models.json`) are invoked by name rather than reached from the table above: `leo:resolve-ticket`, `leo:review-pr`, `leo:watch-review`, and `leo:setup`. Only `setup` and `watch-review` opt out of implicit invocation in Codex metadata; `review-pr`, `resolve-ticket`, and `doctor` remain natural-language routable. One more, `leo:attach-pr`, is Claude Code only and is not registered on any other harness (the harness mapping appended below says so explicitly, and names what else differs here).
@@ -15,11 +15,12 @@
15
15
  | Policy injection | `SessionStart` hook, on every startup / resume / clear / compact |
16
16
  | Subagent spawn | spawn the named native agent; its generated frontmatter pins the model |
17
17
  | Per-spawn model | yes — the agent's own frontmatter |
18
- | Read-only roles | harness-enforced — the tool allowlist omits Write and Edit |
18
+ | Read-only roles | native edit denial — the tool allowlist omits Write and Edit; Bash remains shell-capable, so the read-only prompt and permission constraints are not a hard sandbox |
19
19
  | Worktrees | `EnterWorktree` / `ExitWorktree`, session-tracked and auto-cleaned; pair every Enter with an Exit |
20
20
  | Workflow runner | the Workflow tool runs `workflows/cost-tiered-fix.js` by `scriptPath` |
21
21
  | Follow-up to a live agent | `SendMessage` to the same agent, which keeps the context it already built |
22
22
  | Skill names | `leo:<name>` |
23
+ | Structured question to the user | `AskUserQuestion` — multi-choice, optional multi-select |
23
24
 
24
25
  Visual evidence here: the Browser pane (start or attach a preview, then take a screenshot), an attached Chrome, or the iOS Simulator control tool; some arrive only after a tool search, so an empty tool list is not proof of absence. When no rung answers, leo:visual-verification requires the unverified-change warning in place of a done report.
25
26
 
@@ -6,7 +6,7 @@
6
6
  | Fable | `gpt-5.6-sol` | max |
7
7
  | Opus | `gpt-5.6-sol` | high |
8
8
  | Sonnet | `gpt-5.6-terra` | medium |
9
- | Haiku | `gpt-5.6-luna` | low |
9
+ | Haiku | `gpt-5.6-terra` | low |
10
10
 
11
11
  ## Capabilities here
12
12
 
@@ -18,17 +18,16 @@
18
18
  | Read-only roles | prompt only — a convention, never a guarantee; never route work here that depends on it |
19
19
  | Worktrees | no native tool — raw `git worktree` at `.claude/worktrees/<name>` |
20
20
  | Workflow runner | none — fan out by hand and keep the ledger in `<plugin-root>/scripts/state.py` |
21
- | Follow-up to a live agent | none established re-dispatch cold with the context restated |
21
+ | Follow-up to a live agent | `followup_task` to the same live agent; it retains the context it already built |
22
22
  | Skill names | `leo:<name>` |
23
+ | Structured question to the user | Plan mode `request_user_input` — structured multiple-choice questions; outside Plan mode ask in plain text and default to changing nothing |
23
24
 
24
25
  Visual evidence here: the bundled browser plugin, else computer-use, else Playwright driven from the shell. When no rung answers, leo:visual-verification requires the unverified-change warning in place of a done report.
25
26
 
26
27
  Memory projection here writes to the per-user `AGENTS.md` in the Codex home directory. Only global-scope facts are projected — every per-user surface loads in every repository, so repo facts would leak across projects; they reach the model through the session context block instead. Leo's block is marker-delimited; the rest of the file is untouched.
27
28
 
28
- Tier collapse here: Fable≡Opus (`gpt-5.6-sol`) — routing between collapsed rungs buys role, not power. Fable is not a real rung: `expert` cannot break a deadlock a collapsed Opus already lost, so cap escalation at Opus and report.
29
-
30
29
  ## Leo skills not available here
31
30
 
32
31
  - `leo:attach-pr` — its entire product is a side effect in Claude Code Desktop's PR-card detector, which no other harness has — the same commands would run here, succeed, and produce nothing observable.
33
32
 
34
- Every other skill in the policy's Skill index is registered here and behaves the same, and so are the operational skills — `leo:review-pr`, `leo:resolve-ticket` and `leo:watch-review` all run on this harness. Where they name a capability the table above says is missing, take the fallback each one documents.
33
+ Every other skill in the policy's Skill index is registered here and behaves the same, and so are the operational skills — `leo:resolve-ticket`, `leo:review-pr`, `leo:watch-review`, `leo:setup` all run on this harness. Where they name a capability the table above says is missing, take the fallback each one documents.
@@ -20,6 +20,7 @@
20
20
  | Workflow runner | none — fan out by hand and keep the ledger in `<plugin-root>/scripts/state.py` |
21
21
  | Follow-up to a live agent | none established — re-dispatch cold with the context restated |
22
22
  | Skill names | `leo:<name>` |
23
+ | Structured question to the user | none established — ask in plain text and default to changing nothing |
23
24
 
24
25
  Visual evidence here: Browser Preview against a running dev server, else a Playwright server if one is registered. When no rung answers, leo:visual-verification requires the unverified-change warning in place of a done report.
25
26
 
@@ -31,4 +32,4 @@ Tier collapse here: Opus≡Sonnet (`Grok 4.5`) — routing between collapsed run
31
32
 
32
33
  - `leo:attach-pr` — its entire product is a side effect in Claude Code Desktop's PR-card detector, which no other harness has — the same commands would run here, succeed, and produce nothing observable.
33
34
 
34
- Every other skill in the policy's Skill index is registered here and behaves the same, and so are the operational skills — `leo:review-pr`, `leo:resolve-ticket` and `leo:watch-review` all run on this harness. Where they name a capability the table above says is missing, take the fallback each one documents.
35
+ Every other skill in the policy's Skill index is registered here and behaves the same, and so are the operational skills — `leo:resolve-ticket`, `leo:review-pr`, `leo:watch-review`, `leo:setup` all run on this harness. Where they name a capability the table above says is missing, take the fallback each one documents.
@@ -22,6 +22,7 @@ Provider: `openrouter`
22
22
  | Workflow runner | none — fan out by hand and keep the ledger in `<plugin-root>/scripts/state.py` |
23
23
  | Follow-up to a live agent | none established — re-dispatch cold with the context restated |
24
24
  | Skill names | `leo:<name>` |
25
+ | Structured question to the user | none established — ask in plain text and default to changing nothing |
25
26
 
26
27
  Visual evidence here: no built-in renderer; Playwright driven from the shell is the only rung, and only when the project already depends on it. When no rung answers, leo:visual-verification requires the unverified-change warning in place of a done report.
27
28
 
@@ -33,4 +34,4 @@ Tier collapse here: Fable≡Opus (`moonshotai/kimi-k3`), Sonnet≡Haiku (`z-ai/g
33
34
 
34
35
  - `leo:attach-pr` — its entire product is a side effect in Claude Code Desktop's PR-card detector, which no other harness has — the same commands would run here, succeed, and produce nothing observable.
35
36
 
36
- Every other skill in the policy's Skill index is registered here and behaves the same, and so are the operational skills — `leo:review-pr`, `leo:resolve-ticket` and `leo:watch-review` all run on this harness. Where they name a capability the table above says is missing, take the fallback each one documents.
37
+ Every other skill in the policy's Skill index is registered here and behaves the same, and so are the operational skills — `leo:resolve-ticket`, `leo:review-pr`, `leo:watch-review`, `leo:setup` all run on this harness. Where they name a capability the table above says is missing, take the fallback each one documents.
@@ -17,11 +17,12 @@ Provider: `openrouter`
17
17
  | Policy injection | `config.instructions`, with a system-prompt transform as backstop |
18
18
  | Subagent spawn | registered agent from `agents.json`, spawned via the task tool |
19
19
  | Per-spawn model | no — each agent always runs its registered model, so `reviewer` never downscales on a trivial diff |
20
- | Read-only roles | harness-enforced — generated `permission.edit: deny`, refused by OpenCode itself |
20
+ | Read-only roles | native edit denial — generated `permission.edit: deny`, refused by OpenCode itself; Bash remains shell-capable, so the read-only prompt and permissions are not a hard sandbox |
21
21
  | Worktrees | no native tool — raw `git worktree` at `.claude/worktrees/<name>` |
22
22
  | Workflow runner | no runner — `cost-tiered-fix.js` ships in the package but nothing here executes it; fan out by hand and keep the ledger in `<plugin-root>/scripts/state.py` |
23
23
  | Follow-up to a live agent | none established — re-dispatch cold with the context restated |
24
- | Skill names | bare `<name>` — read every `leo:<x>` above as `<x>` |
24
+ | Skill names | `leo-<name>` — OpenCode has no skill namespace, so the adapter registers a renamed copy; read every `leo:<x>` above as `leo-<x>` |
25
+ | Structured question to the user | native `question` tool — multi-choice, single or multi-select |
25
26
 
26
27
  Visual evidence here: no built-in renderer; a registered Playwright server or the Playwright CLI. When no rung answers, leo:visual-verification requires the unverified-change warning in place of a done report.
27
28
 
@@ -29,8 +30,10 @@ Memory projection here writes to the per-user `AGENTS.md` in the OpenCode config
29
30
 
30
31
  Tier collapse here: Fable≡Opus (`moonshotai/kimi-k3`), Sonnet≡Haiku (`z-ai/glm-5.2`) — routing between collapsed rungs buys role, not power. Fable is not a real rung: `expert` cannot break a deadlock a collapsed Opus already lost, so cap escalation at Opus and report.
31
32
 
33
+ Fable is not a real rung here, so `expert` is not registered as an agent and escalation caps at Opus.
34
+
32
35
  ## Leo skills not available here
33
36
 
34
37
  - `leo:attach-pr` — its entire product is a side effect in Claude Code Desktop's PR-card detector, which no other harness has — the same commands would run here, succeed, and produce nothing observable.
35
38
 
36
- Every other skill in the policy's Skill index is registered here and behaves the same, and so are the operational skills — `leo:review-pr`, `leo:resolve-ticket` and `leo:watch-review` all run on this harness. Where they name a capability the table above says is missing, take the fallback each one documents.
39
+ Every other skill in the policy's Skill index is registered here and behaves the same, and so are the operational skills — `leo:resolve-ticket`, `leo:review-pr`, `leo:watch-review`, `leo:setup` all run on this harness. Where they name a capability the table above says is missing, take the fallback each one documents.
@@ -5,7 +5,8 @@ description: >
5
5
  the main loop, implementer, executor, and anyone reporting completion:
6
6
  a completion claim needs a proving command run in the current turn, whose
7
7
  output was actually read — never a prior run, a "should pass now," or a
8
- subagent's self-report relayed as fact.
8
+ subagent's self-report relayed as fact. Use when making or relaying a
9
+ completion claim. Do not use for in-progress updates or to replace review.
9
10
  when_to_use: >
10
11
  Before writing any completion claim — "tests pass," "build is green,"
11
12
  "bug fixed," "agent finished the task." Also applies when relaying a
@@ -6,7 +6,8 @@ description: >
6
6
  Detection walks a ranked ladder of whatever browser, preview, or simulator
7
7
  tooling this harness exposes; when nothing on the ladder answers, the change
8
8
  is reported with an explicit unverified warning instead of a completion
9
- claim.
9
+ claim. Use when a person can see the changed result. Do not use for
10
+ non-rendered logic, an off feature flag, or as a replacement for tests.
10
11
  when_to_use: >
11
12
  A change whose result someone would notice by looking — layout, styling,
12
13
  on-screen text, a new view or route, a chart, a generated image or rendered
@@ -5,7 +5,9 @@ description: >
5
5
  non-draft PRs where Leo's GitHub user is DIRECTLY requested as reviewer,
6
6
  carry out the review-pr procedure on each new one, and record it in
7
7
  machine-local state so it is never auto-reviewed again. Meant to be
8
- re-invoked on an interval by whatever schedules recurring work here.
8
+ re-invoked on an interval by whatever schedules recurring work here. Use
9
+ when Leo explicitly invokes the watcher only. Do not use because a PR or
10
+ review was merely mentioned.
9
11
  when_to_use: >
10
12
  ONLY when Leo explicitly invokes watch-review (usually on a repeating
11
13
  interval). Never trigger it because a PR or review was merely mentioned —
@@ -27,13 +29,12 @@ whatever this harness offers, or from a shell (`while :; do …; sleep 60; done`
27
29
  or cron). Claude Code's `/loop` is a separate skill that this plugin does not
28
30
  ship, so the scheduler is external on every harness including that one.
29
31
 
30
- A tick is cheap by design: on an idle tick, read the preflight and say one
31
- line. Only a match escalates. Run the idle tick at the Haiku tier and the
32
- review itself at the Opus tier your harness mapping names the concrete
33
- models, and where those two tiers collapse onto one model there is no cheap
34
- rung to tick at, which is worth knowing before running this on a short
35
- interval. If you cannot raise the tier for the review, say so in one line and
36
- let Leo run review-pr directly rather than reviewing a PR at the wrong tier.
32
+ A tick is cheap discovery only: on an idle tick, read the preflight and say one
33
+ line; never load a PR body or diff. Only a match escalates. Run the idle tick
34
+ at the Haiku tier, then hand each match to a **fresh Opus** `review-pr` run
35
+ where the harness supports it. Where it cannot preserve a fresh high-tier
36
+ handoff, emit a cold handoff (PR number, owner/repo, discovered reviewer
37
+ login) and let Leo invoke `review-pr`; do not review at the wrong tier.
37
38
 
38
39
  On Claude Code specifically: do NOT set `disable-model-invocation` in this
39
40
  file — skills marked that way do not execute under `/loop`.
@@ -61,7 +62,7 @@ leo:delegation for the per-harness forms.
61
62
  ```bash
62
63
  gh repo view --json nameWithOwner
63
64
  gh api user --jq .login
64
- gh pr list --state open --search "user-review-requested:@me" \
65
+ gh pr list --state open --search "user-review-requested:<login-from-gh-api>" \
65
66
  --json number,title,isDraft,reviewRequests
66
67
  python3 "${CLAUDE_PLUGIN_ROOT}/scripts/state.py" get review-watcher
67
68
  ```
@@ -71,7 +72,8 @@ one-line diagnosis; touch nothing.
71
72
 
72
73
  ## Filter
73
74
 
74
- `user-review-requested:@me` already matches only PRs where I am **directly**
75
+ Substitute the literal login returned by `gh api user --jq .login`; never rely
76
+ on `@me`. `user-review-requested:<login>` already matches only PRs where I am **directly**
75
77
  requested — a request for a team I belong to does not count and must never
76
78
  trigger a review. Belt and braces, from the preflight list keep only PRs
77
79
  where ALL hold:
@@ -90,10 +92,11 @@ requests for <owner/repo>` — and end the turn. The next tick re-checks.
90
92
 
91
93
  For each remaining PR, in ascending number order, strictly sequentially:
92
94
 
93
- 1. Carry out the **review-pr** procedure for that PR number. Where the harness
94
- has a skill-invocation tool, use it (`leo:review-pr` with the number); where
95
- it does not, read that skill and follow it. Do not improvise a review — the
96
- staged-comment mechanics and the verdict rubric live there.
95
+ 1. Hand off the PR number, `owner/repo`, and literal login to a **fresh Opus**
96
+ **review-pr** run where the harness supports it. Otherwise make a cold
97
+ handoff to Leo and stop before any review action. Do not improvise a review
98
+ in this cheap tick — the staged-comment mechanics and verdict rubric live
99
+ in review-pr.
97
100
  2. **Only after the review completes** (verdict delivered), record it:
98
101
 
99
102
  ```bash
@@ -0,0 +1,5 @@
1
+ interface:
2
+ display_name: "Watch Pull Request Reviews"
3
+ short_description: "Check directly requested pull request reviews"
4
+ policy:
5
+ allow_implicit_invocation: false
@@ -4,7 +4,9 @@ description: >
4
4
  Worktree lifecycle mechanics for isolated branch work — detect, create,
5
5
  and clean up a git worktree so implementation happens off the main
6
6
  checkout. Shared by resolve-ticket, executing-plans, and delegation
7
- fan-outs; not itself a workflow, just the plumbing they all call into.
7
+ fan-outs; not itself a workflow, just the plumbing they all call into. Use
8
+ when creating or tearing down isolated branch work. Do not use to decide
9
+ whether isolation is needed or to dispose of a finished branch.
8
10
  when_to_use: >
9
11
  Any skill or agent about to create or tear down a worktree for isolated
10
12
  branch work. NOT for choosing whether isolation is needed in the first
@@ -5,7 +5,8 @@ description: >
5
5
  plan is done when a Sonnet implementer can execute it without making a
6
6
  single design decision — every step names exact files, shows literal
7
7
  code or commands, and states how to verify it, anchored to a recorded
8
- base ref.
8
+ base ref. Use when writing or reviewing a multi-step implementation plan.
9
+ Do not use to choose an approach or to implement or review the plan's diff.
9
10
  when_to_use: >
10
11
  Writing or reviewing a plan before handoff to leo:executing-plans —
11
12
  planner-agent output, plan-mode output, or any multi-step change spec.
@@ -6,7 +6,9 @@ description: >
6
6
  correctly, the closed-exemption-list structure the existing skills share,
7
7
  and where a personal skill file goes on each harness so it loads beside
8
8
  the plugin's own. Covers both skills that ship with the plugin and
9
- personal ones kept outside it.
9
+ personal ones kept outside it. Use when authoring a skill or choosing its
10
+ personal load path. Do not use to decide whether a process needs a skill or
11
+ to change plugin packaging or loaders.
10
12
  when_to_use: >
11
13
  Writing a new skill, revising an existing one's frontmatter, or deciding
12
14
  where to put a personal skill so a harness picks it up. NOT for deciding
@@ -110,7 +112,12 @@ not obviously point at the omission:
110
112
  2. A row in the policy's skill index — keep it short, since that table is
111
113
  injected into every session on every harness and the smallest budget wins.
112
114
  3. At least one `leo:<name>` reference from some file other than its own body.
113
- 4. The roster constants in the test suite, and the skill list in the README.
115
+ 4. The roster constants and metadata tests in the test suite, plus the
116
+ appropriate registration class: portable skills in `skills/`, Claude-only
117
+ skills in `skills-claude/`, and harness metadata under `agents/openai.yaml`
118
+ only when that skill needs Codex invocation policy. Keep the `leo:`
119
+ namespace in portable policy prose; OpenCode's generated copy uses
120
+ `leo-<name>` because it has no namespace.
114
121
 
115
122
  Write example tokens as `leo:<name>` with the angle brackets. A literal
116
123
  placeholder like a made-up skill name is scanned as a real reference and fails
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) Microsoft
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,26 @@
1
+ # jsonc-parser provenance
2
+
3
+ OpenCode configuration edits use `jsonc-parser` 3.3.1's `modify` plus
4
+ `applyEdits` operations through `scripts/jsonc_bridge.cjs`. It is vendored
5
+ rather than loaded at setup time: setup must be deterministic, work offline,
6
+ and must not turn a user-approved config edit into an unreviewed mutable
7
+ install.
8
+
9
+ Reviewed registry artifact: [jsonc-parser 3.3.1](https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz), MIT.
10
+
11
+ - npm SHA-1: `f2a524b4f7fd11e3d791e559977ad60b98b798b4`
12
+ - npm integrity: `sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==`
13
+ - fetched tarball SHA-256: `4a0315b8671e7463bae7af7c142cdf19e9aa7ba39eb36dc2df383b8648e3cbc9`
14
+
15
+ The vendored files are `LICENSE.md`, `package.json`, and the complete
16
+ dependency-free `lib/umd/` runtime used by the bridge.
17
+
18
+ Update procedure: download that exact registry tarball, verify its SHA-256
19
+ against the reviewed value above, replace only those files, then run both
20
+ `python3 -m unittest tests.test_setup` and `python3.14 -m unittest tests.test_setup`
21
+ plus `python3 -m unittest tests.test_release`. Review the new release and
22
+ record its exact registry URL, SHA-1, SHA-256, integrity, and version here.
23
+ Core MCP executable pins have their separate review procedure in
24
+ `config/MCP_PINS.md`. Preserve the add-only rule, comments, trailing
25
+ commas, indentation, symlinks, and file modes. Never replace a JSONC edit with
26
+ `JSON.stringify` or `json.dumps`.