@chemx/starter-kit 26.9.11-481 → 26.9.12-107

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 (46) hide show
  1. package/cli/audit/ai-slop-detector.js +262 -0
  2. package/cli/audit/extended-visitors.js +359 -0
  3. package/cli/audit/history.js +19 -2
  4. package/cli/audit/metrics.js +69 -0
  5. package/cli/audit/prompts.js +175 -48
  6. package/cli/audit/reporter-banner.d.ts +3 -0
  7. package/cli/audit/reporter-banner.js +74 -0
  8. package/cli/audit/reporter-grades.js +11 -26
  9. package/cli/audit/reporter-grouping-markdown.js +83 -0
  10. package/cli/audit/reporter-grouping.d.ts +42 -0
  11. package/cli/audit/reporter-grouping.js +243 -0
  12. package/cli/audit/reporter-markdown.js +34 -22
  13. package/cli/audit/reporter-sections.d.ts +10 -0
  14. package/cli/audit/reporter-sections.js +259 -0
  15. package/cli/audit/reporter-summary.d.ts +4 -0
  16. package/cli/audit/reporter-summary.js +142 -0
  17. package/cli/audit/reporter-utils.js +13 -1
  18. package/cli/audit/reporter.d.ts +16 -0
  19. package/cli/audit/reporter.js +47 -420
  20. package/cli/audit/rules-helpers.js +16 -0
  21. package/cli/audit/rules-registry.js +88 -1
  22. package/cli/audit/rules.js +32 -1
  23. package/cli/audit/social-git.js +133 -131
  24. package/cli/audit/social.js +15 -2
  25. package/cli/audit/types.d.ts +28 -27
  26. package/cli/audit.js +56 -3
  27. package/cli/badge.js +262 -0
  28. package/cli/generator-templates.js +264 -0
  29. package/cli/generator.d.ts +10 -0
  30. package/cli/generator.js +151 -0
  31. package/cli/help.js +17 -7
  32. package/cli/index.js +26 -16
  33. package/cli/installer.d.ts +2 -0
  34. package/cli/installer.js +52 -38
  35. package/cli/license.js +17 -4
  36. package/cli/navigator-actions.js +63 -1
  37. package/cli/navigator-banner.js +17 -6
  38. package/cli/navigator-grades.js +9 -0
  39. package/cli/navigator-menu.js +36 -0
  40. package/cli/navigator-share.js +7 -4
  41. package/cli/navigator.d.ts +5 -1
  42. package/cli/navigator.js +49 -12
  43. package/cli/scaffold.js +3 -54
  44. package/cli/terminal.js +4 -1
  45. package/docs/CHANGELOG.md +50 -0
  46. package/package.json +1 -1
