amicus 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amicus",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
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,114 @@ All notable changes to Amicus are documented here. Format follows
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [2.2.0] - 2026-07-14
9
+
10
+ ### Added
11
+
12
+ - **Optional council elements** (second-opinion skill): four new opt-in behaviors, presented
13
+ together with Claude-in-the-council as a single numbered Stage-0 menu — all default OFF, enabled
14
+ only when the user names them, and the launch confirmation must enumerate what's on:
15
+ - **Critic seat** — one bench member swaps to a four-pass adversarial brief (adversarial pass,
16
+ edge-case hunt, consistency check, executability test), launched as a concurrent solo beside
17
+ the fanout wave (`role: "critic"`). Its findings enter the same anonymized bundle and are
18
+ peer-adjudicated like any other seat's — the council disciplines the critic.
19
+ - **Expert lenses** — each seat reviews through a distinct expert perspective (panel domain
20
+ scoped with the user: business/technical/customer/financial/custom). Lens runs always tally
21
+ `--no-ledger` and the report discloses the weakened cross-review anonymity.
22
+ - **Debate mode** — a new Stage 2.5 rebuttal round: Contested/Disputed findings go back to their
23
+ raisers to DEFEND / AMEND / WITHDRAW, disputing judges re-vote, then the final ledger-recorded
24
+ tally. Exactly one round; withdrawn findings are auto-denied and listed in the report.
25
+ - **Chair verdict scale** — the chair closes with 3–5 hard questions and a final parseable
26
+ `VERDICT: Ship it | Fix these first | Fundamental rethink` line, surfaced at the top of the
27
+ report.
28
+ - New `skills/second-opinion/SEAT-BRIEFS.md` — briefing boilerplate for the elements plus a
29
+ standard anti-sycophancy clause now required in **every** Stage-1 briefing. Critic and lens
30
+ methodologies adapted from the `/critic` and `/debate` agents in John Renaldi's product-kit
31
+ (MIT), with deliberate deviations documented (no findings quota; verdict moved to the chair).
32
+ - Zero engine changes: free-form `runStats[].role` labels, tally-input re-assembly, and the
33
+ existing `--no-ledger` flag cover all four elements.
34
+
35
+ ### Changed
36
+
37
+ - `COUNCIL-DESIGN.md` gains §12 documenting the elements, their caveats (critic
38
+ self-identification in cross-review; lens anonymity/ledger trade-offs), and parallel panels as
39
+ future work. The `/council` command accepts pre-requested elements in its arguments.
40
+ - MODEL-NOTES seed: fold-back of the v2.2.0 verification council — claim-class dedup
41
+ adjudication limit, minimax debut (strong critic seat), qwen-coder debut.
42
+
43
+ ### Fixed
44
+
45
+ - Resurrected both Windows e2e integration suites, silently dead since before the rebrand:
46
+ Node's `spawn()` cannot execute `node_modules/.bin` `.cmd` shims on Windows, so the Electron
47
+ toolbar suite (electron shim) and the OpenCode server test helper ENOENT'd without a visible
48
+ error. The helper now uses the shared `ensureNodeModulesBinInPath()` (which adds the platform
49
+ `opencode.exe` dirs to PATH) and the toolbar suite spawns the real binary via
50
+ `require('electron')`. Also refreshed two stale pins the dead suites never caught: the wave
51
+ document's `schemaVersion` (now pinned to the shared `SCHEMA_VERSION` constant instead of a
52
+ literal `1`) and the pre-rebrand `Sidecar` toolbar brand assertion (now `Amicus`).
53
+
54
+ ## [2.1.0] - 2026-07-04
55
+
56
+ ### Added
57
+
58
+ - `--json` on `resume`, `continue`, and `abort`. `amicus resume <id> --no-ui --json` and
59
+ `amicus continue <id> --prompt "..." --no-ui --json` emit the same versioned run document as
60
+ `start --json` (a `continue` run's document carries the new continuation task id, not the old
61
+ one). `amicus abort <id|--all> --json` emits a new `type: 'abort'` document
62
+ (`{ schemaVersion, type, ok, scope, taskId, aborted, count }`) covering single-session, wave, and
63
+ `--all` aborts, success and failure alike — stdout carries exactly one parseable document either
64
+ way, and non-`--json` human output is unchanged (byte-identical pinned messages still hold).
65
+ - Did-you-mean suggestions for unknown CLI commands: a near-miss typo like `amicus contnue` now
66
+ prints `Unknown command: contnue` followed by `Did you mean: continue` on stderr (still exits 1).
67
+ Suggestions are capped at 3 and only shown within edit-distance 2 of a known command; unrelated
68
+ garbage input gets no suggestion.
69
+
70
+ ### Changed
71
+
72
+ - Agent-facing polling guidance now recommends `amicus_wait` first across every headless-flow
73
+ reminder, tool description, and guide section (MCP system-reminders, `amicus_start`/`amicus_resume`/
74
+ `amicus_continue`/`amicus_fanout` descriptions, `amicus_guide`'s headless workflow, and the
75
+ `second-opinion`/`sidecar` skill docs) — one blocking call replaces the sleep+status poll loop.
76
+ `sleep 25` + `amicus_status` polling remains documented as the explicit fallback for clients
77
+ without the `amicus_wait` tool; it is never presented as the only mechanism.
78
+
79
+ ### Fixed
80
+
81
+ - `amicus doctor`'s MCP registration check no longer false-negatives on a healthy Claude Code
82
+ registration. The check's only signal was `discoverClaudeCodeMcps()`, which always strips every
83
+ `amicus`/`sidecar`-shaped entry as its own recursive-spawn guard — so the check could never see
84
+ its own registration and warned "not registered in Claude Code" even when one existed. The check
85
+ now reads the same config sources directly (unstripped) to answer "is amicus registered?".
86
+
87
+ ### CI / Security
88
+
89
+ - `council-review.yml`: both fanout legs (review wave and synthesis) now request
90
+ `--summary-length normal` instead of `verbose`. `--summary-length` only shapes the prompt (there is
91
+ no engine-side output-token cap), so `verbose` was asking every model in the wave — on a paid CI
92
+ key — for maximally long output on every PR.
93
+ - `council-review.yml`: the model-to-model handoff from the review wave into the synthesis leg is
94
+ now neutralized. The synthesis briefing previously concatenated raw model review text
95
+ (`reviews.md`) straight into another model's prompt with no sanitization; it now runs the same
96
+ neutralization (byte-identical sed rules, duplicated into the synthesis step's own shell) used on
97
+ the human-facing PR comment, and wraps the reviews in an explicit untrusted-data block before
98
+ handing them to the synthesis model. The comment path itself is unchanged.
99
+ - `ci.yml`: the `quality` job now runs [actionlint](https://github.com/rhysd/actionlint) (pinned to
100
+ v1.7.7) over `.github/workflows/`, which also shellchecks every `run:` block via ubuntu-latest's
101
+ preinstalled shellcheck. Verified locally with the actionlint + shellcheck Windows binaries before
102
+ landing; both are clean against all 5 workflows (0 findings), so no suppression config was needed.
103
+
104
+ ### Documentation
105
+
106
+ - Corrected the `--agent` default docs in `skills/sidecar/SKILL.md`: the flag defaults to `Chat`
107
+ only in interactive mode — headless (`--no-ui`) runs default to `Build`, since `chat` stalls
108
+ without user interaction. The file previously claimed an unqualified "defaults to Chat" in
109
+ several spots while also correctly documenting the headless-`Build` default elsewhere,
110
+ contradicting itself; `docs/usage.md` was already correct and unchanged.
111
+ - Corrected `commands/council.md`'s description of the council pipeline order: `amicus council
112
+ validate` runs per-leg during Stage 1 (independent reviews), and `amicus council tally` runs
113
+ after Stage 2 (cross-review) and before Stage 3 (chair synthesis) — not, as previously worded,
114
+ both after all three review waves.
115
+
8
116
  ## [2.0.0] - 2026-07-03
9
117
 
10
118
  Amicus's first major release: the **`sidecar*` shim removal** (#19). v1.x carried a full
package/README.md CHANGED
@@ -53,6 +53,10 @@ Claude is the orchestrator. The council and chat skills run *on top of* the engi
53
53
 
54
54
  ![What one install delivers: council skill, chat skill, CLI + MCP, live catalog](./docs/what-is-amicus.png)
55
55
 
56
+ The council skill in one picture — independent review, before cross-review or the verdict, with Claude Opus seated among the models it's judging:
57
+
58
+ ![The Amicus council mid-ritual: five models — Gemini 3 Pro, Llama 4, Grok 4, Claude Opus — reading the same material independently, chaired by GPT-5](./docs/council.png)
59
+
56
60
  ---
57
61
 
58
62
  ## Quick start
@@ -209,11 +213,19 @@ Everything you need before your first run, and what's optional.
209
213
  findings-by-tier, cost — no chair prose). This is the default artifact handed to the user.
210
214
  - For an **editable source**, the accepted edits land in `<stem>-reviewed.<ext>` next to the original.
211
215
 
212
- **Claude in the council** (default off): you can add Claude's 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.
216
+ **Optional council elements** (v2.2.0, all default off): five opt-in behaviors, offered once as a menu at launchnothing turns on unless you name it, and the confirmation lists exactly what's on.
217
+
218
+ - **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.
219
+ - **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.
220
+ - **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.
221
+ - **Chair verdict scale** — the chair closes with 3–5 hard questions and one parseable line: `VERDICT: Ship it | Fix these first | Fundamental rethink`.
222
+ - **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.
223
+
224
+ 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).
213
225
 
214
- **Cost is disclosed up front.** Before any model launches, you see the run shape — for example:
226
+ **Cost is disclosed up front.** Before any model launches, you see the run shape — including any enabled optional elements — for example:
215
227
 
216
- > This run uses 3 council models across 2 fanout waves + 1 chair call (~7 model runs).
228
+ > 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).
217
229
 
218
230
  Then the council waits for your confirmation.
219
231
 
@@ -311,7 +323,7 @@ $ amicus status demo123 --json
311
323
  "taskId": "demo123",
312
324
  "status": "complete",
313
325
  "elapsed": "5m 0s",
314
- "version": "2.0.0",
326
+ "version": "2.2.0",
315
327
  "model": "google/gemini-2.5-flash",
316
328
  "phase": "terminal"
317
329
  }
package/bin/amicus.js CHANGED
@@ -11,12 +11,12 @@
11
11
  const { loadCredentials } = require('../src/utils/env-loader');
12
12
  loadCredentials();
13
13
 
14
- const { parseArgs, getUsage } = require('../src/cli');
15
- const { validateTaskId } = require('../src/utils/validators');
16
- const { resolveModelFromArgs, validateFallbackModel } = require('../src/utils/start-helpers');
14
+ const { parseArgs, getUsage, getCommandNames } = require('../src/cli');
17
15
  const { handleSetup, handleAbort, handleUpdate, handleMcp, handleKey } = require('../src/cli-handlers');
18
16
  const { handleStart, handleFanout, handleRead } = require('../src/cli-handlers-run');
17
+ const { handleResume, handleContinue } = require('../src/cli-handlers-resume-continue');
19
18
  const { isOneShotCommand, armExitWatchdog } = require('../src/utils/lifecycle');
19
+ const { suggestCommand } = require('../src/utils/input-validators');
20
20
  const { logger } = require('../src/utils/logger');
21
21
 
22
22
  const VERSION = require('../package.json').version;
@@ -124,7 +124,7 @@ async function main() {
124
124
  await handleKey(args);
125
125
  break;
126
126
  case 'abort':
127
- await handleAbort(args);
127
+ exitCode = await handleAbort(args);
128
128
  break;
129
129
  case 'mcp':
130
130
  await handleMcp();
@@ -132,10 +132,16 @@ async function main() {
132
132
  case 'update':
133
133
  await handleUpdate();
134
134
  break;
135
- default:
135
+ default: {
136
136
  console.error(`Unknown command: ${command}`);
137
+ // suggestCommand honors a cap-3 contract (up to 3 candidates, closest
138
+ // first) — print all of them, not just the closest, matching the
139
+ // join precedent in src/cli-handlers.js.
140
+ const candidates = suggestCommand(command, getCommandNames());
141
+ if (candidates.length > 0) { console.error(`Did you mean: ${candidates.join(', ')}`); }
137
142
  console.log(getUsage());
138
143
  process.exit(1);
144
+ }
139
145
  }
140
146
  } catch (err) {
141
147
  console.error(`Error: ${err.message}`);
@@ -166,94 +172,6 @@ async function handleList(args) {
166
172
  });
167
173
  }
168
174
 
169
- /**
170
- * Handle 'sidecar resume' command
171
- * Spec Reference: §4.3
172
- */
173
- async function handleResume(args) {
174
- const taskId = args._[1];
175
-
176
- if (!taskId) {
177
- console.error('Error: task_id is required for resume');
178
- console.error('Usage: amicus resume <task_id>');
179
- process.exit(1);
180
- }
181
-
182
- const taskIdCheck = validateTaskId(taskId);
183
- if (!taskIdCheck.valid) {
184
- console.error(taskIdCheck.error);
185
- process.exit(1);
186
- }
187
-
188
- const { resumeAmicus } = require('../src/index');
189
-
190
- return await resumeAmicus({
191
- taskId,
192
- project: args.cwd,
193
- headless: args['no-ui'],
194
- timeout: args.timeout
195
- });
196
- }
197
-
198
- /**
199
- * Handle 'sidecar continue' command
200
- * Spec Reference: §4.4
201
- */
202
- async function handleContinue(args) {
203
- const taskId = args._[1];
204
-
205
- if (!taskId) {
206
- console.error('Error: task_id is required for continue');
207
- console.error('Usage: amicus continue <task_id> --prompt "..."');
208
- process.exit(1);
209
- }
210
-
211
- const taskIdCheck = validateTaskId(taskId);
212
- if (!taskIdCheck.valid) {
213
- console.error(taskIdCheck.error);
214
- process.exit(1);
215
- }
216
-
217
- // BL-1: accept --prompt-file (XOR --prompt) so the MCP handler can pass a long
218
- // follow-up prompt via file, dodging the ~32KB Windows command-line cap.
219
- if (args['prompt-file'] !== undefined) {
220
- const { resolvePromptSource } = require('../src/utils/prompt-source');
221
- const promptRes = resolvePromptSource(args);
222
- if (promptRes.error) {
223
- console.error(promptRes.error);
224
- process.exit(1);
225
- }
226
- args.prompt = promptRes.prompt;
227
- delete args['prompt-file'];
228
- }
229
-
230
- if (!args.prompt && !args.briefing) {
231
- console.error('Error: --prompt is required for continue');
232
- process.exit(1);
233
- }
234
-
235
- // F5: an explicitly passed --model gets the same resolution+validation as start.
236
- if (args.model !== undefined) {
237
- const { model, alias } = resolveModelFromArgs(args);
238
- args.model = model;
239
- args.model = await validateFallbackModel(args, alias);
240
- }
241
-
242
- const { continueAmicus } = require('../src/index');
243
-
244
- return await continueAmicus({
245
- taskId,
246
- newTaskId: args['task-id'],
247
- briefing: args.prompt || args.briefing,
248
- model: args.model,
249
- project: args.cwd,
250
- contextTurns: args['context-turns'],
251
- contextMaxTokens: args['context-max-tokens'],
252
- headless: args['no-ui'],
253
- timeout: args.timeout
254
- });
255
- }
256
-
257
175
  // Run main
258
176
  main().catch(err => {
259
177
  console.error(`Fatal error: ${err.message}`);
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Run a structured multi-model LLM council review of the given material — wraps the second-opinion skill (independent reviews → anonymous cross-review → non-Claude chair verdict → accept/deny decisions).
3
- argument-hint: [material, path, or URL] [analysis request + criteria]
3
+ argument-hint: [material, path, or URL] [analysis request + criteria] [optional elements — e.g. "with a critic seat", "debate mode", "expert lenses", "chair verdict scale"]
4
4
  disable-model-invocation: true
5
5
  ---
6
6
 
@@ -17,8 +17,16 @@ 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 end to end: Stage 0 intake/prep and run-folder
21
- setup, council selection with a cost estimate and explicit user confirmation, the
22
- three review waves, `amicus council validate` on each leg's findings block,
23
- `amicus council tally`, the accept/deny decision pass, and `amicus council verdict`
24
- to write the final `verdict.json`.
20
+ Then follow the second-opinion skill end to end, in pipeline order: Stage 0
21
+ intake/prep and run-folder setup, then council selection with a cost estimate
22
+ and explicit user confirmation; Stage 1 independent reviews, running
23
+ `amicus council validate` on each leg's findings block as it lands; Stage 2
24
+ cross-review, followed by `amicus council tally` once cross-review settles;
25
+ Stage 3 council-chair synthesis; Stage 4 the accept/deny decision pass; and
26
+ Stage 5, which runs `amicus council verdict` to write the final `verdict.json`.
27
+
28
+ The user may also name **optional council elements** in the arguments (critic seat,
29
+ expert lenses, debate mode, verdict scale, Claude in the council). All elements
30
+ default OFF; the skill's Stage-0 menu is the single opt-in point. If the user named
31
+ elements here, carry them into Stage 0 as pre-requested — confirm them back by name
32
+ instead of re-asking — and never enable an element the user did not explicitly name.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amicus",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
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": [
@@ -1,8 +1,8 @@
1
1
  # Second Opinion v3 — "LLM Council" Design
2
2
 
3
3
  _Status: implemented (v3). v2 (2026-06-03) added the council mechanics; v3 (2026-06-10) swapped the
4
- transport onto the Amicus fanout/JSON engine primitives. v2 history lives in git
5
- (`V2-COUNCIL-DESIGN.md`, deleted at v3)._
4
+ transport onto the Amicus fanout/JSON engine primitives; v3.1 (2026-07-14) added the optional
5
+ council elements (§12). v2 history lives in git (`V2-COUNCIL-DESIGN.md`, deleted at v3)._
6
6
  _Design for `SKILL.md` and `MODEL-NOTES.md` of the `second-opinion` skill._
7
7
 
8
8
  ## 1. Intent
@@ -224,6 +224,70 @@ The append-only `council-ledger.jsonl` (consumed via `amicus council stats`) is
224
224
  four qualitative tiers, if tiers prove too coarse in practice.
225
225
 
226
226
  ## 11. Implementation surface
227
- - `SKILL.md` — the Stage 0–6 council flow on the v3 transport (WS-3: findings contract, tally assembly recipe, `amicus council tally/stats`, `verdict.json`, ledger auto-append).
227
+ - `SKILL.md` — the Stage 0–6 council flow on the v3 transport (WS-3: findings contract, tally assembly recipe, `amicus council tally/stats`, `verdict.json`, ledger auto-append). v3.1 adds the Stage-0 optional-elements menu, the Stage-1 critic/lens launch blocks, Stage 2.5, and the chair verdict-scale addendum.
228
+ - `SEAT-BRIEFS.md` — v3.1 briefing boilerplate for the optional elements + the standard anti-sycophancy clause.
228
229
  - `MODEL-NOTES.md` — qualitative per-model quirks, structural-conformance notes, cost guardrail, Stage-2 briefing tips. Quantitative reliability data now generated by `amicus council stats` (ledger). Engine workarounds that F1/F2/F4 made obsolete were pruned at v3.
229
- - `src/council/` — the deterministic helpers (`findings.js`, `tally.js`, `verdict.js`, `ledger.js`). No other files.
230
+ - `src/council/` — the deterministic helpers (`findings.js`, `tally.js`, `verdict.js`, `ledger.js`). No other files. **v3.1 required zero engine changes**: `runStats[].role` labels are free-form, the rebuttal round is a tally-input re-assembly, and `--no-ledger` already existed.
231
+
232
+ ## 12. Optional council elements (v3.1)
233
+
234
+ The `/critic` and `/debate` behaviors from John Renaldi's product-kit plugin (MIT — the
235
+ elite-advisor and expert-debate-facilitator agents), grafted onto the council. Both source
236
+ agents are single-model theater: one model playing an adversarial reviewer or a panel of
237
+ disagreeing experts, with no external check on manufactured negativity or fake disagreement.
238
+ The council supplies exactly that check — independent models and deterministic peer-validated
239
+ tiers — so the methodologies port over as *optional elements* whose output is disciplined by
240
+ Stage-2 adjudication.
241
+
242
+ **Opt-in contract.** All elements default OFF. They are presented once, as a single numbered
243
+ menu at Stage 0 (after bench/chair selection, before launch confirmation); the user must name
244
+ an element to enable it — silence means off, and the launch confirmation enumerates enabled
245
+ elements by name. "Claude in the council" (§5.4, semantics unchanged) is presented as one item
246
+ of the same menu so there is exactly one opt-in point per run. Elements compose freely except
247
+ critic + lenses on one seat (the critic takes one seat; lenses take the rest).
248
+
249
+ ### 12.1 Critic seat
250
+ One bench member swaps its standard brief for an adversarial four-pass brief (adversarial
251
+ pass, edge-case hunt, consistency check, executability test — `SEAT-BRIEFS.md`). Launches as
252
+ a concurrent solo run (the red-team variant pattern); same findings contract; `role: "critic"`.
253
+ Judges are never told the seat exists. Two deliberate deviations from the source agent: the
254
+ minimum-10-findings quota is dropped (quotas force invented findings, which waste the bench's
255
+ adjudication capital — the anti-padding rule replaces it), and the hard questions +
256
+ Ship/Fix/Rethink verdict moved to the chair (§12.4). Known cost: the critic model can
257
+ self-identify its review in the Stage-2 bundle by shape, weakening self-bias wash-out for that
258
+ one seat — disclosed in the report. A single-seat brief variant is judged acceptable to record
259
+ to the ledger (precedent: the red-team variant records normally).
260
+
261
+ ### 12.2 Expert lenses
262
+ Each seat gets a distinct expert-perspective brief (panel domain scoped with the user:
263
+ business/technical/specialty/customer/financial/custom). All legs launch as concurrent solos
264
+ (no shared-prompt wave); lens↔model assignment is random and private; `role: "lens:<slug>"`.
265
+ Two standing caveats, both disclosed: (a) **anonymity leak** — every judge can spot its own
266
+ lens-flavored review, so self-bias wash-out is weakened bench-wide; (b) **ledger pollution** —
267
+ lens reviews are not comparable to standard reviews (street-cred and confirm-rate assume a
268
+ shared task), so lens-run tallies always pass `--no-ledger`. The bench-wide task change is what
269
+ separates lenses (no ledger) from the single-seat critic (ledger ok).
270
+
271
+ ### 12.3 Debate mode (Stage 2.5 rebuttal round)
272
+ The debate agent's challenge/stress-test rounds, grounded in findings instead of persona
273
+ prose: the Stage-2 tally runs `--no-ledger` (provisional); every Contested/Disputed finding
274
+ goes back to its raiser (defense mini-wave — solo per raiser: DEFEND / AMEND / WITHDRAW), the
275
+ disputing judges re-vote on defended/amended findings (one shared fanout), and the final tally
276
+ runs with the ledger. Exactly one round — the source agent's open-ended rounds become a fixed
277
+ convergence step, or cost is unbounded. Withdrawn findings stay in `findings[]` and are
278
+ auto-recorded `denied` (never presented for user decision). Missing/unparseable rebuttal or
279
+ re-vote lines mean the original claim/verdict stands. No new decision vocabulary and no engine
280
+ changes: `buildVerdict` and the renderer see a normal tally record.
281
+
282
+ ### 12.4 Chair verdict scale
283
+ A chair-packet addendum: the chair closes with 3–5 hard questions plus a final parseable
284
+ `VERDICT: Ship it | Fix these first | Fundamental rethink` line, surfaced verbatim at the top
285
+ of `report.md` and in chat. Gives the council the single overall call its tier counts never
286
+ provided. Possible later engine touch: an `overallVerdict` field in `verdict.json` + a
287
+ renderer line (not needed for the prose version).
288
+
289
+ ### 12.5 Future work — parallel panels
290
+ The debate agent's parallel-panels + cross-panel synthesis maps to two full council runs over
291
+ different benches or lens-sets plus a super-chair synthesis of where the panels agree,
292
+ disagree, and what each missed. Deferred: cost doubles and the run-folder conventions need
293
+ namespacing. Revisit if lens runs prove valuable.
@@ -4,8 +4,8 @@ This file is the `second-opinion` skill's evolving memory of **how to actually d
4
4
  well**. Read it before Stage 0 (council selection and launch); update it, with the user's
5
5
  approval, at the end of each run (Stage 6). Keep it tight — merge and prune rather than append.
6
6
 
7
- _Last updated: 2026-07-02 (runs 4-7 folded back from the field ledger: PowerShell quoting, date
8
- injection, long-read failures, judge tool-wander; see changelog)._
7
+ _Last updated: 2026-07-14 (v2.2.0 fold-back: v3.1 optional council elements verified live;
8
+ claim-class dedup adjudication limit; minimax and qwen-coder debut notes; see changelog)._
9
9
 
10
10
  ## Global operating rules (all models)
11
11
  - **Council runs are headless by design** (autonomous batch work): `fanout` is headless by
@@ -54,6 +54,19 @@ injection, long-read failures, judge tool-wander; see changelog)._
54
54
  no-tools preamble is now mandatory in SKILL.md Stage 2/3 — keep it verbatim.
55
55
  - The tally input needs **all five keys** (`meta` incl. `meta.models`, `findings`, `adjudications`,
56
56
  `rankings`, `runStats`) — see the SKILL.md Stage-2 recipe step 0.
57
+ - **Claim-class dedup glosses rationale errors.** When several reviews raise the same claim, judges
58
+ adjudicate the class ("same as A3 — agree") and skip verifying each finding's own rationale text:
59
+ a direction-inverted arithmetic detail inside an otherwise-correct finding drew unanimous agrees
60
+ despite an explicit "dispute material factual errors in the rationale" instruction. If
61
+ rationale-level precision matters, instruct judges to independently verify the numbers in each
62
+ finding; otherwise expect class-level adjudication and let the chair reconcile details (a chair
63
+ has caught and corrected such an error unprompted).
64
+ - **Optional council elements (v2.2.0) verified live:** critic seat (solo-alongside-fanout;
65
+ `role: "critic"` passes through `council tally` untouched), debate mode's nothing-to-debate path
66
+ (provisional `--no-ledger` tally → skip rebuttals → final ledger-recorded tally), and the chair
67
+ verdict scale (parseable `VERDICT:` line + hard questions) all behaved per SEAT-BRIEFS. **Debate
68
+ mode's defense/re-vote waves remain unexercised** — an all-Confirmed consensus run has no
69
+ rebuttal surface; exercise them on a contentious artifact before trusting that path blind.
57
70
 
58
71
  ## Per-model notes
59
72
 
@@ -102,6 +115,21 @@ injection, long-read failures, judge tool-wander; see changelog)._
102
115
  ### Claude (in-council, when toggle on)
103
116
  - Consistently the most *calibrated* reviewer (no severity inflation; findings overwhelmingly Confirmed; bench-best street-cred in recent runs) but sometimes the least *original* — it can miss the boldest single catch. Treat as a reliability floor, not a discovery engine.
104
117
 
118
+ ### minimax (`--model minimax` → via OpenRouter)
119
+ - Fast (~2 min review legs), cheap, `clean` findings-JSON conformance on debut.
120
+ - Took the **critic seat** brief exceptionally well: unanimously ranked #1 by its bench, full
121
+ coverage on a ground-truth test, zero padded findings under the anti-padding rule. A strong
122
+ default critic-seat candidate.
123
+ - **Quirks:** occasional CJK character intrusions mid-English prose (cosmetic; the findings JSON
124
+ is unaffected); can invert the direction of an arithmetic detail inside an otherwise-correct
125
+ rationale — see the claim-class-dedup tip in Stage-2 briefing tips.
126
+
127
+ ### qwen-coder (`--model qwen-coder` → via OpenRouter; distinct from `qwen`)
128
+ - Very fast (16–22 s legs, review and judging alike), `clean` conformance, competent
129
+ core-blocker coverage on prose/PRD artifacts.
130
+ - Ranked last on its debut bench — misses the offline, interruption-handling, and
131
+ test-methodology gap classes stronger seats catch. Fine budget-bench filler; do not chair it.
132
+
105
133
  ### (others — add as used)
106
134
  - Opus / o-series etc. are reachable via amicus **if their API keys are configured**. Add notes
107
135
  here the first time each is used.
@@ -160,3 +188,8 @@ This section keeps only per-model **qualitative quirks** and **structural-confor
160
188
  GUI-hangs-on-this-machine rule (resolved 2026-06-10; headless stays the council default by
161
189
  design). Config path updated to `~/.config/amicus/.env`.
162
190
  - **2026-07-02** — Folded back field lessons from runs 4-7 (AV-receiver, pork-shoulder, resume, novel ×2 councils): PowerShell `--models` quoting; current-date injection; long-read model selection; judge no-tools preamble; severity-inflation-justifies-dispute; five-keys tally schema; new Grok/Kimi/Mistral/Claude-in-council sections. Quantitative history stays in the ledger (`amicus council stats`).
191
+ - **2026-07-14 (v2.2.0)** — Optional council elements shipped and verified on a planted-flaw
192
+ ground-truth council (critic seat, debate mode nothing-to-debate path, chair verdict scale;
193
+ expert lenses defined but not yet field-run). New lessons: claim-class dedup glosses
194
+ rationale-level errors in Stage-2; minimax debut (strong critic seat, CJK-intrusion quirk);
195
+ qwen-coder debut (fast budget filler). Debate mode's defense/re-vote waves still unexercised.