amicus 4.0.0 → 4.1.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.
Files changed (38) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +118 -0
  3. package/README.md +3 -3
  4. package/commands/council.md +6 -6
  5. package/package.json +1 -1
  6. package/schemas/council-run.schema.json +16 -1
  7. package/schemas/council-tally.schema.json +10 -1
  8. package/schemas/council-verdict.schema.json +10 -1
  9. package/schemas/error.schema.json +1 -1
  10. package/scripts/postinstall.js +6 -3
  11. package/skills/second-opinion/COUNCIL-DESIGN.md +40 -0
  12. package/skills/second-opinion/MANUAL-ORCHESTRATION.md +266 -0
  13. package/skills/second-opinion/MODEL-NOTES.md +21 -0
  14. package/skills/second-opinion/SEAT-BRIEFS.md +4 -0
  15. package/skills/second-opinion/SKILL.md +319 -333
  16. package/src/cli-handlers-council-run.js +9 -0
  17. package/src/cli-handlers-council.js +20 -2
  18. package/src/cli.js +8 -0
  19. package/src/council/briefings-debate.js +158 -0
  20. package/src/council/briefings-stage2.js +16 -9
  21. package/src/council/debate.js +98 -0
  22. package/src/council/ledger.js +2 -1
  23. package/src/council/parse-stage2.js +83 -1
  24. package/src/council/report-html.js +28 -1
  25. package/src/council/report.js +50 -2
  26. package/src/council/run-assemble.js +91 -9
  27. package/src/council/run-chair.js +145 -0
  28. package/src/council/run-debate.js +289 -0
  29. package/src/council/run-launch.js +27 -1
  30. package/src/council/run-stages.js +41 -13
  31. package/src/council/run-state.js +40 -1
  32. package/src/council/run.js +108 -110
  33. package/src/council/verdict.js +43 -2
  34. package/src/mcp-council-awareness.js +187 -0
  35. package/src/mcp-council-run.js +29 -128
  36. package/src/mcp-server.js +28 -3
  37. package/src/mcp-tools.js +22 -2
  38. package/src/utils/error-doc.js +2 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amicus",