@@ -0,0 +1,42 @@
1
+ import type { HazardViolation, SeverityLevel, AuditReport } from './types';
2
+
3
+ export interface DirectoryHazardSummary {
4
+ readonly directory: string;
5
+ readonly total: number;
6
+ readonly critical: number;
7
+ readonly high: number;
8
+ readonly medium: number;
9
+ readonly low: number;
10
+ readonly violations: readonly HazardViolation[];
11
+ readonly topRules: readonly { readonly rule: string; readonly count: number }[];
12
+ }
13
+
14
+ export interface RuleDirectoryOccurrence {
15
+ readonly directory: string;
16
+ readonly count: number;
17
+ readonly violations: readonly HazardViolation[];
18
+ }
19
+
20
+ export interface RuleHazardSummary {
21
+ readonly rule: string;
22
+ readonly severity: SeverityLevel;
23
+ readonly pillar: string;
24
+ readonly directive: string;
25
+ readonly hazard: string;
26
+ readonly isAiSlop: boolean;
27
+ readonly total: number;
28
+ readonly violations: readonly HazardViolation[];
29
+ readonly directories: readonly RuleDirectoryOccurrence[];
30
+ }
31
+
32
+ export declare function resolveDirectory(filePath?: string): string;
33
+ export declare function groupViolationsByDirectory(violations?: readonly HazardViolation[]): readonly DirectoryHazardSummary[];
34
+ export declare function groupViolationsByRule(violations?: readonly HazardViolation[]): readonly RuleHazardSummary[];
35
+ export declare function formatCompactLocations(violations: readonly HazardViolation[], maxShown?: number): string;
36
+ export declare function renderGroupedViolationsTerminal(violations: readonly HazardViolation[]): string;
37
+ export declare function formatDirectoryDistributionSection(report: AuditReport, themeColor?: string | null): string;
38
+ export declare function formatDirectoryRollupMarkdown(violations?: readonly HazardViolation[]): string;
39
+ export declare function renderGroupedViolationsMarkdown(
40
+ violations?: readonly HazardViolation[],
41
+ options?: { readonly showSeverity?: boolean }
42
+ ): string;
@@ -0,0 +1,243 @@
1
+ import path from 'node:path';
2
+ import {
3
+ CYAN,
4
+ GREEN,
5
+ YELLOW,
6
+ RED,
7
+ ORANGE,
8
+ DIM,
9
+ BOLD,
10
+ RESET,
11
+ resolveTopSectionColor
12
+ } from './reporter-utils.js';
13
+
14
+ export const resolveDirectory = (filePath) => {
15
+ const hasFilePath = Boolean(filePath);
16
+ if (!hasFilePath) return './';
17
+ const normalized = filePath.replace(/\\/g, '/');
18
+ const lastSlash = normalized.lastIndexOf('/');
19
+ const isRoot = lastSlash === -1;
20
+ if (isRoot) return './';
21
+ return normalized.slice(0, lastSlash + 1);
22
+ };
23
+
24
+ export const groupViolationsByDirectory = (violations = []) => {
25
+ const dirMap = new Map();
26
+
27
+ for (const v of violations) {
28
+ const dir = resolveDirectory(v.filePath);
29
+ let group = dirMap.get(dir);
30
+ if (!group) {
31
+ group = {
32
+ directory: dir,
33
+ total: 0,
34
+ critical: 0,
35
+ high: 0,
36
+ medium: 0,
37
+ low: 0,
38
+ violations: [],
39
+ rulesMap: new Map()
40
+ };
41
+ dirMap.set(dir, group);
42
+ }
43
+
44
+ group.total += 1;
45
+ group.violations.push(v);
46
+ if (v.severity === 'CRITICAL') group.critical += 1;
47
+ else if (v.severity === 'HIGH') group.high += 1;
48
+ else if (v.severity === 'MEDIUM') group.medium += 1;
49
+ else group.low += 1;
50
+
51
+ const count = group.rulesMap.get(v.rule) || 0;
52
+ group.rulesMap.set(v.rule, count + 1);
53
+ }
54
+
55
+ const createDirectorySummary = (g) => {
56
+ const topRules = Array.from(g.rulesMap.entries())
57
+ .map(([rule, count]) => ({ rule, count }))
58
+ .sort((a, b) => b.count - a.count);
59
+
60
+ return {
61
+ directory: g.directory,
62
+ total: g.total,
63
+ critical: g.critical,
64
+ high: g.high,
65
+ medium: g.medium,
66
+ low: g.low,
67
+ violations: g.violations,
68
+ topRules
69
+ };
70
+ };
71
+
72
+ const result = Array.from(dirMap.values()).map(createDirectorySummary);
73
+
74
+ const calculateDirectoryWeight = (g) => g.critical * 1000 + g.high * 100 + g.medium * 10 + g.low;
75
+
76
+ const compareDirectoryRisk = (a, b) => {
77
+ const weightDiff = calculateDirectoryWeight(b) - calculateDirectoryWeight(a);
78
+ const hasWeightDiff = weightDiff !== 0;
79
+ if (hasWeightDiff) return weightDiff;
80
+ return b.total - a.total;
81
+ };
82
+
83
+ result.sort(compareDirectoryRisk);
84
+ return result;
85
+ };
86
+
87
+ export const groupViolationsByRule = (violations = []) => {
88
+ const ruleMap = new Map();
89
+
90
+ for (const v of violations) {
91
+ let group = ruleMap.get(v.rule);
92
+ if (!group) {
93
+ group = {
94
+ rule: v.rule,
95
+ severity: v.severity,
96
+ pillar: v.pillar,
97
+ directive: v.directive,
98
+ hazard: v.hazard,
99
+ isAiSlop: Boolean(v.isAiSlop),
100
+ total: 0,
101
+ violations: [],
102
+ dirsMap: new Map()
103
+ };
104
+ ruleMap.set(v.rule, group);
105
+ }
106
+
107
+ group.total += 1;
108
+ group.violations.push(v);
109
+
110
+ const dir = resolveDirectory(v.filePath);
111
+ let dirViolations = group.dirsMap.get(dir);
112
+ if (!dirViolations) {
113
+ dirViolations = [];
114
+ group.dirsMap.set(dir, dirViolations);
115
+ }
116
+ dirViolations.push(v);
117
+ }
118
+
119
+ const createRuleSummary = (g) => {
120
+ const directories = Array.from(g.dirsMap.entries()).map(([directory, list]) => ({
121
+ directory,
122
+ count: list.length,
123
+ violations: list
124
+ }));
125
+
126
+ return {
127
+ rule: g.rule,
128
+ severity: g.severity,
129
+ pillar: g.pillar,
130
+ directive: g.directive,
131
+ hazard: g.hazard,
132
+ isAiSlop: g.isAiSlop,
133
+ total: g.total,
134
+ violations: g.violations,
135
+ directories
136
+ };
137
+ };
138
+
139
+ const result = Array.from(ruleMap.values()).map(createRuleSummary);
140
+
141
+ const SEVERITY_RANKS = { CRITICAL: 4, HIGH: 3, MEDIUM: 2, LOW: 1 };
142
+ const compareRuleSeverity = (a, b) => {
143
+ const rankDiff = (SEVERITY_RANKS[b.severity] || 0) - (SEVERITY_RANKS[a.severity] || 0);
144
+ const hasRankDiff = rankDiff !== 0;
145
+ if (hasRankDiff) return rankDiff;
146
+ return b.total - a.total;
147
+ };
148
+
149
+ result.sort(compareRuleSeverity);
150
+ return result;
151
+ };
152
+
153
+ const resolveSeverityColor = (severity) => {
154
+ if (severity === 'CRITICAL') return RED;
155
+ if (severity === 'HIGH') return ORANGE;
156
+ if (severity === 'MEDIUM') return YELLOW;
157
+ return DIM;
158
+ };
159
+
160
+ export const formatCompactLocations = (violations, maxShown = 4) => {
161
+ const formatLocationItem = (v) => {
162
+ const base = path.basename(v.filePath);
163
+ return `${YELLOW}${base}:${v.line}:${v.column}${RESET}`;
164
+ };
165
+
166
+ const items = violations.slice(0, maxShown).map(formatLocationItem);
167
+ const remaining = violations.length - maxShown;
168
+ const hasRemaining = remaining > 0;
169
+ if (hasRemaining) {
170
+ items.push(`${DIM}(+${remaining} more)${RESET}`);
171
+ }
172
+ return items.join(', ');
173
+ };
174
+
175
+ export const renderGroupedViolationsTerminal = (violations) => {
176
+ const hasNoViolations = violations.length === 0;
177
+ if (hasNoViolations) return '';
178
+
179
+ const ruleGroups = groupViolationsByRule(violations);
180
+ const lines = [];
181
+
182
+ ruleGroups.forEach((rg, idx) => {
183
+ const sevColor = resolveSeverityColor(rg.severity);
184
+ const countLabel = rg.total === 1 ? '1 item' : `${rg.total} items`;
185
+ const isSingleOccurrence = rg.total === 1;
186
+
187
+ if (isSingleOccurrence) {
188
+ const v = rg.violations[0];
189
+ lines.push(` ${sevColor}[#${idx + 1} ${rg.severity}]${RESET} [${rg.rule}] ${YELLOW}${v.filePath}:${v.line}:${v.column}${RESET}`);
190
+ lines.push(` Hazard: ${rg.hazard}`);
191
+ lines.push(` Directive: ${CYAN}${rg.directive}${RESET}\n`);
192
+ return;
193
+ }
194
+
195
+ const dirCount = rg.directories.length;
196
+ const dirLabel = dirCount === 1 ? '1 directory' : `${dirCount} directories`;
197
+ lines.push(` ${sevColor}[#${idx + 1} ${rg.severity}]${RESET} [${rg.rule}] ${BOLD}${countLabel}${RESET} ${DIM}across ${dirLabel}${RESET}`);
198
+ lines.push(` Hazard: ${rg.hazard}`);
199
+ lines.push(` Directive: ${CYAN}${rg.directive}${RESET}`);
200
+ lines.push(` Locations:`);
201
+
202
+ for (const d of rg.directories) {
203
+ const locs = formatCompactLocations(d.violations, 4);
204
+ lines.push(` 📁 ${d.directory} (${d.count}): ${locs}`);
205
+ }
206
+ lines.push('');
207
+ });
208
+
209
+ return lines.join('\n');
210
+ };
211
+
212
+ export const formatDirectoryDistributionSection = (report, themeColor = null) => {
213
+ const { violations = [] } = report;
214
+ const sectionColor = themeColor || resolveTopSectionColor(report);
215
+ const dirGroups = groupViolationsByDirectory(violations);
216
+ const lines = [];
217
+
218
+ lines.push('');
219
+ lines.push(`${sectionColor}======================================================================${RESET}`);
220
+ lines.push(`${BOLD}${sectionColor} HAZARD DISTRIBUTION BY DIRECTORY${RESET}`);
221
+ lines.push(`${sectionColor}======================================================================${RESET}`);
222
+
223
+ const hasNoViolations = dirGroups.length === 0;
224
+ if (hasNoViolations) {
225
+ lines.push(` ${GREEN}✔ Zero violations detected across all project directories.${RESET}`);
226
+ } else {
227
+ lines.push(` ${DIM}Directory Total Crit High Med Low${RESET}`);
228
+ lines.push(` ${DIM}------------------------------------------------------------------${RESET}`);
229
+ for (const g of dirGroups) {
230
+ const isLongDir = g.directory.length > 36;
231
+ const padDir = isLongDir ? `${g.directory.slice(0, 33)}...` : g.directory.padEnd(36, ' ');
232
+ const totalStr = `${BOLD}${g.total}${RESET}`.padStart(6, ' ');
233
+ const critStr = (g.critical > 0 ? `${RED}${g.critical}${RESET}` : `${DIM}0${RESET}`).padStart(5, ' ');
234
+ const highStr = (g.high > 0 ? `${ORANGE}${g.high}${RESET}` : `${DIM}0${RESET}`).padStart(5, ' ');
235
+ const medStr = (g.medium > 0 ? `${YELLOW}${g.medium}${RESET}` : `${DIM}0${RESET}`).padStart(5, ' ');
236
+ const lowStr = (g.low > 0 ? `${DIM}${g.low}${RESET}` : `${DIM}0${RESET}`).padStart(5, ' ');
237
+ lines.push(` ${padDir} ${totalStr} ${critStr} ${highStr} ${medStr} ${lowStr}`);
238
+ }
239
+ }
240
+ lines.push(`${sectionColor}======================================================================${RESET}\n`);
241
+
242
+ return lines.join('\n');
243
+ };
@@ -7,9 +7,13 @@ import {
7
7
  PILLAR_EMOJIS,
8
8
  NUMBER_EMOJIS
9
9
  } from './reporter-utils.js';
