amicus 4.7.1 → 4.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +988 -1
  3. package/README.md +5 -4
  4. package/docs/CITATIONS.md +122 -0
  5. package/docs/ROADMAP.md +33 -5
  6. package/docs/SHIMS.md +1 -1
  7. package/docs/configuration.md +3 -3
  8. package/docs/council.md +179 -32
  9. package/docs/doc-system.md +1 -1
  10. package/docs/publishing.md +2 -0
  11. package/docs/troubleshooting.md +3 -3
  12. package/docs/usage.md +2 -2
  13. package/electron/ipc-setup.js +18 -2
  14. package/electron/main.js +46 -3
  15. package/electron/setup-ui-aliases.js +2 -2
  16. package/electron/setup-ui-model.js +99 -9
  17. package/electron/setup-ui-styles.js +22 -0
  18. package/electron/setup-ui.js +231 -29
  19. package/electron/workspace-ui/index.html +9 -0
  20. package/electron/workspace-ui/live-dead-seats.js +228 -0
  21. package/electron/workspace-ui/live-model.js +10 -236
  22. package/electron/workspace-ui/live-seats.js +126 -0
  23. package/electron/workspace-ui/workspace-app.js +6 -41
  24. package/electron/workspace-ui/workspace-banners.js +95 -0
  25. package/electron/workspace-ui/workspace-lazy.js +55 -12
  26. package/electron/workspace-ui/workspace-matrix.js +2 -2
  27. package/electron/workspace-ui/workspace-panels.js +42 -10
  28. package/electron/workspace-ui/workspace-render.js +2 -2
  29. package/electron/workspace-ui/workspace-seats.js +101 -17
  30. package/package.json +4 -1
  31. package/schemas/council-run-live.schema.json +1 -0
  32. package/schemas/council-run.schema.json +19 -0
  33. package/schemas/council-tally.schema.json +34 -2
  34. package/schemas/council-verdict.schema.json +15 -0
  35. package/skills/second-opinion/COUNCIL-DESIGN.md +9 -4
  36. package/skills/second-opinion/MANUAL-ORCHESTRATION.md +1 -1
  37. package/skills/second-opinion/SKILL.md +25 -11
  38. package/src/cli-handlers-doctor.js +18 -14
  39. package/src/council/anonymize.js +80 -11
  40. package/src/council/briefings-chair.js +272 -0
  41. package/src/council/briefings-stage2.js +12 -140
  42. package/src/council/debate.js +120 -15
  43. package/src/council/ledger-join.js +284 -0
  44. package/src/council/ledger-stats.js +100 -0
  45. package/src/council/ledger.js +177 -88
  46. package/src/council/parse-stage2.js +1 -1
  47. package/src/council/peer-split.js +196 -0
  48. package/src/council/report-html.js +12 -5
  49. package/src/council/report-md.js +146 -0
  50. package/src/council/report.js +188 -112
  51. package/src/council/run-assemble.js +100 -79
  52. package/src/council/run-chair.js +17 -1
  53. package/src/council/run-debate-revote.js +268 -0
  54. package/src/council/run-debate.js +92 -102
  55. package/src/council/run-finish.js +70 -0
  56. package/src/council/run-launch.js +45 -18
  57. package/src/council/run-retry-group.js +266 -0
  58. package/src/council/run-retry-keys.js +74 -0
  59. package/src/council/run-retry-launch.js +55 -0
  60. package/src/council/run-retry-notes.js +65 -13
  61. package/src/council/run-retry.js +166 -161
  62. package/src/council/run-stage1-launch.js +27 -10
  63. package/src/council/run-stage1-rows.js +220 -0
  64. package/src/council/run-stage1-superseded.js +156 -0
  65. package/src/council/run-stage2.js +65 -5
  66. package/src/council/run-stages.js +72 -69
  67. package/src/council/run-state.js +1 -1
  68. package/src/council/run-stats-entry.js +71 -0
  69. package/src/council/run-verdict-files.js +52 -0
  70. package/src/council/run.js +42 -52
  71. package/src/council/seats.js +262 -0
  72. package/src/council/stage1-bind.js +142 -0
  73. package/src/council/street-cred.js +258 -0
  74. package/src/council/tally.js +100 -49
  75. package/src/council/verdict.js +49 -1
  76. package/src/headless.js +20 -6
  77. package/src/mcp-tools.js +71 -1
  78. package/src/observe/council-legs.js +7 -1
  79. package/src/observe/live-doc.js +3 -3
  80. package/src/sidecar/fanout-leg.js +22 -1
  81. package/src/sidecar/fanout-wave-io.js +26 -1
  82. package/src/sidecar/fanout.js +4 -10
  83. package/src/sidecar/leg-ids.js +19 -0
  84. package/src/sidecar/models-probe.js +7 -4
  85. package/src/sidecar/reopen-spend.js +1 -1
  86. package/src/sidecar/setup.js +137 -2
  87. package/src/utils/alias-audit.js +81 -3
  88. package/src/utils/config.js +109 -11
  89. package/src/utils/curated-models.js +17 -2
  90. package/src/utils/degrade.js +5 -0
  91. package/src/utils/doctor-alias-check.js +152 -0
  92. package/src/utils/model-canonicalization.js +64 -0
  93. package/src/utils/model-shortlist.js +100 -0
  94. package/src/utils/no-output-backstop.js +1 -1
  95. package/src/utils/provider-default-picker.js +93 -45
  96. package/src/utils/provider-default-prompt.js +1 -1
  97. package/src/utils/quick-picks.js +2 -2
  98. package/src/utils/remediation-hints.js +37 -0
  99. package/src/utils/session-index-prune.js +297 -0
  100. package/src/utils/session-metadata-tmp-sweep.js +1 -1
  101. package/src/workspace/artifact-guard.js +8 -114
  102. package/src/workspace/artifact-names.js +222 -0
  103. package/src/workspace/fold-format.js +9 -6
  104. package/src/workspace/live-normalize.js +6 -2
  105. package/src/workspace/matrix-model.js +141 -19
  106. package/src/workspace/run-detail.js +30 -4
  107. package/src/workspace/seat-space.js +143 -0
