@kevinrabun/judges 3.98.0 → 3.100.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +126 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/finding-auto-suppress.d.ts +5 -0
- package/dist/commands/finding-auto-suppress.d.ts.map +1 -0
- package/dist/commands/finding-auto-suppress.js +127 -0
- package/dist/commands/finding-auto-suppress.js.map +1 -0
- package/dist/commands/finding-auto-triage.d.ts +5 -0
- package/dist/commands/finding-auto-triage.d.ts.map +1 -0
- package/dist/commands/finding-auto-triage.js +109 -0
- package/dist/commands/finding-auto-triage.js.map +1 -0
- package/dist/commands/finding-change-impact.d.ts +5 -0
- package/dist/commands/finding-change-impact.d.ts.map +1 -0
- package/dist/commands/finding-change-impact.js +108 -0
- package/dist/commands/finding-change-impact.js.map +1 -0
- package/dist/commands/finding-context-enrich.d.ts +5 -0
- package/dist/commands/finding-context-enrich.d.ts.map +1 -0
- package/dist/commands/finding-context-enrich.js +90 -0
- package/dist/commands/finding-context-enrich.js.map +1 -0
- package/dist/commands/finding-dismiss-workflow.d.ts +5 -0
- package/dist/commands/finding-dismiss-workflow.d.ts.map +1 -0
- package/dist/commands/finding-dismiss-workflow.js +120 -0
- package/dist/commands/finding-dismiss-workflow.js.map +1 -0
- package/dist/commands/finding-false-positive-learn.d.ts +5 -0
- package/dist/commands/finding-false-positive-learn.d.ts.map +1 -0
- package/dist/commands/finding-false-positive-learn.js +86 -0
- package/dist/commands/finding-false-positive-learn.js.map +1 -0
- package/dist/commands/finding-reachability-check.d.ts +5 -0
- package/dist/commands/finding-reachability-check.d.ts.map +1 -0
- package/dist/commands/finding-reachability-check.js +103 -0
- package/dist/commands/finding-reachability-check.js.map +1 -0
- package/dist/commands/review-audit-export.d.ts +5 -0
- package/dist/commands/review-audit-export.d.ts.map +1 -0
- package/dist/commands/review-audit-export.js +94 -0
- package/dist/commands/review-audit-export.js.map +1 -0
- package/dist/commands/review-data-retention.d.ts +5 -0
- package/dist/commands/review-data-retention.d.ts.map +1 -0
- package/dist/commands/review-data-retention.js +120 -0
- package/dist/commands/review-data-retention.js.map +1 -0
- package/dist/commands/review-deployment-gate.d.ts +5 -0
- package/dist/commands/review-deployment-gate.d.ts.map +1 -0
- package/dist/commands/review-deployment-gate.js +95 -0
- package/dist/commands/review-deployment-gate.js.map +1 -0
- package/dist/commands/review-environment-config.d.ts +5 -0
- package/dist/commands/review-environment-config.d.ts.map +1 -0
- package/dist/commands/review-environment-config.js +103 -0
- package/dist/commands/review-environment-config.js.map +1 -0
- package/dist/commands/review-multi-repo-sync.d.ts +5 -0
- package/dist/commands/review-multi-repo-sync.d.ts.map +1 -0
- package/dist/commands/review-multi-repo-sync.js +116 -0
- package/dist/commands/review-multi-repo-sync.js.map +1 -0
- package/dist/commands/review-permission-model.d.ts +5 -0
- package/dist/commands/review-permission-model.d.ts.map +1 -0
- package/dist/commands/review-permission-model.js +150 -0
- package/dist/commands/review-permission-model.js.map +1 -0
- package/dist/commands/review-pipeline-status.d.ts +5 -0
- package/dist/commands/review-pipeline-status.d.ts.map +1 -0
- package/dist/commands/review-pipeline-status.js +55 -0
- package/dist/commands/review-pipeline-status.js.map +1 -0
- package/dist/commands/review-repo-onboard.d.ts +5 -0
- package/dist/commands/review-repo-onboard.d.ts.map +1 -0
- package/dist/commands/review-repo-onboard.js +115 -0
- package/dist/commands/review-repo-onboard.js.map +1 -0
- package/dist/commands/review-review-comments.d.ts +5 -0
- package/dist/commands/review-review-comments.d.ts.map +1 -0
- package/dist/commands/review-review-comments.js +85 -0
- package/dist/commands/review-review-comments.js.map +1 -0
- package/dist/commands/review-session-replay.d.ts +5 -0
- package/dist/commands/review-session-replay.d.ts.map +1 -0
- package/dist/commands/review-session-replay.js +82 -0
- package/dist/commands/review-session-replay.js.map +1 -0
- package/dist/commands/review-stakeholder-report.d.ts +5 -0
- package/dist/commands/review-stakeholder-report.d.ts.map +1 -0
- package/dist/commands/review-stakeholder-report.js +76 -0
- package/dist/commands/review-stakeholder-report.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding-dismiss-workflow.js","sourceRoot":"","sources":["../../src/commands/finding-dismiss-workflow.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAkB7D,+EAA+E;AAE/E,MAAM,UAAU,yBAAyB,CAAC,IAAc;IACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC;IACjF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAE9D,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;CAmBf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,IAAI,KAAqB,CAAC;IAC1B,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAmB,CAAC;IACzE,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,CAAC;IAED,UAAU;IACV,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7C,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QACpC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAE7C,MAAM,SAAS,GAAc;YAC3B,MAAM;YACN,MAAM,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAwB;YACvF,WAAW,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;YACrD,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACnD,SAAS,EAAE,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY;YAChE,IAAI,EAAE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;SAC5C,CAAC;QAEF,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACjC,KAAK,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,KAAK,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;QAC1D,OAAO;IACT,CAAC;IAED,SAAS;IACT,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC;QACvC,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QACvE,KAAK,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,sBAAsB,MAAM,EAAE,CAAC,CAAC;QACvF,OAAO;IACT,CAAC;IAED,YAAY;IACZ,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,KAAK,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC;QAEpE,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC1D,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAE5B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACzB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;gBACvB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,QAAQ,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC;gBAC/F,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC1B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,aAAa,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,MAAM,eAAe,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,OAAO;IACP,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;IACrE,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding-false-positive-learn.d.ts","sourceRoot":"","sources":["../../src/commands/finding-false-positive-learn.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqBH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAuFjE"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding-false-positive-learn — Track false positive patterns to improve future triage.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
5
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
6
|
+
export function runFindingFalsePositiveLearn(argv) {
|
|
7
|
+
const storeIdx = argv.indexOf("--store");
|
|
8
|
+
const storePath = storeIdx >= 0 ? argv[storeIdx + 1] : ".judges-false-positives.json";
|
|
9
|
+
const formatIdx = argv.indexOf("--format");
|
|
10
|
+
const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
|
|
11
|
+
const addMode = argv.includes("--add");
|
|
12
|
+
const ruleIdx = argv.indexOf("--rule");
|
|
13
|
+
const ruleId = ruleIdx >= 0 ? argv[ruleIdx + 1] : "";
|
|
14
|
+
const patternIdx = argv.indexOf("--pattern");
|
|
15
|
+
const pattern = patternIdx >= 0 ? argv[patternIdx + 1] : "";
|
|
16
|
+
const reasonIdx = argv.indexOf("--reason");
|
|
17
|
+
const reason = reasonIdx >= 0 ? argv[reasonIdx + 1] : "";
|
|
18
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
19
|
+
console.log(`
|
|
20
|
+
judges finding-false-positive-learn — Track false positive patterns
|
|
21
|
+
|
|
22
|
+
Usage:
|
|
23
|
+
judges finding-false-positive-learn [--store <path>] [--format table|json]
|
|
24
|
+
judges finding-false-positive-learn --add --rule <id> --pattern <pat> --reason <text> [--store <path>]
|
|
25
|
+
|
|
26
|
+
Options:
|
|
27
|
+
--store <path> FP store file (default: .judges-false-positives.json)
|
|
28
|
+
--add Add a new false positive pattern
|
|
29
|
+
--rule <id> Rule ID of the false positive
|
|
30
|
+
--pattern <pat> Code pattern that triggers the FP
|
|
31
|
+
--reason <text> Why this is a false positive
|
|
32
|
+
--format <fmt> Output format: table (default), json
|
|
33
|
+
--help, -h Show this help
|
|
34
|
+
`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const store = existsSync(storePath)
|
|
38
|
+
? JSON.parse(readFileSync(storePath, "utf-8"))
|
|
39
|
+
: { entries: [], lastUpdated: new Date().toISOString() };
|
|
40
|
+
if (addMode) {
|
|
41
|
+
if (!ruleId || !pattern || !reason) {
|
|
42
|
+
console.error("Provide --rule, --pattern, and --reason when using --add.");
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const existing = store.entries.find((e) => e.ruleId === ruleId && e.pattern === pattern);
|
|
47
|
+
if (existing) {
|
|
48
|
+
existing.occurrences += 1;
|
|
49
|
+
existing.reason = reason;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
store.entries.push({
|
|
53
|
+
ruleId,
|
|
54
|
+
pattern,
|
|
55
|
+
reason,
|
|
56
|
+
reportedAt: new Date().toISOString(),
|
|
57
|
+
occurrences: 1,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
store.lastUpdated = new Date().toISOString();
|
|
61
|
+
writeFileSync(storePath, JSON.stringify(store, null, 2));
|
|
62
|
+
console.log(`Recorded false positive pattern for ${ruleId}.`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (format === "json") {
|
|
66
|
+
console.log(JSON.stringify(store, null, 2));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
console.log("\nFalse Positive Patterns");
|
|
70
|
+
console.log("═".repeat(80));
|
|
71
|
+
if (store.entries.length === 0) {
|
|
72
|
+
console.log(" No false positive patterns recorded yet.");
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
console.log(` ${"Rule ID".padEnd(25)} ${"Pattern".padEnd(20)} ${"Count".padEnd(8)} Reason`);
|
|
76
|
+
console.log(" " + "─".repeat(75));
|
|
77
|
+
for (const e of store.entries) {
|
|
78
|
+
const pat = e.pattern.length > 18 ? e.pattern.slice(0, 15) + "..." : e.pattern;
|
|
79
|
+
const rsn = e.reason.length > 25 ? e.reason.slice(0, 22) + "..." : e.reason;
|
|
80
|
+
console.log(` ${e.ruleId.padEnd(25)} ${pat.padEnd(20)} ${String(e.occurrences).padEnd(8)} ${rsn}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
console.log(`\n Total patterns: ${store.entries.length}`);
|
|
84
|
+
console.log("═".repeat(80));
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=finding-false-positive-learn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding-false-positive-learn.js","sourceRoot":"","sources":["../../src/commands/finding-false-positive-learn.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding-reachability-check.d.ts","sourceRoot":"","sources":["../../src/commands/finding-reachability-check.ts"],"names":[],"mappings":"AAAA;;GAEG;AAkBH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAyGhE"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding-reachability-check — Check if findings affect reachable code paths.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, existsSync } from "fs";
|
|
5
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
6
|
+
export function runFindingReachabilityCheck(argv) {
|
|
7
|
+
const reportIdx = argv.indexOf("--report");
|
|
8
|
+
const sourceIdx = argv.indexOf("--source");
|
|
9
|
+
const formatIdx = argv.indexOf("--format");
|
|
10
|
+
const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
|
|
11
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
12
|
+
console.log(`
|
|
13
|
+
judges finding-reachability-check — Check finding reachability
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
judges finding-reachability-check --report <path> [--source <path>]
|
|
17
|
+
[--format table|json]
|
|
18
|
+
|
|
19
|
+
Options:
|
|
20
|
+
--report <path> Report file with findings
|
|
21
|
+
--source <path> Source file to check reachability against
|
|
22
|
+
--format <fmt> Output format: table (default), json
|
|
23
|
+
--help, -h Show this help
|
|
24
|
+
|
|
25
|
+
Checks if findings reference code that is reachable in the source.
|
|
26
|
+
`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (reportIdx < 0) {
|
|
30
|
+
console.error("Missing --report <path>");
|
|
31
|
+
process.exitCode = 1;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const reportPath = argv[reportIdx + 1];
|
|
35
|
+
if (!existsSync(reportPath)) {
|
|
36
|
+
console.error(`Report not found: ${reportPath}`);
|
|
37
|
+
process.exitCode = 1;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const report = JSON.parse(readFileSync(reportPath, "utf-8"));
|
|
41
|
+
const findings = report.findings ?? [];
|
|
42
|
+
let sourceLines = [];
|
|
43
|
+
if (sourceIdx >= 0) {
|
|
44
|
+
const sourcePath = argv[sourceIdx + 1];
|
|
45
|
+
if (existsSync(sourcePath)) {
|
|
46
|
+
sourceLines = readFileSync(sourcePath, "utf-8").split("\n");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const results = findings.map((f) => {
|
|
50
|
+
const lines = f.lineNumbers ?? [];
|
|
51
|
+
let reachable = true;
|
|
52
|
+
let reason = "assumed reachable";
|
|
53
|
+
if (sourceLines.length > 0 && lines.length > 0) {
|
|
54
|
+
// Check if the referenced lines exist and are not commented out
|
|
55
|
+
const referencedLine = lines[0] - 1;
|
|
56
|
+
if (referencedLine >= 0 && referencedLine < sourceLines.length) {
|
|
57
|
+
const line = sourceLines[referencedLine].trim();
|
|
58
|
+
if (line.startsWith("//") || line.startsWith("/*") || line.startsWith("#") || line.startsWith("*")) {
|
|
59
|
+
reachable = false;
|
|
60
|
+
reason = "line is commented out";
|
|
61
|
+
}
|
|
62
|
+
else if (line.length === 0) {
|
|
63
|
+
reachable = false;
|
|
64
|
+
reason = "line is empty";
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
reason = "line exists and is active code";
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
reachable = false;
|
|
72
|
+
reason = "line number out of range";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else if (lines.length === 0) {
|
|
76
|
+
reason = "no line reference — assumed reachable";
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
ruleId: f.ruleId,
|
|
80
|
+
title: f.title,
|
|
81
|
+
severity: f.severity,
|
|
82
|
+
reachable,
|
|
83
|
+
reason,
|
|
84
|
+
lineNumbers: lines,
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
if (format === "json") {
|
|
88
|
+
console.log(JSON.stringify(results, null, 2));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
console.log(`\nReachability Check`);
|
|
92
|
+
console.log("═".repeat(70));
|
|
93
|
+
const reachableCount = results.filter((r) => r.reachable).length;
|
|
94
|
+
const unreachableCount = results.filter((r) => !r.reachable).length;
|
|
95
|
+
for (const r of results) {
|
|
96
|
+
const status = r.reachable ? "REACHABLE" : "UNREACHABLE";
|
|
97
|
+
const lineRef = r.lineNumbers.length > 0 ? `L${r.lineNumbers[0]}` : "N/A";
|
|
98
|
+
console.log(` [${status.padEnd(11)}] ${r.ruleId.padEnd(25)} ${lineRef.padEnd(8)} ${r.reason}`);
|
|
99
|
+
}
|
|
100
|
+
console.log(`\n Reachable: ${reachableCount} | Unreachable: ${unreachableCount} | Total: ${results.length}`);
|
|
101
|
+
console.log("═".repeat(70));
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=finding-reachability-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding-reachability-check.js","sourceRoot":"","sources":["../../src/commands/finding-reachability-check.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAc9C,+EAA+E;AAE/E,MAAM,UAAU,2BAA2B,CAAC,IAAc;IACxD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAE9D,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;CAcf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACzC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;IACvC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,qBAAqB,UAAU,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAA6B,CAAC;IACzF,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;IAEvC,IAAI,WAAW,GAAa,EAAE,CAAC;IAC/B,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACnB,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QACvC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,WAAW,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAyB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACvD,MAAM,KAAK,GAAG,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC;QAClC,IAAI,SAAS,GAAG,IAAI,CAAC;QACrB,IAAI,MAAM,GAAG,mBAAmB,CAAC;QAEjC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/C,gEAAgE;YAChE,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,cAAc,IAAI,CAAC,IAAI,cAAc,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC;gBAC/D,MAAM,IAAI,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC,IAAI,EAAE,CAAC;gBAChD,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACnG,SAAS,GAAG,KAAK,CAAC;oBAClB,MAAM,GAAG,uBAAuB,CAAC;gBACnC,CAAC;qBAAM,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC7B,SAAS,GAAG,KAAK,CAAC;oBAClB,MAAM,GAAG,eAAe,CAAC;gBAC3B,CAAC;qBAAM,CAAC;oBACN,MAAM,GAAG,gCAAgC,CAAC;gBAC5C,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,SAAS,GAAG,KAAK,CAAC;gBAClB,MAAM,GAAG,0BAA0B,CAAC;YACtC,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,GAAG,uCAAuC,CAAC;QACnD,CAAC;QAED,OAAO;YACL,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,SAAS;YACT,MAAM;YACN,WAAW,EAAE,KAAK;SACnB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;IACjE,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;IAEpE,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC;QACzD,MAAM,OAAO,GAAG,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAClG,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,kBAAkB,cAAc,mBAAmB,gBAAgB,aAAa,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9G,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-audit-export.d.ts","sourceRoot":"","sources":["../../src/commands/review-audit-export.ts"],"names":[],"mappings":"AAAA;;GAEG;AAuBH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAiGzD"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review-audit-export — Export audit data for external compliance tools.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, readdirSync } from "fs";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
7
|
+
export function runReviewAuditExport(argv) {
|
|
8
|
+
const dirIdx = argv.indexOf("--dir");
|
|
9
|
+
const dir = dirIdx >= 0 ? argv[dirIdx + 1] : ".judges/audit";
|
|
10
|
+
const outIdx = argv.indexOf("--out");
|
|
11
|
+
const exportFormat = argv.indexOf("--export-format");
|
|
12
|
+
const expFmt = exportFormat >= 0 ? argv[exportFormat + 1] : "json";
|
|
13
|
+
const formatIdx = argv.indexOf("--format");
|
|
14
|
+
const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
|
|
15
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
16
|
+
console.log(`
|
|
17
|
+
judges review-audit-export — Export audit data
|
|
18
|
+
|
|
19
|
+
Usage:
|
|
20
|
+
judges review-audit-export [--dir <path>] [--out <path>]
|
|
21
|
+
[--export-format json|csv]
|
|
22
|
+
[--format table|json]
|
|
23
|
+
|
|
24
|
+
Options:
|
|
25
|
+
--dir <path> Audit data directory (default: .judges/audit)
|
|
26
|
+
--out <path> Write export to file
|
|
27
|
+
--export-format <fmt> Export format: json (default), csv
|
|
28
|
+
--format <fmt> Display format: table (default), json
|
|
29
|
+
--help, -h Show this help
|
|
30
|
+
`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (!existsSync(dir)) {
|
|
34
|
+
console.log(`Audit directory not found: ${dir}`);
|
|
35
|
+
console.log("No audit data to export.");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const files = readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
39
|
+
const records = [];
|
|
40
|
+
for (const file of files) {
|
|
41
|
+
const content = JSON.parse(readFileSync(join(dir, file), "utf-8"));
|
|
42
|
+
if (Array.isArray(content)) {
|
|
43
|
+
records.push(...content);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
records.push(content);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
records.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
|
|
50
|
+
const byAction = {};
|
|
51
|
+
for (const r of records) {
|
|
52
|
+
byAction[r.action] = (byAction[r.action] ?? 0) + 1;
|
|
53
|
+
}
|
|
54
|
+
const auditExport = {
|
|
55
|
+
exportedAt: new Date().toISOString(),
|
|
56
|
+
records,
|
|
57
|
+
summary: { total: records.length, byAction },
|
|
58
|
+
};
|
|
59
|
+
// Write to file
|
|
60
|
+
if (outIdx >= 0) {
|
|
61
|
+
const outPath = argv[outIdx + 1];
|
|
62
|
+
if (expFmt === "csv") {
|
|
63
|
+
const header = "timestamp,action,actor,detail,source";
|
|
64
|
+
const rows = records.map((r) => `"${r.timestamp}","${r.action}","${r.actor}","${r.detail}","${r.source}"`);
|
|
65
|
+
writeFileSync(outPath, [header, ...rows].join("\n"));
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
writeFileSync(outPath, JSON.stringify(auditExport, null, 2));
|
|
69
|
+
}
|
|
70
|
+
console.log(`Audit exported to: ${outPath} (${expFmt}, ${records.length} records)`);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (format === "json") {
|
|
74
|
+
console.log(JSON.stringify(auditExport, null, 2));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
console.log(`\nAudit Export`);
|
|
78
|
+
console.log("═".repeat(70));
|
|
79
|
+
console.log(` Records: ${records.length}`);
|
|
80
|
+
if (Object.keys(byAction).length > 0) {
|
|
81
|
+
console.log(" By action:");
|
|
82
|
+
for (const [action, count] of Object.entries(byAction)) {
|
|
83
|
+
console.log(` ${action.padEnd(20)} ${count}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (records.length > 0) {
|
|
87
|
+
console.log(`\n Latest records:`);
|
|
88
|
+
for (const r of records.slice(-5)) {
|
|
89
|
+
console.log(` ${r.timestamp.padEnd(22)} ${r.action.padEnd(15)} ${r.actor}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
console.log("═".repeat(70));
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=review-audit-export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-audit-export.js","sourceRoot":"","sources":["../../src/commands/review-audit-export.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-data-retention.d.ts","sourceRoot":"","sources":["../../src/commands/review-data-retention.ts"],"names":[],"mappings":"AAAA;;GAEG;AA2BH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmH3D"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review-data-retention — Configure data retention policies for review data.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, readdirSync, unlinkSync } from "fs";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
const DEFAULT_POLICIES = [
|
|
7
|
+
{ dataType: "reports", retentionDays: 90, autoClean: false },
|
|
8
|
+
{ dataType: "cache", retentionDays: 30, autoClean: true },
|
|
9
|
+
{ dataType: "annotations", retentionDays: 365, autoClean: false },
|
|
10
|
+
{ dataType: "dismissals", retentionDays: 180, autoClean: false },
|
|
11
|
+
];
|
|
12
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
13
|
+
export function runReviewDataRetention(argv) {
|
|
14
|
+
const storeIdx = argv.indexOf("--store");
|
|
15
|
+
const storePath = storeIdx >= 0 ? argv[storeIdx + 1] : ".judges-retention.json";
|
|
16
|
+
const formatIdx = argv.indexOf("--format");
|
|
17
|
+
const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
|
|
18
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
19
|
+
console.log(`
|
|
20
|
+
judges review-data-retention — Configure data retention policies
|
|
21
|
+
|
|
22
|
+
Usage:
|
|
23
|
+
judges review-data-retention [--store <path>] [--init] [--set <json>]
|
|
24
|
+
[--clean <dir>] [--format table|json]
|
|
25
|
+
|
|
26
|
+
Options:
|
|
27
|
+
--store <path> Retention config file (default: .judges-retention.json)
|
|
28
|
+
--init Initialize with default retention policies
|
|
29
|
+
--set <json> Set retention policy (JSON)
|
|
30
|
+
--clean <dir> Run cleanup on directory based on retention policy
|
|
31
|
+
--format <fmt> Output format: table (default), json
|
|
32
|
+
--help, -h Show this help
|
|
33
|
+
`);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
// Init
|
|
37
|
+
if (argv.includes("--init")) {
|
|
38
|
+
const store = {
|
|
39
|
+
policies: DEFAULT_POLICIES,
|
|
40
|
+
lastUpdated: new Date().toISOString().split("T")[0],
|
|
41
|
+
};
|
|
42
|
+
writeFileSync(storePath, JSON.stringify(store, null, 2));
|
|
43
|
+
console.log(`Retention policies initialized at: ${storePath}`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
let store;
|
|
47
|
+
if (existsSync(storePath)) {
|
|
48
|
+
store = JSON.parse(readFileSync(storePath, "utf-8"));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
store = { policies: [], lastUpdated: new Date().toISOString().split("T")[0] };
|
|
52
|
+
}
|
|
53
|
+
// Set policy
|
|
54
|
+
const setIdx = argv.indexOf("--set");
|
|
55
|
+
if (setIdx >= 0) {
|
|
56
|
+
const policy = JSON.parse(argv[setIdx + 1]);
|
|
57
|
+
const existingIdx = store.policies.findIndex((p) => p.dataType === policy.dataType);
|
|
58
|
+
if (existingIdx >= 0) {
|
|
59
|
+
store.policies[existingIdx] = policy;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
store.policies.push(policy);
|
|
63
|
+
}
|
|
64
|
+
store.lastUpdated = new Date().toISOString().split("T")[0];
|
|
65
|
+
writeFileSync(storePath, JSON.stringify(store, null, 2));
|
|
66
|
+
console.log(`Retention policy for "${policy.dataType}" saved.`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Clean
|
|
70
|
+
const cleanIdx = argv.indexOf("--clean");
|
|
71
|
+
if (cleanIdx >= 0) {
|
|
72
|
+
const cleanDir = argv[cleanIdx + 1];
|
|
73
|
+
if (!existsSync(cleanDir)) {
|
|
74
|
+
console.log(`Directory not found: ${cleanDir}`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const files = readdirSync(cleanDir).filter((f) => f.endsWith(".json"));
|
|
78
|
+
const cutoffMs = 30 * 24 * 60 * 60 * 1000; // Default 30 days
|
|
79
|
+
const now = Date.now();
|
|
80
|
+
let cleaned = 0;
|
|
81
|
+
for (const file of files) {
|
|
82
|
+
const filePath = join(cleanDir, file);
|
|
83
|
+
try {
|
|
84
|
+
const content = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
85
|
+
if (content.timestamp !== undefined) {
|
|
86
|
+
const fileTime = new Date(content.timestamp).getTime();
|
|
87
|
+
if (now - fileTime > cutoffMs) {
|
|
88
|
+
unlinkSync(filePath);
|
|
89
|
+
cleaned++;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Skip files that can't be parsed
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
console.log(`Cleaned ${cleaned} file(s) from ${cleanDir}`);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Display
|
|
101
|
+
if (format === "json") {
|
|
102
|
+
console.log(JSON.stringify(store, null, 2));
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
console.log(`\nData Retention Policies`);
|
|
106
|
+
console.log("═".repeat(55));
|
|
107
|
+
if (store.policies.length === 0) {
|
|
108
|
+
console.log(" No retention policies. Use --init for defaults.");
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
console.log(` ${"Data Type".padEnd(15)} ${"Retention".padEnd(12)} Auto-clean`);
|
|
112
|
+
console.log(" " + "─".repeat(40));
|
|
113
|
+
for (const p of store.policies) {
|
|
114
|
+
const retention = p.retentionDays < 365 ? `${p.retentionDays}d` : `${Math.round(p.retentionDays / 365)}y`;
|
|
115
|
+
console.log(` ${p.dataType.padEnd(15)} ${retention.padEnd(12)} ${p.autoClean ? "Yes" : "No"}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
console.log("═".repeat(55));
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=review-data-retention.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-data-retention.js","sourceRoot":"","sources":["../../src/commands/review-data-retention.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-deployment-gate.d.ts","sourceRoot":"","sources":["../../src/commands/review-deployment-gate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiDH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAkF5D"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review-deployment-gate — Configure deployment gates based on review thresholds.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
5
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
6
|
+
function evaluateGate(rule, metrics) {
|
|
7
|
+
const actual = metrics[rule.metric] ?? 0;
|
|
8
|
+
let passed = false;
|
|
9
|
+
if (rule.operator === "gte")
|
|
10
|
+
passed = actual >= rule.threshold;
|
|
11
|
+
else if (rule.operator === "lte")
|
|
12
|
+
passed = actual <= rule.threshold;
|
|
13
|
+
else if (rule.operator === "eq")
|
|
14
|
+
passed = actual === rule.threshold;
|
|
15
|
+
return {
|
|
16
|
+
name: rule.name,
|
|
17
|
+
metric: rule.metric,
|
|
18
|
+
threshold: rule.threshold,
|
|
19
|
+
actual,
|
|
20
|
+
passed,
|
|
21
|
+
blocking: rule.blocking,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
25
|
+
export function runReviewDeploymentGate(argv) {
|
|
26
|
+
const configIdx = argv.indexOf("--config");
|
|
27
|
+
const configPath = configIdx >= 0 ? argv[configIdx + 1] : ".judges-deployment-gate.json";
|
|
28
|
+
const metricsIdx = argv.indexOf("--metrics");
|
|
29
|
+
const metricsPath = metricsIdx >= 0 ? argv[metricsIdx + 1] : "";
|
|
30
|
+
const formatIdx = argv.indexOf("--format");
|
|
31
|
+
const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
|
|
32
|
+
const initMode = argv.includes("--init");
|
|
33
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
34
|
+
console.log(`
|
|
35
|
+
judges review-deployment-gate — Configure deployment gates
|
|
36
|
+
|
|
37
|
+
Usage:
|
|
38
|
+
judges review-deployment-gate --metrics <path> [--config <path>] [--format table|json]
|
|
39
|
+
judges review-deployment-gate --init [--config <path>]
|
|
40
|
+
|
|
41
|
+
Options:
|
|
42
|
+
--metrics <path> Path to metrics JSON ({score, criticalCount, highCount, totalFindings})
|
|
43
|
+
--config <path> Gate config file (default: .judges-deployment-gate.json)
|
|
44
|
+
--init Create default gate config
|
|
45
|
+
--format <fmt> Output format: table (default), json
|
|
46
|
+
--help, -h Show this help
|
|
47
|
+
`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (initMode) {
|
|
51
|
+
const defaultConfig = {
|
|
52
|
+
gates: [
|
|
53
|
+
{ name: "Min Score", metric: "score", operator: "gte", threshold: 70, blocking: true },
|
|
54
|
+
{ name: "No Criticals", metric: "criticalCount", operator: "lte", threshold: 0, blocking: true },
|
|
55
|
+
{ name: "Max High", metric: "highCount", operator: "lte", threshold: 3, blocking: false },
|
|
56
|
+
],
|
|
57
|
+
lastUpdated: new Date().toISOString(),
|
|
58
|
+
};
|
|
59
|
+
writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
|
|
60
|
+
console.log(`Created default gate config: ${configPath}`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (!metricsPath || !existsSync(metricsPath)) {
|
|
64
|
+
console.error("Provide --metrics <path> to a valid metrics JSON file.");
|
|
65
|
+
process.exitCode = 1;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (!existsSync(configPath)) {
|
|
69
|
+
console.error(`Gate config not found: ${configPath}. Run with --init to create one.`);
|
|
70
|
+
process.exitCode = 1;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const metrics = JSON.parse(readFileSync(metricsPath, "utf-8"));
|
|
74
|
+
const config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
75
|
+
const results = config.gates.map((g) => evaluateGate(g, metrics));
|
|
76
|
+
if (format === "json") {
|
|
77
|
+
console.log(JSON.stringify(results, null, 2));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const allPassed = results.every((r) => r.passed || !r.blocking);
|
|
81
|
+
console.log(`\nDeployment Gate Evaluation`);
|
|
82
|
+
console.log("═".repeat(70));
|
|
83
|
+
console.log(` ${"Gate".padEnd(20)} ${"Metric".padEnd(18)} ${"Threshold".padEnd(12)} ${"Actual".padEnd(10)} Result`);
|
|
84
|
+
console.log(" " + "─".repeat(65));
|
|
85
|
+
for (const r of results) {
|
|
86
|
+
const status = r.passed ? "PASS" : r.blocking ? "BLOCK" : "WARN";
|
|
87
|
+
console.log(` ${r.name.padEnd(20)} ${r.metric.padEnd(18)} ${String(r.threshold).padEnd(12)} ${String(r.actual).padEnd(10)} ${status}`);
|
|
88
|
+
}
|
|
89
|
+
console.log(`\n Overall: ${allPassed ? "DEPLOY ALLOWED" : "DEPLOY BLOCKED"}`);
|
|
90
|
+
console.log("═".repeat(70));
|
|
91
|
+
if (!allPassed) {
|
|
92
|
+
process.exitCode = 1;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=review-deployment-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-deployment-gate.js","sourceRoot":"","sources":["../../src/commands/review-deployment-gate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AA0B7D,+EAA+E;AAE/E,SAAS,YAAY,CAAC,IAAc,EAAE,OAA+B;IACnE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK;QAAE,MAAM,GAAG,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC;SAC1D,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK;QAAE,MAAM,GAAG,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC;SAC/D,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;QAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC;IAEpE,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,MAAM;QACN,MAAM;QACN,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAC;AACJ,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,uBAAuB,CAAC,IAAc;IACpD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,8BAA8B,CAAC;IACzF,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAChE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEzC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;CAaf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,aAAa,GAAe;YAChC,KAAK,EAAE;gBACL,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBACtF,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAChG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE;aAC1F;YACD,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACtC,CAAC;QACF,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,gCAAgC,UAAU,EAAE,CAAC,CAAC;QAC1D,OAAO;IACT,CAAC;IAED,IAAI,CAAC,WAAW,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,0BAA0B,UAAU,kCAAkC,CAAC,CAAC;QACtF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAA2B,CAAC;IACzF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAe,CAAC;IAC3E,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAElE,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAEhE,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;IACrH,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAEnC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QACjE,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,EAAE,CAC3H,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,gBAAgB,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC/E,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-environment-config.d.ts","sourceRoot":"","sources":["../../src/commands/review-environment-config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAsBH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA8G/D"}
|