@zephyrdeng/pi-review 0.6.2 → 0.7.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/README.md +126 -14
- package/README.zh-CN.md +79 -4
- package/dist/args.d.ts +8 -0
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +167 -28
- package/dist/args.js.map +1 -1
- package/dist/args.test.d.ts +2 -0
- package/dist/args.test.d.ts.map +1 -0
- package/dist/args.test.js +125 -0
- package/dist/args.test.js.map +1 -0
- package/dist/child-process.d.ts +3 -0
- package/dist/child-process.d.ts.map +1 -1
- package/dist/child-process.js +26 -0
- package/dist/child-process.js.map +1 -1
- package/dist/child-process.test.js +13 -0
- package/dist/child-process.test.js.map +1 -1
- package/dist/cli-exit.test.d.ts +2 -0
- package/dist/cli-exit.test.d.ts.map +1 -0
- package/dist/cli-exit.test.js +84 -0
- package/dist/cli-exit.test.js.map +1 -0
- package/dist/cli.js +16 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/extensions/review.d.ts +2 -0
- package/dist/extensions/review.js +22 -0
- package/dist/extensions/rv-prompts.d.ts +19 -0
- package/dist/extensions/rv-prompts.js +132 -0
- package/dist/index.d.ts +22 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -6
- package/dist/index.js.map +1 -1
- package/dist/json-events.d.ts +71 -0
- package/dist/json-events.d.ts.map +1 -1
- package/dist/json-events.js +250 -0
- package/dist/json-events.js.map +1 -1
- package/dist/json-events.test.js +217 -1
- package/dist/json-events.test.js.map +1 -1
- package/dist/loop.d.ts +36 -0
- package/dist/loop.d.ts.map +1 -0
- package/dist/loop.js +73 -0
- package/dist/loop.js.map +1 -0
- package/dist/loop.test.d.ts +2 -0
- package/dist/loop.test.d.ts.map +1 -0
- package/dist/loop.test.js +83 -0
- package/dist/loop.test.js.map +1 -0
- package/dist/matcher.d.ts +74 -0
- package/dist/matcher.d.ts.map +1 -0
- package/dist/matcher.js +202 -0
- package/dist/matcher.js.map +1 -0
- package/dist/matcher.test.d.ts +2 -0
- package/dist/matcher.test.d.ts.map +1 -0
- package/dist/matcher.test.js +161 -0
- package/dist/matcher.test.js.map +1 -0
- package/dist/meta-footer.d.ts +15 -1
- package/dist/meta-footer.d.ts.map +1 -1
- package/dist/meta-footer.js +108 -0
- package/dist/meta-footer.js.map +1 -1
- package/dist/meta-footer.test.js +43 -1
- package/dist/meta-footer.test.js.map +1 -1
- package/dist/panel-aggregate.d.ts +18 -0
- package/dist/panel-aggregate.d.ts.map +1 -0
- package/dist/panel-aggregate.js +247 -0
- package/dist/panel-aggregate.js.map +1 -0
- package/dist/panel-aggregate.test.d.ts +2 -0
- package/dist/panel-aggregate.test.d.ts.map +1 -0
- package/dist/panel-aggregate.test.js +461 -0
- package/dist/panel-aggregate.test.js.map +1 -0
- package/dist/panel-cancellation.test.d.ts +2 -0
- package/dist/panel-cancellation.test.d.ts.map +1 -0
- package/dist/panel-cancellation.test.js +24 -0
- package/dist/panel-cancellation.test.js.map +1 -0
- package/dist/panel-cli.test.d.ts +2 -0
- package/dist/panel-cli.test.d.ts.map +1 -0
- package/dist/panel-cli.test.js +239 -0
- package/dist/panel-cli.test.js.map +1 -0
- package/dist/panel-config.d.ts +19 -0
- package/dist/panel-config.d.ts.map +1 -0
- package/dist/panel-config.js +115 -0
- package/dist/panel-config.js.map +1 -0
- package/dist/panel-config.test.d.ts +2 -0
- package/dist/panel-config.test.d.ts.map +1 -0
- package/dist/panel-config.test.js +94 -0
- package/dist/panel-config.test.js.map +1 -0
- package/dist/panel-loop.test.d.ts +2 -0
- package/dist/panel-loop.test.d.ts.map +1 -0
- package/dist/panel-loop.test.js +118 -0
- package/dist/panel-loop.test.js.map +1 -0
- package/dist/panel-tools.test.d.ts +2 -0
- package/dist/panel-tools.test.d.ts.map +1 -0
- package/dist/panel-tools.test.js +12 -0
- package/dist/panel-tools.test.js.map +1 -0
- package/dist/panel-usage.d.ts +6 -0
- package/dist/panel-usage.d.ts.map +1 -0
- package/dist/panel-usage.js +21 -0
- package/dist/panel-usage.js.map +1 -0
- package/dist/panel-view.d.ts +41 -0
- package/dist/panel-view.d.ts.map +1 -0
- package/dist/panel-view.js +90 -0
- package/dist/panel-view.js.map +1 -0
- package/dist/panel-view.test.d.ts +2 -0
- package/dist/panel-view.test.d.ts.map +1 -0
- package/dist/panel-view.test.js +45 -0
- package/dist/panel-view.test.js.map +1 -0
- package/dist/panel.d.ts +20 -0
- package/dist/panel.d.ts.map +1 -0
- package/dist/panel.js +393 -0
- package/dist/panel.js.map +1 -0
- package/dist/presets.d.ts +2 -1
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +10 -0
- package/dist/presets.js.map +1 -1
- package/dist/prompt.d.ts +14 -1
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +61 -15
- package/dist/prompt.js.map +1 -1
- package/dist/prompt.test.d.ts +2 -0
- package/dist/prompt.test.d.ts.map +1 -0
- package/dist/prompt.test.js +37 -0
- package/dist/prompt.test.js.map +1 -0
- package/dist/review-events.d.ts +70 -0
- package/dist/review-events.d.ts.map +1 -0
- package/dist/review-events.js +52 -0
- package/dist/review-events.js.map +1 -0
- package/dist/review-events.test.d.ts +2 -0
- package/dist/review-events.test.d.ts.map +1 -0
- package/dist/review-events.test.js +47 -0
- package/dist/review-events.test.js.map +1 -0
- package/dist/review-result.d.ts +5 -0
- package/dist/review-result.d.ts.map +1 -0
- package/dist/review-result.js +98 -0
- package/dist/review-result.js.map +1 -0
- package/dist/review-result.test.d.ts +2 -0
- package/dist/review-result.test.d.ts.map +1 -0
- package/dist/review-result.test.js +196 -0
- package/dist/review-result.test.js.map +1 -0
- package/dist/review.d.ts +10 -4
- package/dist/review.d.ts.map +1 -1
- package/dist/review.js +82 -20
- package/dist/review.js.map +1 -1
- package/dist/review.meta.test.js +2 -2
- package/dist/review.meta.test.js.map +1 -1
- package/dist/skill-protocol.test.d.ts +2 -0
- package/dist/skill-protocol.test.d.ts.map +1 -0
- package/dist/skill-protocol.test.js +35 -0
- package/dist/skill-protocol.test.js.map +1 -0
- package/dist/types.d.ts +151 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -1
- package/extensions/panel-tool.test.ts +30 -0
- package/extensions/panel-tool.ts +169 -0
- package/extensions/review.ts +3 -1
- package/extensions/rv-prompts.test.ts +8 -1
- package/extensions/rv-prompts.ts +6 -4
- package/package.json +14 -5
- package/resources/panel-presets.json +21 -0
- package/resources/review-presets.json +2 -2
- package/resources/system-prompt.md +11 -1
- package/skills/pi-review/SKILL.md +93 -15
- package/skills/pi-review/references/codex-tools.md +19 -6
package/dist/matcher.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// Finding clustering for panel review.
|
|
2
|
+
//
|
|
3
|
+
// Two-phase matching: deterministic exact matching on stable anchors first,
|
|
4
|
+
// then an injected semantic adjudicator may merge ambiguous candidate groups
|
|
5
|
+
// (same path, different wording). The adjudicator may never invent source
|
|
6
|
+
// IDs, drop source IDs, or act as another reviewer; low-confidence matches
|
|
7
|
+
// are not merged so that uncertain similarity cannot manufacture quorum.
|
|
8
|
+
import { SEMANTIC_MATCH_CONFIDENCE_THRESHOLD } from "./types.js";
|
|
9
|
+
/** Normalize a path anchor so reviewers that phrase paths slightly differently still match. */
|
|
10
|
+
export function normalizePath(value) {
|
|
11
|
+
if (!value)
|
|
12
|
+
return "";
|
|
13
|
+
return value
|
|
14
|
+
.replace(/^['"`]|['"`]$/g, "")
|
|
15
|
+
.replace(/^\.\//, "")
|
|
16
|
+
.trim()
|
|
17
|
+
.toLowerCase();
|
|
18
|
+
}
|
|
19
|
+
/** Normalize a finding summary for deterministic comparison. */
|
|
20
|
+
export function normalizeSummary(value) {
|
|
21
|
+
if (!value)
|
|
22
|
+
return "";
|
|
23
|
+
return value
|
|
24
|
+
.replace(/[*_`]/g, "")
|
|
25
|
+
.toLowerCase()
|
|
26
|
+
.replace(/[^\p{L}\p{N}\s]/gu, " ")
|
|
27
|
+
.replace(/\s+/g, " ")
|
|
28
|
+
.trim();
|
|
29
|
+
}
|
|
30
|
+
/** Deterministic cluster key: shared path anchor plus normalized summary. */
|
|
31
|
+
export function deterministicKey(finding) {
|
|
32
|
+
return `${normalizePath(finding.path)}::${normalizeSummary(finding.summary)}`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Phase-one matcher: clusters findings that share a path anchor AND a
|
|
36
|
+
* normalized summary. Findings with different paths never merge here; findings
|
|
37
|
+
* with the same path but different wording form separate clusters and become
|
|
38
|
+
* candidates for semantic adjudication.
|
|
39
|
+
*/
|
|
40
|
+
export class DeterministicMatcher {
|
|
41
|
+
match(findings) {
|
|
42
|
+
const byKey = new Map();
|
|
43
|
+
const order = [];
|
|
44
|
+
for (const sf of findings) {
|
|
45
|
+
const key = deterministicKey(sf.finding);
|
|
46
|
+
const group = byKey.get(key);
|
|
47
|
+
if (group) {
|
|
48
|
+
group.push(sf.id);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
const ids = [sf.id];
|
|
52
|
+
byKey.set(key, ids);
|
|
53
|
+
order.push(key);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
groups: order.map((key) => byKey.get(key)),
|
|
58
|
+
errors: [],
|
|
59
|
+
adjudicationUsed: false,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Phase-two matcher: deterministic first, then an injected adjudicator may
|
|
65
|
+
* merge ambiguous same-path candidates. Low-confidence matches are not merged.
|
|
66
|
+
* Invented or missing source IDs are reported as errors and never merged.
|
|
67
|
+
*/
|
|
68
|
+
export class SemanticMatcher {
|
|
69
|
+
adjudicator;
|
|
70
|
+
deterministic = new DeterministicMatcher();
|
|
71
|
+
constructor(adjudicator) {
|
|
72
|
+
this.adjudicator = adjudicator;
|
|
73
|
+
}
|
|
74
|
+
async match(findings) {
|
|
75
|
+
const det = this.deterministic.match(findings);
|
|
76
|
+
if (det.groups.length <= 1) {
|
|
77
|
+
return { ...det, adjudicationUsed: false };
|
|
78
|
+
}
|
|
79
|
+
const byId = new Map();
|
|
80
|
+
for (const sf of findings)
|
|
81
|
+
byId.set(sf.id, sf);
|
|
82
|
+
// Group deterministic clusters by path anchor to find ambiguous candidates:
|
|
83
|
+
// same path, more than one deterministic cluster (i.e. different wording).
|
|
84
|
+
const clustersByPath = new Map();
|
|
85
|
+
for (const group of det.groups) {
|
|
86
|
+
const first = byId.get(group[0]);
|
|
87
|
+
const anchor = normalizePath(first.finding.path);
|
|
88
|
+
const list = clustersByPath.get(anchor);
|
|
89
|
+
if (list)
|
|
90
|
+
list.push(group.map((id) => byId.get(id)));
|
|
91
|
+
else
|
|
92
|
+
clustersByPath.set(anchor, [group.map((id) => byId.get(id))]);
|
|
93
|
+
}
|
|
94
|
+
const candidates = [];
|
|
95
|
+
for (const [anchorPath, clusters] of clustersByPath) {
|
|
96
|
+
if (clusters.length > 1) {
|
|
97
|
+
candidates.push({ anchorPath, findings: clusters.flat() });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (candidates.length === 0) {
|
|
101
|
+
return { ...det, adjudicationUsed: false };
|
|
102
|
+
}
|
|
103
|
+
// A throwing adjudicator is a runtime failure; let it propagate so the
|
|
104
|
+
// aggregator can map it to blocked rather than a silent semantic merge.
|
|
105
|
+
const response = await this.adjudicator.adjudicate({ candidates });
|
|
106
|
+
const candidateIds = new Set();
|
|
107
|
+
const idToCandidate = new Map();
|
|
108
|
+
candidates.forEach((candidate, candidateIndex) => {
|
|
109
|
+
for (const sf of candidate.findings) {
|
|
110
|
+
candidateIds.add(sf.id);
|
|
111
|
+
idToCandidate.set(sf.id, candidateIndex);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
const errors = [];
|
|
115
|
+
if (response.errors?.length)
|
|
116
|
+
errors.push(...response.errors);
|
|
117
|
+
if (!Array.isArray(response.merges)) {
|
|
118
|
+
return {
|
|
119
|
+
groups: det.groups,
|
|
120
|
+
errors: ["malformed adjudicator response: merges is not an array", ...errors],
|
|
121
|
+
adjudicationUsed: true,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
// Union-find over deterministic groups; only candidate IDs may merge.
|
|
125
|
+
const groupIndex = new Map();
|
|
126
|
+
det.groups.forEach((group, index) => {
|
|
127
|
+
for (const id of group)
|
|
128
|
+
groupIndex.set(id, index);
|
|
129
|
+
});
|
|
130
|
+
const parent = det.groups.map((_, index) => index);
|
|
131
|
+
const find = (x) => {
|
|
132
|
+
while (parent[x] !== x) {
|
|
133
|
+
parent[x] = parent[parent[x]];
|
|
134
|
+
x = parent[x];
|
|
135
|
+
}
|
|
136
|
+
return x;
|
|
137
|
+
};
|
|
138
|
+
const union = (a, b) => {
|
|
139
|
+
const ra = find(a);
|
|
140
|
+
const rb = find(b);
|
|
141
|
+
if (ra !== rb)
|
|
142
|
+
parent[ra] = rb;
|
|
143
|
+
};
|
|
144
|
+
for (const merge of response.merges ?? []) {
|
|
145
|
+
if (!merge || typeof merge !== "object" || Array.isArray(merge)) {
|
|
146
|
+
errors.push("adjudicator returned a malformed merge entry (not an object)");
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (!Array.isArray(merge.sourceFindingIds)) {
|
|
150
|
+
errors.push("adjudicator returned a merge with non-array sourceFindingIds");
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
const unknown = merge.sourceFindingIds.filter((id) => !candidateIds.has(id));
|
|
154
|
+
if (unknown.length > 0) {
|
|
155
|
+
errors.push(`adjudicator invented source finding ids: ${unknown.join(", ")}`);
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
// A merge must stay within a single candidate group (same path anchor).
|
|
159
|
+
// Cross-path merges would create false consensus across different files.
|
|
160
|
+
const candidateIndices = new Set(merge.sourceFindingIds.map((id) => idToCandidate.get(id)));
|
|
161
|
+
if (candidateIndices.size > 1) {
|
|
162
|
+
errors.push(`adjudicator merged findings across different path anchors: ${merge.sourceFindingIds.join(", ")}`);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const ids = merge.sourceFindingIds;
|
|
166
|
+
if (ids.length < 2)
|
|
167
|
+
continue; // no-op, not malformed
|
|
168
|
+
const confidence = Number(merge.confidence);
|
|
169
|
+
if (!Number.isFinite(confidence) || confidence < 0 || confidence > 1) {
|
|
170
|
+
errors.push(`adjudicator returned invalid confidence for merge of ${ids.join(", ")}`);
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (confidence < SEMANTIC_MATCH_CONFIDENCE_THRESHOLD)
|
|
174
|
+
continue;
|
|
175
|
+
const rootIndex = groupIndex.get(ids[0]);
|
|
176
|
+
if (rootIndex === undefined)
|
|
177
|
+
continue;
|
|
178
|
+
for (let i = 1; i < ids.length; i += 1) {
|
|
179
|
+
const idx = groupIndex.get(ids[i]);
|
|
180
|
+
if (idx !== undefined)
|
|
181
|
+
union(rootIndex, idx);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const merged = new Map();
|
|
185
|
+
for (let index = 0; index < det.groups.length; index += 1) {
|
|
186
|
+
const root = find(index);
|
|
187
|
+
const list = merged.get(root);
|
|
188
|
+
if (list)
|
|
189
|
+
list.push(...det.groups[index]);
|
|
190
|
+
else
|
|
191
|
+
merged.set(root, [...det.groups[index]]);
|
|
192
|
+
}
|
|
193
|
+
// Preserve a stable order: by first source id within each merged group.
|
|
194
|
+
const groups = [...merged.values()].map((ids) => {
|
|
195
|
+
const sorted = [...ids].sort((a, b) => a.localeCompare(b));
|
|
196
|
+
return sorted;
|
|
197
|
+
});
|
|
198
|
+
groups.sort((a, b) => a[0].localeCompare(b[0]));
|
|
199
|
+
return { groups, errors, adjudicationUsed: true };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.js","sourceRoot":"","sources":["../src/matcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.test.d.ts","sourceRoot":"","sources":["../src/matcher.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import { DeterministicMatcher, SemanticMatcher, deterministicKey, normalizePath, normalizeSummary, } from "./matcher.js";
|
|
4
|
+
function sf(id, reviewerId, finding) {
|
|
5
|
+
return { id, reviewerId, finding };
|
|
6
|
+
}
|
|
7
|
+
function finding(summary, opts = {}) {
|
|
8
|
+
return { summary, actionable: opts.actionable ?? true, ...(opts.path ? { path: opts.path } : {}) };
|
|
9
|
+
}
|
|
10
|
+
test("normalizePath strips leading ./ and quotes and lowercases", () => {
|
|
11
|
+
assert.equal(normalizePath("`./src/cli.ts`"), "src/cli.ts");
|
|
12
|
+
assert.equal(normalizePath("SRC/CLI.TS"), "src/cli.ts");
|
|
13
|
+
assert.equal(normalizePath(undefined), "");
|
|
14
|
+
});
|
|
15
|
+
test("normalizeSummary collapses punctuation and whitespace", () => {
|
|
16
|
+
assert.equal(normalizeSummary("Off-by-one in the loop!"), "off by one in the loop");
|
|
17
|
+
assert.equal(normalizeSummary("`*Null* _deref_`"), "null deref");
|
|
18
|
+
});
|
|
19
|
+
test("deterministicKey combines path and normalized summary", () => {
|
|
20
|
+
assert.equal(deterministicKey({ path: "src/cli.ts", summary: "Off-by-one" }), "src/cli.ts::off by one");
|
|
21
|
+
assert.equal(deterministicKey({ summary: "No path" }), "::no path");
|
|
22
|
+
});
|
|
23
|
+
test("DeterministicMatcher merges same path + same summary across reviewers", () => {
|
|
24
|
+
const findings = [
|
|
25
|
+
sf("r1#F1", "r1", finding("Off-by-one in loop", { path: "src/cli.ts" })),
|
|
26
|
+
sf("r2#F1", "r2", finding("off-by-one in loop", { path: "./src/cli.ts" })),
|
|
27
|
+
];
|
|
28
|
+
const result = new DeterministicMatcher().match(findings);
|
|
29
|
+
assert.equal(result.groups.length, 1);
|
|
30
|
+
assert.deepEqual(result.groups[0].sort(), ["r1#F1", "r2#F1"]);
|
|
31
|
+
assert.equal(result.adjudicationUsed, false);
|
|
32
|
+
assert.deepEqual(result.errors, []);
|
|
33
|
+
});
|
|
34
|
+
test("DeterministicMatcher keeps different bugs in the same path separate", () => {
|
|
35
|
+
const findings = [
|
|
36
|
+
sf("r1#F1", "r1", finding("Null deref", { path: "src/cli.ts" })),
|
|
37
|
+
sf("r2#F1", "r2", finding("Race condition", { path: "src/cli.ts" })),
|
|
38
|
+
];
|
|
39
|
+
const result = new DeterministicMatcher().match(findings);
|
|
40
|
+
assert.equal(result.groups.length, 2);
|
|
41
|
+
});
|
|
42
|
+
test("DeterministicMatcher does not merge across incompatible paths", () => {
|
|
43
|
+
const findings = [
|
|
44
|
+
sf("r1#F1", "r1", finding("same summary", { path: "src/a.ts" })),
|
|
45
|
+
sf("r2#F1", "r2", finding("same summary", { path: "src/b.ts" })),
|
|
46
|
+
];
|
|
47
|
+
const result = new DeterministicMatcher().match(findings);
|
|
48
|
+
assert.equal(result.groups.length, 2);
|
|
49
|
+
});
|
|
50
|
+
function adjudicator(response) {
|
|
51
|
+
return { adjudicate: () => response };
|
|
52
|
+
}
|
|
53
|
+
test("SemanticMatcher merges different-wording same-path findings when adjudicator confirms", async () => {
|
|
54
|
+
const findings = [
|
|
55
|
+
sf("r1#F1", "r1", finding("loop bound is wrong", { path: "src/cli.ts" })),
|
|
56
|
+
sf("r2#F1", "r2", finding("off-by-one iteration", { path: "src/cli.ts" })),
|
|
57
|
+
];
|
|
58
|
+
const matcher = new SemanticMatcher(adjudicator(Promise.resolve({ merges: [{ sourceFindingIds: ["r1#F1", "r2#F1"], confidence: 0.9 }] })));
|
|
59
|
+
const result = await matcher.match(findings);
|
|
60
|
+
assert.equal(result.adjudicationUsed, true);
|
|
61
|
+
assert.equal(result.groups.length, 1);
|
|
62
|
+
assert.deepEqual(result.groups[0].sort(), ["r1#F1", "r2#F1"]);
|
|
63
|
+
});
|
|
64
|
+
test("SemanticMatcher leaves low-confidence matches separate", async () => {
|
|
65
|
+
const findings = [
|
|
66
|
+
sf("r1#F1", "r1", finding("loop bound is wrong", { path: "src/cli.ts" })),
|
|
67
|
+
sf("r2#F1", "r2", finding("off-by-one iteration", { path: "src/cli.ts" })),
|
|
68
|
+
];
|
|
69
|
+
const matcher = new SemanticMatcher(adjudicator(Promise.resolve({ merges: [{ sourceFindingIds: ["r1#F1", "r2#F1"], confidence: 0.3 }] })));
|
|
70
|
+
const result = await matcher.match(findings);
|
|
71
|
+
assert.equal(result.groups.length, 2);
|
|
72
|
+
});
|
|
73
|
+
test("SemanticMatcher rejects invented source ids as errors and does not merge them", async () => {
|
|
74
|
+
const findings = [
|
|
75
|
+
sf("r1#F1", "r1", finding("loop bound is wrong", { path: "src/cli.ts" })),
|
|
76
|
+
sf("r2#F1", "r2", finding("off-by-one iteration", { path: "src/cli.ts" })),
|
|
77
|
+
];
|
|
78
|
+
const matcher = new SemanticMatcher(adjudicator(Promise.resolve({ merges: [{ sourceFindingIds: ["r1#F1", "r9#F1"], confidence: 0.9 }] })));
|
|
79
|
+
const result = await matcher.match(findings);
|
|
80
|
+
assert.ok(result.errors.some((e) => /invented/.test(e)));
|
|
81
|
+
assert.equal(result.groups.length, 2);
|
|
82
|
+
});
|
|
83
|
+
test("SemanticMatcher reports malformed merges array as an error", async () => {
|
|
84
|
+
const findings = [
|
|
85
|
+
sf("r1#F1", "r1", finding("loop bound is wrong", { path: "src/cli.ts" })),
|
|
86
|
+
sf("r2#F1", "r2", finding("off-by-one iteration", { path: "src/cli.ts" })),
|
|
87
|
+
];
|
|
88
|
+
const matcher = new SemanticMatcher(adjudicator(Promise.resolve({ merges: "not-an-array" })));
|
|
89
|
+
const result = await matcher.match(findings);
|
|
90
|
+
assert.ok(result.errors.some((e) => /merges is not an array/.test(e)));
|
|
91
|
+
assert.equal(result.groups.length, 2);
|
|
92
|
+
});
|
|
93
|
+
test("SemanticMatcher ignores missing ids silently is not allowed: missing ids stay unmerged", async () => {
|
|
94
|
+
const findings = [
|
|
95
|
+
sf("r1#F1", "r1", finding("loop bound is wrong", { path: "src/cli.ts" })),
|
|
96
|
+
sf("r2#F1", "r2", finding("off-by-one iteration", { path: "src/cli.ts" })),
|
|
97
|
+
sf("r3#F1", "r3", finding("third issue", { path: "src/cli.ts" })),
|
|
98
|
+
];
|
|
99
|
+
// Adjudicator only mentions two; the third must remain its own cluster.
|
|
100
|
+
const matcher = new SemanticMatcher(adjudicator(Promise.resolve({ merges: [{ sourceFindingIds: ["r1#F1", "r2#F1"], confidence: 0.9 }] })));
|
|
101
|
+
const result = await matcher.match(findings);
|
|
102
|
+
assert.equal(result.groups.length, 2);
|
|
103
|
+
const flat = result.groups.flat();
|
|
104
|
+
assert.deepEqual(flat.sort(), ["r1#F1", "r2#F1", "r3#F1"]);
|
|
105
|
+
});
|
|
106
|
+
test("SemanticMatcher skips merges with invalid confidence and reports them", async () => {
|
|
107
|
+
const findings = [
|
|
108
|
+
sf("r1#F1", "r1", finding("loop bound is wrong", { path: "src/cli.ts" })),
|
|
109
|
+
sf("r2#F1", "r2", finding("off-by-one iteration", { path: "src/cli.ts" })),
|
|
110
|
+
];
|
|
111
|
+
const matcher = new SemanticMatcher(adjudicator(Promise.resolve({ merges: [{ sourceFindingIds: ["r1#F1", "r2#F1"], confidence: 1.7 }] })));
|
|
112
|
+
const result = await matcher.match(findings);
|
|
113
|
+
assert.ok(result.errors.some((e) => /invalid confidence/.test(e)));
|
|
114
|
+
assert.equal(result.groups.length, 2);
|
|
115
|
+
});
|
|
116
|
+
test("SemanticMatcher rejects merges across different path anchors", async () => {
|
|
117
|
+
// Two candidate groups: src/a.ts and src/b.ts, each ambiguous.
|
|
118
|
+
const findings = [
|
|
119
|
+
sf("r1#F1", "r1", finding("a wording one", { path: "src/a.ts" })),
|
|
120
|
+
sf("r2#F1", "r2", finding("a wording two", { path: "src/a.ts" })),
|
|
121
|
+
sf("r1#F2", "r1", finding("b wording one", { path: "src/b.ts" })),
|
|
122
|
+
sf("r2#F2", "r2", finding("b wording two", { path: "src/b.ts" })),
|
|
123
|
+
];
|
|
124
|
+
// Adjudicator tries to merge across a.ts and b.ts — must be rejected.
|
|
125
|
+
const matcher = new SemanticMatcher(adjudicator(Promise.resolve({ merges: [{ sourceFindingIds: ["r1#F1", "r2#F2"], confidence: 0.9 }] })));
|
|
126
|
+
const result = await matcher.match(findings);
|
|
127
|
+
assert.ok(result.errors.some((e) => /across different path anchors/.test(e)));
|
|
128
|
+
// No cross-path merge happened; each finding stays in its own cluster.
|
|
129
|
+
const flat = result.groups.flat().sort();
|
|
130
|
+
assert.deepEqual(flat, ["r1#F1", "r1#F2", "r2#F1", "r2#F2"]);
|
|
131
|
+
});
|
|
132
|
+
test("SemanticMatcher honors a within-candidate merge", async () => {
|
|
133
|
+
const findings = [
|
|
134
|
+
sf("r1#F1", "r1", finding("a wording one", { path: "src/a.ts" })),
|
|
135
|
+
sf("r2#F1", "r2", finding("a wording two", { path: "src/a.ts" })),
|
|
136
|
+
];
|
|
137
|
+
const matcher = new SemanticMatcher(adjudicator(Promise.resolve({ merges: [{ sourceFindingIds: ["r1#F1", "r2#F1"], confidence: 0.9 }] })));
|
|
138
|
+
const result = await matcher.match(findings);
|
|
139
|
+
assert.equal(result.groups.length, 1);
|
|
140
|
+
});
|
|
141
|
+
test("F6: a malformed (non-object) merge entry is reported as an error, not silently skipped", async () => {
|
|
142
|
+
const findings = [
|
|
143
|
+
sf("r1#F1", "r1", finding("loop bound is wrong", { path: "src/cli.ts" })),
|
|
144
|
+
sf("r2#F1", "r2", finding("off-by-one iteration", { path: "src/cli.ts" })),
|
|
145
|
+
];
|
|
146
|
+
const matcher = new SemanticMatcher(adjudicator(Promise.resolve({ merges: ["not-an-object", null, 42] })));
|
|
147
|
+
const result = await matcher.match(findings);
|
|
148
|
+
assert.ok(result.errors.some((e) => /malformed merge entry/.test(e)), `got ${result.errors.join(";")}`);
|
|
149
|
+
assert.equal(result.groups.length, 2);
|
|
150
|
+
});
|
|
151
|
+
test("F6: a merge with non-array sourceFindingIds is reported as an error", async () => {
|
|
152
|
+
const findings = [
|
|
153
|
+
sf("r1#F1", "r1", finding("loop bound is wrong", { path: "src/cli.ts" })),
|
|
154
|
+
sf("r2#F1", "r2", finding("off-by-one iteration", { path: "src/cli.ts" })),
|
|
155
|
+
];
|
|
156
|
+
const matcher = new SemanticMatcher(adjudicator(Promise.resolve({ merges: [{ sourceFindingIds: "r1#F1,r2#F1", confidence: 0.9 }] })));
|
|
157
|
+
const result = await matcher.match(findings);
|
|
158
|
+
assert.ok(result.errors.some((e) => /non-array sourceFindingIds/.test(e)));
|
|
159
|
+
assert.equal(result.groups.length, 2);
|
|
160
|
+
});
|
|
161
|
+
//# sourceMappingURL=matcher.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.test.js","sourceRoot":"","sources":["../src/matcher.test.ts"],"names":[],"mappings":"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"}
|
package/dist/meta-footer.d.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
|
-
import type { ReviewMeta } from "./types.js";
|
|
1
|
+
import type { PanelReviewMeta, ReviewMeta } from "./types.js";
|
|
2
2
|
export declare function formatDurationMs(ms: number): string;
|
|
3
|
+
/** Format a token count with K/M/B units (1024-based). */
|
|
4
|
+
export declare function formatTokens(n: number): string;
|
|
5
|
+
/** Format a token-usage breakdown as "in X · out Y · cache Z · reason W" for compact display. */
|
|
6
|
+
export declare function formatUsage(usage: {
|
|
7
|
+
input: number;
|
|
8
|
+
output: number;
|
|
9
|
+
cacheRead: number;
|
|
10
|
+
cacheWrite: number;
|
|
11
|
+
reasoning: number;
|
|
12
|
+
}): string;
|
|
3
13
|
/** Human-readable ASCII footer for terminals and Pi chat. */
|
|
4
14
|
export declare function formatReviewMetaAscii(meta: ReviewMeta): string;
|
|
5
15
|
/** Machine-readable line for scripts (written to stderr by default). */
|
|
6
16
|
export declare function formatReviewMetaJsonLine(meta: ReviewMeta): string;
|
|
17
|
+
/** Human-readable Markdown body for a panel evaluation (confirmed findings + advisories). */
|
|
18
|
+
export declare function formatPanelFindingsMarkdown(meta: PanelReviewMeta): string;
|
|
19
|
+
/** Human-readable ASCII footer for a panel evaluation. */
|
|
20
|
+
export declare function formatPanelMetaAscii(meta: PanelReviewMeta): string;
|
|
7
21
|
//# sourceMappingURL=meta-footer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"meta-footer.d.ts","sourceRoot":"","sources":["../src/meta-footer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"meta-footer.d.ts","sourceRoot":"","sources":["../src/meta-footer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAgB9D,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED,0DAA0D;AAC1D,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAW9C;AAED,iGAAiG;AACjG,wBAAgB,WAAW,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAEtI;AAMD,6DAA6D;AAC7D,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAyB9D;AAED,wEAAwE;AACxE,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEjE;AAED,6FAA6F;AAC7F,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CA2BzE;AAED,0DAA0D;AAC1D,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAoClE"}
|
package/dist/meta-footer.js
CHANGED
|
@@ -4,6 +4,12 @@ const VERDICT_DISPLAY = {
|
|
|
4
4
|
needs_clarification: { label: "NEEDS CLARIFICATION", mark: "?" },
|
|
5
5
|
blocked: { label: "BLOCKED", mark: "×" },
|
|
6
6
|
};
|
|
7
|
+
const STATUS_DISPLAY = {
|
|
8
|
+
clean: "CLEAN",
|
|
9
|
+
has_findings: "HAS FINDINGS",
|
|
10
|
+
needs_human: "NEEDS HUMAN",
|
|
11
|
+
blocked: "BLOCKED",
|
|
12
|
+
};
|
|
7
13
|
export function formatDurationMs(ms) {
|
|
8
14
|
if (ms < 1000)
|
|
9
15
|
return `${ms}ms`;
|
|
@@ -14,6 +20,24 @@ export function formatDurationMs(ms) {
|
|
|
14
20
|
const s = Math.round(sec % 60);
|
|
15
21
|
return s > 0 ? `${m}m ${s}s` : `${m}m`;
|
|
16
22
|
}
|
|
23
|
+
/** Format a token count with K/M/B units (1024-based). */
|
|
24
|
+
export function formatTokens(n) {
|
|
25
|
+
if (n < 1024)
|
|
26
|
+
return `${n}`;
|
|
27
|
+
const units = ["K", "M", "B"];
|
|
28
|
+
let value = n / 1024;
|
|
29
|
+
let unitIndex = 0;
|
|
30
|
+
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
31
|
+
value /= 1024;
|
|
32
|
+
unitIndex += 1;
|
|
33
|
+
}
|
|
34
|
+
const digits = value < 100 ? 1 : 0;
|
|
35
|
+
return `${value.toFixed(digits)}${units[unitIndex]}`;
|
|
36
|
+
}
|
|
37
|
+
/** Format a token-usage breakdown as "in X · out Y · cache Z · reason W" for compact display. */
|
|
38
|
+
export function formatUsage(usage) {
|
|
39
|
+
return `in ${formatTokens(usage.input)} · out ${formatTokens(usage.output)} · cache ${formatTokens(usage.cacheRead + usage.cacheWrite)} · reason ${formatTokens(usage.reasoning)}`;
|
|
40
|
+
}
|
|
17
41
|
function padLabel(label, width) {
|
|
18
42
|
return label.length >= width ? label : label + " ".repeat(width - label.length);
|
|
19
43
|
}
|
|
@@ -24,10 +48,18 @@ export function formatReviewMetaAscii(meta) {
|
|
|
24
48
|
const lines = [
|
|
25
49
|
"── pi-review " + "─".repeat(28),
|
|
26
50
|
` ${padLabel("Verdict", labelW)} ${v.mark} ${v.label}`,
|
|
51
|
+
` ${padLabel("Status", labelW)} ${STATUS_DISPLAY[meta.status]}`,
|
|
27
52
|
` ${padLabel("Mode", labelW)} ${meta.reviewMode}`,
|
|
28
53
|
];
|
|
54
|
+
if (meta.findings.length > 0) {
|
|
55
|
+
lines.push(` ${padLabel("Findings", labelW)} ${meta.actionableCount} actionable / ${meta.findings.length} total`);
|
|
56
|
+
}
|
|
29
57
|
if (meta.model)
|
|
30
58
|
lines.push(` ${padLabel("Model", labelW)} ${meta.model}`);
|
|
59
|
+
if (meta.thinking)
|
|
60
|
+
lines.push(` ${padLabel("Thinking", labelW)} ${meta.thinking}`);
|
|
61
|
+
if (meta.usage)
|
|
62
|
+
lines.push(` ${padLabel("Tokens", labelW)} ${formatUsage(meta.usage)}`);
|
|
31
63
|
lines.push(` ${padLabel("Duration", labelW)} ${formatDurationMs(meta.durationMs)}`);
|
|
32
64
|
if (meta.sessionHandle) {
|
|
33
65
|
lines.push(` ${padLabel("Session", labelW)} ${meta.sessionHandle}`);
|
|
@@ -43,4 +75,80 @@ export function formatReviewMetaAscii(meta) {
|
|
|
43
75
|
export function formatReviewMetaJsonLine(meta) {
|
|
44
76
|
return `PI_REVIEW_META_JSON: ${JSON.stringify(meta)}\n`;
|
|
45
77
|
}
|
|
78
|
+
/** Human-readable Markdown body for a panel evaluation (confirmed findings + advisories). */
|
|
79
|
+
export function formatPanelFindingsMarkdown(meta) {
|
|
80
|
+
const lines = [];
|
|
81
|
+
if (meta.confirmedClusters.length > 0) {
|
|
82
|
+
lines.push("## Panel Findings (confirmed)");
|
|
83
|
+
for (const c of meta.confirmedClusters) {
|
|
84
|
+
lines.push(`### ${c.id}: ${c.summary}`);
|
|
85
|
+
if (c.severity)
|
|
86
|
+
lines.push(`- Severity: ${c.severity}`);
|
|
87
|
+
if (c.path)
|
|
88
|
+
lines.push(`- Path: ${c.path}`);
|
|
89
|
+
lines.push(`- Support: ${c.supportCount}/${meta.configuredReviewers} reviewers (${c.actionableSupportCount} actionable)`);
|
|
90
|
+
lines.push(`- Reviewers: ${c.supportingReviewerIds.join(", ")}`);
|
|
91
|
+
lines.push(`- Source findings: ${c.sourceFindingIds.join(", ")}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (meta.advisories.length > 0) {
|
|
95
|
+
if (lines.length > 0)
|
|
96
|
+
lines.push("");
|
|
97
|
+
lines.push("## Panel Advisories (non-blocking — do not affect gate status)");
|
|
98
|
+
for (const c of meta.advisories) {
|
|
99
|
+
lines.push(`### ${c.id}: ${c.summary}`);
|
|
100
|
+
if (c.severity)
|
|
101
|
+
lines.push(`- Severity: ${c.severity}`);
|
|
102
|
+
if (c.path)
|
|
103
|
+
lines.push(`- Path: ${c.path}`);
|
|
104
|
+
lines.push(`- Support: ${c.supportCount}/${meta.configuredReviewers} reviewers (${c.actionableSupportCount} actionable)`);
|
|
105
|
+
lines.push(`- Reviewers: ${c.supportingReviewerIds.join(", ")}`);
|
|
106
|
+
lines.push(`- Source findings: ${c.sourceFindingIds.join(", ")}`);
|
|
107
|
+
lines.push(`- Confirmed: no`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return lines.length > 0 ? lines.join("\n") : "";
|
|
111
|
+
}
|
|
112
|
+
/** Human-readable ASCII footer for a panel evaluation. */
|
|
113
|
+
export function formatPanelMetaAscii(meta) {
|
|
114
|
+
const labelW = 10;
|
|
115
|
+
const lines = [
|
|
116
|
+
"── pi-review panel " + "─".repeat(21),
|
|
117
|
+
` ${padLabel("Status", labelW)} ${STATUS_DISPLAY[meta.status]}`,
|
|
118
|
+
` ${padLabel("Health", labelW)} ${meta.panelHealth.toUpperCase()}`,
|
|
119
|
+
` ${padLabel("Mode", labelW)} ${meta.reviewMode}`,
|
|
120
|
+
` ${padLabel("Reviewers", labelW)} ${meta.successfulReviewers}/${meta.configuredReviewers} successful`,
|
|
121
|
+
` ${padLabel("Consensus", labelW)} ${meta.consensusPolicy} (threshold ${meta.consensusThreshold})`,
|
|
122
|
+
` ${padLabel("Confirmed", labelW)} ${meta.confirmedClusters.length} actionable`,
|
|
123
|
+
` ${padLabel("Advisories", labelW)} ${meta.advisories.length} non-blocking`,
|
|
124
|
+
];
|
|
125
|
+
if (meta.panelPreset)
|
|
126
|
+
lines.push(` ${padLabel("Panel", labelW)} ${meta.panelPreset}`);
|
|
127
|
+
if (meta.thinking)
|
|
128
|
+
lines.push(` ${padLabel("Thinking", labelW)} ${meta.thinking}`);
|
|
129
|
+
if (meta.usage)
|
|
130
|
+
lines.push(` ${padLabel("Tokens", labelW)} ${formatUsage(meta.usage)}`);
|
|
131
|
+
if (meta.adjudicationUsed)
|
|
132
|
+
lines.push(` ${padLabel("Adjudicator", labelW)} used`);
|
|
133
|
+
if (meta.adjudicationErrors?.length) {
|
|
134
|
+
lines.push(` ${padLabel("Note", labelW)} ${meta.adjudicationErrors.join("; ")}`);
|
|
135
|
+
}
|
|
136
|
+
lines.push(` ${padLabel("Duration", labelW)} ${formatDurationMs(meta.durationMs)}`);
|
|
137
|
+
lines.push(" Reviewers:");
|
|
138
|
+
for (const r of meta.reviewers) {
|
|
139
|
+
const bits = [
|
|
140
|
+
r.reviewerId,
|
|
141
|
+
STATUS_DISPLAY[r.status],
|
|
142
|
+
r.verdict,
|
|
143
|
+
...(r.role ? [`role:${r.role.split(" ")[0]}`] : []),
|
|
144
|
+
...(r.model ? [r.model] : []),
|
|
145
|
+
...(r.thinking ? [`think:${r.thinking}`] : []),
|
|
146
|
+
...(r.usage ? [formatUsage(r.usage)] : []),
|
|
147
|
+
formatDurationMs(r.durationMs),
|
|
148
|
+
];
|
|
149
|
+
lines.push(` - ${bits.join(" | ")}`);
|
|
150
|
+
}
|
|
151
|
+
lines.push("─".repeat(42));
|
|
152
|
+
return lines.join("\n");
|
|
153
|
+
}
|
|
46
154
|
//# sourceMappingURL=meta-footer.js.map
|
package/dist/meta-footer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"meta-footer.js","sourceRoot":"","sources":["../src/meta-footer.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"meta-footer.js","sourceRoot":"","sources":["../src/meta-footer.ts"],"names":[],"mappings":"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"}
|