amicus 4.4.1 → 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 +130 -0
- package/README.md +15 -2
- package/bin/amicus.js +10 -0
- package/docs/ROADMAP.md +36 -10
- package/docs/configuration.md +24 -0
- package/docs/council.md +59 -0
- package/docs/schemas.md +1 -0
- package/docs/usage.md +151 -1
- package/electron/workspace-ui/workspace-app.js +39 -17
- package/electron/workspace-ui/workspace-panels.js +76 -18
- package/electron/workspace-ui/workspace-render.js +10 -0
- package/package.json +1 -1
- package/schemas/council-run-live.schema.json +1 -1
- package/schemas/council-run.schema.json +14 -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 +1 -1
- package/schemas/run-live.schema.json +1 -1
- package/schemas/run.schema.json +2 -1
- 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-template.js +53 -0
- package/src/cli.js +64 -3
- package/src/council/findings.js +4 -41
- package/src/council/presets-cli.js +23 -11
- package/src/council/run-stages.js +12 -9
- package/src/council/run-state.js +17 -0
- package/src/council/run.js +1 -1
- package/src/headless.js +18 -14
- package/src/mcp-council-run.js +108 -4
- package/src/mcp-server.js +203 -7
- package/src/mcp-tools.js +15 -5
- 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/fanout.js +21 -4
- package/src/sidecar/progress.js +34 -0
- 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/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/result-schema-rebuild.js +1 -0
- package/src/utils/result-schema.js +8 -2
- package/src/workspace/artifact-guard.js +44 -6
- package/src/workspace/run-detail.js +6 -0
|
@@ -96,14 +96,37 @@ function artifactAllowlist(run) {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
// ⚠️ Task 18 (RN-1): the collision above is a real run-integrity defect — the run directory
|
|
100
|
+
// physically holds ONE file where two models' artifacts should be, and no renderer trick can
|
|
101
|
+
// recover both. What the renderer CAN stop doing is showing model A's prose under model B's
|
|
102
|
+
// name. Deterministic disambiguation: per colliding sanitized name, sort the RAW models
|
|
103
|
+
// (sorting, not insertion order, is what keeps this reproducible across processes/runs); the
|
|
104
|
+
// first (sorted) keeps the bare sanitized name, the rest get `~2`, `~3`, ... The suffixed
|
|
105
|
+
// names deliberately do not exist on disk — the presence manifest (run-detail.js, via
|
|
106
|
+
// fs.statSync over this same allowlist) marks them absent, so the renderer shows the honest
|
|
107
|
+
// "not written yet" empty state for every model but the first, instead of cross-matching.
|
|
108
|
+
const nameFor = new Map(); // raw model -> its (possibly suffixed) sanitized name
|
|
99
109
|
for (const m of uniqueModels) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
110
|
+
let s = sanitizeName(m);
|
|
111
|
+
const collision = collisionModels.get(s);
|
|
112
|
+
if (collision) {
|
|
113
|
+
const sortedRaw = [...collision].sort();
|
|
114
|
+
const index = sortedRaw.indexOf(m);
|
|
115
|
+
if (index > 0) { s = `${s}~${index + 1}`; }
|
|
116
|
+
}
|
|
117
|
+
nameFor.set(m, s);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
for (const m of uniqueModels) {
|
|
121
|
+
const s = nameFor.get(m);
|
|
122
|
+
names.push(`review-${s}.md`);
|
|
123
|
+
names.push(`judge-${s}.md`);
|
|
124
|
+
// rebuttal-/revote- are keyed on the same BENCH ALIAS through the same (now possibly
|
|
125
|
+
// suffixed) name — materializeDebate is called with `d.raiser` / the revote leg's model
|
|
126
|
+
// (both aliases), so a colliding pair's debate artifacts are disambiguated the same way.
|
|
104
127
|
if (debated) {
|
|
105
|
-
names.push(`rebuttal-${
|
|
106
|
-
names.push(`revote-${
|
|
128
|
+
names.push(`rebuttal-${s}.md`);
|
|
129
|
+
names.push(`revote-${s}.md`);
|
|
107
130
|
}
|
|
108
131
|
}
|
|
109
132
|
// `uniqueModels` already collapsed genuinely-repeated bench entries, so this final Set is
|
|
@@ -115,6 +138,21 @@ function artifactAllowlist(run) {
|
|
|
115
138
|
sanitized, models: [...models],
|
|
116
139
|
}));
|
|
117
140
|
}
|
|
141
|
+
// Consumed by workspace-panels.js (wireLazyPanels' file lists + drillIntoJudge's artifact
|
|
142
|
+
// lookup), which prefers this map over re-deriving names via sanitizeName(model) directly —
|
|
143
|
+
// that re-derivation is exactly what would ignore the suffixing above and misattribute prose.
|
|
144
|
+
// ⚠️ Fix-wave (review finding 1) residual limit this map cannot close: the BARE (unsuffixed)
|
|
145
|
+
// name is still exactly ONE physical file on disk, and its actual bytes belong to whichever
|
|
146
|
+
// colliding model's writer ran LAST — no map can recover which one that was. The guarantee
|
|
147
|
+
// delivered here is narrower than "attribution is fully sound": at most the sorted-first
|
|
148
|
+
// model can still be misattributed under the bare name; artifactCollisions (the run-integrity
|
|
149
|
+
// banner rendered by workspace-app.js's renderBanners) is what covers that residual case.
|
|
150
|
+
list.artifactsByModel = Object.fromEntries(
|
|
151
|
+
[...nameFor].map(([m, s]) => [m, {
|
|
152
|
+
review: `review-${s}.md`, judge: `judge-${s}.md`,
|
|
153
|
+
rebuttal: `rebuttal-${s}.md`, revote: `revote-${s}.md`,
|
|
154
|
+
}]),
|
|
155
|
+
);
|
|
118
156
|
return list;
|
|
119
157
|
}
|
|
120
158
|
|
|
@@ -209,6 +209,12 @@ function getRunDetail(project, runId) {
|
|
|
209
209
|
// would otherwise silently misattribute prose. Surfaced here (rather than only inside
|
|
210
210
|
// the low-level allowlist helper) so the renderer can warn the user directly.
|
|
211
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,
|
|
212
218
|
};
|
|
213
219
|
}
|
|
214
220
|
|