amicus 4.5.0 → 4.5.2

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amicus",
3
- "version": "4.5.0",
3
+ "version": "4.5.2",
4
4
  "description": "Multi-model LLM Council + parallel AI window for Claude Code. Run structured council reviews across Gemini, GPT, DeepSeek and more — or fork a conversation to any model and fold the results back.",
5
5
  "author": {
6
6
  "name": "Christian Wagner"
package/CHANGELOG.md CHANGED
@@ -3,6 +3,77 @@
3
3
  All notable changes to Amicus are documented here. Format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow semver.
5
5
 
6
+ ## [4.5.2] - 2026-07-31
7
+
8
+ ### Fixed
9
+
10
+ - **OpenCode server-start timeout is no longer pinned to the SDK's 5000 ms, and a start timeout
11
+ is now retried.** `@opencode-ai/sdk` defaults `createOpencodeServer`'s start timeout to 5 s and
12
+ lets the caller override it; amicus never passed one, so every start on every platform ran on
13
+ that default — undocumented, untunable, and invisible to `amicus doctor`. Worse, the existing
14
+ start retry (`retryOnLockRace`) classified only `database is locked` / `SQLITE_BUSY`, so a start
15
+ timeout fell straight through with **zero** retries, past machinery already wired in at every
16
+ call site. On a Windows box with the project on a OneDrive-synced volume and Defender active, a
17
+ cold OpenCode/SQLite start blew the window: the council's shared server failed to acquire, the
18
+ run degraded to exactly the per-wave configuration `src/council/run-server.js` exists to
19
+ eliminate, and the whole Stage-1 bench died with `COUNCIL_QUORUM: Only 0 Stage-1 review(s)
20
+ survived`. Three of the reporter's runs were lost this way. A start timeout is now classified as
21
+ transient (`isTimeoutClassStartFailure`) and retried on the same bounded 250/500/1000/2000 ms
22
+ schedule, the timeout is threaded through `buildServerOptions` and both upstream start sites,
23
+ and the default is raised to **30 s on Windows / 15 s elsewhere** — a slow start costs latency,
24
+ a failed start costs a review seat.
25
+ - **The Electron self-heal was dead code in every published install.** `src/sidecar/unzip.js`
26
+ did a bare, unguarded `require('extract-zip')` for a package that was never declared in
27
+ `dependencies` or `optionalDependencies`. It resolved in the dev tree only because `puppeteer`
28
+ (a devDependency) pulls it transitively — `npm ls extract-zip --omit=dev` returned empty — so on
29
+ a real `npm i -g amicus` `robustExtract` threw `MODULE_NOT_FOUND` before Strategy 1. That made
30
+ the native-unzip fallback below it unreachable, the bounded idle/max timers from the
31
+ extract-zip-node24 work inert, and `amicus doctor --fix` dead-end at `self-heal incomplete` —
32
+ while routing users toward antivirus allow-listing for what was actually a missing module.
33
+ `extract-zip` is now a declared production dependency, the `require` degrades into the native
34
+ strategies instead of throwing out of the function, and a new `no-phantom-dependencies` test
35
+ fails on any undeclared runtime require anywhere in `src/`, `bin/` or `electron/`.
36
+ - **A lost critic is now recorded on `verdict.json`.** The critic is a solo wave with one leg, and
37
+ unlike a dead bench wave (which trips the quorum gate and fails the run loudly) a dead critic is
38
+ survivable — so a run could reach a full verdict, tally and chair synthesis that had never seen
39
+ the adversarial seat, with the only record being `deadWaves` in `run.json`. Field run `dfb6a692`
40
+ did exactly that. `verdict.json` now carries an optional `seatLoss` block
41
+ (`criticRequested`/`criticSeated`/`reason`/`deadBenchSeats`) whenever `--critic` was requested,
42
+ so a reader of the verdict can see the critic never ran. Additive; `schemaVersion` stays `2`.
43
+
44
+ ### Added
45
+
46
+ - **`AMICUS_SERVER_START_TIMEOUT_MS`** — override the server-start window (see
47
+ [docs/configuration.md](docs/configuration.md#server-startup)). Values ≤ 0 are ignored rather
48
+ than honored, since a zero start timeout fails every start instantly.
49
+ - **Successful server starts are logged at debug level** with both `startMs` and the `timeoutMs`
50
+ ceiling in force, so headroom on a slow box is measurable rather than inferred — the question
51
+ the field report could not answer.
52
+
53
+ ## [4.5.1] - 2026-07-30
54
+
55
+ ### Added
56
+
57
+ - **`electron-mcp` doctor check — doctor now validates Electron in the install the MCP actually
58
+ runs from (#76).** `amicus doctor` used to probe Electron only in the copy doctor itself runs
59
+ from (usually the global install), while `npx -y amicus@latest mcp` serves councils from an
60
+ npx-cache copy — so doctor could print `Electron: ok` while every `ui: true` run failed with
61
+ `electron-absent` (the electron-flavored recurrence of the engine's green-while-broken defect).
62
+ The new check enumerates running/global/npx-cache installs (reusing the engine scanner) and
63
+ probes Electron in each through a dual-root resolver — npm nests `electron` under
64
+ `amicus/node_modules` in a global install but hoists it to a sibling in the npx cache (the #69
65
+ layout lesson, now applied to Electron). With `--fix`, binary-missing npx copies are healed in
66
+ place via `repairElectron` under the #56 timeout guard; never-installed copies are reported,
67
+ not repaired.
68
+
69
+ ### Changed
70
+
71
+ - **`workspaceOpenReason` distinguishes a broken Electron from a missing one (#76).**
72
+ `electron-absent` now means the electron package was never installed; the new
73
+ `electron-broken: binary missing under <dir> — run `amicus doctor --fix`` covers the
74
+ package-present-but-binary-missing state (interrupted postinstall, AV quarantine) that the old
75
+ single reason conflated with it — naming the exact dir and the one-command fix.
76
+
6
77
  ## [4.5.0] - 2026-07-28
7
78
 
8
79
  "Save and share your councils" — complex run configurations become one command, repeatable and
package/README.md CHANGED
@@ -15,6 +15,8 @@ Hand Claude a plan, a design, a diff, an architecture decision, a manuscript —
15
15
  [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen?labelColor=1A1C29)](https://nodejs.org)
16
16
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?labelColor=1A1C29)](./CONTRIBUTING.md)
17
17
 
18
+ **[Quick start ↓](#quick-start)** · [Commands](#commands) · [Documentation](#documentation) · [Troubleshooting](#troubleshooting)
19
+
18
20
  > **Supported clients:** Claude Code CLI, Claude Desktop, and Claude Cowork are fully tested and supported. Claude Code web is experimental.
19
21
 
20
22
  </div>
@@ -24,10 +26,10 @@ Hand Claude a plan, a design, a diff, an architecture decision, a manuscript —
24
26
  ## Table of Contents
25
27
 
26
28
  - [What is Amicus](#what-is-amicus)
29
+ - [The Council](#the-council)
27
30
  - [Ways to run the council](#ways-to-run-the-council)
28
31
  - [Quick start](#quick-start)
29
32
  - [Requirements & Dependencies](#requirements--dependencies)
30
- - [The Council](#the-council)
31
33
  - [The parallel window](#the-parallel-window)
32
34
  - [Commands](#commands)
33
35
  - [Models](#models)
@@ -52,7 +54,7 @@ One install delivers six things that work together:
52
54
  - **The `amicus` CLI (with an `am` alias) and an MCP server.** The engine underneath both skills: launches sessions, shares context, runs parallel waves, and exposes the same surface to Claude as MCP tools.
53
55
  - **A self-updating model catalog.** Aliases and validation resolve against a live catalog fetched from provider APIs (cached locally), so model names stay current without a hard-coded table.
54
56
  - **Observability.** `amicus watch <id>` renders any live or finished run (fan-out or council) from any terminal; `--follow` streams milestones as they happen; `--on-complete` fires a hook when a run lands; `--retry-failed` plus opt-in cheaper-model fallbacks recover dead legs without relaunching the whole wave; `amicus spend` answers "what did this cost, and where" with per-run attribution.
55
- - **Council Workspace.** `amicus watch <runId> --ui`: a window that shows a council *thinking* — live seats, the anonymized judge packet, the adjudication matrix, dissent drill-in, chair verdict, and cost-by-seat — for both live and historical runs. It also **auto-opens** on an MCP-invoked council run from Claude Code (local), so you no longer have to remember the flag (see [The Council](#the-council)).
57
+ - **Council Workspace.** `amicus watch <runId> --ui`: a window that shows a council *thinking* — live seats, the anonymized judge packet, the adjudication matrix, dissent drill-in, chair verdict, and cost-by-seat — for both live and historical runs. It also **auto-opens** on an MCP-invoked council run from Claude Code (local), so you no longer have to remember the flag (see [docs/council.md](./docs/council.md#council-workspace-gui)).
56
58
 
57
59
  Claude is the orchestrator. The council and chat skills run *on top of* the engine; you talk to Claude, and Claude drives Amicus.
58
60
 
@@ -60,15 +62,103 @@ Claude is the orchestrator. The council and chat skills run *on top of* the engi
60
62
 
61
63
  ---
62
64
 
65
+ ## The Council
66
+
67
+ > Trigger it by saying *"council review this"* to Claude, or, on the plugin channel, run **`/amicus:council`** directly.
68
+
69
+ **Why multi-model.** Any single model — including the one running your session — has consistent blind spots. Route the *same* material through models from *different* families and the disagreements surface: missed issues, overstated confidence, claims one model alone would have waved through. The council is the structured version of that idea.
70
+
71
+ **The flow, in five beats:**
72
+
73
+ 1. **Independent reviews.** Each council model reviews the artifact on its own (one parallel wave), producing a structured findings list — claim, severity (`blocker | major | minor | nit`), location, rationale.
74
+ 2. **Anonymized cross-review.** Claude relabels every review (Review A, B, C…) and sends the identical bundle to every model. Each model ranks the reviews and adjudicates every finding (`agree | dispute | neutral`) — *unknowingly judging its own*, so self-bias washes out. This yields a **street-cred** ranking and sorts findings into **Disputed / Confirmed / Contested / Singleton** tiers.
75
+ 3. **Chair verdict.** A designated **non-Claude** chair receives the de-anonymized picture — all reviews, rankings, and adjudications — and synthesizes an independent verdict. Claude presents it verbatim; Claude does not synthesize.
76
+ 4. **Tiered decisions.** Confirmed findings get one bulk accept/deny; Contested and Singleton findings are decided one at a time (accept / deny / modify).
77
+ 5. **Outputs applied.** Accepted findings are written into a reviewed copy of the source; the full run is captured in the run folder.
78
+
79
+ ```mermaid
80
+ flowchart LR
81
+ A["Artifact"] --> B["Independent<br/>reviews"]
82
+ B --> C["Anonymized<br/>cross-review"]
83
+ C --> D["Chair verdict<br/>(non-Claude)"]
84
+ D --> E["Tiered<br/>accept / deny"]
85
+ E --> F["Reviewed copy<br/>+ run folder"]
86
+ ```
87
+
88
+ **What a run produces** (in `output/<stem>-council/`):
89
+
90
+ - `review-<model>.md` × N — each model's independent review.
91
+ - `crossreview-matrix.md` — the adjudication grid plus the de-anonymized street-cred table.
92
+ - `verdict.md` — the chair's synthesis.
93
+ - `report.md` — synthesis + the full decision log + a per-call run-stats table.
94
+ - `report.html` — the deterministic renderer output (adjudication matrix, street-cred table,
95
+ findings-by-tier, cost — no chair prose). This is the default artifact handed to the user.
96
+ - For an **editable source**, the accepted edits land in `<stem>-reviewed.<ext>` next to the original.
97
+
98
+ **Optional council elements** (v2.2.0, all default off): five opt-in behaviors, offered once as a menu at launch — nothing turns on unless you name it, and the confirmation lists exactly what's on.
99
+
100
+ - **Critic seat** — one reviewer swaps to a four-pass adversarial brief (adversarial pass, edge-case hunt, consistency check, executability test). Its findings enter the same anonymized bundle as everyone else's, so the bench disciplines the critic: manufactured negativity lands Disputed and dies in the tally.
101
+ - **Expert lenses** — each reviewer takes a distinct expert perspective; you pick the panel domain (business, technical, customer, financial, or custom). Lens runs never feed the reliability ledger, and the report discloses the weakened cross-review anonymity.
102
+ - **Debate mode** — after cross-review, every Contested or Disputed finding goes back to its raiser to **defend, amend, or withdraw**, and the disputing judges re-vote. Exactly one rebuttal round, then the final tally.
103
+ - **Chair verdict scale** — the chair closes with 3–5 hard questions and one parseable line: `VERDICT: Ship it | Fix these first | Fundamental rethink`.
104
+ - **Claude in the council** — Claude adds its own fresh review to the bundle so the bench ranks and adjudicates it. Claude is *judged* but never votes or chairs, so the verdict stays independent.
105
+
106
+ The critic and lens methodologies are adapted from the `/critic` and `/debate` agents in [John Renaldi's product-kit](https://github.com/jrenaldi79/plugin-marketplace) (MIT); the briefing boilerplate lives in [`skills/second-opinion/SEAT-BRIEFS.md`](./skills/second-opinion/SEAT-BRIEFS.md).
107
+
108
+ **Cost is disclosed up front.** Before any model launches, you see the run shape — including any enabled optional elements — for example:
109
+
110
+ > This run uses 3 council models across 2 fanout waves + 1 chair call, with critic seat + debate mode ON (~7 base runs + up to 6 rebuttal calls).
111
+
112
+ Then the council waits for your confirmation.
113
+
114
+ The skill lives at **[`skills/second-opinion/SKILL.md`](./skills/second-opinion/SKILL.md)**; the design spec behind it is **[`skills/second-opinion/COUNCIL-DESIGN.md`](./skills/second-opinion/COUNCIL-DESIGN.md)**. For what `amicus council tally|verdict|report|stats` actually take as input and produce — field-by-field schemas, verdict.json's provenance, and a full worked example run against the real CLI — see **[docs/council.md](./docs/council.md)**.
115
+
116
+ ---
117
+
63
118
  ## Ways to run the council
64
119
 
65
120
  The council is the hero — start with the everyday way, and reach for the more powerful ways when you need them:
66
121
 
67
- - **Just ask, in Claude Code.** Hand Claude a plan, diff, design, or manuscript and say *"council review this."* The `second-opinion` skill runs the whole ritual in your session — several models review independently → anonymized cross-review → a non-Claude chair verdict → tiered accept/deny edits — with no setup beyond your API keys. This is how most people use it. → [The Council](#the-council)
68
- - **Headless, in CI, with no Claude runtime.** `amicus council run --prompt-file plan.md --council free` runs that same pipeline in one command — reviews → cross-review → tally → chair verdict — writing `verdict.json` and `report.html`. It needs no Claude session, so it drops straight into CI. → [Headless council](./docs/council.md#amicus-council-run)
122
+ - **Just ask, in Claude Code.** Hand Claude a plan, diff, design, or manuscript and say *"council review this."* The `second-opinion` skill runs the whole ritual above in your session, with no setup beyond your API keys. This is how most people use it. → [Quick start](#quick-start)
123
+ - **Headless, in CI, with no Claude runtime.** `amicus council run --prompt-file plan.md --council free` runs that same pipeline in one command — reviews → cross-review → tally → chair verdict — writing `verdict.json` and `report.html`. It needs no Claude session, so it drops straight into CI. → [Headless council (CI)](#headless-council-ci)
69
124
  - **With a debate round.** Add `--debate` and every Contested or Disputed finding goes back to its raiser to **defend, amend, or withdraw** while the disputing judges re-vote — exactly one rebuttal round, then the final tally. → [The Council](#the-council)
70
125
  - **On free, local, private models — at $0.** Point the council (and sidecars) at an OpenAI-compatible server already running on your machine — Ollama, LM Studio, or vLLM — with `amicus provider add`. No API key, no per-token bill, nothing leaves your machine, and it works offline. → [`amicus provider`](./docs/usage.md#amicus-provider)
71
126
 
127
+ ### Headless council (CI)
128
+
129
+ The same pipeline runs with no Claude runtime at all: `amicus council run --prompt-file briefing.md --models gemini,glm --chair deepseek --json` executes the review waves, the anonymized cross-review, the tally, and the chair verdict in one command, and writes the full run directory (`verdict.json` with the chair's parsed `overallVerdict`, `report.html`, every review and judge output). That is what powers the repo's own **Council Review GitHub Action v2** — on PRs labeled `council-review` it posts an adjudicated verdict as a check run plus a sticky comment, uploads the run directory as an evidence artifact, and can optionally gate merges via its `fail_on` input (default: report-only). Reference: [docs/council.md](./docs/council.md#amicus-council-run).
130
+
131
+ ### Free council (zero-cost)
132
+
133
+ Want the cross-examination without the model spend? `amicus setup` offers a **Free OpenRouter council** mode — readline wizard option 2, and the Electron **Models** step. It detects the free `:free` models live from the catalog, lets you multi-pick (Enter takes a vendor-diverse default), and saves them as `councils.free` — a first-class `councils` config primitive seeded under collision-safe `free-*` aliases. Your `config.default` is left untouched, and all you need is an `OPENROUTER_API_KEY`.
134
+
135
+ Run it anywhere a council runs:
136
+
137
+ ```bash
138
+ amicus fanout --council free --prompt "Review this design"
139
+ ```
140
+
141
+ The `amicus_fanout` MCP tool takes the same `council` parameter, and the `second-opinion` skill reads `councils.free` automatically. A member that gets delisted is dropped with a warning — the council still runs as long as ≥2 survive. Free models are **rate-limited and quality-variable**, and some return 404 unless you enable data-sharing at [openrouter.ai/settings/privacy](https://openrouter.ai/settings/privacy).
142
+
143
+ ### Council presets
144
+
145
+ Save your own named member lists with `amicus council save <name> --models a,b,c` (≥2 resolvable aliases or `provider/model` IDs), then run them with `--council <name>` anywhere a council runs. `amicus council list` shows saved presets plus three built-in benches that work with no setup at all — `free` (the same zero-cost dynamic pick described above, used when you haven't seeded `councils.free`), `budget` (cheap workhorses, one per vendor family), and `frontier` (premium flagships, one per vendor family). `amicus council show <name>` resolves any of them (saved or built-in) and reports which members are currently usable. A saved council always shadows a built-in of the same name — exactly how the wizard's `councils.free` seeding already worked.
146
+
147
+ ### Policy packs (v4.5)
148
+
149
+ A council preset only saves the bench. A **pack** saves the whole run — bench, chair, critic/lenses, cost/timeout options, and a briefing template — as one named, shareable JSON file:
150
+
151
+ ```bash
152
+ amicus pack save review-bench --kind council --bench gemini,deepseek,gpt --chair opus --timeout 20 --max-cost 2
153
+ amicus council run --pack review-bench --prompt-file plan.md --json
154
+ ```
155
+
156
+ Any flag you also type on that second line overrides just that value — a pack only fills in what you didn't say explicitly, and it's recorded on the run either way. Packs work the same way on `fanout`/`start` and on the `amicus_fanout`/`amicus_start`/`amicus_council_run` MCP tools. `amicus pack list`/`show`/`rm` manage them, and `--from-run <id>` builds one from a run you already liked instead of typing flags at all. Full reference: [docs/usage.md § Policy packs](./docs/usage.md#policy-packs).
157
+
158
+ ### Briefing templates (v4.5)
159
+
160
+ `--template <name> --artifact <file>` (plus repeatable `--var k=v`) renders a `{{prompt}}`/`{{artifact}}`-style Markdown template before it's sent, on `start`/`fanout`/`council run` alike — templates live in `~/.config/amicus/templates/`, and a pack's `briefing.template` is how one reaches an MCP-invoked run (MCP has no template param of its own). `amicus template list|show` manage them; v4.5 ships one built-in, `review`. Full reference: [docs/usage.md § Briefing templates](./docs/usage.md#briefing-templates).
161
+
72
162
  ---
73
163
 
74
164
  ## Quick start
@@ -152,6 +242,14 @@ amicus start --model gemini --prompt "Fact-check the auth approach Claude just p
152
242
 
153
243
  A window opens alongside your editor with Gemini ready, pre-loaded with your conversation. Work with it, then **Fold** the summary back.
154
244
 
245
+ ### Updating
246
+
247
+ Amicus checks the npm registry at most once every 24 hours (cached background check). When an update exists, the CLI prints a notice and the Electron toolbar shows a one-click **Update** banner. Or run it yourself:
248
+
249
+ ```bash
250
+ amicus update
251
+ ```
252
+
155
253
  ### Install from GitHub
156
254
 
157
255
  The npm package is the primary path. To install straight from the repo instead — the postinstall runs **identically** (same MCP registration, same two skills) — you just need `git` on your `PATH`:
@@ -204,82 +302,6 @@ Everything you need before your first run, and what's optional.
204
302
 
205
303
  ---
206
304
 
207
- ## The Council
208
-
209
- > Trigger it by saying *"council review this"* to Claude, or, on the plugin channel, run **`/amicus:council`** directly.
210
-
211
- **Why multi-model.** Any single model — including the one running your session — has consistent blind spots. Route the *same* material through models from *different* families and the disagreements surface: missed issues, overstated confidence, claims one model alone would have waved through. The council is the structured version of that idea.
212
-
213
- **The flow, in five beats:**
214
-
215
- 1. **Independent reviews.** Each council model reviews the artifact on its own (one parallel wave), producing a structured findings list — claim, severity (`blocker | major | minor | nit`), location, rationale.
216
- 2. **Anonymized cross-review.** Claude relabels every review (Review A, B, C…) and sends the identical bundle to every model. Each model ranks the reviews and adjudicates every finding (`agree | dispute | neutral`) — *unknowingly judging its own*, so self-bias washes out. This yields a **street-cred** ranking and sorts findings into **Disputed / Confirmed / Contested / Singleton** tiers.
217
- 3. **Chair verdict.** A designated **non-Claude** chair receives the de-anonymized picture — all reviews, rankings, and adjudications — and synthesizes an independent verdict. Claude presents it verbatim; Claude does not synthesize.
218
- 4. **Tiered decisions.** Confirmed findings get one bulk accept/deny; Contested and Singleton findings are decided one at a time (accept / deny / modify).
219
- 5. **Outputs applied.** Accepted findings are written into a reviewed copy of the source; the full run is captured in the run folder.
220
-
221
- **What a run produces** (in `output/<stem>-council/`):
222
-
223
- - `review-<model>.md` × N — each model's independent review.
224
- - `crossreview-matrix.md` — the adjudication grid plus the de-anonymized street-cred table.
225
- - `verdict.md` — the chair's synthesis.
226
- - `report.md` — synthesis + the full decision log + a per-call run-stats table.
227
- - `report.html` — the deterministic renderer output (adjudication matrix, street-cred table,
228
- findings-by-tier, cost — no chair prose). This is the default artifact handed to the user.
229
- - For an **editable source**, the accepted edits land in `<stem>-reviewed.<ext>` next to the original.
230
-
231
- **Optional council elements** (v2.2.0, all default off): five opt-in behaviors, offered once as a menu at launch — nothing turns on unless you name it, and the confirmation lists exactly what's on.
232
-
233
- - **Critic seat** — one reviewer swaps to a four-pass adversarial brief (adversarial pass, edge-case hunt, consistency check, executability test). Its findings enter the same anonymized bundle as everyone else's, so the bench disciplines the critic: manufactured negativity lands Disputed and dies in the tally.
234
- - **Expert lenses** — each reviewer takes a distinct expert perspective; you pick the panel domain (business, technical, customer, financial, or custom). Lens runs never feed the reliability ledger, and the report discloses the weakened cross-review anonymity.
235
- - **Debate mode** — after cross-review, every Contested or Disputed finding goes back to its raiser to **defend, amend, or withdraw**, and the disputing judges re-vote. Exactly one rebuttal round, then the final tally.
236
- - **Chair verdict scale** — the chair closes with 3–5 hard questions and one parseable line: `VERDICT: Ship it | Fix these first | Fundamental rethink`.
237
- - **Claude in the council** — Claude adds its own fresh review to the bundle so the bench ranks and adjudicates it. Claude is *judged* but never votes or chairs, so the verdict stays independent.
238
-
239
- The critic and lens methodologies are adapted from the `/critic` and `/debate` agents in [John Renaldi's product-kit](https://github.com/jrenaldi79/plugin-marketplace) (MIT); the briefing boilerplate lives in [`skills/second-opinion/SEAT-BRIEFS.md`](./skills/second-opinion/SEAT-BRIEFS.md).
240
-
241
- **Cost is disclosed up front.** Before any model launches, you see the run shape — including any enabled optional elements — for example:
242
-
243
- > This run uses 3 council models across 2 fanout waves + 1 chair call, with critic seat + debate mode ON (~7 base runs + up to 6 rebuttal calls).
244
-
245
- Then the council waits for your confirmation.
246
-
247
- The skill lives at **[`skills/second-opinion/SKILL.md`](./skills/second-opinion/SKILL.md)**; the design spec behind it is **[`skills/second-opinion/COUNCIL-DESIGN.md`](./skills/second-opinion/COUNCIL-DESIGN.md)**. For what `amicus council tally|verdict|report|stats` actually take as input and produce — field-by-field schemas, verdict.json's provenance, and a full worked example run against the real CLI — see **[docs/council.md](./docs/council.md)**.
248
-
249
- **Headless council (CI).** The same pipeline runs with no Claude runtime at all: `amicus council
250
- run --prompt-file briefing.md --models gemini,glm --chair deepseek --json` executes the review
251
- waves, the anonymized cross-review, the tally, and the chair verdict in one command, and writes
252
- the full run directory (`verdict.json` with the chair's parsed `overallVerdict`, `report.html`,
253
- every review and judge output). That is what powers the repo's own **Council Review GitHub Action
254
- v2** — on PRs labeled `council-review` it posts an adjudicated verdict as a check run plus a
255
- sticky comment, uploads the run directory as an evidence artifact, and can optionally gate merges
256
- via its `fail_on` input (default: report-only). Reference: [docs/council.md](./docs/council.md#amicus-council-run).
257
-
258
- **Free council (zero-cost).** Want the cross-examination without the model spend? `amicus setup` offers a **Free OpenRouter council** mode — readline wizard option 2, and the Electron **Models** step. It detects the free `:free` models live from the catalog, lets you multi-pick (Enter takes a vendor-diverse default), and saves them as `councils.free` — a first-class `councils` config primitive seeded under collision-safe `free-*` aliases. Your `config.default` is left untouched, and all you need is an `OPENROUTER_API_KEY`.
259
-
260
- Run it anywhere a council runs:
261
-
262
- ```bash
263
- amicus fanout --council free --prompt "Review this design"
264
- ```
265
-
266
- The `amicus_fanout` MCP tool takes the same `council` parameter, and the `second-opinion` skill reads `councils.free` automatically. A member that gets delisted is dropped with a warning — the council still runs as long as ≥2 survive. Free models are **rate-limited and quality-variable**, and some return 404 unless you enable data-sharing at [openrouter.ai/settings/privacy](https://openrouter.ai/settings/privacy).
267
-
268
- **Council presets.** Save your own named member lists with `amicus council save <name> --models a,b,c` (≥2 resolvable aliases or `provider/model` IDs), then run them with `--council <name>` anywhere a council runs. `amicus council list` shows saved presets plus three built-in benches that work with no setup at all — `free` (the same zero-cost dynamic pick described above, used when you haven't seeded `councils.free`), `budget` (cheap workhorses, one per vendor family), and `frontier` (premium flagships, one per vendor family). `amicus council show <name>` resolves any of them (saved or built-in) and reports which members are currently usable. A saved council always shadows a built-in of the same name — exactly how the wizard's `councils.free` seeding already worked.
269
-
270
- **Policy packs (v4.5).** A council preset only saves the bench. A **pack** saves the whole run — bench, chair, critic/lenses, cost/timeout options, and a briefing template — as one named, shareable JSON file:
271
-
272
- ```bash
273
- amicus pack save review-bench --kind council --bench gemini,deepseek,gpt --chair opus --timeout 20 --max-cost 2
274
- amicus council run --pack review-bench --prompt-file plan.md --json
275
- ```
276
-
277
- Any flag you also type on that second line overrides just that value — a pack only fills in what you didn't say explicitly, and it's recorded on the run either way. Packs work the same way on `fanout`/`start` and on the `amicus_fanout`/`amicus_start`/`amicus_council_run` MCP tools. `amicus pack list`/`show`/`rm` manage them, and `--from-run <id>` builds one from a run you already liked instead of typing flags at all. Full reference: [docs/usage.md § Policy packs](./docs/usage.md#policy-packs).
278
-
279
- **Briefing templates (v4.5).** `--template <name> --artifact <file>` (plus repeatable `--var k=v`) renders a `{{prompt}}`/`{{artifact}}`-style Markdown template before it's sent, on `start`/`fanout`/`council run` alike — templates live in `~/.config/amicus/templates/`, and a pack's `briefing.template` is how one reaches an MCP-invoked run (MCP has no template param of its own). `amicus template list|show` manage them; v4.5 ships one built-in, `review`. Full reference: [docs/usage.md § Briefing templates](./docs/usage.md#briefing-templates).
280
-
281
- ---
282
-
283
305
  ## The parallel window
284
306
 
285
307
  When you don't need a full council — just one other model's take — fork a conversation. Amicus extracts your current Claude Code context, opens a session pre-loaded with it, you **work** alongside it, and you **fold** a structured summary back into Claude's context when you're done.
@@ -305,12 +327,6 @@ When you don't need a full council — just one other model's take — fork a co
305
327
 
306
328
  **Safety.** Amicus warns on **file conflicts** (a file changed externally while the session ran) and on **context drift** (the shared context may be stale relative to your current session), so a fold never silently overwrites newer work.
307
329
 
308
- **Auto-update.** Amicus checks the npm registry at most once every 24 hours (cached background check). When an update exists, the CLI prints a notice and the Electron toolbar shows a one-click **Update** banner. Or run it yourself:
309
-
310
- ```bash
311
- amicus update
312
- ```
313
-
314
330
  ![The parallel-window architecture: fork, work, fold](./docs/architecture.png)
315
331
 
316
332
  ---
@@ -332,7 +348,7 @@ amicus update
332
348
  | `amicus spend` | Cross-run cost rollup from the spend ledger, with per-run attribution — total + per-model spend, tokens, and source mix, most-expensive first (`--wave`/`--council`/`--project`/`--model`/`--op`/`--failed` filter it, `--group-by` buckets it, `--since 7d` windows it; `--json` for a versioned doc; shows remaining OpenRouter credit when a key is configured). |
333
349
  | `amicus key` | Manage API keys non-interactively: `amicus key <provider> <key>` saves after live validation; `--remove`; bare `amicus key` lists providers. |
334
350
  | `amicus provider` | Add/list/test/remove local, OpenAI-compatible providers (LM Studio, Ollama, vLLM) — configured with `--preset` or `--url`, at **$0** marginal cost (`--json` on every subcommand). |
335
- | `amicus council` | Council math: `tally <input.json>` (deterministic tiers + ledger append), `stats` (reviewer reliability), `report <verdict.json> [--md\|--html]`, `validate <file>` (findings-block check, exit 0/2/1), `verdict <tally.json> [--decisions <d.json>] [-o <out.json>]` (build + write verdict.json). Presets: `save <name> --models a,b,c`, `list [--json]`, `show <name> [--json]` — see [The Council](#the-council) for the built-in `free`/`budget`/`frontier` benches. |
351
+ | `amicus council` | Council math: `tally <input.json>` (deterministic tiers + ledger append), `stats` (reviewer reliability), `report <verdict.json> [--md\|--html]`, `validate <file>` (findings-block check, exit 0/2/1), `verdict <tally.json> [--decisions <d.json>] [-o <out.json>]` (build + write verdict.json). Presets: `save <name> --models a,b,c`, `list [--json]`, `show <name> [--json]` — see [Council presets](#council-presets) for the built-in `free`/`budget`/`frontier` benches. |
336
352
  | `amicus council run` | The headless council engine: Stage-1 reviews → anonymized cross-review → deterministic tally → non-Claude chair verdict, in one command with no Claude runtime. Add `--debate` for a Stage-2.5 rebuttal round (raisers defend/amend/withdraw, disputing judges re-vote) and `--claude-review <file>` to enter Claude's own review as judged review N+1. Writes a run directory with `verdict.json` (including `overallVerdict`) and `report.html` — see [docs/council.md](./docs/council.md#amicus-council-run). |
337
353
  | `amicus pack` | Save a full run configuration — bench, chair/critic/lenses, options, briefing template — and invoke it by name: `save <name> --kind council\|fanout\|solo [flags]` (or `--from-run <id>`), `list`, `show <name>`, `rm <name>`. `--pack <name>` on `start`/`fanout`/`council run` loads one; explicit flags always override it. See [docs/usage.md § Policy packs](./docs/usage.md#policy-packs). |
338
354
  | `amicus template` | `list`/`show <name>` a briefing template. `--template <name> [--artifact <file>] [--var k=v]` on `start`/`fanout`/`council run` renders one before the briefing is sent. See [docs/usage.md § Briefing templates](./docs/usage.md#briefing-templates). |
@@ -364,7 +380,7 @@ $ amicus status demo123 --json
364
380
  "taskId": "demo123",
365
381
  "status": "complete",
366
382
  "elapsed": "5m 0s",
367
- "version": "4.5.0",
383
+ "version": "4.5.2",
368
384
  "model": "google/gemini-2.5-flash",
369
385
  "phase": "terminal"
370
386
  }
@@ -474,7 +490,7 @@ Run `amicus doctor` first — it checks keys, catalog, OpenCode binary, Electron
474
490
  | `npm install -g amicus` fails with `EEXIST: … claude-sidecar` | The old upstream `claude-sidecar` package is still installed globally; npm won't overwrite another package's bin shims | `npm uninstall -g claude-sidecar`, then `npm install -g amicus`. Your keys and past sessions are not lost, but v2.0.0 no longer reads the old paths automatically — see [docs/SHIMS.md](./docs/SHIMS.md) for the one-time migration steps (rename `~/.config/sidecar/` and any `.claude/sidecar_sessions/` dirs). |
475
491
  | Install fails partway, or `amicus doctor` reports the OpenCode binary "not found" | A **transient** error during the OpenCode engine's own postinstall (a spawn `ENOENT`, or an antivirus file-lock while it lays down its 11 per-platform binaries) can roll back the whole atomic install — retrying usually succeeds | Just re-run `npm install -g amicus`. If it still fails, clear the cache first: `npm cache clean --force && npm install -g amicus`. |
476
492
  | `401` / auth error | No usable key for the model's vendor — bare `provider/model` ids fall back to `OPENROUTER_API_KEY` automatically, so this means neither the direct key nor an OpenRouter key is configured (or `--gateway direct`/`openrouter` forced a gateway whose key is missing) | Run `amicus setup`, or `amicus key <provider> <key>` to add the missing key; see [Routing](#routing). |
477
- | `402` / "Payment Required" on first council review / `start` / `fanout` call | Your OpenRouter key is real but has no credit. Key save (`amicus key openrouter <key>` or the setup wizard's key step) only checks that the key **authenticates** — it doesn't check balance, so a zero-credit key saves cleanly and only fails later, on the first real model call. (The `amicus council` subcommand itself is deterministic math and never calls a model.) | Add credit at [openrouter.ai/credits](https://openrouter.ai/credits), **or** switch to a zero-cost council: `amicus setup` → option 2 (Free OpenRouter council) builds one from live `:free`-suffixed models and saves it as `councils.free` — then run `amicus fanout --council free …`. See "Free council (zero-cost)" under [The Council](#the-council) above. |
493
+ | `402` / "Payment Required" on first council review / `start` / `fanout` call | Your OpenRouter key is real but has no credit. Key save (`amicus key openrouter <key>` or the setup wizard's key step) only checks that the key **authenticates** — it doesn't check balance, so a zero-credit key saves cleanly and only fails later, on the first real model call. (The `amicus council` subcommand itself is deterministic math and never calls a model.) | Add credit at [openrouter.ai/credits](https://openrouter.ai/credits), **or** switch to a zero-cost council: `amicus setup` → option 2 (Free OpenRouter council) builds one from live `:free`-suffixed models and saves it as `councils.free` — then run `amicus fanout --council free …`. See [Free council (zero-cost)](#free-council-zero-cost) above. |
478
494
  | Every direct `anthropic/…` model (`haiku`, `sonnet`, `opus`, `claude`) errors `Not Found` in ~2 s at zero tokens, but the same model works via `openrouter/anthropic/…` | An inherited `ANTHROPIC_BASE_URL` missing its `/v1` path segment. The engine appends only `/messages`, so requests hit `https://api.anthropic.com/messages` → HTTP 404 with an empty body → the bare status text. A shell spawned by Claude Code sets the `/v1`-less form for you. The model id, alias, and key are all fine. | `export ANTHROPIC_BASE_URL=https://api.anthropic.com/v1`, or unset it entirely, or pass `--gateway openrouter`. In a council a dead seat **degrades the run instead of failing it** — smoke-test each seat with one throwaway `amicus start` before paying for a council. See [docs/troubleshooting.md](./docs/troubleshooting.md#every-direct-anthropic-model-fails-with-not-found). |
479
495
  | `Model 'X' is unverified against the direct catalog; attempting anyway` for a model that plainly exists | Not a claim the model is wrong — amicus **couldn't check**. That vendor's direct catalog fetch failed (usually a stale or truncated stored key), leaving its namespace empty, and an empty namespace never blocks a launch. The engine may still run the model from its own credential store, so a working model warns forever. | `amicus models --refresh` and watch for a provider that stays empty; re-save the good key with `amicus key <provider> <apikey>`. See [docs/troubleshooting.md](./docs/troubleshooting.md#model-x-is-unverified-against-the-direct-catalog-attempting-anyway). |
480
496
  | Session not found | No session matches the given ID | Run `amicus list`, or omit `--session-id` to use the most recent. |
package/docs/ROADMAP.md CHANGED
@@ -7,14 +7,12 @@ major jump, gated on funding/cofounder. The observability arc is split so the **
7
7
  first (v4.3)** and the **Electron "Council Workspace" (v4.4)** rides on top of it. `--dry-run` cost
8
8
  preview dropped to the backlog.
9
9
 
10
- Amicus is at **v4.4.1** (2026-07-27), the fast-follow patch on v4.4.0 (tagged 2026-07-26). Each
11
- 4.x rev below leads with the benefit, not the plumbing.
10
+ Amicus is at **v4.5.0** (tagged 2026-07-28). Each 4.x rev below leads with the benefit, not the
11
+ plumbing.
12
12
 
13
- **Status:** v4.0 through **v4.4.1** have **shipped** — everything down to the v4.5 heading is a
14
- record of what landed, not a plan. **v4.5 (packs + templates + auto-open) is the next rev**, with
15
- **v4.6 (composition + tagging + GUI ergonomics)** behind it — the former combined v4.5 scope,
16
- split 2026-07-27 (design: `docs/superpowers/specs/2026-07-27-v4.5-save-and-share-design.md`). v5.0
17
- remains forward-looking.
13
+ **Status:** v4.0 through **v4.5.0** have **shipped** — everything down to the v4.6 heading is a
14
+ record of what landed, not a plan. **v4.6 (composition + tagging + GUI ergonomics) is the next
15
+ rev.** v5.0 remains forward-looking.
18
16
 
19
17
  > 📁 **Reading this from an npm install?** Some references below point at working documents that
20
18
  > live in the git repository and are deliberately **not** in the published package — anything under
@@ -87,7 +85,7 @@ and a review that honestly finds nothing stops being an error.
87
85
  > repo's working notes (`.superpowers/sdd/v441/backlog-and-proposal.md`, local-only) and in the
88
86
  > repo's root `BACKLOG.md` — neither ships in the npm package; see the note at the top.
89
87
 
90
- ## v4.5 — "Save and share your councils" *(scope split 2026-07-27 — composition moved to v4.6)*
88
+ ## v4.5 — "Save and share your councils" *(scope split 2026-07-27 — composition moved to v4.6)* — ✅ SHIPPED v4.5.0, 2026-07-28
91
89
  **Benefit:** complex councils become one-command, repeatable, and shareable — and the flagship GUI
92
90
  stops hiding. Design: `docs/superpowers/specs/2026-07-27-v4.5-save-and-share-design.md`.
93
91
  - **★ Auto-open the Council Workspace on a council run (Christian, 2026-07-26)** — when a council is
@@ -137,6 +137,22 @@ Legacy `SIDECAR_IDLE_TIMEOUT*` names were removed in v2.0.0 — rename to the `A
137
137
 
138
138
  Set `AMICUS_IDLE_TIMEOUT=0` to disable self-termination entirely.
139
139
 
140
+ ### Server startup
141
+
142
+ | Variable | Purpose | Default |
143
+ |----------|---------|---------|
144
+ | `AMICUS_SERVER_START_TIMEOUT_MS` | How long to wait for OpenCode to report it is listening before treating the start as failed. | `30000` on Windows, `15000` elsewhere |
145
+
146
+ A start that exceeds this window is treated as **transient** and retried on the same bounded schedule as an OpenCode database lock race (5 attempts, 250/500/1000/2000 ms), because retrying costs nothing but the backoff while a failed start costs a whole review seat.
147
+
148
+ Raise it if you see `Timeout waiting for server to start` on a slow box — a project directory on a sync-backed volume (OneDrive, Dropbox) with an antivirus scanner attached can push a cold OpenCode/SQLite start well past the default. Values of `0` or below are ignored rather than honored, since a zero start timeout fails every start instantly.
149
+
150
+ To see how much headroom you actually have, run with `LOG_LEVEL=debug` and look for the `OpenCode server started` line — it reports both `startMs` (what the start took) and `timeoutMs` (the ceiling it ran against):
151
+
152
+ ```json
153
+ {"level":"debug","msg":"OpenCode server started","startMs":561,"timeoutMs":30000}
154
+ ```
155
+
140
156
  ### Shared server
141
157
 
142
158
  The shared-server mode (`AMICUS_SHARED_SERVER=1`, which is the default) lets multiple Amicus sessions reuse a single OpenCode Go binary process rather than spawning one per invocation, eliminating cold-start latency on the second and subsequent calls. Disable it with `AMICUS_SHARED_SERVER=0` if you need per-process isolation or are diagnosing a crash loop.
package/docs/council.md CHANGED
@@ -413,8 +413,11 @@ bottom, first match wins:
413
413
  6. Otherwise → opens.
414
414
 
415
415
  **Response fields.** `amicus_council_run`'s result always carries `workspaceOpened: boolean`, and,
416
- **only when it did not open**, `workspaceOpenReason` — one of `param-suppressed`, `electron-absent`,
417
- `no-display`, `config-disabled`, `client-not-code-local`, or a `spawn-failed:`/`auto-open-failed:`
416
+ **only when it did not open**, `workspaceOpenReason` — one of `param-suppressed`, `electron-absent`
417
+ (the electron package was never installed for this copy), an `electron-broken:` detail (the package
418
+ is present but its binary never arrived — interrupted download or AV quarantine; the reason names
419
+ the electron dir and points at `amicus doctor --fix`), `no-display`, `config-disabled`,
420
+ `client-not-code-local`, or a `spawn-failed:`/`auto-open-failed:`
418
421
  detail if the decision said to open but the launch itself failed. The launch is fire-and-forget: it
419
422
  never blocks the tool's response, and a launch failure never fails the council run itself — the run
420
423
  proceeds exactly as it would with no Workspace at all, and `amicus watch <runId> --ui` still works
package/docs/usage.md CHANGED
@@ -443,7 +443,7 @@ $ amicus status demo123 --json
443
443
  "taskId": "demo123",
444
444
  "status": "complete",
445
445
  "elapsed": "5m 0s",
446
- "version": "4.5.0",
446
+ "version": "4.5.2",
447
447
  "model": "google/gemini-2.5-flash",
448
448
  "phase": "terminal"
449
449
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amicus",
3
- "version": "4.5.0",
3
+ "version": "4.5.2",
4
4
  "mcpName": "io.github.BourbonDog/amicus",
5
5
  "description": "Multi-model LLM Council + parallel AI window for Claude Code. Run structured council reviews across Gemini, GPT, DeepSeek and more — or fork a conversation to any model and fold the results back.",
6
6
  "keywords": [
@@ -77,6 +77,7 @@
77
77
  "@modelcontextprotocol/sdk": "^1.27.0",
78
78
  "@opencode-ai/sdk": "^1.1.36",
79
79
  "dotenv": "^17.2.3",
80
+ "extract-zip": "^2.0.1",
80
81
  "opencode-ai": "^1.2.20",
81
82
  "tiktoken": "^1.0.0",
82
83
  "update-notifier": "^7.3.1",
@@ -93,7 +94,7 @@
93
94
  "jest": "^29.0.0",
94
95
  "lint-staged": "^16.3.2",
95
96
  "puppeteer": "^24.36.0",
96
- "sharp": "^0.33.5",
97
+ "sharp": "^0.35.3",
97
98
  "ws": "^8.19.0"
98
99
  },
99
100
  "engines": {