@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.
Files changed (40) hide show
  1. package/cli/audit/ast-visitors.js +243 -0
  2. package/cli/audit/discussion-store.js +39 -0
  3. package/cli/audit/history.d.ts +63 -0
  4. package/cli/audit/history.js +352 -0
  5. package/cli/audit/metrics.js +179 -0
  6. package/cli/audit/prompts.js +174 -0
  7. package/cli/audit/reporter-grades.js +259 -0
  8. package/cli/audit/reporter-markdown.js +136 -0
  9. package/cli/audit/reporter-utils.js +107 -0
  10. package/cli/audit/reporter.js +459 -0
  11. package/cli/audit/rules-helpers.js +109 -0
  12. package/cli/audit/rules-registry.js +97 -0
  13. package/cli/audit/rules.js +123 -0
  14. package/cli/audit/social-constants.js +4 -0
  15. package/cli/audit/social-gh.js +126 -0
  16. package/cli/audit/social-git.js +214 -0
  17. package/cli/audit/social-http.js +222 -0
  18. package/cli/audit/social-publisher.js +193 -0
  19. package/cli/audit/social.d.ts +66 -0
  20. package/cli/audit/social.js +254 -0
  21. package/cli/audit/types.d.ts +131 -0
  22. package/cli/audit.d.ts +3 -24
  23. package/cli/audit.js +195 -210
  24. package/cli/help.d.ts +1 -0
  25. package/cli/help.js +136 -0
  26. package/cli/index.js +128 -566
  27. package/cli/installer-templates.js +80 -0
  28. package/cli/installer.d.ts +20 -0
  29. package/cli/installer.js +56 -0
  30. package/cli/license.js +320 -0
  31. package/cli/navigator-conversion.js +100 -0
  32. package/cli/navigator-grades.js +70 -0
  33. package/cli/navigator-paged.js +86 -0
  34. package/cli/navigator-share.js +129 -0
  35. package/cli/navigator.d.ts +24 -0
  36. package/cli/navigator.js +400 -0
  37. package/cli/scaffold.js +148 -0
  38. package/cli/terminal.js +126 -0
  39. package/docs/CHANGELOG.md +73 -0
  40. package/package.json +11 -10
