amicus 4.6.3 → 4.7.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.
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +349 -0
- package/README.md +19 -7
- package/bin/amicus.js +31 -0
- package/docs/ROADMAP.md +143 -36
- package/docs/configuration.md +52 -4
- package/docs/council.md +65 -12
- package/docs/doc-system.md +8 -7
- package/docs/schemas.md +10 -1
- package/docs/testing.md +1 -1
- package/docs/troubleshooting.md +33 -5
- package/docs/usage.md +64 -14
- package/electron/workspace-ui/index.html +3 -0
- package/electron/workspace-ui/live-model.js +52 -14
- package/electron/workspace-ui/workspace-app.js +14 -3
- package/electron/workspace-ui/workspace-lazy.js +233 -0
- package/electron/workspace-ui/workspace-matrix.js +12 -1
- package/electron/workspace-ui/workspace-panels.js +24 -171
- package/electron/workspace-ui/workspace-render.js +6 -2
- package/electron/workspace-ui/workspace-seats.js +68 -0
- package/electron/workspace-ui/workspace.css +6 -0
- package/package.json +8 -4
- package/schemas/council-run.schema.json +1 -0
- package/schemas/council-stats.schema.json +9 -1
- package/schemas/run.schema.json +2 -1
- package/schemas/spend.schema.json +1 -1
- package/schemas/wave.schema.json +2 -1
- package/scripts/postinstall.js +6 -3
- package/scripts/setup-hooks.js +49 -3
- package/skills/second-opinion/MANUAL-ORCHESTRATION.md +12 -0
- package/skills/second-opinion/MODEL-NOTES.md +5 -4
- package/skills/sidecar/SKILL.md +9 -2
- package/src/cli-council-run-bench.js +86 -0
- package/src/cli-handlers-council-run.js +65 -81
- package/src/cli-handlers-council.js +17 -5
- package/src/cli-handlers-fanout.js +179 -0
- package/src/cli-handlers-pack.js +24 -10
- package/src/cli-handlers-resume-continue.js +20 -0
- package/src/cli-handlers-run.js +19 -161
- package/src/cli-template-args.js +48 -0
- package/src/cli.js +39 -46
- package/src/council/debate.js +89 -10
- package/src/council/ledger.js +72 -11
- package/src/council/report.js +17 -6
- package/src/council/run-assemble.js +15 -3
- package/src/council/run-budget.js +2 -2
- package/src/council/run-chair.js +61 -5
- package/src/council/run-debate.js +51 -67
- package/src/council/run-launch.js +20 -2
- package/src/council/run-retry.js +17 -2
- package/src/council/run-stage1-launch.js +94 -0
- package/src/council/run-stage2.js +25 -4
- package/src/council/run-stages.js +79 -86
- package/src/council/run-state.js +10 -2
- package/src/council/run.js +26 -2
- package/src/council/tally.js +6 -2
- package/src/headless.js +69 -6
- package/src/mcp-council-awareness.js +1 -0
- package/src/mcp-council-bench.js +4 -0
- package/src/mcp-council-run.js +10 -0
- package/src/mcp-server.js +114 -54
- package/src/mcp-tools.js +12 -5
- package/src/pack/pack-cli.js +1 -1
- package/src/pack/pack-forward.js +12 -4
- package/src/pack/pack-resolve.js +3 -0
- package/src/pack/pack-store.js +20 -3
- package/src/pack/pack-validate.js +5 -1
- package/src/sidecar/budget.js +38 -4
- package/src/sidecar/continue.js +8 -23
- package/src/sidecar/fanout-budget.js +1 -2
- package/src/sidecar/fanout-leg-fallback.js +7 -3
- package/src/sidecar/fanout-retry.js +15 -3
- package/src/sidecar/fanout-wave-io.js +13 -1
- package/src/sidecar/fanout.js +11 -9
- package/src/sidecar/list-limit.js +50 -0
- package/src/sidecar/list-search.js +69 -0
- package/src/sidecar/read.js +90 -5
- package/src/sidecar/reopen-spend.js +32 -0
- package/src/sidecar/resume.js +1 -1
- package/src/sidecar/start-metadata.js +58 -0
- package/src/sidecar/start.js +8 -43
- package/src/sidecar/workspace-auto-open.js +2 -2
- package/src/spend-query.js +2 -1
- package/src/template/apply.js +7 -4
- package/src/template/render.js +6 -2
- package/src/template/store.js +1 -1
- package/src/utils/cli-preflight.js +27 -1
- package/src/utils/config.js +15 -0
- package/src/utils/doctor-engine-check.js +32 -0
- package/src/utils/engine-install-scan.js +98 -15
- package/src/utils/engine-repair.js +96 -2
- package/src/utils/remediation-hints.js +29 -0
- package/src/utils/result-schema-rebuild.js +1 -0
- package/src/utils/result-schema.js +6 -1
- package/src/utils/session-index-tmp-sweep.js +18 -3
- package/src/utils/session-index.js +1 -0
- package/src/utils/session-metadata-tmp-sweep.js +24 -4
- package/src/utils/spend-ledger.js +11 -4
- package/src/utils/validators.js +16 -0
package/docs/ROADMAP.md
CHANGED
|
@@ -2,19 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
**Reprioritization guidance (Christian, 2026-07-18):** engine-first is locked; the near-term work
|
|
4
4
|
ships as an incremental **4.x point-release line**, each rev delivering a **behavioral / feature
|
|
5
|
-
benefit users feel
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
benefit users feel**. The observability arc is split so the **data layer ships first (v4.3)** and
|
|
6
|
+
the **Electron "Council Workspace" (v4.4)** rides on top of it. `--dry-run` cost preview dropped to
|
|
7
|
+
the backlog.
|
|
8
|
+
|
|
9
|
+
**Amendment (Christian, 2026-08-05): enterprise-readiness leaves the rev pipeline.** It was carried
|
|
10
|
+
here as a numbered **v5.0** heading, which made it read as *scheduled work with a version reserved
|
|
11
|
+
for it* — a commitment the product cannot make while it is gated on funding and a cofounder. It now
|
|
12
|
+
lives under **Backlog (tracked, not scheduled)** with everything else that is real but unscheduled.
|
|
13
|
+
Nothing about the content changed and no judgment about its value is implied; only its status. When
|
|
14
|
+
an org buyer and the org to support them exist, it earns a number then.
|
|
15
|
+
|
|
16
|
+
Amicus is at **v4.7.0** (tagged 2026-08-08). Each 4.x rev below leads with the benefit, not the
|
|
11
17
|
plumbing.
|
|
12
18
|
|
|
13
|
-
**Status:** v4.0 through **v4.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
**Status:** v4.0 through **v4.7.0** have **shipped** — everything on this page is a record of what
|
|
20
|
+
landed, not a plan. Composition — the scope that
|
|
21
|
+
carried the number v4.6 here until the degrade-announcement-invariant milestone took the v4.6.0
|
|
22
|
+
release (2026-08-02) — is now an unscheduled candidate for the next rev, tabled in its own section
|
|
23
|
+
below (dropped from v4.7, 2026-08-05); its contents are decided at kickoff per the anti-rot rule,
|
|
24
|
+
not assumed in advance. There is **no numbered major** on this roadmap.
|
|
18
25
|
|
|
19
26
|
> 📁 **Reading this from an npm install?** Some references below point at working documents that
|
|
20
27
|
> live in the git repository and are deliberately **not** in the published package — anything under
|
|
@@ -169,20 +176,78 @@ fooled, and a handful of proven small defects land with tests.
|
|
|
169
176
|
path; the README/install scripts/doctor all agree on the real Node ≥22.12 floor; eleven
|
|
170
177
|
duplicated doctor test fixtures consolidate into one factory — #110
|
|
171
178
|
|
|
172
|
-
## v4.7 — "
|
|
173
|
-
**Benefit:**
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
179
|
+
## v4.7 — "The count is the count" — ✅ SHIPPED v4.7.0, 2026-08-08
|
|
180
|
+
**Benefit:** every number amicus shows you is the number — what a council cost, which legs ran, and
|
|
181
|
+
which model earned the credit.
|
|
182
|
+
|
|
183
|
+
**Shipped across ten `v4.7-*` PRs** — PR0 (extractions) through PR7, plus the PR3 riders and a
|
|
184
|
+
closing documentation pass: the `runStats` completeness half of CA-4, the GOA-7 ledger
|
|
185
|
+
prerequisite, F8 session/wave tagging with `--search`, and four correction sweeps (PR4–PR7).
|
|
186
|
+
|
|
187
|
+
**Why this scope, and why it replaced composition.** Rescoped after a roadmap review on 2026-08-05
|
|
188
|
+
(the number was carried here as v4.6 until the degrade-announcement-invariant milestone took the
|
|
189
|
+
v4.6.0 release) that started from *how the tool is actually used* rather than from the deferral
|
|
190
|
+
list. Two findings drove it:
|
|
191
|
+
|
|
192
|
+
1. **The Workspace is an instrument panel, not a workspace** (owner, 2026-08-05): it is used for
|
|
193
|
+
**live status while a council runs** and for **quantitative stats** — *never* to read council
|
|
194
|
+
output, which is read in the terminal or through the orchestrating agent. That retires the F10
|
|
195
|
+
ergonomics line wholesale (all three items are reading/working affordances) and promotes anything
|
|
196
|
+
that makes the numbers right.
|
|
197
|
+
2. **`runStats` is a cost source, not just a record.** Verified at `8d0584a`:
|
|
198
|
+
`cli-handlers-council.js:56` computes `amicus council stats` cost as
|
|
199
|
+
`sumWaveUsage(r.runStats).cost` with **no fallback**; `council/report.js:79` falls back to
|
|
200
|
+
`sumWaveUsage(runStats).cost` when wave usage is absent; `council/ledger.js:24` joins street-cred
|
|
201
|
+
off the same array. So CA-4's omissions are not a schema nicety — they under-report spend on the
|
|
202
|
+
surface the owner relies on, which collides with the cost-truth principle (*reported > estimated
|
|
203
|
+
> unknown; never fabricate $0*). An omitted leg is not "unknown" — it renders as money never
|
|
204
|
+
spent on legs that spent money.
|
|
205
|
+
|
|
206
|
+
> **Tense note.** The bullets below were written as pre-work problem statements and are kept for
|
|
207
|
+
> the record of *why* the rev was scoped this way. Each now leads with what shipped; the
|
|
208
|
+
> problem-statement text that follows it is history, not a live defect.
|
|
209
|
+
|
|
210
|
+
- **CA-4 (remaining half) — `runStats` completeness** *(M)*: **shipped.** Stage-2 judges and repair
|
|
211
|
+
solos *were* absent from `tally.json`'s `runStats` (observed: 5 rows for 11 real legs in
|
|
212
|
+
`wsgate04`); `runStats` now carries one row per paid launch — one `judge` row per judge
|
|
213
|
+
(`run-assemble.js:180-184`) and one `repair` row per `-q<N>` solo, failed ones included
|
|
214
|
+
(`run-stage2.js:122`).
|
|
215
|
+
⚠️ **Scope correction:** the failed-chair third of the original CA-4 is **closed** — v4.6.2's
|
|
216
|
+
`chairAttempts[]` records every attempt on `run.json` (`run-chair.js:133` cites LC-5 by name), and
|
|
217
|
+
failed-chair cost already reaches `runStats` too: a failed ch1–ch3 attempt gets its own
|
|
218
|
+
`chair-attempt` row there carrying that leg's real `usage` (`run-chair.js:154-156`), so no third
|
|
219
|
+
row class was needed.
|
|
220
|
+
- **GOA-7 prerequisite — segment the ledger by RESOLVED model, not alias** *(S–M)*: **shipped.**
|
|
221
|
+
`ledger.js:124` now keys on `row.resolvedModel || row.model` and `LEDGER_SCHEMA_VERSION` is 2.
|
|
222
|
+
It *was* a live defect: ledger rows keyed by council alias and aliases silently retarget (`gpt-pro` →
|
|
223
|
+
`gpt-5.6-sol-pro`, the `opus` re-pin — both 2026-08-04), so `council stats` conflates distinct
|
|
224
|
+
models under one name. The ledger is append-only, so every run adds rows that will later have to
|
|
225
|
+
be distrusted, and both GOA-1 and GOA-2 plan to build on this data. Bump `LEDGER_SCHEMA_VERSION`;
|
|
226
|
+
old rows stay readable (absent id ⇒ legacy). Full write-up and schema discipline: `BACKLOG.md`
|
|
227
|
+
GOA-7. *(Recency decay — GOA-7's second half — is NOT in this rev.)*
|
|
228
|
+
- **Session/wave tagging + `--search` + grouped history** (F8) *(S–M)* — **shipped**
|
|
229
|
+
(`--tag`, `amicus list --search`, `--limit`, `spend --group-by tag`). The one element carried
|
|
230
|
+
over from the composition scope, and the one with a visible paper trail: this repo's own
|
|
231
|
+
`BACKLOG.md` hand-maintained an index of run identifiers (`wave 47278069`, `run dfb6a692`,
|
|
232
|
+
`runs 0084d48c + 2039b2d1`, `wsgate02`/`wsgate04`) **because there was no search**. It is also the
|
|
233
|
+
rev's only daily-felt user surface — three schema fixes alone are a thin story.
|
|
234
|
+
- **README + docs update** *(S)* — the last scope line; **closed by PR #132**, which corrected the
|
|
235
|
+
sentences v4.7 had made false rather than adding coverage the feature PRs had already shipped.
|
|
236
|
+
|
|
237
|
+
> **Why these belong in one rev.** CA-4 and GOA-7's prerequisite are the same defect class — the run
|
|
238
|
+
> record under-reporting what actually happened — and both are schema-shaped. Each was individually
|
|
239
|
+
> deferred with the same reason (*"M, a schema question, not a fix"*), which is exactly why neither
|
|
240
|
+
> has ever been done: too big for a patch, too small to carry a rev alone. One schema pass is
|
|
241
|
+
> materially cheaper than two.
|
|
242
|
+
>
|
|
243
|
+
> **Lineage.** v4.6 made a loss announce itself; v4.7 makes the accounting match reality. Same
|
|
244
|
+
> invariant family, applied to numbers instead of degradation.
|
|
245
|
+
>
|
|
246
|
+
> ⚠️ **Two hard gates apply before any task touches council internals** — see `BACKLOG.md`
|
|
247
|
+
> *Next-rev hard gates*: the tight-file extraction pass (`cli-handlers-council-run.js` is at
|
|
248
|
+
> **299/300 exactly**, `run-debate.js` at 299, two files **at 300**), and KNOWN_VARIABLES
|
|
249
|
+
> single-sourcing **only if** `{{input}}` is ever scoped — it is not in this rev, so that gate
|
|
250
|
+
> travels with composition rather than blocking here.
|
|
186
251
|
|
|
187
252
|
### Deferred out of v4.4.1 into v4.5 (2026-07-27)
|
|
188
253
|
|
|
@@ -202,7 +267,7 @@ a proposed disposition — v4.5 ride-along / v4.6 / backlog — tabled for rulin
|
|
|
202
267
|
| **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 |
|
|
203
268
|
| **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 |
|
|
204
269
|
| **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 |
|
|
205
|
-
|
|
|
270
|
+
| ~~**LC-5**~~ | ~~A chair fallback leaves no trace in `run.json`~~ — ✅ **CLOSED by v4.6.2**: `chairAttempts[]` records every attempt (`{waveId, model, outcome, reason}`), checkpointed after each; `run-chair.js:113` cites LC-5 by name. **Do not re-file.** | — |
|
|
206
271
|
| **RN-1** | `sanitizeName` collisions surface as a banner rather than a refusal | `S` + a product decision that was already argued once |
|
|
207
272
|
| **RN-2** | `renderRunList` blind masking is best-effort — only the open run resolves labels | `M` |
|
|
208
273
|
| **RN-5** | A blind-mode flip closes every open prose panel and repaints twice | `S–M` |
|
|
@@ -219,15 +284,6 @@ record ("eleven `Number(env) || default` sites"), not a task — a blanket migra
|
|
|
219
284
|
six new defects to fix one, and `src/utils/env-num.js`'s docblock records which knobs deliberately
|
|
220
285
|
keep the old form.
|
|
221
286
|
|
|
222
|
-
## v5.0 — Enterprise-readiness *(the deliberate major jump — a venture unto itself, gated on funding / cofounder)*
|
|
223
|
-
**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.
|
|
224
|
-
- Secret-store backends + env-var-only mode (A3); org allowlists/blocklists, per-team cost ceilings, read-only enforcement (A6); RBAC
|
|
225
|
-
- Audit & compliance: reproducibility manifests + replay (B11), seed/temp/version pinning (A7), spend export to SIEM/warehouse (A10), `/health` + metrics + structured logging (A8)
|
|
226
|
-
- Team config `.amicusrc` (A9); spend **governance** (per-team caps/enforcement) — the governance half of A4
|
|
227
|
-
- 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)
|
|
228
|
-
- README + docs update: deployment/admin documentation for the above, in `README.md` and `docs/`
|
|
229
|
-
> These cluster because they share one prerequisite you don't have yet: an org buyer + the org to support. Revisit as a funded track.
|
|
230
|
-
|
|
231
287
|
---
|
|
232
288
|
|
|
233
289
|
### Design notes — auto-open the Council Workspace
|
|
@@ -271,6 +327,57 @@ LC-10) that stretch the definition; a third that pops a GUI window would not be
|
|
|
271
327
|
patch. Sits naturally beside v4.5's existing **GUI power ergonomics (F10)** line.
|
|
272
328
|
|
|
273
329
|
## Backlog (tracked, not scheduled)
|
|
330
|
+
|
|
331
|
+
### Enterprise-readiness *(unscheduled — gated on funding / cofounder)*
|
|
332
|
+
*Moved here from a numbered `v5.0` heading, 2026-08-05. Content unchanged; only its status. It was
|
|
333
|
+
never a rev — it is a distinct product and go-to-market motion (SOC2, SLAs, sales, support), and per
|
|
334
|
+
the chair's hard-question #5 a solo dev can't credibly ship or support it alone. These items cluster
|
|
335
|
+
because they share one prerequisite that does not exist yet: **an org buyer, and the org to support
|
|
336
|
+
them.** Revisit as a funded track; it earns a version number when that track is real.*
|
|
337
|
+
- Secret-store backends + env-var-only mode (A3); org allowlists/blocklists, per-team cost ceilings, read-only enforcement (A6); RBAC
|
|
338
|
+
- Audit & compliance: reproducibility manifests + replay (B11), seed/temp/version pinning (A7), spend export to SIEM/warehouse (A10), `/health` + metrics + structured logging (A8)
|
|
339
|
+
- Team config `.amicusrc` (A9); spend **governance** (per-team caps/enforcement) — the governance half of A4
|
|
340
|
+
- 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)
|
|
341
|
+
- README + docs update: deployment/admin documentation for the above, in `README.md` and `docs/`
|
|
342
|
+
> ⚠️ **B4 (reliability-aware seat selection) now overlaps live backlog work.** `GOA-1` (auto-bench
|
|
343
|
+
> query-aware seat selection, filed 2026-08-05 in `BACKLOG.md`) blends the street-cred ledger into
|
|
344
|
+
> seat choice — that is B4's core idea arriving as a single-user feature rather than an enterprise
|
|
345
|
+
> learning loop. Reconcile before either is scoped; do not build both.
|
|
346
|
+
|
|
347
|
+
### Composition / chained waves (F6) *(unscheduled — dropped from v4.7, 2026-08-05)*
|
|
348
|
+
`--input-from <id>` / `--prompt-file -` pipe + per-source digests *(M)*, bringing the `{{input}}`
|
|
349
|
+
template variable and the `critique`/`refine` built-ins.
|
|
350
|
+
|
|
351
|
+
*Not cancelled — waiting on a use case that asks for it.* The reasoning, recorded so it is not
|
|
352
|
+
re-argued from scratch: **the chaining already happens, performed by the orchestrating agent.** When
|
|
353
|
+
a council needs to critique a previous council's output, Claude reads run A's verdict and composes
|
|
354
|
+
run B's prompt — adapting the handoff, dropping what is irrelevant, reframing what matters. A fixed
|
|
355
|
+
`--input-from` digest is *less* flexible than that for interactive use. The feature's real
|
|
356
|
+
beneficiary is **headless/CI chaining, where no orchestrator is in the loop** — and the one headless
|
|
357
|
+
consumer today (the Council Review GitHub Action) runs a single review per PR, not a chain.
|
|
358
|
+
|
|
359
|
+
**Revisit when:** a headless or scheduled workflow genuinely needs to chain councils without an
|
|
360
|
+
agent driving it, or the `critique`/`refine` built-ins are wanted on their own — those are a much
|
|
361
|
+
smaller slice than the chaining machinery and could ship independently of F6.
|
|
362
|
+
|
|
363
|
+
⚠️ **Carries its own hard gate:** KNOWN_VARIABLES single-sourcing (`src/template/render.js:45` keeps
|
|
364
|
+
two hand-maintained copies of the known-variable set) must land **before** `{{input}}` does. See
|
|
365
|
+
`BACKLOG.md` *Next-rev hard gates* — that gate travels with this item, not with v4.7.
|
|
366
|
+
|
|
367
|
+
### GUI power ergonomics (F10) *(unscheduled — dropped from v4.7, 2026-08-05)*
|
|
368
|
+
Focus-follows-fold hotkey, distinguishable window titles, tiling presets *(S each)*.
|
|
369
|
+
|
|
370
|
+
Dropped on an owner usage finding, recorded here because it should inform every future GUI decision:
|
|
371
|
+
**the Council Workspace is used as an instrument panel — live status while a council runs, plus
|
|
372
|
+
quantitative stats — and never to read council output.** All three F10 items are reading/working
|
|
373
|
+
ergonomics for a surface that is not used that way; "distinguishable window titles" and "tiling
|
|
374
|
+
presets" both presuppose multi-window reading sessions that do not happen.
|
|
375
|
+
|
|
376
|
+
**Consequence beyond F10:** GUI work should be judged on *live-status fidelity* and *stat accuracy*
|
|
377
|
+
first. The prose-panel and blind-masking nits (RN-2, RN-5, the `T19-*`/`T20-*` family in
|
|
378
|
+
`BACKLOG.md`) sit on the unused half of the surface and should rank accordingly.
|
|
379
|
+
|
|
380
|
+
### Other tracked items
|
|
274
381
|
- **`--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.
|
|
275
382
|
- **F7** — Parallel council panels + super-chair (opt-in `--panels N` high-assurance; niche).
|
|
276
383
|
- **E7** — Prompt dedup cache (exact-dup, opt-in, excludes council/fanout) — minor cost optimization.
|
|
@@ -285,6 +392,6 @@ patch. Sits naturally beside v4.5's existing **GUI power ergonomics (F10)** line
|
|
|
285
392
|
- **Local providers stays near-term** (v4.2) — a broad cost/privacy benefit, not enterprise.
|
|
286
393
|
- **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.
|
|
287
394
|
- **`--dry-run` cost preview → backlog** (was in the observability rev).
|
|
288
|
-
- **Enterprise/governance/audit/compliance/learning-loops → v5.0**, reframed as the deliberate *major-version venture* gated on funding.
|
|
395
|
+
- **Enterprise/governance/audit/compliance/learning-loops → v5.0**, reframed as the deliberate *major-version venture* gated on funding. **Superseded 2026-08-05:** moved out of the rev pipeline entirely, into *Backlog (tracked, not scheduled)*. A reserved version number read as a commitment; it isn't one.
|
|
289
396
|
- The **cheap trust fixes** (envelope, injection fencing, fold nonce) pulled into **v4.0** because the engine needs them to be trustworthy in automation.
|
|
290
397
|
- **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/configuration.md
CHANGED
|
@@ -238,7 +238,7 @@ Everything lives under `~/.config/amicus/` (`getConfigDir()` in `src/utils/confi
|
|
|
238
238
|
| `.env` | `amicus setup` / `amicus key` | API keys (`OPENROUTER_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY`, `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `DEEPSEEK_API_KEY`). `0600` permissions. |
|
|
239
239
|
| `model-catalog.json` | `refreshCatalog()` (`src/utils/model-catalog.js`) | The cached provider model list, schema-versioned, with a **24-hour TTL**. Also carries refresh-outcome fields — `lastRefreshAttempt` and `lastRefreshError` — stamped on a *failed* refresh without touching the last-good `models`/`fetchedAt` (a bad fetch never clobbers a good cache). Human-readable JSON; safe to delete, it rebuilds on next use. |
|
|
240
240
|
| `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. |
|
|
241
|
-
| `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`. |
|
|
241
|
+
| `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. At `LEDGER_SCHEMA_VERSION` **2** (v4.7 GOA-7), rows may also carry `resolvedModel` (the executable id that served); legacy-read, no migration — a row without one (all pre-v2 history, plus leg-less rows) aggregates under its alias, and a group is marked `legacy` only when every row in it lacks `resolvedModel`. Read back by `amicus council stats`. |
|
|
242
242
|
| `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). |
|
|
243
243
|
| `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). |
|
|
244
244
|
| `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). |
|
|
@@ -287,8 +287,20 @@ Per-session directory contents:
|
|
|
287
287
|
**Fanout waves.** A wave (`amicus fanout`) gets its own session dir at `<waveId>` (same
|
|
288
288
|
`amicus_sessions/` root); each leg is a full sibling session dir named `<waveId>-1` through
|
|
289
289
|
`<waveId>-N` (`deriveLegIds()` in `src/sidecar/fanout.js`). The wave-heartbeat display reads each
|
|
290
|
-
leg's `progress.json`/`conversation.jsonl` directly
|
|
291
|
-
|
|
290
|
+
leg's `progress.json`/`conversation.jsonl` directly. The wave dir itself holds:
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
<waveId>/
|
|
294
|
+
metadata.json # type "wave", legs: [...], plus a 200-char rendered briefing excerpt
|
|
295
|
+
wave.json # written on completion
|
|
296
|
+
briefing.md # the RENDERED prompt — the corpus `amicus list --search` matches against.
|
|
297
|
+
# Written by mcp-server.js BEFORE the child spawns (so an aborted wave
|
|
298
|
+
# stays searchable), and again by fanout.js:145 once the child runs
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
One more file appears only for an `amicus_fanout` wave whose prompt came from a **template**: a
|
|
302
|
+
sibling `briefing-input.md` holding the raw pre-render prompt handed to the spawned child, so the
|
|
303
|
+
child's own re-render stays byte-identical and `promptMeta.template` provenance survives.
|
|
292
304
|
|
|
293
305
|
### Log location + LOG_LEVEL
|
|
294
306
|
|
|
@@ -383,6 +395,42 @@ a hard-coded built-in (`DEFAULTS` in `src/cli.js`) — so for those the chain is
|
|
|
383
395
|
pack > built-in** today. See [Policy packs](./usage.md#policy-packs) for the full per-kind field
|
|
384
396
|
reference.
|
|
385
397
|
|
|
398
|
+
### Cost gate
|
|
399
|
+
|
|
400
|
+
Two independent pre-flight guards run before a paid model call, both set via top-level
|
|
401
|
+
`config.json` keys that are **hand-edited only** — no wizard or CLI command writes them
|
|
402
|
+
(`src/sidecar/budget.js`):
|
|
403
|
+
|
|
404
|
+
- **`maxCostPerMtok`** — hard per-$/Mtok refusal threshold. Refuses any leg whose catalog
|
|
405
|
+
price-per-Mtok exceeds the cap. Defaults to **60**; a non-positive value falls back to that
|
|
406
|
+
default.
|
|
407
|
+
- **`maxCost`** — soft ceiling on the estimated total $ for the call. Absent, zero or negative all
|
|
408
|
+
mean no ceiling.
|
|
409
|
+
|
|
410
|
+
> ⚠️ **`0` means the opposite thing on each key.** `maxCostPerMtok: 0` falls back to the default 60,
|
|
411
|
+
> so that guard stays **on**; `maxCost: 0` disables the ceiling entirely. Neither key is turned off
|
|
412
|
+
> by setting it to zero in the way you might expect — use `--no-cost-gate` (CLI) or
|
|
413
|
+
> `noCostGate` (`amicus_council_run`) to actually disable them.
|
|
414
|
+
|
|
415
|
+
```jsonc
|
|
416
|
+
{
|
|
417
|
+
"maxCostPerMtok": 60,
|
|
418
|
+
"maxCost": 5
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
On the CLI, `--max-cost <$>` overrides `maxCost` for that call, and `--no-cost-gate` disables both
|
|
423
|
+
guards (e.g. for an intentional o3 run).
|
|
424
|
+
|
|
425
|
+
Over MCP the per-call override depends on the tool. `amicus_council_run` takes its own `maxCost`
|
|
426
|
+
and `noCostGate` params, which forward to the spawned child exactly as the CLI flags do.
|
|
427
|
+
**`amicus_start` takes neither.** On that path `maxCostPerMtok` is config-only and nothing can turn
|
|
428
|
+
the gate off at all; the soft ceiling is the **effective** `maxCost` — the pack's if the run used a
|
|
429
|
+
pack that set one, otherwise the config's (`mcp-server.js:454`). Only one of those two values is in
|
|
430
|
+
effect, so raising the other one changes nothing. See
|
|
431
|
+
[Troubleshooting: MCP run fails with "budget gate refused the
|
|
432
|
+
run"](./troubleshooting.md#mcp-run-fails-with-budget-gate-refused-the-run).
|
|
433
|
+
|
|
386
434
|
### Uninstall instructions
|
|
387
435
|
|
|
388
436
|
`npm uninstall -g amicus` removes the package and its bin shims. It does **not** clean up everything
|
|
@@ -412,6 +460,6 @@ aliases, and council presets carry over untouched.
|
|
|
412
460
|
| `eslint` ^8.0.0 | Code linting |
|
|
413
461
|
| `lint-staged` ^16.3.2 | Run linters on staged files |
|
|
414
462
|
|
|
415
|
-
|
|
463
|
+
The bundled **`opencode-ai`** engine (pinned to `1.18.15`, matched by `@opencode-ai/sdk`) installs automatically as a normal dependency — you don't install it separately. Its own postinstall lays down the per-platform binaries.
|
|
416
464
|
|
|
417
465
|
> **Legacy names.** Pre-rebrand `SIDECAR_*` environment variables were removed entirely in v2.0.0 — they are no longer read, with no warning. Rename to the `AMICUS_*` equivalents documented above. See [docs/SHIMS.md](./SHIMS.md) for the full removal record and rename table.
|
package/docs/council.md
CHANGED
|
@@ -85,9 +85,15 @@ Three things to hold onto:
|
|
|
85
85
|
changed for them.** The skill's opt-in elements (critic seat, expert lenses, debate mode, chair
|
|
86
86
|
verdict scale — see [SKILL.md](../skills/second-opinion/SKILL.md) and
|
|
87
87
|
[SEAT-BRIEFS.md](../skills/second-opinion/SEAT-BRIEFS.md)) ride on existing engine surfaces:
|
|
88
|
-
seat roles travel as free-form `runStats[].role` labels
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
seat roles travel as free-form `runStats[].role` labels in the tally/verdict artifact
|
|
89
|
+
(`"critic"`, `"lens:<slug>"`, or any other skill-authored label) — **but since v4.7 the
|
|
90
|
+
council-ledger join reads only an allowlist** (`seat`, `critic`, `lens:*`, `chair`, `claude`,
|
|
91
|
+
`council`, `redteam` — see the `runStats[]` row inventory under
|
|
92
|
+
[`amicus council tally`](#amicus-council-tally)), so a custom/free-form label outside that set
|
|
93
|
+
still renders in the tally/report artifact but no longer contributes its
|
|
94
|
+
role/wasChair/conformance to `amicus council stats` reliability numbers. Debate mode runs the
|
|
95
|
+
Stage-2 tally with `--no-ledger` (provisional) and re-tallies after the rebuttal round (that
|
|
96
|
+
second, post-rebuttal tally is the ledger-recorded one), and lens runs always pass
|
|
91
97
|
`--no-ledger` so non-comparable reviews never feed `stats`.
|
|
92
98
|
|
|
93
99
|
---
|
|
@@ -322,8 +328,10 @@ launch:
|
|
|
322
328
|
discovered from the sessions-dir pointer files (`council-<runId>.json`); each row shows status,
|
|
323
329
|
the chair's `overallVerdict` chip once one exists, and cost.
|
|
324
330
|
- **Run detail** (`--ui <runId>`) — header + status/verdict chips, a stage rail, a live **Seats**
|
|
325
|
-
table (model, role, status, stage, messages, tokens, cost, last activity, a
|
|
326
|
-
|
|
331
|
+
table (model, role, status, stage, messages, tokens, cost, last activity, and a trailing flag
|
|
332
|
+
cell — `⏳ stalled` while live, or on a finished run `↻ retried once` marking a reviewing seat
|
|
333
|
+
whose once-only Stage-1 retry didn't save it), the Stage-1 reviews, the **verbatim** anonymized
|
|
334
|
+
Stage-2 packet (`bundle-stage2.md`, shown as-is —
|
|
327
335
|
never re-rendered), judge prose, the **adjudication matrix** (finding × judge, tier-colored
|
|
328
336
|
rows, `a/d/n` basis counts, a `thin` badge when `a+d<=1`, an override badge when a Stage-4
|
|
329
337
|
decision changed a finding's tier, capped at 500 rows with a "showing N of M" note past that),
|
|
@@ -532,8 +540,8 @@ model to the reliability ledger. Thin CLI wrapper over `tally()` (`src/council/t
|
|
|
532
540
|
### Tally-input schema
|
|
533
541
|
|
|
534
542
|
Claude assembles this file at the end of Stage 2 (the full assembly recipe is in
|
|
535
|
-
[SKILL.md](../skills/second-opinion/SKILL.md#
|
|
536
|
-
assembly recipe"). It needs **all five top-level keys** — `tally()` throws
|
|
543
|
+
[SKILL.md](../skills/second-opinion/SKILL.md#the-engine-run--stages-13-plus-the-stage-5-artifacts),
|
|
544
|
+
under "Stage-2 → tally assembly recipe"). It needs **all five top-level keys** — `tally()` throws
|
|
537
545
|
`Cannot read properties of undefined (reading 'map')` if `meta` or `findings` is missing:
|
|
538
546
|
|
|
539
547
|
| Field | Type | Meaning |
|
|
@@ -546,7 +554,44 @@ assembly recipe"). It needs **all five top-level keys** — `tally()` throws
|
|
|
546
554
|
| `findings[]` | array | One entry per finding across all reviews: `{id, raiser, severity}` (`claim` may ride along but isn't required by the tally engine). `id` is the run-global label (e.g. `A1`, `B2`) assigned during Stage-2 assembly, not the reviewer's local integer id. |
|
|
547
555
|
| `adjudications[]` | array | One entry per (judge × finding): `{findingId, judge, verdict}`, `verdict ∈ {agree, dispute, neutral}`. Include every judge's verdict on every finding, **including the raiser's own adjudication of its own finding** — the engine excludes it automatically when scoring (don't pre-filter it). |
|
|
548
556
|
| `rankings[]` | array | One entry per judge: `{judge, order}`. `order` is that judge's `FINAL RANKING:` block translated to model ids, e.g. `["gpt", "deepseek"]` (ties may use a nested array, e.g. `[["gpt","deepseek"], "mistral"]`). |
|
|
549
|
-
| `runStats[]` | array | One
|
|
557
|
+
| `runStats[]` | array | One row per paid launch (v4.7 spec §5 D1/D2 — no longer capped at one row per model; see the role roster below): `{model, role, wasChair, conformance, status, durationMs, usage, waveId?, resolvedModel?}`. May be `[]`. Any leg with no run document gets `durationMs: null, usage: null` — never invent a value. `waveId` is emit-only-when-set. `resolvedModel?` (v4.7) — the executable id that actually served the row's leg, emit-only-when-set; leg-less rows (the give-up chair row, dead seats with no leg, the claude row) never carry it. `model` stays the council alias. |
|
|
558
|
+
|
|
559
|
+
**`runStats[].role` roster (v4.7 row-per-launch).** Every leg the run budget counts gets exactly
|
|
560
|
+
one row, so a seat that needed a repair or lost a leg to a retry can now show up more than once.
|
|
561
|
+
|
|
562
|
+
*Primary rows* — exactly one per requested reviewing seat, unchanged in shape from pre-v4.7:
|
|
563
|
+
`seat`, `critic`, `lens:<slug>`, `judge`, `chair` (`wasChair: true`), synthetic `claude`, and the
|
|
564
|
+
legacy default `council` (pre-#83 rows, or hand-assembled tally input that never set a role). A
|
|
565
|
+
dead seat/critic/lens with no recovery, and a chair walk that gives up entirely, get an honest
|
|
566
|
+
primary **error** row too — the #83 judge treatment extended to every seat (`usage: null` on the
|
|
567
|
+
give-up chair; the dead leg's own usage on a dead seat/critic/lens).
|
|
568
|
+
|
|
569
|
+
*Non-primary rows* — `wasChair` always `false`: `chair-attempt` (a failed ch1–ch3 chair launch),
|
|
570
|
+
`repair` (a Stage-1 `-p`, Stage-2 `-q`, chair-ch4, or debate-born `-d<N>r`/`-rv-…r` solo — a
|
|
571
|
+
failed defense or re-vote repair), and `superseded` (a first leg a later attempt replaced — an
|
|
572
|
+
SL-2 retry or a debate repair) — all three new in v4.7's row-per-launch change — plus `rebuttal`
|
|
573
|
+
and `revote` (a `--debate` round's defense/re-vote legs; v4.1, pre-dating row-per-launch). All
|
|
574
|
+
five still cost money and land in `runStats`, so they raise the run's totals everywhere those are
|
|
575
|
+
summed. In `council report`'s cost table only `judge`/`chair-attempt`/`repair`/`superseded` get a
|
|
576
|
+
suffixed label (`rebuttal`/`revote` render unsuffixed); `council tally` has no per-row cost table
|
|
577
|
+
at all, only an aggregate. And only `chair-attempt`/`repair`/`superseded` are filtered out of the
|
|
578
|
+
Workspace seats panel — `rebuttal`/`revote` rows still render there.
|
|
579
|
+
|
|
580
|
+
`runStats[].waveId` names the exact wave/leg a row was built from, present **iff a real billed
|
|
581
|
+
leg backs the row** — e.g. the synthetic `claude` row, a give-up chair's error row, and a
|
|
582
|
+
leg-less dead-seat/critic/lens primary error row (the two SL-2 retry note-classes that never
|
|
583
|
+
produced a real leg for the seat at all) carry none. It's the join key the leg–row bijection
|
|
584
|
+
invariant suite (`tests/council/run-cost-bijection.test.js`) uses to prove every budget-counted
|
|
585
|
+
leg lands on exactly one row. `resolvedModel` follows the same emit-only-when-set discipline and
|
|
586
|
+
the same never-invent rule — it is never derived from the alias.
|
|
587
|
+
|
|
588
|
+
**Ledger-join consequence.** `council stats`'s reliability aggregation (`ledger.js`) only reads
|
|
589
|
+
rows whose role is in the allowlist above (`seat`, `critic`, `lens:*`, `chair`, `claude`,
|
|
590
|
+
`council`, `redteam`) — everything else, including all three new non-primary roles and any
|
|
591
|
+
custom/free-form label a skill or caller invents, is fail-closed excluded and never contributes
|
|
592
|
+
role/wasChair/conformance to reliability stats, even though it still renders in the tally/report
|
|
593
|
+
artifact. Since v4.7 the ledger row copies the joined row's `resolvedModel` and `council stats`
|
|
594
|
+
groups by `resolvedModel || model` — see the stats section below.
|
|
550
595
|
|
|
551
596
|
### Tally-record schema (what `tally()` returns / prints)
|
|
552
597
|
|
|
@@ -723,7 +768,10 @@ Since v4.0 (council schema v2), `--json` wraps the rows in the family envelope
|
|
|
723
768
|
`{ "schemaVersion": 2, "type": "council-stats", "models": [ … ] }` — the per-model row
|
|
724
769
|
shape below is unchanged. (Pre-4.0 emitted the bare array.)
|
|
725
770
|
|
|
726
|
-
**Output
|
|
771
|
+
**Output**: one row per RESOLVED model (v4.7 — rows that carry `resolvedModel` group by the
|
|
772
|
+
executable id that served; rows without one group by alias and are marked `legacy`). Each row
|
|
773
|
+
also lists `aliases[]` — every alias observed for the group, most recent first; the chair
|
|
774
|
+
fallback promotion launches `aliases[0]`.
|
|
727
775
|
|
|
728
776
|
| Field | Meaning |
|
|
729
777
|
|---|---|
|
|
@@ -733,6 +781,8 @@ shape below is unchanged. (Pre-4.0 emitted the bare array.)
|
|
|
733
781
|
| `lifetimeConfirmRate` | Mean, across runs, of `(findings this model raised that landed Confirmed) / (findings this model raised)`. `null` when `judged` was false for every run or the model raised nothing. |
|
|
734
782
|
| `lifetimeFactErrorRate` | Same shape, but for the `Disputed` tier — a proxy for how often the bench caught this model asserting something wrong. |
|
|
735
783
|
| `conformance` | Tally of `{clean, repaired, unstructured}` counts — how often this model's Stage-1 findings JSON needed a repair re-prompt. |
|
|
784
|
+
| `aliases` | Every alias (row-level `model` value) observed for this group, most recently observed first (v4.7). `aliases[0]` is the launch-preferred name. |
|
|
785
|
+
| `legacy` | `true` when every row in the group lacks `resolvedModel` — alias-keyed history from before resolved-id segmentation, or leg-less rows whose resolution is unknowable (v4.7). Omitted (not `false`) when the group has any resolved rows. |
|
|
736
786
|
|
|
737
787
|
This is the data source the `second-opinion` skill's Stage 0 model recommendations and the
|
|
738
788
|
`MODEL-NOTES.md` quantitative table both read — **never hand-edit reliability numbers there**;
|
|
@@ -910,11 +960,14 @@ _Legend: ✓ agree · ✗ dispute · – neutral · `*` raiser's own vote_
|
|
|
910
960
|
```bash
|
|
911
961
|
$ amicus council stats
|
|
912
962
|
model runs avg-cred confirm fact-err notes
|
|
913
|
-
deepseek 1 2.00 1.00 0.00 low-N
|
|
914
|
-
gpt 1 1.00 0.00 0.00 low-N
|
|
963
|
+
deepseek 1 2.00 1.00 0.00 low-N legacy
|
|
964
|
+
gpt 1 1.00 0.00 0.00 low-N legacy
|
|
915
965
|
```
|
|
916
966
|
|
|
917
|
-
(`low-N` because each model has only 1 recorded run — `runs < 3`.
|
|
967
|
+
(`low-N` because each model has only 1 recorded run — `runs < 3`. `legacy` because this
|
|
968
|
+
hand-assembled `tally-input.json` never sets `runStats[].resolvedModel` — v4.7 groups by
|
|
969
|
+
alias and marks the group `legacy` whenever none of its rows carry a resolved id; see
|
|
970
|
+
[`amicus council stats`](#amicus-council-stats) above.)
|
|
918
971
|
|
|
919
972
|
**7. Presets**, for reference (independent of the run above):
|
|
920
973
|
|
package/docs/doc-system.md
CHANGED
|
@@ -56,16 +56,18 @@ When running `--check` mode, the script validates every markdown link in CLAUDE.
|
|
|
56
56
|
|
|
57
57
|
## Plans Index
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
No plans index is generated **today**. `buildPlansIndex()` in `scripts/generate-docs.js` scans
|
|
60
|
+
`docs/plans/` and `docs/archive/plans/`, but neither directory exists in this repo, and
|
|
61
|
+
`runWriteMode()` writes `docs/plans/index.md` only when `docs/plans/` already exists — so the write
|
|
62
|
+
never fires. Note that guard is a runtime `fs.existsSync` check, not a disabled feature: creating
|
|
63
|
+
`docs/plans/` would silently reactivate it, emitting a bare list of `- [name](path)` links without
|
|
64
|
+
the per-plan first heading or date the old text here promised. Plans actually live in
|
|
65
|
+
`docs/superpowers/plans/`, uncataloged.
|
|
64
66
|
|
|
65
67
|
## Commands
|
|
66
68
|
|
|
67
69
|
```bash
|
|
68
|
-
node scripts/generate-docs.js # Regenerate all auto sections
|
|
70
|
+
node scripts/generate-docs.js # Regenerate all auto sections
|
|
69
71
|
node scripts/generate-docs.js --check # Verify everything is current (CI mode)
|
|
70
72
|
npm run generate-docs # Alias for write mode
|
|
71
73
|
npm run generate-docs:check # Alias for check mode
|
|
@@ -89,4 +91,3 @@ Hook order:
|
|
|
89
91
|
| "Marker not found" error | Ensure `<!-- AUTO:name -->` and `<!-- /AUTO:name -->` exist in CLAUDE.md |
|
|
90
92
|
| Stale markers after code change | Run `node scripts/generate-docs.js` manually |
|
|
91
93
|
| Cross-link validation failure | Fix the broken link in CLAUDE.md or create the missing file |
|
|
92
|
-
| Plans index missing | Run the script; it creates `docs/plans/index.md` |
|
package/docs/schemas.md
CHANGED
|
@@ -49,7 +49,16 @@ This is the one non-additive shape change in the envelope unification; migrate `
|
|
|
49
49
|
|
|
50
50
|
## Documented exclusions
|
|
51
51
|
|
|
52
|
-
- **The two JSONL ledgers** (`council-ledger.jsonl`, `spend-ledger.jsonl`): internal
|
|
52
|
+
- **The two JSONL ledgers** (`council-ledger.jsonl`, `spend-ledger.jsonl`): internal
|
|
53
|
+
append-only storage, not emitted/published docs. `spend-ledger.jsonl` stays at its own v1
|
|
54
|
+
row format (`SPEND_LEDGER_SCHEMA_VERSION` is 1, unrelated to the envelope versions above).
|
|
55
|
+
`council-ledger.jsonl` is at `LEDGER_SCHEMA_VERSION` **2** (v4.7 GOA-7): v2 rows may carry
|
|
56
|
+
`resolvedModel` — the executable id that actually served. **Legacy-read, no migration:**
|
|
57
|
+
readers never inspect a row's schemaVersion; a row without `resolvedModel` (all pre-v2
|
|
58
|
+
history, plus leg-less rows whose resolution is unknowable) simply aggregates under its
|
|
59
|
+
alias — a group is marked `legacy` in `council stats` output only when EVERY row in it
|
|
60
|
+
lacks `resolvedModel`. `spend.schema.json` (above) is still the published doc built from
|
|
61
|
+
`spend-ledger.jsonl` rows — neither ledger's row shape itself is published.
|
|
53
62
|
- **`amicus_list`** (MCP): returns a bare JSON array of session rows; a wrap would be a second breaking change and is deliberately not taken.
|
|
54
63
|
- **`setup` / `update` / `key`**: interactive-only commands with no `--json` mode.
|
|
55
64
|
- **MCP acks and live-status snapshots** (start/resume/continue/abort acks, `amicus_status`/`amicus_wait` bodies): carry the envelope keys with subject-family types (`run`/`wave`/`abort`) but are point-in-time snapshots, not the durable result docs the published schemas describe.
|
package/docs/testing.md
CHANGED
|
@@ -523,7 +523,7 @@ Complete mapping of test files to their targets and focus areas.
|
|
|
523
523
|
| `evals/tests/result_writer.test.js` | Result output | Summary formatting, file writing |
|
|
524
524
|
| `scripts/check-secrets.test.js` | Secret detection | Pattern matching, allowlist, multi-secret |
|
|
525
525
|
| `scripts/check-file-sizes.test.js` | File size limits | Line counting, batch checking |
|
|
526
|
-
| `scripts/validate-docs.test.js` | Doc drift detection |
|
|
526
|
+
| `scripts/validate-docs.test.js` | Doc drift detection | Staged file check |
|
|
527
527
|
| `helpers/cdp-client.test.js` | CDP helper | Mock HTTP+WebSocket CDP server, factory methods |
|
|
528
528
|
| `electron-headless-mode.test.js` | Electron headless | Source-level verify `AMICUS_HEADLESS_TEST` guard |
|
|
529
529
|
| `cli-headless-e2e.integration.test.js` | CLI E2E (real LLM) | `start --no-ui`, `list`, `read`, `read --metadata` |
|
package/docs/troubleshooting.md
CHANGED
|
@@ -5,7 +5,33 @@
|
|
|
5
5
|
|
|
6
6
|
## First: run `amicus doctor`
|
|
7
7
|
|
|
8
|
-
Before working through any symptom below, run `amicus doctor` (plugin-only installs: `npx -y amicus@latest doctor`). It checks, in order: Node version, config directory, API keys, default model, catalog freshness, alias staleness and drift, the ANTHROPIC_BASE_URL form, the OpenCode binary, the OpenCode engine's MCP launch path, Electron, installed skills, MCP registration, the legacy sidecar MCP entry, session index tmp files, OpenRouter credit, local providers, and the project root — and prints a targeted fix hint for every failing check. `amicus doctor --fix` self-heals what it can (e.g. re-installs a broken Electron in place); `--json` gives machine-readable output.
|
|
8
|
+
Before working through any symptom below, run `amicus doctor` (plugin-only installs: `npx -y amicus@latest doctor`). It checks, in order: Node version, config directory, API keys, default model, catalog freshness, alias staleness and drift, the ANTHROPIC_BASE_URL form, the OpenCode binary, the OpenCode engine's MCP launch path, Electron, installed skills, MCP registration, the legacy sidecar MCP entry, session index and session metadata tmp files, OpenRouter credit, local providers, and the project root — and prints a targeted fix hint for every failing check. `amicus doctor --fix` self-heals what it can (e.g. re-installs a broken Electron in place); `--json` gives machine-readable output.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## MCP run fails with "budget gate refused the run"
|
|
13
|
+
|
|
14
|
+
**Symptom:** An `amicus_start` call over MCP returns an error with `message: "Error: budget gate
|
|
15
|
+
refused the run"` (`ERROR_CODES.BUDGET_EXCEEDED`).
|
|
16
|
+
|
|
17
|
+
**Cause:** v4.7 made the `amicus_start` shared-server budget gate unconditional
|
|
18
|
+
(`src/mcp-server.js:442-467`) — it used to run only when a pack forwarded `maxCost`, so a no-pack
|
|
19
|
+
MCP start that worked on 4.6.x can now refuse. The gate has two independent guards; when both fire,
|
|
20
|
+
raising only one will not clear the run.
|
|
21
|
+
|
|
22
|
+
**Fix:** the error text names which guard fired — raise that one, or choose a cheaper model. **If
|
|
23
|
+
both fired, you must raise both**; clearing one leaves the other refusing. See
|
|
24
|
+
[Cost gate](./configuration.md#cost-gate).
|
|
25
|
+
|
|
26
|
+
- **`maxCostPerMtok`** (the per-$/Mtok guard) lives only in `config.json`. No pack and no MCP param
|
|
27
|
+
can override it.
|
|
28
|
+
- **`maxCost`** (the total-$ ceiling) is whichever value is *in effect*: **the pack's if this run
|
|
29
|
+
used a pack that set one, otherwise the config's.** Editing the loser of that pair changes
|
|
30
|
+
nothing.
|
|
31
|
+
|
|
32
|
+
`amicus_start` has **no per-call override** — it takes neither a `maxCost` nor a `noCostGate` param,
|
|
33
|
+
and nothing can turn the gate off on that path. (`amicus_council_run` is different: it does take
|
|
34
|
+
both, and they forward to its child exactly like the CLI flags.)
|
|
9
35
|
|
|
10
36
|
---
|
|
11
37
|
|
|
@@ -207,13 +233,15 @@ For full headless configuration, see [docs/configuration.md](./configuration.md)
|
|
|
207
233
|
|
|
208
234
|
## Headless Leg Fails with `NO_OUTPUT_BACKSTOP`
|
|
209
235
|
|
|
210
|
-
**Symptom:** A headless leg (`amicus start --no-ui`, or one leg of a `fanout`/council run) fails with an error starting `NO_OUTPUT_BACKSTOP:
|
|
236
|
+
**Symptom:** A headless leg (`amicus start --no-ui`, or one leg of a `fanout`/council run) fails with an error starting `NO_OUTPUT_BACKSTOP: no output, reasoning, or tool calls in Ns — the AMICUS_NO_OUTPUT_BACKSTOP_MS window (0 disables)`. You may instead see `...in Ns — a caller-set window overriding the AMICUS_NO_OUTPUT_BACKSTOP_MS default` — this covers two different cases with the same wording: a Stage-1 retry (its window is the resolved `AMICUS_NO_OUTPUT_BACKSTOP_MS` value **doubled**, so a 120 s default reads `240s` on the retry) and the `amicus models --check --live` probe (a fixed, non-tunable `30s` — see below). Both are "caller-set" in the sense that the specific window wasn't read live from the env var at that call, but only the retry case is actually governed by it.
|
|
237
|
+
|
|
238
|
+
**Cause:** The mechanism only knows that the deadline passed with no substantive activity — no output, reasoning, or tool calls — for the backstop window (120 s by default for an ordinary leg). It does **not** know *why*. Do not read this as "the endpoint is dead" or "the model isn't being served" — the message deliberately stops short of that claim, because at one of its two firing sites the backstop can win the race before the prompt send even resolves, so acceptance itself was never observed. Treat `NO_OUTPUT_BACKSTOP` as "silence past the deadline," not a diagnosis.
|
|
211
239
|
|
|
212
|
-
**
|
|
240
|
+
**Lesson from #133:** an earlier version of this message *did* guess a cause ("likely a listed-but-not-serving model or a dead endpoint"), and that guess sent 30 minutes of debugging at model ids and API keys on a real incident. The actual cause was an OpenCode engine version skew between the npx-cached copy and the global install — sitting the whole time in `~/.local/share/opencode/log/opencode.log`. **Before chasing model/endpoint theories, check that log for the session's real error.**
|
|
213
241
|
|
|
214
|
-
**Confirm:** `amicus models --check` — audits your configured aliases against the live catalog and flags drift/staleness. A model that still resolves locally but has quietly been retired upstream is
|
|
242
|
+
**Confirm:** `amicus models --check` — audits your configured aliases against the live catalog and flags drift/staleness. A model that still resolves locally but has quietly been retired upstream is one possible explanation, but a static audit only compares against the catalog's *listing* — it can't tell you whether a still-listed model actually answers. For that, run `amicus models --check --live` on demand: it sends one tiny real request to every stored alias and reports `SERVED` / `SILENT` / `ERROR` per alias, where `SILENT` (`accepted-but-silent`) is this exact `NO_OUTPUT_BACKSTOP` failure, caught deliberately instead of by accident. It spends real money (one tiny leg per stored alias) — see [docs/usage.md § `amicus models`](./usage.md#amicus-models--the-model-catalog) for cost, scope, and exit-code details.
|
|
215
243
|
|
|
216
|
-
**Fix:** Check the alias's target (`amicus models --search <term>` to find the current id, then re-point the alias) —
|
|
244
|
+
**Fix:** Check the `~/.local/share/opencode/log/opencode.log` for the session's real error first (see #133 above). Then check the alias's target (`amicus models --search <term>` to find the current id, then re-point the alias) — a stale alias is a common case, but not the only one. If the failing leg was a Stage-1 retry (the window read `240s`, or generally double your configured/default value), `AMICUS_NO_OUTPUT_BACKSTOP_MS` **is** the lever — raising it raises both the first attempt's window and the retry's doubled one, unless your `--timeout` is low enough that the doubled window is clamped to the leg timeout. On an ordinary (non-retry) leg, raise it only if a model legitimately needs more than 120 s to produce its first token. The live probe's fixed 30 s window is the one case the env var genuinely cannot touch. See [docs/configuration.md § Headless Poller Tuning](./configuration.md#headless-poller-tuning).
|
|
217
245
|
|
|
218
246
|
---
|
|
219
247
|
|