@eddacraft/anvil-core 0.1.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/LICENSE +14 -0
- package/dist/antipattern/index.d.ts +11 -0
- package/dist/antipattern/index.d.ts.map +1 -0
- package/dist/antipattern/index.js +31 -0
- package/dist/antipattern/patterns-css.d.ts +17 -0
- package/dist/antipattern/patterns-css.d.ts.map +1 -0
- package/dist/antipattern/patterns-css.js +72 -0
- package/dist/antipattern/patterns-html.d.ts +21 -0
- package/dist/antipattern/patterns-html.d.ts.map +1 -0
- package/dist/antipattern/patterns-html.js +139 -0
- package/dist/antipattern/patterns.d.ts +72 -0
- package/dist/antipattern/patterns.d.ts.map +1 -0
- package/dist/antipattern/patterns.js +301 -0
- package/dist/antipattern/scanner.d.ts +32 -0
- package/dist/antipattern/scanner.d.ts.map +1 -0
- package/dist/antipattern/scanner.js +89 -0
- package/dist/antipattern/types.d.ts +318 -0
- package/dist/antipattern/types.d.ts.map +1 -0
- package/dist/antipattern/types.js +278 -0
- package/dist/architecture/analyzer.d.ts +123 -0
- package/dist/architecture/analyzer.d.ts.map +1 -0
- package/dist/architecture/analyzer.js +321 -0
- package/dist/architecture/baseline.d.ts +112 -0
- package/dist/architecture/baseline.d.ts.map +1 -0
- package/dist/architecture/baseline.js +245 -0
- package/dist/architecture/compiler.d.ts +24 -0
- package/dist/architecture/compiler.d.ts.map +1 -0
- package/dist/architecture/compiler.js +57 -0
- package/dist/architecture/context.d.ts +129 -0
- package/dist/architecture/context.d.ts.map +1 -0
- package/dist/architecture/context.js +116 -0
- package/dist/architecture/dc-generator.d.ts +9 -0
- package/dist/architecture/dc-generator.d.ts.map +1 -0
- package/dist/architecture/dc-generator.js +220 -0
- package/dist/architecture/definition-schema.d.ts +128 -0
- package/dist/architecture/definition-schema.d.ts.map +1 -0
- package/dist/architecture/definition-schema.js +94 -0
- package/dist/architecture/edge-detector-html.d.ts +6 -0
- package/dist/architecture/edge-detector-html.d.ts.map +1 -0
- package/dist/architecture/edge-detector-html.js +5 -0
- package/dist/architecture/edge-detector-web.d.ts +32 -0
- package/dist/architecture/edge-detector-web.d.ts.map +1 -0
- package/dist/architecture/edge-detector-web.js +133 -0
- package/dist/architecture/edge-detector.d.ts +116 -0
- package/dist/architecture/edge-detector.d.ts.map +1 -0
- package/dist/architecture/edge-detector.js +229 -0
- package/dist/architecture/entry-detector.d.ts +44 -0
- package/dist/architecture/entry-detector.d.ts.map +1 -0
- package/dist/architecture/entry-detector.js +263 -0
- package/dist/architecture/index.d.ts +21 -0
- package/dist/architecture/index.d.ts.map +1 -0
- package/dist/architecture/index.js +48 -0
- package/dist/architecture/layer-detector.d.ts +60 -0
- package/dist/architecture/layer-detector.d.ts.map +1 -0
- package/dist/architecture/layer-detector.js +331 -0
- package/dist/architecture/rego-generator.d.ts +25 -0
- package/dist/architecture/rego-generator.d.ts.map +1 -0
- package/dist/architecture/rego-generator.js +229 -0
- package/dist/architecture/templates/index.d.ts +39 -0
- package/dist/architecture/templates/index.d.ts.map +1 -0
- package/dist/architecture/templates/index.js +124 -0
- package/dist/architecture/types.d.ts +280 -0
- package/dist/architecture/types.d.ts.map +1 -0
- package/dist/architecture/types.js +269 -0
- package/dist/architecture/yaml-parser.d.ts +13 -0
- package/dist/architecture/yaml-parser.d.ts.map +1 -0
- package/dist/architecture/yaml-parser.js +234 -0
- package/dist/config/constants.d.ts +9 -0
- package/dist/config/constants.d.ts.map +1 -0
- package/dist/config/constants.js +20 -0
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +8 -0
- package/dist/config/loader.d.ts +41 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +76 -0
- package/dist/config/nudge-config.d.ts +35 -0
- package/dist/config/nudge-config.d.ts.map +1 -0
- package/dist/config/nudge-config.js +34 -0
- package/dist/config/types.d.ts +30 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +4 -0
- package/dist/contracts/index.d.ts +14 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +13 -0
- package/dist/contracts/schemas/aps.schema.d.ts +269 -0
- package/dist/contracts/schemas/aps.schema.d.ts.map +1 -0
- package/dist/contracts/schemas/aps.schema.js +183 -0
- package/dist/contracts/schemas/index.d.ts +12 -0
- package/dist/contracts/schemas/index.d.ts.map +1 -0
- package/dist/contracts/schemas/index.js +14 -0
- package/dist/contracts/schemas/json-schema.d.ts +14 -0
- package/dist/contracts/schemas/json-schema.d.ts.map +1 -0
- package/dist/contracts/schemas/json-schema.js +31 -0
- package/dist/contracts/schemas/warning.schema.d.ts +171 -0
- package/dist/contracts/schemas/warning.schema.d.ts.map +1 -0
- package/dist/contracts/schemas/warning.schema.js +123 -0
- package/dist/contracts/types/gate.types.d.ts +194 -0
- package/dist/contracts/types/gate.types.d.ts.map +1 -0
- package/dist/contracts/types/gate.types.js +19 -0
- package/dist/contracts/types/index.d.ts +9 -0
- package/dist/contracts/types/index.d.ts.map +1 -0
- package/dist/contracts/types/index.js +8 -0
- package/dist/crypto/hash.d.ts +47 -0
- package/dist/crypto/hash.d.ts.map +1 -0
- package/dist/crypto/hash.js +110 -0
- package/dist/crypto/index.d.ts +7 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +6 -0
- package/dist/drift/index.d.ts +6 -0
- package/dist/drift/index.d.ts.map +1 -0
- package/dist/drift/index.js +5 -0
- package/dist/drift/report-generator.d.ts +21 -0
- package/dist/drift/report-generator.d.ts.map +1 -0
- package/dist/drift/report-generator.js +240 -0
- package/dist/drift/snapshot-capture.d.ts +26 -0
- package/dist/drift/snapshot-capture.d.ts.map +1 -0
- package/dist/drift/snapshot-capture.js +195 -0
- package/dist/drift/snapshot-compare.d.ts +50 -0
- package/dist/drift/snapshot-compare.d.ts.map +1 -0
- package/dist/drift/snapshot-compare.js +142 -0
- package/dist/drift/snapshot-schema.d.ts +197 -0
- package/dist/drift/snapshot-schema.d.ts.map +1 -0
- package/dist/drift/snapshot-schema.js +193 -0
- package/dist/drift/snapshot-storage.d.ts +25 -0
- package/dist/drift/snapshot-storage.d.ts.map +1 -0
- package/dist/drift/snapshot-storage.js +179 -0
- package/dist/explain/antipattern-explainer.d.ts +4 -0
- package/dist/explain/antipattern-explainer.d.ts.map +1 -0
- package/dist/explain/antipattern-explainer.js +196 -0
- package/dist/explain/boundary-explainer.d.ts +5 -0
- package/dist/explain/boundary-explainer.d.ts.map +1 -0
- package/dist/explain/boundary-explainer.js +261 -0
- package/dist/explain/explain-service.d.ts +19 -0
- package/dist/explain/explain-service.d.ts.map +1 -0
- package/dist/explain/explain-service.js +106 -0
- package/dist/explain/index.d.ts +7 -0
- package/dist/explain/index.d.ts.map +1 -0
- package/dist/explain/index.js +5 -0
- package/dist/explain/template-loader.d.ts +9 -0
- package/dist/explain/template-loader.d.ts.map +1 -0
- package/dist/explain/template-loader.js +51 -0
- package/dist/explain/types.d.ts +46 -0
- package/dist/explain/types.d.ts.map +1 -0
- package/dist/explain/types.js +31 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/provenance/collector.d.ts +86 -0
- package/dist/provenance/collector.d.ts.map +1 -0
- package/dist/provenance/collector.js +425 -0
- package/dist/provenance/git-ai-standard/git-notes.d.ts +85 -0
- package/dist/provenance/git-ai-standard/git-notes.d.ts.map +1 -0
- package/dist/provenance/git-ai-standard/git-notes.js +292 -0
- package/dist/provenance/git-ai-standard/index.d.ts +44 -0
- package/dist/provenance/git-ai-standard/index.d.ts.map +1 -0
- package/dist/provenance/git-ai-standard/index.js +47 -0
- package/dist/provenance/git-ai-standard/serializer.d.ts +54 -0
- package/dist/provenance/git-ai-standard/serializer.d.ts.map +1 -0
- package/dist/provenance/git-ai-standard/serializer.js +224 -0
- package/dist/provenance/git-ai-standard/session.d.ts +51 -0
- package/dist/provenance/git-ai-standard/session.d.ts.map +1 -0
- package/dist/provenance/git-ai-standard/session.js +118 -0
- package/dist/provenance/git-ai-standard/types.d.ts +173 -0
- package/dist/provenance/git-ai-standard/types.d.ts.map +1 -0
- package/dist/provenance/git-ai-standard/types.js +109 -0
- package/dist/provenance/index.d.ts +5 -0
- package/dist/provenance/index.d.ts.map +1 -0
- package/dist/provenance/index.js +6 -0
- package/dist/provenance/store.d.ts +83 -0
- package/dist/provenance/store.d.ts.map +1 -0
- package/dist/provenance/store.js +248 -0
- package/dist/provenance/types.d.ts +160 -0
- package/dist/provenance/types.d.ts.map +1 -0
- package/dist/provenance/types.js +112 -0
- package/dist/suppression/index.d.ts +4 -0
- package/dist/suppression/index.d.ts.map +1 -0
- package/dist/suppression/index.js +3 -0
- package/dist/suppression/parser.d.ts +31 -0
- package/dist/suppression/parser.d.ts.map +1 -0
- package/dist/suppression/parser.js +219 -0
- package/dist/suppression/service.d.ts +29 -0
- package/dist/suppression/service.d.ts.map +1 -0
- package/dist/suppression/service.js +132 -0
- package/dist/suppression/store.d.ts +61 -0
- package/dist/suppression/store.d.ts.map +1 -0
- package/dist/suppression/store.js +169 -0
- package/dist/utils/debug.d.ts +48 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +100 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/path-safety.d.ts +21 -0
- package/dist/utils/path-safety.d.ts.map +1 -0
- package/dist/utils/path-safety.js +49 -0
- package/dist/utils/severity.d.ts +37 -0
- package/dist/utils/severity.d.ts.map +1 -0
- package/dist/utils/severity.js +22 -0
- package/dist/validation/aps-validator.d.ts +66 -0
- package/dist/validation/aps-validator.d.ts.map +1 -0
- package/dist/validation/aps-validator.js +173 -0
- package/dist/validation/errors.d.ts +52 -0
- package/dist/validation/errors.d.ts.map +1 -0
- package/dist/validation/errors.js +115 -0
- package/dist/validation/index.d.ts +8 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +13 -0
- package/dist/warnings/index.d.ts +2 -0
- package/dist/warnings/index.d.ts.map +1 -0
- package/dist/warnings/index.js +1 -0
- package/dist/warnings/warning-id.d.ts +180 -0
- package/dist/warnings/warning-id.d.ts.map +1 -0
- package/dist/warnings/warning-id.js +257 -0
- package/package.json +79 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { registerTemplate } from './template-loader.js';
|
|
2
|
+
const ARCH_RULES = {
|
|
3
|
+
'ARCH-001': {
|
|
4
|
+
id: 'ARCH-001',
|
|
5
|
+
name: 'Circular dependency',
|
|
6
|
+
description: 'A circular dependency chain was detected in imports.',
|
|
7
|
+
},
|
|
8
|
+
'ARCH-002': {
|
|
9
|
+
id: 'ARCH-002',
|
|
10
|
+
name: 'Orphan module',
|
|
11
|
+
description: 'This module is not imported by any other module.',
|
|
12
|
+
},
|
|
13
|
+
'ARCH-003': {
|
|
14
|
+
id: 'ARCH-003',
|
|
15
|
+
name: 'Layer boundary violation',
|
|
16
|
+
description: 'An import crosses an architectural layer boundary.',
|
|
17
|
+
},
|
|
18
|
+
'ARCH-004': {
|
|
19
|
+
id: 'ARCH-004',
|
|
20
|
+
name: 'Architecture violation',
|
|
21
|
+
description: 'General architecture rule violation detected.',
|
|
22
|
+
},
|
|
23
|
+
'BOUND-001': {
|
|
24
|
+
id: 'BOUND-001',
|
|
25
|
+
name: 'Boundary violation',
|
|
26
|
+
description: 'A new cross-boundary dependency was detected.',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
function createBoundaryExplanation(ruleId, context) {
|
|
30
|
+
const ruleInfo = ARCH_RULES[ruleId];
|
|
31
|
+
if (!ruleInfo) {
|
|
32
|
+
return createFallbackExplanation(ruleId, context);
|
|
33
|
+
}
|
|
34
|
+
const locationSummary = formatLocationSummary(ruleId, context);
|
|
35
|
+
return {
|
|
36
|
+
ruleId,
|
|
37
|
+
title: ruleInfo.name,
|
|
38
|
+
summary: locationSummary,
|
|
39
|
+
whyItMatters: {
|
|
40
|
+
title: 'WHY THIS WARNING EXISTS',
|
|
41
|
+
content: getWhyContent(ruleId, context),
|
|
42
|
+
},
|
|
43
|
+
howToAddress: {
|
|
44
|
+
title: 'HOW TO ADDRESS',
|
|
45
|
+
content: getHowContent(ruleId, context),
|
|
46
|
+
},
|
|
47
|
+
whenToSuppress: {
|
|
48
|
+
title: 'WHEN TO SUPPRESS',
|
|
49
|
+
content: getWhenToSuppressContent(ruleId),
|
|
50
|
+
},
|
|
51
|
+
related: {
|
|
52
|
+
ruleDefinition: `${ruleId} in architecture rules`,
|
|
53
|
+
similarWarnings: context.similarCount,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function formatLocationSummary(ruleId, context) {
|
|
58
|
+
if (context.fromFile && context.toFile) {
|
|
59
|
+
return `${context.fromFile} → ${context.toFile}`;
|
|
60
|
+
}
|
|
61
|
+
return `${ruleId} at ${context.file}:${context.line}`;
|
|
62
|
+
}
|
|
63
|
+
function getWhyContent(ruleId, context) {
|
|
64
|
+
const layerContext = context.fromLayer && context.toLayer
|
|
65
|
+
? `\n\nIn this case, ${context.fromLayer} is importing from ${context.toLayer}.`
|
|
66
|
+
: '';
|
|
67
|
+
const whyContent = {
|
|
68
|
+
'ARCH-001': `
|
|
69
|
+
Circular dependencies create tightly coupled code that is:
|
|
70
|
+
|
|
71
|
+
- Difficult to test in isolation
|
|
72
|
+
- Hard to understand (dependencies loop back)
|
|
73
|
+
- Prone to initialisation order bugs
|
|
74
|
+
- Resistant to refactoring
|
|
75
|
+
|
|
76
|
+
The dependency chain forms a cycle, meaning module A depends on B,
|
|
77
|
+
which depends on C, which depends back on A.${layerContext}`,
|
|
78
|
+
'ARCH-002': `
|
|
79
|
+
Orphan modules are files that no other code imports. This may indicate:
|
|
80
|
+
|
|
81
|
+
- Dead code that should be removed
|
|
82
|
+
- Missing integration (forgot to wire it up)
|
|
83
|
+
- Incorrect file organisation
|
|
84
|
+
- A utility that lost its callers after refactoring
|
|
85
|
+
|
|
86
|
+
While not always a problem, orphans often represent unused code
|
|
87
|
+
that adds maintenance burden.`,
|
|
88
|
+
'ARCH-003': `
|
|
89
|
+
This import violates defined layer boundaries. Layer violations:
|
|
90
|
+
|
|
91
|
+
- Break architectural contracts
|
|
92
|
+
- Create hidden dependencies
|
|
93
|
+
- Make changes risky (unknown blast radius)
|
|
94
|
+
- Complicate testing and deployment${layerContext}`,
|
|
95
|
+
'ARCH-004': `
|
|
96
|
+
This code violates an architecture rule defined for your project.
|
|
97
|
+
|
|
98
|
+
Architecture rules exist to:
|
|
99
|
+
- Enforce separation of concerns
|
|
100
|
+
- Prevent coupling between unrelated modules
|
|
101
|
+
- Maintain clear dependency direction
|
|
102
|
+
- Enable independent testing and deployment${layerContext}`,
|
|
103
|
+
'BOUND-001': `
|
|
104
|
+
A NEW cross-boundary dependency was introduced. This means code
|
|
105
|
+
that previously didn't exist is now crossing an architectural boundary.
|
|
106
|
+
|
|
107
|
+
New boundary violations are significant because:
|
|
108
|
+
- They indicate potential architecture drift
|
|
109
|
+
- The change was made without considering boundaries
|
|
110
|
+
- They may create precedent for further violations${layerContext}`,
|
|
111
|
+
};
|
|
112
|
+
return (whyContent[ruleId] ?? ARCH_RULES[ruleId]?.description ?? 'Architecture violation detected.');
|
|
113
|
+
}
|
|
114
|
+
function getHowContent(ruleId, context) {
|
|
115
|
+
const howContent = {
|
|
116
|
+
'ARCH-001': `
|
|
117
|
+
1. Identify the cycle
|
|
118
|
+
Look at the import chain to understand how modules connect
|
|
119
|
+
|
|
120
|
+
2. Break the cycle using one of these patterns:
|
|
121
|
+
- Extract shared code to a common module
|
|
122
|
+
- Use dependency injection
|
|
123
|
+
- Introduce an interface/abstraction layer
|
|
124
|
+
- Merge tightly coupled modules
|
|
125
|
+
|
|
126
|
+
3. Consider if the modules should be combined
|
|
127
|
+
Sometimes circular deps indicate a single concept split artificially`,
|
|
128
|
+
'ARCH-002': `
|
|
129
|
+
1. Verify the module is actually unused
|
|
130
|
+
Search for dynamic imports or test files that might use it
|
|
131
|
+
|
|
132
|
+
2. If unused, consider removing it
|
|
133
|
+
Dead code adds maintenance burden
|
|
134
|
+
|
|
135
|
+
3. If it should be used, add the missing integration
|
|
136
|
+
Wire it into the appropriate consumer
|
|
137
|
+
|
|
138
|
+
4. If it's a utility, document its purpose
|
|
139
|
+
Make sure others know it exists and when to use it`,
|
|
140
|
+
'ARCH-003': `
|
|
141
|
+
1. Understand the layer structure
|
|
142
|
+
Review which layer should depend on which
|
|
143
|
+
|
|
144
|
+
2. Consider using an intermediary
|
|
145
|
+
If presentation needs data, go through application layer
|
|
146
|
+
|
|
147
|
+
3. Move the code to the appropriate layer
|
|
148
|
+
Sometimes code is in the wrong place
|
|
149
|
+
|
|
150
|
+
4. Use dependency inversion
|
|
151
|
+
Depend on abstractions, not concretions`,
|
|
152
|
+
'ARCH-004': `
|
|
153
|
+
1. Review the architecture rule being violated
|
|
154
|
+
Understand why the rule exists
|
|
155
|
+
|
|
156
|
+
2. Determine if the violation is intentional
|
|
157
|
+
Sometimes rules need exceptions
|
|
158
|
+
|
|
159
|
+
3. Refactor to comply with the rule
|
|
160
|
+
Or propose a rule change if it's outdated`,
|
|
161
|
+
'BOUND-001': `
|
|
162
|
+
1. Understand what boundary was crossed
|
|
163
|
+
${context.fromLayer ? `From: ${context.fromLayer}` : ''}
|
|
164
|
+
${context.toLayer ? `To: ${context.toLayer}` : ''}
|
|
165
|
+
|
|
166
|
+
2. Consider the proper path
|
|
167
|
+
Is there an existing service or abstraction to use?
|
|
168
|
+
|
|
169
|
+
3. If the boundary is wrong, update architecture
|
|
170
|
+
Boundaries should reflect actual needs
|
|
171
|
+
|
|
172
|
+
4. If crossing is necessary, suppress with explanation
|
|
173
|
+
Document why this exception exists`,
|
|
174
|
+
};
|
|
175
|
+
return howContent[ruleId] ?? 'Review the architecture and consider refactoring.';
|
|
176
|
+
}
|
|
177
|
+
function getWhenToSuppressContent(ruleId) {
|
|
178
|
+
const suppressionContent = {
|
|
179
|
+
'ARCH-001': `
|
|
180
|
+
Suppress only if:
|
|
181
|
+
- The cycle is intentional and well-understood
|
|
182
|
+
- Breaking it would require major refactoring with a planned ticket
|
|
183
|
+
- The modules are conceptually a single unit
|
|
184
|
+
|
|
185
|
+
Example:
|
|
186
|
+
// @anvil-ignore ARCH-001: mutually recursive parsers, by design`,
|
|
187
|
+
'ARCH-002': `
|
|
188
|
+
Suppress only if:
|
|
189
|
+
- The module is a valid entry point (e.g., CLI, test setup)
|
|
190
|
+
- It's dynamically imported in ways not detected
|
|
191
|
+
- It's intentionally a standalone utility
|
|
192
|
+
|
|
193
|
+
Example:
|
|
194
|
+
// @anvil-ignore ARCH-002: CLI entry point, not imported`,
|
|
195
|
+
'ARCH-003': `
|
|
196
|
+
Suppress only if:
|
|
197
|
+
- The layer structure doesn't fit this use case
|
|
198
|
+
- You're actively migrating and have a ticket
|
|
199
|
+
- This is a pragmatic exception with clear reasoning
|
|
200
|
+
|
|
201
|
+
Example:
|
|
202
|
+
// @anvil-ignore ARCH-003: legacy code, migrating in JIRA-789`,
|
|
203
|
+
'ARCH-004': `
|
|
204
|
+
Suppress only if:
|
|
205
|
+
- The rule is overly strict for this case
|
|
206
|
+
- A rule change is pending
|
|
207
|
+
- This is a documented exception
|
|
208
|
+
|
|
209
|
+
Example:
|
|
210
|
+
// @anvil-ignore ARCH-004: approved exception per ADR-042`,
|
|
211
|
+
'BOUND-001': `
|
|
212
|
+
Suppress only if:
|
|
213
|
+
- The new dependency is intentional and reviewed
|
|
214
|
+
- The architecture definition needs updating
|
|
215
|
+
- This is a temporary bridge during migration
|
|
216
|
+
|
|
217
|
+
Example:
|
|
218
|
+
// @anvil-ignore BOUND-001: approved in PR review, updating baseline`,
|
|
219
|
+
};
|
|
220
|
+
return (suppressionContent[ruleId] ??
|
|
221
|
+
`
|
|
222
|
+
Suppress only with clear justification.
|
|
223
|
+
Use: // @anvil-ignore ${ruleId}: [your reason]`);
|
|
224
|
+
}
|
|
225
|
+
function createFallbackExplanation(ruleId, context) {
|
|
226
|
+
return {
|
|
227
|
+
ruleId,
|
|
228
|
+
title: `Architecture violation ${ruleId}`,
|
|
229
|
+
summary: `Violation at ${context.file}:${context.line}`,
|
|
230
|
+
whyItMatters: {
|
|
231
|
+
title: 'WHY THIS WARNING EXISTS',
|
|
232
|
+
content: 'This warning indicates an architecture boundary violation.',
|
|
233
|
+
},
|
|
234
|
+
howToAddress: {
|
|
235
|
+
title: 'HOW TO ADDRESS',
|
|
236
|
+
content: 'Review the architecture and consider refactoring.',
|
|
237
|
+
},
|
|
238
|
+
whenToSuppress: {
|
|
239
|
+
title: 'WHEN TO SUPPRESS',
|
|
240
|
+
content: `Use: // @anvil-ignore ${ruleId}: [reason]`,
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
export function registerBoundaryTemplates() {
|
|
245
|
+
for (const ruleId of Object.keys(ARCH_RULES)) {
|
|
246
|
+
const template = {
|
|
247
|
+
ruleId,
|
|
248
|
+
render: (context) => createBoundaryExplanation(ruleId, context),
|
|
249
|
+
};
|
|
250
|
+
registerTemplate(template);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
export function getBoundaryExplanation(ruleId, context) {
|
|
254
|
+
if (!ARCH_RULES[ruleId]) {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
return createBoundaryExplanation(ruleId, context);
|
|
258
|
+
}
|
|
259
|
+
export function isArchitectureRule(ruleId) {
|
|
260
|
+
return ruleId in ARCH_RULES;
|
|
261
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Warning } from '../antipattern/types.js';
|
|
2
|
+
import type { ExplanationContext, WarningExplanation } from './types.js';
|
|
3
|
+
export declare function resetExplainService(): void;
|
|
4
|
+
export declare function initExplainService(): void;
|
|
5
|
+
export declare function explainWarning(warning: Warning, allWarnings?: Warning[]): WarningExplanation;
|
|
6
|
+
export declare function explainById(warningId: string, warnings: Warning[]): WarningExplanation | null;
|
|
7
|
+
export declare function explainByRule(ruleId: string, context?: Partial<ExplanationContext>): WarningExplanation | null;
|
|
8
|
+
export interface ListWarningsResult {
|
|
9
|
+
warningId: string;
|
|
10
|
+
ruleId: string;
|
|
11
|
+
file: string;
|
|
12
|
+
line: number;
|
|
13
|
+
title: string;
|
|
14
|
+
severity: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function listWarnings(warnings: Warning[]): ListWarningsResult[];
|
|
17
|
+
export declare function isExplainable(ruleId: string): boolean;
|
|
18
|
+
export declare function getExplainableRules(): string[];
|
|
19
|
+
//# sourceMappingURL=explain-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explain-service.d.ts","sourceRoot":"","sources":["../../src/explain/explain-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA+BzE,wBAAgB,mBAAmB,IAAI,IAAI,CAG1C;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAoBD,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO,EAAE,GAAG,kBAAkB,CAkB5F;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,kBAAkB,GAAG,IAAI,CAgB7F;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GACpC,kBAAkB,GAAG,IAAI,CAuB3B;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,kBAAkB,EAAE,CAWtE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGrD;AAED,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAK9C"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { hasTemplate, renderExplanation, createGenericExplanation, clearTemplates, } from './template-loader.js';
|
|
2
|
+
import { registerAntiPatternTemplates } from './antipattern-explainer.js';
|
|
3
|
+
import { registerBoundaryTemplates, isArchitectureRule } from './boundary-explainer.js';
|
|
4
|
+
import { parseWarningId, findWarningById, findWarningsByRule, getWarningIds, } from '../warnings/warning-id.js';
|
|
5
|
+
import { getPattern } from '../antipattern/patterns.js';
|
|
6
|
+
import { createDebugger } from '../utils/debug.js';
|
|
7
|
+
const debug = createDebugger('explain');
|
|
8
|
+
let templatesInitialised = false;
|
|
9
|
+
function ensureTemplatesInitialised() {
|
|
10
|
+
if (!templatesInitialised) {
|
|
11
|
+
clearTemplates();
|
|
12
|
+
registerAntiPatternTemplates();
|
|
13
|
+
registerBoundaryTemplates();
|
|
14
|
+
templatesInitialised = true;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function resetExplainService() {
|
|
18
|
+
clearTemplates();
|
|
19
|
+
templatesInitialised = false;
|
|
20
|
+
}
|
|
21
|
+
export function initExplainService() {
|
|
22
|
+
ensureTemplatesInitialised();
|
|
23
|
+
}
|
|
24
|
+
function buildContext(warning, allWarnings) {
|
|
25
|
+
const context = {
|
|
26
|
+
file: warning.location.file,
|
|
27
|
+
line: warning.location.line,
|
|
28
|
+
patternName: warning.pattern,
|
|
29
|
+
};
|
|
30
|
+
if (allWarnings) {
|
|
31
|
+
const sameRuleWarnings = findWarningsByRule(allWarnings, warning.id);
|
|
32
|
+
const sameFileWarnings = sameRuleWarnings.filter((w) => w.location.file === warning.location.file);
|
|
33
|
+
context.similarCount = sameFileWarnings.length - 1;
|
|
34
|
+
}
|
|
35
|
+
return context;
|
|
36
|
+
}
|
|
37
|
+
export function explainWarning(warning, allWarnings) {
|
|
38
|
+
debug('explaining warning', {
|
|
39
|
+
id: warning.id,
|
|
40
|
+
file: warning.location.file,
|
|
41
|
+
line: warning.location.line,
|
|
42
|
+
});
|
|
43
|
+
ensureTemplatesInitialised();
|
|
44
|
+
const context = buildContext(warning, allWarnings);
|
|
45
|
+
if (hasTemplate(warning.id)) {
|
|
46
|
+
const explanation = renderExplanation(warning.id, context);
|
|
47
|
+
if (explanation) {
|
|
48
|
+
return explanation;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return createGenericExplanation(warning.id, warning.title, context);
|
|
52
|
+
}
|
|
53
|
+
export function explainById(warningId, warnings) {
|
|
54
|
+
debug('explaining by id', warningId);
|
|
55
|
+
ensureTemplatesInitialised();
|
|
56
|
+
const parsed = parseWarningId(warningId);
|
|
57
|
+
if (!parsed) {
|
|
58
|
+
debug('invalid warning id format', warningId);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const warning = findWarningById(warnings, warningId);
|
|
62
|
+
if (!warning) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
return explainWarning(warning, warnings);
|
|
66
|
+
}
|
|
67
|
+
export function explainByRule(ruleId, context) {
|
|
68
|
+
ensureTemplatesInitialised();
|
|
69
|
+
const fullContext = {
|
|
70
|
+
file: context?.file ?? 'unknown',
|
|
71
|
+
line: context?.line ?? 1,
|
|
72
|
+
...context,
|
|
73
|
+
};
|
|
74
|
+
if (hasTemplate(ruleId)) {
|
|
75
|
+
return renderExplanation(ruleId, fullContext);
|
|
76
|
+
}
|
|
77
|
+
const pattern = getPattern(ruleId);
|
|
78
|
+
if (pattern) {
|
|
79
|
+
return renderExplanation(ruleId, fullContext);
|
|
80
|
+
}
|
|
81
|
+
if (isArchitectureRule(ruleId)) {
|
|
82
|
+
return renderExplanation(ruleId, fullContext);
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
export function listWarnings(warnings) {
|
|
87
|
+
const warningIds = getWarningIds(warnings);
|
|
88
|
+
return warnings.map((w, i) => ({
|
|
89
|
+
warningId: warningIds[i],
|
|
90
|
+
ruleId: w.id,
|
|
91
|
+
file: w.location.file,
|
|
92
|
+
line: w.location.line,
|
|
93
|
+
title: w.title,
|
|
94
|
+
severity: w.severity,
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
export function isExplainable(ruleId) {
|
|
98
|
+
ensureTemplatesInitialised();
|
|
99
|
+
return hasTemplate(ruleId);
|
|
100
|
+
}
|
|
101
|
+
export function getExplainableRules() {
|
|
102
|
+
ensureTemplatesInitialised();
|
|
103
|
+
const antiPatternIds = ['AP-001', 'AP-002', 'AP-003', 'AP-004', 'AP-005', 'AP-006', 'AP-007'];
|
|
104
|
+
const archIds = ['ARCH-001', 'ARCH-002', 'ARCH-003', 'ARCH-004', 'BOUND-001'];
|
|
105
|
+
return [...antiPatternIds, ...archIds];
|
|
106
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { ExplanationSection, WarningExplanation, ExplanationContext, ExplanationTemplate, } from './types.js';
|
|
2
|
+
export { ExplanationSectionSchema, WarningExplanationSchema, ExplanationContextSchema, } from './types.js';
|
|
3
|
+
export { registerTemplate, getTemplate, hasTemplate, getRegisteredRuleIds, renderExplanation, clearTemplates, createGenericExplanation, } from './template-loader.js';
|
|
4
|
+
export { registerAntiPatternTemplates, getAntiPatternExplanation, } from './antipattern-explainer.js';
|
|
5
|
+
export { registerBoundaryTemplates, getBoundaryExplanation, isArchitectureRule, } from './boundary-explainer.js';
|
|
6
|
+
export { resetExplainService, initExplainService, explainWarning, explainById, explainByRule, listWarnings, isExplainable, getExplainableRules, type ListWarningsResult, } from './explain-service.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/explain/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,aAAa,EACb,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,KAAK,kBAAkB,GACxB,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ExplanationSectionSchema, WarningExplanationSchema, ExplanationContextSchema, } from './types.js';
|
|
2
|
+
export { registerTemplate, getTemplate, hasTemplate, getRegisteredRuleIds, renderExplanation, clearTemplates, createGenericExplanation, } from './template-loader.js';
|
|
3
|
+
export { registerAntiPatternTemplates, getAntiPatternExplanation, } from './antipattern-explainer.js';
|
|
4
|
+
export { registerBoundaryTemplates, getBoundaryExplanation, isArchitectureRule, } from './boundary-explainer.js';
|
|
5
|
+
export { resetExplainService, initExplainService, explainWarning, explainById, explainByRule, listWarnings, isExplainable, getExplainableRules, } from './explain-service.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ExplanationTemplate, ExplanationContext, WarningExplanation } from './types.js';
|
|
2
|
+
export declare function registerTemplate(template: ExplanationTemplate): void;
|
|
3
|
+
export declare function getTemplate(ruleId: string): ExplanationTemplate | undefined;
|
|
4
|
+
export declare function hasTemplate(ruleId: string): boolean;
|
|
5
|
+
export declare function getRegisteredRuleIds(): string[];
|
|
6
|
+
export declare function renderExplanation(ruleId: string, context: ExplanationContext): WarningExplanation | null;
|
|
7
|
+
export declare function clearTemplates(): void;
|
|
8
|
+
export declare function createGenericExplanation(ruleId: string, title: string, context: ExplanationContext): WarningExplanation;
|
|
9
|
+
//# sourceMappingURL=template-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-loader.d.ts","sourceRoot":"","sources":["../../src/explain/template-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAO9F,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAGpE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAE3E;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,wBAAgB,oBAAoB,IAAI,MAAM,EAAE,CAE/C;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,kBAAkB,GAC1B,kBAAkB,GAAG,IAAI,CAO3B;AAED,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,kBAAkB,GAC1B,kBAAkB,CA0BpB"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { createDebugger } from '../utils/debug.js';
|
|
2
|
+
const debug = createDebugger('explain');
|
|
3
|
+
const templateRegistry = new Map();
|
|
4
|
+
export function registerTemplate(template) {
|
|
5
|
+
debug('registering template', template.ruleId);
|
|
6
|
+
templateRegistry.set(template.ruleId, template);
|
|
7
|
+
}
|
|
8
|
+
export function getTemplate(ruleId) {
|
|
9
|
+
return templateRegistry.get(ruleId);
|
|
10
|
+
}
|
|
11
|
+
export function hasTemplate(ruleId) {
|
|
12
|
+
return templateRegistry.has(ruleId);
|
|
13
|
+
}
|
|
14
|
+
export function getRegisteredRuleIds() {
|
|
15
|
+
return Array.from(templateRegistry.keys());
|
|
16
|
+
}
|
|
17
|
+
export function renderExplanation(ruleId, context) {
|
|
18
|
+
const template = templateRegistry.get(ruleId);
|
|
19
|
+
if (!template) {
|
|
20
|
+
debug('no template found for rule', ruleId);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
return template.render(context);
|
|
24
|
+
}
|
|
25
|
+
export function clearTemplates() {
|
|
26
|
+
templateRegistry.clear();
|
|
27
|
+
}
|
|
28
|
+
export function createGenericExplanation(ruleId, title, context) {
|
|
29
|
+
return {
|
|
30
|
+
ruleId,
|
|
31
|
+
title,
|
|
32
|
+
summary: `Warning ${ruleId} detected at ${context.file}:${context.line}`,
|
|
33
|
+
whyItMatters: {
|
|
34
|
+
title: 'WHY THIS WARNING EXISTS',
|
|
35
|
+
content: 'This warning indicates a potential issue in your code. ' +
|
|
36
|
+
'Please refer to the warning message for specific details.',
|
|
37
|
+
},
|
|
38
|
+
howToAddress: {
|
|
39
|
+
title: 'HOW TO ADDRESS',
|
|
40
|
+
content: 'Review the flagged code and consider the warning message. ' +
|
|
41
|
+
'Determine if changes are needed based on your project requirements.',
|
|
42
|
+
},
|
|
43
|
+
whenToSuppress: {
|
|
44
|
+
title: 'WHEN TO SUPPRESS',
|
|
45
|
+
content: 'Suppress only if you understand the warning and have a valid reason. ' +
|
|
46
|
+
'Use: // @anvil-ignore ' +
|
|
47
|
+
ruleId +
|
|
48
|
+
': [your reason]',
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const ExplanationSectionSchema: z.ZodObject<{
|
|
3
|
+
title: z.ZodString;
|
|
4
|
+
content: z.ZodString;
|
|
5
|
+
}, z.core.$strip>;
|
|
6
|
+
export type ExplanationSection = z.infer<typeof ExplanationSectionSchema>;
|
|
7
|
+
export declare const WarningExplanationSchema: z.ZodObject<{
|
|
8
|
+
ruleId: z.ZodString;
|
|
9
|
+
title: z.ZodString;
|
|
10
|
+
summary: z.ZodString;
|
|
11
|
+
whyItMatters: z.ZodObject<{
|
|
12
|
+
title: z.ZodString;
|
|
13
|
+
content: z.ZodString;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
howToAddress: z.ZodObject<{
|
|
16
|
+
title: z.ZodString;
|
|
17
|
+
content: z.ZodString;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
whenToSuppress: z.ZodObject<{
|
|
20
|
+
title: z.ZodString;
|
|
21
|
+
content: z.ZodString;
|
|
22
|
+
}, z.core.$strip>;
|
|
23
|
+
related: z.ZodOptional<z.ZodObject<{
|
|
24
|
+
documentation: z.ZodOptional<z.ZodString>;
|
|
25
|
+
ruleDefinition: z.ZodOptional<z.ZodString>;
|
|
26
|
+
similarWarnings: z.ZodOptional<z.ZodNumber>;
|
|
27
|
+
}, z.core.$strip>>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
export type WarningExplanation = z.infer<typeof WarningExplanationSchema>;
|
|
30
|
+
export declare const ExplanationContextSchema: z.ZodObject<{
|
|
31
|
+
file: z.ZodString;
|
|
32
|
+
line: z.ZodNumber;
|
|
33
|
+
code: z.ZodOptional<z.ZodString>;
|
|
34
|
+
fromFile: z.ZodOptional<z.ZodString>;
|
|
35
|
+
toFile: z.ZodOptional<z.ZodString>;
|
|
36
|
+
fromLayer: z.ZodOptional<z.ZodString>;
|
|
37
|
+
toLayer: z.ZodOptional<z.ZodString>;
|
|
38
|
+
patternName: z.ZodOptional<z.ZodString>;
|
|
39
|
+
similarCount: z.ZodOptional<z.ZodNumber>;
|
|
40
|
+
}, z.core.$strip>;
|
|
41
|
+
export type ExplanationContext = z.infer<typeof ExplanationContextSchema>;
|
|
42
|
+
export interface ExplanationTemplate {
|
|
43
|
+
ruleId: string;
|
|
44
|
+
render(context: ExplanationContext): WarningExplanation;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/explain/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,wBAAwB;;;iBAGnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;iBAcnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,wBAAwB;;;;;;;;;;iBAUnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,OAAO,EAAE,kBAAkB,GAAG,kBAAkB,CAAC;CACzD"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const ExplanationSectionSchema = z.object({
|
|
3
|
+
title: z.string().describe('Section title (e.g., "WHY THIS WARNING EXISTS")'),
|
|
4
|
+
content: z.string().describe('Section content, may contain placeholders'),
|
|
5
|
+
});
|
|
6
|
+
export const WarningExplanationSchema = z.object({
|
|
7
|
+
ruleId: z.string().describe('Rule ID (e.g., AP-003, ARCH-001)'),
|
|
8
|
+
title: z.string().describe('Warning title'),
|
|
9
|
+
summary: z.string().describe('One-line summary of the warning'),
|
|
10
|
+
whyItMatters: ExplanationSectionSchema.describe('Why this warning exists'),
|
|
11
|
+
howToAddress: ExplanationSectionSchema.describe('How to fix or address'),
|
|
12
|
+
whenToSuppress: ExplanationSectionSchema.describe('When suppression is appropriate'),
|
|
13
|
+
related: z
|
|
14
|
+
.object({
|
|
15
|
+
documentation: z.string().optional(),
|
|
16
|
+
ruleDefinition: z.string().optional(),
|
|
17
|
+
similarWarnings: z.number().int().nonnegative().optional(),
|
|
18
|
+
})
|
|
19
|
+
.optional(),
|
|
20
|
+
});
|
|
21
|
+
export const ExplanationContextSchema = z.object({
|
|
22
|
+
file: z.string().describe('File path where warning occurred'),
|
|
23
|
+
line: z.number().int().positive().describe('Line number'),
|
|
24
|
+
code: z.string().optional().describe('Source code snippet at the location'),
|
|
25
|
+
fromFile: z.string().optional().describe('Source file (for boundary violations)'),
|
|
26
|
+
toFile: z.string().optional().describe('Target file (for boundary violations)'),
|
|
27
|
+
fromLayer: z.string().optional().describe('Source layer (for boundary violations)'),
|
|
28
|
+
toLayer: z.string().optional().describe('Target layer (for boundary violations)'),
|
|
29
|
+
patternName: z.string().optional().describe('Pattern name (for anti-patterns)'),
|
|
30
|
+
similarCount: z.number().int().nonnegative().optional(),
|
|
31
|
+
});
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @eddacraft/anvil-core
|
|
3
|
+
*
|
|
4
|
+
* Core domain logic for the Anvil system.
|
|
5
|
+
* Contains antipattern detection, architecture analysis, drift detection,
|
|
6
|
+
* suppression management, validation, and other core functionality.
|
|
7
|
+
*
|
|
8
|
+
* Note: Some modules perform filesystem I/O (provenance, drift snapshots,
|
|
9
|
+
* architecture baseline, suppression store). Heavy I/O orchestration
|
|
10
|
+
* (gate runner, caching, OPA execution) lives in @eddacraft/anvil-runtime.
|
|
11
|
+
*
|
|
12
|
+
* @module @eddacraft/anvil-core
|
|
13
|
+
*/
|
|
14
|
+
export * from './contracts/index.js';
|
|
15
|
+
export * from './config/index.js';
|
|
16
|
+
export * from './antipattern/index.js';
|
|
17
|
+
export * from './suppression/index.js';
|
|
18
|
+
export * from './architecture/index.js';
|
|
19
|
+
export * from './drift/index.js';
|
|
20
|
+
export * from './provenance/index.js';
|
|
21
|
+
export * from './warnings/index.js';
|
|
22
|
+
export * from './explain/index.js';
|
|
23
|
+
export * from './validation/index.js';
|
|
24
|
+
export * from './crypto/index.js';
|
|
25
|
+
export * from './utils/index.js';
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,cAAc,sBAAsB,CAAC;AAGrC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,kBAAkB,CAAC;AAGjC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @eddacraft/anvil-core
|
|
3
|
+
*
|
|
4
|
+
* Core domain logic for the Anvil system.
|
|
5
|
+
* Contains antipattern detection, architecture analysis, drift detection,
|
|
6
|
+
* suppression management, validation, and other core functionality.
|
|
7
|
+
*
|
|
8
|
+
* Note: Some modules perform filesystem I/O (provenance, drift snapshots,
|
|
9
|
+
* architecture baseline, suppression store). Heavy I/O orchestration
|
|
10
|
+
* (gate runner, caching, OPA execution) lives in @eddacraft/anvil-runtime.
|
|
11
|
+
*
|
|
12
|
+
* @module @eddacraft/anvil-core
|
|
13
|
+
*/
|
|
14
|
+
// Contracts (schemas, types, events) — formerly @eddacraft/anvil-contracts
|
|
15
|
+
export * from './contracts/index.js';
|
|
16
|
+
// Platform config — formerly @eddacraft/anvil-platform-config
|
|
17
|
+
export * from './config/index.js';
|
|
18
|
+
// Antipattern detection
|
|
19
|
+
export * from './antipattern/index.js';
|
|
20
|
+
// Suppression management
|
|
21
|
+
export * from './suppression/index.js';
|
|
22
|
+
// Architecture analysis
|
|
23
|
+
export * from './architecture/index.js';
|
|
24
|
+
// Drift detection
|
|
25
|
+
export * from './drift/index.js';
|
|
26
|
+
// Provenance tracking
|
|
27
|
+
export * from './provenance/index.js';
|
|
28
|
+
// Warning utilities
|
|
29
|
+
export * from './warnings/index.js';
|
|
30
|
+
// Explain functionality
|
|
31
|
+
export * from './explain/index.js';
|
|
32
|
+
// Validation
|
|
33
|
+
export * from './validation/index.js';
|
|
34
|
+
// Crypto utilities
|
|
35
|
+
export * from './crypto/index.js';
|
|
36
|
+
// General utilities
|
|
37
|
+
export * from './utils/index.js';
|