@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.
- package/README.md +109 -0
- package/dist/analyze/drift-detector.d.ts +30 -0
- package/dist/analyze/drift-detector.d.ts.map +1 -0
- package/dist/analyze/drift-detector.js +310 -0
- package/dist/analyze/drift-detector.js.map +1 -0
- package/dist/analyze/health-scorer.d.ts +71 -0
- package/dist/analyze/health-scorer.d.ts.map +1 -0
- package/dist/analyze/health-scorer.js +420 -0
- package/dist/analyze/health-scorer.js.map +1 -0
- package/dist/analyze/index.d.ts +11 -0
- package/dist/analyze/index.d.ts.map +1 -0
- package/dist/analyze/index.js +11 -0
- package/dist/analyze/index.js.map +1 -0
- package/dist/analyze/naming-validator.d.ts +99 -0
- package/dist/analyze/naming-validator.d.ts.map +1 -0
- package/dist/analyze/naming-validator.js +430 -0
- package/dist/analyze/naming-validator.js.map +1 -0
- package/dist/analyze/slot-contract-validator.d.ts +68 -0
- package/dist/analyze/slot-contract-validator.d.ts.map +1 -0
- package/dist/analyze/slot-contract-validator.js +232 -0
- package/dist/analyze/slot-contract-validator.js.map +1 -0
- package/dist/analyze/token-validator.d.ts +62 -0
- package/dist/analyze/token-validator.d.ts.map +1 -0
- package/dist/analyze/token-validator.js +348 -0
- package/dist/analyze/token-validator.js.map +1 -0
- package/dist/cli/brain.d.ts +12 -0
- package/dist/cli/brain.d.ts.map +1 -0
- package/dist/cli/brain.js +641 -0
- package/dist/cli/brain.js.map +1 -0
- package/dist/cli/formatters/json.d.ts +15 -0
- package/dist/cli/formatters/json.d.ts.map +1 -0
- package/dist/cli/formatters/json.js +18 -0
- package/dist/cli/formatters/json.js.map +1 -0
- package/dist/cli/formatters/terminal.d.ts +19 -0
- package/dist/cli/formatters/terminal.d.ts.map +1 -0
- package/dist/cli/formatters/terminal.js +125 -0
- package/dist/cli/formatters/terminal.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/data/governance-rules.json +94 -0
- package/dist/governance/audit-log.d.ts +17 -0
- package/dist/governance/audit-log.d.ts.map +1 -0
- package/dist/governance/audit-log.js +44 -0
- package/dist/governance/audit-log.js.map +1 -0
- package/dist/governance/index.d.ts +8 -0
- package/dist/governance/index.d.ts.map +1 -0
- package/dist/governance/index.js +8 -0
- package/dist/governance/index.js.map +1 -0
- package/dist/governance/permissions.d.ts +26 -0
- package/dist/governance/permissions.d.ts.map +1 -0
- package/dist/governance/permissions.js +75 -0
- package/dist/governance/permissions.js.map +1 -0
- package/dist/governance/rules-engine.d.ts +24 -0
- package/dist/governance/rules-engine.d.ts.map +1 -0
- package/dist/governance/rules-engine.js +111 -0
- package/dist/governance/rules-engine.js.map +1 -0
- package/dist/governance/trust-manager.d.ts +34 -0
- package/dist/governance/trust-manager.d.ts.map +1 -0
- package/dist/governance/trust-manager.js +148 -0
- package/dist/governance/trust-manager.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/knowledge-graph/component-index.d.ts +320 -0
- package/dist/knowledge-graph/component-index.d.ts.map +1 -0
- package/dist/knowledge-graph/component-index.js +1033 -0
- package/dist/knowledge-graph/component-index.js.map +1 -0
- package/dist/knowledge-graph/index.d.ts +134 -0
- package/dist/knowledge-graph/index.d.ts.map +1 -0
- package/dist/knowledge-graph/index.js +249 -0
- package/dist/knowledge-graph/index.js.map +1 -0
- package/dist/knowledge-graph/learning-history.d.ts +77 -0
- package/dist/knowledge-graph/learning-history.d.ts.map +1 -0
- package/dist/knowledge-graph/learning-history.js +187 -0
- package/dist/knowledge-graph/learning-history.js.map +1 -0
- package/dist/knowledge-graph/relationship-map.d.ts +55 -0
- package/dist/knowledge-graph/relationship-map.d.ts.map +1 -0
- package/dist/knowledge-graph/relationship-map.js +238 -0
- package/dist/knowledge-graph/relationship-map.js.map +1 -0
- package/dist/knowledge-graph/token-taxonomy.d.ts +127 -0
- package/dist/knowledge-graph/token-taxonomy.d.ts.map +1 -0
- package/dist/knowledge-graph/token-taxonomy.js +357 -0
- package/dist/knowledge-graph/token-taxonomy.js.map +1 -0
- package/dist/loop/fix-agent.d.ts +55 -0
- package/dist/loop/fix-agent.d.ts.map +1 -0
- package/dist/loop/fix-agent.js +344 -0
- package/dist/loop/fix-agent.js.map +1 -0
- package/dist/loop/index.d.ts +8 -0
- package/dist/loop/index.d.ts.map +1 -0
- package/dist/loop/index.js +8 -0
- package/dist/loop/index.js.map +1 -0
- package/dist/loop/issue-fetcher.d.ts +51 -0
- package/dist/loop/issue-fetcher.d.ts.map +1 -0
- package/dist/loop/issue-fetcher.js +188 -0
- package/dist/loop/issue-fetcher.js.map +1 -0
- package/dist/loop/observer.d.ts +42 -0
- package/dist/loop/observer.d.ts.map +1 -0
- package/dist/loop/observer.js +220 -0
- package/dist/loop/observer.js.map +1 -0
- package/dist/loop/pacer.d.ts +44 -0
- package/dist/loop/pacer.d.ts.map +1 -0
- package/dist/loop/pacer.js +90 -0
- package/dist/loop/pacer.js.map +1 -0
- package/dist/loop/reporter.d.ts +9 -0
- package/dist/loop/reporter.d.ts.map +1 -0
- package/dist/loop/reporter.js +119 -0
- package/dist/loop/reporter.js.map +1 -0
- package/dist/loop/runner.d.ts +57 -0
- package/dist/loop/runner.d.ts.map +1 -0
- package/dist/loop/runner.js +390 -0
- package/dist/loop/runner.js.map +1 -0
- package/dist/loop/types.d.ts +151 -0
- package/dist/loop/types.d.ts.map +1 -0
- package/dist/loop/types.js +22 -0
- package/dist/loop/types.js.map +1 -0
- package/dist/mcp/index.d.ts +7 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +7 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +12 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +618 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/pipeline/agent-runner.d.ts +34 -0
- package/dist/pipeline/agent-runner.d.ts.map +1 -0
- package/dist/pipeline/agent-runner.js +323 -0
- package/dist/pipeline/agent-runner.js.map +1 -0
- package/dist/pipeline/agents/accessibility-auditor.d.ts +10 -0
- package/dist/pipeline/agents/accessibility-auditor.d.ts.map +1 -0
- package/dist/pipeline/agents/accessibility-auditor.js +69 -0
- package/dist/pipeline/agents/accessibility-auditor.js.map +1 -0
- package/dist/pipeline/agents/code-reviewer.d.ts +10 -0
- package/dist/pipeline/agents/code-reviewer.d.ts.map +1 -0
- package/dist/pipeline/agents/code-reviewer.js +75 -0
- package/dist/pipeline/agents/code-reviewer.js.map +1 -0
- package/dist/pipeline/agents/code-writer.d.ts +10 -0
- package/dist/pipeline/agents/code-writer.d.ts.map +1 -0
- package/dist/pipeline/agents/code-writer.js +103 -0
- package/dist/pipeline/agents/code-writer.js.map +1 -0
- package/dist/pipeline/agents/component-architect.d.ts +13 -0
- package/dist/pipeline/agents/component-architect.d.ts.map +1 -0
- package/dist/pipeline/agents/component-architect.js +81 -0
- package/dist/pipeline/agents/component-architect.js.map +1 -0
- package/dist/pipeline/agents/index.d.ts +16 -0
- package/dist/pipeline/agents/index.d.ts.map +1 -0
- package/dist/pipeline/agents/index.js +24 -0
- package/dist/pipeline/agents/index.js.map +1 -0
- package/dist/pipeline/agents/library-researcher.d.ts +12 -0
- package/dist/pipeline/agents/library-researcher.d.ts.map +1 -0
- package/dist/pipeline/agents/library-researcher.js +85 -0
- package/dist/pipeline/agents/library-researcher.js.map +1 -0
- package/dist/pipeline/agents/quality-gate.d.ts +9 -0
- package/dist/pipeline/agents/quality-gate.d.ts.map +1 -0
- package/dist/pipeline/agents/quality-gate.js +71 -0
- package/dist/pipeline/agents/quality-gate.js.map +1 -0
- package/dist/pipeline/agents/spec-analyst.d.ts +10 -0
- package/dist/pipeline/agents/spec-analyst.d.ts.map +1 -0
- package/dist/pipeline/agents/spec-analyst.js +72 -0
- package/dist/pipeline/agents/spec-analyst.js.map +1 -0
- package/dist/pipeline/agents/story-author.d.ts +9 -0
- package/dist/pipeline/agents/story-author.d.ts.map +1 -0
- package/dist/pipeline/agents/story-author.js +65 -0
- package/dist/pipeline/agents/story-author.js.map +1 -0
- package/dist/pipeline/artifact-store.d.ts +27 -0
- package/dist/pipeline/artifact-store.d.ts.map +1 -0
- package/dist/pipeline/artifact-store.js +77 -0
- package/dist/pipeline/artifact-store.js.map +1 -0
- package/dist/pipeline/conversational-gate.d.ts +26 -0
- package/dist/pipeline/conversational-gate.d.ts.map +1 -0
- package/dist/pipeline/conversational-gate.js +122 -0
- package/dist/pipeline/conversational-gate.js.map +1 -0
- package/dist/pipeline/index.d.ts +14 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +17 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/iteration-tracker.d.ts +29 -0
- package/dist/pipeline/iteration-tracker.d.ts.map +1 -0
- package/dist/pipeline/iteration-tracker.js +102 -0
- package/dist/pipeline/iteration-tracker.js.map +1 -0
- package/dist/pipeline/learning-bridge.d.ts +37 -0
- package/dist/pipeline/learning-bridge.d.ts.map +1 -0
- package/dist/pipeline/learning-bridge.js +118 -0
- package/dist/pipeline/learning-bridge.js.map +1 -0
- package/dist/pipeline/orchestrator.d.ts +45 -0
- package/dist/pipeline/orchestrator.d.ts.map +1 -0
- package/dist/pipeline/orchestrator.js +473 -0
- package/dist/pipeline/orchestrator.js.map +1 -0
- package/dist/pipeline/templates/architecture.d.ts +27 -0
- package/dist/pipeline/templates/architecture.d.ts.map +1 -0
- package/dist/pipeline/templates/architecture.js +111 -0
- package/dist/pipeline/templates/architecture.js.map +1 -0
- package/dist/pipeline/templates/brief.d.ts +22 -0
- package/dist/pipeline/templates/brief.d.ts.map +1 -0
- package/dist/pipeline/templates/brief.js +121 -0
- package/dist/pipeline/templates/brief.js.map +1 -0
- package/dist/pipeline/templates/component-rules.d.ts +25 -0
- package/dist/pipeline/templates/component-rules.d.ts.map +1 -0
- package/dist/pipeline/templates/component-rules.js +93 -0
- package/dist/pipeline/templates/component-rules.js.map +1 -0
- package/dist/pipeline/templates/index.d.ts +9 -0
- package/dist/pipeline/templates/index.d.ts.map +1 -0
- package/dist/pipeline/templates/index.js +7 -0
- package/dist/pipeline/templates/index.js.map +1 -0
- package/dist/pipeline/tool-handler.d.ts +25 -0
- package/dist/pipeline/tool-handler.d.ts.map +1 -0
- package/dist/pipeline/tool-handler.js +392 -0
- package/dist/pipeline/tool-handler.js.map +1 -0
- package/dist/pipeline/types.d.ts +146 -0
- package/dist/pipeline/types.d.ts.map +1 -0
- package/dist/pipeline/types.js +27 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/plan/action-types.d.ts +31 -0
- package/dist/plan/action-types.d.ts.map +1 -0
- package/dist/plan/action-types.js +83 -0
- package/dist/plan/action-types.js.map +1 -0
- package/dist/plan/decision-engine.d.ts +57 -0
- package/dist/plan/decision-engine.d.ts.map +1 -0
- package/dist/plan/decision-engine.js +162 -0
- package/dist/plan/decision-engine.js.map +1 -0
- package/dist/plan/index.d.ts +6 -0
- package/dist/plan/index.d.ts.map +1 -0
- package/dist/plan/index.js +6 -0
- package/dist/plan/index.js.map +1 -0
- package/dist/types.d.ts +351 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +26 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/anthropic.d.ts +15 -0
- package/dist/utils/anthropic.d.ts.map +1 -0
- package/dist/utils/anthropic.js +40 -0
- package/dist/utils/anthropic.js.map +1 -0
- package/dist/utils/id.d.ts +8 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +14 -0
- package/dist/utils/id.js.map +1 -0
- package/package.json +80 -0
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Eddie Brain
|
|
2
|
+
|
|
3
|
+
The agentic intelligence layer for the Eddie Design System. Exposes an MCP server so AI coding tools (Claude Code, Cursor, etc.) can query component metadata, validate token usage, check design system health, and compose canonical UI patterns.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
- **`eddie_get_component`** — Full component docs: props, slots, events, guidelines
|
|
8
|
+
- **`eddie_search`** — Search across components, tokens, and recipes
|
|
9
|
+
- **`eddie_get_token`** — Token value, tier, intent, and which components use it
|
|
10
|
+
- **`eddie_compose_recipe`** — Canonical composition patterns for a given UI intent (e.g. "login form", "destructive confirmation dialog")
|
|
11
|
+
- **`eddie_check_health`** — Health scores across tokens, naming, docs, coverage, accessibility, and consistency
|
|
12
|
+
- **`eddie_validate_file`** — Validate a file against Eddie conventions
|
|
13
|
+
- **`eddie_suggest_fix`** — Suggest fixes for detected violations
|
|
14
|
+
- **`eddie_get_relationships`** — Component composition relationships
|
|
15
|
+
|
|
16
|
+
## Setup
|
|
17
|
+
|
|
18
|
+
### Prerequisites
|
|
19
|
+
|
|
20
|
+
- Node.js (same version as the monorepo)
|
|
21
|
+
- The `eddie-design-system` repo cloned locally
|
|
22
|
+
|
|
23
|
+
### 1. Install dependencies
|
|
24
|
+
|
|
25
|
+
From the repo root:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 2. Build the package
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
cd packages/eddie-brain
|
|
35
|
+
npm run build
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This runs `tsc` and copies the static knowledge base files (`components.json`, `tokens.json`, etc.) into `dist/`.
|
|
39
|
+
|
|
40
|
+
Verify the output:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
ls dist/mcp/server.js
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 3. MCP registration is automatic
|
|
47
|
+
|
|
48
|
+
The repo's `.mcp.json` at the root handles registration for Claude Code:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"mcpServers": {
|
|
53
|
+
"eddie-brain": {
|
|
54
|
+
"command": "node",
|
|
55
|
+
"args": ["packages/eddie-brain/dist/mcp/server.js"],
|
|
56
|
+
"env": {
|
|
57
|
+
"EDDIE_ROOT": "."
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Claude Code reads `.mcp.json` on startup when your working directory is inside `eddie-design-system`. The `EDDIE_ROOT: "."` env var tells the server where to find the design system files. No additional configuration needed.
|
|
65
|
+
|
|
66
|
+
### Rebuilding After Changes
|
|
67
|
+
|
|
68
|
+
Whenever `src/` or `data/` files change, rebuild and restart your editor session:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cd packages/eddie-brain
|
|
72
|
+
npm run build
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## CLI
|
|
76
|
+
|
|
77
|
+
The package also ships a standalone CLI:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Health report for the whole system
|
|
81
|
+
node packages/eddie-brain/dist/cli/brain.js health
|
|
82
|
+
|
|
83
|
+
# Full scan (monitor + analyze)
|
|
84
|
+
node packages/eddie-brain/dist/cli/brain.js scan
|
|
85
|
+
node packages/eddie-brain/dist/cli/brain.js scan --component ed-button
|
|
86
|
+
|
|
87
|
+
# Validate tokens and naming in source files
|
|
88
|
+
node packages/eddie-brain/dist/cli/brain.js validate src/
|
|
89
|
+
node packages/eddie-brain/dist/cli/brain.js validate --fix
|
|
90
|
+
|
|
91
|
+
# Compose a pattern from components
|
|
92
|
+
node packages/eddie-brain/dist/cli/brain.js compose "destructive confirmation dialog"
|
|
93
|
+
|
|
94
|
+
# View audit log
|
|
95
|
+
node packages/eddie-brain/dist/cli/brain.js audit
|
|
96
|
+
node packages/eddie-brain/dist/cli/brain.js audit --since 2026-03-01
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Development
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm run dev # TypeScript watch mode
|
|
103
|
+
npm test # Run tests
|
|
104
|
+
npm run health # Quick health check
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Architecture
|
|
108
|
+
|
|
109
|
+
See [SPEC.md](./SPEC.md) for the full technical specification, including the knowledge graph schema, trust level model, health scoring categories, and implementation phases.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drift Detector
|
|
3
|
+
*
|
|
4
|
+
* Detects deviations from the knowledge graph:
|
|
5
|
+
* - Token drift: new/changed/removed tokens
|
|
6
|
+
* - Recipe drift: composition recipe inconsistencies
|
|
7
|
+
* - Naming drift: naming convention violations
|
|
8
|
+
*/
|
|
9
|
+
import { Signal, CompositionRecipe } from '../types.js';
|
|
10
|
+
import type { TokenTaxonomy } from '../knowledge-graph/token-taxonomy.js';
|
|
11
|
+
import type { ComponentIndex } from '../knowledge-graph/component-index.js';
|
|
12
|
+
export declare class DriftDetector {
|
|
13
|
+
/**
|
|
14
|
+
* Detect new, changed, or removed tokens in the codebase
|
|
15
|
+
*/
|
|
16
|
+
detectTokenDrift(rootDir: string, taxonomy: TokenTaxonomy): Promise<Signal[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Detect deviations from canonical composition recipes
|
|
19
|
+
*/
|
|
20
|
+
detectRecipeDrift(rootDir: string, recipes: CompositionRecipe[]): Promise<Signal[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Detect naming convention violations
|
|
23
|
+
*/
|
|
24
|
+
detectNamingDrift(rootDir: string, componentIndex: ComponentIndex): Promise<Signal[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Detect if a component deviates from an expected recipe
|
|
27
|
+
*/
|
|
28
|
+
private detectRecipeInComponent;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=drift-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift-detector.d.ts","sourceRoot":"","sources":["../../src/analyze/drift-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,EAAE,MAAM,EAAgC,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAwC5E,qBAAa,aAAa;IACxB;;OAEG;IACG,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAqHnF;;OAEG;IACG,iBAAiB,CACrB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,iBAAiB,EAAE,GAC3B,OAAO,CAAC,MAAM,EAAE,CAAC;IA+BpB;;OAEG;IACG,iBAAiB,CACrB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,cAAc,GAC7B,OAAO,CAAC,MAAM,EAAE,CAAC;IAmIpB;;OAEG;IACH,OAAO,CAAC,uBAAuB;CAoDhC"}
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drift Detector
|
|
3
|
+
*
|
|
4
|
+
* Detects deviations from the knowledge graph:
|
|
5
|
+
* - Token drift: new/changed/removed tokens
|
|
6
|
+
* - Recipe drift: composition recipe inconsistencies
|
|
7
|
+
* - Naming drift: naming convention violations
|
|
8
|
+
*/
|
|
9
|
+
import { readFile } from 'fs/promises';
|
|
10
|
+
import glob from 'fast-glob';
|
|
11
|
+
export class DriftDetector {
|
|
12
|
+
/**
|
|
13
|
+
* Detect new, changed, or removed tokens in the codebase
|
|
14
|
+
*/
|
|
15
|
+
async detectTokenDrift(rootDir, taxonomy) {
|
|
16
|
+
const signals = [];
|
|
17
|
+
// Find all SCSS files
|
|
18
|
+
const scssFiles = await glob('**/*.scss', {
|
|
19
|
+
cwd: rootDir,
|
|
20
|
+
absolute: true,
|
|
21
|
+
ignore: ['**/node_modules/**'],
|
|
22
|
+
});
|
|
23
|
+
const usedTokens = new Set();
|
|
24
|
+
const tokenUsageMap = new Map();
|
|
25
|
+
// Scan files for token usage
|
|
26
|
+
for (const file of scssFiles) {
|
|
27
|
+
try {
|
|
28
|
+
const content = await readFile(file, 'utf-8');
|
|
29
|
+
const tokenMatches = content.match(/var\((--ed-[^)]+)\)/g) || [];
|
|
30
|
+
for (const match of tokenMatches) {
|
|
31
|
+
const tokenName = match.replace(/var\(|\)/g, '');
|
|
32
|
+
usedTokens.add(tokenName);
|
|
33
|
+
if (!tokenUsageMap.has(tokenName)) {
|
|
34
|
+
tokenUsageMap.set(tokenName, []);
|
|
35
|
+
}
|
|
36
|
+
tokenUsageMap.get(tokenName).push(file);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
// Skip files that can't be read
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Get tokens from taxonomy
|
|
44
|
+
const allTokensArray = taxonomy.getAll?.() || [];
|
|
45
|
+
const knownTokens = new Set(allTokensArray.map((t) => t.name) || []);
|
|
46
|
+
// Detect orphaned tokens (used but not in taxonomy)
|
|
47
|
+
for (const token of usedTokens) {
|
|
48
|
+
if (!knownTokens.has(token)) {
|
|
49
|
+
signals.push({
|
|
50
|
+
id: `drift-token-orphaned-${token}`,
|
|
51
|
+
timestamp: new Date().toISOString(),
|
|
52
|
+
source: 'usage',
|
|
53
|
+
severity: 'warning',
|
|
54
|
+
type: 'token-inconsistent',
|
|
55
|
+
message: `Token "${token}" is used in code but not found in token taxonomy`,
|
|
56
|
+
target: token,
|
|
57
|
+
payload: {
|
|
58
|
+
tokenName: token,
|
|
59
|
+
missingThemes: taxonomy.getThemes?.() || [],
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Detect unused tokens (in taxonomy but not used)
|
|
65
|
+
const allThemes = taxonomy.getThemes?.() || [];
|
|
66
|
+
for (const theme of allThemes) {
|
|
67
|
+
const themeTokens = taxonomy.getByTheme?.(theme) || [];
|
|
68
|
+
for (const token of themeTokens) {
|
|
69
|
+
// Skip internal/private tokens
|
|
70
|
+
if (!token.name || token.name.includes('private')) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (!usedTokens.has(token.name)) {
|
|
74
|
+
signals.push({
|
|
75
|
+
id: `drift-token-unused-${token.name}-${theme}`,
|
|
76
|
+
timestamp: new Date().toISOString(),
|
|
77
|
+
source: 'usage',
|
|
78
|
+
severity: 'info',
|
|
79
|
+
type: 'token-removed',
|
|
80
|
+
message: `Token "${token.name}" is defined in theme "${theme}" but not used anywhere`,
|
|
81
|
+
target: token.name,
|
|
82
|
+
payload: {
|
|
83
|
+
tokenName: token.name,
|
|
84
|
+
theme,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Check for theme coverage gaps
|
|
91
|
+
for (const token of usedTokens) {
|
|
92
|
+
const missingThemes = [];
|
|
93
|
+
for (const theme of allThemes) {
|
|
94
|
+
const themeTokens = taxonomy.getByTheme?.(theme) || [];
|
|
95
|
+
const hasToken = themeTokens.some((t) => t.name === token);
|
|
96
|
+
if (!hasToken) {
|
|
97
|
+
missingThemes.push(theme);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (missingThemes.length > 0) {
|
|
101
|
+
signals.push({
|
|
102
|
+
id: `drift-token-coverage-${token}`,
|
|
103
|
+
timestamp: new Date().toISOString(),
|
|
104
|
+
source: 'usage',
|
|
105
|
+
severity: 'error',
|
|
106
|
+
type: 'token-inconsistent',
|
|
107
|
+
message: `Token "${token}" missing from themes: ${missingThemes.join(', ')}`,
|
|
108
|
+
target: token,
|
|
109
|
+
payload: {
|
|
110
|
+
tokenName: token,
|
|
111
|
+
missingThemes,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return signals;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Detect deviations from canonical composition recipes
|
|
120
|
+
*/
|
|
121
|
+
async detectRecipeDrift(rootDir, recipes) {
|
|
122
|
+
const signals = [];
|
|
123
|
+
// Find all component files that might use these recipes
|
|
124
|
+
const componentFiles = await glob('**/components/**/*.ts', {
|
|
125
|
+
cwd: rootDir,
|
|
126
|
+
absolute: true,
|
|
127
|
+
ignore: ['**/node_modules/**', '**/*.test.ts'],
|
|
128
|
+
});
|
|
129
|
+
for (const file of componentFiles) {
|
|
130
|
+
try {
|
|
131
|
+
const content = await readFile(file, 'utf-8');
|
|
132
|
+
for (const recipe of recipes) {
|
|
133
|
+
// Check if this component file uses this recipe
|
|
134
|
+
const recipeSignals = this.detectRecipeInComponent(file, content, recipe);
|
|
135
|
+
signals.push(...recipeSignals);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
// Skip files that can't be read
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return signals;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Detect naming convention violations
|
|
146
|
+
*/
|
|
147
|
+
async detectNamingDrift(rootDir, componentIndex) {
|
|
148
|
+
const signals = [];
|
|
149
|
+
// Find all SCSS files with class definitions
|
|
150
|
+
const scssFiles = await glob('**/components/**/*.scss', {
|
|
151
|
+
cwd: rootDir,
|
|
152
|
+
absolute: true,
|
|
153
|
+
ignore: ['**/node_modules/**'],
|
|
154
|
+
});
|
|
155
|
+
const validPrefixes = [
|
|
156
|
+
/^ed-c-/, // Component
|
|
157
|
+
/^ed-l-/, // Layout
|
|
158
|
+
/^ed-u-/, // Utility
|
|
159
|
+
/^ed-r-/, // Recipe component
|
|
160
|
+
/^is-/, // State
|
|
161
|
+
/^has-/, // State
|
|
162
|
+
];
|
|
163
|
+
for (const file of scssFiles) {
|
|
164
|
+
try {
|
|
165
|
+
const content = await readFile(file, 'utf-8');
|
|
166
|
+
const lines = content.split('\n');
|
|
167
|
+
lines.forEach((line, lineIndex) => {
|
|
168
|
+
// Skip comments
|
|
169
|
+
if (line.trim().startsWith('//'))
|
|
170
|
+
return;
|
|
171
|
+
// Find class definitions (.className {)
|
|
172
|
+
const classMatches = line.matchAll(/\.([a-zA-Z0-9_-]+)\s*[{&]/g);
|
|
173
|
+
for (const match of classMatches) {
|
|
174
|
+
const className = match[1];
|
|
175
|
+
// Check for valid prefix
|
|
176
|
+
const hasValidPrefix = validPrefixes.some((p) => p.test(className));
|
|
177
|
+
if (!hasValidPrefix && !className.startsWith('_') && className.length > 3) {
|
|
178
|
+
signals.push({
|
|
179
|
+
id: `drift-naming-prefix-${className}-${lineIndex}`,
|
|
180
|
+
timestamp: new Date().toISOString(),
|
|
181
|
+
source: 'git',
|
|
182
|
+
severity: 'warning',
|
|
183
|
+
type: 'prefix-mismatch',
|
|
184
|
+
message: `Class ".${className}" in ${file} uses invalid prefix. Expected: ed-c-, ed-l-, ed-u-, ed-r-, is-, or has-`,
|
|
185
|
+
target: className,
|
|
186
|
+
payload: {
|
|
187
|
+
className,
|
|
188
|
+
expectedPrefix: 'ed-c- or ed-l- or ed-u- or ed-r- or is- or has-',
|
|
189
|
+
actualPrefix: className.match(/^[a-z]+-/)?.[0] || 'none',
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
// Check for uppercase in class names
|
|
194
|
+
if (/[A-Z]/.test(className)) {
|
|
195
|
+
signals.push({
|
|
196
|
+
id: `drift-naming-case-${className}-${lineIndex}`,
|
|
197
|
+
timestamp: new Date().toISOString(),
|
|
198
|
+
source: 'git',
|
|
199
|
+
severity: 'warning',
|
|
200
|
+
type: 'naming-violation',
|
|
201
|
+
message: `Class ".${className}" contains uppercase letters. BEM classes must be lowercase`,
|
|
202
|
+
target: className,
|
|
203
|
+
payload: {
|
|
204
|
+
className,
|
|
205
|
+
expectedPattern: className.toLowerCase(),
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
// Skip files that can't be read
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// Check for unclassed HTML elements in component templates
|
|
217
|
+
const componentFiles = await glob('**/components/**/*.ts', {
|
|
218
|
+
cwd: rootDir,
|
|
219
|
+
absolute: true,
|
|
220
|
+
ignore: ['**/node_modules/**', '**/*.test.ts'],
|
|
221
|
+
});
|
|
222
|
+
const allowedUnclassed = [
|
|
223
|
+
'svg', 'path', 'g', 'circle', 'rect', 'ellipse', 'line',
|
|
224
|
+
'style', 'script', 'template', 'slot', 'use', 'defs',
|
|
225
|
+
];
|
|
226
|
+
for (const file of componentFiles) {
|
|
227
|
+
try {
|
|
228
|
+
const content = await readFile(file, 'utf-8');
|
|
229
|
+
// Skip TextPassage components
|
|
230
|
+
if (file.includes('TextPassage'))
|
|
231
|
+
continue;
|
|
232
|
+
const lines = content.split('\n');
|
|
233
|
+
lines.forEach((line, lineIndex) => {
|
|
234
|
+
// Look for HTML elements without class attributes
|
|
235
|
+
const elementMatches = line.matchAll(/<([a-z][a-z0-9]*)\s+(?!.*class=)[^>]*>/gi);
|
|
236
|
+
for (const match of elementMatches) {
|
|
237
|
+
const tag = match[1].toLowerCase();
|
|
238
|
+
if (!allowedUnclassed.includes(tag) && !tag.includes('-')) {
|
|
239
|
+
signals.push({
|
|
240
|
+
id: `drift-unclassed-element-${tag}-${lineIndex}`,
|
|
241
|
+
timestamp: new Date().toISOString(),
|
|
242
|
+
source: 'git',
|
|
243
|
+
severity: 'warning',
|
|
244
|
+
type: 'naming-violation',
|
|
245
|
+
message: `Unclassed <${tag}> element found in ${file}. Every element should have a BEM class`,
|
|
246
|
+
target: tag,
|
|
247
|
+
payload: {
|
|
248
|
+
className: `<${tag}>`,
|
|
249
|
+
expectedPattern: `<${tag} class="ed-c-...">`,
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
// Skip files that can't be read
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return signals;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Detect if a component deviates from an expected recipe
|
|
264
|
+
*/
|
|
265
|
+
detectRecipeInComponent(file, content, recipe) {
|
|
266
|
+
const signals = [];
|
|
267
|
+
// Check if component file mentions recipe components
|
|
268
|
+
for (const recipeComp of recipe.components) {
|
|
269
|
+
const isComponentMentioned = content.includes(recipeComp.tagName);
|
|
270
|
+
if (recipeComp.required && !isComponentMentioned) {
|
|
271
|
+
signals.push({
|
|
272
|
+
id: `drift-recipe-missing-${recipe.name}-${recipeComp.tagName}`,
|
|
273
|
+
timestamp: new Date().toISOString(),
|
|
274
|
+
source: 'usage',
|
|
275
|
+
severity: 'warning',
|
|
276
|
+
type: 'recipe-incomplete',
|
|
277
|
+
message: `Recipe "${recipe.name}" requires component "${recipeComp.tagName}", but it's not found in ${file}`,
|
|
278
|
+
target: recipeComp.tagName,
|
|
279
|
+
payload: {
|
|
280
|
+
recipeName: recipe.name,
|
|
281
|
+
missingComponent: recipeComp.tagName,
|
|
282
|
+
expectedRole: recipeComp.role,
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
// Check for required tokens in this component if it uses the recipe
|
|
288
|
+
if (recipe.components.some((c) => content.includes(c.tagName))) {
|
|
289
|
+
for (const [tokenKey, tokenValue] of Object.entries(recipe.tokens)) {
|
|
290
|
+
if (!content.includes(tokenValue)) {
|
|
291
|
+
signals.push({
|
|
292
|
+
id: `drift-recipe-missing-token-${recipe.name}-${tokenKey}`,
|
|
293
|
+
timestamp: new Date().toISOString(),
|
|
294
|
+
source: 'usage',
|
|
295
|
+
severity: 'info',
|
|
296
|
+
type: 'recipe-missing-token',
|
|
297
|
+
message: `Recipe "${recipe.name}" expects token "${tokenValue}" to be used, but not found in ${file}`,
|
|
298
|
+
target: tokenValue,
|
|
299
|
+
payload: {
|
|
300
|
+
recipeName: recipe.name,
|
|
301
|
+
tokenName: tokenValue,
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return signals;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=drift-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift-detector.js","sourceRoot":"","sources":["../../src/analyze/drift-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
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 { HealthScore, HealthReport, BrainConfig } from '../types.js';
|
|
13
|
+
interface KnowledgeGraph {
|
|
14
|
+
getComponentEntries?: () => any[];
|
|
15
|
+
getTokenTaxonomy?: () => any;
|
|
16
|
+
getTokens?: () => any[];
|
|
17
|
+
getAllThemes?: () => string[];
|
|
18
|
+
}
|
|
19
|
+
export declare class HealthScorer {
|
|
20
|
+
private knowledgeGraph;
|
|
21
|
+
private config;
|
|
22
|
+
private tokenValidator;
|
|
23
|
+
private namingValidator;
|
|
24
|
+
constructor(knowledgeGraph: KnowledgeGraph, config: BrainConfig);
|
|
25
|
+
/**
|
|
26
|
+
* Score a single component across all health categories
|
|
27
|
+
*/
|
|
28
|
+
scoreComponent(tagName: string): Promise<HealthScore[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Generate full system health report
|
|
31
|
+
*/
|
|
32
|
+
scoreAll(): Promise<HealthReport>;
|
|
33
|
+
/**
|
|
34
|
+
* Score token usage health
|
|
35
|
+
*/
|
|
36
|
+
private scoreTokenHealth;
|
|
37
|
+
/**
|
|
38
|
+
* Score naming convention compliance
|
|
39
|
+
*/
|
|
40
|
+
private scoreNamingHealth;
|
|
41
|
+
/**
|
|
42
|
+
* Score documentation completeness
|
|
43
|
+
*/
|
|
44
|
+
private scoreDocumentationHealth;
|
|
45
|
+
/**
|
|
46
|
+
* Score metadata coverage
|
|
47
|
+
*/
|
|
48
|
+
private scoreCoverageHealth;
|
|
49
|
+
/**
|
|
50
|
+
* Score accessibility features
|
|
51
|
+
*/
|
|
52
|
+
private scoreAccessibilityHealth;
|
|
53
|
+
/**
|
|
54
|
+
* Score API consistency with similar components
|
|
55
|
+
*/
|
|
56
|
+
private scoreConsistencyHealth;
|
|
57
|
+
/**
|
|
58
|
+
* Aggregate scores by category
|
|
59
|
+
*/
|
|
60
|
+
private aggregateScores;
|
|
61
|
+
/**
|
|
62
|
+
* Calculate weighted overall score
|
|
63
|
+
*/
|
|
64
|
+
private calculateWeightedScore;
|
|
65
|
+
/**
|
|
66
|
+
* Count issues by severity
|
|
67
|
+
*/
|
|
68
|
+
private countIssuesBySeverity;
|
|
69
|
+
}
|
|
70
|
+
export {};
|
|
71
|
+
//# sourceMappingURL=health-scorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-scorer.d.ts","sourceRoot":"","sources":["../../src/analyze/health-scorer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EACL,WAAW,EACX,YAAY,EAGZ,WAAW,EACZ,MAAM,aAAa,CAAC;AAIrB,UAAU,cAAc;IACtB,mBAAmB,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC;IAClC,gBAAgB,CAAC,EAAE,MAAM,GAAG,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;CAC/B;AAOD,qBAAa,YAAY;IAKrB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,MAAM;IALhB,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,eAAe,CAAkB;gBAG/B,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,WAAW;IAM7B;;OAEG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAgD7D;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,YAAY,CAAC;IA4BvC;;OAEG;YACW,gBAAgB;IA2B9B;;OAEG;YACW,iBAAiB;IA8B/B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAwEhC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAqD3B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAwDhC;;OAEG;YACW,sBAAsB;IA8DpC;;OAEG;IACH,OAAO,CAAC,eAAe;IAyBvB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAgB9B;;OAEG;IACH,OAAO,CAAC,qBAAqB;CAkB9B"}
|