amicus 4.4.1 → 4.5.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 -1
- package/CHANGELOG.md +130 -0
- package/README.md +15 -2
- package/bin/amicus.js +10 -0
- package/docs/ROADMAP.md +36 -10
- package/docs/configuration.md +24 -0
- package/docs/council.md +59 -0
- package/docs/schemas.md +1 -0
- package/docs/usage.md +151 -1
- package/electron/workspace-ui/workspace-app.js +39 -17
- package/electron/workspace-ui/workspace-panels.js +76 -18
- package/electron/workspace-ui/workspace-render.js +10 -0
- package/package.json +1 -1
- package/schemas/council-run-live.schema.json +1 -1
- package/schemas/council-run.schema.json +14 -0
- package/schemas/error.schema.json +1 -1
- package/schemas/event.schema.json +1 -1
- package/schemas/pack.schema.json +30 -0
- package/schemas/progress.schema.json +1 -1
- package/schemas/run-live.schema.json +1 -1
- package/schemas/run.schema.json +2 -1
- package/schemas/wave-live.schema.json +1 -1
- package/schemas/wave.schema.json +2 -1
- package/skills/second-opinion/SKILL.md +5 -0
- package/src/cli-handlers-council-run.js +51 -8
- package/src/cli-handlers-pack.js +238 -0
- package/src/cli-handlers-run.js +36 -8
- package/src/cli-handlers-template.js +53 -0
- package/src/cli.js +64 -3
- package/src/council/findings.js +4 -41
- package/src/council/presets-cli.js +23 -11
- package/src/council/run-stages.js +12 -9
- package/src/council/run-state.js +17 -0
- package/src/council/run.js +1 -1
- package/src/headless.js +18 -14
- package/src/mcp-council-run.js +108 -4
- package/src/mcp-server.js +203 -7
- package/src/mcp-tools.js +15 -5
- package/src/pack/pack-cli.js +38 -0
- package/src/pack/pack-forward.js +96 -0
- package/src/pack/pack-resolve.js +297 -0
- package/src/pack/pack-store.js +130 -0
- package/src/pack/pack-validate.js +113 -0
- package/src/sidecar/fanout.js +21 -4
- package/src/sidecar/progress.js +34 -0
- package/src/sidecar/start.js +5 -4
- package/src/sidecar/workspace-auto-open.js +69 -0
- package/src/sidecar/workspace-window.js +46 -1
- package/src/template/apply.js +88 -0
- package/src/template/render.js +86 -0
- package/src/template/store.js +106 -0
- package/src/utils/config.js +65 -25
- package/src/utils/error-doc.js +5 -0
- package/src/utils/result-schema-rebuild.js +1 -0
- package/src/utils/result-schema.js +8 -2
- package/src/workspace/artifact-guard.js +44 -6
- package/src/workspace/run-detail.js +6 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amicus",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.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
|
@@ -3,6 +3,136 @@
|
|
|
3
3
|
All notable changes to Amicus are documented here. Format follows
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow semver.
|
|
5
5
|
|
|
6
|
+
## [4.5.0] - 2026-07-28
|
|
7
|
+
|
|
8
|
+
"Save and share your councils" — complex run configurations become one command, repeatable and
|
|
9
|
+
shareable, and the flagship Council Workspace stops being opt-in on its best client.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Policy packs — save a full run configuration and invoke it by name.** `amicus pack save <name>
|
|
14
|
+
--kind council|fanout|solo [flags]` (or `--from-run <id>`, which captures an existing council
|
|
15
|
+
run / fanout wave / solo session instead of typing flags) writes one JSON file per pack to
|
|
16
|
+
`~/.config/amicus/packs/<name>.json`; `pack list` / `pack show` / `pack rm` manage them. `--pack
|
|
17
|
+
<name|path>` on `amicus start` / `fanout` / `council run` — and the new `pack` param on the
|
|
18
|
+
`amicus_start` / `amicus_fanout` / `amicus_council_run` MCP tools — loads a pack's bench,
|
|
19
|
+
chair/critic/lenses, options, and briefing template as this run's defaults. **Explicit flags
|
|
20
|
+
always override the pack's values, and the pack is recorded either way** — `pack: {name,
|
|
21
|
+
version, hash, source}` lands on the resulting session `metadata.json`, wave `metadata.json` /
|
|
22
|
+
`wave.json`, or council `run.json`. Precedence throughout: **flag > pack > config default >
|
|
23
|
+
built-in default**. A pack is validated on save (hard-fail — `PACK_INVALID` — with any
|
|
24
|
+
non-fatal warnings printed to stderr) and again whenever it's used to launch a run; `pack show`
|
|
25
|
+
never fails on an invalid pack, only reports what's wrong with it; `pack show` and `pack rm` both
|
|
26
|
+
return `PACK_NOT_FOUND` for a missing pack. New `schemas/pack.schema.json`.
|
|
27
|
+
- **MCP pack semantics.** Over MCP, `pack` resolves entirely **in-process**, on the same call that
|
|
28
|
+
reads it — a resolved pack is never forwarded as `--pack` to a spawned child. Two knobs get
|
|
29
|
+
special-cased handling for CLI parity: a pack's `options.maxCost` and `briefing.template` have no
|
|
30
|
+
MCP schema param of their own on `amicus_start`/`amicus_fanout`, but they still apply — forwarded
|
|
31
|
+
to the spawned CLI child's argv as `--max-cost`/`--template` (`amicus_fanout` always spawns;
|
|
32
|
+
`amicus_start`'s spawn-fallback path does the same), or, on `amicus_start`'s in-process
|
|
33
|
+
shared-server path, applied via the same budget-gate/template-render code the CLI itself uses,
|
|
34
|
+
before any session is created — so a shared pack's spend cap and briefing template never silently
|
|
35
|
+
vanish over MCP. (`amicus_council_run` already has real MCP params for both.) Any *other* pack
|
|
36
|
+
knob with no destination in a tool's own MCP input schema is never silently dropped either: it
|
|
37
|
+
surfaces as an explicit `Notice: pack '<name>' sets <key>, which <tool> does not support over
|
|
38
|
+
MCP — ignored.` content block, naming the pack's own camelCase option key (e.g. `contextTurns`,
|
|
39
|
+
never the CLI's `context-turns`). Concretely, `amicus_fanout` has no MCP destination for
|
|
40
|
+
`options.contextTurns` / `options.contextMaxTokens` (both notice); `amicus_start` has real params
|
|
41
|
+
for both, so neither does.
|
|
42
|
+
- **Council packs do not accept `agent`/`thinking`/`summaryLength`.** They were inert on every
|
|
43
|
+
surface — no council code path, CLI or MCP, ever reads a pack-filled one; the engine hardcodes
|
|
44
|
+
agent `Plan`/summaryLength `verbose` regardless of what a pack says — so `KIND_OPTIONS.council`
|
|
45
|
+
never accepted them; a council pack that sets one fails `pack save` (`PACK_INVALID`), naming the
|
|
46
|
+
offending key. They remain valid, and functional, on `fanout`/`solo` packs.
|
|
47
|
+
- **Briefing templates.** `amicus template list|show`, plus `--template <name|path>` / `--artifact
|
|
48
|
+
<file>` / `--var <k=v>` (repeatable) on `start` / `fanout` / `council run`, render a
|
|
49
|
+
`{{variable}}` briefing before it's sent. Templates are Markdown files in
|
|
50
|
+
`~/.config/amicus/templates/` — a same-named user file shadows a built-in, the same precedent
|
|
51
|
+
saved councils already use — and v4.5 ships one built-in, `review`. Known variables: `{{prompt}}`,
|
|
52
|
+
`{{artifact}}`, `{{artifact_path}}`, `{{date}}`, `{{project}}`, `{{var.<key>}}`. Rendering is
|
|
53
|
+
strict by design: an unknown variable, a slot with no data behind it, or data passed with no slot
|
|
54
|
+
to receive it are all hard errors (`TEMPLATE_RENDER`) rather than a silently dropped value. MCP
|
|
55
|
+
has no `template` param of its own on any of the three run tools — a pack's `briefing.template` is
|
|
56
|
+
the only way a template reaches an MCP-invoked run.
|
|
57
|
+
- **The Council Workspace auto-opens on `amicus_council_run` from Claude Code (local).** When the
|
|
58
|
+
MCP tool `amicus_council_run` is invoked from Claude Code (local), the same Electron window that
|
|
59
|
+
`amicus watch <runId> --ui` has always opened by hand now launches automatically, detached, right
|
|
60
|
+
after the run starts — no more separate `--ui` call to see the flagship v4.4 surface. The CLI
|
|
61
|
+
`amicus council run` is unaffected (there is no MCP client to detect on that path). Decision
|
|
62
|
+
order: an explicit `ui: false` param beats everything; the hard guards (Electron not installed —
|
|
63
|
+
this path never installs it; Linux with no `DISPLAY`) beat even an explicit `ui: true`; `ui: true`
|
|
64
|
+
then overrides both the new `workspace.autoOpen` config key and the client check; short of an
|
|
65
|
+
explicit param, `workspace.autoOpen === false` disables it, and any client other than Claude Code
|
|
66
|
+
(local) simply doesn't auto-open. New `workspace.autoOpen` config key (`config.json`, default on
|
|
67
|
+
— only an explicit `false` turns it off). The tool response carries `workspaceOpened: boolean`
|
|
68
|
+
and, only when it did not open, `workspaceOpenReason` (`param-suppressed`, `electron-absent`,
|
|
69
|
+
`no-display`, `config-disabled`, `client-not-code-local`, or a `spawn-failed:` /
|
|
70
|
+
`auto-open-failed:` detail).
|
|
71
|
+
|
|
72
|
+
### Fixed
|
|
73
|
+
|
|
74
|
+
- **A failed council seat no longer renders as perpetually live.** `createSession`'s early return
|
|
75
|
+
under a shared server bypassed the terminal `progress.json` write, leaving a stage marked
|
|
76
|
+
in-progress in `progress.json` after `metadata.json` had already recorded the error. The
|
|
77
|
+
terminal-write logic is now one shared helper (`writeTerminalProgressSafe`), called at all three
|
|
78
|
+
early-return sites plus the original one, so the paths can no longer drift apart.
|
|
79
|
+
- **Collided artifact names no longer misattribute one model's prose to another's.** Two bench
|
|
80
|
+
models whose sanitized filenames collide (e.g. `vendor/a` and `vendor?a` both → `vendor-a`) share
|
|
81
|
+
one physical file on disk; the Council Workspace compounded that with a rendering bug that showed
|
|
82
|
+
the first model's review/judge prose under the *second* model's panel — including, in a `--debate`
|
|
83
|
+
run, the rebuttal/re-vote drill-in. Collided names now get a deterministic suffix (`~2`, `~3`,
|
|
84
|
+
…), and every Workspace file lookup consults the resulting name map instead of recomputing a bare
|
|
85
|
+
sanitized name — the second colliding model's row is now correctly dropped by the existing
|
|
86
|
+
presence filter (its suffixed name was never physically written) instead of showing the wrong
|
|
87
|
+
model's text, and a run-integrity banner names the collision so the gap reads as a known
|
|
88
|
+
limitation rather than missing data.
|
|
89
|
+
- **A blind-mode toggle no longer collapses every open prose panel or repaints twice.** Flipping
|
|
90
|
+
Blind mid-run used to unconditionally recompute the blind default, forcing one paint with the
|
|
91
|
+
wrong value, a restore, and a second compensating repaint — and reset every lazy-loaded panel's
|
|
92
|
+
open/loaded state along the way, closing whatever the user had expanded. Blind state and
|
|
93
|
+
lazy-panel state now key off whether the run — and, separately, its status — actually changed
|
|
94
|
+
since the last render, so a same-run toggle updates in place and paints once without closing any
|
|
95
|
+
open panel; a run reaching its terminal status still recomputes the blind default and auto-reveals
|
|
96
|
+
exactly as before.
|
|
97
|
+
- **`renderSeats` now reorders rows to match the composed run document.** The keyed seat-table
|
|
98
|
+
update already added and removed rows on change but never moved one, so the table's row order
|
|
99
|
+
froze at first render — visibly wrong once a repair solo or a new wave changed the underlying leg
|
|
100
|
+
order mid-run. Existing rows are now moved into place at the end of every render pass.
|
|
101
|
+
- **`amicus council show` no longer reports a catalog-delisted bench member as healthy, and a
|
|
102
|
+
dropped member is no longer invisible to scripted/MCP callers.** `show`'s resolved/dropped split
|
|
103
|
+
checked only whether a member's alias mapped to *some* id, never whether that id was still in
|
|
104
|
+
the cached catalog — so a preset member whose alias now resolves to a catalog-absent id (e.g. a
|
|
105
|
+
direct-vendor route with no matching cached row) read as fully healthy in `show` while the real
|
|
106
|
+
run path (`resolveCouncilMembers`) silently dropped it on every actual run. `show` now reuses
|
|
107
|
+
that exact check — alias resolution, then catalog membership, with the same local-provider/
|
|
108
|
+
offline-catalog rule that a catalog it cannot consult never blocks a member, only a non-empty
|
|
109
|
+
catalog that omits it does. Separately, `council run --json` already suppressed the human-mode
|
|
110
|
+
`Notice: dropped unavailable council member(s): ...` line, and `run.json` carried no field for
|
|
111
|
+
it at all — a JSON-mode or MCP caller had zero signal a bench member vanished short of diffing
|
|
112
|
+
`bench` against the preset's nominal member list. `run.json` now carries an additive
|
|
113
|
+
`droppedMembers: [{member, reason}]` array (present only when at least one member was actually
|
|
114
|
+
dropped), reaching the `--json` envelope and the `amicus_council_run` MCP response body for
|
|
115
|
+
free. Resolution behavior itself — which members run, exit codes, spend — is unchanged; this is
|
|
116
|
+
observability only.
|
|
117
|
+
|
|
118
|
+
### Changed
|
|
119
|
+
|
|
120
|
+
- **`amicus_start` / `amicus_fanout`'s MCP schemas no longer declare a JSON-Schema `default` for
|
|
121
|
+
`agent`, `noUi`, or `includeContext`.** Client-visible metadata only — nothing behavioral: the
|
|
122
|
+
defaults are still applied at the same read sites they always were, and are still stated in each
|
|
123
|
+
param's own description. (`amicus_resume` / `amicus_continue`'s `noUi` keep their schema-level
|
|
124
|
+
default; they were not part of this pass.)
|
|
125
|
+
|
|
126
|
+
### Removed
|
|
127
|
+
|
|
128
|
+
- **The inert `repairCanHonorContract` guard.** 4.4.1's empty-findings acceptance flipped this
|
|
129
|
+
predicate permanently true by its own design, so `run-stages.js`'s `repairable &&` check could no
|
|
130
|
+
longer short-circuit on it and no test failed if the function were deleted outright — a
|
|
131
|
+
silent-deletion hazard that would otherwise re-arm the deadlock it used to guard against the day
|
|
132
|
+
empty-set validation tightens again. Removed deliberately instead: the underlying reasoning moved
|
|
133
|
+
to its call site, and the zero-findings regression test's comment now explains why the case it
|
|
134
|
+
covers still holds without the guard.
|
|
135
|
+
|
|
6
136
|
## [4.4.1] - 2026-07-27
|
|
7
137
|
|
|
8
138
|
A fast-follow patch on 4.4.0. Every item is a correction to something already shipped, and almost all of it was measured against real paid council runs rather than reasoned about — the five gate councils that certified the Council Workspace are also what found these. Five behaviour changes ride along and are called out under **Changed**, because a user upgrading a patch should not discover them by surprise.
|
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ One install delivers six things that work together:
|
|
|
52
52
|
- **The `amicus` CLI (with an `am` alias) and an MCP server.** The engine underneath both skills: launches sessions, shares context, runs parallel waves, and exposes the same surface to Claude as MCP tools.
|
|
53
53
|
- **A self-updating model catalog.** Aliases and validation resolve against a live catalog fetched from provider APIs (cached locally), so model names stay current without a hard-coded table.
|
|
54
54
|
- **Observability.** `amicus watch <id>` renders any live or finished run (fan-out or council) from any terminal; `--follow` streams milestones as they happen; `--on-complete` fires a hook when a run lands; `--retry-failed` plus opt-in cheaper-model fallbacks recover dead legs without relaunching the whole wave; `amicus spend` answers "what did this cost, and where" with per-run attribution.
|
|
55
|
-
- **Council Workspace.** `amicus watch <runId> --ui`: a window that shows a council *thinking* — live seats, the anonymized judge packet, the adjudication matrix, dissent drill-in, chair verdict, and cost-by-seat — for both live and historical runs.
|
|
55
|
+
- **Council Workspace.** `amicus watch <runId> --ui`: a window that shows a council *thinking* — live seats, the anonymized judge packet, the adjudication matrix, dissent drill-in, chair verdict, and cost-by-seat — for both live and historical runs. It also **auto-opens** on an MCP-invoked council run from Claude Code (local), so you no longer have to remember the flag (see [The Council](#the-council)).
|
|
56
56
|
|
|
57
57
|
Claude is the orchestrator. The council and chat skills run *on top of* the engine; you talk to Claude, and Claude drives Amicus.
|
|
58
58
|
|
|
@@ -267,6 +267,17 @@ The `amicus_fanout` MCP tool takes the same `council` parameter, and the `second
|
|
|
267
267
|
|
|
268
268
|
**Council presets.** Save your own named member lists with `amicus council save <name> --models a,b,c` (≥2 resolvable aliases or `provider/model` IDs), then run them with `--council <name>` anywhere a council runs. `amicus council list` shows saved presets plus three built-in benches that work with no setup at all — `free` (the same zero-cost dynamic pick described above, used when you haven't seeded `councils.free`), `budget` (cheap workhorses, one per vendor family), and `frontier` (premium flagships, one per vendor family). `amicus council show <name>` resolves any of them (saved or built-in) and reports which members are currently usable. A saved council always shadows a built-in of the same name — exactly how the wizard's `councils.free` seeding already worked.
|
|
269
269
|
|
|
270
|
+
**Policy packs (v4.5).** A council preset only saves the bench. A **pack** saves the whole run — bench, chair, critic/lenses, cost/timeout options, and a briefing template — as one named, shareable JSON file:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
amicus pack save review-bench --kind council --bench gemini,deepseek,gpt --chair opus --timeout 20 --max-cost 2
|
|
274
|
+
amicus council run --pack review-bench --prompt-file plan.md --json
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Any flag you also type on that second line overrides just that value — a pack only fills in what you didn't say explicitly, and it's recorded on the run either way. Packs work the same way on `fanout`/`start` and on the `amicus_fanout`/`amicus_start`/`amicus_council_run` MCP tools. `amicus pack list`/`show`/`rm` manage them, and `--from-run <id>` builds one from a run you already liked instead of typing flags at all. Full reference: [docs/usage.md § Policy packs](./docs/usage.md#policy-packs).
|
|
278
|
+
|
|
279
|
+
**Briefing templates (v4.5).** `--template <name> --artifact <file>` (plus repeatable `--var k=v`) renders a `{{prompt}}`/`{{artifact}}`-style Markdown template before it's sent, on `start`/`fanout`/`council run` alike — templates live in `~/.config/amicus/templates/`, and a pack's `briefing.template` is how one reaches an MCP-invoked run (MCP has no template param of its own). `amicus template list|show` manage them; v4.5 ships one built-in, `review`. Full reference: [docs/usage.md § Briefing templates](./docs/usage.md#briefing-templates).
|
|
280
|
+
|
|
270
281
|
---
|
|
271
282
|
|
|
272
283
|
## The parallel window
|
|
@@ -323,6 +334,8 @@ amicus update
|
|
|
323
334
|
| `amicus provider` | Add/list/test/remove local, OpenAI-compatible providers (LM Studio, Ollama, vLLM) — configured with `--preset` or `--url`, at **$0** marginal cost (`--json` on every subcommand). |
|
|
324
335
|
| `amicus council` | Council math: `tally <input.json>` (deterministic tiers + ledger append), `stats` (reviewer reliability), `report <verdict.json> [--md\|--html]`, `validate <file>` (findings-block check, exit 0/2/1), `verdict <tally.json> [--decisions <d.json>] [-o <out.json>]` (build + write verdict.json). Presets: `save <name> --models a,b,c`, `list [--json]`, `show <name> [--json]` — see [The Council](#the-council) for the built-in `free`/`budget`/`frontier` benches. |
|
|
325
336
|
| `amicus council run` | The headless council engine: Stage-1 reviews → anonymized cross-review → deterministic tally → non-Claude chair verdict, in one command with no Claude runtime. Add `--debate` for a Stage-2.5 rebuttal round (raisers defend/amend/withdraw, disputing judges re-vote) and `--claude-review <file>` to enter Claude's own review as judged review N+1. Writes a run directory with `verdict.json` (including `overallVerdict`) and `report.html` — see [docs/council.md](./docs/council.md#amicus-council-run). |
|
|
337
|
+
| `amicus pack` | Save a full run configuration — bench, chair/critic/lenses, options, briefing template — and invoke it by name: `save <name> --kind council\|fanout\|solo [flags]` (or `--from-run <id>`), `list`, `show <name>`, `rm <name>`. `--pack <name>` on `start`/`fanout`/`council run` loads one; explicit flags always override it. See [docs/usage.md § Policy packs](./docs/usage.md#policy-packs). |
|
|
338
|
+
| `amicus template` | `list`/`show <name>` a briefing template. `--template <name> [--artifact <file>] [--var k=v]` on `start`/`fanout`/`council run` renders one before the briefing is sent. See [docs/usage.md § Briefing templates](./docs/usage.md#briefing-templates). |
|
|
326
339
|
| `amicus abort` | Abort a running session (or `--all`). |
|
|
327
340
|
| `amicus setup` | Configure default model, API keys, and aliases. |
|
|
328
341
|
| `amicus update` | Update to the latest version. |
|
|
@@ -351,7 +364,7 @@ $ amicus status demo123 --json
|
|
|
351
364
|
"taskId": "demo123",
|
|
352
365
|
"status": "complete",
|
|
353
366
|
"elapsed": "5m 0s",
|
|
354
|
-
"version": "4.
|
|
367
|
+
"version": "4.5.0",
|
|
355
368
|
"model": "google/gemini-2.5-flash",
|
|
356
369
|
"phase": "terminal"
|
|
357
370
|
}
|
package/bin/amicus.js
CHANGED
|
@@ -152,6 +152,16 @@ async function main() {
|
|
|
152
152
|
case 'update':
|
|
153
153
|
await handleUpdate();
|
|
154
154
|
break;
|
|
155
|
+
case 'template': {
|
|
156
|
+
const { handleTemplate } = require('../src/cli-handlers-template');
|
|
157
|
+
exitCode = await handleTemplate(args);
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
case 'pack': {
|
|
161
|
+
const { handlePack } = require('../src/cli-handlers-pack');
|
|
162
|
+
exitCode = await handlePack(args);
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
155
165
|
default: {
|
|
156
166
|
console.error(`Unknown command: ${command}`);
|
|
157
167
|
// suggestCommand honors a cap-3 contract (up to 3 candidates, closest
|
package/docs/ROADMAP.md
CHANGED
|
@@ -11,7 +11,9 @@ Amicus is at **v4.4.1** (2026-07-27), the fast-follow patch on v4.4.0 (tagged 20
|
|
|
11
11
|
4.x rev below leads with the benefit, not the plumbing.
|
|
12
12
|
|
|
13
13
|
**Status:** v4.0 through **v4.4.1** have **shipped** — everything down to the v4.5 heading is a
|
|
14
|
-
record of what landed, not a plan. **v4.5 (
|
|
14
|
+
record of what landed, not a plan. **v4.5 (packs + templates + auto-open) is the next rev**, with
|
|
15
|
+
**v4.6 (composition + tagging + GUI ergonomics)** behind it — the former combined v4.5 scope,
|
|
16
|
+
split 2026-07-27 (design: `docs/superpowers/specs/2026-07-27-v4.5-save-and-share-design.md`). v5.0
|
|
15
17
|
remains forward-looking.
|
|
16
18
|
|
|
17
19
|
> 📁 **Reading this from an npm install?** Some references below point at working documents that
|
|
@@ -85,18 +87,38 @@ and a review that honestly finds nothing stops being an error.
|
|
|
85
87
|
> repo's working notes (`.superpowers/sdd/v441/backlog-and-proposal.md`, local-only) and in the
|
|
86
88
|
> repo's root `BACKLOG.md` — neither ships in the npm package; see the note at the top.
|
|
87
89
|
|
|
88
|
-
## v4.5 — "Save
|
|
89
|
-
**Benefit:** complex councils become one-command, repeatable, and
|
|
90
|
+
## v4.5 — "Save and share your councils" *(scope split 2026-07-27 — composition moved to v4.6)*
|
|
91
|
+
**Benefit:** complex councils become one-command, repeatable, and shareable — and the flagship GUI
|
|
92
|
+
stops hiding. Design: `docs/superpowers/specs/2026-07-27-v4.5-save-and-share-design.md`.
|
|
90
93
|
- **★ Auto-open the Council Workspace on a council run (Christian, 2026-07-26)** — when a council is
|
|
91
|
-
invoked from Claude
|
|
94
|
+
invoked from Claude Code (local) and Electron is already present, the Workspace window opens by
|
|
92
95
|
default instead of requiring a separate `amicus watch <runId> --ui`. Today the GUI is opt-in and
|
|
93
96
|
discoverable only from `watch --help`, so the flagship v4.4 surface goes unseen on the very
|
|
94
97
|
client best able to show it. *(S–M; the pieces exist — see the design notes below.)*
|
|
95
98
|
- **Council policy packs + full run-profiles** (bench + lenses + options + briefing template, invoke by name) — B7/F5 *(M)*
|
|
96
|
-
- **
|
|
97
|
-
|
|
98
|
-
- **
|
|
99
|
-
|
|
99
|
+
- **Briefing templates + library** (F9) *(S–M)* — the foundation packs reference; the `{{input}}`
|
|
100
|
+
chaining variable and the `critique`/`refine` built-ins arrive with v4.6
|
|
101
|
+
- **Ride-along fixes** — FR-1 (a failed council seat can render perpetually live), the FR-2 ruling,
|
|
102
|
+
RN-1/RN-5/RN-11 Workspace renderer fixes, TST-3 real-CDP abort pass *(S each; dispositions for
|
|
103
|
+
all 17 open items are tabled in the design doc's §8)*
|
|
104
|
+
- **README + docs update** — policy packs, the template library, and auto-open in `README.md` and `docs/` *(S)*
|
|
105
|
+
> Why here: save/share velocity multipliers that only pay off once councils are a command (v4.0)
|
|
106
|
+
> and observable (v4.3/v4.4); auto-open makes the v4.4 surface discoverable on its best client.
|
|
107
|
+
|
|
108
|
+
## v4.6 — "Compose your councils" *(specced after v4.5 ships — anti-rot rule)*
|
|
109
|
+
**Benefit:** councils chain — generate → critique → refine with no manual copy-paste — and history
|
|
110
|
+
becomes navigable.
|
|
111
|
+
- **Composable/chained waves** (`--input-from <id>` / `--prompt-file -` pipe + per-source digests) —
|
|
112
|
+
F6 *(M)* — brings the `{{input}}` template variable + the `critique`/`refine` built-ins
|
|
113
|
+
- **Session/wave tagging + `--search` + grouped history** (F8) *(S–M)*
|
|
114
|
+
- **GUI power ergonomics** (F10: focus-follows fold hotkey, distinguishable window titles, tiling
|
|
115
|
+
presets) *(S each)*
|
|
116
|
+
- Deferred-item candidates per the v4.5 design doc's §8: RN-2, TST-1/TST-2, REL-2, CA-4, LC-5,
|
|
117
|
+
remainder of TST-7
|
|
118
|
+
- **README + docs update** *(S)*
|
|
119
|
+
> The 2026-07-19 combined spec (`2026-07-19-v4.5-policy-packs-composition-design.md`) holds the
|
|
120
|
+
> approved chaining/tagging/F10 design detail and is the primary input to the v4.6 brainstorm; it
|
|
121
|
+
> is NOT executed as-written — v4.6 gets its own spec + fresh plan once v4.5 ships.
|
|
100
122
|
|
|
101
123
|
### Deferred out of v4.4.1 into v4.5 (2026-07-27)
|
|
102
124
|
|
|
@@ -107,6 +129,10 @@ disposition that put them here in `.superpowers/sdd/v441/backlog-and-proposal.md
|
|
|
107
129
|
those notes, read that backlog's Appendix A (settled decisions) and Appendix B (known false
|
|
108
130
|
positives) before re-filing anything from this list.**
|
|
109
131
|
|
|
132
|
+
**Disposition update (2026-07-27):** every item below (plus FR-1/2/3 from `BACKLOG.md`) now carries
|
|
133
|
+
a proposed disposition — v4.5 ride-along / v4.6 / backlog — tabled for ruling in §8 of
|
|
134
|
+
`docs/superpowers/specs/2026-07-27-v4.5-save-and-share-design.md`.
|
|
135
|
+
|
|
110
136
|
| ID | What | Why not 4.4.1 |
|
|
111
137
|
|---|---|---|
|
|
112
138
|
| **CA-4** | `tally.json`'s `runStats` omits Stage-2 judges, repair solos and failed chair attempts (5 rows for 11 real legs in `wsgate04`) | `M` — a schema question, not a fix |
|
|
@@ -154,9 +180,9 @@ rather than re-deriving them.
|
|
|
154
180
|
| Is Electron usable | `src/sidecar/electron-install.js` `isElectronUsable` / `resolveElectronBinary` |
|
|
155
181
|
| Current entry point | `amicus watch <runId> --ui` (`src/cli-handlers-watch.js:87`) |
|
|
156
182
|
|
|
157
|
-
**"Claude
|
|
183
|
+
**"Claude Code (local)" maps to `code-local`.** ⚠️ But `detectClient` reads the MCP client's
|
|
158
184
|
`getClientVersion().name`, so it **only works on the MCP path** — `amicus_council_run`, which is
|
|
159
|
-
exactly the Claude
|
|
185
|
+
exactly the Claude Code (local) case. A `council run` typed into a terminal has no MCP server, so
|
|
160
186
|
detection there falls through to the env override or the `cowork` status-quo default. Do not build
|
|
161
187
|
this on the CLI path expecting detection to work; either gate it on the MCP entry point or thread
|
|
162
188
|
an explicit client tag through. (Related: the Phase 12 backlog item about persisting the client tag
|
package/docs/configuration.md
CHANGED
|
@@ -220,6 +220,8 @@ Everything lives under `~/.config/amicus/` (`getConfigDir()` in `src/utils/confi
|
|
|
220
220
|
| `sessions-index.json` | `session-index.js` (`recordSession`, written at session start) | A **global** map of `taskId → project path`, consulted only when a per-project session lookup misses (e.g. an MCP server whose cwd differs from where the session was created). Navigation aid only, never authoritative — a corrupt index degrades to "no entry," never a crash. |
|
|
221
221
|
| `council-ledger.jsonl` | `src/council/ledger.js` (`appendRun`), on every `council tally` | One row per council model per run — findings raised, severity breakdown, street-cred, conformance. Read back by `amicus council stats`. |
|
|
222
222
|
| `spend-ledger.jsonl` | `src/utils/spend-ledger.js` (`appendSpend`), new in Phase 16 | One row per completed run/leg — tokens + resolved cost. Read back by `amicus spend` for the cross-run rollup. Append is best-effort and can never fail the run it's recording; safe to delete (starts fresh, loses history only). |
|
|
223
|
+
| `packs/<name>.json` (v4.5) | `amicus pack save` (`src/pack/pack-store.js`) | One JSON file per saved policy pack — bench/model, chair/critic/lenses, options, and a briefing-template *reference*. Peer directory of `templates/` below. Safe to inspect, hand-edit, or delete individually; see [Policy packs](./usage.md#policy-packs). |
|
|
224
|
+
| `templates/<name>.md` (v4.5) | You, by hand (your editor is the manager) | User-authored briefing templates; a file here shadows a built-in of the same name. Amicus itself never writes into this directory — there is no `template save`/`rm`. See [Briefing templates](./usage.md#briefing-templates). |
|
|
223
225
|
|
|
224
226
|
**Tmp-file pattern.** Several writers (`model-catalog.json`, `sessions-index.json`, session
|
|
225
227
|
metadata) use an atomic write: a temp file named `.<target>.<pid>.<random>.tmp` is written
|
|
@@ -328,6 +330,16 @@ level includes everything above it.
|
|
|
328
330
|
"apiKeyEnv": "VLLM_LAB_API_KEY",
|
|
329
331
|
"pricing": { "prompt": 0.0000005, "completion": 0.0000015 }
|
|
330
332
|
}
|
|
333
|
+
},
|
|
334
|
+
|
|
335
|
+
// v4.5: opt out of auto-opening the Council Workspace window on an
|
|
336
|
+
// MCP-invoked `amicus_council_run` from Claude Code (local). Absent, null,
|
|
337
|
+
// or anything other than a literal `false` leaves auto-open ON — only an
|
|
338
|
+
// explicit `false` here disables it. See docs/council.md's Council
|
|
339
|
+
// Workspace section for the full decision order (the `ui` MCP param and
|
|
340
|
+
// the hard guards both take precedence over this key either way).
|
|
341
|
+
"workspace": {
|
|
342
|
+
"autoOpen": false
|
|
331
343
|
}
|
|
332
344
|
}
|
|
333
345
|
```
|
|
@@ -337,6 +349,18 @@ A provider id may not shadow one of the five built-in vendors — `openrouter`,
|
|
|
337
349
|
An alias whose value is missing, `null`, or not a string is stripped on the next `saveConfig()`
|
|
338
350
|
call, with a notice printed to stderr — `config.json` never accumulates dead aliases silently.
|
|
339
351
|
|
|
352
|
+
**Policy pack precedence.** A saved [policy pack](./usage.md#policy-packs) sits between your flags
|
|
353
|
+
and whatever this repo's existing default logic already was for a given knob — the resolution
|
|
354
|
+
order everywhere a pack applies is **flag > pack > config default > built-in default.** A pack only
|
|
355
|
+
fills in a value you did not type explicitly on the command line; everything below that layer is
|
|
356
|
+
unchanged from before packs existed. `--gateway` is the clearest example with all four tiers live
|
|
357
|
+
today: an explicit `--gateway` wins, then a pack's `options.gateway`, then `routing.prefer` in
|
|
358
|
+
`config.json` (this section, above), then the hard-coded `"auto"` fallback. Most other pack-fillable
|
|
359
|
+
options (`timeout`, `maxCost`, `agent`, `thinking`, …) have no `config.json`-level default yet — just
|
|
360
|
+
a hard-coded built-in (`DEFAULTS` in `src/cli.js`) — so for those the chain is effectively **flag >
|
|
361
|
+
pack > built-in** today. See [Policy packs](./usage.md#policy-packs) for the full per-kind field
|
|
362
|
+
reference.
|
|
363
|
+
|
|
340
364
|
### Uninstall instructions
|
|
341
365
|
|
|
342
366
|
`npm uninstall -g amicus` removes the package and its bin shims. It does **not** clean up everything
|
package/docs/council.md
CHANGED
|
@@ -23,6 +23,7 @@ orchestration recipe. This page is the reference for the artifacts that recipe p
|
|
|
23
23
|
- [`amicus council run`](#amicus-council-run)
|
|
24
24
|
- [Debate mode](#debate-mode)
|
|
25
25
|
- [Council Workspace (GUI)](#council-workspace-gui)
|
|
26
|
+
- [Auto-open on `amicus_council_run` (v4.5)](#auto-open-on-amicus_council_run-v45)
|
|
26
27
|
- [`amicus council validate`](#amicus-council-validate)
|
|
27
28
|
- [`amicus council tally`](#amicus-council-tally)
|
|
28
29
|
- [`amicus council verdict`](#amicus-council-verdict)
|
|
@@ -103,6 +104,8 @@ amicus council run --prompt-file <briefing.md>
|
|
|
103
104
|
[--out-dir <dir>] # default ./council-<runId>/
|
|
104
105
|
[--json] [--max-cost <usd>] [--timeout <min>]
|
|
105
106
|
[--gateway auto|direct|openrouter] [--no-validate-model]
|
|
107
|
+
[--template <name|path>] [--artifact <file>] [--var k=v] # v4.5, see docs/usage.md#briefing-templates
|
|
108
|
+
[--pack <name|path>] # v4.5, see docs/usage.md#policy-packs
|
|
106
109
|
```
|
|
107
110
|
|
|
108
111
|
**The headless engine (v4.0).** Everything the `second-opinion` skill orchestrates by hand in
|
|
@@ -118,6 +121,12 @@ Key semantics:
|
|
|
118
121
|
- `--prompt-file` is **required** — councils always have real briefings (no inline `--prompt`).
|
|
119
122
|
- Seat/chair/critic/lens validation happens **pre-flight** and fails through the error envelope
|
|
120
123
|
(exit 1) before any spend. The chair must not be a bench seat.
|
|
124
|
+
- **`--pack <name|path>` (v4.5)** loads a saved bench/chair/critic/lenses/options/template as this
|
|
125
|
+
run's defaults — any flag you also typed always overrides the pack's value for that field, and
|
|
126
|
+
the pack is recorded on `run.json` (`pack: {name, version, hash, source}`) either way. When a
|
|
127
|
+
pre-flight error names a value the pack supplied (e.g. "chair is a bench seat"), the message adds
|
|
128
|
+
`(set by pack '<name>')` so a pack-caused failure is never mistaken for a typo in your own flags.
|
|
129
|
+
Full reference: [docs/usage.md § Policy packs](./usage.md#policy-packs).
|
|
121
130
|
- `--timeout` is the **per-leg** timeout (existing fanout semantics); there is no run-level
|
|
122
131
|
watchdog in v4.0 — bound the aggregate with your CI job timeout.
|
|
123
132
|
- `--max-cost` is a **whole-run** ceiling checked before each paid stage launch (Stage-1 wave,
|
|
@@ -154,6 +163,17 @@ Key semantics:
|
|
|
154
163
|
proceeded** on one server per wave, the configuration that races. Also printed as a
|
|
155
164
|
`Notice:`. It does not change the exit code; treat its presence as "expect degraded
|
|
156
165
|
results".
|
|
166
|
+
- **A `--council <preset>` member that resolution drops is recorded on `run.json`, not just
|
|
167
|
+
printed.** A preset member whose alias no longer resolves, or whose resolved id has fallen out
|
|
168
|
+
of the cached model catalog, is silently excluded from `bench` (the same graceful-degradation
|
|
169
|
+
`resolveCouncilMembers` applies everywhere) — human mode also prints a `Notice: dropped
|
|
170
|
+
unavailable council member(s): ...`, but `--json` mode (every scripted/MCP caller) printed
|
|
171
|
+
nothing at all. `run.json` now carries an additive `droppedMembers: [{member, reason}]` array —
|
|
172
|
+
present only when at least one member was actually dropped. The `--json` envelope carries it
|
|
173
|
+
via the same run.json serialization; the `amicus_council_run` MCP response body includes it
|
|
174
|
+
via an explicit conditional spread (`...(droppedMembers.length ? { droppedMembers } : {})`),
|
|
175
|
+
hand-built separate from run.json. `amicus council show <name>` reports the identical resolved/dropped split (and the
|
|
176
|
+
same per-member reason) as a preview, before you spend anything.
|
|
157
177
|
- Chair failure recovery: one retry of the same chair → promote the highest peers-only
|
|
158
178
|
street-cred model (from `amicus council stats`) that is not a bench seat → give up and write
|
|
159
179
|
the verdict with `overallVerdict: null`.
|
|
@@ -367,6 +387,45 @@ gated by a 7-channel allowlist, a CSP with **no network directive at all** (`def
|
|
|
367
387
|
and every model-derived string reaches the DOM through `textContent`/`createTextNode` only —
|
|
368
388
|
never `innerHTML`, enforced by a static source scan in the test suite.
|
|
369
389
|
|
|
390
|
+
### Auto-open on `amicus_council_run` (v4.5)
|
|
391
|
+
|
|
392
|
+
The window above no longer needs a separate `amicus watch <runId> --ui` call every time. When the
|
|
393
|
+
**MCP tool** `amicus_council_run` is invoked from **Claude Code (local)**, Amicus launches this same
|
|
394
|
+
Council Workspace window automatically, detached, right after the run starts — the flagship v4.4
|
|
395
|
+
surface is no longer opt-in on the client best able to show it. The plain CLI `amicus council run`
|
|
396
|
+
is unaffected: `detectClient` (`src/utils/client-detect.js`) only resolves from the MCP `initialize`
|
|
397
|
+
handshake, so a terminal invocation has no client to detect and never auto-opens; use
|
|
398
|
+
`amicus watch <runId> --ui` there as before.
|
|
399
|
+
|
|
400
|
+
**Decision order** (`shouldAutoOpenWorkspace`, `src/sidecar/workspace-auto-open.js`) — read top to
|
|
401
|
+
bottom, first match wins:
|
|
402
|
+
|
|
403
|
+
1. The tool's `ui: false` param — **beats everything**, including every guard below.
|
|
404
|
+
2. The hard guards, which beat even an explicit `ui: true`: Electron is not installed (this path
|
|
405
|
+
**never** installs it — that would be a surprise ~100 MB download on someone's first MCP council
|
|
406
|
+
run) → does not open; on Linux, no `DISPLAY` in the environment → does not open.
|
|
407
|
+
3. The tool's `ui: true` param — overrides both the config key and the client check below (but
|
|
408
|
+
never a hard guard above).
|
|
409
|
+
4. `workspace.autoOpen === false` in `config.json` (see
|
|
410
|
+
[Configuration § Config file format](./configuration.md#config-file-format)) → does not open.
|
|
411
|
+
5. The caller isn't Claude Code (local) (i.e. `client !== 'code-local'` — Claude Desktop/Cowork and
|
|
412
|
+
Claude Code web are deliberately excluded from the default) → does not open.
|
|
413
|
+
6. Otherwise → opens.
|
|
414
|
+
|
|
415
|
+
**Response fields.** `amicus_council_run`'s result always carries `workspaceOpened: boolean`, and,
|
|
416
|
+
**only when it did not open**, `workspaceOpenReason` — one of `param-suppressed`, `electron-absent`,
|
|
417
|
+
`no-display`, `config-disabled`, `client-not-code-local`, or a `spawn-failed:`/`auto-open-failed:`
|
|
418
|
+
detail if the decision said to open but the launch itself failed. The launch is fire-and-forget: it
|
|
419
|
+
never blocks the tool's response, and a launch failure never fails the council run itself — the run
|
|
420
|
+
proceeds exactly as it would with no Workspace at all, and `amicus watch <runId> --ui` still works
|
|
421
|
+
as the manual fallback.
|
|
422
|
+
|
|
423
|
+
**The `ui` param and the `workspace.autoOpen` config key are independent knobs, not aliases of each
|
|
424
|
+
other** — `ui` is a **per-call** override (either direction), while `workspace.autoOpen` sets the
|
|
425
|
+
**standing default** every call without an explicit `ui` falls back to. Turning the config default
|
|
426
|
+
off does not stop you from asking for the window on one particular run with `ui: true`, and leaving
|
|
427
|
+
the default on does not stop you from suppressing it on one noisy run with `ui: false`.
|
|
428
|
+
|
|
370
429
|
---
|
|
371
430
|
|
|
372
431
|
## `amicus council validate`
|
package/docs/schemas.md
CHANGED
|
@@ -27,6 +27,7 @@ Schemas leave `additionalProperties` open for exactly this reason — a doc with
|
|
|
27
27
|
| [`error.schema.json`](../schemas/error.schema.json) | every `--json` pre-flight/validation/route failure (stdout, exit 1) and every MCP error tool-text |
|
|
28
28
|
| [`spend.schema.json`](../schemas/spend.schema.json) | `spend --json` |
|
|
29
29
|
| [`model-catalog.schema.json`](../schemas/model-catalog.schema.json) | `models --json` |
|
|
30
|
+
| [`pack.schema.json`](../schemas/pack.schema.json) | policy pack configuration files (council, fanout, or solo) |
|
|
30
31
|
| [`alias-audit.schema.json`](../schemas/alias-audit.schema.json) | `models --check --json` |
|
|
31
32
|
| [`doctor.schema.json`](../schemas/doctor.schema.json) | `doctor --json` |
|
|
32
33
|
| [`council-tally.schema.json`](../schemas/council-tally.schema.json) | `council tally --json`; `amicus_council_tally` |
|