@ipation/specbridge 1.2.1 → 1.3.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/dist/index.d.ts CHANGED
@@ -33,6 +33,22 @@ interface DecisionContent {
33
33
  context?: string;
34
34
  consequences?: string[];
35
35
  }
36
+ /**
37
+ * Exception to a constraint
38
+ */
39
+ interface ConstraintException {
40
+ pattern: string;
41
+ reason: string;
42
+ approvedBy?: string;
43
+ expiresAt?: string;
44
+ }
45
+ /**
46
+ * Structured verifier check specification
47
+ */
48
+ interface ConstraintCheck {
49
+ verifier: string;
50
+ params?: Record<string, unknown>;
51
+ }
36
52
  /**
37
53
  * A single constraint within a decision
38
54
  */
@@ -43,18 +59,10 @@ interface Constraint {
43
59
  severity: Severity;
44
60
  scope: string;
45
61
  verifier?: string;
62
+ check?: ConstraintCheck;
46
63
  autofix?: boolean;
47
64
  exceptions?: ConstraintException[];
48
65
  }
49
- /**
50
- * Exception to a constraint
51
- */
52
- interface ConstraintException {
53
- pattern: string;
54
- reason: string;
55
- approvedBy?: string;
56
- expiresAt?: string;
57
- }
58
66
  /**
59
67
  * Automated verification configuration
60
68
  */
@@ -167,6 +175,27 @@ interface LevelConfig {
167
175
  timeout?: number;
168
176
  severity?: Severity[];
169
177
  }
178
+ /**
179
+ * Warning during verification (non-blocking)
180
+ */
181
+ interface VerificationWarning {
182
+ type: 'missing_verifier' | 'invalid_pattern' | 'other';
183
+ message: string;
184
+ decisionId: string;
185
+ constraintId: string;
186
+ file?: string;
187
+ }
188
+ /**
189
+ * Error during verification (continued after error)
190
+ */
191
+ interface VerificationIssue {
192
+ type: 'verifier_exception' | 'file_read_error' | 'other';
193
+ message: string;
194
+ decisionId?: string;
195
+ constraintId?: string;
196
+ file?: string;
197
+ stack?: string;
198
+ }
170
199
  /**
171
200
  * Result of a verification run
172
201
  */
@@ -178,6 +207,8 @@ interface VerificationResult {
178
207
  failed: number;
179
208
  skipped: number;
180
209
  duration: number;
210
+ warnings?: VerificationWarning[];
211
+ errors?: VerificationIssue[];
181
212
  }
