@grafema/util 0.3.0-beta
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/LICENSE +190 -0
- package/dist/api/GraphAPI.d.ts +87 -0
- package/dist/api/GraphAPI.d.ts.map +1 -0
- package/dist/api/GraphAPI.js +212 -0
- package/dist/api/GraphAPI.js.map +1 -0
- package/dist/api/GuaranteeAPI.d.ts +147 -0
- package/dist/api/GuaranteeAPI.d.ts.map +1 -0
- package/dist/api/GuaranteeAPI.js +290 -0
- package/dist/api/GuaranteeAPI.js.map +1 -0
- package/dist/config/ConfigLoader.d.ts +214 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +441 -0
- package/dist/config/ConfigLoader.js.map +1 -0
- package/dist/config/index.d.ts +6 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +5 -0
- package/dist/config/index.js.map +1 -0
- package/dist/core/CoverageAnalyzer.d.ts +65 -0
- package/dist/core/CoverageAnalyzer.d.ts.map +1 -0
- package/dist/core/CoverageAnalyzer.js +199 -0
- package/dist/core/CoverageAnalyzer.js.map +1 -0
- package/dist/core/FileExplainer.d.ts +101 -0
- package/dist/core/FileExplainer.d.ts.map +1 -0
- package/dist/core/FileExplainer.js +140 -0
- package/dist/core/FileExplainer.js.map +1 -0
- package/dist/core/FileOverview.d.ts +124 -0
- package/dist/core/FileOverview.d.ts.map +1 -0
- package/dist/core/FileOverview.js +279 -0
- package/dist/core/FileOverview.js.map +1 -0
- package/dist/core/GrafemaUri.d.ts +66 -0
- package/dist/core/GrafemaUri.d.ts.map +1 -0
- package/dist/core/GrafemaUri.js +191 -0
- package/dist/core/GrafemaUri.js.map +1 -0
- package/dist/core/GraphBackend.d.ts +158 -0
- package/dist/core/GraphBackend.d.ts.map +1 -0
- package/dist/core/GraphBackend.js +85 -0
- package/dist/core/GraphBackend.js.map +1 -0
- package/dist/core/GraphFreshnessChecker.d.ts +33 -0
- package/dist/core/GraphFreshnessChecker.d.ts.map +1 -0
- package/dist/core/GraphFreshnessChecker.js +104 -0
- package/dist/core/GraphFreshnessChecker.js.map +1 -0
- package/dist/core/GuaranteeManager.d.ts +254 -0
- package/dist/core/GuaranteeManager.d.ts.map +1 -0
- package/dist/core/GuaranteeManager.js +447 -0
- package/dist/core/GuaranteeManager.js.map +1 -0
- package/dist/core/HashUtils.d.ts +24 -0
- package/dist/core/HashUtils.d.ts.map +1 -0
- package/dist/core/HashUtils.js +46 -0
- package/dist/core/HashUtils.js.map +1 -0
- package/dist/core/IncrementalReanalyzer.d.ts +33 -0
- package/dist/core/IncrementalReanalyzer.d.ts.map +1 -0
- package/dist/core/IncrementalReanalyzer.js +67 -0
- package/dist/core/IncrementalReanalyzer.js.map +1 -0
- package/dist/core/ResourceRegistry.d.ts +17 -0
- package/dist/core/ResourceRegistry.d.ts.map +1 -0
- package/dist/core/ResourceRegistry.js +32 -0
- package/dist/core/ResourceRegistry.js.map +1 -0
- package/dist/core/SemanticId.d.ts +159 -0
- package/dist/core/SemanticId.d.ts.map +1 -0
- package/dist/core/SemanticId.js +291 -0
- package/dist/core/SemanticId.js.map +1 -0
- package/dist/core/VersionManager.d.ts +166 -0
- package/dist/core/VersionManager.d.ts.map +1 -0
- package/dist/core/VersionManager.js +239 -0
- package/dist/core/VersionManager.js.map +1 -0
- package/dist/core/brandNodeInternal.d.ts +14 -0
- package/dist/core/brandNodeInternal.d.ts.map +1 -0
- package/dist/core/brandNodeInternal.js +4 -0
- package/dist/core/brandNodeInternal.js.map +1 -0
- package/dist/core/nodes/GuaranteeNode.d.ts +76 -0
- package/dist/core/nodes/GuaranteeNode.d.ts.map +1 -0
- package/dist/core/nodes/GuaranteeNode.js +118 -0
- package/dist/core/nodes/GuaranteeNode.js.map +1 -0
- package/dist/core/nodes/IssueNode.d.ts +73 -0
- package/dist/core/nodes/IssueNode.d.ts.map +1 -0
- package/dist/core/nodes/IssueNode.js +130 -0
- package/dist/core/nodes/IssueNode.js.map +1 -0
- package/dist/core/nodes/NodeKind.d.ts +104 -0
- package/dist/core/nodes/NodeKind.d.ts.map +1 -0
- package/dist/core/nodes/NodeKind.js +166 -0
- package/dist/core/nodes/NodeKind.js.map +1 -0
- package/dist/diagnostics/DiagnosticCollector.d.ts +103 -0
- package/dist/diagnostics/DiagnosticCollector.d.ts.map +1 -0
- package/dist/diagnostics/DiagnosticCollector.js +133 -0
- package/dist/diagnostics/DiagnosticCollector.js.map +1 -0
- package/dist/diagnostics/DiagnosticReporter.d.ts +122 -0
- package/dist/diagnostics/DiagnosticReporter.d.ts.map +1 -0
- package/dist/diagnostics/DiagnosticReporter.js +300 -0
- package/dist/diagnostics/DiagnosticReporter.js.map +1 -0
- package/dist/diagnostics/DiagnosticWriter.d.ts +31 -0
- package/dist/diagnostics/DiagnosticWriter.d.ts.map +1 -0
- package/dist/diagnostics/DiagnosticWriter.js +44 -0
- package/dist/diagnostics/DiagnosticWriter.js.map +1 -0
- package/dist/diagnostics/categories.d.ts +57 -0
- package/dist/diagnostics/categories.d.ts.map +1 -0
- package/dist/diagnostics/categories.js +71 -0
- package/dist/diagnostics/categories.js.map +1 -0
- package/dist/diagnostics/index.d.ts +17 -0
- package/dist/diagnostics/index.d.ts.map +1 -0
- package/dist/diagnostics/index.js +15 -0
- package/dist/diagnostics/index.js.map +1 -0
- package/dist/errors/GrafemaError.d.ts +200 -0
- package/dist/errors/GrafemaError.d.ts.map +1 -0
- package/dist/errors/GrafemaError.js +209 -0
- package/dist/errors/GrafemaError.js.map +1 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/instructions/index.d.ts +8 -0
- package/dist/instructions/index.d.ts.map +1 -0
- package/dist/instructions/index.js +20 -0
- package/dist/instructions/index.js.map +1 -0
- package/dist/instructions/onboarding.md +133 -0
- package/dist/knowledge/KnowledgeBase.d.ts +113 -0
- package/dist/knowledge/KnowledgeBase.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeBase.js +420 -0
- package/dist/knowledge/KnowledgeBase.js.map +1 -0
- package/dist/knowledge/SemanticAddressResolver.d.ts +59 -0
- package/dist/knowledge/SemanticAddressResolver.d.ts.map +1 -0
- package/dist/knowledge/SemanticAddressResolver.js +160 -0
- package/dist/knowledge/SemanticAddressResolver.js.map +1 -0
- package/dist/knowledge/git-ingest.d.ts +58 -0
- package/dist/knowledge/git-ingest.d.ts.map +1 -0
- package/dist/knowledge/git-ingest.js +301 -0
- package/dist/knowledge/git-ingest.js.map +1 -0
- package/dist/knowledge/git-queries.d.ts +86 -0
- package/dist/knowledge/git-queries.d.ts.map +1 -0
- package/dist/knowledge/git-queries.js +177 -0
- package/dist/knowledge/git-queries.js.map +1 -0
- package/dist/knowledge/index.d.ts +14 -0
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/knowledge/index.js +10 -0
- package/dist/knowledge/index.js.map +1 -0
- package/dist/knowledge/parser.d.ts +39 -0
- package/dist/knowledge/parser.d.ts.map +1 -0
- package/dist/knowledge/parser.js +292 -0
- package/dist/knowledge/parser.js.map +1 -0
- package/dist/knowledge/types.d.ts +133 -0
- package/dist/knowledge/types.d.ts.map +1 -0
- package/dist/knowledge/types.js +8 -0
- package/dist/knowledge/types.js.map +1 -0
- package/dist/logging/Logger.d.ts +98 -0
- package/dist/logging/Logger.d.ts.map +1 -0
- package/dist/logging/Logger.js +274 -0
- package/dist/logging/Logger.js.map +1 -0
- package/dist/notation/archetypes.d.ts +36 -0
- package/dist/notation/archetypes.d.ts.map +1 -0
- package/dist/notation/archetypes.js +173 -0
- package/dist/notation/archetypes.js.map +1 -0
- package/dist/notation/fold.d.ts +25 -0
- package/dist/notation/fold.d.ts.map +1 -0
- package/dist/notation/fold.js +598 -0
- package/dist/notation/fold.js.map +1 -0
- package/dist/notation/index.d.ts +18 -0
- package/dist/notation/index.d.ts.map +1 -0
- package/dist/notation/index.js +16 -0
- package/dist/notation/index.js.map +1 -0
- package/dist/notation/lodExtractor.d.ts +32 -0
- package/dist/notation/lodExtractor.d.ts.map +1 -0
- package/dist/notation/lodExtractor.js +149 -0
- package/dist/notation/lodExtractor.js.map +1 -0
- package/dist/notation/nameShortener.d.ts +22 -0
- package/dist/notation/nameShortener.d.ts.map +1 -0
- package/dist/notation/nameShortener.js +24 -0
- package/dist/notation/nameShortener.js.map +1 -0
- package/dist/notation/perspectives.d.ts +11 -0
- package/dist/notation/perspectives.d.ts.map +1 -0
- package/dist/notation/perspectives.js +16 -0
- package/dist/notation/perspectives.js.map +1 -0
- package/dist/notation/renderer.d.ts +31 -0
- package/dist/notation/renderer.d.ts.map +1 -0
- package/dist/notation/renderer.js +315 -0
- package/dist/notation/renderer.js.map +1 -0
- package/dist/notation/traceRenderer.d.ts +39 -0
- package/dist/notation/traceRenderer.d.ts.map +1 -0
- package/dist/notation/traceRenderer.js +358 -0
- package/dist/notation/traceRenderer.js.map +1 -0
- package/dist/notation/types.d.ts +66 -0
- package/dist/notation/types.d.ts.map +1 -0
- package/dist/notation/types.js +10 -0
- package/dist/notation/types.js.map +1 -0
- package/dist/queries/NodeContext.d.ts +81 -0
- package/dist/queries/NodeContext.d.ts.map +1 -0
- package/dist/queries/NodeContext.js +196 -0
- package/dist/queries/NodeContext.js.map +1 -0
- package/dist/queries/findCallsInFunction.d.ts +62 -0
- package/dist/queries/findCallsInFunction.d.ts.map +1 -0
- package/dist/queries/findCallsInFunction.js +169 -0
- package/dist/queries/findCallsInFunction.js.map +1 -0
- package/dist/queries/findContainingFunction.d.ts +57 -0
- package/dist/queries/findContainingFunction.d.ts.map +1 -0
- package/dist/queries/findContainingFunction.js +91 -0
- package/dist/queries/findContainingFunction.js.map +1 -0
- package/dist/queries/index.d.ts +18 -0
- package/dist/queries/index.d.ts.map +1 -0
- package/dist/queries/index.js +14 -0
- package/dist/queries/index.js.map +1 -0
- package/dist/queries/traceDataflow.d.ts +65 -0
- package/dist/queries/traceDataflow.d.ts.map +1 -0
- package/dist/queries/traceDataflow.js +754 -0
- package/dist/queries/traceDataflow.js.map +1 -0
- package/dist/queries/traceValues.d.ts +70 -0
- package/dist/queries/traceValues.d.ts.map +1 -0
- package/dist/queries/traceValues.js +373 -0
- package/dist/queries/traceValues.js.map +1 -0
- package/dist/queries/types.d.ts +166 -0
- package/dist/queries/types.d.ts.map +1 -0
- package/dist/queries/types.js +10 -0
- package/dist/queries/types.js.map +1 -0
- package/dist/schema/GraphSchemaExtractor.d.ts +53 -0
- package/dist/schema/GraphSchemaExtractor.d.ts.map +1 -0
- package/dist/schema/GraphSchemaExtractor.js +125 -0
- package/dist/schema/GraphSchemaExtractor.js.map +1 -0
- package/dist/schema/InterfaceSchemaExtractor.d.ts +73 -0
- package/dist/schema/InterfaceSchemaExtractor.d.ts.map +1 -0
- package/dist/schema/InterfaceSchemaExtractor.js +113 -0
- package/dist/schema/InterfaceSchemaExtractor.js.map +1 -0
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +3 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/storage/backends/RFDBServerBackend.d.ts +356 -0
- package/dist/storage/backends/RFDBServerBackend.d.ts.map +1 -0
- package/dist/storage/backends/RFDBServerBackend.js +748 -0
- package/dist/storage/backends/RFDBServerBackend.js.map +1 -0
- package/dist/storage/backends/typeValidation.d.ts +47 -0
- package/dist/storage/backends/typeValidation.d.ts.map +1 -0
- package/dist/storage/backends/typeValidation.js +141 -0
- package/dist/storage/backends/typeValidation.js.map +1 -0
- package/dist/utils/findRfdbBinary.d.ts +67 -0
- package/dist/utils/findRfdbBinary.d.ts.map +1 -0
- package/dist/utils/findRfdbBinary.js +261 -0
- package/dist/utils/findRfdbBinary.js.map +1 -0
- package/dist/utils/lazyDownload.d.ts +43 -0
- package/dist/utils/lazyDownload.d.ts.map +1 -0
- package/dist/utils/lazyDownload.js +175 -0
- package/dist/utils/lazyDownload.js.map +1 -0
- package/dist/utils/moduleResolution.d.ts +134 -0
- package/dist/utils/moduleResolution.d.ts.map +1 -0
- package/dist/utils/moduleResolution.js +189 -0
- package/dist/utils/moduleResolution.js.map +1 -0
- package/dist/utils/resolveNodeFile.d.ts +13 -0
- package/dist/utils/resolveNodeFile.d.ts.map +1 -0
- package/dist/utils/resolveNodeFile.js +18 -0
- package/dist/utils/resolveNodeFile.js.map +1 -0
- package/dist/utils/startRfdbServer.d.ts +63 -0
- package/dist/utils/startRfdbServer.d.ts.map +1 -0
- package/dist/utils/startRfdbServer.js +142 -0
- package/dist/utils/startRfdbServer.js.map +1 -0
- package/dist/validation/PathValidator.d.ts +80 -0
- package/dist/validation/PathValidator.d.ts.map +1 -0
- package/dist/validation/PathValidator.js +252 -0
- package/dist/validation/PathValidator.js.map +1 -0
- package/dist/version.d.ts +11 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +26 -0
- package/dist/version.js.map +1 -0
- package/package.json +50 -0
- package/src/api/GraphAPI.ts +307 -0
- package/src/api/GuaranteeAPI.ts +402 -0
- package/src/config/ConfigLoader.ts +653 -0
- package/src/config/index.ts +13 -0
- package/src/core/CoverageAnalyzer.ts +243 -0
- package/src/core/FileExplainer.ts +179 -0
- package/src/core/FileOverview.ts +397 -0
- package/src/core/GrafemaUri.ts +216 -0
- package/src/core/GraphBackend.ts +266 -0
- package/src/core/GraphFreshnessChecker.ts +145 -0
- package/src/core/GuaranteeManager.ts +684 -0
- package/src/core/HashUtils.ts +48 -0
- package/src/core/IncrementalReanalyzer.ts +106 -0
- package/src/core/ResourceRegistry.ts +39 -0
- package/src/core/SemanticId.ts +423 -0
- package/src/core/VersionManager.ts +405 -0
- package/src/core/brandNodeInternal.ts +16 -0
- package/src/core/nodes/GuaranteeNode.ts +162 -0
- package/src/core/nodes/IssueNode.ts +177 -0
- package/src/core/nodes/NodeKind.ts +192 -0
- package/src/diagnostics/DiagnosticCollector.ts +170 -0
- package/src/diagnostics/DiagnosticReporter.ts +395 -0
- package/src/diagnostics/DiagnosticWriter.ts +50 -0
- package/src/diagnostics/categories.ts +104 -0
- package/src/diagnostics/index.ts +30 -0
- package/src/errors/GrafemaError.ts +297 -0
- package/src/index.ts +261 -0
- package/src/instructions/index.ts +21 -0
- package/src/instructions/onboarding.md +133 -0
- package/src/knowledge/KnowledgeBase.ts +486 -0
- package/src/knowledge/SemanticAddressResolver.ts +191 -0
- package/src/knowledge/git-ingest.ts +402 -0
- package/src/knowledge/git-queries.ts +269 -0
- package/src/knowledge/index.ts +29 -0
- package/src/knowledge/parser.ts +294 -0
- package/src/knowledge/types.ts +146 -0
- package/src/logging/Logger.ts +303 -0
- package/src/notation/archetypes.ts +189 -0
- package/src/notation/fold.ts +696 -0
- package/src/notation/index.ts +27 -0
- package/src/notation/lodExtractor.ts +177 -0
- package/src/notation/nameShortener.ts +24 -0
- package/src/notation/perspectives.ts +18 -0
- package/src/notation/renderer.ts +394 -0
- package/src/notation/traceRenderer.ts +458 -0
- package/src/notation/types.ts +79 -0
- package/src/queries/NodeContext.ts +280 -0
- package/src/queries/findCallsInFunction.ts +249 -0
- package/src/queries/findContainingFunction.ts +124 -0
- package/src/queries/index.ts +44 -0
- package/src/queries/traceDataflow.ts +838 -0
- package/src/queries/traceValues.ts +531 -0
- package/src/queries/types.ts +191 -0
- package/src/schema/GraphSchemaExtractor.ts +177 -0
- package/src/schema/InterfaceSchemaExtractor.ts +173 -0
- package/src/schema/index.ts +5 -0
- package/src/storage/backends/RFDBServerBackend.ts +895 -0
- package/src/storage/backends/typeValidation.ts +154 -0
- package/src/utils/findRfdbBinary.ts +288 -0
- package/src/utils/lazyDownload.ts +206 -0
- package/src/utils/moduleResolution.ts +271 -0
- package/src/utils/resolveNodeFile.ts +18 -0
- package/src/utils/startRfdbServer.ts +197 -0
- package/src/validation/PathValidator.ts +334 -0
- package/src/version.ts +28 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DiagnosticReporter - Formats diagnostics for output
|
|
3
|
+
*
|
|
4
|
+
* Supports multiple output formats:
|
|
5
|
+
* - text: Human-readable format with severity indicators
|
|
6
|
+
* - json: Machine-readable JSON format for CI integration
|
|
7
|
+
* - csv: Spreadsheet-compatible format
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* const reporter = new DiagnosticReporter(collector);
|
|
11
|
+
* console.log(reporter.report({ format: 'text', includeSummary: true }));
|
|
12
|
+
* console.log(reporter.summary());
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { Diagnostic, DiagnosticCollector } from './DiagnosticCollector.js';
|
|
16
|
+
import { CODE_TO_CATEGORY } from './categories.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Report output options
|
|
20
|
+
*/
|
|
21
|
+
export interface ReportOptions {
|
|
22
|
+
format: 'text' | 'json' | 'csv';
|
|
23
|
+
includeSummary?: boolean;
|
|
24
|
+
includeTrace?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Options for strict mode formatting (REG-332)
|
|
29
|
+
*/
|
|
30
|
+
export interface StrictFormatOptions {
|
|
31
|
+
/** Show resolution chain (hybrid: auto-show for ≤3 errors, hide for more) */
|
|
32
|
+
verbose?: boolean;
|
|
33
|
+
/** REG-332: Number of errors suppressed by grafema-ignore comments */
|
|
34
|
+
suppressedCount?: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Summary statistics
|
|
39
|
+
*/
|
|
40
|
+
export interface SummaryStats {
|
|
41
|
+
total: number;
|
|
42
|
+
fatal: number;
|
|
43
|
+
errors: number;
|
|
44
|
+
warnings: number;
|
|
45
|
+
info: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Category count with metadata
|
|
50
|
+
*/
|
|
51
|
+
export interface CategoryCount {
|
|
52
|
+
code: string;
|
|
53
|
+
count: number;
|
|
54
|
+
name: string;
|
|
55
|
+
checkCommand: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Summary statistics with category breakdown
|
|
60
|
+
*/
|
|
61
|
+
export interface CategorizedSummaryStats extends SummaryStats {
|
|
62
|
+
byCode: CategoryCount[];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* DiagnosticReporter - formats diagnostics for different output formats
|
|
67
|
+
*/
|
|
68
|
+
export class DiagnosticReporter {
|
|
69
|
+
constructor(private collector: DiagnosticCollector) {}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Generate a formatted report of all diagnostics.
|
|
73
|
+
*/
|
|
74
|
+
report(options: ReportOptions): string {
|
|
75
|
+
const diagnostics = this.collector.getAll();
|
|
76
|
+
|
|
77
|
+
if (options.format === 'json') {
|
|
78
|
+
return this.jsonReport(diagnostics, options);
|
|
79
|
+
} else if (options.format === 'csv') {
|
|
80
|
+
return this.csvReport(diagnostics);
|
|
81
|
+
} else {
|
|
82
|
+
return this.textReport(diagnostics, options);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Generate a human-readable summary of diagnostic counts.
|
|
88
|
+
*/
|
|
89
|
+
summary(): string {
|
|
90
|
+
const stats = this.getStats();
|
|
91
|
+
|
|
92
|
+
if (stats.total === 0) {
|
|
93
|
+
return 'No issues found.';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const parts: string[] = [];
|
|
97
|
+
|
|
98
|
+
if (stats.fatal > 0) {
|
|
99
|
+
parts.push(`Fatal: ${stats.fatal}`);
|
|
100
|
+
}
|
|
101
|
+
if (stats.errors > 0) {
|
|
102
|
+
parts.push(`Errors: ${stats.errors}`);
|
|
103
|
+
}
|
|
104
|
+
if (stats.warnings > 0) {
|
|
105
|
+
parts.push(`Warnings: ${stats.warnings}`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return parts.join(', ');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Generate a categorized summary with actionable commands.
|
|
113
|
+
*/
|
|
114
|
+
categorizedSummary(): string {
|
|
115
|
+
const stats = this.getCategorizedStats();
|
|
116
|
+
|
|
117
|
+
if (stats.total === 0) {
|
|
118
|
+
return 'No issues found.';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const lines: string[] = [];
|
|
122
|
+
|
|
123
|
+
// Severity totals (same format as summary())
|
|
124
|
+
const severityParts: string[] = [];
|
|
125
|
+
if (stats.fatal > 0) {
|
|
126
|
+
severityParts.push(`Fatal: ${stats.fatal}`);
|
|
127
|
+
}
|
|
128
|
+
if (stats.errors > 0) {
|
|
129
|
+
severityParts.push(`Errors: ${stats.errors}`);
|
|
130
|
+
}
|
|
131
|
+
if (stats.warnings > 0) {
|
|
132
|
+
severityParts.push(`Warnings: ${stats.warnings}`);
|
|
133
|
+
}
|
|
134
|
+
lines.push(severityParts.join(', '));
|
|
135
|
+
|
|
136
|
+
// Top 5 categories
|
|
137
|
+
const topCategories = stats.byCode.slice(0, 5);
|
|
138
|
+
for (const category of topCategories) {
|
|
139
|
+
lines.push(` - ${category.count} ${category.name} (run \`${category.checkCommand}\`)`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// "Other issues" if more than 5 categories
|
|
143
|
+
if (stats.byCode.length > 5) {
|
|
144
|
+
const remainingCount = stats.byCode.slice(5).reduce((sum, cat) => sum + cat.count, 0);
|
|
145
|
+
const issueWord = remainingCount === 1 ? 'other issue' : 'other issues';
|
|
146
|
+
lines.push(` - ${remainingCount} ${issueWord}`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Footer
|
|
150
|
+
lines.push('');
|
|
151
|
+
lines.push('Run `grafema check --all` for full diagnostics.');
|
|
152
|
+
|
|
153
|
+
return lines.join('\n');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Get diagnostic statistics by severity.
|
|
158
|
+
*/
|
|
159
|
+
getStats(): SummaryStats {
|
|
160
|
+
const diagnostics = this.collector.getAll();
|
|
161
|
+
return {
|
|
162
|
+
total: diagnostics.length,
|
|
163
|
+
fatal: diagnostics.filter(d => d.severity === 'fatal').length,
|
|
164
|
+
errors: diagnostics.filter(d => d.severity === 'error').length,
|
|
165
|
+
warnings: diagnostics.filter(d => d.severity === 'warning').length,
|
|
166
|
+
info: diagnostics.filter(d => d.severity === 'info').length,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Get diagnostic statistics grouped by category.
|
|
172
|
+
*/
|
|
173
|
+
getCategorizedStats(): CategorizedSummaryStats {
|
|
174
|
+
const diagnostics = this.collector.getAll();
|
|
175
|
+
|
|
176
|
+
// Get severity stats
|
|
177
|
+
const severityStats: SummaryStats = {
|
|
178
|
+
total: diagnostics.length,
|
|
179
|
+
fatal: diagnostics.filter(d => d.severity === 'fatal').length,
|
|
180
|
+
errors: diagnostics.filter(d => d.severity === 'error').length,
|
|
181
|
+
warnings: diagnostics.filter(d => d.severity === 'warning').length,
|
|
182
|
+
info: diagnostics.filter(d => d.severity === 'info').length,
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// Group by code
|
|
186
|
+
const codeMap = new Map<string, number>();
|
|
187
|
+
for (const diag of diagnostics) {
|
|
188
|
+
const count = codeMap.get(diag.code) || 0;
|
|
189
|
+
codeMap.set(diag.code, count + 1);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Convert to CategoryCount array with metadata
|
|
193
|
+
const byCode: CategoryCount[] = [];
|
|
194
|
+
for (const [code, count] of codeMap.entries()) {
|
|
195
|
+
const category = CODE_TO_CATEGORY[code];
|
|
196
|
+
byCode.push({
|
|
197
|
+
code,
|
|
198
|
+
count,
|
|
199
|
+
name: category?.name || code,
|
|
200
|
+
checkCommand: category?.checkCommand || 'grafema check --all',
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Sort by count descending
|
|
205
|
+
byCode.sort((a, b) => b.count - a.count);
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
...severityStats,
|
|
209
|
+
byCode,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Format strict mode errors with enhanced context (REG-332).
|
|
215
|
+
* Shows resolution chain and context-aware suggestions.
|
|
216
|
+
*
|
|
217
|
+
* Uses hybrid progressive disclosure:
|
|
218
|
+
* - ≤3 errors: show chain by default
|
|
219
|
+
* - >3 errors: hide chain unless verbose=true
|
|
220
|
+
*
|
|
221
|
+
* @param diagnostics - The fatal diagnostics from strict mode
|
|
222
|
+
* @param options - Formatting options
|
|
223
|
+
* @returns Formatted string for CLI output
|
|
224
|
+
*/
|
|
225
|
+
formatStrict(diagnostics: Diagnostic[], options: StrictFormatOptions = {}): string {
|
|
226
|
+
const lines: string[] = [];
|
|
227
|
+
// Hybrid: show chain for ≤3 errors unless explicitly set
|
|
228
|
+
const showChain = options.verbose ?? diagnostics.length <= 3;
|
|
229
|
+
|
|
230
|
+
for (const diag of diagnostics) {
|
|
231
|
+
// Header: CODE file:line
|
|
232
|
+
const location = diag.file
|
|
233
|
+
? diag.line
|
|
234
|
+
? `${diag.file}:${diag.line}`
|
|
235
|
+
: diag.file
|
|
236
|
+
: '';
|
|
237
|
+
lines.push(`${diag.code} ${location}`);
|
|
238
|
+
lines.push('');
|
|
239
|
+
|
|
240
|
+
// Message
|
|
241
|
+
lines.push(` ${diag.message}`);
|
|
242
|
+
|
|
243
|
+
// Resolution chain (if showing and present)
|
|
244
|
+
if (showChain && diag.resolutionChain && diag.resolutionChain.length > 0) {
|
|
245
|
+
lines.push('');
|
|
246
|
+
lines.push(' Resolution chain:');
|
|
247
|
+
for (const step of diag.resolutionChain) {
|
|
248
|
+
const stepLocation = step.file
|
|
249
|
+
? step.line
|
|
250
|
+
? ` (${step.file}:${step.line})`
|
|
251
|
+
: ` (${step.file})`
|
|
252
|
+
: '';
|
|
253
|
+
lines.push(` ${step.step} -> ${step.result}${stepLocation}`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Suggestion (if present)
|
|
258
|
+
if (diag.suggestion) {
|
|
259
|
+
lines.push('');
|
|
260
|
+
lines.push(` Suggestion: ${diag.suggestion}`);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
lines.push('');
|
|
264
|
+
lines.push('---');
|
|
265
|
+
lines.push('');
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Remove trailing separator
|
|
269
|
+
if (lines.length > 0) {
|
|
270
|
+
lines.splice(-3);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Add hint about verbose mode if chain hidden
|
|
274
|
+
if (!showChain && diagnostics.some(d => d.resolutionChain && d.resolutionChain.length > 0)) {
|
|
275
|
+
lines.push('');
|
|
276
|
+
lines.push(' Run with --verbose to see resolution chains.');
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// REG-332: Show suppression summary if any errors were suppressed
|
|
280
|
+
if (options.suppressedCount && options.suppressedCount > 0) {
|
|
281
|
+
lines.push('');
|
|
282
|
+
lines.push(` ${options.suppressedCount} error(s) suppressed by grafema-ignore comments.`);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return lines.join('\n');
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Generate human-readable text report.
|
|
290
|
+
*/
|
|
291
|
+
private textReport(diagnostics: Diagnostic[], options: ReportOptions): string {
|
|
292
|
+
if (diagnostics.length === 0) {
|
|
293
|
+
return 'No issues found.';
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const lines: string[] = [];
|
|
297
|
+
|
|
298
|
+
for (const diag of diagnostics) {
|
|
299
|
+
const icon = this.getSeverityIcon(diag.severity);
|
|
300
|
+
const location = this.formatLocation(diag);
|
|
301
|
+
|
|
302
|
+
lines.push(`${icon} ${diag.code} ${location} ${diag.message}`);
|
|
303
|
+
|
|
304
|
+
if (diag.suggestion) {
|
|
305
|
+
lines.push(` Suggestion: ${diag.suggestion}`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (options.includeSummary) {
|
|
310
|
+
lines.push('');
|
|
311
|
+
lines.push(this.summary());
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return lines.join('\n');
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Generate JSON report.
|
|
319
|
+
*/
|
|
320
|
+
private jsonReport(diagnostics: Diagnostic[], options: ReportOptions): string {
|
|
321
|
+
const result: {
|
|
322
|
+
diagnostics: Diagnostic[];
|
|
323
|
+
summary?: SummaryStats;
|
|
324
|
+
} = {
|
|
325
|
+
diagnostics,
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
if (options.includeSummary) {
|
|
329
|
+
result.summary = this.getStats();
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return JSON.stringify(result, null, 2);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Generate CSV report.
|
|
337
|
+
*/
|
|
338
|
+
private csvReport(diagnostics: Diagnostic[]): string {
|
|
339
|
+
const header = 'severity,code,file,line,message,plugin,phase,suggestion';
|
|
340
|
+
const rows = diagnostics.map(d =>
|
|
341
|
+
[
|
|
342
|
+
d.severity,
|
|
343
|
+
d.code,
|
|
344
|
+
d.file || '',
|
|
345
|
+
d.line || '',
|
|
346
|
+
this.csvEscape(d.message),
|
|
347
|
+
d.plugin,
|
|
348
|
+
d.phase,
|
|
349
|
+
d.suggestion ? this.csvEscape(d.suggestion) : '',
|
|
350
|
+
].join(',')
|
|
351
|
+
);
|
|
352
|
+
return [header, ...rows].join('\n');
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Get severity indicator for text output.
|
|
357
|
+
*/
|
|
358
|
+
private getSeverityIcon(severity: Diagnostic['severity']): string {
|
|
359
|
+
switch (severity) {
|
|
360
|
+
case 'fatal':
|
|
361
|
+
return '[FATAL]';
|
|
362
|
+
case 'error':
|
|
363
|
+
return '[ERROR]';
|
|
364
|
+
case 'warning':
|
|
365
|
+
return '[WARN]';
|
|
366
|
+
case 'info':
|
|
367
|
+
return '[INFO]';
|
|
368
|
+
default:
|
|
369
|
+
return '[?]';
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Format file location for display.
|
|
375
|
+
*/
|
|
376
|
+
private formatLocation(diag: Diagnostic): string {
|
|
377
|
+
if (!diag.file) {
|
|
378
|
+
return '';
|
|
379
|
+
}
|
|
380
|
+
if (diag.line) {
|
|
381
|
+
return `(${diag.file}:${diag.line})`;
|
|
382
|
+
}
|
|
383
|
+
return `(${diag.file})`;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Escape a value for CSV output.
|
|
388
|
+
* Wraps in quotes and escapes internal quotes.
|
|
389
|
+
*/
|
|
390
|
+
private csvEscape(value: string): string {
|
|
391
|
+
// Always quote to handle commas and special characters
|
|
392
|
+
const escaped = value.replace(/"/g, '""');
|
|
393
|
+
return `"${escaped}"`;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DiagnosticWriter - Writes diagnostics to .grafema/diagnostics.log
|
|
3
|
+
*
|
|
4
|
+
* Writes diagnostics in JSON lines format (one JSON object per line).
|
|
5
|
+
* This format is:
|
|
6
|
+
* - Easy to parse line-by-line
|
|
7
|
+
* - Appendable without reading entire file
|
|
8
|
+
* - Compatible with streaming tools (grep, jq, etc.)
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* const writer = new DiagnosticWriter();
|
|
12
|
+
* await writer.write(collector, '/project/.grafema');
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
16
|
+
import { join, dirname } from 'path';
|
|
17
|
+
|
|
18
|
+
import type { DiagnosticCollector } from './DiagnosticCollector.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* DiagnosticWriter - writes diagnostics.log file
|
|
22
|
+
*/
|
|
23
|
+
export class DiagnosticWriter {
|
|
24
|
+
/**
|
|
25
|
+
* Write all diagnostics to .grafema/diagnostics.log
|
|
26
|
+
*
|
|
27
|
+
* Creates the directory if it doesn't exist.
|
|
28
|
+
* Overwrites existing file.
|
|
29
|
+
*/
|
|
30
|
+
async write(collector: DiagnosticCollector, grafemaDir: string): Promise<void> {
|
|
31
|
+
const logPath = this.getLogPath(grafemaDir);
|
|
32
|
+
|
|
33
|
+
// Create directory if it doesn't exist
|
|
34
|
+
const dir = dirname(logPath);
|
|
35
|
+
if (!existsSync(dir)) {
|
|
36
|
+
mkdirSync(dir, { recursive: true });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Write diagnostics as JSON lines
|
|
40
|
+
const content = collector.toDiagnosticsLog();
|
|
41
|
+
writeFileSync(logPath, content, 'utf-8');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the path to the diagnostics.log file
|
|
46
|
+
*/
|
|
47
|
+
getLogPath(grafemaDir: string): string {
|
|
48
|
+
return join(grafemaDir, 'diagnostics.log');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagnostic Categories - Single source of truth for category/code mappings
|
|
3
|
+
*
|
|
4
|
+
* This module defines diagnostic categories once and derives both mapping
|
|
5
|
+
* directions:
|
|
6
|
+
* - DIAGNOSTIC_CATEGORIES: category → codes (used by CLI check command)
|
|
7
|
+
* - CODE_TO_CATEGORY: code → category metadata (used by DiagnosticReporter)
|
|
8
|
+
*
|
|
9
|
+
* Adding a new diagnostic code requires updating only this file.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Category definition with human-readable metadata and associated codes
|
|
14
|
+
*/
|
|
15
|
+
export interface DiagnosticCategory {
|
|
16
|
+
/** Human-readable name for display */
|
|
17
|
+
readonly name: string;
|
|
18
|
+
/** Description of what this category checks */
|
|
19
|
+
readonly description: string;
|
|
20
|
+
/** Diagnostic codes that belong to this category */
|
|
21
|
+
readonly codes: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Valid category keys
|
|
26
|
+
*/
|
|
27
|
+
export type DiagnosticCategoryKey = 'connectivity' | 'calls' | 'dataflow' | 'imports';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Canonical definition of all diagnostic categories
|
|
31
|
+
*
|
|
32
|
+
* This is the SINGLE SOURCE OF TRUTH for category mappings.
|
|
33
|
+
* Both CLI and DiagnosticReporter derive their mappings from this.
|
|
34
|
+
*/
|
|
35
|
+
export const DIAGNOSTIC_CATEGORIES: Record<DiagnosticCategoryKey, DiagnosticCategory> = {
|
|
36
|
+
connectivity: {
|
|
37
|
+
name: 'Graph Connectivity',
|
|
38
|
+
description: 'Check for disconnected nodes in the graph',
|
|
39
|
+
codes: ['ERR_DISCONNECTED_NODES', 'ERR_DISCONNECTED_NODE'],
|
|
40
|
+
},
|
|
41
|
+
calls: {
|
|
42
|
+
name: 'Call Resolution',
|
|
43
|
+
description: 'Check for unresolved function calls',
|
|
44
|
+
codes: ['ERR_UNRESOLVED_CALL'],
|
|
45
|
+
},
|
|
46
|
+
dataflow: {
|
|
47
|
+
name: 'Data Flow',
|
|
48
|
+
description: 'Check for missing assignments and broken references',
|
|
49
|
+
codes: ['ERR_MISSING_ASSIGNMENT', 'ERR_BROKEN_REFERENCE', 'ERR_NO_LEAF_NODE'],
|
|
50
|
+
},
|
|
51
|
+
imports: {
|
|
52
|
+
name: 'Import Validation',
|
|
53
|
+
description: 'Check for broken imports and undefined symbols',
|
|
54
|
+
codes: ['ERR_BROKEN_IMPORT', 'ERR_UNDEFINED_SYMBOL'],
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Metadata for code-to-category lookup (used by DiagnosticReporter)
|
|
60
|
+
*/
|
|
61
|
+
export interface CodeCategoryInfo {
|
|
62
|
+
/** Human-readable name for the issue type */
|
|
63
|
+
name: string;
|
|
64
|
+
/** CLI command to check this category */
|
|
65
|
+
checkCommand: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Derived mapping: code → category metadata
|
|
70
|
+
*
|
|
71
|
+
* Auto-generated from DIAGNOSTIC_CATEGORIES.
|
|
72
|
+
* Used by DiagnosticReporter to show actionable commands.
|
|
73
|
+
*/
|
|
74
|
+
export const CODE_TO_CATEGORY: Record<string, CodeCategoryInfo> = (() => {
|
|
75
|
+
const result: Record<string, CodeCategoryInfo> = {};
|
|
76
|
+
|
|
77
|
+
for (const [categoryKey, category] of Object.entries(DIAGNOSTIC_CATEGORIES)) {
|
|
78
|
+
// Generate human-readable name from category name (lowercase, plural)
|
|
79
|
+
const issueName = category.name.toLowerCase().replace('graph ', '');
|
|
80
|
+
|
|
81
|
+
for (const code of category.codes) {
|
|
82
|
+
result[code] = {
|
|
83
|
+
name: issueName,
|
|
84
|
+
checkCommand: `grafema check ${categoryKey}`,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return result;
|
|
90
|
+
})();
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get category for a diagnostic code
|
|
94
|
+
*/
|
|
95
|
+
export function getCategoryForCode(code: string): CodeCategoryInfo | undefined {
|
|
96
|
+
return CODE_TO_CATEGORY[code];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get all codes for a category
|
|
101
|
+
*/
|
|
102
|
+
export function getCodesForCategory(category: DiagnosticCategoryKey): readonly string[] {
|
|
103
|
+
return DIAGNOSTIC_CATEGORIES[category].codes;
|
|
104
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagnostics - Error collection, reporting, and logging
|
|
3
|
+
*
|
|
4
|
+
* This module provides the diagnostics infrastructure for Grafema:
|
|
5
|
+
* - DiagnosticCollector: Collects errors from plugin execution
|
|
6
|
+
* - DiagnosticReporter: Formats diagnostics for output (text/json/csv)
|
|
7
|
+
* - DiagnosticWriter: Writes diagnostics.log file
|
|
8
|
+
* - categories: Single source of truth for diagnostic category mappings
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export { DiagnosticCollector } from './DiagnosticCollector.js';
|
|
12
|
+
export type { Diagnostic, DiagnosticInput } from './DiagnosticCollector.js';
|
|
13
|
+
|
|
14
|
+
export { DiagnosticReporter } from './DiagnosticReporter.js';
|
|
15
|
+
export type { ReportOptions, SummaryStats, CategoryCount, CategorizedSummaryStats } from './DiagnosticReporter.js';
|
|
16
|
+
|
|
17
|
+
export { DiagnosticWriter } from './DiagnosticWriter.js';
|
|
18
|
+
|
|
19
|
+
// Category mappings (single source of truth)
|
|
20
|
+
export {
|
|
21
|
+
DIAGNOSTIC_CATEGORIES,
|
|
22
|
+
CODE_TO_CATEGORY,
|
|
23
|
+
getCategoryForCode,
|
|
24
|
+
getCodesForCategory,
|
|
25
|
+
} from './categories.js';
|
|
26
|
+
export type {
|
|
27
|
+
DiagnosticCategory,
|
|
28
|
+
DiagnosticCategoryKey,
|
|
29
|
+
CodeCategoryInfo,
|
|
30
|
+
} from './categories.js';
|