package/README.md CHANGED
@@ -75,7 +75,7 @@ Claude is the orchestrator. The council and chat skills run *on top of* the engi
75
75
  **The flow, in five beats:**
76
76
 
77
77
  1. **Independent reviews.** Each council model reviews the artifact on its own (one parallel wave), producing a structured findings list — claim, severity (`blocker | major | minor | nit`), location, rationale.
78
- 2. **Anonymized cross-review.** Claude relabels every review (Review A, B, C…) and sends the identical bundle to every model. Each model ranks the reviews and adjudicates every finding (`agree | dispute | neutral`) — *unknowingly judging its own*, so self-bias washes out. This yields a **street-cred** ranking and sorts findings into **Disputed / Confirmed / Contested / Singleton** tiers.
78
+ 2. **Anonymized cross-review.** Claude relabels every review (Review A, B, C…) and sends the identical bundle to every model. Each model ranks the reviews and adjudicates every finding (`agree | dispute | neutral`) — *unknowingly judging its own*, so self-bias washes out. This yields a **street-cred** ranking and sorts findings into **Disputed / Confirmed / Contested / Singleton** tiers. Self-bias is washed out per **seat**: if you deliberately seat one model twice, each seat's vote on the *other* seat's finding is counted as the real peer vote it is, and the finding is flagged when its only corroboration came from its own twin.
79
79
  3. **Chair verdict.** A designated **non-Claude** chair receives the de-anonymized picture — all reviews, rankings, and adjudications — and synthesizes an independent verdict. Claude presents it verbatim; Claude does not synthesize.
