@webpieces/pr-gate 0.4.564 → 0.4.565
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/package.json +2 -2
- package/src/dashboard/checklist-comment-row.d.ts +42 -0
- package/src/dashboard/checklist-comment-row.js +59 -0
- package/src/dashboard/checklist-comment-row.js.map +1 -0
- package/src/dashboard/dashboard.d.ts +19 -29
- package/src/dashboard/dashboard.js +57 -53
- package/src/dashboard/dashboard.js.map +1 -1
- package/src/scripts/commands/finish-upsert-pr-command.d.ts +9 -0
- package/src/scripts/commands/finish-upsert-pr-command.js +24 -4
- package/src/scripts/commands/finish-upsert-pr-command.js.map +1 -1
- package/src/scripts/commands/review-upsert-pr-command.d.ts +12 -1
- package/src/scripts/commands/review-upsert-pr-command.js +20 -4
- package/src/scripts/commands/review-upsert-pr-command.js.map +1 -1
- package/src/scripts/pr-gate-app.d.ts +2 -2
- package/src/scripts/pr-gate-app.js +2 -2
- package/src/scripts/pr-gate-app.js.map +1 -1
- package/src/scripts/workflow/checklist-detector.js +1 -1
- package/src/scripts/workflow/checklist-detector.js.map +1 -1
- package/src/scripts/workflow/checklist-scanner.d.ts +21 -1
- package/src/scripts/workflow/checklist-scanner.js +31 -3
- package/src/scripts/workflow/checklist-scanner.js.map +1 -1
- package/src/scripts/workflow/review-report.d.ts +62 -1
- package/src/scripts/workflow/review-report.js +165 -34
- package/src/scripts/workflow/review-report.js.map +1 -1
- package/src/scripts/workflow/reviewer-briefing-builder.js +1 -0
- package/src/scripts/workflow/reviewer-briefing-builder.js.map +1 -1
- package/src/scripts/workflow/reviewer-verdict-gate.d.ts +10 -0
- package/src/scripts/workflow/reviewer-verdict-gate.js +17 -1
- package/src/scripts/workflow/reviewer-verdict-gate.js.map +1 -1
- package/src/scripts/wp-review-upsert-pr.js +9 -2
- package/src/scripts/wp-review-upsert-pr.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webpieces/pr-gate",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.565",
|
|
4
4
|
"description": "Gated PR system: 3-point squash-merge, merge validation gate, and red/yellow/green PR dashboard. Standalone scripts, no Nx dependency required.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"directory": "packages/tooling/pr-gate"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@webpieces/rules-config": "0.4.
|
|
29
|
+
"@webpieces/rules-config": "0.4.565",
|
|
30
30
|
"@inversifyjs/binding-decorators": "1.1.5",
|
|
31
31
|
"inversify": "7.10.4",
|
|
32
32
|
"reflect-metadata": "0.2.2"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One roster line of the checklist COMMENT: a defined checklist, whether its reviewer ran, and the evidence
|
|
3
|
+
* for WHY. Deliberately separate from {@link ChecklistRow} rather than five more fields on it — ChecklistRow
|
|
4
|
+
* also feeds the PR body and the squash-commit body, and roster evidence has no business travelling into
|
|
5
|
+
* main's git history or through every DashboardInput construction site.
|
|
6
|
+
*
|
|
7
|
+
* Kept in pr-gate, not rules-config: the shape of a GitHub comment is this package's concern, and
|
|
8
|
+
* rules-config is the dependency, not the dependent. Its own FILE (rather than sitting in dashboard.ts)
|
|
9
|
+
* per the one-class-per-file convention — dashboard.ts is a large renderer against a hard max-file-lines
|
|
10
|
+
* limit, while this is a data class its consumers construct directly: finish builds these, Dashboard only
|
|
11
|
+
* reads them.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ChecklistCommentRow {
|
|
14
|
+
subagent: string;
|
|
15
|
+
status: string;
|
|
16
|
+
detail: string;
|
|
17
|
+
ran: boolean;
|
|
18
|
+
configuredPatterns: string[];
|
|
19
|
+
firedPatterns: string[];
|
|
20
|
+
matchedFiles: string[];
|
|
21
|
+
changedFileCount: number;
|
|
22
|
+
/**
|
|
23
|
+
* Whether this reviewer's own transcript shows it OPENING the extracted diff.
|
|
24
|
+
*
|
|
25
|
+
* '' = not assessed (no Claude Code session, or nothing was materialized) and prints nothing — "no
|
|
26
|
+
* evidence recorded" and "evidence says it never looked" are different claims, and conflating them
|
|
27
|
+
* would accuse a reviewer that ran perfectly well in CI. 'yes' | 'no' otherwise. Defaulted, so every
|
|
28
|
+
* existing construction site is unchanged.
|
|
29
|
+
*/
|
|
30
|
+
diffRead: string;
|
|
31
|
+
/**
|
|
32
|
+
* The checklist's configured `required`. Published because "no verdict" means two opposite things and the
|
|
33
|
+
* roster is the only place a reader can tell them apart: a REQUIRED checklist with no verdict could not
|
|
34
|
+
* have opened this PR at all, so seeing one means something went wrong; an OPTIONAL one with no verdict
|
|
35
|
+
* is a review the human was offered and declined, which is the feature working.
|
|
36
|
+
*
|
|
37
|
+
* Defaulted to the blocking value so every existing construction site is unchanged and a row that forgets
|
|
38
|
+
* to set it is reported as the stricter of the two.
|
|
39
|
+
*/
|
|
40
|
+
required: boolean;
|
|
41
|
+
constructor(subagent: string, status: string, detail: string, ran: boolean, configuredPatterns: string[], firedPatterns: string[], matchedFiles: string[], changedFileCount: number);
|
|
42
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChecklistCommentRow = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* One roster line of the checklist COMMENT: a defined checklist, whether its reviewer ran, and the evidence
|
|
6
|
+
* for WHY. Deliberately separate from {@link ChecklistRow} rather than five more fields on it — ChecklistRow
|
|
7
|
+
* also feeds the PR body and the squash-commit body, and roster evidence has no business travelling into
|
|
8
|
+
* main's git history or through every DashboardInput construction site.
|
|
9
|
+
*
|
|
10
|
+
* Kept in pr-gate, not rules-config: the shape of a GitHub comment is this package's concern, and
|
|
11
|
+
* rules-config is the dependency, not the dependent. Its own FILE (rather than sitting in dashboard.ts)
|
|
12
|
+
* per the one-class-per-file convention — dashboard.ts is a large renderer against a hard max-file-lines
|
|
13
|
+
* limit, while this is a data class its consumers construct directly: finish builds these, Dashboard only
|
|
14
|
+
* reads them.
|
|
15
|
+
*/
|
|
16
|
+
class ChecklistCommentRow {
|
|
17
|
+
subagent; // the reviewer / checklist id
|
|
18
|
+
status; // CK_* verdict; '' when it did not run
|
|
19
|
+
detail; // verbatim reviewer output
|
|
20
|
+
ran; // false = skipped, which is a NORMAL, healthy outcome
|
|
21
|
+
// The checklist's CONFIGURED globs. The only safe signal for "always runs": a patternless checklist and
|
|
22
|
+
// a skipped one both have an empty `firedPatterns`, and they mean opposite things.
|
|
23
|
+
configuredPatterns;
|
|
24
|
+
firedPatterns; // which configured globs actually hit a changed file
|
|
25
|
+
matchedFiles;
|
|
26
|
+
changedFileCount; // how many files were considered at all — "0 of N" needs the N
|
|
27
|
+
/**
|
|
28
|
+
* Whether this reviewer's own transcript shows it OPENING the extracted diff.
|
|
29
|
+
*
|
|
30
|
+
* '' = not assessed (no Claude Code session, or nothing was materialized) and prints nothing — "no
|
|
31
|
+
* evidence recorded" and "evidence says it never looked" are different claims, and conflating them
|
|
32
|
+
* would accuse a reviewer that ran perfectly well in CI. 'yes' | 'no' otherwise. Defaulted, so every
|
|
33
|
+
* existing construction site is unchanged.
|
|
34
|
+
*/
|
|
35
|
+
diffRead = '';
|
|
36
|
+
/**
|
|
37
|
+
* The checklist's configured `required`. Published because "no verdict" means two opposite things and the
|
|
38
|
+
* roster is the only place a reader can tell them apart: a REQUIRED checklist with no verdict could not
|
|
39
|
+
* have opened this PR at all, so seeing one means something went wrong; an OPTIONAL one with no verdict
|
|
40
|
+
* is a review the human was offered and declined, which is the feature working.
|
|
41
|
+
*
|
|
42
|
+
* Defaulted to the blocking value so every existing construction site is unchanged and a row that forgets
|
|
43
|
+
* to set it is reported as the stricter of the two.
|
|
44
|
+
*/
|
|
45
|
+
required = true;
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/max-params
|
|
47
|
+
constructor(subagent, status, detail, ran, configuredPatterns, firedPatterns, matchedFiles, changedFileCount) {
|
|
48
|
+
this.subagent = subagent;
|
|
49
|
+
this.status = status;
|
|
50
|
+
this.detail = detail;
|
|
51
|
+
this.ran = ran;
|
|
52
|
+
this.configuredPatterns = configuredPatterns;
|
|
53
|
+
this.firedPatterns = firedPatterns;
|
|
54
|
+
this.matchedFiles = matchedFiles;
|
|
55
|
+
this.changedFileCount = changedFileCount;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.ChecklistCommentRow = ChecklistCommentRow;
|
|
59
|
+
//# sourceMappingURL=checklist-comment-row.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checklist-comment-row.js","sourceRoot":"","sources":["../../../../../../packages/tooling/pr-gate/src/dashboard/checklist-comment-row.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;GAWG;AACH,MAAa,mBAAmB;IAC5B,QAAQ,CAAS,CAAC,8BAA8B;IAChD,MAAM,CAAS,CAAC,uCAAuC;IACvD,MAAM,CAAS,CAAC,2BAA2B;IAC3C,GAAG,CAAU,CAAC,sDAAsD;IACpE,wGAAwG;IACxG,mFAAmF;IACnF,kBAAkB,CAAW;IAC7B,aAAa,CAAW,CAAC,qDAAqD;IAC9E,YAAY,CAAW;IACvB,gBAAgB,CAAS,CAAC,+DAA+D;IACzF;;;;;;;OAOG;IACH,QAAQ,GAAW,EAAE,CAAC;IACtB;;;;;;;;OAQG;IACH,QAAQ,GAAY,IAAI,CAAC;IAEzB,yDAAyD;IACzD,YACI,QAAgB,EAChB,MAAc,EACd,MAAc,EACd,GAAY,EACZ,kBAA4B,EAC5B,aAAuB,EACvB,YAAsB,EACtB,gBAAwB;QAExB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;QAC7C,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;IAC7C,CAAC;CACJ;AAnDD,kDAmDC","sourcesContent":["/**\n * One roster line of the checklist COMMENT: a defined checklist, whether its reviewer ran, and the evidence\n * for WHY. Deliberately separate from {@link ChecklistRow} rather than five more fields on it — ChecklistRow\n * also feeds the PR body and the squash-commit body, and roster evidence has no business travelling into\n * main's git history or through every DashboardInput construction site.\n *\n * Kept in pr-gate, not rules-config: the shape of a GitHub comment is this package's concern, and\n * rules-config is the dependency, not the dependent. Its own FILE (rather than sitting in dashboard.ts)\n * per the one-class-per-file convention — dashboard.ts is a large renderer against a hard max-file-lines\n * limit, while this is a data class its consumers construct directly: finish builds these, Dashboard only\n * reads them.\n */\nexport class ChecklistCommentRow {\n subagent: string; // the reviewer / checklist id\n status: string; // CK_* verdict; '' when it did not run\n detail: string; // verbatim reviewer output\n ran: boolean; // false = skipped, which is a NORMAL, healthy outcome\n // The checklist's CONFIGURED globs. The only safe signal for \"always runs\": a patternless checklist and\n // a skipped one both have an empty `firedPatterns`, and they mean opposite things.\n configuredPatterns: string[];\n firedPatterns: string[]; // which configured globs actually hit a changed file\n matchedFiles: string[];\n changedFileCount: number; // how many files were considered at all — \"0 of N\" needs the N\n /**\n * Whether this reviewer's own transcript shows it OPENING the extracted diff.\n *\n * '' = not assessed (no Claude Code session, or nothing was materialized) and prints nothing — \"no\n * evidence recorded\" and \"evidence says it never looked\" are different claims, and conflating them\n * would accuse a reviewer that ran perfectly well in CI. 'yes' | 'no' otherwise. Defaulted, so every\n * existing construction site is unchanged.\n */\n diffRead: string = '';\n /**\n * The checklist's configured `required`. Published because \"no verdict\" means two opposite things and the\n * roster is the only place a reader can tell them apart: a REQUIRED checklist with no verdict could not\n * have opened this PR at all, so seeing one means something went wrong; an OPTIONAL one with no verdict\n * is a review the human was offered and declined, which is the feature working.\n *\n * Defaulted to the blocking value so every existing construction site is unchanged and a row that forgets\n * to set it is reported as the stricter of the two.\n */\n required: boolean = true;\n\n // eslint-disable-next-line @typescript-eslint/max-params\n constructor(\n subagent: string,\n status: string,\n detail: string,\n ran: boolean,\n configuredPatterns: string[],\n firedPatterns: string[],\n matchedFiles: string[],\n changedFileCount: number,\n ) {\n this.subagent = subagent;\n this.status = status;\n this.detail = detail;\n this.ran = ran;\n this.configuredPatterns = configuredPatterns;\n this.firedPatterns = firedPatterns;\n this.matchedFiles = matchedFiles;\n this.changedFileCount = changedFileCount;\n }\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GateDefinition, ReviewJson } from '@webpieces/rules-config';
|
|
2
|
+
import { ChecklistCommentRow } from './checklist-comment-row';
|
|
2
3
|
export declare const CHECKLIST_COMMENT_MARKER = "<!-- webpieces-checklists v2 -->";
|
|
3
4
|
export declare class GateResult {
|
|
4
5
|
name: string;
|
|
@@ -12,35 +13,6 @@ export declare class ChecklistRow {
|
|
|
12
13
|
detail: string;
|
|
13
14
|
constructor(title: string, status: string, detail?: string);
|
|
14
15
|
}
|
|
15
|
-
/**
|
|
16
|
-
* One roster line of the checklist COMMENT: a defined checklist, whether its reviewer ran, and the evidence
|
|
17
|
-
* for WHY. Deliberately separate from {@link ChecklistRow} rather than five more fields on it — ChecklistRow
|
|
18
|
-
* also feeds the PR body and the squash-commit body, and roster evidence has no business travelling into
|
|
19
|
-
* main's git history or through every DashboardInput construction site.
|
|
20
|
-
*
|
|
21
|
-
* Kept in pr-gate, not rules-config: the shape of a GitHub comment is this package's concern, and
|
|
22
|
-
* rules-config is the dependency, not the dependent.
|
|
23
|
-
*/
|
|
24
|
-
export declare class ChecklistCommentRow {
|
|
25
|
-
subagent: string;
|
|
26
|
-
status: string;
|
|
27
|
-
detail: string;
|
|
28
|
-
ran: boolean;
|
|
29
|
-
configuredPatterns: string[];
|
|
30
|
-
firedPatterns: string[];
|
|
31
|
-
matchedFiles: string[];
|
|
32
|
-
changedFileCount: number;
|
|
33
|
-
/**
|
|
34
|
-
* Whether this reviewer's own transcript shows it OPENING the extracted diff.
|
|
35
|
-
*
|
|
36
|
-
* '' = not assessed (no Claude Code session, or nothing was materialized) and prints nothing — "no
|
|
37
|
-
* evidence recorded" and "evidence says it never looked" are different claims, and conflating them
|
|
38
|
-
* would accuse a reviewer that ran perfectly well in CI. 'yes' | 'no' otherwise. Defaulted, so every
|
|
39
|
-
* existing construction site is unchanged.
|
|
40
|
-
*/
|
|
41
|
-
diffRead: string;
|
|
42
|
-
constructor(subagent: string, status: string, detail: string, ran: boolean, configuredPatterns: string[], firedPatterns: string[], matchedFiles: string[], changedFileCount: number);
|
|
43
|
-
}
|
|
44
16
|
export declare class DisableCounts {
|
|
45
17
|
webpiecesCount: number;
|
|
46
18
|
eslintCount: number;
|
|
@@ -78,9 +50,27 @@ export declare class Dashboard {
|
|
|
78
50
|
* Idempotent: keyed by the hidden marker so wp-finish PATCHes this same comment on every push.
|
|
79
51
|
*/
|
|
80
52
|
renderChecklistComment(rows: readonly ChecklistCommentRow[], provenanceVerified: boolean, baseResolved: boolean): string;
|
|
53
|
+
/**
|
|
54
|
+
* The closing note when no reviewer produced a verdict. The original wording — "every configured
|
|
55
|
+
* checklist was evaluated and none of them applied" — is an all-clear, and it becomes FALSE the moment a
|
|
56
|
+
* checklist did apply and was declined. That sentence under a PR nobody reviewed is precisely the
|
|
57
|
+
* misreport this feature could otherwise introduce, so the declined case gets its own words.
|
|
58
|
+
*/
|
|
59
|
+
private nothingRanNote;
|
|
81
60
|
private rollupHeader;
|
|
82
61
|
private rollupCounts;
|
|
83
62
|
private rosterBullet;
|
|
63
|
+
/**
|
|
64
|
+
* Did a reviewer actually produce a verdict for this row?
|
|
65
|
+
*
|
|
66
|
+
* `row.ran` is really "this checklist APPLIED to the diff" — for a required checklist the two are the
|
|
67
|
+
* same thing, because the PR cannot open otherwise, and the field was named before optional checklists
|
|
68
|
+
* existed. For a DECLINED optional one they diverge, and using `ran` alone would put a checked box and a
|
|
69
|
+
* reviewer section on a review that nobody performed.
|
|
70
|
+
*/
|
|
71
|
+
private reviewerRan;
|
|
72
|
+
private declined;
|
|
73
|
+
private optionalTag;
|
|
84
74
|
/**
|
|
85
75
|
* Whether the reviewer demonstrably opened the diff, read from its own transcript. A QUALITY signal and
|
|
86
76
|
* never a blocker (see SubagentProvenanceService.evidenceFor) — but published, because "wrote a verdict
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Dashboard = exports.DashboardInput = exports.DisableCounts = exports.
|
|
3
|
+
exports.Dashboard = exports.DashboardInput = exports.DisableCounts = exports.ChecklistRow = exports.GateResult = exports.CHECKLIST_COMMENT_MARKER = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const rules_config_1 = require("@webpieces/rules-config");
|
|
6
6
|
const inversify_1 = require("inversify");
|
|
@@ -47,48 +47,6 @@ class ChecklistRow {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
exports.ChecklistRow = ChecklistRow;
|
|
50
|
-
/**
|
|
51
|
-
* One roster line of the checklist COMMENT: a defined checklist, whether its reviewer ran, and the evidence
|
|
52
|
-
* for WHY. Deliberately separate from {@link ChecklistRow} rather than five more fields on it — ChecklistRow
|
|
53
|
-
* also feeds the PR body and the squash-commit body, and roster evidence has no business travelling into
|
|
54
|
-
* main's git history or through every DashboardInput construction site.
|
|
55
|
-
*
|
|
56
|
-
* Kept in pr-gate, not rules-config: the shape of a GitHub comment is this package's concern, and
|
|
57
|
-
* rules-config is the dependency, not the dependent.
|
|
58
|
-
*/
|
|
59
|
-
class ChecklistCommentRow {
|
|
60
|
-
subagent; // the reviewer / checklist id
|
|
61
|
-
status; // CK_* verdict; '' when it did not run
|
|
62
|
-
detail; // verbatim reviewer output
|
|
63
|
-
ran; // false = skipped, which is a NORMAL, healthy outcome
|
|
64
|
-
// The checklist's CONFIGURED globs. The only safe signal for "always runs": a patternless checklist and
|
|
65
|
-
// a skipped one both have an empty `firedPatterns`, and they mean opposite things.
|
|
66
|
-
configuredPatterns;
|
|
67
|
-
firedPatterns; // which configured globs actually hit a changed file
|
|
68
|
-
matchedFiles;
|
|
69
|
-
changedFileCount; // how many files were considered at all — "0 of N" needs the N
|
|
70
|
-
/**
|
|
71
|
-
* Whether this reviewer's own transcript shows it OPENING the extracted diff.
|
|
72
|
-
*
|
|
73
|
-
* '' = not assessed (no Claude Code session, or nothing was materialized) and prints nothing — "no
|
|
74
|
-
* evidence recorded" and "evidence says it never looked" are different claims, and conflating them
|
|
75
|
-
* would accuse a reviewer that ran perfectly well in CI. 'yes' | 'no' otherwise. Defaulted, so every
|
|
76
|
-
* existing construction site is unchanged.
|
|
77
|
-
*/
|
|
78
|
-
diffRead = '';
|
|
79
|
-
// eslint-disable-next-line @typescript-eslint/max-params
|
|
80
|
-
constructor(subagent, status, detail, ran, configuredPatterns, firedPatterns, matchedFiles, changedFileCount) {
|
|
81
|
-
this.subagent = subagent;
|
|
82
|
-
this.status = status;
|
|
83
|
-
this.detail = detail;
|
|
84
|
-
this.ran = ran;
|
|
85
|
-
this.configuredPatterns = configuredPatterns;
|
|
86
|
-
this.firedPatterns = firedPatterns;
|
|
87
|
-
this.matchedFiles = matchedFiles;
|
|
88
|
-
this.changedFileCount = changedFileCount;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
exports.ChecklistCommentRow = ChecklistCommentRow;
|
|
92
50
|
/**
|
|
93
51
|
* One severity bucket of the rolled-up **Checklists** dashboard row: its emoji, the words that describe it,
|
|
94
52
|
* and which checklists landed in it. Data-only.
|
|
@@ -239,11 +197,24 @@ let Dashboard = class Dashboard {
|
|
|
239
197
|
lines.push(this.rosterBullet(row));
|
|
240
198
|
const header = lines.join('\n');
|
|
241
199
|
if (ran.length === 0) {
|
|
242
|
-
return
|
|
243
|
-
`evaluated and none of them applied._`);
|
|
200
|
+
return `${header}\n\n${this.nothingRanNote(rows)}`;
|
|
244
201
|
}
|
|
245
202
|
return this.fitComment(`${header}\n\n### Reviews that ran`, ran.map((r) => this.commentSection(r)));
|
|
246
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* The closing note when no reviewer produced a verdict. The original wording — "every configured
|
|
206
|
+
* checklist was evaluated and none of them applied" — is an all-clear, and it becomes FALSE the moment a
|
|
207
|
+
* checklist did apply and was declined. That sentence under a PR nobody reviewed is precisely the
|
|
208
|
+
* misreport this feature could otherwise introduce, so the declined case gets its own words.
|
|
209
|
+
*/
|
|
210
|
+
nothingRanNote(rows) {
|
|
211
|
+
const declined = rows.filter((r) => this.declined(r));
|
|
212
|
+
if (declined.length === 0) {
|
|
213
|
+
return '_No reviewer had to run on this diff — every configured checklist was evaluated and none of them applied._';
|
|
214
|
+
}
|
|
215
|
+
return (`_No reviewer ran. ${declined.length} OPTIONAL checklist(s) DID apply to this diff and were not ` +
|
|
216
|
+
`run; the rest were evaluated and did not apply._`);
|
|
217
|
+
}
|
|
247
218
|
// The roll-up line. `baseResolved:false` replaces it entirely: with no fork point the changed-file set is
|
|
248
219
|
// EMPTY, so nothing matched — including patternless ALWAYS-RUNS checklists — and reporting that as
|
|
249
220
|
// "all skipped ✅" would post a green all-clear for a PR where nothing was actually evaluated.
|
|
@@ -253,14 +224,19 @@ let Dashboard = class Dashboard {
|
|
|
253
224
|
`_No diff base (fork point of main) could be resolved, so no checklist was matched against ` +
|
|
254
225
|
`anything. This is **not** an all-clear._`);
|
|
255
226
|
}
|
|
256
|
-
const ran = rows.filter((r) => r
|
|
257
|
-
const
|
|
227
|
+
const ran = rows.filter((r) => this.reviewerRan(r));
|
|
228
|
+
const declined = rows.filter((r) => this.declined(r));
|
|
229
|
+
const skipped = rows.length - ran.length - declined.length;
|
|
258
230
|
const parts = [];
|
|
259
231
|
for (const pair of this.rollupCounts(ran))
|
|
260
232
|
parts.push(pair);
|
|
261
233
|
const breakdown = parts.length > 0 ? ` (${parts.join(' · ')})` : '';
|
|
262
234
|
const skip = skipped > 0 ? ` · ${skipped} skipped ✅` : '';
|
|
263
|
-
|
|
235
|
+
// Counted SEPARATELY from "skipped", and without a ✅. A declined optional review is a legitimate
|
|
236
|
+
// outcome, but it is not the same good news as a checklist that had nothing to look at — folding the
|
|
237
|
+
// two together would let a PR that declined every optional review read as fully covered.
|
|
238
|
+
const notRun = declined.length > 0 ? ` · ${declined.length} optional not run` : '';
|
|
239
|
+
return `## 🔍 Company review checklists — ${rows.length} defined · ${ran.length} ran${breakdown}${skip}${notRun}`;
|
|
264
240
|
}
|
|
265
241
|
// `🟢 2 · 🟡 1` — only the non-zero buckets, so a clean run reads as one number rather than four.
|
|
266
242
|
rollupCounts(ran) {
|
|
@@ -277,22 +253,45 @@ let Dashboard = class Dashboard {
|
|
|
277
253
|
// One roster line + its why sub-bullet. A checked box means a reviewer ran; an unchecked one means the
|
|
278
254
|
// checklist was evaluated and did not apply, which the words state as the good news it is.
|
|
279
255
|
rosterBullet(row) {
|
|
280
|
-
const box = row
|
|
281
|
-
return (`${box} ${this.verdictEmoji(row)} **${row.subagent}
|
|
256
|
+
const box = this.reviewerRan(row) ? '- [x]' : '- [ ]';
|
|
257
|
+
return (`${box} ${this.verdictEmoji(row)} **${row.subagent}**${this.optionalTag(row)} — ` +
|
|
258
|
+
`${this.verdictWords(row)}${this.evidenceSuffix(row)}\n` +
|
|
282
259
|
` - ${this.whyLine(row)}`);
|
|
283
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Did a reviewer actually produce a verdict for this row?
|
|
263
|
+
*
|
|
264
|
+
* `row.ran` is really "this checklist APPLIED to the diff" — for a required checklist the two are the
|
|
265
|
+
* same thing, because the PR cannot open otherwise, and the field was named before optional checklists
|
|
266
|
+
* existed. For a DECLINED optional one they diverge, and using `ran` alone would put a checked box and a
|
|
267
|
+
* reviewer section on a review that nobody performed.
|
|
268
|
+
*/
|
|
269
|
+
reviewerRan(row) {
|
|
270
|
+
return row.ran && !this.declined(row);
|
|
271
|
+
}
|
|
272
|
+
// Applied, optional, and carrying no verdict — i.e. the human was offered this review and said no (or
|
|
273
|
+
// `--no-optional` skipped the offer). Never true of a required checklist: one of those with no verdict
|
|
274
|
+
// does not reach a PR at all.
|
|
275
|
+
declined(row) {
|
|
276
|
+
return row.ran && !row.required && (row.status === rules_config_1.CK_MISSING || row.status === '');
|
|
277
|
+
}
|
|
278
|
+
// Marks which rows the human could have declined. Without it a reader cannot tell a review that was
|
|
279
|
+
// skippable from one that simply passed, and so cannot judge how much this PR was actually reviewed.
|
|
280
|
+
optionalTag(row) {
|
|
281
|
+
return row.required ? '' : ' _(optional)_';
|
|
282
|
+
}
|
|
284
283
|
/**
|
|
285
284
|
* Whether the reviewer demonstrably opened the diff, read from its own transcript. A QUALITY signal and
|
|
286
285
|
* never a blocker (see SubagentProvenanceService.evidenceFor) — but published, because "wrote a verdict
|
|
287
286
|
* without reading the change" is exactly what a reader of this comment would want to weigh.
|
|
288
287
|
*/
|
|
289
288
|
evidenceSuffix(row) {
|
|
290
|
-
if (!row
|
|
289
|
+
if (!this.reviewerRan(row) || row.diffRead === '')
|
|
291
290
|
return '';
|
|
292
291
|
return row.diffRead === 'yes' ? ' _(diff read ✓)_' : ' _(⚠️ no diff read recorded)_';
|
|
293
292
|
}
|
|
294
293
|
verdictEmoji(row) {
|
|
295
|
-
if (!row
|
|
294
|
+
if (!this.reviewerRan(row))
|
|
296
295
|
return '⚪';
|
|
297
296
|
if (row.status === rules_config_1.CK_PASS)
|
|
298
297
|
return '🟢';
|
|
@@ -307,6 +306,11 @@ let Dashboard = class Dashboard {
|
|
|
307
306
|
// SHORT words for a roster line / section heading. Short on purpose: the reviewer's own output and any
|
|
308
307
|
// override justification get their own section below, and a roster exists to be scanned.
|
|
309
308
|
verdictWords(row) {
|
|
309
|
+
// Two different unchecked boxes, two different sentences. "Not applicable" is the diff's doing;
|
|
310
|
+
// "not run" is a person's, and reporting the second as the first would quietly credit a review that
|
|
311
|
+
// a human deliberately declined.
|
|
312
|
+
if (this.declined(row))
|
|
313
|
+
return 'OPTIONAL — applied to this diff but was NOT run (not selected)';
|
|
310
314
|
if (!row.ran)
|
|
311
315
|
return 'skipped, not applicable to this diff (expected ✅)';
|
|
312
316
|
if (row.status === rules_config_1.CK_PASS)
|
|
@@ -352,7 +356,7 @@ let Dashboard = class Dashboard {
|
|
|
352
356
|
ranOrdered(rows) {
|
|
353
357
|
const rank = [rules_config_1.CK_OVERRIDDEN, rules_config_1.CK_WARN, rules_config_1.CK_PASS];
|
|
354
358
|
return rows
|
|
355
|
-
.filter((r) => r
|
|
359
|
+
.filter((r) => this.reviewerRan(r))
|
|
356
360
|
.slice()
|
|
357
361
|
.sort((a, b) => this.rankOf(rank, a.status) - this.rankOf(rank, b.status));
|
|
358
362
|
}
|