@chemx/starter-kit 26.9.9-786 â 26.9.11-362
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/cli/audit/ast-visitors.js +243 -0
- package/cli/audit/discussion-store.js +39 -0
- package/cli/audit/history.d.ts +63 -0
- package/cli/audit/history.js +352 -0
- package/cli/audit/metrics.js +179 -0
- package/cli/audit/prompts.js +174 -0
- package/cli/audit/reporter-grades.js +259 -0
- package/cli/audit/reporter-markdown.js +136 -0
- package/cli/audit/reporter-utils.js +107 -0
- package/cli/audit/reporter.js +459 -0
- package/cli/audit/rules-helpers.js +109 -0
- package/cli/audit/rules-registry.js +97 -0
- package/cli/audit/rules.js +123 -0
- package/cli/audit/social-constants.js +4 -0
- package/cli/audit/social-gh.js +126 -0
- package/cli/audit/social-git.js +214 -0
- package/cli/audit/social-http.js +222 -0
- package/cli/audit/social-publisher.js +193 -0
- package/cli/audit/social.d.ts +66 -0
- package/cli/audit/social.js +254 -0
- package/cli/audit/types.d.ts +131 -0
- package/cli/audit.d.ts +3 -24
- package/cli/audit.js +195 -210
- package/cli/help.d.ts +1 -0
- package/cli/help.js +136 -0
- package/cli/index.js +128 -566
- package/cli/installer-templates.js +80 -0
- package/cli/installer.d.ts +20 -0
- package/cli/installer.js +56 -0
- package/cli/license.js +320 -0
- package/cli/navigator-conversion.js +100 -0
- package/cli/navigator-grades.js +70 -0
- package/cli/navigator-paged.js +86 -0
- package/cli/navigator-share.js +129 -0
- package/cli/navigator.d.ts +24 -0
- package/cli/navigator.js +400 -0
- package/cli/scaffold.js +148 -0
- package/cli/terminal.js +126 -0
- package/docs/CHANGELOG.md +73 -0
- package/package.json +11 -10
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { PILLARS } from './rules.js';
|
|
2
|
+
|
|
3
|
+
export const calculateMolecularHealthScore = (violations, totalFiles) => {
|
|
4
|
+
if (totalFiles === 0) {
|
|
5
|
+
return { score: 100, grade: 'A+', label: 'Crystalline Molecular' };
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let penalty = 0;
|
|
9
|
+
for (const v of violations) {
|
|
10
|
+
if (v.severity === 'CRITICAL') penalty += 8;
|
|
11
|
+
else if (v.severity === 'HIGH') penalty += 4;
|
|
12
|
+
else if (v.severity === 'MEDIUM') penalty += 2;
|
|
13
|
+
else if (v.severity === 'LOW') penalty += 1;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Normalize penalty against codebase size
|
|
17
|
+
const scale = Math.max(1, Math.log10(totalFiles + 1));
|
|
18
|
+
const adjustedPenalty = penalty / scale;
|
|
19
|
+
const score = Math.max(0, Math.min(100, Math.round(100 - adjustedPenalty)));
|
|
20
|
+
|
|
21
|
+
let grade = 'F';
|
|
22
|
+
let label = 'Severe Context Rot';
|
|
23
|
+
|
|
24
|
+
if (score >= 95) {
|
|
25
|
+
grade = 'A+';
|
|
26
|
+
label = 'Crystalline Molecular';
|
|
27
|
+
} else if (score >= 90) {
|
|
28
|
+
grade = 'A';
|
|
29
|
+
label = 'Highly Modular';
|
|
30
|
+
} else if (score >= 80) {
|
|
31
|
+
grade = 'B';
|
|
32
|
+
label = 'Moderately Modular';
|
|
33
|
+
} else if (score >= 70) {
|
|
34
|
+
grade = 'C';
|
|
35
|
+
label = 'Monolithic Drift';
|
|
36
|
+
} else if (score >= 60) {
|
|
37
|
+
grade = 'D';
|
|
38
|
+
label = 'High Context Hazard';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return { score, grade, label };
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const calculatePillarBreakdown = (violations) => {
|
|
45
|
+
const breakdown = {};
|
|
46
|
+
for (const [key, name] of Object.entries(PILLARS)) {
|
|
47
|
+
breakdown[name] = {
|
|
48
|
+
pillarKey: key,
|
|
49
|
+
violations: 0,
|
|
50
|
+
critical: 0,
|
|
51
|
+
high: 0,
|
|
52
|
+
medium: 0,
|
|
53
|
+
low: 0,
|
|
54
|
+
status: 'PASSED'
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
for (const v of violations) {
|
|
59
|
+
const pillarName = v.pillar || PILLARS.PILLAR_1;
|
|
60
|
+
if (!breakdown[pillarName]) {
|
|
61
|
+
breakdown[pillarName] = {
|
|
62
|
+
pillarKey: 'UNKNOWN',
|
|
63
|
+
violations: 0,
|
|
64
|
+
critical: 0,
|
|
65
|
+
high: 0,
|
|
66
|
+
medium: 0,
|
|
67
|
+
low: 0,
|
|
68
|
+
status: 'PASSED'
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const item = breakdown[pillarName];
|
|
72
|
+
item.violations += 1;
|
|
73
|
+
if (v.severity === 'CRITICAL') item.critical += 1;
|
|
74
|
+
else if (v.severity === 'HIGH') item.high += 1;
|
|
75
|
+
else if (v.severity === 'MEDIUM') item.medium += 1;
|
|
76
|
+
else if (v.severity === 'LOW') item.low += 1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
for (const item of Object.values(breakdown)) {
|
|
80
|
+
if (item.critical > 0) {
|
|
81
|
+
item.status = 'FAILED';
|
|
82
|
+
} else if (item.high > 0 || item.medium > 1) {
|
|
83
|
+
item.status = 'WARN';
|
|
84
|
+
} else {
|
|
85
|
+
item.status = 'PASSED';
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return breakdown;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const MODEL_PRICING_RATES = {
|
|
93
|
+
blended: { name: 'Frontier Blended ($3.00/1M)', costPerMillion: 3.0 },
|
|
94
|
+
claude: { name: 'Claude 3.5 Sonnet ($3.00/1M)', costPerMillion: 3.0 },
|
|
95
|
+
gpt4o: { name: 'GPT-4o ($2.50/1M)', costPerMillion: 2.5 }
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export const calculateTokenBurnAnalytics = (fileStats, options = {}) => {
|
|
99
|
+
let totalRawChars = 0;
|
|
100
|
+
let excessChars = 0;
|
|
101
|
+
|
|
102
|
+
for (const f of fileStats) {
|
|
103
|
+
totalRawChars += f.charCount;
|
|
104
|
+
// Budget: 500 lines max for files (~18,000 chars), 100 lines for molecules (~3,600 chars)
|
|
105
|
+
const maxChars = f.isMolecule ? 3600 : 18000;
|
|
106
|
+
if (f.charCount > maxChars) {
|
|
107
|
+
excessChars += f.charCount - maxChars;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const estimatedTokens = Math.round(totalRawChars / 3.8);
|
|
112
|
+
const estimatedExcessTokens = Math.round(excessChars / 3.8);
|
|
113
|
+
const potentialSavingsPct = totalRawChars > 0
|
|
114
|
+
? Math.min(85, Math.round((excessChars / totalRawChars) * 100))
|
|
115
|
+
: 0;
|
|
116
|
+
|
|
117
|
+
const resolveRiskLevel = (pct) => {
|
|
118
|
+
if (pct > 40) return 'HIGH';
|
|
119
|
+
if (pct > 15) return 'MODERATE';
|
|
120
|
+
return 'LOW';
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const selectedModel = options?.model?.toLowerCase() || 'blended';
|
|
124
|
+
const modelConfig = MODEL_PRICING_RATES[selectedModel] || MODEL_PRICING_RATES.blended;
|
|
125
|
+
const costPerMillion = options?.costPerMillion ? Number(options.costPerMillion) : modelConfig.costPerMillion;
|
|
126
|
+
|
|
127
|
+
const excessCostPerPass = Number(((estimatedExcessTokens / 1000000) * costPerMillion).toFixed(3));
|
|
128
|
+
const weeklyWastePerDev = Number((excessCostPerPass * 20 * 5).toFixed(2));
|
|
129
|
+
const monthlyWastePerDev = Number((weeklyWastePerDev * 4).toFixed(2));
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
estimatedTokens,
|
|
133
|
+
estimatedExcessTokens,
|
|
134
|
+
potentialSavingsPct,
|
|
135
|
+
riskLevel: resolveRiskLevel(potentialSavingsPct),
|
|
136
|
+
pricingModel: modelConfig.name,
|
|
137
|
+
costPerMillion,
|
|
138
|
+
excessCostPerPass,
|
|
139
|
+
weeklyWastePerDev,
|
|
140
|
+
monthlyWastePerDev
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const resolveMonolithTierName = (lineCount) => {
|
|
145
|
+
if (lineCount >= 2000) return 'CRITICAL';
|
|
146
|
+
if (lineCount >= 1000) return 'SEVERE';
|
|
147
|
+
if (lineCount > 500) return 'WARNING';
|
|
148
|
+
return null;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export const calculateHotspots = (violations, fileStats, limit = 5) => {
|
|
152
|
+
const violationCountsByFile = {};
|
|
153
|
+
for (const v of violations) {
|
|
154
|
+
violationCountsByFile[v.filePath] = (violationCountsByFile[v.filePath] || 0) + 1;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const fileMap = {};
|
|
158
|
+
for (const f of fileStats) {
|
|
159
|
+
fileMap[f.relativePath] = f;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const scoredFiles = Object.entries(violationCountsByFile).map(([filePath, count]) => {
|
|
163
|
+
const stats = fileMap[filePath] || { lineCount: 0 };
|
|
164
|
+
const monolithTier = resolveMonolithTierName(stats.lineCount);
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
|
+
filePath,
|
|
168
|
+
violationCount: count,
|
|
169
|
+
lineCount: stats.lineCount,
|
|
170
|
+
isMonolith: stats.lineCount > 500,
|
|
171
|
+
monolithTier
|
|
172
|
+
};
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
scoredFiles.sort((a, b) => b.violationCount - a.violationCount || b.lineCount - a.lineCount);
|
|
176
|
+
return scoredFiles.slice(0, limit);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
export const calculateQuantumHealthScore = calculateMolecularHealthScore;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
const CYAN = '\x1b[38;2;98;201;255m';
|
|
2
|
+
const BOLD = '\x1b[1m';
|
|
3
|
+
const DIM = '\x1b[2m';
|
|
4
|
+
const RESET = '\x1b[0m';
|
|
5
|
+
|
|
6
|
+
export const buildGradeFPrompt = (report) => {
|
|
7
|
+
const { violations, hotspots } = report;
|
|
8
|
+
const critical = violations.filter((v) => v.severity === 'CRITICAL');
|
|
9
|
+
const extremeMonoliths = hotspots.filter((h) => h.lineCount >= 2000);
|
|
10
|
+
|
|
11
|
+
if (critical.length === 0 && extremeMonoliths.length === 0) return '';
|
|
12
|
+
|
|
13
|
+
const lines = [];
|
|
14
|
+
lines.push('Act as a Principal Systems Architect. Surgically refactor the following Grade F Critical Context Hazards in our codebase according to Chemical X Molecular Architecture Standards:\n');
|
|
15
|
+
|
|
16
|
+
if (extremeMonoliths.length > 0) {
|
|
17
|
+
lines.push('### EXTREME MONOLITHS (>= 2,000 LOC) : MONOLITH DECOMPOSITION');
|
|
18
|
+
extremeMonoliths.forEach((h, i) => {
|
|
19
|
+
lines.push(`${i + 1}. File: \`${h.filePath}\` (${h.lineCount} lines)`);
|
|
20
|
+
lines.push(' Action: Decompose this monolith into crystalline single-responsibility capsules (< 100 lines per molecule). Convert top-level view into a declarative Table-of-Contents view.');
|
|
21
|
+
});
|
|
22
|
+
lines.push('');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (critical.length > 0) {
|
|
26
|
+
lines.push('### CRITICAL AST VIOLATIONS');
|
|
27
|
+
critical.forEach((v, i) => {
|
|
28
|
+
lines.push(`${i + 1}. \`${v.filePath}:${v.line}:${v.column}\` [${v.rule}]`);
|
|
29
|
+
lines.push(` Hazard: ${v.hazard}`);
|
|
30
|
+
lines.push(` Directive: ${v.directive}`);
|
|
31
|
+
});
|
|
32
|
+
lines.push('');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
lines.push('### STRICT EXECUTION RULES:');
|
|
36
|
+
lines.push('1. Every new molecule component must stay under 100 lines.');
|
|
37
|
+
lines.push('2. Top-level page views must be 10-20 line declarative Table-of-Contents templates assembling components via named slots.');
|
|
38
|
+
lines.push('3. Zero synthetic or mock data: return live data or explicit empty states.');
|
|
39
|
+
lines.push('4. Zero render-hack setTimeout: replace with await nextTick() or flush: post.');
|
|
40
|
+
lines.push('5. Output surgical diffs or modular replacements. Preserve existing external exports.');
|
|
41
|
+
|
|
42
|
+
return lines.join('\n');
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const buildGradeDPrompt = (report) => {
|
|
46
|
+
const { violations, hotspots } = report;
|
|
47
|
+
const high = violations.filter((v) => v.severity === 'HIGH');
|
|
48
|
+
const severeMonoliths = hotspots.filter((h) => h.lineCount >= 1000 && h.lineCount < 2000);
|
|
49
|
+
|
|
50
|
+
if (high.length === 0 && severeMonoliths.length === 0) return '';
|
|
51
|
+
|
|
52
|
+
const lines = [];
|
|
53
|
+
lines.push('Act as a Principal Systems Architect. Refactor the following Grade D High-Severity Architectural Debts according to Chemical X Molecular Architecture Standards:\n');
|
|
54
|
+
|
|
55
|
+
if (severeMonoliths.length > 0) {
|
|
56
|
+
lines.push('### SEVERE MONOLITHS (1,000 - 1,999 LOC)');
|
|
57
|
+
severeMonoliths.forEach((h, i) => {
|
|
58
|
+
lines.push(`${i + 1}. File: \`${h.filePath}\` (${h.lineCount} lines)`);
|
|
59
|
+
lines.push(' Action: Extract sub-features into isolated molecule capsules (< 100 LOC) and domain composables.');
|
|
60
|
+
});
|
|
61
|
+
lines.push('');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (high.length > 0) {
|
|
65
|
+
lines.push('### HIGH SEVERITY VIOLATIONS');
|
|
66
|
+
high.forEach((v, i) => {
|
|
67
|
+
lines.push(`${i + 1}. \`${v.filePath}:${v.line}:${v.column}\` [${v.rule}]`);
|
|
68
|
+
lines.push(` Hazard: ${v.hazard}`);
|
|
69
|
+
lines.push(` Directive: ${v.directive}`);
|
|
70
|
+
});
|
|
71
|
+
lines.push('');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
lines.push('### STRICT EXECUTION RULES:');
|
|
75
|
+
lines.push('1. Hook Saturation: Extract component hooks into dedicated domain composables adhering to the 3-5 property return limit (State + Status + Actions).');
|
|
76
|
+
lines.push('2. Complex Control Flow: Break multi-clause conditionals into 2-stage atomic boolean variables with early-return guard clauses.');
|
|
77
|
+
lines.push('3. Zero breaking changes to caller APIs or existing props.');
|
|
78
|
+
|
|
79
|
+
return lines.join('\n');
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const buildGradeCPrompt = (report) => {
|
|
83
|
+
const { violations, hotspots } = report;
|
|
84
|
+
const medium = violations.filter((v) => v.severity === 'MEDIUM');
|
|
85
|
+
const warningMonoliths = hotspots.filter((h) => h.lineCount >= 500 && h.lineCount < 1000);
|
|
86
|
+
|
|
87
|
+
if (medium.length === 0 && warningMonoliths.length === 0) return '';
|
|
88
|
+
|
|
89
|
+
const lines = [];
|
|
90
|
+
lines.push('Act as a Senior Frontend Engineer. Refactor the following Grade C Medium-Severity Technical Debts according to Chemical X Molecular Architecture Standards:\n');
|
|
91
|
+
|
|
92
|
+
if (warningMonoliths.length > 0) {
|
|
93
|
+
lines.push('### WARNING MONOLITHS (500 - 999 LOC)');
|
|
94
|
+
warningMonoliths.forEach((h, i) => {
|
|
95
|
+
lines.push(`${i + 1}. File: \`${h.filePath}\` (${h.lineCount} lines)`);
|
|
96
|
+
lines.push(' Action: Bring file under 500 line budget by extracting helper functions, types, and child molecules.');
|
|
97
|
+
});
|
|
98
|
+
lines.push('');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (medium.length > 0) {
|
|
102
|
+
lines.push('### MEDIUM SEVERITY VIOLATIONS');
|
|
103
|
+
medium.forEach((v, i) => {
|
|
104
|
+
lines.push(`${i + 1}. \`${v.filePath}:${v.line}:${v.column}\` [${v.rule}]`);
|
|
105
|
+
lines.push(` Hazard: ${v.hazard}`);
|
|
106
|
+
lines.push(` Directive: ${v.directive}`);
|
|
107
|
+
});
|
|
108
|
+
lines.push('');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
lines.push('### STRICT EXECUTION RULES:');
|
|
112
|
+
lines.push('1. Zero raw inline styles: Replace style={{...}} with atom props, SCSS mixins (@include glass), or scoped BEM classes.');
|
|
113
|
+
lines.push('2. Extract anonymous inline callbacks into named functions before passing as props.');
|
|
114
|
+
lines.push('3. Co-locate granular types (*.d.ts) inside feature capsules (< 100 LOC). Avoid type monoliths.');
|
|
115
|
+
|
|
116
|
+
return lines.join('\n');
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export const buildGradeBPrompt = (report) => {
|
|
120
|
+
const { violations } = report;
|
|
121
|
+
const low = violations.filter((v) => v.severity === 'LOW');
|
|
122
|
+
|
|
123
|
+
if (low.length === 0) return '';
|
|
124
|
+
|
|
125
|
+
const lines = [];
|
|
126
|
+
lines.push('Act as a Clean Code Specialist. Clean up the following Grade B Low-Severity Hygiene Issues according to Chemical X standards:\n');
|
|
127
|
+
|
|
128
|
+
lines.push('### LOW HYGIENE VIOLATIONS');
|
|
129
|
+
low.forEach((v, i) => {
|
|
130
|
+
lines.push(`${i + 1}. \`${v.filePath}:${v.line}:${v.column}\` [${v.rule}]`);
|
|
131
|
+
lines.push(` Hazard: ${v.hazard}`);
|
|
132
|
+
lines.push(` Directive: ${v.directive}`);
|
|
133
|
+
});
|
|
134
|
+
lines.push('');
|
|
135
|
+
|
|
136
|
+
lines.push('### STRICT EXECUTION RULES:');
|
|
137
|
+
lines.push('1. Typography Hygiene: Replace all em dashes with standard hyphens (-) or colons (:).');
|
|
138
|
+
lines.push('2. Logging Hygiene: Remove unguarded console.log calls or route through central debug proxy.');
|
|
139
|
+
lines.push('3. FontAwesome Compliance: Remove text-* utility classes from icons; use :color prop or inline CSS.');
|
|
140
|
+
|
|
141
|
+
return lines.join('\n');
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export const buildMasterPrompt = (report) => {
|
|
145
|
+
const sections = [
|
|
146
|
+
buildGradeFPrompt(report),
|
|
147
|
+
buildGradeDPrompt(report),
|
|
148
|
+
buildGradeCPrompt(report),
|
|
149
|
+
buildGradeBPrompt(report)
|
|
150
|
+
].filter(Boolean);
|
|
151
|
+
|
|
152
|
+
if (sections.length === 0) return '';
|
|
153
|
+
|
|
154
|
+
const header = `Act as a Principal Systems Architect. Execute a phased architectural refactoring of our codebase according to Chemical X Molecular Architecture Standards.\n\n`;
|
|
155
|
+
return header + sections.join('\n\n---\n\n');
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export const formatPromptBox = (title, promptText) => {
|
|
159
|
+
if (!promptText) return '';
|
|
160
|
+
|
|
161
|
+
const lines = [];
|
|
162
|
+
lines.push(`\n ${CYAN}ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ${RESET}`);
|
|
163
|
+
lines.push(` ${CYAN}â${RESET} ${BOLD}${title}${RESET}`);
|
|
164
|
+
lines.push(` ${CYAN}â${RESET} ${DIM}Copy and paste the block below directly into Cursor / Claude / Windsurf:${RESET}`);
|
|
165
|
+
lines.push(` ${CYAN}ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤${RESET}`);
|
|
166
|
+
|
|
167
|
+
const promptLines = promptText.split('\n');
|
|
168
|
+
for (const pl of promptLines) {
|
|
169
|
+
lines.push(` ${CYAN}â${RESET} ${pl}`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
lines.push(` ${CYAN}ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ${RESET}\n`);
|
|
173
|
+
return lines.join('\n');
|
|
174
|
+
};
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildGradeFPrompt,
|
|
3
|
+
buildGradeDPrompt,
|
|
4
|
+
buildGradeCPrompt,
|
|
5
|
+
buildGradeBPrompt,
|
|
6
|
+
formatPromptBox
|
|
7
|
+
} from './prompts.js';
|
|
8
|
+
import {
|
|
9
|
+
CYAN,
|
|
10
|
+
GREEN,
|
|
11
|
+
YELLOW,
|
|
12
|
+
RED,
|
|
13
|
+
ORANGE,
|
|
14
|
+
DIM,
|
|
15
|
+
BOLD,
|
|
16
|
+
RESET,
|
|
17
|
+
groupViolationsBySeverity
|
|
18
|
+
} from './reporter-utils.js';
|
|
19
|
+
|
|
20
|
+
export const formatGradeFSection = (report) => {
|
|
21
|
+
const { violations, hotspots, pillars } = report;
|
|
22
|
+
const { critical } = groupViolationsBySeverity(violations);
|
|
23
|
+
const extremeMonoliths = hotspots.filter((h) => h.lineCount >= 2000);
|
|
24
|
+
const failedPillars = Object.entries(pillars || {}).filter(([_, p]) => p.status === 'FAILED');
|
|
25
|
+
const lines = [];
|
|
26
|
+
|
|
27
|
+
lines.push('');
|
|
28
|
+
lines.push(`${RED}======================================================================${RESET}`);
|
|
29
|
+
lines.push(`${BOLD}${RED} GRADE F : CRITICAL ARCHITECTURAL HAZARDS & EXTREME MONOLITHS${RESET}`);
|
|
30
|
+
lines.push(`${DIM} Immediate action required: >2,000 LOC monoliths, render hacks, mock data${RESET}`);
|
|
31
|
+
lines.push(`${RED}======================================================================${RESET}`);
|
|
32
|
+
lines.push(` Critical Violations: ${critical.length > 0 ? `${RED}${BOLD}${critical.length}${RESET}` : `${GREEN}0${RESET}`}`);
|
|
33
|
+
lines.push(` Extreme Monoliths: ${extremeMonoliths.length > 0 ? `${RED}${BOLD}${extremeMonoliths.length}${RESET}` : `${GREEN}0${RESET}`}`);
|
|
34
|
+
lines.push(` Failed Pillars: ${failedPillars.length > 0 ? `${RED}${BOLD}${failedPillars.length}${RESET}` : `${GREEN}0${RESET}`}`);
|
|
35
|
+
lines.push(`${RED}----------------------------------------------------------------------${RESET}`);
|
|
36
|
+
|
|
37
|
+
const totalGradeFItems = critical.length + extremeMonoliths.length + failedPillars.length;
|
|
38
|
+
if (totalGradeFItems === 0) {
|
|
39
|
+
lines.push(`\n ${GREEN}â Outstanding! Zero Grade F hazards detected.${RESET}`);
|
|
40
|
+
lines.push(` ${DIM}Codebase is free of extreme monoliths (>2k LOC) and critical violations.${RESET}`);
|
|
41
|
+
} else {
|
|
42
|
+
if (critical.length > 0) {
|
|
43
|
+
lines.push(`\n ${BOLD}${RED}đ¨ CRITICAL AST VIOLATIONS (${critical.length}):${RESET}`);
|
|
44
|
+
critical.forEach((v, idx) => {
|
|
45
|
+
lines.push(` ${RED}[#${idx + 1} CRITICAL]${RESET} [${v.rule}] ${YELLOW}${v.filePath}:${v.line}:${v.column}${RESET}`);
|
|
46
|
+
lines.push(` Hazard: ${v.hazard}`);
|
|
47
|
+
lines.push(` Directive: ${CYAN}${v.directive}${RESET}\n`);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (extremeMonoliths.length > 0) {
|
|
52
|
+
lines.push(` ${BOLD}${RED}đŖ EXTREME MONOLITHS (>= 2,000 LINES):${RESET}`);
|
|
53
|
+
lines.push(` ${DIM}Massive token burn files causing severe context rot and agent hallucination.${RESET}`);
|
|
54
|
+
extremeMonoliths.forEach((h, idx) => {
|
|
55
|
+
lines.push(` [#${idx + 1}] ${YELLOW}${h.filePath}${RESET} (${h.lineCount} lines, ${h.violationCount} hazards) ${RED}[EXTREME MONOLITH]${RESET}`);
|
|
56
|
+
});
|
|
57
|
+
lines.push('');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (failedPillars.length > 0) {
|
|
61
|
+
lines.push(` ${BOLD}${RED}đī¸ FAILED PILLARS (CRITICAL INFECTIONS):${RESET}`);
|
|
62
|
+
for (const [name, p] of failedPillars) {
|
|
63
|
+
lines.push(` â ${YELLOW}${name}${RESET}: ${p.violations} violations (${p.critical} Critical, ${p.high} High, ${p.medium} Med)`);
|
|
64
|
+
}
|
|
65
|
+
lines.push('');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const promptF = buildGradeFPrompt(report);
|
|
70
|
+
if (promptF) {
|
|
71
|
+
lines.push(formatPromptBox('đ¤ AI AGENT REFACTORING PROMPT (GRADE F HAZARDS)', promptF));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
lines.push(`${RED}======================================================================${RESET}\n`);
|
|
75
|
+
return lines.join('\n');
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const formatGradeDSection = (report) => {
|
|
79
|
+
const { violations, hotspots, pillars } = report;
|
|
80
|
+
const { high } = groupViolationsBySeverity(violations);
|
|
81
|
+
const severeMonoliths = hotspots.filter((h) => h.lineCount >= 1000 && h.lineCount < 2000);
|
|
82
|
+
const warnPillars = Object.entries(pillars || {}).filter(([_, p]) => p.status === 'WARN');
|
|
83
|
+
const lines = [];
|
|
84
|
+
|
|
85
|
+
lines.push('');
|
|
86
|
+
lines.push(`${ORANGE}======================================================================${RESET}`);
|
|
87
|
+
lines.push(`${BOLD}${ORANGE} GRADE D : HIGH SEVERITY DEBTS & SEVERE MONOLITHS${RESET}`);
|
|
88
|
+
lines.push(`${DIM} Refactoring priorities: 1,000 to 1,999 LOC files and hook saturation > 5${RESET}`);
|
|
89
|
+
lines.push(`${ORANGE}======================================================================${RESET}`);
|
|
90
|
+
lines.push(` High Severity Debts: ${high.length > 0 ? `${ORANGE}${BOLD}${high.length}${RESET}` : `${GREEN}0${RESET}`}`);
|
|
91
|
+
lines.push(` Severe Monoliths: ${severeMonoliths.length > 0 ? `${ORANGE}${BOLD}${severeMonoliths.length}${RESET}` : `${GREEN}0${RESET}`}`);
|
|
92
|
+
lines.push(` Degraded Pillars: ${warnPillars.length > 0 ? `${ORANGE}${BOLD}${warnPillars.length}${RESET}` : `${GREEN}0${RESET}`}`);
|
|
93
|
+
lines.push(`${ORANGE}----------------------------------------------------------------------${RESET}`);
|
|
94
|
+
|
|
95
|
+
const totalGradeDItems = high.length + severeMonoliths.length + warnPillars.length;
|
|
96
|
+
if (totalGradeDItems === 0) {
|
|
97
|
+
lines.push(`\n ${GREEN}â Zero Grade D debts detected.${RESET}`);
|
|
98
|
+
lines.push(` ${DIM}No severe monoliths (1k-2k LOC) or saturated hook anti-patterns.${RESET}`);
|
|
99
|
+
} else {
|
|
100
|
+
if (high.length > 0) {
|
|
101
|
+
lines.push(`\n ${BOLD}${ORANGE}â ī¸ HIGH SEVERITY VIOLATIONS (${high.length}):${RESET}`);
|
|
102
|
+
high.forEach((v, idx) => {
|
|
103
|
+
lines.push(` ${ORANGE}[#${idx + 1} HIGH]${RESET} [${v.rule}] ${YELLOW}${v.filePath}:${v.line}:${v.column}${RESET}`);
|
|
104
|
+
lines.push(` Hazard: ${v.hazard}`);
|
|
105
|
+
lines.push(` Directive: ${CYAN}${v.directive}${RESET}\n`);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (severeMonoliths.length > 0) {
|
|
110
|
+
lines.push(` ${BOLD}${ORANGE}đĨ SEVERE MONOLITHS (1,000 - 1,999 LINES):${RESET}`);
|
|
111
|
+
severeMonoliths.forEach((h, idx) => {
|
|
112
|
+
lines.push(` [#${idx + 1}] ${YELLOW}${h.filePath}${RESET} (${h.lineCount} lines, ${h.violationCount} hazards) ${ORANGE}[SEVERE MONOLITH]${RESET}`);
|
|
113
|
+
});
|
|
114
|
+
lines.push('');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (warnPillars.length > 0) {
|
|
118
|
+
lines.push(` ${BOLD}${ORANGE}đī¸ DEGRADED PILLARS (MULTIPLE HIGH/MED DEBTS):${RESET}`);
|
|
119
|
+
for (const [name, p] of warnPillars) {
|
|
120
|
+
lines.push(` â ${YELLOW}${name}${RESET}: ${p.violations} violations (${p.high} High, ${p.medium} Med)`);
|
|
121
|
+
}
|
|
122
|
+
lines.push('');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const promptD = buildGradeDPrompt(report);
|
|
127
|
+
if (promptD) {
|
|
128
|
+
lines.push(formatPromptBox('đ¤ AI AGENT REFACTORING PROMPT (GRADE D DEBTS)', promptD));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
lines.push(`${ORANGE}======================================================================${RESET}\n`);
|
|
132
|
+
return lines.join('\n');
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export const formatGradeCSection = (report) => {
|
|
136
|
+
const { violations, hotspots } = report;
|
|
137
|
+
const { medium } = groupViolationsBySeverity(violations);
|
|
138
|
+
const warningMonoliths = hotspots.filter((h) => h.lineCount >= 500 && h.lineCount < 1000);
|
|
139
|
+
const lines = [];
|
|
140
|
+
|
|
141
|
+
lines.push('');
|
|
142
|
+
lines.push(`${CYAN}======================================================================${RESET}`);
|
|
143
|
+
lines.push(`${BOLD}${CYAN} GRADE C : MEDIUM SEVERITY DEBTS & MONOLITHIC DRIFT${RESET}`);
|
|
144
|
+
lines.push(`${DIM} Architecture debts: 500 to 999 LOC files and raw inline style attributes${RESET}`);
|
|
145
|
+
lines.push(`${CYAN}======================================================================${RESET}`);
|
|
146
|
+
lines.push(` Medium Debts: ${medium.length > 0 ? `${YELLOW}${BOLD}${medium.length}${RESET}` : `${GREEN}0${RESET}`}`);
|
|
147
|
+
lines.push(` Warning Monoliths: ${warningMonoliths.length > 0 ? `${YELLOW}${BOLD}${warningMonoliths.length}${RESET}` : `${GREEN}0${RESET}`}`);
|
|
148
|
+
lines.push(`${CYAN}----------------------------------------------------------------------${RESET}`);
|
|
149
|
+
|
|
150
|
+
const totalGradeCItems = medium.length + warningMonoliths.length;
|
|
151
|
+
if (totalGradeCItems === 0) {
|
|
152
|
+
lines.push(`\n ${GREEN}â Zero Grade C debts detected.${RESET}`);
|
|
153
|
+
lines.push(` ${DIM}All files remain under 500 lines with clean styling and handlers.${RESET}`);
|
|
154
|
+
} else {
|
|
155
|
+
if (medium.length > 0) {
|
|
156
|
+
lines.push(`\n ${BOLD}${CYAN}⥠MEDIUM SEVERITY VIOLATIONS (${medium.length}):${RESET}`);
|
|
157
|
+
medium.forEach((v, idx) => {
|
|
158
|
+
lines.push(` ${YELLOW}[#${idx + 1} MED]${RESET} [${v.rule}] ${YELLOW}${v.filePath}:${v.line}:${v.column}${RESET}`);
|
|
159
|
+
lines.push(` Hazard: ${v.hazard}`);
|
|
160
|
+
lines.push(` Directive: ${CYAN}${v.directive}${RESET}\n`);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (warningMonoliths.length > 0) {
|
|
165
|
+
lines.push(` ${BOLD}${CYAN}â ī¸ WARNING MONOLITHS (500 - 999 LINES):${RESET}`);
|
|
166
|
+
warningMonoliths.forEach((h, idx) => {
|
|
167
|
+
lines.push(` [#${idx + 1}] ${YELLOW}${h.filePath}${RESET} (${h.lineCount} lines, ${h.violationCount} hazards) ${DIM}[MONOLITH WARNING]${RESET}`);
|
|
168
|
+
});
|
|
169
|
+
lines.push('');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const promptC = buildGradeCPrompt(report);
|
|
174
|
+
if (promptC) {
|
|
175
|
+
lines.push(formatPromptBox('đ¤ AI AGENT REFACTORING PROMPT (GRADE C DEBTS)', promptC));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
lines.push(`${CYAN}======================================================================${RESET}\n`);
|
|
179
|
+
return lines.join('\n');
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export const formatGradeBSection = (report) => {
|
|
183
|
+
const { violations } = report;
|
|
184
|
+
const { low } = groupViolationsBySeverity(violations);
|
|
185
|
+
const lines = [];
|
|
186
|
+
|
|
187
|
+
lines.push('');
|
|
188
|
+
lines.push(`${YELLOW}======================================================================${RESET}`);
|
|
189
|
+
lines.push(`${BOLD}${YELLOW} GRADE B : LOW SEVERITY HYGIENE & MINOR CODE SMELLS${RESET}`);
|
|
190
|
+
lines.push(`${DIM} Hygiene & polish: Em dash typography leaks and unguarded console logging${RESET}`);
|
|
191
|
+
lines.push(`${YELLOW}======================================================================${RESET}`);
|
|
192
|
+
lines.push(` Low Hygiene Issues: ${low.length > 0 ? `${YELLOW}${BOLD}${low.length}${RESET}` : `${GREEN}0${RESET}`}`);
|
|
193
|
+
lines.push(`${YELLOW}----------------------------------------------------------------------${RESET}`);
|
|
194
|
+
|
|
195
|
+
if (low.length === 0) {
|
|
196
|
+
lines.push(`\n ${GREEN}â Outstanding hygiene! Zero Grade B issues detected.${RESET}`);
|
|
197
|
+
lines.push(` ${DIM}Zero em dashes and zero unguarded console statements found.${RESET}`);
|
|
198
|
+
} else {
|
|
199
|
+
lines.push(`\n ${BOLD}${YELLOW}âšī¸ LOW HYGIENE VIOLATIONS (${low.length}):${RESET}`);
|
|
200
|
+
low.forEach((v, idx) => {
|
|
201
|
+
lines.push(` ${YELLOW}[#${idx + 1} LOW]${RESET} [${v.rule}] ${YELLOW}${v.filePath}:${v.line}:${v.column}${RESET}`);
|
|
202
|
+
lines.push(` Hazard: ${v.hazard}`);
|
|
203
|
+
lines.push(` Directive: ${CYAN}${v.directive}${RESET}\n`);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const promptB = buildGradeBPrompt(report);
|
|
208
|
+
if (promptB) {
|
|
209
|
+
lines.push(formatPromptBox('đ¤ AI AGENT REFACTORING PROMPT (GRADE B HYGIENE)', promptB));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
lines.push(`${YELLOW}======================================================================${RESET}\n`);
|
|
213
|
+
return lines.join('\n');
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
export const formatGradeASection = (report) => {
|
|
217
|
+
const { metrics, health, pillars, hotspots, contextAnalysis } = report;
|
|
218
|
+
const passedPillars = Object.entries(pillars || {}).filter(([_, p]) => p.status === 'PASSED');
|
|
219
|
+
const lines = [];
|
|
220
|
+
|
|
221
|
+
lines.push('');
|
|
222
|
+
lines.push(`${GREEN}======================================================================${RESET}`);
|
|
223
|
+
lines.push(`${BOLD}${GREEN} GRADE A : COMPLIANT ARCHITECTURE & PASSING PILLARS${RESET}`);
|
|
224
|
+
lines.push(`${DIM} Molecular Architecture verified clean areas and crystalline modules${RESET}`);
|
|
225
|
+
lines.push(`${GREEN}======================================================================${RESET}`);
|
|
226
|
+
lines.push(` Molecular Health Score: ${BOLD}${GREEN}${health.score}/100${RESET} [Grade: ${BOLD}${GREEN}${health.grade}${RESET}]`);
|
|
227
|
+
lines.push(` Passing Pillars: ${BOLD}${GREEN}${passedPillars.length} / 7 Pillars PASSED${RESET}`);
|
|
228
|
+
lines.push(` Capsule Compliance: ${BOLD}${GREEN}${metrics.moleculeCompliantPct}%${RESET} compliant (< 100 LOC)`);
|
|
229
|
+
lines.push(`${GREEN}----------------------------------------------------------------------${RESET}`);
|
|
230
|
+
|
|
231
|
+
lines.push(`\n ${BOLD}${GREEN}â COMPLIANT PILLARS (${passedPillars.length} / 7):${RESET}`);
|
|
232
|
+
if (passedPillars.length === 0) {
|
|
233
|
+
lines.push(` ${YELLOW}No pillars are currently 100% compliant.${RESET}\n`);
|
|
234
|
+
} else {
|
|
235
|
+
for (const [name] of passedPillars) {
|
|
236
|
+
lines.push(` ${GREEN}â${RESET} ${name} ${DIM}(0 violations)${RESET}`);
|
|
237
|
+
}
|
|
238
|
+
lines.push('');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
lines.push(` ${BOLD}${CYAN}STANDARDS MET & CLEAN CODEBASE ASSETS:${RESET}`);
|
|
242
|
+
if (metrics.moleculeCompliantPct === 100) {
|
|
243
|
+
lines.push(` ${GREEN}â${RESET} 100% Molecule Capsule Limit (< 100 lines per molecule)`);
|
|
244
|
+
}
|
|
245
|
+
const hasExtremeMonolith = hotspots.some((h) => h.lineCount >= 2000);
|
|
246
|
+
if (!hasExtremeMonolith) {
|
|
247
|
+
lines.push(` ${GREEN}â${RESET} Zero Extreme Monoliths (0 files >= 2,000 LOC)`);
|
|
248
|
+
}
|
|
249
|
+
const hasSevereMonolith = hotspots.some((h) => h.lineCount >= 1000);
|
|
250
|
+
if (!hasSevereMonolith) {
|
|
251
|
+
lines.push(` ${GREEN}â${RESET} Zero Severe Monoliths (0 files >= 1,000 LOC)`);
|
|
252
|
+
}
|
|
253
|
+
if (contextAnalysis.riskLevel === 'LOW') {
|
|
254
|
+
lines.push(` ${GREEN}â${RESET} Low Context Hazard & Token Burn Risk`);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
lines.push(`\n${GREEN}======================================================================${RESET}\n`);
|
|
258
|
+
return lines.join('\n');
|
|
259
|
+
};
|