amicus 4.3.0 → 4.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +64 -0
- package/README.md +6 -3
- package/docs/DISTRIBUTION.md +234 -0
- package/docs/ROADMAP.md +200 -0
- package/docs/SHIMS.md +62 -0
- package/docs/architecture.md +104 -0
- package/docs/configuration.md +371 -0
- package/docs/council.md +911 -0
- package/docs/doc-system.md +92 -0
- package/docs/electron-testing.md +471 -0
- package/docs/jsdoc-setup.md +75 -0
- package/docs/opencode-integration.md +114 -0
- package/docs/publishing.md +60 -0
- package/docs/schemas.md +55 -0
- package/docs/testing.md +589 -0
- package/docs/troubleshooting.md +298 -0
- package/docs/usage.md +699 -0
- package/electron/fold.js +1 -1
- package/electron/ipc-workspace.js +283 -0
- package/electron/main.js +31 -1
- package/electron/preload-workspace.js +40 -0
- package/electron/setup-ui-aliases.js +6 -6
- package/electron/workspace-shell.js +85 -0
- package/electron/workspace-ui/index.html +111 -0
- package/electron/workspace-ui/live-model.js +112 -0
- package/electron/workspace-ui/md-lite.js +163 -0
- package/electron/workspace-ui/workspace-app.js +240 -0
- package/electron/workspace-ui/workspace-matrix.js +249 -0
- package/electron/workspace-ui/workspace-panels.js +237 -0
- package/electron/workspace-ui/workspace-render.js +277 -0
- package/electron/workspace-ui/workspace-verbs.js +293 -0
- package/electron/workspace-ui/workspace.css +172 -0
- package/package.json +8 -3
- package/schemas/council-run-live.schema.json +25 -1
- package/schemas/council-run.schema.json +34 -0
- package/schemas/progress.schema.json +26 -1
- package/schemas/spend.schema.json +52 -4
- package/skills/second-opinion/MODEL-NOTES.md +53 -5
- package/src/cli-handlers-council-run.js +25 -3
- package/src/cli-handlers-spend.js +50 -5
- package/src/cli-handlers-watch.js +48 -10
- package/src/cli.js +4 -2
- package/src/council/briefings-debate.js +27 -7
- package/src/council/briefings-stage2.js +155 -25
- package/src/council/briefings.js +59 -3
- package/src/council/findings.js +236 -9
- package/src/council/parse-stage2.js +10 -2
- package/src/council/report.js +19 -8
- package/src/council/run-assemble.js +42 -1
- package/src/council/run-budget.js +277 -0
- package/src/council/run-chair.js +4 -1
- package/src/council/run-debate.js +4 -2
- package/src/council/run-finalize.js +102 -0
- package/src/council/run-launch.js +73 -7
- package/src/council/run-server.js +248 -0
- package/src/council/run-stage2.js +118 -0
- package/src/council/run-stages.js +148 -113
- package/src/council/run-state.js +23 -1
- package/src/council/run.js +52 -53
- package/src/council/tally.js +10 -0
- package/src/headless.js +519 -17
- package/src/mcp-council-awareness.js +53 -3
- package/src/observe/council-legs.js +240 -0
- package/src/observe/live-doc.js +39 -4
- package/src/observe/watch-render.js +23 -1
- package/src/opencode-client.js +15 -3
- package/src/sidecar/child-sessions.js +197 -0
- package/src/sidecar/conversation-mirror.js +111 -37
- package/src/sidecar/fanout-budget.js +71 -0
- package/src/sidecar/fanout-leg-fallback.js +69 -21
- package/src/sidecar/fanout-leg.js +29 -1
- package/src/sidecar/fanout-signals.js +61 -0
- package/src/sidecar/fanout-wave-io.js +75 -0
- package/src/sidecar/fanout.js +65 -81
- package/src/sidecar/progress-fields.js +26 -4
- package/src/sidecar/progress.js +8 -1
- package/src/sidecar/session-utils.js +23 -14
- package/src/sidecar/tool-part.js +196 -0
- package/src/sidecar/workspace-window.js +62 -0
- package/src/spend-query.js +33 -6
- package/src/utils/env-num.js +42 -0
- package/src/utils/lifecycle.js +37 -1
- package/src/utils/path-fence.js +120 -0
- package/src/utils/pricing.js +114 -9
- package/src/utils/server-setup.js +79 -1
- package/src/utils/spend-ledger.js +24 -3
- package/src/workspace/artifact-guard.js +208 -0
- package/src/workspace/blind-mode.js +32 -0
- package/src/workspace/fold-format.js +124 -0
- package/src/workspace/live-normalize.js +169 -0
- package/src/workspace/matrix-model.js +94 -0
- package/src/workspace/run-detail.js +229 -0
- package/src/workspace/run-scan.js +148 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# OpenCode Integration
|
|
2
|
+
|
|
3
|
+
How Amicus integrates with OpenCode's native capabilities and avoids redundant implementations.
|
|
4
|
+
|
|
5
|
+
## SDK & API Notes
|
|
6
|
+
|
|
7
|
+
### OpenCode SDK Requirements
|
|
8
|
+
|
|
9
|
+
- SDK's `createOpencodeServer()` spawns `opencode` CLI internally
|
|
10
|
+
- `opencode-ai` is a regular dependency -- its binary is in `node_modules/.bin/`
|
|
11
|
+
- `src/utils/path-setup.js` adds `node_modules/.bin/` to PATH so the binary is always found
|
|
12
|
+
- SDK is ESM-only; use dynamic `import()` not `require()` in CommonJS projects
|
|
13
|
+
- Jest can't mock dynamic imports without `--experimental-vm-modules` - skip those tests
|
|
14
|
+
|
|
15
|
+
### OpenCode API Format
|
|
16
|
+
|
|
17
|
+
- Model must be object: `{ providerID: 'openrouter', modelID: 'google/gemini-2.5-flash' }`
|
|
18
|
+
- Sending model as string causes 400 Bad Request
|
|
19
|
+
- Use `formatModelForAPI()` from `electron/ui/model-picker.js` for conversion
|
|
20
|
+
|
|
21
|
+
### Session Status Idle Signal
|
|
22
|
+
|
|
23
|
+
The OpenCode SDK exposes `client.session.status({ path: { id } })`, wrapped by `getSessionStatus()` in `src/opencode-client.js`. In headless runs this is the **authoritative completion signal**: when the response is `{ type: 'idle' }`, the poll loop in `src/headless.js` treats the session as done and exits immediately.
|
|
24
|
+
|
|
25
|
+
This signal is **gated on real output existing** (the `output.length > 0` check at `src/headless.js` line 500) so a pre-processing `idle` response from the SDK cannot end the run before the model has produced any text. If the status call fails or returns an unexpected shape, the code falls back transparently to the activity-heuristic idle detection (consecutive polls with no output growth, no new tool calls, no new messages). This gating was introduced as the F1 authoritative-idle-signal improvement.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## What OpenCode Provides (Use Native APIs)
|
|
30
|
+
|
|
31
|
+
| Feature | OpenCode API | How We Use It |
|
|
32
|
+
|---------|-------------|---------------|
|
|
33
|
+
| **Agent Types** | Native `build`, `plan`, `explore`, `general`, `chat` | Pass `agent` parameter to `sendPrompt()` |
|
|
34
|
+
| **Tool Permissions** | Enforced by agent framework | NO custom prompt-based restrictions |
|
|
35
|
+
| **Session Status** | `session.status()` | Used in `headless.js` as authoritative idle signal (F1) |
|
|
36
|
+
| **Session Messages** | `session.messages()` | Used for polling and conversation capture |
|
|
37
|
+
| **Child Sessions** | `session.create({ parentID })` | Used for subagent spawning |
|
|
38
|
+
| **Health Check** | `config.get()` | Used to verify server ready state |
|
|
39
|
+
|
|
40
|
+
## What We Built (Unique Value)
|
|
41
|
+
|
|
42
|
+
| Feature | Why We Need It | Implementation |
|
|
43
|
+
|---------|----------------|----------------|
|
|
44
|
+
| **Context Extraction** | Bridge Claude Code sessions to OpenCode | `context.js` reads `.jsonl` files |
|
|
45
|
+
| **File Conflict Detection** | Safety feature - OpenCode doesn't track this | `conflict.js` compares mtimes |
|
|
46
|
+
| **Context Drift Detection** | Safety feature - detect stale context | `drift.js` calculates staleness |
|
|
47
|
+
| **Session Persistence** | Custom metadata (briefing, agent, thinking) | `session-manager.js` |
|
|
48
|
+
| **MCP Config Merging** | CLI overrides + file config | `opencode-client.js` |
|
|
49
|
+
| **Client-aware prompt** | Cowork needs general-purpose, not SE-focused | `prompts/cowork-agent-prompt.js` sets `chat` agent `prompt` field |
|
|
50
|
+
|
|
51
|
+
## Removed Redundancies
|
|
52
|
+
|
|
53
|
+
The following custom implementations were **removed** because OpenCode handles them natively:
|
|
54
|
+
|
|
55
|
+
| Removed | Reason | Native Replacement |
|
|
56
|
+
|---------|--------|-------------------|
|
|
57
|
+
| ~~`buildCodeModeEnvironment()`~~ | Tool restrictions in prompts | OpenCode `build` agent |
|
|
58
|
+
| ~~`buildPlanModeEnvironment()`~~ | Tool restrictions in prompts | OpenCode `plan` agent |
|
|
59
|
+
| ~~`buildAskModeEnvironment()`~~ | Tool restrictions in prompts | OpenCode `build` with `permissions` |
|
|
60
|
+
| ~~Custom heartbeat polling~~ | Basic sleep loop | `session.status()` API |
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Agent Type Mapping
|
|
65
|
+
|
|
66
|
+
Agent name mapping is implemented in `src/utils/agent-mapping.js`. All known OpenCode native agents are normalised to lowercase before being sent to the API:
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
// src/utils/agent-mapping.js
|
|
70
|
+
mapAgentToOpenCode('build') // -> { agent: 'build' }
|
|
71
|
+
mapAgentToOpenCode('plan') // -> { agent: 'plan' }
|
|
72
|
+
mapAgentToOpenCode('explore') // -> { agent: 'explore' }
|
|
73
|
+
mapAgentToOpenCode('general') // -> { agent: 'general' }
|
|
74
|
+
mapAgentToOpenCode('chat') // -> { agent: 'chat' }
|
|
75
|
+
mapAgentToOpenCode('custom') // -> { agent: 'custom' } // passed through as lowercase
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Default when agent is unset:** `mapAgentToOpenCode(undefined)` returns `{ agent: 'chat' }`.
|
|
79
|
+
|
|
80
|
+
**Headless mode default:** When `--no-ui` is set, Amicus hard-codes `agent || 'build'` before calling `mapAgentToOpenCode` (`src/headless.js` line 275), so the effective default in headless mode is `build`, not `chat`. The `chat` agent requires user interaction for write/bash permissions and stalls in headless mode.
|
|
81
|
+
|
|
82
|
+
`isHeadlessSafe(agent)` returns `true` (safe: build/plan/explore/general), `false` (unsafe: chat), or `null` (custom/unknown).
|
|
83
|
+
|
|
84
|
+
## Key Integration Files
|
|
85
|
+
|
|
86
|
+
| File | OpenCode Integration |
|
|
87
|
+
|------|---------------------|
|
|
88
|
+
| `src/opencode-client.js` | SDK wrapper - `createSession()`, `sendPrompt()`, `getSessionStatus()` |
|
|
89
|
+
| `src/headless.js` | Uses `session.status()` for authoritative idle detection (F1); falls back to activity heuristic |
|
|
90
|
+
| `src/utils/agent-mapping.js` | Maps Amicus agent names to OpenCode agents (all lowercase) |
|
|
91
|
+
| `electron/main.js` | Creates child sessions for subagents |
|
|
92
|
+
| `src/sidecar/fanout.js` | `amicus fanout` reuses the same `runHeadless` path per leg over one shared server — see [Fanout Wave Architecture](architecture.md#fanout-wave-architecture). |
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Backward Compatibility
|
|
97
|
+
|
|
98
|
+
**Removed in v2.0.0.** Through v1.9.1, `src/index.js` exported `startSidecar`, `listSidecars`, `resumeSidecar`, `continueSidecar`, `readSidecar` from the package root as deprecated aliases (present on npm in every v1.x release), alongside the canonical `startAmicus`, `listAmicus`, `resumeAmicus`, `continueAmicus`, `readAmicus` names. v2.0.0 deletes the `*Sidecar` aliases from `module.exports`; only the canonical `*Amicus` names remain exported. There is no `*Sidecar`-named export on the package root in this version — switch any import of one to its `*Amicus` equivalent. See [docs/SHIMS.md](./SHIMS.md) for the full removal record.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## SDK & HTTP API Reference
|
|
103
|
+
|
|
104
|
+
Refer to the [OpenCode documentation](https://opencode.ai/docs/) for SDK and server API details.
|
|
105
|
+
|
|
106
|
+
**Critical: Model Format** -- Models MUST be objects, not strings:
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
// WRONG - causes 400 Bad Request
|
|
110
|
+
{ model: "google/gemini-2.5-flash" }
|
|
111
|
+
|
|
112
|
+
// CORRECT
|
|
113
|
+
{ model: { providerID: "openrouter", modelID: "google/gemini-2.5-flash" } }
|
|
114
|
+
```
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# npm Publishing
|
|
2
|
+
|
|
3
|
+
**Package**: `amicus` on npm (public)
|
|
4
|
+
**Repo**: `github.com/BourbonDog/amicus`
|
|
5
|
+
|
|
6
|
+
## How to Publish a New Version
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm version patch # or minor/major (bumps version + creates git tag)
|
|
10
|
+
git push origin main --tags
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The `.github/workflows/publish.yml` workflow triggers on `v*` tags and publishes automatically.
|
|
14
|
+
|
|
15
|
+
## What the Workflow Does
|
|
16
|
+
|
|
17
|
+
1. `npm ci` — install dependencies
|
|
18
|
+
2. `npm publish --access public --provenance` — publish with Sigstore attestation (requires `id-token: write` permission)
|
|
19
|
+
3. Create a GitHub Release with auto-generated notes
|
|
20
|
+
4. Call the Anthropic API to write richer release notes and update the release
|
|
21
|
+
|
|
22
|
+
**Publish auth: npm Trusted Publishing (OIDC).** Configured on npm for
|
|
23
|
+
`BourbonDog/amicus` + `publish.yml` (2026-06-11). The workflow authenticates via
|
|
24
|
+
GitHub's OIDC token (`id-token: write`) — no npm token is used. The runner
|
|
25
|
+
upgrades npm first (OIDC publishing needs npm ≥ 11.5; Node 22 bundles 10.x).
|
|
26
|
+
Provenance is implied under trusted publishing.
|
|
27
|
+
|
|
28
|
+
**Secrets:**
|
|
29
|
+
| Secret | Purpose |
|
|
30
|
+
|--------|---------|
|
|
31
|
+
| `ANTHROPIC_API_KEY` | Used in the "Generate release notes with Claude" step (direct `/v1/messages` call). Without it the step exits 0 with a warning and keeps the default GitHub release notes. **As of v1.0.0 this secret exists but is empty — set a real key to get Claude-written notes.** |
|
|
32
|
+
| `NPM_TOKEN` | **Legacy — no longer read by the workflow.** Kept only until the first successful OIDC publish confirms trusted publishing end-to-end; then delete the secret and revoke the token on npmjs.com. |
|
|
33
|
+
|
|
34
|
+
## Publishing history / notes
|
|
35
|
+
|
|
36
|
+
- v1.0.0 (2026-06-11) was published with `NPM_TOKEN` (granular, bypass-2FA). First
|
|
37
|
+
attempt failed `EOTP` because the original token lacked 2FA bypass.
|
|
38
|
+
- Trusted Publishing was configured immediately after launch; the next tagged
|
|
39
|
+
release is the first OIDC publish. If it fails, re-add a bypass-2FA granular
|
|
40
|
+
token as `NPM_TOKEN` and restore the `NODE_AUTH_TOKEN` env on the publish step
|
|
41
|
+
(see git history of `publish.yml`).
|
|
42
|
+
- After the first successful OIDC publish, optionally tighten the package's
|
|
43
|
+
publishing access on npmjs.com to require trusted publishing.
|
|
44
|
+
- The upstream `jrenaldi79/sidecar` repo had its own npm trusted-publisher
|
|
45
|
+
config; it never applied to this repository.
|
|
46
|
+
|
|
47
|
+
## Release checklist
|
|
48
|
+
|
|
49
|
+
Run top-to-bottom before `npm version`:
|
|
50
|
+
|
|
51
|
+
1. **MODEL-NOTES fold-back:** diff the machine-local ledger (`~/.claude/skills/second-opinion/MODEL-NOTES.md`) against the shipped seed (`skills/second-opinion/MODEL-NOTES.md`); port durable, machine-independent lessons into the shipped file (merge/prune, keep it tight — no run-ledger numbers, those live in `amicus council stats`).
|
|
52
|
+
2. `npm test` green; `npm run lint` clean.
|
|
53
|
+
3. **Integration tier, both rails:**
|
|
54
|
+
- `npm run test:integration` (keyless) — must be **0 failures**. This is the same thing the `integration` job in `ci.yml` runs on every push, so it should already be green.
|
|
55
|
+
- `npm run test:integration:live` **with real keys** — must be **0 failures**. This is the only step in the whole release that exercises the paid E2E suites (real CLI/MCP sessions against a real LLM), so it is the only thing that catches a break in the spawn/session/MCP lifecycle or a dead model alias. **It spends money — expect that, and do not skip it because the keyless run was green:** keyless *skips* those suites entirely, so a green keyless run says nothing about them. Locally: `npm run test:integration:live` with `OPENROUTER_API_KEY` set (or a key in `~/.config/amicus/.env`). In CI: dispatch `.github/workflows/integration-live.yml` from the Actions tab. The script carries `--runInBand` as of v4.4.1 (REL-1) and the CI job runs the same script, so **no extra flag is needed on either surface** — if you find an older note telling you to append `-- --runInBand`, it is stale. Expect ~2 minutes rather than ~40 s; that is the serialization, not a hang (see [testing.md](testing.md#which-gate-runs-which-tier)).
|
|
56
|
+
- A suite that reports *skipped* here means the key was not picked up. That is a misconfigured run, not a pass — fix it and re-run.
|
|
57
|
+
4. `npm run generate-docs:check` passes (CLAUDE.md markers + cross-links).
|
|
58
|
+
5. Bump `.claude-plugin/plugin.json` `version` to match `package.json` (no script syncs it). Also bump `server.json` — both `.version` and `.packages[0].version` — to the same value (no script syncs this either). Also bump the `status --json` **example blocks** in `README.md` and `docs/usage.md` (`"version": "x.y.z"`) — they are drift-test-pinned to `package.json` by `tests/docs-quick-sync.test.js` and have now missed the cut twice (v2.1.0 and v2.2.0).
|
|
59
|
+
6. Update `CHANGELOG.md` (move Unreleased → the new version).
|
|
60
|
+
7. `npm version <x.y.z> --no-git-tag-version` + plugin.json lockstep + server.json lockstep (`.version` and `.packages[0].version`), single `chore(release): vX.Y.Z` commit, then push main + tag (publish.yml does the rest — see the canonical ritual in Phase 2 of the 2026-07-01 review-execution plan). If you forget the server.json bump, `tests/scripts/package-manifest.test.js` fails the suite (`server.json versions stay in lockstep with package.json`) — that's your safety net, but don't rely on it; do the bump.
|
package/docs/schemas.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# JSON output schemas
|
|
2
|
+
|
|
3
|
+
Every JSON document Amicus emits carries a versioned envelope: `{ "schemaVersion": <n>, "type": "<doc-type>", … }`.
|
|
4
|
+
Published JSON Schemas (draft 2020-12) live in [`schemas/`](../schemas/) at the repo root and ship in the npm tarball —
|
|
5
|
+
validate any `--json` output with them (e.g. `ajv validate -s node_modules/amicus/schemas/run.schema.json -d out.json`).
|
|
6
|
+
|
|
7
|
+
**Stability contract:** within a `schemaVersion`, fields are only ever ADDED. Any rename/removal bumps the family's version.
|
|
8
|
+
Schemas leave `additionalProperties` open for exactly this reason — a doc with extra fields still validates.
|
|
9
|
+
|
|
10
|
+
## Families
|
|
11
|
+
|
|
12
|
+
| Family | schemaVersion | Types |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| result | 2 | `run`, `wave`, `abort`, `error`, `spend`, `model-catalog`, `alias-audit`, `doctor` |
|
|
15
|
+
| council | 2 (v4.0 bumped 1→2) | `council-tally`, `council-verdict`, `council-stats`, `council-validate`, `council-run` |
|
|
16
|
+
| observability | 1 | `event`, `progress` (v4.3, spec §4.2 — the events stream and the progress snapshot) |
|
|
17
|
+
|
|
18
|
+
`wave-live` and `run-live` are not a new family: they're the existing **result family (v2)** `wave`/`run` docs, composed at read time with an additive `view:'live'` marker — `amicus_status` stamps `schemaVersion: 2` (`stampEnvelope`) exactly as the durable `wave.json`/per-leg `run` docs do. `council-run-live` is the composed council live status payload (`buildCouncilStatusPayload`) — a point-in-time `amicus_status` snapshot like the other live/ack payloads in [Documented exclusions](#documented-exclusions), not a versioned result doc — and carries **no `schemaVersion` key at all**.
|
|
19
|
+
|
|
20
|
+
## Files
|
|
21
|
+
|
|
22
|
+
| Schema | Emitted by |
|
|
23
|
+
|---|---|
|
|
24
|
+
| [`run.schema.json`](../schemas/run.schema.json) | `start`/`read`/`resume`/`continue --json`; every wave leg |
|
|
25
|
+
| [`wave.schema.json`](../schemas/wave.schema.json) | `fanout --json`; `wave.json` |
|
|
26
|
+
| [`abort.schema.json`](../schemas/abort.schema.json) | `abort <id|--all> --json` |
|
|
27
|
+
| [`error.schema.json`](../schemas/error.schema.json) | every `--json` pre-flight/validation/route failure (stdout, exit 1) and every MCP error tool-text |
|
|
28
|
+
| [`spend.schema.json`](../schemas/spend.schema.json) | `spend --json` |
|
|
29
|
+
| [`model-catalog.schema.json`](../schemas/model-catalog.schema.json) | `models --json` |
|
|
30
|
+
| [`alias-audit.schema.json`](../schemas/alias-audit.schema.json) | `models --check --json` |
|
|
31
|
+
| [`doctor.schema.json`](../schemas/doctor.schema.json) | `doctor --json` |
|
|
32
|
+
| [`council-tally.schema.json`](../schemas/council-tally.schema.json) | `council tally --json`; `amicus_council_tally` |
|
|
33
|
+
| [`council-verdict.schema.json`](../schemas/council-verdict.schema.json) | `council verdict --json`; `amicus_verdict`; `verdict.json` |
|
|
34
|
+
| [`council-stats.schema.json`](../schemas/council-stats.schema.json) | `council stats --json`; `amicus_council_stats` |
|
|
35
|
+
| [`council-validate.schema.json`](../schemas/council-validate.schema.json) | `council validate --json` |
|
|
36
|
+
| [`council-run.schema.json`](../schemas/council-run.schema.json) | the headless engine's `run.json` manifest (`amicus council run` — lands after the trust-foundation phase; the schema is published ahead as the contract) |
|
|
37
|
+
| [`event.schema.json`](../schemas/event.schema.json) | `events.jsonl` lines — one append-only file per wave dir / council-run dir, milestone events appended by fan-out waves and council runs (wave/leg/run/stage lifecycle) |
|
|
38
|
+
| [`progress.schema.json`](../schemas/progress.schema.json) | `progress.json` — a leg/solo session's lifecycle stage + raw per-leg usage snapshot |
|
|
39
|
+
| [`wave-live.schema.json`](../schemas/wave-live.schema.json) | `amicus_status` on a running wave — the composed doc, `view:'live'` + per-leg read-time usage |
|
|
40
|
+
| [`run-live.schema.json`](../schemas/run-live.schema.json) | `amicus_status` on a running single session — the composed doc, `view:'live'` + read-time usage |
|
|
41
|
+
| [`council-run-live.schema.json`](../schemas/council-run-live.schema.json) | `amicus_status` on a running council run (`buildCouncilStatusPayload`) — the composed doc, `view:'live'` + read-time usage |
|
|
42
|
+
|
|
43
|
+
## Breaking change at v4.0 — `council stats --json`
|
|
44
|
+
|
|
45
|
+
Pre-4.0, `council stats --json` (and the `amicus_council_stats` MCP tool) emitted a **bare array** of per-model rows.
|
|
46
|
+
v4.0 wraps it: `{ "schemaVersion": 2, "type": "council-stats", "models": [ … ] }`. The row shape is unchanged.
|
|
47
|
+
This is the one non-additive shape change in the envelope unification; migrate `doc[0]` → `doc.models[0]`.
|
|
48
|
+
|
|
49
|
+
## Documented exclusions
|
|
50
|
+
|
|
51
|
+
- **The two JSONL ledgers** (`council-ledger.jsonl`, `spend-ledger.jsonl`): internal append-only storage, each stays at its own v1 row format (`SPEND_LEDGER_SCHEMA_VERSION` is 1, unrelated to and unbumped by the result/council envelope versions above) — not an emitted/published doc. `spend.schema.json` (the `amicus spend --json` output) is the published, versioned doc built *from* `spend-ledger.jsonl` rows — the ledger row shape itself is not published.
|
|
52
|
+
- **`amicus_list`** (MCP): returns a bare JSON array of session rows; a wrap would be a second breaking change and is deliberately not taken.
|
|
53
|
+
- **`setup` / `update` / `key`**: interactive-only commands with no `--json` mode.
|
|
54
|
+
- **MCP acks and live-status snapshots** (start/resume/continue/abort acks, `amicus_status`/`amicus_wait` bodies): carry the envelope keys with subject-family types (`run`/`wave`/`abort`) but are point-in-time snapshots, not the durable result docs the published schemas describe.
|
|
55
|
+
- **Fencing:** MCP council tool text arrives wrapped in the `<untrusted_sidecar_output>` fence with the JSON intact inside; CLI `--json` stdout is never fenced.
|