ghagga-core 3.3.0 → 3.4.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/dist/acp/adapter.d.ts.map +1 -1
- package/dist/acp/adapter.js +8 -1
- package/dist/acp/adapter.js.map +1 -1
- package/dist/agents/consensus.d.ts +2 -2
- package/dist/agents/consensus.d.ts.map +1 -1
- package/dist/agents/consensus.js +13 -5
- package/dist/agents/consensus.js.map +1 -1
- package/dist/agents/fan-out-lenses.d.ts +33 -2
- package/dist/agents/fan-out-lenses.d.ts.map +1 -1
- package/dist/agents/fan-out-lenses.js +245 -8
- package/dist/agents/fan-out-lenses.js.map +1 -1
- package/dist/agents/issue-code-discovery.d.ts +58 -0
- package/dist/agents/issue-code-discovery.d.ts.map +1 -0
- package/dist/agents/issue-code-discovery.js +144 -0
- package/dist/agents/issue-code-discovery.js.map +1 -0
- package/dist/agents/issue-triage.d.ts +10 -0
- package/dist/agents/issue-triage.d.ts.map +1 -1
- package/dist/agents/issue-triage.js +53 -4
- package/dist/agents/issue-triage.js.map +1 -1
- package/dist/agents/prompts.d.ts +12 -3
- package/dist/agents/prompts.d.ts.map +1 -1
- package/dist/agents/prompts.js +21 -2
- package/dist/agents/prompts.js.map +1 -1
- package/dist/agents/simple.d.ts.map +1 -1
- package/dist/agents/simple.js +1 -1
- package/dist/agents/simple.js.map +1 -1
- package/dist/agents/voice-validation.d.ts +34 -0
- package/dist/agents/voice-validation.d.ts.map +1 -0
- package/dist/agents/voice-validation.js +64 -0
- package/dist/agents/voice-validation.js.map +1 -0
- package/dist/agents/workflow.d.ts.map +1 -1
- package/dist/agents/workflow.js +8 -0
- package/dist/agents/workflow.js.map +1 -1
- package/dist/critique/critique.js +1 -1
- package/dist/critique/critique.js.map +1 -1
- package/dist/critique/prompts.d.ts +1 -1
- package/dist/critique/prompts.d.ts.map +1 -1
- package/dist/critique/prompts.js +1 -1
- package/dist/enhance/prompt.d.ts +1 -1
- package/dist/enhance/prompt.d.ts.map +1 -1
- package/dist/explanation.d.ts +69 -0
- package/dist/explanation.d.ts.map +1 -0
- package/dist/explanation.js +16 -0
- package/dist/explanation.js.map +1 -0
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +1 -0
- package/dist/format.js.map +1 -1
- package/dist/index.d.ts +11 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/memory/decay.d.ts +40 -0
- package/dist/memory/decay.d.ts.map +1 -1
- package/dist/memory/decay.js +57 -0
- package/dist/memory/decay.js.map +1 -1
- package/dist/memory/engram.d.ts.map +1 -1
- package/dist/memory/engram.js +15 -3
- package/dist/memory/engram.js.map +1 -1
- package/dist/memory/search.d.ts +157 -0
- package/dist/memory/search.d.ts.map +1 -1
- package/dist/memory/search.js +420 -0
- package/dist/memory/search.js.map +1 -1
- package/dist/memory/sqlite.d.ts.map +1 -1
- package/dist/memory/sqlite.js +11 -3
- package/dist/memory/sqlite.js.map +1 -1
- package/dist/pipeline/execute.d.ts.map +1 -1
- package/dist/pipeline/execute.js +14 -0
- package/dist/pipeline/execute.js.map +1 -1
- package/dist/providers/cli-bridge.d.ts +13 -11
- package/dist/providers/cli-bridge.d.ts.map +1 -1
- package/dist/providers/cli-bridge.js +155 -40
- package/dist/providers/cli-bridge.js.map +1 -1
- package/dist/providers/explanation-generate-fn.d.ts +28 -0
- package/dist/providers/explanation-generate-fn.d.ts.map +1 -0
- package/dist/providers/explanation-generate-fn.js +122 -0
- package/dist/providers/explanation-generate-fn.js.map +1 -0
- package/dist/types.d.ts +43 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -1
- package/package.json +15 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/acp/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EACV,WAAW,EAIX,cAAc,EACf,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EACV,oBAAoB,EAEpB,UAAU,EACV,WAAW,EACX,OAAO,EAEP,YAAY,EAGb,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/acp/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EACV,WAAW,EAIX,cAAc,EACf,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EACV,oBAAoB,EAEpB,UAAU,EACV,WAAW,EACX,OAAO,EAEP,YAAY,EAGb,MAAM,YAAY,CAAC;AAiBpB;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAA8B;IAE3C,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAIpC,GAAG,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAIxB,IAAI,IAAI,OAAO,EAAE;IAIjB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;CAG5B;AAID,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,QAAQ,EAAE,WAAW,CAAC;IAEtB,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IAEd,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IAEf,4DAA4D;IAC5D,eAAe,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAE1C,kDAAkD;IAClD,SAAS,CAAC,EAAE,YAAY,CAAC;IAEzB,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,gBAAgB,CAAsC;gBAElD,OAAO,EAAE,iBAAiB;IAOtC,eAAe,IAAI,oBAAoB;IAcvC;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO;IAkBxC;;;OAGG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IA+CzF;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAiB/C;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI5C;;OAEG;IACH,SAAS,IAAI,OAAO,EAAE;IAMtB;;;OAGG;IACG,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IAoD9D,OAAO,CAAC,gBAAgB;IA2BxB,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,cAAc;IAmCtB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,YAAY;CAGrB;AAaD,iDAAiD;AACjD,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
|
package/dist/acp/adapter.js
CHANGED
|
@@ -19,7 +19,14 @@ import { DEFAULT_SETTINGS } from '../types.js';
|
|
|
19
19
|
// ─── Constants ─────────────────────────────────────────────────
|
|
20
20
|
const AGENT_NAME = 'ghagga';
|
|
21
21
|
const AGENT_VERSION = '2.8.1';
|
|
22
|
-
const SUPPORTED_MODES = [
|
|
22
|
+
const SUPPORTED_MODES = [
|
|
23
|
+
'simple',
|
|
24
|
+
'workflow',
|
|
25
|
+
'consensus',
|
|
26
|
+
'diagnostic',
|
|
27
|
+
'fan-out',
|
|
28
|
+
'hybrid-4r',
|
|
29
|
+
];
|
|
23
30
|
// ─── Task Store ────────────────────────────────────────────────
|
|
24
31
|
/**
|
|
25
32
|
* In-memory task store for the ACP adapter.
|
package/dist/acp/adapter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/acp/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAQ/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAa/C,kEAAkE;AAElE,MAAM,UAAU,GAAG,QAAQ,CAAC;AAC5B,MAAM,aAAa,GAAG,OAAO,CAAC;AAC9B,MAAM,eAAe,GAAiB,
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/acp/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Thresholds:
|
|
10
10
|
* - 60% weighted votes for approve/reject → that decision wins
|
|
11
11
|
* - 30% minimum confidence gap between approve and reject
|
|
12
|
-
* - If thresholds not met →
|
|
12
|
+
* - If thresholds not met → INCONCLUSIVE
|
|
13
13
|
*/
|
|
14
14
|
import type { GenerateTextFn } from '../providers/generate-fn.js';
|
|
15
15
|
import type { ConsensusStance, ConsensusVote, LLMProvider, ProgressCallback, ReviewLevel, ReviewResult, ReviewStatus } from '../types.js';
|
|
@@ -66,7 +66,7 @@ export declare function parseVote(text: string, provider: LLMProvider, model: st
|
|
|
66
66
|
* Decision rules:
|
|
67
67
|
* - If approve ratio ≥ 60% → PASSED
|
|
68
68
|
* - If reject ratio ≥ 60% → FAILED
|
|
69
|
-
* - If confidence gap < 30% →
|
|
69
|
+
* - If totalWeight is 0, confidence gap < 30%, or neither ratio ≥ 60% → INCONCLUSIVE
|
|
70
70
|
*/
|
|
71
71
|
export declare function calculateConsensus(votes: ConsensusVote[]): {
|
|
72
72
|
status: ReviewStatus;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consensus.d.ts","sourceRoot":"","sources":["../../src/agents/consensus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,YAAY,EACb,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"consensus.d.ts","sourceRoot":"","sources":["../../src/agents/consensus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,YAAY,EACb,MAAM,aAAa,CAAC;AAoBrB,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAE9B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAE/B,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAmBD;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,eAAe,GACtB,aAAa,CAef;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG;IAC1D,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAuDA;AAID;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,YAAY,CAAC,CA2J3F"}
|
package/dist/agents/consensus.js
CHANGED
|
@@ -9,11 +9,12 @@
|
|
|
9
9
|
* Thresholds:
|
|
10
10
|
* - 60% weighted votes for approve/reject → that decision wins
|
|
11
11
|
* - 30% minimum confidence gap between approve and reject
|
|
12
|
-
* - If thresholds not met →
|
|
12
|
+
* - If thresholds not met → INCONCLUSIVE
|
|
13
13
|
*/
|
|
14
14
|
import { runWithConcurrency } from '../utils/concurrency.js';
|
|
15
15
|
import { calculateRateSchedule } from '../utils/token-budget.js';
|
|
16
16
|
import { buildMemoryContext, buildReviewLevelInstruction, COMPACT_CALIBRATION, CONSENSUS_AGAINST_SYSTEM, CONSENSUS_FOR_SYSTEM, CONSENSUS_NEUTRAL_SYSTEM, REVIEW_CALIBRATION, STATIC_ANALYSIS_UNTRUSTED_LABEL, UNTRUSTED_CONTENT_POLICY, wrapUntrusted, wrapUntrustedDiff, } from './prompts.js';
|
|
17
|
+
import { getDeadVoiceReason } from './voice-validation.js';
|
|
17
18
|
// ─── Constants ──────────────────────────────────────────────────
|
|
18
19
|
/** Minimum percentage of weighted votes to decide approve/reject */
|
|
19
20
|
const DECISION_THRESHOLD = 0.6;
|
|
@@ -60,7 +61,7 @@ export function parseVote(text, provider, model, stance) {
|
|
|
60
61
|
* Decision rules:
|
|
61
62
|
* - If approve ratio ≥ 60% → PASSED
|
|
62
63
|
* - If reject ratio ≥ 60% → FAILED
|
|
63
|
-
* - If confidence gap < 30% →
|
|
64
|
+
* - If totalWeight is 0, confidence gap < 30%, or neither ratio ≥ 60% → INCONCLUSIVE
|
|
64
65
|
*/
|
|
65
66
|
export function calculateConsensus(votes) {
|
|
66
67
|
let approveWeight = 0;
|
|
@@ -80,7 +81,7 @@ export function calculateConsensus(votes) {
|
|
|
80
81
|
// Prevent division by zero
|
|
81
82
|
if (totalWeight === 0) {
|
|
82
83
|
return {
|
|
83
|
-
status: '
|
|
84
|
+
status: 'INCONCLUSIVE',
|
|
84
85
|
summary: 'All models abstained. Manual review is recommended.',
|
|
85
86
|
};
|
|
86
87
|
}
|
|
@@ -90,7 +91,7 @@ export function calculateConsensus(votes) {
|
|
|
90
91
|
// Check confidence gap
|
|
91
92
|
if (gap < CONFIDENCE_GAP_THRESHOLD) {
|
|
92
93
|
return {
|
|
93
|
-
status: '
|
|
94
|
+
status: 'INCONCLUSIVE',
|
|
94
95
|
summary: `Consensus inconclusive (approve: ${(approveRatio * 100).toFixed(0)}%, reject: ${(rejectRatio * 100).toFixed(0)}%). The confidence gap (${(gap * 100).toFixed(0)}%) is below the ${(CONFIDENCE_GAP_THRESHOLD * 100).toFixed(0)}% threshold. Manual review recommended.`,
|
|
95
96
|
};
|
|
96
97
|
}
|
|
@@ -108,7 +109,7 @@ export function calculateConsensus(votes) {
|
|
|
108
109
|
};
|
|
109
110
|
}
|
|
110
111
|
return {
|
|
111
|
-
status: '
|
|
112
|
+
status: 'INCONCLUSIVE',
|
|
112
113
|
summary: `No clear consensus reached (approve: ${(approveRatio * 100).toFixed(0)}%, reject: ${(rejectRatio * 100).toFixed(0)}%). Manual review recommended.`,
|
|
113
114
|
};
|
|
114
115
|
}
|
|
@@ -176,6 +177,13 @@ export async function runConsensusReview(input) {
|
|
|
176
177
|
.filter(Boolean)
|
|
177
178
|
.join('\n');
|
|
178
179
|
const result = await generateFn(system, userPrompt);
|
|
180
|
+
// A fulfilled call can still be a dead voice (e.g. gateway returned
|
|
181
|
+
// HTTP 200 whose text is a raw CLI error envelope). Route it into the
|
|
182
|
+
// existing rejected/failure path instead of counting it as a vote.
|
|
183
|
+
const deadReason = getDeadVoiceReason(result.text);
|
|
184
|
+
if (deadReason) {
|
|
185
|
+
throw new Error(`${config.stance} vote (${result.provider}/${result.model}): ${deadReason}`);
|
|
186
|
+
}
|
|
179
187
|
return {
|
|
180
188
|
vote: parseVote(result.text, result.provider, result.model, config.stance),
|
|
181
189
|
tokensUsed: result.tokensUsed,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consensus.js","sourceRoot":"","sources":["../../src/agents/consensus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAYH,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,wBAAwB,EACxB,kBAAkB,EAClB,+BAA+B,EAC/B,wBAAwB,EACxB,aAAa,EACb,iBAAiB,GAClB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"consensus.js","sourceRoot":"","sources":["../../src/agents/consensus.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* - accessibility — a11y attributes, ARIA, keyboard navigation
|
|
15
15
|
*/
|
|
16
16
|
import type { GenerateTextFn } from '../providers/generate-fn.js';
|
|
17
|
-
import type { LLMProvider, ProgressCallback, ReviewLevel, ReviewResult } from '../types.js';
|
|
17
|
+
import type { LLMProvider, ProgressCallback, ReviewFinding, ReviewLevel, ReviewResult } from '../types.js';
|
|
18
18
|
/**
|
|
19
19
|
* A review lens: a focused perspective for code review.
|
|
20
20
|
* Each lens gets its own system prompt that constrains the LLM
|
|
@@ -102,13 +102,39 @@ export interface FanOutReviewInput {
|
|
|
102
102
|
delayMs?: number;
|
|
103
103
|
/**
|
|
104
104
|
* Backend-agnostic generation functions for lenses (round-robin).
|
|
105
|
-
* When provided, each lens uses generateFns[index % generateFns.length]
|
|
105
|
+
* When provided, each lens uses generateFns[index % generateFns.length],
|
|
106
|
+
* unless pinLensesToFirst is true (every lens uses generateFns[0]).
|
|
106
107
|
* When omitted, pipeline creates them from provider/model/apiKey.
|
|
107
108
|
*/
|
|
108
109
|
generateFns?: GenerateTextFn[];
|
|
110
|
+
/**
|
|
111
|
+
* When true, every resolved lens uses generateFns[0] instead of round-robin.
|
|
112
|
+
* Default undefined/false keeps current round-robin assignment.
|
|
113
|
+
* Fails closed if generateFns is missing or empty.
|
|
114
|
+
*/
|
|
115
|
+
pinLensesToFirst?: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Opt-in count of unlensed whole-diff contrarian voices.
|
|
118
|
+
* When set, must be an integer >= 1, requires pinLensesToFirst === true,
|
|
119
|
+
* and generateFns.length >= 1 + N. Contrarian i uses generateFns[1 + i].
|
|
120
|
+
*/
|
|
121
|
+
contrarianCount?: number;
|
|
122
|
+
/**
|
|
123
|
+
* Opt-in batched 2-of-K refuters over the closed critical ledger.
|
|
124
|
+
* When set, must be an integer >= 2, requires pinLensesToFirst === true,
|
|
125
|
+
* and generateFns.length >= 1 + (contrarianCount or 0) + refuterCount.
|
|
126
|
+
* Refuter i uses generateFns[1 + (contrarianCount or 0) + i].
|
|
127
|
+
*/
|
|
128
|
+
refuterCount?: number;
|
|
109
129
|
/** Optional SOLID/boundary checklist context for structured review. */
|
|
110
130
|
checklistContext?: string;
|
|
111
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Parse per-id refuter verdicts from model text.
|
|
134
|
+
* Only explicit `refute` or `stands` lines count. Unknown ids are kept in the
|
|
135
|
+
* map for the caller to ignore. Missing candidate ids have no map entry.
|
|
136
|
+
*/
|
|
137
|
+
export declare function parseRefuterVerdicts(text: string): Map<string, 'refute' | 'stands'>;
|
|
112
138
|
/**
|
|
113
139
|
* Deduplicate findings by file+line, taking the highest severity
|
|
114
140
|
* when the same location is flagged by multiple lenses.
|
|
@@ -117,6 +143,11 @@ export interface FanOutReviewInput {
|
|
|
117
143
|
* to avoid false deduplication.
|
|
118
144
|
*/
|
|
119
145
|
export declare function mergeFindings(allFindings: import('../types.js').ReviewFinding[]): import('../types.js').ReviewFinding[];
|
|
146
|
+
/**
|
|
147
|
+
* Stamp a first-class per-finding ledger onto fan-out results.
|
|
148
|
+
* Does not mutate inputs; returns new objects.
|
|
149
|
+
*/
|
|
150
|
+
export declare function stampFindingLedger(findings: ReviewFinding[]): ReviewFinding[];
|
|
120
151
|
/**
|
|
121
152
|
* Run a fan-out (multi-lens) code review.
|
|
122
153
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fan-out-lenses.d.ts","sourceRoot":"","sources":["../../src/agents/fan-out-lenses.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAEV,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EAEb,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"fan-out-lenses.d.ts","sourceRoot":"","sources":["../../src/agents/fan-out-lenses.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,9 +13,11 @@
|
|
|
13
13
|
* - typing — type safety, generics, strict mode
|
|
14
14
|
* - accessibility — a11y attributes, ARIA, keyboard navigation
|
|
15
15
|
*/
|
|
16
|
+
import { FINDING_LEDGER_STATUS } from '../types.js';
|
|
16
17
|
import { runWithConcurrency } from '../utils/concurrency.js';
|
|
17
18
|
import { buildMemoryContext, buildReviewLevelInstruction, COMPACT_CALIBRATION, REVIEW_CALIBRATION, STATIC_ANALYSIS_UNTRUSTED_LABEL, UNTRUSTED_CONTENT_POLICY, wrapUntrusted, wrapUntrustedDiff, } from './prompts.js';
|
|
18
19
|
import { parseFindingsBlock } from './simple.js';
|
|
20
|
+
import { getDeadVoiceReason } from './voice-validation.js';
|
|
19
21
|
// ─── Default Lenses ────────────────────────────────────────────
|
|
20
22
|
export const LENS_SECURITY = {
|
|
21
23
|
name: 'security',
|
|
@@ -321,6 +323,51 @@ const SEVERITY_RANK = {
|
|
|
321
323
|
low: 2,
|
|
322
324
|
info: 1,
|
|
323
325
|
};
|
|
326
|
+
/** Unlensed whole-diff voice. Not a specialty lens and not SIMPLE_REVIEW_SYSTEM. */
|
|
327
|
+
const CONTRARIAN_SYSTEM = `You are an unlensed whole-diff code reviewer. You have no specialty lens.
|
|
328
|
+
|
|
329
|
+
Report only real defects you are confident about. Do not invent issues.
|
|
330
|
+
|
|
331
|
+
Format your response EXACTLY as:
|
|
332
|
+
|
|
333
|
+
STATUS: [PASSED or FAILED]
|
|
334
|
+
SUMMARY: [1-2 sentence assessment]
|
|
335
|
+
FINDINGS:
|
|
336
|
+
- SEVERITY: [critical|high|medium|low|info]
|
|
337
|
+
CATEGORY: contrarian
|
|
338
|
+
FILE: [file path]
|
|
339
|
+
LINE: [line number or "N/A"]
|
|
340
|
+
MESSAGE: [clear description of the defect]
|
|
341
|
+
SUGGESTION: [specific fix]
|
|
342
|
+
|
|
343
|
+
FAILED if: Any critical or high issues. PASSED otherwise.`;
|
|
344
|
+
/** Batched closed-list refuter. Not a lens and not SIMPLE_REVIEW_SYSTEM. */
|
|
345
|
+
const REFUTER_SYSTEM = `You are a batched finding refuter. You are not a review lens.
|
|
346
|
+
|
|
347
|
+
You receive a closed candidate list. Do not add findings. Do not invent ids.
|
|
348
|
+
For each candidate id, emit exactly one verdict: stands or refute.
|
|
349
|
+
A missing or malformed verdict is treated as stands.
|
|
350
|
+
|
|
351
|
+
Format each verdict on its own line as:
|
|
352
|
+
<id>: stands
|
|
353
|
+
<id>: refute`;
|
|
354
|
+
/**
|
|
355
|
+
* Parse per-id refuter verdicts from model text.
|
|
356
|
+
* Only explicit `refute` or `stands` lines count. Unknown ids are kept in the
|
|
357
|
+
* map for the caller to ignore. Missing candidate ids have no map entry.
|
|
358
|
+
*/
|
|
359
|
+
export function parseRefuterVerdicts(text) {
|
|
360
|
+
const verdicts = new Map();
|
|
361
|
+
const pattern = /^\s*([A-Za-z0-9][A-Za-z0-9_-]*)\s*:\s*(refute|stands)\b/gim;
|
|
362
|
+
for (const match of text.matchAll(pattern)) {
|
|
363
|
+
const id = match[1];
|
|
364
|
+
const verdict = match[2]?.toLowerCase();
|
|
365
|
+
if (!id || (verdict !== 'refute' && verdict !== 'stands'))
|
|
366
|
+
continue;
|
|
367
|
+
verdicts.set(id, verdict);
|
|
368
|
+
}
|
|
369
|
+
return verdicts;
|
|
370
|
+
}
|
|
324
371
|
// ─── Merge Logic ───────────────────────────────────────────────
|
|
325
372
|
/**
|
|
326
373
|
* Deduplicate findings by file+line, taking the highest severity
|
|
@@ -357,6 +404,27 @@ export function mergeFindings(allFindings) {
|
|
|
357
404
|
return a.file.localeCompare(b.file);
|
|
358
405
|
});
|
|
359
406
|
}
|
|
407
|
+
/**
|
|
408
|
+
* Stamp a first-class per-finding ledger onto fan-out results.
|
|
409
|
+
* Does not mutate inputs; returns new objects.
|
|
410
|
+
*/
|
|
411
|
+
export function stampFindingLedger(findings) {
|
|
412
|
+
const counters = new Map();
|
|
413
|
+
return findings.map((finding) => {
|
|
414
|
+
const lens = finding.category || 'unknown';
|
|
415
|
+
const next = (counters.get(lens) ?? 0) + 1;
|
|
416
|
+
counters.set(lens, next);
|
|
417
|
+
const location = typeof finding.line === 'number' ? `${finding.file}:${finding.line}` : finding.file;
|
|
418
|
+
return {
|
|
419
|
+
...finding,
|
|
420
|
+
id: `${lens}-${String(next).padStart(3, '0')}`,
|
|
421
|
+
lens,
|
|
422
|
+
location,
|
|
423
|
+
ledgerStatus: FINDING_LEDGER_STATUS.open,
|
|
424
|
+
evidence: finding.message,
|
|
425
|
+
};
|
|
426
|
+
});
|
|
427
|
+
}
|
|
360
428
|
// ─── Main Function ─────────────────────────────────────────────
|
|
361
429
|
/**
|
|
362
430
|
* Run a fan-out (multi-lens) code review.
|
|
@@ -398,6 +466,38 @@ export async function runFanOutReview(input) {
|
|
|
398
466
|
}
|
|
399
467
|
// ── Resolve GenerateTextFn array ────────────────────────────
|
|
400
468
|
const resolvedGenerateFns = input.generateFns ?? [];
|
|
469
|
+
if (input.pinLensesToFirst === true && resolvedGenerateFns.length === 0) {
|
|
470
|
+
throw new Error('pinLensesToFirst requires a non-empty generateFns array');
|
|
471
|
+
}
|
|
472
|
+
const contrarianCount = input.contrarianCount;
|
|
473
|
+
if (contrarianCount !== undefined) {
|
|
474
|
+
if (!Number.isInteger(contrarianCount) || contrarianCount < 1) {
|
|
475
|
+
throw new Error(`contrarianCount must be an integer >= 1, received: ${contrarianCount}`);
|
|
476
|
+
}
|
|
477
|
+
if (input.pinLensesToFirst !== true) {
|
|
478
|
+
throw new Error('contrarianCount requires pinLensesToFirst === true');
|
|
479
|
+
}
|
|
480
|
+
if (resolvedGenerateFns.length < 1 + contrarianCount) {
|
|
481
|
+
throw new Error(`contrarianCount ${contrarianCount} requires generateFns.length >= ${1 + contrarianCount}`);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
const refuterCount = input.refuterCount;
|
|
485
|
+
if (refuterCount !== undefined) {
|
|
486
|
+
if (!Number.isInteger(refuterCount) || refuterCount < 2) {
|
|
487
|
+
throw new Error(`refuterCount must be an integer >= 2, received: ${refuterCount}`);
|
|
488
|
+
}
|
|
489
|
+
if (input.pinLensesToFirst !== true) {
|
|
490
|
+
throw new Error('refuterCount requires pinLensesToFirst === true');
|
|
491
|
+
}
|
|
492
|
+
const contrarianN = typeof contrarianCount === 'number' &&
|
|
493
|
+
Number.isInteger(contrarianCount) &&
|
|
494
|
+
contrarianCount >= 1
|
|
495
|
+
? contrarianCount
|
|
496
|
+
: 0;
|
|
497
|
+
if (resolvedGenerateFns.length < 1 + contrarianN + refuterCount) {
|
|
498
|
+
throw new Error(`refuterCount ${refuterCount} requires generateFns.length >= ${1 + contrarianN + refuterCount}`);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
401
501
|
const concurrency = input.concurrency ?? 3;
|
|
402
502
|
const delayMs = input.delayMs ?? 0;
|
|
403
503
|
const startTime = Date.now();
|
|
@@ -411,9 +511,11 @@ export async function runFanOutReview(input) {
|
|
|
411
511
|
// ── Step 1: Run lenses with bounded concurrency ─────────────
|
|
412
512
|
const lensTasks = resolvedLenses.map((lens, index) => {
|
|
413
513
|
return async () => {
|
|
414
|
-
// Round-robin generateFn assignment
|
|
514
|
+
// Round-robin generateFn assignment unless pinLensesToFirst pins all to [0].
|
|
415
515
|
const generateFn = resolvedGenerateFns.length > 0
|
|
416
|
-
?
|
|
516
|
+
? input.pinLensesToFirst === true
|
|
517
|
+
? resolvedGenerateFns[0]
|
|
518
|
+
: resolvedGenerateFns[index % resolvedGenerateFns.length]
|
|
417
519
|
: null;
|
|
418
520
|
if (!generateFn) {
|
|
419
521
|
throw new Error(`No generateFn available for lens "${lens.name}" at index ${index}`);
|
|
@@ -432,6 +534,13 @@ export async function runFanOutReview(input) {
|
|
|
432
534
|
.filter(Boolean)
|
|
433
535
|
.join('\n');
|
|
434
536
|
const result = await generateFn(system, userPrompt);
|
|
537
|
+
// A fulfilled call can still be a dead voice (e.g. gateway returned
|
|
538
|
+
// HTTP 200 whose text is a raw CLI error envelope). Route it into the
|
|
539
|
+
// existing rejected/failure path instead of counting it as a lens pass.
|
|
540
|
+
const deadReason = getDeadVoiceReason(result.text);
|
|
541
|
+
if (deadReason) {
|
|
542
|
+
throw new Error(`${lens.label} (${result.provider}/${result.model}): ${deadReason}`);
|
|
543
|
+
}
|
|
435
544
|
return {
|
|
436
545
|
name: lens.name,
|
|
437
546
|
label: lens.label,
|
|
@@ -443,6 +552,35 @@ export async function runFanOutReview(input) {
|
|
|
443
552
|
};
|
|
444
553
|
});
|
|
445
554
|
const results = await runWithConcurrency(lensTasks, { concurrency, delayMs });
|
|
555
|
+
let contrarianResults = [];
|
|
556
|
+
if (typeof contrarianCount === 'number' &&
|
|
557
|
+
Number.isInteger(contrarianCount) &&
|
|
558
|
+
contrarianCount >= 1) {
|
|
559
|
+
const contrarianTasks = Array.from({ length: contrarianCount }, (_, i) => {
|
|
560
|
+
return async () => {
|
|
561
|
+
const generateFn = resolvedGenerateFns[1 + i];
|
|
562
|
+
const system = [CONTRARIAN_SYSTEM, UNTRUSTED_CONTENT_POLICY].join('\n');
|
|
563
|
+
const result = await generateFn(system, userPrompt);
|
|
564
|
+
const deadReason = getDeadVoiceReason(result.text);
|
|
565
|
+
if (deadReason) {
|
|
566
|
+
throw new Error(`Contrarian ${i + 1} (${result.provider}/${result.model}): ${deadReason}`);
|
|
567
|
+
}
|
|
568
|
+
return {
|
|
569
|
+
name: 'contrarian',
|
|
570
|
+
label: `Contrarian ${i + 1}`,
|
|
571
|
+
text: result.text,
|
|
572
|
+
tokensUsed: result.tokensUsed,
|
|
573
|
+
providerUsed: result.provider,
|
|
574
|
+
modelUsed: result.model,
|
|
575
|
+
};
|
|
576
|
+
};
|
|
577
|
+
});
|
|
578
|
+
emit({
|
|
579
|
+
step: 'fan-out-contrarian',
|
|
580
|
+
message: `Launching ${contrarianCount} unlensed contrarian voice(s)`,
|
|
581
|
+
});
|
|
582
|
+
contrarianResults = await runWithConcurrency(contrarianTasks, { concurrency, delayMs });
|
|
583
|
+
}
|
|
446
584
|
// ── Step 2: Collect findings from all lenses ────────────────
|
|
447
585
|
let totalTokens = 0;
|
|
448
586
|
const allFindings = [];
|
|
@@ -468,7 +606,7 @@ export async function runFanOutReview(input) {
|
|
|
468
606
|
}
|
|
469
607
|
allFindings.push(...findings);
|
|
470
608
|
// Track individual lens status
|
|
471
|
-
const statusMatch = /STATUS:\s*(PASSED|FAILED|NEEDS_HUMAN_REVIEW|SKIPPED)/i.exec(result.value.text);
|
|
609
|
+
const statusMatch = /STATUS:\s*(PASSED|FAILED|NEEDS_HUMAN_REVIEW|SKIPPED|INCONCLUSIVE)/i.exec(result.value.text);
|
|
472
610
|
const lensStatus = (statusMatch?.[1]?.toUpperCase() ?? 'NEEDS_HUMAN_REVIEW');
|
|
473
611
|
lensStatuses.push(lensStatus);
|
|
474
612
|
emit({
|
|
@@ -486,15 +624,114 @@ export async function runFanOutReview(input) {
|
|
|
486
624
|
});
|
|
487
625
|
}
|
|
488
626
|
}
|
|
627
|
+
for (let i = 0; i < contrarianResults.length; i++) {
|
|
628
|
+
const result = contrarianResults[i];
|
|
629
|
+
const voiceName = `contrarian-${i + 1}`;
|
|
630
|
+
if (!result)
|
|
631
|
+
continue;
|
|
632
|
+
if (result.status === 'fulfilled') {
|
|
633
|
+
totalTokens += result.value.tokensUsed;
|
|
634
|
+
modelsUsed.push(`${voiceName}:${result.value.providerUsed}/${result.value.modelUsed}`);
|
|
635
|
+
const findings = parseFindingsBlock(result.value.text);
|
|
636
|
+
for (const finding of findings) {
|
|
637
|
+
finding.source = 'ai';
|
|
638
|
+
if (!finding.category.includes('contrarian')) {
|
|
639
|
+
finding.category = 'contrarian';
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
allFindings.push(...findings);
|
|
643
|
+
const statusMatch = /STATUS:\s*(PASSED|FAILED|NEEDS_HUMAN_REVIEW|SKIPPED|INCONCLUSIVE)/i.exec(result.value.text);
|
|
644
|
+
const voiceStatus = (statusMatch?.[1]?.toUpperCase() ?? 'NEEDS_HUMAN_REVIEW');
|
|
645
|
+
lensStatuses.push(voiceStatus);
|
|
646
|
+
emit({
|
|
647
|
+
step: voiceName,
|
|
648
|
+
message: `✓ ${result.value.label} — ${findings.length} finding(s), ${result.value.tokensUsed} tokens`,
|
|
649
|
+
detail: result.value.text,
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
else {
|
|
653
|
+
const reason = result.reason instanceof Error ? result.reason.message : String(result.reason);
|
|
654
|
+
modelsUsed.push(`${voiceName}:FAILED`);
|
|
655
|
+
emit({
|
|
656
|
+
step: voiceName,
|
|
657
|
+
message: `✗ Contrarian ${i + 1} — FAILED: ${reason}`,
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
}
|
|
489
661
|
emit({
|
|
490
662
|
step: 'fan-out-merge',
|
|
491
663
|
message: `Merging ${allFindings.length} findings from ${resolvedLenses.length} lenses...`,
|
|
492
664
|
});
|
|
493
|
-
// ── Step 3: Merge and deduplicate
|
|
494
|
-
|
|
665
|
+
// ── Step 3: Merge and deduplicate, then stamp the ledger ───
|
|
666
|
+
let mergedFindings = stampFindingLedger(mergeFindings(allFindings));
|
|
667
|
+
if (typeof refuterCount === 'number' && Number.isInteger(refuterCount) && refuterCount >= 2) {
|
|
668
|
+
const candidates = mergedFindings.filter((f) => f.severity === 'critical' && f.id);
|
|
669
|
+
if (candidates.length > 0) {
|
|
670
|
+
const contrarianN = typeof contrarianCount === 'number' &&
|
|
671
|
+
Number.isInteger(contrarianCount) &&
|
|
672
|
+
contrarianCount >= 1
|
|
673
|
+
? contrarianCount
|
|
674
|
+
: 0;
|
|
675
|
+
const refuterStart = 1 + contrarianN;
|
|
676
|
+
const candidateBlock = candidates
|
|
677
|
+
.map((c) => [
|
|
678
|
+
`- ID: ${c.id}`,
|
|
679
|
+
` LENS: ${c.lens ?? c.category}`,
|
|
680
|
+
` LOCATION: ${c.location ?? c.file}`,
|
|
681
|
+
` SEVERITY: ${c.severity}`,
|
|
682
|
+
` EVIDENCE: ${c.evidence ?? c.message}`,
|
|
683
|
+
].join('\n'))
|
|
684
|
+
.join('\n');
|
|
685
|
+
const refuterUser = `${userPrompt}\n\nCANDIDATES:\n${candidateBlock}`;
|
|
686
|
+
const refuterSystem = [REFUTER_SYSTEM, UNTRUSTED_CONTENT_POLICY].join('\n');
|
|
687
|
+
const refuteVotes = new Map();
|
|
688
|
+
for (const candidate of candidates) {
|
|
689
|
+
if (candidate.id)
|
|
690
|
+
refuteVotes.set(candidate.id, 0);
|
|
691
|
+
}
|
|
692
|
+
const refuterTasks = Array.from({ length: refuterCount }, (_, i) => {
|
|
693
|
+
return async () => {
|
|
694
|
+
const generateFn = resolvedGenerateFns[refuterStart + i];
|
|
695
|
+
const result = await generateFn(refuterSystem, refuterUser);
|
|
696
|
+
const deadReason = getDeadVoiceReason(result.text);
|
|
697
|
+
if (deadReason) {
|
|
698
|
+
throw new Error(`Refuter ${i + 1} (${result.provider}/${result.model}): ${deadReason}`);
|
|
699
|
+
}
|
|
700
|
+
return result;
|
|
701
|
+
};
|
|
702
|
+
});
|
|
703
|
+
emit({
|
|
704
|
+
step: 'fan-out-refuter',
|
|
705
|
+
message: `Launching ${refuterCount} batched refuter voice(s) on ${candidates.length} critical finding(s)`,
|
|
706
|
+
});
|
|
707
|
+
const refuterResults = await runWithConcurrency(refuterTasks, { concurrency, delayMs });
|
|
708
|
+
for (const result of refuterResults) {
|
|
709
|
+
if (result.status !== 'fulfilled')
|
|
710
|
+
continue;
|
|
711
|
+
totalTokens += result.value.tokensUsed;
|
|
712
|
+
const verdicts = parseRefuterVerdicts(result.value.text);
|
|
713
|
+
for (const candidate of candidates) {
|
|
714
|
+
if (!candidate.id)
|
|
715
|
+
continue;
|
|
716
|
+
if (verdicts.get(candidate.id) === 'refute') {
|
|
717
|
+
refuteVotes.set(candidate.id, (refuteVotes.get(candidate.id) ?? 0) + 1);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
mergedFindings = mergedFindings.map((finding) => {
|
|
722
|
+
if (finding.severity !== 'critical' || !finding.id)
|
|
723
|
+
return finding;
|
|
724
|
+
const votes = refuteVotes.get(finding.id) ?? 0;
|
|
725
|
+
if (votes >= 2) {
|
|
726
|
+
return { ...finding, ledgerStatus: FINDING_LEDGER_STATUS.refuted };
|
|
727
|
+
}
|
|
728
|
+
return finding;
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
}
|
|
495
732
|
// ── Step 4: Determine overall status ────────────────────────
|
|
496
|
-
const hasCritical = mergedFindings.some((f) => f.severity === 'critical');
|
|
497
|
-
const highCount = mergedFindings.filter((f) => f.severity === 'high').length;
|
|
733
|
+
const hasCritical = mergedFindings.some((f) => f.severity === 'critical' && f.ledgerStatus !== FINDING_LEDGER_STATUS.refuted);
|
|
734
|
+
const highCount = mergedFindings.filter((f) => f.severity === 'high' && f.ledgerStatus !== FINDING_LEDGER_STATUS.refuted).length;
|
|
498
735
|
const anyFailed = lensStatuses.includes('FAILED');
|
|
499
736
|
let status;
|
|
500
737
|
if (hasCritical || highCount >= 3) {
|
|
@@ -517,7 +754,7 @@ export async function runFanOutReview(input) {
|
|
|
517
754
|
});
|
|
518
755
|
const summary = mergedFindings.length > 0
|
|
519
756
|
? `Fan-out review with ${resolvedLenses.length} lenses found ${mergedFindings.length} unique finding(s). Lenses: ${lensSummaryParts.join(', ')}.`
|
|
520
|
-
: `Fan-out review with ${resolvedLenses.length} lenses found no issues.
|
|
757
|
+
: `Fan-out review with ${resolvedLenses.length} lenses found no issues. Lenses: ${lensSummaryParts.join(', ')}.`;
|
|
521
758
|
return {
|
|
522
759
|
status,
|
|
523
760
|
summary,
|