amicus 1.8.0 → 1.9.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.
- package/.claude-plugin/plugin.json +1 -2
- package/CHANGELOG.md +148 -0
- package/README.md +43 -6
- package/commands/council.md +22 -0
- package/electron/close-guard.js +140 -0
- package/electron/fold.js +39 -2
- package/electron/main.js +12 -2
- package/package.json +3 -1
- package/skills/second-opinion/MODEL-NOTES.md +47 -1
- package/skills/second-opinion/SKILL.md +51 -10
- package/skills/sidecar/SKILL.md +51 -38
- package/src/cli-handlers-doctor.js +1 -1
- package/src/headless.js +2 -0
- package/src/mcp-server.js +29 -33
- package/src/sidecar/interactive-process.js +99 -0
- package/src/sidecar/interactive.js +1 -87
- package/src/sidecar/read.js +13 -5
- package/src/sidecar/session-utils.js +7 -2
- package/src/sidecar/setup-window.js +1 -1
- package/src/sidecar/start.js +2 -1
- package/src/utils/client-detect.js +118 -0
- package/src/utils/untrusted-fence.js +38 -0
|
@@ -4,7 +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-
|
|
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)._
|
|
8
9
|
|
|
9
10
|
## Global operating rules (all models)
|
|
10
11
|
- **Council runs are headless by design** (autonomous batch work): `fanout` is headless by
|
|
@@ -26,6 +27,18 @@ _Last updated: 2026-06-10 (v3 migration: engine workarounds pruned — see chang
|
|
|
26
27
|
model-specific signals. Never present a half-finished run as an answer.
|
|
27
28
|
- **Credentials:** keys live in `~/.config/amicus/.env` (legacy `~/.config/sidecar/.env` still
|
|
28
29
|
read). Configure with `amicus setup`.
|
|
30
|
+
- **PowerShell `--models` quoting (Windows):** always quote comma-separated model lists —
|
|
31
|
+
`--models "gemini,gpt,deepseek"`. Unquoted, PowerShell splits on commas and amicus receives one
|
|
32
|
+
mangled alias → instant arg-parse failure. (Now baked into every SKILL.md example.)
|
|
33
|
+
- **Inject the current date into briefings for time-sensitive artifacts** (resumes, dated plans).
|
|
34
|
+
Headless models don't reliably know "today": one run produced a false "future-dated" blocker two
|
|
35
|
+
judges then confirmed. (Now a Stage-0 rule in SKILL.md.)
|
|
36
|
+
- **Very long artifacts (80k+ words) break the agent-reads-the-file transport for some models.**
|
|
37
|
+
gpt/deepseek/grok have handled 82k-word agentic reads; gemini(-flash) and kimi stalled (narrate-
|
|
38
|
+
stall / 25-min timeout / poller "Incomplete"). Pre-select proven long-read models or inline the
|
|
39
|
+
text for large-context models.
|
|
40
|
+
- **Stage-6 approvals:** write the proposed MODEL-NOTES diff to a run-folder file and put that path
|
|
41
|
+
in the approval prompt — chat-text diffs can be hidden behind the approval dialog.
|
|
29
42
|
|
|
30
43
|
## Stage-2 cross-review briefing tips
|
|
31
44
|
|
|
@@ -36,6 +49,11 @@ _Last updated: 2026-06-10 (v3 migration: engine workarounds pruned — see chang
|
|
|
36
49
|
finding referenced by run-global label id (e.g. `A2` = Review A's 2nd finding).
|
|
37
50
|
- After de-anonymizing, assemble the tally input (see SKILL.md Stage 2 assembly recipe) and run
|
|
38
51
|
`amicus council tally <input.json> --json` — do not hand-tally tiers or street-cred numbers.
|
|
52
|
+
- Telling judges that **material severity inflation can justify a `dispute`** sharpens adjudications.
|
|
53
|
+
- **Plan-agent judges can wander to tools** (reading run-folder files = anonymization leak). The
|
|
54
|
+
no-tools preamble is now mandatory in SKILL.md Stage 2/3 — keep it verbatim.
|
|
55
|
+
- The tally input needs **all five keys** (`meta` incl. `meta.models`, `findings`, `adjudications`,
|
|
56
|
+
`rankings`, `runStats`) — see the SKILL.md Stage-2 recipe step 0.
|
|
39
57
|
|
|
40
58
|
## Per-model notes
|
|
41
59
|
|
|
@@ -45,17 +63,44 @@ _Last updated: 2026-06-10 (v3 migration: engine workarounds pruned — see chang
|
|
|
45
63
|
structured output verbatim, without preamble. (Historical: its narrate-then-glob habit used to
|
|
46
64
|
trip the old headless poller; the engine handles tool-call gaps now — F1.)
|
|
47
65
|
- Don't trust its self-reported version string ("I am gemini-X") as ground truth.
|
|
66
|
+
- **Red-team:** takes an adversarial brief well — high variance by design; use when consensus risk is high.
|
|
67
|
+
- **Blind self-votes are inconsistent** (self-#1 in some runs, self-last in others) → discount self-votes either way.
|
|
68
|
+
- Alias has resolved to **flash** tiers: fast, shallowest coverage, yet a recurring sharp fact/consistency checker (it alone refuted a bench-wide date error). Cheap cross-check value.
|
|
69
|
+
- **Unreliable on long agentic reads** (see global rule) — inline the text or swap models for book-length material.
|
|
48
70
|
|
|
49
71
|
### DeepSeek (`--model deepseek` → via OpenRouter)
|
|
50
72
|
- **Strengths:** resilient; produces strong, well-structured, well-cited critical analysis. A good
|
|
51
73
|
default reviewer and a proven chair.
|
|
52
74
|
- **Quirk:** occasional transient 502 mid-run → re-run the leg.
|
|
75
|
+
- Proven chair (5 clean chairings) — decisive, well-structured synthesis.
|
|
76
|
+
- As a Stage-1 reviewer of human-facing documents it **over-escalates severity** (typos/tenure → "blocker"); discount its blocker labels against peers. Prune its self-retractions when tallying.
|
|
77
|
+
- **"Agree-with-the-adversary" lean:** it has been the lone endorser of a red-team's harshest claims, turning them Contested — cross-check before treating its lone agreements as consensus.
|
|
53
78
|
|
|
54
79
|
### GPT (`--model gpt` → via OpenRouter)
|
|
55
80
|
- **Strengths:** reachable via the OpenRouter key; resilient; very thorough structured critique
|
|
56
81
|
(25 findings on a 1-page framework). Cleanly separates the review criteria.
|
|
57
82
|
- **Quirks:** verbose — peers dinged it for volume-over-judgment (good coverage, lower
|
|
58
83
|
discrimination); **self-ranked its own review #1** in cross-review → discount self-votes.
|
|
84
|
+
- Ranked genuine #1 by all judges (incl. non-self) in one run — thoroughness is real, not a self-vote artifact. Handled an 82k-word agentic read cleanly.
|
|
85
|
+
- **Asserts context-dependent facts (dates, "is this future?") without verifying** — and self-confirms them in adjudication. Cross-check any time-dependent claim it raises.
|
|
86
|
+
- A good calibration anchor in cross-review: confirms observational findings, disputes interpretive overreach.
|
|
87
|
+
|
|
88
|
+
### Grok (`--model grok` → via OpenRouter)
|
|
89
|
+
- Very fast legs; credible judge and chair (rejected its own weak findings as chair; honest blind self-rank).
|
|
90
|
+
- Strong red-team fit; handled an 82k-word agentic read. Weight its **observational** catches heavily and its **interpretive** verdicts cautiously (bench pattern: the former confirmed, the latter disputed).
|
|
91
|
+
- Stage-1 non-red-team reviews skew to scope-inflated "missing content" majors.
|
|
92
|
+
|
|
93
|
+
### Kimi (`--model kimi` → via OpenRouter)
|
|
94
|
+
- The bench's sharpest adjudicator (caught strawmen and misreads other judges waved through).
|
|
95
|
+
- **Very slow legs (5-7 min)** — it gates wave wall-clock; budget timeouts around it.
|
|
96
|
+
- Stalls on long agentic reads (poller "Incomplete" with only a preamble). Reserve for short-artifact adjudication.
|
|
97
|
+
|
|
98
|
+
### Mistral (`--model mistral` → via OpenRouter)
|
|
99
|
+
- Fast, broad coverage, catches real issues.
|
|
100
|
+
- **Hallucination risk is real:** has invented non-existent product models/specs, disputed independently by two judges. Cross-check every specific model number or product claim it introduces.
|
|
101
|
+
|
|
102
|
+
### Claude (in-council, when toggle on)
|
|
103
|
+
- 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.
|
|
59
104
|
|
|
60
105
|
### (others — add as used)
|
|
61
106
|
- Opus / o-series etc. are reachable via amicus **if their API keys are configured**. Add notes
|
|
@@ -114,3 +159,4 @@ This section keeps only per-model **qualitative quirks** and **structural-confor
|
|
|
114
159
|
cap (superseded by `--prompt-file`), the absolute-path/cwd trap (fixed by F2), and the
|
|
115
160
|
GUI-hangs-on-this-machine rule (resolved 2026-06-10; headless stays the council default by
|
|
116
161
|
design). Config path updated to `~/.config/amicus/.env`.
|
|
162
|
+
- **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`).
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: second-opinion
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Run a structured, multi-model "council" review of material the user provides plus
|
|
5
|
+
an analysis request and criteria, turning it into decisions. Models review the
|
|
6
|
+
material independently, then anonymously rank and adjudicate each other's reviews
|
|
7
|
+
in a peer cross-review stage, and a designated non-Claude "chair" model synthesizes
|
|
8
|
+
the verdict — Claude orchestrates but does not synthesize. Trigger on "second
|
|
9
|
+
opinion", "multi-model review", "council review", "have other models
|
|
10
|
+
review/critique/evaluate this", "cross-check this against the research",
|
|
11
|
+
"red-team/stress-test this doc", "what would other models conclude about this", or
|
|
12
|
+
any request to review provided material with external model(s) and turn it into
|
|
13
|
+
accept/deny decisions — even if the user never says "sidecar". This is NOT for
|
|
14
|
+
quick or exploratory single-model chats — "ask Gemini…", "what does DeepSeek
|
|
15
|
+
think", brainstorming with a model, or spawning/forking a conversation with
|
|
16
|
+
another model — use the sidecar skill instead.
|
|
4
17
|
---
|
|
5
18
|
|
|
6
19
|
# Second Opinion (LLM Council)
|
|
@@ -18,6 +31,8 @@ Operating lessons from each run fold back into `MODEL-NOTES.md` (with approval),
|
|
|
18
31
|
|
|
19
32
|
**Before launching any model, READ `MODEL-NOTES.md`** (next to this file). It holds the operating rules and per-model quirks that decide whether a run succeeds or silently fails. These were learned the hard way; skipping them wastes runs and produces empty results that look like answers.
|
|
20
33
|
|
|
34
|
+
**Transport rule — CLI not on PATH:** every command below assumes the `amicus` CLI. If `amicus` is not on PATH (typical for **plugin-only installs**), run the identical commands as `npx -y amicus@latest <args>` (e.g. `npx -y amicus@latest fanout --models "m1,m2,m3" --prompt-file <path> --json`), or use the equivalent MCP tools (`amicus_fanout`, `amicus_start`, `amicus_status`, `amicus_read`, `amicus_council_tally`, `amicus_council_stats`, `amicus_verdict`) — council briefings are always self-contained (`--no-context`), so MCP transport is equivalent.
|
|
35
|
+
|
|
21
36
|
## When to use
|
|
22
37
|
|
|
23
38
|
- The user provides documents, artifacts, or links **and** an analysis request **and** criteria, and wants other models to weigh in independently.
|
|
@@ -53,13 +68,17 @@ in this run is written here. Use its absolute path in all `--prompt-file` argume
|
|
|
53
68
|
- Write every briefing to a temp file (`_tmp-*.md` in the run folder) and pass it with
|
|
54
69
|
`--prompt-file` — never inline a briefing as a CLI argument. All `_tmp-*` files are cleaned up
|
|
55
70
|
after the run.
|
|
71
|
+
- **Inject the current date into every briefing when the artifact is time-sensitive** (resumes, dated
|
|
72
|
+
plans, anything with start/end dates or 'present' ranges). Headless council models do not reliably
|
|
73
|
+
know "today" and have raised false "future-dated" blockers; state the date explicitly, e.g.
|
|
74
|
+
"Today's date is YYYY-MM-DD."
|
|
56
75
|
|
|
57
76
|
**Pick the council.** Default: **3 models from different families (non-Claude)**. Recommend them ranked by fit, consulting both the reviewer-reliability data from `amicus council stats` (the authoritative quantitative source — runs, avg peers-only street-cred, confirm-rate, fact-error rate) and the qualitative quirks in `MODEL-NOTES.md`. State the estimated cost. The estimate is the budget gate's pre-flight figure (per-$/Mtok pricing from the cached catalog; direct-provider legs without catalog pricing are disclosed as "cost unknown"). State it as an estimate, not a guarantee. **Disclose the run shape up front** before asking for confirmation — e.g.:
|
|
58
77
|
|
|
59
78
|
**Free council (zero-cost).** If the user asks for a "free council" / "zero-cost council",
|
|
60
79
|
read `councils.free` from `~/.config/amicus/config.json` and run
|
|
61
80
|
`amicus fanout --council free --prompt-file <briefing>`. Free-tier handling:
|
|
62
|
-
- Cost ≈
|
|
81
|
+
- Cost ≈ \$0 — skip the paid-run cost framing (the budget gate is a no-op at zero price).
|
|
63
82
|
- No reliability history: free models have no `amicus council stats` / `MODEL-NOTES` record,
|
|
64
83
|
so don't rank on street-cred. Pick the most capable free model as chair and state lower confidence.
|
|
65
84
|
- Weak structured output: small free models are less reliable at the strict findings JSON; expect
|
|
@@ -97,10 +116,12 @@ Each council model reviews **the artifact** independently. Write one Stage-1 bri
|
|
|
97
116
|
(`_tmp-briefing-stage1.md` in the run folder) and launch the whole wave as ONE background call:
|
|
98
117
|
|
|
99
118
|
```
|
|
100
|
-
amicus fanout --models <m1,m2,m3> --prompt-file <run-folder>/_tmp-briefing-stage1.md --json \
|
|
119
|
+
amicus fanout --models "<m1,m2,m3>" --prompt-file <run-folder>/_tmp-briefing-stage1.md --json \
|
|
101
120
|
--agent Plan --no-context --summary-length verbose --timeout <minutes>
|
|
102
121
|
```
|
|
103
122
|
|
|
123
|
+
Always quote the `--models` list — unquoted, PowerShell splits on commas and the CLI receives one mangled alias (instant arg-parse failure).
|
|
124
|
+
|
|
104
125
|
Run it in the background (`run_in_background: true`); you are notified on completion — do not
|
|
105
126
|
poll. `fanout` is headless by definition. The command exits when every leg is terminal and prints
|
|
106
127
|
ONE JSON wave document on stdout (`schemaVersion: 1`; the wave's id field is `waveId`, each leg's id is `taskId`): check `status` (`complete` | `partial` |
|
|
@@ -145,7 +166,7 @@ equivalent.
|
|
|
145
166
|
Instruct models to emit the structured JSON verbatim after the prose, without preamble, so it parses cleanly.
|
|
146
167
|
|
|
147
168
|
**After the wave returns, validate each leg's findings block** using `validateFindings` (Unit A — `src/council/findings.js`). If a leg's JSON fails validation:
|
|
148
|
-
1. Issue a **solo `start --json`** re-prompt to that one model: "re-emit only the findings JSON, fixing: \<errors\>." Keep the first-pass prose. (Solo `start`
|
|
169
|
+
1. Issue a **solo `start --json`** re-prompt to that one model: "re-emit only the findings JSON, fixing: \<errors\>." Keep the first-pass prose. (Solo `start` passes through the **same budget gate** as `fanout`. If launching the wave required `--max-cost <$>` or `--no-cost-gate`, pass the **same flag on every repair re-prompt and on the chair call** — otherwise the gate can refuse a repair or the chair mid-council.)
|
|
149
170
|
2. If still malformed, retry **once more** (cap = **2** re-prompts total).
|
|
150
171
|
3. If still malformed after 2 retries, mark the review `unstructured` and hand-parse its prose into the schema. The review proceeds — never dropped for a formatting miss.
|
|
151
172
|
|
|
@@ -182,7 +203,7 @@ Each model **unknowingly ranks and adjudicates its own review** — this is the
|
|
|
182
203
|
model. Write the bundle + judging instructions to `_tmp-bundle-stage2.md` and launch one wave:
|
|
183
204
|
|
|
184
205
|
```
|
|
185
|
-
amicus fanout --models <m1,m2,m3> --prompt-file <run-folder>/_tmp-bundle-stage2.md --json \
|
|
206
|
+
amicus fanout --models "<m1,m2,m3>" --prompt-file <run-folder>/_tmp-bundle-stage2.md --json \
|
|
186
207
|
--agent Plan --no-context --summary-length verbose --timeout <minutes>
|
|
187
208
|
```
|
|
188
209
|
|
|
@@ -191,6 +212,12 @@ adjudication response. **Stage-2 degrade:** a judge leg dies → tally over the
|
|
|
191
212
|
(≥ 1) and disclose the reduced bench in `crossreview-matrix.md`; tier definitions are unchanged
|
|
192
213
|
(they already count "judges engaged"). Each judge is asked to do two things on the bundle:
|
|
193
214
|
|
|
215
|
+
**Judge-briefing hardening (required).** Open `_tmp-bundle-stage2.md` with this preamble, verbatim, as its first line:
|
|
216
|
+
|
|
217
|
+
> Do NOT use any tools or read any files; everything is in this message; begin immediately with A1:
|
|
218
|
+
|
|
219
|
+
Plan-agent judges have wandered to tools mid-adjudication (reading files instead of judging and returning only narration), and a tool-capable judge can read the de-anonymized `review-<model>.md` files in the run folder — an anonymization leak. The preamble closes both. **Scratch-cwd (optional second layer):** launch the Stage-2 wave (and the Stage-3 chair call) with `--cwd <run-folder>/_scratch/` — create the empty directory first — so even a wandering agent finds nothing to read. Caveat: those legs' session records then live under `_scratch/.claude/amicus_sessions/`, so any later `amicus read <taskId>` for them needs the same `--cwd`.
|
|
220
|
+
|
|
194
221
|
**Task A — Rank.** Order the reviews from most to least accurate and insightful. End the response with a parseable block in exactly this format (no other text on those lines):
|
|
195
222
|
|
|
196
223
|
```
|
|
@@ -205,11 +232,16 @@ FINAL RANKING:
|
|
|
205
232
|
As each judge's ranking + adjudication response returns, collect it (the raw per-judge responses are working intermediates, not separate run-folder artifacts). Once all are in, **assemble the de-anonymized tally input** and then call `amicus council tally`:
|
|
206
233
|
|
|
207
234
|
**Stage-2 → tally assembly recipe (Claude's work before calling `tally`):**
|
|
235
|
+
0. **Build `meta` and `findings[]` first — `tally` requires both** (missing either fails with `BAD_ARGS: Cannot read properties of undefined (reading 'map')`):
|
|
236
|
+
- `meta` = `{ "runId": "<run-folder stem>", "models": [<every reviewed model id, including "claude" when the toggle is on — this is the street-cred universe>], "chair": "<confirmed chair model id>", "claudeInCouncil": <Stage-0 toggle> }`. Optional extras: `runType`, `date`.
|
|
237
|
+
- `findings[]` = one entry per finding across ALL reviews: `{ "id": "<run-global label id from step 1, e.g. A1>", "raiser": "<de-anonymized model that raised it>", "severity": "<from the review JSON>" }` (`claim` may be carried along but is not required).
|
|
208
238
|
1. **Rewrite finding ids to run-global label ids.** Each Stage-1 review's local integer ids (`1`, `2`, `3`…) become `A1`, `A2`, `A3`… (where `A` is that review's anonymized label). The label↔model map (`Review A → deepseek`, etc.) is the key.
|
|
209
239
|
2. **Build `adjudications`** — for every judge across all findings: `findingId` = run-global label id; `judge` = the model id (de-anonymized via the map); `verdict ∈ {agree, dispute, neutral}`. Include every judge's verdict on every finding. The raiser's own adjudication of its own finding is **included in the input** (the tally engine excludes it when computing peers-only tiers — do not pre-filter it).
|
|
210
240
|
3. **Translate each judge's `FINAL RANKING:` block** — convert the label order (`1. Review C / 2. Review A / 3. Review B`) into a model `order` array via the same map (e.g. `{C→mistral, A→deepseek, B→gpt}` ⇒ `order: ["mistral","deepseek","gpt"]`). This is each entry in `rankings[]`.
|
|
211
241
|
4. **Populate `runStats`** from the per-leg run documents emitted by `fanout --json` (and any solo red-team/chair `start --json` docs): copy `model`, `status`, `durationMs`, `usage` verbatim. Any leg with no run doc gets `durationMs: null` and `usage: null` — never invent a value. Attach `role` (`council` | `redteam` | `claude`), `wasChair`, and `conformance` (`clean` | `repaired` | `unstructured`) as council-domain labels.
|
|
212
242
|
|
|
243
|
+
**Five-keys checklist — verify `tally-input.json` has ALL of:** `meta` (with `meta.models`), `findings`, `adjudications`, `rankings`, `runStats` (`runStats` may be `[]`; the other four are required). Do not call `tally` until all five are present.
|
|
244
|
+
|
|
213
245
|
Then call:
|
|
214
246
|
|
|
215
247
|
```
|
|
@@ -240,11 +272,15 @@ amicus start --model <chair> --no-ui --json \
|
|
|
240
272
|
--agent Plan --no-context --summary-length verbose --timeout <minutes>
|
|
241
273
|
```
|
|
242
274
|
|
|
275
|
+
(The budget gate applies to this solo call too — if Stage 0 needed `--max-cost <$>` or `--no-cost-gate` to launch the wave, the chair call needs the same flag.)
|
|
276
|
+
|
|
243
277
|
The run document's `summary` is the verdict. The packet contains:
|
|
244
278
|
- All Stage-1 reviews (de-anonymized — model attribution restored)
|
|
245
279
|
- All cross-review ranking outputs (with model attribution)
|
|
246
280
|
- All adjudication outputs (with model attribution and `agree | dispute | neutral` verdicts per finding)
|
|
247
281
|
|
|
282
|
+
Open `_tmp-chair-packet.md` with the no-tools preamble, adjusted for the chair: *'Do NOT use any tools or read any files; everything is in this message; begin immediately with the verdict.'* The packet is complete by construction — the chair must never go looking for files.
|
|
283
|
+
|
|
248
284
|
Instruct the chair to write a **synthesized verdict** that:
|
|
249
285
|
- Weighs each reviewer's findings by their peer-validated standing (street-cred rank and adjudication pattern)
|
|
250
286
|
- Distinguishes findings the bench broadly endorsed from contested or singleton claims
|
|
@@ -307,15 +343,17 @@ Do not advance to Stage 5 until every finding in both tiers has a recorded decis
|
|
|
307
343
|
— exact for `reported`, `~` for `estimated`, `?` for `unknown` — and never
|
|
308
344
|
invent a figure. Add a wave **total cost** row from the wave document's
|
|
309
345
|
`usage.cost` (`source: reported|estimated|mixed|unknown`). Any leg with no run doc → `durationMs: null`, `usage: null`; never invent a value.
|
|
310
|
-
- **Renderer:** once `verdict.json` is written, generate
|
|
311
|
-
`amicus council report <run-folder>/verdict.json --md > <run-folder>/report.md`
|
|
312
|
-
|
|
346
|
+
- **Renderer:** once `verdict.json` is written, generate BOTH renderings:
|
|
347
|
+
`amicus council report <run-folder>/verdict.json --md > <run-folder>/report.md` and
|
|
348
|
+
`amicus council report <run-folder>/verdict.json --html > <run-folder>/report.html`.
|
|
349
|
+
**`report.html` is the default final artifact to hand the user** — a self-contained,
|
|
350
|
+
shareable page. This emits the
|
|
313
351
|
adjudication matrix (finding × judge), the peers-only street-cred table, the
|
|
314
352
|
findings-by-tier groupings (Disputed-first), and the per-model + wave cost —
|
|
315
353
|
deterministic data only. Prefer it over hand-assembling the matrix; reserve
|
|
316
354
|
prose for the chair's synthesis and the decision log.
|
|
317
355
|
|
|
318
|
-
Tell the user exactly which files were written and where.
|
|
356
|
+
Tell the user exactly which files were written and where, leading with `report.html`, **and present the verdict inline in chat** — the chair's overall assessment (verbatim or lightly trimmed) plus the tier counts (Confirmed/Disputed/Contested/Singleton) and what was applied. Never hand over only file paths.
|
|
319
357
|
|
|
320
358
|
---
|
|
321
359
|
|
|
@@ -323,6 +361,8 @@ Tell the user exactly which files were written and where.
|
|
|
323
361
|
|
|
324
362
|
This stage updates `MODEL-NOTES.md` to make future runs better. **Nothing is written until the user approves a specific diff.**
|
|
325
363
|
|
|
364
|
+
The `MODEL-NOTES.md` **next to this file** is your machine-local run ledger: npm updates never overwrite it (it is installed only if missing), so lessons accumulate per machine. Durable, machine-independent lessons get folded back into the version-controlled copy in the amicus repo at release time (see the release checklist in `docs/publishing.md`).
|
|
365
|
+
|
|
326
366
|
**Reflect on this run.** Review the run for:
|
|
327
367
|
- Failures, near-misses, and mitigations that worked (poller traps, empty responses, timeout issues, briefing problems)
|
|
328
368
|
- Briefing wording that produced **richer or poorer** structured output than expected
|
|
@@ -432,6 +472,7 @@ Always **rank recommendations by fit**, state the trade-off for each option, and
|
|
|
432
472
|
— exact for `reported`, `~` for `estimated`, `?` for `unknown` — and never
|
|
433
473
|
invent a figure. Add a wave **total cost** row from the wave document's
|
|
434
474
|
`usage.cost` (`source: reported|estimated|mixed|unknown`). Any leg with no run doc → `durationMs: null`, `usage: null`.
|
|
475
|
+
- `report.html` — the same report rendered as a self-contained page (`amicus council report <verdict.json> --html`); the default artifact to share.
|
|
435
476
|
- Reviewed copy: `<stem>-reviewed.<ext>`, next to the source.
|
|
436
477
|
- Temp working files (`_tmp-*.md`: extracts, stage briefings, red-team brief, bundle, chair packet, proposed
|
|
437
478
|
MODEL-NOTES diff) live in the run folder and are cleaned up at the end of the run — the proposed-diff file
|
|
@@ -441,5 +482,5 @@ Always **rank recommendations by fit**, state the trade-off for each option, and
|
|
|
441
482
|
|
|
442
483
|
## Files
|
|
443
484
|
|
|
444
|
-
- `MODEL-NOTES.md` — operating rules, per-model qualitative quirks, cost guardrail, and structural-conformance notes. **Read it before Stage 0 (council selection and launch); update qualitative notes (with approval) in Stage 6.** Quantitative reliability data (runs, avg street-cred, confirm-rate, fact-error rate) comes from `amicus council stats`, not this file.
|
|
485
|
+
- `MODEL-NOTES.md` — operating rules, per-model qualitative quirks, cost guardrail, and structural-conformance notes. **Read it before Stage 0 (council selection and launch); update qualitative notes (with approval) in Stage 6.** Quantitative reliability data (runs, avg street-cred, confirm-rate, fact-error rate) comes from `amicus council stats`, not this file. This copy is machine-local (never overwritten on update); the shipped seed lives in the amicus repo and absorbs durable lessons at release time.
|
|
445
486
|
- `COUNCIL-DESIGN.md` — the design spec this skill implements (v3 + WS-3). Consult it if a mechanics question arises that the skill prose does not resolve.
|
package/skills/sidecar/SKILL.md
CHANGED
|
@@ -1,39 +1,52 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sidecar
|
|
3
|
+
argument-hint: "[model] [prompt...]"
|
|
3
4
|
description: >
|
|
4
|
-
Spawn
|
|
5
|
-
Grok, Mistral,
|
|
6
|
-
talk to, chat with,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
and argument-size caps). (4) NEVER use o3 or o3-pro unless the user explicitly asks for it by
|
|
17
|
-
name. These models are extremely expensive ($10-60+ per request). If the user asks for
|
|
18
|
-
o3, warn them about the cost before proceeding. Default to gemini for most tasks.
|
|
19
|
-
(5) When the user asks to query MULTIPLE LLMs simultaneously (e.g., "ask Gemini AND
|
|
20
|
-
ChatGPT", "compare Gemini vs GPT"), ALWAYS use --no-ui (headless) for all of them
|
|
21
|
-
unless the user explicitly requests interactive. Opening multiple Electron windows at
|
|
22
|
-
once is disruptive. Launch them all in parallel with run_in_background: true.
|
|
23
|
-
(6) When the SAME prompt should go to N models, use `amicus fanout --models a,b,c
|
|
24
|
-
--prompt-file <path> --json` (one headless wave, one JSON result) instead of N
|
|
25
|
-
separate start calls. Different prompts per model → separate parallel
|
|
26
|
-
`amicus start --no-ui` calls.
|
|
27
|
-
(7) For a SINGLE-model sidecar, DEFAULT to interactive — omit --no-ui so the
|
|
28
|
-
Electron UI opens and the user can watch, converse, and click Fold. Use --no-ui
|
|
29
|
-
for a single model only when the user asks for headless/autonomous, or for
|
|
30
|
-
unattended bulk automation. Interactive launches still use run_in_background: true.
|
|
5
|
+
Spawn a conversation with another LLM (Gemini, GPT, ChatGPT, Codex, o3, DeepSeek,
|
|
6
|
+
Qwen, Grok, Mistral, or Claude as a target) and fold the results back into your
|
|
7
|
+
context. TRIGGER when: the user asks to talk to, chat with, call, use, or spawn
|
|
8
|
+
another LLM or model; names any non-current model; wants parallel exploration or
|
|
9
|
+
a quick take from a different model; or says "sidecar", "fork", or "fold". This
|
|
10
|
+
is NOT the skill for structured multi-model review of provided material — requests
|
|
11
|
+
like "second opinion", "council review", or red-team/stress-test against criteria
|
|
12
|
+
belong to the second-opinion skill. Before running any amicus command, read the
|
|
13
|
+
Operating Rules section at the top of this document: background launches,
|
|
14
|
+
--prompt-file briefings, interactive vs headless defaults, fanout for same-prompt
|
|
15
|
+
multi-model runs, the o3/o3-pro cost warning, and the npx fallback when amicus is
|
|
16
|
+
not on PATH.
|
|
31
17
|
---
|
|
32
18
|
|
|
33
19
|
# Amicus: Multi-Model Sidecar Tool
|
|
34
20
|
|
|
35
21
|
Spawn parallel conversations with different LLMs (Gemini, GPT, ChatGPT, Codex, o3, etc.) and fold results back into your context.
|
|
36
22
|
|
|
23
|
+
## Slash invocation (`/amicus:sidecar <model> <prompt…>`)
|
|
24
|
+
|
|
25
|
+
When invoked as a slash command with arguments:
|
|
26
|
+
|
|
27
|
+
- First argument (the model): $1
|
|
28
|
+
- Full argument string: $ARGUMENTS
|
|
29
|
+
|
|
30
|
+
Treat $1 as the target model alias and the remainder of $ARGUMENTS as the prompt.
|
|
31
|
+
If $1 is not a plausible model alias (gemini, gemini-pro, gpt, codex, deepseek,
|
|
32
|
+
qwen, grok, mistral, glm, …), treat the ENTIRE argument string as the prompt and
|
|
33
|
+
default to gemini. Then apply the critical rules below exactly as for any other
|
|
34
|
+
invocation (run_in_background: true, --prompt-file for long briefings, interactive
|
|
35
|
+
by default for a single model, never o3/o3-pro unprompted).
|
|
36
|
+
|
|
37
|
+
## Operating Rules
|
|
38
|
+
|
|
39
|
+
These rules are mandatory for every amicus invocation in this skill:
|
|
40
|
+
|
|
41
|
+
1. **ALWAYS launch amicus CLI commands with the Bash tool's `run_in_background: true`.** Never run `amicus start/resume/continue` in the foreground.
|
|
42
|
+
2. **The fold summary returns on stdout** when the user clicks Fold in the GUI or the headless agent finishes. Use TaskOutput to read it when the background task completes.
|
|
43
|
+
3. **For long or multi-line briefings, write them to a temp file and pass `--prompt-file <path>`** (mutually exclusive with `--prompt`; avoids shell-quoting hazards and argument-size caps).
|
|
44
|
+
4. **NEVER use o3 or o3-pro unless the user explicitly asks for it by name.** These models are extremely expensive (\$10-60+ per request). If the user asks for o3, warn them about the cost before proceeding. Default to gemini for most tasks. The CLI enforces this in code: a built-in budget gate refuses any model above a per-$/Mtok threshold (o3-pro class) before launch unless you pass `--no-cost-gate`; `--max-cost <$>` sets a soft estimated-total ceiling. When a run is refused with `BUDGET_EXCEEDED`, relay the gate's message — don't silently retry with the flag.
|
|
45
|
+
5. **When the user asks to query MULTIPLE LLMs simultaneously** (e.g., "ask Gemini AND ChatGPT", "compare Gemini vs GPT"), ALWAYS use `--no-ui` (headless) for all of them unless the user explicitly requests interactive. Opening multiple Electron windows at once is disruptive. Launch them all in parallel with `run_in_background: true`.
|
|
46
|
+
6. **When the SAME prompt should go to N models, use `amicus fanout --models "a,b,c" --prompt-file <path> --json`** (one headless wave, one JSON result) instead of N separate start calls. Different prompts per model → separate parallel `amicus start --no-ui` calls.
|
|
47
|
+
7. **For a SINGLE-model sidecar, DEFAULT to interactive** — omit `--no-ui` so the Electron UI opens and the user can watch, converse, and click Fold. Use `--no-ui` for a single model only when the user asks for headless/autonomous, or for unattended bulk automation. Interactive launches still use `run_in_background: true`.
|
|
48
|
+
8. **If `amicus` is not on PATH** (typical for plugin-only installs), run every command in this skill as `npx -y amicus@latest <args>` (e.g. `npx -y amicus@latest start --model gemini --prompt "..."`), or use the MCP tools (`amicus_start`, `amicus_status`, `amicus_read`, …) instead. Do not conclude the tool is broken because `amicus` is not found.
|
|
49
|
+
|
|
37
50
|
## Installation
|
|
38
51
|
|
|
39
52
|
```bash
|
|
@@ -204,11 +217,11 @@ amicus start \
|
|
|
204
217
|
```
|
|
205
218
|
|
|
206
219
|
**Required:**
|
|
207
|
-
- `--
|
|
208
|
-
- `--prompt`: Detailed task description you generate
|
|
220
|
+
- `--prompt` (or `--prompt-file`): Detailed task description you generate
|
|
209
221
|
|
|
210
222
|
**Recommended:**
|
|
211
|
-
- `--
|
|
223
|
+
- `--model`: The model to use (see Models below). Omit it to use your configured default (`amicus setup`); the CLI errors only when neither an explicit model nor a configured default exists.
|
|
224
|
+
- `--session-id`: Your Claude Code session ID for accurate context passing
|
|
212
225
|
|
|
213
226
|
**Optional:**
|
|
214
227
|
- `--no-ui`: Run autonomously without GUI (for bulk tasks)
|
|
@@ -257,7 +270,7 @@ The CLI validates all inputs **before** launching the sidecar. Invalid inputs fa
|
|
|
257
270
|
|
|
258
271
|
| Input | Validation | Error Message |
|
|
259
272
|
|-------|------------|---------------|
|
|
260
|
-
| `--model` |
|
|
273
|
+
| `--model` | Optional — falls back to the config default. An explicit value must resolve to a known alias or `provider/model` | `Error: Unknown model alias '<x>' …` or `No model specified and no default configured. Run 'amicus setup' to set a default model.` |
|
|
261
274
|
| `--prompt` | Must be present and non-empty | `Error: --prompt is required` or `Error: --prompt cannot be empty or whitespace-only` |
|
|
262
275
|
| `--cwd` | If provided, directory must exist | `Error: --cwd path does not exist: <path>` |
|
|
263
276
|
| `--session-id` | If explicit ID provided (not 'current'), must exist | `Error: --session-id '<id>' not found. Use 'amicus list' to see available sessions or omit --session-id for most recent.` |
|
|
@@ -283,7 +296,7 @@ If you receive a validation error, fix the input and retry:
|
|
|
283
296
|
|
|
284
297
|
```bash
|
|
285
298
|
# Error: --session-id 'abc123' not found
|
|
286
|
-
# Fix: Use 'current' or omit --session
|
|
299
|
+
# Fix: Use 'current' or omit --session-id
|
|
287
300
|
amicus start --model gemini --prompt "Task" --session-id current
|
|
288
301
|
|
|
289
302
|
# Error: --agent cannot be empty
|
|
@@ -303,7 +316,7 @@ amicus start --model gemini --prompt "Task"
|
|
|
303
316
|
### Fan Out One Prompt to N Models
|
|
304
317
|
|
|
305
318
|
```bash
|
|
306
|
-
amicus fanout --models gemini,gpt,deepseek --prompt-file ./briefing.md --json
|
|
319
|
+
amicus fanout --models "gemini,gpt,deepseek" --prompt-file ./briefing.md --json
|
|
307
320
|
```
|
|
308
321
|
|
|
309
322
|
Runs the same prompt on every listed model in parallel (one shared engine server, headless),
|
|
@@ -404,7 +417,7 @@ amicus abort --all # stop every running session in this project
|
|
|
404
417
|
|
|
405
418
|
### Model Selection
|
|
406
419
|
|
|
407
|
-
Use short aliases (run `amicus
|
|
420
|
+
Use short aliases (run `amicus models` to see the live catalog, and `amicus models --check` to audit your aliases):
|
|
408
421
|
- `--model gemini` -- Google Gemini (fast, large context)
|
|
409
422
|
- `--model opus` -- Claude Opus (deep analysis)
|
|
410
423
|
- `--model gpt` -- OpenAI GPT
|
|
@@ -454,13 +467,13 @@ ls -lt ~/.claude/projects/-Users-john-myproject/*.jsonl | head -5
|
|
|
454
467
|
The most recently modified file is likely your current session. Extract the UUID from the filename.
|
|
455
468
|
|
|
456
469
|
**Session ID behavior:**
|
|
457
|
-
- **Omit `--session`** or
|
|
470
|
+
- **Omit `--session-id`** or pass `--session-id current`: Uses the most recently modified session file (less reliable if multiple sessions are active)
|
|
458
471
|
- **Explicit session ID** (`--session-id abc123-def456`): Must exist or the command fails immediately with: `Error: --session-id 'abc123-def456' not found`
|
|
459
472
|
|
|
460
473
|
**If you get a session not found error:**
|
|
461
474
|
1. List available sessions: `amicus list`
|
|
462
475
|
2. Use one of the listed session IDs, OR
|
|
463
|
-
3. Omit `--session` to use the most recent session
|
|
476
|
+
3. Omit `--session-id` to use the most recent session
|
|
464
477
|
|
|
465
478
|
---
|
|
466
479
|
|
|
@@ -849,7 +862,7 @@ Find the correct encoded path for your project. Remember that `/`, `\`, and `_`
|
|
|
849
862
|
|
|
850
863
|
### "Multiple active sessions detected"
|
|
851
864
|
|
|
852
|
-
You have multiple Claude Code windows. Pass `--session` explicitly:
|
|
865
|
+
You have multiple Claude Code windows. Pass `--session-id` explicitly:
|
|
853
866
|
```bash
|
|
854
867
|
ls -lt ~/.claude/projects/[your-path]/*.jsonl | head -3
|
|
855
868
|
# Pick the correct session UUID
|
|
@@ -912,7 +925,7 @@ amicus start --model gemini --prompt "Debug the auth issue in TokenManager.ts"
|
|
|
912
925
|
|
|
913
926
|
The explicit session ID doesn't exist. Either:
|
|
914
927
|
1. Use `amicus list` to find valid session IDs
|
|
915
|
-
2. Omit `--session` to use the most recent session
|
|
928
|
+
2. Omit `--session-id` to use the most recent session
|
|
916
929
|
3. Use `--session-id current` for automatic resolution
|
|
917
930
|
|
|
918
931
|
```bash
|
|
@@ -34,7 +34,7 @@ function realDeps() {
|
|
|
34
34
|
ensureNodeModulesBinInPath();
|
|
35
35
|
return hasOpencodeBinary();
|
|
36
36
|
},
|
|
37
|
-
getElectronPath: () => require('./sidecar/interactive').getElectronPath(),
|
|
37
|
+
getElectronPath: () => require('./sidecar/interactive-process').getElectronPath(),
|
|
38
38
|
// #56: self-heal primitive for `doctor --fix`. Pure probe (getElectronPath)
|
|
39
39
|
// stays separate; repair only runs when fix is requested.
|
|
40
40
|
repairElectron: (opts) => require('./sidecar/electron-install').repairElectron(opts),
|
package/src/headless.js
CHANGED
|
@@ -463,6 +463,7 @@ async function runHeadless(model, systemPrompt, userMessage, taskId, project, ti
|
|
|
463
463
|
const s = (statusData && statusData.type) ? statusData : (statusData && statusData[sessionId]);
|
|
464
464
|
if (s && s.type === 'idle') {
|
|
465
465
|
logger.debug('Session reported idle by SDK — completing', { sessionId });
|
|
466
|
+
completed = true;
|
|
466
467
|
break;
|
|
467
468
|
}
|
|
468
469
|
} catch (statusErr) {
|
|
@@ -493,6 +494,7 @@ async function runHeadless(model, systemPrompt, userMessage, taskId, project, ti
|
|
|
493
494
|
const threshold = assistantFinished ? stableFinishedPolls : stableIdlePolls;
|
|
494
495
|
if (stablePolls >= threshold) {
|
|
495
496
|
logger.debug('Session appears complete (idle)', { stablePolls, assistantFinished });
|
|
497
|
+
completed = true;
|
|
496
498
|
break;
|
|
497
499
|
}
|
|
498
500
|
} else {
|