@wrongstack/cli 0.318.0 → 0.319.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/data/providers.json +1 -22
- package/dist/{acp-CEQINXWB.js → acp-5ANIAOZC.js} +4 -4
- package/dist/arg-parser.d.ts +4 -0
- package/dist/{auth-3OSF6BMU.js → auth-ND7J7DTD.js} +10 -10
- package/dist/{chunk-QC5I4VWZ.js → chunk-635WW3II.js} +8 -14
- package/dist/{chunk-7CECQDNH.js → chunk-D3K4NYQL.js} +1 -1
- package/dist/{chunk-QYIIOMLE.js → chunk-E4I2TF5S.js} +2 -2
- package/dist/{chunk-4JRIWVJ4.js → chunk-ERX4BLKP.js} +1 -1
- package/dist/{chunk-37SPPLUD.js → chunk-F5GA2QW2.js} +15 -2
- package/dist/chunk-GGGUZSAU.js +235 -0
- package/dist/{chunk-GKHUHAIK.js → chunk-HF5VQWIY.js} +5 -5
- package/dist/{chunk-YX6KUIDF.js → chunk-IMT6PNV5.js} +861 -29
- package/dist/{chunk-G7337TTK.js → chunk-IS2PPBQV.js} +1 -1
- package/dist/{chunk-G3IMKQRH.js → chunk-JHPXJRRI.js} +1 -1
- package/dist/chunk-KYDJJLJI.js +52 -0
- package/dist/chunk-LIWVIEZM.js +46 -0
- package/dist/chunk-P2OKBDCH.js +1166 -0
- package/dist/chunk-PCBJSXYV.js +65 -0
- package/dist/{chunk-7JBKXVMK.js → chunk-TALOKMIC.js} +14 -18
- package/dist/{chunk-KG4X5F7Z.js → chunk-VFCJOWJB.js} +10 -12
- package/dist/{chunk-SYIBTG3X.js → chunk-VOTTENR5.js} +3 -5
- package/dist/chunk-WHOIR577.js +1 -0
- package/dist/{chunk-2ZNBRZ4W.js → chunk-WQZW3RDP.js} +2 -2
- package/dist/{chunk-BXFYBQKR.js → chunk-XPX432BZ.js} +8 -1
- package/dist/cli-context-K73EIND5.js +3369 -0
- package/dist/{cli-main-ILRTNPDP.js → cli-main-QXSKKANW.js} +84 -93
- package/dist/{diag-doctor-LFCCBPMD.js → diag-doctor-QZVKUAE5.js} +4 -5
- package/dist/{execution-BN4QIFH6.js → execution-7ZFY4FJY.js} +499 -473
- package/dist/{hq-3GWBFLON.js → hq-4QQJO2GN.js} +2 -2
- package/dist/hq-server/routes.d.ts +1 -1
- package/dist/{hq-server-OARPUSQJ.js → hq-server-CVAYICIS.js} +2 -2
- package/dist/index.js +20 -4440
- package/dist/{modeldiag-4NYBRSFP.js → modeldiag-ZL4ROTQ5.js} +2 -2
- package/dist/per-subcommand-help-6VCIKDUW.js +23 -0
- package/dist/{plugin-usage-AP7SJCDA.js → plugin-usage-7WCZW4NP.js} +2 -2
- package/dist/{plugins-HQ5FU2AM.js → plugins-7N3TF2QF.js} +3 -3
- package/dist/pre-launch/first-run.d.ts +51 -0
- package/dist/pre-launch.d.ts +1 -0
- package/dist/{project-manifest-YFTJ3D5N.js → project-manifest-RV5FXGQI.js} +2 -2
- package/dist/{project-picker-R5TYAE3Q.js → project-picker-CCQR3W4I.js} +3 -3
- package/dist/{providers-models-663NDPRQ.js → providers-models-OKKQZIWU.js} +2 -2
- package/dist/{proxy-wiring-EQB5X5YH.js → proxy-wiring-QCI7EWQC.js} +3 -3
- package/dist/{sdd-runtime-FLKCSTYV.js → sdd-runtime-R6FAK2G2.js} +2 -2
- package/dist/services/sdd-runtime.d.ts +1 -1
- package/dist/{sessions-config-P2LK2L32.js → sessions-config-KAMEBVOX.js} +4 -4
- package/dist/short-circuit-flags-7YUCERBB.js +11 -0
- package/dist/slash-commands/sdd.d.ts +1 -1
- package/dist/subcommands-KE6MEQQP.js +10 -0
- package/dist/{webui-server-OJLLM6PE.js → webui-server-F7MSRHOF.js} +8 -6
- package/dist/wiring/wrongtrace-gate.d.ts +2 -2
- package/dist/wiring/wrongtrace-hooks.d.ts +1 -1
- package/dist/{wrongtrace-gate-counters-P5BCBXQN.js → wrongtrace-gate-counters-GSVY372D.js} +2 -2
- package/dist/{wrongtrace-telemetry-FNLANZ5I.js → wrongtrace-telemetry-KBBM5NLQ.js} +2 -2
- package/package.json +28 -28
- package/dist/chunk-ALE5KHCA.js +0 -1
- package/dist/chunk-L6ZNCTRJ.js +0 -1067
|
@@ -11,7 +11,18 @@ import {
|
|
|
11
11
|
resolveActualTarget,
|
|
12
12
|
resolvePersistPath
|
|
13
13
|
} from "./chunk-JACOMTIH.js";
|
|
14
|
-
import
|
|
14
|
+
import {
|
|
15
|
+
theme
|
|
16
|
+
} from "./chunk-QD544J2B.js";
|
|
17
|
+
import {
|
|
18
|
+
WEBUI_SESSION_CHILD_CAPABILITIES,
|
|
19
|
+
writeWebuiSessionChildError,
|
|
20
|
+
writeWebuiSessionChildReady
|
|
21
|
+
} from "./chunk-GPPRNAKW.js";
|
|
22
|
+
import {
|
|
23
|
+
fmtTok
|
|
24
|
+
} from "./chunk-TYO2OVAD.js";
|
|
25
|
+
import "./chunk-WHOIR577.js";
|
|
15
26
|
import {
|
|
16
27
|
advanceToNextTask,
|
|
17
28
|
autoDetectTaskCompletion,
|
|
@@ -25,24 +36,13 @@ import {
|
|
|
25
36
|
trySaveSpecFromAIOutput,
|
|
26
37
|
trySaveTasksFromAIOutput
|
|
27
38
|
} from "./chunk-JHUJUIOH.js";
|
|
28
|
-
import {
|
|
29
|
-
startCliHqConnection
|
|
30
|
-
} from "./chunk-XYKYXFEE.js";
|
|
31
|
-
import {
|
|
32
|
-
theme
|
|
33
|
-
} from "./chunk-QD544J2B.js";
|
|
34
|
-
import {
|
|
35
|
-
fmtTok
|
|
36
|
-
} from "./chunk-TYO2OVAD.js";
|
|
37
|
-
import {
|
|
38
|
-
WEBUI_SESSION_CHILD_CAPABILITIES,
|
|
39
|
-
writeWebuiSessionChildError,
|
|
40
|
-
writeWebuiSessionChildReady
|
|
41
|
-
} from "./chunk-GPPRNAKW.js";
|
|
42
39
|
import {
|
|
43
40
|
terminalLink,
|
|
44
41
|
terminalText
|
|
45
42
|
} from "./chunk-HXJYHAR4.js";
|
|
43
|
+
import {
|
|
44
|
+
startCliHqConnection
|
|
45
|
+
} from "./chunk-XYKYXFEE.js";
|
|
46
46
|
import {
|
|
47
47
|
CLI_VERSION
|
|
48
48
|
} from "./chunk-XJXDOF63.js";
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
} from "./chunk-YMXXOOFN.js";
|
|
52
52
|
import {
|
|
53
53
|
resolveActiveApiKey
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-XPX432BZ.js";
|
|
55
55
|
import "./chunk-7OCVIDC7.js";
|
|
56
56
|
|
|
57
57
|
// src/execution.ts
|
|
@@ -212,7 +212,7 @@ async function runWebUIDispatch(ctx) {
|
|
|
212
212
|
const isSimpleUi = !isSessionChild && flags["simpleui"] === true;
|
|
213
213
|
agent.disableInteractiveConfirmation();
|
|
214
214
|
renderer.setSilent(true);
|
|
215
|
-
const { runWebUI } = await import("./webui-server-
|
|
215
|
+
const { runWebUI } = await import("./webui-server-F7MSRHOF.js");
|
|
216
216
|
const flagValue = (names) => {
|
|
217
217
|
for (const name of names) {
|
|
218
218
|
if (!Object.hasOwn(flags, name)) continue;
|
|
@@ -415,7 +415,7 @@ async function runWebUIDispatch(ctx) {
|
|
|
415
415
|
applyLiveSettings?.({ yolo: enabled });
|
|
416
416
|
},
|
|
417
417
|
onWrongProxyPrefsChange: (payload) => {
|
|
418
|
-
void import("./proxy-wiring-
|
|
418
|
+
void import("./proxy-wiring-QCI7EWQC.js").then(
|
|
419
419
|
({ applyWrongProxyPrefs }) => applyWrongProxyPrefs(payload)
|
|
420
420
|
);
|
|
421
421
|
}
|
|
@@ -893,7 +893,7 @@ function onSwitchToSession(ctx, _sessionId, targetRoot, projectName) {
|
|
|
893
893
|
import * as path4 from "node:path";
|
|
894
894
|
import { color as color3 } from "@wrongstack/core/utils";
|
|
895
895
|
async function getProjectPickerItems(ctx) {
|
|
896
|
-
const { buildPickerItems } = await import("./project-picker-
|
|
896
|
+
const { buildPickerItems } = await import("./project-picker-CCQR3W4I.js");
|
|
897
897
|
return buildPickerItems({
|
|
898
898
|
globalConfigPath: ctx.state.wpaths.globalConfig,
|
|
899
899
|
currentProjectRoot: ctx.state.projectRoot
|
|
@@ -911,7 +911,7 @@ async function onProjectSelect(ctx, slug, kind) {
|
|
|
911
911
|
}
|
|
912
912
|
return;
|
|
913
913
|
}
|
|
914
|
-
const { loadManifest, saveManifest } = await import("./project-manifest-
|
|
914
|
+
const { loadManifest, saveManifest } = await import("./project-manifest-RV5FXGQI.js");
|
|
915
915
|
const manifest = await loadManifest(state.wpaths.globalConfig);
|
|
916
916
|
const project = manifest.projects.find((p) => p.slug === slug);
|
|
917
917
|
if (!project) return;
|
|
@@ -1214,7 +1214,7 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
|
|
|
1214
1214
|
|
|
1215
1215
|
// src/boot/tui-sdd-callback.ts
|
|
1216
1216
|
async function getSDDContext() {
|
|
1217
|
-
const { getActiveSDDContext: getActiveSDDContext2 } = await import("./sdd-runtime-
|
|
1217
|
+
const { getActiveSDDContext: getActiveSDDContext2 } = await import("./sdd-runtime-R6FAK2G2.js");
|
|
1218
1218
|
return getActiveSDDContext2();
|
|
1219
1219
|
}
|
|
1220
1220
|
async function onSDDOutput(output) {
|
|
@@ -1225,7 +1225,7 @@ async function onSDDOutput(output) {
|
|
|
1225
1225
|
autoDetectTaskCompletion: autoDetectTaskCompletion2,
|
|
1226
1226
|
getTaskProgress: getTaskProgress2,
|
|
1227
1227
|
getActiveSDDPhase: getActiveSDDPhase2
|
|
1228
|
-
} = await import("./sdd-runtime-
|
|
1228
|
+
} = await import("./sdd-runtime-R6FAK2G2.js");
|
|
1229
1229
|
const messages = [];
|
|
1230
1230
|
const specSaved = await trySaveSpecFromAIOutput2(output);
|
|
1231
1231
|
if (specSaved) messages.push("\u2713 Spec detected and saved! Use /sdd approve to continue.");
|
|
@@ -1851,7 +1851,15 @@ function coerceAgentSwarmMode(v) {
|
|
|
1851
1851
|
if (typeof v === "string" && (v === "bottom" || v === "sidebar" || v === "off")) return v;
|
|
1852
1852
|
return "bottom";
|
|
1853
1853
|
}
|
|
1854
|
-
var ANIMATION_STYLES = [
|
|
1854
|
+
var ANIMATION_STYLES = [
|
|
1855
|
+
"rainbow",
|
|
1856
|
+
"wave",
|
|
1857
|
+
"pulse",
|
|
1858
|
+
"dots",
|
|
1859
|
+
"breathe",
|
|
1860
|
+
"static",
|
|
1861
|
+
"cycle"
|
|
1862
|
+
];
|
|
1855
1863
|
function normalizeAnimationStyle(raw) {
|
|
1856
1864
|
return typeof raw === "string" && ANIMATION_STYLES.includes(raw) ? raw : "rainbow";
|
|
1857
1865
|
}
|
|
@@ -2665,7 +2673,7 @@ async function finalizeExecutionCleanup(input) {
|
|
|
2665
2673
|
})
|
|
2666
2674
|
);
|
|
2667
2675
|
} else {
|
|
2668
|
-
const { reportWrongTraceSessionTelemetry } = await import("./wrongtrace-telemetry-
|
|
2676
|
+
const { reportWrongTraceSessionTelemetry } = await import("./wrongtrace-telemetry-KBBM5NLQ.js");
|
|
2669
2677
|
const usage = tokenCounter.total();
|
|
2670
2678
|
const report = reportWrongTraceSessionTelemetry({
|
|
2671
2679
|
sessionId: activeSession.id,
|
|
@@ -2693,7 +2701,7 @@ async function finalizeExecutionCleanup(input) {
|
|
|
2693
2701
|
} catch {
|
|
2694
2702
|
}
|
|
2695
2703
|
try {
|
|
2696
|
-
const { snapshotGateDecisions, persistWrongTraceGateCounters } = await import("./wrongtrace-gate-counters-
|
|
2704
|
+
const { snapshotGateDecisions, persistWrongTraceGateCounters } = await import("./wrongtrace-gate-counters-GSVY372D.js");
|
|
2697
2705
|
const projectRoot = agent.ctx.projectRoot;
|
|
2698
2706
|
if (projectRoot) {
|
|
2699
2707
|
await persistWrongTraceGateCounters(projectRoot, snapshotGateDecisions());
|
|
@@ -2814,7 +2822,7 @@ function resolveKanbanDispatchRoute(config, spawnOpts) {
|
|
|
2814
2822
|
tier = resolved.tier;
|
|
2815
2823
|
provider = provider ?? resolved.provider ?? config.provider;
|
|
2816
2824
|
model = model ?? resolved.model;
|
|
2817
|
-
fallbackModels = fallbackModels ??
|
|
2825
|
+
fallbackModels = fallbackModels ?? resolved.fallbackModels?.slice() ?? void 0;
|
|
2818
2826
|
}
|
|
2819
2827
|
}
|
|
2820
2828
|
return { provider, model, fallbackModels, ...tier ? { tier } : {} };
|
|
@@ -3453,8 +3461,12 @@ function buildChimeraReviewTaskDescription(p) {
|
|
|
3453
3461
|
lines.push("---");
|
|
3454
3462
|
lines.push("");
|
|
3455
3463
|
lines.push("**Review Instructions:**");
|
|
3456
|
-
lines.push(
|
|
3457
|
-
|
|
3464
|
+
lines.push(
|
|
3465
|
+
"- Review the diffs and new file contents carefully for real bugs, broken logic, null dereferences, and security gaps."
|
|
3466
|
+
);
|
|
3467
|
+
lines.push(
|
|
3468
|
+
"- Stay strictly within the scoped diffs. DO NOT audit unchanged files, pre-existing debt, or stylistic preferences."
|
|
3469
|
+
);
|
|
3458
3470
|
lines.push("- Use tools only when you need surrounding lines to verify a concrete issue.");
|
|
3459
3471
|
lines.push("- Once the diff is validated, output your report (findings or all-clear) promptly.");
|
|
3460
3472
|
return lines.join("\n");
|
|
@@ -3651,122 +3663,126 @@ function installChimeraCascadeHandler({
|
|
|
3651
3663
|
persistEvidence,
|
|
3652
3664
|
teardownHandlers
|
|
3653
3665
|
}) {
|
|
3654
|
-
const off = events.onPattern(
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
} catch {
|
|
3664
|
-
}
|
|
3665
|
-
const agentEvidence = [];
|
|
3666
|
-
for (const agentKind of p.agents) {
|
|
3666
|
+
const off = events.onPattern(
|
|
3667
|
+
"chimera.cascade_needed",
|
|
3668
|
+
(_event, payload) => {
|
|
3669
|
+
const p = payload;
|
|
3670
|
+
const dir = director;
|
|
3671
|
+
if (!dir) return;
|
|
3672
|
+
if (p.agents.length === 0) return;
|
|
3673
|
+
const previousWork = getPendingWork();
|
|
3674
|
+
const pendingWork = (async () => {
|
|
3667
3675
|
try {
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3676
|
+
await previousWork;
|
|
3677
|
+
} catch {
|
|
3678
|
+
}
|
|
3679
|
+
const agentEvidence = [];
|
|
3680
|
+
for (const agentKind of p.agents) {
|
|
3681
|
+
try {
|
|
3682
|
+
const taskDesc = buildChimeraCascadeTaskDescription(agentKind, p);
|
|
3683
|
+
const role = agentKind === "security-scanner" ? "security-scanner" : "bug-hunter";
|
|
3684
|
+
const ladder = buildLadder?.() ?? INHERIT_ONLY_LADDER;
|
|
3685
|
+
const outcome = await runSubagentModelLadder({
|
|
3686
|
+
director: dir,
|
|
3687
|
+
ladder,
|
|
3688
|
+
attemptTimeoutMs: CASCADE_ATTEMPT_TIMEOUT_MS,
|
|
3689
|
+
budgetMs: CASCADE_LADDER_BUDGET_MS,
|
|
3690
|
+
buildConfig: (attempt, timeoutMs) => ({
|
|
3691
|
+
name: `chimera-cascade-${agentKind}`,
|
|
3692
|
+
role,
|
|
3693
|
+
maxIterations: 40,
|
|
3694
|
+
maxToolCalls: 200,
|
|
3695
|
+
timeoutMs,
|
|
3696
|
+
// Cascade agents are ephemeral infrastructure: like reviewers,
|
|
3697
|
+
// they must not consume the leader's lifetime maxSpawns budget.
|
|
3698
|
+
spawnBudgetExempt: true,
|
|
3699
|
+
// Model-driven completion (see core coordination/subagent-finish.ts):
|
|
3700
|
+
// a rung crossing its wall-clock budget is notified in-band
|
|
3701
|
+
// between tool batches and finishes its own turn within the
|
|
3702
|
+
// grace window instead of being killed. Ladder-retry semantics
|
|
3703
|
+
// are intact: a rung that still exhausts the grace window lands
|
|
3704
|
+
// as a `timeout` task result, which advances the ladder, and
|
|
3705
|
+
// `buildRetryPreamble` below already warns the successor that
|
|
3706
|
+
// the tree may hold the dead rung's partial edits.
|
|
3707
|
+
gracefulFinish: true,
|
|
3708
|
+
// Rung 0 stays unpinned so the role model matrix still decides;
|
|
3709
|
+
// later rungs pin a model precisely because it just failed.
|
|
3710
|
+
...attempt.tier === "inherit" ? {} : {
|
|
3711
|
+
provider: attempt.provider,
|
|
3712
|
+
model: attempt.model,
|
|
3713
|
+
fallbackModels: attempt.fallbackModels
|
|
3714
|
+
}
|
|
3715
|
+
}),
|
|
3716
|
+
// Cascade agents write files, so a successor must be told the tree
|
|
3717
|
+
// may already hold the dead attempt's partial edits.
|
|
3718
|
+
buildTask: (_attempt, failures) => `${buildRetryPreamble(failures)}${taskDesc}`,
|
|
3719
|
+
onAttemptFailed: async (failure, next) => {
|
|
3720
|
+
if (!next) return;
|
|
3721
|
+
await session.append({
|
|
3722
|
+
type: "error",
|
|
3723
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3724
|
+
message: `\u{1F982} Chimera cascade (${agentKind}) on ${failure.model} failed (${failure.reason}) \u2014 retrying on ${attemptLabel(next)} (${next.tier}).`,
|
|
3725
|
+
phase: "agent"
|
|
3726
|
+
});
|
|
3727
|
+
}
|
|
3728
|
+
});
|
|
3729
|
+
const result = outcome.result;
|
|
3730
|
+
if (result?.status === "success") {
|
|
3731
|
+
const resultText = typeof result.result === "string" ? result.result : JSON.stringify(result.result);
|
|
3732
|
+
const claimed = extractCascadeEvidence(resultText);
|
|
3733
|
+
if (claimed) {
|
|
3734
|
+
agentEvidence.push({ agentKind, evidence: claimed });
|
|
3700
3735
|
}
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3736
|
+
await session.append({
|
|
3737
|
+
type: "llm_response",
|
|
3738
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3739
|
+
content: [
|
|
3740
|
+
{
|
|
3741
|
+
type: "text",
|
|
3742
|
+
text: `\u{1F982} Chimera cascade (${agentKind}) \u2014 ${resultText}`
|
|
3743
|
+
}
|
|
3744
|
+
],
|
|
3745
|
+
stopReason: "end_turn",
|
|
3746
|
+
usage: { input: 0, output: 0 }
|
|
3747
|
+
});
|
|
3748
|
+
} else {
|
|
3749
|
+
const detail = outcome.lastError ? outcome.lastError instanceof Error ? outcome.lastError.message : String(outcome.lastError) : `${result?.status ?? "unknown"}: ${result?.error?.message ?? "no result"}`;
|
|
3707
3750
|
await session.append({
|
|
3708
3751
|
type: "error",
|
|
3709
3752
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3710
|
-
message: `\u{1F982} Chimera cascade (${agentKind})
|
|
3753
|
+
message: `\u{1F982} Chimera cascade (${agentKind}) ${result?.status ?? "unknown"}: ${detail} \u2014 exhausted ${outcome.attemptsUsed} of ${ladder.length} model(s)`,
|
|
3711
3754
|
phase: "agent"
|
|
3712
3755
|
});
|
|
3713
3756
|
}
|
|
3714
|
-
})
|
|
3715
|
-
const result = outcome.result;
|
|
3716
|
-
if (result?.status === "success") {
|
|
3717
|
-
const resultText = typeof result.result === "string" ? result.result : JSON.stringify(result.result);
|
|
3718
|
-
const claimed = extractCascadeEvidence(resultText);
|
|
3719
|
-
if (claimed) {
|
|
3720
|
-
agentEvidence.push({ agentKind, evidence: claimed });
|
|
3721
|
-
}
|
|
3722
|
-
await session.append({
|
|
3723
|
-
type: "llm_response",
|
|
3724
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3725
|
-
content: [
|
|
3726
|
-
{
|
|
3727
|
-
type: "text",
|
|
3728
|
-
text: `\u{1F982} Chimera cascade (${agentKind}) \u2014 ${resultText}`
|
|
3729
|
-
}
|
|
3730
|
-
],
|
|
3731
|
-
stopReason: "end_turn",
|
|
3732
|
-
usage: { input: 0, output: 0 }
|
|
3733
|
-
});
|
|
3734
|
-
} else {
|
|
3735
|
-
const detail = outcome.lastError ? outcome.lastError instanceof Error ? outcome.lastError.message : String(outcome.lastError) : `${result?.status ?? "unknown"}: ${result?.error?.message ?? "no result"}`;
|
|
3757
|
+
} catch (err) {
|
|
3736
3758
|
await session.append({
|
|
3737
3759
|
type: "error",
|
|
3738
3760
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3739
|
-
message: `\u{1F982} Chimera cascade (${agentKind})
|
|
3761
|
+
message: `\u{1F982} Chimera cascade (${agentKind}) failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
3740
3762
|
phase: "agent"
|
|
3741
3763
|
});
|
|
3742
3764
|
}
|
|
3743
|
-
} catch (err) {
|
|
3744
|
-
await session.append({
|
|
3745
|
-
type: "error",
|
|
3746
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3747
|
-
message: `\u{1F982} Chimera cascade (${agentKind}) failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
3748
|
-
phase: "agent"
|
|
3749
|
-
});
|
|
3750
3765
|
}
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3766
|
+
const accumulatedEvidence = {};
|
|
3767
|
+
for (const { evidence } of agentEvidence) {
|
|
3768
|
+
for (const name of ["typecheck", "lint", "tests"]) {
|
|
3769
|
+
if (evidence[name]) accumulatedEvidence[name] = evidence[name];
|
|
3770
|
+
}
|
|
3756
3771
|
}
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
});
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3772
|
+
await maybeReReviewCascade({
|
|
3773
|
+
events,
|
|
3774
|
+
session,
|
|
3775
|
+
bundle: p.bundle,
|
|
3776
|
+
reportId: p.reportId,
|
|
3777
|
+
claimedEvidence: accumulatedEvidence,
|
|
3778
|
+
verifyEvidence,
|
|
3779
|
+
persistEvidence
|
|
3780
|
+
});
|
|
3781
|
+
})();
|
|
3782
|
+
trackWork(pendingWork);
|
|
3783
|
+
},
|
|
3784
|
+
"chimera-cascade"
|
|
3785
|
+
);
|
|
3770
3786
|
if (off) teardownHandlers?.push(off);
|
|
3771
3787
|
}
|
|
3772
3788
|
async function maybeReReviewCascade({
|
|
@@ -3948,372 +3964,376 @@ function installChimeraReviewHandler({
|
|
|
3948
3964
|
trackWork,
|
|
3949
3965
|
teardownHandlers
|
|
3950
3966
|
}) {
|
|
3951
|
-
const off = events.onPattern(
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
if (!dir) {
|
|
3960
|
-
void recordCompletedReview(events, { bundle: p }).catch(() => void 0);
|
|
3961
|
-
return;
|
|
3962
|
-
}
|
|
3963
|
-
if (p.files.length === 0) return;
|
|
3964
|
-
const appendChimeraNotice = async (message) => {
|
|
3965
|
-
try {
|
|
3966
|
-
await session.append({
|
|
3967
|
-
type: "error",
|
|
3968
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3969
|
-
message,
|
|
3970
|
-
phase: "agent"
|
|
3971
|
-
});
|
|
3972
|
-
} catch (err) {
|
|
3973
|
-
console.warn(
|
|
3974
|
-
JSON.stringify({
|
|
3975
|
-
level: "warn",
|
|
3976
|
-
event: "execution.chimera_notice_append_failed",
|
|
3977
|
-
message: err instanceof Error ? err.message : String(err),
|
|
3978
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3979
|
-
})
|
|
3980
|
-
);
|
|
3967
|
+
const off = events.onPattern(
|
|
3968
|
+
"chimera.review_needed",
|
|
3969
|
+
(_event, payload) => {
|
|
3970
|
+
const p = payload;
|
|
3971
|
+
const reviewSessionId = agent.ctx.activeRunSessionId ?? agent.ctx.session?.id ?? session.id;
|
|
3972
|
+
if (!areSubagentsAllowedForSession(reviewSessionId)) {
|
|
3973
|
+
void recordCompletedReview(events, { bundle: p }).catch(() => void 0);
|
|
3974
|
+
return;
|
|
3981
3975
|
}
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
events.emitCustom("chimera.review_persisted", {
|
|
3987
|
-
reportId: completion.reportId,
|
|
3988
|
-
sessionId: completion.sessionId,
|
|
3989
|
-
cwd: completion.cwd
|
|
3990
|
-
});
|
|
3991
|
-
} catch (error) {
|
|
3992
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
3993
|
-
events.emitCustom("chimera.review_persistence_failed", {
|
|
3994
|
-
reportId: completion.reportId,
|
|
3995
|
-
sessionId: completion.sessionId,
|
|
3996
|
-
cwd: completion.cwd,
|
|
3997
|
-
error: message
|
|
3998
|
-
});
|
|
3999
|
-
await appendChimeraNotice(
|
|
4000
|
-
`\u{1F982} Chimera report persistence failed: ${message}. The review remains in the session transcript and mailbox.`
|
|
4001
|
-
);
|
|
4002
|
-
} finally {
|
|
4003
|
-
await recordCompletedReview(events, completion);
|
|
4004
|
-
events.emitCustom("chimera.review_complete", completion);
|
|
3976
|
+
const dir = director;
|
|
3977
|
+
if (!dir) {
|
|
3978
|
+
void recordCompletedReview(events, { bundle: p }).catch(() => void 0);
|
|
3979
|
+
return;
|
|
4005
3980
|
}
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
(async () => {
|
|
4009
|
-
let subagentId;
|
|
3981
|
+
if (p.files.length === 0) return;
|
|
3982
|
+
const appendChimeraNotice = async (message) => {
|
|
4010
3983
|
try {
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
const assigned = assignReviewerModels(
|
|
4026
|
-
baseProvider,
|
|
4027
|
-
baseModel,
|
|
4028
|
-
baseFallbacks,
|
|
4029
|
-
p.reviewModelSelection ?? "round-robin",
|
|
4030
|
-
statusTracker
|
|
3984
|
+
await session.append({
|
|
3985
|
+
type: "error",
|
|
3986
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3987
|
+
message,
|
|
3988
|
+
phase: "agent"
|
|
3989
|
+
});
|
|
3990
|
+
} catch (err) {
|
|
3991
|
+
console.warn(
|
|
3992
|
+
JSON.stringify({
|
|
3993
|
+
level: "warn",
|
|
3994
|
+
event: "execution.chimera_notice_append_failed",
|
|
3995
|
+
message: err instanceof Error ? err.message : String(err),
|
|
3996
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3997
|
+
})
|
|
4031
3998
|
);
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
3999
|
+
}
|
|
4000
|
+
};
|
|
4001
|
+
const persistAndEmitCompletion = async (completion) => {
|
|
4002
|
+
try {
|
|
4003
|
+
await persistReview(completion, projectDir);
|
|
4004
|
+
events.emitCustom("chimera.review_persisted", {
|
|
4005
|
+
reportId: completion.reportId,
|
|
4006
|
+
sessionId: completion.sessionId,
|
|
4007
|
+
cwd: completion.cwd
|
|
4036
4008
|
});
|
|
4037
|
-
|
|
4038
|
-
const
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4009
|
+
} catch (error) {
|
|
4010
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4011
|
+
events.emitCustom("chimera.review_persistence_failed", {
|
|
4012
|
+
reportId: completion.reportId,
|
|
4013
|
+
sessionId: completion.sessionId,
|
|
4014
|
+
cwd: completion.cwd,
|
|
4015
|
+
error: message
|
|
4016
|
+
});
|
|
4017
|
+
await appendChimeraNotice(
|
|
4018
|
+
`\u{1F982} Chimera report persistence failed: ${message}. The review remains in the session transcript and mailbox.`
|
|
4019
|
+
);
|
|
4020
|
+
} finally {
|
|
4021
|
+
await recordCompletedReview(events, completion);
|
|
4022
|
+
events.emitCustom("chimera.review_complete", completion);
|
|
4023
|
+
}
|
|
4024
|
+
};
|
|
4025
|
+
trackWork(
|
|
4026
|
+
(async () => {
|
|
4027
|
+
let subagentId;
|
|
4028
|
+
try {
|
|
4029
|
+
const taskDesc = buildChimeraReviewTaskDescription(p);
|
|
4030
|
+
const tProvider = config.provider?.trim() || void 0;
|
|
4031
|
+
const tModel = config.model?.trim() || void 0;
|
|
4032
|
+
const rawProvider = p.reviewFallbackModels ? p.config.provider?.trim() || void 0 : tProvider;
|
|
4033
|
+
const rawModel = p.reviewFallbackModels ? p.config.model?.trim() || void 0 : tModel;
|
|
4034
|
+
const baseProvider = rawProvider || tProvider || config.provider;
|
|
4035
|
+
const baseModel = rawModel || tModel || config.model;
|
|
4036
|
+
const configFallbacks = [...p.config.fallbackModels ?? []];
|
|
4037
|
+
if (p.config.fallbackProfile) {
|
|
4038
|
+
configFallbacks.push(...fallbackProfileChain2(config, p.config.fallbackProfile));
|
|
4039
|
+
}
|
|
4040
|
+
const baseFallbacks = p.reviewFallbackModels ? [...p.reviewFallbackModels] : resolveReviewerFallbackModels(
|
|
4041
|
+
configFallbacks.length > 0 ? configFallbacks : void 0
|
|
4042
|
+
);
|
|
4043
|
+
const assigned = assignReviewerModels(
|
|
4044
|
+
baseProvider,
|
|
4045
|
+
baseModel,
|
|
4046
|
+
baseFallbacks,
|
|
4047
|
+
p.reviewModelSelection ?? "round-robin",
|
|
4048
|
+
statusTracker
|
|
4049
|
+
);
|
|
4050
|
+
const ladder = buildReviewerAttemptLadder({
|
|
4051
|
+
assigned,
|
|
4052
|
+
profileChain: effectiveFallbackChain(config),
|
|
4053
|
+
session: { provider: config.provider, model: config.model }
|
|
4054
|
+
});
|
|
4055
|
+
const ladderRefs = ladder.map(attemptLabel);
|
|
4056
|
+
const outcome = await runSubagentModelLadder({
|
|
4057
|
+
director: dir,
|
|
4058
|
+
ladder,
|
|
4059
|
+
budgetMs: REVIEWER_LADDER_BUDGET_MS,
|
|
4060
|
+
keepWinnerAlive: false,
|
|
4061
|
+
buildConfig: (attempt, timeoutMs) => applyChimeraReviewerReadOnlyPolicy({
|
|
4062
|
+
name: "chimera-review",
|
|
4063
|
+
role: "reviewer",
|
|
4064
|
+
systemPromptOverride: CHIMERA_REVIEW_PROMPT,
|
|
4065
|
+
maxIterations: 50,
|
|
4066
|
+
maxToolCalls: 250,
|
|
4067
|
+
timeoutMs,
|
|
4068
|
+
provider: attempt.provider,
|
|
4069
|
+
model: attempt.model,
|
|
4070
|
+
fallbackModels: attempt.fallbackModels,
|
|
4071
|
+
// Reviewers are ephemeral background infrastructure: they must
|
|
4072
|
+
// not consume the leader's lifetime maxSpawns budget.
|
|
4073
|
+
spawnBudgetExempt: true
|
|
4074
|
+
}),
|
|
4075
|
+
// The reviewer is read-only, so a retry re-runs the task verbatim.
|
|
4076
|
+
buildTask: () => taskDesc,
|
|
4077
|
+
onAttemptFailed: async (failure, next) => {
|
|
4078
|
+
console.warn(
|
|
4079
|
+
JSON.stringify({
|
|
4080
|
+
level: "warn",
|
|
4081
|
+
event: "execution.chimera_reviewer_attempt_failed",
|
|
4082
|
+
message: failure.reason,
|
|
4083
|
+
model: failure.model,
|
|
4084
|
+
tier: failure.tier,
|
|
4085
|
+
attempt: failure.attempt,
|
|
4086
|
+
of: ladder.length,
|
|
4087
|
+
nextModel: next ? attemptLabel(next) : void 0,
|
|
4088
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4089
|
+
})
|
|
4090
|
+
);
|
|
4091
|
+
if (!next) return;
|
|
4092
|
+
events.emitCustom("chimera.reviewer_model_fallback", {
|
|
4093
|
+
from: failure.model,
|
|
4094
|
+
to: attemptLabel(next),
|
|
4095
|
+
tier: next.tier,
|
|
4067
4096
|
attempt: failure.attempt,
|
|
4068
4097
|
of: ladder.length,
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4098
|
+
reason: failure.reason
|
|
4099
|
+
});
|
|
4100
|
+
await appendChimeraNotice(
|
|
4101
|
+
`\u{1F982} Chimera review on ${failure.model} failed (${failure.reason}) \u2014 retrying the same review on ${attemptLabel(next)} (${next.tier}).`
|
|
4102
|
+
);
|
|
4103
|
+
},
|
|
4104
|
+
onRecovered: async (attempt, failures) => {
|
|
4105
|
+
await appendChimeraNotice(
|
|
4106
|
+
`\u{1F982} Chimera review recovered on ${attemptLabel(attempt)} (${attempt.tier}) after ${failures.length} failed attempt(s).`
|
|
4107
|
+
);
|
|
4108
|
+
}
|
|
4109
|
+
});
|
|
4110
|
+
subagentId = outcome.subagentId;
|
|
4111
|
+
const result = outcome.result;
|
|
4112
|
+
if (result?.status !== "success") {
|
|
4113
|
+
const exhaustedDetail = outcome.lastError ? outcome.lastError instanceof Error ? outcome.lastError.message : String(outcome.lastError) : `${result?.status ?? "unknown"}: ${result?.error?.message ?? "no result"}`;
|
|
4114
|
+
try {
|
|
4115
|
+
await session.append({
|
|
4116
|
+
type: "error",
|
|
4117
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4118
|
+
message: `\u{1F982} Chimera review subagent ${result?.status ?? "unknown"}: ${exhaustedDetail} \u2014 exhausted ${outcome.attemptsUsed} of ${ladder.length} model(s): ${ladderRefs.join(" \u2192 ")}`,
|
|
4119
|
+
phase: "agent"
|
|
4120
|
+
});
|
|
4121
|
+
} catch (err) {
|
|
4122
|
+
console.error(
|
|
4123
|
+
JSON.stringify({
|
|
4124
|
+
level: "error",
|
|
4125
|
+
event: "execution.chimera_append_failed",
|
|
4126
|
+
message: err instanceof Error ? err.message : String(err),
|
|
4127
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4128
|
+
})
|
|
4129
|
+
);
|
|
4130
|
+
}
|
|
4131
|
+
await persistAndEmitCompletion({
|
|
4132
|
+
bundle: p,
|
|
4133
|
+
reviewText: "",
|
|
4134
|
+
status: result?.status ?? "unknown",
|
|
4135
|
+
cwd: p.cwd,
|
|
4136
|
+
sessionId: reviewSessionId,
|
|
4137
|
+
reportId: randomUUID3()
|
|
4081
4138
|
});
|
|
4082
|
-
|
|
4083
|
-
`\u{1F982} Chimera review on ${failure.model} failed (${failure.reason}) \u2014 retrying the same review on ${attemptLabel(next)} (${next.tier}).`
|
|
4084
|
-
);
|
|
4085
|
-
},
|
|
4086
|
-
onRecovered: async (attempt, failures) => {
|
|
4087
|
-
await appendChimeraNotice(
|
|
4088
|
-
`\u{1F982} Chimera review recovered on ${attemptLabel(attempt)} (${attempt.tier}) after ${failures.length} failed attempt(s).`
|
|
4089
|
-
);
|
|
4090
|
-
}
|
|
4091
|
-
});
|
|
4092
|
-
subagentId = outcome.subagentId;
|
|
4093
|
-
const result = outcome.result;
|
|
4094
|
-
if (result?.status !== "success") {
|
|
4095
|
-
const exhaustedDetail = outcome.lastError ? outcome.lastError instanceof Error ? outcome.lastError.message : String(outcome.lastError) : `${result?.status ?? "unknown"}: ${result?.error?.message ?? "no result"}`;
|
|
4096
|
-
try {
|
|
4097
|
-
await session.append({
|
|
4098
|
-
type: "error",
|
|
4099
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4100
|
-
message: `\u{1F982} Chimera review subagent ${result?.status ?? "unknown"}: ${exhaustedDetail} \u2014 exhausted ${outcome.attemptsUsed} of ${ladder.length} model(s): ${ladderRefs.join(" \u2192 ")}`,
|
|
4101
|
-
phase: "agent"
|
|
4102
|
-
});
|
|
4103
|
-
} catch (err) {
|
|
4104
|
-
console.error(
|
|
4105
|
-
JSON.stringify({
|
|
4106
|
-
level: "error",
|
|
4107
|
-
event: "execution.chimera_append_failed",
|
|
4108
|
-
message: err instanceof Error ? err.message : String(err),
|
|
4109
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4110
|
-
})
|
|
4111
|
-
);
|
|
4139
|
+
return;
|
|
4112
4140
|
}
|
|
4141
|
+
const reviewText = typeof result.result === "string" ? result.result.trim() : JSON.stringify(result.result);
|
|
4142
|
+
const reportId = randomUUID3();
|
|
4143
|
+
const reviewSource = classifyChimeraReviewSource(p);
|
|
4144
|
+
const winningAttempt = outcome.wonAt ? ladder[outcome.wonAt - 1] : void 0;
|
|
4145
|
+
const parsedReport = parseChimeraReviewReport(reviewText, {
|
|
4146
|
+
sessionId: reviewSessionId,
|
|
4147
|
+
agentId: p.fileProvenance?.find((entry) => entry.agentId)?.agentId ?? "chimera-review",
|
|
4148
|
+
reviewerModel: winningAttempt ? attemptLabel(winningAttempt) : void 0,
|
|
4149
|
+
reviewType: reviewSource,
|
|
4150
|
+
reportId
|
|
4151
|
+
});
|
|
4152
|
+
const verifiedFindings = await verifyFindingsAgainstDisk(parsedReport.findings, {
|
|
4153
|
+
cwd: p.cwd
|
|
4154
|
+
});
|
|
4155
|
+
const verifiedParsedReport = {
|
|
4156
|
+
...parsedReport,
|
|
4157
|
+
findings: verifiedFindings
|
|
4158
|
+
};
|
|
4113
4159
|
await persistAndEmitCompletion({
|
|
4114
4160
|
bundle: p,
|
|
4115
|
-
reviewText
|
|
4116
|
-
status:
|
|
4161
|
+
reviewText,
|
|
4162
|
+
status: "success",
|
|
4117
4163
|
cwd: p.cwd,
|
|
4118
4164
|
sessionId: reviewSessionId,
|
|
4119
|
-
reportId
|
|
4165
|
+
reportId,
|
|
4166
|
+
parsedReport: verifiedParsedReport
|
|
4120
4167
|
});
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
const winningAttempt = outcome.wonAt ? ladder[outcome.wonAt - 1] : void 0;
|
|
4127
|
-
const parsedReport = parseChimeraReviewReport(reviewText, {
|
|
4128
|
-
sessionId: reviewSessionId,
|
|
4129
|
-
agentId: p.fileProvenance?.find((entry) => entry.agentId)?.agentId ?? "chimera-review",
|
|
4130
|
-
reviewerModel: winningAttempt ? attemptLabel(winningAttempt) : void 0,
|
|
4131
|
-
reviewType: reviewSource,
|
|
4132
|
-
reportId
|
|
4133
|
-
});
|
|
4134
|
-
const verifiedFindings = await verifyFindingsAgainstDisk(parsedReport.findings, {
|
|
4135
|
-
cwd: p.cwd
|
|
4136
|
-
});
|
|
4137
|
-
const verifiedParsedReport = {
|
|
4138
|
-
...parsedReport,
|
|
4139
|
-
findings: verifiedFindings
|
|
4140
|
-
};
|
|
4141
|
-
await persistAndEmitCompletion({
|
|
4142
|
-
bundle: p,
|
|
4143
|
-
reviewText,
|
|
4144
|
-
status: "success",
|
|
4145
|
-
cwd: p.cwd,
|
|
4146
|
-
sessionId: reviewSessionId,
|
|
4147
|
-
reportId,
|
|
4148
|
-
parsedReport: verifiedParsedReport
|
|
4149
|
-
});
|
|
4150
|
-
if (reviewText) {
|
|
4151
|
-
const reviewHasFindings = !isChimeraAllClearReview(reviewText);
|
|
4152
|
-
const citedFindings = verifiedFindings.filter((finding) => finding.location);
|
|
4153
|
-
const citedPaths = new Set(
|
|
4154
|
-
p.files.map((file) => normalizeFileKeyForCitation(file.path, p.cwd))
|
|
4155
|
-
);
|
|
4156
|
-
const changedBasenameIndex = /* @__PURE__ */ new Map();
|
|
4157
|
-
for (const file of p.files) {
|
|
4158
|
-
const normalized = normalizeFileKeyForCitation(file.path, p.cwd);
|
|
4159
|
-
const basename7 = path12.basename(file.path).toLowerCase();
|
|
4160
|
-
const bucket = changedBasenameIndex.get(basename7);
|
|
4161
|
-
if (bucket) bucket.push(normalized);
|
|
4162
|
-
else changedBasenameIndex.set(basename7, [normalized]);
|
|
4163
|
-
}
|
|
4164
|
-
const inScopeCited = citedFindings.filter((finding) => {
|
|
4165
|
-
const citedKey = normalizeFileKeyForCitation(finding.location.file, p.cwd);
|
|
4166
|
-
if (citedPaths.has(citedKey)) return true;
|
|
4167
|
-
const suffixMatches = [...citedPaths].filter(
|
|
4168
|
-
(cp) => cp.endsWith(`/${citedKey}`) || cp === citedKey
|
|
4168
|
+
if (reviewText) {
|
|
4169
|
+
const reviewHasFindings = !isChimeraAllClearReview(reviewText);
|
|
4170
|
+
const citedFindings = verifiedFindings.filter((finding) => finding.location);
|
|
4171
|
+
const citedPaths = new Set(
|
|
4172
|
+
p.files.map((file) => normalizeFileKeyForCitation(file.path, p.cwd))
|
|
4169
4173
|
);
|
|
4170
|
-
|
|
4171
|
-
const
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4174
|
+
const changedBasenameIndex = /* @__PURE__ */ new Map();
|
|
4175
|
+
for (const file of p.files) {
|
|
4176
|
+
const normalized = normalizeFileKeyForCitation(file.path, p.cwd);
|
|
4177
|
+
const basename7 = path12.basename(file.path).toLowerCase();
|
|
4178
|
+
const bucket = changedBasenameIndex.get(basename7);
|
|
4179
|
+
if (bucket) bucket.push(normalized);
|
|
4180
|
+
else changedBasenameIndex.set(basename7, [normalized]);
|
|
4181
|
+
}
|
|
4182
|
+
const inScopeCited = citedFindings.filter((finding) => {
|
|
4183
|
+
const citedKey = normalizeFileKeyForCitation(finding.location.file, p.cwd);
|
|
4184
|
+
if (citedPaths.has(citedKey)) return true;
|
|
4185
|
+
const suffixMatches = [...citedPaths].filter(
|
|
4186
|
+
(cp) => cp.endsWith(`/${citedKey}`) || cp === citedKey
|
|
4187
|
+
);
|
|
4188
|
+
if (suffixMatches.length === 1) return true;
|
|
4189
|
+
const basename7 = path12.basename(finding.location.file).toLowerCase();
|
|
4190
|
+
const bucket = changedBasenameIndex.get(basename7);
|
|
4191
|
+
return !!(bucket && bucket.length === 1);
|
|
4192
|
+
});
|
|
4193
|
+
const droppedCitations = citedFindings.filter(
|
|
4194
|
+
(finding) => !inScopeCited.includes(finding)
|
|
4195
|
+
);
|
|
4196
|
+
const actionableFindings = inScopeCited.filter(
|
|
4197
|
+
(finding) => finding.verification?.status === "verified"
|
|
4198
|
+
);
|
|
4199
|
+
const unverifiedInScope = inScopeCited.filter(
|
|
4200
|
+
(finding) => finding.verification?.status === "unverified"
|
|
4201
|
+
);
|
|
4202
|
+
const failedVerificationCount = inScopeCited.filter(
|
|
4203
|
+
(finding) => finding.verification?.status === "failed"
|
|
4204
|
+
).length;
|
|
4205
|
+
const effectiveHasFindings = reviewHasFindings && (actionableFindings.length > 0 || unverifiedInScope.length > 0);
|
|
4206
|
+
const verifiedCount = actionableFindings.length;
|
|
4207
|
+
const unverifiedCount = unverifiedInScope.length;
|
|
4208
|
+
const hallucinationNote = droppedCitations.length > 0 ? `
|
|
4191
4209
|
|
|
4192
4210
|
\u26A0\uFE0F Citation validation: ${droppedCitations.length} finding(s) cite files outside the changed-file set and should be verified before acting.` : "";
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4211
|
+
const subject = `\u{1F982} Chimera report ready \u2014 ${p.files.length} file(s) checked`;
|
|
4212
|
+
let reviewMailMessageId;
|
|
4213
|
+
try {
|
|
4214
|
+
const directive = effectiveHasFindings ? "Chimera found potential issues. This report is informational: no leader turn, fix agent, or cascade was started. Open the report and explicitly ask the leader to act if you want changes." : "Chimera completed with no actionable findings. No follow-up was started.";
|
|
4215
|
+
const reviewBody = reviewText.length > 7500 ? truncateAtCodePointBoundary(reviewText, 7500) + "\n\n\u2026(truncated, full report is in the Chimera report store)" : reviewText;
|
|
4216
|
+
const body = `${directive}${hallucinationNote}
|
|
4199
4217
|
|
|
4200
4218
|
${reviewBody}`;
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
messageId: reviewMailMessageId,
|
|
4236
|
-
readerId: "chimera",
|
|
4237
|
-
completed: true,
|
|
4238
|
-
outcome: "Review completed with no actionable findings."
|
|
4239
|
-
});
|
|
4240
|
-
} catch (ackError) {
|
|
4241
|
-
console.warn(
|
|
4242
|
-
JSON.stringify({
|
|
4243
|
-
level: "warn",
|
|
4244
|
-
event: "execution.chimera_mailbox_completion_failed",
|
|
4245
|
-
message: ackError instanceof Error ? ackError.message : String(ackError),
|
|
4219
|
+
const mailMsg = await mailbox.send({
|
|
4220
|
+
from: "chimera-review",
|
|
4221
|
+
to: "leader",
|
|
4222
|
+
type: "result",
|
|
4223
|
+
audience: "leaders",
|
|
4224
|
+
subject,
|
|
4225
|
+
body,
|
|
4226
|
+
priority: "normal",
|
|
4227
|
+
// Session-affinity stamp: the recipient's leader filter
|
|
4228
|
+
// uses this to drop the message for any leader whose current
|
|
4229
|
+
// session id does NOT match the originating session of the
|
|
4230
|
+
// review (`reviewSessionId` is captured above from the
|
|
4231
|
+
// agent's active run / session id). Without this token the
|
|
4232
|
+
// project-wide mailbox would deliver every chimera result to
|
|
4233
|
+
// every leader, inviting them to act on reports that belong
|
|
4234
|
+
// to a different session.
|
|
4235
|
+
sessionAffinity: {
|
|
4236
|
+
sessionId: reviewSessionId,
|
|
4237
|
+
reportId,
|
|
4238
|
+
kind: "chimera.review"
|
|
4239
|
+
}
|
|
4240
|
+
});
|
|
4241
|
+
if (!mailMsg?.id) throw new Error("mailbox.send returned no message id");
|
|
4242
|
+
reviewMailMessageId = mailMsg.id;
|
|
4243
|
+
events.emitCustom("chimera.mailbox_delivered", {
|
|
4244
|
+
subject,
|
|
4245
|
+
autoFixMode: "off",
|
|
4246
|
+
fileCount: p.files.length,
|
|
4247
|
+
reviewLength: reviewText.length,
|
|
4248
|
+
messageId: reviewMailMessageId
|
|
4249
|
+
});
|
|
4250
|
+
if (!reviewHasFindings) {
|
|
4251
|
+
try {
|
|
4252
|
+
await mailbox.ack({
|
|
4246
4253
|
messageId: reviewMailMessageId,
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4254
|
+
readerId: "chimera",
|
|
4255
|
+
completed: true,
|
|
4256
|
+
outcome: "Review completed with no actionable findings."
|
|
4257
|
+
});
|
|
4258
|
+
} catch (ackError) {
|
|
4259
|
+
console.warn(
|
|
4260
|
+
JSON.stringify({
|
|
4261
|
+
level: "warn",
|
|
4262
|
+
event: "execution.chimera_mailbox_completion_failed",
|
|
4263
|
+
message: ackError instanceof Error ? ackError.message : String(ackError),
|
|
4264
|
+
messageId: reviewMailMessageId,
|
|
4265
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4266
|
+
})
|
|
4267
|
+
);
|
|
4268
|
+
}
|
|
4250
4269
|
}
|
|
4270
|
+
} catch (mailErr) {
|
|
4271
|
+
const errMsg = mailErr instanceof Error ? mailErr.message : String(mailErr);
|
|
4272
|
+
console.error(
|
|
4273
|
+
JSON.stringify({
|
|
4274
|
+
level: "error",
|
|
4275
|
+
event: "execution.chimera_mailbox_failed",
|
|
4276
|
+
message: errMsg,
|
|
4277
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4278
|
+
})
|
|
4279
|
+
);
|
|
4280
|
+
events.emitCustom("chimera.mailbox_failed", {
|
|
4281
|
+
subject,
|
|
4282
|
+
autoFixMode: "off",
|
|
4283
|
+
fileCount: p.files.length,
|
|
4284
|
+
reviewLength: reviewText.length,
|
|
4285
|
+
error: errMsg
|
|
4286
|
+
});
|
|
4287
|
+
await session.append({
|
|
4288
|
+
type: "error",
|
|
4289
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4290
|
+
message: `\u{1F982} Chimera report ${reportId} is ready, but mailbox delivery failed: ${errMsg}. No follow-up was started.`,
|
|
4291
|
+
phase: "agent"
|
|
4292
|
+
});
|
|
4251
4293
|
}
|
|
4252
|
-
|
|
4253
|
-
const
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
message: errMsg,
|
|
4259
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4260
|
-
})
|
|
4261
|
-
);
|
|
4262
|
-
events.emitCustom("chimera.mailbox_failed", {
|
|
4263
|
-
subject,
|
|
4264
|
-
autoFixMode: "off",
|
|
4294
|
+
const findingCount = actionableFindings.length;
|
|
4295
|
+
const message = effectiveHasFindings ? `\u{1F982} Chimera report ready \u2014 ${findingCount || "unparsed"} potential finding(s) (${verifiedCount} verified against disk, ${unverifiedCount} unverified, ${failedVerificationCount} failed) across ${p.files.length} file(s). No follow-up started; open the mailbox and explicitly ask the leader to act if wanted.` : `\u{1F982} Chimera report ready \u2014 ${p.files.length} file(s) checked, no actionable findings. No follow-up started.`;
|
|
4296
|
+
events.emitCustom("chimera.report_available", {
|
|
4297
|
+
reportId,
|
|
4298
|
+
sessionId: reviewSessionId,
|
|
4299
|
+
message,
|
|
4265
4300
|
fileCount: p.files.length,
|
|
4266
|
-
|
|
4267
|
-
|
|
4301
|
+
findingCount,
|
|
4302
|
+
hasActionableFindings: effectiveHasFindings,
|
|
4303
|
+
...reviewMailMessageId ? { messageId: reviewMailMessageId } : {}
|
|
4268
4304
|
});
|
|
4305
|
+
}
|
|
4306
|
+
} catch (err) {
|
|
4307
|
+
try {
|
|
4269
4308
|
await session.append({
|
|
4270
4309
|
type: "error",
|
|
4271
4310
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4272
|
-
message: `\u{1F982} Chimera
|
|
4311
|
+
message: `\u{1F982} Chimera review failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
4273
4312
|
phase: "agent"
|
|
4274
4313
|
});
|
|
4314
|
+
} catch (appendErr) {
|
|
4315
|
+
console.error(
|
|
4316
|
+
JSON.stringify({
|
|
4317
|
+
level: "error",
|
|
4318
|
+
event: "execution.chimera_review_append_failed",
|
|
4319
|
+
message: appendErr instanceof Error ? appendErr.message : String(appendErr),
|
|
4320
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4321
|
+
})
|
|
4322
|
+
);
|
|
4275
4323
|
}
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
fileCount: p.files.length,
|
|
4283
|
-
findingCount,
|
|
4284
|
-
hasActionableFindings: effectiveHasFindings,
|
|
4285
|
-
...reviewMailMessageId ? { messageId: reviewMailMessageId } : {}
|
|
4286
|
-
});
|
|
4287
|
-
}
|
|
4288
|
-
} catch (err) {
|
|
4289
|
-
try {
|
|
4290
|
-
await session.append({
|
|
4291
|
-
type: "error",
|
|
4292
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4293
|
-
message: `\u{1F982} Chimera review failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
4294
|
-
phase: "agent"
|
|
4295
|
-
});
|
|
4296
|
-
} catch (appendErr) {
|
|
4297
|
-
console.error(
|
|
4298
|
-
JSON.stringify({
|
|
4299
|
-
level: "error",
|
|
4300
|
-
event: "execution.chimera_review_append_failed",
|
|
4301
|
-
message: appendErr instanceof Error ? appendErr.message : String(appendErr),
|
|
4302
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4303
|
-
})
|
|
4304
|
-
);
|
|
4305
|
-
}
|
|
4306
|
-
} finally {
|
|
4307
|
-
if (subagentId) {
|
|
4308
|
-
try {
|
|
4309
|
-
await dir.terminate(subagentId);
|
|
4310
|
-
} catch {
|
|
4324
|
+
} finally {
|
|
4325
|
+
if (subagentId) {
|
|
4326
|
+
try {
|
|
4327
|
+
await dir.terminate(subagentId);
|
|
4328
|
+
} catch {
|
|
4329
|
+
}
|
|
4311
4330
|
}
|
|
4312
4331
|
}
|
|
4313
|
-
}
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4332
|
+
})()
|
|
4333
|
+
);
|
|
4334
|
+
},
|
|
4335
|
+
"chimera-review"
|
|
4336
|
+
);
|
|
4317
4337
|
if (off) teardownHandlers?.push(off);
|
|
4318
4338
|
}
|
|
4319
4339
|
async function persistChimeraReview(payload, projectDir) {
|
|
@@ -4825,9 +4845,7 @@ async function runReplEternalLoop(opts, onInterruptsReset) {
|
|
|
4825
4845
|
if (autonomy === "eternal-parallel") {
|
|
4826
4846
|
const engine = opts.getParallelEngine?.();
|
|
4827
4847
|
if (!engine) {
|
|
4828
|
-
opts.renderer.writeWarning(
|
|
4829
|
-
"Parallel mode set but no engine wired \u2014 falling back to off."
|
|
4830
|
-
);
|
|
4848
|
+
opts.renderer.writeWarning("Parallel mode set but no engine wired \u2014 falling back to off.");
|
|
4831
4849
|
return false;
|
|
4832
4850
|
}
|
|
4833
4851
|
const beforeGoal = await loadGoalSafe(opts);
|
|
@@ -4841,10 +4859,8 @@ async function runReplEternalLoop(opts, onInterruptsReset) {
|
|
|
4841
4859
|
) + "\n"
|
|
4842
4860
|
);
|
|
4843
4861
|
}
|
|
4844
|
-
opts.renderer.write(
|
|
4845
|
-
|
|
4846
|
-
`)
|
|
4847
|
-
);
|
|
4862
|
+
opts.renderer.write(color8.magenta(` \u21B3 [parallel #${beforeIter + 1}] launching fan-out\u2026
|
|
4863
|
+
`));
|
|
4848
4864
|
onInterruptsReset();
|
|
4849
4865
|
try {
|
|
4850
4866
|
await engine.runOneIteration();
|
|
@@ -5691,7 +5707,11 @@ function tierMenu(store) {
|
|
|
5691
5707
|
],
|
|
5692
5708
|
body: "A tier binds a fallback profile, a spend budget and a runtime setting under one name, then routes work to it by role or phase. While disabled, spawns resolve exactly as they did before tiers existed.",
|
|
5693
5709
|
actions: [
|
|
5694
|
-
{
|
|
5710
|
+
{
|
|
5711
|
+
key: "t",
|
|
5712
|
+
label: enabled ? "turn off" : "turn on",
|
|
5713
|
+
command: `/tier ${enabled ? "off" : "on"}`
|
|
5714
|
+
}
|
|
5695
5715
|
]
|
|
5696
5716
|
},
|
|
5697
5717
|
{
|
|
@@ -5725,8 +5745,14 @@ function tierMenu(store) {
|
|
|
5725
5745
|
details: [
|
|
5726
5746
|
{ label: "rung", value: `${index + 1} of ${levelIds.length}` },
|
|
5727
5747
|
{ label: "profile", value: level?.fallbackProfile ?? "(none)" },
|
|
5728
|
-
{
|
|
5729
|
-
|
|
5748
|
+
{
|
|
5749
|
+
label: "max cost",
|
|
5750
|
+
value: level?.maxCostUsd !== void 0 ? `$${level.maxCostUsd}` : "(role default)"
|
|
5751
|
+
},
|
|
5752
|
+
{
|
|
5753
|
+
label: "max iterations",
|
|
5754
|
+
value: level?.maxIterations !== void 0 ? String(level.maxIterations) : "(role default)"
|
|
5755
|
+
},
|
|
5730
5756
|
{ label: "routed by", value: routedBy.join(", ") || "(nothing)" }
|
|
5731
5757
|
],
|
|
5732
5758
|
body: [
|
|
@@ -6698,4 +6724,4 @@ export {
|
|
|
6698
6724
|
execute,
|
|
6699
6725
|
resolveReviewerFallbackModels
|
|
6700
6726
|
};
|
|
6701
|
-
//# sourceMappingURL=execution-
|
|
6727
|
+
//# sourceMappingURL=execution-7ZFY4FJY.js.map
|