amicus 4.4.0 → 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 +162 -0
- package/README.md +17 -2
- package/bin/amicus.js +10 -0
- package/docs/DISTRIBUTION.md +234 -0
- package/docs/ROADMAP.md +226 -0
- package/docs/SHIMS.md +62 -0
- package/docs/architecture.md +104 -0
- package/docs/configuration.md +395 -0
- package/docs/council.md +970 -0
- package/docs/doc-system.md +92 -0
- package/docs/electron-testing.md +471 -0
- package/docs/jsdoc-setup.md +75 -0
- package/docs/opencode-integration.md +114 -0
- package/docs/publishing.md +60 -0
- package/docs/schemas.md +56 -0
- package/docs/testing.md +589 -0
- package/docs/troubleshooting.md +298 -0
- package/docs/usage.md +849 -0
- package/electron/fold.js +1 -1
- package/electron/main.js +4 -1
- package/electron/setup-ui-aliases.js +6 -6
- package/electron/workspace-ui/live-model.js +12 -1
- package/electron/workspace-ui/md-lite.js +52 -8
- package/electron/workspace-ui/workspace-app.js +39 -17
- package/electron/workspace-ui/workspace-matrix.js +46 -9
- package/electron/workspace-ui/workspace-panels.js +88 -19
- package/electron/workspace-ui/workspace-render.js +17 -1
- package/electron/workspace-ui/workspace-verbs.js +48 -2
- package/package.json +8 -3
- package/schemas/council-run-live.schema.json +1 -1
- package/schemas/council-run.schema.json +34 -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 +13 -1
- package/schemas/run-live.schema.json +1 -1
- package/schemas/run.schema.json +2 -1
- package/schemas/spend.schema.json +52 -4
- 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-spend.js +20 -2
- package/src/cli-handlers-template.js +53 -0
- package/src/cli-handlers-watch.js +11 -0
- package/src/cli.js +68 -5
- package/src/council/briefings-debate.js +27 -7
- package/src/council/briefings-stage2.js +155 -25
- package/src/council/briefings.js +24 -1
- package/src/council/findings.js +199 -9
- package/src/council/parse-stage2.js +10 -2
- package/src/council/presets-cli.js +23 -11
- package/src/council/report.js +19 -8
- package/src/council/run-assemble.js +42 -1
- package/src/council/run-budget.js +64 -11
- package/src/council/run-chair.js +4 -1
- package/src/council/run-debate.js +4 -2
- package/src/council/run-finalize.js +102 -0
- package/src/council/run-launch.js +29 -1
- package/src/council/run-server.js +248 -0
- package/src/council/run-stage2.js +118 -0
- package/src/council/run-stages.js +134 -110
- package/src/council/run-state.js +40 -1
- package/src/council/run.js +45 -47
- package/src/council/tally.js +10 -0
- package/src/headless.js +180 -7
- package/src/mcp-council-run.js +108 -4
- package/src/mcp-server.js +203 -7
- package/src/mcp-tools.js +15 -5
- package/src/observe/council-legs.js +60 -3
- package/src/observe/live-doc.js +18 -1
- package/src/observe/watch-render.js +4 -1
- 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/child-sessions.js +1 -2
- package/src/sidecar/fanout-leg-fallback.js +69 -21
- package/src/sidecar/fanout-leg.js +6 -0
- package/src/sidecar/fanout-signals.js +61 -0
- package/src/sidecar/fanout-wave-io.js +75 -0
- package/src/sidecar/fanout.js +82 -74
- package/src/sidecar/progress-fields.js +26 -4
- package/src/sidecar/progress.js +42 -1
- package/src/sidecar/session-utils.js +23 -14
- 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/spend-query.js +17 -5
- 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/lifecycle.js +37 -1
- package/src/utils/path-fence.js +39 -1
- package/src/utils/pricing.js +26 -10
- package/src/utils/result-schema-rebuild.js +1 -0
- package/src/utils/result-schema.js +8 -2
- package/src/utils/server-setup.js +79 -1
- package/src/utils/spend-ledger.js +24 -3
- package/src/workspace/artifact-guard.js +66 -7
- package/src/workspace/fold-format.js +33 -4
- package/src/workspace/live-normalize.js +28 -15
- package/src/workspace/run-detail.js +13 -1
package/docs/ROADMAP.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Amicus — reprioritized roadmap
|
|
2
|
+
|
|
3
|
+
**Reprioritization guidance (Christian, 2026-07-18):** engine-first is locked; the near-term work
|
|
4
|
+
ships as an incremental **4.x point-release line**, each rev delivering a **behavioral / feature
|
|
5
|
+
benefit users feel**; **enterprise-readiness is a venture unto itself** — the deliberate **5.0**
|
|
6
|
+
major jump, gated on funding/cofounder. The observability arc is split so the **data layer ships
|
|
7
|
+
first (v4.3)** and the **Electron "Council Workspace" (v4.4)** rides on top of it. `--dry-run` cost
|
|
8
|
+
preview dropped to the backlog.
|
|
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.
|
|
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 (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
|
|
17
|
+
remains forward-looking.
|
|
18
|
+
|
|
19
|
+
> 📁 **Reading this from an npm install?** Some references below point at working documents that
|
|
20
|
+
> live in the git repository and are deliberately **not** in the published package — anything under
|
|
21
|
+
> `.superpowers/` (the SDD working area, gitignored) and the root `BACKLOG.md`. The npm tarball
|
|
22
|
+
> ships `docs/*.md` only. Read those files at
|
|
23
|
+
> [github.com/BourbonDog/amicus](https://github.com/BourbonDog/amicus); the `.superpowers/` ones are
|
|
24
|
+
> local-only working notes and are not published anywhere. Every claim this roadmap makes is
|
|
25
|
+
> summarized here — the pointers are provenance, not prerequisites.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## v4.0 — "Councils become a command you can trust" *(foundation — engine-first)* — ✅ SHIPPED v4.0.0, 2026-07-20
|
|
30
|
+
**Benefit:** the flagship council stops being a manual 6-stage ritual — run a real adjudicated
|
|
31
|
+
council headlessly and in CI, and trust the output enough to gate on it.
|
|
32
|
+
- **Headless council orchestration engine** + `council run --headless` + `amicus_council_run` MCP — B1/A2/D2/F1 *(L)*
|
|
33
|
+
- **Council Review GitHub Action v2** (real adjudicated verdict on PRs) — B2 *(M)*
|
|
34
|
+
- **Versioned JSON envelope + published schema**, all failures routed through it — D3/C3 *(M)* — the engine's trustable contract
|
|
35
|
+
- **Prompt-injection fencing on JSON MCP tools** (H9) — A5/C6/D5 *(S)* — required before councils chew on untrusted CI content
|
|
36
|
+
- **Per-run fold nonce** (BL-7) — C5/D4 *(S)* — correctness/safety
|
|
37
|
+
> Why here: the engine is the moat and everything downstream (CI, automation, dashboards) needs it. The 3 cheap trust fixes ride along because a council you can't trust in automation isn't automatable.
|
|
38
|
+
|
|
39
|
+
## v4.1 — "The skill sheds the ritual" *(skill-on-engine fast path)* — ✅ SHIPPED v4.1.0, 2026-07-21
|
|
40
|
+
**Benefit:** the daily interactive council stops being a manual 6-stage ritual too — the
|
|
41
|
+
second-opinion skill delegates Stages 1–3+5 to `council run` and keeps only the human stages
|
|
42
|
+
(0 intake, 4 decisions, 6 lessons).
|
|
43
|
+
- **Skill fast path** — SKILL.md orchestration rewired onto `amicus council run` *(M)*
|
|
44
|
+
- **Debate mode headless** (Stage 2.5 rebuttal round in the engine; here or v4.2 at the latest) *(M)*
|
|
45
|
+
- **README + docs update** — skill fast path and headless debate mode reflected in `README.md` and `docs/council.md` *(S)*
|
|
46
|
+
> Why here: locked during the v4.0 design (2026-07-19) — the engine proves itself in CI first
|
|
47
|
+
> (v4.0), then the flagship interactive UX adopts it before any new feature front opens.
|
|
48
|
+
|
|
49
|
+
## v4.2 — "Bring your own models — $0, private, offline" — ✅ SHIPPED v4.2.0, 2026-07-23
|
|
50
|
+
**Benefit:** run sidecars and councils on local / OpenAI-compatible models (Ollama, LM Studio, vLLM)
|
|
51
|
+
— free marginal cost, private, air-gapped. The single biggest adoption + cost unlock (5 of 6 lenses' #1).
|
|
52
|
+
- **Local / OpenAI-compatible provider support** — `baseURL`/`type` discriminator, `$0`/offline pricing tier, setup-wizard support — A1/B3/C1/D1/E1 *(L)*
|
|
53
|
+
- **Adoption polish** (rides the "easy to start" story): `amicus init --claude` (C2), `doctor` at end of setup wizard (C8), docs for `spend`/`doctor`/`key` (C10) *(S)*
|
|
54
|
+
- **README + docs update** — local / OpenAI-compatible provider setup + `$0` pricing tier in `README.md` and `docs/configuration.md` *(S)*
|
|
55
|
+
> Why here (not enterprise): local models are a broad user benefit — cost, privacy, offline — not an enterprise-only feature. Comes right after the engine so councils can run on free/local seats.
|
|
56
|
+
|
|
57
|
+
## v4.3 — "See runs live in the terminal — and never waste one" *(observability data layer, first)* — ✅ SHIPPED v4.3.0, 2026-07-24
|
|
58
|
+
**Benefit:** watch runs in real time in the terminal, recover from dead legs, and see where every dollar went.
|
|
59
|
+
- **Live wave observability data layer** + CLI/TUI `amicus watch <waveId>` + `--follow` streaming + `--on-complete <exec|mcp-notify>` hook — F3/D6 *(M)* — the shared data layer v4.4 builds on
|
|
60
|
+
- **Failed-leg retry** `fanout --retry-failed <waveId>` + **cheaper-model fallback chains** + failed-leg partial-spend tracking — F2/E10/E8 *(M)*
|
|
61
|
+
- **Spend visibility & attribution (basic):** fix continue/resume zero-spend rows, attribute waveId/council/project on every row, queryable `spend query` — A4(basic)/E3/E4/E9/D7/C9 *(M)*
|
|
62
|
+
- **README + docs update** — `watch`/`--follow`, failed-leg retry, and `spend query` documented in `README.md` and `docs/usage.md` *(S)*
|
|
63
|
+
> Why here / why first: this is the observability data layer + terminal surface. It ships **before** the GUI (v4.4) because the desktop workspace is a front-end on exactly this data. All M-effort, so it lands fast.
|
|
64
|
+
|
|
65
|
+
## v4.4 — "The Council Workspace" *(desktop GUI on the v4.3 data layer)* — ✅ SHIPPED v4.4.0, 2026-07-26
|
|
66
|
+
**Benefit:** the same live data as a rich desktop app — watch a council *think*, not just tail a log.
|
|
67
|
+
- **★ Electron "Council Workspace" GUI** — live reviewer progress, anonymized peer packets, adjudication tiers, dissent, cost-by-seat, one-click fold into Claude Code — **B9** *(L)*
|
|
68
|
+
- **README + docs update** — Council Workspace walkthrough + screenshots in `README.md` and `docs/` *(S)*
|
|
69
|
+
> Why here: a GUI layer on top of v4.3's data layer. Split into its own point release because it's the one **L-effort** build in the observability arc — keeping v4.3 small and shippable.
|
|
70
|
+
>
|
|
71
|
+
> The five paid gate councils run against it (`wsgate01`–`wsgate04`, `costgate01`) are also what
|
|
72
|
+
> produced the 4.4.1 backlog below: the GUI shipped, and running real money through it is what
|
|
73
|
+
> surfaced the cost-attribution and repair-path defects that patch closes.
|
|
74
|
+
|
|
75
|
+
## v4.4.1 — "What the gate councils found" *(fast-follow patch on 4.4.0)* — ✅ SHIPPED v4.4.1, 2026-07-27
|
|
76
|
+
**Benefit:** the product stops mis-stating its own spend, a repair leg stops fabricating findings,
|
|
77
|
+
and a review that honestly finds nothing stops being an error.
|
|
78
|
+
- **Cost truthfulness** — subtree-unknown spend carried into the ledger, the sticky unknown-spend notice unstuck, a cache-only leg reported `unknown` rather than falsely free, and `--max-cost` degraded to exit `2` when the total is inexact rather than claiming a percentage it cannot know — CA-2/CA-3/CA-6/CA-7 *(M)*
|
|
79
|
+
- **The repair path, whole** — all four remaining repair-prompt builders now carry the artifact they are repairing, and a repaired review no longer splices two generations together — LC-12/LC-11 *(M)*
|
|
80
|
+
- **A clean review is a valid review** — `EMPTY_FINDINGS` accepts a well-formed empty set, and the tally, street-cred and chair degrade gracefully on an all-clean bench — LC-10 *(M)*
|
|
81
|
+
- **One OpenCode server per council run** — concurrent waves no longer race each other's SQLite open, which was making `--critic` a coin flip *(M)*
|
|
82
|
+
- Renderer, progress and leg-row robustness; `electron/` under the lint gate; the read-only-workspace invariant test; live rails green as documented *(S each)*
|
|
83
|
+
> Why a patch and not a rev: every item is a correction to something already shipped, all of it
|
|
84
|
+
> measured against real paid runs. Two behaviour changes ride along (LC-2's session abort at the
|
|
85
|
+
> tool-settle ceiling, LC-10's acceptance of an empty finding set) — both owner-ruled, both
|
|
86
|
+
> corrections rather than new capability. Scope, rulings and the full 61-item inventory live in the
|
|
87
|
+
> repo's working notes (`.superpowers/sdd/v441/backlog-and-proposal.md`, local-only) and in the
|
|
88
|
+
> repo's root `BACKLOG.md` — neither ships in the npm package; see the note at the top.
|
|
89
|
+
|
|
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`.
|
|
93
|
+
- **★ Auto-open the Council Workspace on a council run (Christian, 2026-07-26)** — when a council is
|
|
94
|
+
invoked from Claude Code (local) and Electron is already present, the Workspace window opens by
|
|
95
|
+
default instead of requiring a separate `amicus watch <runId> --ui`. Today the GUI is opt-in and
|
|
96
|
+
discoverable only from `watch --help`, so the flagship v4.4 surface goes unseen on the very
|
|
97
|
+
client best able to show it. *(S–M; the pieces exist — see the design notes below.)*
|
|
98
|
+
- **Council policy packs + full run-profiles** (bench + lenses + options + briefing template, invoke by name) — B7/F5 *(M)*
|
|
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.
|
|
122
|
+
|
|
123
|
+
### Deferred out of v4.4.1 into v4.5 (2026-07-27)
|
|
124
|
+
|
|
125
|
+
Each is `M`+, or needs data or a design decision — the bar a patch on a published release cannot
|
|
126
|
+
carry. The table below is self-contained; the full write-ups (what, where, what breaks if it stays)
|
|
127
|
+
live in the repo's local-only working notes — `.superpowers/sdd/v44/v4.4.1-backlog.md`, with the
|
|
128
|
+
disposition that put them here in `.superpowers/sdd/v441/backlog-and-proposal.md`. **If you have
|
|
129
|
+
those notes, read that backlog's Appendix A (settled decisions) and Appendix B (known false
|
|
130
|
+
positives) before re-filing anything from this list.**
|
|
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
|
+
|
|
136
|
+
| ID | What | Why not 4.4.1 |
|
|
137
|
+
|---|---|---|
|
|
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 |
|
|
139
|
+
| **CA-5** | `isSubagentToolCall` is still a `name === 'task'` string proxy | `M`, and **reduced** by v4.4.0: it is now only the fallback when the real subtree walk finds nothing |
|
|
140
|
+
| **LC-1** | B53's stall kill is skipped while a tool-settle deferral is active | `S–M` — shipped deliberately; the author wants a second opinion, which needs data from real runs |
|
|
141
|
+
| **LC-5** | A chair fallback leaves no trace in `run.json` (`wsgate02`'s haiku failed twice; only `"chair":"minimax"` was recorded) | `M` — a run-record schema addition |
|
|
142
|
+
| **RN-1** | `sanitizeName` collisions surface as a banner rather than a refusal | `S` + a product decision that was already argued once |
|
|
143
|
+
| **RN-2** | `renderRunList` blind masking is best-effort — only the open run resolves labels | `M` |
|
|
144
|
+
| **RN-5** | A blind-mode flip closes every open prose panel and repaints twice | `S–M` |
|
|
145
|
+
| **RN-11** | `renderSeats` never reorders existing rows | `S`, cosmetic, no consequence yet |
|
|
146
|
+
| **REL-2** | `mcp-repomix-e2e` skips, so plugin-chain MCP discovery is exercised nowhere | `M` — needs `AMICUS_REPOMIX_E2E_PROJECT` pointed at a real project *and* `repomix` on PATH |
|
|
147
|
+
| **TST-1 / TST-2** | No real `--debate` fixture; the `lens:<slug>` role branch has zero coverage | `M` each, and they want doing together |
|
|
148
|
+
| **TST-3** | Abort confirm→status-flip is proven only against the fake DOM | `M` — needs a real CDP pass |
|
|
149
|
+
| **TST-7** | Six render functions have no unit coverage | `M` |
|
|
150
|
+
| *(new)* | **Residual integration-suite handle leaks** — a NAMED leak with evidence, filed 2026-07-27 after 4.4.1 fixed ENV-6 and the live rail still warned from *different* suites | `S–M`. Full evidence, including why `--detectOpenHandles` cannot diagnose this class, is in the repo's root `BACKLOG.md` (not in the npm package — read it on GitHub) — start there rather than re-deriving it |
|
|
151
|
+
|
|
152
|
+
**ENV-6 is NOT on this list** — it was pulled into 4.4.1 by owner ruling and fixed at the source
|
|
153
|
+
(the CDP e2e suite's SIGKILL escalation timer). **ENV-1** is not on it either: it is a decision
|
|
154
|
+
record ("eleven `Number(env) || default` sites"), not a task — a blanket migration would introduce
|
|
155
|
+
six new defects to fix one, and `src/utils/env-num.js`'s docblock records which knobs deliberately
|
|
156
|
+
keep the old form.
|
|
157
|
+
|
|
158
|
+
## v5.0 — Enterprise-readiness *(the deliberate major jump — a venture unto itself, gated on funding / cofounder)*
|
|
159
|
+
**Benefit:** team/org deployment — but a distinct product + go-to-market motion (SOC2, SLAs, sales, support), not a feature drop. Parked as the 5.0 major per the chair's hard-question #5: a solo dev can't credibly ship or support this alone.
|
|
160
|
+
- Secret-store backends + env-var-only mode (A3); org allowlists/blocklists, per-team cost ceilings, read-only enforcement (A6); RBAC
|
|
161
|
+
- Audit & compliance: reproducibility manifests + replay (B11), seed/temp/version pinning (A7), spend export to SIEM/warehouse (A10), `/health` + metrics + structured logging (A8)
|
|
162
|
+
- Team config `.amicusrc` (A9); spend **governance** (per-team caps/enforcement) — the governance half of A4
|
|
163
|
+
- Learning loops that need scale anyway: reliability-aware seat selection (B4), calibration benchmarks (B5), decision-outcome feedback (B10), adaptive strategy planner (B8), evidence provenance (B6)
|
|
164
|
+
- README + docs update: deployment/admin documentation for the above, in `README.md` and `docs/`
|
|
165
|
+
> These cluster because they share one prerequisite you don't have yet: an org buyer + the org to support. Revisit as a funded track.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
### Design notes — auto-open the Council Workspace
|
|
170
|
+
|
|
171
|
+
Recorded 2026-07-26 from a read of the shipped code, so the v4.5 implementer starts from facts
|
|
172
|
+
rather than re-deriving them.
|
|
173
|
+
|
|
174
|
+
**The pieces already exist.**
|
|
175
|
+
|
|
176
|
+
| Need | Where it lives today |
|
|
177
|
+
|---|---|
|
|
178
|
+
| Launch the window | `src/sidecar/workspace-window.js` `launchWorkspaceWindow({project, runId})` |
|
|
179
|
+
| Detect the client | `src/utils/client-detect.js` `detectClient(mcpServer)` → `code-local` \| `code-web` \| `cowork` |
|
|
180
|
+
| Is Electron usable | `src/sidecar/electron-install.js` `isElectronUsable` / `resolveElectronBinary` |
|
|
181
|
+
| Current entry point | `amicus watch <runId> --ui` (`src/cli-handlers-watch.js:87`) |
|
|
182
|
+
|
|
183
|
+
**"Claude Code (local)" maps to `code-local`.** ⚠️ But `detectClient` reads the MCP client's
|
|
184
|
+
`getClientVersion().name`, so it **only works on the MCP path** — `amicus_council_run`, which is
|
|
185
|
+
exactly the Claude Code (local) case. A `council run` typed into a terminal has no MCP server, so
|
|
186
|
+
detection there falls through to the env override or the `cowork` status-quo default. Do not build
|
|
187
|
+
this on the CLI path expecting detection to work; either gate it on the MCP entry point or thread
|
|
188
|
+
an explicit client tag through. (Related: the Phase 12 backlog item about persisting the client tag
|
|
189
|
+
into shared-server `metadata.json` is the same seam.)
|
|
190
|
+
|
|
191
|
+
**Four guards, all load-bearing:**
|
|
192
|
+
|
|
193
|
+
1. **Never under `--json`.** `--ui` already rejects `--json` (interactive-only); an implicit default
|
|
194
|
+
must not create the combination the explicit flag refuses.
|
|
195
|
+
2. **Never in CI or headless.** `council run` is the engine behind the Council Review GitHub Action
|
|
196
|
+
and every headless fanout. A popped window on a runner is a hang, not a feature. Gate on the same
|
|
197
|
+
display check the e2e suite uses (`HAS_DISPLAY`).
|
|
198
|
+
3. **Never trigger an install.** Requirement is *"where Electron is installed"* — check
|
|
199
|
+
`isElectronUsable`, and if it is absent, do nothing silently. An implicit ~100 MB Electron
|
|
200
|
+
download on someone's first council run is a hostile surprise.
|
|
201
|
+
4. **Must be opt-out.** A `--no-ui` (or config key) that suppresses it, because this changes default
|
|
202
|
+
behaviour for an existing command.
|
|
203
|
+
|
|
204
|
+
**Why not v4.4.1.** It is a new default behaviour — a feature — and 4.4.1 is a patch on a shipped
|
|
205
|
+
release whose scope was explicitly locked. The patch already carries two behaviour changes (LC-2,
|
|
206
|
+
LC-10) that stretch the definition; a third that pops a GUI window would not be defensible as a
|
|
207
|
+
patch. Sits naturally beside v4.5's existing **GUI power ergonomics (F10)** line.
|
|
208
|
+
|
|
209
|
+
## Backlog (tracked, not scheduled)
|
|
210
|
+
- **`--dry-run` / cost & route preview** across start/fanout/council — E2/C7/F4 *(M)* — "know the cost/route before you commit"; useful, not essential to the near-term line.
|
|
211
|
+
- **F7** — Parallel council panels + super-chair (opt-in `--panels N` high-assurance; niche).
|
|
212
|
+
- **E7** — Prompt dedup cache (exact-dup, opt-in, excludes council/fanout) — minor cost optimization.
|
|
213
|
+
- **E6** — Cost-per-quality metric (withdrawn in debate; revisit if street-cred stabilizes).
|
|
214
|
+
- **`amicus key --local` picker** *(S)* — a default local-provider picker so `amicus key` sets/clears a bearer without naming the provider id: auto-select (and announce) when exactly one local provider is configured, a numbered prompt when several, and a hard error under `--json`/non-interactive rather than guessing a secret's destination. Register `--local` as a boolean flag. Deferred out of v4.2.1 as feature material (a new CLI surface, not a patch fix).
|
|
215
|
+
- **Headless no-output fast-fail backstop** *(M)* — fail a headless run fast (env-tunable `AMICUS_NO_OUTPUT_BACKSTOP_MS`, ~120s default) when a misconfigured local model produces zero output, reasoning, and tool-calls, instead of polling to the request/overall timeout. Disarms permanently on the first token/reasoning/tool_use, so a legit slow cold-prefill local model (30–90s is normal) is never affected. Deferred out of v4.2.1 as new runtime behavior.
|
|
216
|
+
|
|
217
|
+
## What changed vs. the council's flat top-10
|
|
218
|
+
- Split the flat list into a **benefit-themed 4.x point-release line** (v4.0 → v4.2 → v4.3 → v4.4 → v4.5).
|
|
219
|
+
- **v4.1 inserted post-design (2026-07-19):** skill-on-engine fast path + headless debate mode,
|
|
220
|
+
between the engine (v4.0) and local providers (v4.2). Spec: `docs/superpowers/specs/2026-07-19-v4.0-headless-council-engine-design.md`.
|
|
221
|
+
- **Local providers stays near-term** (v4.2) — a broad cost/privacy benefit, not enterprise.
|
|
222
|
+
- **Observability arc split:** v4.3 = the data layer + terminal surface + resilience + spend (ships first); **v4.4 = the Electron Council Workspace (B9)** as a GUI on that data.
|
|
223
|
+
- **`--dry-run` cost preview → backlog** (was in the observability rev).
|
|
224
|
+
- **Enterprise/governance/audit/compliance/learning-loops → v5.0**, reframed as the deliberate *major-version venture* gated on funding.
|
|
225
|
+
- The **cheap trust fixes** (envelope, injection fencing, fold nonce) pulled into **v4.0** because the engine needs them to be trustworthy in automation.
|
|
226
|
+
- **Docs are part of the rev (2026-07-20):** every rev from v4.1 onward closes with a **README + docs update** line item, so each release ships its own documentation rather than deferring it.
|
package/docs/SHIMS.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Amicus compatibility shims — v2.0.0 removal record
|
|
2
|
+
|
|
3
|
+
v2.0.0 removed every pre-rebrand `sidecar*` compatibility shim (#19). This
|
|
4
|
+
document is now a **removal record**, not a live shim inventory: it exists so
|
|
5
|
+
that (a) anyone still on a `sidecar*`-era install has a one-line migration
|
|
6
|
+
remedy per removed shim, and (b) the v2.0.0 CHANGELOG migration section can be
|
|
7
|
+
lifted from this table nearly verbatim.
|
|
8
|
+
|
|
9
|
+
Two of the rows below are **not** removals — one is re-scoped as a kept
|
|
10
|
+
healing tool, the other was never a compat shim to begin with — each explains
|
|
11
|
+
its own status inline in its own Status/Migration cells. A related but
|
|
12
|
+
separate guard, which is not itself a table row, is called out explicitly
|
|
13
|
+
below the table: see "Not a removal: the mcp-self-identity recursive-spawn
|
|
14
|
+
guard".
|
|
15
|
+
|
|
16
|
+
| Shim | Location (at removal) | Legacy form | Status | Migration |
|
|
17
|
+
| --- | --- | --- | --- | --- |
|
|
18
|
+
| Env var prefix | `src/utils/env-compat.js` (deleted) | `SIDECAR_*` env vars | REMOVED in v2.0.0 | Rename every `SIDECAR_*` var you set to its `AMICUS_*` equivalent (e.g. `SIDECAR_ENV_DIR` → `AMICUS_ENV_DIR`, `SIDECAR_IDLE_TIMEOUT*` → `AMICUS_IDLE_TIMEOUT*`, `SIDECAR_DEBUG_PORT` → `AMICUS_DEBUG_PORT`, `SIDECAR_MOCK_UPDATE` → `AMICUS_MOCK_UPDATE`). One additional rename landed in the same removal pass: `SIDECAR_MAX_SESSIONS` → `AMICUS_MAX_SESSIONS` (this was the last remaining legacy-prefixed env var read anywhere in the codebase). Unrenamed `SIDECAR_*` vars are now silently ignored — no warning, no fallback. |
|
|
19
|
+
| CLI bins | `package.json` `bin` | `sidecar`, `claude-sidecar` commands | REMOVED in v2.0.0 | Use `amicus` (or the `am` short alias). If `npm install -g amicus` now fails with `EEXIST` naming an old `claude-sidecar`/`sidecar` file, that's a *stale* global install of the old upstream package, not this shim — see [docs/troubleshooting.md](./troubleshooting.md#install-fails-with-eexist--claude-sidecar). |
|
|
20
|
+
| Config dir | `src/utils/config.js` `getConfigDir()` | `~/.config/sidecar` fallback + `migrateLegacyConfigDir()` | REMOVED in v2.0.0 | No action needed for most users: config data was auto-migrated forward on every v1.x run (each v1.x launch copied `~/.config/sidecar/` into `~/.config/amicus/` once, non-destructively, if the new dir didn't exist yet). If you skipped every v1.x release and jumped straight from a pre-rebrand install to v2.0.0, copy `~/.config/sidecar/` to `~/.config/amicus/` by hand — `getConfigDir()` no longer reads the old location at all. |
|
|
21
|
+
| Session dir | `src/session-manager.js` + call sites | `.claude/sidecar_sessions/` dual-read | REMOVED in v2.0.0 | Amicus only reads `.claude/amicus_sessions/` now. Old session directories are not auto-migrated (per-project, not worth a background sweep) — rename `.claude/sidecar_sessions/` to `.claude/amicus_sessions/` in any project whose history you want `amicus list`/`amicus read` to see again. |
|
|
22
|
+
| Config token | `skills/sidecar/SKILL.md` dual-token instruction + test-only regexes (**not** `config.js` — `config.js` only ever emitted the canonical form; see History below for `c3de5bf`) | `[SIDECAR_CONFIG_UPDATE]` stderr marker / `sidecar-config-hash` HTML-comment parse | REMOVED in v2.0.0 | The skill instructs the canonical forms only: `[AMICUS_CONFIG_UPDATE]` and `<!-- amicus-config-hash: ... -->`. Old CLAUDE.md files carrying a leftover `<!-- sidecar-config-hash: ... -->` comment are not auto-migrated — the comment is simply no longer recognized; the next `amicus setup` alias change will write a fresh `amicus-config-hash` comment and the stale one can be deleted by hand. |
|
|
23
|
+
| MCP tool names | `src/mcp-server.js` registration | `sidecar_*` tool aliases — opt-in via `AMICUS_LEGACY_ALIASES=1` since v1.8.0 | REMOVED in v2.0.0 | `AMICUS_LEGACY_ALIASES=1` is now a **no-op**: setting it changes nothing, and only the canonical `amicus_*` tools register (regression-pinned in `tests/mcp-server-legacy-aliases.test.js`). Update any MCP client config or tooling that still calls a `sidecar_*` tool name to use the `amicus_*` equivalent. |
|
|
24
|
+
| Public API | `src/index.js` | `startSidecar`/`listSidecars`/`resumeSidecar`/`continueSidecar`/`readSidecar` exports | REMOVED in v2.0.0 | These were exported as deprecated aliases from the package root through v1.9.1 (present on npm in every release). v2.0.0 deletes them from `module.exports`; only the canonical `startAmicus`/`listAmicus`/`resumeAmicus`/`continueAmicus`/`readAmicus` names remain exported. Rename any import of a `*Sidecar`-named export from `amicus`'s package root to its `*Amicus` equivalent. |
|
|
25
|
+
| MCP registration cleanup | `src/utils/legacy-mcp-migration.js`, invoked by `scripts/postinstall.js` and `amicus doctor --fix` | duplicate `'sidecar'` MCP server entry in `~/.claude.json` / `claude_desktop_config.json` | **KEPT** (re-scoped, #19) | Not a compat shim — a one-shot **healing** tool for pre-1.8.0 installs that registered the same server under both `'amicus'` and `'sidecar'`. It only removes a `'sidecar'` entry verified identical-in-effect to the `'amicus'` one (`isAmicusMcpConfig()`); a customized `'sidecar'` entry pointing elsewhere is left alone. Still runs on every `postinstall` and via `amicus doctor --fix`. Kept indefinitely — there is no removal date. |
|
|
26
|
+
| Fold-marker constant | `src/headless.js` `FOLD_MARKER`/`COMPLETE_MARKER` exports | bare `[SIDECAR_FOLD]` literal, export-only back-compat — as of v4.0 no code path writes OR matches the bare form (`extractSummary`/`formatFoldOutput` require the per-run nonce; the legacy matcher/writer fallbacks are retired). On the wire the bare literal survives only as the prefix inside the nonced `[SIDECAR_FOLD:<nonce>]` form — see [docs/architecture.md](./architecture.md) | **KEEP** — deliberate wire-token continuity, not a compat shim, not scheduled for removal (B38 keeps it) | No action needed. |
|
|
27
|
+
|
|
28
|
+
## Not a removal: the mcp-self-identity recursive-spawn guard
|
|
29
|
+
|
|
30
|
+
`src/utils/mcp-self-identity.js` still recognizes the old bin/server names
|
|
31
|
+
`'sidecar'`/`'claude-sidecar'` in its self-exclusion lists (`SELF_MCP_NAMES`,
|
|
32
|
+
`SELF_BIN_NAMES`), even though v2.0.0 no longer ships them. This is
|
|
33
|
+
**deliberate and out of scope for this removal** — it's a defense, not a
|
|
34
|
+
shim: a stale pre-rebrand global install can still have `sidecar`/
|
|
35
|
+
`claude-sidecar` linked on a user's `PATH`, and a stale `claude.json`/MCP
|
|
36
|
+
config can still reference the old `'sidecar'` server name. Recognizing them
|
|
37
|
+
here only ever prevents amicus from recursively spawning itself under an old
|
|
38
|
+
alias — it never restores old behavior or re-exposes removed surface, so
|
|
39
|
+
there's no cost to keeping the wider net. Not tracked for future removal.
|
|
40
|
+
|
|
41
|
+
## Verification
|
|
42
|
+
|
|
43
|
+
Removal is verified in the codebase, not just asserted here:
|
|
44
|
+
|
|
45
|
+
- `grep -r "SIDECAR_" src/` → every hit is the `[SIDECAR_FOLD:<nonce>]` fold-marker contract (`src/headless.js`, `src/prompt-builder.js`, `src/utils/fold-marker.js`), a comment referencing it (e.g. `src/sidecar/interactive-process.js`), or the bracket-less `SIDECAR_FOLD` prefix inside the nonced form. The bare `[SIDECAR_FOLD]` literal survives **in code** in exactly two inert spots: the export-only back-compat constant `FOLD_MARKER` (`src/headless.js` — assigned, aliased to `COMPLETE_MARKER`, exported, never used in live logic), and the fallback branch of `buildHeadlessModeSection` (`src/prompt-builder.js`: `nonce ? buildFoldMarker(nonce) : '[SIDECAR_FOLD]'`) — reachable ONLY via the deprecated, production-unused `buildSystemPrompt()`, which builds no prompt for any real run. No **live** run path writes or matches the bare form since v4.0: `buildPrompts` — the orchestration entry point every real headless run routes through (`start` / `continue` / `fanout` / `mcp-server`) — throws a `TypeError` rather than emit a nonce-less headless prompt, and the detector (`trailingFoldMarkerRegex` in `src/utils/fold-marker.js`) matches only the nonced form. No `SIDECAR_*` env var is read or written anywhere in `src/`.
|
|
46
|
+
- `tests/mcp-server-legacy-aliases.test.js` — regression-pins that `AMICUS_LEGACY_ALIASES=1` registers zero `sidecar_*` tools.
|
|
47
|
+
- `tests/where-things-live-docs.test.js`, `tests/shim-removal-docs.test.js` — pin that docs describe the removal, not a live shim.
|
|
48
|
+
|
|
49
|
+
## History
|
|
50
|
+
|
|
51
|
+
Removed across the following commits on `p18/shim-removal` (#19):
|
|
52
|
+
|
|
53
|
+
- `a33690c` — MCP tool alias shim
|
|
54
|
+
- `fc7f0db` — public API `*Sidecar` alias exports
|
|
55
|
+
- `3791a6e` — `SIDECAR_*` env-var fallback shim
|
|
56
|
+
- `e9dade0` — `~/.config/sidecar` dir-fallback + `migrateLegacyConfigDir`
|
|
57
|
+
- `887912a` — `sidecar_sessions` dual-read shim
|
|
58
|
+
- `4ebc84d` — `sidecar`/`claude-sidecar` CLI bin aliases
|
|
59
|
+
- `c3de5bf` — dead `sidecar-config-hash` comment-parse tolerance (test-only tolerance removal — `config.js` never had dual-parse code; the skill-text acceptance instruction is fixed by this docs sweep)
|
|
60
|
+
- `9273dd1` — `SIDECAR_MAX_SESSIONS` → `AMICUS_MAX_SESSIONS` rename (the last legacy-prefixed env var read anywhere in the codebase)
|
|
61
|
+
|
|
62
|
+
See the rebrand plan for the original shim rationale: `docs/superpowers/plans/2026-06-08-amicus-rebrand.md`.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Architecture Details
|
|
2
|
+
|
|
3
|
+
## Data Flow
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
User: amicus start --model google/gemini-2.5 --briefing "Debug auth issue"
|
|
7
|
+
↓
|
|
8
|
+
CLI parses args (cli.js)
|
|
9
|
+
↓
|
|
10
|
+
buildContext() extracts from ~/.claude/projects/[project]/[session].jsonl
|
|
11
|
+
↓
|
|
12
|
+
buildPrompts() creates system prompt + user message
|
|
13
|
+
Interactive: context in system prompt (hidden from UI)
|
|
14
|
+
Headless: context in user message (no UI)
|
|
15
|
+
↓
|
|
16
|
+
startOpenCodeServer() → createSession() → sendPromptAsync()
|
|
17
|
+
↓
|
|
18
|
+
[Interactive] [Headless]
|
|
19
|
+
Electron BrowserView opens OpenCode async API (promptAsync)
|
|
20
|
+
User converses with model Agent works autonomously
|
|
21
|
+
FOLD clicked → Polls for [SIDECAR_FOLD:<nonce>] marker
|
|
22
|
+
Model generates summary ↓
|
|
23
|
+
(SUMMARY_TEMPLATE prompt) extractSummary() captures output
|
|
24
|
+
↓ ↓
|
|
25
|
+
Summary output to stdout → Claude Code receives in context
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Fold Mechanism
|
|
29
|
+
|
|
30
|
+
When the user clicks **Fold** (or presses `Cmd+Shift+F`) in interactive mode:
|
|
31
|
+
|
|
32
|
+
1. UI shows overlay with spinner ("Generating summary...")
|
|
33
|
+
2. `SUMMARY_TEMPLATE` is sent to the model via OpenCode HTTP API (`prompt_async`)
|
|
34
|
+
3. Electron polls `/session/:id/message` for the model's response
|
|
35
|
+
4. Model generates a structured summary with: Task, Findings, Attempted Approaches, Recommendations, Code Changes, Files Modified, Assumptions, Open Questions
|
|
36
|
+
5. Summary is written to stdout with a `[SIDECAR_FOLD:<nonce>]` metadata header
|
|
37
|
+
6. Electron window closes, `start.js` captures stdout and finalizes session
|
|
38
|
+
|
|
39
|
+
In headless mode, the agent outputs `[SIDECAR_FOLD:<nonce>]` autonomously when done, and `headless.js` extracts everything before the marker.
|
|
40
|
+
|
|
41
|
+
**Wire-format token:** The wire-format token emitted by the model in headless mode is `[SIDECAR_FOLD:<nonce>]` — a per-run random nonce, generated once per run before prompt construction (`src/utils/fold-marker.js`), embedded in headless mode instructions by `src/prompt-builder.js`, and required by `src/headless.js`'s detector (`findTrailingFoldMarker`, final-non-empty-line match on the exact nonced marker). This closes a hardening gap (#BL-7): a static, public marker meant model output that merely echoed it (prior instructions, a scraped doc, another run's transcript) could force a premature completion; requiring the run's own nonce means only a model that actually finished can produce it. The bare `[SIDECAR_FOLD]` literal (no `:<nonce>`) is kept only as a legacy/back-compat constant (`FOLD_MARKER` in `src/headless.js`) for callers with no nonce context — it is never accepted by the detector. Tracked in `docs/SHIMS.md`.
|
|
42
|
+
|
|
43
|
+
## Shared Server Architecture
|
|
44
|
+
|
|
45
|
+
Multiple Amicus invocations share a single OpenCode Go binary when `AMICUS_SHARED_SERVER=1` (the default). This eliminates per-invocation cold-start latency and reduces memory overhead.
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
Before (per-process): After (shared server):
|
|
49
|
+
MCP Server MCP Server
|
|
50
|
+
+-- amicus CLI (port 4096) +-- Shared OpenCode Server (port 4096)
|
|
51
|
+
| +-- OpenCode Go binary +-- Session A
|
|
52
|
+
+-- amicus CLI (port 4097) +-- Session B
|
|
53
|
+
| +-- OpenCode Go binary +-- Session C
|
|
54
|
+
+-- amicus CLI (port 4098)
|
|
55
|
+
+-- OpenCode Go binary
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The shared server restarts automatically on crash, up to 3 times within any 5-minute window. After 3 restarts the server is considered unstable and will not restart again; use `AMICUS_SHARED_SERVER=0` to fall back to per-process mode.
|
|
59
|
+
|
|
60
|
+
## Fanout Wave Architecture
|
|
61
|
+
|
|
62
|
+
`amicus fanout` runs N models on the same prompt concurrently using **one shared OpenCode server** (external-server mode). Key design properties, each traceable to source:
|
|
63
|
+
|
|
64
|
+
- **One server, N legs.** A single OpenCode server is started once (`src/sidecar/fanout.js` line 170–175) and passed via `options.client` / `options.server` to every `runHeadless` call.
|
|
65
|
+
- **Context built once.** `buildContext()` and `buildPrompts()` are called once before the leg loop (fanout.js lines 153–162); the resulting `systemPrompt` and `userMessage` are reused by all legs without per-leg re-serialisation.
|
|
66
|
+
- **Legs are ordinary sessions.** Each leg is an independent `runHeadless` session. Leg IDs follow the pattern `<waveId>-1`, `<waveId>-N` derived by `deriveLegIds()` (fanout.js line 37–39). Leg metadata carries `parentWave: waveId` (fanout-leg.js line 52).
|
|
67
|
+
- **Atomic wave document.** After all legs settle, `wave.json` is written atomically via a `.tmp` + rename sequence in the wave session directory (fanout.js lines 222–224). If the file is absent (e.g. hard kill), `buildWaveResultFromSession()` rebuilds it live from per-leg metadata.json files (`src/utils/result-schema.js` lines 179–217).
|
|
68
|
+
- **Per-leg watchdog backstop.** Each leg runs its own `IdleWatchdog` set to `timeoutMs + 60s` (fanout-leg.js lines 59–70). On timeout it marks only that leg aborted; it never calls `server.close()` or `process.exit()` — shared server safety.
|
|
69
|
+
- **Dead-server fast-exit.** Consecutive poll failures against a dead server exit immediately instead of burning the full timeout. The threshold is `AMICUS_MAX_CONSECUTIVE_POLL_FAILURES` (default 15, ≈ 30 s at 2 s polls), defined at `src/headless.js` line 33.
|
|
70
|
+
- **Signal handling.** On SIGINT or SIGTERM, the wave marks itself and all leg directories aborted, closes the server, then arms an exit watchdog. A second signal causes an immediate `process.exit(130/143)`. The control flow then proceeds through step 7 (aggregate + write `wave.json` + emit), so even an aborted wave produces a parseable JSON document (fanout.js lines 183–195, 227–229).
|
|
71
|
+
- **Wave status aggregation** (`src/utils/result-schema.js` lines 83–90):
|
|
72
|
+
- Any leg still running → `running`
|
|
73
|
+
- All legs complete → `complete`
|
|
74
|
+
- ≥ 1 complete, others failed → `partial`
|
|
75
|
+
- 0 complete, ≥ 1 aborted → `aborted`
|
|
76
|
+
- All failed (no complete, no aborted) → `error`
|
|
77
|
+
- **Exit codes** (result-schema.js lines 97–101): `complete` → 0, `partial` → 2, all other statuses → 1.
|
|
78
|
+
|
|
79
|
+
## IdleWatchdog State Machine
|
|
80
|
+
|
|
81
|
+
Each Amicus process runs an `IdleWatchdog` that transitions between two states:
|
|
82
|
+
|
|
83
|
+
- **BUSY**: A prompt is in flight or a session was recently active. Idle timer is paused.
|
|
84
|
+
- **IDLE**: No active requests for the configured idle period. Process (or shared server) self-terminates.
|
|
85
|
+
|
|
86
|
+
Transitions: `BUSY → IDLE` when the last active session goes quiet; `IDLE → BUSY` on any new incoming request. The idle clock resets on each BUSY→IDLE transition.
|
|
87
|
+
|
|
88
|
+
Timeout resolution priority (highest wins):
|
|
89
|
+
1. Per-mode env var: `AMICUS_IDLE_TIMEOUT_HEADLESS`, `AMICUS_IDLE_TIMEOUT_INTERACTIVE`, `AMICUS_IDLE_TIMEOUT_SERVER` (in minutes; the legacy `SIDECAR_IDLE_TIMEOUT_*` env-compat shim was removed in v2.0.0 — see `docs/SHIMS.md`)
|
|
90
|
+
2. Blanket env var `AMICUS_IDLE_TIMEOUT` in minutes
|
|
91
|
+
3. Constructor `timeout` option in milliseconds
|
|
92
|
+
4. Mode defaults: headless=15 m, interactive=60 m, server=30 m
|
|
93
|
+
|
|
94
|
+
Set the appropriate per-mode env var to `0` to disable self-termination for that mode entirely.
|
|
95
|
+
|
|
96
|
+
## Electron BrowserView Architecture
|
|
97
|
+
|
|
98
|
+
The Electron shell (`electron/main.js`) uses a **BrowserView** to avoid CSS conflicts between the OpenCode SPA and the Amicus toolbar:
|
|
99
|
+
|
|
100
|
+
- **BrowserView** (top): Loads the OpenCode web UI at `http://localhost:<port>`. Gets its own physical viewport, no CSS interference with the host window.
|
|
101
|
+
- **Main window** (bottom 40px): Renders the Amicus toolbar (branding, task ID, timer, Fold button) via a `data:` URL.
|
|
102
|
+
- On resize, `updateContentBounds()` adjusts the BrowserView to fill `height - 40px`.
|
|
103
|
+
|
|
104
|
+
This replaced earlier CSS-based approaches (`padding-bottom`, `calc(100dvh - 40px)`) which failed because OpenCode's Tailwind `h-dvh` class resolves to the actual browser viewport and ignores parent element overrides.
|