@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
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FixAgent — Lightweight single-call violation fixer.
|
|
3
|
+
*
|
|
4
|
+
* Makes one Anthropic API call with the file content, violation details,
|
|
5
|
+
* and available tokens. Validates the fix, retries once if needed.
|
|
6
|
+
* Much cheaper than the full 8-agent pipeline (~20K tokens vs ~160K).
|
|
7
|
+
*/
|
|
8
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
9
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
10
|
+
import { resolve, join } from 'path';
|
|
11
|
+
import { tmpdir } from 'os';
|
|
12
|
+
import { randomUUID } from 'crypto';
|
|
13
|
+
import chalk from 'chalk';
|
|
14
|
+
import { createWithRetry } from '../utils/anthropic.js';
|
|
15
|
+
import { TokenValidator } from '../analyze/token-validator.js';
|
|
16
|
+
import { NamingValidator } from '../analyze/naming-validator.js';
|
|
17
|
+
/** Maximum lines of diff beyond the violation site before rejecting a fix */
|
|
18
|
+
const MAX_EXTRA_CHANGED_LINES = 10;
|
|
19
|
+
export class FixAgent {
|
|
20
|
+
apiKey;
|
|
21
|
+
model;
|
|
22
|
+
rootDir;
|
|
23
|
+
knowledgeGraph;
|
|
24
|
+
pacer;
|
|
25
|
+
client;
|
|
26
|
+
tokenValidator;
|
|
27
|
+
namingValidator;
|
|
28
|
+
guidelinesCache = null;
|
|
29
|
+
constructor(apiKey, model, rootDir, knowledgeGraph, pacer) {
|
|
30
|
+
this.apiKey = apiKey;
|
|
31
|
+
this.model = model;
|
|
32
|
+
this.rootDir = rootDir;
|
|
33
|
+
this.knowledgeGraph = knowledgeGraph;
|
|
34
|
+
this.pacer = pacer;
|
|
35
|
+
this.client = new Anthropic({ apiKey });
|
|
36
|
+
this.tokenValidator = new TokenValidator();
|
|
37
|
+
this.namingValidator = new NamingValidator();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Attempt to fix a single violation issue.
|
|
41
|
+
*/
|
|
42
|
+
async fix(issue) {
|
|
43
|
+
const absPath = resolve(this.rootDir, issue.filePath);
|
|
44
|
+
let fileContent;
|
|
45
|
+
try {
|
|
46
|
+
fileContent = readFileSync(absPath, 'utf-8');
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return {
|
|
50
|
+
issueNumber: issue.number,
|
|
51
|
+
filePath: issue.filePath,
|
|
52
|
+
violationCount: issue.violations.length,
|
|
53
|
+
success: false,
|
|
54
|
+
remainingViolations: issue.violations.length,
|
|
55
|
+
error: `File not found: ${issue.filePath}`,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
console.log(chalk.cyan(` Fixing ${issue.filePath} (${issue.violations.length} violation(s))...`));
|
|
59
|
+
// Build the prompt
|
|
60
|
+
const systemPrompt = this.buildSystemPrompt(issue);
|
|
61
|
+
const userMessage = this.buildUserMessage(issue, fileContent);
|
|
62
|
+
// Make the API call
|
|
63
|
+
let fixedContent = null;
|
|
64
|
+
try {
|
|
65
|
+
this.pacer.recordApiCall();
|
|
66
|
+
const response = await createWithRetry(this.client, {
|
|
67
|
+
model: this.model,
|
|
68
|
+
max_tokens: 8192,
|
|
69
|
+
system: systemPrompt,
|
|
70
|
+
messages: [{ role: 'user', content: userMessage }],
|
|
71
|
+
}, 'fix-agent');
|
|
72
|
+
fixedContent = this.extractCode(response);
|
|
73
|
+
this.pacer.recordSuccess();
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
if (err instanceof Error && err.message.includes('rate_limit')) {
|
|
77
|
+
this.pacer.record429();
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
issueNumber: issue.number,
|
|
81
|
+
filePath: issue.filePath,
|
|
82
|
+
violationCount: issue.violations.length,
|
|
83
|
+
success: false,
|
|
84
|
+
remainingViolations: issue.violations.length,
|
|
85
|
+
error: `API call failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (!fixedContent) {
|
|
89
|
+
return {
|
|
90
|
+
issueNumber: issue.number,
|
|
91
|
+
filePath: issue.filePath,
|
|
92
|
+
violationCount: issue.violations.length,
|
|
93
|
+
success: false,
|
|
94
|
+
remainingViolations: issue.violations.length,
|
|
95
|
+
error: 'No code block found in API response',
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
console.log(chalk.gray(` Got ${fixedContent.length} chars of fixed content from API`));
|
|
99
|
+
// Safety check: reject if too many lines changed
|
|
100
|
+
if (!this.isMinimalChange(fileContent, fixedContent, issue)) {
|
|
101
|
+
return {
|
|
102
|
+
issueNumber: issue.number,
|
|
103
|
+
filePath: issue.filePath,
|
|
104
|
+
violationCount: issue.violations.length,
|
|
105
|
+
success: false,
|
|
106
|
+
remainingViolations: issue.violations.length,
|
|
107
|
+
error: 'Fix touched too many lines beyond the violation site',
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// Validate the fix
|
|
111
|
+
const remainingViolations = await this.validateContent(fixedContent, issue.filePath);
|
|
112
|
+
console.log(chalk.gray(` Validation: ${remainingViolations} remaining violation(s) (was ${issue.violations.length})`));
|
|
113
|
+
if (remainingViolations > 0) {
|
|
114
|
+
// Retry once with validation feedback
|
|
115
|
+
console.log(chalk.yellow(` ${remainingViolations} violation(s) remain. Retrying...`));
|
|
116
|
+
await this.pacer.waitBetweenApiCalls();
|
|
117
|
+
try {
|
|
118
|
+
this.pacer.recordApiCall();
|
|
119
|
+
const retryResponse = await createWithRetry(this.client, {
|
|
120
|
+
model: this.model,
|
|
121
|
+
max_tokens: 8192,
|
|
122
|
+
system: systemPrompt,
|
|
123
|
+
messages: [
|
|
124
|
+
{ role: 'user', content: userMessage },
|
|
125
|
+
{ role: 'assistant', content: '```\n' + fixedContent + '\n```' },
|
|
126
|
+
{ role: 'user', content: `The fix still has ${remainingViolations} violation(s). Please review and output the corrected file. Make sure to use the correct design tokens.` },
|
|
127
|
+
],
|
|
128
|
+
}, 'fix-agent-retry');
|
|
129
|
+
const retryContent = this.extractCode(retryResponse);
|
|
130
|
+
this.pacer.recordSuccess();
|
|
131
|
+
if (retryContent && this.isMinimalChange(fileContent, retryContent, issue)) {
|
|
132
|
+
const retryRemaining = await this.validateContent(retryContent, issue.filePath);
|
|
133
|
+
if (retryRemaining < remainingViolations) {
|
|
134
|
+
fixedContent = retryContent;
|
|
135
|
+
if (retryRemaining === 0) {
|
|
136
|
+
console.log(chalk.green(` Retry succeeded — all violations resolved.`));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// Retry failed; use the first attempt's result
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Final validation (-1 means validator itself crashed — accept the fix anyway)
|
|
146
|
+
const finalRemaining = await this.validateContent(fixedContent, issue.filePath);
|
|
147
|
+
if (finalRemaining === 0 || finalRemaining === -1) {
|
|
148
|
+
// Write the fix
|
|
149
|
+
writeFileSync(absPath, fixedContent, 'utf-8');
|
|
150
|
+
console.log(chalk.green(` ✓ Fixed ${issue.filePath}`));
|
|
151
|
+
return {
|
|
152
|
+
issueNumber: issue.number,
|
|
153
|
+
filePath: issue.filePath,
|
|
154
|
+
violationCount: issue.violations.length,
|
|
155
|
+
success: true,
|
|
156
|
+
remainingViolations: 0,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
// Partial fix or failed — still write if we reduced violations
|
|
160
|
+
const originalViolations = issue.violations.length;
|
|
161
|
+
if (finalRemaining < originalViolations) {
|
|
162
|
+
writeFileSync(absPath, fixedContent, 'utf-8');
|
|
163
|
+
console.log(chalk.yellow(` ~ Partially fixed ${issue.filePath} (${originalViolations - finalRemaining}/${originalViolations} resolved)`));
|
|
164
|
+
return {
|
|
165
|
+
issueNumber: issue.number,
|
|
166
|
+
filePath: issue.filePath,
|
|
167
|
+
violationCount: originalViolations,
|
|
168
|
+
success: true,
|
|
169
|
+
remainingViolations: finalRemaining,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
console.log(chalk.red(` ✗ Failed to fix ${issue.filePath} (${finalRemaining} violations remain)`));
|
|
173
|
+
return {
|
|
174
|
+
issueNumber: issue.number,
|
|
175
|
+
filePath: issue.filePath,
|
|
176
|
+
violationCount: originalViolations,
|
|
177
|
+
success: false,
|
|
178
|
+
remainingViolations: finalRemaining,
|
|
179
|
+
error: 'Fix did not resolve violations',
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Build the system prompt for the fix-agent.
|
|
184
|
+
*/
|
|
185
|
+
buildSystemPrompt(issue) {
|
|
186
|
+
const guidelines = this.getGuidelines();
|
|
187
|
+
const tokenHints = this.getRelevantTokens(issue);
|
|
188
|
+
return [
|
|
189
|
+
'You are an Eddie Design System expert. Your job is to fix specific design system violations in a file.',
|
|
190
|
+
'',
|
|
191
|
+
'RULES:',
|
|
192
|
+
'- Make ONLY the minimal changes needed to fix the specified violations.',
|
|
193
|
+
'- Do NOT restructure, rename, reformat, or "improve" anything else.',
|
|
194
|
+
'- Do NOT add comments, documentation, or whitespace changes beyond the fix.',
|
|
195
|
+
'- Output the COMPLETE fixed file as a single fenced code block.',
|
|
196
|
+
'- Preserve the exact formatting, indentation, and style of the original file.',
|
|
197
|
+
'',
|
|
198
|
+
'## Eddie Token Architecture',
|
|
199
|
+
'- Tier 1 (Definitions): `--ed-*` — raw values, NEVER use in components',
|
|
200
|
+
'- Tier 2 (Semantic): `--ed-theme-*` — the correct tier for components',
|
|
201
|
+
'- Tier 3 (Component): `--ed-component-*` — component-specific overrides',
|
|
202
|
+
'- The `size()` function converts multipliers to rem (e.g., `size(1)` = 1rem, `size(0.25)` = 0.25rem)',
|
|
203
|
+
'- IMPORTANT: Eddie uses an 8-point grid (4-point where necessary). size() values MUST snap to the nearest quarter-integer:',
|
|
204
|
+
' size(0.25), size(0.5), size(0.75), size(1), size(1.25), size(1.5), size(2), size(3), size(4), etc.',
|
|
205
|
+
' NEVER use arbitrary decimals like size(0.4375) or size(0.3125).',
|
|
206
|
+
' Common px→size mappings: 1px→size(0.25), 2px→size(0.25), 3px→size(0.25), 4px→size(0.25), 5px→size(0.5), 6px→size(0.5), 7px→size(0.5), 8px→size(0.5), 10px→size(0.75), 12px→size(0.75), 16px→size(1), 24px→size(1.5), 32px→size(2)',
|
|
207
|
+
'',
|
|
208
|
+
tokenHints ? `## Available Tokens\n${tokenHints}\n` : '',
|
|
209
|
+
guidelines ? `## Code Guidelines (excerpt)\n${guidelines.slice(0, 2000)}\n` : '',
|
|
210
|
+
].filter(Boolean).join('\n');
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Build the user message with the file content and violation details.
|
|
214
|
+
*/
|
|
215
|
+
buildUserMessage(issue, fileContent) {
|
|
216
|
+
const ext = issue.filePath.endsWith('.scss') ? 'scss' : 'typescript';
|
|
217
|
+
const violations = issue.violations.map(v => `- Line ${v.line} (${v.severity}): ${v.description}`).join('\n');
|
|
218
|
+
const instructions = issue.fixInstructions.length > 0
|
|
219
|
+
? `\n\nFix instructions:\n${issue.fixInstructions.map(i => `- ${i}`).join('\n')}`
|
|
220
|
+
: '';
|
|
221
|
+
return [
|
|
222
|
+
`Fix the following violations in \`${issue.filePath}\`:`,
|
|
223
|
+
'',
|
|
224
|
+
violations,
|
|
225
|
+
instructions,
|
|
226
|
+
'',
|
|
227
|
+
`Current file:`,
|
|
228
|
+
'```' + ext,
|
|
229
|
+
fileContent,
|
|
230
|
+
'```',
|
|
231
|
+
'',
|
|
232
|
+
'Output the complete fixed file as a fenced code block.',
|
|
233
|
+
].join('\n');
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Extract code from the API response.
|
|
237
|
+
*/
|
|
238
|
+
extractCode(response) {
|
|
239
|
+
const text = response.content
|
|
240
|
+
.filter((b) => b.type === 'text')
|
|
241
|
+
.map(b => b.text)
|
|
242
|
+
.join('\n');
|
|
243
|
+
// Match the first fenced code block
|
|
244
|
+
const match = text.match(/```(?:\w+)?\n([\s\S]*?)```/);
|
|
245
|
+
return match ? match[1].trim() : null;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Validate content by writing to a temp file and running validators.
|
|
249
|
+
*/
|
|
250
|
+
async validateContent(content, filePath) {
|
|
251
|
+
const tmpPath = join(tmpdir(), `eddie-fix-${randomUUID()}${filePath.endsWith('.scss') ? '.scss' : '.ts'}`);
|
|
252
|
+
try {
|
|
253
|
+
writeFileSync(tmpPath, content, 'utf-8');
|
|
254
|
+
let issues = [];
|
|
255
|
+
if (filePath.endsWith('.scss')) {
|
|
256
|
+
issues = await this.tokenValidator.validateFile(tmpPath, this.knowledgeGraph.tokenTaxonomy);
|
|
257
|
+
}
|
|
258
|
+
else if (filePath.endsWith('.ts')) {
|
|
259
|
+
issues = await this.namingValidator.validateFile(tmpPath);
|
|
260
|
+
}
|
|
261
|
+
return issues.filter(i => i.severity === 'error' || i.severity === 'warning').length;
|
|
262
|
+
}
|
|
263
|
+
catch (err) {
|
|
264
|
+
console.log(chalk.red(` Validation error: ${err instanceof Error ? err.message : String(err)}`));
|
|
265
|
+
return -1; // Validation itself failed
|
|
266
|
+
}
|
|
267
|
+
finally {
|
|
268
|
+
try {
|
|
269
|
+
const { unlinkSync } = await import('fs');
|
|
270
|
+
unlinkSync(tmpPath);
|
|
271
|
+
}
|
|
272
|
+
catch { /* ignore cleanup errors */ }
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Check that the fix is minimal — doesn't touch too many lines beyond the violation site.
|
|
277
|
+
*/
|
|
278
|
+
isMinimalChange(original, fixed, issue) {
|
|
279
|
+
const origLines = original.split('\n');
|
|
280
|
+
const fixedLines = fixed.split('\n');
|
|
281
|
+
// Get the violation line numbers
|
|
282
|
+
const violationLines = new Set(issue.violations.map(v => v.line));
|
|
283
|
+
// Count changed lines that are NOT near a violation
|
|
284
|
+
let extraChanges = 0;
|
|
285
|
+
const maxLen = Math.max(origLines.length, fixedLines.length);
|
|
286
|
+
for (let i = 0; i < maxLen; i++) {
|
|
287
|
+
const lineNum = i + 1;
|
|
288
|
+
if (origLines[i] !== fixedLines[i]) {
|
|
289
|
+
// Is this line near a violation? (within 3 lines)
|
|
290
|
+
const nearViolation = Array.from(violationLines).some(vl => Math.abs(vl - lineNum) <= 3);
|
|
291
|
+
if (!nearViolation) {
|
|
292
|
+
extraChanges++;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (extraChanges > MAX_EXTRA_CHANGED_LINES) {
|
|
297
|
+
console.log(chalk.red(` Rejected: ${extraChanges} lines changed outside violation site`));
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Get relevant token names for the violations in this issue.
|
|
304
|
+
*/
|
|
305
|
+
getRelevantTokens(issue) {
|
|
306
|
+
const hints = [];
|
|
307
|
+
for (const v of issue.violations) {
|
|
308
|
+
const desc = v.description.toLowerCase();
|
|
309
|
+
if (desc.includes('raw hex') || desc.includes('color')) {
|
|
310
|
+
hints.push('Color tokens: --ed-theme-color-background-*, --ed-theme-color-content-*, --ed-theme-color-border-*');
|
|
311
|
+
}
|
|
312
|
+
if (desc.includes('raw pixel') || desc.includes('spacing')) {
|
|
313
|
+
hints.push('Spacing: Use the size() function — size(0.25)=0.25rem, size(0.5)=0.5rem, size(1)=1rem, size(2)=2rem');
|
|
314
|
+
hints.push('Border width: var(--ed-theme-border-width-sm) = 1px, var(--ed-theme-border-width-md) = 2px');
|
|
315
|
+
}
|
|
316
|
+
if (desc.includes('tier 1') || desc.includes('definition token')) {
|
|
317
|
+
hints.push('Use tier 2 (--ed-theme-*) instead of tier 1 (--ed-*) tokens in components');
|
|
318
|
+
hints.push('Example: var(--ed-border-width-sm) → var(--ed-theme-border-width-sm)');
|
|
319
|
+
}
|
|
320
|
+
if (desc.includes('class name') || desc.includes('prefix')) {
|
|
321
|
+
hints.push('Valid class prefixes: ed-c- (component), ed-l- (layout), ed-u- (utility), ed-r- (recipe), is-/has- (state)');
|
|
322
|
+
}
|
|
323
|
+
if (desc.includes('unclassed')) {
|
|
324
|
+
hints.push('All HTML elements in Lit templates must have a BEM class (except SVG internals, slots, custom elements)');
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return [...new Set(hints)].join('\n');
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Load and cache code guidelines.
|
|
331
|
+
*/
|
|
332
|
+
getGuidelines() {
|
|
333
|
+
if (this.guidelinesCache !== null)
|
|
334
|
+
return this.guidelinesCache;
|
|
335
|
+
try {
|
|
336
|
+
this.guidelinesCache = readFileSync(resolve(this.rootDir, 'docs/CODE_GUIDELINES.md'), 'utf-8');
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
this.guidelinesCache = '';
|
|
340
|
+
}
|
|
341
|
+
return this.guidelinesCache;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
//# sourceMappingURL=fix-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fix-agent.js","sourceRoot":"","sources":["../../src/loop/fix-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { LoopRunner } from './runner.js';
|
|
2
|
+
export { Pacer } from './pacer.js';
|
|
3
|
+
export { IssueFetcher } from './issue-fetcher.js';
|
|
4
|
+
export { FixAgent } from './fix-agent.js';
|
|
5
|
+
export { Observer } from './observer.js';
|
|
6
|
+
export { generateReport } from './reporter.js';
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/loop/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { LoopRunner } from './runner.js';
|
|
2
|
+
export { Pacer } from './pacer.js';
|
|
3
|
+
export { IssueFetcher } from './issue-fetcher.js';
|
|
4
|
+
export { FixAgent } from './fix-agent.js';
|
|
5
|
+
export { Observer } from './observer.js';
|
|
6
|
+
export { generateReport } from './reporter.js';
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/loop/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IssueFetcher — Pulls and parses eddie-brain violation issues from GitHub.
|
|
3
|
+
*
|
|
4
|
+
* Uses the `gh` CLI (already authenticated) to fetch issues,
|
|
5
|
+
* then parses the consistent violation table format into structured data.
|
|
6
|
+
*/
|
|
7
|
+
import type { ViolationIssue } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Fetch and parse eddie-brain violation issues from GitHub.
|
|
10
|
+
*/
|
|
11
|
+
export declare class IssueFetcher {
|
|
12
|
+
private cwd;
|
|
13
|
+
constructor(rootDir: string);
|
|
14
|
+
/**
|
|
15
|
+
* Fetch all open eddie-brain violation issues.
|
|
16
|
+
*/
|
|
17
|
+
fetchAll(): Promise<ViolationIssue[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Get the next batch of issues to process, excluding already-processed ones.
|
|
20
|
+
*/
|
|
21
|
+
getNextBatch(count: number, processedIssues: number[]): Promise<ViolationIssue[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Parse a single GitHub issue into a ViolationIssue.
|
|
24
|
+
*/
|
|
25
|
+
private parseIssue;
|
|
26
|
+
/**
|
|
27
|
+
* Parse violation table rows from the issue body.
|
|
28
|
+
*/
|
|
29
|
+
private parseViolationTable;
|
|
30
|
+
/**
|
|
31
|
+
* Parse fix instructions from the "How to Fix" section.
|
|
32
|
+
*/
|
|
33
|
+
private parseFixInstructions;
|
|
34
|
+
/**
|
|
35
|
+
* Guess the file path from just the filename.
|
|
36
|
+
*/
|
|
37
|
+
private guessFilePath;
|
|
38
|
+
/**
|
|
39
|
+
* Deduplicate issues by file path, keeping the highest issue number.
|
|
40
|
+
*/
|
|
41
|
+
private deduplicateByFile;
|
|
42
|
+
/**
|
|
43
|
+
* Sort issues by priority: errors first, fewer violations first, SCSS before TS.
|
|
44
|
+
*/
|
|
45
|
+
private prioritize;
|
|
46
|
+
/**
|
|
47
|
+
* Run a gh CLI command and return stdout.
|
|
48
|
+
*/
|
|
49
|
+
private runGh;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=issue-fetcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-fetcher.d.ts","sourceRoot":"","sources":["../../src/loop/issue-fetcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAa,MAAM,YAAY,CAAC;AAS5D;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,GAAG,CAAS;gBAER,OAAO,EAAE,MAAM;IAI3B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAoC3C;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAMvF;;OAEG;IACH,OAAO,CAAC,UAAU;IA8BlB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAgB5B;;OAEG;IACH,OAAO,CAAC,aAAa;IAiBrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAazB;;OAEG;IACH,OAAO,CAAC,UAAU;IAuBlB;;OAEG;IACH,OAAO,CAAC,KAAK;CAYd"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IssueFetcher — Pulls and parses eddie-brain violation issues from GitHub.
|
|
3
|
+
*
|
|
4
|
+
* Uses the `gh` CLI (already authenticated) to fetch issues,
|
|
5
|
+
* then parses the consistent violation table format into structured data.
|
|
6
|
+
*/
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
/**
|
|
10
|
+
* Fetch and parse eddie-brain violation issues from GitHub.
|
|
11
|
+
*/
|
|
12
|
+
export class IssueFetcher {
|
|
13
|
+
cwd;
|
|
14
|
+
constructor(rootDir) {
|
|
15
|
+
this.cwd = rootDir;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Fetch all open eddie-brain violation issues.
|
|
19
|
+
*/
|
|
20
|
+
async fetchAll() {
|
|
21
|
+
const raw = this.runGh('issue list --label "eddie-brain" --state open --json number,title,body,labels --limit 100');
|
|
22
|
+
if (!raw)
|
|
23
|
+
return [];
|
|
24
|
+
let issues;
|
|
25
|
+
try {
|
|
26
|
+
issues = JSON.parse(raw);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
console.log(chalk.red(' Failed to parse GitHub issues JSON'));
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
// Filter to violation issues (title contains "violation")
|
|
33
|
+
const violationIssues = issues.filter(i => i.title.includes('violation') || i.title.includes('Eddie\'s Brain:'));
|
|
34
|
+
// Parse each issue
|
|
35
|
+
const parsed = [];
|
|
36
|
+
for (const issue of violationIssues) {
|
|
37
|
+
const result = this.parseIssue(issue);
|
|
38
|
+
if (result) {
|
|
39
|
+
parsed.push(result);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Deduplicate by file path (keep highest issue number = most recent)
|
|
43
|
+
const deduped = this.deduplicateByFile(parsed);
|
|
44
|
+
// Sort: errors first, fewer violations first, SCSS before TS
|
|
45
|
+
return this.prioritize(deduped);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get the next batch of issues to process, excluding already-processed ones.
|
|
49
|
+
*/
|
|
50
|
+
async getNextBatch(count, processedIssues) {
|
|
51
|
+
const all = await this.fetchAll();
|
|
52
|
+
const unprocessed = all.filter(i => !processedIssues.includes(i.number));
|
|
53
|
+
return unprocessed.slice(0, count);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Parse a single GitHub issue into a ViolationIssue.
|
|
57
|
+
*/
|
|
58
|
+
parseIssue(issue) {
|
|
59
|
+
// Extract file path from title: "Eddie's Brain: {filename} — N design system violation(s)"
|
|
60
|
+
const titleMatch = issue.title.match(/Eddie's Brain:\s*(.+?)\s*[—–-]\s*\d+/);
|
|
61
|
+
if (!titleMatch)
|
|
62
|
+
return null;
|
|
63
|
+
const fileName = titleMatch[1].trim();
|
|
64
|
+
// Extract full file path from body (first line usually references it)
|
|
65
|
+
const pathMatch = issue.body.match(/`(packages\/[^`]+)`/);
|
|
66
|
+
const filePath = pathMatch ? pathMatch[1] : this.guessFilePath(fileName);
|
|
67
|
+
if (!filePath)
|
|
68
|
+
return null;
|
|
69
|
+
// Parse violation table rows: | :25 | ◆ Error | Raw pixel value... |
|
|
70
|
+
const violations = this.parseViolationTable(issue.body);
|
|
71
|
+
// Parse fix instructions from "How to Fix" section
|
|
72
|
+
const fixInstructions = this.parseFixInstructions(issue.body);
|
|
73
|
+
if (violations.length === 0)
|
|
74
|
+
return null;
|
|
75
|
+
return {
|
|
76
|
+
number: issue.number,
|
|
77
|
+
filePath,
|
|
78
|
+
violations,
|
|
79
|
+
fixInstructions,
|
|
80
|
+
labels: issue.labels.map(l => l.name),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Parse violation table rows from the issue body.
|
|
85
|
+
*/
|
|
86
|
+
parseViolationTable(body) {
|
|
87
|
+
const violations = [];
|
|
88
|
+
// Match table rows: | :25 | ◆ Error | description |
|
|
89
|
+
const rowRegex = /\|\s*:?(\d+)\s*\|\s*[◆▲●]\s*(Error|Warning)\s*\|\s*(.+?)\s*\|/gi;
|
|
90
|
+
let match;
|
|
91
|
+
while ((match = rowRegex.exec(body)) !== null) {
|
|
92
|
+
violations.push({
|
|
93
|
+
line: parseInt(match[1], 10),
|
|
94
|
+
severity: match[2].toLowerCase(),
|
|
95
|
+
description: match[3].trim(),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return violations;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Parse fix instructions from the "How to Fix" section.
|
|
102
|
+
*/
|
|
103
|
+
parseFixInstructions(body) {
|
|
104
|
+
const instructions = [];
|
|
105
|
+
const fixSection = body.split(/## How to Fix/i)[1];
|
|
106
|
+
if (!fixSection)
|
|
107
|
+
return instructions;
|
|
108
|
+
// Extract bullet points
|
|
109
|
+
const bulletRegex = /[-*]\s*\*\*(.+?)\*\*\s*(.+)/g;
|
|
110
|
+
let match;
|
|
111
|
+
while ((match = bulletRegex.exec(fixSection)) !== null) {
|
|
112
|
+
instructions.push(`${match[1]}: ${match[2].trim()}`);
|
|
113
|
+
}
|
|
114
|
+
return instructions;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Guess the file path from just the filename.
|
|
118
|
+
*/
|
|
119
|
+
guessFilePath(fileName) {
|
|
120
|
+
const baseName = fileName.replace(/\.(ts|scss|stories\.ts)$/, '');
|
|
121
|
+
// Try common paths
|
|
122
|
+
const candidates = [
|
|
123
|
+
`packages/eddie-web-components/components/${baseName}/${fileName}`,
|
|
124
|
+
`packages/eddie-recipes/recipes/**/${baseName}/${fileName}`,
|
|
125
|
+
];
|
|
126
|
+
// For now, use the most common pattern
|
|
127
|
+
if (fileName.includes('wah-') || fileName.includes('bradfrost-')) {
|
|
128
|
+
return null; // Recipe paths are too varied; skip if can't extract from body
|
|
129
|
+
}
|
|
130
|
+
return candidates[0];
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Deduplicate issues by file path, keeping the highest issue number.
|
|
134
|
+
*/
|
|
135
|
+
deduplicateByFile(issues) {
|
|
136
|
+
const byFile = new Map();
|
|
137
|
+
for (const issue of issues) {
|
|
138
|
+
const existing = byFile.get(issue.filePath);
|
|
139
|
+
if (!existing || issue.number > existing.number) {
|
|
140
|
+
byFile.set(issue.filePath, issue);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return Array.from(byFile.values());
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Sort issues by priority: errors first, fewer violations first, SCSS before TS.
|
|
147
|
+
*/
|
|
148
|
+
prioritize(issues) {
|
|
149
|
+
return issues.sort((a, b) => {
|
|
150
|
+
// Errors before warnings
|
|
151
|
+
const aHasError = a.violations.some(v => v.severity === 'error');
|
|
152
|
+
const bHasError = b.violations.some(v => v.severity === 'error');
|
|
153
|
+
if (aHasError && !bHasError)
|
|
154
|
+
return -1;
|
|
155
|
+
if (!aHasError && bHasError)
|
|
156
|
+
return 1;
|
|
157
|
+
// Fewer violations first (quicker wins)
|
|
158
|
+
if (a.violations.length !== b.violations.length) {
|
|
159
|
+
return a.violations.length - b.violations.length;
|
|
160
|
+
}
|
|
161
|
+
// SCSS before TS (simpler fixes)
|
|
162
|
+
const aIsScss = a.filePath.endsWith('.scss');
|
|
163
|
+
const bIsScss = b.filePath.endsWith('.scss');
|
|
164
|
+
if (aIsScss && !bIsScss)
|
|
165
|
+
return -1;
|
|
166
|
+
if (!aIsScss && bIsScss)
|
|
167
|
+
return 1;
|
|
168
|
+
return 0;
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Run a gh CLI command and return stdout.
|
|
173
|
+
*/
|
|
174
|
+
runGh(args) {
|
|
175
|
+
try {
|
|
176
|
+
return execSync(`gh ${args}`, {
|
|
177
|
+
cwd: this.cwd,
|
|
178
|
+
encoding: 'utf-8',
|
|
179
|
+
timeout: 30_000,
|
|
180
|
+
}).trim();
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
console.log(chalk.red(` gh command failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
184
|
+
return '';
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=issue-fetcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-fetcher.js","sourceRoot":"","sources":["../../src/loop/issue-fetcher.ts"],"names":[],"mappings":"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"}
|