@@ -0,0 +1,459 @@
1
+ import { PILLARS } from './rules.js';
2
+ import {
3
+ buildMasterPrompt,
4
+ formatPromptBox
5
+ } from './prompts.js';
6
+ import {
7
+ CYAN,
8
+ GREEN,
9
+ YELLOW,
10
+ RED,
11
+ ORANGE,
12
+ DIM,
13
+ BOLD,
14
+ RESET,
15
+ groupViolationsBySeverity,
16
+ getStatusBadge,
17
+ resolveGradeColor,
18
+ resolveRiskColor,
19
+ resolveHotspotBadge
20
+ } from './reporter-utils.js';
21
+
22
+ export {
23
+ groupViolationsBySeverity,
24
+ getSeverityBadge,
25
+ getStatusBadge,
26
+ resolveGradeColor,
27
+ resolveRiskColor,
28
+ resolveHotspotBadge,
29
+ resolveMarkdownStatusIcon,
30
+ resolveMarkdownMonolithText,
31
+ PILLAR_EMOJIS,
32
+ NUMBER_EMOJIS,
33
+ resolvePriorityBadge,
34
+ CYAN,
35
+ GREEN,
36
+ YELLOW,
37
+ RED,
38
+ ORANGE,
39
+ DIM,
40
+ BOLD,
41
+ RESET
42
+ } from './reporter-utils.js';
43
+
44
+ export { generateMarkdownReport } from './reporter-markdown.js';
45
+
46
+ export {
47
+ formatGradeFSection,
48
+ formatGradeDSection,
49
+ formatGradeCSection,
50
+ formatGradeBSection,
51
+ formatGradeASection
52
+ } from './reporter-grades.js';
53
+
54
+ export const resolveTopSectionColor = (report) => {
55
+ const hasNoViolations = (report?.violations?.length ?? 0) === 0;
56
+ const hasNoHotspots = (report?.hotspots?.length ?? 0) === 0;
57
+ const areAllPillarsPassed = Object.values(report?.pillars ?? {}).every((p) => p.status === 'PASSED');
58
+ const isAllPassed = hasNoViolations && hasNoHotspots && areAllPillarsPassed;
59
+ return isAllPassed ? GREEN : CYAN;
60
+ };
61
+
62
+ export const formatScorecardSection = (report, themeColor = null) => {
63
+ const { metrics, health } = report;
64
+ const sectionColor = themeColor || resolveTopSectionColor(report);
65
+ const gradeColor = resolveGradeColor(health.score);
66
+ const lines = [];
67
+
68
+ lines.push('');
69
+ lines.push(`${sectionColor}======================================================================${RESET}`);
70
+ lines.push(`${BOLD}${sectionColor} MOLECULAR HEALTH INDEX & CODEBASE OVERVIEW${RESET}`);
71
+ lines.push(`${sectionColor}======================================================================${RESET}`);
72
+ lines.push(` Health Score: ${gradeColor}${BOLD}${health.score} / 100${RESET} (Grade: ${gradeColor}${BOLD}${health.grade}${RESET} - ${health.label})`);
73
+ lines.push(` Files Scanned: ${BOLD}${metrics.scannedFiles}${RESET} source files`);
74
+ lines.push(` Total Lines of Code: ${BOLD}${metrics.totalLoc}${RESET} LOC (avg: ${metrics.avgLoc} lines/file)`);
75
+ lines.push(` Largest File: ${BOLD}${metrics.largestFile.filePath || 'None'}${RESET} (${metrics.largestFile.lineCount} lines)`);
76
+ lines.push(` Molecule Capsules: ${metrics.moleculeCount} found (${metrics.moleculeCompliantPct}% compliant < 100 lines)`);
77
+ lines.push(` Custom Hooks: ${metrics.hookCount} detected`);
78
+ lines.push(`${sectionColor}======================================================================${RESET}\n`);
79
+
80
+ return lines.join('\n');
81
+ };
82
+
83
+ export const formatCriticalSection = (report) => {
84
+ const { violations } = report;
85
+ const { critical } = groupViolationsBySeverity(violations);
86
+ const lines = [];
87
+
88
+ lines.push('');
89
+ lines.push(`${RED}======================================================================${RESET}`);
90
+ lines.push(`${BOLD}${RED} CRITICAL HAZARDS (${critical.length} TOTAL) : IMMEDIATE ACTION REQUIRED${RESET}`);
91
+ lines.push(`${DIM} Violations that break Molecular line budgets or introduce severe AST bugs${RESET}`);
92
+ lines.push(`${RED}======================================================================${RESET}`);
93
+
94
+ if (critical.length === 0) {
95
+ lines.push(` ${GREEN}✔ Zero critical hazards detected. No monoliths or breaking AST patterns.${RESET}`);
96
+ } else {
97
+ critical.forEach((v, idx) => {
98
+ lines.push(` ${RED}[#${idx + 1} CRITICAL]${RESET} [${v.rule}] ${YELLOW}${v.filePath}:${v.line}:${v.column}${RESET}`);
99
+ lines.push(` Hazard: ${v.hazard}`);
100
+ lines.push(` Directive: ${CYAN}${v.directive}${RESET}\n`);
101
+ });
102
+ }
103
+ lines.push(`${RED}======================================================================${RESET}\n`);
104
+
105
+ return lines.join('\n');
106
+ };
107
+
108
+ export const formatHighMediumSection = (report) => {
109
+ const { violations } = report;
110
+ const { high, medium } = groupViolationsBySeverity(violations);
111
+ const totalCount = high.length + medium.length;
112
+ const lines = [];
113
+
114
+ lines.push('');
115
+ lines.push(`${ORANGE}======================================================================${RESET}`);
116
+ lines.push(`${BOLD}${ORANGE} HIGH & MEDIUM HAZARDS (${totalCount} TOTAL) : ARCHITECTURE DEBTS${RESET}`);
117
+ lines.push(`${DIM} Saturation, complex control flow booleans, and raw inline styles${RESET}`);
118
+ lines.push(`${ORANGE}======================================================================${RESET}`);
119
+
120
+ if (totalCount === 0) {
121
+ lines.push(` ${GREEN}✔ Zero high or medium architecture hazards detected.${RESET}`);
122
+ } else {
123
+ if (high.length > 0) {
124
+ lines.push(`\n ${BOLD}--- High Severity (${high.length} items) ---${RESET}`);
125
+ high.forEach((v, idx) => {
126
+ lines.push(` ${ORANGE}[#${idx + 1} HIGH]${RESET} [${v.rule}] ${YELLOW}${v.filePath}:${v.line}:${v.column}${RESET}`);
127
+ lines.push(` Hazard: ${v.hazard}`);
128
+ lines.push(` Directive: ${CYAN}${v.directive}${RESET}\n`);
129
+ });
130
+ }
131
+
132
+ if (medium.length > 0) {
133
+ lines.push(`\n ${BOLD}--- Medium Severity (${medium.length} items) ---${RESET}`);
134
+ medium.forEach((v, idx) => {
135
+ lines.push(` ${ORANGE}[#${idx + 1} MED]${RESET} [${v.rule}] ${YELLOW}${v.filePath}:${v.line}:${v.column}${RESET}`);
136
+ lines.push(` Hazard: ${v.hazard}`);
137
+ lines.push(` Directive: ${CYAN}${v.directive}${RESET}\n`);
138
+ });
139
+ }
140
+ }
141
+ lines.push(`${ORANGE}======================================================================${RESET}\n`);
142
+
143
+ return lines.join('\n');
144
+ };
145
+
146
+ export const formatLowSection = (report) => {
147
+ const { violations } = report;
148
+ const { low } = groupViolationsBySeverity(violations);
149
+ const lines = [];
150
+
151
+ lines.push('');
152
+ lines.push(`${YELLOW}======================================================================${RESET}`);
153
+ lines.push(`${BOLD}${YELLOW} LOW & HYGIENE ISSUES (${low.length} TOTAL) : TYPOGRAPHY & LOGGING${RESET}`);
154
+ lines.push(`${DIM} Em dash typography violations and unguarded console statements${RESET}`);
155
+ lines.push(`${YELLOW}======================================================================${RESET}`);
156
+
157
+ if (low.length === 0) {
158
+ lines.push(` ${GREEN}✔ Zero typography or logging hygiene issues detected.${RESET}`);
159
+ } else {
160
+ low.forEach((v, idx) => {
161
+ lines.push(` ${YELLOW}[#${idx + 1} LOW]${RESET} [${v.rule}] ${YELLOW}${v.filePath}:${v.line}:${v.column}${RESET}`);
162
+ lines.push(` Hazard: ${v.hazard}`);
163
+ lines.push(` Directive: ${CYAN}${v.directive}${RESET}\n`);
164
+ });
165
+ }
166
+ lines.push(`${YELLOW}======================================================================${RESET}\n`);
167
+
168
+ return lines.join('\n');
169
+ };
170
+
171
+ export const formatPillarsSection = (report, themeColor = null) => {
172
+ const { pillars } = report;
173
+ const sectionColor = themeColor || resolveTopSectionColor(report);
174
+ const lines = [];
175
+
176
+ lines.push('');
177
+ lines.push(`${sectionColor}======================================================================${RESET}`);
178
+ lines.push(`${BOLD}${sectionColor} 7-PILLAR ARCHITECTURAL COMPLIANCE MATRIX${RESET}`);
179
+ lines.push(`${sectionColor}======================================================================${RESET}`);
180
+ lines.push(` ${DIM}Pillar Name Status Violations${RESET}`);
181
+ lines.push(` ${DIM}------------------------------------------------------------------${RESET}`);
182
+ for (const [pillarName, data] of Object.entries(pillars)) {
183
+ const padName = pillarName.padEnd(45, ' ');
184
+ const badge = getStatusBadge(data.status).padEnd(16, ' ');
185
+ const countStr = data.violations === 0 ? `${GREEN}0${RESET}` : `${RED}${data.violations}${RESET}`;
186
+ lines.push(` ${padName} ${badge} ${countStr}`);
187
+ }
188
+ lines.push(`${sectionColor}======================================================================${RESET}\n`);
189
+
190
+ return lines.join('\n');
191
+ };
192
+
193
+ export const formatHotspotsSection = (report, themeColor = null) => {
194
+ const { hotspots } = report;
195
+ const sectionColor = themeColor || resolveTopSectionColor(report);
196
+ const lines = [];
197
+
198
+ lines.push('');
199
+ lines.push(`${sectionColor}======================================================================${RESET}`);
200
+ lines.push(`${BOLD}${sectionColor} TOP REFACTORING HOTSPOTS (PRIORITY RANKING)${RESET}`);
201
+ lines.push(`${sectionColor}======================================================================${RESET}`);
202
+
203
+ if (hotspots.length === 0) {
204
+ lines.push(` ${GREEN}✔ Zero hotspot files. All files stay within architectural budgets.${RESET}`);
205
+ } else {
206
+ hotspots.forEach((h, idx) => {
207
+ const monolithBadge = resolveHotspotBadge(h.lineCount);
208
+ lines.push(` [#${idx + 1}] ${YELLOW}${h.filePath}${RESET} (${h.lineCount} lines, ${h.violationCount} hazards)${monolithBadge}`);
209
+ });
210
+ }
211
+ lines.push(`${sectionColor}======================================================================${RESET}\n`);
212
+
213
+ return lines.join('\n');
214
+ };
215
+
216
+ export const formatContextAnalysisSection = (report, themeColor = null) => {
217
+ const { contextAnalysis } = report;
218
+ const sectionColor = themeColor || resolveTopSectionColor(report);
219
+ const riskColor = resolveRiskColor(contextAnalysis.riskLevel);
220
+ const lines = [];
221
+
222
+ lines.push('');
223
+ lines.push(`${sectionColor}======================================================================${RESET}`);
224
+ lines.push(`${BOLD}${sectionColor} CONTEXT ROT & TOKEN BURN ANALYTICS${RESET}`);
225
+ lines.push(`${sectionColor}======================================================================${RESET}`);
226
+ lines.push(` Estimated Codebase Tokens: ~${contextAnalysis.estimatedTokens.toLocaleString()} tokens`);
227
+ lines.push(` Estimated Monolith Bloat: ~${contextAnalysis.estimatedExcessTokens.toLocaleString()} tokens`);
228
+ lines.push(` Target Architecture Cut: ${BOLD}${contextAnalysis.potentialSavingsPct}%${RESET} token reduction potential`);
229
+ lines.push(` Agent Hallucination Risk: ${riskColor}${BOLD}${contextAnalysis.riskLevel}${RESET}`);
230
+ if (contextAnalysis.excessCostPerPass !== undefined) {
231
+ const costPass = contextAnalysis.excessCostPerPass.toFixed(3);
232
+ const costMonth = contextAnalysis.monthlyWastePerDev.toFixed(2);
233
+ const costWeek = contextAnalysis.weeklyWastePerDev.toFixed(2);
234
+ lines.push(` Pricing Model Baseline: ${contextAnalysis.pricingModel}`);
235
+ lines.push(` Monolith Bloat per AI Turn: \x1b[38;5;208;1m$${costPass}\x1b[0m / prompt turn`);
236
+ lines.push(` Projected Dev Context Tax: \x1b[31;1m$${costMonth}/mo\x1b[0m per engineer ($${costWeek}/wk)`);
237
+ }
238
+ lines.push(`${sectionColor}======================================================================${RESET}\n`);
239
+
240
+ return lines.join('\n');
241
+ };
242
+
243
+ export const getChemicalXAsciiBanner = (gradeOrReport = null) => {
244
+ const grade = typeof gradeOrReport === 'object' && gradeOrReport !== null
245
+ ? gradeOrReport.health?.grade
246
+ : gradeOrReport;
247
+
248
+ const art = [
249
+ ' ██████╗██╗ ██╗███████╗███╗ ███╗██╗ ██████╗ █████╗ ██╗ ██╗ ██╗',
250
+ '██╔════╝██║ ██║██╔════╝████╗ ████║██║██╔════╝██╔══██╗██║ ╚██╗██╔╝',
251
+ '██║ ███████║█████╗ ██╔████╔██║██║██║ ███████║██║ ╚███╔╝ ',
252
+ '██║ ██╔══██║██╔══╝ ██║╚██╔╝██║██║██║ ██╔══██║██║ ██╔██╗ ',
253
+ '╚██████╗██║ ██║███████╗██║ ╚═╝ ██║██║╚██████╗██║ ██║███████╗ ██╔╝ ██╗',
254
+ ' ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝'
255
+ ];
256
+
257
+ const maxLen = 74;
258
+ const lines = [];
259
+
260
+ lines.push(' \x1b[1m\x1b[37mThe Secret Sauce to \x1b[38;2;98;201;255mVibe Coding\x1b[0m');
261
+
262
+ for (let lineIdx = 0; lineIdx < art.length; lineIdx++) {
263
+ const line = art[lineIdx];
264
+ let out = '';
265
+ for (let i = 0; i < line.length; i++) {
266
+ const ch = line[i];
267
+ if (ch === ' ') {
268
+ out += ' ';
269
+ continue;
270
+ }
271
+ const t = i / (maxLen - 1);
272
+ let r, g, b;
273
+ if (t < 0.5) {
274
+ const factor = t * 2;
275
+ r = Math.round(244 * (1 - factor) + 192 * factor);
276
+ g = Math.round(114 * (1 - factor) + 132 * factor);
277
+ b = Math.round(182 * (1 - factor) + 252 * factor);
278
+ } else {
279
+ const factor = (t - 0.5) * 2;
280
+ r = Math.round(192 * (1 - factor) + 129 * factor);
281
+ g = Math.round(132 * (1 - factor) + 140 * factor);
282
+ b = Math.round(252 * (1 - factor) + 248 * factor);
283
+ }
284
+ out += `\x1b[38;2;${r};${g};${b}m\x1b[1m${ch}\x1b[0m`;
285
+ }
286
+
287
+ if (grade && lineIdx === 2) {
288
+ const gColor = resolveGradeColor(grade);
289
+ out += ` \x1b[1m\x1b[37m=\x1b[0m ${gColor}\x1b[1mGrade ${grade}\x1b[0m`;
290
+ }
291
+
292
+ lines.push(out);
293
+ }
294
+
295
+ const subtitle = 'Architectural guardrails to eliminate token burn and AI hallucinations.';
296
+ const pad = ' '.repeat(Math.max(0, Math.floor((maxLen - subtitle.length) / 2)));
297
+ lines.push(`${pad}\x1b[2m${subtitle}\x1b[0m\n`);
298
+ return lines.join('\n');
299
+ };
300
+
301
+ export const formatTerminalReport = (report) => {
302
+ const lines = [];
303
+ const topColor = resolveTopSectionColor(report);
304
+
305
+ lines.push('');
306
+ lines.push(getChemicalXAsciiBanner(report?.health?.grade));
307
+ lines.push(`${topColor}======================================================================${RESET}`);
308
+ lines.push(`${BOLD}${topColor} CHEMICAL X PROTOCOL : FULL CODEBASE ARCHITECTURAL AUDIT REPORT${RESET}`);
309
+ lines.push(`${DIM} Molecular Architecture Standards & Context Hazard Verification${RESET}`);
310
+ lines.push(`${topColor}======================================================================${RESET}`);
311
+
312
+ lines.push(formatScorecardSection(report, topColor));
313
+ lines.push(formatContextAnalysisSection(report, topColor));
314
+ lines.push(formatPillarsSection(report, topColor));
315
+ lines.push(formatHotspotsSection(report, topColor));
316
+ lines.push(formatCriticalSection(report));
317
+ lines.push(formatHighMediumSection(report));
318
+ lines.push(formatLowSection(report));
319
+
320
+ const masterPrompt = buildMasterPrompt(report);
321
+ if (masterPrompt) {
322
+ lines.push(formatPromptBox('🤖 MASTER AI AGENT REFACTORING PROMPT', masterPrompt));
323
+ }
324
+
325
+ return lines.join('\n');
326
+ };
327
+
328
+ export const formatFailuresSection = (report) => {
329
+ const { violations, pillars, hotspots } = report;
330
+ const { critical, high, medium, low } = groupViolationsBySeverity(violations);
331
+ const lines = [];
332
+
333
+ lines.push('');
334
+ lines.push(`${RED}======================================================================${RESET}`);
335
+ lines.push(`${BOLD}${RED} FAILED & DEGRADED CHECKS : HAZARDS, DEBTS & HOTSPOTS${RESET}`);
336
+ lines.push(`${DIM} Consolidated breakdown of all failed architectural checks${RESET}`);
337
+ lines.push(`${RED}======================================================================${RESET}`);
338
+
339
+ if (violations.length === 0 && hotspots.length === 0) {
340
+ lines.push(`\n ${GREEN}${BOLD}✔ ZERO FAILURES DETECTED!${RESET}`);
341
+ lines.push(' All 7 Chemical X Molecular Architecture Pillars are 100% Compliant.\n');
342
+ lines.push(`${RED}======================================================================${RESET}\n`);
343
+ return lines.join('\n');
344
+ }
345
+
346
+ lines.push(` Total Hazards Flagged: ${BOLD}${RED}${violations.length}${RESET}`);
347
+ const critDesc = critical.length > 0 ? `${RED}${BOLD}${critical.length} (Immediate Action Required)${RESET}` : `${GREEN}0${RESET}`;
348
+ lines.push(` Critical Hazards: ${critDesc}`);
349
+ const debtsTotal = high.length + medium.length;
350
+ const debtsDesc = debtsTotal > 0 ? `${ORANGE}${BOLD}${debtsTotal}${RESET}` : `${GREEN}0${RESET}`;
351
+ lines.push(` High/Med Debts: ${debtsDesc}`);
352
+ const lowDesc = low.length > 0 ? `${YELLOW}${low.length}${RESET}` : `${GREEN}0${RESET}`;
353
+ lines.push(` Low Hygiene Issues: ${lowDesc}`);
354
+ const hotspotsDesc = hotspots.length > 0 ? `${YELLOW}${hotspots.length}${RESET}` : `${GREEN}0${RESET}`;
355
+ lines.push(` Hotspot Files: ${hotspotsDesc}`);
356
+ lines.push(`${RED}----------------------------------------------------------------------${RESET}`);
357
+
358
+ if (critical.length > 0) {
359
+ lines.push(`\n ${BOLD}${RED}🚨 CRITICAL HAZARDS (${critical.length}) : IMMEDIATE ACTION REQUIRED${RESET}`);
360
+ critical.forEach((v, idx) => {
361
+ lines.push(` ${RED}[#${idx + 1} CRITICAL]${RESET} [${v.rule}] ${YELLOW}${v.filePath}:${v.line}:${v.column}${RESET}`);
362
+ lines.push(` Hazard: ${v.hazard}`);
363
+ lines.push(` Directive: ${CYAN}${v.directive}${RESET}\n`);
364
+ });
365
+ }
366
+
367
+ if (debtsTotal > 0) {
368
+ lines.push(` ${BOLD}${ORANGE}⚠️ HIGH & MEDIUM HAZARDS (${debtsTotal}) : ARCHITECTURE DEBTS${RESET}`);
369
+ [...high, ...medium].forEach((v, idx) => {
370
+ const isHigh = v.severity === 'HIGH';
371
+ const badge = isHigh ? `${ORANGE}[#${idx + 1} HIGH]${RESET}` : `${ORANGE}[#${idx + 1} MED]${RESET}`;
372
+ lines.push(` ${badge} [${v.rule}] ${YELLOW}${v.filePath}:${v.line}:${v.column}${RESET}`);
373
+ lines.push(` Hazard: ${v.hazard}`);
374
+ lines.push(` Directive: ${CYAN}${v.directive}${RESET}\n`);
375
+ });
376
+ }
377
+
378
+ if (low.length > 0) {
379
+ lines.push(` ${BOLD}${YELLOW}🧹 LOW & HYGIENE ISSUES (${low.length})${RESET}`);
380
+ low.forEach((v, idx) => {
381
+ lines.push(` ${YELLOW}[#${idx + 1} LOW]${RESET} [${v.rule}] ${YELLOW}${v.filePath}:${v.line}:${v.column}${RESET}`);
382
+ lines.push(` Hazard: ${v.hazard}`);
383
+ lines.push(` Directive: ${CYAN}${v.directive}${RESET}\n`);
384
+ });
385
+ }
386
+
387
+ const failedPillars = Object.entries(pillars).filter(([_, p]) => p.status !== 'PASSED');
388
+ if (failedPillars.length > 0) {
389
+ lines.push(` ${BOLD}${RED}🏛️ FAILED / DEGRADED PILLARS (${failedPillars.length})${RESET}`);
390
+ for (const [name, p] of failedPillars) {
391
+ lines.push(` ✕ ${YELLOW}${name}${RESET}: ${p.violations} violations (${p.critical} Critical, ${p.high} High, ${p.medium} Med)`);
392
+ }
393
+ lines.push('');
394
+ }
395
+
396
+ if (hotspots.length > 0) {
397
+ lines.push(` ${BOLD}${YELLOW}🔥 REFACTORING HOTSPOTS (${hotspots.length})${RESET}`);
398
+ hotspots.forEach((h, idx) => {
399
+ const monolithBadge = resolveHotspotBadge(h.lineCount);
400
+ lines.push(` [#${idx + 1}] ${YELLOW}${h.filePath}${RESET} (${h.lineCount} lines, ${h.violationCount} hazards)${monolithBadge}`);
401
+ });
402
+ lines.push('');
403
+ }
404
+
405
+ const prompt = buildMasterPrompt(report);
406
+ if (prompt) {
407
+ lines.push(formatPromptBox('🤖 AI AGENT REFACTORING PROMPT (ALL FAILED CHECKS)', prompt));
408
+ }
409
+
410
+ lines.push(`${RED}======================================================================${RESET}\n`);
411
+ return lines.join('\n');
412
+ };
413
+
414
+ export const formatPassesSection = (report) => {
415
+ const { metrics, health, pillars, hotspots, contextAnalysis } = report;
416
+ const passedPillars = Object.entries(pillars).filter(([_, p]) => p.status === 'PASSED');
417
+ const lines = [];
418
+
419
+ lines.push('');
420
+ lines.push(`${GREEN}======================================================================${RESET}`);
421
+ lines.push(`${BOLD}${GREEN} PASSED & COMPLIANT CHECKS : CLEAN ARCHITECTURE STANDARDS${RESET}`);
422
+ lines.push(`${DIM} Consolidated breakdown of verified compliant areas${RESET}`);
423
+ lines.push(`${GREEN}======================================================================${RESET}`);
424
+
425
+ lines.push(` Molecular Health Score: ${BOLD}${GREEN}${health.score}/100${RESET} [Grade: ${BOLD}${GREEN}${health.grade}${RESET}]`);
426
+ lines.push(` Passing Pillars: ${BOLD}${GREEN}${passedPillars.length} / 7 Pillars PASSED${RESET}`);
427
+ lines.push(` Capsule Compliance: ${BOLD}${GREEN}${metrics.moleculeCompliantPct}%${RESET} molecules compliant (< 100 LOC)`);
428
+ lines.push(` Total Files Scanned: ${metrics.scannedFiles} source files (${metrics.totalLoc} total LOC)`);
429
+ lines.push(`${GREEN}----------------------------------------------------------------------${RESET}`);
430
+
431
+ lines.push(`\n ${BOLD}${GREEN}✔ COMPLIANT ARCHITECTURAL PILLARS:${RESET}`);
432
+ if (passedPillars.length === 0) {
433
+ lines.push(` ${YELLOW}No pillars are completely hazard-free.${RESET}\n`);
434
+ } else {
435
+ for (const [name] of passedPillars) {
436
+ lines.push(` ${GREEN}✔${RESET} ${name} ${DIM}(0 violations)${RESET}`);
437
+ }
438
+ lines.push('');
439
+ }
440
+
441
+ lines.push(` ${BOLD}${CYAN}STANDARDS MET & CLEAN AREAS:${RESET}`);
442
+ if (metrics.moleculeCompliantPct === 100) {
443
+ lines.push(` ${GREEN}✔${RESET} 100% Molecule Capsule Limit (< 100 lines per molecule)`);
444
+ }
445
+ const hasExtremeMonolith = hotspots.some((h) => h.lineCount >= 2000);
446
+ if (!hasExtremeMonolith) {
447
+ lines.push(` ${GREEN}✔${RESET} Zero Extreme Monoliths (0 files >= 2,000 LOC)`);
448
+ }
449
+ const hasSevereMonolith = hotspots.some((h) => h.lineCount >= 1000);
450
+ if (!hasSevereMonolith) {
451
+ lines.push(` ${GREEN}✔${RESET} Zero Severe Monoliths (0 files >= 1,000 LOC)`);
452
+ }
453
+ if (contextAnalysis.riskLevel === 'LOW') {
454
+ lines.push(` ${GREEN}✔${RESET} Low Context Hazard & Token Burn Risk`);
455
+ }
456
+
457
+ lines.push(`\n${GREEN}======================================================================${RESET}\n`);
458
+ return lines.join('\n');
459
+ };
@@ -0,0 +1,109 @@
1
+ import * as t from '@babel/types';
2
+ import { RULE_REGISTRY } from './rules-registry.js';
3
+
4
+ export const countLogicalOperators = (node) => {
5
+ let count = 0;
6
+ if (t.isLogicalExpression(node)) {
7
+ count += 1;
8
+ count += countLogicalOperators(node.left);
9
+ count += countLogicalOperators(node.right);
10
+ } else if (t.isUnaryExpression(node) && node.operator === '!') {
11
+ count += 1;
12
+ count += countLogicalOperators(node.argument);
13
+ }
14
+ return count;
15
+ };
16
+
17
+ export const extractParseableCode = (content, ext) => {
18
+ if (ext === '.vue') {
19
+ const scriptMatch = content.match(/<script\b[^>]*>([\s\S]*?)<\/script>/i);
20
+ return scriptMatch ? scriptMatch[1] : '';
21
+ }
22
+ return content;
23
+ };
24
+
25
+ export const checkTypographyEmDash = (content, lines, relativePath, violations) => {
26
+ if (!content.includes('\u2014')) return;
27
+ lines.forEach((lineText, idx) => {
28
+ if (lineText.includes('\u2014')) {
29
+ const ruleMeta = RULE_REGISTRY.TYPOGRAPHY_EM_DASH;
30
+ violations.push({
31
+ filePath: relativePath,
32
+ line: idx + 1,
33
+ column: lineText.indexOf('\u2014') + 1,
34
+ hazard: 'Em dash detected in source code or copy',
35
+ rule: 'TYPOGRAPHY_EM_DASH',
36
+ severity: ruleMeta.severity,
37
+ pillar: ruleMeta.pillar,
38
+ directive: ruleMeta.directive
39
+ });
40
+ }
41
+ });
42
+ };
43
+
44
+ export const checkMockDataPatterns = (content, lines, relativePath, violations) => {
45
+ const mockEmailRegex = /['"][a-zA-Z0-9._%+-]+@(example\.com|test\.com|gmail\.com|foo\.bar)['"]/g;
46
+ const mockPhoneRegex = /['"]555-\d{3,4}['"]/g;
47
+
48
+ lines.forEach((lineText, idx) => {
49
+ const hasMockEmail = mockEmailRegex.test(lineText);
50
+ const hasMockPhone = mockPhoneRegex.test(lineText);
51
+ if (hasMockEmail || hasMockPhone) {
52
+ const ruleMeta = RULE_REGISTRY.SYNTHETIC_MOCK_DATA;
53
+ violations.push({
54
+ filePath: relativePath,
55
+ line: idx + 1,
56
+ column: 1,
57
+ hazard: 'Hardcoded synthetic mock data pattern detected',
58
+ rule: 'SYNTHETIC_MOCK_DATA',
59
+ severity: ruleMeta.severity,
60
+ pillar: ruleMeta.pillar,
61
+ directive: ruleMeta.directive
62
+ });
63
+ }
64
+ });
65
+ };
66
+
67
+ export const resolveMonolithTier = (lineCount) => {
68
+ if (lineCount >= 2000) {
69
+ return {
70
+ severity: 'CRITICAL',
71
+ hazard: `Extreme monolith hazard (${lineCount} >= 2,000 lines)`,
72
+ directive: 'Immediate decomposition required: extreme monolith induces severe agent context degradation'
73
+ };
74
+ }
75
+ if (lineCount >= 1000) {
76
+ return {
77
+ severity: 'HIGH',
78
+ hazard: `Severe monolith hazard (${lineCount} >= 1,000 lines)`,
79
+ directive: 'Decompose file into domain capsules and molecules to prevent context degradation'
80
+ };
81
+ }
82
+ return {
83
+ severity: 'MEDIUM',
84
+ hazard: `Monolith line budget warning (${lineCount} > 500 lines)`,
85
+ directive: 'Plan decomposition into focused modules before file grows further'
86
+ };
87
+ };
88
+
89
+ export const resolveMoleculeTier = (lineCount) => {
90
+ if (lineCount >= 500) {
91
+ return {
92
+ severity: 'CRITICAL',
93
+ hazard: `Extreme molecule monolith (${lineCount} >= 500 lines)`,
94
+ directive: 'Decompose molecule capsule into smaller sub-molecules or extract state to hooks'
95
+ };
96
+ }
97
+ if (lineCount >= 250) {
98
+ return {
99
+ severity: 'HIGH',
100
+ hazard: `Oversized molecule capsule (${lineCount} >= 250 lines)`,
101
+ directive: 'Decompose molecule capsule into smaller sub-molecules or extract state to hooks'
102
+ };
103
+ }
104
+ return {
105
+ severity: 'MEDIUM',
106
+ hazard: `Molecule capsule budget warning (${lineCount} > 100 lines)`,
107
+ directive: 'Split molecule into focused sub-molecules or extract state to hook'
108
+ };
109
+ };
@@ -0,0 +1,97 @@
1
+ export const PILLARS = {
2
+ PILLAR_1: 'Line Budgets & Monolith Decomposition',
3
+ PILLAR_2: 'Control Flow & Boolean Logic',
4
+ PILLAR_3: 'Reactivity & Composable Contracts',
5
+ PILLAR_4: 'Type Architecture & Data Integrity',
6
+ PILLAR_5: 'Design System & Styling Hygiene',
7
+ PILLAR_6: 'Timers & Macro-Task Discipline',
8
+ PILLAR_7: 'Global Hygiene & Typography'
9
+ };
10
+
11
+ export const RULE_REGISTRY = {
12
+ LINE_BUDGET_FILE: {
13
+ pillar: PILLARS.PILLAR_1,
14
+ severity: 'MEDIUM',
15
+ directive: 'Decompose monolith into domain capsules and molecules'
16
+ },
17
+ LINE_BUDGET_MOLECULE: {
18
+ pillar: PILLARS.PILLAR_1,
19
+ severity: 'MEDIUM',
20
+ directive: 'Split molecule into focused sub-molecules or extract state to hook'
21
+ },
22
+ VIEW_MONOLITH: {
23
+ pillar: PILLARS.PILLAR_1,
24
+ severity: 'HIGH',
25
+ directive: 'Refactor top-level view to a 10 to 20 line Table of Contents'
26
+ },
27
+ CONTROL_FLOW_INLINE_BOOLEAN: {
28
+ pillar: PILLARS.PILLAR_2,
29
+ severity: 'MEDIUM',
30
+ directive: 'Compose booleans into Stage 1 concepts and Stage 2 decision variables'
31
+ },
32
+ CONTROL_FLOW_NESTED_TERNARY: {
33
+ pillar: PILLARS.PILLAR_2,
34
+ severity: 'CRITICAL',
35
+ directive: 'Extract display states into computed descriptor objects or early returns'
36
+ },
37
+ HOOK_SATURATION: {
38
+ pillar: PILLARS.PILLAR_3,
39
+ severity: 'HIGH',
40
+ directive: 'Extract related state and effects into dedicated domain hooks'
41
+ },
42
+ HOOK_RETURN_OVERLOAD: {
43
+ pillar: PILLARS.PILLAR_3,
44
+ severity: 'HIGH',
45
+ directive: 'Limit hook return values to 3 to 5 properties (State + Status + Actions)'
46
+ },
47
+ TIMER_DISCIPLINE: {
48
+ pillar: PILLARS.PILLAR_6,
49
+ severity: 'CRITICAL',
50
+ directive: 'Wrap timers in self-cleaning hooks returning lifecycle cleanup disposers'
51
+ },
52
+ RENDER_HACK_TIMEOUT: {
53
+ pillar: PILLARS.PILLAR_6,
54
+ severity: 'CRITICAL',
55
+ directive: 'Replace render-hack setTimeout(0) with await nextTick() or RAF'
56
+ },
57
+ TYPE_COLOCATION: {
58
+ pillar: PILLARS.PILLAR_4,
59
+ severity: 'MEDIUM',
60
+ directive: 'Define co-located domain interfaces in types/*.d.ts'
61
+ },
62
+ TYPE_MONOLITH: {
63
+ pillar: PILLARS.PILLAR_4,
64
+ severity: 'HIGH',
65
+ directive: 'Decompose root type monolith into co-located capsule types'
66
+ },
67
+ SYNTHETIC_MOCK_DATA: {
68
+ pillar: PILLARS.PILLAR_4,
69
+ severity: 'MEDIUM',
70
+ directive: 'Use live API data or explicit empty states instead of mock placeholders'
71
+ },
72
+ RAW_INLINE_STYLE: {
73
+ pillar: PILLARS.PILLAR_5,
74
+ severity: 'MEDIUM',
75
+ directive: 'Decouple into Level 1 atom props, SCSS mixins, or scoped classes via @apply'
76
+ },
77
+ ICON_SVG_STYLE_LEAK: {
78
+ pillar: PILLARS.PILLAR_5,
79
+ severity: 'LOW',
80
+ directive: 'Avoid text-* utility classes on FontAwesome icons; use color prop or CSS'
81
+ },
82
+ TYPOGRAPHY_EM_DASH: {
83
+ pillar: PILLARS.PILLAR_7,
84
+ severity: 'LOW',
85
+ directive: 'Replace em dashes with hyphens or colons per typography standard'
86
+ },
87
+ UNGUARDED_LOGGING: {
88
+ pillar: PILLARS.PILLAR_7,
89
+ severity: 'LOW',
90
+ directive: 'Route runtime diagnostics through a production-silenced debug proxy'
91
+ },
92
+ SYNTAX_PARSE_ERROR: {
93
+ pillar: PILLARS.PILLAR_1,
94
+ severity: 'CRITICAL',
95
+ directive: 'Fix syntax errors before static analysis'
96
+ }
97
+ };