@vibecheckai/cli 3.7.0 → 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/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/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/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 +68 -11
- package/mcp-server/tools-v3.js +70 -16
- package/package.json +1 -1
- package/bin/runners/runProof.zip +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Simple 2-tier model:
|
|
5
5
|
* - FREE ($0): Inspect & Observe
|
|
6
|
-
* - PRO ($
|
|
6
|
+
* - PRO ($49/mo): Fix, Prove & Enforce
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
"use strict";
|
|
@@ -199,7 +199,7 @@ ${c.bold}This feature requires Pro.${c.reset}
|
|
|
199
199
|
|
|
200
200
|
${c.yellow}${feature}${c.reset} is a Pro feature.
|
|
201
201
|
|
|
202
|
-
Upgrade to Pro ($
|
|
202
|
+
Upgrade to Pro ($49/mo) to unlock Fix, Prove & Enforce capabilities.
|
|
203
203
|
|
|
204
204
|
vibecheck upgrade
|
|
205
205
|
https://vibecheckai.dev/pricing
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
// bin/runners/lib/missions/briefing.js
|
|
2
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
3
|
+
// MISSION BRIEFING - Beautiful plan-only mode output
|
|
4
|
+
// Shows what would happen without executing, building trust and transparency
|
|
5
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
6
|
+
|
|
7
|
+
const { RISK_LEVEL, BLAST_RADIUS } = require('./schema');
|
|
8
|
+
const { runPreFlightGates, formatGateResults } = require('./safety-gates');
|
|
9
|
+
|
|
10
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
11
|
+
// TERMINAL STYLING
|
|
12
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
13
|
+
|
|
14
|
+
const c = {
|
|
15
|
+
reset: '\x1b[0m',
|
|
16
|
+
bold: '\x1b[1m',
|
|
17
|
+
dim: '\x1b[2m',
|
|
18
|
+
italic: '\x1b[3m',
|
|
19
|
+
underline: '\x1b[4m',
|
|
20
|
+
// Colors
|
|
21
|
+
red: '\x1b[31m',
|
|
22
|
+
green: '\x1b[32m',
|
|
23
|
+
yellow: '\x1b[33m',
|
|
24
|
+
blue: '\x1b[34m',
|
|
25
|
+
magenta: '\x1b[35m',
|
|
26
|
+
cyan: '\x1b[36m',
|
|
27
|
+
white: '\x1b[37m',
|
|
28
|
+
gray: '\x1b[90m',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// RGB helper
|
|
32
|
+
const rgb = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
|
|
33
|
+
|
|
34
|
+
// Premium color palette
|
|
35
|
+
const colors = {
|
|
36
|
+
accent: rgb(255, 150, 50),
|
|
37
|
+
muted: rgb(120, 120, 140),
|
|
38
|
+
success: rgb(0, 255, 150),
|
|
39
|
+
warning: rgb(255, 200, 0),
|
|
40
|
+
danger: rgb(255, 80, 80),
|
|
41
|
+
info: rgb(100, 200, 255),
|
|
42
|
+
|
|
43
|
+
// Risk colors
|
|
44
|
+
low: rgb(100, 200, 100),
|
|
45
|
+
medium: rgb(255, 200, 100),
|
|
46
|
+
high: rgb(255, 150, 100),
|
|
47
|
+
critical: rgb(255, 80, 80),
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const ICONS = {
|
|
51
|
+
mission: '🎯',
|
|
52
|
+
file: '📄',
|
|
53
|
+
check: '✓',
|
|
54
|
+
cross: '✗',
|
|
55
|
+
warning: '⚠',
|
|
56
|
+
info: 'ℹ',
|
|
57
|
+
arrow: '→',
|
|
58
|
+
bullet: '•',
|
|
59
|
+
shield: '🛡️',
|
|
60
|
+
checkpoint: '💾',
|
|
61
|
+
rollback: '↩️',
|
|
62
|
+
lock: '🔒',
|
|
63
|
+
unlock: '🔓',
|
|
64
|
+
rocket: '🚀',
|
|
65
|
+
brain: '🧠',
|
|
66
|
+
gear: '⚙️',
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const BOX = {
|
|
70
|
+
topLeft: '╭',
|
|
71
|
+
topRight: '╮',
|
|
72
|
+
bottomLeft: '╰',
|
|
73
|
+
bottomRight: '╯',
|
|
74
|
+
horizontal: '─',
|
|
75
|
+
vertical: '│',
|
|
76
|
+
teeRight: '├',
|
|
77
|
+
teeLeft: '┤',
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
81
|
+
// FORMATTING UTILITIES
|
|
82
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get color for risk level
|
|
86
|
+
*/
|
|
87
|
+
function getRiskColor(riskLevel) {
|
|
88
|
+
switch (riskLevel) {
|
|
89
|
+
case RISK_LEVEL.LOW: return colors.low;
|
|
90
|
+
case RISK_LEVEL.MEDIUM: return colors.medium;
|
|
91
|
+
case RISK_LEVEL.HIGH: return colors.high;
|
|
92
|
+
case RISK_LEVEL.CRITICAL: return colors.critical;
|
|
93
|
+
default: return colors.muted;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Get icon for mission type
|
|
99
|
+
*/
|
|
100
|
+
function getMissionIcon(type) {
|
|
101
|
+
const icons = {
|
|
102
|
+
'REMOVE_OWNER_MODE': '🔐',
|
|
103
|
+
'FIX_STRIPE_WEBHOOKS': '💰',
|
|
104
|
+
'ENFORCE_PAID_SURFACE': '🛡️',
|
|
105
|
+
'ADD_SERVER_AUTH': '🔒',
|
|
106
|
+
'FIX_MISSING_ROUTE': '🛤️',
|
|
107
|
+
'FIX_FAKE_SUCCESS': '👻',
|
|
108
|
+
'FIX_ENV_CONTRACT': '🌍',
|
|
109
|
+
'FIX_DEAD_UI': '💀',
|
|
110
|
+
'FIX_EMPTY_CATCH': '🐛',
|
|
111
|
+
'FIX_TEST_KEYS': '🔑',
|
|
112
|
+
'FIX_MOCK_DOMAINS': '🔗',
|
|
113
|
+
'FIX_PLACEHOLDER_DATA': '📝',
|
|
114
|
+
'FIX_HARDCODED_SECRETS': '🔐',
|
|
115
|
+
'FIX_SIMULATED_BILLING': '💳',
|
|
116
|
+
'FIX_SILENT_FALLBACK': '🔇',
|
|
117
|
+
'SYNC_CONTRACTS': '📊',
|
|
118
|
+
'FIX_ROUTE_DRIFT': '🛤️',
|
|
119
|
+
'FIX_AUTH_DRIFT': '🛡️',
|
|
120
|
+
};
|
|
121
|
+
return icons[type] || ICONS.mission;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Truncate string to max length
|
|
126
|
+
*/
|
|
127
|
+
function truncate(str, max) {
|
|
128
|
+
if (!str) return '';
|
|
129
|
+
if (str.length <= max) return str;
|
|
130
|
+
return str.slice(0, max - 3) + '...';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Create a horizontal line
|
|
135
|
+
*/
|
|
136
|
+
function line(width = 60, char = '─') {
|
|
137
|
+
return c.dim + char.repeat(width) + c.reset;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
141
|
+
// MISSION BRIEFING FORMATTERS
|
|
142
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Format a single mission briefing
|
|
146
|
+
* @param {object} mission - Mission object
|
|
147
|
+
* @param {object} gateResults - Pre-flight gate results
|
|
148
|
+
* @param {number} index - Mission index (1-based)
|
|
149
|
+
* @param {number} total - Total missions
|
|
150
|
+
* @returns {string} Formatted briefing
|
|
151
|
+
*/
|
|
152
|
+
function formatMissionBriefing(mission, gateResults, index, total) {
|
|
153
|
+
const lines = [];
|
|
154
|
+
const w = 60;
|
|
155
|
+
const icon = getMissionIcon(mission.type);
|
|
156
|
+
const riskColor = getRiskColor(mission.safety?.riskLevel);
|
|
157
|
+
|
|
158
|
+
// Header box
|
|
159
|
+
lines.push('');
|
|
160
|
+
lines.push(` ${c.dim}${BOX.topLeft}${BOX.horizontal.repeat(w)}${BOX.topRight}${c.reset}`);
|
|
161
|
+
|
|
162
|
+
// Mission type header
|
|
163
|
+
const header = `${icon} Mission ${index}/${total}: ${mission.type}`;
|
|
164
|
+
const headerPad = Math.max(0, w - header.length - 2);
|
|
165
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${colors.accent}${c.bold}${header}${c.reset}${' '.repeat(headerPad)} ${c.dim}${BOX.vertical}${c.reset}`);
|
|
166
|
+
|
|
167
|
+
// Separator
|
|
168
|
+
lines.push(` ${c.dim}${BOX.teeRight}${BOX.horizontal.repeat(w)}${BOX.teeLeft}${c.reset}`);
|
|
169
|
+
|
|
170
|
+
// Objective section
|
|
171
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${c.bold}Objective${c.reset}`);
|
|
172
|
+
const intent = truncate(mission.template?.intent || mission.objective?.intent || 'Fix issues', w - 4);
|
|
173
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${intent}`);
|
|
174
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset}`);
|
|
175
|
+
|
|
176
|
+
// Files section
|
|
177
|
+
const files = mission.scope?.allowedFiles || [];
|
|
178
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${c.bold}Files${c.reset} ${c.dim}(${files.length} total)${c.reset}`);
|
|
179
|
+
for (const file of files.slice(0, 4)) {
|
|
180
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${ICONS.file} ${truncate(file, w - 8)}`);
|
|
181
|
+
}
|
|
182
|
+
if (files.length > 4) {
|
|
183
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${c.dim}... and ${files.length - 4} more${c.reset}`);
|
|
184
|
+
}
|
|
185
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset}`);
|
|
186
|
+
|
|
187
|
+
// Risk section
|
|
188
|
+
const riskLevel = (mission.safety?.riskLevel || 'medium').toUpperCase();
|
|
189
|
+
const blastRadius = mission.scope?.blastRadius || 'medium';
|
|
190
|
+
const confidence = Math.round((mission.safety?.confidence || 0.5) * 100);
|
|
191
|
+
|
|
192
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${c.bold}Risk Assessment${c.reset}`);
|
|
193
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${riskColor}${ICONS.shield} Risk: ${riskLevel}${c.reset}`);
|
|
194
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${ICONS.bullet} Blast radius: ${blastRadius} (${files.length} files)`);
|
|
195
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${ICONS.bullet} Confidence: ${confidence}%`);
|
|
196
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${mission.safety?.reversible !== false ? colors.success + ICONS.check : colors.danger + ICONS.cross}${c.reset} Reversible: ${mission.safety?.reversible !== false ? 'Yes' : 'No'}`);
|
|
197
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset}`);
|
|
198
|
+
|
|
199
|
+
// Safety gates section
|
|
200
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${c.bold}Safety Gates${c.reset}`);
|
|
201
|
+
for (const result of gateResults.results) {
|
|
202
|
+
const gateIcon = result.pass
|
|
203
|
+
? (result.severity === 'warning' ? colors.warning + ICONS.warning : colors.success + ICONS.check)
|
|
204
|
+
: colors.danger + ICONS.cross;
|
|
205
|
+
const gateName = result.gate.replace(/_/g, ' ');
|
|
206
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${gateIcon}${c.reset} ${gateName}`);
|
|
207
|
+
}
|
|
208
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset}`);
|
|
209
|
+
|
|
210
|
+
// Success criteria section
|
|
211
|
+
const criteria = mission.template?.success || mission.objective?.successCriteria || [];
|
|
212
|
+
if (criteria.length > 0) {
|
|
213
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${c.bold}Success Criteria${c.reset}`);
|
|
214
|
+
for (const criterion of criteria.slice(0, 3)) {
|
|
215
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${ICONS.bullet} ${truncate(criterion, w - 8)}`);
|
|
216
|
+
}
|
|
217
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset}`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Actions section
|
|
221
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${c.bold}Actions (on --apply)${c.reset}`);
|
|
222
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${c.dim}1.${c.reset} Create checkpoint ${ICONS.checkpoint}`);
|
|
223
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${c.dim}2.${c.reset} Generate LLM prompt with Reality Firewall ${ICONS.brain}`);
|
|
224
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${c.dim}3.${c.reset} Validate and apply patch ${ICONS.gear}`);
|
|
225
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${c.dim}4.${c.reset} Run ship to verify ${ICONS.rocket}`);
|
|
226
|
+
lines.push(` ${c.dim}${BOX.vertical}${c.reset} ${c.dim}5.${c.reset} Auto-rollback if gates fail ${ICONS.rollback}`);
|
|
227
|
+
|
|
228
|
+
// Footer box
|
|
229
|
+
lines.push(` ${c.dim}${BOX.bottomLeft}${BOX.horizontal.repeat(w)}${BOX.bottomRight}${c.reset}`);
|
|
230
|
+
|
|
231
|
+
// Execute hint
|
|
232
|
+
if (gateResults.ok) {
|
|
233
|
+
lines.push(` ${colors.success}${ICONS.check}${c.reset} Ready to execute: ${colors.accent}vibecheck fix --apply --mission ${mission.id}${c.reset}`);
|
|
234
|
+
} else {
|
|
235
|
+
lines.push(` ${colors.danger}${ICONS.cross}${c.reset} Cannot execute: ${gateResults.summary}`);
|
|
236
|
+
// Show remedies
|
|
237
|
+
for (const result of gateResults.results.filter(r => !r.pass && r.remedy)) {
|
|
238
|
+
lines.push(` ${c.dim}${ICONS.arrow} ${result.remedy}${c.reset}`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return lines.join('\n');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Format all mission briefings
|
|
247
|
+
* @param {string} repoRoot - Repository root
|
|
248
|
+
* @param {object[]} missions - Array of missions
|
|
249
|
+
* @param {object} options - Formatting options
|
|
250
|
+
* @returns {string} Formatted output
|
|
251
|
+
*/
|
|
252
|
+
function formatAllBriefings(repoRoot, missions, options = {}) {
|
|
253
|
+
const lines = [];
|
|
254
|
+
|
|
255
|
+
// Header
|
|
256
|
+
lines.push('');
|
|
257
|
+
lines.push(` ${colors.accent}${c.bold}MISSION BRIEFINGS${c.reset}`);
|
|
258
|
+
lines.push(` ${c.dim}Plan-only mode: No changes will be made${c.reset}`);
|
|
259
|
+
lines.push(' ' + line(60));
|
|
260
|
+
|
|
261
|
+
// Summary stats
|
|
262
|
+
const stats = {
|
|
263
|
+
total: missions.length,
|
|
264
|
+
findings: missions.reduce((sum, m) => sum + (m.objective?.findingCount || 1), 0),
|
|
265
|
+
files: new Set(missions.flatMap(m => m.scope?.allowedFiles || [])).size,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
lines.push('');
|
|
269
|
+
lines.push(` ${ICONS.mission} ${c.bold}${stats.total}${c.reset} missions targeting ${c.bold}${stats.findings}${c.reset} findings in ${c.bold}${stats.files}${c.reset} files`);
|
|
270
|
+
lines.push('');
|
|
271
|
+
|
|
272
|
+
// Individual briefings
|
|
273
|
+
let readyCount = 0;
|
|
274
|
+
let blockedCount = 0;
|
|
275
|
+
|
|
276
|
+
for (let i = 0; i < missions.length; i++) {
|
|
277
|
+
const mission = missions[i];
|
|
278
|
+
const gateResults = runPreFlightGates(repoRoot, mission, options);
|
|
279
|
+
|
|
280
|
+
if (gateResults.ok) readyCount++;
|
|
281
|
+
else blockedCount++;
|
|
282
|
+
|
|
283
|
+
lines.push(formatMissionBriefing(mission, gateResults, i + 1, missions.length));
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Summary footer
|
|
287
|
+
lines.push('');
|
|
288
|
+
lines.push(' ' + line(60, '═'));
|
|
289
|
+
lines.push(` ${c.bold}SUMMARY${c.reset}`);
|
|
290
|
+
lines.push(` ${colors.success}${ICONS.check}${c.reset} Ready: ${readyCount}/${missions.length} missions`);
|
|
291
|
+
if (blockedCount > 0) {
|
|
292
|
+
lines.push(` ${colors.danger}${ICONS.cross}${c.reset} Blocked: ${blockedCount}/${missions.length} missions`);
|
|
293
|
+
}
|
|
294
|
+
lines.push('');
|
|
295
|
+
|
|
296
|
+
// Next steps
|
|
297
|
+
lines.push(` ${c.bold}Next Steps:${c.reset}`);
|
|
298
|
+
if (readyCount > 0) {
|
|
299
|
+
lines.push(` ${colors.accent}vibecheck fix --apply${c.reset} ${c.dim}Execute all ready missions${c.reset}`);
|
|
300
|
+
lines.push(` ${colors.accent}vibecheck fix --apply --mission M_xxx${c.reset} ${c.dim}Execute specific mission${c.reset}`);
|
|
301
|
+
}
|
|
302
|
+
if (blockedCount > 0) {
|
|
303
|
+
lines.push(` ${colors.accent}vibecheck fix --apply --force${c.reset} ${c.dim}Override safety gates${c.reset}`);
|
|
304
|
+
}
|
|
305
|
+
lines.push('');
|
|
306
|
+
|
|
307
|
+
return lines.join('\n');
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Format a compact mission summary (for non-plan-only mode)
|
|
312
|
+
* @param {object[]} missions - Array of missions
|
|
313
|
+
* @returns {string} Formatted summary
|
|
314
|
+
*/
|
|
315
|
+
function formatMissionSummary(missions) {
|
|
316
|
+
const lines = [];
|
|
317
|
+
|
|
318
|
+
lines.push('');
|
|
319
|
+
lines.push(` ${colors.accent}${ICONS.mission}${c.reset} ${c.bold}MISSION PLAN${c.reset} ${c.dim}(${missions.length} missions)${c.reset}`);
|
|
320
|
+
lines.push('');
|
|
321
|
+
|
|
322
|
+
for (let i = 0; i < missions.length; i++) {
|
|
323
|
+
const m = missions[i];
|
|
324
|
+
const icon = getMissionIcon(m.type);
|
|
325
|
+
const riskColor = getRiskColor(m.safety?.riskLevel);
|
|
326
|
+
const fileCount = m.scope?.allowedFiles?.length || 0;
|
|
327
|
+
const findingCount = m.objective?.findingCount || 1;
|
|
328
|
+
|
|
329
|
+
lines.push(` ${icon} ${c.bold}${i + 1}.${c.reset} ${m.type.padEnd(24)} ${c.dim}${findingCount} finding(s)${c.reset} ${riskColor}${m.safety?.riskLevel?.toUpperCase() || 'MEDIUM'}${c.reset}`);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
lines.push('');
|
|
333
|
+
|
|
334
|
+
return lines.join('\n');
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Format mission execution result
|
|
339
|
+
* @param {object} mission - Mission object
|
|
340
|
+
* @param {object} result - Execution result
|
|
341
|
+
* @returns {string} Formatted result
|
|
342
|
+
*/
|
|
343
|
+
function formatMissionResult(mission, result) {
|
|
344
|
+
const lines = [];
|
|
345
|
+
const icon = getMissionIcon(mission.type);
|
|
346
|
+
|
|
347
|
+
if (result.success) {
|
|
348
|
+
lines.push(` ${colors.success}${ICONS.check}${c.reset} ${icon} ${mission.type} ${c.bold}completed${c.reset}`);
|
|
349
|
+
if (result.findings) {
|
|
350
|
+
lines.push(` ${c.dim}${ICONS.arrow} ${result.findings.before} → ${result.findings.after} findings${c.reset}`);
|
|
351
|
+
}
|
|
352
|
+
} else if (result.rolledBack) {
|
|
353
|
+
lines.push(` ${colors.warning}${ICONS.rollback}${c.reset} ${icon} ${mission.type} ${c.bold}rolled back${c.reset}`);
|
|
354
|
+
lines.push(` ${c.dim}${ICONS.arrow} ${result.reason || 'Post-flight gates failed'}${c.reset}`);
|
|
355
|
+
} else {
|
|
356
|
+
lines.push(` ${colors.danger}${ICONS.cross}${c.reset} ${icon} ${mission.type} ${c.bold}failed${c.reset}`);
|
|
357
|
+
lines.push(` ${c.dim}${ICONS.arrow} ${result.reason || 'Unknown error'}${c.reset}`);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return lines.join('\n');
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Format final summary after all missions
|
|
365
|
+
* @param {object} summary - Execution summary
|
|
366
|
+
* @returns {string} Formatted summary
|
|
367
|
+
*/
|
|
368
|
+
function formatFinalSummary(summary) {
|
|
369
|
+
const lines = [];
|
|
370
|
+
|
|
371
|
+
lines.push('');
|
|
372
|
+
lines.push(' ' + line(60, '═'));
|
|
373
|
+
lines.push(` ${c.bold}MISSION CONTROL SUMMARY${c.reset}`);
|
|
374
|
+
lines.push('');
|
|
375
|
+
|
|
376
|
+
// Stats
|
|
377
|
+
lines.push(` ${colors.success}${ICONS.check}${c.reset} Completed: ${summary.completed}/${summary.total}`);
|
|
378
|
+
if (summary.rolledBack > 0) {
|
|
379
|
+
lines.push(` ${colors.warning}${ICONS.rollback}${c.reset} Rolled back: ${summary.rolledBack}`);
|
|
380
|
+
}
|
|
381
|
+
if (summary.failed > 0) {
|
|
382
|
+
lines.push(` ${colors.danger}${ICONS.cross}${c.reset} Failed: ${summary.failed}`);
|
|
383
|
+
}
|
|
384
|
+
if (summary.skipped > 0) {
|
|
385
|
+
lines.push(` ${c.dim}${ICONS.bullet}${c.reset} Skipped: ${summary.skipped}`);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Duration
|
|
389
|
+
if (summary.duration) {
|
|
390
|
+
const seconds = Math.round(summary.duration / 1000);
|
|
391
|
+
lines.push(` ${ICONS.bullet} Duration: ${seconds}s`);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Verdict
|
|
395
|
+
lines.push('');
|
|
396
|
+
if (summary.verdict === 'SHIP') {
|
|
397
|
+
lines.push(` ${colors.success}${ICONS.rocket} SHIP${c.reset} ${c.dim}All issues resolved!${c.reset}`);
|
|
398
|
+
} else if (summary.verdict === 'WARN') {
|
|
399
|
+
lines.push(` ${colors.warning}${ICONS.warning} WARN${c.reset} ${c.dim}Some warnings remain${c.reset}`);
|
|
400
|
+
} else {
|
|
401
|
+
lines.push(` ${colors.danger}${ICONS.cross} BLOCK${c.reset} ${c.dim}Blocking issues remain${c.reset}`);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
lines.push('');
|
|
405
|
+
|
|
406
|
+
return lines.join('\n');
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
module.exports = {
|
|
410
|
+
// Main formatters
|
|
411
|
+
formatMissionBriefing,
|
|
412
|
+
formatAllBriefings,
|
|
413
|
+
formatMissionSummary,
|
|
414
|
+
formatMissionResult,
|
|
415
|
+
formatFinalSummary,
|
|
416
|
+
|
|
417
|
+
// Utilities
|
|
418
|
+
getMissionIcon,
|
|
419
|
+
getRiskColor,
|
|
420
|
+
truncate,
|
|
421
|
+
line,
|
|
422
|
+
|
|
423
|
+
// Colors and icons for external use
|
|
424
|
+
colors,
|
|
425
|
+
ICONS,
|
|
426
|
+
c,
|
|
427
|
+
};
|