amicus 4.0.1 → 4.1.1
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.
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +169 -0
- package/README.md +4 -4
- package/commands/council.md +6 -6
- package/package.json +3 -2
- package/schemas/council-run.schema.json +15 -1
- package/schemas/council-tally.schema.json +10 -1
- package/schemas/council-verdict.schema.json +10 -1
- package/schemas/error.schema.json +1 -1
- package/scripts/postinstall.js +6 -3
- package/skills/second-opinion/COUNCIL-DESIGN.md +40 -0
- package/skills/second-opinion/MANUAL-ORCHESTRATION.md +266 -0
- package/skills/second-opinion/MODEL-NOTES.md +21 -0
- package/skills/second-opinion/SEAT-BRIEFS.md +4 -0
- package/skills/second-opinion/SKILL.md +319 -333
- package/skills/sidecar/SKILL.md +5 -5
- package/src/cli-handlers-council-run.js +9 -0
- package/src/cli-handlers-council.js +20 -2
- package/src/cli.js +8 -0
- package/src/council/briefings-debate.js +158 -0
- package/src/council/briefings-stage2.js +16 -9
- package/src/council/debate.js +98 -0
- package/src/council/ledger.js +2 -1
- package/src/council/parse-stage2.js +83 -1
- package/src/council/report-html.js +28 -1
- package/src/council/report.js +64 -4
- package/src/council/run-assemble.js +91 -9
- package/src/council/run-chair.js +145 -0
- package/src/council/run-debate.js +293 -0
- package/src/council/run-launch.js +27 -1
- package/src/council/run-stages.js +19 -7
- package/src/council/run.js +104 -110
- package/src/council/verdict.js +43 -2
- package/src/mcp-council-run.js +7 -0
- package/src/mcp-server.js +28 -3
- package/src/mcp-tools.js +24 -4
- package/src/utils/curated-models.js +22 -20
- package/src/utils/error-doc.js +2 -0
- package/src/utils/model-fetcher.js +6 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amicus",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.1",
|
|
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
|
@@ -5,6 +5,175 @@ All notable changes to Amicus are documented here. Format follows
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [4.1.1] - 2026-07-21
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **The integration tier is tested again, and now something actually watches it.** All 14
|
|
13
|
+
`tests/**/*.integration.test.js` files were unreachable from every gate — `jest.config.js` excludes
|
|
14
|
+
them from `npm test`, no workflow ran `npm run test:integration`, and the pre-push hook ran only the
|
|
15
|
+
unit suite. Six tests had been failing unnoticed behind a single dead model alias: three E2E suites
|
|
16
|
+
passed `--model gemini-flash`, which is not a live alias (`tryResolveModel('gemini-flash')` returns
|
|
17
|
+
`Unknown model alias`). They now pass `gemini`.
|
|
18
|
+
- **`--claude-review` reports no longer grow a blank `claude` judge column, or a false self-vote `*`.**
|
|
19
|
+
`report.js`'s `toModel()` reused `verdict.council` (the street-cred universe, which legitimately
|
|
20
|
+
includes `claude` on a `--claude-review` run) as the adjudication-matrix judge roster too. Claude is
|
|
21
|
+
judged but never judges, so the matrix grew an extra column that always rendered blank, or a bare
|
|
22
|
+
`*` on a row Claude itself raised — asserting Claude voted for its own finding, the opposite of the
|
|
23
|
+
documented guarantee. `judges` is now filtered out of `council` independently (gated on the
|
|
24
|
+
`claudeInCouncil` flag plus the `claude` name, never on whether a model cast any adjudications, so a
|
|
25
|
+
genuinely dead/unstructured bench judge with zero votes still keeps its blank column).
|
|
26
|
+
- **`debate-revote` now checkpoints `skipped`, not a false `complete`, when the re-vote wave never
|
|
27
|
+
launches** (nothing was defended/amended, or the cost ceiling skipped it). **This is a
|
|
28
|
+
consumer-visible `run.json` value change**: anything parsing `stages[].status` for this stage — the
|
|
29
|
+
Council Review Action's stage-ladder footer, `amicus status`, or a user script — now sees `skipped`
|
|
30
|
+
instead of `complete` on a run that hits this path. Neither the Action's footer nor `amicus
|
|
31
|
+
status`'s human/JSON renderers special-case `complete`, so both already print whatever value is
|
|
32
|
+
there correctly; a script that hard-coded an expectation of `complete` for this stage should treat
|
|
33
|
+
`skipped` as the equivalent no-op, the same way `run-chair.js`'s existing chair-skipped-over-budget
|
|
34
|
+
convention already works.
|
|
35
|
+
- **`amicus council verdict --render` now writes `report.html` at `0o600`**, matching every sibling
|
|
36
|
+
writer (`run-assemble.js`, `mcp-server.js`'s `amicus_verdict` `render:true` path, `run-launch.js`).
|
|
37
|
+
It previously wrote with no explicit mode, which falls back to the process umask (typically `0o644`
|
|
38
|
+
on POSIX — group/world-readable) whenever the target directory had no pre-existing `report.html`,
|
|
39
|
+
i.e. exactly the fresh-`--out-dir` case, for a file that holds model output.
|
|
40
|
+
- **Dropped the false `amicus wait` CLI claim.** `docs/usage.md` and `docs/council.md` both documented
|
|
41
|
+
`amicus status|wait|abort <councilRunId>` as working CLI commands. There is no CLI `wait` (verified
|
|
42
|
+
against `bin/amicus.js`'s command dispatch) — only `status` and `abort` genuinely resolve council
|
|
43
|
+
runs via the sessions-dir pointer file. Both docs now point readers at the MCP `amicus_wait` tool
|
|
44
|
+
instead.
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- **Keyless integration job in CI.** `.github/workflows/ci.yml` gained an `integration` job that runs
|
|
49
|
+
`npm run test:integration` with no secrets on every push and PR, so the tier is permanently watched
|
|
50
|
+
for free (~51 assertions, ~10s). `npm run test:integration` now goes through
|
|
51
|
+
`scripts/run-integration-keyless.js`, which strips every provider credential and sandboxes
|
|
52
|
+
`HOME`/`USERPROFILE` before spawning jest — the money-spending suites self-skip and the script cannot
|
|
53
|
+
bill even on a machine with keys on disk. The scrub derives its key names from the engine's own
|
|
54
|
+
`PROVIDER_ENV_MAP`, so it covers providers and paid suites added later without maintenance.
|
|
55
|
+
- **`npm run test:integration:live`** — the paid rail, split out so the CI job cannot silently start
|
|
56
|
+
billing if secrets are ever added to it. Run by the new `.github/workflows/integration-live.yml`
|
|
57
|
+
(`workflow_dispatch` only, carries `secrets.OPENROUTER_API_KEY`) and by the release checklist in
|
|
58
|
+
`docs/publishing.md`.
|
|
59
|
+
|
|
60
|
+
### Fixed (docs)
|
|
61
|
+
|
|
62
|
+
- `docs/testing.md` and `CLAUDE.md` both claimed a pre-push integration gate that has never existed;
|
|
63
|
+
the pre-push hook runs the unit suite only, deliberately, so a local push never spends money. Both
|
|
64
|
+
now describe the real rails, and `.husky/pre-push`'s stale "until the 'Fix integration tests' task
|
|
65
|
+
lands" comment is replaced with the reason the hook stays unit-only.
|
|
66
|
+
- **`amicus doctor` no longer warns about Amicus's own shipped defaults — on a fresh install, and in
|
|
67
|
+
the keyless `model-drift.yml` CI check.** Both previously reported `⚠ Model aliases: 2 stale: opus,
|
|
68
|
+
haiku` (and the scheduled Model Drift Check ran red) with no user config involved.
|
|
69
|
+
`toDefaultAliases()` built each alias's pinned id by string-stripping the `openrouter/` prefix
|
|
70
|
+
instead of routing through the module's own `directFormFor()`, so it emitted OpenRouter's dot ids
|
|
71
|
+
for Anthropic — `anthropic/claude-opus-4.8`, `anthropic/claude-haiku-4.5` — which the direct API
|
|
72
|
+
rejects, and invented a bare `anthropic/claude-fable-5` for a model OpenRouter serves exclusively.
|
|
73
|
+
Defaults now come from `toGatewayRoutes()`, so an alias resolves to its authored direct form when
|
|
74
|
+
one exists (`anthropic/claude-opus-4-8`, `anthropic/claude-haiku-4-5-20251001`) and to its
|
|
75
|
+
OpenRouter route when none does (`openrouter/anthropic/claude-fable-5`). `fable`'s *recorded* form
|
|
76
|
+
changes, but this is **not a routing change** — OpenRouter was already the only gateway that serves
|
|
77
|
+
it, so a `fable` run resolves and routes identically before and after; only the id `doctor`/`amicus
|
|
78
|
+
models` display and compare against is different. Council artifacts are unaffected either way — they
|
|
79
|
+
record alias strings, not resolved ids.
|
|
80
|
+
- **This fix does not reach everyone who already ran `amicus setup`.** `createDefaultConfig()`
|
|
81
|
+
(`src/sidecar/setup.js`) persists the *entire* default alias map into `config.json` at setup time,
|
|
82
|
+
and `getEffectiveAliases()` lets that persisted user config win over the shipped defaults — so
|
|
83
|
+
anyone who ran `amicus setup` on Amicus ≤4.1.0 has the old, broken ids frozen on disk
|
|
84
|
+
(`source: user-config`), which `findStaleAliases()` never suppresses. Measured: such a user sees
|
|
85
|
+
**4 stale** aliases after upgrading to 4.1.1 — `opus`, `haiku`, `fable` (the pre-fix ids) plus
|
|
86
|
+
`gemini` (this release's own pin move, see Changed below) — not zero, and `amicus doctor` /
|
|
87
|
+
the Model Drift Check will keep warning for them. **There is no code fix for this in 4.1.1**; a
|
|
88
|
+
self-healing config migration is a 4.2 candidate. If `amicus doctor` still warns after upgrading,
|
|
89
|
+
re-run `amicus setup`, or fix individual aliases by hand, e.g.
|
|
90
|
+
`amicus setup --add-alias opus=anthropic/claude-opus-4-8`.
|
|
91
|
+
- The offline Anthropic model floor now also lists `anthropic/claude-haiku-4-5-20251001`, the dated id
|
|
92
|
+
Anthropic's own listing returns. Without it, keyless and OpenRouter-only users saw the shipped
|
|
93
|
+
`haiku` default reported stale against the shipped floor.
|
|
94
|
+
|
|
95
|
+
### Changed
|
|
96
|
+
|
|
97
|
+
- **Curated `gemini` pin moves from Gemini 3.5 Flash to Gemini 3.6 Flash on both gateways.** This is a
|
|
98
|
+
**silent model change, not merely a drift-notice cleanup**: a user with no `gemini` alias override of
|
|
99
|
+
their own starts talking to a different underlying model the next time they use the `gemini` alias
|
|
100
|
+
after upgrading. It also clears the pinned-fallback drift notice from `amicus models --check`.
|
|
101
|
+
|
|
102
|
+
## [4.1.0] - 2026-07-21
|
|
103
|
+
|
|
104
|
+
The `second-opinion` skill stops hand-driving councils. Stages 1–3 and the Stage-5 artifacts
|
|
105
|
+
collapse into a single `amicus council run`, leaving Claude only the stages that genuinely need
|
|
106
|
+
judgement — intake, decisions, and lessons. The engine gains an optional rebuttal round so a
|
|
107
|
+
finding's author can answer the reviewers who disputed it, and Claude can now enter its own review
|
|
108
|
+
into the bundle without ever being launched as a model leg.
|
|
109
|
+
|
|
110
|
+
### Added
|
|
111
|
+
|
|
112
|
+
- **Skill fast path.** `skills/second-opinion/SKILL.md` now delegates Stages 1–3 (and the Stage-5
|
|
113
|
+
artifact materialization) to one `amicus council run` invocation; the human stages (0 intake,
|
|
114
|
+
4 decisions, 6 lessons) stay Claude-orchestrated. The manual mechanics are preserved verbatim in
|
|
115
|
+
the new `skills/second-opinion/MANUAL-ORCHESTRATION.md` as the documented fallback for when the
|
|
116
|
+
engine is unavailable or a case the fast path cannot express.
|
|
117
|
+
- **Headless debate mode** — `amicus council run --debate` / `amicus_council_run {debate:true}`.
|
|
118
|
+
A Stage-2.5 rebuttal round runs between cross-review and the final tally: findings that came out
|
|
119
|
+
Contested or Disputed go back to the model that raised them, which defends, amends, or withdraws
|
|
120
|
+
each; the judges who disputed them then re-vote; a final tally folds the outcome in. Exactly one
|
|
121
|
+
round, structurally — there is no edge back into a debate stage. `run.json` gains an additive
|
|
122
|
+
`debate` summary, tally/verdict findings gain a `debate` decoration, and both report renderers
|
|
123
|
+
gain a "Debate round" section. The Council Review Action gains a `debate` input (default off),
|
|
124
|
+
and withdrawn findings are excluded from its PR annotations.
|
|
125
|
+
- **`--claude-review <file>` / `claudeReviewFile`.** Enters Claude's own review as judged review
|
|
126
|
+
N+1 from a file. No model leg is ever launched for it and it may never chair — `claude` is a
|
|
127
|
+
reserved seat name that is rejected pre-flight in `--models`, `--chair` and `--critic` on such a
|
|
128
|
+
run.
|
|
129
|
+
- **`--render` on `council verdict`, `render:true` on `amicus_verdict`.** Refreshes `report.html`
|
|
130
|
+
from the decided verdict. The MCP tool also returns the markdown rendering; it writes only when
|
|
131
|
+
an `outDir` inside the project is supplied, and its `readOnlyHint` is now correctly `false`.
|
|
132
|
+
- **`--no-cost-gate` on `council run`.** Disables the per-leg price gate for the whole run —
|
|
133
|
+
repairs, chair chain and debate legs included — in one place instead of per invocation.
|
|
134
|
+
|
|
135
|
+
### Fixed
|
|
136
|
+
|
|
137
|
+
- **The Council Review Action no longer defaults to a bench that cannot lose a leg.** Its default
|
|
138
|
+
`models` were `deepseek,gemini,glm` with `deepseek` as chair; because the chair is excluded from
|
|
139
|
+
the bench, that left **two** seats against a quorum minimum of two, so one stalled leg failed the
|
|
140
|
+
entire review. The default is now four seats (`glm,qwen,minimax,qwen-coder`), leaving real slack.
|
|
141
|
+
- **`postinstall` now installs `SEAT-BRIEFS.md`.** It shipped in the tarball but was never copied
|
|
142
|
+
into `~/.claude/skills/second-opinion/`, so the seat briefing reference has been missing from
|
|
143
|
+
every installation to date.
|
|
144
|
+
- **`amicus council verdict` no longer discards the chair's verdict.** Writing the decided verdict
|
|
145
|
+
over the engine's one dropped `overallVerdict` to `null`, because the tally record it is built
|
|
146
|
+
from does not carry it. `runVerdict` now recovers it from the run folder — the engine's
|
|
147
|
+
`verdict.json` when present (guarded on `runId`, so a foreign file cannot inject another run's
|
|
148
|
+
verdict), otherwise by re-parsing `chair-output.md` with the engine's own chair parser. A run
|
|
149
|
+
whose chair was skipped still yields `null`; nothing is ever invented. `amicus_verdict` had the
|
|
150
|
+
same loss on the Cowork path and gains an explicit optional `overallVerdict` input, since the MCP
|
|
151
|
+
tool receives a record inline with no run folder to recover from.
|
|
152
|
+
|
|
153
|
+
### Documentation
|
|
154
|
+
|
|
155
|
+
- **The skill's Stage 4 and Stage 5 now name where finding claims actually live.** Both stages
|
|
156
|
+
instructed the reader to show each finding's claim while pointing only at `tally.json`, whose
|
|
157
|
+
findings carry tiers and adjudications but no `claim`. The claim and location live in
|
|
158
|
+
`tally-input.json`; both stages now state the join (on finding `id`) explicitly.
|
|
159
|
+
|
|
160
|
+
### Changed
|
|
161
|
+
|
|
162
|
+
- **`claude` can no longer be promoted as fallback chair on any run.** When a configured chair
|
|
163
|
+
dies, the engine promotes another model by reliability; `claude` is now excluded unconditionally.
|
|
164
|
+
This affects runs that never use `--claude-review`, because the reliability ledger has no way to
|
|
165
|
+
distinguish a file-sourced `claude` row from a real leg — and promoting it would select a chair
|
|
166
|
+
the engine cannot launch.
|
|
167
|
+
- **`npm i -g amicus@4.1` rewrites the installed `SKILL.md`** to the fast path (existing
|
|
168
|
+
product-code overwrite policy). `MODEL-NOTES.md` remains machine-local and is never overwritten.
|
|
169
|
+
Rollback is a reinstall of 4.0.x.
|
|
170
|
+
|
|
171
|
+
### Notes
|
|
172
|
+
|
|
173
|
+
- All changes are additive: the council document family stays `schemaVersion: 2`, the MCP tool
|
|
174
|
+
count stays 15 (new inputs only), and a run using none of the new flags produces byte-identical
|
|
175
|
+
artifacts to 4.0.1. No migration is required.
|
|
176
|
+
|
|
8
177
|
## [4.0.1] - 2026-07-20
|
|
9
178
|
|
|
10
179
|
Follow-up fixes to the v4.0.0 council engine: `amicus abort` and `amicus status` now see every
|
package/README.md
CHANGED
|
@@ -301,7 +301,7 @@ amicus update
|
|
|
301
301
|
| `amicus spend` | Cross-run cost rollup from the spend ledger — total + per-model spend, tokens, and source mix, most-expensive first (`--since 7d` windows it; `--json` for a versioned doc; shows remaining OpenRouter credit when a key is configured). |
|
|
302
302
|
| `amicus key` | Manage API keys non-interactively: `amicus key <provider> <key>` saves after live validation; `--remove`; bare `amicus key` lists providers. |
|
|
303
303
|
| `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. |
|
|
304
|
-
| `amicus council run` | The headless council engine
|
|
304
|
+
| `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). |
|
|
305
305
|
| `amicus abort` | Abort a running session (or `--all`). |
|
|
306
306
|
| `amicus setup` | Configure default model, API keys, and aliases. |
|
|
307
307
|
| `amicus update` | Update to the latest version. |
|
|
@@ -329,7 +329,7 @@ $ amicus status demo123 --json
|
|
|
329
329
|
"taskId": "demo123",
|
|
330
330
|
"status": "complete",
|
|
331
331
|
"elapsed": "5m 0s",
|
|
332
|
-
"version": "4.
|
|
332
|
+
"version": "4.1.1",
|
|
333
333
|
"model": "google/gemini-2.5-flash",
|
|
334
334
|
"phase": "terminal"
|
|
335
335
|
}
|
|
@@ -352,7 +352,7 @@ amicus models --search gemini # filter by substring
|
|
|
352
352
|
|
|
353
353
|
### Routing
|
|
354
354
|
|
|
355
|
-
- **Bare `provider/model`** (e.g. `openai/gpt-5.5`, `anthropic/claude-opus-4
|
|
355
|
+
- **Bare `provider/model`** (e.g. `openai/gpt-5.5`, `anthropic/claude-opus-4-8`, `google/gemini-3.6-flash`) is the canonical, policy-routed form — Amicus routes it **direct-first**: your direct provider key when one is configured, falling back to OpenRouter automatically when only an OpenRouter key exists.
|
|
356
356
|
- **`openrouter/provider/model`** is an explicit override that always forces OpenRouter, even when a direct key is present — reach for it deliberately, or for gateway-only vendors with no direct integration (Qwen, Grok, Mistral, GLM, …).
|
|
357
357
|
- **`--gateway auto|direct|openrouter`** (CLI, also on the MCP tools) overrides routing for one call; `auto` is the direct-first default. `routing.prefer` in `config.json` (`"direct"` by default, or `"openrouter"`) sets the global default.
|
|
358
358
|
- **One-time migration notice:** if you hold both an OpenRouter key and a direct key for a vendor, the first launch that resolves to that vendor under **`auto`** routing (the default) prints a one-time notice that routing moved to direct API; set `routing.prefer: "openrouter"` to restore the old all-OpenRouter behavior. The notice never fires when you explicitly pass `--gateway direct` — that's your own choice, not a migration.
|
|
@@ -380,7 +380,7 @@ The MCP server is auto-registered on install (Claude Code and Claude Desktop / C
|
|
|
380
380
|
| `amicus_fanout` | Launch a same-prompt wave; returns `{ waveId, taskIds[] }`. |
|
|
381
381
|
| `amicus_council_tally` | Aggregate a council wave's reviews into a scored tally. |
|
|
382
382
|
| `amicus_council_stats` | Reviewer-reliability stats from past council runs. |
|
|
383
|
-
| `amicus_verdict` | Build the final council verdict from a tally + decisions. |
|
|
383
|
+
| `amicus_verdict` | Build the final council verdict from a tally + decisions; writes `<outDir>/report.html` when `render:true` and `outDir` are given. |
|
|
384
384
|
| `amicus_council_run` | Run the full headless council engine (Stage-1 reviews → anonymized cross-review → tally → chair verdict); returns `{ runId, runDir }`, async. |
|
|
385
385
|
|
|
386
386
|
The async pattern is **start → status → read** — `amicus_start`/`amicus_fanout` return immediately, then you poll `amicus_status` and call `amicus_read`; `amicus_wait` collapses that poll loop into one blocking call.
|
package/commands/council.md
CHANGED
|
@@ -17,13 +17,13 @@ the **analysis request**, and the **criteria**. If any of the three is missing o
|
|
|
17
17
|
ambiguous, ask for it before launching any model (the skill's Stage 0 covers this —
|
|
18
18
|
don't re-ask for what is already present).
|
|
19
19
|
|
|
20
|
-
Then follow the second-opinion skill
|
|
20
|
+
Then follow the second-opinion skill's engine fast path, in pipeline order: Stage 0
|
|
21
21
|
intake/prep and run-folder setup, then council selection with a cost estimate
|
|
22
|
-
and explicit user confirmation;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Stage 5, which runs `amicus council verdict` to write the
|
|
22
|
+
and explicit user confirmation; one `amicus council run` call — the engine runs
|
|
23
|
+
validate, cross-review, tally, and chair internally, covering the Stage-1
|
|
24
|
+
independent reviews through the Stage-3 chair synthesis with no Claude runtime
|
|
25
|
+
in between; Stage 4, the accept/deny decision pass, once the run returns; and
|
|
26
|
+
Stage 5, which runs `amicus council verdict` to write the decided `verdict.json`.
|
|
27
27
|
|
|
28
28
|
The user may also name **optional council elements** in the arguments (critic seat,
|
|
29
29
|
expert lenses, debate mode, verdict scale, Claude in the council). All elements
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amicus",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.1",
|
|
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": [
|
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
"scripts": {
|
|
50
50
|
"start": "node --experimental-top-level-await --experimental-vm-modules bin/amicus.js",
|
|
51
51
|
"test": "jest",
|
|
52
|
-
"test:integration": "
|
|
52
|
+
"test:integration": "node scripts/run-integration-keyless.js",
|
|
53
|
+
"test:integration:live": "jest --testPathIgnorePatterns='worktrees' --testMatch='**/tests/**/*.integration.test.js'",
|
|
53
54
|
"test:all": "jest --testPathIgnorePatterns='/node_modules/' --testPathIgnorePatterns='worktrees' && node scripts/mark-test-passed.js",
|
|
54
55
|
"test:e2e:mcp": "jest tests/mcp-repomix-e2e.integration.test.js --testTimeout=180000 --forceExit",
|
|
55
56
|
"posttest": "node scripts/mark-test-passed.js",
|
|
@@ -33,6 +33,20 @@
|
|
|
33
33
|
"labelMap": { "type": ["object", "null"], "additionalProperties": { "type": "string" } },
|
|
34
34
|
"options": { "type": "object" },
|
|
35
35
|
"usage": { "type": "object" },
|
|
36
|
-
"exitCode": { "type": ["number", "null"] }
|
|
36
|
+
"exitCode": { "type": ["number", "null"] },
|
|
37
|
+
"debate": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"properties": {
|
|
40
|
+
"enabled": { "type": "boolean" },
|
|
41
|
+
"outcome": { "enum": ["ran", "nothing-to-debate", "skipped-cost-ceiling"] },
|
|
42
|
+
"contested": { "type": "integer" }, "disputed": { "type": "integer" },
|
|
43
|
+
"defended": { "type": "integer" }, "amended": { "type": "integer" },
|
|
44
|
+
"withdrawn": { "type": "integer" }, "noResponse": { "type": "integer" },
|
|
45
|
+
"revoteJudges": { "type": "integer" }, "revoteApplied": { "type": "integer" },
|
|
46
|
+
"verdictChanges": { "type": "integer" }
|
|
47
|
+
},
|
|
48
|
+
"required": ["enabled"],
|
|
49
|
+
"additionalProperties": false
|
|
50
|
+
}
|
|
37
51
|
}
|
|
38
52
|
}
|
|
@@ -51,7 +51,16 @@
|
|
|
51
51
|
},
|
|
52
52
|
"confidence": { "enum": ["thin", "solid"] },
|
|
53
53
|
"tierOverride": { "type": ["object", "null"] },
|
|
54
|
-
"adjudications": { "type": "array", "items": { "type": "object" } }
|
|
54
|
+
"adjudications": { "type": "array", "items": { "type": "object" } },
|
|
55
|
+
"debate": {
|
|
56
|
+
"type": "object",
|
|
57
|
+
"properties": {
|
|
58
|
+
"action": { "enum": ["defended", "amended", "withdrawn", "no-response"] },
|
|
59
|
+
"previousTier": { "type": ["string", "null"] }
|
|
60
|
+
},
|
|
61
|
+
"required": ["action"],
|
|
62
|
+
"additionalProperties": false
|
|
63
|
+
}
|
|
55
64
|
}
|
|
56
65
|
}
|
|
57
66
|
},
|
|
@@ -36,7 +36,16 @@
|
|
|
36
36
|
"duplicateOf": { "type": ["string", "null"] },
|
|
37
37
|
"adjudications": { "type": "array" },
|
|
38
38
|
"decision": { "type": ["string", "null"] },
|
|
39
|
-
"applied": { "type": "boolean" }
|
|
39
|
+
"applied": { "type": "boolean" },
|
|
40
|
+
"debate": {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"properties": {
|
|
43
|
+
"action": { "enum": ["defended", "amended", "withdrawn", "no-response"] },
|
|
44
|
+
"previousTier": { "type": ["string", "null"] }
|
|
45
|
+
},
|
|
46
|
+
"required": ["action"],
|
|
47
|
+
"additionalProperties": false
|
|
48
|
+
}
|
|
40
49
|
}
|
|
41
50
|
}
|
|
42
51
|
},
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"type": "object",
|
|
14
14
|
"required": ["code", "message"],
|
|
15
15
|
"properties": {
|
|
16
|
-
"code": { "enum": ["BAD_ARGS", "MISSING_PROMPT", "BAD_MODEL", "MISSING_KEY", "BAD_SESSION", "BUDGET_EXCEEDED", "INTERNAL"] },
|
|
16
|
+
"code": { "enum": ["BAD_ARGS", "MISSING_PROMPT", "BAD_MODEL", "MISSING_KEY", "BAD_SESSION", "BUDGET_EXCEEDED", "INTERNAL", "COUNCIL_QUORUM", "COST_EXCEEDED", "COUNCIL_CLAUDE_REVIEW_INVALID"] },
|
|
17
17
|
"message": { "type": "string" },
|
|
18
18
|
"hint": { "type": ["string", "null"] },
|
|
19
19
|
"command": { "type": ["string", "null"] }
|
package/scripts/postinstall.js
CHANGED
|
@@ -25,12 +25,15 @@ const PROVISION_TIMEOUT_MS = 15000;
|
|
|
25
25
|
const SKILL_SOURCE = path.join(__dirname, '..', 'skills', 'sidecar', 'SKILL.md');
|
|
26
26
|
const COUNCIL_SOURCE_DIR = path.join(__dirname, '..', 'skills', 'second-opinion');
|
|
27
27
|
|
|
28
|
-
/** Council files + per-file install semantics: SKILL/COUNCIL-DESIGN are
|
|
29
|
-
* (overwrite on update
|
|
30
|
-
* per-run, so it is
|
|
28
|
+
/** Council files + per-file install semantics: SKILL/COUNCIL-DESIGN/SEAT-BRIEFS are
|
|
29
|
+
* product code (overwrite on update, so upgrades keep them in sync with the package);
|
|
30
|
+
* MODEL-NOTES is user data — its reviewer-reliability table evolves per-run, so it is
|
|
31
|
+
* seeded once and never clobbered. */
|
|
31
32
|
const COUNCIL_FILES = [
|
|
32
33
|
{ file: 'SKILL.md', mode: 'overwrite' },
|
|
33
34
|
{ file: 'COUNCIL-DESIGN.md', mode: 'overwrite' },
|
|
35
|
+
{ file: 'SEAT-BRIEFS.md', mode: 'overwrite' },
|
|
36
|
+
{ file: 'MANUAL-ORCHESTRATION.md', mode: 'overwrite' },
|
|
34
37
|
{ file: 'MODEL-NOTES.md', mode: 'if-missing' },
|
|
35
38
|
];
|
|
36
39
|
|
|
@@ -36,6 +36,10 @@ non-Claude chairman + per-model inspectable artifacts.
|
|
|
36
36
|
is now engine-native — each review wave is ONE `amicus fanout --json` call returning structured
|
|
37
37
|
run documents — but scoring, tallying, anonymization, and synthesis remain Claude's manual work.
|
|
38
38
|
No backend, no parsing code beyond reading JSON fields. Deterministic arithmetic/formatting/schema helpers under `amicus council` (findings validation, tier tally, street-cred, ledger) are sanctioned; judgment, synthesis, anonymization, and de-anonymization remain Claude's inline work.
|
|
39
|
+
_(v4.1 annotation — superseded by the engine in the fast path: `amicus council run` now performs
|
|
40
|
+
the anonymization, scoring, tallying, and chair-dispatch steps above headlessly, with no Claude
|
|
41
|
+
runtime in the loop. This v3 note remains an accurate historical record of the design this repo
|
|
42
|
+
shipped from v3 through v4.0's manual path; see §13.)_
|
|
39
43
|
|
|
40
44
|
## 3. What changes vs. v1
|
|
41
45
|
|
|
@@ -156,6 +160,9 @@ The cross-review matrix shows both; the ledger and Stage-0 bench recommendations
|
|
|
156
160
|
- Default: Claude **recommends a non-Claude chair** from the council each run (often the
|
|
157
161
|
strongest reasoner / best reviewer-reliability) and the user confirms at launch.
|
|
158
162
|
- The chair **may** also be a Stage-1 council member (it sees the anonymized bundle + scores).
|
|
163
|
+
_(v4.1 annotation: the engine fast path's `amicus council run` rejects this — the chair must
|
|
164
|
+
NOT be a bench seat, checked pre-flight, exit 1 before any spend. This flexibility survives only
|
|
165
|
+
in the manual path; see `MANUAL-ORCHESTRATION.md` and §13.)_
|
|
159
166
|
- **Fallback order if the chair fails:** re-run → promote next-best council model →
|
|
160
167
|
**Claude chairs only as last resort, with explicit disclosure** that the verdict is no longer
|
|
161
168
|
fully independent.
|
|
@@ -291,3 +298,36 @@ The debate agent's parallel-panels + cross-panel synthesis maps to two full coun
|
|
|
291
298
|
different benches or lens-sets plus a super-chair synthesis of where the panels agree,
|
|
292
299
|
disagree, and what each missed. Deferred: cost doubles and the run-folder conventions need
|
|
293
300
|
namespacing. Revisit if lens runs prove valuable.
|
|
301
|
+
|
|
302
|
+
## 13. v4.1 — the engine fast path
|
|
303
|
+
|
|
304
|
+
`amicus council run` (v4.0; extended in v4.1 with `--debate`, `--claude-review`, and `council
|
|
305
|
+
verdict --render`) is the **headless realization of Stages 1–3 plus the Stage-5 deterministic
|
|
306
|
+
artifacts** described above: the Stage-1 review wave, per-leg findings validation and bounded
|
|
307
|
+
repair, anonymization and run-global finding-id rewriting, the identical judge bundle, the
|
|
308
|
+
Stage-2 cross-review wave, the optional Stage-2.5 debate round (§12.3), the tally, the chair
|
|
309
|
+
synthesis, and the deterministic `verdict.json` (undecided) + `report.html` — all as **one
|
|
310
|
+
command with no Claude runtime** in the loop. `SKILL.md`'s engine fast path drives this directly.
|
|
311
|
+
The hand-driven Stage 1 → 2 → 3 waves this document describes above remain available as
|
|
312
|
+
`MANUAL-ORCHESTRATION.md` — the fallback for the engine being unavailable/misbehaving, a fully
|
|
313
|
+
custom per-seat brief beyond `--critic`/`--lenses`, or deliberate mid-stage inspection.
|
|
314
|
+
|
|
315
|
+
**Stage 4 stays human, always.** The engine is report-only: `amicus council run` never
|
|
316
|
+
fabricates an accept/deny decision. Claude still drives Stage 4 (§4) and finalizes the verdict via
|
|
317
|
+
`amicus council verdict --decisions <decisions.json> --render` (§4, Stage 5) — the fast path
|
|
318
|
+
changes the *transport* for Stages 1–3 plus the Stage-5 artifacts, not the decision authority of
|
|
319
|
+
Stage 4.
|
|
320
|
+
|
|
321
|
+
**§12.4 (chair verdict scale) is standard-on in the fast path.** What was an opt-in menu item in
|
|
322
|
+
the manual path is now baked into `amicus council run`'s chair packet unconditionally — every
|
|
323
|
+
headless chair closes with the hard questions and a parseable `VERDICT:` line, surfaced as
|
|
324
|
+
`overallVerdict` in `verdict.json`. There is no toggle for it on the engine path; it is always on.
|
|
325
|
+
|
|
326
|
+
**§12.3 (debate mode) headless realization: `--debate` on `council run`.** The Stage-2.5 rebuttal
|
|
327
|
+
round described in §12.3 is implemented headlessly in `src/council/run-debate.js`
|
|
328
|
+
(orchestration) + `src/council/debate.js` (pure tally-input reassembly) +
|
|
329
|
+
`src/council/briefings-debate.js` (rebuttal/re-vote prompt templates) — same mechanics, same
|
|
330
|
+
exactly-one-round rule, same withdrawn-findings-auto-denied outcome (§12.3), now driven by the
|
|
331
|
+
engine instead of Claude's hand-launched solos/waves. The round's summary lands in `run.json`'s
|
|
332
|
+
`debate` object and each affected finding's `findings[].debate` decoration — see
|
|
333
|
+
[docs/council.md](../../docs/council.md) for the field-by-field reference.
|