@vibecheckai/cli 3.6.1 → 3.8.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 +622 -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/policy/rules/fake-success.js +31 -38
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +68 -3
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +4 -2
- package/bin/runners/lib/agent-firewall/risk/thresholds.js +5 -4
- 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/engines/attack-detector.js +1192 -0
- package/bin/runners/lib/entitlements-v2.js +2 -2
- package/bin/runners/lib/error-messages.js +1 -1
- 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/report-output.js +6 -6
- 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/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/tool-handler.ts +3 -3
- package/mcp-server/index.js +16 -0
- package/mcp-server/intent-firewall-interceptor.js +529 -0
- 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/tier-auth.js +164 -16
- package/mcp-server/tools-v3.js +70 -16
- package/package.json +1 -1
- package/bin/runners/runProof.zip +0 -0
package/bin/runners/runFix.js
CHANGED
|
@@ -23,7 +23,7 @@ const path = require('path');
|
|
|
23
23
|
const fs = require('fs');
|
|
24
24
|
const { execSync } = require('child_process');
|
|
25
25
|
const { shipCore } = require('./runShip');
|
|
26
|
-
const { planMissions } = require('./lib/missions/plan');
|
|
26
|
+
const { planMissions, getMissionStats } = require('./lib/missions/plan');
|
|
27
27
|
const { templateForMissionType } = require('./lib/missions/templates');
|
|
28
28
|
const { expandEvidence } = require('./lib/missions/evidence');
|
|
29
29
|
const { buildRealityFirewall } = require('./lib/firewall-prompt');
|
|
@@ -42,6 +42,45 @@ const upsell = require('./lib/upsell');
|
|
|
42
42
|
// Mission Control output formatter
|
|
43
43
|
const { formatFixOutput } = require('./lib/fix-output');
|
|
44
44
|
|
|
45
|
+
// Fix Missions V2 - New components
|
|
46
|
+
const { updateMissionStatus, MISSION_STATUS, isSafeToAutoApply } = require('./lib/missions/schema');
|
|
47
|
+
const {
|
|
48
|
+
createCheckpoint,
|
|
49
|
+
rollbackToCheckpoint,
|
|
50
|
+
rollbackMission,
|
|
51
|
+
markCheckpointApplied,
|
|
52
|
+
markCheckpointFailed,
|
|
53
|
+
listCheckpoints,
|
|
54
|
+
getMissionHistory,
|
|
55
|
+
cleanupOldCheckpoints,
|
|
56
|
+
} = require('./lib/missions/checkpoint');
|
|
57
|
+
const {
|
|
58
|
+
runPreFlightGates,
|
|
59
|
+
runPostFlightGates,
|
|
60
|
+
shouldAutoApply,
|
|
61
|
+
DEFAULT_THRESHOLDS,
|
|
62
|
+
} = require('./lib/missions/safety-gates');
|
|
63
|
+
const {
|
|
64
|
+
formatAllBriefings,
|
|
65
|
+
formatMissionSummary,
|
|
66
|
+
formatMissionResult,
|
|
67
|
+
formatFinalSummary,
|
|
68
|
+
formatMissionBriefing,
|
|
69
|
+
colors: briefingColors,
|
|
70
|
+
ICONS: briefingIcons,
|
|
71
|
+
} = require('./lib/missions/briefing');
|
|
72
|
+
const {
|
|
73
|
+
initAuditTrail,
|
|
74
|
+
getAuditTrail,
|
|
75
|
+
circuitBreakerAllows,
|
|
76
|
+
circuitBreakerSuccess,
|
|
77
|
+
circuitBreakerFailure,
|
|
78
|
+
circuitBreakerReset,
|
|
79
|
+
circuitBreakerStatus,
|
|
80
|
+
safeExecute,
|
|
81
|
+
ExecutionError,
|
|
82
|
+
} = require('./lib/missions/hardening');
|
|
83
|
+
|
|
45
84
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
46
85
|
// ADVANCED TERMINAL - ANSI CODES & UTILITIES
|
|
47
86
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -511,11 +550,103 @@ async function runFix(args) {
|
|
|
511
550
|
const root = path.resolve(opts.path || process.cwd());
|
|
512
551
|
const projectName = path.basename(root);
|
|
513
552
|
|
|
553
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
554
|
+
// FIX MISSIONS V2 - Initialize hardening components
|
|
555
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
556
|
+
|
|
557
|
+
// Initialize audit trail
|
|
558
|
+
const auditDir = path.join(root, '.vibecheck', 'logs');
|
|
559
|
+
initAuditTrail(auditDir);
|
|
560
|
+
const audit = getAuditTrail();
|
|
561
|
+
|
|
562
|
+
// Generate session ID for tracking
|
|
563
|
+
const sessionId = `fix_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
564
|
+
process.env.VIBECHECK_SESSION_ID = sessionId;
|
|
565
|
+
|
|
566
|
+
audit.info('fix_session_start', {
|
|
567
|
+
sessionId,
|
|
568
|
+
projectName,
|
|
569
|
+
root,
|
|
570
|
+
args: args.filter(a => !a.includes('key') && !a.includes('token')), // Filter sensitive args
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
// Check circuit breaker
|
|
574
|
+
if (!circuitBreakerAllows()) {
|
|
575
|
+
const status = circuitBreakerStatus();
|
|
576
|
+
console.log(` ${colors.blockRed}${ICONS.stop}${c.reset} Circuit breaker is open - too many recent failures`);
|
|
577
|
+
console.log(` ${c.dim}Failures: ${status.failures}, Last failure: ${new Date(status.lastFailure).toISOString()}${c.reset}`);
|
|
578
|
+
console.log(` ${c.dim}Wait ${Math.ceil((status.resetTimeout - (Date.now() - status.lastFailure)) / 1000)}s or use --force to override${c.reset}`);
|
|
579
|
+
|
|
580
|
+
if (!opts.force) {
|
|
581
|
+
audit.warn('circuit_breaker_blocked', { status });
|
|
582
|
+
return EXIT.BLOCKING;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
audit.warn('circuit_breaker_override', { status });
|
|
586
|
+
circuitBreakerReset();
|
|
587
|
+
}
|
|
588
|
+
|
|
514
589
|
// Print banner
|
|
515
590
|
printBanner();
|
|
516
591
|
console.log(` ${c.dim}Project:${c.reset} ${c.bold}${projectName}${c.reset}`);
|
|
517
592
|
console.log(` ${c.dim}Path:${c.reset} ${root}`);
|
|
593
|
+
console.log(` ${c.dim}Session:${c.reset} ${c.dim}${sessionId}${c.reset}`);
|
|
518
594
|
console.log();
|
|
595
|
+
|
|
596
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
597
|
+
// FIX MISSIONS V2 - Handle special modes first
|
|
598
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
599
|
+
|
|
600
|
+
// Handle --list-checkpoints
|
|
601
|
+
if (opts.listCheckpoints) {
|
|
602
|
+
const checkpoints = listCheckpoints(root);
|
|
603
|
+
if (checkpoints.length === 0) {
|
|
604
|
+
console.log(` ${c.dim}No checkpoints found${c.reset}`);
|
|
605
|
+
} else {
|
|
606
|
+
console.log(` ${colors.accent}${ICONS.mission}${c.reset} ${c.bold}CHECKPOINTS${c.reset} ${c.dim}(${checkpoints.length})${c.reset}`);
|
|
607
|
+
console.log();
|
|
608
|
+
for (const cp of checkpoints.slice(0, 10)) {
|
|
609
|
+
const age = Math.round((Date.now() - new Date(cp.createdAt).getTime()) / 1000 / 60);
|
|
610
|
+
console.log(` ${ICONS.check} ${cp.id}`);
|
|
611
|
+
console.log(` ${c.dim}Mission: ${cp.missionType} • ${cp.files} files • ${age}m ago${c.reset}`);
|
|
612
|
+
}
|
|
613
|
+
if (checkpoints.length > 10) {
|
|
614
|
+
console.log(` ${c.dim}... and ${checkpoints.length - 10} more${c.reset}`);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
console.log();
|
|
618
|
+
return 0;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// Handle --cleanup-checkpoints
|
|
622
|
+
if (opts.cleanupCheckpoints) {
|
|
623
|
+
startSpinner('Cleaning up old checkpoints...', 'dots');
|
|
624
|
+
const result = cleanupOldCheckpoints(root);
|
|
625
|
+
stopSpinner(`Cleaned up ${result.count} checkpoints`, true);
|
|
626
|
+
return 0;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// Handle --rollback
|
|
630
|
+
if (opts.rollback) {
|
|
631
|
+
const missionId = opts.rollback;
|
|
632
|
+
console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Rolling back mission: ${c.bold}${missionId}${c.reset}`);
|
|
633
|
+
|
|
634
|
+
const result = rollbackMission(root, missionId);
|
|
635
|
+
|
|
636
|
+
if (result.ok) {
|
|
637
|
+
console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} Rollback successful`);
|
|
638
|
+
if (result.restored.length > 0) {
|
|
639
|
+
console.log(` ${c.dim}Restored: ${result.restored.length} files${c.reset}`);
|
|
640
|
+
}
|
|
641
|
+
if (result.deleted.length > 0) {
|
|
642
|
+
console.log(` ${c.dim}Deleted: ${result.deleted.length} files${c.reset}`);
|
|
643
|
+
}
|
|
644
|
+
return 0;
|
|
645
|
+
} else {
|
|
646
|
+
console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} Rollback failed: ${result.error}`);
|
|
647
|
+
return EXIT.INTERNAL_ERROR;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
519
650
|
|
|
520
651
|
// TIER ENFORCEMENT: Check if --apply is allowed
|
|
521
652
|
if (opts.apply || opts.autopilot) {
|
|
@@ -558,14 +689,65 @@ async function runFix(args) {
|
|
|
558
689
|
return 0;
|
|
559
690
|
}
|
|
560
691
|
|
|
561
|
-
// Plan missions
|
|
692
|
+
// Plan missions with enhanced options
|
|
562
693
|
startSpinner('Planning fix missions...', 'gears');
|
|
563
|
-
const missions = planMissions(first.report.findings, {
|
|
564
|
-
|
|
565
|
-
|
|
694
|
+
const missions = planMissions(first.report.findings, {
|
|
695
|
+
maxMissions: opts.maxMissions || 8,
|
|
696
|
+
truthpack: first.truthpack,
|
|
697
|
+
maxBlastRadius: opts.maxBlast,
|
|
698
|
+
minConfidence: opts.minConfidence,
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
// Filter to specific mission if requested
|
|
702
|
+
let targetMissions = missions;
|
|
703
|
+
if (opts.mission) {
|
|
704
|
+
targetMissions = missions.filter(m => m.id === opts.mission || m.id.includes(opts.mission));
|
|
705
|
+
if (targetMissions.length === 0) {
|
|
706
|
+
stopSpinner('Mission not found', false);
|
|
707
|
+
console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} No mission found with ID: ${opts.mission}`);
|
|
708
|
+
console.log(` ${c.dim}Available missions:${c.reset}`);
|
|
709
|
+
for (const m of missions.slice(0, 5)) {
|
|
710
|
+
console.log(` ${c.dim}${m.id} - ${m.type}${c.reset}`);
|
|
711
|
+
}
|
|
712
|
+
return EXIT.BLOCKING;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
fs.writeFileSync(path.join(outDir, "missions.json"), JSON.stringify({ missions: targetMissions, fromVerdict: first.verdict }, null, 2));
|
|
717
|
+
stopSpinner(`Planned ${targetMissions.length} missions`, true);
|
|
718
|
+
|
|
719
|
+
// Get mission stats
|
|
720
|
+
const stats = getMissionStats(targetMissions);
|
|
721
|
+
|
|
722
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
723
|
+
// FIX MISSIONS V2 - Plan-only mode with full briefings
|
|
724
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
725
|
+
|
|
726
|
+
if (opts.planOnly) {
|
|
727
|
+
// Show full mission briefings
|
|
728
|
+
const gateOptions = {
|
|
729
|
+
minConfidence: opts.minConfidence,
|
|
730
|
+
maxBlastRadius: opts.maxBlast,
|
|
731
|
+
force: opts.force,
|
|
732
|
+
allowDirty: opts.allowDirty,
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
console.log(formatAllBriefings(root, targetMissions, gateOptions));
|
|
736
|
+
|
|
737
|
+
// Save briefings to file
|
|
738
|
+
fs.writeFileSync(
|
|
739
|
+
path.join(outDir, "briefings.txt"),
|
|
740
|
+
formatAllBriefings(root, targetMissions, gateOptions).replace(/\x1b\[[0-9;]*m/g, ''),
|
|
741
|
+
"utf8"
|
|
742
|
+
);
|
|
743
|
+
console.log(` ${c.dim}${ICONS.folder} Briefings saved: ${colors.accent}${path.relative(root, path.join(outDir, "briefings.txt"))}${c.reset}`);
|
|
744
|
+
console.log();
|
|
745
|
+
|
|
746
|
+
return 0;
|
|
747
|
+
}
|
|
566
748
|
|
|
567
749
|
// Show mission summary
|
|
568
|
-
printMissionSummary(
|
|
750
|
+
printMissionSummary(targetMissions);
|
|
569
751
|
console.log();
|
|
570
752
|
console.log(` ${c.dim}${ICONS.folder} Mission pack: ${colors.accent}${path.relative(root, outDir)}${c.reset}`);
|
|
571
753
|
console.log();
|
|
@@ -575,8 +757,11 @@ async function runFix(args) {
|
|
|
575
757
|
console.log();
|
|
576
758
|
console.log(` ${c.bold}Choose a mode:${c.reset}`);
|
|
577
759
|
console.log();
|
|
760
|
+
console.log(` ${colors.accent}${ICONS.prompt}${c.reset} ${c.bold}vibecheck fix --plan-only${c.reset}`);
|
|
761
|
+
console.log(` ${c.dim}Full mission briefings with safety gates ${c.green}(FREE)${c.reset}${c.dim}${c.reset}`);
|
|
762
|
+
console.log();
|
|
578
763
|
console.log(` ${colors.accent}${ICONS.prompt}${c.reset} ${c.bold}vibecheck fix --prompt-only${c.reset}`);
|
|
579
|
-
console.log(` ${c.dim}Generate
|
|
764
|
+
console.log(` ${c.dim}Generate LLM prompts, no edits ${c.green}(FREE)${c.reset}${c.dim}${c.reset}`);
|
|
580
765
|
console.log();
|
|
581
766
|
|
|
582
767
|
// Check if apply features are available
|
|
@@ -615,6 +800,15 @@ async function runFix(args) {
|
|
|
615
800
|
printLoopHeader(maxSteps, stagnationLimit);
|
|
616
801
|
}
|
|
617
802
|
|
|
803
|
+
// Track execution summary for V2
|
|
804
|
+
const executionSummary = {
|
|
805
|
+
total: targetMissions.length,
|
|
806
|
+
completed: 0,
|
|
807
|
+
failed: 0,
|
|
808
|
+
rolledBack: 0,
|
|
809
|
+
skipped: 0,
|
|
810
|
+
};
|
|
811
|
+
|
|
618
812
|
for (let step = 1; step <= maxSteps; step++) {
|
|
619
813
|
const before = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
|
|
620
814
|
|
|
@@ -635,12 +829,12 @@ async function runFix(args) {
|
|
|
635
829
|
// Mission Control output
|
|
636
830
|
if (!opts.json && !opts.quiet) {
|
|
637
831
|
console.log(formatFixOutput({
|
|
638
|
-
missions,
|
|
832
|
+
missions: targetMissions,
|
|
639
833
|
verdict: before.verdict,
|
|
640
834
|
beforeVerdict: first.verdict,
|
|
641
835
|
afterVerdict: before.verdict,
|
|
642
836
|
appliedMissions: step - 1,
|
|
643
|
-
totalMissions:
|
|
837
|
+
totalMissions: targetMissions.length,
|
|
644
838
|
duration,
|
|
645
839
|
success: true,
|
|
646
840
|
}, { apply: opts.apply, promptOnly: opts.promptOnly, loop: opts.loop || opts.autopilot }));
|
|
@@ -650,7 +844,7 @@ async function runFix(args) {
|
|
|
650
844
|
}
|
|
651
845
|
|
|
652
846
|
const ids = new Set(before.report.findings.map(f => f.id));
|
|
653
|
-
const mission =
|
|
847
|
+
const mission = targetMissions.find(m => m.objective?.targetFindingIds?.some(id => ids.has(id)) || m.targetFindingIds?.some(id => ids.has(id)));
|
|
654
848
|
if (!mission) {
|
|
655
849
|
printSection('COMPLETE', ICONS.check);
|
|
656
850
|
console.log();
|
|
@@ -660,6 +854,28 @@ async function runFix(args) {
|
|
|
660
854
|
return 0;
|
|
661
855
|
}
|
|
662
856
|
|
|
857
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
858
|
+
// FIX MISSIONS V2 - Pre-flight safety gates
|
|
859
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
860
|
+
|
|
861
|
+
const gateOptions = {
|
|
862
|
+
minConfidence: opts.minConfidence,
|
|
863
|
+
maxBlastRadius: opts.maxBlast,
|
|
864
|
+
force: opts.force,
|
|
865
|
+
allowDirty: opts.allowDirty,
|
|
866
|
+
};
|
|
867
|
+
|
|
868
|
+
const preFlightResults = runPreFlightGates(root, mission, gateOptions);
|
|
869
|
+
|
|
870
|
+
if (!preFlightResults.ok && !opts.force) {
|
|
871
|
+
console.log(` ${colors.warnAmber}${ICONS.warning}${c.reset} Mission ${mission.id} skipped: pre-flight gates failed`);
|
|
872
|
+
for (const result of preFlightResults.results.filter(r => !r.pass)) {
|
|
873
|
+
console.log(` ${c.dim}${ICONS.cross} ${result.gate}: ${result.reason}${c.reset}`);
|
|
874
|
+
}
|
|
875
|
+
executionSummary.skipped++;
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
|
|
663
879
|
// Save before proof
|
|
664
880
|
fs.writeFileSync(
|
|
665
881
|
path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_before_ship.json`),
|
|
@@ -667,7 +883,8 @@ async function runFix(args) {
|
|
|
667
883
|
"utf8"
|
|
668
884
|
);
|
|
669
885
|
|
|
670
|
-
const
|
|
886
|
+
const targetFindingIds = mission.objective?.targetFindingIds || mission.targetFindingIds || [];
|
|
887
|
+
const targetFindings = before.report.findings.filter(f => targetFindingIds.includes(f.id));
|
|
671
888
|
|
|
672
889
|
// Show mission card
|
|
673
890
|
printMissionCard(mission, step, maxSteps, 'running');
|
|
@@ -753,28 +970,60 @@ async function runFix(args) {
|
|
|
753
970
|
return 0;
|
|
754
971
|
}
|
|
755
972
|
|
|
756
|
-
//
|
|
973
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
974
|
+
// FIX MISSIONS V2 - Apply patch with checkpoint-based rollback
|
|
975
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
976
|
+
|
|
977
|
+
// Determine files to touch
|
|
757
978
|
const touchedFiles = new Set();
|
|
758
979
|
for (const ed of patchJson.edits) {
|
|
759
980
|
for (const f of parseDiffTouchedFiles(ed.diff)) touchedFiles.add(f);
|
|
760
981
|
}
|
|
761
982
|
const touchedList = Array.from(touchedFiles);
|
|
762
983
|
|
|
763
|
-
|
|
764
|
-
|
|
984
|
+
// Create checkpoint before applying (V2)
|
|
985
|
+
let checkpoint;
|
|
986
|
+
try {
|
|
987
|
+
checkpoint = createCheckpoint(root, mission, touchedList);
|
|
988
|
+
mission.safety = mission.safety || {};
|
|
989
|
+
mission.safety.checkpointId = checkpoint.id;
|
|
990
|
+
console.log(` ${briefingColors.info}${briefingIcons.checkpoint}${c.reset} Checkpoint: ${c.dim}${checkpoint.id}${c.reset}`);
|
|
991
|
+
} catch (e) {
|
|
992
|
+
// Fall back to simple backup
|
|
993
|
+
const backupRoot = path.join(outDir, `backup_step_${String(step).padStart(2,"0")}`);
|
|
994
|
+
backupFiles(root, touchedList, backupRoot);
|
|
995
|
+
checkpoint = { id: null, backupRoot };
|
|
996
|
+
}
|
|
765
997
|
|
|
998
|
+
// Apply patches
|
|
999
|
+
let applyFailed = false;
|
|
766
1000
|
for (const ed of patchJson.edits) {
|
|
767
1001
|
const res = applyUnifiedDiff(root, ed.diff);
|
|
768
1002
|
if (!res.ok) {
|
|
769
1003
|
console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} Patch apply failed: ${res.error}`);
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
return EXIT.INTERNAL_ERROR;
|
|
1004
|
+
applyFailed = true;
|
|
1005
|
+
break;
|
|
773
1006
|
}
|
|
774
1007
|
console.log(` ${colors.patch}${ICONS.patch}${c.reset} Applied: ${c.dim}${ed.path}${c.reset}`);
|
|
775
1008
|
}
|
|
776
1009
|
|
|
777
|
-
//
|
|
1010
|
+
// Handle apply failure - rollback
|
|
1011
|
+
if (applyFailed) {
|
|
1012
|
+
if (checkpoint.id) {
|
|
1013
|
+
const rollbackResult = rollbackToCheckpoint(root, checkpoint.id);
|
|
1014
|
+
markCheckpointFailed(root, checkpoint.id, 'Patch apply failed');
|
|
1015
|
+
console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Rolled back via checkpoint`);
|
|
1016
|
+
} else if (checkpoint.backupRoot) {
|
|
1017
|
+
restoreBackup(root, checkpoint.backupRoot);
|
|
1018
|
+
console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Restored from backup`);
|
|
1019
|
+
}
|
|
1020
|
+
executionSummary.failed++;
|
|
1021
|
+
circuitBreakerFailure();
|
|
1022
|
+
audit.error('mission_apply_failed', { missionId: mission.id, step });
|
|
1023
|
+
return EXIT.INTERNAL_ERROR;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
// Verify fix
|
|
778
1027
|
startSpinner('Verifying fix...', 'dots');
|
|
779
1028
|
const after = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
|
|
780
1029
|
|
|
@@ -790,29 +1039,101 @@ async function runFix(args) {
|
|
|
790
1039
|
"utf8"
|
|
791
1040
|
);
|
|
792
1041
|
|
|
1042
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
1043
|
+
// FIX MISSIONS V2 - Post-flight safety gates
|
|
1044
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
1045
|
+
|
|
1046
|
+
const postFlightResults = runPostFlightGates(root, mission, before, after, {
|
|
1047
|
+
runTests: !opts.skipTests,
|
|
1048
|
+
testCommand: opts.testCommand,
|
|
1049
|
+
});
|
|
1050
|
+
|
|
793
1051
|
const beforeScore = score(before.report.findings);
|
|
794
1052
|
const afterScore = score(after.report.findings);
|
|
795
|
-
const targetStillThere =
|
|
796
|
-
const improved = (afterScore < beforeScore) || (!targetStillThere);
|
|
1053
|
+
const targetStillThere = targetFindingIds.some(id => after.report.findings.some(f => f.id === id));
|
|
1054
|
+
const improved = (afterScore < beforeScore) || (!targetStillThere) || postFlightResults.ok;
|
|
797
1055
|
|
|
798
|
-
if (!improved) {
|
|
799
|
-
console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} No measurable progress`);
|
|
800
|
-
|
|
801
|
-
|
|
1056
|
+
if (!improved || postFlightResults.shouldRollback) {
|
|
1057
|
+
console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} ${postFlightResults.shouldRollback ? 'Post-flight gates failed' : 'No measurable progress'}`);
|
|
1058
|
+
|
|
1059
|
+
// Show failed gates
|
|
1060
|
+
for (const result of postFlightResults.results.filter(r => !r.pass)) {
|
|
1061
|
+
console.log(` ${c.dim}${ICONS.cross} ${result.gate}: ${result.reason}${c.reset}`);
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
// Rollback
|
|
1065
|
+
if (checkpoint.id) {
|
|
1066
|
+
const rollbackResult = rollbackToCheckpoint(root, checkpoint.id);
|
|
1067
|
+
console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Rolled back via checkpoint`);
|
|
1068
|
+
} else if (checkpoint.backupRoot) {
|
|
1069
|
+
restoreBackup(root, checkpoint.backupRoot);
|
|
1070
|
+
console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Restored from backup`);
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
executionSummary.rolledBack++;
|
|
1074
|
+
circuitBreakerFailure();
|
|
1075
|
+
audit.warn('mission_rolled_back', {
|
|
1076
|
+
missionId: mission.id,
|
|
1077
|
+
step,
|
|
1078
|
+
reason: postFlightResults.shouldRollback ? 'post_flight_failed' : 'no_progress',
|
|
1079
|
+
failedGates: postFlightResults.results.filter(r => !r.pass).map(r => r.gate),
|
|
1080
|
+
});
|
|
1081
|
+
|
|
802
1082
|
stagnant += 1;
|
|
1083
|
+
|
|
803
1084
|
if (!opts.autopilot || stagnant >= stagnationLimit) {
|
|
804
1085
|
printSection('STAGNATION', ICONS.stop);
|
|
805
1086
|
console.log();
|
|
806
1087
|
console.log(` ${colors.blockRed}${ICONS.stop}${c.reset} Stopping: stagnation limit reached (${stagnant}/${stagnationLimit})`);
|
|
807
1088
|
console.log();
|
|
1089
|
+
|
|
1090
|
+
// Show final summary
|
|
1091
|
+
executionSummary.verdict = after.verdict;
|
|
1092
|
+
executionSummary.duration = Date.now() - startTime;
|
|
1093
|
+
console.log(formatFinalSummary(executionSummary));
|
|
1094
|
+
|
|
1095
|
+
audit.error('fix_session_stagnation', {
|
|
1096
|
+
sessionId,
|
|
1097
|
+
stagnant,
|
|
1098
|
+
stagnationLimit,
|
|
1099
|
+
duration: Date.now() - startTime,
|
|
1100
|
+
});
|
|
1101
|
+
|
|
808
1102
|
return EXIT.BLOCKING;
|
|
809
1103
|
}
|
|
810
1104
|
continue;
|
|
811
1105
|
}
|
|
812
1106
|
|
|
1107
|
+
// Success - mark checkpoint as applied
|
|
1108
|
+
if (checkpoint.id) {
|
|
1109
|
+
markCheckpointApplied(root, checkpoint.id);
|
|
1110
|
+
}
|
|
1111
|
+
|
|
813
1112
|
console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} Progress confirmed`);
|
|
1113
|
+
console.log(formatMissionResult(mission, {
|
|
1114
|
+
success: true,
|
|
1115
|
+
findings: { before: beforeScore, after: afterScore }
|
|
1116
|
+
}));
|
|
1117
|
+
|
|
1118
|
+
executionSummary.completed++;
|
|
1119
|
+
circuitBreakerSuccess();
|
|
1120
|
+
audit.info('mission_completed', {
|
|
1121
|
+
missionId: mission.id,
|
|
1122
|
+
step,
|
|
1123
|
+
beforeScore,
|
|
1124
|
+
afterScore,
|
|
1125
|
+
improvement: beforeScore - afterScore,
|
|
1126
|
+
});
|
|
1127
|
+
|
|
814
1128
|
stagnant = 0;
|
|
815
|
-
if (!opts.autopilot)
|
|
1129
|
+
if (!opts.autopilot) {
|
|
1130
|
+
audit.info('fix_session_end', {
|
|
1131
|
+
sessionId,
|
|
1132
|
+
duration: Date.now() - startTime,
|
|
1133
|
+
result: 'success_single_mission',
|
|
1134
|
+
});
|
|
1135
|
+
return 0;
|
|
1136
|
+
}
|
|
816
1137
|
}
|
|
817
1138
|
|
|
818
1139
|
// Max steps reached
|
|
@@ -833,17 +1154,32 @@ async function runFix(args) {
|
|
|
833
1154
|
// Mission Control output
|
|
834
1155
|
if (!opts.json && !opts.quiet) {
|
|
835
1156
|
console.log(formatFixOutput({
|
|
836
|
-
missions,
|
|
1157
|
+
missions: targetMissions,
|
|
837
1158
|
verdict: lastShip.verdict,
|
|
838
1159
|
beforeVerdict: first.verdict,
|
|
839
1160
|
afterVerdict: lastShip.verdict,
|
|
840
1161
|
appliedMissions: maxSteps,
|
|
841
|
-
totalMissions:
|
|
1162
|
+
totalMissions: targetMissions.length,
|
|
842
1163
|
duration,
|
|
843
1164
|
success: false,
|
|
844
1165
|
}, { apply: opts.apply, promptOnly: opts.promptOnly, loop: opts.loop || opts.autopilot }));
|
|
1166
|
+
|
|
1167
|
+
// V2 Final summary
|
|
1168
|
+
executionSummary.verdict = lastShip.verdict;
|
|
1169
|
+
executionSummary.duration = duration;
|
|
1170
|
+
console.log(formatFinalSummary(executionSummary));
|
|
845
1171
|
}
|
|
846
1172
|
|
|
1173
|
+
// Flush audit trail
|
|
1174
|
+
audit.info('fix_session_end', {
|
|
1175
|
+
sessionId,
|
|
1176
|
+
duration,
|
|
1177
|
+
result: 'max_steps_reached',
|
|
1178
|
+
executionSummary,
|
|
1179
|
+
verdict: lastShip.verdict,
|
|
1180
|
+
});
|
|
1181
|
+
audit.flush();
|
|
1182
|
+
|
|
847
1183
|
return EXIT.WARNINGS; // Max steps reached, incomplete
|
|
848
1184
|
}
|
|
849
1185
|
|
|
@@ -865,12 +1201,23 @@ function parseArgs(args) {
|
|
|
865
1201
|
path: globalFlags.path || process.cwd(),
|
|
866
1202
|
apply: false,
|
|
867
1203
|
promptOnly: false,
|
|
1204
|
+
planOnly: false,
|
|
868
1205
|
loop: false,
|
|
869
1206
|
share: false,
|
|
870
1207
|
maxMissions: 8,
|
|
871
1208
|
maxSteps: 10,
|
|
872
1209
|
stagnationLimit: 2,
|
|
873
1210
|
fastifyEntry: null,
|
|
1211
|
+
// Fix Missions V2 - New options
|
|
1212
|
+
rollback: null, // Mission ID to rollback
|
|
1213
|
+
mission: null, // Specific mission ID to run
|
|
1214
|
+
force: false, // Override safety gates
|
|
1215
|
+
minConfidence: DEFAULT_THRESHOLDS.minConfidence,
|
|
1216
|
+
maxBlast: DEFAULT_THRESHOLDS.maxBlastRadius,
|
|
1217
|
+
allowDirty: false, // Allow uncommitted changes
|
|
1218
|
+
skipTests: true, // Skip post-flight tests
|
|
1219
|
+
listCheckpoints: false,
|
|
1220
|
+
cleanupCheckpoints: false,
|
|
874
1221
|
// Note: help comes from globalFlags, don't override it here
|
|
875
1222
|
};
|
|
876
1223
|
|
|
@@ -879,6 +1226,7 @@ function parseArgs(args) {
|
|
|
879
1226
|
const arg = cleanArgs[i];
|
|
880
1227
|
if (arg === '--apply') opts.apply = true;
|
|
881
1228
|
else if (arg === '--prompt-only') opts.promptOnly = true;
|
|
1229
|
+
else if (arg === '--plan-only') opts.planOnly = true;
|
|
882
1230
|
else if (arg === '--autopilot') opts.autopilot = true;
|
|
883
1231
|
else if (arg === '--share') opts.share = true;
|
|
884
1232
|
else if (arg === '--max-missions') opts.maxMissions = Number(cleanArgs[++i]) || 8;
|
|
@@ -887,6 +1235,16 @@ function parseArgs(args) {
|
|
|
887
1235
|
else if (arg === '--fastify-entry') opts.fastifyEntry = cleanArgs[++i];
|
|
888
1236
|
else if (arg === '--path' || arg === '-p') opts.path = cleanArgs[++i];
|
|
889
1237
|
else if (arg === '--help' || arg === '-h') opts.help = true;
|
|
1238
|
+
// Fix Missions V2 - New flags
|
|
1239
|
+
else if (arg === '--rollback') opts.rollback = cleanArgs[++i];
|
|
1240
|
+
else if (arg === '--mission') opts.mission = cleanArgs[++i];
|
|
1241
|
+
else if (arg === '--force') opts.force = true;
|
|
1242
|
+
else if (arg === '--min-confidence') opts.minConfidence = Number(cleanArgs[++i]) || DEFAULT_THRESHOLDS.minConfidence;
|
|
1243
|
+
else if (arg === '--max-blast') opts.maxBlast = Number(cleanArgs[++i]) || DEFAULT_THRESHOLDS.maxBlastRadius;
|
|
1244
|
+
else if (arg === '--allow-dirty') opts.allowDirty = true;
|
|
1245
|
+
else if (arg === '--run-tests') opts.skipTests = false;
|
|
1246
|
+
else if (arg === '--list-checkpoints') opts.listCheckpoints = true;
|
|
1247
|
+
else if (arg === '--cleanup-checkpoints') opts.cleanupCheckpoints = true;
|
|
890
1248
|
}
|
|
891
1249
|
|
|
892
1250
|
return opts;
|
|
@@ -899,22 +1257,43 @@ function printHelp(showBanner = true) {
|
|
|
899
1257
|
console.log(`
|
|
900
1258
|
${c.bold}Usage:${c.reset} vibecheck fix (f) [options]
|
|
901
1259
|
|
|
902
|
-
${c.bold}Mission Control${c.reset} —
|
|
1260
|
+
${c.bold}Mission Control V2${c.reset} — "Missions, not chaos" - Surgical fixes with safety gates.
|
|
903
1261
|
|
|
904
1262
|
${c.bold}Modes:${c.reset}
|
|
905
1263
|
${colors.accent}vibecheck fix${c.reset} ${c.dim}Plan missions (no changes) ${c.green}(FREE)${c.reset}${c.dim}${c.reset}
|
|
906
|
-
${colors.accent}vibecheck fix --
|
|
1264
|
+
${colors.accent}vibecheck fix --plan-only${c.reset} ${c.dim}Full mission briefings ${c.green}(FREE)${c.reset}${c.dim}${c.reset}
|
|
1265
|
+
${colors.accent}vibecheck fix --prompt-only${c.reset} ${c.dim}Generate LLM prompts ${c.green}(FREE)${c.reset}${c.dim}${c.reset}
|
|
907
1266
|
${colors.accent}vibecheck fix --apply${c.reset} ${c.dim}Apply patches from LLM ${c.yellow}(PRO)${c.reset}${c.dim}${c.reset}
|
|
908
|
-
${colors.accent}vibecheck fix --
|
|
1267
|
+
${colors.accent}vibecheck fix --autopilot --apply${c.reset} ${c.dim}Loop until SHIP or stuck ${c.yellow}(PRO)${c.reset}${c.dim}${c.reset}
|
|
909
1268
|
|
|
910
|
-
${c.bold}Options:${c.reset}
|
|
1269
|
+
${c.bold}Core Options:${c.reset}
|
|
1270
|
+
${colors.accent}--plan-only${c.reset} Show full mission briefings with safety gates
|
|
911
1271
|
${colors.accent}--prompt-only${c.reset} Generate mission prompts only ${c.dim}(no edits)${c.reset}
|
|
912
1272
|
${colors.accent}--apply${c.reset} Apply patches returned by the model ${c.dim}(PRO tier)${c.reset}
|
|
913
|
-
${colors.accent}--
|
|
1273
|
+
${colors.accent}--autopilot${c.reset} Loop: fix → verify → fix until SHIP ${c.dim}(PRO tier)${c.reset}
|
|
914
1274
|
${colors.accent}--share${c.reset} Generate share bundle after fix ${c.dim}(PRO tier)${c.reset}
|
|
1275
|
+
|
|
1276
|
+
${c.bold}Mission Selection:${c.reset}
|
|
1277
|
+
${colors.accent}--mission <id>${c.reset} Run specific mission only (e.g., M_abc123)
|
|
915
1278
|
${colors.accent}--max-missions <n>${c.reset} Max missions to plan ${c.dim}(default: 8)${c.reset}
|
|
1279
|
+
|
|
1280
|
+
${c.bold}Safety Gates (V2):${c.reset}
|
|
1281
|
+
${colors.accent}--force${c.reset} Override safety gates for critical missions
|
|
1282
|
+
${colors.accent}--min-confidence <n>${c.reset} Min confidence threshold ${c.dim}(default: 0.6)${c.reset}
|
|
1283
|
+
${colors.accent}--max-blast <n>${c.reset} Max files per mission ${c.dim}(default: 10)${c.reset}
|
|
1284
|
+
${colors.accent}--allow-dirty${c.reset} Allow uncommitted git changes
|
|
1285
|
+
${colors.accent}--run-tests${c.reset} Run tests in post-flight gates
|
|
1286
|
+
|
|
1287
|
+
${c.bold}Rollback & Checkpoints (V2):${c.reset}
|
|
1288
|
+
${colors.accent}--rollback <id>${c.reset} Rollback a mission by ID
|
|
1289
|
+
${colors.accent}--list-checkpoints${c.reset} List all checkpoints
|
|
1290
|
+
${colors.accent}--cleanup-checkpoints${c.reset} Clean up old checkpoints
|
|
1291
|
+
|
|
1292
|
+
${c.bold}Autopilot Options:${c.reset}
|
|
916
1293
|
${colors.accent}--max-steps <n>${c.reset} Max autopilot steps ${c.dim}(default: 10)${c.reset}
|
|
917
1294
|
${colors.accent}--stagnation-limit${c.reset} Stop after N non-improving steps ${c.dim}(default: 2)${c.reset}
|
|
1295
|
+
|
|
1296
|
+
${c.bold}Other Options:${c.reset}
|
|
918
1297
|
${colors.accent}--fastify-entry${c.reset} Fastify entry file ${c.dim}(e.g. src/server.ts)${c.reset}
|
|
919
1298
|
${colors.accent}--path, -p${c.reset} Project path ${c.dim}(default: current directory)${c.reset}
|
|
920
1299
|
${colors.accent}--help, -h${c.reset} Show this help
|