amicus 4.4.1 → 4.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +154 -0
  3. package/README.md +15 -2
  4. package/bin/amicus.js +10 -0
  5. package/docs/ROADMAP.md +38 -14
  6. package/docs/configuration.md +24 -0
  7. package/docs/council.md +62 -0
  8. package/docs/schemas.md +1 -0
  9. package/docs/usage.md +151 -1
  10. package/electron/workspace-ui/workspace-app.js +39 -17
  11. package/electron/workspace-ui/workspace-panels.js +76 -18
  12. package/electron/workspace-ui/workspace-render.js +10 -0
  13. package/package.json +1 -1
  14. package/schemas/council-run-live.schema.json +1 -1
  15. package/schemas/council-run.schema.json +14 -0
  16. package/schemas/error.schema.json +1 -1
  17. package/schemas/event.schema.json +1 -1
  18. package/schemas/pack.schema.json +30 -0
  19. package/schemas/progress.schema.json +1 -1
  20. package/schemas/run-live.schema.json +1 -1
  21. package/schemas/run.schema.json +2 -1
  22. package/schemas/wave-live.schema.json +1 -1
  23. package/schemas/wave.schema.json +2 -1
  24. package/skills/second-opinion/SKILL.md +5 -0
  25. package/src/cli-handlers-council-run.js +51 -8
  26. package/src/cli-handlers-doctor.js +10 -0
  27. package/src/cli-handlers-pack.js +238 -0
  28. package/src/cli-handlers-run.js +36 -8
  29. package/src/cli-handlers-template.js +53 -0
  30. package/src/cli.js +64 -3
  31. package/src/council/findings.js +4 -41
  32. package/src/council/presets-cli.js +23 -11
  33. package/src/council/run-stages.js +12 -9
  34. package/src/council/run-state.js +17 -0
  35. package/src/council/run.js +1 -1
  36. package/src/headless.js +18 -14
  37. package/src/mcp-council-run.js +110 -4
  38. package/src/mcp-server.js +203 -7
  39. package/src/mcp-tools.js +15 -5
  40. package/src/pack/pack-cli.js +38 -0
  41. package/src/pack/pack-forward.js +96 -0
  42. package/src/pack/pack-resolve.js +297 -0
  43. package/src/pack/pack-store.js +130 -0
  44. package/src/pack/pack-validate.js +113 -0
  45. package/src/sidecar/electron-state.js +61 -0
  46. package/src/sidecar/fanout.js +21 -4
  47. package/src/sidecar/progress.js +34 -0
  48. package/src/sidecar/start.js +5 -4
  49. package/src/sidecar/workspace-auto-open.js +83 -0
  50. package/src/sidecar/workspace-window.js +46 -1
  51. package/src/template/apply.js +88 -0
  52. package/src/template/render.js +86 -0
  53. package/src/template/store.js +106 -0
  54. package/src/utils/config.js +65 -25
  55. package/src/utils/doctor-electron-mcp-check.js +150 -0
  56. package/src/utils/error-doc.js +5 -0
  57. package/src/utils/result-schema-rebuild.js +1 -0
  58. package/src/utils/result-schema.js +8 -2
  59. package/src/workspace/artifact-guard.js +44 -6
  60. package/src/workspace/run-detail.js +6 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amicus",
3
- "version": "4.4.1",
3
+ "version": "4.5.1",
4
4
  "description": "Multi-model LLM Council + parallel AI window for Claude Code. Run structured council reviews across Gemini, GPT, DeepSeek and more — or fork a conversation to any model and fold the results back.",