182
213
  /**
183
214
  * Result of an inference run
@@ -350,6 +381,16 @@ declare const ConstraintExceptionSchema: z.ZodObject<{
350
381
  approvedBy?: string | undefined;
351
382
  expiresAt?: string | undefined;
352
383
  }>;
384
+ declare const ConstraintCheckSchema: z.ZodObject<{
385
+ verifier: z.ZodString;
386
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
387
+ }, "strip", z.ZodTypeAny, {
388
+ verifier: string;
389
+ params?: Record<string, unknown> | undefined;
390
+ }, {
391
+ verifier: string;
392
+ params?: Record<string, unknown> | undefined;
393
+ }>;
353
394
  declare const ConstraintSchema: z.ZodObject<{
354
395
  id: z.ZodString;
355
396
  type: z.ZodEnum<["invariant", "convention", "guideline"]>;
@@ -357,6 +398,16 @@ declare const ConstraintSchema: z.ZodObject<{
357
398
  severity: z.ZodEnum<["critical", "high", "medium", "low"]>;
358
399
  scope: z.ZodString;
359
400
  verifier: z.ZodOptional<z.ZodString>;
401
+ check: z.ZodOptional<z.ZodObject<{
402
+ verifier: z.ZodString;
403
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
404
+ }, "strip", z.ZodTypeAny, {
405
+ verifier: string;
406
+ params?: Record<string, unknown> | undefined;
407
+ }, {
408
+ verifier: string;
409
+ params?: Record<string, unknown> | undefined;
410
+ }>>;
360
411
  autofix: z.ZodOptional<z.ZodBoolean>;
361
412
  exceptions: z.ZodOptional<z.ZodArray<z.ZodObject<{
362
413
  pattern: z.ZodString;
@@ -381,6 +432,10 @@ declare const ConstraintSchema: z.ZodObject<{
381
432
  severity: "critical" | "high" | "medium" | "low";
382
433
  scope: string;
383
434
  verifier?: string | undefined;
435
+ check?: {
436
+ verifier: string;
437
+ params?: Record<string, unknown> | undefined;
438
+ } | undefined;
384
439
  autofix?: boolean | undefined;
385
440
  exceptions?: {
386
441
  pattern: string;
@@ -395,6 +450,10 @@ declare const ConstraintSchema: z.ZodObject<{
395
450
  severity: "critical" | "high" | "medium" | "low";
396
451
  scope: string;
397
452
  verifier?: string | undefined;
453
+ check?: {
454
+ verifier: string;
455
+ params?: Record<string, unknown> | undefined;
456
+ } | undefined;
398
457
  autofix?: boolean | undefined;
399
458
  exceptions?: {
400
459
  pattern: string;
@@ -485,6 +544,16 @@ declare const DecisionSchema: z.ZodObject<{
485
544
  severity: z.ZodEnum<["critical", "high", "medium", "low"]>;
486
545
  scope: z.ZodString;
487
546
  verifier: z.ZodOptional<z.ZodString>;
547
+ check: z.ZodOptional<z.ZodObject<{
548
+ verifier: z.ZodString;
549
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
550
+ }, "strip", z.ZodTypeAny, {
551
+ verifier: string;
552
+ params?: Record<string, unknown> | undefined;
553
+ }, {
554
+ verifier: string;
555
+ params?: Record<string, unknown> | undefined;
556
+ }>>;
488
557
  autofix: z.ZodOptional<z.ZodBoolean>;
489
558
  exceptions: z.ZodOptional<z.ZodArray<z.ZodObject<{
490
559
  pattern: z.ZodString;
@@ -509,6 +578,10 @@ declare const DecisionSchema: z.ZodObject<{
509
578
  severity: "critical" | "high" | "medium" | "low";
510
579
  scope: string;
511
580
  verifier?: string | undefined;
581
+ check?: {
582
+ verifier: string;
583
+ params?: Record<string, unknown> | undefined;
584
+ } | undefined;
512
585
  autofix?: boolean | undefined;
513
586
  exceptions?: {
514
587
  pattern: string;
@@ -523,6 +596,10 @@ declare const DecisionSchema: z.ZodObject<{
523
596
  severity: "critical" | "high" | "medium" | "low";
524
597
  scope: string;
525
598
  verifier?: string | undefined;
599
+ check?: {
600
+ verifier: string;
601
+ params?: Record<string, unknown> | undefined;
602
+ } | undefined;
526
603
  autofix?: boolean | undefined;
527
604
  exceptions?: {
528
605
  pattern: string;
@@ -601,6 +678,10 @@ declare const DecisionSchema: z.ZodObject<{
601
678
  severity: "critical" | "high" | "medium" | "low";
602
679
  scope: string;
603
680
  verifier?: string | undefined;
681
+ check?: {
682
+ verifier: string;
683
+ params?: Record<string, unknown> | undefined;
684
+ } | undefined;
604
685
  autofix?: boolean | undefined;
605
686
  exceptions?: {
606
687
  pattern: string;
@@ -647,6 +728,10 @@ declare const DecisionSchema: z.ZodObject<{
647
728
  severity: "critical" | "high" | "medium" | "low";
648
729
  scope: string;
649
730
  verifier?: string | undefined;
731
+ check?: {
732
+ verifier: string;
733
+ params?: Record<string, unknown> | undefined;
734
+ } | undefined;
650
735
  autofix?: boolean | undefined;
651
736
  exceptions?: {
652
737
  pattern: string;
@@ -676,6 +761,7 @@ type VerificationFrequencySchema_ = z.infer<typeof VerificationFrequencySchema>;
676
761
  type DecisionMetadataSchema_ = z.infer<typeof DecisionMetadataSchema>;
677
762
  type DecisionContentSchema_ = z.infer<typeof DecisionContentSchema>;
678
763
  type ConstraintExceptionSchema_ = z.infer<typeof ConstraintExceptionSchema>;
764
+ type ConstraintCheckSchema_ = z.infer<typeof ConstraintCheckSchema>;
679
765
  type ConstraintSchema_ = z.infer<typeof ConstraintSchema>;
680
766
  type VerificationConfigSchema_ = z.infer<typeof VerificationConfigSchema>;
681
767
  type DecisionTypeSchema = z.infer<typeof DecisionSchema>;
@@ -1378,6 +1464,45 @@ declare function getAnalyzer(id: string): Analyzer | null;
1378
1464
  */
1379
1465
  declare function getAnalyzerIds(): string[];
1380
1466
 
