@brad-frost-web/eddie-brain 0.32.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.
Files changed (239) hide show
  1. package/README.md +109 -0
  2. package/dist/analyze/drift-detector.d.ts +30 -0
  3. package/dist/analyze/drift-detector.d.ts.map +1 -0
  4. package/dist/analyze/drift-detector.js +310 -0
  5. package/dist/analyze/drift-detector.js.map +1 -0
  6. package/dist/analyze/health-scorer.d.ts +71 -0
  7. package/dist/analyze/health-scorer.d.ts.map +1 -0
  8. package/dist/analyze/health-scorer.js +420 -0
  9. package/dist/analyze/health-scorer.js.map +1 -0
  10. package/dist/analyze/index.d.ts +11 -0
  11. package/dist/analyze/index.d.ts.map +1 -0
  12. package/dist/analyze/index.js +11 -0
  13. package/dist/analyze/index.js.map +1 -0
  14. package/dist/analyze/naming-validator.d.ts +99 -0
  15. package/dist/analyze/naming-validator.d.ts.map +1 -0
  16. package/dist/analyze/naming-validator.js +430 -0
  17. package/dist/analyze/naming-validator.js.map +1 -0
  18. package/dist/analyze/slot-contract-validator.d.ts +68 -0
  19. package/dist/analyze/slot-contract-validator.d.ts.map +1 -0
  20. package/dist/analyze/slot-contract-validator.js +232 -0
  21. package/dist/analyze/slot-contract-validator.js.map +1 -0
  22. package/dist/analyze/token-validator.d.ts +62 -0
  23. package/dist/analyze/token-validator.d.ts.map +1 -0
  24. package/dist/analyze/token-validator.js +348 -0
  25. package/dist/analyze/token-validator.js.map +1 -0
  26. package/dist/cli/brain.d.ts +12 -0
  27. package/dist/cli/brain.d.ts.map +1 -0
  28. package/dist/cli/brain.js +641 -0
  29. package/dist/cli/brain.js.map +1 -0
  30. package/dist/cli/formatters/json.d.ts +15 -0
  31. package/dist/cli/formatters/json.d.ts.map +1 -0
  32. package/dist/cli/formatters/json.js +18 -0
  33. package/dist/cli/formatters/json.js.map +1 -0
  34. package/dist/cli/formatters/terminal.d.ts +19 -0
  35. package/dist/cli/formatters/terminal.d.ts.map +1 -0
  36. package/dist/cli/formatters/terminal.js +125 -0
  37. package/dist/cli/formatters/terminal.js.map +1 -0
  38. package/dist/cli/index.d.ts +7 -0
  39. package/dist/cli/index.d.ts.map +1 -0
  40. package/dist/cli/index.js +7 -0
  41. package/dist/cli/index.js.map +1 -0
  42. package/dist/data/governance-rules.json +94 -0
  43. package/dist/governance/audit-log.d.ts +17 -0
  44. package/dist/governance/audit-log.d.ts.map +1 -0
  45. package/dist/governance/audit-log.js +44 -0
  46. package/dist/governance/audit-log.js.map +1 -0
  47. package/dist/governance/index.d.ts +8 -0
  48. package/dist/governance/index.d.ts.map +1 -0
  49. package/dist/governance/index.js +8 -0
  50. package/dist/governance/index.js.map +1 -0
  51. package/dist/governance/permissions.d.ts +26 -0
  52. package/dist/governance/permissions.d.ts.map +1 -0
  53. package/dist/governance/permissions.js +75 -0
  54. package/dist/governance/permissions.js.map +1 -0
  55. package/dist/governance/rules-engine.d.ts +24 -0
  56. package/dist/governance/rules-engine.d.ts.map +1 -0
  57. package/dist/governance/rules-engine.js +111 -0
  58. package/dist/governance/rules-engine.js.map +1 -0
  59. package/dist/governance/trust-manager.d.ts +34 -0
  60. package/dist/governance/trust-manager.d.ts.map +1 -0
  61. package/dist/governance/trust-manager.js +148 -0
  62. package/dist/governance/trust-manager.js.map +1 -0
  63. package/dist/index.d.ts +23 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +28 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/knowledge-graph/component-index.d.ts +320 -0
  68. package/dist/knowledge-graph/component-index.d.ts.map +1 -0
  69. package/dist/knowledge-graph/component-index.js +1033 -0
  70. package/dist/knowledge-graph/component-index.js.map +1 -0
  71. package/dist/knowledge-graph/index.d.ts +134 -0
  72. package/dist/knowledge-graph/index.d.ts.map +1 -0
  73. package/dist/knowledge-graph/index.js +249 -0
  74. package/dist/knowledge-graph/index.js.map +1 -0
  75. package/dist/knowledge-graph/learning-history.d.ts +77 -0
  76. package/dist/knowledge-graph/learning-history.d.ts.map +1 -0
  77. package/dist/knowledge-graph/learning-history.js +187 -0
  78. package/dist/knowledge-graph/learning-history.js.map +1 -0
  79. package/dist/knowledge-graph/relationship-map.d.ts +55 -0
  80. package/dist/knowledge-graph/relationship-map.d.ts.map +1 -0
  81. package/dist/knowledge-graph/relationship-map.js +238 -0
  82. package/dist/knowledge-graph/relationship-map.js.map +1 -0
  83. package/dist/knowledge-graph/token-taxonomy.d.ts +127 -0
  84. package/dist/knowledge-graph/token-taxonomy.d.ts.map +1 -0
  85. package/dist/knowledge-graph/token-taxonomy.js +357 -0
  86. package/dist/knowledge-graph/token-taxonomy.js.map +1 -0
  87. package/dist/loop/fix-agent.d.ts +55 -0
  88. package/dist/loop/fix-agent.d.ts.map +1 -0
  89. package/dist/loop/fix-agent.js +344 -0
  90. package/dist/loop/fix-agent.js.map +1 -0
  91. package/dist/loop/index.d.ts +8 -0
  92. package/dist/loop/index.d.ts.map +1 -0
  93. package/dist/loop/index.js +8 -0
  94. package/dist/loop/index.js.map +1 -0
  95. package/dist/loop/issue-fetcher.d.ts +51 -0
  96. package/dist/loop/issue-fetcher.d.ts.map +1 -0
  97. package/dist/loop/issue-fetcher.js +188 -0
  98. package/dist/loop/issue-fetcher.js.map +1 -0
  99. package/dist/loop/observer.d.ts +42 -0
  100. package/dist/loop/observer.d.ts.map +1 -0
  101. package/dist/loop/observer.js +220 -0
  102. package/dist/loop/observer.js.map +1 -0
  103. package/dist/loop/pacer.d.ts +44 -0
  104. package/dist/loop/pacer.d.ts.map +1 -0
  105. package/dist/loop/pacer.js +90 -0
  106. package/dist/loop/pacer.js.map +1 -0
  107. package/dist/loop/reporter.d.ts +9 -0
  108. package/dist/loop/reporter.d.ts.map +1 -0
  109. package/dist/loop/reporter.js +119 -0
  110. package/dist/loop/reporter.js.map +1 -0
  111. package/dist/loop/runner.d.ts +57 -0
  112. package/dist/loop/runner.d.ts.map +1 -0
  113. package/dist/loop/runner.js +390 -0
  114. package/dist/loop/runner.js.map +1 -0
  115. package/dist/loop/types.d.ts +151 -0
  116. package/dist/loop/types.d.ts.map +1 -0
  117. package/dist/loop/types.js +22 -0
  118. package/dist/loop/types.js.map +1 -0
  119. package/dist/mcp/index.d.ts +7 -0
  120. package/dist/mcp/index.d.ts.map +1 -0
  121. package/dist/mcp/index.js +7 -0
  122. package/dist/mcp/index.js.map +1 -0
  123. package/dist/mcp/server.d.ts +12 -0
  124. package/dist/mcp/server.d.ts.map +1 -0
  125. package/dist/mcp/server.js +618 -0
  126. package/dist/mcp/server.js.map +1 -0
  127. package/dist/pipeline/agent-runner.d.ts +34 -0
  128. package/dist/pipeline/agent-runner.d.ts.map +1 -0
  129. package/dist/pipeline/agent-runner.js +323 -0
  130. package/dist/pipeline/agent-runner.js.map +1 -0
  131. package/dist/pipeline/agents/accessibility-auditor.d.ts +10 -0
  132. package/dist/pipeline/agents/accessibility-auditor.d.ts.map +1 -0
  133. package/dist/pipeline/agents/accessibility-auditor.js +69 -0
  134. package/dist/pipeline/agents/accessibility-auditor.js.map +1 -0
  135. package/dist/pipeline/agents/code-reviewer.d.ts +10 -0
  136. package/dist/pipeline/agents/code-reviewer.d.ts.map +1 -0
  137. package/dist/pipeline/agents/code-reviewer.js +75 -0
  138. package/dist/pipeline/agents/code-reviewer.js.map +1 -0
  139. package/dist/pipeline/agents/code-writer.d.ts +10 -0
  140. package/dist/pipeline/agents/code-writer.d.ts.map +1 -0
  141. package/dist/pipeline/agents/code-writer.js +103 -0
  142. package/dist/pipeline/agents/code-writer.js.map +1 -0
  143. package/dist/pipeline/agents/component-architect.d.ts +13 -0
  144. package/dist/pipeline/agents/component-architect.d.ts.map +1 -0
  145. package/dist/pipeline/agents/component-architect.js +81 -0
  146. package/dist/pipeline/agents/component-architect.js.map +1 -0
  147. package/dist/pipeline/agents/index.d.ts +16 -0
  148. package/dist/pipeline/agents/index.d.ts.map +1 -0
  149. package/dist/pipeline/agents/index.js +24 -0
  150. package/dist/pipeline/agents/index.js.map +1 -0
  151. package/dist/pipeline/agents/library-researcher.d.ts +12 -0
  152. package/dist/pipeline/agents/library-researcher.d.ts.map +1 -0
  153. package/dist/pipeline/agents/library-researcher.js +85 -0
  154. package/dist/pipeline/agents/library-researcher.js.map +1 -0
  155. package/dist/pipeline/agents/quality-gate.d.ts +9 -0
  156. package/dist/pipeline/agents/quality-gate.d.ts.map +1 -0
  157. package/dist/pipeline/agents/quality-gate.js +71 -0
  158. package/dist/pipeline/agents/quality-gate.js.map +1 -0
  159. package/dist/pipeline/agents/spec-analyst.d.ts +10 -0
  160. package/dist/pipeline/agents/spec-analyst.d.ts.map +1 -0
  161. package/dist/pipeline/agents/spec-analyst.js +72 -0
  162. package/dist/pipeline/agents/spec-analyst.js.map +1 -0
  163. package/dist/pipeline/agents/story-author.d.ts +9 -0
  164. package/dist/pipeline/agents/story-author.d.ts.map +1 -0
  165. package/dist/pipeline/agents/story-author.js +65 -0
  166. package/dist/pipeline/agents/story-author.js.map +1 -0
  167. package/dist/pipeline/artifact-store.d.ts +27 -0
  168. package/dist/pipeline/artifact-store.d.ts.map +1 -0
  169. package/dist/pipeline/artifact-store.js +77 -0
  170. package/dist/pipeline/artifact-store.js.map +1 -0
  171. package/dist/pipeline/conversational-gate.d.ts +26 -0
  172. package/dist/pipeline/conversational-gate.d.ts.map +1 -0
  173. package/dist/pipeline/conversational-gate.js +122 -0
  174. package/dist/pipeline/conversational-gate.js.map +1 -0
  175. package/dist/pipeline/index.d.ts +14 -0
  176. package/dist/pipeline/index.d.ts.map +1 -0
  177. package/dist/pipeline/index.js +17 -0
  178. package/dist/pipeline/index.js.map +1 -0
  179. package/dist/pipeline/iteration-tracker.d.ts +29 -0
  180. package/dist/pipeline/iteration-tracker.d.ts.map +1 -0
  181. package/dist/pipeline/iteration-tracker.js +102 -0
  182. package/dist/pipeline/iteration-tracker.js.map +1 -0
  183. package/dist/pipeline/learning-bridge.d.ts +37 -0
  184. package/dist/pipeline/learning-bridge.d.ts.map +1 -0
  185. package/dist/pipeline/learning-bridge.js +118 -0
  186. package/dist/pipeline/learning-bridge.js.map +1 -0
  187. package/dist/pipeline/orchestrator.d.ts +45 -0
  188. package/dist/pipeline/orchestrator.d.ts.map +1 -0
  189. package/dist/pipeline/orchestrator.js +473 -0
  190. package/dist/pipeline/orchestrator.js.map +1 -0
  191. package/dist/pipeline/templates/architecture.d.ts +27 -0
  192. package/dist/pipeline/templates/architecture.d.ts.map +1 -0
  193. package/dist/pipeline/templates/architecture.js +111 -0
  194. package/dist/pipeline/templates/architecture.js.map +1 -0
  195. package/dist/pipeline/templates/brief.d.ts +22 -0
  196. package/dist/pipeline/templates/brief.d.ts.map +1 -0
  197. package/dist/pipeline/templates/brief.js +121 -0
  198. package/dist/pipeline/templates/brief.js.map +1 -0
  199. package/dist/pipeline/templates/component-rules.d.ts +25 -0
  200. package/dist/pipeline/templates/component-rules.d.ts.map +1 -0
  201. package/dist/pipeline/templates/component-rules.js +93 -0
  202. package/dist/pipeline/templates/component-rules.js.map +1 -0
  203. package/dist/pipeline/templates/index.d.ts +9 -0
  204. package/dist/pipeline/templates/index.d.ts.map +1 -0
  205. package/dist/pipeline/templates/index.js +7 -0
  206. package/dist/pipeline/templates/index.js.map +1 -0
  207. package/dist/pipeline/tool-handler.d.ts +25 -0
  208. package/dist/pipeline/tool-handler.d.ts.map +1 -0
  209. package/dist/pipeline/tool-handler.js +392 -0
  210. package/dist/pipeline/tool-handler.js.map +1 -0
  211. package/dist/pipeline/types.d.ts +146 -0
  212. package/dist/pipeline/types.d.ts.map +1 -0
  213. package/dist/pipeline/types.js +27 -0
  214. package/dist/pipeline/types.js.map +1 -0
  215. package/dist/plan/action-types.d.ts +31 -0
  216. package/dist/plan/action-types.d.ts.map +1 -0
  217. package/dist/plan/action-types.js +83 -0
  218. package/dist/plan/action-types.js.map +1 -0
  219. package/dist/plan/decision-engine.d.ts +57 -0
  220. package/dist/plan/decision-engine.d.ts.map +1 -0
  221. package/dist/plan/decision-engine.js +162 -0
  222. package/dist/plan/decision-engine.js.map +1 -0
  223. package/dist/plan/index.d.ts +6 -0
  224. package/dist/plan/index.d.ts.map +1 -0
  225. package/dist/plan/index.js +6 -0
  226. package/dist/plan/index.js.map +1 -0
  227. package/dist/types.d.ts +351 -0
  228. package/dist/types.d.ts.map +1 -0
  229. package/dist/types.js +26 -0
  230. package/dist/types.js.map +1 -0
  231. package/dist/utils/anthropic.d.ts +15 -0
  232. package/dist/utils/anthropic.d.ts.map +1 -0
  233. package/dist/utils/anthropic.js +40 -0
  234. package/dist/utils/anthropic.js.map +1 -0
  235. package/dist/utils/id.d.ts +8 -0
  236. package/dist/utils/id.d.ts.map +1 -0
  237. package/dist/utils/id.js +14 -0
  238. package/dist/utils/id.js.map +1 -0
  239. package/package.json +80 -0
