Skip to content

Commit d9f13ce

Browse files
committed
feat(enrichment): add enum/union exhaustiveness-drift analyzer
Detect switches that covered every old enum or union member but omit a variant newly added by the PR. Fixes #2028
1 parent b98229d commit d9f13ce

10 files changed

Lines changed: 613 additions & 3 deletions

File tree

.env.example

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ GITTENSORY_REVIEW_ENRICHMENT=false
6969
# blameLink,approvalIntegrity,ciCheckSignals,undocumentedExport,staleBranch,commitHygiene
7070
# pendingReviewRequests,testRatio,migrationSafety,looseRange,terminology,todoMarker,magicNumber
7171
# conflictMarker,debugLeftover,sizeSmell,floatingPromise,deepNesting,errorSwallow,unsafeAny,a11y
72-
# i18n,unusedExport,commitLint
72+
# i18n,unusedExport,exhaustiveness,commitLint
7373
#
7474
# Profile defaults:
7575
# fast: dependency,dependencyDiff,lockfileDrift,secret,license,installScript,heavyDependency
@@ -82,14 +82,14 @@ GITTENSORY_REVIEW_ENRICHMENT=false
8282
# churnHotspot,blameLink,approvalIntegrity,ciCheckSignals,undocumentedExport,staleBranch
8383
# commitHygiene,pendingReviewRequests,testRatio,migrationSafety,looseRange,terminology
8484
# todoMarker,magicNumber,conflictMarker,debugLeftover,sizeSmell,floatingPromise,deepNesting
85-
# errorSwallow,unsafeAny,a11y,i18n,unusedExport,commitLint
85+
# errorSwallow,unsafeAny,a11y,i18n,unusedExport,exhaustiveness,commitLint
8686
# deep: dependency,dependencyDiff,lockfileDrift,secret,license,installScript,heavyDependency
8787
# hardcodedUrl,actionPin,eol,redos,provenance,codeowners,secretLog,assetWeight,typosquat
8888
# commitSignature,iacMisconfig,nativeBuild,history,docCommentDrift,duplication,churnHotspot
8989
# blameLink,approvalIntegrity,ciCheckSignals,undocumentedExport,staleBranch,commitHygiene
9090
# pendingReviewRequests,testRatio,migrationSafety,looseRange,terminology,todoMarker,magicNumber
9191
# conflictMarker,debugLeftover,sizeSmell,floatingPromise,deepNesting,errorSwallow,unsafeAny,a11y
92-
# i18n,unusedExport,commitLint
92+
# i18n,unusedExport,exhaustiveness,commitLint
9393
# END GENERATED REES ANALYZERS
9494

9595
# Submitter-reputation spend control (internal-only): downgrades new/burst/low-rep

apps/gittensory-ui/src/lib/rees-analyzers.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,32 @@ export const REES_ANALYZERS = [
11421142
"Conservative: re-export lists and `export *` are ignored (same as undocumented-export). Skips symbols shorter than 3 chars. Checks same-file references in the headSha file before querying default-branch Code Search (where brand-new PR exports are usually absent). Fail-safe on search errors or incomplete results.",
11431143
},
11441144
},
1145+
{
1146+
name: "exhaustiveness",
1147+
title: "Enum/union exhaustiveness drift",
1148+
category: "quality",
1149+
cost: "github-light",
1150+
defaultEnabled: true,
1151+
profiles: ["balanced", "deep"],
1152+
requires: ["files", "github-token", "head-sha"],
1153+
limits: {
1154+
maxFiles: 10,
1155+
maxFetches: 10,
1156+
maxFindings: 25,
1157+
},
1158+
docs: {
1159+
summary:
1160+
"Flags when a PR adds a new enum member or string-literal union variant but an exhaustive switch still omits it.",
1161+
looksAt:
1162+
"Added enum/union members in changed TS/JS files, comparing pre-PR vs headSha member sets and scanning changed files for switches that covered all old members.",
1163+
reports:
1164+
"Type file, line, union/enum name, added member, and optional consumer file — never file contents.",
1165+
network:
1166+
"Bounded GitHub contents fetches at headSha for changed source files. Requires GitHub token forwarding for private repos.",
1167+
notes:
1168+
"Conservative: only explicit enum/union case labels; switches with a default branch are skipped. Fail-safe on fetch errors or ambiguous type parsing.",
1169+
},
1170+
},
11451171
{
11461172
name: "commitLint",
11471173
title: "Conventional-commit subjects",

review-enrichment/analyzer-metadata.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,6 +1293,34 @@
12931293
"notes": "Conservative: re-export lists and `export *` are ignored (same as undocumented-export). Skips symbols shorter than 3 chars. Checks same-file references in the headSha file before querying default-branch Code Search (where brand-new PR exports are usually absent). Fail-safe on search errors or incomplete results."
12941294
}
12951295
},
1296+
{
1297+
"name": "exhaustiveness",
1298+
"title": "Enum/union exhaustiveness drift",
1299+
"category": "quality",
1300+
"cost": "github-light",
1301+
"defaultEnabled": true,
1302+
"profiles": [
1303+
"balanced",
1304+
"deep"
1305+
],
1306+
"requires": [
1307+
"files",
1308+
"github-token",
1309+
"head-sha"
1310+
],
1311+
"limits": {
1312+
"maxFiles": 10,
1313+
"maxFetches": 10,
1314+
"maxFindings": 25
1315+
},
1316+
"docs": {
1317+
"summary": "Flags when a PR adds a new enum member or string-literal union variant but an exhaustive switch still omits it.",
1318+
"looksAt": "Added enum/union members in changed TS/JS files, comparing pre-PR vs headSha member sets and scanning changed files for switches that covered all old members.",
1319+
"reports": "Type file, line, union/enum name, added member, and optional consumer file — never file contents.",
1320+
"network": "Bounded GitHub contents fetches at headSha for changed source files. Requires GitHub token forwarding for private repos.",
1321+
"notes": "Conservative: only explicit enum/union case labels; switches with a default branch are skipped. Fail-safe on fetch errors or ambiguous type parsing."
1322+
}
1323+
},
12961324
{
12971325
"name": "commitLint",
12981326
"title": "Conventional-commit subjects",

0 commit comments

Comments
 (0)