@behavioral-contracts/verify-cli 1.1.0 → 1.2.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.
Files changed (47) hide show
  1. package/dist/ai-prompt-generator.d.ts +16 -0
  2. package/dist/ai-prompt-generator.d.ts.map +1 -0
  3. package/dist/ai-prompt-generator.js +481 -0
  4. package/dist/ai-prompt-generator.js.map +1 -0
  5. package/dist/analyzer.d.ts +41 -0
  6. package/dist/analyzer.d.ts.map +1 -1
  7. package/dist/analyzer.js +93 -1
  8. package/dist/analyzer.js.map +1 -1
  9. package/dist/analyzers/event-listener-analyzer.d.ts +39 -4
  10. package/dist/analyzers/event-listener-analyzer.d.ts.map +1 -1
  11. package/dist/analyzers/event-listener-analyzer.js +123 -10
  12. package/dist/analyzers/event-listener-analyzer.js.map +1 -1
  13. package/dist/cli/suppressions.d.ts +9 -0
  14. package/dist/cli/suppressions.d.ts.map +1 -0
  15. package/dist/cli/suppressions.js +242 -0
  16. package/dist/cli/suppressions.js.map +1 -0
  17. package/dist/index.js +81 -38
  18. package/dist/index.js.map +1 -1
  19. package/dist/suppressions/config-loader.d.ts +47 -0
  20. package/dist/suppressions/config-loader.d.ts.map +1 -0
  21. package/dist/suppressions/config-loader.js +214 -0
  22. package/dist/suppressions/config-loader.js.map +1 -0
  23. package/dist/suppressions/dead-suppression-detector.d.ts +45 -0
  24. package/dist/suppressions/dead-suppression-detector.d.ts.map +1 -0
  25. package/dist/suppressions/dead-suppression-detector.js +101 -0
  26. package/dist/suppressions/dead-suppression-detector.js.map +1 -0
  27. package/dist/suppressions/index.d.ts +12 -0
  28. package/dist/suppressions/index.d.ts.map +1 -0
  29. package/dist/suppressions/index.js +18 -0
  30. package/dist/suppressions/index.js.map +1 -0
  31. package/dist/suppressions/manifest.d.ts +114 -0
  32. package/dist/suppressions/manifest.d.ts.map +1 -0
  33. package/dist/suppressions/manifest.js +281 -0
  34. package/dist/suppressions/manifest.js.map +1 -0
  35. package/dist/suppressions/matcher.d.ts +73 -0
  36. package/dist/suppressions/matcher.d.ts.map +1 -0
  37. package/dist/suppressions/matcher.js +163 -0
  38. package/dist/suppressions/matcher.js.map +1 -0
  39. package/dist/suppressions/parser.d.ts +59 -0
  40. package/dist/suppressions/parser.d.ts.map +1 -0
  41. package/dist/suppressions/parser.js +156 -0
  42. package/dist/suppressions/parser.js.map +1 -0
  43. package/dist/suppressions/types.d.ts +121 -0
  44. package/dist/suppressions/types.d.ts.map +1 -0
  45. package/dist/suppressions/types.js +8 -0
  46. package/dist/suppressions/types.js.map +1 -0
  47. package/package.json +4 -2
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Dead Suppression Detector
3
+ *
4
+ * Detects suppressions that are no longer needed because the analyzer has improved.
5
+ */
6
+ import { loadManifestSync, saveManifestSync } from './manifest.js';
7
+ /**
8
+ * Detect dead suppressions in the manifest
9
+ *
10
+ * A dead suppression is one where stillViolates is false,
11
+ * meaning the analyzer no longer flags this location.
12
+ *
13
+ * @param projectRoot - Project root directory
14
+ * @param currentVersion - Current analyzer version
15
+ * @returns Array of dead suppressions
16
+ */
17
+ export function detectDeadSuppressions(projectRoot, currentVersion) {
18
+ const manifest = loadManifestSync(projectRoot);
19
+ const deadSuppressions = [];
20
+ for (const suppression of manifest.suppressions) {
21
+ if (!suppression.stillViolates) {
22
+ deadSuppressions.push({
23
+ suppression,
24
+ improvedInVersion: currentVersion,
25
+ originalVersion: suppression.analyzerVersion,
26
+ improvementReason: `Analyzer ${currentVersion} no longer flags this pattern`
27
+ });
28
+ }
29
+ }
30
+ return deadSuppressions;
31
+ }
32
+ /**
33
+ * Remove dead suppressions from manifest
34
+ *
35
+ * @param projectRoot - Project root directory
36
+ * @returns Number of dead suppressions removed
37
+ */
38
+ export function removeDeadSuppressionsFromManifest(projectRoot) {
39
+ const manifest = loadManifestSync(projectRoot);
40
+ const beforeCount = manifest.suppressions.length;
41
+ manifest.suppressions = manifest.suppressions.filter(s => s.stillViolates);
42
+ saveManifestSync(manifest);
43
+ return beforeCount - manifest.suppressions.length;
44
+ }
45
+ /**
46
+ * Get dead suppression summary
47
+ *
48
+ * @param deadSuppressions - Array of dead suppressions
49
+ * @returns Summary object
50
+ */
51
+ export function getDeadSuppressionSummary(deadSuppressions) {
52
+ const byPackage = new Map();
53
+ const byFile = new Map();
54
+ let oldestDate = null;
55
+ let newestDate = null;
56
+ for (const dead of deadSuppressions) {
57
+ // Count by package
58
+ const packageCount = byPackage.get(dead.suppression.package) || 0;
59
+ byPackage.set(dead.suppression.package, packageCount + 1);
60
+ // Count by file
61
+ const fileCount = byFile.get(dead.suppression.file) || 0;
62
+ byFile.set(dead.suppression.file, fileCount + 1);
63
+ // Track dates
64
+ const suppressedAt = new Date(dead.suppression.suppressedAt);
65
+ if (!oldestDate || suppressedAt < oldestDate) {
66
+ oldestDate = suppressedAt;
67
+ }
68
+ if (!newestDate || suppressedAt > newestDate) {
69
+ newestDate = suppressedAt;
70
+ }
71
+ }
72
+ return {
73
+ totalDead: deadSuppressions.length,
74
+ byPackage,
75
+ byFile,
76
+ oldestSuppression: oldestDate,
77
+ newestSuppression: newestDate
78
+ };
79
+ }
80
+ /**
81
+ * Format dead suppression for display
82
+ *
83
+ * @param dead - Dead suppression
84
+ * @returns Formatted string
85
+ */
86
+ export function formatDeadSuppression(dead) {
87
+ const s = dead.suppression;
88
+ const daysAgo = Math.floor((Date.now() - new Date(s.suppressedAt).getTime()) / (1000 * 60 * 60 * 24));
89
+ return [
90
+ `├─ ${s.file}:${s.line}`,
91
+ `│ Package: ${s.package}`,
92
+ `│ Postcondition: ${s.postconditionId}`,
93
+ `│ Suppressed: ${new Date(s.suppressedAt).toISOString().split('T')[0]} (${daysAgo} days ago)`,
94
+ `│ Analyzer: ${dead.originalVersion} → ${dead.improvedInVersion}`,
95
+ `│`,
96
+ `│ Why improved: ${dead.improvementReason || 'Analyzer no longer flags this pattern'}`,
97
+ `│ Action: Remove @behavioral-contract-ignore comment at line ${s.line}`,
98
+ `│`
99
+ ].join('\n');
100
+ }
101
+ //# sourceMappingURL=dead-suppression-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dead-suppression-detector.js","sourceRoot":"","sources":["../../src/suppressions/dead-suppression-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Suppression System
3
+ *
4
+ * Public API for suppressing false positive violations and detecting dead suppressions.
5
+ */
6
+ export * from './types.js';
7
+ export { parseInlineSuppressions, getSuppressionForLine, suppressionMatches, validateSuppressionComment, generateSuppressionComment, getNodeComments } from './parser.js';
8
+ export { loadConfig, loadConfigSync, ruleMatches, findMatchingRules, createDefaultConfig } from './config-loader.js';
9
+ export { loadManifest, loadManifestSync, saveManifest, saveManifestSync, createManifest, upsertSuppression, removeSuppression, findSuppression, generateSuppressionId, createSuppression, getDeadSuppressions, getActiveSuppressions, removeDeadSuppressions } from './manifest.js';
10
+ export { checkSuppression, batchCheckSuppressions, getSuppressionStats } from './matcher.js';
11
+ export { detectDeadSuppressions, removeDeadSuppressionsFromManifest, getDeadSuppressionSummary, formatDeadSuppression } from './dead-suppression-detector.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/suppressions/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,kBAAkB,EAClB,0BAA0B,EAC1B,0BAA0B,EAC1B,eAAe,EAChB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,UAAU,EACV,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,sBAAsB,EACtB,kCAAkC,EAClC,yBAAyB,EACzB,qBAAqB,EACtB,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Suppression System
3
+ *
4
+ * Public API for suppressing false positive violations and detecting dead suppressions.
5
+ */
6
+ // Types
7
+ export * from './types.js';
8
+ // Inline comment parsing
9
+ export { parseInlineSuppressions, getSuppressionForLine, suppressionMatches, validateSuppressionComment, generateSuppressionComment, getNodeComments } from './parser.js';
10
+ // Config file loading
11
+ export { loadConfig, loadConfigSync, ruleMatches, findMatchingRules, createDefaultConfig } from './config-loader.js';
12
+ // Manifest management
13
+ export { loadManifest, loadManifestSync, saveManifest, saveManifestSync, createManifest, upsertSuppression, removeSuppression, findSuppression, generateSuppressionId, createSuppression, getDeadSuppressions, getActiveSuppressions, removeDeadSuppressions } from './manifest.js';
14
+ // Suppression checking
15
+ export { checkSuppression, batchCheckSuppressions, getSuppressionStats } from './matcher.js';
16
+ // Dead suppression detection
17
+ export { detectDeadSuppressions, removeDeadSuppressionsFromManifest, getDeadSuppressionSummary, formatDeadSuppression } from './dead-suppression-detector.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/suppressions/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,QAAQ;AACR,cAAc,YAAY,CAAC;AAE3B,yBAAyB;AACzB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,kBAAkB,EAClB,0BAA0B,EAC1B,0BAA0B,EAC1B,eAAe,EAChB,MAAM,aAAa,CAAC;AAErB,sBAAsB;AACtB,OAAO,EACL,UAAU,EACV,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAE5B,sBAAsB;AACtB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,eAAe,CAAC;AAEvB,uBAAuB;AACvB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAEtB,6BAA6B;AAC7B,OAAO,EACL,sBAAsB,EACtB,kCAAkC,EAClC,yBAAyB,EACzB,qBAAqB,EACtB,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Suppression Manifest Management
3
+ *
4
+ * Handles loading, saving, and updating .verify-cli/suppressions.json
5
+ */
6
+ import { Suppression, SuppressionManifest } from './types.js';
7
+ /**
8
+ * Load suppression manifest from project root
9
+ *
10
+ * @param projectRoot - Absolute path to project root
11
+ * @returns Manifest object (creates new if doesn't exist)
12
+ */
13
+ export declare function loadManifest(projectRoot: string): Promise<SuppressionManifest>;
14
+ /**
15
+ * Load manifest synchronously
16
+ *
17
+ * @param projectRoot - Absolute path to project root
18
+ * @returns Manifest object
19
+ */
20
+ export declare function loadManifestSync(projectRoot: string): SuppressionManifest;
21
+ /**
22
+ * Save suppression manifest to disk
23
+ *
24
+ * @param manifest - Manifest to save
25
+ */
26
+ export declare function saveManifest(manifest: SuppressionManifest): Promise<void>;
27
+ /**
28
+ * Save manifest synchronously
29
+ *
30
+ * @param manifest - Manifest to save
31
+ */
32
+ export declare function saveManifestSync(manifest: SuppressionManifest): void;
33
+ /**
34
+ * Create a new empty manifest
35
+ *
36
+ * @param projectRoot - Absolute path to project root
37
+ * @returns New manifest
38
+ */
39
+ export declare function createManifest(projectRoot: string): SuppressionManifest;
40
+ /**
41
+ * Add or update a suppression in the manifest
42
+ *
43
+ * @param manifest - Manifest to update
44
+ * @param suppression - Suppression to add or update
45
+ * @returns Updated manifest
46
+ */
47
+ export declare function upsertSuppression(manifest: SuppressionManifest, suppression: Suppression): SuppressionManifest;
48
+ /**
49
+ * Remove a suppression from the manifest
50
+ *
51
+ * @param manifest - Manifest to update
52
+ * @param suppressionId - ID of suppression to remove
53
+ * @returns Updated manifest
54
+ */
55
+ export declare function removeSuppression(manifest: SuppressionManifest, suppressionId: string): SuppressionManifest;
56
+ /**
57
+ * Find a suppression by location
58
+ *
59
+ * @param manifest - Manifest to search
60
+ * @param file - File path (relative to project root)
61
+ * @param line - Line number
62
+ * @param packageName - Package name
63
+ * @param postconditionId - Postcondition ID
64
+ * @returns Suppression if found, undefined otherwise
65
+ */
66
+ export declare function findSuppression(manifest: SuppressionManifest, file: string, line: number, packageName: string, postconditionId: string): Suppression | undefined;
67
+ /**
68
+ * Generate a unique suppression ID
69
+ *
70
+ * @param file - File path
71
+ * @param line - Line number
72
+ * @param packageName - Package name
73
+ * @param postconditionId - Postcondition ID
74
+ * @returns Unique ID string
75
+ */
76
+ export declare function generateSuppressionId(file: string, line: number, packageName: string, postconditionId: string): string;
77
+ /**
78
+ * Create a suppression object
79
+ *
80
+ * @param options - Suppression options
81
+ * @returns Suppression object
82
+ */
83
+ export declare function createSuppression(options: {
84
+ file: string;
85
+ line: number;
86
+ column?: number;
87
+ packageName: string;
88
+ postconditionId: string;
89
+ reason: string;
90
+ suppressedBy: Suppression['suppressedBy'];
91
+ analyzerVersion: string;
92
+ }): Suppression;
93
+ /**
94
+ * Get all dead suppressions (stillViolates: false)
95
+ *
96
+ * @param manifest - Manifest to search
97
+ * @returns Array of dead suppressions
98
+ */
99
+ export declare function getDeadSuppressions(manifest: SuppressionManifest): Suppression[];
100
+ /**
101
+ * Get all active suppressions (stillViolates: true)
102
+ *
103
+ * @param manifest - Manifest to search
104
+ * @returns Array of active suppressions
105
+ */
106
+ export declare function getActiveSuppressions(manifest: SuppressionManifest): Suppression[];
107
+ /**
108
+ * Remove all dead suppressions from manifest
109
+ *
110
+ * @param manifest - Manifest to clean
111
+ * @returns Updated manifest
112
+ */
113
+ export declare function removeDeadSuppressions(manifest: SuppressionManifest): SuppressionManifest;
114
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/suppressions/manifest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAM9D;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,mBAAmB,CAAC,CAyB9B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,CAyBzE;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAa/E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAapE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,CAOvE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,mBAAmB,EAC7B,WAAW,EAAE,WAAW,GACvB,mBAAmB,CAYrB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,mBAAmB,EAC7B,aAAa,EAAE,MAAM,GACpB,mBAAmB,CAGrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,mBAAmB,EAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,GACtB,WAAW,GAAG,SAAS,CAQzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,GACtB,MAAM,CASR;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;IAC1C,eAAe,EAAE,MAAM,CAAC;CACzB,GAAG,WAAW,CAwBd;AAwED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,WAAW,EAAE,CAEhF;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,WAAW,EAAE,CAElF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,mBAAmB,CAGzF"}
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Suppression Manifest Management
3
+ *
4
+ * Handles loading, saving, and updating .verify-cli/suppressions.json
5
+ */
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ import * as crypto from 'crypto';
9
+ const MANIFEST_DIR = '.verify-cli';
10
+ const MANIFEST_FILENAME = 'suppressions.json';
11
+ const MANIFEST_VERSION = '1.0.0';
12
+ /**
13
+ * Load suppression manifest from project root
14
+ *
15
+ * @param projectRoot - Absolute path to project root
16
+ * @returns Manifest object (creates new if doesn't exist)
17
+ */
18
+ export async function loadManifest(projectRoot) {
19
+ const manifestPath = getManifestPath(projectRoot);
20
+ if (!fs.existsSync(manifestPath)) {
21
+ return createManifest(projectRoot);
22
+ }
23
+ try {
24
+ const content = await fs.promises.readFile(manifestPath, 'utf-8');
25
+ const manifest = JSON.parse(content);
26
+ // Validate manifest structure
27
+ validateManifest(manifest);
28
+ // Migrate if needed
29
+ if (manifest.version !== MANIFEST_VERSION) {
30
+ return migrateManifest(manifest, projectRoot);
31
+ }
32
+ return manifest;
33
+ }
34
+ catch (error) {
35
+ throw new Error(`Failed to load suppression manifest: ${error instanceof Error ? error.message : String(error)}`);
36
+ }
37
+ }
38
+ /**
39
+ * Load manifest synchronously
40
+ *
41
+ * @param projectRoot - Absolute path to project root
42
+ * @returns Manifest object
43
+ */
44
+ export function loadManifestSync(projectRoot) {
45
+ const manifestPath = getManifestPath(projectRoot);
46
+ if (!fs.existsSync(manifestPath)) {
47
+ return createManifest(projectRoot);
48
+ }
49
+ try {
50
+ const content = fs.readFileSync(manifestPath, 'utf-8');
51
+ const manifest = JSON.parse(content);
52
+ // Validate manifest structure
53
+ validateManifest(manifest);
54
+ // Migrate if needed
55
+ if (manifest.version !== MANIFEST_VERSION) {
56
+ return migrateManifest(manifest, projectRoot);
57
+ }
58
+ return manifest;
59
+ }
60
+ catch (error) {
61
+ throw new Error(`Failed to load suppression manifest: ${error instanceof Error ? error.message : String(error)}`);
62
+ }
63
+ }
64
+ /**
65
+ * Save suppression manifest to disk
66
+ *
67
+ * @param manifest - Manifest to save
68
+ */
69
+ export async function saveManifest(manifest) {
70
+ const manifestPath = getManifestPath(manifest.projectRoot);
71
+ // Ensure directory exists
72
+ await fs.promises.mkdir(path.dirname(manifestPath), { recursive: true });
73
+ // Update timestamp
74
+ manifest.lastUpdated = new Date().toISOString();
75
+ // Pretty print JSON
76
+ const content = JSON.stringify(manifest, null, 2);
77
+ await fs.promises.writeFile(manifestPath, content, 'utf-8');
78
+ }
79
+ /**
80
+ * Save manifest synchronously
81
+ *
82
+ * @param manifest - Manifest to save
83
+ */
84
+ export function saveManifestSync(manifest) {
85
+ const manifestPath = getManifestPath(manifest.projectRoot);
86
+ // Ensure directory exists
87
+ fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
88
+ // Update timestamp
89
+ manifest.lastUpdated = new Date().toISOString();
90
+ // Pretty print JSON
91
+ const content = JSON.stringify(manifest, null, 2);
92
+ fs.writeFileSync(manifestPath, content, 'utf-8');
93
+ }
94
+ /**
95
+ * Create a new empty manifest
96
+ *
97
+ * @param projectRoot - Absolute path to project root
98
+ * @returns New manifest
99
+ */
100
+ export function createManifest(projectRoot) {
101
+ return {
102
+ version: MANIFEST_VERSION,
103
+ projectRoot: path.resolve(projectRoot),
104
+ lastUpdated: new Date().toISOString(),
105
+ suppressions: []
106
+ };
107
+ }
108
+ /**
109
+ * Add or update a suppression in the manifest
110
+ *
111
+ * @param manifest - Manifest to update
112
+ * @param suppression - Suppression to add or update
113
+ * @returns Updated manifest
114
+ */
115
+ export function upsertSuppression(manifest, suppression) {
116
+ const existingIndex = manifest.suppressions.findIndex(s => s.id === suppression.id);
117
+ if (existingIndex >= 0) {
118
+ // Update existing suppression
119
+ manifest.suppressions[existingIndex] = suppression;
120
+ }
121
+ else {
122
+ // Add new suppression
123
+ manifest.suppressions.push(suppression);
124
+ }
125
+ return manifest;
126
+ }
127
+ /**
128
+ * Remove a suppression from the manifest
129
+ *
130
+ * @param manifest - Manifest to update
131
+ * @param suppressionId - ID of suppression to remove
132
+ * @returns Updated manifest
133
+ */
134
+ export function removeSuppression(manifest, suppressionId) {
135
+ manifest.suppressions = manifest.suppressions.filter(s => s.id !== suppressionId);
136
+ return manifest;
137
+ }
138
+ /**
139
+ * Find a suppression by location
140
+ *
141
+ * @param manifest - Manifest to search
142
+ * @param file - File path (relative to project root)
143
+ * @param line - Line number
144
+ * @param packageName - Package name
145
+ * @param postconditionId - Postcondition ID
146
+ * @returns Suppression if found, undefined otherwise
147
+ */
148
+ export function findSuppression(manifest, file, line, packageName, postconditionId) {
149
+ return manifest.suppressions.find(s => s.file === file &&
150
+ s.line === line &&
151
+ s.package === packageName &&
152
+ s.postconditionId === postconditionId);
153
+ }
154
+ /**
155
+ * Generate a unique suppression ID
156
+ *
157
+ * @param file - File path
158
+ * @param line - Line number
159
+ * @param packageName - Package name
160
+ * @param postconditionId - Postcondition ID
161
+ * @returns Unique ID string
162
+ */
163
+ export function generateSuppressionId(file, line, packageName, postconditionId) {
164
+ const data = `${file}:${line}:${packageName}:${postconditionId}`;
165
+ const hash = crypto
166
+ .createHash('sha256')
167
+ .update(data)
168
+ .digest('hex')
169
+ .substring(0, 8);
170
+ return `suppress-${file.replace(/[^a-z0-9]/gi, '-')}-${line}-${hash}`;
171
+ }
172
+ /**
173
+ * Create a suppression object
174
+ *
175
+ * @param options - Suppression options
176
+ * @returns Suppression object
177
+ */
178
+ export function createSuppression(options) {
179
+ const id = generateSuppressionId(options.file, options.line, options.packageName, options.postconditionId);
180
+ const now = new Date().toISOString();
181
+ return {
182
+ id,
183
+ file: options.file,
184
+ line: options.line,
185
+ column: options.column,
186
+ package: options.packageName,
187
+ postconditionId: options.postconditionId,
188
+ reason: options.reason,
189
+ suppressedAt: now,
190
+ suppressedBy: options.suppressedBy,
191
+ lastChecked: now,
192
+ stillViolates: true,
193
+ analyzerVersion: options.analyzerVersion
194
+ };
195
+ }
196
+ /**
197
+ * Get path to manifest file
198
+ *
199
+ * @param projectRoot - Project root directory
200
+ * @returns Absolute path to manifest file
201
+ */
202
+ function getManifestPath(projectRoot) {
203
+ return path.join(projectRoot, MANIFEST_DIR, MANIFEST_FILENAME);
204
+ }
205
+ /**
206
+ * Validate manifest structure
207
+ *
208
+ * @param manifest - Manifest to validate
209
+ * @throws Error if manifest is invalid
210
+ */
211
+ function validateManifest(manifest) {
212
+ if (typeof manifest !== 'object' || manifest === null) {
213
+ throw new Error('Manifest must be an object');
214
+ }
215
+ if (!manifest.version || typeof manifest.version !== 'string') {
216
+ throw new Error('Manifest must have a version');
217
+ }
218
+ if (!manifest.projectRoot || typeof manifest.projectRoot !== 'string') {
219
+ throw new Error('Manifest must have a projectRoot');
220
+ }
221
+ if (!manifest.lastUpdated || typeof manifest.lastUpdated !== 'string') {
222
+ throw new Error('Manifest must have a lastUpdated timestamp');
223
+ }
224
+ if (!Array.isArray(manifest.suppressions)) {
225
+ throw new Error('Manifest suppressions must be an array');
226
+ }
227
+ manifest.suppressions.forEach((s, index) => {
228
+ if (!s.id || typeof s.id !== 'string') {
229
+ throw new Error(`Suppression ${index}: Missing or invalid id`);
230
+ }
231
+ if (!s.file || typeof s.file !== 'string') {
232
+ throw new Error(`Suppression ${index}: Missing or invalid file`);
233
+ }
234
+ if (typeof s.line !== 'number') {
235
+ throw new Error(`Suppression ${index}: Missing or invalid line`);
236
+ }
237
+ });
238
+ }
239
+ /**
240
+ * Migrate manifest to current version
241
+ *
242
+ * @param oldManifest - Old manifest
243
+ * @param projectRoot - Project root
244
+ * @returns Migrated manifest
245
+ */
246
+ function migrateManifest(oldManifest, projectRoot) {
247
+ // Currently only one version, but prepare for future migrations
248
+ const newManifest = createManifest(projectRoot);
249
+ // Copy suppressions
250
+ newManifest.suppressions = oldManifest.suppressions || [];
251
+ return newManifest;
252
+ }
253
+ /**
254
+ * Get all dead suppressions (stillViolates: false)
255
+ *
256
+ * @param manifest - Manifest to search
257
+ * @returns Array of dead suppressions
258
+ */
259
+ export function getDeadSuppressions(manifest) {
260
+ return manifest.suppressions.filter(s => !s.stillViolates);
261
+ }
262
+ /**
263
+ * Get all active suppressions (stillViolates: true)
264
+ *
265
+ * @param manifest - Manifest to search
266
+ * @returns Array of active suppressions
267
+ */
268
+ export function getActiveSuppressions(manifest) {
269
+ return manifest.suppressions.filter(s => s.stillViolates);
270
+ }
271
+ /**
272
+ * Remove all dead suppressions from manifest
273
+ *
274
+ * @param manifest - Manifest to clean
275
+ * @returns Updated manifest
276
+ */
277
+ export function removeDeadSuppressions(manifest) {
278
+ manifest.suppressions = manifest.suppressions.filter(s => s.stillViolates);
279
+ return manifest;
280
+ }
281
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/suppressions/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Suppression Matcher
3
+ *
4
+ * Combines inline comments and config rules to check if violations are suppressed
5
+ */
6
+ import * as ts from 'typescript';
7
+ import { SuppressionCheckResult } from './types.js';
8
+ /**
9
+ * Options for checking suppressions
10
+ */
11
+ export interface CheckSuppressionOptions {
12
+ /** Project root directory */
13
+ projectRoot: string;
14
+ /** TypeScript source file */
15
+ sourceFile: ts.SourceFile;
16
+ /** Line number of violation (1-indexed) */
17
+ line: number;
18
+ /** Column number of violation (1-indexed) */
19
+ column?: number;
20
+ /** Package name */
21
+ packageName: string;
22
+ /** Postcondition ID */
23
+ postconditionId: string;
24
+ /** Current analyzer version */
25
+ analyzerVersion: string;
26
+ /** Update manifest with suppression metadata */
27
+ updateManifest?: boolean;
28
+ }
29
+ /**
30
+ * Check if a violation is suppressed
31
+ *
32
+ * Checks both inline comments and config file rules.
33
+ * Optionally updates manifest with metadata.
34
+ *
35
+ * @param options - Check options
36
+ * @returns Suppression check result
37
+ */
38
+ export declare function checkSuppression(options: CheckSuppressionOptions): SuppressionCheckResult;
39
+ /**
40
+ * Batch check suppressions for multiple violations
41
+ *
42
+ * @param violations - Array of violations to check
43
+ * @param projectRoot - Project root directory
44
+ * @param analyzerVersion - Current analyzer version
45
+ * @returns Map of violation ID to suppression result
46
+ */
47
+ export declare function batchCheckSuppressions(violations: Array<{
48
+ id: string;
49
+ sourceFile: ts.SourceFile;
50
+ line: number;
51
+ column?: number;
52
+ packageName: string;
53
+ postconditionId: string;
54
+ }>, projectRoot: string, analyzerVersion: string): Map<string, SuppressionCheckResult>;
55
+ /**
56
+ * Get suppression statistics
57
+ *
58
+ * @param projectRoot - Project root directory
59
+ * @returns Statistics object
60
+ */
61
+ export declare function getSuppressionStats(projectRoot: string): {
62
+ totalSuppressions: number;
63
+ activeSuppressions: number;
64
+ deadSuppressions: number;
65
+ bySource: {
66
+ inlineComment: number;
67
+ configFile: number;
68
+ aiAgent: number;
69
+ cli: number;
70
+ };
71
+ byPackage: Map<string, number>;
72
+ };
73
+ //# sourceMappingURL=matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../../src/suppressions/matcher.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAQjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IAEpB,6BAA6B;IAC7B,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC;IAE1B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IAEb,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB,uBAAuB;IACvB,eAAe,EAAE,MAAM,CAAC;IAExB,+BAA+B;IAC/B,eAAe,EAAE,MAAM,CAAC;IAExB,gDAAgD;IAChD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,sBAAsB,CAiFzF;AAgDD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,KAAK,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC,EACF,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,GACtB,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAmBrC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG;IACxD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE;QACR,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CA0BA"}