@vibecheckai/cli 3.7.0 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -63
- package/bin/_deprecations.js +447 -19
- package/bin/_router.js +1 -1
- package/bin/registry.js +347 -280
- package/bin/runners/context/generators/cursor-enhanced.js +2439 -0
- package/bin/runners/lib/agent-firewall/enforcement/gateway.js +1059 -0
- package/bin/runners/lib/agent-firewall/enforcement/index.js +98 -0
- package/bin/runners/lib/agent-firewall/enforcement/mode.js +318 -0
- package/bin/runners/lib/agent-firewall/enforcement/orchestrator.js +484 -0
- package/bin/runners/lib/agent-firewall/enforcement/proof-artifact.js +418 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/change-event.schema.json +173 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/intent.schema.json +181 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/verdict.schema.json +222 -0
- package/bin/runners/lib/agent-firewall/enforcement/verdict-v2.js +333 -0
- package/bin/runners/lib/agent-firewall/index.js +200 -0
- package/bin/runners/lib/agent-firewall/integration/index.js +20 -0
- package/bin/runners/lib/agent-firewall/integration/ship-gate.js +437 -0
- package/bin/runners/lib/agent-firewall/intent/alignment-engine.js +634 -0
- package/bin/runners/lib/agent-firewall/intent/auto-detect.js +426 -0
- package/bin/runners/lib/agent-firewall/intent/index.js +102 -0
- package/bin/runners/lib/agent-firewall/intent/schema.js +352 -0
- package/bin/runners/lib/agent-firewall/intent/store.js +283 -0
- package/bin/runners/lib/agent-firewall/interception/fs-interceptor.js +502 -0
- package/bin/runners/lib/agent-firewall/interception/index.js +23 -0
- package/bin/runners/lib/agent-firewall/interceptor/base.js +7 -3
- package/bin/runners/lib/agent-firewall/session/collector.js +451 -0
- package/bin/runners/lib/agent-firewall/session/index.js +26 -0
- package/bin/runners/lib/artifact-envelope.js +540 -0
- package/bin/runners/lib/auth-shared.js +977 -0
- package/bin/runners/lib/checkpoint.js +941 -0
- package/bin/runners/lib/cleanup/engine.js +571 -0
- package/bin/runners/lib/cleanup/index.js +53 -0
- package/bin/runners/lib/cleanup/output.js +375 -0
- package/bin/runners/lib/cleanup/rules.js +1060 -0
- package/bin/runners/lib/doctor/diagnosis-receipt.js +454 -0
- package/bin/runners/lib/doctor/failure-signatures.js +526 -0
- package/bin/runners/lib/doctor/fix-script.js +336 -0
- package/bin/runners/lib/doctor/modules/build-tools.js +453 -0
- package/bin/runners/lib/doctor/modules/index.js +62 -3
- package/bin/runners/lib/doctor/modules/os-quirks.js +706 -0
- package/bin/runners/lib/doctor/modules/repo-integrity.js +485 -0
- package/bin/runners/lib/doctor/safe-repair.js +384 -0
- package/bin/runners/lib/engine/ast-cache.js +210 -210
- package/bin/runners/lib/engine/auth-extractor.js +211 -211
- package/bin/runners/lib/engine/billing-extractor.js +112 -112
- package/bin/runners/lib/engine/enforcement-extractor.js +100 -100
- package/bin/runners/lib/engine/env-extractor.js +207 -207
- package/bin/runners/lib/engine/express-extractor.js +208 -208
- package/bin/runners/lib/engine/extractors.js +849 -849
- package/bin/runners/lib/engine/index.js +207 -207
- package/bin/runners/lib/engine/repo-index.js +514 -514
- package/bin/runners/lib/engine/types.js +124 -124
- package/bin/runners/lib/engines/attack-detector.js +1192 -0
- package/bin/runners/lib/entitlements-v2.js +2 -2
- package/bin/runners/lib/missions/briefing.js +427 -0
- package/bin/runners/lib/missions/checkpoint.js +753 -0
- package/bin/runners/lib/missions/hardening.js +851 -0
- package/bin/runners/lib/missions/plan.js +421 -32
- package/bin/runners/lib/missions/safety-gates.js +645 -0
- package/bin/runners/lib/missions/schema.js +478 -0
- package/bin/runners/lib/packs/bundle.js +675 -0
- package/bin/runners/lib/packs/evidence-pack.js +671 -0
- package/bin/runners/lib/packs/pack-factory.js +837 -0
- package/bin/runners/lib/packs/permissions-pack.js +686 -0
- package/bin/runners/lib/packs/proof-graph-pack.js +779 -0
- package/bin/runners/lib/safelist/index.js +96 -0
- package/bin/runners/lib/safelist/integration.js +334 -0
- package/bin/runners/lib/safelist/matcher.js +696 -0
- package/bin/runners/lib/safelist/schema.js +948 -0
- package/bin/runners/lib/safelist/store.js +438 -0
- package/bin/runners/lib/schemas/ship-manifest.schema.json +251 -0
- package/bin/runners/lib/ship-gate.js +832 -0
- package/bin/runners/lib/ship-manifest.js +1153 -0
- package/bin/runners/lib/ship-output.js +1 -1
- package/bin/runners/lib/unified-cli-output.js +710 -383
- package/bin/runners/lib/upsell.js +3 -3
- package/bin/runners/lib/why-tree.js +650 -0
- package/bin/runners/runAllowlist.js +33 -4
- package/bin/runners/runApprove.js +240 -1122
- package/bin/runners/runAudit.js +692 -0
- package/bin/runners/runAuth.js +325 -29
- package/bin/runners/runCheckpoint.js +442 -494
- package/bin/runners/runCleanup.js +343 -0
- package/bin/runners/runDoctor.js +269 -19
- package/bin/runners/runFix.js +411 -32
- package/bin/runners/runForge.js +411 -0
- package/bin/runners/runIntent.js +906 -0
- package/bin/runners/runKickoff.js +878 -0
- package/bin/runners/runLaunch.js +2000 -0
- package/bin/runners/runLink.js +785 -0
- package/bin/runners/runMcp.js +1741 -837
- package/bin/runners/runPacks.js +2089 -0
- package/bin/runners/runPolish.js +41 -0
- package/bin/runners/runReality.js +178 -1
- package/bin/runners/runSafelist.js +1190 -0
- package/bin/runners/runScan.js +21 -9
- package/bin/runners/runShield.js +1282 -0
- package/bin/runners/runShip.js +395 -16
- package/bin/vibecheck.js +34 -6
- package/mcp-server/README.md +117 -158
- package/mcp-server/handlers/index.ts +2 -2
- package/mcp-server/handlers/tool-handler.ts +50 -11
- package/mcp-server/index.js +16 -0
- package/mcp-server/intent-firewall-interceptor.js +529 -0
- package/mcp-server/lib/executor.ts +5 -5
- package/mcp-server/lib/index.ts +14 -4
- package/mcp-server/lib/sandbox.test.ts +4 -4
- package/mcp-server/lib/sandbox.ts +2 -2
- package/mcp-server/manifest.json +473 -0
- package/mcp-server/package.json +1 -1
- package/mcp-server/registry/tool-registry.js +315 -523
- package/mcp-server/registry/tools.json +442 -428
- package/mcp-server/registry.test.ts +18 -12
- package/mcp-server/tier-auth.js +68 -11
- package/mcp-server/tools-v3.js +70 -16
- package/mcp-server/tsconfig.json +1 -0
- package/package.json +2 -1
- package/bin/runners/runProof.zip +0 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vibecheck polish --cleanup
|
|
3
|
+
*
|
|
4
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
5
|
+
* PRODUCTION-GRADE CLEANUP WITHOUT CHAOS
|
|
6
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
7
|
+
*
|
|
8
|
+
* Safe transformations to improve code quality:
|
|
9
|
+
* - Remove console.log, debugger statements
|
|
10
|
+
* - Flag empty catch blocks, dead code
|
|
11
|
+
* - Identify unsafe regex patterns
|
|
12
|
+
*
|
|
13
|
+
* Design:
|
|
14
|
+
* - Safe by default: Only transformations that cannot change behavior
|
|
15
|
+
* - Aggressive opt-in: Requires --aggressive --yes-i-am-sure
|
|
16
|
+
* - Checkpoint integration: Automatic backup before any changes
|
|
17
|
+
* - Transparent: Full diff preview before applying
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* vibecheck polish --cleanup # Analyze and show diff
|
|
21
|
+
* vibecheck polish --cleanup --apply # Apply safe fixes
|
|
22
|
+
* vibecheck polish --cleanup --aggressive # Include risky fixes (preview only)
|
|
23
|
+
* vibecheck polish --cleanup --aggressive --yes-i-am-sure --apply # Apply all
|
|
24
|
+
* vibecheck polish --rollback <backup-id> # Undo changes
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
"use strict";
|
|
28
|
+
|
|
29
|
+
const fs = require("fs");
|
|
30
|
+
const path = require("path");
|
|
31
|
+
const { EXIT } = require("./lib/exit-codes");
|
|
32
|
+
const { parseGlobalFlags, shouldSuppressOutput, isJsonMode } = require("./lib/global-flags");
|
|
33
|
+
const cleanup = require("./lib/cleanup");
|
|
34
|
+
|
|
35
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
36
|
+
// ARGUMENT PARSING
|
|
37
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
38
|
+
|
|
39
|
+
function parseArgs(args) {
|
|
40
|
+
const opts = {
|
|
41
|
+
help: false,
|
|
42
|
+
json: false,
|
|
43
|
+
apply: false,
|
|
44
|
+
aggressive: false,
|
|
45
|
+
yesIAmSure: false,
|
|
46
|
+
rollback: null,
|
|
47
|
+
verbose: false,
|
|
48
|
+
path: process.cwd(),
|
|
49
|
+
quiet: false,
|
|
50
|
+
maxFiles: 1000,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
for (let i = 0; i < args.length; i++) {
|
|
54
|
+
const arg = args[i];
|
|
55
|
+
|
|
56
|
+
if (arg === "--help" || arg === "-h") opts.help = true;
|
|
57
|
+
else if (arg === "--json") opts.json = true;
|
|
58
|
+
else if (arg === "--apply" || arg === "-a") opts.apply = true;
|
|
59
|
+
else if (arg === "--aggressive") opts.aggressive = true;
|
|
60
|
+
else if (arg === "--yes-i-am-sure") opts.yesIAmSure = true;
|
|
61
|
+
else if (arg === "--verbose" || arg === "-v") opts.verbose = true;
|
|
62
|
+
else if (arg === "--quiet" || arg === "-q") opts.quiet = true;
|
|
63
|
+
else if (arg === "--rollback" || arg === "-r") opts.rollback = args[++i];
|
|
64
|
+
else if (arg === "--path" || arg === "-p") opts.path = args[++i];
|
|
65
|
+
else if (arg === "--max-files") opts.maxFiles = parseInt(args[++i], 10);
|
|
66
|
+
else if (!arg.startsWith("-") && !opts.rollback) opts.path = arg;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return opts;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
73
|
+
// HELP
|
|
74
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
75
|
+
|
|
76
|
+
function printHelp() {
|
|
77
|
+
const { colors: c, icons } = cleanup;
|
|
78
|
+
|
|
79
|
+
console.log(`
|
|
80
|
+
${c.bold}${icons.broom} vibecheck polish --cleanup${c.reset}
|
|
81
|
+
${c.dim}Production-grade cleanup without chaos${c.reset}
|
|
82
|
+
|
|
83
|
+
${c.bold}USAGE${c.reset}
|
|
84
|
+
vibecheck polish --cleanup [options]
|
|
85
|
+
|
|
86
|
+
${c.bold}OPTIONS${c.reset}
|
|
87
|
+
${c.cyan}--apply, -a${c.reset} Apply safe fixes (creates backup first)
|
|
88
|
+
${c.cyan}--aggressive${c.reset} Include risky transformations in analysis
|
|
89
|
+
${c.cyan}--yes-i-am-sure${c.reset} Confirm aggressive fixes (required with --aggressive --apply)
|
|
90
|
+
${c.cyan}--rollback <id>${c.reset} Rollback changes using backup
|
|
91
|
+
${c.cyan}--verbose, -v${c.reset} Show detailed output
|
|
92
|
+
${c.cyan}--json${c.reset} Output as JSON
|
|
93
|
+
${c.cyan}--path, -p <dir>${c.reset} Project path (default: current directory)
|
|
94
|
+
${c.cyan}--max-files <n>${c.reset} Maximum files to scan (default: 1000)
|
|
95
|
+
|
|
96
|
+
${c.bold}WHAT IT CLEANS${c.reset}
|
|
97
|
+
|
|
98
|
+
${c.green}${icons.check} Safe (auto-fixable):${c.reset}
|
|
99
|
+
• console.log, console.debug, console.info
|
|
100
|
+
• debugger statements
|
|
101
|
+
• Trailing whitespace
|
|
102
|
+
• Multiple empty lines
|
|
103
|
+
|
|
104
|
+
${c.yellow}${icons.warning} Moderate (flagged for review):${c.reset}
|
|
105
|
+
• Empty catch blocks (silent failures)
|
|
106
|
+
• Empty functions
|
|
107
|
+
• TODO/FIXME comments
|
|
108
|
+
• Code after return statements
|
|
109
|
+
|
|
110
|
+
${c.red}${icons.cross} Aggressive (requires explicit opt-in):${c.reset}
|
|
111
|
+
• Unsafe regex patterns (ReDoS risk)
|
|
112
|
+
• Commented-out code blocks
|
|
113
|
+
• TypeScript 'any' types
|
|
114
|
+
• console.error statements
|
|
115
|
+
• Browser alert/confirm/prompt
|
|
116
|
+
|
|
117
|
+
${c.bold}EXAMPLES${c.reset}
|
|
118
|
+
|
|
119
|
+
${c.dim}# Preview what would be cleaned${c.reset}
|
|
120
|
+
${c.cyan}vibecheck polish --cleanup${c.reset}
|
|
121
|
+
|
|
122
|
+
${c.dim}# Apply safe fixes${c.reset}
|
|
123
|
+
${c.cyan}vibecheck polish --cleanup --apply${c.reset}
|
|
124
|
+
|
|
125
|
+
${c.dim}# See aggressive issues (preview only)${c.reset}
|
|
126
|
+
${c.cyan}vibecheck polish --cleanup --aggressive${c.reset}
|
|
127
|
+
|
|
128
|
+
${c.dim}# Apply ALL fixes (with confirmation)${c.reset}
|
|
129
|
+
${c.cyan}vibecheck polish --cleanup --aggressive --yes-i-am-sure --apply${c.reset}
|
|
130
|
+
|
|
131
|
+
${c.dim}# Undo changes${c.reset}
|
|
132
|
+
${c.cyan}vibecheck polish --rollback .vibecheck/cleanup-backups/2024-01-15T10-30-00${c.reset}
|
|
133
|
+
|
|
134
|
+
${c.bold}RISK LEVELS${c.reset}
|
|
135
|
+
|
|
136
|
+
${c.green}Safe${c.reset} Cannot change program behavior. Auto-applied with --apply.
|
|
137
|
+
${c.yellow}Moderate${c.reset} Generally safe, but worth reviewing. Flagged in output.
|
|
138
|
+
${c.red}Aggressive${c.reset} Could change behavior. Requires --aggressive --yes-i-am-sure.
|
|
139
|
+
|
|
140
|
+
${c.bold}INTEGRATION${c.reset}
|
|
141
|
+
|
|
142
|
+
• Creates automatic backups before changes
|
|
143
|
+
• Use ${c.cyan}vibecheck checkpoint${c.reset} before cleanup for full rollback support
|
|
144
|
+
• JSON output available for CI integration
|
|
145
|
+
|
|
146
|
+
${c.dim}${"─".repeat(60)}${c.reset}
|
|
147
|
+
${c.dim}Tip: Always run tests after applying fixes!${c.reset}
|
|
148
|
+
`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
152
|
+
// MAIN
|
|
153
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
154
|
+
|
|
155
|
+
async function runCleanup(args = [], context = {}) {
|
|
156
|
+
const { flags: globalFlags, cleanArgs } = parseGlobalFlags(args);
|
|
157
|
+
const opts = parseArgs([...cleanArgs, ...args]);
|
|
158
|
+
|
|
159
|
+
const quiet = shouldSuppressOutput(globalFlags) || opts.quiet;
|
|
160
|
+
const json = isJsonMode(globalFlags) || opts.json;
|
|
161
|
+
const projectPath = path.resolve(opts.path || context.repoRoot || process.cwd());
|
|
162
|
+
|
|
163
|
+
// Handle help
|
|
164
|
+
if (opts.help) {
|
|
165
|
+
printHelp();
|
|
166
|
+
return EXIT.SUCCESS;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Handle rollback
|
|
170
|
+
if (opts.rollback) {
|
|
171
|
+
return handleRollback(opts.rollback, json, quiet);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const { colors: c, icons } = cleanup;
|
|
175
|
+
|
|
176
|
+
// Validate project path
|
|
177
|
+
if (!fs.existsSync(projectPath)) {
|
|
178
|
+
if (json) {
|
|
179
|
+
console.log(JSON.stringify({ success: false, error: `Path not found: ${projectPath}` }));
|
|
180
|
+
} else {
|
|
181
|
+
console.error(`${c.red}${icons.cross}${c.reset} Path not found: ${projectPath}`);
|
|
182
|
+
}
|
|
183
|
+
return EXIT.NOT_FOUND;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Validate aggressive confirmation
|
|
187
|
+
if (opts.aggressive && opts.apply && !opts.yesIAmSure) {
|
|
188
|
+
if (json) {
|
|
189
|
+
console.log(JSON.stringify({
|
|
190
|
+
success: false,
|
|
191
|
+
error: "Aggressive apply requires --yes-i-am-sure flag",
|
|
192
|
+
hint: "Add --yes-i-am-sure to confirm you understand the risks"
|
|
193
|
+
}));
|
|
194
|
+
} else {
|
|
195
|
+
console.error(`
|
|
196
|
+
${c.red}${c.bold}${icons.warning} CONFIRMATION REQUIRED${c.reset}
|
|
197
|
+
|
|
198
|
+
Aggressive transformations could change program behavior.
|
|
199
|
+
To proceed, add the confirmation flag:
|
|
200
|
+
|
|
201
|
+
${c.cyan}vibecheck polish --cleanup --aggressive --yes-i-am-sure --apply${c.reset}
|
|
202
|
+
|
|
203
|
+
${c.dim}This ensures you understand that these changes need testing.${c.reset}
|
|
204
|
+
`);
|
|
205
|
+
}
|
|
206
|
+
return EXIT.USER_ERROR;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Print banner
|
|
210
|
+
if (!json && !quiet) {
|
|
211
|
+
cleanup.printBanner();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Analyze project
|
|
215
|
+
if (!json && !quiet) {
|
|
216
|
+
process.stdout.write(`${icons.broom} Scanning project for cleanup opportunities...`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const analysis = await cleanup.analyzeProject(projectPath, {
|
|
220
|
+
aggressive: opts.aggressive,
|
|
221
|
+
includeModerate: true,
|
|
222
|
+
maxFiles: opts.maxFiles,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
if (!json && !quiet && process.stdout.clearLine) {
|
|
226
|
+
process.stdout.clearLine(0);
|
|
227
|
+
process.stdout.cursorTo(0);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Calculate diffs
|
|
231
|
+
const diffsResult = await cleanup.calculateDiffs(projectPath, analysis, {
|
|
232
|
+
dryRun: !opts.apply,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Assess risk
|
|
236
|
+
const riskAssessment = cleanup.assessRisk(analysis, diffsResult);
|
|
237
|
+
|
|
238
|
+
// JSON output
|
|
239
|
+
if (json) {
|
|
240
|
+
const output = cleanup.formatJsonOutput(analysis, diffsResult, riskAssessment, opts);
|
|
241
|
+
console.log(JSON.stringify(output, null, 2));
|
|
242
|
+
return analysis.byRisk.aggressive.length > 0 && !opts.aggressive
|
|
243
|
+
? EXIT.BLOCKING
|
|
244
|
+
: EXIT.SUCCESS;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Human-readable output
|
|
248
|
+
if (!quiet) {
|
|
249
|
+
cleanup.printAnalysisSummary(analysis, projectPath);
|
|
250
|
+
cleanup.printRiskAssessment(riskAssessment);
|
|
251
|
+
cleanup.printFindingsByCategory(analysis, { verbose: opts.verbose });
|
|
252
|
+
cleanup.printDiffPreview(diffsResult, { verbose: opts.verbose });
|
|
253
|
+
|
|
254
|
+
// Warn about aggressive findings if not in aggressive mode
|
|
255
|
+
if (!opts.aggressive) {
|
|
256
|
+
cleanup.printAggressiveWarning(analysis.byRisk.aggressive);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Apply changes if requested
|
|
261
|
+
if (opts.apply && diffsResult.filesChanged > 0) {
|
|
262
|
+
// Create backup directory
|
|
263
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
264
|
+
const backupDir = path.join(projectPath, ".vibecheck", "cleanup-backups", timestamp);
|
|
265
|
+
|
|
266
|
+
if (!quiet) {
|
|
267
|
+
console.log(`${c.bold}${icons.shield} Creating backup...${c.reset}`);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const applyResult = await cleanup.applyTransformations(projectPath, diffsResult.diffs, backupDir);
|
|
271
|
+
|
|
272
|
+
if (!quiet) {
|
|
273
|
+
cleanup.printApplyResults(applyResult);
|
|
274
|
+
cleanup.printRollbackInfo(backupDir);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Next steps
|
|
279
|
+
if (!quiet) {
|
|
280
|
+
cleanup.printNextSteps(analysis, diffsResult, {
|
|
281
|
+
applied: opts.apply,
|
|
282
|
+
aggressive: opts.aggressive,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Exit code based on findings
|
|
287
|
+
if (analysis.byRisk.aggressive.length > 0 && !opts.aggressive) {
|
|
288
|
+
return EXIT.BLOCKING; // Has aggressive findings that weren't addressed
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return EXIT.SUCCESS;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
295
|
+
// ROLLBACK HANDLER
|
|
296
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
297
|
+
|
|
298
|
+
async function handleRollback(backupPath, json, quiet) {
|
|
299
|
+
const { colors: c, icons } = cleanup;
|
|
300
|
+
|
|
301
|
+
if (!fs.existsSync(backupPath)) {
|
|
302
|
+
if (json) {
|
|
303
|
+
console.log(JSON.stringify({ success: false, error: `Backup not found: ${backupPath}` }));
|
|
304
|
+
} else {
|
|
305
|
+
console.error(`${c.red}${icons.cross}${c.reset} Backup not found: ${backupPath}`);
|
|
306
|
+
}
|
|
307
|
+
return EXIT.NOT_FOUND;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const result = await cleanup.rollbackTransformations(backupPath);
|
|
311
|
+
|
|
312
|
+
if (json) {
|
|
313
|
+
console.log(JSON.stringify(result, null, 2));
|
|
314
|
+
return result.success ? EXIT.SUCCESS : EXIT.INTERNAL_ERROR;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (result.success) {
|
|
318
|
+
console.log(`
|
|
319
|
+
${c.green}${c.bold}${icons.check} ROLLBACK COMPLETE${c.reset}
|
|
320
|
+
|
|
321
|
+
Restored ${result.restored.length} file(s) to original state.
|
|
322
|
+
|
|
323
|
+
${c.dim}Tip: Run your tests to verify everything works.${c.reset}
|
|
324
|
+
`);
|
|
325
|
+
return EXIT.SUCCESS;
|
|
326
|
+
} else {
|
|
327
|
+
console.error(`
|
|
328
|
+
${c.red}${c.bold}${icons.cross} ROLLBACK FAILED${c.reset}
|
|
329
|
+
|
|
330
|
+
${result.error || "Unknown error"}
|
|
331
|
+
|
|
332
|
+
Failed files:
|
|
333
|
+
${result.failed.map(f => ` ${c.red}•${c.reset} ${f.file}: ${f.error}`).join("\n")}
|
|
334
|
+
`);
|
|
335
|
+
return EXIT.INTERNAL_ERROR;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
340
|
+
// EXPORTS
|
|
341
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
342
|
+
|
|
343
|
+
module.exports = { runCleanup };
|