5
5
  "author": {
6
6
  "name": "Christian Wagner"
package/CHANGELOG.md CHANGED
@@ -3,6 +3,160 @@
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.1] - 2026-07-30
7
+
8
+ ### Added
9
+
10
+ - **`electron-mcp` doctor check — doctor now validates Electron in the install the MCP actually
11
+ runs from (#76).** `amicus doctor` used to probe Electron only in the copy doctor itself runs
12
+ from (usually the global install), while `npx -y amicus@latest mcp` serves councils from an
13
+ npx-cache copy — so doctor could print `Electron: ok` while every `ui: true` run failed with
14
+ `electron-absent` (the electron-flavored recurrence of the engine's green-while-broken defect).
15
+ The new check enumerates running/global/npx-cache installs (reusing the engine scanner) and
16
+ probes Electron in each through a dual-root resolver — npm nests `electron` under
17
+ `amicus/node_modules` in a global install but hoists it to a sibling in the npx cache (the #69
18
+ layout lesson, now applied to Electron). With `--fix`, binary-missing npx copies are healed in
19
+ place via `repairElectron` under the #56 timeout guard; never-installed copies are reported,
20
+ not repaired.
21
+
22
+ ### Changed
23
+
24
+ - **`workspaceOpenReason` distinguishes a broken Electron from a missing one (#76).**
25
+ `electron-absent` now means the electron package was never installed; the new
26
+ `electron-broken: binary missing under <dir> — run `amicus doctor --fix`` covers the
27
+ package-present-but-binary-missing state (interrupted postinstall, AV quarantine) that the old
28
+ single reason conflated with it — naming the exact dir and the one-command fix.
29
+
30
+ ## [4.5.0] - 2026-07-28
31
+
32
+ "Save and share your councils" — complex run configurations become one command, repeatable and
33
+ shareable, and the flagship Council Workspace stops being opt-in on its best client.
34
+
35
+ ### Added
36
+
37
+ - **Policy packs — save a full run configuration and invoke it by name.** `amicus pack save <name>
38
+ --kind council|fanout|solo [flags]` (or `--from-run <id>`, which captures an existing council
39
+ run / fanout wave / solo session instead of typing flags) writes one JSON file per pack to
40
+ `~/.config/amicus/packs/<name>.json`; `pack list` / `pack show` / `pack rm` manage them. `--pack
41
+ <name|path>` on `amicus start` / `fanout` / `council run` — and the new `pack` param on the
42
+ `amicus_start` / `amicus_fanout` / `amicus_council_run` MCP tools — loads a pack's bench,
43
+ chair/critic/lenses, options, and briefing template as this run's defaults. **Explicit flags
44
+ always override the pack's values, and the pack is recorded either way** — `pack: {name,
45
+ version, hash, source}` lands on the resulting session `metadata.json`, wave `metadata.json` /
46
+ `wave.json`, or council `run.json`. Precedence throughout: **flag > pack > config default >
47
+ built-in default**. A pack is validated on save (hard-fail — `PACK_INVALID` — with any
48
+ non-fatal warnings printed to stderr) and again whenever it's used to launch a run; `pack show`
49
+ never fails on an invalid pack, only reports what's wrong with it; `pack show` and `pack rm` both
50
+ return `PACK_NOT_FOUND` for a missing pack. New `schemas/pack.schema.json`.
51
+ - **MCP pack semantics.** Over MCP, `pack` resolves entirely **in-process**, on the same call that
52
+ reads it — a resolved pack is never forwarded as `--pack` to a spawned child. Two knobs get
53
+ special-cased handling for CLI parity: a pack's `options.maxCost` and `briefing.template` have no
54
+ MCP schema param of their own on `amicus_start`/`amicus_fanout`, but they still apply — forwarded
55
+ to the spawned CLI child's argv as `--max-cost`/`--template` (`amicus_fanout` always spawns;
56
+ `amicus_start`'s spawn-fallback path does the same), or, on `amicus_start`'s in-process
57
+ shared-server path, applied via the same budget-gate/template-render code the CLI itself uses,
58
+ before any session is created — so a shared pack's spend cap and briefing template never silently
59
+ vanish over MCP. (`amicus_council_run` already has real MCP params for both.) Any *other* pack
60
+ knob with no destination in a tool's own MCP input schema is never silently dropped either: it
61
+ surfaces as an explicit `Notice: pack '<name>' sets <key>, which <tool> does not support over
62
+ MCP — ignored.` content block, naming the pack's own camelCase option key (e.g. `contextTurns`,
63
+ never the CLI's `context-turns`). Concretely, `amicus_fanout` has no MCP destination for
64
+ `options.contextTurns` / `options.contextMaxTokens` (both notice); `amicus_start` has real params
65
+ for both, so neither does.
66
+ - **Council packs do not accept `agent`/`thinking`/`summaryLength`.** They were inert on every
67
+ surface — no council code path, CLI or MCP, ever reads a pack-filled one; the engine hardcodes
68
+ agent `Plan`/summaryLength `verbose` regardless of what a pack says — so `KIND_OPTIONS.council`
69
+ never accepted them; a council pack that sets one fails `pack save` (`PACK_INVALID`), naming the
70
+ offending key. They remain valid, and functional, on `fanout`/`solo` packs.
71
+ - **Briefing templates.** `amicus template list|show`, plus `--template <name|path>` / `--artifact
72
+ <file>` / `--var <k=v>` (repeatable) on `start` / `fanout` / `council run`, render a
73
+ `{{variable}}` briefing before it's sent. Templates are Markdown files in
74
+ `~/.config/amicus/templates/` — a same-named user file shadows a built-in, the same precedent
75
+ saved councils already use — and v4.5 ships one built-in, `review`. Known variables: `{{prompt}}`,
76
+ `{{artifact}}`, `{{artifact_path}}`, `{{date}}`, `{{project}}`, `{{var.<key>}}`. Rendering is
77
+ strict by design: an unknown variable, a slot with no data behind it, or data passed with no slot
78
+ to receive it are all hard errors (`TEMPLATE_RENDER`) rather than a silently dropped value. MCP
79
+ has no `template` param of its own on any of the three run tools — a pack's `briefing.template` is
80
+ the only way a template reaches an MCP-invoked run.
81
+ - **The Council Workspace auto-opens on `amicus_council_run` from Claude Code (local).** When the
82
+ MCP tool `amicus_council_run` is invoked from Claude Code (local), the same Electron window that
83
+ `amicus watch <runId> --ui` has always opened by hand now launches automatically, detached, right
84
+ after the run starts — no more separate `--ui` call to see the flagship v4.4 surface. The CLI
85
+ `amicus council run` is unaffected (there is no MCP client to detect on that path). Decision
86
+ order: an explicit `ui: false` param beats everything; the hard guards (Electron not installed —
87
+ this path never installs it; Linux with no `DISPLAY`) beat even an explicit `ui: true`; `ui: true`
88
+ then overrides both the new `workspace.autoOpen` config key and the client check; short of an
89
+ explicit param, `workspace.autoOpen === false` disables it, and any client other than Claude Code
90
+ (local) simply doesn't auto-open. New `workspace.autoOpen` config key (`config.json`, default on
91
+ — only an explicit `false` turns it off). The tool response carries `workspaceOpened: boolean`
92
+ and, only when it did not open, `workspaceOpenReason` (`param-suppressed`, `electron-absent`,
93
+ `no-display`, `config-disabled`, `client-not-code-local`, or a `spawn-failed:` /
94
+ `auto-open-failed:` detail).
95
+
96
+ ### Fixed
97
+
98
+ - **A failed council seat no longer renders as perpetually live.** `createSession`'s early return
99
+ under a shared server bypassed the terminal `progress.json` write, leaving a stage marked
100
+ in-progress in `progress.json` after `metadata.json` had already recorded the error. The
101
+ terminal-write logic is now one shared helper (`writeTerminalProgressSafe`), called at all three
102
+ early-return sites plus the original one, so the paths can no longer drift apart.
103
+ - **Collided artifact names no longer misattribute one model's prose to another's.** Two bench
104
+ models whose sanitized filenames collide (e.g. `vendor/a` and `vendor?a` both → `vendor-a`) share
105
+ one physical file on disk; the Council Workspace compounded that with a rendering bug that showed
106
+ the first model's review/judge prose under the *second* model's panel — including, in a `--debate`
107
+ run, the rebuttal/re-vote drill-in. Collided names now get a deterministic suffix (`~2`, `~3`,
108
+ …), and every Workspace file lookup consults the resulting name map instead of recomputing a bare
109
+ sanitized name — the second colliding model's row is now correctly dropped by the existing
110
+ presence filter (its suffixed name was never physically written) instead of showing the wrong
111
+ model's text, and a run-integrity banner names the collision so the gap reads as a known
112
+ limitation rather than missing data.
113
+ - **A blind-mode toggle no longer collapses every open prose panel or repaints twice.** Flipping
114
+ Blind mid-run used to unconditionally recompute the blind default, forcing one paint with the
115
+ wrong value, a restore, and a second compensating repaint — and reset every lazy-loaded panel's
116
+ open/loaded state along the way, closing whatever the user had expanded. Blind state and
117
+ lazy-panel state now key off whether the run — and, separately, its status — actually changed
118
+ since the last render, so a same-run toggle updates in place and paints once without closing any
119
+ open panel; a run reaching its terminal status still recomputes the blind default and auto-reveals
120
+ exactly as before.
121
+ - **`renderSeats` now reorders rows to match the composed run document.** The keyed seat-table
122
+ update already added and removed rows on change but never moved one, so the table's row order
123
+ froze at first render — visibly wrong once a repair solo or a new wave changed the underlying leg
124
+ order mid-run. Existing rows are now moved into place at the end of every render pass.
125
+ - **`amicus council show` no longer reports a catalog-delisted bench member as healthy, and a
126
+ dropped member is no longer invisible to scripted/MCP callers.** `show`'s resolved/dropped split
127
+ checked only whether a member's alias mapped to *some* id, never whether that id was still in
128
+ the cached catalog — so a preset member whose alias now resolves to a catalog-absent id (e.g. a
129
+ direct-vendor route with no matching cached row) read as fully healthy in `show` while the real
130
+ run path (`resolveCouncilMembers`) silently dropped it on every actual run. `show` now reuses
131
+ that exact check — alias resolution, then catalog membership, with the same local-provider/
132
+ offline-catalog rule that a catalog it cannot consult never blocks a member, only a non-empty
133
+ catalog that omits it does. Separately, `council run --json` already suppressed the human-mode
134
+ `Notice: dropped unavailable council member(s): ...` line, and `run.json` carried no field for
135
+ it at all — a JSON-mode or MCP caller had zero signal a bench member vanished short of diffing
136
+ `bench` against the preset's nominal member list. `run.json` now carries an additive
137
+ `droppedMembers: [{member, reason}]` array (present only when at least one member was actually
138
+ dropped), reaching the `--json` envelope and the `amicus_council_run` MCP response body for
139
+ free. Resolution behavior itself — which members run, exit codes, spend — is unchanged; this is
140
+ observability only.
141
+
142
+ ### Changed
143
+
144
+ - **`amicus_start` / `amicus_fanout`'s MCP schemas no longer declare a JSON-Schema `default` for
145
+ `agent`, `noUi`, or `includeContext`.** Client-visible metadata only — nothing behavioral: the
146
+ defaults are still applied at the same read sites they always were, and are still stated in each
147
+ param's own description. (`amicus_resume` / `amicus_continue`'s `noUi` keep their schema-level
148
+ default; they were not part of this pass.)
149
+
150
+ ### Removed
151
+
152
+ - **The inert `repairCanHonorContract` guard.** 4.4.1's empty-findings acceptance flipped this
153
+ predicate permanently true by its own design, so `run-stages.js`'s `repairable &&` check could no
154
+ longer short-circuit on it and no test failed if the function were deleted outright — a
155
+ silent-deletion hazard that would otherwise re-arm the deadlock it used to guard against the day
156
+ empty-set validation tightens again. Removed deliberately instead: the underlying reasoning moved
157
+ to its call site, and the zero-findings regression test's comment now explains why the case it
158
+ covers still holds without the guard.
159
+
6
160
  ## [4.4.1] - 2026-07-27
7
161
 
8
162
  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.4.1",
367
+ "version": "4.5.1",
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
@@ -7,12 +7,12 @@ major jump, gated on funding/cofounder. The observability arc is split so the **
7
7
  first (v4.3)** and the **Electron "Council Workspace" (v4.4)** rides on top of it. `--dry-run` cost
8
8
  preview dropped to the backlog.
9
9
 
10
- Amicus is at **v4.4.1** (2026-07-27), the fast-follow patch on v4.4.0 (tagged 2026-07-26). Each
11
- 4.x rev below leads with the benefit, not the plumbing.
10
+ Amicus is at **v4.5.0** (tagged 2026-07-28). Each 4.x rev below leads with the benefit, not the
11
+ plumbing.
12
12
 
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 (policy packs + composition) is the next rev.** v5.0
15
- remains forward-looking.
13
+ **Status:** v4.0 through **v4.5.0** have **shipped** — everything down to the v4.6 heading is a
14
+ record of what landed, not a plan. **v4.6 (composition + tagging + GUI ergonomics) is the next
15
+ rev.** v5.0 remains forward-looking.
16
16
 
17
17
  > 📁 **Reading this from an npm install?** Some references below point at working documents that
18
18
  > live in the git repository and are deliberately **not** in the published package — anything under
@@ -85,18 +85,38 @@ and a review that honestly finds nothing stops being an error.
85
85
  > repo's working notes (`.superpowers/sdd/v441/backlog-and-proposal.md`, local-only) and in the
86
86
  > repo's root `BACKLOG.md` — neither ships in the npm package; see the note at the top.
87
87
 
88
- ## v4.5 — "Save, share, and compose your councils"
89
- **Benefit:** complex councils become one-command, repeatable, and chainable.
88
+ ## v4.5 — "Save and share your councils" *(scope split 2026-07-27 — composition moved to v4.6)* — ✅ SHIPPED v4.5.0, 2026-07-28
89
+ **Benefit:** complex councils become one-command, repeatable, and shareable — and the flagship GUI
90
+ stops hiding. Design: `docs/superpowers/specs/2026-07-27-v4.5-save-and-share-design.md`.
90
91
  - **★ Auto-open the Council Workspace on a council run (Christian, 2026-07-26)** — when a council is
91
- invoked from Claude Desktop and Electron is already present, the Workspace window opens by
92
+ invoked from Claude Code (local) and Electron is already present, the Workspace window opens by
92
93
  default instead of requiring a separate `amicus watch <runId> --ui`. Today the GUI is opt-in and
93
94
  discoverable only from `watch --help`, so the flagship v4.4 surface goes unseen on the very
94
95
  client best able to show it. *(S–M; the pieces exist — see the design notes below.)*
95
96
  - **Council policy packs + full run-profiles** (bench + lenses + options + briefing template, invoke by name) — B7/F5 *(M)*
96
- - **Composable/chained waves** (`--input-from <waveId>` / pipe) for generate→critique→refine F6 *(M)*
97
- - **Briefing templates + library** (F9), **session/wave tagging + `--search` + grouped history** (F8), **GUI power ergonomics** (F10) *(S–M)*
98
- - **README + docs update** — policy packs, chained waves, and the briefing-template library in `README.md` and `docs/` *(S)*
99
- > Why here: velocity multipliers that only pay off once councils are a command (v4.0) and observable (v4.3/v4.4).
97
+ - **Briefing templates + library** (F9) *(S–M)* the foundation packs reference; the `{{input}}`
98
+ chaining variable and the `critique`/`refine` built-ins arrive with v4.6
99
+ - **Ride-along fixes** — FR-1 (a failed council seat can render perpetually live), the FR-2 ruling,
100
+ RN-1/RN-5/RN-11 Workspace renderer fixes, TST-3 real-CDP abort pass *(S each; dispositions for
101
+ all 17 open items are tabled in the design doc's §8)*
102
+ - **README + docs update** — policy packs, the template library, and auto-open in `README.md` and `docs/` *(S)*
103
+ > Why here: save/share velocity multipliers that only pay off once councils are a command (v4.0)
104
+ > and observable (v4.3/v4.4); auto-open makes the v4.4 surface discoverable on its best client.
105
+
106
+ ## v4.6 — "Compose your councils" *(specced after v4.5 ships — anti-rot rule)*
107
+ **Benefit:** councils chain — generate → critique → refine with no manual copy-paste — and history
108
+ becomes navigable.
109
+ - **Composable/chained waves** (`--input-from <id>` / `--prompt-file -` pipe + per-source digests) —
110
+ F6 *(M)* — brings the `{{input}}` template variable + the `critique`/`refine` built-ins
111
+ - **Session/wave tagging + `--search` + grouped history** (F8) *(S–M)*
112
+ - **GUI power ergonomics** (F10: focus-follows fold hotkey, distinguishable window titles, tiling
113
+ presets) *(S each)*
114
+ - Deferred-item candidates per the v4.5 design doc's §8: RN-2, TST-1/TST-2, REL-2, CA-4, LC-5,
115
+ remainder of TST-7
116
+ - **README + docs update** *(S)*
117
+ > The 2026-07-19 combined spec (`2026-07-19-v4.5-policy-packs-composition-design.md`) holds the
118
+ > approved chaining/tagging/F10 design detail and is the primary input to the v4.6 brainstorm; it
119
+ > is NOT executed as-written — v4.6 gets its own spec + fresh plan once v4.5 ships.
100
120
 
101
121
  ### Deferred out of v4.4.1 into v4.5 (2026-07-27)
102
122
 
@@ -107,6 +127,10 @@ disposition that put them here in `.superpowers/sdd/v441/backlog-and-proposal.md
107
127
  those notes, read that backlog's Appendix A (settled decisions) and Appendix B (known false
108
128
  positives) before re-filing anything from this list.**
109
129
 
130
+ **Disposition update (2026-07-27):** every item below (plus FR-1/2/3 from `BACKLOG.md`) now carries
131
+ a proposed disposition — v4.5 ride-along / v4.6 / backlog — tabled for ruling in §8 of
132
+ `docs/superpowers/specs/2026-07-27-v4.5-save-and-share-design.md`.
133
+
110
134
  | ID | What | Why not 4.4.1 |
111
135
  |---|---|---|
112
136
  | **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 +178,9 @@ rather than re-deriving them.
154
178
  | Is Electron usable | `src/sidecar/electron-install.js` `isElectronUsable` / `resolveElectronBinary` |
155
179
  | Current entry point | `amicus watch <runId> --ui` (`src/cli-handlers-watch.js:87`) |
156
180
 
157
- **"Claude Desktop" maps to `code-local`.** ⚠️ But `detectClient` reads the MCP client's
181
+ **"Claude Code (local)" maps to `code-local`.** ⚠️ But `detectClient` reads the MCP client's
158
182
  `getClientVersion().name`, so it **only works on the MCP path** — `amicus_council_run`, which is
159
- exactly the Claude Desktop case. A `council run` typed into a terminal has no MCP server, so
183
+ exactly the Claude Code (local) case. A `council run` typed into a terminal has no MCP server, so
160
184
  detection there falls through to the env override or the `cowork` status-quo default. Do not build
161
185
  this on the CLI path expecting detection to work; either gate it on the MCP entry point or thread
162
186
  an explicit client tag through. (Related: the Phase 12 backlog item about persisting the client tag
@@ -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,48 @@ 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
+ (the electron package was never installed for this copy), an `electron-broken:` detail (the package
418
+ is present but its binary never arrived — interrupted download or AV quarantine; the reason names
419
+ the electron dir and points at `amicus doctor --fix`), `no-display`, `config-disabled`,
420
+ `client-not-code-local`, or a `spawn-failed:`/`auto-open-failed:`
421
+ detail if the decision said to open but the launch itself failed. The launch is fire-and-forget: it
422
+ never blocks the tool's response, and a launch failure never fails the council run itself — the run
423
+ proceeds exactly as it would with no Workspace at all, and `amicus watch <runId> --ui` still works
424
+ as the manual fallback.
425
+
426
+ **The `ui` param and the `workspace.autoOpen` config key are independent knobs, not aliases of each
427
+ other** — `ui` is a **per-call** override (either direction), while `workspace.autoOpen` sets the
428
+ **standing default** every call without an explicit `ui` falls back to. Turning the config default
429
+ off does not stop you from asking for the window on one particular run with `ui: true`, and leaving
430
+ the default on does not stop you from suppressing it on one noisy run with `ui: false`.
431
+
370
432
  ---
371
433
 
372
434
  ## `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` |