1467
+ /**
1468
+ * Entry in the explanation trace
1469
+ */
1470
+ interface ExplanationEntry {
1471
+ file: string;
1472
+ decision: Decision;
1473
+ constraint: Constraint;
1474
+ applied: boolean;
1475
+ reason: string;
1476
+ selectedVerifier?: string;
1477
+ verifierOutput?: {
1478
+ violations: number;
1479
+ duration: number;
1480
+ error?: string;
1481
+ };
1482
+ }
1483
+ /**
1484
+ * Reporter for --explain mode
1485
+ */
1486
+ declare class ExplainReporter {
1487
+ private entries;
1488
+ /**
1489
+ * Add an entry to the explanation trace
1490
+ */
1491
+ add(entry: ExplanationEntry): void;
1492
+ /**
1493
+ * Print the explanation trace
1494
+ */
1495
+ print(): void;
1496
+ /**
1497
+ * Get all entries
1498
+ */
1499
+ getEntries(): ExplanationEntry[];
1500
+ /**
1501
+ * Clear all entries
1502
+ */
1503
+ clear(): void;
1504
+ }
1505
+
1381
1506
  interface VerificationOptions {
1382
1507
  level?: VerificationLevel;
1383
1508
  files?: string[];
@@ -1385,6 +1510,7 @@ interface VerificationOptions {
1385
1510
  severity?: Severity[];
1386
1511
  timeout?: number;
1387
1512
  cwd?: string;
1513
+ reporter?: ExplainReporter;
1388
1514
  }
1389
1515
  /**
1390
1516
  * Verification Engine class
@@ -1401,7 +1527,11 @@ declare class VerificationEngine {
1401
1527
  /**
1402
1528
  * Verify a single file
1403
1529
  */
1404
- verifyFile(filePath: string, decisions: Decision[], severityFilter?: Severity[], cwd?: string): Promise<Violation[]>;
1530
+ verifyFile(filePath: string, decisions: Decision[], severityFilter?: Severity[], cwd?: string, reporter?: ExplainReporter): Promise<{
1531
+ violations: Violation[];
1532
+ warnings: VerificationWarning[];
1533
+ errors: VerificationIssue[];
1534
+ }>;
1405
1535
  /**
1406
1536
  * Verify multiple files
1407
1537
  */
@@ -1573,9 +1703,12 @@ declare function getVerifier(id: string): Verifier | null;
1573
1703
  */
1574
1704
  declare function getVerifierIds(): string[];
1575
1705
  /**
1576
- * Select appropriate verifier based on constraint rule
1706
+ * Select appropriate verifier based on constraint
1577
1707
  */
1578
- declare function selectVerifierForConstraint(rule: string, specifiedVerifier?: string): Verifier | null;
1708
+ declare function selectVerifierForConstraint(rule: string, specifiedVerifier?: string, check?: {
1709
+ verifier: string;
1710
+ params?: Record<string, unknown>;
1711
+ }): Verifier | null;
1579
1712
 
1580
1713
  interface AutofixPatch {
1581
1714
  filePath: string;
@@ -2020,4 +2153,4 @@ declare function matchesAnyPattern(filePath: string, patterns: string[], options
2020
2153
  cwd?: string;
2021
2154
  }): boolean;
2022
2155
 
2023
- export { type AffectedFile, type AgentContext, AgentContextGenerator, AlreadyInitializedError, type Analyzer, AnalyzerNotFoundError, ApiVerifier, type ApplicableConstraint, type ApplicableDecision, AstCache, AutofixEngine, type AutofixPatch, type AutofixResult, CodeScanner, ComplexityVerifier, type ComplianceReport, ConfigError, type Constraint, type ConstraintException, ConstraintExceptionSchema, type ConstraintExceptionSchema_, ConstraintSchema, type ConstraintSchema_, type ConstraintType, ConstraintTypeSchema, type ConstraintTypeSchema_, type ContextOptions, type Decision, type DecisionCompliance, type DecisionContent, DecisionContentSchema, type DecisionContentSchema_, type DecisionFilter, type DecisionMetadata, DecisionMetadataSchema, type DecisionMetadataSchema_, DecisionNotFoundError, DecisionSchema, type DecisionStatus, DecisionStatusSchema, type DecisionStatusSchema_, type DecisionTypeSchema, DecisionValidationError, type DependencyGraph, DependencyVerifier, type DriftAnalysis, ErrorsAnalyzer, ErrorsVerifier, FileSystemError, type GlobOptions, type GraphNode, HookError, type ImpactAnalysis, ImportsAnalyzer, ImportsVerifier, InferenceEngine, InferenceError, type InferenceOptions, type InferenceResult, type LevelConfig, LinksSchema, type LoadError, type LoadResult, type LoadedDecision, type McpServerOptions, type MigrationStep, NamingAnalyzer, NamingVerifier, NotInitializedError, type OverallDrift, type Pattern, type PatternExample, type PromptTemplate, PropagationEngine, type PropagationOptions, RegexVerifier, Registry, type RegistryConstraintMatch, RegistryError, type RegistryOptions, type ReportOptions, ReportStorage, Reporter, type ScanOptions, type ScanResult, type ScannedFile, SecurityVerifier, type Severity, SeveritySchema, type SeveritySchema_, type SpecBridgeConfig, SpecBridgeConfigSchema, type SpecBridgeConfigType, SpecBridgeError, SpecBridgeMcpServer, type StoredReport, StructureAnalyzer, type TextEdit, type TrendAnalysis, type TrendData, type TrendDirection, type VerificationConfig, VerificationConfigSchema, type VerificationConfigSchema_, type VerificationContext, VerificationEngine, VerificationError, type VerificationFrequency, VerificationFrequencySchema, type VerificationFrequencySchema_, type VerificationLevel, type VerificationOptions, type VerificationResult, type Verifier, VerifierNotFoundError, type Violation, type ViolationFix, analyzeTrend, buildDependencyGraph, builtinAnalyzers, builtinVerifiers, calculateConfidence, checkDegradation, createInferenceEngine, createPattern, createPropagationEngine, createRegistry, createScannerFromConfig, createVerificationEngine, createViolation, defaultConfig, detectDrift, ensureDir, extractSnippet, formatConsoleReport, formatContextAsJson, formatContextAsMarkdown, formatContextAsMcp, formatError, formatMarkdownReport, formatValidationErrors, generateContext, generateFormattedContext, generateReport, getAffectedFiles, getAffectingDecisions, getAnalyzer, getAnalyzerIds, getChangedFiles, getConfigPath, getDecisionsDir, getInferredDir, getReportsDir, getSpecBridgeDir, getTransitiveDependencies, getVerifier, getVerifierIds, getVerifiersDir, glob, isConstraintExcepted, isDirectory, loadConfig, loadDecisionFile, loadDecisionsFromDir, matchesAnyPattern, matchesPattern, mergeWithDefaults, normalizePath, parseYaml, parseYamlDocument, pathExists, readFilesInDir, readTextFile, runInference, selectVerifierForConstraint, shouldApplyConstraintToFile, stringifyYaml, templates, updateYamlDocument, validateConfig, validateDecision, validateDecisionFile, writeTextFile };
2156
+ export { type AffectedFile, type AgentContext, AgentContextGenerator, AlreadyInitializedError, type Analyzer, AnalyzerNotFoundError, ApiVerifier, type ApplicableConstraint, type ApplicableDecision, AstCache, AutofixEngine, type AutofixPatch, type AutofixResult, CodeScanner, ComplexityVerifier, type ComplianceReport, ConfigError, type Constraint, type ConstraintCheck, ConstraintCheckSchema, type ConstraintCheckSchema_, type ConstraintException, ConstraintExceptionSchema, type ConstraintExceptionSchema_, ConstraintSchema, type ConstraintSchema_, type ConstraintType, ConstraintTypeSchema, type ConstraintTypeSchema_, type ContextOptions, type Decision, type DecisionCompliance, type DecisionContent, DecisionContentSchema, type DecisionContentSchema_, type DecisionFilter, type DecisionMetadata, DecisionMetadataSchema, type DecisionMetadataSchema_, DecisionNotFoundError, DecisionSchema, type DecisionStatus, DecisionStatusSchema, type DecisionStatusSchema_, type DecisionTypeSchema, DecisionValidationError, type DependencyGraph, DependencyVerifier, type DriftAnalysis, ErrorsAnalyzer, ErrorsVerifier, FileSystemError, type GlobOptions, type GraphNode, HookError, type ImpactAnalysis, ImportsAnalyzer, ImportsVerifier, InferenceEngine, InferenceError, type InferenceOptions, type InferenceResult, type LevelConfig, LinksSchema, type LoadError, type LoadResult, type LoadedDecision, type McpServerOptions, type MigrationStep, NamingAnalyzer, NamingVerifier, NotInitializedError, type OverallDrift, type Pattern, type PatternExample, type PromptTemplate, PropagationEngine, type PropagationOptions, RegexVerifier, Registry, type RegistryConstraintMatch, RegistryError, type RegistryOptions, type ReportOptions, ReportStorage, Reporter, type ScanOptions, type ScanResult, type ScannedFile, SecurityVerifier, type Severity, SeveritySchema, type SeveritySchema_, type SpecBridgeConfig, SpecBridgeConfigSchema, type SpecBridgeConfigType, SpecBridgeError, SpecBridgeMcpServer, type StoredReport, StructureAnalyzer, type TextEdit, type TrendAnalysis, type TrendData, type TrendDirection, type VerificationConfig, VerificationConfigSchema, type VerificationConfigSchema_, type VerificationContext, VerificationEngine, VerificationError, type VerificationFrequency, VerificationFrequencySchema, type VerificationFrequencySchema_, type VerificationIssue, type VerificationLevel, type VerificationOptions, type VerificationResult, type VerificationWarning, type Verifier, VerifierNotFoundError, type Violation, type ViolationFix, analyzeTrend, buildDependencyGraph, builtinAnalyzers, builtinVerifiers, calculateConfidence, checkDegradation, createInferenceEngine, createPattern, createPropagationEngine, createRegistry, createScannerFromConfig, createVerificationEngine, createViolation, defaultConfig, detectDrift, ensureDir, extractSnippet, formatConsoleReport, formatContextAsJson, formatContextAsMarkdown, formatContextAsMcp, formatError, formatMarkdownReport, formatValidationErrors, generateContext, generateFormattedContext, generateReport, getAffectedFiles, getAffectingDecisions, getAnalyzer, getAnalyzerIds, getChangedFiles, getConfigPath, getDecisionsDir, getInferredDir, getReportsDir, getSpecBridgeDir, getTransitiveDependencies, getVerifier, getVerifierIds, getVerifiersDir, glob, isConstraintExcepted, isDirectory, loadConfig, loadDecisionFile, loadDecisionsFromDir, matchesAnyPattern, matchesPattern, mergeWithDefaults, normalizePath, parseYaml, parseYamlDocument, pathExists, readFilesInDir, readTextFile, runInference, selectVerifierForConstraint, shouldApplyConstraintToFile, stringifyYaml, templates, updateYamlDocument, validateConfig, validateDecision, validateDecisionFile, writeTextFile };
package/dist/index.js CHANGED
@@ -26,6 +26,10 @@ var ConstraintExceptionSchema = z.object({
26
26
  approvedBy: z.string().optional(),
27
27
  expiresAt: z.string().datetime().optional()
28
28
  });
29
+ var ConstraintCheckSchema = z.object({
30
+ verifier: z.string().min(1),
31
+ params: z.record(z.unknown()).optional()
32
+ });
29
33
  var ConstraintSchema = z.object({
30
34
  id: z.string().min(1).regex(/^[a-z0-9-]+$/, "Constraint ID must be lowercase alphanumeric with hyphens"),
31
35
  type: ConstraintTypeSchema,
@@ -33,6 +37,7 @@ var ConstraintSchema = z.object({
33
37
  severity: SeveritySchema,
34
38
  scope: z.string().min(1),
35
39
  verifier: z.string().optional(),
40
+ check: ConstraintCheckSchema.optional(),
36
41
  autofix: z.boolean().optional(),
37
42
  exceptions: z.array(ConstraintExceptionSchema).optional()
38
43
  });
@@ -1577,6 +1582,7 @@ async function runInference(config, options) {
1577
1582
 
1578
1583
  // src/verification/engine.ts
1579
1584
  import { Project as Project2 } from "ts-morph";
1585
+ import chalk from "chalk";
1580
1586
 
1581
1587
  // src/verification/verifiers/base.ts
1582
1588
  function createViolation(params) {
@@ -2577,7 +2583,10 @@ function getVerifier(id) {
2577
2583
  function getVerifierIds() {
2578
2584
  return Object.keys(builtinVerifiers);
2579
2585
  }
2580
- function selectVerifierForConstraint(rule, specifiedVerifier) {
2586
+ function selectVerifierForConstraint(rule, specifiedVerifier, check) {
2587
+ if (check?.verifier) {
2588
+ return getVerifier(check.verifier);
2589
+ }
2581
2590
  if (specifiedVerifier) {
2582
2591
  return getVerifier(specifiedVerifier);
2583
2592
  }
@@ -2708,10 +2717,14 @@ var VerificationEngine = class {
2708
2717
  passed: 0,
2709
2718
  failed: 0,
2710
2719
  skipped: 0,
2711
- duration: Date.now() - startTime
2720
+ duration: Date.now() - startTime,
2721
+ warnings: [],
2722
+ errors: []
2712
2723
  };
2713
2724
  }
2714
2725
  const allViolations = [];
2726
+ const allWarnings = [];
2727
+ const allErrors = [];
2715
2728
  let checked = 0;
2716
2729
  let passed = 0;
2717
2730
  let failed = 0;
@@ -2726,8 +2739,11 @@ var VerificationEngine = class {
2726
2739
  decisions,
2727
2740
  severityFilter,
2728
2741
  cwd,
2729
- (violations) => {
2742
+ options.reporter,
2743
+ (violations, warnings, errors) => {
2730
2744
  allViolations.push(...violations);
2745
+ allWarnings.push(...warnings);
2746
+ allErrors.push(...errors);
2731
2747
  checked++;
2732
2748
  if (violations.length > 0) {
2733
2749
  failed++;
@@ -2747,7 +2763,9 @@ var VerificationEngine = class {
2747
2763
  passed,
2748
2764
  failed,
2749
2765
  skipped: filesToVerify.length - checked,
2750
- duration: timeout
2766
+ duration: timeout,
2767
+ warnings: allWarnings,
2768
+ errors: allErrors
2751
2769
  };
2752
2770
  }
2753
2771
  } finally {
@@ -2772,23 +2790,64 @@ var VerificationEngine = class {
2772
2790
  passed,
2773
2791
  failed,
2774
2792
  skipped,
2775
- duration: Date.now() - startTime
2793
+ duration: Date.now() - startTime,
2794
+ warnings: allWarnings,
2795
+ errors: allErrors
2776
2796
  };
2777
2797
  }
2778
2798
  /**
2779
2799
  * Verify a single file
2780
2800
  */
2781
- async verifyFile(filePath, decisions, severityFilter, cwd = process.cwd()) {
2801
+ async verifyFile(filePath, decisions, severityFilter, cwd = process.cwd(), reporter) {
2782
2802
  const violations = [];
2803
+ const warnings = [];
2804
+ const errors = [];
2783
2805
  const sourceFile = await this.astCache.get(filePath, this.project);
2784
- if (!sourceFile) return violations;
2806
+ if (!sourceFile) return { violations, warnings, errors };
2785
2807
  for (const decision of decisions) {
2786
2808
  for (const constraint of decision.constraints) {
2787
2809
  if (!shouldApplyConstraintToFile({ filePath, constraint, cwd, severityFilter })) {
2810
+ if (reporter) {
2811
+ reporter.add({
2812
+ file: filePath,
2813
+ decision,
2814
+ constraint,
2815
+ applied: false,
2816
+ reason: "File does not match scope pattern or severity filter"
2817
+ });
2818
+ }
2788
2819
  continue;
2789
2820
  }
2790
- const verifier = selectVerifierForConstraint(constraint.rule, constraint.verifier);
2821
+ const verifier = selectVerifierForConstraint(
2822
+ constraint.rule,
2823
+ constraint.verifier,
2824
+ constraint.check
2825
+ );
2791
2826
  if (!verifier) {
2827
+ const requestedVerifier = constraint.check?.verifier || constraint.verifier || "auto-detected";
2828
+ console.warn(
2829
+ chalk.yellow(
2830
+ `Warning: No verifier found for ${decision.metadata.id}/${constraint.id}
2831
+ Requested: ${requestedVerifier}
2832
+ Available: ${getVerifierIds().join(", ")}`
2833
+ )
2834
+ );
2835
+ warnings.push({
2836
+ type: "missing_verifier",
2837
+ message: `No verifier found for constraint (requested: ${requestedVerifier})`,
2838
+ decisionId: decision.metadata.id,
2839
+ constraintId: constraint.id,
2840
+ file: filePath
2841
+ });
2842
+ if (reporter) {
2843
+ reporter.add({
2844
+ file: filePath,
2845
+ decision,
2846
+ constraint,
2847
+ applied: false,
2848
+ reason: `No verifier found (requested: ${requestedVerifier})`
2849
+ });
2850
+ }
2792
2851
  continue;
2793
2852
  }
2794
2853
  const ctx = {
@@ -2797,27 +2856,78 @@ var VerificationEngine = class {
2797
2856
  constraint,
2798
2857
  decisionId: decision.metadata.id
2799
2858
  };
2859
+ const verificationStart = Date.now();
2800
2860
  try {
2801
2861
  const constraintViolations = await verifier.verify(ctx);
2802
2862
  violations.push(...constraintViolations);
2803
- } catch {
2863
+ if (reporter) {
2864
+ reporter.add({
2865
+ file: filePath,
2866
+ decision,
2867
+ constraint,
2868
+ applied: true,
2869
+ reason: "Constraint matches file scope",
2870
+ selectedVerifier: verifier.id,
2871
+ verifierOutput: {
2872
+ violations: constraintViolations.length,
2873
+ duration: Date.now() - verificationStart
2874
+ }
2875
+ });
2876
+ }
2877
+ } catch (error) {
2878
+ const errorMessage = error instanceof Error ? error.message : String(error);
2879
+ const errorStack = error instanceof Error ? error.stack : void 0;
2880
+ console.error(
2881
+ chalk.red(
2882
+ `Error: Verifier '${verifier.id}' failed
2883
+ File: ${filePath}
2884
+ Decision: ${decision.metadata.id}/${constraint.id}
2885
+ Error: ${errorMessage}`
2886
+ )
2887
+ );
2888
+ if (errorStack) {
2889
+ console.error(chalk.dim(errorStack));
2890
+ }
2891
+ errors.push({
2892
+ type: "verifier_exception",
2893
+ message: `Verifier '${verifier.id}' failed: ${errorMessage}`,
2894
+ decisionId: decision.metadata.id,
2895
+ constraintId: constraint.id,
2896
+ file: filePath,
2897
+ stack: errorStack
2898
+ });
2899
+ if (reporter) {
2900
+ reporter.add({
2901
+ file: filePath,
2902
+ decision,
2903
+ constraint,
2904
+ applied: true,
2905
+ reason: "Constraint matches file scope",
2906
+ selectedVerifier: verifier.id,
2907
+ verifierOutput: {
2908
+ violations: 0,
2909
+ duration: Date.now() - verificationStart,
2910
+ error: errorMessage
2911
+ }
2912
+ });
2913
+ }
2804
2914
  }
2805
2915
  }
2806
2916
  }
2807
- return violations;
2917
+ return { violations, warnings, errors };
2808
2918
  }
2809
2919
  /**
2810
2920
  * Verify multiple files
2811
2921
  */
2812
- async verifyFiles(files, decisions, severityFilter, cwd, onFileVerified) {
2922
+ async verifyFiles(files, decisions, severityFilter, cwd, reporter, onFileVerified) {
2813
2923
  const BATCH_SIZE = 10;
2814
2924
  for (let i = 0; i < files.length; i += BATCH_SIZE) {
2815
2925
  const batch = files.slice(i, i + BATCH_SIZE);
2816
2926
  const results = await Promise.all(
2817
- batch.map((file) => this.verifyFile(file, decisions, severityFilter, cwd))
2927
+ batch.map((file) => this.verifyFile(file, decisions, severityFilter, cwd, reporter))
2818
2928
  );
2819
- for (const violations of results) {
2820
- onFileVerified(violations);
2929
+ for (const result of results) {
2930
+ onFileVerified(result.violations, result.warnings, result.errors);
2821
2931
  }
2822
2932
  }
2823
2933
  }
@@ -3375,54 +3485,54 @@ var Reporter = class {
3375
3485
  };
3376
3486
 
3377
3487
  // src/reporting/formats/console.ts
3378
- import chalk from "chalk";
3488
+ import chalk2 from "chalk";
3379
3489
  import { table } from "table";
3380
3490
  function formatConsoleReport(report) {
3381
3491
  const lines = [];
3382
3492
  lines.push("");
3383
- lines.push(chalk.bold.blue("SpecBridge Compliance Report"));
3384
- lines.push(chalk.dim(`Generated: ${new Date(report.timestamp).toLocaleString()}`));
3385
- lines.push(chalk.dim(`Project: ${report.project}`));
3493
+ lines.push(chalk2.bold.blue("SpecBridge Compliance Report"));
3494
+ lines.push(chalk2.dim(`Generated: ${new Date(report.timestamp).toLocaleString()}`));
3495
+ lines.push(chalk2.dim(`Project: ${report.project}`));
3386
3496
  lines.push("");
3387
3497
  const complianceColor = getComplianceColor(report.summary.compliance);
3388
- lines.push(chalk.bold("Overall Compliance"));
3498
+ lines.push(chalk2.bold("Overall Compliance"));
3389
3499
  lines.push(` ${complianceColor(formatComplianceBar(report.summary.compliance))} ${complianceColor(`${report.summary.compliance}%`)}`);
3390
3500
  lines.push("");
3391
- lines.push(chalk.bold("Summary"));
3501
+ lines.push(chalk2.bold("Summary"));
3392
3502
  lines.push(` Decisions: ${report.summary.activeDecisions} active / ${report.summary.totalDecisions} total`);
3393
3503
  lines.push(` Constraints: ${report.summary.totalConstraints}`);
3394
3504
  lines.push("");
3395
- lines.push(chalk.bold("Violations"));
3505
+ lines.push(chalk2.bold("Violations"));
3396
3506
  const { violations } = report.summary;
3397
3507
  const violationParts = [];
3398
3508
  if (violations.critical > 0) {
3399
- violationParts.push(chalk.red(`${violations.critical} critical`));
3509
+ violationParts.push(chalk2.red(`${violations.critical} critical`));
3400
3510
  }
3401
3511
  if (violations.high > 0) {
3402
- violationParts.push(chalk.yellow(`${violations.high} high`));
3512
+ violationParts.push(chalk2.yellow(`${violations.high} high`));
3403
3513
  }
3404
3514
  if (violations.medium > 0) {
3405
- violationParts.push(chalk.cyan(`${violations.medium} medium`));
3515
+ violationParts.push(chalk2.cyan(`${violations.medium} medium`));
3406
3516
  }
3407
3517
  if (violations.low > 0) {
3408
- violationParts.push(chalk.dim(`${violations.low} low`));
3518
+ violationParts.push(chalk2.dim(`${violations.low} low`));
3409
3519
  }
3410
3520
  if (violationParts.length > 0) {
3411
3521
  lines.push(` ${violationParts.join(" | ")}`);
3412
3522
  } else {
3413
- lines.push(chalk.green(" No violations"));
3523
+ lines.push(chalk2.green(" No violations"));
3414
3524
  }
3415
3525
  lines.push("");
3416
3526
  if (report.byDecision.length > 0) {
3417
- lines.push(chalk.bold("By Decision"));
3527
+ lines.push(chalk2.bold("By Decision"));
3418
3528
  lines.push("");
3419
3529
  const tableData = [
3420
3530
  [
3421
- chalk.bold("Decision"),
3422
- chalk.bold("Status"),
3423
- chalk.bold("Constraints"),
3424
- chalk.bold("Violations"),
3425
- chalk.bold("Compliance")
3531
+ chalk2.bold("Decision"),
3532
+ chalk2.bold("Status"),
3533
+ chalk2.bold("Constraints"),
3534
+ chalk2.bold("Violations"),
3535
+ chalk2.bold("Compliance")
3426
3536
  ]
3427
3537
  ];
3428
3538
  for (const dec of report.byDecision) {
@@ -3432,7 +3542,7 @@ function formatConsoleReport(report) {
3432
3542
  truncate(dec.title, 40),
3433
3543
  statusColor(dec.status),
3434
3544
  String(dec.constraints),
3435
- dec.violations > 0 ? chalk.red(String(dec.violations)) : chalk.green("0"),
3545
+ dec.violations > 0 ? chalk2.red(String(dec.violations)) : chalk2.green("0"),
3436
3546
  compColor(`${dec.compliance}%`)
3437
3547
  ]);
3438
3548
  }
@@ -3466,23 +3576,23 @@ function formatComplianceBar(compliance) {
3466
3576
  return "\u2588".repeat(filled) + "\u2591".repeat(empty);
3467
3577
  }
3468
3578
  function getComplianceColor(compliance) {
3469
- if (compliance >= 90) return chalk.green;
3470
- if (compliance >= 70) return chalk.yellow;
3471
- if (compliance >= 50) return chalk.hex("#FFA500");
3472
- return chalk.red;
3579
+ if (compliance >= 90) return chalk2.green;
3580
+ if (compliance >= 70) return chalk2.yellow;
3581
+ if (compliance >= 50) return chalk2.hex("#FFA500");
3582
+ return chalk2.red;
3473
3583
  }
3474
3584
  function getStatusColor(status) {
3475
3585
  switch (status) {
3476
3586
  case "active":
3477
- return chalk.green;
3587
+ return chalk2.green;
3478
3588
  case "draft":
3479
- return chalk.yellow;
3589
+ return chalk2.yellow;
3480
3590
  case "deprecated":
3481
- return chalk.gray;
3591
+ return chalk2.gray;
3482
3592
  case "superseded":
3483
- return chalk.blue;
3593
+ return chalk2.blue;
3484
3594
  default:
3485
- return chalk.white;
3595
+ return chalk2.white;
3486
3596
  }
3487
3597
  }
3488
3598
  function truncate(str, length) {
@@ -4269,6 +4379,7 @@ export {
4269
4379
  CodeScanner,
4270
4380
  ComplexityVerifier,
4271
4381
  ConfigError,
4382
+ ConstraintCheckSchema,
4272
4383
  ConstraintExceptionSchema,
4273
4384
  ConstraintSchema,
4274
4385
  ConstraintTypeSchema,