leos-agent 7.0.0 → 10.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.
Files changed (96) hide show
  1. package/README.md +544 -28
  2. package/commands/handoff.md +11 -0
  3. package/commands/handon.md +10 -0
  4. package/commands/review-pr.md +9 -0
  5. package/commands-claude/watch-review.md +9 -0
  6. package/index.js +12 -0
  7. package/package.json +29 -14
  8. package/payload/codex-agents/leo-executor.toml +36 -0
  9. package/payload/codex-agents/leo-runner.toml +28 -0
  10. package/rules/preferences.md +97 -0
  11. package/scripts/check.py +244 -0
  12. package/scripts/ghreview.py +17 -3
  13. package/scripts/handoff.py +183 -0
  14. package/scripts/leo-install.py +509 -0
  15. package/scripts/measure_context.py +113 -0
  16. package/scripts/publish-npm.py +138 -0
  17. package/scripts/watch_review.py +169 -0
  18. package/skills/doctor/SKILL.md +73 -115
  19. package/skills/doctor/agents/openai.yaml +5 -0
  20. package/skills/handoff/SKILL.md +99 -0
  21. package/skills/handoff/agents/openai.yaml +5 -0
  22. package/skills/handon/SKILL.md +61 -0
  23. package/skills/install/SKILL.md +79 -0
  24. package/skills/install/agents/openai.yaml +5 -0
  25. package/skills/review-pr/SKILL.md +59 -318
  26. package/skills/review-pr/reference/lenses.md +67 -0
  27. package/skills/review-pr/reference/procedure.md +348 -0
  28. package/skills-claude/attach-pr/SKILL.md +178 -0
  29. package/skills-claude/watch-review/SKILL.md +91 -0
  30. package/adapters/cursor/agents/executor.md +0 -17
  31. package/adapters/cursor/agents/expert.md +0 -70
  32. package/adapters/cursor/agents/explore.md +0 -16
  33. package/adapters/cursor/agents/implementer.md +0 -18
  34. package/adapters/cursor/agents/investigator.md +0 -18
  35. package/adapters/cursor/agents/planner.md +0 -28
  36. package/adapters/cursor/agents/review-lens.md +0 -22
  37. package/adapters/cursor/agents/reviewer.md +0 -34
  38. package/adapters/opencode/agents.json +0 -105
  39. package/adapters/opencode/plugin.js +0 -576
  40. package/config/MCP_PINS.md +0 -17
  41. package/config/models.json +0 -676
  42. package/hooks/bash-guard.py +0 -583
  43. package/hooks/cursor-guard.py +0 -84
  44. package/hooks/hooks-cursor.json +0 -11
  45. package/hooks/hooks.json +0 -20
  46. package/hooks/session-start.py +0 -148
  47. package/roles/executor.md +0 -15
  48. package/roles/expert.md +0 -67
  49. package/roles/explore.md +0 -13
  50. package/roles/implementer.md +0 -16
  51. package/roles/investigator.md +0 -15
  52. package/roles/planner.md +0 -25
  53. package/roles/review-lens.md +0 -20
  54. package/roles/reviewer.md +0 -31
  55. package/scripts/doctor.py +0 -520
  56. package/scripts/jsonc_bridge.cjs +0 -23
  57. package/scripts/memory.py +0 -744
  58. package/scripts/render_adapters.py +0 -508
  59. package/scripts/setup.py +0 -1753
  60. package/settings.json +0 -7
  61. package/skills/.gitkeep +0 -0
  62. package/skills/brainstorming/SKILL.md +0 -111
  63. package/skills/debugging/SKILL.md +0 -100
  64. package/skills/delegation/SKILL.md +0 -143
  65. package/skills/executing-plans/SKILL.md +0 -117
  66. package/skills/finishing-a-branch/SKILL.md +0 -125
  67. package/skills/freshness/SKILL.md +0 -131
  68. package/skills/memory/SKILL.md +0 -154
  69. package/skills/resolve-ticket/SKILL.md +0 -275
  70. package/skills/setup/SKILL.md +0 -199
  71. package/skills/setup/agents/openai.yaml +0 -5
  72. package/skills/test-first/SKILL.md +0 -92
  73. package/skills/using-leo/SKILL.md +0 -101
  74. package/skills/using-leo/references/claude-mapping.md +0 -33
  75. package/skills/using-leo/references/codex-mapping.md +0 -33
  76. package/skills/using-leo/references/cursor-mapping.md +0 -35
  77. package/skills/using-leo/references/hermes-mapping.md +0 -37
  78. package/skills/using-leo/references/opencode-mapping.md +0 -39
  79. package/skills/verification/SKILL.md +0 -110
  80. package/skills/visual-verification/SKILL.md +0 -115
  81. package/skills/watch-review/SKILL.md +0 -128
  82. package/skills/watch-review/agents/openai.yaml +0 -5
  83. package/skills/worktrees/SKILL.md +0 -131
  84. package/skills/writing-plans/SKILL.md +0 -97
  85. package/skills/writing-skills/SKILL.md +0 -141
  86. package/vendor/jsonc-parser-3.3.1/LICENSE.md +0 -21
  87. package/vendor/jsonc-parser-3.3.1/README.md +0 -26
  88. package/vendor/jsonc-parser-3.3.1/lib/umd/impl/edit.js +0 -201
  89. package/vendor/jsonc-parser-3.3.1/lib/umd/impl/format.js +0 -275
  90. package/vendor/jsonc-parser-3.3.1/lib/umd/impl/parser.js +0 -682
  91. package/vendor/jsonc-parser-3.3.1/lib/umd/impl/scanner.js +0 -456
  92. package/vendor/jsonc-parser-3.3.1/lib/umd/impl/string-intern.js +0 -42
  93. package/vendor/jsonc-parser-3.3.1/lib/umd/main.d.ts +0 -351
  94. package/vendor/jsonc-parser-3.3.1/lib/umd/main.js +0 -194
  95. package/vendor/jsonc-parser-3.3.1/package.json +0 -37
  96. package/workflows/cost-tiered-fix.js +0 -287