@@ -0,0 +1,420 @@
1
+ /**
2
+ * Health Scorer
3
+ *
4
+ * Scores system health across 6 categories:
5
+ * - Tokens: proper usage of design tokens
6
+ * - Naming: BEM/BEMIT compliance
7
+ * - Coverage: completeness of component metadata
8
+ * - Documentation: presence and quality of documentation
9
+ * - Accessibility: ARIA and keyboard handling
10
+ * - Consistency: API and pattern consistency
11
+ */
12
+ import { resolve } from 'path';
13
+ import { TokenValidator } from './token-validator.js';
14
+ import { NamingValidator } from './naming-validator.js';
15
+ export class HealthScorer {
16
+ knowledgeGraph;
17
+ config;
18
+ tokenValidator;
19
+ namingValidator;
20
+ constructor(knowledgeGraph, config) {
21
+ this.knowledgeGraph = knowledgeGraph;
22
+ this.config = config;
23
+ this.tokenValidator = new TokenValidator();
24
+ this.namingValidator = new NamingValidator();
25
+ }
26
+ /**
27
+ * Score a single component across all health categories
28
+ */
29
+ async scoreComponent(tagName) {
30
+ const scores = [];
31
+ // Get component entry
32
+ const componentEntry = this.knowledgeGraph.getComponentEntries?.()?.find((c) => c.tagName === tagName);
33
+ if (!componentEntry) {
34
+ return [
35
+ {
36
+ category: 'tokens',
37
+ score: 0,
38
+ issues: [
39
+ {
40
+ id: `health-component-not-found-${tagName}`,
41
+ category: 'tokens',
42
+ severity: 'error',
43
+ message: `Component ${tagName} not found in knowledge graph`,
44
+ file: 'unknown',
45
+ autoFixable: false,
46
+ },
47
+ ],
48
+ },
49
+ ];
50
+ }
51
+ // Token health
52
+ scores.push(await this.scoreTokenHealth(componentEntry));
53
+ // Naming health
54
+ scores.push(await this.scoreNamingHealth(componentEntry));
55
+ // Documentation health
56
+ scores.push(this.scoreDocumentationHealth(componentEntry));
57
+ // Coverage health
58
+ scores.push(this.scoreCoverageHealth(componentEntry));
59
+ // Accessibility health
60
+ scores.push(this.scoreAccessibilityHealth(componentEntry));
61
+ // Consistency health
62
+ scores.push(await this.scoreConsistencyHealth(componentEntry));
63
+ return scores;
64
+ }
65
+ /**
66
+ * Generate full system health report
67
+ */
68
+ async scoreAll() {
69
+ const components = this.knowledgeGraph.getComponentEntries?.() || [];
70
+ const allScores = [];
71
+ const startTime = Date.now();
72
+ for (const component of components) {
73
+ const scores = await this.scoreComponent(component.tagName);
74
+ allScores.push(...scores);
75
+ }
76
+ // Aggregate scores by category
77
+ const categoryScores = this.aggregateScores(allScores);
78
+ // Calculate overall weighted score
79
+ const overall = this.calculateWeightedScore(categoryScores);
80
+ // Count issues by severity
81
+ const issueCounts = this.countIssuesBySeverity(allScores);
82
+ return {
83
+ timestamp: new Date().toISOString(),
84
+ overall,
85
+ categories: categoryScores,
86
+ totalIssues: allScores.reduce((sum, score) => sum + score.issues.length, 0),
87
+ issueCounts,
88
+ };
89
+ }
90
+ /**
91
+ * Score token usage health
92
+ */
93
+ async scoreTokenHealth(component) {
94
+ const issues = [];
95
+ // Validate component SCSS file if it exists
96
+ if (component.paths?.styles) {
97
+ const stylesPath = resolve(this.config.rootDir, component.paths.styles);
98
+ const taxonomy = this.knowledgeGraph.getTokenTaxonomy?.();
99
+ if (taxonomy) {
100
+ const styleIssues = await this.tokenValidator.validateFile(stylesPath, taxonomy);
101
+ issues.push(...styleIssues);
102
+ }
103
+ }
104
+ // Score: 100 - (violations / total_checks * 100)
105
+ // Assume ~10 token uses per component file
106
+ const estimatedTokenUses = 10;
107
+ const violationRate = issues.length / Math.max(estimatedTokenUses, 1);
108
+ const score = Math.max(0, Math.round(100 - violationRate * 100));
109
+ return {
110
+ category: 'tokens',
111
+ score,
112
+ issues,
113
+ };
114
+ }
115
+ /**
116
+ * Score naming convention compliance
117
+ */
118
+ async scoreNamingHealth(component) {
119
+ const issues = [];
120
+ // Validate component file
121
+ if (component.paths?.component) {
122
+ const componentPath = resolve(this.config.rootDir, component.paths.component);
123
+ const componentIssues = await this.namingValidator.validateFile(componentPath);
124
+ issues.push(...componentIssues);
125
+ }
126
+ // Validate SCSS file for class naming
127
+ if (component.paths?.styles) {
128
+ const stylesPath = resolve(this.config.rootDir, component.paths.styles);
129
+ const styleIssues = await this.namingValidator.validateFile(stylesPath);
130
+ issues.push(...styleIssues);
131
+ }
132
+ // Score based on issue count
133
+ // Assume ~5 class names per component
134
+ const estimatedClasses = 5;
135
+ const violationRate = issues.length / Math.max(estimatedClasses, 1);
136
+ const score = Math.max(0, Math.round(100 - violationRate * 100));
137
+ return {
138
+ category: 'naming',
139
+ score,
140
+ issues,
141
+ };
142
+ }
143
+ /**
144
+ * Score documentation completeness
145
+ */
146
+ scoreDocumentationHealth(component) {
147
+ const issues = [];
148
+ let docScore = 100;
149
+ // Check for intent
150
+ if (!component.intent || component.intent.length < 10) {
151
+ docScore -= 15;
152
+ issues.push({
153
+ id: `doc-missing-intent-${component.tagName}`,
154
+ category: 'documentation',
155
+ severity: 'warning',
156
+ message: `Component "${component.tagName}" missing or minimal intent description`,
157
+ file: component.paths?.component || 'unknown',
158
+ autoFixable: true,
159
+ suggestion: 'Add a clear intent: "For [purpose], allowing users to [action]"',
160
+ });
161
+ }
162
+ // Check for slot descriptions
163
+ if (component.slots && component.slots.length > 0) {
164
+ const undocumentedSlots = component.slots.filter((slot) => !slot.description || slot.description.length < 5);
165
+ if (undocumentedSlots.length > 0) {
166
+ docScore -= undocumentedSlots.length * 5;
167
+ issues.push({
168
+ id: `doc-undocumented-slots-${component.tagName}`,
169
+ category: 'documentation',
170
+ severity: 'info',
171
+ message: `Component "${component.tagName}" has ${undocumentedSlots.length} undocumented slot(s)`,
172
+ file: component.paths?.stories || 'unknown',
173
+ autoFixable: true,
174
+ });
175
+ }
176
+ }
177
+ // Check for property descriptions
178
+ const undocumentedProps = component.properties?.filter((p) => !p.description || p.description.length < 5) || [];
179
+ if (undocumentedProps.length > 0) {
180
+ docScore -= Math.min(undocumentedProps.length * 3, 20);
181
+ issues.push({
182
+ id: `doc-undocumented-props-${component.tagName}`,
183
+ category: 'documentation',
184
+ severity: 'info',
185
+ message: `Component "${component.tagName}" has ${undocumentedProps.length} undocumented property(ies)`,
186
+ file: component.paths?.component || 'unknown',
187
+ autoFixable: true,
188
+ });
189
+ }
190
+ // Check for guidelines
191
+ if (!component.guidelines || !component.guidelines.use || component.guidelines.use.length === 0) {
192
+ docScore -= 15;
193
+ issues.push({
194
+ id: `doc-missing-guidelines-${component.tagName}`,
195
+ category: 'documentation',
196
+ severity: 'warning',
197
+ message: `Component "${component.tagName}" missing usage guidelines`,
198
+ file: component.paths?.stories || 'unknown',
199
+ autoFixable: true,
200
+ });
201
+ }
202
+ return {
203
+ category: 'documentation',
204
+ score: Math.max(0, docScore),
205
+ issues,
206
+ };
207
+ }
208
+ /**
209
+ * Score metadata coverage
210
+ */
211
+ scoreCoverageHealth(component) {
212
+ const issues = [];
213
+ let coverageScore = 100;
214
+ // Check required metadata
215
+ const requiredFields = ['tagName', 'displayName', 'cssClassName', 'intent', 'baseClass'];
216
+ for (const field of requiredFields) {
217
+ if (!component[field]) {
218
+ coverageScore -= 10;
219
+ issues.push({
220
+ id: `coverage-missing-${field}-${component.tagName}`,
221
+ category: 'coverage',
222
+ severity: 'error',
223
+ message: `Component "${component.tagName}" missing required field: ${field}`,
224
+ file: component.paths?.component || 'unknown',
225
+ autoFixable: true,
226
+ });
227
+ }
228
+ }
229
+ // Check for test coverage
230
+ if (!component.paths?.test) {
231
+ coverageScore -= 15;
232
+ issues.push({
233
+ id: `coverage-no-test-${component.tagName}`,
234
+ category: 'coverage',
235
+ severity: 'warning',
236
+ message: `Component "${component.tagName}" has no test file`,
237
+ file: component.paths?.component || 'unknown',
238
+ autoFixable: false,
239
+ });
240
+ }
241
+ // Check for story coverage
242
+ if (!component.paths?.stories) {
243
+ coverageScore -= 10;
244
+ issues.push({
245
+ id: `coverage-no-stories-${component.tagName}`,
246
+ category: 'coverage',
247
+ severity: 'warning',
248
+ message: `Component "${component.tagName}" has no Storybook stories`,
249
+ file: component.paths?.component || 'unknown',
250
+ autoFixable: false,
251
+ });
252
+ }
253
+ return {
254
+ category: 'coverage',
255
+ score: Math.max(0, coverageScore),
256
+ issues,
257
+ };
258
+ }
259
+ /**
260
+ * Score accessibility features
261
+ */
262
+ scoreAccessibilityHealth(component) {
263
+ const issues = [];
264
+ let a11yScore = 100;
265
+ // Check for ARIA properties
266
+ const hasAriaProps = component.properties?.some((p) => p.name.toLowerCase().includes('aria') || p.name.toLowerCase().includes('role'));
267
+ if (!hasAriaProps && component.baseClass === 'EdFormElement') {
268
+ a11yScore -= 20;
269
+ issues.push({
270
+ id: `a11y-missing-aria-${component.tagName}`,
271
+ category: 'accessibility',
272
+ severity: 'warning',
273
+ message: `Form component "${component.tagName}" should have ARIA properties (aria-label, aria-describedby, etc.)`,
274
+ file: component.paths?.component || 'unknown',
275
+ autoFixable: true,
276
+ });
277
+ }
278
+ // Check for accessibility guidelines
279
+ if (!component.guidelines?.accessibility || component.guidelines.accessibility.length === 0) {
280
+ a11yScore -= 15;
281
+ issues.push({
282
+ id: `a11y-missing-guidelines-${component.tagName}`,
283
+ category: 'accessibility',
284
+ severity: 'warning',
285
+ message: `Component "${component.tagName}" missing accessibility guidelines`,
286
+ file: component.paths?.stories || 'unknown',
287
+ autoFixable: true,
288
+ });
289
+ }
290
+ // Check for keyboard handling documentation
291
+ const hasKeyboardDocs = component.guidelines?.accessibility?.some((g) => g.toLowerCase().includes('keyboard') || g.toLowerCase().includes('focus'));
292
+ if (!hasKeyboardDocs && component.baseClass === 'EdFormElement') {
293
+ a11yScore -= 10;
294
+ issues.push({
295
+ id: `a11y-no-keyboard-docs-${component.tagName}`,
296
+ category: 'accessibility',
297
+ severity: 'info',
298
+ message: `Form component "${component.tagName}" should document keyboard interactions`,
299
+ file: component.paths?.stories || 'unknown',
300
+ autoFixable: true,
301
+ });
302
+ }
303
+ return {
304
+ category: 'accessibility',
305
+ score: Math.max(0, a11yScore),
306
+ issues,
307
+ };
308
+ }
309
+ /**
310
+ * Score API consistency with similar components
311
+ */
312
+ async scoreConsistencyHealth(component) {
313
+ const issues = [];
314
+ let consistencyScore = 100;
315
+ // Find similar components (same atomic level, same category)
316
+ const allComponents = this.knowledgeGraph.getComponentEntries?.() || [];
317
+ const similarComponents = allComponents.filter((c) => c.atomicLevel === component.atomicLevel &&
318
+ c.tagName !== component.tagName &&
319
+ c.package === component.package);
320
+ if (similarComponents.length === 0) {
321
+ // Not enough similar components to compare
322
+ return {
323
+ category: 'consistency',
324
+ score: consistencyScore,
325
+ issues,
326
+ };
327
+ }
328
+ // Check API consistency
329
+ const refComponent = similarComponents[0];
330
+ // Check property naming consistency
331
+ const hasVariantProp = component.properties?.some((p) => p.name === 'variant');
332
+ const refHasVariant = refComponent.properties?.some((p) => p.name === 'variant');
333
+ if (hasVariantProp !== refHasVariant && similarComponents.length > 2) {
334
+ consistencyScore -= 5;
335
+ issues.push({
336
+ id: `consistency-variant-naming-${component.tagName}`,
337
+ category: 'consistency',
338
+ severity: 'info',
339
+ message: `Component "${component.tagName}" naming differs from similar components regarding "variant" property`,
340
+ file: component.paths?.component || 'unknown',
341
+ autoFixable: false,
342
+ });
343
+ }
344
+ // Check size property naming
345
+ const hasSizeProp = component.properties?.some((p) => p.name === 'size');
346
+ const refHasSize = refComponent.properties?.some((p) => p.name === 'size');
347
+ if (hasSizeProp !== refHasSize && similarComponents.length > 2) {
348
+ consistencyScore -= 5;
349
+ issues.push({
350
+ id: `consistency-size-naming-${component.tagName}`,
351
+ category: 'consistency',
352
+ severity: 'info',
353
+ message: `Component "${component.tagName}" naming differs from similar components regarding "size" property`,
354
+ file: component.paths?.component || 'unknown',
355
+ autoFixable: false,
356
+ });
357
+ }
358
+ return {
359
+ category: 'consistency',
360
+ score: Math.max(0, consistencyScore),
361
+ issues,
362
+ };
363
+ }
364
+ /**
365
+ * Aggregate scores by category
366
+ */
367
+ aggregateScores(allScores) {
368
+ const byCategory = new Map();
369
+ for (const score of allScores) {
370
+ if (!byCategory.has(score.category)) {
371
+ byCategory.set(score.category, []);
372
+ }
373
+ byCategory.get(score.category).push(score);
374
+ }
375
+ const aggregated = [];
376
+ for (const [category, scores] of byCategory.entries()) {
377
+ const avgScore = Math.round(scores.reduce((sum, s) => sum + s.score, 0) / scores.length);
378
+ const allIssues = scores.flatMap((s) => s.issues);
379
+ aggregated.push({
380
+ category,
381
+ score: avgScore,
382
+ issues: allIssues,
383
+ });
384
+ }
385
+ return aggregated;
386
+ }
387
+ /**
388
+ * Calculate weighted overall score
389
+ */
390
+ calculateWeightedScore(categoryScores) {
391
+ let weightedSum = 0;
392
+ let totalWeight = 0;
393
+ for (const category of Object.keys(this.config.healthWeights)) {
394
+ const weight = this.config.healthWeights[category];
395
+ const categoryScore = categoryScores.find((s) => s.category === category);
396
+ const score = categoryScore?.score || 0;
397
+ weightedSum += score * weight;
398
+ totalWeight += weight;
399
+ }
400
+ return Math.round(weightedSum / (totalWeight || 1));
401
+ }
402
+ /**
403
+ * Count issues by severity
404
+ */
405
+ countIssuesBySeverity(allScores) {
406
+ const counts = {
407
+ info: 0,
408
+ warning: 0,
409
+ error: 0,
410
+ critical: 0,
411
+ };
412
+ for (const score of allScores) {
413
+ for (const issue of score.issues) {
414
+ counts[issue.severity]++;
415
+ }
416
+ }
417
+ return counts;
418
+ }
419
+ }
420
+ //# sourceMappingURL=health-scorer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health-scorer.js","sourceRoot":"","sources":["../../src/analyze/health-scorer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Analysis Layer
3
+ *
4
+ * Exports all analyzer classes for detecting health issues and drift in the Eddie Design System.
5
+ */
6
+ export { TokenValidator } from './token-validator.js';
7
+ export { NamingValidator } from './naming-validator.js';
8
+ export { SlotContractValidator } from './slot-contract-validator.js';
9
+ export { HealthScorer } from './health-scorer.js';
10
+ export { DriftDetector } from './drift-detector.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyze/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Analysis Layer
3
+ *
4
+ * Exports all analyzer classes for detecting health issues and drift in the Eddie Design System.
5
+ */
6
+ export { TokenValidator } from './token-validator.js';
7
+ export { NamingValidator } from './naming-validator.js';
8
+ export { SlotContractValidator } from './slot-contract-validator.js';
9
+ export { HealthScorer } from './health-scorer.js';
10
+ export { DriftDetector } from './drift-detector.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analyze/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Naming Validator
3
+ *
4
+ * Validates BEM/BEMIT naming conventions in Eddie components:
5
+ * - CSS class prefixes (ed-c-, ed-l-, ed-u-, ed-r-, ed-p-, etc.)
6
+ * - BEM structure (block__element--modifier)
7
+ * - Detects unclassed HTML elements in Lit component templates
8
+ *
9
+ * Understands Lit-specific patterns:
10
+ * - Only scans inside html`...` tagged template literals
11
+ * - Recognizes dynamic class bindings (class="${expr}")
12
+ * - Skips JSDoc/comment blocks
13
+ * - Skips .stories.ts files for unclassed element checks (slot content is fine)
14
+ */
15
+ import { HealthIssue } from '../types.js';
16
+ export declare class NamingValidator {
17
+ /**
18
+ * Class prefix patterns
19
+ */
20
+ private readonly validPrefixes;
21
+ /**
22
+ * HTML elements that can exist without a class
23
+ * - SVG internals, slots, templates, scripts, style tags
24
+ * - Custom elements (contain a hyphen) always skip
25
+ */
26
+ private readonly unclassedAllowed;
27
+ /**
28
+ * Validate a single component file
29
+ */
30
+ validateFile(filePath: string): Promise<HealthIssue[]>;
31
+ /**
32
+ * Validate all component files in a directory
33
+ */
34
+ validateDirectory(dirPath: string): Promise<HealthIssue[]>;
35
+ /**
36
+ * Validate a single CSS class name string
37
+ */
38
+ validateClassName(className: string): HealthIssue | null;
39
+ /**
40
+ * Validate HTML elements inside Lit templates.
41
+ *
42
+ * Key behaviors:
43
+ * - Extracts only the content inside html`...` tagged template literals
44
+ * - Strips JSDoc/block comments before scanning
45
+ * - Recognizes dynamic class bindings: class="${...}" counts as having a class
46
+ * - Skips unclassed-element checks in .stories.ts (slot content is fine)
47
+ * - Skips self-closing void elements and custom elements (contain hyphen)
48
+ */
49
+ private validateTemplate;
50
+ /**
51
+ * Strip block comments (/* ... * /) including JSDoc (/** ... * /)
52
+ * Preserves line count by replacing comment content with blank lines.
53
+ */
54
+ private stripBlockComments;
55
+ /**
56
+ * Extract content from html`...` tagged template literals.
57
+ * Returns regions with their content and the line offset where they start.
58
+ */
59
+ private extractLitTemplates;
60
+ /**
61
+ * Simplified check: does a template close on this line?
62
+ * Looks for a ` that's not preceded by ${ context.
63
+ */
64
+ private templateClosesOnLine;
65
+ /**
66
+ * Check for HTML elements without classes in template content.
67
+ *
68
+ * Understands:
69
+ * - class="${expr}" — dynamic class, counts as having a class
70
+ * - class="literal" — static class
71
+ * - styleModifier="..." — Eddie's pattern for passing classes to children
72
+ * - Tags with a hyphen are custom elements (always skip)
73
+ */
74
+ private checkUnclassedElements;
75
+ /**
76
+ * Check static class name values in templates for Eddie naming compliance.
77
+ * Only validates literal class strings, not dynamic ${} expressions.
78
+ */
79
+ private checkStaticClassNames;
80
+ /**
81
+ * Validate class names in SCSS file
82
+ */
83
+ private validateStyleFile;
84
+ /**
85
+ * Validate a single class name string against Eddie's BEM/BEMIT conventions
86
+ */
87
+ private classNameValidation;
88
+ /**
89
+ * Validate BEM structure (block__element--modifier)
90
+ * Allows: block, block__element, block--modifier, block__element--modifier
91
+ * Parts can contain hyphens (single) for multi-word names.
92
+ */
93
+ private validateBemStructure;
94
+ /**
95
+ * Suggest a corrected class name
96
+ */
97
+ private suggestClassName;
98
+ }
99
+ //# sourceMappingURL=naming-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naming-validator.d.ts","sourceRoot":"","sources":["../../src/analyze/naming-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAS1C,qBAAa,eAAe;IAC1B;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAQ5B;IAEF;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAQ9B;IAEH;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IA8B5D;;OAEG;IACG,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAmBhE;;OAEG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAuBxD;;;;;;;;;OASG;IACH,OAAO,CAAC,gBAAgB;IA4BxB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAQ1B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IA2D3B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAgB5B;;;;;;;;OAQG;IACH,OAAO,CAAC,sBAAsB;IAyD9B;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAgD7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAgDzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA4C3B;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAK5B;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAMzB"}