From 30ad0828c0ca0296bf2f2060bcb62837bb16ad61 Mon Sep 17 00:00:00 2001 From: Robert Gering Date: Wed, 15 Jul 2026 23:14:02 +0200 Subject: [PATCH] Fix swarm grok compat with grok CLI 0.2.101 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit grok 0.2.101 renamed the schema-capable model and trimmed the effort ladder, breaking every /swarm:review grok leg: - Pin GROK_DEFAULT_MODEL to grok-4.5 (grok-build no longer exists; verified drop-in: same envelope/structuredOutput, --single unchanged) - grok's effort ladder is now low|medium|high — the adapter maps xhigh/max down to high (mirror of codex's max→xhigh), so stale callers degrade instead of erroring; the workflow's --max profile sends plain high (grok's ceiling on both profiles) - Rename the fan-out voice label grok-build:full → grok:full and set the balance MODEL_LABEL to grok-4.5 - Doc sweep (READMEs, SKILL.md, blueprint, CLAUDE.md) + knowledge update (verified CLI facts: model id, effort ladders) - swarm 0.4.1 → 0.4.2 (plugin.json + marketplace.json), CHANGELOG entry Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01VcgtcycuY5NaMjbqCiJfYw --- .claude-plugin/marketplace.json | 4 +-- .../features/swarm-backend-adapter.md | 27 +++++++++------- .../features/swarm-review-pipeline.md | 21 ++++++------ CHANGELOG.md | 3 ++ CLAUDE.md | 2 +- README.md | 2 +- plugins/swarm/.claude-plugin/plugin.json | 4 +-- plugins/swarm/README.md | 13 ++++---- plugins/swarm/docs/pipeline-blueprint.md | 4 +-- plugins/swarm/scripts/agents.sh | 32 ++++++++++++------- plugins/swarm/skills/review/SKILL.md | 15 +++++---- plugins/swarm/workflows/swarm-review.js | 15 +++++---- 12 files changed, 82 insertions(+), 60 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index f8d4fda..fee7f0e 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -29,8 +29,8 @@ { "name": "swarm", "source": "./plugins/swarm", - "description": "Local mixture-of-agents code review for Claude Code. Fans a diff across Claude lenses plus the codex and grok CLIs (grok-build + composer models), merges by mechanism with cross-family consensus, verifies solo findings, and presents one ranked report. Optional --fix / --loop applies the findings you agreed with; --pr reviews a GitHub PR diff and posts the result. Skills: /swarm:review, /swarm:agents.", - "version": "0.4.1" + "description": "Local mixture-of-agents code review for Claude Code. Fans a diff across Claude lenses plus the codex and grok CLIs (grok-4.5 + composer models), merges by mechanism with cross-family consensus, verifies solo findings, and presents one ranked report. Optional --fix / --loop applies the findings you agreed with; --pr reviews a GitHub PR diff and posts the result. Skills: /swarm:review, /swarm:agents.", + "version": "0.4.2" } ] } diff --git a/.claude/knowledge/features/swarm-backend-adapter.md b/.claude/knowledge/features/swarm-backend-adapter.md index 50b6fe5..c852176 100644 --- a/.claude/knowledge/features/swarm-backend-adapter.md +++ b/.claude/knowledge/features/swarm-backend-adapter.md @@ -1,9 +1,9 @@ --- title: "Swarm Backend Adapter Layer" createdAt: 2026-07-03 -updatedAt: 2026-07-12 +updatedAt: 2026-07-15 createdFrom: "PR #21" -updatedFrom: "session: 2026-07-12" +updatedFrom: "session: 2026-07-15" pluginVersion: 1.8.2 prime: false reindexedAt: 2026-07-12 @@ -19,7 +19,7 @@ The script header documents the per-backend mechanics; this entry captures the *verified* CLI behavior the adapter is built on and the gotchas that cost a debugging round. -## Verified CLI facts (codex 0.128 / grok 0.2.77, 2026-07) +## Verified CLI facts (codex 0.128 / grok 0.2.101, 2026-07) - **Uniform findings JSON** is achievable from both CLIs: `codex exec --output-schema ` and `grok --json-schema ''` both enforce a @@ -32,10 +32,15 @@ debugging round. `--output-last-message ` (stdout carries the agent transcript, stderr the progress log); grok prints a response **envelope** on stdout — the validated object is its `.structuredOutput` field. -- **grok's default model rejects `--effort`** (`grok-composer-2.5-fast` errors - with "does not support parameter reasoningEffort"). The adapter must pin - `-m grok-build`. grok's effort ladder (low…max) matches code-review's; - codex has no `max` tier → map `max`→`xhigh` (`-c model_reasoning_effort=…`). +- **The adapter pins `-m grok-4.5`** — the schema-capable model. grok 0.2.101 + renamed it from `grok-build` (same upstream pin-rename class as codex's + `gpt-5.6-terra`; verified drop-in: identical envelope/`structuredOutput` + shape, `--single` unchanged). `grok-composer-2.5-fast` still rejects + `--effort` ("does not support parameter reasoningEffort"). +- **Effort ladders**: grok is `low|medium|high` since 0.2.101 (the `max` tier + is gone) → the adapter maps `xhigh`/`max`→`high`; codex has no `max` tier → + map `max`→`xhigh` (`-c model_reasoning_effort=…`). Both mappings degrade a + stale caller instead of erroring. - **codex model is pinned** to `CODEX_DEFAULT_MODEL` (`gpt-5.6-terra`, the adapter passes `-m` on every call), overridable per call via `--model` — so a review is reproducible instead of tracking the user's ambient `~/.codex/config` default. @@ -46,18 +51,18 @@ debugging round. still usable as a second grok voice. Given a strict-JSON *prompt* (the adapter appends the schema text and drops `--json-schema`/`--effort`), it emits **pure `{"findings":[...]}` directly on stdout — no response envelope, no - `structuredOutput`** (verified P2, grok 0.2.82; simpler than grok-build's + `structuredOutput`** (verified P2, grok 0.2.82; simpler than grok-4.5's envelope). The adapter routes `--model grok-composer-2.5-fast` to a separate `run_grok_composer` path that parses the answer **defensively**: collect ALL balanced `{...}` objects (whole string, fenced blocks, every `{` run), pick the first **non-empty** `findings` object (a leading `{"note":…}`/`{"findings":[]}` would otherwise mask the real one), and **validate every item against - `finding.schema.json`** (composer, unlike codex/grok-build, is not CLI-schema- + `finding.schema.json`** (composer, unlike codex/grok-4.5, is not CLI-schema- enforced — a malformed item must ERROR, not reach merge/verify). Both the first-object bug and the missing per-item validation were caught by swarm reviewing its own diff. composer is - ~2× faster than grok-build. It is same-family-correlated, so consumers must - count consensus by **model family**, not backend (composer + grok-build + ~2× faster than grok-4.5. It is same-family-correlated, so consumers must + count consensus by **model family**, not backend (composer + grok-4.5 agreeing is one grok vote — see [swarm-review-pipeline](swarm-review-pipeline.md)). - **Headless tool execution**: both CLIs run read-only commands (e.g. `git diff`) without extra approval flags — codex inside `-s read-only` diff --git a/.claude/knowledge/features/swarm-review-pipeline.md b/.claude/knowledge/features/swarm-review-pipeline.md index 2c356df..0debcf3 100644 --- a/.claude/knowledge/features/swarm-review-pipeline.md +++ b/.claude/knowledge/features/swarm-review-pipeline.md @@ -1,9 +1,9 @@ --- title: "Swarm Review Pipeline (/swarm:review)" createdAt: 2026-07-08 -updatedAt: 2026-07-14 +updatedAt: 2026-07-15 createdFrom: "PR #24" -updatedFrom: "session: 2026-07-14" +updatedFrom: "session: 2026-07-15" pluginVersion: 1.8.2 prime: false reindexedAt: 2026-07-12 @@ -15,7 +15,7 @@ P2 turns the blueprint into a working review: a **Workflow-tool script** (`plugins/swarm/workflows/swarm-review.js`) launched by the `/swarm:review` skill. Shape: `scope+gate → fan-out (4 voices) → merge (file,mechanism) → verify solos → output-gated synthesis`. Four voices: Claude lenses ∥ codex ∥ -grok-build ∥ composer (see [swarm-backend-adapter](swarm-backend-adapter.md)). +grok-4.5 ∥ composer (see [swarm-backend-adapter](swarm-backend-adapter.md)). ## The skill ↔ workflow wiring (the non-obvious parts) @@ -41,7 +41,7 @@ grok-build ∥ composer (see [swarm-backend-adapter](swarm-backend-adapter.md)). - **Consensus counts model *families*, not backends.** A cross-family cluster (≥2 of claude / openai / grok) is CONFIRMED without extra verify; everything else is solo and goes through the adversarial 3-state verifier. composer + - grok-build agreeing is one grok vote — they cannot alone mint consensus. + grok-4.5 agreeing is one grok vote — they cannot alone mint consensus. - **Security is intentionally minimal** (user directive: no cannons-at-sparrows). The P1 adapter floor stays (sandbox, tool-less grok, secret scrub, env filter, caps); P2 adds only three cheap things — **fencing** the diff as data @@ -60,7 +60,7 @@ grok-build ∥ composer (see [swarm-backend-adapter](swarm-backend-adapter.md)). the delimiter); the workflow only collision-checks it against the returned findings and extends it deterministically (`nonce-1`, `-2`…) on collision. -- **`args.claude: false`** runs an **external-only control** (codex + grok-build +- **`args.claude: false`** runs an **external-only control** (codex + grok-4.5 + composer, no Claude finder lenses, no gate; merge/verify still in-session). Proven useful: a control run found real bugs the with-Claude run missed (an `aws_secret_access_key` scrub-list drift, `git diff` omitting untracked files) @@ -95,11 +95,12 @@ the diff out of the script, above). Claude applies edits between rounds. the report table contract this entry defines above (P2 reserved them). - **`--max` profile** (`INPUT.max` in the workflow): lifts every voice to its ceiling — codex `gpt-5.6-sol`@`xhigh` (codex has NO `max` tier, xhigh is its - top), grok-build `max`, Claude finder lenses + verifier `xhigh`; gate/merge - and composer (no effort control) unchanged. Orthogonal to `--fix`/`--loop`, - composes with both. Both max-tier settings were verified live before wiring - (`gpt-5.6-sol`@xhigh + grok `--effort max` end-to-end) — the "no silent fail - on a non-existent model/effort" rule. + top), Claude finder lenses + verifier `xhigh`; gate/merge, grok (`high` is + its ceiling since grok 0.2.101 dropped `max` — it runs there on both + profiles) and composer (no effort control) unchanged. Orthogonal to `--fix`/`--loop`, + composes with both. The profile's live settings are verified end-to-end + (`gpt-5.6-sol`@`xhigh` at wiring time; grok re-verified at `--effort high` on + 0.2.101) — the "no silent fail on a non-existent model/effort" rule. ## `--pr`: review a PR diff and post the result (swarm 0.4.0) diff --git a/CHANGELOG.md b/CHANGELOG.md index 898ba00..715c72d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -173,6 +173,9 @@ entries are grouped per plugin, newest first. ## swarm +### 0.4.2 — 2026-07-15 +- Fix grok CLI 0.2.101 compat: pin `grok-4.5` (upstream renamed `grok-build`), cap grok effort at `high` (the `max` tier is gone; the adapter maps `xhigh`/`max` → `high` so stale callers degrade instead of erroring). + ### 0.4.1 — 2026-07-15 - Extract the `/swarm:review --pr` publish path into a deterministic, unit-tested `scripts/pr-post.py` (per-cell sanitizer, stale-head gate, `gh` post); shrink `SKILL.md` step 5 to orchestration + the human confirm gate. diff --git a/CLAUDE.md b/CLAUDE.md index 24e7d03..ed0844d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -21,7 +21,7 @@ This is a **Claude Code plugin marketplace** (monorepo) containing plugins that - **knowledge-system** (v1.5.x) — Knowledge management with three layers: Rules, Knowledge, Memory. Skills: `/init`, `/query`, `/curate`, `/reindex`, `/backfill-knowledge`, `/migrate`, `/statusline` - **work-system** (v1.2.x) — Task and worktree workflow. Skills: `/define`, `/kickoff`, `/adopt`, `/continue`, `/status`, `/close`, `/list` - **pr-flow** (v1.1.x) — PR review feedback loop. Skills: `/open`, `/cycle`, `/check`, `/fix`, `/rebase`, `/merge` -- **swarm** (v0.3.x) — Local mixture-of-agents code review (external `codex`/`grok` CLIs — grok-build + composer — plus Claude lenses). P2: `/swarm:review` pipeline (scope→fan-out→merge→verify); P5: `--fix`/`--loop` apply the findings you agreed with. Skills: `/swarm:review`, `/swarm:agents` +- **swarm** (v0.4.x) — Local mixture-of-agents code review (external `codex`/`grok` CLIs — grok-4.5 + composer — plus Claude lenses). P2: `/swarm:review` pipeline (scope→fan-out→merge→verify); P5: `--fix`/`--loop` apply the findings you agreed with. Skills: `/swarm:review`, `/swarm:agents` ## Plugin Anatomy diff --git a/README.md b/README.md index 5406091..09c3947 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ PR review feedback loop. Create PRs with readiness checks, commit + push + trigg ### Swarm -Local mixture-of-agents code review. Fans out one review across Claude lens subagents plus the `codex` and `grok` CLIs (grok in `grok-build` + `composer` modes), merges and verifies their findings, and presents a single ranked report — before anything is pushed. With `--fix` / `--loop` it also applies the findings you agreed with (only Claude edits; the external agents stay review-only). `--pr []` runs the same ensemble against a GitHub PR's diff and posts the gated result as a PR comment (via your own `gh` auth, after one confirmation) — no CI or API-token setup. Complementary to PR Flow's GitHub-side loop. *(Phase 5: `/swarm:review` pipeline + fix loop + PR posting.)* +Local mixture-of-agents code review. Fans out one review across Claude lens subagents plus the `codex` and `grok` CLIs (grok in `grok-4.5` + `composer` modes), merges and verifies their findings, and presents a single ranked report — before anything is pushed. With `--fix` / `--loop` it also applies the findings you agreed with (only Claude edits; the external agents stay review-only). `--pr []` runs the same ensemble against a GitHub PR's diff and posts the gated result as a PR comment (via your own `gh` auth, after one confirmation) — no CI or API-token setup. Complementary to PR Flow's GitHub-side loop. *(Phase 5: `/swarm:review` pipeline + fix loop + PR posting.)* **Commands:** `/swarm:review [--fix | --loop[=N]] [--max]`, `/swarm:review --pr []`, `/swarm:agents` *(more to come: `/swarm:adversarial`, `/swarm:style`, `/swarm:security`)* diff --git a/plugins/swarm/.claude-plugin/plugin.json b/plugins/swarm/.claude-plugin/plugin.json index d9c8e89..654a710 100644 --- a/plugins/swarm/.claude-plugin/plugin.json +++ b/plugins/swarm/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "swarm", - "description": "Local mixture-of-agents code review for Claude Code. Fans a diff across Claude lenses plus the codex and grok CLIs (grok-build + composer models), merges by mechanism with cross-family consensus, verifies solo findings, and presents one ranked report. Optional --fix / --loop applies the findings you agreed with; --pr reviews a GitHub PR diff and posts the result. Skills: /swarm:review, /swarm:agents.", - "version": "0.4.1", + "description": "Local mixture-of-agents code review for Claude Code. Fans a diff across Claude lenses plus the codex and grok CLIs (grok-4.5 + composer models), merges by mechanism with cross-family consensus, verifies solo findings, and presents one ranked report. Optional --fix / --loop applies the findings you agreed with; --pr reviews a GitHub PR diff and posts the result. Skills: /swarm:review, /swarm:agents.", + "version": "0.4.2", "author": { "name": "gering" }, diff --git a/plugins/swarm/README.md b/plugins/swarm/README.md index 9c2b067..21d0277 100644 --- a/plugins/swarm/README.md +++ b/plugins/swarm/README.md @@ -14,7 +14,7 @@ Complementary to [pr-flow](../pr-flow/): pr-flow drives the GitHub-PR **Phase 5 of 6** — the pipeline can now **act** (P3/P4 lens presets still to come). `/swarm:review` fans a diff -across four voices (Claude lenses + `codex` + `grok-build` + `composer`), +across four voices (Claude lenses + `codex` + `grok-4.5` + `composer`), merges by mechanism, verifies solo findings, presents one ranked report, and — with `--fix` / `--loop` — applies the findings you agreed with. @@ -25,7 +25,8 @@ with `--fix` / `--loop` — applies the findings you agreed with. default branch (including uncommitted work). `--fix` applies the agreed findings once; `--loop[=N]` re-reviews after each fix round until it converges (cap default `10`); `--max` runs the deepest-effort profile (codex - `gpt-5.6-sol`/`xhigh`, grok `max`, Claude lenses + verifier `xhigh`) — slower, + `gpt-5.6-sol`/`xhigh`, Claude lenses + verifier `xhigh`; grok already runs + at `high`, its ceiling) — slower, more thorough, composes with `--fix`/`--loop`. - `/swarm:review --pr []` — run the same ensemble against a **GitHub PR's diff** (`gh pr diff`; bare `--pr` resolves the current branch's PR) and, @@ -43,7 +44,7 @@ presets). ## The pipeline (`/swarm:review`) ``` -Scope+gate → Fan-out (Claude lenses ∥ codex ∥ grok-build ∥ composer) +Scope+gate → Fan-out (Claude lenses ∥ codex ∥ grok-4.5 ∥ composer) → Merge (file, mechanism) → Verify solos → Ranked synthesis ``` @@ -51,13 +52,13 @@ Scope+gate → Fan-out (Claude lenses ∥ codex ∥ grok-build ∥ composer) lenses are worth running (security is never gated out when code/args/files flow to an external process). 2. **Fan-out** — four voices in parallel: one Claude finder per gated lens plus - `codex`, `grok-build` and `composer` as full reviews through the adapter. + `codex`, `grok-4.5` and `composer` as full reviews through the adapter. 3. **Merge** — an LLM step clusters findings by `(file, mechanism)`, not `(file, line)` (external CLIs number against the inlined diff). 4. **Verify** — solo clusters go through an adversarial 3-state verifier (`CONFIRMED`/`PLAUSIBLE`/`REFUTED`; only `REFUTED` is dropped). -**Consensus counts model *families*, not backends.** `grok-build` and +**Consensus counts model *families*, not backends.** `grok-4.5` and `composer` are both grok, so their agreement is one vote — a `CONSENSUS` tag requires ≥2 of *claude / openai / grok*. Everything else is a solo and earns its place through the verifier. @@ -93,7 +94,7 @@ Backends: |---------|------|-----------| | `claude` | probe-only | reviews run in-session via the Agent tool | | `codex` | external reviewer | `codex exec --output-schema` (model `gpt-5.6-terra`, effort `xhigh`) in a read-only sandbox; auth via `codex login status` | -| `grok` | external reviewer | headless `-p` with inline `--json-schema` (model `grok-build`); findings extracted from the response envelope. `--model grok-composer-2.5-fast` takes a separate defensive-parse path (a ~2×-faster second grok voice, no schema flag). | +| `grok` | external reviewer | headless `-p` with inline `--json-schema` (model `grok-4.5`); findings extracted from the response envelope. `--model grok-composer-2.5-fast` takes a separate defensive-parse path (a ~2×-faster second grok voice, no schema flag). | Unavailable backends drop from the ensemble — `claude` alone still works. `/swarm:review` reports a backend that *errored* mid-run distinctly from one diff --git a/plugins/swarm/docs/pipeline-blueprint.md b/plugins/swarm/docs/pipeline-blueprint.md index 8b93d96..76b40bb 100644 --- a/plugins/swarm/docs/pipeline-blueprint.md +++ b/plugins/swarm/docs/pipeline-blueprint.md @@ -287,11 +287,11 @@ credential mid-review) converged on these non-negotiable mitigations: - **Registered workflow** (not inline) so per-agent `durationMs` is available for the timing balance line. -- **Model labels** in the balance line (`Opus-4.8`/`GPT-5.5`/`grok-build`), +- **Model labels** in the balance line (`Opus-4.8`/`GPT-5.5`/`grok-4.5`), read from each backend's review output. - **Optional composer lens-gate**: `grok-composer-2.5-fast` can't enforce `--json-schema`/`--effort`, but a strict-JSON prompt makes it emit valid JSON - and reason on demand (tested 2/2). It's ~2× faster than grok-build but its + and reason on demand (tested 2/2). It's ~2× faster than grok-4.5 but its ~20s CLI cost undercuts a Haiku gate; keep it optional, with a defensive parser + fallback-to-all-lenses. - **Balance / footer / loop-round box:** render deterministically from the diff --git a/plugins/swarm/scripts/agents.sh b/plugins/swarm/scripts/agents.sh index cd0eb62..3081e19 100755 --- a/plugins/swarm/scripts/agents.sh +++ b/plugins/swarm/scripts/agents.sh @@ -14,7 +14,7 @@ # --model Backend model override # --schema JSON schema to enforce (default: bundled finding.schema.json) # -# Backend notes (probed against codex 0.128 / grok 0.2.77, 2026-07): +# Backend notes (probed against codex 0.128 / grok 0.2.101, 2026-07): # claude — probe-only: reviews run in-session via the Agent tool, so # `run claude` is a usage error. available/ready/list include it. # codex — `codex exec --output-schema` in a read-only sandbox; the pure @@ -23,13 +23,15 @@ # Reasoning effort has no "max" tier -> max maps to xhigh. # grok — headless `-p` with inline --json-schema; the validated object is # the `.structuredOutput` field of a response envelope. Needs an -# explicit model (-m): grok-build is the schema-capable default and -# accepts --effort. The one other accepted model is +# explicit model (-m): grok-4.5 is the schema-capable default and +# accepts --effort (ladder is low|medium|high — no max tier, so the +# adapter maps xhigh/max down to high, mirroring codex's missing +# max). The one other accepted model is # grok-composer-2.5-fast (`--model grok-composer-2.5-fast`): it # ignores --json-schema/--effort, so the adapter drives it with a # strict-JSON prompt and parses the findings defensively (verified: # emits pure {"findings":[...]} on stdout, no envelope). It is a -# second, ~2x-faster grok voice — same family as grok-build, so a +# second, ~2x-faster grok voice — same family as grok-4.5, so a # caller must treat their agreement as one family, not consensus. # Auth heuristic: non-empty ~/.grok/auth.json (no status command). # @@ -40,7 +42,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" DEFAULT_SCHEMA="$SCRIPT_DIR/schema/finding.schema.json" CODEX_DEFAULT_MODEL="gpt-5.6-terra" -GROK_DEFAULT_MODEL="grok-build" +GROK_DEFAULT_MODEL="grok-4.5" GROK_COMPOSER_MODEL="grok-composer-2.5-fast" # Default HOME so `$HOME` expansions below (auth file, sandbox deny paths) don't # abort the whole script under `set -u` when HOME is unset. @@ -395,7 +397,7 @@ subcmd_run() { esac [[ -f "$schema" ]] || { echo "Schema not found: $schema" >&2; exit 2; } # composer has no reasoning-effort control; say so if the caller set --effort - # explicitly, so review depth isn't misjudged against grok-build. + # explicitly, so review depth isn't misjudged against grok-4.5. if [[ "$backend" == "grok" && "$model" == "$GROK_COMPOSER_MODEL" && -n "$effort_set" ]]; then echo "note: --effort is ignored for $GROK_COMPOSER_MODEL (it has no reasoning-effort control)" >&2 fi @@ -484,6 +486,10 @@ if not (isinstance(d, dict) and isinstance(d.get("findings"), list)): run_grok() { local prompt="$1" effort="$2" model="$3" schema="$4" + # grok's effort ladder is low|medium|high (0.2.101 dropped max) — map the two + # higher adapter tiers down so a stale caller degrades instead of erroring, + # mirroring codex's max→xhigh mapping. + case "$effort" in xhigh|max) effort="high" ;; esac local grok_model="${model:-$GROK_DEFAULT_MODEL}" # grok-composer-2.5-fast is the one non-default model the adapter supports; it @@ -493,7 +499,7 @@ run_grok() { return fi - # Preflight-reject any OTHER non-default model: only grok-build enforces + # Preflight-reject any OTHER non-default model: only grok-4.5 enforces # --json-schema (and accepts --effort). An unlisted model would silently # return structuredOutput:null and fail late with no schema output — so reject # up front with a usage error rather than burn a review on it. @@ -516,7 +522,11 @@ run_grok() { --json-schema "$(cat "$schema")" \ --single="$prompt" /dev/null)" || rc=$? if (( rc != 0 )); then - (( rc == 124 )) && echo "grok timed out after ${ADAPTER_TIMEOUT}s" >&2 || echo "grok failed" >&2 + # stderr is deliberately discarded (injection guard), so name the likely + # cause: an older CLI that predates the pinned model reports Ready (auth + # heuristic) yet rejects the model id at runtime. + (( rc == 124 )) && echo "grok timed out after ${ADAPTER_TIMEOUT}s" >&2 \ + || echo "grok failed — check that the installed grok CLI knows model '$grok_model' ($GROK_DEFAULT_MODEL needs grok >= 0.2.101)" >&2 exit 1 fi printf '%s' "$raw" | python3 -c ' @@ -548,12 +558,12 @@ print() } run_grok_composer() { - # grok-composer-2.5-fast: ~2x faster than grok-build but ignores + # grok-composer-2.5-fast: ~2x faster than grok-4.5 but ignores # --json-schema/--effort (would return plain text with structuredOutput:null). # So we DON'T pass those flags — instead we append a strict-JSON directive # (the schema itself) to the prompt and parse the answer defensively. Verified: # composer then emits pure {"findings":[...]} on stdout (no envelope). Same - # sandbox + env filter + scrub as grok-build; only the schema mechanism differs. + # sandbox + env filter + scrub as grok-4.5; only the schema mechanism differs. local prompt="$1" schema="$2" local full full="$prompt @@ -645,7 +655,7 @@ KEYS = {"file", "line", "severity", "summary", "failure_scenario", "confidence", def valid_item(f): # Mirror finding.schema.json EXACTLY. composer is not CLI-schema-enforced - # (unlike codex/grok-build), so a malformed item must ERROR here rather than + # (unlike codex/grok-4.5), so a malformed item must ERROR here rather than # reach merge/verify, which rely on the uniform-findings contract. Check the # exact key set (additionalProperties:false + all required), maxLength, and # enums — a hand-rolled type-only subset would drop valid rows and pass diff --git a/plugins/swarm/skills/review/SKILL.md b/plugins/swarm/skills/review/SKILL.md index 8830761..8df82b2 100644 --- a/plugins/swarm/skills/review/SKILL.md +++ b/plugins/swarm/skills/review/SKILL.md @@ -1,7 +1,7 @@ --- name: review description: | - Local mixture-of-agents review: Claude lenses plus codex and grok (build + + Local mixture-of-agents review: Claude lenses plus codex and grok (grok-4.5 + composer), one ranked report. --fix/--loop applies agreed findings; --pr reviews a GitHub PR diff and posts the result. Trigger: "swarm review", "review my changes", "review this PR". @@ -10,7 +10,7 @@ user_invocable: true # Swarm Review -> Fan one code review across Claude lenses + codex + grok-build + composer, +> Fan one code review across Claude lenses + codex + grok-4.5 + composer, > merge by mechanism, verify solos, and present one ranked report. ## Arguments @@ -47,9 +47,10 @@ branch delta). slowest, most thorough review (costs more time + tokens). Orthogonal to `--fix`/`--loop` — composes with both (`--max --loop` = max-depth fix loop). Set `max: true` in the workflow args (step 2). It bumps: codex → - `gpt-5.6-sol` at `xhigh` (codex has no `max` tier), grok-build → `max`, - Claude finder lenses + the adversarial verifier → `xhigh`. gate/merge and the - composer voice (no effort control) are unchanged. + `gpt-5.6-sol` at `xhigh` (codex has no `max` tier), Claude finder lenses + + the adversarial verifier → `xhigh`. gate/merge, the grok voice (`high` is + grok's ceiling — it runs there on both profiles) and the composer voice (no + effort control) are unchanged. - Anything left after removing the flags → the scope argument for step 1. Without either flag the review is **read-only**: present the report and offer to @@ -282,7 +283,7 @@ Workflow({ Fill ``/``/`` from the echoed values. Add `max: true` to `args` when `--max` was given (step 1 stripped it) — the deepest-effort profile. Add `claude: false` to `args` -for an **external-only control run** (codex + grok-build + composer, no Claude +for an **external-only control run** (codex + grok-4.5 + composer, no Claude finder lenses — merge/verify still run in-session); default is the full ensemble. The workflow runs in the background for several minutes — **tell the user they can watch live progress with `/workflows`** while it runs. It returns @@ -589,7 +590,7 @@ post. Do **not** re-implement the sanitize/gate/post logic inline. ## Notes - **Consensus = cross-family agreement** (≥2 of claude / openai / grok). Two - grok voices (grok-build + composer) agreeing count as one family, so they + grok voices (grok-4.5 + composer) agreeing count as one family, so they cannot alone mint a CONSENSUS — solos go through the adversarial verifier. - **Security floor** (inherited from the adapter, plus this pipeline): the diff is fenced as data, external CLIs run sandboxed + tool-less (grok) with a diff --git a/plugins/swarm/workflows/swarm-review.js b/plugins/swarm/workflows/swarm-review.js index 0e5bdbe..9e06b0f 100644 --- a/plugins/swarm/workflows/swarm-review.js +++ b/plugins/swarm/workflows/swarm-review.js @@ -1,9 +1,9 @@ export const meta = { name: 'swarm-review', - description: 'Local mixture-of-agents review: scope+gate → fan-out (Claude lenses + codex + grok-build + composer) → (file,mechanism) merge with family-aware consensus → verify solos → output-gated ranked synthesis.', + description: 'Local mixture-of-agents review: scope+gate → fan-out (Claude lenses + codex + grok + composer) → (file,mechanism) merge with family-aware consensus → verify solos → output-gated ranked synthesis.', phases: [ { title: 'Scope', detail: 'classify diff + gate lenses' }, - { title: 'Fan-out', detail: 'Claude lenses + codex + grok-build + composer in parallel' }, + { title: 'Fan-out', detail: 'Claude lenses + codex + grok + composer in parallel' }, { title: 'Merge', detail: 'cluster by (file, mechanism), consensus by family' }, { title: 'Verify', detail: '3-state verify of solo clusters' }, ], @@ -43,8 +43,9 @@ const FINDING_NONCE_RAW = FINDING_NONCE // remember what was passed, to explain if (FINDING_NONCE && !/^[a-f0-9]{16,}$/.test(FINDING_NONCE)) FINDING_NONCE = '' const fenceDegraded = !FINDING_NONCE // no structural fence at merge/verify — surfaced in the return payload // `--max` profile: lift every voice to its ceiling for a deepest-effort review. -// codex has no `max` tier (xhigh is its top) + gets the stronger model; grok -// goes to `max`; the in-session Claude finders and verifier go to `xhigh`. +// codex has no `max` tier (xhigh is its top) + gets the stronger model; grok's +// ladder is low|medium|high since 0.2.101, so `high` is already its ceiling on +// both profiles; the in-session Claude finders and verifier go to `xhigh`. // Strict === true: the skill always passes a boolean, and a stray truthy value // (max:1 / "true") should NOT silently trigger a slower, costlier run. // MAX_CODEX_MODEL must be a model the local codex CLI can load — if it's been @@ -277,7 +278,7 @@ const claudeThunks = runLensesSafe.map((lens) => () => // backend is visible, not mistaken for a clean empty review. const EXTERNAL_VOICES = [ { backend: 'codex', label: 'codex:full', cmd: `bash "${ADAPTER}" run codex ${MAX ? `--model ${MAX_CODEX_MODEL} --effort xhigh` : '--effort high'} --prompt-file "${EXTERNAL_PROMPT}"` }, - { backend: 'grok', label: 'grok-build:full', cmd: `bash "${ADAPTER}" run grok --effort ${MAX ? 'max' : 'high'} --prompt-file "${EXTERNAL_PROMPT}"` }, + { backend: 'grok', label: 'grok:full', cmd: `bash "${ADAPTER}" run grok --effort high --prompt-file "${EXTERNAL_PROMPT}"` }, { backend: 'composer', label: 'composer:full', cmd: `bash "${ADAPTER}" run grok --model grok-composer-2.5-fast --prompt-file "${EXTERNAL_PROMPT}"` }, ] // Only spawn transports for backends the skill reported live (probed via the @@ -353,7 +354,7 @@ if (pool.length > 0) { members.forEach((i) => assigned.add(i)) const backends = Array.from(new Set(members.map((i) => pool[i].backend))).sort() const families = Array.from(new Set(members.map((i) => pool[i].family))).sort() - // Consensus requires >=2 distinct FAMILIES (composer+grok-build = one family). + // Consensus requires >=2 distinct FAMILIES (composer+grok-4.5 = one family). return { ...c, member_indices: members, backends, families, consensus: families.length >= 2 ? 'CONFIRMED' : 'solo' } }).filter((c) => c.backends.length > 0) // drop clusters whose member_indices all filtered out — no backing voice @@ -435,7 +436,7 @@ const findings = gatedFindings.sort((a, b) => (sevOf(a) - sevOf(b)) || (conRank( // Per-backend rollup for the balance "Agents" line: concrete short model label // + voice/finding counts + whether it ran clean. Wall-time (per-agent durationMs) // needs a registered workflow to surface — tracked as P4 wiring. -const MODEL_LABEL = { claude: 'opus', codex: 'gpt', grok: 'grok', composer: 'composer' } +const MODEL_LABEL = { claude: 'opus', codex: 'gpt', grok: 'grok-4.5', composer: 'composer' } const agents = {} for (const v of voices) { const a = agents[v.backend] || (agents[v.backend] = { backend: v.backend, model: MODEL_LABEL[v.backend] || v.backend, voices: 0, failedVoices: 0, findings: 0, ok: true })