amicus 4.9.3 → 4.9.5

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 (65) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +324 -0
  3. package/README.md +1 -1
  4. package/docs/ROADMAP.md +8 -5
  5. package/docs/architecture-map.md +736 -0
  6. package/docs/configuration.md +165 -26
  7. package/docs/council.md +9 -0
  8. package/docs/doc-system.md +12 -9
  9. package/docs/testing.md +2 -1
  10. package/docs/troubleshooting.md +113 -0
  11. package/docs/usage.md +11 -6
  12. package/package.json +1 -1
  13. package/schemas/model-catalog.schema.json +2 -1
  14. package/schemas/run.schema.json +13 -0
  15. package/scripts/postinstall.js +4 -0
  16. package/skills/sidecar/SKILL.md +1 -8
  17. package/src/cli-handlers-doctor.js +3 -0
  18. package/src/cli-handlers-fanout.js +10 -1
  19. package/src/cli-handlers-resume-continue.js +25 -0
  20. package/src/cli.js +5 -8
  21. package/src/council/briefings-chair.js +4 -2
  22. package/src/council/run-assemble.js +7 -2
  23. package/src/council/run-retry-notes.js +21 -1
  24. package/src/council/run-stages.js +8 -1
  25. package/src/headless.js +125 -7
  26. package/src/mcp-server.js +26 -0
  27. package/src/mcp-tools.js +4 -4
  28. package/src/opencode-client.js +84 -8
  29. package/src/pack/pack-validate.js +3 -0
  30. package/src/session-manager.js +2 -2
  31. package/src/sidecar/continue.js +6 -1
  32. package/src/sidecar/conversation-mirror.js +35 -11
  33. package/src/sidecar/electron-install.js +81 -81
  34. package/src/sidecar/electron-provision.js +179 -0
  35. package/src/sidecar/electron-trust.js +299 -0
  36. package/src/sidecar/fanout-leg-fallback.js +1 -0
  37. package/src/sidecar/fanout-leg.js +10 -2
  38. package/src/sidecar/fanout.js +2 -2
  39. package/src/sidecar/interactive.js +31 -4
  40. package/src/sidecar/models-ceiling-line.js +72 -0
  41. package/src/sidecar/models.js +4 -2
  42. package/src/sidecar/reopen-notices.js +97 -0
  43. package/src/sidecar/reopen-spend.js +3 -2
  44. package/src/sidecar/resume.js +15 -2
  45. package/src/sidecar/session-finalize.js +4 -1
  46. package/src/sidecar/session-utils.js +5 -1
  47. package/src/sidecar/start-metadata.js +1 -1
  48. package/src/sidecar/start.js +10 -5
  49. package/src/sidecar/unzip.js +40 -0
  50. package/src/utils/config.js +33 -12
  51. package/src/utils/curated-models.js +8 -8
  52. package/src/utils/degrade.js +7 -0
  53. package/src/utils/doctor-output-budget-check.js +198 -0
  54. package/src/utils/engine-output-flag.js +105 -0
  55. package/src/utils/engine-variants.js +298 -0
  56. package/src/utils/http-get.js +284 -0
  57. package/src/utils/model-catalog.js +36 -4
  58. package/src/utils/model-ceilings-modelsdev.js +230 -0
  59. package/src/utils/model-fetcher.js +12 -36
  60. package/src/utils/model-output-limit.js +21 -13
  61. package/src/utils/output-length.js +90 -0
  62. package/src/utils/result-schema.js +7 -2
  63. package/src/utils/spend-ledger.js +5 -1
  64. package/src/utils/thinking-validators.js +27 -80
  65. package/src/utils/validators.js +2 -3
