amicus 4.4.0 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +162 -0
- package/README.md +17 -2
- package/bin/amicus.js +10 -0
- package/docs/DISTRIBUTION.md +234 -0
- package/docs/ROADMAP.md +226 -0
- package/docs/SHIMS.md +62 -0
- package/docs/architecture.md +104 -0
- package/docs/configuration.md +395 -0
- package/docs/council.md +970 -0
- package/docs/doc-system.md +92 -0
- package/docs/electron-testing.md +471 -0
- package/docs/jsdoc-setup.md +75 -0
- package/docs/opencode-integration.md +114 -0
- package/docs/publishing.md +60 -0
- package/docs/schemas.md +56 -0
- package/docs/testing.md +589 -0
- package/docs/troubleshooting.md +298 -0
- package/docs/usage.md +849 -0
- package/electron/fold.js +1 -1
- package/electron/main.js +4 -1
- package/electron/setup-ui-aliases.js +6 -6
- package/electron/workspace-ui/live-model.js +12 -1
- package/electron/workspace-ui/md-lite.js +52 -8
- package/electron/workspace-ui/workspace-app.js +39 -17
- package/electron/workspace-ui/workspace-matrix.js +46 -9
- package/electron/workspace-ui/workspace-panels.js +88 -19
- package/electron/workspace-ui/workspace-render.js +17 -1
- package/electron/workspace-ui/workspace-verbs.js +48 -2
- package/package.json +8 -3
- package/schemas/council-run-live.schema.json +1 -1
- package/schemas/council-run.schema.json +34 -0
- package/schemas/error.schema.json +1 -1
- package/schemas/event.schema.json +1 -1
- package/schemas/pack.schema.json +30 -0
- package/schemas/progress.schema.json +13 -1
- package/schemas/run-live.schema.json +1 -1
- package/schemas/run.schema.json +2 -1
- package/schemas/spend.schema.json +52 -4
- package/schemas/wave-live.schema.json +1 -1
- package/schemas/wave.schema.json +2 -1
- package/skills/second-opinion/SKILL.md +5 -0
- package/src/cli-handlers-council-run.js +51 -8
- package/src/cli-handlers-pack.js +238 -0
- package/src/cli-handlers-run.js +36 -8
- package/src/cli-handlers-spend.js +20 -2
- package/src/cli-handlers-template.js +53 -0
- package/src/cli-handlers-watch.js +11 -0
- package/src/cli.js +68 -5
- package/src/council/briefings-debate.js +27 -7
- package/src/council/briefings-stage2.js +155 -25
- package/src/council/briefings.js +24 -1
- package/src/council/findings.js +199 -9
- package/src/council/parse-stage2.js +10 -2
- package/src/council/presets-cli.js +23 -11
- package/src/council/report.js +19 -8
- package/src/council/run-assemble.js +42 -1
- package/src/council/run-budget.js +64 -11
- package/src/council/run-chair.js +4 -1
- package/src/council/run-debate.js +4 -2
- package/src/council/run-finalize.js +102 -0
- package/src/council/run-launch.js +29 -1
- package/src/council/run-server.js +248 -0
- package/src/council/run-stage2.js +118 -0
- package/src/council/run-stages.js +134 -110
- package/src/council/run-state.js +40 -1
- package/src/council/run.js +45 -47
- package/src/council/tally.js +10 -0
- package/src/headless.js +180 -7
- package/src/mcp-council-run.js +108 -4
- package/src/mcp-server.js +203 -7
- package/src/mcp-tools.js +15 -5
- package/src/observe/council-legs.js +60 -3
- package/src/observe/live-doc.js +18 -1
- package/src/observe/watch-render.js +4 -1
- package/src/pack/pack-cli.js +38 -0
- package/src/pack/pack-forward.js +96 -0
- package/src/pack/pack-resolve.js +297 -0
- package/src/pack/pack-store.js +130 -0
- package/src/pack/pack-validate.js +113 -0
- package/src/sidecar/child-sessions.js +1 -2
- package/src/sidecar/fanout-leg-fallback.js +69 -21
- package/src/sidecar/fanout-leg.js +6 -0
- package/src/sidecar/fanout-signals.js +61 -0
- package/src/sidecar/fanout-wave-io.js +75 -0
- package/src/sidecar/fanout.js +82 -74
- package/src/sidecar/progress-fields.js +26 -4
- package/src/sidecar/progress.js +42 -1
- package/src/sidecar/session-utils.js +23 -14
- package/src/sidecar/start.js +5 -4
- package/src/sidecar/workspace-auto-open.js +69 -0
- package/src/sidecar/workspace-window.js +46 -1
- package/src/spend-query.js +17 -5
- package/src/template/apply.js +88 -0
- package/src/template/render.js +86 -0
- package/src/template/store.js +106 -0
- package/src/utils/config.js +65 -25
- package/src/utils/error-doc.js +5 -0
- package/src/utils/lifecycle.js +37 -1
- package/src/utils/path-fence.js +39 -1
- package/src/utils/pricing.js +26 -10
- package/src/utils/result-schema-rebuild.js +1 -0
- package/src/utils/result-schema.js +8 -2
- package/src/utils/server-setup.js +79 -1
- package/src/utils/spend-ledger.js +24 -3
- package/src/workspace/artifact-guard.js +66 -7
- package/src/workspace/fold-format.js +33 -4
- package/src/workspace/live-normalize.js +28 -15
- package/src/workspace/run-detail.js +13 -1
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
* Council Workspace — fold payload builder (v4.4 §7).
|
|
3
3
|
*
|
|
4
4
|
* MIRRORS the shipped fold-header builder `formatFoldOutput`
|
|
5
|
-
* (src/headless.js
|
|
6
|
-
* — byte-for-byte the same
|
|
7
|
-
*
|
|
5
|
+
* (src/headless.js `formatFoldOutput`, exported from src/headless.js and
|
|
6
|
+
* re-exported from src/index.js) — byte-for-byte the same **7-line** head:
|
|
7
|
+
* marker, Model, Session, Client, CWD, Mode, `---`. ⚠️ v4.4.1 DOC-5: this said
|
|
8
|
+
* "8-line" for two releases. Line 8 (`VERDICT:`) is council's OWN addition and
|
|
9
|
+
* has no counterpart in formatFoldOutput, whose 8th element is the summary
|
|
10
|
+
* body. Only the first 7 lines are the shared contract; anyone changing the
|
|
11
|
+
* shared format must sync those and leave `VERDICT:` alone.
|
|
12
|
+
* src/headless.js is the SOURCE OF TRUTH; keep the head in sync with it.
|
|
13
|
+
* (Line numbers deliberately omitted — the previous `:775-789`/`:797` citation
|
|
14
|
+
* had drifted by ~500 lines.) The duplication is deliberate:
|
|
8
15
|
* requiring headless.js transitively pulls opencode-client / progress /
|
|
9
16
|
* conversation-mirror at require time (src/headless.js:8-17), which
|
|
10
17
|
* src/workspace/ must stay free of.
|
|
@@ -79,7 +86,29 @@ function buildFoldText(o) {
|
|
|
79
86
|
} else {
|
|
80
87
|
head.push(`Run: ${run.status || 'unknown'} — ${stageSummary(run)}`);
|
|
81
88
|
}
|
|
82
|
-
|
|
89
|
+
// ⚠️ v4.4.1 DOC-5: this used to append ` (${cost.source})` for EVERY source,
|
|
90
|
+
// on top of a glyph formatCost had already spent on the same fact —
|
|
91
|
+
// `~$0.0100 (estimated)`, `? (unknown)`. formatCost (src/utils/pricing.js)
|
|
92
|
+
// prefixes `~` for both 'estimated' and 'mixed', and returns a bare `?` when
|
|
93
|
+
// the source is 'unknown'. So for 'estimated' and 'unknown' the word was pure
|
|
94
|
+
// repetition and is gone.
|
|
95
|
+
//
|
|
96
|
+
// Two sources still spell themselves out, because the glyph vocabulary cannot
|
|
97
|
+
// express them:
|
|
98
|
+
// - `reported` — a plain `$0.4321` is also what an unrecognised/absent
|
|
99
|
+
// source renders as, so the absence of a glyph cannot mean "exact".
|
|
100
|
+
// - `mixed` — `~` encodes *inexact*, not *which kind of inexact*. Collapsing
|
|
101
|
+
// 'mixed' into a bare `~$…` makes it indistinguishable from 'estimated',
|
|
102
|
+
// and the two are not the same claim: 'mixed' means some legs reported
|
|
103
|
+
// real usage and some were estimated, i.e. part of this number is
|
|
104
|
+
// measured. That is strictly more information than 'estimated', and this
|
|
105
|
+
// is the fold line of a release whose theme is cost truthfulness.
|
|
106
|
+
// Each thing is still said exactly once — the `~` says "inexact", the word
|
|
107
|
+
// says "which kind", and neither restates the other.
|
|
108
|
+
const costSourceLabel = cost && (cost.source === 'reported' || cost.source === 'mixed')
|
|
109
|
+
? ` (${cost.source})`
|
|
110
|
+
: '';
|
|
111
|
+
head.push(`Cost: ${formatCost(cost)}${costSourceLabel}`);
|
|
83
112
|
|
|
84
113
|
// Review follow-up #1: strip FIRST, then test emptiness on the STRIPPED
|
|
85
114
|
// result — not the raw one. A chair body consisting solely of a marker
|
|
@@ -20,10 +20,14 @@
|
|
|
20
20
|
const { formatCost } = require('../utils/pricing');
|
|
21
21
|
const { TERMINAL_STATUSES } = require('./run-detail');
|
|
22
22
|
|
|
23
|
+
// ⚠️ v4.4.1 RN-7: the `doc.wave.legs` fallback that used to sit here is GONE, deliberately.
|
|
24
|
+
// No producer nests legs under `wave` — the WAVE composed doc (src/mcp-server.js:592-662)
|
|
25
|
+
// carries a TOP-LEVEL `legs`, exactly like the council one, and this file's header already
|
|
26
|
+
// says not to model the wave doc at all. The arm asserted a shape that does not exist, and
|
|
27
|
+
// wsgate01's reviewer believed it. If a nested shape ever appears, add it back WITH a
|
|
28
|
+
// producer to point at.
|
|
23
29
|
function legRowsOf(doc) {
|
|
24
|
-
|
|
25
|
-
if (doc.wave && Array.isArray(doc.wave.legs)) { return doc.wave.legs; }
|
|
26
|
-
return [];
|
|
30
|
+
return Array.isArray(doc.legs) ? doc.legs : [];
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
function numOrNull(v) { return typeof v === 'number' ? v : null; }
|
|
@@ -32,7 +36,9 @@ function seatOf(leg) {
|
|
|
32
36
|
const usage = leg.usage || null;
|
|
33
37
|
const tokens = usage && usage.tokens ? usage.tokens : null;
|
|
34
38
|
return {
|
|
35
|
-
|
|
39
|
+
// ⚠️ v4.4.1 RN-7: `leg.legId` was a second dead fallback here — no leg row, council or
|
|
40
|
+
// wave, has ever carried it (src/observe/council-legs.js stamps `taskId`). Deleted.
|
|
41
|
+
id: leg.taskId || null,
|
|
36
42
|
// ⚠️ DE-ROT (F34/F36): `model` and `modelInput` are TWO SEPARATE fields, never collapsed.
|
|
37
43
|
// A live leg's `model` is the resolved executable id (e.g. `google/gemini-2.5`); `modelInput`
|
|
38
44
|
// is the council ALIAS (e.g. `gemini`) that run.json's labelMap and blind mode's labelFor()
|
|
@@ -108,19 +114,26 @@ function normalizeLive(doc) {
|
|
|
108
114
|
view: doc.view || null,
|
|
109
115
|
runId: doc.runId || doc.taskId || null,
|
|
110
116
|
status,
|
|
111
|
-
// ⚠️ PRE-FLIGHT
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
|
|
117
|
+
// ⚠️ v4.4.1 RN-7 (was PRE-FLIGHT P6): the `|| doc.currentStage` fallback is GONE. P6 had
|
|
118
|
+
// already corrected it once — from the phantom `doc.stage` to the real `currentStage` — and
|
|
119
|
+
// its own comment conceded the arm was "harmless today only by coincidence". It is in fact
|
|
120
|
+
// strictly unreachable: buildCouncilStatusPayload writes `stages` as `(run.stages || []).map(…)`
|
|
121
|
+
// (always an array) and derives `currentStage` from the SAME
|
|
122
|
+
// `stages.find(s => s.status === 'running')` predicate `active` uses one line up
|
|
123
|
+
// (src/mcp-council-awareness.js:155-157), so `active` is null in exactly the cases
|
|
124
|
+
// `currentStage` is too. Keeping it asserted a divergence between the two fields that no
|
|
125
|
+
// producer can create.
|
|
126
|
+
stageName: active ? active.name : null,
|
|
118
127
|
stages,
|
|
119
128
|
seats: legRowsOf(doc).map(seatOf),
|
|
120
|
-
//
|
|
121
|
-
// fallback readout if a seat row
|
|
122
|
-
|
|
123
|
-
|
|
129
|
+
// ⚠️ v4.4.1 RN-8 (D1 ruling: delete the promise). `legsTotal`/`legsComplete` used to be
|
|
130
|
+
// mapped here under a comment promising them as "the honest fallback readout if a seat row
|
|
131
|
+
// is ever unavailable" — a UI fallback nobody ever wired. Nothing in electron/workspace-ui/
|
|
132
|
+
// read either field. Documenting a feature that does not exist is worse than not having it,
|
|
133
|
+
// so the fields and the promise are both gone. ⚠️ The SAME names on the composed doc
|
|
134
|
+
// (src/mcp-council-awareness.js) and in src/cli-handlers-status.js / src/mcp-wait.js ARE
|
|
135
|
+
// consumed — this deletion is scoped to the workspace's LiveModel only. If a future task
|
|
136
|
+
// wants the counters in the GUI, re-add them WITH the renderer that paints them.
|
|
124
137
|
// ⚠️ DE-ROT (F39): these two are ACTIVE-STAGE spend, not the run total.
|
|
125
138
|
// buildCouncilStatusPayload rolls up only the legs of the currently-RUNNING stage's sub-waves
|
|
126
139
|
// (mcp-council-awareness.js:136-146) and omits `usage` entirely until one of those legs flushes
|
|
@@ -23,7 +23,13 @@ const { isRealpathContained } = require('../utils/path-fence');
|
|
|
23
23
|
* ("zero v4.3") and live-doc.js is v4.3. Not to be confused with the shipped
|
|
24
24
|
* src/utils/result-schema.js:13 TERMINAL_STATUSES, which is the LEG set (no 'partial').
|
|
25
25
|
*/
|
|
26
|
-
|
|
26
|
+
// ⚠️ v4.4.1 A1: 'timed-out' added alongside 'timeout' — see the long note at
|
|
27
|
+
// src/observe/live-doc.js:18 for why both spellings are real and which producer writes each.
|
|
28
|
+
// Council run.json only ever carries aborted|complete|error|partial (run-finalize.js:38
|
|
29
|
+
// statusForExit), so the new name is inert for THIS module's own reads; it is carried anyway
|
|
30
|
+
// because the drift pin demands byte-identity with the source list, and that pin is the only
|
|
31
|
+
// thing keeping the three copies honest.
|
|
32
|
+
const TERMINAL_STATUSES = ['complete', 'partial', 'error', 'crashed', 'aborted', 'timeout', 'timed-out', 'idle-timeout'];
|
|
27
33
|
|
|
28
34
|
/** Friendly labels for known v4.0 stage names; unknown names pass through raw
|
|
29
35
|
* — the graceful-when-present rule (spec §5.2). */
|
|
@@ -203,6 +209,12 @@ function getRunDetail(project, runId) {
|
|
|
203
209
|
// would otherwise silently misattribute prose. Surfaced here (rather than only inside
|
|
204
210
|
// the low-level allowlist helper) so the renderer can warn the user directly.
|
|
205
211
|
artifactCollisions: artifactNames.collisions || [],
|
|
212
|
+
// ⚠️ Task 18 (RN-1): the de-collision map itself (raw model -> {review, judge} filename),
|
|
213
|
+
// built once in artifactAllowlist alongside `collisions` above. `|| null` (absent, not an
|
|
214
|
+
// empty object) so workspace-panels.js can tell "no map at all" (older detail payloads —
|
|
215
|
+
// pre-v4.5 runs, live-doc consumers not yet updated) apart from a real map, and fall back
|
|
216
|
+
// to its legacy sanitizeName(model) computation only in the former case.
|
|
217
|
+
artifactsByModel: artifactNames.artifactsByModel || null,
|
|
206
218
|
};
|
|
207
219
|
}
|
|
208
220
|
|