3
- "version": "4.0.0",
3
+ "version": "4.1.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,124 @@ All notable changes to Amicus are documented here. Format follows
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [4.1.0] - 2026-07-21
9
+
10
+ The `second-opinion` skill stops hand-driving councils. Stages 1–3 and the Stage-5 artifacts
11
+ collapse into a single `amicus council run`, leaving Claude only the stages that genuinely need
12
+ judgement — intake, decisions, and lessons. The engine gains an optional rebuttal round so a
13
+ finding's author can answer the reviewers who disputed it, and Claude can now enter its own review
14
+ into the bundle without ever being launched as a model leg.
15
+
16
+ ### Added
17
+
18
+ - **Skill fast path.** `skills/second-opinion/SKILL.md` now delegates Stages 1–3 (and the Stage-5
19
+ artifact materialization) to one `amicus council run` invocation; the human stages (0 intake,
20
+ 4 decisions, 6 lessons) stay Claude-orchestrated. The manual mechanics are preserved verbatim in
21
+ the new `skills/second-opinion/MANUAL-ORCHESTRATION.md` as the documented fallback for when the
22
+ engine is unavailable or a case the fast path cannot express.
23
+ - **Headless debate mode** — `amicus council run --debate` / `amicus_council_run {debate:true}`.
24
+ A Stage-2.5 rebuttal round runs between cross-review and the final tally: findings that came out
25
+ Contested or Disputed go back to the model that raised them, which defends, amends, or withdraws
26
+ each; the judges who disputed them then re-vote; a final tally folds the outcome in. Exactly one
27
+ round, structurally — there is no edge back into a debate stage. `run.json` gains an additive
28
+ `debate` summary, tally/verdict findings gain a `debate` decoration, and both report renderers
29
+ gain a "Debate round" section. The Council Review Action gains a `debate` input (default off),
30
+ and withdrawn findings are excluded from its PR annotations.
31
+ - **`--claude-review <file>` / `claudeReviewFile`.** Enters Claude's own review as judged review
32
+ N+1 from a file. No model leg is ever launched for it and it may never chair — `claude` is a
33
+ reserved seat name that is rejected pre-flight in `--models`, `--chair` and `--critic` on such a
34
+ run.
35
+ - **`--render` on `council verdict`, `render:true` on `amicus_verdict`.** Refreshes `report.html`
36
+ from the decided verdict. The MCP tool also returns the markdown rendering; it writes only when
37
+ an `outDir` inside the project is supplied, and its `readOnlyHint` is now correctly `false`.
38
+ - **`--no-cost-gate` on `council run`.** Disables the per-leg price gate for the whole run —
39
+ repairs, chair chain and debate legs included — in one place instead of per invocation.
40
+
41
+ ### Fixed
42
+
43
+ - **The Council Review Action no longer defaults to a bench that cannot lose a leg.** Its default
44
+ `models` were `deepseek,gemini,glm` with `deepseek` as chair; because the chair is excluded from
45
+ the bench, that left **two** seats against a quorum minimum of two, so one stalled leg failed the
46
+ entire review. The default is now four seats (`glm,qwen,minimax,qwen-coder`), leaving real slack.
47
+ - **`postinstall` now installs `SEAT-BRIEFS.md`.** It shipped in the tarball but was never copied
48
+ into `~/.claude/skills/second-opinion/`, so the seat briefing reference has been missing from
49
+ every installation to date.
50
+ - **`amicus council verdict` no longer discards the chair's verdict.** Writing the decided verdict
51
+ over the engine's one dropped `overallVerdict` to `null`, because the tally record it is built
52
+ from does not carry it. `runVerdict` now recovers it from the run folder — the engine's
53
+ `verdict.json` when present (guarded on `runId`, so a foreign file cannot inject another run's
54
+ verdict), otherwise by re-parsing `chair-output.md` with the engine's own chair parser. A run
55
+ whose chair was skipped still yields `null`; nothing is ever invented. `amicus_verdict` had the
56
+ same loss on the Cowork path and gains an explicit optional `overallVerdict` input, since the MCP
57
+ tool receives a record inline with no run folder to recover from.
58
+
59
+ ### Documentation
60
+
61
+ - **The skill's Stage 4 and Stage 5 now name where finding claims actually live.** Both stages
62
+ instructed the reader to show each finding's claim while pointing only at `tally.json`, whose
63
+ findings carry tiers and adjudications but no `claim`. The claim and location live in
64
+ `tally-input.json`; both stages now state the join (on finding `id`) explicitly.
65
+
66
+ ### Changed
67
+
68
+ - **`claude` can no longer be promoted as fallback chair on any run.** When a configured chair
69
+ dies, the engine promotes another model by reliability; `claude` is now excluded unconditionally.
70
+ This affects runs that never use `--claude-review`, because the reliability ledger has no way to
71
+ distinguish a file-sourced `claude` row from a real leg — and promoting it would select a chair
72
+ the engine cannot launch.
73
+ - **`npm i -g amicus@4.1` rewrites the installed `SKILL.md`** to the fast path (existing
74
+ product-code overwrite policy). `MODEL-NOTES.md` remains machine-local and is never overwritten.
75
+ Rollback is a reinstall of 4.0.x.
76
+
77
+ ### Notes
78
+
79
+ - All changes are additive: the council document family stays `schemaVersion: 2`, the MCP tool
80
+ count stays 15 (new inputs only), and a run using none of the new flags produces byte-identical
81
+ artifacts to 4.0.1. No migration is required.
82
+
83
+ ## [4.0.1] - 2026-07-20
84
+
85
+ Follow-up fixes to the v4.0.0 council engine: `amicus abort` and `amicus status` now see every
86
+ sub-wave a stage launched, a council run that dies before its first checkpoint is recoverable
87
+ instead of stranded, and neither command can be thrown by a malformed wave record.
88
+
89
+ ### Fixed
90
+
91
+ - **`amicus abort` now cascades to every in-flight council leg, not just the primary wave of
92
+ each stage.** A stage can own several sub-waves — the chair's `ch1..ch4` retry/fallback/repair
93
+ chain, one solo per lens, a critic solo beside the seat wave, and the bounded Stage-1/Stage-2
94
+ repair re-prompts — but only a single `waveId` was recorded per stage (and the chair stage
95
+ recorded none at all), so the targeted cascade skipped those legs and left them to the
96
+ `waitThenKill` process-tree fallback. They were still killed, so this was never a leak or a
97
+ hang; what was lost were the per-leg `aborted` markers, an accurate `legsAborted` count, and a
98
+ faithful per-stage audit trail in `run.json`. Stage entries now carry a `waveIds` array
99
+ recording every sub-wave at launch time (documented in `schemas/council-run.schema.json`), and
100
+ the cascade targets the union of `waveId` + `waveIds`. In lens mode `stage1` previously
101
+ advertised only a phantom `-s1` wave that never launches, so *no* Stage-1 leg was reachable;
102
+ lens runs no longer record that `waveId` at all.
103
+ - **`amicus status` now rolls up council legs across every sub-wave of the active stage.** It
104
+ counted only the stage's primary `waveId`, so a lens run — which has no seat wave — always
105
+ reported `legsTotal: null`, and a run with a critic omitted the critic's leg from the count
106
+ (e.g. `2` instead of `3` for two seats plus a critic). Note that `legsTotal` can now rise
107
+ mid-stage when a bounded repair re-prompt launches, which is a real additional model call.
108
+ - **A council run spawned through `amicus_council_run` that died before its first checkpoint no
109
+ longer strands an unrecoverable record.** The MCP handler wrote `run.json` with
110
+ `status: "running"` and no `pid`, leaving the spawned CLI child to record its own pid at
111
+ startup; a child that died inside that window left a pid-less `running` run that `amicus
112
+ status` skipped entirely (its crash detection is guarded on `run.pid`) and that `amicus abort`
113
+ could not fall back to killing, so the run was recoverable only by hand. The handler now
114
+ captures the pid from the spawned child and checkpoints it immediately — the same value the
115
+ engine writes itself, recorded a beat earlier. The pid is written to its own
116
+ `spawn.pid` file rather than patched into `run.json`: the spawning process and the engine
117
+ child both write `run.json`, and `checkpoint` is a read-merge-write with no cross-process
118
+ lock, so a pid patch could clobber (or be clobbered by) the child's first checkpoint. Readers
119
+ prefer `run.json`'s own pid and fall back to `spawn.pid`.
120
+ - **A malformed wave `metadata.json` no longer throws out of `amicus status` or `amicus abort`.**
121
+ `countWaveLegs` and `cascadeWave` both assumed the `legs` field was an array if it was present
122
+ at all, so a half-written or hand-edited record raised a `TypeError` past its caller. Both now
123
+ treat a non-array `legs` as no legs. `cascadeWave`'s wave-level abort mark is also guarded, so
124
+ a failure there can no longer discard the count of legs it had already marked.
125
+
8
126
  ## [4.0.0] - 2026-07-20