@@ -0,0 +1,736 @@
1
+ # Architecture Map
2
+
3
+ Generated inventory of this repository: the directory tree and the module table.
4
+
5
+ The sections between `<!-- AUTO:... -->` markers are maintained by
6
+ `scripts/generate-docs.js` and regenerated by the pre-commit hook. Do NOT edit
7
+ them by hand -- run `node scripts/generate-docs.js` instead.
8
+
9
+ This file lists **what exists**. For **how it connects** -- which test suites drive
10
+ a source file, what a module reaches -- query the graphify index instead; see
11
+ [Finding Things in This Repo](../CLAUDE.md#finding-things-in-this-repo).
12
+
13
+ ---
14
+
15
+ ## Directory Structure
16
+
17
+ <!-- AUTO:tree -->
18
+ bin/
19
+ └── amicus.js # Amicus CLI Entry Point
20
+ src/
21
+ ├── council/
22
+ │ ├── anonymize.js
23
+ │ ├── briefings-chair-task.js
24
+ │ ├── briefings-chair.js
25
+ │ ├── briefings-debate.js
26
+ │ ├── briefings-stage2-task.js
27
+ │ ├── briefings-stage2.js
28
+ │ ├── briefings-task.js
29
+ │ ├── briefings.js
30
+ │ ├── chair-fallback.js
31
+ │ ├── debate.js
32
+ │ ├── findings.js
33
+ │ ├── ledger-join.js
34
+ │ ├── ledger-stats.js
35
+ │ ├── ledger.js
36
+ │ ├── parse-stage2.js
37
+ │ ├── peer-split.js
38
+ │ ├── presets-cli.js
39
+ │ ├── report-cost.js
40
+ │ ├── report-html.js
41
+ │ ├── report-md.js
42
+ │ ├── report.js
43
+ │ ├── run-assemble.js
44
+ │ ├── run-budget.js
45
+ │ ├── run-chair.js
46
+ │ ├── run-debate-revote.js
47
+ │ ├── run-debate-stage.js
48
+ │ ├── run-debate.js
49
+ │ ├── run-degrade.js
50
+ │ ├── run-finalize.js
51
+ │ ├── run-finish.js
52
+ │ ├── run-launch.js
53
+ │ ├── run-retry-group.js
54
+ │ ├── run-retry-keys.js
55
+ │ ├── run-retry-launch.js
56
+ │ ├── run-retry-notes.js
57
+ │ ├── run-retry-window.js # The Stage-1 retry's no-output window: how long a RELAUNCHED leg may stay
58
+ │ ├── run-retry.js
59
+ │ ├── run-server.js
60
+ │ ├── run-stage1-launch.js # Stage-1 launch pass for the council engine.
61
+ │ ├── run-stage1-rows.js
62
+ │ ├── run-stage1-superseded.js
63
+ │ ├── run-stage2.js
64
+ │ ├── run-stages.js
65
+ │ ├── run-state.js
66
+ │ ├── run-stats-entry.js
67
+ │ ├── run-verdict-files.js
68
+ │ ├── run.js
69
+ │ ├── seats.js
70
+ │ ├── stage1-bind.js
71
+ │ ├── street-cred.js
72
+ │ ├── tally.js
73
+ │ ├── verdict-seat-loss.js
74
+ │ ├── verdict-seats-reviewed.js # #202: the bench-seat census for verdict.json, as a spreadable fragment.
75
+ │ └── verdict.js
76
+ ├── design/
77
+ │ ├── fonts/
78
+ │ │ ├── IBMPlexMono-400.ttf
79
+ │ │ ├── IBMPlexMono-500.ttf
80
+ │ │ ├── IBMPlexMono-600.ttf
81
+ │ │ ├── Outfit-300.ttf
82
+ │ │ ├── Outfit-400.ttf
83
+ │ │ ├── Outfit-500.ttf
84
+ │ │ ├── Outfit-600.ttf
85
+ │ │ ├── Outfit-700.ttf
86
+ │ │ └── Outfit-800.ttf
87
+ │ ├── tokens.css
88
+ │ └── tokens.js
89
+ ├── observe/
90
+ │ ├── council-legs.js
91
+ │ ├── events.js
92
+ │ ├── follow.js
93
+ │ ├── live-doc.js
94
+ │ ├── on-complete.js
95
+ │ └── watch-render.js
96
+ ├── pack/
97
+ │ ├── pack-cli.js
98
+ │ ├── pack-forward.js
99
+ │ ├── pack-resolve.js
100
+ │ ├── pack-store.js
101
+ │ └── pack-validate.js
102
+ ├── prompts/
103
+ │ └── cowork-agent-prompt.js # Cowork Agent Prompt
104
+ ├── sidecar/
105
+ │ ├── budget.js
106
+ │ ├── child-sessions.js
107
+ │ ├── context-builder.js # Context Builder Module
108
+ │ ├── continue.js # Sidecar Continue Operations - Handles continuing from previous sessions
109
+ │ ├── conversation-mirror.js
110
+ │ ├── crash-handler.js # Crash Handler - Updates metadata to 'error' on uncaught exceptions
111
+ │ ├── electron-cache.js # Electron download-cache root resolution (#53 helper).
112
+ │ ├── electron-ensure.js # ensureElectron() — lazy first-GUI provisioning (#55).
113
+ │ ├── electron-install.js # Electron self-heal primitive (#53, #59).
114
+ │ ├── electron-lock.js # Stale-aware single-flight lock for the electron self-heal (#53).
115
+ │ ├── electron-provision.js # Electron CONTROLLED provision — the pinned download, and what happens to a
116
+ │ ├── electron-quarantine.js # AV / antivirus quarantine detection for the electron self-heal (#53).
117
+ │ ├── electron-state.js # Electron install-state probes (#76).
118
+ │ ├── electron-trust.js # Electron artifact TRUST core — the digest anchor, the gate, and the env scrub.
119
+ │ ├── fallback-chains.js
120
+ │ ├── fanout-budget.js
121
+ │ ├── fanout-leg-fallback.js
122
+ │ ├── fanout-leg.js
123
+ │ ├── fanout-output.js
124
+ │ ├── fanout-retry.js
125
+ │ ├── fanout-signals.js
126
+ │ ├── fanout-validate.js
127
+ │ ├── fanout-wave-io.js
128
+ │ ├── fanout.js
129
+ │ ├── interactive-abort.js
130
+ │ ├── interactive-mirror.js
131
+ │ ├── interactive-process.js # Sidecar Interactive Process Helpers - Electron probe/env/process-exit plumbing
132
+ │ ├── interactive.js # Sidecar Interactive Mode - Electron GUI session management
133
+ │ ├── leg-ids.js
134
+ │ ├── list-council.js # Council rows on the CLI `amicus list` surface (v4.9 W12).
135
+ │ ├── list-limit.js # The `--limit` core behind `amicus list` (v4.7 PR3 rider).
136
+ │ ├── list-search.js # The `--search` core behind both list surfaces (F8 D15, errata E-PR3-5).
137
+ │ ├── models-ceiling-line.js # The one `Ceilings:` line `amicus models --refresh` prints (#218 P3).
138
+ │ ├── models-probe.js
139
+ │ ├── models-render.js # Presentation helpers for `amicus models` -- pure string formatting, no I/O.
140
+ │ ├── models.js # `amicus models` (F5) — list/search the catalog, refresh it, audit aliases.
141
+ │ ├── progress-fields.js # Derived, agent-facing progress fields shared by the MCP status/list
142
+ │ ├── progress.js # Sidecar Progress Reader
143
+ │ ├── read.js # Sidecar Read Operations Module
144
+ │ ├── reopen-notices.js # The stderr Notice a reopen owes the user for the effort level it does NOT carry (#218 PR 4, council #235 r5 J1/A3).
145
+ │ ├── reopen-spend.js # Spend finalization for a REOPENED session (continue/resume). Split out of
146
+ │ ├── resume.js # Sidecar Resume Operations - Handles resuming previous sidecar sessions
147
+ │ ├── session-finalize.js
148
+ │ ├── session-utils.js # Sidecar Session Utilities - Shared functionality for session management
149
+ │ ├── setup-local.js # The readline setup wizard's local / self-hosted provider add step (v4.2 §4.6, Task 12).
150
+ │ ├── setup-window.js # Setup Window Launcher
151
+ │ ├── setup.js # Sidecar Setup Wizard
152
+ │ ├── start-metadata.js
153
+ │ ├── start.js # Sidecar Start Operations - Handles starting new sidecar sessions
154
+ │ ├── tool-part.js
155
+ │ ├── unzip.js # Robust unzip for the electron self-heal (#53 follow-up; extract-zip-node24).
156
+ │ ├── wave-progress.js
157
+ │ ├── workspace-auto-open.js # Workspace Auto-Open Decision Helper
158
+ │ └── workspace-window.js # Council Workspace launcher (v4.4 §4.3/§4.4) — setup-window.js pattern:
159
+ ├── template/
160
+ │ ├── apply.js
161
+ │ ├── render.js
162
+ │ └── store.js
163
+ ├── utils/
164
+ │ ├── abort-coordinator.js
165
+ │ ├── abort-result.js # The abort-result document builder for `abort <taskId|--all> --json` (B21-rest).
166
+ │ ├── activity-poller.js
167
+ │ ├── agent-mapping.js # Agent Mapping Module
168
+ │ ├── alias-audit.js # Alias Audit (F5) — report + suggest for most classes; doctor --fix auto-repairs one narrow, mechanically-unambiguous class (B3).
169
+ │ ├── alias-resolver.js # Alias Resolver Utilities
170
+ │ ├── alias-shadow-writer.js # The alias-shadow notice's WRITE half: say it without ever sinking the run.
171
+ │ ├── alias-shadow.js # Alias-shadow self-diagnosis — name a local alias that repoints a curated one.
172
+ │ ├── api-key-store.js # API Key Store — reading, saving, and validating API keys.
173
+ │ ├── api-key-validation.js # API Key Validation — test API keys against provider endpoints.
174
+ │ ├── atomic-write.js # Atomic file write helper.
175
+ │ ├── auth-json.js # Auth JSON Reader
176
+ │ ├── base-url-classify.js # v4.6.2 PR1 (spec §4, D1/D2): ANTHROPIC_BASE_URL classification, the
177
+ │ ├── claude-register.js # Registration core for amicus: skill install (chat skill + LLM Council),
178
+ │ ├── cli-preflight.js # Tiny shared preflight guards used by more than one CLI run handler
179
+ │ ├── client-detect.js # Detects which caller (Claude Code vs. Cowork/Claude Desktop) spawned this
180
+ │ ├── config.js # Amicus Config Module
181
+ │ ├── council-presets.js # Built-in council benches (B23).
182
+ │ ├── curated-models.js # Family definitions + pinned fallbacks for the wizard model picker (v2).
183
+ │ ├── degrade.js
184
+ │ ├── doctor-alias-check.js
185
+ │ ├── doctor-base-url-check.js # v4.6.2 PR1 (spec §4): the 'anthropic-base-url' doctor row.
186
+ │ ├── doctor-credit-check.js # The `openrouter-credit` doctor row (#43), split out of
187
+ │ ├── doctor-degrade.js
188
+ │ ├── doctor-electron-mcp-check.js # The `electron-mcp` doctor check ("Electron (MCP launch path)"), split out of
189
+ │ ├── doctor-engine-check.js # The `engine-mcp` doctor check ("OpenCode engine (MCP launch path)"), split out
190
+ │ ├── doctor-key-auth-check.js # The `key-auth` doctor row (issue #210), split out of src/cli-handlers-doctor.js
191
+ │ ├── doctor-local-providers-check.js # The `local-providers` doctor check (v4.2 §4.7 C8), split out of
192
+ │ ├── doctor-mcp-checks.js # B14/Task 4.3: the two MCP-registration doctor checks ('mcp' and
193
+ │ ├── doctor-output-budget-check.js # #218 PR 2: the 'output-budget' doctor row.
194
+ │ ├── doctor-summary.js # Compact doctor summary (v4.2 §4.7 C8). All-ok -> one line; otherwise the
195
+ │ ├── engine-ensure.js # ensureEngine() — runtime engine self-heal at server start (report #2).
196
+ │ ├── engine-install-scan.js # Discover + probe every amicus install that could serve the MCP (running,
197
+ │ ├── engine-lock.js # Stale-aware single-flight lock for the engine self-heal (report #2).
198
+ │ ├── engine-log-parse.js # Line-shape parsing for the engine log: level, session, message.
199
+ │ ├── engine-log-tail.js # One engine-log FILE: read its tail, find the newest usable excerpt in it.
200
+ │ ├── engine-log.js # Resolve the OpenCode engine's own error line for one session.
201
+ │ ├── engine-output-flag.js # #218 PR 2 — the one engine env flag amicus sets: OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX.
202
+ │ ├── engine-repair.js # Engine self-heal primitive (report #2): make the opencode engine present ON
203
+ │ ├── engine-skew-records.js # Server identity and the bounded store of standing engine-skew records.
204
+ │ ├── engine-skew.js # Runtime detection of an opencode ENGINE version skew: server vs installed.
205
+ │ ├── engine-variants.js # The effort lever (#218 PR 4): --thinking sent as the engine's variant field, validated against the engine's own declaration.
206
+ │ ├── env-loader.js # Credential Loader
207
+ │ ├── env-num.js
208
+ │ ├── env-raw-store.js # Arbitrary-env-var writes to the amicus .env (local-provider bearers, v4.2 §4.6).
209
+ │ ├── error-classify.js
210
+ │ ├── error-doc.js
211
+ │ ├── fold-marker.js # Fold marker construction/parsing helpers — shared by prompt-builder.js
212
+ │ ├── format-duration.js
213
+ │ ├── free-models.js # Free OpenRouter model detection (Unit A).
214
+ │ ├── gateway-route-audit.js # Per-gateway-form audit for curated DEFAULT aliases (Task 6, #gwid).
215
+ │ ├── gateway-route-catalog.js # Conservative cross-gateway catalog pairing helper (Task 5, #gwid).
216
+ │ ├── gateway-router.js # Pure gateway router (#61). Decides direct vs OpenRouter for a request using
217
+ │ ├── http-get.js # One HTTPS GET, always resolved, never rejected — the timer/destroy/failure
218
+ │ ├── idle-watchdog.js # IdleWatchdog - BUSY/IDLE state machine with self-terminating timer.
219
+ │ ├── input-validators.js
220
+ │ ├── known-flags.js
221
+ │ ├── legacy-mcp-migration.js
222
+ │ ├── lifecycle.js
223
+ │ ├── live-probes.js # The single gate on outbound AUTHENTICATED network probes made by diagnostics
224
+ │ ├── local-probe.js
225
+ │ ├── local-providers.js
226
+ │ ├── logger.js # Structured Logger Module
227
+ │ ├── mcp-discovery.js # MCP Discovery - Discovers MCP servers from parent LLM configuration
228
+ │ ├── mcp-self-identity.js
229
+ │ ├── mcp-validators.js # MCP Validators
230
+ │ ├── model-canonicalization.js # Direct-first id canonicalization, guarded by `classifyModel`
231
+ │ ├── model-catalog.js # OpenRouter model catalog cache (F3 #18 / F5 foundation).
232
+ │ ├── model-ceilings-modelsdev.js # #218 P3 — output ceilings for the direct-provider catalog rows.
233
+ │ ├── model-classification.js # Tri-state catalog classification (#61).
234
+ │ ├── model-descriptor.js # Model-descriptor grammar + RouteResult factories (#61).
235
+ │ ├── model-fetcher.js # Model Fetcher
236
+ │ ├── model-input-default.js
237
+ │ ├── model-output-limit.js # Issue #218 — the per-model `limit` descriptor amicus hands opencode.
238
+ │ ├── model-shortlist.js # Vendor model shortlist (#138) -- the family -> model second level.
239
+ │ ├── model-tiers.js # Per-vendor cost tiers (economy/balanced/frontier) + resolution against the
240
+ │ ├── model-validator.js # Model Validator
241
+ │ ├── no-output-backstop.js # v4.6.2 PR2 (spec §5, D4): fail a headless leg fast when the model produces
242
+ │ ├── node-version-guard.js
243
+ │ ├── openrouter-credit.js # The OpenRouter credit/limit probe, split out of api-key-validation.js to keep
244
+ │ ├── output-length.js # #218 PR 3: name the "Mode 2" death.
245
+ │ ├── path-fence.js # Shared realpath-containment fence.
246
+ │ ├── path-setup.js
247
+ │ ├── port-pid.js # Cross-platform listener-PID lookup.
248
+ │ ├── pricing.js
249
+ │ ├── project-path.js # Canonical project-path helper.
250
+ │ ├── project-root-sanity.js
251
+ │ ├── prompt-source.js
252
+ │ ├── provider-default-picker.js # Provider-default picker core (Part 2, Task 4).
253
+ │ ├── provider-default-prompt.js # Provider-default prompt flow (Part 2, Task 6/7 shared helper).
254
+ │ ├── provider-registry.js # Provider-capability registry — the single source of truth for provider
255
+ │ ├── quick-picks.js # Quick-pick resolution (wizard Step 2) — resolves each curated family to
256
+ │ ├── read-slice.js # Byte-bounded slicing for amicus_read (15a.3 / B17).
257
+ │ ├── remediation-hints.js
258
+ │ ├── result-schema-rebuild.js
259
+ │ ├── result-schema-version.js # The single SCHEMA_VERSION constant shared by result-schema.js and
260
+ │ ├── result-schema.js
261
+ │ ├── route-error.js # Shared renderer (#61 Task 6.1): turns a router RouteResult — an error or a
262
+ │ ├── route-launch.js # Route-launch views (#61 gateway routing integration, Task 4.2).
263
+ │ ├── route-suggestions.js
264
+ │ ├── server-setup.js # Server Setup Utilities
265
+ │ ├── session-abort.js # Session abort utilities: signal handler installation and terminal metadata writes.
266
+ │ ├── session-index-prune.js
267
+ │ ├── session-index-tmp-sweep.js
268
+ │ ├── session-index.js # Global session index (issue #40).
269
+ │ ├── session-lock.js
270
+ │ ├── session-metadata-tmp-sweep.js
271
+ │ ├── session-path.js # Session path resolution.
272
+ │ ├── session-status.js # #202: render the engine's SESSION STATUS as a clause on a leg's death report.
273
+ │ ├── shared-server.js
274
+ │ ├── spend-ledger.js
275
+ │ ├── start-helpers.js # Start Command Helpers
276
+ │ ├── text-sanitize.js # One third-party string, safe to render: no escapes, no bidi, one short line.
277
+ │ ├── thinking-validators.js # Thinking Level Validators
278
+ │ ├── ttft.js # The one honesty predicate for the time-to-first-token probe (v4.9 W13).
279
+ │ ├── untrusted-fence.js # Untrusted sidecar output fence.
280
+ │ ├── update-notice.js # The MCP server is the one entry point that skips bin/amicus.js's update
281
+ │ ├── update-notifier-loader.js # update-notifier Loader
282
+ │ ├── updater.js # Updater Module
283
+ │ ├── validators.js # Input Validators
284
+ │ └── version-info.js # After an `npm i -g amicus` upgrade, a long-lived MCP server process keeps
285
+ ├── workspace/
286
+ │ ├── artifact-guard.js # Council Workspace — artifact read guard (v4.4 §4.5 workspace:read-artifact).
287
+ │ ├── artifact-names.js # Council Workspace — artifact NAME derivation (v4.8 PR5a).
288
+ │ ├── blind-mode.js # Council Workspace — blind-mode name mapping (v4.4 §6.3).
289
+ │ ├── fold-format.js # Council Workspace — fold payload builder (v4.4 §7).
290
+ │ ├── live-normalize.js # Council Workspace — live-doc normalization (v4.4 §3 A1/A2/A4 seam).
291
+ │ ├── matrix-model.js # Council Workspace — adjudication matrix view model (v4.4 §5.2).
292
+ │ ├── run-detail.js # Council Workspace — run detail: defensive parse of run.json / tally.json /
293
+ │ ├── run-scan.js # Council Workspace — run discovery (v4.4 spec §4.3 / §5.1).
294
+ │ └── seat-space.js # Council Workspace — the seat-space PREDICATES (v4.8 PR5b).
295
+ ├── cli-council-run-bench.js # Bench and input resolution for the council run command.
296
+ ├── cli-council-run-render.js
297
+ ├── cli-handlers-abort.js # CLI Abort Handler (B21-rest extraction)
298
+ ├── cli-handlers-council-run.js
299
+ ├── cli-handlers-council.js
300
+ ├── cli-handlers-doctor.js
301
+ ├── cli-handlers-fanout.js # CLI handler for the fanout command (multi-model parallel runs).
302
+ ├── cli-handlers-init.js # `amicus init [--claude] [--desktop] [--json]` (v4.2 §4.8, C2). Re-runs the
303
+ ├── cli-handlers-key-local.js # amicus key <localId> — bearer lifecycle for a config-defined local /
304
+ ├── cli-handlers-pack.js
305
+ ├── cli-handlers-provider.js # `amicus provider add|list|test|remove` (v4.2 §4.6): configure local /
306
+ ├── cli-handlers-resume-continue.js # CLI Resume/Continue Handlers (B21-rest extraction)
307
+ ├── cli-handlers-run.js # CLI Run Handlers (WS-2 extraction)
308
+ ├── cli-handlers-spend.js
309
+ ├── cli-handlers-status.js # `amicus status <task_id>` — one-shot human/JSON status for a session or wave.
310
+ ├── cli-handlers-template.js
311
+ ├── cli-handlers-watch.js
312
+ ├── cli-handlers.js # CLI Command Handlers
313
+ ├── cli-template-args.js
314
+ ├── cli.js # CLI Argument Parser
315
+ ├── conflict.js # File Conflict Detection Module
316
+ ├── context-compression.js # Context Compression Module
317
+ ├── context.js # Context Filtering Module
318
+ ├── drift.js # Context Drift Detection Module
319
+ ├── environment.js # Environment Detection Module
320
+ ├── headless.js # Headless Mode Runner
321
+ ├── index.js # Amicus - Main Module
322
+ ├── jsonl-parser.js # JSONL Parser
323
+ ├── mcp-council-awareness.js
324
+ ├── mcp-council-bench.js
325
+ ├── mcp-council-run.js
326
+ ├── mcp-notify.js # Pure helpers + in-process registry for the MCP `onComplete: 'mcp-notify'`
327
+ ├── mcp-server.js # @module mcp-server — Amicus MCP Server (stdio transport)
328
+ ├── mcp-spend.js
329
+ ├── mcp-tools.js # MCP Tool Definitions for Amicus
330
+ ├── mcp-wait.js # Engine for the amicus_wait MCP tool: blocks inside one tool call until a session/wave reaches a terminal state or the wait window closes.
331
+ ├── opencode-client.js # OpenCode SDK Client Wrapper
332
+ ├── project-root-allowlist.js # The MCP `project` / cwd input becomes the session-store parent AND the spawned
333
+ ├── prompt-builder.js # System Prompt Builder
334
+ ├── session-manager.js # Session Manager Module
335
+ ├── session.js # Session Resolver
336
+ └── spend-query.js
337
+ electron/
338
+ ├── assets/
339
+ │ ├── icon.png
340
+ │ └── icon.svg
341
+ ├── workspace-ui/
342
+ │ ├── index.html
343
+ │ ├── live-dead-seats.js
344
+ │ ├── live-model.js # Council Workspace — pure renderer-side view logic (poll cadence, seat row
345
+ │ ├── live-seats.js
346
+ │ ├── md-lite.js # markdown-lite — dependency-free renderer for untrusted model prose
347
+ │ ├── workspace-app.js # Council Workspace — application state + wiring (v4.4 §5).
348
+ │ ├── workspace-banners.js # Council Workspace — the run-detail banner ladder (v4.4 §9, spec's "graceful when present").
349
+ │ ├── workspace-lazy.js # Council Workspace — lazy prose-panel loading (v4.4 §5.2). v4.7 PR7 extraction of the
350
+ │ ├── workspace-matrix.js # Council Workspace — adjudication matrix + verdict panel painters.
351
+ │ ├── workspace-panels.js # Council Workspace — name resolution + the matrix/verdict/seats panel adapters
352
+ │ ├── workspace-render.js # Council Workspace — DOM painters (run list, header, stage rail, seats,
353
+ │ ├── workspace-seats.js # Council Workspace — seats panel painter (v4.4 §5). D8 extraction (Task 1, v4.6.2 PR4): moved
354
+ │ ├── workspace-verbs.js # Council Workspace — action verbs (v4.4 §5, ⚠️ DE-ROT F05 split of
355
+ │ └── workspace.css
356
+ ├── close-guard.js # Close Guard — auto-fold on window close (backlog B01)
357
+ ├── fold.js # Fold Logic
358
+ ├── ipc-guard.js # IPC Guard Helpers
359
+ ├── ipc-setup-local.js # IPC handlers for the Electron wizard's "Local server" card (Task 13, v4.2 §4.6).
360
+ ├── ipc-setup.js # IPC Setup Handlers
361
+ ├── ipc-workspace.js # Council Workspace IPC (v4.4 §4.5) — all seven workspace: channels.
362
+ ├── load-failsafe.js # Load Failsafe
363
+ ├── main.js # Amicus Electron Shell - v3
364
+ ├── offer-session.js # Offer-session catalog snapshots for the setup wizard's provider-default
365
+ ├── opencode-theme.js
366
+ ├── preload-content.js # Content Preload - OpenCode WebContentsView (minimal, no privileged bridge)
367
+ ├── preload-setup.js # Sidecar Preload - Setup Mode
368
+ ├── preload-workspace.js # Council Workspace Preload — minimal typed IPC bridge (v4.4 §4.2/§4.5).
369
+ ├── preload.js # Sidecar Preload - v3 Minimal
370
+ ├── session-route.js # Web-UI session route builder (#45).
371
+ ├── setup-ui-alias-groups.js # Setup UI - Alias grouping rule (issue 213)
372
+ ├── setup-ui-alias-script.js # Setup UI - Alias Editor Script
373
+ ├── setup-ui-aliases.js # Setup UI - Alias Editor
374
+ ├── setup-ui-council.js # Setup UI — Free OpenRouter council picker (mounted on the Models step).
375
+ ├── setup-ui-keys-script.js # Setup UI - Step 1 Key Management Script
376
+ ├── setup-ui-keys.js # Setup UI - Step 1: API Keys
377
+ ├── setup-ui-local-script.js # Setup UI — Local server widget runtime script (Task 13, v4.2 §4.6).
378
+ ├── setup-ui-local.js # Setup UI — "Local server" step-1 add-on widget (Task 13, v4.2 §4.6).
379
+ ├── setup-ui-model.js # Setup UI - Step 2: Default Model Selection
380
+ ├── setup-ui-provider-default.js # Setup UI — Per-provider default model picker (Part 2, Task 8).
381
+ ├── setup-ui-styles.js # Setup UI - Shared CSS Styles (clay/gold token-driven)
382
+ ├── setup-ui.js # Setup UI - Wizard Orchestrator: API Keys → Models → Aliases → Review
383
+ ├── summary.js # Summary Generation via OpenCode API
384
+ ├── toolbar.js # Amicus Toolbar HTML Builder
385
+ ├── window-position.js # Window Position Calculator
386
+ └── workspace-shell.js # Council Workspace window (v4.4 §4.1/§4.2) — the third Electron mode's
387
+ scripts/
388
+ ├── benchmark-api-direct.js # Direct OpenRouter API Benchmark for Thinking Levels
389
+ ├── benchmark-thinking.js # Benchmark Thinking Levels
390
+ ├── check-ci-alias-pins.js # Drift gate for the CI alias map (.github/amicus-ci-aliases.json).
391
+ ├── check-citations.js # Cross-file citation enforcement for the pre-commit hook and the whole-tree
392
+ ├── check-file-sizes.js # File size enforcement for the pre-commit hook and the whole-tree CI gate (--all).
393
+ ├── check-global-install.js # CI assertion (Windows install-smoke job, #35): after a REAL global install
394
+ ├── check-html.js
395
+ ├── check-secrets.js # Secret detection for the pre-commit hook and the whole-tree CI gate (--all).
396
+ ├── check-tarball-lifecycle.js # CI guard: assert every script referenced by an npm *lifecycle* hook actually
397
+ ├── check-ui.js
398
+ ├── debug-cdp.js
399
+ ├── eval-with-monitoring.sh
400
+ ├── extract-workflow-env.js # Extract the workflow-level and job-level `env:` blocks of a GitHub Actions
401
+ ├── generate-docs-helpers.js # Helper functions for generate-docs.js.
402
+ ├── generate-docs.js # Auto-generate documentation sections from source code.
403
+ ├── generate-icon.js # Generate app icon PNG from SVG source.
404
+ ├── git-index.js # Read file content from the git INDEX rather than the working tree, and list
405
+ ├── integration-test.sh
406
+ ├── mark-test-passed.js # Writes the current git HEAD SHA to .test-passed for the pre-push SHA cache
407
+ ├── postinstall.js # Post-install script for amicus
408
+ ├── probe-max-tokens.js # Wire probe for issue #218: what max_tokens / reasoning / thinking does the
409
+ ├── run-integration-keyless.js
410
+ ├── setup-hooks.js # Configure git to run the version-controlled hooks in .husky/.
411
+ ├── test-tools.sh
412
+ ├── validate-docs.js # CLAUDE.md drift detection script.
413
+ ├── validate-thinking.js
414
+ └── validate-ui.js
415
+ evals/
416
+ ├── tests/
417
+ │ ├── claude_runner.test.js
418
+ │ ├── eval_tasks.test.js
419
+ │ ├── evaluator.test.js
420
+ │ ├── result_writer.test.js
421
+ │ └── transcript_parser.test.js
422
+ ├── claude_runner.js
423
+ ├── eval_tasks.json
424
+ ├── evaluator.js
425
+ ├── README.md
426
+ ├── result_writer.js
427
+ ├── run_eval.js # Sidecar Agentic Eval Runner
428
+ └── transcript_parser.js # Parse Claude Code stream-json output into structured transcript.
429
+ <!-- /AUTO:tree -->
430
+
431
+ ---
432
+
433
+ ## Key Modules
434
+
435
+ <!-- AUTO:modules -->
436
+ | Module | Purpose | Key Exports |
437
+ |--------|---------|-------------|
438
+ | `cli-council-run-bench.js` | Bench and input resolution for the council run command. | `resolveBench()`, `resolveChair()`, `resolveCritic()`, `CHAIR_DEFAULT()`, `parseList()` |
439
+ | `cli-council-run-render.js` | | `renderRunHuman()` |
440
+ | `cli-handlers-abort.js` | CLI Abort Handler (B21-rest extraction) | `handleAbort()` |
441
+ | `cli-handlers-council-run.js` | | `handleCouncilRun()`, `renderRunHuman()`, `CHAIR_DEFAULT()` |
442
+ | `cli-handlers-council.js` | | `handleCouncil()` |
443
+ | `cli-handlers-doctor.js` | | `runDoctorChecks()`, `handleDoctor()`, `MAX_CATALOG_AGE_MS()` |
444
+ | `cli-handlers-fanout.js` | CLI handler for the fanout command (multi-model parallel runs). | `handleFanout()` |
445
+ | `cli-handlers-init.js` | `amicus init [--claude] [--desktop] [--json]` (v4.2 §4.8, C2). Re-runs the | `handleInit()` |
446
+ | `cli-handlers-key-local.js` | amicus key <localId> — bearer lifecycle for a config-defined local / | `handleLocalKey()`, `formatLocalKeyList()`, `maskKey()` |
447
+ | `cli-handlers-pack.js` | | `handlePack()` |
448
+ | `cli-handlers-provider.js` | `amicus provider add|list|test|remove` (v4.2 §4.6): configure local / | `handleProvider()`, `isLoopbackUrl()`, `isPlaintextRemote()` |
449
+ | `cli-handlers-resume-continue.js` | CLI Resume/Continue Handlers (B21-rest extraction) | `handleResume()`, `handleContinue()` |
450
+ | `cli-handlers-run.js` | CLI Run Handlers (WS-2 extraction) | `handleStart()`, `handleFanout()`, `handleRead()` |
451
+ | `cli-handlers-spend.js` | | `handleSpend()`, `aggregateSpend()`, `buildSpendDoc()`, `parseSinceDays()`, `filterRows()` |
452
+ | `cli-handlers-status.js` | `amicus status <task_id>` — one-shot human/JSON status for a session or wave. | `handleStatus()`, `formatRunHuman()`, `formatWaveHumanStatus()`, `formatCouncilHuman()` |
453
+ | `cli-handlers-template.js` | | `handleTemplate()` |
454
+ | `cli-handlers-watch.js` | | `handleWatch()`, `resolveWatchTarget()` |
455
+ | `cli-handlers.js` | CLI Command Handlers | `handleSetup()`, `handleAbort()`, `handleUpdate()`, `handleMcp()`, `handleKey()` |
456
+ | `cli-template-args.js` | | `applyTemplateForArgs()`, `NEEDS_TEMPLATE_MSG()` |
457
+ | `cli.js` | CLI Argument Parser | `parseArgs()`, `validateStartArgs()`, `getUsage()`, `getCommandNames()`, `getBooleanFlags()` |
458
+ | `conflict.js` | File Conflict Detection Module | `detectConflicts()`, `formatConflictWarning()` |
459
+ | `context-compression.js` | Context Compression Module | `compressContext()`, `estimateTokenCount()`, `buildPreamble()`, `DEFAULT_TOKEN_LIMIT()` |
460
+ | `context.js` | Context Filtering Module | `filterContext()`, `parseDuration()`, `estimateTokens()`, `takeLastNTurns()` |
461
+ | `drift.js` | Context Drift Detection Module | `calculateDrift()`, `formatDriftWarning()`, `countTurnsSince()`, `isDriftSignificant()` |
462
+ | `environment.js` | Environment Detection Module | `inferClient()`, `getSessionRoot()`, `detectEnvironment()`, `VALID_CLIENTS()` |
463
+ | `headless.js` | Headless Mode Runner | `runHeadless()`, `waitForServer()`, `withTimeout()`, `extractSummary()`, `findTrailingFoldMarker()` |
464
+ | `index.js` | Amicus - Main Module | `startAmicus()`, `listAmicus()`, `resumeAmicus()`, `continueAmicus()`, `readAmicus()` |
465
+ | `jsonl-parser.js` | JSONL Parser | `parseJSONLLine()`, `readJSONL()`, `extractTimestamp()`, `formatMessage()`, `formatContext()` |
466
+ | `mcp-council-awareness.js` | | `subWaveIds()`, `countWaveLegs()`, `elapsedOf()`, `enginePid()`, `buildCouncilStatusPayload()` |
467
+ | `mcp-council-bench.js` | | `resolveBenchInput()`, `auditBenchAliases()` |
468
+ | `mcp-council-run.js` | | `handleCouncilRunTool()`, `COUNCIL_PACK_PARAM_MAP()`, `buildCouncilStatusPayload()`, `listCouncilRuns()`, `abortCouncilRun()` |
469
+ | `mcp-notify.js` | Pure helpers + in-process registry for the MCP `onComplete: 'mcp-notify'` | `validateOnComplete()`, `buildNotifyPayload()`, `requestMcpNotify()`, `consumeMcpNotify()` |
470
+ | `mcp-server.js` | @module mcp-server — Amicus MCP Server (stdio transport) | `handlers()`, `startMcpServer()`, `getProjectDir()`, `resolveProjectDir()`, `getClientRoot()` |
471
+ | `mcp-spend.js` | | `amicus_spend()`, `buildSpendResult()` |
472
+ | `mcp-tools.js` | MCP Tool Definitions for Amicus | `getTools()`, `getGuideText()`, `safeTaskId()`, `safeModel()` |
473
+ | `mcp-wait.js` | Engine for the amicus_wait MCP tool: blocks inside one tool call until a session/wave reaches a terminal state or the wait window closes. | `runWait()`, `registerInProcessRun()`, `settleInProcessRun()`, `hasInProcessRun()`, `clampTimeout()` |
474
+ | `opencode-client.js` | OpenCode SDK Client Wrapper | `INSUFFICIENT_CREDITS_REASON()`, `providerErrorReason()`, `parseModelString()`, `createClient()`, `createSession()` |
475
+ | `project-root-allowlist.js` | The MCP `project` / cwd input becomes the session-store parent AND the spawned | `isAllowedProjectRoot()`, `isPathInside()`, `allowedRoots()` |
476
+ | `prompt-builder.js` | System Prompt Builder | `buildSystemPrompt()`, `buildPrompts()`, `buildEnvironmentSection()`, `getSummaryTemplate()`, `SUMMARY_TEMPLATE()` |
477
+ | `session-manager.js` | Session Manager Module | `createSession()`, `updateSession()`, `getSession()`, `saveConversation()`, `saveSummary()` |
478
+ | `session.js` | Session Resolver | `encodeProjectPath()`, `getSessionDirectory()`, `getSessionId()`, `resolveSession()` |
479
+ | `spend-query.js` | | `filterRows()`, `groupRows()`, `computeWasted()`, `emptyTokens()`, `addTokens()` |
480
+ | `council/anonymize.js` | | `assignLabels()`, `toGlobalId()`, `toGlobalFindings()`, `rankingToOrder()`, `LETTERS()` |
481
+ | `council/briefings-chair-task.js` | | `CHAIR_ANSWER_VALUES()`, `ANSWER_SCALE_ADDENDUM()`, `TASK_CHAIR_SYNTHESIS()`, `TASK_CHAIR_SYNTHESIS_NO_CLAIMS()`, `TASK_CONCURRENCE_CAVEAT()` |
482
+ | `council/briefings-chair.js` | | `dateLine()`, `CHAIR_NO_TOOLS_PREAMBLE()`, `chairRepairPromptFor()`, `CHAIR_VERDICT_VALUES()`, `VERDICT_SCALE_ADDENDUM()` |
483
+ | `council/briefings-debate.js` | | `DEBATE_NO_TOOLS_PREAMBLE()`, `DEFENSE_CONTRACT()`, `REVOTE_CONTRACT()`, `buildDefenseBrief()`, `buildRevoteBundle()` |
484
+ | `council/briefings-stage2-task.js` | | `TASK_JUDGE_FRAME()`, `TASK_JUDGE_A()`, `TASK_JUDGE_B()`, `TASK_JUDGE_B_NO_CLAIMS()`, `NO_CLAIMS_INDEX()` |
485
+ | `council/briefings-stage2.js` | | `JUDGE_NO_TOOLS_PREAMBLE()`, `CHAIR_NO_TOOLS_PREAMBLE()`, `CHAIR_VERDICT_VALUES()`, `JUDGE_OUTPUT_CONTRACT()`, `VERDICT_SCALE_ADDENDUM()` |
486
+ | `council/briefings-task.js` | | `TASK_ANTI_SYCOPHANCY_CLAUSE()`, `TASK_FINDINGS_JSON_SHAPE()`, `TASK_FINDINGS_CONTRACT()`, `buildTaskSeatBriefing()`, `buildTaskCriticBriefing()` |
487
+ | `council/briefings.js` | | `ANTI_SYCOPHANCY_CLAUSE()`, `FINDINGS_CONTRACT()`, `FINDINGS_JSON_SHAPE()`, `FINDINGS_TWO_PART_FRAMING()`, `buildSeatBriefing()` |
488
+ | `council/chair-fallback.js` | | `pickFallbackChair()`, `classifyChairAttempt()` |
489
+ | `council/debate.js` | | `applyDebate()`, `decorateRecord()`, `debateRunStatsRows()`, `PAST_TENSE()`, `DEBATE_ROLES()` |
490
+ | `council/findings.js` | | `validateFindings()`, `buildValidateDoc()`, `SEVERITIES()`, `lastJsonBlock()`, `countAttemptedFindings()` |
491
+ | `council/ledger-join.js` | | `benchLegs()`, `credFor()`, `splitFindingsBySeat()`, `meanCred()` |
492
+ | `council/ledger-stats.js` | | `LEDGER_FILE()`, `readRows()`, `avg()`, `countRuns()`, `deriveReliability()` |
493
+ | `council/ledger.js` | | `buildLedgerRows()`, `appendRun()`, `deriveReliability()`, `buildStatsDoc()`, `LEDGER_FILE()` |
494
+ | `council/parse-stage2.js` | | `parseJudgeOutput()`, `parseChairVerdict()`, `CHAIR_VERDICTS()`, `JUDGE_VERDICTS()`, `parseChairAnswer()` |
495
+ | `council/peer-split.js` | | `peersOf()`, `unattributedPeerDrops()` |
496
+ | `council/presets-cli.js` | | `runSave()`, `runList()`, `runShow()` |
497
+ | `council/report-cost.js` | | `buildCostModel()` |
498
+ | `council/report-html.js` | | `renderHtml()` |
499
+ | `council/report-md.js` | | `renderMd()` |
500
+ | `council/report.js` | | `buildReport()`, `toModel()`, `TIER_ORDER()`, `SYMBOL()`, `isSeatSpace()` |
501
+ | `council/run-assemble.js` | | `buildRunStatsEntry()`, `worseConformance()`, `buildTallyInput()`, `writeTallyFiles()`, `writeVerdictFiles()` |
502
+ | `council/run-budget.js` | | `createBudget()` |
503
+ | `council/run-chair.js` | | `runChair()`, `pickFallbackChair()`, `classifyChairAttempt()` |
504
+ | `council/run-debate-revote.js` | | `legOpts()`, `legRow()`, `runRevoteWave()` |
505
+ | `council/run-debate-stage.js` | | `runDebateStage()` |
506
+ | `council/run-debate.js` | | `runDebate()`, `nothingToDebate()`, `disputingJudges()`, `debateTargets()` |
507
+ | `council/run-degrade.js` | | `createDegradeSink()` |
508
+ | `council/run-finalize.js` | | `statusForExit()`, `resolveTerminalExit()`, `writeRunTerminal()`, `SIGNAL_EXIT()` |
509
+ | `council/run-finish.js` | | `finishRun()` |
510
+ | `council/run-launch.js` | | `createLaunchers()`, `materializeReviews()`, `materializeDebate()`, `sanitizeName()`, `isAbortExit()` |
511
+ | `council/run-retry-group.js` | | `lensIndexOf()`, `recordFailure()`, `groupStage1Losses()`, `planStillDeadSources()`, `seatKey()` |
512
+ | `council/run-retry-keys.js` | | `seatKey()`, `twinAliases()`, `legLossKey()`, `srcLegClaimer()` |
513
+ | `council/run-retry-launch.js` | | `briefingFor()`, `bindRetryWave()` |
514
+ | `council/run-retry-notes.js` | | `waveStillDeadNote()`, `skippedWaveNote()`, `srcLegStillDeadNote()`, `retryLegStillDeadNote()`, `missingLegStillDeadNote()` |
515
+ | `council/run-retry-window.js` | The Stage-1 retry's no-output window: how long a RELAUNCHED leg may stay | `retryBackstopMs()` |
516
+ | `council/run-retry.js` | | `groupStage1Losses()`, `retryStage1Losses()` |
517
+ | `council/run-server.js` | | `acquireRunServer()`, `releaseRunServer()`, `resolveRunServerModels()`, `recordServerFate()` |
518
+ | `council/run-stage1-launch.js` | Stage-1 launch pass for the council engine. | `launchStage1()` |
519
+ | `council/run-stage1-rows.js` | | `pushDeadSeatRows()`, `supersededRows()` |
520
+ | `council/run-stage1-superseded.js` | | `supersededRows()` |
521
+ | `council/run-stage2.js` | | `runStage2()` |
522
+ | `council/run-stages.js` | | `runStage1()`, `runStage2()`, `isAbortExit()`, `slug()`, `roleFor()` |
523
+ | `council/run-state.js` | | `RUN_FILE()`, `readRun()`, `initRun()`, `initCouncilRun()`, `checkpoint()` |
524
+ | `council/run-stats-entry.js` | | `buildRunStatsEntry()` |
525
+ | `council/run-verdict-files.js` | | `writeVerdictFiles()` |
526
+ | `council/run.js` | | `runCouncil()`, `pickFallbackChair()`, `SIGNAL_EXIT()` |
527
+ | `council/seats.js` | | `buildSeats()`, `roleAt()`, `bindSeats()`, `artifactName()`, `displayName()` |
528
+ | `council/stage1-bind.js` | | `bindStage1Waves()`, `orphanLegNote()`, `missingSeatDeadWave()`, `bindPaddedWave()` |
529
+ | `council/street-cred.js` | | `computeStreetCred()`, `rankPositions()`, `credSeats()` |
530
+ | `council/tally.js` | | `assignTier()`, `computeStreetCred()`, `tally()`, `COUNCIL_SCHEMA_VERSION()` |
531
+ | `council/verdict-seat-loss.js` | | `summarizeSeatLoss()`, `deriveSeatLoss()` |
532
+ | `council/verdict-seats-reviewed.js` | #202: the bench-seat census for verdict.json, as a spreadable fragment. | `seatsReviewedOf()` |
533
+ | `council/verdict.js` | | `buildVerdict()`, `summarizeSeatLoss()`, `deriveSeatLoss()`, `readOverallVerdict()`, `readPriorVerdictSurfaces()` |
534
+ | `design/tokens.js` | | `tokenCss()`, `TOKENS()` |
535
+ | `observe/council-legs.js` | | `buildLegRows()` |
536
+ | `observe/events.js` | | `appendEvent()`, `createEventTail()`, `EVENTS_FILE()`, `EVENTS_SCHEMA_VERSION()`, `emitWaveStarted()` |
537
+ | `observe/follow.js` | | `createFollowPrinter()` |
538
+ | `observe/live-doc.js` | | `enrichLegUsage()`, `markLive()`, `rollupWaveUsage()`, `TERMINAL()` |
539
+ | `observe/on-complete.js` | | `buildHookEnv()`, `runOnComplete()`, `fireWaveOnComplete()`, `fireCouncilOnComplete()`, `HOOK_TIMEOUT_MS()` |
540
+ | `observe/watch-render.js` | | `renderTable()`, `renderPlainLines()`, `mapExitCode()`, `emitJsonChange()`, `runWatchLoop()` |
541
+ | `pack/pack-cli.js` | | `applyPackOrExit()` |
542
+ | `pack/pack-forward.js` | | `prepareForward()` |
543
+ | `pack/pack-resolve.js` | | `applyPackToArgs()`, `applyPackToMcpInput()` |
544
+ | `pack/pack-store.js` | | `packsDir()`, `canonicalHash()`, `resolvePackRef()`, `readPack()`, `writePack()` |
545
+ | `pack/pack-validate.js` | | `validatePack()`, `KIND_OPTIONS()`, `KINDS()` |
546
+ | `prompts/cowork-agent-prompt.js` | Cowork Agent Prompt | `buildCoworkAgentPrompt()` |
547
+ | `sidecar/budget.js` | | `checkBudget()`, `formatBudgetError()`, `DEFAULT_MAX_COST_PER_MTOK()`, `ASSUMED_OUTPUT_TOKENS()` |
548
+ | `sidecar/child-sessions.js` | | `collectSubtreeUsage()`, `subtreeIsUnknown()`, `SUBTREE_MAX_DEPTH()`, `SUBTREE_MAX_SESSIONS()` |
549
+ | `sidecar/context-builder.js` | Context Builder Module | `buildContext()`, `parseDuration()`, `resolveSessionFile()`, `applyContextFilters()`, `findCoworkSession()` |
550
+ | `sidecar/continue.js` | Sidecar Continue Operations - Handles continuing from previous sessions | `loadPreviousSession()`, `buildContinuationContext()`, `createContinueSessionMetadata()`, `continueSidecar()` |
551
+ | `sidecar/conversation-mirror.js` | | `createMirrorState()`, `mirrorMessages()`, `logMessage()`, `mirrorUsageOnly()`, `allAssistantUsagePresent()` |
552
+ | `sidecar/crash-handler.js` | Crash Handler - Updates metadata to 'error' on uncaught exceptions | `installCrashHandler()` |
553
+ | `sidecar/electron-cache.js` | Electron download-cache root resolution (#53 helper). | `resolveCacheRoots()`, `defaultCacheRoot()` |
554
+ | `sidecar/electron-ensure.js` | ensureElectron() — lazy first-GUI provisioning (#55). | `ensureElectron()`, `_resetEnsureElectron()` |
555
+ | `sidecar/electron-install.js` | Electron self-heal primitive (#53, #59). | `resolveElectronBinary()`, `isElectronUsable()`, `cachedZip()`, `repairElectron()`, `platformExe()` |
556
+ | `sidecar/electron-lock.js` | Stale-aware single-flight lock for the electron self-heal (#53). | `acquireRepairLock()`, `isStaleLock()`, `lockPathFor()`, `STALE_MS()` |
557
+ | `sidecar/electron-provision.js` | Electron CONTROLLED provision — the pinned download, and what happens to a | `cacheRootFor()`, `controlledProvision()`, `mayDeleteRejectedZip()`, `rejectCachedZip()`, `isUnsafeArchive()` |
558
+ | `sidecar/electron-quarantine.js` | AV / antivirus quarantine detection for the electron self-heal (#53). | `avHint()`, `quarantineReason()`, `verifyExtractOutcome()` |
559
+ | `sidecar/electron-state.js` | Electron install-state probes (#76). | `electronDirFor()`, `probeElectronState()` |
560
+ | `sidecar/electron-trust.js` | Electron artifact TRUST core — the digest anchor, the gate, and the env scrub. | `electronTrustPolicy()`, `resolveAnchor()`, `expectedDigest()`, `verifyArtifact()`, `sha256File()` |
561
+ | `sidecar/fallback-chains.js` | | `resolveFallbackConfig()`, `deriveChain()`, `vendorOf()`, `DEFAULT_MAX_SUBSTITUTIONS()` |
562
+ | `sidecar/fanout-budget.js` | | `preflightBudget()` |
563
+ | `sidecar/fanout-leg-fallback.js` | | `runLegWithFallback()`, `recordAttemptSpend()`, `sumAttemptUsage()` |
564
+ | `sidecar/fanout-leg.js` | | `legStatusFromResult()`, `writeLegPatch()`, `runLeg()`, `buildRoutingFailureLeg()`, `runSingleAttempt()` |
565
+ | `sidecar/fanout-output.js` | | `formatWaveHuman()`, `fmtDuration()` |
566
+ | `sidecar/fanout-retry.js` | | `ELIGIBLE_RETRY()`, `parseInitialContext()`, `buildRetryPlan()`, `retryFailedWave()` |
567
+ | `sidecar/fanout-signals.js` | | `installWaveAbort()`, `WAVE_FORCE_EXIT_MS()` |
568
+ | `sidecar/fanout-validate.js` | | `parseModelsList()`, `DEFAULT_MAX_LEGS()`, `validateFanoutModels()` |
569
+ | `sidecar/fanout-wave-io.js` | | `writeWaveMetadata()`, `writeWaveDoc()`, `finishWave()`, `stampLegAttribution()` |
570
+ | `sidecar/fanout.js` | | `parseModelsList()`, `deriveLegIds()`, `validateFanoutModels()`, `DEFAULT_MAX_LEGS()`, `runFanout()` |
571
+ | `sidecar/interactive-abort.js` | | `startAbortWatch()`, `markResultAborted()`, `readAbortedMarker()`, `DEFAULT_INTERVAL_MS()` |
572
+ | `sidecar/interactive-mirror.js` | | `startInteractiveMirror()` |
573
+ | `sidecar/interactive-process.js` | Sidecar Interactive Process Helpers - Electron probe/env/process-exit plumbing | `getElectronPath()`, `checkElectronAvailable()`, `buildElectronEnv()`, `handleElectronProcess()` |
574
+ | `sidecar/interactive.js` | Sidecar Interactive Mode - Electron GUI session management | `runInteractive()` |
575
+ | `sidecar/leg-ids.js` | | `deriveLegIds()` |
576
+ | `sidecar/list-council.js` | Council rows on the CLI `amicus list` surface (v4.9 W12). | `padModel()`, `modelCell()`, `mergeCouncilRows()`, `councilScopeNotice()` |
577
+ | `sidecar/list-limit.js` | The `--limit` core behind `amicus list` (v4.7 PR3 rider). | `normalizeLimit()`, `truncationNotice()` |
578
+ | `sidecar/list-search.js` | The `--search` core behind both list surfaces (F8 D15, errata E-PR3-5). | `searchSessions()` |
579
+ | `sidecar/models-ceiling-line.js` | The one `Ceilings:` line `amicus models --refresh` prints (#218 P3). | `fmtCeilingLine()` |
580
+ | `sidecar/models-probe.js` | | `probeStoredAliases()`, `selectStoredAliases()`, `PROBE_WINDOW_MS()`, `PROBE_PROMPT()` |
581
+ | `sidecar/models-render.js` | Presentation helpers for `amicus models` -- pure string formatting, no I/O. | `perMtok()`, `fmtRow()`, `fmtGatewayFinding()`, `PROBE_LABELS()`, `fmtProbeCost()` |
582
+ | `sidecar/models.js` | `amicus models` (F5) — list/search the catalog, refresh it, audit aliases. | `handleModels()`, `buildFallbackDriftReport()` |
583
+ | `sidecar/progress-fields.js` | Derived, agent-facing progress fields shared by the MCP status/list | `sanitizePreview()`, `latestAssistantPreview()`, `deriveStage()`, `COARSE_STAGES()`, `TERMINAL_PROGRESS_STAGES()` |
584
+ | `sidecar/progress.js` | Sidecar Progress Reader | `readProgress()`, `writeProgress()`, `writeTerminalProgressSafe()`, `extractLatest()`, `computeLastActivity()` |
585
+ | `sidecar/read.js` | Sidecar Read Operations Module | `formatAge()`, `enumerateSessions()`, `enumerateAllProjects()`, `searchSessions()`, `listSidecars()` |
586
+ | `sidecar/reopen-notices.js` | The stderr Notice a reopen owes the user for the effort level it does NOT carry (#218 PR 4, council #235 r5 J1/A3). | `formatDroppedLevelNotice()`, `noticeDroppedLevel()` |
587
+ | `sidecar/reopen-spend.js` | Spend finalization for a REOPENED session (continue/resume). Split out of | `finalizeSpendForReopen()` |
588
+ | `sidecar/resume.js` | Sidecar Resume Operations - Handles resuming previous sidecar sessions | `loadSessionMetadata()`, `loadInitialContext()`, `checkFileDrift()`, `buildDriftWarning()`, `buildResumeUserMessage()` |
589
+ | `sidecar/session-finalize.js` | | `resolveTerminalState()`, `finalizeHeadlessResult()` |
590
+ | `sidecar/session-utils.js` | Sidecar Session Utilities - Shared functionality for session management | `HEARTBEAT_INTERVAL()`, `SessionPaths()`, `saveInitialContext()`, `finalizeSession()`, `outputSummary()` |
591
+ | `sidecar/setup-local.js` | The readline setup wizard's local / self-hosted provider add step (v4.2 §4.6, Task 12). | `addLocalProviderInteractive()` |
592
+ | `sidecar/setup-window.js` | Setup Window Launcher | `launchSetupWindow()` |
593
+ | `sidecar/setup.js` | Sidecar Setup Wizard | `addAlias()`, `addLocalProviderInteractive()`, `createDefaultConfig()`, `deriveFreeAlias()`, `detectApiKeys()` |
594
+ | `sidecar/start-metadata.js` | | `createSessionMetadata()` |
595
+ | `sidecar/start.js` | Sidecar Start Operations - Handles starting new sidecar sessions | `generateTaskId()`, `createSessionMetadata()`, `buildMcpConfig()`, `checkElectronAvailable()`, `runInteractive()` |
596
+ | `sidecar/tool-part.js` | | `TERMINAL_TOOL_STATUSES()`, `LIVE_TOOL_STATUSES()`, `isToolPart()`, `toolPartName()`, `toolPartInput()` |
597
+ | `sidecar/unzip.js` | Robust unzip for the electron self-heal (#53 follow-up; extract-zip-node24). | `robustExtract()`, `nativeUnzipPlan()`, `IDLE_MS()`, `MAX_MS()` |
598
+ | `sidecar/wave-progress.js` | | `formatWaveProgress()`, `readLegState()`, `createWaveHeartbeat()`, `WAVE_HEARTBEAT_INTERVAL()` |
599
+ | `sidecar/workspace-auto-open.js` | Workspace Auto-Open Decision Helper | `shouldAutoOpenWorkspace()` |
600
+ | `sidecar/workspace-window.js` | Council Workspace launcher (v4.4 §4.3/§4.4) — setup-window.js pattern: | `launchWorkspaceWindow()`, `launchWorkspaceWindowDetached()` |
601
+ | `template/apply.js` | | `applyTemplate()`, `ARTIFACT_CAP_BYTES()` |
602
+ | `template/render.js` | | `renderTemplate()`, `KNOWN_VARIABLES()` |
603
+ | `template/store.js` | | `templatesDir()`, `resolveTemplate()`, `listTemplates()`, `BUILTIN_TEMPLATES()` |
604
+ | `utils/abort-coordinator.js` | | `abortGraceMs()`, `isAlive()`, `killPidBestEffort()`, `killPidHard()`, `waitThenKill()` |
605
+ | `utils/abort-result.js` | The abort-result document builder for `abort <taskId|--all> --json` (B21-rest). | `buildAbortResult()` |
606
+ | `utils/activity-poller.js` | | `createActivityPoller()`, `killIfAlive()` |
607
+ | `utils/agent-mapping.js` | Agent Mapping Module | `PRIMARY_AGENTS()`, `OPENCODE_AGENTS()`, `HEADLESS_SAFE_AGENTS()`, `mapAgentToOpenCode()`, `isValidAgent()` |
608
+ | `utils/alias-audit.js` | Alias Audit (F5) — report + suggest for most classes; doctor --fix auto-repairs one narrow, mechanically-unambiguous class (B3). | `collectAliasSources()`, `findStaleAliases()`, `findDriftedStoredAliases()`, `suggestReplacements()`, `findFabricatedAliasRepairs()` |
609
+ | `utils/alias-resolver.js` | Alias Resolver Utilities | `autoRepairAlias()` |
610
+ | `utils/alias-shadow-writer.js` | The alias-shadow notice's WRITE half: say it without ever sinking the run. | `safeWrite()`, `armStream()`, `writeNoticeToStderr()` |
611
+ | `utils/alias-shadow.js` | Alias-shadow self-diagnosis — name a local alias that repoints a curated one. | `findAliasShadows()`, `formatAliasShadow()`, `noteAliasShadows()`, `auditAliasShadows()` |
612
+ | `utils/api-key-store.js` | API Key Store — reading, saving, and validating API keys. | `getEnvPath()`, `loadEnvEntries()`, `readApiKeys()`, `readApiKeyHints()`, `readApiKeyValues()` |
613
+ | `utils/api-key-validation.js` | API Key Validation — test API keys against provider endpoints. | `validateApiKey()`, `redactSecret()`, `validateOpenRouterKey()`, `checkOpenRouterCredit()`, `OPENROUTER_NO_CREDIT_WARNING()` |
614
+ | `utils/atomic-write.js` | Atomic file write helper. | `writeFileAtomic()` |
615
+ | `utils/auth-json.js` | Auth JSON Reader | `readAuthJsonKeys()`, `importFromAuthJson()`, `checkAuthJson()`, `removeFromAuthJson()`, `AUTH_JSON_PATH()` |
616
+ | `utils/base-url-classify.js` | v4.6.2 PR1 (spec §4, D1/D2): ANTHROPIC_BASE_URL classification, the | `classifyBaseUrl()`, `resolveBaseUrlOverride()`, `announceBaseUrlNormalizationOnce()`, `_resetBaseUrlNotice()` |
617
+ | `utils/claude-register.js` | Registration core for amicus: skill install (chat skill + LLM Council), | `MCP_CONFIG()`, `addMcpToConfigFile()`, `installSkill()`, `installCouncilSkill()`, `readPrevClaudeCodeAmicusEntry()` |
618
+ | `utils/cli-preflight.js` | Tiny shared preflight guards used by more than one CLI run handler | `requireNoUiForJson()`, `requireValidTaskId()`, `packSaveVersionConflict()` |
619
+ | `utils/client-detect.js` | Detects which caller (Claude Code vs. Cowork/Claude Desktop) spawned this | `detectClient()`, `matchClientName()` |
620
+ | `utils/config.js` | Amicus Config Module | `getConfigDir()`, `getConfigPath()`, `loadConfig()`, `saveConfig()`, `getDefaultAliases()` |
621
+ | `utils/council-presets.js` | Built-in council benches (B23). | `BUDGET_ALIASES()`, `FRONTIER_ALIASES()`, `resolveBuiltinCouncil()`, `listBuiltinCouncilNames()` |
622
+ | `utils/curated-models.js` | Family definitions + pinned fallbacks for the wizard model picker (v2). | `getFamilies()`, `toDefaultAliases()`, `stripGatewayPrefix()`, `listCuratedRoutes()`, `toGatewayRoutes()` |
623
+ | `utils/degrade.js` | | `makeDegrade()`, `formatDegrade()`, `DEGRADE_CHANNELS()` |
624
+ | `utils/doctor-alias-check.js` | | `evaluateAliasesCheck()`, `repairAlias()` |
625
+ | `utils/doctor-base-url-check.js` | v4.6.2 PR1 (spec §4): the 'anthropic-base-url' doctor row. | `evaluateAnthropicBaseUrl()` |
626
+ | `utils/doctor-credit-check.js` | The `openrouter-credit` doctor row (#43), split out of | `evaluateOpenRouterCredit()` |
627
+ | `utils/doctor-degrade.js` | | `collectDoctorDegrades()` |
628
+ | `utils/doctor-electron-mcp-check.js` | The `electron-mcp` doctor check ("Electron (MCP launch path)"), split out of | `scanElectronInstalls()`, `evaluateElectronInstalls()`, `evaluateElectronMcp()`, `evaluateElectronInteractive()` |
629
+ | `utils/doctor-engine-check.js` | The `engine-mcp` doctor check ("OpenCode engine (MCP launch path)"), split out | `evaluateEngineInstalls()`, `evaluateEngineMcp()` |
630
+ | `utils/doctor-key-auth-check.js` | The `key-auth` doctor row (issue #210), split out of src/cli-handlers-doctor.js | `evaluateKeyAuth()`, `classifyProbeFailure()`, `probeApiKey()`, `probeOpenRouterCredit()`, `liveProbesDisabled()` |
631
+ | `utils/doctor-local-providers-check.js` | The `local-providers` doctor check (v4.2 §4.7 C8), split out of | `evaluateLocalProviders()` |
632
+ | `utils/doctor-mcp-checks.js` | B14/Task 4.3: the two MCP-registration doctor checks ('mcp' and | `evaluateMcpRegistration()`, `evaluateLegacyMcpEntry()` |
633
+ | `utils/doctor-output-budget-check.js` | #218 PR 2: the 'output-budget' doctor row. | `evaluateOutputBudget()` |
634
+ | `utils/doctor-summary.js` | Compact doctor summary (v4.2 §4.7 C8). All-ok -> one line; otherwise the | `summarizeDoctor()` |
635
+ | `utils/engine-ensure.js` | ensureEngine() — runtime engine self-heal at server start (report #2). | `ensureEngine()`, `_resetEnsureEngine()` |
636
+ | `utils/engine-install-scan.js` | Discover + probe every amicus install that could serve the MCP (running, | `listAmicusInstalls()`, `scanEngineInstalls()`, `classifyLaunch()`, `resolveNpmRootG()` |
637
+ | `utils/engine-lock.js` | Stale-aware single-flight lock for the engine self-heal (report #2). | `acquireRepairLock()`, `isStaleLock()`, `lockPathFor()`, `STALE_MS()` |
638
+ | `utils/engine-log-parse.js` | Line-shape parsing for the engine log: level, session, message. | `isErrorLine()`, `extractMessage()`, `collapseExcerpt()`, `mentionsSession()`, `lineIsAboutSession()` |
639
+ | `utils/engine-log-tail.js` | One engine-log FILE: read its tail, find the newest usable excerpt in it. | `newestExcerptInFile()` |
640
+ | `utils/engine-log.js` | Resolve the OpenCode engine's own error line for one session. | `engineErrorForSession()`, `engineLogDirCandidates()`, `isErrorLine()`, `extractMessage()`, `collapseExcerpt()` |
641
+ | `utils/engine-output-flag.js` | #218 PR 2 — the one engine env flag amicus sets: OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX. | `withOutputTokenFlag()`, `outputTokenFlagValue()`, `OUTPUT_TOKEN_FLAG()`, `ENGINE_DEFAULT_OUTPUT_TOKENS()`, `PLAIN_OUTPUT_TOKEN_FLAG()` |
642
+ | `utils/engine-repair.js` | Engine self-heal primitive (report #2): make the opencode engine present ON | `repairEngine()`, `findDonor()`, `engineSourceRoot()`, `copyEnginePackages()`, `runningPkgDir()` |
643
+ | `utils/engine-skew-records.js` | Server identity and the bounded store of standing engine-skew records. | `serverKeyForClient()`, `currentEngineSkew()`, `skewForKey()`, `rememberSkew()`, `forgetSkew()` |
644
+ | `utils/engine-skew.js` | Runtime detection of an opencode ENGINE version skew: server vs installed. | `noteSessionVersion()`, `currentEngineSkew()`, `serverKeyForClient()`, `formatSkewWarning()`, `formatSkewSuffix()` |
645
+ | `utils/engine-variants.js` | The effort lever (#218 PR 4): --thinking sent as the engine's variant field, validated against the engine's own declaration. | `VARIANT_LEVELS()`, `VariantRefusedError()`, `readModelDeclaration()`, `checkVariant()`, `formatUnverifiedVariantNote()` |
646
+ | `utils/env-loader.js` | Credential Loader | `loadCredentials()` |
647
+ | `utils/env-num.js` | | `envNumber()` |
648
+ | `utils/env-raw-store.js` | Arbitrary-env-var writes to the amicus .env (local-provider bearers, v4.2 §4.6). | `saveRawEnv()`, `removeRawEnv()`, `upsertEnvLine()`, `deleteEnvLine()` |
649
+ | `utils/error-classify.js` | | `classifyLegError()`, `isRetryable()` |
650
+ | `utils/error-doc.js` | | `ERROR_CODES()`, `buildErrorDoc()`, `failJson()` |
651
+ | `utils/fold-marker.js` | Fold marker construction/parsing helpers — shared by prompt-builder.js | `FOLD_MARKER_PREFIX()`, `generateFoldNonce()`, `buildFoldMarker()`, `trailingFoldMarkerRegex()`, `extractNonceFromText()` |
652
+ | `utils/format-duration.js` | | `formatDuration()` |
653
+ | `utils/free-models.js` | Free OpenRouter model detection (Unit A). | `isFreeModel()`, `listFreeModels()`, `suggestFreeCouncil()`, `PINNED_FREE_MODELS()` |
654
+ | `utils/gateway-route-audit.js` | Per-gateway-form audit for curated DEFAULT aliases (Task 6, #gwid). | `auditGatewayRoutes()` |
655
+ | `utils/gateway-route-catalog.js` | Conservative cross-gateway catalog pairing helper (Task 5, #gwid). | `pairAcrossGateways()` |
656
+ | `utils/gateway-router.js` | Pure gateway router (#61). Decides direct vs OpenRouter for a request using | `gatewayOf()`, `resolveRoute()` |
657
+ | `utils/http-get.js` | One HTTPS GET, always resolved, never rejected — the timer/destroy/failure | `httpGetText()`, `getJson()`, `DEFAULT_TIMEOUT_MS()`, `DEFAULT_MAX_BYTES()`, `MAX_REDIRECTS()` |
658
+ | `utils/idle-watchdog.js` | IdleWatchdog - BUSY/IDLE state machine with self-terminating timer. | `IdleWatchdog()`, `resolveTimeout()` |
659
+ | `utils/input-validators.js` | | `validateStartInputs()`, `levenshteinDistance()`, `suggestCommand()` |
660
+ | `utils/known-flags.js` | | `getKnownFlags()`, `unknownFlags()`, `INTERNAL_FLAGS()` |
661
+ | `utils/legacy-mcp-migration.js` | | `claudeCodeConfigPath()`, `claudeDesktopConfigPath()`, `inspectLegacySidecarEntry()`, `removeLegacySidecarEntry()`, `inspectAllLegacySidecarEntries()` |
662
+ | `utils/lifecycle.js` | | `isOneShotCommand()`, `armExitWatchdog()`, `exitReaping()`, `ONE_SHOT_COMMANDS()` |
663
+ | `utils/live-probes.js` | The single gate on outbound AUTHENTICATED network probes made by diagnostics | `enableLiveProbes()`, `liveProbesAllowed()`, `_resetLiveProbes()` |
664
+ | `utils/local-probe.js` | | `probeLocalProvider()`, `listLocalModels()` |
665
+ | `utils/local-providers.js` | | `getLocalProviders()`, `isLocalProvider()`, `deriveKeyEnv()`, `validateProviderEntry()`, `resolveLocalRouteInputs()` |
666
+ | `utils/logger.js` | Structured Logger Module | `logger()`, `LOG_LEVELS()` |
667
+ | `utils/mcp-discovery.js` | MCP Discovery - Discovers MCP servers from parent LLM configuration | `discoverParentMcps()`, `discoverClaudeCodeMcps()`, `discoverCoworkMcps()`, `hasAmicusRegistration()`, `readAmicusMcpConfig()` |
668
+ | `utils/mcp-self-identity.js` | | `SELF_MCP_NAMES()`, `isAmicusMcpConfig()`, `stripSelfMcpEntries()`, `normalizeToken()` |
669
+ | `utils/mcp-validators.js` | MCP Validators | `validateMcpSpec()`, `validateMcpConfigFile()` |
670
+ | `utils/model-canonicalization.js` | Direct-first id canonicalization, guarded by `classifyModel` | `directFormIfSafe()`, `directFormIfProven()`, `namespaceFetchFailed()`, `vendorOfId()` |
671
+ | `utils/model-catalog.js` | OpenRouter model catalog cache (F3 #18 / F5 foundation). | `getCatalog()`, `refreshCatalog()`, `catalogPath()`, `getCatalogInfo()`, `readCache()` |
672
+ | `utils/model-ceilings-modelsdev.js` | #218 P3 — output ceilings for the direct-provider catalog rows. | `enrichCeilings()`, `fillCeilings()`, `needsFillCount()`, `limitsFromModelsDev()`, `emptyOutcome()` |
673
+ | `utils/model-classification.js` | Tri-state catalog classification (#61). | `classifyModel()` |
674
+ | `utils/model-descriptor.js` | Model-descriptor grammar + RouteResult factories (#61). | `GATEWAY_MODES()`, `parseDescriptor()`, `resolved()`, `selectionRequired()`, `routeError()` |
675
+ | `utils/model-fetcher.js` | Model Fetcher | `fetchModelsFromProvider()`, `fetchAllModels()`, `fetchAllModelsDetailed()`, `fetchModelsFromProviderDetailed()`, `providersToFetch()` |
676
+ | `utils/model-input-default.js` | | `resolveModelInputOrDefault()` |
677
+ | `utils/model-output-limit.js` | Issue #218 — the per-model `limit` descriptor amicus hands opencode. | `normalizeOutputBudget()`, `buildLimitLookup()`, `computeModelLimit()`, `positiveCount()` |
678
+ | `utils/model-shortlist.js` | Vendor model shortlist (#138) -- the family -> model second level. | `buildModelShortlist()`, `compareShortlistRows()`, `SHORTLIST_LIMIT()` |
679
+ | `utils/model-tiers.js` | Per-vendor cost tiers (economy/balanced/frontier) + resolution against the | `TIERS()`, `TIER_ORDER()`, `resolveTier()` |
680
+ | `utils/model-validator.js` | Model Validator | `filterRelevantModels()`, `normalizeModelId()`, `validateAgainstCatalog()`, `warnIfNotInCatalog()`, `promptRouteSelection()` |
681
+ | `utils/no-output-backstop.js` | v4.6.2 PR2 (spec §5, D4): fail a headless leg fast when the model produces | `resolveNoOutputBackstopMs()`, `createNoOutputBackstop()`, `DEFAULT_NO_OUTPUT_BACKSTOP_MS()` |
682
+ | `utils/node-version-guard.js` | | `checkNodeVersion()`, `MIN_NODE()` |
683
+ | `utils/openrouter-credit.js` | The OpenRouter credit/limit probe, split out of api-key-validation.js to keep | `checkOpenRouterCredit()`, `OPENROUTER_NO_CREDIT_WARNING()`, `OPENROUTER_FREE_TIER_WARNING()` |
684
+ | `utils/output-length.js` | #218 PR 3: name the "Mode 2" death. | `OUTPUT_LENGTH_PREFIX()`, `isOutputLengthDeath()`, `formatOutputLengthReason()` |
685
+ | `utils/path-fence.js` | Shared realpath-containment fence. | `isRealpathContained()`, `containsOnDisk()` |
686
+ | `utils/path-setup.js` | | `ensureNodeModulesBinInPath()`, `hasOpencodeBinary()`, `opencodeRoots()` |
687
+ | `utils/port-pid.js` | Cross-platform listener-PID lookup. | `findListenerPid()` |
688
+ | `utils/pricing.js` | | `emptyUsageTotals()`, `sumPerMessageUsage()`, `lookupPricing()`, `hasObservedTokens()`, `resolveLegCost()` |
689
+ | `utils/project-path.js` | Canonical project-path helper. | `canonicalProjectPath()` |
690
+ | `utils/project-root-sanity.js` | | `assessProjectRoot()`, `looksLikeInstallDir()`, `INSTALL_PATTERNS()` |
691
+ | `utils/prompt-source.js` | | `resolvePromptSource()` |
692
+ | `utils/provider-default-picker.js` | Provider-default picker core (Part 2, Task 4). | `buildProviderDefaultChoices()`, `applyProviderDefault()`, `pricePerMInputFrom()`, `directFormIfSafe()`, `directFormIfProven()` |
693
+ | `utils/provider-default-prompt.js` | Provider-default prompt flow (Part 2, Task 6/7 shared helper). | `runProviderDefaultFlow()`, `formatPrice()`, `formatRow()` |
694
+ | `utils/provider-registry.js` | Provider-capability registry — the single source of truth for provider | `PROVIDERS()`, `getProvider()`, `isDirectProvider()`, `listDirectProviders()`, `PROVIDER_ENV_MAP()` |
695
+ | `utils/quick-picks.js` | Quick-pick resolution (wizard Step 2) — resolves each curated family to | `compareIdsDesc()`, `canonicalRoutesFor()`, `pickCurrent()`, `resolveQuickPicks()`, `toLiveSeedAliases()` |
696
+ | `utils/read-slice.js` | Byte-bounded slicing for amicus_read (15a.3 / B17). | `sliceForRead()`, `READ_CAP_BYTES()` |
697
+ | `utils/remediation-hints.js` | | |
698
+ | `utils/result-schema-rebuild.js` | | `buildRunResultFromSession()`, `buildWaveResultFromSession()` |
699
+ | `utils/result-schema-version.js` | The single SCHEMA_VERSION constant shared by result-schema.js and | `SCHEMA_VERSION()` |
700
+ | `utils/result-schema.js` | | `SCHEMA_VERSION()`, `TERMINAL_STATUSES()`, `durationBetween()`, `statusFromResult()`, `buildRunResult()` |
701
+ | `utils/route-error.js` | Shared renderer (#61 Task 6.1): turns a router RouteResult — an error or a | `toStructuredError()`, `toCliMessage()`, `toErrorDocFields()`, `REASON_TEXT()`, `ROUTE_ERROR_REASONS()` |
702
+ | `utils/route-launch.js` | Route-launch views (#61 gateway routing integration, Task 4.2). | `buildLaunchKeys()`, `getRouteCatalogInfo()`, `resolveRouteForLaunch()`, `buildSuggestions()`, `ROUTE_VERSION()` |
703
+ | `utils/route-suggestions.js` | | `buildSuggestions()`, `applySuggestions()` |
704
+ | `utils/server-setup.js` | Server Setup Utilities | `DEFAULT_PORT()`, `LOCK_RETRY_DELAYS_MS()`, `isPortInUse()`, `getPortPid()`, `killPortProcess()` |
705
+ | `utils/session-abort.js` | Session abort utilities: signal handler installation and terminal metadata writes. | `markTerminal()`, `markAborted()`, `installSignalAbort()`, `idleBackstopTeardown()` |
706
+ | `utils/session-index-prune.js` | | `listStaleSessionIndexEntries()`, `pruneStaleSessionIndexEntries()`, `evaluateSessionIndexPrune()` |
707
+ | `utils/session-index-tmp-sweep.js` | | `AGE_THRESHOLD_MS()`, `listSessionIndexTmpFiles()`, `unlinkSessionIndexTmp()`, `evaluateSessionIndexTmpSweep()` |
708
+ | `utils/session-index.js` | Global session index (issue #40). | `INDEX_FILENAME()`, `recordSession()`, `lookupSessionProject()`, `readIndex()` |
709
+ | `utils/session-lock.js` | | `acquireLock()`, `releaseLock()`, `isLockStale()`, `isPidAlive()` |
710
+ | `utils/session-metadata-tmp-sweep.js` | | `AGE_THRESHOLD_MS()`, `listSessionMetadataTmpFiles()`, `unlinkSessionMetadataTmp()`, `evaluateSessionMetadataTmpSweep()` |
711
+ | `utils/session-path.js` | Session path resolution. | `safeSessionDir()`, `safeSessionDirUnder()` |
712
+ | `utils/session-status.js` | #202: render the engine's SESSION STATUS as a clause on a leg's death report. | `formatSessionStatusSuffix()`, `MAX_STATUS_MESSAGE_CHARS()` |
713
+ | `utils/shared-server.js` | | `SharedServerManager()` |
714
+ | `utils/spend-ledger.js` | | `appendSpend()`, `readSpendRows()`, `SPEND_LEDGER_FILE()`, `SPEND_LEDGER_SCHEMA_VERSION()` |
715
+ | `utils/start-helpers.js` | Start Command Helpers | `resolveLaunchModel()`, `deriveAlias()`, `maybeOfferProviderDefaults()` |
716
+ | `utils/text-sanitize.js` | One third-party string, safe to render: no escapes, no bidi, one short line. | `collapseExcerpt()`, `MAX_EXCERPT_CHARS()` |
717
+ | `utils/thinking-validators.js` | Thinking Level Validators | `VARIANT_LEVELS()`, `validateThinkingLevel()` |
718
+ | `utils/ttft.js` | The one honesty predicate for the time-to-first-token probe (v4.9 W13). | `isMeasuredTtft()` |
719
+ | `utils/untrusted-fence.js` | Untrusted sidecar output fence. | `fenceSidecarOutput()`, `defangOutboundFenceTags()`, `OUTBOUND_FENCE_TAGS()` |
720
+ | `utils/update-notice.js` | The MCP server is the one entry point that skips bin/amicus.js's update | `classifySelfInstall()`, `upgradeInstruction()`, `buildUpdateNotice()`, `maybeAppendUpdateNotice()`, `guideUpdateLine()` |
721
+ | `utils/update-notifier-loader.js` | update-notifier Loader | `loadUpdateNotifier()` |
722
+ | `utils/updater.js` | Updater Module | `initUpdateCheck()`, `getUpdateInfo()`, `notifyUpdate()`, `performUpdate()` |
723
+ | `utils/validators.js` | Input Validators | `VALID_AGENT_MODES()`, `PROVIDER_KEY_MAP()`, `VARIANT_LEVELS()`, `TASK_ID_PATTERN()`, `validateTaskId()` |
724
+ | `utils/version-info.js` | After an `npm i -g amicus` upgrade, a long-lived MCP server process keeps | `RUNNING_VERSION()`, `readOnDiskVersion()`, `versionWarning()`, `PKG_PATH()` |
725
+ | `workspace/artifact-guard.js` | Council Workspace — artifact read guard (v4.4 §4.5 workspace:read-artifact). | `artifactAllowlist()`, `isSeatTable()`, `readRunArtifact()`, `isRealpathContained()`, `FIXED_ARTIFACTS()` |
726
+ | `workspace/artifact-names.js` | Council Workspace — artifact NAME derivation (v4.8 PR5a). | `artifactAllowlist()`, `isSeatTable()`, `orphanExonerations()`, `FIXED_ARTIFACTS()`, `DEBATE_ARTIFACTS()` |
727
+ | `workspace/blind-mode.js` | Council Workspace — blind-mode name mapping (v4.4 §6.3). | `buildNamePairs()`, `labelFor()`, `pairFor()` |
728
+ | `workspace/fold-format.js` | Council Workspace — fold payload builder (v4.4 §7). | `buildFoldText()` |
729
+ | `workspace/live-normalize.js` | Council Workspace — live-doc normalization (v4.4 §3 A1/A2/A4 seam). | `normalizeLive()` |
730
+ | `workspace/matrix-model.js` | Council Workspace — adjudication matrix view model (v4.4 §5.2). | `buildMatrixModel()` |
731
+ | `workspace/run-detail.js` | Council Workspace — run detail: defensive parse of run.json / tally.json / | `getRunDetail()`, `costPanel()`, `TERMINAL_STATUSES()`, `STAGE_LABELS()` |
732
+ | `workspace/run-scan.js` | Council Workspace — run discovery (v4.4 spec §4.3 / §5.1). | `scanCouncilRuns()`, `readPointer()`, `POINTER_RE()` |
733
+ | `workspace/seat-space.js` | Council Workspace — the seat-space PREDICATES (v4.8 PR5b). | `isSeatTable()`, `orphanExonerations()` |
734
+ <!-- /AUTO:modules -->
735
+
736
+ ---