Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 118 additions & 2 deletions commands/v-init.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,88 @@ cursor-agent status </dev/null 2>&1 | head -3 # or: [ -n "$CURSOR_API_KEY" ]
> preferred for untrusted / high-stakes work**. See
> [`adapter-cursor.md`](../skills/backend-launcher/adapter-cursor.md).

### 1a-quater. Devin CLI (`devin`) — optional, lower-trust, WORKER-ONLY backend

```bash
command -v devin
```

If absent → Devin is **not available** (record it; routing never offers it).

If present → check **authentication** (auth-free command, verified live):

```bash
devin auth status </dev/null 2>&1 | head -3 # or: [ -n "$COGNITION_API_KEY" ]
```

- Installed **and** authenticated (`devin auth login`, or `COGNITION_API_KEY` set) →
Devin is **usable**; record it and add it to `backends`. The pinned headless invocation
(devin-cli 3000.1.27, verified live for its help/flag surface — task-execution behavior is
DOC-CLAIMED, unverified without an authenticated run):
`cd "$WT" && devin -p "<prompt>" --permission-mode dangerous [--model <M>] --export <path> </dev/null`.
Also probe sandbox availability (auth-free, verified live): `devin sandbox setup` — on macOS
reports *"No sandbox setup is required"*; on Linux it either confirms `bubblewrap`+`socat`
are present or prints install instructions. Record the result — it tells `/v:models` /
the operator whether Devin's `--sandbox` (Research Preview) is even usable on this machine,
though this plugin does **not** rely on it for enforcement in v1 (see below).
- Installed but **not** authenticated → record it as **present but unauthenticated**; treat as
unavailable and tell the user to run `devin auth login` (or set `COGNITION_API_KEY`).

> **Flag it as lower-trust AND worker-only when you record it.** Devin has a real,
> live-confirmed kernel `--sandbox` flag (macOS Seatbelt / Linux bwrap+seccomp) — a
> genuine differentiator from Antigravity/Cursor — but Cognition labels it
> **"[Research Preview]"**, its coverage is scoped to "exec-tool processes" (non-shell
> file-edit tool coverage unverified), and its network-filtering is called "currently
> unstable" in Cognition's own docs. Until those are live-verified, this plugin treats
> Devin as **opt-in, lower-trust — the same tier as Antigravity/Cursor**, NOT Codex: the
> worktree + `git diff` gate is the *real* enforcement (detection, not confirmed
> prevention). **Prefer Codex for untrusted / high-stakes work.** Devin is also
> **model-agnostic** (`--model` accepts a free string spanning Claude/GPT/Gemini/Devin's
> own SWE family) — its resolved model family is data-dependent, so it is **WORKER-ONLY
> for v1, excluded from any cross-model arbiter/review panel** until family-dedup keys on
> the resolved model rather than the backend name. See
> [`adapter-devin.md`](../skills/backend-launcher/adapter-devin.md).

### 1a-quinquies. opencode CLI (`opencode`) — optional, lower-trust, WORKER-ONLY, multi-provider backend

```bash
command -v opencode || npx -y opencode-ai@latest --version # confirms installable even if not on PATH
```

If absent → opencode is **not available** (record it; routing never offers it).

If present → check for at least one usable provider credential (auth-free command,
verified live):

```bash
opencode providers list </dev/null 2>&1 | grep -qv '0 credentials' \
&& echo "opencode has stored credentials" \
|| echo "opencode has NO stored credentials (may still work via ambient provider env vars)"
```

- Installed **and** (stored credentials via `opencode providers login`, **or** a known
provider env var like `ANTHROPIC_API_KEY`/`OPENAI_API_KEY`/`ANTHROPIC_BASE_URL` is
explicitly set for this purpose) → opencode is **usable**; record it and add it to
`backends`. **Load-bearing, live-observed finding:** opencode successfully authenticated
with **zero** stored credentials purely from an inherited `ANTHROPIC_BASE_URL` — record
`auth` as `ambient-env` vs `stored-credentials` so the operator knows which path is live
on this machine, and see the adapter's env-scrub requirement below.
- Installed but no credentials and no relevant env var set → present but unauthenticated;
tell the user to run `opencode providers login`.