9
127
 
10
128
  The **headless council engine** release. `amicus council run` (CLI) and `amicus_council_run`
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 (v4.0): Stage-1 reviews → anonymized cross-review → deterministic tally → non-Claude chair verdict, in one command with no Claude runtime. Writes a run directory with `verdict.json` (including `overallVerdict`) and `report.html` — see [docs/council.md](./docs/council.md#amicus-council-run). |
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.0.0",
332
+ "version": "4.1.0",
333
333
  "model": "google/gemini-2.5-flash",
334
334
  "phase": "terminal"
335
335
  }
@@ -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.
@@ -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 end to end, in pipeline order: Stage 0
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; 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`.
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.0.0",
3
+ "version": "4.1.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": [
@@ -21,6 +21,7 @@
21
21
  "startedAt": { "type": ["string", "null"] },
22
22
  "completedAt": { "type": ["string", "null"] },
23
23
  "waveId": { "type": "string" },
24
+ "waveIds": { "type": "array", "items": { "type": "string" } },
24
25
  "taskIds": { "type": "array", "items": { "type": "string" } }
25
26
  }
26
27
  }
@@ -32,6 +33,20 @@
32
33
  "labelMap": { "type": ["object", "null"], "additionalProperties": { "type": "string" } },
33
34
  "options": { "type": "object" },
34
35
  "usage": { "type": "object" },
35
- "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
+ }
36
51
  }
37
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"] }
@@ -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 product code
29
- * (overwrite on update); MODEL-NOTES is user data its reviewer-reliability table evolves
30
- * per-run, so it is seeded once and never clobbered. */
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.