@chemx/starter-kit 26.9.11-362 → 26.9.11-481
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/history.d.ts +6 -0
- package/cli/audit/history.js +60 -15
- package/cli/audit/prompts.js +5 -5
- package/cli/audit/reporter-ascii.d.ts +4 -0
- package/cli/audit/reporter-ascii.js +99 -0
- package/cli/audit/reporter-grades.js +24 -8
- package/cli/audit/reporter-markdown.js +5 -4
- package/cli/audit/reporter-utils.js +24 -6
- package/cli/audit/reporter.js +49 -11
- package/cli/audit/social.d.ts +3 -0
- package/cli/audit/social.js +60 -11
- package/cli/audit/types.d.ts +9 -0
- package/cli/audit.js +14 -2
- package/cli/help.js +4 -4
- package/cli/installer-templates.js +13 -2
- package/cli/installer.d.ts +1 -0
- package/cli/installer.js +48 -0
- package/cli/license.js +8 -8
- package/cli/navigator-actions.js +274 -0
- package/cli/navigator-banner.js +98 -0
- package/cli/navigator-conversion.js +3 -3
- package/cli/navigator-grades.js +20 -3
- package/cli/navigator-menu.js +127 -0
- package/cli/navigator.d.ts +21 -2
- package/cli/navigator.js +46 -320
- package/cli/terminal.js +3 -3
- package/docs/CHANGELOG.md +29 -1
- package/package.json +1 -1
package/cli/navigator.js
CHANGED
|
@@ -1,56 +1,29 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { spawnSync } from "node:child_process";
|
|
4
1
|
import {
|
|
5
2
|
hasGum,
|
|
6
3
|
gumChoose,
|
|
7
|
-
gumInput,
|
|
8
4
|
promptQuestion,
|
|
9
5
|
stripAnsi,
|
|
10
6
|
confirmAction
|
|
11
7
|
} from "./terminal.js";
|
|
8
|
+
import { saveAuditSnapshot, groupViolationsBySeverity } from "./audit.js";
|
|
9
|
+
import { areGuardrailsInstalled } from "./installer.js";
|
|
10
|
+
import { renderDashboardBanner } from "./navigator-banner.js";
|
|
12
11
|
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
formatGradeCSection,
|
|
19
|
-
formatGradeBSection,
|
|
20
|
-
formatGradeASection,
|
|
21
|
-
getChemicalXAsciiBanner,
|
|
22
|
-
saveAuditSnapshot,
|
|
23
|
-
getAuditHistory,
|
|
24
|
-
getAuditBaseline,
|
|
25
|
-
createSnapshotFromReport,
|
|
26
|
-
formatTransformationTerminal,
|
|
27
|
-
formatHistoryTimelineTerminal,
|
|
28
|
-
buildGradeFPrompt,
|
|
29
|
-
buildGradeDPrompt,
|
|
30
|
-
buildGradeCPrompt,
|
|
31
|
-
buildGradeBPrompt,
|
|
32
|
-
buildMasterPrompt,
|
|
33
|
-
DISCUSSION_CATEGORY
|
|
34
|
-
} from "./audit.js";
|
|
35
|
-
|
|
12
|
+
formatButtonTag,
|
|
13
|
+
buildNavigatorMenu,
|
|
14
|
+
matchGumChoice,
|
|
15
|
+
matchFallbackChoice
|
|
16
|
+
} from "./navigator-menu.js";
|
|
36
17
|
import {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
resolveHighMedGrade,
|
|
41
|
-
resolveLowGrade,
|
|
42
|
-
resolvePillarGrade,
|
|
43
|
-
resolveHotspotGrade,
|
|
44
|
-
resolveContextGrade
|
|
45
|
-
} from "./navigator-grades.js";
|
|
46
|
-
import { extractPromptFromContent, showPagedContent } from "./navigator-paged.js";
|
|
47
|
-
import { showConversionMenu } from "./navigator-conversion.js";
|
|
18
|
+
buildActiveGrades,
|
|
19
|
+
buildDashboardActionGroups
|
|
20
|
+
} from "./navigator-actions.js";
|
|
48
21
|
import { handleShareToDiscussions } from "./navigator-share.js";
|
|
49
|
-
import { runInstallWizard } from "./installer.js";
|
|
50
22
|
|
|
51
23
|
export {
|
|
52
24
|
resolveGradeColor,
|
|
53
25
|
resolveGradeBadge,
|
|
26
|
+
resolveHealthHearts,
|
|
54
27
|
resolveCriticalGrade,
|
|
55
28
|
resolveHighMedGrade,
|
|
56
29
|
resolveLowGrade,
|
|
@@ -61,248 +34,22 @@ export {
|
|
|
61
34
|
export { extractPromptFromContent, showPagedContent } from "./navigator-paged.js";
|
|
62
35
|
export { showConversionMenu } from "./navigator-conversion.js";
|
|
63
36
|
export { handleShareToDiscussions } from "./navigator-share.js";
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const isSevereMonolith = (h) => h.lineCount >= 1000 && h.lineCount < 2000;
|
|
67
|
-
const isWarningMonolith = (h) => h.lineCount >= 500 && h.lineCount < 1000;
|
|
68
|
-
const isPassedPillar = (p) => p.status === "PASSED";
|
|
69
|
-
const hasGradeItems = (g) => g.count > 0;
|
|
70
|
-
|
|
71
|
-
export const renderDashboardBanner = (
|
|
72
|
-
health,
|
|
73
|
-
metrics,
|
|
74
|
-
violations,
|
|
75
|
-
critical,
|
|
76
|
-
highMediumCount,
|
|
77
|
-
low
|
|
78
|
-
) => {
|
|
79
|
-
if (process.stdout.isTTY) {
|
|
80
|
-
console.clear();
|
|
81
|
-
}
|
|
82
|
-
process.stdout.write(getChemicalXAsciiBanner(health.grade));
|
|
83
|
-
|
|
84
|
-
const gColor = resolveGradeColor(health.grade);
|
|
85
|
-
const critColor = critical.length > 0 ? "\x1b[31;1m" : "\x1b[32m";
|
|
86
|
-
const highMedColor = highMediumCount > 0 ? "\x1b[38;5;208;1m" : "\x1b[32m";
|
|
87
|
-
const lowColor = low.length > 0 ? "\x1b[33;1m" : "\x1b[32m";
|
|
88
|
-
|
|
89
|
-
if (hasGum()) {
|
|
90
|
-
spawnSync(
|
|
91
|
-
"gum",
|
|
92
|
-
[
|
|
93
|
-
"style",
|
|
94
|
-
"--border=rounded",
|
|
95
|
-
"--border-foreground=81",
|
|
96
|
-
"--padding=0 2",
|
|
97
|
-
"--bold",
|
|
98
|
-
`\x1b[1m\x1b[38;2;98;201;255mChemical X Protocol: Architectural Audit Dashboard\x1b[0m\n` +
|
|
99
|
-
`Health Score: \x1b[1m\x1b[38;2;98;201;255m${health.score}/100\x1b[0m ${gColor}[Grade: ${health.grade}]\x1b[0m (${gColor}${health.label}\x1b[0m)\n` +
|
|
100
|
-
`Scanned: \x1b[36m${metrics.scannedFiles} files\x1b[0m | LOC: \x1b[36m${metrics.totalLoc}\x1b[0m | Violations: \x1b[33m${violations.length}\x1b[0m\n` +
|
|
101
|
-
`Hazards: ${critColor}${critical.length} Critical\x1b[0m | ${highMedColor}${highMediumCount} High/Med\x1b[0m | ${lowColor}${low.length} Low\x1b[0m`
|
|
102
|
-
],
|
|
103
|
-
{ stdio: "inherit" }
|
|
104
|
-
);
|
|
105
|
-
} else {
|
|
106
|
-
process.stdout.write(
|
|
107
|
-
`\n\x1b[1m\x1b[38;2;98;201;255mChemical X Protocol: Architectural Audit Dashboard\x1b[0m\n` +
|
|
108
|
-
`Health Score: \x1b[1m\x1b[38;2;98;201;255m${health.score}/100\x1b[0m ${gColor}[Grade: ${health.grade}]\x1b[0m (${gColor}${health.label}\x1b[0m)\n` +
|
|
109
|
-
`Scanned: \x1b[36m${metrics.scannedFiles} files\x1b[0m | LOC: \x1b[36m${metrics.totalLoc}\x1b[0m | Violations: \x1b[33m${violations.length}\x1b[0m\n` +
|
|
110
|
-
`Hazards: ${critColor}${critical.length} Critical\x1b[0m | ${highMedColor}${highMediumCount} High/Med\x1b[0m | ${lowColor}${low.length} Low\x1b[0m\n\n`
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
};
|
|
37
|
+
export { formatButtonTag, buildNavigatorMenu } from "./navigator-menu.js";
|
|
38
|
+
export { renderDashboardBanner } from "./navigator-banner.js";
|
|
114
39
|
|
|
115
40
|
export const runInteractiveAuditNavigator = async (report, onScaffold = null) => {
|
|
116
41
|
saveAuditSnapshot(report);
|
|
117
|
-
const { metrics, health,
|
|
42
|
+
const { metrics, health, violations, contextAnalysis } = report;
|
|
118
43
|
const { critical, high, medium, low } = groupViolationsBySeverity(violations);
|
|
119
44
|
const highMediumCount = high.length + medium.length;
|
|
120
45
|
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
const extremeMonoliths = hotspots.filter(isExtremeMonolith);
|
|
124
|
-
const severeMonoliths = hotspots.filter(isSevereMonolith);
|
|
125
|
-
const warningMonoliths = hotspots.filter(isWarningMonolith);
|
|
126
|
-
|
|
127
|
-
const gradeFCount = critical.length + extremeMonoliths.length;
|
|
128
|
-
const gradeDCount = high.length + severeMonoliths.length;
|
|
129
|
-
const gradeCCount = medium.length + warningMonoliths.length;
|
|
130
|
-
const gradeBCount = low.length;
|
|
131
|
-
const gradeACount = passedPillarsCount;
|
|
132
|
-
|
|
133
|
-
const actions = [
|
|
134
|
-
{
|
|
135
|
-
key: "report",
|
|
136
|
-
tag: "\x1b[36m[Report ]\x1b[0m",
|
|
137
|
-
label: "📋 Show Full Report (All Sections at Once)",
|
|
138
|
-
action: async () => {
|
|
139
|
-
await showPagedContent(formatTerminalReport(report), buildMasterPrompt(report));
|
|
140
|
-
}
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
key: "progress",
|
|
144
|
-
tag: "\x1b[32m[Progress ]\x1b[0m",
|
|
145
|
-
label: "📈 View Before & After Transformation Progress",
|
|
146
|
-
action: async () => {
|
|
147
|
-
const baseline = getAuditBaseline();
|
|
148
|
-
const history = getAuditHistory();
|
|
149
|
-
const currentSnapshot = createSnapshotFromReport(report);
|
|
150
|
-
|
|
151
|
-
let output = "";
|
|
152
|
-
if (baseline) {
|
|
153
|
-
output += formatTransformationTerminal(baseline, currentSnapshot);
|
|
154
|
-
} else {
|
|
155
|
-
output +=
|
|
156
|
-
"\n\x1b[33mNo baseline audit found. Current audit established as baseline.\x1b[0m\n";
|
|
157
|
-
}
|
|
46
|
+
const activeGrades = buildActiveGrades(report);
|
|
47
|
+
const actions = buildDashboardActionGroups({ report, onScaffold });
|
|
158
48
|
|
|
159
|
-
|
|
160
|
-
output += "\n\n" + formatHistoryTimelineTerminal(history);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
await showPagedContent(output);
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
key: "share",
|
|
168
|
-
tag: "\x1b[35m[Share ]\x1b[0m",
|
|
169
|
-
label: `🕵 Post to GitHub Discussions (${DISCUSSION_CATEGORY})`,
|
|
170
|
-
action: async () => {
|
|
171
|
-
await handleShareToDiscussions(report);
|
|
172
|
-
}
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
key: "export",
|
|
176
|
-
tag: "\x1b[36m[Export ]\x1b[0m",
|
|
177
|
-
label: "💾 Export Markdown Report to File",
|
|
178
|
-
action: async () => {
|
|
179
|
-
const outName = hasGum()
|
|
180
|
-
? gumInput("Export file path:", "AUDIT_REPORT.md") || "AUDIT_REPORT.md"
|
|
181
|
-
: (await promptQuestion("Export file path [AUDIT_REPORT.md]: ")) || "AUDIT_REPORT.md";
|
|
182
|
-
const md = generateMarkdownReport(report);
|
|
183
|
-
fs.writeFileSync(path.resolve(process.cwd(), outName), md, "utf-8");
|
|
184
|
-
process.stdout.write(`\x1b[32m✔ Exported markdown audit report to ${outName}\x1b[0m\n\n`);
|
|
185
|
-
if (hasGum()) {
|
|
186
|
-
gumChoose(["<-- Back to Audit Dashboard"]);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
{
|
|
191
|
-
key: "install",
|
|
192
|
-
tag: "\x1b[32m[Install ]\x1b[0m",
|
|
193
|
-
label: "🪝 Install Pre-Commit Hook & GitHub CI Workflow",
|
|
194
|
-
action: async () => {
|
|
195
|
-
await runInstallWizard(process.cwd());
|
|
196
|
-
if (hasGum()) {
|
|
197
|
-
gumChoose(["<-- Back to Audit Dashboard"]);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
key: "upgrade",
|
|
203
|
-
tag: "\x1b[33m[Upgrade ]\x1b[0m",
|
|
204
|
-
label: "💎 Unlock Full Molecular Rules & Scaffolding (Chemical X: Team Power Puff)",
|
|
205
|
-
action: async () => {
|
|
206
|
-
await showConversionMenu(onScaffold);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
];
|
|
210
|
-
|
|
211
|
-
const gradeTiers = [
|
|
212
|
-
{
|
|
213
|
-
grade: "F",
|
|
214
|
-
count: gradeFCount,
|
|
215
|
-
icon: "❌",
|
|
216
|
-
description: "Critical Hazards & Extreme Monoliths",
|
|
217
|
-
action: async () => {
|
|
218
|
-
await showPagedContent(formatGradeFSection(report), buildGradeFPrompt(report));
|
|
219
|
-
}
|
|
220
|
-
},
|
|
221
|
-
{
|
|
222
|
-
grade: "D",
|
|
223
|
-
count: gradeDCount,
|
|
224
|
-
icon: "⚠️ ",
|
|
225
|
-
description: "High Severity Debts & Severe Monoliths",
|
|
226
|
-
action: async () => {
|
|
227
|
-
await showPagedContent(formatGradeDSection(report), buildGradeDPrompt(report));
|
|
228
|
-
}
|
|
229
|
-
},
|
|
230
|
-
{
|
|
231
|
-
grade: "C",
|
|
232
|
-
count: gradeCCount,
|
|
233
|
-
icon: "⚡",
|
|
234
|
-
description: "Medium Severity Debts & Monolith Drift",
|
|
235
|
-
action: async () => {
|
|
236
|
-
await showPagedContent(formatGradeCSection(report), buildGradeCPrompt(report));
|
|
237
|
-
}
|
|
238
|
-
},
|
|
239
|
-
{
|
|
240
|
-
grade: "B",
|
|
241
|
-
count: gradeBCount,
|
|
242
|
-
icon: "ℹ️ ",
|
|
243
|
-
description: "Low Hygiene Issues & Minor Debts",
|
|
244
|
-
action: async () => {
|
|
245
|
-
await showPagedContent(formatGradeBSection(report), buildGradeBPrompt(report));
|
|
246
|
-
}
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
grade: "A",
|
|
250
|
-
count: gradeACount,
|
|
251
|
-
icon: "✅",
|
|
252
|
-
description: "Compliant Checks & Passing Pillars",
|
|
253
|
-
action: async () => {
|
|
254
|
-
await showPagedContent(formatGradeASection(report));
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
];
|
|
258
|
-
|
|
259
|
-
const createActiveGradeItem = (g) => ({
|
|
260
|
-
key: `grade_${g.grade.toLowerCase()}`,
|
|
261
|
-
grade: g.grade.toLowerCase(),
|
|
262
|
-
tag: resolveGradeBadge(g.grade),
|
|
263
|
-
label: `${g.icon} Grade ${g.grade}: ${g.description} (${g.count} ${g.grade === "A" ? "clean" : "items"})`,
|
|
264
|
-
action: g.action
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
const activeGrades = gradeTiers.filter(hasGradeItems).map(createActiveGradeItem);
|
|
268
|
-
|
|
269
|
-
const exitAction = {
|
|
270
|
-
key: "exit",
|
|
271
|
-
tag: "\x1b[90m[Exit ]\x1b[0m",
|
|
272
|
-
label: "🚪 Exit",
|
|
273
|
-
action: async () => {}
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
const menuItems = [...actions, ...activeGrades, exitAction];
|
|
277
|
-
const menuOptions = [];
|
|
278
|
-
let currentIndex = 1;
|
|
279
|
-
|
|
280
|
-
for (const act of actions) {
|
|
281
|
-
act.index = currentIndex;
|
|
282
|
-
const pad = String(currentIndex).padStart(2, " ");
|
|
283
|
-
menuOptions.push(` ${pad}. ${act.tag} ${act.label}`);
|
|
284
|
-
currentIndex++;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
if (activeGrades.length > 0) {
|
|
288
|
-
menuOptions.push("──────────────────────────────────────────────────────────────────────");
|
|
289
|
-
for (const g of activeGrades) {
|
|
290
|
-
g.index = currentIndex;
|
|
291
|
-
const pad = String(currentIndex).padStart(2, " ");
|
|
292
|
-
menuOptions.push(` ${pad}. ${g.tag} ${g.label}`);
|
|
293
|
-
currentIndex++;
|
|
294
|
-
}
|
|
295
|
-
menuOptions.push("──────────────────────────────────────────────────────────────────────");
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
exitAction.index = currentIndex;
|
|
299
|
-
const exitPad = String(currentIndex).padStart(2, " ");
|
|
300
|
-
menuOptions.push(` ${exitPad}. ${exitAction.tag} ${exitAction.label}`);
|
|
301
|
-
|
|
302
|
-
renderDashboardBanner(health, metrics, violations, critical, highMediumCount, low);
|
|
49
|
+
renderDashboardBanner(health, metrics, violations, critical, highMediumCount, low, contextAnalysis);
|
|
303
50
|
|
|
304
51
|
const shouldPublish = await confirmAction(
|
|
305
|
-
"
|
|
52
|
+
"Publish audit report and promote your project to our GitHub Discussions Audits Forum?",
|
|
306
53
|
"Publish Report",
|
|
307
54
|
"Skip to Menu",
|
|
308
55
|
true
|
|
@@ -313,7 +60,28 @@ export const runInteractiveAuditNavigator = async (report, onScaffold = null) =>
|
|
|
313
60
|
}
|
|
314
61
|
|
|
315
62
|
while (true) {
|
|
316
|
-
renderDashboardBanner(health, metrics, violations, critical, highMediumCount, low);
|
|
63
|
+
renderDashboardBanner(health, metrics, violations, critical, highMediumCount, low, contextAnalysis);
|
|
64
|
+
|
|
65
|
+
const guardrailsInstalled = areGuardrailsInstalled(process.cwd());
|
|
66
|
+
const topActions = [];
|
|
67
|
+
if (!guardrailsInstalled) {
|
|
68
|
+
topActions.push(actions.installAction);
|
|
69
|
+
}
|
|
70
|
+
topActions.push(actions.upgradeAction, actions.reportAction);
|
|
71
|
+
|
|
72
|
+
const midActions = [actions.shareAction, actions.progressAction, actions.exportAction];
|
|
73
|
+
const bottomActions = [];
|
|
74
|
+
if (actions.shouldShowPromptAction) {
|
|
75
|
+
bottomActions.push(actions.copyPromptAction);
|
|
76
|
+
}
|
|
77
|
+
bottomActions.push(actions.exitAction);
|
|
78
|
+
|
|
79
|
+
const { menuItems, menuOptions } = buildNavigatorMenu(
|
|
80
|
+
topActions,
|
|
81
|
+
activeGrades,
|
|
82
|
+
midActions,
|
|
83
|
+
bottomActions
|
|
84
|
+
);
|
|
317
85
|
|
|
318
86
|
if (hasGum()) {
|
|
319
87
|
const choice = gumChoose(menuOptions, "Select an audit section or grade to inspect:");
|
|
@@ -324,41 +92,7 @@ export const runInteractiveAuditNavigator = async (report, onScaffold = null) =>
|
|
|
324
92
|
continue;
|
|
325
93
|
}
|
|
326
94
|
|
|
327
|
-
const match = menuItems
|
|
328
|
-
const prefix = `${item.index}.`;
|
|
329
|
-
if (cleanChoice.startsWith(prefix) || cleanChoice === String(item.index)) return true;
|
|
330
|
-
if (
|
|
331
|
-
item.key === "exit" &&
|
|
332
|
-
(cleanChoice.includes("Exit") || cleanChoice.toLowerCase() === "exit")
|
|
333
|
-
)
|
|
334
|
-
return true;
|
|
335
|
-
if (item.key === "report" && cleanChoice.includes("Report")) return true;
|
|
336
|
-
if (item.key === "share" && cleanChoice.includes("Share")) return true;
|
|
337
|
-
if (item.key === "export" && cleanChoice.includes("Export")) return true;
|
|
338
|
-
if (
|
|
339
|
-
item.key === "install" &&
|
|
340
|
-
(cleanChoice.includes("Install") ||
|
|
341
|
-
cleanChoice.includes("Pre-Commit") ||
|
|
342
|
-
cleanChoice.includes("Workflow"))
|
|
343
|
-
)
|
|
344
|
-
return true;
|
|
345
|
-
if (
|
|
346
|
-
item.key === "upgrade" &&
|
|
347
|
-
(cleanChoice.includes("Upgrade") ||
|
|
348
|
-
cleanChoice.includes("Power Puff") ||
|
|
349
|
-
cleanChoice.includes("Team Power Puff") ||
|
|
350
|
-
cleanChoice.includes("Molecular Rules"))
|
|
351
|
-
)
|
|
352
|
-
return true;
|
|
353
|
-
if (
|
|
354
|
-
item.grade &&
|
|
355
|
-
(cleanChoice.toLowerCase().includes(`grade ${item.grade}`) ||
|
|
356
|
-
cleanChoice.toLowerCase().includes(`grade: ${item.grade}`))
|
|
357
|
-
)
|
|
358
|
-
return true;
|
|
359
|
-
return false;
|
|
360
|
-
});
|
|
361
|
-
|
|
95
|
+
const match = matchGumChoice(cleanChoice, menuItems);
|
|
362
96
|
const shouldExit = !match || match.key === "exit";
|
|
363
97
|
if (shouldExit) {
|
|
364
98
|
break;
|
|
@@ -371,23 +105,15 @@ export const runInteractiveAuditNavigator = async (report, onScaffold = null) =>
|
|
|
371
105
|
}
|
|
372
106
|
process.stdout.write("\n");
|
|
373
107
|
|
|
374
|
-
const
|
|
108
|
+
const exitIndex = actions.exitAction.index;
|
|
109
|
+
const promptMsg = `Select option [1-${exitIndex}] (default: ${exitIndex}): `;
|
|
375
110
|
const selection = await promptQuestion(promptMsg);
|
|
376
|
-
const effective = selection.trim().toLowerCase() || String(
|
|
111
|
+
const effective = selection.trim().toLowerCase() || String(exitIndex);
|
|
377
112
|
|
|
378
113
|
const isSep = effective.includes("---") || effective.includes("───");
|
|
379
114
|
if (isSep) continue;
|
|
380
115
|
|
|
381
|
-
const match =
|
|
382
|
-
if (effective === String(item.index)) return true;
|
|
383
|
-
if (item.key === "exit" && (effective === "exit" || effective === String(exitAction.index)))
|
|
384
|
-
return true;
|
|
385
|
-
if (item.key === effective) return true;
|
|
386
|
-
if (item.grade && (effective === item.grade || effective === `grade ${item.grade}`))
|
|
387
|
-
return true;
|
|
388
|
-
return false;
|
|
389
|
-
});
|
|
390
|
-
|
|
116
|
+
const match = matchFallbackChoice(effective, menuItems, exitIndex);
|
|
391
117
|
const shouldExit = !match || match.key === "exit";
|
|
392
118
|
if (shouldExit) {
|
|
393
119
|
break;
|
package/cli/terminal.js
CHANGED
|
@@ -84,7 +84,7 @@ export const renderBanner = (title = "Chemical X Protocol: Molecular Architectur
|
|
|
84
84
|
};
|
|
85
85
|
|
|
86
86
|
export const gumConfirm = (
|
|
87
|
-
promptText = "
|
|
87
|
+
promptText = "Publish audit report and promote your project to our GitHub Discussions Audits Forum?",
|
|
88
88
|
affirmative = "Publish Report",
|
|
89
89
|
negative = "Skip to Menu",
|
|
90
90
|
defaultVal = true
|
|
@@ -104,7 +104,7 @@ export const gumConfirm = (
|
|
|
104
104
|
};
|
|
105
105
|
|
|
106
106
|
export const promptConfirm = async (
|
|
107
|
-
query = "
|
|
107
|
+
query = "Publish audit report and promote your project to our GitHub Discussions Audits Forum?",
|
|
108
108
|
defaultVal = true
|
|
109
109
|
) => {
|
|
110
110
|
const suffix = defaultVal ? " [Y/n]: " : " [y/N]: ";
|
|
@@ -114,7 +114,7 @@ export const promptConfirm = async (
|
|
|
114
114
|
};
|
|
115
115
|
|
|
116
116
|
export const confirmAction = async (
|
|
117
|
-
promptText = "
|
|
117
|
+
promptText = "Publish audit report and promote your project to our GitHub Discussions Audits Forum?",
|
|
118
118
|
affirmative = "Publish Report",
|
|
119
119
|
negative = "Skip to Menu",
|
|
120
120
|
defaultVal = true
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -16,16 +16,44 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
16
16
|
- `useSelfCleaningTimer`: unmount-safe interval and timeout utilities
|
|
17
17
|
- Interactive CLI capsule generator (`cli/index.js`).
|
|
18
18
|
|
|
19
|
+
## [2026-09-11]
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- Conditioned `[ Prompt ] 📋 Copy AI Prompt Fix to Clipboard` dashboard action to hide when the codebase earns a pristine Grade A+ with no pending refactoring prompt (`cli/navigator.js`, `cli/navigator-actions.js`).
|
|
23
|
+
- Added early-return guard clause to `handleCopyPromptAction` preventing empty clipboard copy operations on pristine Grade A+ audits (`cli/navigator-actions.js`).
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- Fixed typographical artifact (`and p`) in the interactive audit publication confirmation prompt across navigator and terminal handlers (`cli/navigator.js`, `cli/terminal.js`).
|
|
27
|
+
|
|
19
28
|
## [2026-09-10]
|
|
20
29
|
|
|
30
|
+
### Changed
|
|
31
|
+
- Decomposed warning monolith `cli/navigator.js` (515 lines to 123 lines) by extracting single-responsibility capsules: `cli/navigator-banner.js` (84 lines: Gamer HUD terminal rendering), `cli/navigator-menu.js` (115 lines: button tags, menu assembly, selection matching), and `cli/navigator-actions.js` (165 lines: grade drill-downs and dashboard actions), preserving all public exports and type declarations.
|
|
32
|
+
- Extracted anonymous inline callbacks into named functions across navigator modules adhering to Chemical X code syntax standards.
|
|
33
|
+
- Replaced all abbreviated `LOC` acronym references across dashboard banners, reports, Markdown exports, and refactoring prompts with fully spelled-out `lines of code` (`cli/navigator.js`, `cli/audit/reporter.js`, `cli/audit/reporter-grades.js`, `cli/audit/reporter-utils.js`, `cli/audit/reporter-markdown.js`, `cli/audit/prompts.js`, `cli/audit/social.js`, `cli/audit/history.js`, `cli/help.js`).
|
|
34
|
+
- Reordered interactive Audit Navigator dashboard menu (`cli/navigator.js`) into four distinct operational sections separated by clean dividers: top actions (`[ Install ]`, `[ Upgrade ]`, `[Full Report]`), grade drill-downs (`[ Grade: A ]`), community and metrics actions (`[ Share ]`, `[ Progress ]`, `[ Export ]`), and footer actions (`[ Prompt ]`, `[ Exit ]`).
|
|
35
|
+
- Conditioned `[ Install ]` action to display only when git pre-commit hooks and GitHub Actions CI workflow are not already installed (`areGuardrailsInstalled` in `cli/installer.js`, `cli/navigator.js`).
|
|
36
|
+
- Centered button bracket text across all dashboard actions and grade tags for uniform 13-character button width and column alignment (`formatButtonTag` in `cli/navigator.js`, `resolveGradeBadge` in `cli/navigator-grades.js`).
|
|
37
|
+
- Renamed prompt copy menu item to `[ Prompt ] 📋 Copy AI Prompt Fix to Clipboard` (`cli/navigator.js`).
|
|
38
|
+
- Renamed full report menu button to `[Full Report]` and share option label to plug website and post to GitHub Discussions (`cli/navigator.js`).
|
|
39
|
+
- Aligned terminal output columns across `METRIC COMPARISON TABLE` and `7-PILLAR PROGRESSION` in `formatTransformationTerminal` (`cli/audit/history.js`), expanding pillar and metric padding to 40 characters with uniform divider widths.
|
|
40
|
+
|
|
21
41
|
### Added
|
|
42
|
+
- Integrated real-time Token Estimate (`-TOKEN EST-`) and Currency Cost (`-CURRENCY-`) metrics into Gamer HUD (`cli/navigator-banner.js`, `cli/navigator.js`).
|
|
43
|
+
- Embedded project name in top rounded border and project working directory (`pwd`) in bottom rounded border of Gamer HUD (`cli/navigator-banner.js`).
|
|
44
|
+
- Swapped Gamer HUD column positions in `renderDashboardBanner` (`cli/navigator-banner.js`): `-FILES-` and `-LINES OF CODE-` on the left column, and `-HEALTH-` and `-HAZARDS-` on the right column.
|
|
45
|
+
- Hazard emojis (💥 for Critical, 🔥 for High/Med, 💣 for Low) in `-HAZARDS-` HUD status row (`cli/navigator-banner.js`) and interactive grade drilldown actions (`cli/navigator-actions.js`).
|
|
46
|
+
- Gamer HUD with 2-column layout in `renderDashboardBanner` (`cli/navigator.js`) grouping `-HEALTH-` and `-HAZARDS-` on the left and `-FILES-` and `-LINES OF CODE-` on the right, removing HUD title banner and quote text.
|
|
47
|
+
- Heart emoji container display (`❤️❤️❤️❤️❤️` to `🖤🖤🖤🖤🖤`) in `resolveHealthHearts` (`cli/navigator-grades.js`).
|
|
48
|
+
- Compact `X = [Grade]` ASCII art banner in `getChemicalXAsciiBanner` (`cli/audit/reporter.js`, `cli/audit/reporter-ascii.js`) removing the redundant `GRADE` text and linking Chemical X with bold ASCII `=` and dynamic letter grade typography (`A+`, `A`, `B`, etc.).
|
|
49
|
+
- Four-line compact block `REPORT CARD` ASCII art banner (`REPORT_CARD_ASCII` in `cli/audit/reporter-ascii.js`) added to the top of all grade report card sections (`formatGradeASection`, `formatGradeBSection`, `formatGradeCSection`, `formatGradeDSection`, `formatGradeFSection`) and the audit scorecard overview (`formatScorecardSection`).
|
|
22
50
|
- Free, standalone POSIX git pre-commit hook script (`scripts/pre-commit.sh`) enforcing 500-line file budgets, 100-line molecule capsule limits, and configurable minimum grade/score thresholds with automatic AI refactoring prompt clipboard copying.
|
|
23
51
|
- Production GitHub Actions CI workflow blueprint (`blueprints/workflows/chemx-audit.yml`) executing architectural audits with configurable grade thresholds and artifact uploads.
|
|
24
52
|
- Modular CLI installer capsule (`cli/installer.js`, `cli/installer.d.ts`) enabling interactive Gum and ANSI installation of pre-commit hooks, GitHub workflows, and `.chemx/config.json` project configurations.
|
|
25
53
|
- Dedicated `[Install ] 🪝 Install Pre-Commit Hook & GitHub CI Workflow` action in the interactive Audit Navigator dashboard (`cli/navigator.js`).
|
|
26
54
|
- Standalone CLI subcommands `hook`, `hooks`, `install-hooks`, and `setup-ci` in `cli/index.js` for direct non-interactive setup.
|
|
27
55
|
- Token financial telemetry engine in `cli/audit/metrics.js` translating context bloat into real-world dollar waste per AI prompt turn, weekly developer waste, and monthly team context tax based on configurable model baselines (`--model=claude|gpt4o|blended` or custom rate).
|
|
28
|
-
- Financial metrics reporting in terminal reports (`formatContextAnalysisSection` in `cli/audit/reporter.js`)
|
|
56
|
+
- Financial metrics reporting in terminal reports (`formatContextAnalysisSection` in `cli/audit/reporter.js`), Markdown reports (`cli/audit/reporter-markdown.js`), and published GitHub Discussion reports (`generateDiscussionContent` and `generateTransformationDiscussionContent` in `cli/audit/social.js`).
|
|
29
57
|
- Flexible audit threshold flags: `--min-grade`, `--min-score`, `--prompt-on-fail`, and `--copy-prompt`.
|
|
30
58
|
- Hybrid GitHub Sponsors licensing CTAs in `cli/navigator-conversion.js` and `cli/license.js` spotlighting $9/mo solo and $49/mo team unlimited sponsorship.
|
|
31
59
|
- Robust 7-pillar Quantum Engineering Architecture static analysis rule engine (`cli/audit/rules.js`) covering line budgets, control flow booleans, nested ternaries, hook saturation and return budgets, timer disposal, render-hack timeouts, type co-location, type monoliths, mock data patterns, inline styles, icon SVG leaks, and typography hygiene.
|