arcvision 0.2.14 → 0.2.16

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 (134) hide show
  1. package/ARCVISION_DIRECTORY_STRUCTURE.md +104 -0
  2. package/CLI_STRUCTURE.md +110 -0
  3. package/CONFIGURATION.md +119 -0
  4. package/IMPLEMENTATION_SUMMARY.md +99 -0
  5. package/README.md +149 -89
  6. package/architecture.authority.ledger.json +46 -0
  7. package/arcvision-0.2.3.tgz +0 -0
  8. package/arcvision-0.2.4.tgz +0 -0
  9. package/arcvision-0.2.5.tgz +0 -0
  10. package/arcvision.context.diff.json +2181 -0
  11. package/arcvision.context.json +1021 -0
  12. package/arcvision.context.v1.json +2163 -0
  13. package/arcvision.context.v2.json +2173 -0
  14. package/arcvision_context/README.md +93 -0
  15. package/arcvision_context/architecture.authority.ledger.json +83 -0
  16. package/arcvision_context/arcvision.context.json +6884 -0
  17. package/debug-cycle-detection.js +56 -0
  18. package/dist/index.js +1626 -25
  19. package/docs/ENHANCED_ACCURACY_SAFETY_PROTOCOL.md +172 -0
  20. package/docs/accuracy-enhancement-artifacts/enhanced-validation-config.json +98 -0
  21. package/docs/acig-robustness-guide.md +164 -0
  22. package/docs/authoritative-gate-implementation.md +168 -0
  23. package/docs/cli-strengthening-summary.md +232 -0
  24. package/docs/invariant-system-summary.md +100 -0
  25. package/docs/invariant-system.md +112 -0
  26. package/generate_large_test.js +42 -0
  27. package/large_test_repo.json +1 -0
  28. package/output1.json +2163 -0
  29. package/output2.json +2163 -0
  30. package/package.json +46 -36
  31. package/scan_calcom_report.txt +0 -0
  32. package/scan_leafmint_report.txt +0 -0
  33. package/scan_output.txt +0 -0
  34. package/scan_trigger_report.txt +0 -0
  35. package/schema/arcvision_context_schema_v1.json +136 -1
  36. package/src/arcvision-guard.js +433 -0
  37. package/src/core/authority-core-detector.js +382 -0
  38. package/src/core/authority-ledger.js +300 -0
  39. package/src/core/blastRadius.js +299 -0
  40. package/src/core/call-resolver.js +196 -0
  41. package/src/core/change-evaluator.js +509 -0
  42. package/src/core/change-evaluator.js.backup +424 -0
  43. package/src/core/change-evaluator.ts +285 -0
  44. package/src/core/chunked-uploader.js +180 -0
  45. package/src/core/circular-dependency-detector.js +404 -0
  46. package/src/core/cli-error-handler.js +458 -0
  47. package/src/core/cli-validator.js +458 -0
  48. package/src/core/compression.js +64 -0
  49. package/src/core/context_builder.js +741 -0
  50. package/src/core/dependency-manager.js +134 -0
  51. package/src/core/di-detector.js +202 -0
  52. package/src/core/diff-analyzer.js +76 -0
  53. package/src/core/example-invariants.js +135 -0
  54. package/src/core/failure-mode-synthesizer.js +341 -0
  55. package/src/core/invariant-analyzer.js +294 -0
  56. package/src/core/invariant-detector.js +548 -0
  57. package/src/core/invariant-enforcer.js +171 -0
  58. package/src/core/invariant-evaluation-utils.js +172 -0
  59. package/src/core/invariant-hooks.js +152 -0
  60. package/src/core/invariant-integration-example.js +186 -0
  61. package/src/core/invariant-registry.js +298 -0
  62. package/src/core/invariant-registry.ts +100 -0
  63. package/src/core/invariant-types.js +66 -0
  64. package/src/core/invariants-index.js +88 -0
  65. package/src/core/method-tracker.js +170 -0
  66. package/src/core/override-handler.js +304 -0
  67. package/src/core/ownership-resolver.js +227 -0
  68. package/src/core/parser-enhanced.js +80 -0
  69. package/src/core/parser.js +610 -0
  70. package/src/core/path-resolver.js +240 -0
  71. package/src/core/pattern-matcher.js +246 -0
  72. package/src/core/progress-tracker.js +71 -0
  73. package/src/core/react-nextjs-detector.js +245 -0
  74. package/src/core/readme-generator.js +167 -0
  75. package/src/core/retry-handler.js +57 -0
  76. package/src/core/scanner.js +289 -0
  77. package/src/core/semantic-analyzer.js +204 -0
  78. package/src/core/structural-context-owner.js +442 -0
  79. package/src/core/symbol-indexer.js +164 -0
  80. package/src/core/tsconfig-utils.js +73 -0
  81. package/src/core/type-analyzer.js +272 -0
  82. package/src/core/watcher.js +18 -0
  83. package/src/core/workspace-scanner.js +88 -0
  84. package/src/engine/context_builder.js +280 -0
  85. package/src/engine/context_sorter.js +59 -0
  86. package/src/engine/context_validator.js +200 -0
  87. package/src/engine/id-generator.js +16 -0
  88. package/src/engine/pass1_facts.js +260 -0
  89. package/src/engine/pass2_semantics.js +333 -0
  90. package/src/engine/pass3_lifter.js +99 -0
  91. package/src/engine/pass4_signals.js +201 -0
  92. package/src/index.js +830 -0
  93. package/src/plugins/express-plugin.js +48 -0
  94. package/src/plugins/plugin-manager.js +58 -0
  95. package/src/plugins/react-plugin.js +54 -0
  96. package/temp_original.js +0 -0
  97. package/test/determinism-test.js +83 -0
  98. package/test-authoritative-context.js +53 -0
  99. package/test-real-authoritative-context.js +118 -0
  100. package/test-upload-enhancements.js +111 -0
  101. package/test_repos/allowed-clean-architecture/.arcvision/invariants.json +57 -0
  102. package/test_repos/allowed-clean-architecture/adapters/controllers/UserController.js +95 -0
  103. package/test_repos/allowed-clean-architecture/adapters/http/HttpServer.js +78 -0
  104. package/test_repos/allowed-clean-architecture/application/dtos/CreateUserRequest.js +37 -0
  105. package/test_repos/allowed-clean-architecture/application/services/UserService.js +61 -0
  106. package/test_repos/allowed-clean-architecture/arcvision_context/README.md +93 -0
  107. package/test_repos/allowed-clean-architecture/arcvision_context/arcvision.context.json +2796 -0
  108. package/test_repos/allowed-clean-architecture/domain/interfaces/UserRepository.js +25 -0
  109. package/test_repos/allowed-clean-architecture/domain/models/User.js +39 -0
  110. package/test_repos/allowed-clean-architecture/index.js +45 -0
  111. package/test_repos/allowed-clean-architecture/infrastructure/database/DatabaseConnection.js +56 -0
  112. package/test_repos/allowed-clean-architecture/infrastructure/repositories/InMemoryUserRepository.js +61 -0
  113. package/test_repos/allowed-clean-architecture/package.json +15 -0
  114. package/test_repos/blocked-legacy-monolith/.arcvision/invariants.json +78 -0
  115. package/test_repos/blocked-legacy-monolith/arcvision_context/README.md +93 -0
  116. package/test_repos/blocked-legacy-monolith/arcvision_context/arcvision.context.json +2882 -0
  117. package/test_repos/blocked-legacy-monolith/database/dbConnection.js +35 -0
  118. package/test_repos/blocked-legacy-monolith/index.js +38 -0
  119. package/test_repos/blocked-legacy-monolith/modules/emailService.js +31 -0
  120. package/test_repos/blocked-legacy-monolith/modules/paymentProcessor.js +37 -0
  121. package/test_repos/blocked-legacy-monolith/package.json +15 -0
  122. package/test_repos/blocked-legacy-monolith/shared/utils.js +19 -0
  123. package/test_repos/blocked-legacy-monolith/utils/helpers.js +23 -0
  124. package/test_repos/risky-microservices-concerns/.arcvision/invariants.json +69 -0
  125. package/test_repos/risky-microservices-concerns/arcvision_context/README.md +93 -0
  126. package/test_repos/risky-microservices-concerns/arcvision_context/arcvision.context.json +3070 -0
  127. package/test_repos/risky-microservices-concerns/common/utils.js +77 -0
  128. package/test_repos/risky-microservices-concerns/gateways/apiGateway.js +84 -0
  129. package/test_repos/risky-microservices-concerns/index.js +20 -0
  130. package/test_repos/risky-microservices-concerns/libs/deprecatedHelper.js +36 -0
  131. package/test_repos/risky-microservices-concerns/package.json +15 -0
  132. package/test_repos/risky-microservices-concerns/services/orderService.js +42 -0
  133. package/test_repos/risky-microservices-concerns/services/userService.js +48 -0
  134. package/verify_engine.js +116 -0