10
+ import {
11
+ formatDirectoryRollupMarkdown,
12
+ renderGroupedViolationsMarkdown
13
+ } from './reporter-grouping-markdown.js';
10
14
 
11
15
  export const generateMarkdownReport = (report) => {
12
- const { metrics, health, pillars, contextAnalysis, hotspots, violations } = report;
16
+ const { metrics, health, pillars, contextAnalysis, hotspots, violations, aiSlop } = report;
13
17
  const { critical, high, medium, low } = groupViolationsBySeverity(violations);
14
18
  const lines = [];
15
19
 
@@ -24,6 +28,10 @@ export const generateMarkdownReport = (report) => {
24
28
  const hearts = resolveHealthHearts(health?.grade, health?.score, false);
25
29
  lines.push(`| **Life / Health Meter** | ${hearts} (Grade **${health.grade}**) | ${health.score} / 100 (${health.label}) |`);
26
30
  lines.push(`| **Molecular Health Index** | **${health.score} / 100** | Grade: **${health.grade}** (${health.label}) |`);
31
+ const slopScore = aiSlop?.score ?? 100;
32
+ const slopGrade = aiSlop?.grade ?? 'A+';
33
+ const slopLabel = aiSlop?.label ?? 'Pure Artisanal';
34
+ lines.push(`| **AI Slop Index (ASI)** | **${slopScore} / 100** | Grade: **${slopGrade}** (${slopLabel}) |`);
27
35
  lines.push(`| **Scanned Files** | ${metrics.scannedFiles} source files | Verified |`);
28
36
  lines.push(`| **Total Lines of Code** | ${metrics.totalLoc} lines of code | Avg ${metrics.avgLoc} lines/file |`);
29
37
  lines.push(`| **Largest File** | \`${metrics.largestFile.filePath || 'None'}\` | ${metrics.largestFile.lineCount} lines |`);
@@ -69,61 +77,65 @@ export const generateMarkdownReport = (report) => {
69
77
  lines.push('');
70
78
  lines.push('---');
71
79
  lines.push('');
72
- lines.push('## 4. Architectural Hazard Inventory (Grouped by Severity)');
80
+ lines.push('## 4. Architectural Hazard Inventory (Grouped by Directory & Severity)');
73
81
  lines.push('');
74
82
 
75
83
  if (violations.length === 0) {
76
84
  lines.push('Zero context hazard violations detected across all line budgets, hooks, and AST rules.');
77
85
  } else {
86
+ lines.push(formatDirectoryRollupMarkdown(violations));
87
+
78
88
  if (critical.length > 0) {
79
89
  lines.push('### Critical Hazards (Immediate Action Required)');
80
90
  lines.push('');
81
- lines.push('| Location | Rule | Hazard Description | Directive |');
82
- lines.push('| :--- | :--- | :--- | :--- |');
83
- for (const v of critical) {
84
- lines.push(`| \`${v.filePath}:${v.line}:${v.column}\` | \`${v.rule}\` | ${v.hazard} | ${v.directive} |`);
85
- }
86
- lines.push('');
91
+ lines.push(renderGroupedViolationsMarkdown(critical, { showSeverity: false }));
87
92
  }
88
93
 
89
94
  if (high.length > 0 || medium.length > 0) {
90
95
  lines.push('### High & Medium Hazards (Architecture Debts)');
91
96
  lines.push('');
92
- lines.push('| Location | Severity | Rule | Hazard Description | Directive |');
93
- lines.push('| :--- | :---: | :--- | :--- | :--- |');
94
- for (const v of [...high, ...medium]) {
95
- lines.push(`| \`${v.filePath}:${v.line}:${v.column}\` | ${v.severity} | \`${v.rule}\` | ${v.hazard} | ${v.directive} |`);
96
- }
97
- lines.push('');
97
+ lines.push(renderGroupedViolationsMarkdown([...high, ...medium], { showSeverity: true }));
98
98
  }
99
99
 
100
100
  if (low.length > 0) {
101
101
  lines.push('### Low & Hygiene Issues (Typography & Logging)');
102
102
  lines.push('');
103
- lines.push('| Location | Rule | Hazard Description | Directive |');
104
- lines.push('| :--- | :--- | :--- | :--- |');
105
- for (const v of low) {
106
- lines.push(`| \`${v.filePath}:${v.line}:${v.column}\` | \`${v.rule}\` | ${v.hazard} | ${v.directive} |`);
107
- }
108
- lines.push('');
103
+ lines.push(renderGroupedViolationsMarkdown(low, { showSeverity: false }));
109
104
  }
110
105
  }
111
106
 
107
+ const slopViolations = violations.filter((v) => v.isAiSlop);
108
+ lines.push('---');
109
+ lines.push('');
110
+ lines.push('## 5. AI Slop & Code Authenticity Audit');
111
+ lines.push('');
112
+ lines.push(`* **AI Slop Index (ASI)**: **${slopScore} / 100** (Grade: **${slopGrade}** - ${slopLabel})`);
113
+ lines.push(`* **Slop Hazards Flagged**: **${slopViolations.length}**`);
114
+ lines.push('');
115
+
116
+ if (slopViolations.length === 0) {
117
+ lines.push('🟢 Zero AI slop detected. Codebase demonstrates pure artisanal craftsmanship with no LLM conversational residue or echo comments.');
118
+ } else {
119
+ lines.push(renderGroupedViolationsMarkdown(slopViolations, { showSeverity: true }));
120
+ }
121
+ lines.push('');
122
+
112
123
  lines.push('---');
113
124
  lines.push('');
114
- lines.push('## 5. Remediation Roadmap');
125
+ lines.push('## 6. Remediation Roadmap');
115
126
  lines.push('');
116
127
  lines.push('1. **Decompose Monoliths**: Break down any file exceeding 500 lines into single-responsibility capsules.');
117
128
  lines.push('2. **Cap Molecule Size**: Ensure all molecule components (`m-*`) remain strictly under 100 lines.');
118
129
  lines.push('3. **Two-Stage Boolean Logic**: Replace complex multi-clause expressions with atomic boolean variables.');
119
130
  lines.push('4. **Lifecycle-Safe Timers**: Migrate raw `setInterval` and `setTimeout` calls to self-cleaning composables.');
131
+ lines.push('5. **Purge AI Slop**: Remove conversational residue, eliminate echo comments, and inline single-use passthrough assignments.');
120
132
  lines.push('');
121
133
 
122
134
  const masterPrompt = buildMasterPrompt(report);
123
135
  if (masterPrompt) {
124
136
  lines.push('---');
125
137
  lines.push('');
126
- lines.push('## 6. 🤖 Copy-Paste AI Agent Refactoring Directives');
138
+ lines.push('## 7. 🤖 Copy-Paste AI Agent Refactoring Directives');
127
139
  lines.push('');
128
140
  lines.push('Feed the prompt below directly into your AI coding agent (Cursor, Windsurf, Claude, Copilot, or Antigravity) to surgically refactor flagged hazards:');
129
141
  lines.push('');
@@ -0,0 +1,10 @@
1
+ import type { AuditReport } from './types';
2
+
3
+ export declare function formatScorecardSection(report: AuditReport, themeColor?: string | null): string;
4
+ export declare function formatCriticalSection(report: AuditReport): string;
5
+ export declare function formatHighMediumSection(report: AuditReport): string;
6
+ export declare function formatLowSection(report: AuditReport): string;
7
+ export declare function formatPillarsSection(report: AuditReport, themeColor?: string | null): string;
8
+ export declare function formatHotspotsSection(report: AuditReport, themeColor?: string | null): string;
9
+ export declare function formatContextAnalysisSection(report: AuditReport, themeColor?: string | null): string;
10
+ export declare function formatAiSlopSection(report: AuditReport, themeColor?: string | null): string;
@@ -0,0 +1,259 @@
1
+ import {
2
+ CYAN,
3
+ GREEN,
4
+ YELLOW,
5
+ RED,
6
+ ORANGE,
7
+ DIM,
8
+ BOLD,
9
+ RESET,
10
+ groupViolationsBySeverity,
11
+ getStatusBadge,
12
+ resolveGradeColor,
13
+ resolveHealthHearts,
14
+ resolveRiskColor,
15
+ resolveHotspotBadge,
16
+ resolveTopSectionColor
17
+ } from './reporter-utils.js';
18
+ import { getAsciiGradeLines, getReportCardAsciiLines } from './reporter-ascii.js';
19
+ import { renderGroupedViolationsTerminal } from './reporter-grouping.js';
20
+ import {
21
+ buildAiSlopPrompt,
22
+ buildHotspotsPrompt,
23
+ formatPromptBox
24
+ } from './prompts.js';
25
+
26
+ const isSlopViolation = (v) => Boolean(v.isAiSlop);
27
+
28
+ const formatHotspotItem = (h, idx) => {
29
+ const monolithBadge = resolveHotspotBadge(h.lineCount);
30
+ return ` [#${idx + 1}] ${YELLOW}${h.filePath}${RESET} (${h.lineCount} lines, ${h.violationCount} hazards)${monolithBadge}`;
31
+ };
32
+
33
+ export const formatScorecardSection = (report, themeColor = null) => {
34
+ const { metrics, health } = report;
35
+ const sectionColor = themeColor || resolveTopSectionColor(report);
36
+ const gradeColor = resolveGradeColor(health?.score ?? health?.grade ?? 'A');
37
+ const lines = [];
38
+
39
+ lines.push('');
40
+ for (const rcLine of getReportCardAsciiLines(sectionColor)) {
41
+ lines.push(` ${rcLine}`);
42
+ }
43
+ lines.push(`${sectionColor}======================================================================${RESET}`);
44
+ lines.push(`${BOLD}${sectionColor} MOLECULAR HEALTH INDEX & CODEBASE OVERVIEW${RESET}`);
45
+ lines.push(`${sectionColor}======================================================================${RESET}`);
46
+
47
+ const asciiGradeLines = getAsciiGradeLines(health?.grade || 'A', gradeColor);
48
+ if (asciiGradeLines.length > 0) {
49
+ lines.push('');
50
+ for (const asciiLine of asciiGradeLines) {
51
+ lines.push(` ${asciiLine}`);
52
+ }
53
+ lines.push('');
54
+ lines.push(`${sectionColor}----------------------------------------------------------------------${RESET}`);
55
+ }
56
+
57
+ const hearts = resolveHealthHearts(health?.grade, health?.score);
58
+ lines.push(` Life / Health Meter: ${hearts} ${gradeColor}${BOLD}${health.score} / 100${RESET} (Grade: ${gradeColor}${BOLD}${health.grade}${RESET} - ${health.label})`);
59
+
60
+ if (report.aiSlop) {
61
+ const slopGradeColor = resolveGradeColor(report.aiSlop.grade);
62
+ const slopHearts = resolveHealthHearts(report.aiSlop.grade, report.aiSlop.score);
63
+ lines.push(` AI Slop Index (ASI): ${slopHearts} ${slopGradeColor}${BOLD}${report.aiSlop.score} / 100${RESET} (Grade: ${slopGradeColor}${BOLD}${report.aiSlop.grade}${RESET} - ${report.aiSlop.label})`);
64
+ }
65
+ lines.push(` Files Scanned: ${BOLD}${metrics.scannedFiles}${RESET} source files`);
66
+ lines.push(` Total Lines of Code: ${BOLD}${metrics.totalLoc}${RESET} lines of code (avg: ${metrics.avgLoc} lines/file)`);
67
+ lines.push(` Largest File: ${BOLD}${metrics.largestFile.filePath || 'None'}${RESET} (${metrics.largestFile.lineCount} lines)`);
68
+ lines.push(` Molecule Capsules: ${metrics.moleculeCount} found (${metrics.moleculeCompliantPct}% compliant < 100 lines of code)`);
69
+ lines.push(` Custom Hooks: ${metrics.hookCount} detected`);
70
+ lines.push(`${sectionColor}======================================================================${RESET}\n`);
71
+
72
+ return lines.join('\n');
73
+ };
74
+
75
+ export const formatCriticalSection = (report) => {
76
+ const { violations } = report;
77
+ const { critical } = groupViolationsBySeverity(violations);
78
+ const lines = [];
79
+
80
+ lines.push('');
81
+ lines.push(`${RED}======================================================================${RESET}`);
82
+ lines.push(`${BOLD}${RED} CRITICAL HAZARDS (${critical.length} TOTAL) : IMMEDIATE ACTION REQUIRED${RESET}`);
83
+ lines.push(`${DIM} Violations that break Molecular line budgets or introduce severe AST bugs${RESET}`);
84
+ lines.push(`${RED}======================================================================${RESET}`);
85
+
86
+ if (critical.length === 0) {
87
+ lines.push(` ${GREEN}✔ Zero critical hazards detected. No monoliths or breaking AST patterns.${RESET}`);
88
+ } else {
89
+ lines.push(renderGroupedViolationsTerminal(critical));
90
+ }
91
+ lines.push(`${RED}======================================================================${RESET}\n`);
92
+
93
+ return lines.join('\n');
94
+ };
95
+
96
+ export const formatHighMediumSection = (report) => {
97
+ const { violations } = report;
98
+ const { high, medium } = groupViolationsBySeverity(violations);
99
+ const totalCount = high.length + medium.length;
100
+ const lines = [];
101
+
102
+ lines.push('');
103
+ lines.push(`${ORANGE}======================================================================${RESET}`);
104
+ lines.push(`${BOLD}${ORANGE} HIGH & MEDIUM HAZARDS (${totalCount} TOTAL) : ARCHITECTURE DEBTS${RESET}`);
105
+ lines.push(`${DIM} Saturation, complex control flow booleans, and raw inline styles${RESET}`);
106
+ lines.push(`${ORANGE}======================================================================${RESET}`);
107
+
108
+ if (totalCount === 0) {
109
+ lines.push(` ${GREEN}✔ Zero high or medium architecture hazards detected.${RESET}`);
110
+ } else {
111
+ if (high.length > 0) {
112
+ lines.push(`\n ${BOLD}--- High Severity (${high.length} items) ---${RESET}\n`);
113
+ lines.push(renderGroupedViolationsTerminal(high));
114
+ }
115
+
116
+ if (medium.length > 0) {
117
+ lines.push(`\n ${BOLD}--- Medium Severity (${medium.length} items) ---${RESET}\n`);
118
+ lines.push(renderGroupedViolationsTerminal(medium));
119
+ }
120
+ }
121
+ lines.push(`${ORANGE}======================================================================${RESET}\n`);
122
+
123
+ return lines.join('\n');
124
+ };
125
+
126
+ export const formatLowSection = (report) => {
127
+ const { violations } = report;
128
+ const { low } = groupViolationsBySeverity(violations);
129
+ const lines = [];
130
+
131
+ lines.push('');
132
+ lines.push(`${YELLOW}======================================================================${RESET}`);
133
+ lines.push(`${BOLD}${YELLOW} LOW & HYGIENE ISSUES (${low.length} TOTAL) : TYPOGRAPHY & LOGGING${RESET}`);
134
+ lines.push(`${DIM} Em dash typography violations and unguarded console statements${RESET}`);
135
+ lines.push(`${YELLOW}======================================================================${RESET}`);
136
+
137
+ if (low.length === 0) {
138
+ lines.push(` ${GREEN}✔ Zero typography or logging hygiene issues detected.${RESET}`);
139
+ } else {
140
+ lines.push(renderGroupedViolationsTerminal(low));
141
+ }
142
+ lines.push(`${YELLOW}======================================================================${RESET}\n`);
143
+
144
+ return lines.join('\n');
145
+ };
146
+
147
+ export const formatPillarsSection = (report, themeColor = null) => {
148
+ const { pillars } = report;
149
+ const sectionColor = themeColor || resolveTopSectionColor(report);
150
+ const lines = [];
151
+
152
+ lines.push('');
153
+ lines.push(`${sectionColor}======================================================================${RESET}`);
154
+ lines.push(`${BOLD}${sectionColor} 7-PILLAR ARCHITECTURAL COMPLIANCE MATRIX${RESET}`);
155
+ lines.push(`${sectionColor}======================================================================${RESET}`);
156
+ lines.push(` ${DIM}Pillar Name Status Violations${RESET}`);
157
+ lines.push(` ${DIM}------------------------------------------------------------------${RESET}`);
158
+ for (const [pillarName, data] of Object.entries(pillars)) {
159
+ const padName = pillarName.padEnd(45, ' ');
160
+ const badge = getStatusBadge(data.status).padEnd(16, ' ');
161
+ const countStr = data.violations === 0 ? `${GREEN}0${RESET}` : `${RED}${data.violations}${RESET}`;
162
+ lines.push(` ${padName} ${badge} ${countStr}`);
163
+ }
164
+ lines.push(`${sectionColor}======================================================================${RESET}\n`);
165
+
166
+ return lines.join('\n');
167
+ };
168
+
169
+ export const formatHotspotsSection = (report, themeColor = null, options = {}) => {
170
+ const { includePrompt = true } = typeof options === 'boolean' ? { includePrompt: options } : options;
171
+ const { hotspots } = report;
172
+ const sectionColor = themeColor || resolveTopSectionColor(report);
173
+ const lines = [];
174
+
175
+ lines.push('');
176
+ lines.push(`${sectionColor}======================================================================${RESET}`);
177
+ lines.push(`${BOLD}${sectionColor} TOP REFACTORING HOTSPOTS (PRIORITY RANKING)${RESET}`);
178
+ lines.push(`${sectionColor}======================================================================${RESET}`);
179
+
180
+ if (hotspots.length === 0) {
181
+ lines.push(` ${GREEN}✔ Zero hotspot files. All files stay within architectural budgets.${RESET}`);
182
+ } else {
183
+ for (let idx = 0; idx < hotspots.length; idx++) {
184
+ lines.push(formatHotspotItem(hotspots[idx], idx));
185
+ }
186
+ }
187
+
188
+ if (includePrompt) {
189
+ const promptHotspots = buildHotspotsPrompt(report);
190
+ if (promptHotspots) {
191
+ lines.push(formatPromptBox('🤖 AI AGENT REFACTORING PROMPT (MONOLITH DECOMPOSITION)', promptHotspots));
192
+ }
193
+ }
194
+
195
+ lines.push(`${sectionColor}======================================================================${RESET}\n`);
196
+
197
+ return lines.join('\n');
198
+ };
199
+
200
+ export const formatContextAnalysisSection = (report, themeColor = null) => {
201
+ const { contextAnalysis } = report;
202
+ const sectionColor = themeColor || resolveTopSectionColor(report);
203
+ const riskColor = resolveRiskColor(contextAnalysis.riskLevel);
204
+ const lines = [];
205
+
206
+ lines.push('');
207
+ lines.push(`${sectionColor}======================================================================${RESET}`);
208
+ lines.push(`${BOLD}${sectionColor} CONTEXT ROT & TOKEN BURN ANALYTICS${RESET}`);
209
+ lines.push(`${sectionColor}======================================================================${RESET}`);
210
+ lines.push(` Estimated Codebase Tokens: ~${contextAnalysis.estimatedTokens.toLocaleString()} tokens`);
211
+ lines.push(` Estimated Monolith Bloat: ~${contextAnalysis.estimatedExcessTokens.toLocaleString()} tokens`);
212
+ lines.push(` Target Architecture Cut: ${BOLD}${contextAnalysis.potentialSavingsPct}%${RESET} token reduction potential`);
213
+ lines.push(` Agent Hallucination Risk: ${riskColor}${BOLD}${contextAnalysis.riskLevel}${RESET}`);
214
+ if (contextAnalysis.excessCostPerPass !== undefined) {
215
+ const costPass = contextAnalysis.excessCostPerPass.toFixed(3);
216
+ const costMonth = contextAnalysis.monthlyWastePerDev.toFixed(2);
217
+ const costWeek = contextAnalysis.weeklyWastePerDev.toFixed(2);
218
+ lines.push(` Pricing Model Baseline: ${contextAnalysis.pricingModel}`);
219
+ lines.push(` Monolith Bloat per AI Turn: \x1b[38;5;208;1m$${costPass}\x1b[0m / prompt turn`);
220
+ lines.push(` Projected Dev Context Tax: \x1b[31;1m$${costMonth}/mo\x1b[0m per engineer ($${costWeek}/wk)`);
221
+ }
222
+ lines.push(`${sectionColor}======================================================================${RESET}\n`);
223
+
224
+ return lines.join('\n');
225
+ };
226
+
227
+ export const formatAiSlopSection = (report, themeColor = null, options = {}) => {
228
+ const { includePrompt = true } = typeof options === 'boolean' ? { includePrompt: options } : options;
229
+ const { aiSlop, violations = [] } = report;
230
+ const slopViolations = violations.filter(isSlopViolation);
231
+ const sectionColor = themeColor || resolveTopSectionColor(report);
232
+ const slopColor = resolveGradeColor(aiSlop?.grade || 'A+');
233
+ const lines = [];
234
+
235
+ lines.push('');
236
+ lines.push(`${sectionColor}======================================================================${RESET}`);
237
+ lines.push(`${BOLD}${sectionColor} AI SLOP INDEX & CODE AUTHENTICITY AUDIT${RESET}`);
238
+ lines.push(`${DIM} Deterministic detection of LLM conversational residue and echo comments${RESET}`);
239
+ lines.push(`${sectionColor}======================================================================${RESET}`);
240
+ lines.push(` AI Slop Score: ${slopColor}${BOLD}${aiSlop?.score ?? 100} / 100${RESET} (Grade: ${slopColor}${BOLD}${aiSlop?.grade ?? 'A+'}${RESET} - ${aiSlop?.label ?? 'Pure Artisanal'})`);
241
+ lines.push(` Slop Hazards Flagged: ${slopViolations.length > 0 ? `${RED}${BOLD}${slopViolations.length}${RESET}` : `${GREEN}0 (Artisanal Clean)${RESET}`}`);
242
+ lines.push(`${sectionColor}----------------------------------------------------------------------${RESET}`);
243
+
244
+ if (slopViolations.length === 0) {
245
+ lines.push(` ${GREEN}✔ Zero AI slop detected. Codebase is free of conversational residue and echo comments.${RESET}`);
246
+ } else {
247
+ lines.push(renderGroupedViolationsTerminal(slopViolations));
248
+ }
249
+
250
+ if (includePrompt) {
251
+ const promptSlop = buildAiSlopPrompt(report);
252
+ if (promptSlop) {
253
+ lines.push(formatPromptBox('🤖 AI AGENT REFACTORING PROMPT (AI SLOP & AUTHENTICITY)', promptSlop));
254
+ }
255
+ }
256
+
257
+ lines.push(`${sectionColor}======================================================================${RESET}\n`);
258
+ return lines.join('\n');
259
+ };
@@ -0,0 +1,4 @@
1
+ import type { AuditReport } from './types';
2
+
3
+ export declare function formatFailuresSection(report: AuditReport): string;
4
+ export declare function formatPassesSection(report: AuditReport): string;