@@ -1,199 +0,0 @@
1
- ---
2
- name: setup
3
- description: >
4
- Turn on the opt-in wiring a plugin install cannot turn on for itself.
5
- Every harness installs Leo through its own plugin system, and none of them
6
- offers an install-time hook, so anything that writes into a file the user
7
- already owns is asked for once, here, and recorded in machine-local state.
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.
12
- when_to_use: >
13
- Leo asks to enable Hermes memory projection, or invokes setup by name after
14
- installing on a new machine. NOT for diagnosing whether the plugin loaded
15
- (that is leo:doctor, which reports and never changes anything), and NOT
16
- something to run unprompted — it writes to a file outside the repository.
17
- ---
18
-
19
- # setup
20
-
21
- Leo's Agent installs through each harness's own plugin system. None of those
22
- systems runs arbitrary code at install time — Hermes' `register()` fires at
23
- session start, not on `hermes plugins install` — so there is no moment during
24
- installation at which consent for a write outside the plugin could be implied.
25
- Anything with that blast radius lives behind this command instead.
26
-
27
- ## Run it
28
-
29
- ```sh
30
- python3 "${CLAUDE_PLUGIN_ROOT}/scripts/setup.py"
31
- ```
32
-
33
- `${CLAUDE_PLUGIN_ROOT}` is the Claude Code spelling of the plugin root; Codex
34
- exports `$PLUGIN_ROOT`, Cursor `$CURSOR_PLUGIN_ROOT`, and on Hermes and
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.
38
-
39
- With no arguments it reports what is on, what is available, and what each
40
- feature would actually do right now. It changes nothing. Add `--json` for the
41
- same facts as data.
42
-
43
- ```sh
44
- python3 "${CLAUDE_PLUGIN_ROOT}/scripts/setup.py" enable hermes-memory
45
- python3 "${CLAUDE_PLUGIN_ROOT}/scripts/setup.py" disable hermes-memory
46
- ```
47
-
48
- Enabling something already on prints that and exits 0 — re-running is always
49
- safe, and never a reason to check first.
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
-
158
- ## Features
159
-
160
- ### `hermes-memory`
161
-
162
- Projects the **global** memory facts into `$HERMES_HOME/SOUL.md` (default
163
- `~/.hermes/SOUL.md`), the same marker-spliced block the other four harnesses
164
- receive in their own per-user file.
165
-
166
- It is the one projection target that is opt-in, because it is the one whose
167
- file is not simply a place for user instructions: `SOUL.md` is the agent's
168
- identity prompt and the opening section of every Hermes system prompt on that
169
- machine. The safeguards are the same as everywhere else, plus one:
170
-
171
- - Only global-scope facts. Repo facts never leave the store — every per-user
172
- file loads in every repository, so projecting them would leak one project's
173
- memories into unrelated sessions.
174
- - Everything outside Leo's `BEGIN`/`END` markers is preserved byte for byte,
175
- and one `SOUL.md.leo-backup` is taken before the first ever write.
176
- - Unbalanced or duplicated markers abort the write and report an error rather
177
- than guessing which block is Leo's.
178
- - **The file is never created.** Hermes falls back to a built-in persona when
179
- `SOUL.md` is absent, so creating it would silently replace the user's agent
180
- identity. Enabled with no `SOUL.md` present reports `skipped:no-soul` and
181
- does nothing. Write the file yourself and the next session splices into it.
182
-
183
- `LEOS_AGENT_NO_PROJECT=1` still disables all projection, including this one.
184
-
185
- Hermes' `memories/MEMORY.md` and `memories/USER.md` are deliberately **not**
186
- targets: the agent owns those through its own memory tool and would overwrite
187
- Leo's markers.
188
-
189
- ## What setup never does
190
-
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.
@@ -1,5 +0,0 @@
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
@@ -1,92 +0,0 @@
1
- ---
2
- name: test-first
3
- description: >
4
- Failing-test-first as the default for runtime-behavior changes. Before
5
- writing the change, write a test that fails for the intended reason, watch
6
- it fail, then make it pass with the change — the red-to-green transition is
7
- the evidence a real guard exists, not a rubber stamp added after the fact.
8
- Applies to implementer and executor during implementation; reviewer checks
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.
12
- when_to_use: >
13
- Any implementation task that changes runtime behavior — fix, feature,
14
- refactor with observable effect — routed through implementer or executor.
15
- NOT for spikes/throwaway exploration that gets deleted, NOT for
16
- docs/comments/config/dependency-bump edits, and NOT for pure UI copy or
17
- styling tweaks — see Exemptions below for the full closed list.
18
- ---
19
-
20
- # test-first
21
-
22
- **Core rule**: before writing the change, write a failing test — and watch
23
- it fail — for the reason the change is supposed to fix. Then make it pass.
24
- A test that passes on its first run proves nothing about what it guards; it
25
- could be checking the wrong thing, hitting a no-op path, or asserting
26
- something already true.
27
-
28
- ## When it fires
29
-
30
- Any task that changes runtime behavior: a bug fix, a new code path, a
31
- refactor that alters observable output. If the diff can make a program do
32
- something different, this skill applies before the diff is written.
33
-
34
- ## When it doesn't — Exemptions
35
-
36
- A closed, named list. Outside it, the default holds — no free pass by
37
- analogy, no "this one's basically like a spike."
38
-
39
- 1. **Spike** — throwaway exploration that gets deleted, never merged. If it
40
- survives into the diff, it was not a spike; go back and cover it.
41
- 2. **Docs / comments / config / dependency bumps** — no runtime behavior
42
- changes, nothing to guard with a test.
43
- 3. **Pure UI copy or styling tweaks** — text or CSS changes with no logic
44
- branch behind them.
45
-
46
- A skip must name its exemption in the report — "skipped test-first: spike,
47
- deleted before merge" or "skipped test-first: config only." An unnamed skip
48
- is not a skip; treat it as coverage missing.
49
-
50
- ## Procedure
51
-
52
- 1. Write the test first, targeting the exact failure the change is meant to
53
- fix (the bug's symptom, or the new behavior's absence).
54
- 2. Run it. Watch it fail — and confirm it fails for the intended reason, not
55
- a typo, import error, or wrong assertion. A red test that fails for the
56
- wrong reason is as useless as one that never went red.
57
- 3. Make the change.
58
- 4. Run the test again. Green confirms the change closed the gap the red run
59
- opened — this red-to-green transition is the evidence, and it's the same
60
- evidence leo:verification asks for when confirming a change actually
61
- works end-to-end: don't produce it twice in different words, point to it.
62
- 5. Report which exemption applied, or report the red-then-green pair (what
63
- failed, what changed, what passed).
64
-
65
- ## Self-talk to catch
66
-
67
- - "I'll add the test after, same effect" — it isn't. A test written against
68
- passing code never proves it can fail; you've verified the assertion
69
- compiles, not that it guards anything.
70
- - "This is basically a spike" — if it's in the diff you're about to submit,
71
- it isn't a spike. Spikes get deleted, not merged.
72
- - "It's small, not worth a test" — size isn't in the exemption list.
73
- Behavior change is the trigger, not line count.
74
- - "I ran it and it passed, close enough" — passing without ever having seen
75
- it fail is not evidence. Go back and force the fail first.
76
-
77
- ## Reviewable finding
78
-
79
- Changed runtime behavior with no test that would fail without the change is
80
- a reviewable finding — blocking when the behavior is load-bearing (the
81
- user-facing or system-critical path the task was actually about), otherwise
82
- non-blocking. The reviewer checks for the red-to-green evidence, not for
83
- test existence alone: a test that was never watched failing doesn't clear
84
- the bar even if one exists in the diff.
85
-
86
- ## Works with
87
-
88
- - leo:verification — shares the red-to-green transition as evidence of a
89
- real fix; don't duplicate the check, cite it.
90
- - reviewer — enforces the coverage rubric line above on the actual diff.
91
- - implementer, executor — the tiers that own writing the failing test and
92
- then the fix.
@@ -1,101 +0,0 @@
1
- ---
2
- name: using-leo
3
- description: >
4
- Leo's global operating policy: cost-tiered model routing, the
5
- execute-then-review gate, delegation rules, orchestration triggers,
6
- machine-local state, and the index of leo:* process skills. Injected
7
- into every session by the harness bootstrap (with a per-harness mapping
8
- appended) — it is context, not a skill to run.
9
- ---
10
-
11
- # Leo's global agent directives
12
-
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.
19
-
20
- ## Model routing
21
-
22
- Tier every task by the kind of work, not per session. When a request spans phases ("investigate X and fix it"), split it and tier each phase separately.
23
-
24
- | Work type | Typical verbs | Tier | Do it via |
25
- |---|---|---|---|
26
- | Investigation | investigate, diagnose, debug, root-cause, "why does…" | Opus | the `investigator` role |
27
- | Planning / design | plan, design, architect, decide | Opus | the `planner` role (or the harness's native plan flow at the Opus tier) |
28
- | Implementation | implement, fix, build, refactor, execute | Sonnet | the `implementer` role |
29
- | Mechanical | rename, codemod, apply known pattern, boilerplate, format | Haiku | the `executor` role |
30
- | Review / verification | review, verify, audit, judge | Opus | the `reviewer` role on the real diff |
31
- | Hardest problems / arbitration | "use expert", "deep thinking", "deep investigate", Fable by name | Fable | the `expert` role |
32
-
33
- Code location and structure-mapping that precedes any tiered work above goes to `explore` (Haiku tier, read-only) — cheap scouting that feeds the roles in the table; it returns file:line locations, never verdicts.
34
-
35
- **Escalate, don't struggle**: if a cheap-tier task turns out ambiguous or fails twice, step up one tier rather than retrying at the same tier. When the right tier is unclear, default up — **capped at Opus**. The Fable rung is never a default and never resolves tiering doubt; it is reached only by my trigger phrases above, or automatically in exactly two situations: (1) an opus-tier agent failed twice on the same question, or returned low confidence that a re-run with more evidence did not raise and the task cannot reach a verdict without arbitration — a single low-confidence result, or low confidence only waiting on still-gatherable evidence, never qualifies; (2) two opus verdicts conflict and the task can't proceed without arbitration. Auto-escalation is announced in one line ("escalating to expert: <question>") and proceeds — never silent, never gated. On a harness with no Fable tier (see the mapping), escalation caps at Opus: stop and report to Leo instead, offering to continue at the Opus tier or hand off to a harness that has the expert rung.
36
-
37
- ## Execute means execute-then-review
38
-
39
- Every implementation request — "fix", "implement", "execute the plan", anything that changes code — implicitly includes a review phase, whether or not review was mentioned. Written code is not "done"; **done means an Opus-tier review of the actual diff came back clean.**
40
-
41
- 1. Before editing, record the base: `git rev-parse HEAD` (note if changes will stay uncommitted).
42
- 2. Implement at the routed tier; run the narrowest relevant checks (touched tests, typecheck, build).
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.
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).
45
- 5. Report done as three lines: what changed / checks run / review verdict.
46
-
47
- ## Delegate the labor
48
-
49
- The main loop orchestrates; delegated roles do the volume. In an expensive-tier session, inline bulk work burns the expensive tier — delegate down:
50
-
51
- - Locating code, mapping structure → `explore` (Haiku tier), in parallel when questions are independent.
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.
53
- - Mechanical edits → `executor` (Haiku tier), fanned across independent items.
54
- - Normal implementation and executing a written plan → `implementer` (Sonnet tier); `executor` is mechanical work only.
55
- - Judging a diff → `reviewer` (Opus tier).
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).
57
-
58
- Scale to complexity: simple lookup = 1 agent; comparing a few areas = 2–4 in parallel; large parallel workloads = orchestration triggers below. A fan-out costs roughly an order of magnitude more than a single chat — reserve it for genuinely parallel, high-value work. In an expensive-tier session this is a hard rule, not a heuristic: implementation and mechanical edits MUST go to `implementer`/`executor`, and code searches to `explore`; editing or grepping inline is the exception, reserved for a trivial single-file touch (< ~10 lines) where writing the spec would cost more than the change. More than ~3 inline file edits or ~5 inline searches in an expensive-tier session means the work should have been delegated. Dispatch mechanics — brief structure, the return-status contract, durable progress — live in leo:delegation.
59
-
60
- ## Agent teams
61
-
62
- Where the harness offers persistent teammates rather than one-shot subagents, the topology changes but nothing above relaxes. Every rule in this policy binds a teammate exactly as it binds a dispatched role: execute-then-review still gates "done", one investigator per question still holds, `expert` is still never fanned out, and every teammate is still tier-pinned — an unpinned teammate inherits the session tier and quietly bills a judge's rate for an executor's work. Verdicts route through the main loop: peer messages coordinate, they never approve. Reach for a team only when a role must *accompany* the work — a reviewer watching an implementer's long run, an investigator unblocking it live. Batch-shaped work stays with fan-out or the workflow tool, which is cheaper and already has ledger-backed progress.
63
-
64
- ## Orchestration triggers
65
-
66
- These phrases are my standing opt-in to multi-agent orchestration: **"fan this out"**, **"workflow this"**, **"grind on this"**, **"do this properly"**.
67
-
68
- For a non-trivial task where I haven't used a trigger phrase, propose orchestration in one line (rough shape: agent count + model mix) and proceed single-agent unless I take the offer. Never launch a large fan-out silently. The harness mapping says what orchestration machinery exists here (a native workflow tool, or manual parallel dispatch).
69
-
70
- ## Machine-local state
71
-
72
- Any skill or agent that needs to persist information writes JSON to `$LEOS_AGENT_LOCAL_PATH/<skill-or-agent-name>.json` — `LEOS_AGENT_LOCAL_PATH` is an optional override, unset it defaults to `~/.leos-agent-local` (in bash: `${LEOS_AGENT_LOCAL_PATH:-$HOME/.leos-agent-local}`). Top-level keys are `owner/repo` (or the absolute project path when there's no GitHub repo): **data always stays separate per repo/project**. Read and write through `python3 "${CLAUDE_PLUGIN_ROOT}/scripts/state.py"` (`get` / `merge` / `path`) instead of hand-rolling read-modify-write — the code ships with the plugin, the data stays under `${LEOS_AGENT_LOCAL_PATH:-$HOME/.leos-agent-local}/`, gitignored, per-machine, never synced, and survives plugin updates. Examples: `review-watcher.json` (PR numbers already auto-reviewed), `resolve-ticket.json` (ticket-prefix → tracker mappings).
73
-
74
- Durable facts are a different thing and do not belong in those JSON files: a preference, a repo rule the code never states, a settled decision goes to the memory store at `$LEOS_AGENT_LOCAL_PATH/memory/`, one fact per file, through `python3 "${CLAUDE_PLUGIN_ROOT}/scripts/memory.py"` and leo:memory. That store is canonical and each harness's own memory surface receives a generated copy of the global facts, so a preference learned on one harness is in front of me on the next. Its index is appended below when the store is not empty.
75
-
76
- ## Cost discipline
77
-
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).
79
-
80
- ## Skill index
81
-
82
- Reach for the matching skill at the decision point — each one encodes the mechanics these directives already assume, sized to the work, not extra ritual.
83
-
84
- | At this point | Consult |
85
- |---|---|
86
- | A bug or failing test, before any fix | leo:debugging |
87
- | An approach not yet settled, before non-trivial code | leo:brainstorming |
88
- | Turning a chosen approach into a plan | leo:writing-plans |
89
- | Carrying out a written plan | leo:executing-plans |
90
- | Adding or changing runtime behavior | leo:test-first |
91
- | Coding against a third-party API | leo:freshness |
92
- | Before claiming anything done / fixed / passing | leo:verification |
93
- | A UI-visible change, before done | leo:visual-verification |
94
- | Dispatching subagents or a fan-out | leo:delegation |
95
- | Isolating branch work | leo:worktrees |
96
- | Landing or cleaning up a finished branch | leo:finishing-a-branch |
97
- | A durable fact surfaces, or one turns out wrong | leo:memory |
98
- | Policy or harness wiring in doubt | leo:doctor |
99
- | Authoring or editing a skill | leo:writing-skills |
100
-
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).
@@ -1,33 +0,0 @@
1
- <!-- Generated by scripts/render_adapters.py; do not edit. -->
2
- # Claude Code mapping
3
-
4
- | Tier | Model | Effort |
5
- |---|---|---|
6
- | Fable | `fable` | max |
7
- | Opus | `opus` | native default |
8
- | Sonnet | `sonnet` | native default |
9
- | Haiku | `haiku` | native default |
10
-
11
- ## Capabilities here
12
-
13
- | Capability | Here |
14
- |---|---|
15
- | Policy injection | `SessionStart` hook, on every startup / resume / clear / compact |
16
- | Subagent spawn | spawn the named native agent; its generated frontmatter pins the model |
17
- | Per-spawn model | yes — the agent's own frontmatter |
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
- | Worktrees | `EnterWorktree` / `ExitWorktree`, session-tracked and auto-cleaned; pair every Enter with an Exit |
20
- | Workflow runner | the Workflow tool runs `workflows/cost-tiered-fix.js` by `scriptPath` |
21
- | Follow-up to a live agent | `SendMessage` to the same agent, which keeps the context it already built |
22
- | Skill names | `leo:<name>` |
23
- | Structured question to the user | `AskUserQuestion` — multi-choice, optional multi-select |
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.
26
-
27
- Memory projection here writes to the per-user `CLAUDE.md` in the Claude config 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.
28
-
29
- ## Leo skills only available here
30
-
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.
32
-
33
- Every other skill in the policy's Skill index is registered on every harness and behaves the same. These are not, so a procedure that leans on one of them does not transfer.
@@ -1,33 +0,0 @@
1
- <!-- Generated by scripts/render_adapters.py; do not edit. -->
2
- # Codex mapping
3
-
4
- | Tier | Model | Effort |
5
- |---|---|---|
6
- | Fable | `gpt-5.6-sol` | max |
7
- | Opus | `gpt-5.6-sol` | high |
8
- | Sonnet | `gpt-5.6-terra` | medium |
9
- | Haiku | `gpt-5.6-terra` | low |
10
-
11
- ## Capabilities here
12
-
13
- | Capability | Here |
14
- |---|---|
15
- | Policy injection | `SessionStart` hook, on every startup / resume / clear / compact |
16
- | Subagent spawn | generic subagent with `roles/<role>.md` pasted in |
17
- | Per-spawn model | yes — pass `model` and `reasoning_effort` explicitly; a user or `AGENTS.md` override still wins |
18
- | Read-only roles | prompt only — a convention, never a guarantee; never route work here that depends on it |
19
- | Worktrees | no native tool — raw `git worktree` at `.claude/worktrees/<name>` |
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 | `followup_task` to the same live agent; it retains the context it already built |
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 |
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.
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.
28
-
29
- ## Leo skills not available here
30
-
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.
32
-
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.
@@ -1,35 +0,0 @@
1
- <!-- Generated by scripts/render_adapters.py; do not edit. -->
2
- # Cursor mapping
3
-
4
- | Tier | Model | Effort |
5
- |---|---|---|
6
- | Fable | `GPT-5.6 Sol` | native default |
7
- | Opus | `Grok 4.5` | native default |
8
- | Sonnet | `Grok 4.5` | native default |
9
- | Haiku | `Composer 2.5` | native default |
10
-
11
- ## Capabilities here
12
-
13
- | Capability | Here |
14
- |---|---|
15
- | Policy injection | `sessionStart` hook, every session |
16
- | Subagent spawn | plugin agent from the generated Cursor agents directory |
17
- | Per-spawn model | no — agents are `model: inherit`; select the tier's model in the UI before a homogeneous batch |
18
- | Read-only roles | harness-enforced — generated `readonly: true` |
19
- | Worktrees | no native tool — raw `git worktree` at `.claude/worktrees/<name>` |
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 |
22
- | Skill names | `leo:<name>` |
23
- | Structured question to the user | none established — ask in plain text and default to changing nothing |
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.
26
-
27
- Memory projection here writes to a generated rules file in the per-user Cursor rules 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.
28
-
29
- Tier collapse here: Opus≡Sonnet (`Grok 4.5`) — routing between collapsed rungs buys role, not power.
30
-
31
- ## Leo skills not available here
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.
34
-
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.
@@ -1,37 +0,0 @@
1
- <!-- Generated by scripts/render_adapters.py; do not edit. -->
2
- # Hermes mapping
3
-
4
- Provider: `openrouter`
5
-
6
- | Tier | Model | Effort |
7
- |---|---|---|
8
- | Fable | `moonshotai/kimi-k3` | native default |
9
- | Opus | `moonshotai/kimi-k3` | native default |
10
- | Sonnet | `z-ai/glm-5.2` | native default |
11
- | Haiku | `z-ai/glm-5.2` | native default |
12
-
13
- ## Capabilities here
14
-
15
- | Capability | Here |
16
- |---|---|
17
- | Policy injection | rides the session's first tool result — so a session that runs no tool gets none; read `leo:using-leo` if the policy is not already in your context |
18
- | Subagent spawn | native `delegate_task`, canonical role prompt pasted in |
19
- | Per-spawn model | no — one `delegation.model` for every child, so batch homogeneous Kimi or GLM work and switch it between batches |
20
- | Read-only roles | prompt only — a convention, never a guarantee; never route work here that depends on it |
21
- | Worktrees | no native tool — raw `git worktree` at `.claude/worktrees/<name>` |
22
- | Workflow runner | none — fan out by hand and keep the ledger in `<plugin-root>/scripts/state.py` |
23
- | Follow-up to a live agent | none established — re-dispatch cold with the context restated |
24
- | Skill names | `leo:<name>` |
25
- | Structured question to the user | none established — ask in plain text and default to changing nothing |
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.
28
-
29
- Memory projection here writes to `SOUL.md` in the Hermes home, and only once `leo:setup enable hermes-memory` turns it on — that file is the agent's own identity prompt, so it is never written to unasked and never created. 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.
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.
32
-
33
- ## Leo skills not available here
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.
36
-
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.
@@ -1,39 +0,0 @@
1
- <!-- Generated by scripts/render_adapters.py; do not edit. -->
2
- # OpenCode mapping
3
-
4
- Provider: `openrouter`
5
-
6
- | Tier | Model | Effort |
7
- |---|---|---|
8
- | Fable | `moonshotai/kimi-k3` | native default |
9
- | Opus | `moonshotai/kimi-k3` | native default |
10
- | Sonnet | `z-ai/glm-5.2` | native default |
11
- | Haiku | `z-ai/glm-5.2` | native default |
12
-
13
- ## Capabilities here
14
-
15
- | Capability | Here |
16
- |---|---|
17
- | Policy injection | `config.instructions`, with a system-prompt transform as backstop |
18
- | Subagent spawn | registered agent from `agents.json`, spawned via the task tool |
19
- | Per-spawn model | no — each agent always runs its registered model, so `reviewer` never downscales on a trivial diff |
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
- | Worktrees | no native tool — raw `git worktree` at `.claude/worktrees/<name>` |
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
- | Follow-up to a live agent | none established — re-dispatch cold with the context restated |
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 |
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.
28
-
29
- Memory projection here writes to the per-user `AGENTS.md` in the OpenCode config 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.
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.
32
-
33
- Fable is not a real rung here, so `expert` is not registered as an agent and escalation caps at Opus.
34
-
35
- ## Leo skills not available here
36
-
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.
38
-
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.