@@ -0,0 +1,548 @@
1
+ /**
2
+ * Invariant Detector - Detects architectural invariants in scanned repositories
3
+ * Analyzes code structure to identify system-level constraints that must always hold
4
+ */
5
+
6
+ const fs = require('fs').promises;
7
+ const path = require('path');
8
+
9
+ class InvariantDetector {
10
+ constructor() {
11
+ this.detectedInvariants = [];
12
+ }
13
+
14
+
15
+
16
+ /**
17
+ * Detect invariants in a scanned codebase
18
+ * @param {Object} scanResult - The result from the scanner
19
+ * @param {string} directory - The directory that was scanned
20
+ * @returns {Array} - Array of detected invariants
21
+ */
22
+ async detectInvariants(scanResult, directory) {
23
+ this.detectedInvariants = [];
24
+
25
+ try {
26
+ // Analyze the structural context for potential invariants
27
+ await this.analyzeNodesForInvariants(scanResult.nodes, directory);
28
+ await this.analyzeEdgesForInvariants(scanResult.edges);
29
+ await this.analyzeCodeFilesForInvariants(directory);
30
+
31
+ console.log(`\n🛡️ Invariant Detection Complete`);
32
+ console.log(` Found ${this.detectedInvariants.length} potential system invariants`);
33
+
34
+ return this.detectedInvariants;
35
+ } catch (error) {
36
+ console.error('Invariant detection failed:', error.message);
37
+ return [];
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Analyze nodes for invariant patterns
43
+ */
44
+ async analyzeNodesForInvariants(nodes, directory) {
45
+ for (const node of nodes) {
46
+ if (!node.path) continue;
47
+
48
+ try {
49
+ const filePath = path.join(directory, node.path);
50
+ if (await this.isFileAccessible(filePath)) {
51
+ const content = await fs.readFile(filePath, 'utf8');
52
+
53
+ // Look for validation/assertion patterns in the file
54
+ const fileInvariants = this.extractInvariantsFromFile(content, node.path);
55
+
56
+ for (const invariant of fileInvariants) {
57
+ const nodeId = node.path || node.id || 'unknown';
58
+ this.detectedInvariants.push({
59
+ id: this.generateInvariantId(invariant.pattern, nodeId),
60
+ statement: invariant.description,
61
+ description: invariant.description,
62
+ scope: this.determineScopeFromPath(nodeId),
63
+ critical_path: invariant.isCritical,
64
+ assertion: `Pattern: ${invariant.pattern}`,
65
+ status: 'suspected',
66
+ confidence: this.calculateConfidenceScore(invariant.pattern, nodeId, content),
67
+ source_file: nodeId,
68
+ detected_at: new Date().toISOString()
69
+ });
70
+ }
71
+ }
72
+ } catch (error) {
73
+ // Skip files that can't be read
74
+ continue;
75
+ }
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Analyze edges for potential invariant relationships
81
+ */
82
+ async analyzeEdgesForInvariants(edges) {
83
+ // Look for dependency patterns that suggest invariants
84
+ const dependencyConstraints = this.identifyDependencyInvariants(edges);
85
+
86
+ for (const constraint of dependencyConstraints) {
87
+ this.detectedInvariants.push({
88
+ id: this.generateInvariantId('dependency_constraint', constraint.from + '_' + constraint.to),
89
+ statement: constraint.description,
90
+ description: constraint.description,
91
+ scope: 'boundary',
92
+ critical_path: constraint.critical,
93
+ assertion: `Dependency constraint: ${constraint.from} -> ${constraint.to}`,
94
+ status: 'suspected',
95
+ confidence: this.calculateConfidenceScore('dependency_constraint', constraint.from, ''),
96
+ source_relationship: `${constraint.from} -> ${constraint.to}`,
97
+ detected_at: new Date().toISOString()
98
+ });
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Analyze code files directly for invariant patterns
104
+ */
105
+ async analyzeCodeFilesForInvariants(directory) {
106
+ const invariantFiles = await this.findInvariantRelatedFiles(directory);
107
+
108
+ for (const filePath of invariantFiles) {
109
+ try {
110
+ const content = await fs.readFile(filePath, 'utf8');
111
+ const relativePath = path.relative(directory, filePath);
112
+
113
+ // Look for common invariant implementation patterns
114
+ const patterns = this.searchForInvariantPatterns(content);
115
+
116
+ for (const pattern of patterns) {
117
+ this.detectedInvariants.push({
118
+ id: this.generateInvariantId(pattern.type, relativePath),
119
+ statement: `System invariant implemented in ${relativePath}: ${pattern.description}`,
120
+ description: `System invariant implemented in ${relativePath}: ${pattern.description}`,
121
+ scope: 'system',
122
+ critical_path: true, // File specifically for invariants is likely critical
123
+ assertion: pattern.assertion,
124
+ status: 'suspected',
125
+ confidence: this.calculateConfidenceScore(pattern.type, relativePath, content),
126
+ source_file: relativePath,
127
+ implementation_type: pattern.type,
128
+ detected_at: new Date().toISOString()
129
+ });
130
+ }
131
+ } catch (error) {
132
+ // Skip files that can't be read
133
+ continue;
134
+ }
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Extract invariants from file content based on patterns
140
+ */
141
+ extractInvariantsFromFile(content, filePath) {
142
+ const invariants = [];
143
+
144
+ // Check for validation function patterns
145
+ const validationPatterns = [
146
+ /function\s+validate\w+/gi,
147
+ /function\s+check\w+/gi,
148
+ /function\s+ensure\w+/gi,
149
+ /function\s+guard\w+/gi,
150
+ /function\s+verify\w+/gi,
151
+ /function\s+assert\w+/gi,
152
+ /function\s+enforce\w+/gi
153
+ ];
154
+
155
+ for (const pattern of validationPatterns) {
156
+ const matches = content.match(pattern);
157
+ if (matches) {
158
+ invariants.push({
159
+ pattern: pattern.source,
160
+ description: `Validation function pattern found in ${filePath}: ${matches.length} matches`,
161
+ isCritical: true
162
+ });
163
+ }
164
+ }
165
+
166
+ // Check for error handling patterns that suggest invariant enforcement
167
+ const errorHandlingPatterns = [
168
+ /try\s*\{/gi,
169
+ /catch\s*\(/gi,
170
+ /throw\s+new/gi,
171
+ /if\s*\([^)]+\)\s*throw/gi,
172
+ /error\.message/gi
173
+ ];
174
+
175
+ for (const pattern of errorHandlingPatterns) {
176
+ const match = content.match(pattern);
177
+ if (match) {
178
+ invariants.push({
179
+ pattern: pattern.source,
180
+ description: `Constraint enforcement pattern found in ${filePath}`,
181
+ isCritical: false
182
+ });
183
+ }
184
+ }
185
+
186
+ // Check for state management patterns
187
+ const stateManagementPatterns = [
188
+ /setState\s*\(/gi,
189
+ /dispatch\s*\(/gi,
190
+ /useReducer/gi,
191
+ /useState/gi,
192
+ /store\./gi,
193
+ /state\./gi,
194
+ /state\s*=\s*/gi
195
+ ];
196
+
197
+ for (const pattern of stateManagementPatterns) {
198
+ const match = content.match(pattern);
199
+ if (match) {
200
+ invariants.push({
201
+ pattern: pattern.source,
202
+ description: `State transition constraint pattern found in ${filePath}`,
203
+ isCritical: true
204
+ });
205
+ }
206
+ }
207
+
208
+ // Check for boundary enforcement patterns
209
+ const boundaryCheckPatterns = [
210
+ /boundary\s*check/gi,
211
+ /range\s*check/gi,
212
+ /limit\s*check/gi,
213
+ /max\s*\w*\s*>/gi,
214
+ /min\s*\w*\s*</gi,
215
+ /within\s*bound/gi,
216
+ /validate\s*input/gi,
217
+ /sanitiz/gi
218
+ ];
219
+
220
+ for (const pattern of boundaryCheckPatterns) {
221
+ const match = content.match(pattern);
222
+ if (match) {
223
+ invariants.push({
224
+ pattern: pattern.source,
225
+ description: `Boundary enforcement pattern found in ${filePath}`,
226
+ isCritical: true
227
+ });
228
+ }
229
+ }
230
+
231
+ // Check for invariant indicators from pass 1
232
+ const invariantIndicators = this.extractDetailedInvariantIndicators(content, filePath);
233
+ for (const indicator of invariantIndicators) {
234
+ invariants.push(indicator);
235
+ }
236
+
237
+ return invariants;
238
+ }
239
+
240
+ /**
241
+ * Extract detailed invariant indicators from content
242
+ */
243
+ extractDetailedInvariantIndicators(content, filePath) {
244
+ const indicators = [];
245
+
246
+ // Look for common invariant/pattern validation patterns
247
+ const patterns = [
248
+ // Assertion and validation patterns
249
+ { pattern: /assert\(/gi, description: 'Assertion-based invariant check', critical: true },
250
+ { pattern: /console\.assert\(/gi, description: 'Console assertion pattern', critical: true },
251
+ { pattern: /validate[A-Z]/gi, description: 'Validate function pattern', critical: false },
252
+ { pattern: /check[A-Z]/gi, description: 'Check function pattern', critical: false },
253
+ { pattern: /ensure[A-Z]/gi, description: 'Ensure function pattern', critical: true },
254
+ { pattern: /guard[A-Z]/gi, description: 'Guard function pattern', critical: true },
255
+ { pattern: /verify[A-Z]/gi, description: 'Verify function pattern', critical: false },
256
+ { pattern: /validate\(/gi, description: 'Validation function call', critical: false },
257
+
258
+ // Constraint and invariant mentions
259
+ { pattern: /Invariant/gi, description: 'Invariant mention', critical: true },
260
+ { pattern: /constraint/gi, description: 'Constraint mention', critical: true },
261
+ { pattern: /require\(/gi, description: 'Requirement assertion', critical: true },
262
+ { pattern: /enforce/gi, description: 'Enforcement pattern', critical: true },
263
+
264
+ // Conditional guard patterns
265
+ { pattern: /must.*be/gi, description: 'Must-be pattern', critical: true },
266
+ { pattern: /should.*be/gi, description: 'Should-be pattern', critical: false },
267
+ { pattern: /expected.*to/gi, description: 'Expected-to pattern', critical: false },
268
+ { pattern: /if.*!\s*[^\s]+\s*throw/gi, description: 'Guard clause pattern', critical: true },
269
+ { pattern: /if.*!\s*[^\s]+\s*reject/gi, description: 'Promise rejection guard', critical: true },
270
+ { pattern: /throw.*Error/gi, description: 'Error throwing pattern', critical: true },
271
+
272
+ // Boundary and validation patterns
273
+ { pattern: /boundary.*check/gi, description: 'Boundary check', critical: true },
274
+ { pattern: /range.*check/gi, description: 'Range check', critical: true },
275
+ { pattern: /within.*bounds/gi, description: 'Bounds check', critical: true },
276
+ { pattern: /validat(e|ion)/gi, description: 'Validation pattern', critical: false },
277
+ { pattern: /guard/i, description: 'Guard pattern', critical: true },
278
+
279
+ // Access control and security patterns
280
+ { pattern: /access.*control/gi, description: 'Access control', critical: true },
281
+ { pattern: /permission.*check/gi, description: 'Permission check', critical: true },
282
+ { pattern: /auth(?:oriz|enticat)/gi, description: 'Authorization/authentication', critical: true },
283
+ { pattern: /acl/gi, description: 'Access Control List', critical: true },
284
+
285
+ // State management patterns
286
+ { pattern: /state.*transition/gi, description: 'State transition', critical: true },
287
+ { pattern: /setState/gi, description: 'State setter', critical: true },
288
+ { pattern: /update.*state/gi, description: 'State updater', critical: true },
289
+ { pattern: /transition/gi, description: 'Transition pattern', critical: true },
290
+ { pattern: /immutable/gi, description: 'Immutability pattern', critical: true },
291
+
292
+ // Type and schema validation patterns
293
+ { pattern: /zod/gi, description: 'Zod validation schema', critical: false },
294
+ { pattern: /joi/gi, description: 'Joi validation schema', critical: false },
295
+ { pattern: /yup/gi, description: 'Yup validation schema', critical: false },
296
+ { pattern: /ajv/gi, description: 'Ajv validation schema', critical: false },
297
+ { pattern: /schema/gi, description: 'Schema definition', critical: false },
298
+
299
+ // Configuration patterns
300
+ { pattern: /config.*environ/gi, description: 'Environment configuration', critical: true },
301
+ { pattern: /env.*validation/gi, description: 'Environment validation', critical: true }
302
+ ];
303
+
304
+ for (const item of patterns) {
305
+ if (!item.pattern || !content) continue; // Skip if pattern or content is undefined
306
+ let match;
307
+ try {
308
+ while ((match = item.pattern.exec(content)) !== null) {
309
+ // Avoid duplicate matches by position
310
+ const position = item.pattern.lastIndex;
311
+ const prevMatch = indicators.find(ind => ind.pattern === item.pattern.source &&
312
+ ind.description.includes(match[0]));
313
+ if (!prevMatch) {
314
+ indicators.push({
315
+ pattern: item.pattern.source,
316
+ description: `${item.description} found in ${filePath}: '${match[0]}' at position ${position}`,
317
+ isCritical: item.critical
318
+ });
319
+ }
320
+ }
321
+ } catch (error) {
322
+ // Continue if regex execution fails
323
+ continue;
324
+ }
325
+ }
326
+
327
+ return indicators;
328
+ }
329
+
330
+ /**
331
+ * Identify dependency-based invariants from edges
332
+ */
333
+ identifyDependencyInvariants(edges) {
334
+ const constraints = [];
335
+
336
+ // Look for patterns like core modules that should not depend on peripheral modules
337
+ const coreModules = new Set();
338
+ const peripheralModules = new Set();
339
+
340
+ for (const edge of edges) {
341
+ // Identify potential architectural layers based on file paths
342
+ if (this.isCoreLayer(edge.from) && this.isPeripheralLayer(edge.to)) {
343
+ // This suggests an invariant: core modules shouldn't depend on peripheral modules
344
+ constraints.push({
345
+ from: edge.from,
346
+ to: edge.to,
347
+ description: `Potential architectural invariant: Core module ${edge.from} depends on peripheral module ${edge.to}`,
348
+ critical: true
349
+ });
350
+ }
351
+ }
352
+
353
+ return constraints;
354
+ }
355
+
356
+ /**
357
+ * Find files that are likely related to invariant implementation
358
+ */
359
+ async findInvariantRelatedFiles(directory) {
360
+ const invariantFiles = [];
361
+
362
+ const walk = async (dir) => {
363
+ try {
364
+ const entries = await fs.readdir(dir, { withFileTypes: true });
365
+
366
+ for (const entry of entries) {
367
+ const fullPath = path.join(dir, entry.name);
368
+
369
+ if (entry.isDirectory()) {
370
+ await walk(fullPath);
371
+ } else if (entry.isFile()) {
372
+ const fileName = entry.name.toLowerCase();
373
+
374
+ // Look for files that commonly contain invariants
375
+ if (
376
+ fileName.includes('invariant') ||
377
+ fileName.includes('validation') ||
378
+ fileName.includes('guard') ||
379
+ fileName.includes('assert') ||
380
+ fileName.includes('constraint') ||
381
+ fileName.includes('boundary') ||
382
+ fileName.includes('policy') ||
383
+ fileName.includes('rule')
384
+ ) {
385
+ invariantFiles.push(fullPath);
386
+ }
387
+ }
388
+ }
389
+ } catch (error) {
390
+ // Skip directories we can't access
391
+ }
392
+ };
393
+
394
+ await walk(directory);
395
+ return invariantFiles;
396
+ }
397
+
398
+ /**
399
+ * Search for specific invariant implementation patterns
400
+ */
401
+ searchForInvariantPatterns(content) {
402
+ const patterns = [];
403
+
404
+ // Look for assertion/verification patterns
405
+ if (content.includes('assert(') || content.includes('AssertionError')) {
406
+ patterns.push({
407
+ type: 'assertion',
408
+ description: 'Assertion-based invariant checking found',
409
+ assertion: 'Code contains assert() calls for invariant enforcement'
410
+ });
411
+ }
412
+
413
+ // Look for validation patterns
414
+ if (content.includes('validate(') || content.includes('isValid') || content.includes('checkValid')) {
415
+ patterns.push({
416
+ type: 'validation',
417
+ description: 'Validation-based invariant checking found',
418
+ assertion: 'Code contains validation functions for invariant enforcement'
419
+ });
420
+ }
421
+
422
+ // Look for guard clauses
423
+ if (content.includes('if (!condition) throw') || content.includes('guard clause')) {
424
+ patterns.push({
425
+ type: 'guard_clause',
426
+ description: 'Guard clause invariant enforcement found',
427
+ assertion: 'Code contains early-exit guard clauses for invariant enforcement'
428
+ });
429
+ }
430
+
431
+ // Look for state machine patterns
432
+ if (content.includes('state') && (content.includes('transition') || content.includes('transitions'))) {
433
+ patterns.push({
434
+ type: 'state_machine',
435
+ description: 'State transition invariant found',
436
+ assertion: 'Code implements state machine with transition constraints'
437
+ });
438
+ }
439
+
440
+ return patterns;
441
+ }
442
+
443
+ /**
444
+ * Determine scope based on file path
445
+ */
446
+ determineScopeFromPath(filePath) {
447
+ if (!filePath) return 'module'; // Default to module if no path provided
448
+ if (filePath.includes('/core/') || filePath.includes('/lib/') || filePath.includes('/shared/')) {
449
+ return 'system';
450
+ } else if (filePath.includes('/modules/') || filePath.includes('/components/')) {
451
+ return 'boundary';
452
+ } else {
453
+ return 'module';
454
+ }
455
+ }
456
+
457
+ /**
458
+ * Check if file is accessible
459
+ */
460
+ async isFileAccessible(filePath) {
461
+ try {
462
+ await fs.access(filePath);
463
+ return true;
464
+ } catch {
465
+ return false;
466
+ }
467
+ }
468
+
469
+ /**
470
+ * Check if path represents a core layer
471
+ */
472
+ isCoreLayer(filePath) {
473
+ if (!filePath) return false;
474
+ return filePath.includes('/core/') ||
475
+ filePath.includes('/lib/') ||
476
+ filePath.includes('/shared/') ||
477
+ filePath.includes('config') ||
478
+ filePath.includes('auth');
479
+ }
480
+
481
+ /**
482
+ * Check if path represents a peripheral layer
483
+ */
484
+ isPeripheralLayer(filePath) {
485
+ if (!filePath) return false;
486
+ return filePath.includes('/views/') ||
487
+ filePath.includes('/templates/') ||
488
+ filePath.includes('/ui/') ||
489
+ filePath.includes('/tests/') ||
490
+ filePath.includes('/mocks/');
491
+ }
492
+
493
+ /**
494
+ * Generate unique invariant ID
495
+ */
496
+ generateInvariantId(pattern, context) {
497
+ const baseId = `${pattern}_${context}`.replace(/[^a-zA-Z0-9_-]/g, '_');
498
+ return baseId.substring(0, 100); // Limit length
499
+ }
500
+
501
+ /**
502
+ * Calculate confidence score for an invariant based on various factors
503
+ */
504
+ calculateConfidenceScore(pattern, context, content = '') {
505
+ let score = 0.5; // Base confidence
506
+
507
+ // Increase confidence based on pattern type
508
+ if (pattern.includes('assert') || pattern.includes('validate') || pattern.includes('guard')) {
509
+ score += 0.2;
510
+ }
511
+
512
+ if (pattern.includes('state') || pattern.includes('mutation') || pattern.includes('setState')) {
513
+ score += 0.15;
514
+ }
515
+
516
+ // Increase confidence if context suggests critical file
517
+ if (context.includes('core') || context.includes('lib') || context.includes('shared')) {
518
+ score += 0.1;
519
+ }
520
+
521
+ // Increase confidence based on frequency of pattern in content
522
+ if (content && typeof content === 'string') {
523
+ const matches = content.match(new RegExp(pattern, 'gi'));
524
+ if (matches && matches.length > 1) {
525
+ score += Math.min(matches.length * 0.05, 0.2); // Up to 0.2 for multiple matches
526
+ }
527
+ }
528
+
529
+ // Ensure score stays within bounds
530
+ return Math.min(Math.max(score, 0.1), 1.0);
531
+ }
532
+
533
+ /**
534
+ * Determine the owner of an invariant based on the source file
535
+ */
536
+ determineOwnerFromPath(filePath) {
537
+ if (!filePath) return 'unknown';
538
+
539
+ // Extract function or module name from file path
540
+ const parts = filePath.split(/[\/]/);
541
+ const fileName = parts[parts.length - 1];
542
+ const baseName = fileName.replace(/\.[^/.]+$/, ''); // Remove extension
543
+
544
+ return baseName;
545
+ }
546
+ }
547
+
548
+ module.exports = { InvariantDetector };