clud-bug 0.7.0-rc.2 → 0.7.0-rc.21
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/README.md +20 -0
- package/data/canonical-v1.json +37 -0
- package/dist/cli/configure-github.d.ts +58 -0
- package/dist/cli/configure-github.d.ts.map +1 -0
- package/dist/cli/configure-github.js +242 -0
- package/dist/cli/configure-github.js.map +1 -0
- package/dist/cli/hooks.d.ts +51 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +138 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +1 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +949 -35
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/post-check-run.d.ts +16 -0
- package/dist/cli/post-check-run.d.ts.map +1 -0
- package/dist/cli/post-check-run.js +93 -0
- package/dist/cli/post-check-run.js.map +1 -0
- package/dist/cli/review-prompt.d.ts +43 -0
- package/dist/cli/review-prompt.d.ts.map +1 -0
- package/dist/cli/review-prompt.js +287 -0
- package/dist/cli/review-prompt.js.map +1 -0
- package/dist/cli/skills.d.ts +7 -0
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +42 -2
- package/dist/cli/skills.js.map +1 -1
- package/dist/cli/update-notifier.d.ts +17 -0
- package/dist/cli/update-notifier.d.ts.map +1 -0
- package/dist/cli/update-notifier.js +88 -0
- package/dist/cli/update-notifier.js.map +1 -0
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +60 -11
- package/dist/cli/update.js.map +1 -1
- package/dist/core/auto-resolve.d.ts +235 -0
- package/dist/core/auto-resolve.d.ts.map +1 -0
- package/dist/core/auto-resolve.js +293 -0
- package/dist/core/auto-resolve.js.map +1 -0
- package/dist/core/budget-plan.d.ts +125 -0
- package/dist/core/budget-plan.d.ts.map +1 -0
- package/dist/core/budget-plan.js +211 -0
- package/dist/core/budget-plan.js.map +1 -0
- package/dist/core/check-verdict.d.ts +31 -0
- package/dist/core/check-verdict.d.ts.map +1 -0
- package/dist/core/check-verdict.js +66 -0
- package/dist/core/check-verdict.js.map +1 -0
- package/dist/core/configure-github.d.ts +179 -0
- package/dist/core/configure-github.d.ts.map +1 -0
- package/dist/core/configure-github.js +289 -0
- package/dist/core/configure-github.js.map +1 -0
- package/dist/core/design.d.ts +37 -0
- package/dist/core/design.d.ts.map +1 -0
- package/dist/core/design.js +47 -0
- package/dist/core/design.js.map +1 -0
- package/dist/core/diff-findings.d.ts +96 -0
- package/dist/core/diff-findings.d.ts.map +1 -0
- package/dist/core/diff-findings.js +261 -0
- package/dist/core/diff-findings.js.map +1 -0
- package/dist/core/formal-review.d.ts +79 -0
- package/dist/core/formal-review.d.ts.map +1 -0
- package/dist/core/formal-review.js +71 -0
- package/dist/core/formal-review.js.map +1 -0
- package/dist/core/index.d.ts +15 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +53 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/inline-threads.d.ts +160 -0
- package/dist/core/inline-threads.d.ts.map +1 -0
- package/dist/core/inline-threads.js +369 -0
- package/dist/core/inline-threads.js.map +1 -0
- package/dist/core/multi-pass-aggregate.d.ts +161 -0
- package/dist/core/multi-pass-aggregate.d.ts.map +1 -0
- package/dist/core/multi-pass-aggregate.js +457 -0
- package/dist/core/multi-pass-aggregate.js.map +1 -0
- package/dist/core/plan-review.d.ts +57 -0
- package/dist/core/plan-review.d.ts.map +1 -0
- package/dist/core/plan-review.js +77 -0
- package/dist/core/plan-review.js.map +1 -0
- package/dist/core/prompt-builder.d.ts +18 -0
- package/dist/core/prompt-builder.d.ts.map +1 -1
- package/dist/core/prompt-builder.js +24 -2
- package/dist/core/prompt-builder.js.map +1 -1
- package/dist/core/render.d.ts.map +1 -1
- package/dist/core/render.js +1 -19
- package/dist/core/render.js.map +1 -1
- package/dist/core/resolve-verifier.d.ts +53 -0
- package/dist/core/resolve-verifier.d.ts.map +1 -0
- package/dist/core/resolve-verifier.js +204 -0
- package/dist/core/resolve-verifier.js.map +1 -0
- package/dist/core/review-context.d.ts +39 -0
- package/dist/core/review-context.d.ts.map +1 -0
- package/dist/core/review-context.js +99 -0
- package/dist/core/review-context.js.map +1 -0
- package/dist/core/review-plan.d.ts +219 -0
- package/dist/core/review-plan.d.ts.map +1 -0
- package/dist/core/review-plan.js +274 -0
- package/dist/core/review-plan.js.map +1 -0
- package/dist/core/review-writeback.d.ts +74 -0
- package/dist/core/review-writeback.d.ts.map +1 -1
- package/dist/core/review-writeback.js +71 -4
- package/dist/core/review-writeback.js.map +1 -1
- package/dist/core/skills.d.ts +25 -0
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +100 -4
- package/dist/core/skills.js.map +1 -1
- package/dist/core/version.d.ts +2 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +4 -0
- package/dist/core/version.js.map +1 -0
- package/package.json +11 -5
- package/src/cli/configure-github.ts +329 -0
- package/src/cli/hooks.ts +155 -0
- package/src/cli/index.ts +6 -0
- package/src/cli/main.ts +1031 -37
- package/src/cli/post-check-run.ts +115 -0
- package/src/cli/review-prompt.ts +355 -0
- package/src/cli/skills.ts +42 -2
- package/src/cli/update-notifier.ts +100 -0
- package/src/cli/update.ts +60 -11
- package/src/core/auto-resolve.ts +488 -0
- package/src/core/budget-plan.ts +324 -0
- package/src/core/check-verdict.ts +93 -0
- package/src/core/configure-github.ts +497 -0
- package/src/core/design.ts +73 -0
- package/src/core/diff-findings.ts +323 -0
- package/src/core/formal-review.ts +168 -0
- package/src/core/index.ts +188 -0
- package/src/core/inline-threads.ts +471 -0
- package/src/core/multi-pass-aggregate.ts +591 -0
- package/src/core/plan-review.ts +136 -0
- package/src/core/prompt-builder.ts +44 -2
- package/src/core/render.ts +10 -16
- package/src/core/resolve-verifier.ts +254 -0
- package/src/core/review-context.ts +106 -0
- package/src/core/review-plan.ts +485 -0
- package/src/core/review-writeback.ts +161 -4
- package/src/core/skills.ts +128 -5
- package/src/core/version.ts +3 -0
- package/templates/clud-bug-review.md.tmpl +115 -0
- package/templates/skills/design/design-system-consistency.md +41 -0
- package/templates/skills/design/frontend-a11y.md +41 -0
- package/templates/skills/design/visual-polish.md +41 -0
- package/templates/workflow-py.yml.tmpl +92 -2
- package/templates/workflow-ts.yml.tmpl +92 -2
- package/templates/workflow.yml.tmpl +173 -2
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import type { ReviewRole } from './review-plan.js';
|
|
2
|
+
import { type Finding, type Review } from './review-schema-zod.js';
|
|
3
|
+
import type { Consensus, MultiPassReview, PassAttribution, ReviewPassMode, UnifiedFinding } from './review-writeback.js';
|
|
4
|
+
/**
|
|
5
|
+
* Multi-pass aggregator.
|
|
6
|
+
*
|
|
7
|
+
* Takes N passes' review outputs + the active mode + the role definitions
|
|
8
|
+
* and produces a single unified `MultiPassReview` payload the renderer can
|
|
9
|
+
* format with per-pass attribution inline.
|
|
10
|
+
*
|
|
11
|
+
* The three modes are NOT interchangeable in their output shape — see the
|
|
12
|
+
* per-mode comments below.
|
|
13
|
+
*
|
|
14
|
+
* Design discipline:
|
|
15
|
+
* - Pure function. No I/O, no AI calls. Input = N validated reviews +
|
|
16
|
+
* metadata; output = aggregated findings list.
|
|
17
|
+
* - Order-stable. The renderer needs a deterministic finding order so the
|
|
18
|
+
* comment is stable across re-reviews (matters for thread continuity in
|
|
19
|
+
* D.2.6). We preserve Pass 1's order, then append later-pass findings.
|
|
20
|
+
* - Match semantics live here. Two findings are "the same" if their
|
|
21
|
+
* (file, line, skill) tuple matches. Summaries diverge stylistically
|
|
22
|
+
* between passes; key matching on summary is too brittle.
|
|
23
|
+
* - Resolution rules:
|
|
24
|
+
* cross-check → Pass 2 explicitly classified Pass-1 findings as
|
|
25
|
+
* agreed/disagreed via the cross-check schema; we use
|
|
26
|
+
* its verdict verbatim.
|
|
27
|
+
* consensus → Pass 2 ran independent. Same-tuple findings across
|
|
28
|
+
* passes are marked `agreed`; tuple-unique findings are
|
|
29
|
+
* attributed to their pass with provenance.
|
|
30
|
+
* independent → No merging. We emit a flat list with one entry per
|
|
31
|
+
* (pass, finding) — the renderer formats them as a
|
|
32
|
+
* side-by-side review block.
|
|
33
|
+
*
|
|
34
|
+
* The orchestrator owns the AI call orchestration upstream. This module just
|
|
35
|
+
* deals with shapes — call it once per skill (or once per shared bundle).
|
|
36
|
+
*
|
|
37
|
+
* Ported from clud-bug-app/lib/multi-pass-aggregator.ts. The result types
|
|
38
|
+
* (`MultiPassReview`, `UnifiedFinding`, `PassAttribution`, `PassSource`,
|
|
39
|
+
* `ReviewPassMode`) live in `./review-writeback.ts` and are imported here so
|
|
40
|
+
* core has a single declaration for each. The aggregator-internal contracts
|
|
41
|
+
* (`PassSource` is shared; `Consensus`, `CrossCheckVerdict`,
|
|
42
|
+
* `CrossCheckPassResult`, `AggregateInput`) are defined below.
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* Derive the SPEC §6.10.1 consensus marker from a finding's per-pass
|
|
46
|
+
* attribution list. Mapping rules:
|
|
47
|
+
*
|
|
48
|
+
* - any source === 'agreed' → '2-of-2' (consensus reached)
|
|
49
|
+
* - any source === 'disagreed' → 'arbitrated' (cross-check produced
|
|
50
|
+
* active dissent; the finding still made it through, which is the
|
|
51
|
+
* arbitration outcome we model today — see Consensus type doc)
|
|
52
|
+
* - otherwise (just 'first' / 'independent') → '1-of-N' (single-pass)
|
|
53
|
+
*
|
|
54
|
+
* Priority order: agreed > disagreed > default. If a finding has BOTH
|
|
55
|
+
* an `agreed` and a `disagreed` attribution (e.g., 3-pass setup with
|
|
56
|
+
* Pass 2 agreed + Pass 3 disagreed), `agreed` wins — at least one pass
|
|
57
|
+
* cross-validated the finding, so the gate has consensus.
|
|
58
|
+
*/
|
|
59
|
+
export declare function deriveConsensus(attributions: PassAttribution[]): Consensus;
|
|
60
|
+
/**
|
|
61
|
+
* The cross-check pass returns:
|
|
62
|
+
* - One verdict per Pass-1 finding (agreed / disagreed + rationale).
|
|
63
|
+
* - A list of independently-discovered findings (same shape as Finding).
|
|
64
|
+
*
|
|
65
|
+
* We define the response shape here (not in review-schema-zod.ts) because
|
|
66
|
+
* it's an aggregator-internal contract. The orchestrator uses
|
|
67
|
+
* `crossCheckSchema` (from review-schema-zod) for the AI call output type.
|
|
68
|
+
*/
|
|
69
|
+
export interface CrossCheckVerdict {
|
|
70
|
+
/** 0-indexed reference to the Pass-1 finding being judged. */
|
|
71
|
+
pass1Index: number;
|
|
72
|
+
/** Pass 2's verdict. */
|
|
73
|
+
verdict: 'agreed' | 'disagreed';
|
|
74
|
+
/** One-line rationale shown inline. Optional but recommended. */
|
|
75
|
+
rationale?: string;
|
|
76
|
+
}
|
|
77
|
+
export interface CrossCheckPassResult {
|
|
78
|
+
/** Per-Pass-1-finding judgements. */
|
|
79
|
+
verdicts: CrossCheckVerdict[];
|
|
80
|
+
/** Newly-discovered findings, independent of Pass 1's list. */
|
|
81
|
+
independentFindings: Finding[];
|
|
82
|
+
}
|
|
83
|
+
export interface AggregateInput {
|
|
84
|
+
/** Mode driving the merge. */
|
|
85
|
+
mode: ReviewPassMode;
|
|
86
|
+
/** Pass 1's review. Required — at minimum we need one pass. */
|
|
87
|
+
firstPass: Review;
|
|
88
|
+
/**
|
|
89
|
+
* Subsequent passes. Shape depends on mode:
|
|
90
|
+
* - cross-check: each entry has `crossCheck` populated; `review` may be
|
|
91
|
+
* omitted (the cross-check pass doesn't produce a full review object).
|
|
92
|
+
* - consensus / independent: each entry has `review` populated; the
|
|
93
|
+
* `crossCheck` field is ignored.
|
|
94
|
+
*/
|
|
95
|
+
subsequentPasses: Array<{
|
|
96
|
+
/** 1-indexed pass number, starting at 2. */
|
|
97
|
+
passNumber: number;
|
|
98
|
+
/** Role label + model used. */
|
|
99
|
+
role: ReviewRole;
|
|
100
|
+
/** Cross-check response (only valid when mode === 'cross-check'). */
|
|
101
|
+
crossCheck?: CrossCheckPassResult;
|
|
102
|
+
/** Full review (for consensus / independent modes). */
|
|
103
|
+
review?: Review;
|
|
104
|
+
}>;
|
|
105
|
+
/** Role assigned to Pass 1 — needed for attribution headers. */
|
|
106
|
+
firstPassRole: ReviewRole;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Merges the per-pass results into a single MultiPassReview.
|
|
110
|
+
*/
|
|
111
|
+
export declare function aggregatePasses(input: AggregateInput): MultiPassReview;
|
|
112
|
+
export interface EscalationInput {
|
|
113
|
+
/** Active aggregation mode — escalation only applies to cross-check. */
|
|
114
|
+
mode: ReviewPassMode;
|
|
115
|
+
/** Resolved pass count — escalation only when the plan ran exactly 2. */
|
|
116
|
+
passCount: number;
|
|
117
|
+
/** Pass 1's review; its findings are indexed by the cross-check verdicts. */
|
|
118
|
+
firstPass: Review;
|
|
119
|
+
/** Subsequent passes — the cross-check verdicts live here. */
|
|
120
|
+
subsequentPasses: AggregateInput['subsequentPasses'];
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* 6c arbiter gate (SPEC §6.10.1 `arbitrated`). Returns true when a 2-pass
|
|
124
|
+
* cross-check disagreed on a gate-relevant (`critical` | `minor`) Pass-1
|
|
125
|
+
* finding — the only case worth spending a 3rd Mantis arbiter pass on. Pure:
|
|
126
|
+
* it reads the verdicts Pass 2 already produced; no I/O, no AI call.
|
|
127
|
+
*
|
|
128
|
+
* Scope rationale:
|
|
129
|
+
* - cross-check only — `consensus` already runs Mantis as its final pass and
|
|
130
|
+
* `independent` has no arbiter; both return false.
|
|
131
|
+
* - `passCount === 2` (not `>= 2`) — a statically-configured 3-pass
|
|
132
|
+
* cross-check already runs Mantis as pass 3 via the loop, so escalating
|
|
133
|
+
* there would stack a redundant 4th pass past MAX_PASSES.
|
|
134
|
+
* - severity `critical | minor` — a `preexisting` dispute can never flip the
|
|
135
|
+
* merge gate, so it doesn't earn an Opus-class arbiter.
|
|
136
|
+
*
|
|
137
|
+
* Authority is marker-only: the arbiter's verdict sets the disputed finding's
|
|
138
|
+
* consensus marker + rationale; it does not change which findings gate the
|
|
139
|
+
* merge (that stays `resolveVerdict`'s job).
|
|
140
|
+
*/
|
|
141
|
+
export declare function shouldEscalate(input: EscalationInput): boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Resolves the APPROVE / REQUEST_CHANGES verdict per the SPEC §1.8.5 table:
|
|
144
|
+
*
|
|
145
|
+
* mode | request_changes when…
|
|
146
|
+
* --------------+------------------------------------------------------
|
|
147
|
+
* strict (=cross-check default) | ANY pass flagged critical
|
|
148
|
+
* consensus | ≥2 passes flagged the same critical tuple
|
|
149
|
+
* independent | findings side-by-side — human decides per finding.
|
|
150
|
+
* | For automation purposes we treat ANY critical as
|
|
151
|
+
* | request_changes (safer default; humans can downgrade).
|
|
152
|
+
*
|
|
153
|
+
* We expose this both as a return field on `MultiPassReview.verdict` and
|
|
154
|
+
* separately (for tests + future D.2 wiring) as `resolveVerdict`.
|
|
155
|
+
*
|
|
156
|
+
* NOTE: The broader D.2 phase wires APPROVE/REQUEST_CHANGES into actual
|
|
157
|
+
* PR check states. D.2.5 only computes the verdict — surfacing it is left
|
|
158
|
+
* to the renderer (which prefixes the header line with the verdict label).
|
|
159
|
+
*/
|
|
160
|
+
export declare function resolveVerdict(mode: ReviewPassMode, findings: UnifiedFinding[], passCount: number): MultiPassReview['verdict'];
|
|
161
|
+
//# sourceMappingURL=multi-pass-aggregate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-pass-aggregate.d.ts","sourceRoot":"","sources":["../../src/core/multi-pass-aggregate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAEL,KAAK,OAAO,EACZ,KAAK,MAAM,EAEZ,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,eAAe,EAEf,cAAc,EACd,cAAc,EACf,MAAM,uBAAuB,CAAC;AAE/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAUH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,eAAe,EAAE,GAAG,SAAS,CAO1E;AAWD;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,wBAAwB;IACxB,OAAO,EAAE,QAAQ,GAAG,WAAW,CAAC;IAChC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,+DAA+D;IAC/D,mBAAmB,EAAE,OAAO,EAAE,CAAC;CAChC;AAMD,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,IAAI,EAAE,cAAc,CAAC;IACrB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,gBAAgB,EAAE,KAAK,CAAC;QACtB,4CAA4C;QAC5C,UAAU,EAAE,MAAM,CAAC;QACnB,+BAA+B;QAC/B,IAAI,EAAE,UAAU,CAAC;QACjB,qEAAqE;QACrE,UAAU,CAAC,EAAE,oBAAoB,CAAC;QAClC,uDAAuD;QACvD,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,gEAAgE;IAChE,aAAa,EAAE,UAAU,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CAStE;AAMD,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,IAAI,EAAE,cAAc,CAAC;IACrB,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,gBAAgB,EAAE,cAAc,CAAC,kBAAkB,CAAC,CAAC;CACtD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAU9D;AA2UD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,cAAc,EAAE,EAC1B,SAAS,EAAE,MAAM,GAChB,eAAe,CAAC,SAAS,CAAC,CA0B5B"}
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
import { flattenFindings, } from './review-schema-zod.js';
|
|
2
|
+
/**
|
|
3
|
+
* Multi-pass aggregator.
|
|
4
|
+
*
|
|
5
|
+
* Takes N passes' review outputs + the active mode + the role definitions
|
|
6
|
+
* and produces a single unified `MultiPassReview` payload the renderer can
|
|
7
|
+
* format with per-pass attribution inline.
|
|
8
|
+
*
|
|
9
|
+
* The three modes are NOT interchangeable in their output shape — see the
|
|
10
|
+
* per-mode comments below.
|
|
11
|
+
*
|
|
12
|
+
* Design discipline:
|
|
13
|
+
* - Pure function. No I/O, no AI calls. Input = N validated reviews +
|
|
14
|
+
* metadata; output = aggregated findings list.
|
|
15
|
+
* - Order-stable. The renderer needs a deterministic finding order so the
|
|
16
|
+
* comment is stable across re-reviews (matters for thread continuity in
|
|
17
|
+
* D.2.6). We preserve Pass 1's order, then append later-pass findings.
|
|
18
|
+
* - Match semantics live here. Two findings are "the same" if their
|
|
19
|
+
* (file, line, skill) tuple matches. Summaries diverge stylistically
|
|
20
|
+
* between passes; key matching on summary is too brittle.
|
|
21
|
+
* - Resolution rules:
|
|
22
|
+
* cross-check → Pass 2 explicitly classified Pass-1 findings as
|
|
23
|
+
* agreed/disagreed via the cross-check schema; we use
|
|
24
|
+
* its verdict verbatim.
|
|
25
|
+
* consensus → Pass 2 ran independent. Same-tuple findings across
|
|
26
|
+
* passes are marked `agreed`; tuple-unique findings are
|
|
27
|
+
* attributed to their pass with provenance.
|
|
28
|
+
* independent → No merging. We emit a flat list with one entry per
|
|
29
|
+
* (pass, finding) — the renderer formats them as a
|
|
30
|
+
* side-by-side review block.
|
|
31
|
+
*
|
|
32
|
+
* The orchestrator owns the AI call orchestration upstream. This module just
|
|
33
|
+
* deals with shapes — call it once per skill (or once per shared bundle).
|
|
34
|
+
*
|
|
35
|
+
* Ported from clud-bug-app/lib/multi-pass-aggregator.ts. The result types
|
|
36
|
+
* (`MultiPassReview`, `UnifiedFinding`, `PassAttribution`, `PassSource`,
|
|
37
|
+
* `ReviewPassMode`) live in `./review-writeback.ts` and are imported here so
|
|
38
|
+
* core has a single declaration for each. The aggregator-internal contracts
|
|
39
|
+
* (`PassSource` is shared; `Consensus`, `CrossCheckVerdict`,
|
|
40
|
+
* `CrossCheckPassResult`, `AggregateInput`) are defined below.
|
|
41
|
+
*/
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Public types
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// `Consensus` (the SPEC §6.10.1 marker) is defined in `./review-writeback.ts`
|
|
46
|
+
// alongside `UnifiedFinding` and imported above — core keeps a single
|
|
47
|
+
// declaration so it rides on `MultiPassReview.findings[].consensus`.
|
|
48
|
+
/**
|
|
49
|
+
* Derive the SPEC §6.10.1 consensus marker from a finding's per-pass
|
|
50
|
+
* attribution list. Mapping rules:
|
|
51
|
+
*
|
|
52
|
+
* - any source === 'agreed' → '2-of-2' (consensus reached)
|
|
53
|
+
* - any source === 'disagreed' → 'arbitrated' (cross-check produced
|
|
54
|
+
* active dissent; the finding still made it through, which is the
|
|
55
|
+
* arbitration outcome we model today — see Consensus type doc)
|
|
56
|
+
* - otherwise (just 'first' / 'independent') → '1-of-N' (single-pass)
|
|
57
|
+
*
|
|
58
|
+
* Priority order: agreed > disagreed > default. If a finding has BOTH
|
|
59
|
+
* an `agreed` and a `disagreed` attribution (e.g., 3-pass setup with
|
|
60
|
+
* Pass 2 agreed + Pass 3 disagreed), `agreed` wins — at least one pass
|
|
61
|
+
* cross-validated the finding, so the gate has consensus.
|
|
62
|
+
*/
|
|
63
|
+
export function deriveConsensus(attributions) {
|
|
64
|
+
let sawDisagreed = false;
|
|
65
|
+
for (const a of attributions) {
|
|
66
|
+
if (a.source === 'agreed')
|
|
67
|
+
return '2-of-2';
|
|
68
|
+
if (a.source === 'disagreed')
|
|
69
|
+
sawDisagreed = true;
|
|
70
|
+
}
|
|
71
|
+
return sawDisagreed ? 'arbitrated' : '1-of-N';
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Merges the per-pass results into a single MultiPassReview.
|
|
75
|
+
*/
|
|
76
|
+
export function aggregatePasses(input) {
|
|
77
|
+
switch (input.mode) {
|
|
78
|
+
case 'cross-check':
|
|
79
|
+
return aggregateCrossCheck(input);
|
|
80
|
+
case 'consensus':
|
|
81
|
+
return aggregateConsensus(input);
|
|
82
|
+
case 'independent':
|
|
83
|
+
return aggregateIndependent(input);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 6c arbiter gate (SPEC §6.10.1 `arbitrated`). Returns true when a 2-pass
|
|
88
|
+
* cross-check disagreed on a gate-relevant (`critical` | `minor`) Pass-1
|
|
89
|
+
* finding — the only case worth spending a 3rd Mantis arbiter pass on. Pure:
|
|
90
|
+
* it reads the verdicts Pass 2 already produced; no I/O, no AI call.
|
|
91
|
+
*
|
|
92
|
+
* Scope rationale:
|
|
93
|
+
* - cross-check only — `consensus` already runs Mantis as its final pass and
|
|
94
|
+
* `independent` has no arbiter; both return false.
|
|
95
|
+
* - `passCount === 2` (not `>= 2`) — a statically-configured 3-pass
|
|
96
|
+
* cross-check already runs Mantis as pass 3 via the loop, so escalating
|
|
97
|
+
* there would stack a redundant 4th pass past MAX_PASSES.
|
|
98
|
+
* - severity `critical | minor` — a `preexisting` dispute can never flip the
|
|
99
|
+
* merge gate, so it doesn't earn an Opus-class arbiter.
|
|
100
|
+
*
|
|
101
|
+
* Authority is marker-only: the arbiter's verdict sets the disputed finding's
|
|
102
|
+
* consensus marker + rationale; it does not change which findings gate the
|
|
103
|
+
* merge (that stays `resolveVerdict`'s job).
|
|
104
|
+
*/
|
|
105
|
+
export function shouldEscalate(input) {
|
|
106
|
+
if (input.mode !== 'cross-check' || input.passCount !== 2)
|
|
107
|
+
return false;
|
|
108
|
+
const pass1 = flattenFindings(input.firstPass);
|
|
109
|
+
return input.subsequentPasses.some((pass) => (pass.crossCheck?.verdicts ?? []).some((v) => {
|
|
110
|
+
if (v.verdict !== 'disagreed')
|
|
111
|
+
return false;
|
|
112
|
+
const severity = pass1[v.pass1Index]?.severity;
|
|
113
|
+
return severity === 'critical' || severity === 'minor';
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// Mode: cross-check
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
/**
|
|
120
|
+
* Cross-check: Pass 2 saw Pass 1's findings + the diff. Each Pass-1 finding
|
|
121
|
+
* gets a per-pass-2 verdict; Pass 2's independent findings are appended.
|
|
122
|
+
*
|
|
123
|
+
* Output order:
|
|
124
|
+
* 1. Pass-1 findings in original order, each with their pass-2 verdict
|
|
125
|
+
* attribution attached (one PassAttribution for Pass 1, one for Pass 2
|
|
126
|
+
* if applicable, etc.).
|
|
127
|
+
* 2. Pass-2 (and beyond) independent findings, in pass order.
|
|
128
|
+
*/
|
|
129
|
+
function aggregateCrossCheck(input) {
|
|
130
|
+
const findings = [];
|
|
131
|
+
const firstRoleAttribution = (_f, source = 'first') => ({
|
|
132
|
+
passNumber: 1,
|
|
133
|
+
roleName: input.firstPassRole.name,
|
|
134
|
+
model: input.firstPassRole.model,
|
|
135
|
+
source,
|
|
136
|
+
});
|
|
137
|
+
// Initialize the unified list with Pass 1's findings. Wire-shape Review
|
|
138
|
+
// splits findings across 3 severity arrays; flatten to internal Finding[].
|
|
139
|
+
for (const f of flattenFindings(input.firstPass)) {
|
|
140
|
+
findings.push({
|
|
141
|
+
...f,
|
|
142
|
+
attributions: [firstRoleAttribution(f)],
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
// Layer in each subsequent pass's verdicts + independent findings.
|
|
146
|
+
for (const pass of input.subsequentPasses) {
|
|
147
|
+
if (!pass.crossCheck)
|
|
148
|
+
continue; // mis-configured input; skip cleanly
|
|
149
|
+
// 1. Verdicts on Pass-1 findings — attach a PassAttribution per verdict.
|
|
150
|
+
for (const v of pass.crossCheck.verdicts) {
|
|
151
|
+
const target = findings[v.pass1Index];
|
|
152
|
+
if (!target)
|
|
153
|
+
continue; // out-of-range index — ignore
|
|
154
|
+
target.attributions.push({
|
|
155
|
+
passNumber: pass.passNumber,
|
|
156
|
+
roleName: pass.role.name,
|
|
157
|
+
model: pass.role.model,
|
|
158
|
+
source: v.verdict,
|
|
159
|
+
// exactOptionalPropertyTypes: omit `note` entirely when the pass
|
|
160
|
+
// supplied no rationale (vs. setting it to `undefined`). Behavior is
|
|
161
|
+
// identical for every consumer (renderer/tests read `note` only when
|
|
162
|
+
// present); the App relied on a looser tsconfig where `note:
|
|
163
|
+
// undefined` was allowed.
|
|
164
|
+
...(v.rationale !== undefined ? { note: v.rationale } : {}),
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
// 2. Independent findings — append with provenance.
|
|
168
|
+
for (const f of pass.crossCheck.independentFindings) {
|
|
169
|
+
findings.push({
|
|
170
|
+
...f,
|
|
171
|
+
attributions: [
|
|
172
|
+
{
|
|
173
|
+
passNumber: pass.passNumber,
|
|
174
|
+
roleName: pass.role.name,
|
|
175
|
+
model: pass.role.model,
|
|
176
|
+
source: 'independent',
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return finalize({
|
|
183
|
+
mode: 'cross-check',
|
|
184
|
+
findings,
|
|
185
|
+
firstPassRole: input.firstPassRole,
|
|
186
|
+
subsequentPasses: input.subsequentPasses,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
// ---------------------------------------------------------------------------
|
|
190
|
+
// Mode: consensus
|
|
191
|
+
// ---------------------------------------------------------------------------
|
|
192
|
+
/**
|
|
193
|
+
* Consensus: every pass ran fully independent of the others. We diff the
|
|
194
|
+
* passes pairwise and label same-tuple findings as `agreed` (intersection)
|
|
195
|
+
* and tuple-unique findings as `first` / `independent` per pass.
|
|
196
|
+
*
|
|
197
|
+
* Output order:
|
|
198
|
+
* 1. Pass 1's findings in original order (each enriched with `agreed`
|
|
199
|
+
* attributions if other passes also raised the same tuple).
|
|
200
|
+
* 2. Tuple-unique findings from later passes, in pass-number order.
|
|
201
|
+
*/
|
|
202
|
+
function aggregateConsensus(input) {
|
|
203
|
+
const findings = [];
|
|
204
|
+
// Index Pass 1's findings by tuple → list index.
|
|
205
|
+
const tupleToIndex = new Map();
|
|
206
|
+
flattenFindings(input.firstPass).forEach((f, i) => {
|
|
207
|
+
findings.push({
|
|
208
|
+
...f,
|
|
209
|
+
attributions: [
|
|
210
|
+
{
|
|
211
|
+
passNumber: 1,
|
|
212
|
+
roleName: input.firstPassRole.name,
|
|
213
|
+
model: input.firstPassRole.model,
|
|
214
|
+
source: 'first',
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
});
|
|
218
|
+
tupleToIndex.set(tupleKey(f), i);
|
|
219
|
+
});
|
|
220
|
+
for (const pass of input.subsequentPasses) {
|
|
221
|
+
if (!pass.review)
|
|
222
|
+
continue;
|
|
223
|
+
for (const f of flattenFindings(pass.review)) {
|
|
224
|
+
const key = tupleKey(f);
|
|
225
|
+
const existingIndex = tupleToIndex.get(key);
|
|
226
|
+
if (existingIndex !== undefined) {
|
|
227
|
+
// Same-tuple match → consensus. Append an "agreed" attribution.
|
|
228
|
+
const target = findings[existingIndex];
|
|
229
|
+
if (!target)
|
|
230
|
+
continue;
|
|
231
|
+
target.attributions.push({
|
|
232
|
+
passNumber: pass.passNumber,
|
|
233
|
+
roleName: pass.role.name,
|
|
234
|
+
model: pass.role.model,
|
|
235
|
+
source: 'agreed',
|
|
236
|
+
});
|
|
237
|
+
// Promote severity if this pass flagged it higher (e.g. Pass 1 minor,
|
|
238
|
+
// Pass 2 critical — we keep the more conservative critical).
|
|
239
|
+
if (severityRank(f.severity) > severityRank(target.severity)) {
|
|
240
|
+
target.severity = f.severity;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
// New tuple — append + index for future passes.
|
|
245
|
+
const newIdx = findings.length;
|
|
246
|
+
findings.push({
|
|
247
|
+
...f,
|
|
248
|
+
attributions: [
|
|
249
|
+
{
|
|
250
|
+
passNumber: pass.passNumber,
|
|
251
|
+
roleName: pass.role.name,
|
|
252
|
+
model: pass.role.model,
|
|
253
|
+
source: 'independent',
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
});
|
|
257
|
+
tupleToIndex.set(key, newIdx);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return finalize({
|
|
262
|
+
mode: 'consensus',
|
|
263
|
+
findings,
|
|
264
|
+
firstPassRole: input.firstPassRole,
|
|
265
|
+
subsequentPasses: input.subsequentPasses,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
// ---------------------------------------------------------------------------
|
|
269
|
+
// Mode: independent
|
|
270
|
+
// ---------------------------------------------------------------------------
|
|
271
|
+
/**
|
|
272
|
+
* Independent: no merging. Every finding from every pass is emitted with
|
|
273
|
+
* `source: 'first'` (Pass 1) or `source: 'independent'` (Pass N > 1). The
|
|
274
|
+
* renderer is responsible for formatting as side-by-side blocks.
|
|
275
|
+
*
|
|
276
|
+
* Output order: Pass 1's findings, then Pass 2's, then Pass 3's — preserving
|
|
277
|
+
* each pass's internal order.
|
|
278
|
+
*/
|
|
279
|
+
function aggregateIndependent(input) {
|
|
280
|
+
const findings = [];
|
|
281
|
+
for (const f of flattenFindings(input.firstPass)) {
|
|
282
|
+
findings.push({
|
|
283
|
+
...f,
|
|
284
|
+
attributions: [
|
|
285
|
+
{
|
|
286
|
+
passNumber: 1,
|
|
287
|
+
roleName: input.firstPassRole.name,
|
|
288
|
+
model: input.firstPassRole.model,
|
|
289
|
+
source: 'first',
|
|
290
|
+
},
|
|
291
|
+
],
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
for (const pass of input.subsequentPasses) {
|
|
295
|
+
if (!pass.review)
|
|
296
|
+
continue;
|
|
297
|
+
for (const f of flattenFindings(pass.review)) {
|
|
298
|
+
findings.push({
|
|
299
|
+
...f,
|
|
300
|
+
attributions: [
|
|
301
|
+
{
|
|
302
|
+
passNumber: pass.passNumber,
|
|
303
|
+
roleName: pass.role.name,
|
|
304
|
+
model: pass.role.model,
|
|
305
|
+
source: 'independent',
|
|
306
|
+
},
|
|
307
|
+
],
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return finalize({
|
|
312
|
+
mode: 'independent',
|
|
313
|
+
findings,
|
|
314
|
+
firstPassRole: input.firstPassRole,
|
|
315
|
+
subsequentPasses: input.subsequentPasses,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
// ---------------------------------------------------------------------------
|
|
319
|
+
// Internal helpers
|
|
320
|
+
// ---------------------------------------------------------------------------
|
|
321
|
+
/**
|
|
322
|
+
* Tuple-key used to detect "same finding" across passes.
|
|
323
|
+
*
|
|
324
|
+
* We key on (file, line, skill) instead of summary because:
|
|
325
|
+
* - Summaries vary stylistically between passes (Sonnet vs Opus phrasing).
|
|
326
|
+
* - File + line + cited skill is the SPEC §1.8.1 minimum identity unit.
|
|
327
|
+
* - File-level findings (no line) collapse to the same tuple regardless of
|
|
328
|
+
* phrasing, which is the desired consensus semantic.
|
|
329
|
+
*/
|
|
330
|
+
function tupleKey(f) {
|
|
331
|
+
return `${f.file}::${f.line ?? '*'}::${f.skill}`;
|
|
332
|
+
}
|
|
333
|
+
function severityRank(s) {
|
|
334
|
+
switch (s) {
|
|
335
|
+
case 'critical':
|
|
336
|
+
return 3;
|
|
337
|
+
case 'minor':
|
|
338
|
+
return 2;
|
|
339
|
+
case 'preexisting':
|
|
340
|
+
return 1;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
function finalize(input) {
|
|
344
|
+
const passCount = 1 + input.subsequentPasses.length;
|
|
345
|
+
const roles = [
|
|
346
|
+
{
|
|
347
|
+
passNumber: 1,
|
|
348
|
+
roleName: input.firstPassRole.name,
|
|
349
|
+
model: input.firstPassRole.model,
|
|
350
|
+
},
|
|
351
|
+
...input.subsequentPasses.map((p) => ({
|
|
352
|
+
passNumber: p.passNumber,
|
|
353
|
+
roleName: p.role.name,
|
|
354
|
+
model: p.role.model,
|
|
355
|
+
})),
|
|
356
|
+
];
|
|
357
|
+
// SPEC §6.10.1 consensus marker — single derivation point.
|
|
358
|
+
// Aggregators emit findings without `consensus`; this map adds it
|
|
359
|
+
// from the accumulated per-pass attributions. Renderer + auto-fix
|
|
360
|
+
// gate both consume `finding.consensus` downstream.
|
|
361
|
+
const findingsWithConsensus = input.findings.map((f) => ({
|
|
362
|
+
...f,
|
|
363
|
+
consensus: deriveConsensus(f.attributions),
|
|
364
|
+
}));
|
|
365
|
+
// Derive summary counts + skills_referenced from the aggregated list.
|
|
366
|
+
const counts = {
|
|
367
|
+
critical: findingsWithConsensus.filter((f) => f.severity === 'critical').length,
|
|
368
|
+
minor: findingsWithConsensus.filter((f) => f.severity === 'minor').length,
|
|
369
|
+
preexisting: findingsWithConsensus.filter((f) => f.severity === 'preexisting')
|
|
370
|
+
.length,
|
|
371
|
+
resolved_from_prior: 0,
|
|
372
|
+
still_open: 0,
|
|
373
|
+
};
|
|
374
|
+
const skillsReferenced = uniqInOrder(findingsWithConsensus.map((f) => f.skill));
|
|
375
|
+
// Status header logic:
|
|
376
|
+
// - empty → "clean"
|
|
377
|
+
// - any critical → "critical findings"
|
|
378
|
+
// - else → "clean" (minor + preexisting alone don't headline as critical)
|
|
379
|
+
const status_header = counts.critical > 0
|
|
380
|
+
? 'critical findings'
|
|
381
|
+
: 'clean';
|
|
382
|
+
// Verdict resolution — see resolveVerdict for the per-mode rules.
|
|
383
|
+
const verdict = resolveVerdict(input.mode, findingsWithConsensus, passCount);
|
|
384
|
+
return {
|
|
385
|
+
status_header,
|
|
386
|
+
summary_counts: counts,
|
|
387
|
+
skills_referenced: skillsReferenced,
|
|
388
|
+
findings: findingsWithConsensus,
|
|
389
|
+
mode: input.mode,
|
|
390
|
+
passCount,
|
|
391
|
+
roles,
|
|
392
|
+
verdict,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
function uniqInOrder(items) {
|
|
396
|
+
const seen = new Set();
|
|
397
|
+
const out = [];
|
|
398
|
+
for (const it of items) {
|
|
399
|
+
if (seen.has(it))
|
|
400
|
+
continue;
|
|
401
|
+
seen.add(it);
|
|
402
|
+
out.push(it);
|
|
403
|
+
}
|
|
404
|
+
return out;
|
|
405
|
+
}
|
|
406
|
+
// ---------------------------------------------------------------------------
|
|
407
|
+
// Verdict resolution
|
|
408
|
+
// ---------------------------------------------------------------------------
|
|
409
|
+
/**
|
|
410
|
+
* Resolves the APPROVE / REQUEST_CHANGES verdict per the SPEC §1.8.5 table:
|
|
411
|
+
*
|
|
412
|
+
* mode | request_changes when…
|
|
413
|
+
* --------------+------------------------------------------------------
|
|
414
|
+
* strict (=cross-check default) | ANY pass flagged critical
|
|
415
|
+
* consensus | ≥2 passes flagged the same critical tuple
|
|
416
|
+
* independent | findings side-by-side — human decides per finding.
|
|
417
|
+
* | For automation purposes we treat ANY critical as
|
|
418
|
+
* | request_changes (safer default; humans can downgrade).
|
|
419
|
+
*
|
|
420
|
+
* We expose this both as a return field on `MultiPassReview.verdict` and
|
|
421
|
+
* separately (for tests + future D.2 wiring) as `resolveVerdict`.
|
|
422
|
+
*
|
|
423
|
+
* NOTE: The broader D.2 phase wires APPROVE/REQUEST_CHANGES into actual
|
|
424
|
+
* PR check states. D.2.5 only computes the verdict — surfacing it is left
|
|
425
|
+
* to the renderer (which prefixes the header line with the verdict label).
|
|
426
|
+
*/
|
|
427
|
+
export function resolveVerdict(mode, findings, passCount) {
|
|
428
|
+
if (findings.length === 0)
|
|
429
|
+
return 'clean';
|
|
430
|
+
const criticals = findings.filter((f) => f.severity === 'critical');
|
|
431
|
+
if (criticals.length === 0)
|
|
432
|
+
return 'review_only';
|
|
433
|
+
switch (mode) {
|
|
434
|
+
case 'cross-check':
|
|
435
|
+
case 'independent':
|
|
436
|
+
// Strict: any critical → request_changes.
|
|
437
|
+
return 'request_changes';
|
|
438
|
+
case 'consensus':
|
|
439
|
+
// ≥2 passes must agree on the same critical tuple.
|
|
440
|
+
// Single-pass consensus is degenerate but valid — any critical fires.
|
|
441
|
+
if (passCount < 2)
|
|
442
|
+
return 'request_changes';
|
|
443
|
+
for (const f of criticals) {
|
|
444
|
+
// Spec: "≥2 passes flagged the same critical tuple."
|
|
445
|
+
// Each attribution represents exactly one pass, so the correct
|
|
446
|
+
// count is f.attributions.length. The earlier filter on
|
|
447
|
+
// `source === 'first' | 'agreed'` silently dropped findings
|
|
448
|
+
// raised by Pass 2 + confirmed by Pass 3 but missed by Pass 1
|
|
449
|
+
// (attributions = [independent, agreed], neither matches → the
|
|
450
|
+
// consensus gate never fired).
|
|
451
|
+
if (f.attributions.length >= 2)
|
|
452
|
+
return 'request_changes';
|
|
453
|
+
}
|
|
454
|
+
return 'review_only';
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
//# sourceMappingURL=multi-pass-aggregate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-pass-aggregate.js","sourceRoot":"","sources":["../../src/core/multi-pass-aggregate.ts"],"names":[],"mappings":"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"}
|