> **Flag it as lower-trust, worker-only, AND multi-provider when you record it.** opencode
> has **no kernel write-confinement** at all (no `--sandbox` equivalent), and per its own
> docs defaults to **allowing all operations without explicit approval** — the opposite
> posture from Cursor/Antigravity, which refuse until explicitly unlocked. The worktree +
> `git diff` gate is the only real enforcement (detection, not prevention). **Prefer Codex
> for untrusted / high-stakes work.** opencode addresses models as `provider/model`
> strings (e.g. `anthropic/claude-opus-4-6`), so — like Devin — its resolved model family
> is data-dependent; it is **WORKER-ONLY for v1, excluded from any cross-model
> arbiter/review panel** until family-dedup keys on the resolved model. See
> [`adapter-opencode.md`](../skills/backend-launcher/adapter-opencode.md) for the
> **mandatory env-scrub** (the worker script must NOT blindly inherit the dispatcher's own
> provider env vars into the `opencode run` child process).

### 1b. Context7 MCP (match by namespace)

Context7 is **plugin-namespaced** — match the namespace, not a bare `context7`:
Expand Down Expand Up @@ -408,18 +490,27 @@ was, in those two fields).
"claude": { "deep": "opus", "standard": "opus", "light": "sonnet" },
"codex": { "deep": "gpt-5.6-sol", "standard": "gpt-5.6-terra", "light": "gpt-5.6-luna" },
"antigravity": { "deep": "Gemini 3.1 Pro (High)", "standard": "Gemini 3.1 Pro (Low)", "light": "Gemini 3.5 Flash (Low)" },
"cursor": { "deep": "auto", "standard": "auto", "light": "auto" }
"cursor": { "deep": "auto", "standard": "auto", "light": "auto" },
"devin": { "deep": "claude-opus-4.6", "standard": "claude-sonnet-4", "light": "gpt-5.5" },
"opencode": { "deep": "anthropic/claude-opus-4-6", "standard": "openai/gpt-5.6-terra", "light": "opencode/mimo-v2.5-free" }
},
"cost-aware": {
"claude": { "deep": "opus", "standard": "sonnet", "light": "sonnet" },
"codex": { "deep": "gpt-5.6-sol", "standard": "gpt-5.6-terra", "light": "gpt-5.6-luna" },
"antigravity": { "deep": "Gemini 3.1 Pro (High)", "standard": "Gemini 3.1 Pro (Low)", "light": "Gemini 3.5 Flash (Low)" },
"cursor": { "deep": "auto", "standard": "auto", "light": "auto" }
"cursor": { "deep": "auto", "standard": "auto", "light": "auto" },
"devin": { "deep": "claude-opus-4.6", "standard": "claude-sonnet-4", "light": "gpt-5.5" },
"opencode": { "deep": "anthropic/claude-opus-4-6", "standard": "openai/gpt-5.6-terra", "light": "opencode/mimo-v2.5-free" }
}
}
}
```

- `devin` and `opencode` are **worker-only** backends (v1): excluded from any cross-model
arbiter/review panel until family-dedup keys on the *resolved* model rather than the
backend name (both are multi-provider routers, so `backend: devin`/`backend: opencode`
does not fix a single model family — see `adapter-devin.md` / `adapter-opencode.md`).

(`conservative` and `claude-only` mirror `balanced` — seed those two stance blocks
identically to `balanced`. Only `cost-aware.claude.standard` differs: `sonnet`, not
`opus`; `cost-aware.claude.deep` stays `opus`.)
Expand Down Expand Up @@ -506,6 +597,20 @@ The user-level cache of what this machine can do, reused across repos:
"codex": { "available": true, "exec_flags_verified": true, "version": "<from `codex --version`>" },
"antigravity": { "available": false, "trust": "lower (no kernel sandbox)", "version": "<from `agy --version`>" },
"cursor": { "available": false, "authenticated": false, "trust": "lower (no kernel sandbox)", "version": "<from `cursor-agent --version`>" },
"devin": {
"available": false,
"authenticated": false,
"trust": "lower (Research-Preview kernel sandbox; exec-tool-only coverage unverified; network filtering unstable per vendor); worker-only",
"version": "<from `devin --version`>",
"sandbox_setup_required": null
},
"opencode": {
"available": false,
"auth": "none",
"trust": "lower (no kernel sandbox; docs claim default-allow permissions); worker-only, multi-provider",
"version": "<from `opencode --version`>",
"providers_configured": []
},
"context7": { "available": true },
"workflows": { "available": false },
"deep_research": true,
Expand All @@ -518,6 +623,17 @@ The user-level cache of what this machine can do, reused across repos:
- `antigravity.available` reflects the Step 1a-bis `command -v agy` probe; record the
`version` from `agy --version`. When present, Step 1a-bis also seeds a real model map
via `agy models </dev/null` (headless — no TTY needed).
- `devin.available` reflects the Step 1a-quater `command -v devin` probe;
`devin.authenticated` reflects `devin auth status`. `sandbox_setup_required` records
whether `devin sandbox setup` reported readiness (macOS: always ready; Linux: depends
on `bubblewrap`/`socat`) — informational only, not relied on for enforcement in v1.
- `opencode.available` reflects the Step 1a-quinquies `command -v opencode` probe;
`opencode.auth` records **how** it is authenticating (`ambient-env` /
`stored-credentials` / `none`) — this machine-local nuance matters more for opencode
than any other backend, given the live-observed ambient-credential finding (see
`adapter-opencode.md`).
- `devin` and `opencode` are never added to any arbiter/review-panel capability block —
they are **worker-only** in v1.
- `deep_research` reflects the Step 1d-bis presence probe (is `deep-research` in the
available-skills listing?) — an **advisory hint only**: Trigger 0 re-checks the live
listing at fire time, because the flag can go stale (`disableBundledSkills` /
Expand Down
85 changes: 76 additions & 9 deletions commands/v-models.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
description: Refresh the Compound V tier→model map — discover the concrete models each backend (claude, codex, antigravity, cursor) currently offers, show them, let you assign deep/standard/light, and write the result into .claude/compound-v.json so intent-based routing survives model churn without touching any call site.
description: Refresh the Compound V tier→model map — discover the concrete models each backend (claude, codex, antigravity, cursor, devin, opencode) currently offers, show them, let you assign deep/standard/light, and write the result into .claude/compound-v.json so intent-based routing survives model churn without touching any call site.
disable-model-invocation: true
---

Expand All @@ -15,7 +15,9 @@ at dispatch time, so refreshing the map here is the *only* thing you ever touch
when models churn.

Argument (optional): `{{args}}` may name a single backend to refresh in isolation
(`claude` | `codex` | `antigravity` | `cursor`); otherwise walk all of them.
(`claude` | `codex` | `antigravity` | `cursor` | `devin` | `opencode`); otherwise walk
all of them. `devin` and `opencode` are **worker-only** backends (v1) — their model
maps drive dispatch only, never any arbiter/review panel seat.

**This is the "skill picks the models and offers you the options" surface.** Do the
discovery, *show* what you found, then let the user choose. Never silently pick a
Expand Down Expand Up @@ -150,6 +152,62 @@ command -v cursor-agent && cursor-agent status </dev/null >/dev/null 2>&1 && ech
`sonnet-4-thinking`) — a curated roster like codex (no discovery; whatever the plan accepts
via `cursor-agent --model` is valid). Only offer named models if the user confirms a paid plan.

### 1e. devin — curated list, no discovery command (mirrors codex's pattern)

Devin has **no `devin models` / `--list-models` subcommand** — like codex, discovery is
only via the interactive `/model` picker inside a session, so the map is a small
**curated** roster the user can override by hand (devin accepts whatever string you pass
to `--model`). Present this curated starting roster (DOC-CLAIMED aliases — devin-cli
3000.1.27's own `--help` uses these exact strings as its examples, but no authenticated
run has confirmed they resolve):

- `claude-opus-4.6` — strongest; suggested for `deep`
- `claude-sonnet-4` — balanced; suggested for `standard`
- `gpt-5.5` — fast/cheap; suggested for `light`

Confirm devin is even usable first:

```bash
command -v devin && devin auth status </dev/null 2>&1 | grep -q 'Not logged in' \
&& echo "devin present, unauthenticated" || echo "devin usable (or absent)"
```

If devin is unavailable/unauthenticated, say so, keep the existing devin block
unchanged, and skip its reassignment. **Devin is model-agnostic** (`--model` spans
Claude/GPT/Gemini/Devin's own SWE family) — remind the user that whichever family they
pick here determines Devin's error-correlation with the rest of the panel, which is
exactly why it stays **worker-only, never an arbiter seat**, in this plugin.

### 1f. opencode — real discovery command, but curated + user-confirmed assignment

opencode **does** have a real, live discovery command that works even with **zero**
stored credentials (it falls back to a credential-free `opencode/*` catalog via
models.dev):

```bash
command -v opencode >/dev/null && opencode models </dev/null 2>&1 || echo "opencode unavailable"
```

Unlike antigravity's single-family Gemini catalog, opencode spans **multiple unrelated
providers with no shared naming convention** — so, like cursor, Compound V does **not**
auto-rank it. Show the user the live `opencode models` output, then let them assign each
tier. The one genuinely novel option here: `light` MAY legitimately point at one of the
**credential-free** `opencode/*` models (e.g. `opencode/mimo-v2.5-free`) — a real free
tier no other backend offers. Every cell **MUST** be a full `provider/model` string (the
resolver's selftest asserts every `opencode` tier cell contains `/`); a bare model name
will likely fail opencode's own model resolution even though `--model` accepts the
string syntactically. The built-in fallback map (curated, user-overridable):

- `deep` → `anthropic/claude-opus-4-6`
- `standard` → `openai/gpt-5.6-terra`
- `light` → `opencode/mimo-v2.5-free`

If opencode is unavailable/unauthenticated, say so and keep the existing opencode block
unchanged. **opencode is model-agnostic per-cell** (each tier may use a different
provider) — remind the user this is exactly why it stays **worker-only, never an
arbiter seat**: an opencode ballot's family is determined entirely by which
`provider/model` was resolved, not by the backend name.

---

## Step 2 — Show findings and let the user assign tiers
Expand All @@ -164,6 +222,8 @@ fast/cheap option → `light`). Example shape:
| claude | opus, sonnet | opus | opus | sonnet |
| codex | gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna | gpt-5.6-sol | gpt-5.6-terra | gpt-5.6-luna |
| antigravity | *(from `agy models </dev/null`)* | Gemini 3.1 Pro (High) | Gemini 3.1 Pro (Low) | Gemini 3.5 Flash (Low) |
| devin | *(curated: claude-opus-4.6, claude-sonnet-4, gpt-5.5)* | claude-opus-4.6 | claude-sonnet-4 | gpt-5.5 |
| opencode | *(from `opencode models </dev/null`)* | anthropic/claude-opus-4-6 | openai/gpt-5.6-terra | opencode/mimo-v2.5-free |

Then **let the user assign** each tier per backend — accept the suggestion as-is, or
override any cell with any model name the discovery surfaced (or, for codex, any
Expand Down Expand Up @@ -205,13 +265,17 @@ Resulting shape (only `models` is this command's responsibility) — write the
"claude": { "deep": "opus", "standard": "opus", "light": "sonnet" },
"codex": { "deep": "gpt-5.6-sol", "standard": "gpt-5.6-terra", "light": "gpt-5.6-luna" },
"antigravity": { "deep": "…", "standard": "…", "light": "…" },
"cursor": { "deep": "auto", "standard": "auto", "light": "auto" }
"cursor": { "deep": "auto", "standard": "auto", "light": "auto" },
"devin": { "deep": "claude-opus-4.6", "standard": "claude-sonnet-4", "light": "gpt-5.5" },
"opencode": { "deep": "anthropic/claude-opus-4-6", "standard": "openai/gpt-5.6-terra", "light": "opencode/mimo-v2.5-free" }
},
"cost-aware": {
"claude": { "deep": "opus", "standard": "sonnet", "light": "sonnet" },
"codex": { "deep": "gpt-5.6-sol", "standard": "gpt-5.6-terra", "light": "gpt-5.6-luna" },
"antigravity": { "deep": "…", "standard": "…", "light": "…" },
"cursor": { "deep": "auto", "standard": "auto", "light": "auto" }
"cursor": { "deep": "auto", "standard": "auto", "light": "auto" },
"devin": { "deep": "claude-opus-4.6", "standard": "claude-sonnet-4", "light": "gpt-5.5" },
"opencode": { "deep": "anthropic/claude-opus-4-6", "standard": "openai/gpt-5.6-terra", "light": "opencode/mimo-v2.5-free" }
}
// conservative + claude-only mirror balanced
}
Expand All @@ -237,7 +301,7 @@ resolver reads the per-stance block you wrote (omitting it defaults to `balanced

```bash
for s in balanced cost-aware; do
for b in claude codex antigravity; do
for b in claude codex antigravity cursor devin opencode; do
for t in deep standard light; do
python3 scripts/compound-v-resolve-model.py --backend "$b" --tier "$t" \
--stance "$s" --config .claude/compound-v.json
Expand Down Expand Up @@ -271,7 +335,10 @@ set here. `xhigh` is valid **iff** `backend: codex`; every other backend rejects
with a clear error naming the rule (use `high` instead).

**Honesty rules:** report only what discovery actually returned. `agy models </dev/null`
runs headlessly and returns the live catalog, so report the discovered models as
discovered. Only if `agy` is **absent** do we fall back to the built-in map — say so
plainly when that happens, rather than passing the fallback off as discovered. Never
print token or cost numbers (anti-ruflo). Never assign `haiku`.
and `opencode models </dev/null` both run headlessly and return live catalogs, so
report the discovered models as discovered. Only if the CLI is **absent** do we fall
back to the built-in map — say so plainly when that happens, rather than passing the
fallback off as discovered. devin has no discovery command at all — its roster is
always curated, say so. Never print token or cost numbers (anti-ruflo). Never assign
`haiku`. Always remind the user that `devin` and `opencode` are worker-only backends —
whatever they assign here never seats either on an arbiter/review panel.
Loading
Loading