80
80
  4. **Tiered decisions.** Confirmed findings get one bulk accept/deny; Contested and Singleton findings are decided one at a time (accept / deny / modify).
81
81
  5. **Outputs applied.** Accepted findings are written into a reviewed copy of the source; the full run is captured in the run folder.
@@ -137,7 +137,7 @@ The council is the hero — start with the everyday way, and reach for the more
137
137
 
138
138
  ### Headless council (CI)
139
139
 
140
- The same pipeline runs with no Claude runtime at all: `amicus council run --prompt-file briefing.md --models gemini,glm --chair deepseek --json` executes the review waves, the anonymized cross-review, the tally, and the chair verdict in one command, and writes the full run directory (`verdict.json` with the chair's parsed `overallVerdict`, `report.html`, every review and judge output). That is what powers the repo's own **Council Review GitHub Action v2** — on PRs labeled `council-review` it posts an adjudicated verdict as a check run plus a sticky comment, uploads the run directory as an evidence artifact, and can optionally gate merges via its `fail_on` input (default: report-only). Reference: [docs/council.md](./docs/council.md#amicus-council-run).
140
+ The same pipeline runs with no Claude runtime at all: `amicus council run --prompt-file briefing.md --models gemini,glm --chair deepseek --json` executes the review waves, the anonymized cross-review, the tally, and the chair verdict in one command, and writes the full run directory (`verdict.json` with the chair's parsed `overallVerdict`, `report.html`, every review and judge output). That is what powers the repo's own **Council Review GitHub Action v2** — on PRs labeled `council-review` it posts an adjudicated verdict as a check run plus a sticky comment, uploads the run directory as an evidence artifact, and gates merges by default via its `fail_on` input (fails only on a `Fundamental rethink` verdict; pass `fail_on: fix` to require `Ship it`, or `fail_on: none` for report-only). Reference: [docs/council.md](./docs/council.md#amicus-council-run).
141
141
 
142
142
  <p align="center"><img src="./docs/cards/ship-gate.svg" alt="A council gating a release pipeline: exit 0 ships it, exit 1 sends it back"></p>
143
143
 
@@ -275,7 +275,7 @@ This opens a graphical wizard:
275
275
  | Step | What it does |
276
276
  |------|--------------|
277
277
  | **1. API Keys** | Enter keys for OpenRouter, Google, OpenAI, Anthropic, and/or DeepSeek. Each is validated live against the provider's API. Written to `~/.config/amicus/.env` with `0600` permissions. |
278
- | **2. Default Model** | Pick your go-to model from a searchable live picker (backed by the catalog). Used whenever you omit `--model`. |
278
+ | **2. Default Model** | Pick your go-to model from a searchable live picker (backed by the catalog) — each provider card also lets you drill down to a specific model instead of just the family default. Used whenever you omit `--model`. |
279
279
  | **3. Model Routing** | Decide which provider serves each model — e.g. route Gemini through a direct Google key and everything else through OpenRouter. |
280
280
  | **4. Review** | Confirm the configuration before saving. |
281
281
 
@@ -450,7 +450,7 @@ $ amicus status demo123 --json
450
450
  "taskId": "demo123",
451
451
  "status": "complete",
452
452
  "elapsed": "5m 0s",
453
- "version": "4.7.1",
453
+ "version": "4.8.1",
454
454
  "model": "google/gemini-2.5-flash",
455
455
  "phase": "terminal"
456
456
  }
@@ -594,6 +594,7 @@ LOG_LEVEL=debug amicus start --model gemini --prompt "test" --no-ui
594
594
  | [docs/troubleshooting.md](./docs/troubleshooting.md) | Extended troubleshooting. |
595
595
  | [docs/electron-testing.md](./docs/electron-testing.md) | Chrome DevTools Protocol patterns for UI testing. |
596
596
  | [docs/testing.md](./docs/testing.md) | Test suite layout and how to run it. |
597
+ | [docs/CITATIONS.md](./docs/CITATIONS.md) | How to cite one file from another so the citation cannot rot, and what the citation gate enforces. |
597
598
  | [docs/publishing.md](./docs/publishing.md) | Release and publish process. |
598
599
  | [docs/SHIMS.md](./docs/SHIMS.md) | v2.0.0 removal record for the pre-rebrand `sidecar*` compatibility shims — what was removed and how to migrate. |
599
600
  | [skills/second-opinion/SKILL.md](./skills/second-opinion/SKILL.md) | The LLM Council skill. |
@@ -0,0 +1,122 @@
1
+ # Citing one file from another
2
+
3
+ Comments, tests and planning docs in this repo cite other files. Those
4
+ citations rot silently whenever the cited file changes, and the rot is
5
+ expensive: PR #171 produced roughly thirty review findings and **not one was in
6
+ the code** — every one was a stale or false statement *about* the code, and the
7
+ majority were rotted citations. Five consecutive fix rounds on a single task
8
+ went entirely to citations, and fixing them moved lines, which falsified more.
9
+
10
+ ## The forms
11
+
12
+ | Form | Use it for | Enforced by |
13
+ |---|---|---|
14
+ | `file.js :: symbolName` | **Default.** Any claim about current code. | the symbol must appear in the target, dotted paths **as written** |
15
+ | `file.js:NNN` / `file.js:NNN-MMM` | A claim no symbol can carry (a line inside a function, a specific guard). | target resolves, line in range |
16
+ | `file.js@<ref>:NNN` | Provenance — "moved verbatim from", "was true at". | line in range **in the file at that ref** |
17
+
18
+ **Prefer the symbol anchor.** A corrected line number is true until the next
19
+ edit and then silently false; a symbol anchor survives every move. Measured in
20
+ PR #171: symbol-anchoring one file removed it from the citation-rot class
21
+ entirely.
22
+
23
+ Use the `@ref` form rather than deleting or "correcting" a provenance
24
+ statement. `run-finish.js` says its body was *moved verbatim from
25
+ `run.js@6b0c3b6b:242-288`* — that range is past EOF in today's `run.js` and
26
+ looks exactly like rot, but it is true at the pre-split commit, and the gate
27
+ verifies it there. Pin the ref to a commit reachable from `main`.
28
+
29
+ **`@ref` needs full history.** `actions/checkout` defaults to a shallow clone
30
+ (`fetch-depth: 1`), where the historical commit is simply absent — which is
31
+ indistinguishable from a bogus ref. On a shallow clone the gate SKIPS those
32
+ checks and prints exactly which ones it skipped; it never fails them, and never
33
+ passes them silently. The `quality` CI job checks out full history
34
+ (`fetch-depth: 0`), so every `@ref` is really verified once per push, while the
35
+ six test legs stay shallow and cheap.
36
+
37
+ ## What the gate checks
38
+
39
+ `scripts/check-citations.js` runs in `.husky/pre-commit` and in the `quality`
40
+ CI job (`npm run check:citations`).
41
+
42
+ **Pre-commit reads the git INDEX, not the working tree** — the index is what the
43
+ commit will actually contain. This is true of all three pre-commit gates
44
+ (`check-secrets`, `check-file-sizes`, `check-citations`), which share
45
+ `scripts/git-index.js`. Reading the working copy meant staging a violation and
46
+ then cleaning the working copy let the violation through, and — just as bad — a
47
+ *valid staged fix* could be blocked by an unstaged edit that was never going to
48
+ ship, which is how people learn to reach for `--no-verify`. `--all` deliberately
49
+ still reads the working tree: it audits the checkout as it stands, and CI has no
50
+ staging area to differ from.
51
+
52
+ Per commit it checks the union of two scopes:
53
+
54
+ - **IN** — citations living in the files the commit changed.
55
+ - **TO** — citations anywhere in live code that *point at* a file the commit changed.
56
+
57
+ A commit's changed set deliberately includes **deletions**, and a **rename
58
+ contributes both of its paths**. `git diff --name-only` reports a rename as its
59
+ new path alone, which would leave the renaming commit unable to see the
60
+ citations to the old path it just broke — the same hole deletions had. This is
61
+ why the gate uses `--diff-filter=ACMRD` and `--name-status` where its sibling
62
+ gates use plain `ACM`: a deleted file needs no size or secret scan, but deleting
63
+ or renaming one is among the surest ways to falsify *other* files' citations.
64
+
65
+ **What the symbol check is, honestly.** It is a text search on identifier
66
+ boundaries, not a parse. `file.js :: foo.bar` requires the literal `foo.bar` to
67
+ appear in the target; it does not prove `bar` is a property of `foo`, and it
68
+ cannot see a symbol reached through destructuring or a computed key. It catches
69
+ the case that actually rots — a renamed or removed symbol — and it will not be
70
+ fooled by an unrelated `foo` and an unrelated `bar` merely coexisting.
71
+
72
+ **TO is not optional.** Measured across PR #171's 38 commits, 119 corrected
73
+ citations split 66 IN-scope / 18 TO-scope-only. A gate scoped to changed files
74
+ alone would have shipped all 18 — including every `run-retry.js` citation in
75
+ `src/headless.js` and three test files that the extraction commit never had
76
+ open. An extraction moves *one* file's lines and falsifies citations in files it
77
+ never touches.
78
+
79
+ ## What the gate does not check
80
+
81
+ Only live code (`src/`, `electron/`, `tests/`) is scanned. `BACKLOG.md` and
82
+ `docs/` hold 3639 of the repo's 4128 citations and are **out of scope by
83
+ design**.
84
+
85
+ **Doc-tree citations are dated historical record. Read them as history, not as
86
+ claims about the current tree.** In particular `docs/superpowers/plans/*` and
87
+ `docs/superpowers/specs/*` are snapshots: their filenames carry the date they
88
+ were written, and their citations were true against the tree of that date.
89
+
90
+ Do not bulk-rewrite them. In PR #171 `BACKLOG.md:1820` looked like rot and was
91
+ **true as of tag v4.7.0** — merely undated. It was annotated, not overwritten. A
92
+ codemod would have destroyed a true statement. When a doc citation is genuinely
93
+ misleading, annotate it with the ref it was true at, or convert it to `@ref`
94
+ form; do not silently renumber it.
95
+
96
+ ## Fixing a stale citation
97
+
98
+ 1. **Open the cited line.** Never derive a correction by offset arithmetic —
99
+ extractions do not shift a file uniformly. PR #171 measured offsets of
100
+ 0/-1/-9/-10/-32 within one commit, and 0/+10/+15 within a single file in
101
+ another. Applying one offset shipped fresh wrong values twice.
102
+ 2. Re-anchor by symbol wherever the claim allows it.
103
+ 3. **Sweep every file your commit touches**, not just the one you set out to
104
+ fix — a comment-only edit still moves line numbers. This exact miss caused
105
+ two fix rounds in #171.
106
+ 4. Prefer line-count-neutral edits. That is what finally stopped the cascade.
107
+
108
+ ## The burn-down list
109
+
110
+ `CONFIG.grandfathered` in `scripts/check-citations.js` is the escape hatch for
111
+ citations already stale when a gate change lands, so the gate can block from day
112
+ one instead of shipping advisory. **It is empty, and should stay that way.** Fix
113
+ the citation, then **delete the entry** — a test asserts every entry still names
114
+ a real citation, so the list cannot quietly accumulate dead weight.
115
+
116
+ The original eight were burned down in one pass. **Four were born stale** — wrong
117
+ in the commit that wrote them, not rotted by later drift: three reused a line
118
+ number from a split that had already landed (one from a split made in that very
119
+ commit), and one wrote a symbol name with `.js` appended as if it were a path.
120
+ The other four were ordinary rot from the PR0/PR5c splits. A gate that catches
121
+ only decay would never have caught the first four — which is the case for
122
+ `file.js :: symbol` being the default form.
package/docs/ROADMAP.md CHANGED
@@ -136,7 +136,7 @@ as hard as a crash.
136
136
  (`runStats` consumers keying by model must exclude `role: 'judge'`).
137
137
  - **Docs** — the full record is `CHANGELOG.md` §4.6.0; spec
138
138
  `docs/superpowers/specs/2026-08-01-degrade-announcement-invariant-design.md`; plans 1–4 under
139
- `docs/superpowers/plans/` (`2026-08-0*-v4.6-degrade-invariant-plan-*.md`).
139
+ the v4.6 degrade-invariant plans (pruned at the release cut; see git history for the branch).
140
140
  > Why it jumped the queue (2026-08-01): the v4.5.x field reports showed the engine was not losing
141
141
  > legs (11 four-seat council runs on v4.5.4, 10 clean) — but when a seat *was* lost, nothing told
142
142
  > the user which one. That silent-degrade class was ruled a north-star violation and took the rev
@@ -196,9 +196,18 @@ list. Two findings drove it:
196
196
  that makes the numbers right.
197
197
  2. **`runStats` is a cost source, not just a record.** Verified at `8d0584a`:
198
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
199
+ `sumWaveUsage(r.runStats).cost` with **no fallback**; `council/report.js@8d0584a:79` falls back to
200
+ `sumWaveUsage(runStats).cost` when wave usage is absent; `council/ledger.js@8d0584a:24` joins street-cred
201
+ off the same array. ⚠️ **Two of the three pinned to `@8d0584a` on 2026-08-20 (v4.8 T2.4); the
202
+ first deliberately NOT pinned, because it never rotted.** Opened at all three refs,
203
+ `cli-handlers-council.js:56` is byte-identical — `const cost = sumWaveUsage(r.runStats || []).cost;`
204
+ at `8d0584a`, at `ed5c0c02` and at the current tree — so it is a **live-true** citation and
205
+ pinning it to a historical ref would have made a correct present-tense claim read as history.
206
+ An earlier draft of this note said *"all three had already rotted"*; that universal is false and
207
+ is corrected here. The other two HAD already rotted before T2.4 began (`report.js:79` and
208
+ `ledger.js:24` are comments at `ed5c0c02`), so their drift is pre-existing, not this release's.
209
+ The report fallback is now at `src/council/report.js :: toModel`'s `total`; all three claims
210
+ themselves still hold. So CA-4's omissions are not a schema nicety — they under-report spend on the
202
211
  surface the owner relies on, which collides with the cost-truth principle (*reported > estimated
203
212
  > unknown; never fabricate $0*). An omitted leg is not "unknown" — it renders as money never
204
213
  spent on legs that spent money.
@@ -326,6 +335,25 @@ release whose scope was explicitly locked. The patch already carries two behavio
326
335
  LC-10) that stretch the definition; a third that pops a GUI window would not be defensible as a
327
336
  patch. Sits naturally beside v4.5's existing **GUI power ergonomics (F10)** line.
328
337
 
338
+ ### v4.7.1 — the diagnostics stop lying *(patch)* — ✅ SHIPPED v4.7.1, 2026-08-09
339
+ Nine fix/test-hardening items and one mandatory extraction. No new commands; three declared
340
+ behaviour changes.
341
+ - **`doctor` stops grading the engine on presence** — the install record gains a version and skew
342
+ is reported as a WARN. Underneath it, `npm root -g` could never resolve on Windows, so amicus had
343
+ never been able to see a global install at all — which also blinded `doctor --fix`'s donor
344
+ selection — #133
345
+ - **The NO_OUTPUT_BACKSTOP message stops guessing** — it asserted a cause it had no evidence for,
346
+ which misdirected 30 minutes of a real incident. It now states only what the deadline
347
+ observed — #129, #133
348
+ - **Retries can heal a slow model** — the once-only Stage-1 retry doubles its window, clamped to the
349
+ leg timeout so a low `--timeout` cannot silently reclassify the failure class — #129
350
+ - **Tags stop being dropped** — `continue`, `resume` and `--retry-failed` inherit the parent tag, so
351
+ `spend --group-by tag` stops mis-bucketing continued work under `(unattributed)`. `--tag` is now
352
+ rejected on continue/resume rather than silently ignored *(behaviour change)*
353
+ - **The engine is pinned exactly** — `opencode-ai` and `@opencode-ai/sdk` at 1.18.15, moving dev and
354
+ CI off 1.2.20. First release whose suite ran against the engine users actually get
355
+ - Plus a `sidecar/reopen-spend.js` extraction, a dead-code deletion, and three documentation gates
356
+
329
357
  ## Backlog (tracked, not scheduled)
330
358
 
331
359
  ### Enterprise-readiness *(unscheduled — gated on funding / cofounder)*
@@ -383,7 +411,7 @@ first. The prose-panel and blind-masking nits (RN-2, RN-5, the `T19-*`/`T20-*` f
383
411
  - **E7** — Prompt dedup cache (exact-dup, opt-in, excludes council/fanout) — minor cost optimization.
384
412
  - **E6** — Cost-per-quality metric (withdrawn in debate; revisit if street-cred stabilizes).
385
413
  - **`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).
386
- - **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.
414
+ - ~~**Headless no-output fast-fail backstop** *(M)*~~**SHIPPED** (#99; the live default is **300 s**, not the ~120 s proposed here, and a Stage-1 retry doubles it to 600 s). Fail a headless run fast (env-tunable `AMICUS_NO_OUTPUT_BACKSTOP_MS`) 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. (Was deferred out of v4.2.1 as new runtime behavior; it landed later.)
387
415
 
388
416
  ## What changed vs. the council's flat top-10
389
417
  - Split the flat list into a **benefit-themed 4.x point-release line** (v4.0 → v4.2 → v4.3 → v4.4 → v4.5).
package/docs/SHIMS.md CHANGED
@@ -59,4 +59,4 @@ Removed across the following commits on `p18/shim-removal` (#19):
59
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
60
  - `9273dd1` — `SIDECAR_MAX_SESSIONS` → `AMICUS_MAX_SESSIONS` rename (the last legacy-prefixed env var read anywhere in the codebase)
61
61
 
62
- See the rebrand plan for the original shim rationale: `docs/superpowers/plans/2026-06-08-amicus-rebrand.md`.
62
+ The original shim rationale is in the 2026-06-08 rebrand plan, pruned at its release cut; see git history.
@@ -1,6 +1,6 @@
1
1
  # Configuration Reference
2
2
 
3
- `amicus setup` is the recommended way to configure Amicus. It opens a graphical wizard that validates your API keys live, lets you pick a default model from the live catalog, and saves everything to `~/.config/amicus/.env` (permissions `0600`). The environment variables below are for overrides and advanced tuning — most users only need the API keys section.
3
+ `amicus setup` is the recommended way to configure Amicus. It opens a graphical wizard that validates your API keys live, lets you pick a default model from the live catalog — down to a specific model per provider, not just the family default — and saves everything to `~/.config/amicus/.env` (permissions `0600`). The environment variables below are for overrides and advanced tuning — most users only need the API keys section.
4
4
 
5
5
  ---
6
6
 
@@ -108,7 +108,7 @@ These variables control the polling loop that drives headless sessions. The defa
108
108
  | `AMICUS_STABLE_IDLE_POLLS` | Number of consecutive idle polls required when no explicit completion signal is received (approximately 60 s at the 2 s default). This is the fallback heuristic for models or SDK versions that don't emit a clean completion event. | `30` |
109
109
  | `AMICUS_MAX_CONSECUTIVE_POLL_FAILURES` | Consecutive poll failures before the headless runner bails. At the 2 s interval this is approximately 30 s. Prevents a dead server from burning the full session timeout on futile polls. | `15` |
110
110
  | `AMICUS_TOOL_CALL_STALL_MS` | How long a tool call may sit pending with **no** result and no output growth before the leg is failed with `Tool call stalled: <tool>` and its OpenCode session aborted. This is the wedge guard: it targets a leg producing nothing at all, and it is skipped while a tool-settle deferral is active (`AMICUS_TOOL_SETTLE_GRACE_MS` owns that decision instead, and ends in a completion rather than a failure). **`0` is ignored** — it falls back to the default rather than disabling the guard, because a `0` threshold would kill every leg on its first poll. There is no way to switch this off; raise it if you legitimately run very long single tool calls. | `180000` |
111
- | `AMICUS_NO_OUTPUT_BACKSTOP_MS` | Fail a headless leg fast when the model has produced no output, reasoning, or tool calls for this long — the "accepted but not serving" class. Disarms permanently on the first sign of activity, so slow cold-prefill local models are unaffected. **Set `0` (or negative) to disable the backstop entirely** — silent legs then run to the ordinary timeout. | `120000` |
111
+ | `AMICUS_NO_OUTPUT_BACKSTOP_MS` | Fail a headless leg fast when the model has produced no output, reasoning, or tool calls for this long — the "accepted but not serving" class. Disarms permanently on the first sign of activity, so slow cold-prefill local models are unaffected. **Set `0` (or negative) to disable the backstop entirely** — silent legs then run to the ordinary timeout. | `300000` |
112
112
  | `AMICUS_USAGE_SETTLE_POLLS` | How many extra `getMessages` reads run **after** a leg has already finished, to catch provider usage/cost that lands milliseconds after the completion signal (measured: real paid legs losing their cost by 29 ms and 155 ms). The loop breaks early as soon as every assistant message carries usage, so the common case is one extra read. **Set to `0` to disable the reconciliation entirely** — legs then report whatever usage was present at completion, which can be `$0` on a leg that really did cost money. | `3` |
113
113
  | `AMICUS_USAGE_SETTLE_INTERVAL_MS` | Delay between those settle reads. **`0` is honoured and means no delay** — the reads run back to back. It does **not** disable the reconciliation (that is `AMICUS_USAGE_SETTLE_POLLS=0`); it only removes the gap between attempts. | `400` |
114
114
  | `AMICUS_USAGE_SETTLE_CALL_TIMEOUT_MS` | Per-call deadline for a settle read and for the child-session (subagent) spend walk. Deliberately much tighter than `AMICUS_POLL_CALL_TIMEOUT_MS`: the leg is already finished, so a hung read must not add 30 s × 3 to a run's wall time. The effective value is the **smaller** of this and `AMICUS_POLL_CALL_TIMEOUT_MS`, so raising it above that has no effect. **`0` is honoured and means no timer is armed at all** — a hung settle read or subtree walk would then wait indefinitely. | `5000` |
@@ -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. 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`. |
241
+ | `council-ledger.jsonl` | `src/council/ledger.js` (`appendRun`), on every `council tally` | One row per distinct (council model, resolved executable) pair per run — findings raised, severity breakdown, street-cred, conformance. On an ordinary bench that is one row per council model; where **one alias** was served by one executable across more than one seat (a repeated alias, or a chair that is also a bench seat *when its chair and seat legs resolved to the same executable*) those seats collapse into a single row (v4.8), and an alias whose seats resolved differently gets one row per executable. Two *distinct* aliases sharing one resolution still write **two** rows — one per alias — which `amicus council stats` then aggregates into a single executable-keyed group. `runs` in `amicus council stats` counts distinct `meta.runId` values, not rows. 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). |