@ipation/specbridge 1.2.0 → 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/CHANGELOG.md +70 -1
- package/README.md +32 -1
- package/dist/cli.js +704 -209
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +146 -13
- package/dist/index.js +153 -42
- package/dist/index.js.map +1 -1
- package/dist/public/index.html +551 -0
- package/package.json +1 -1
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<
|
|
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
|
|
1706
|
+
* Select appropriate verifier based on constraint
|
|
1577
1707
|
*/
|
|
1578
|
-
declare function selectVerifierForConstraint(rule: string, specifiedVerifier?: string
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
|
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
|
|
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(
|
|
3384
|
-
lines.push(
|
|
3385
|
-
lines.push(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
3509
|
+
violationParts.push(chalk2.red(`${violations.critical} critical`));
|
|
3400
3510
|
}
|
|
3401
3511
|
if (violations.high > 0) {
|
|
3402
|
-
violationParts.push(
|
|
3512
|
+
violationParts.push(chalk2.yellow(`${violations.high} high`));
|
|
3403
3513
|
}
|
|
3404
3514
|
if (violations.medium > 0) {
|
|
3405
|
-
violationParts.push(
|
|
3515
|
+
violationParts.push(chalk2.cyan(`${violations.medium} medium`));
|
|
3406
3516
|
}
|
|
3407
3517
|
if (violations.low > 0) {
|
|
3408
|
-
violationParts.push(
|
|
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(
|
|
3523
|
+
lines.push(chalk2.green(" No violations"));
|
|
3414
3524
|
}
|
|
3415
3525
|
lines.push("");
|
|
3416
3526
|
if (report.byDecision.length > 0) {
|
|
3417
|
-
lines.push(
|
|
3527
|
+
lines.push(chalk2.bold("By Decision"));
|
|
3418
3528
|
lines.push("");
|
|
3419
3529
|
const tableData = [
|
|
3420
3530
|
[
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
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 ?
|
|
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
|
|
3470
|
-
if (compliance >= 70) return
|
|
3471
|
-
if (compliance >= 50) return
|
|
3472
|
-
return
|
|
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
|
|
3587
|
+
return chalk2.green;
|
|
3478
3588
|
case "draft":
|
|
3479
|
-
return
|
|
3589
|
+
return chalk2.yellow;
|
|
3480
3590
|
case "deprecated":
|
|
3481
|
-
return
|
|
3591
|
+
return chalk2.gray;
|
|
3482
3592
|
case "superseded":
|
|
3483
|
-
return
|
|
3593
|
+
return chalk2.blue;
|
|
3484
3594
|
default:
|
|
3485
|
-
return
|
|
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,
|