@vibecheckai/cli 3.1.2 → 3.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +60 -33
  2. package/bin/registry.js +319 -34
  3. package/bin/runners/CLI_REFACTOR_SUMMARY.md +229 -0
  4. package/bin/runners/REPORT_AUDIT.md +64 -0
  5. package/bin/runners/lib/entitlements-v2.js +97 -28
  6. package/bin/runners/lib/entitlements.js +3 -6
  7. package/bin/runners/lib/init-wizard.js +1 -1
  8. package/bin/runners/lib/report-engine.js +459 -280
  9. package/bin/runners/lib/report-html.js +1154 -1423
  10. package/bin/runners/lib/report-output.js +187 -0
  11. package/bin/runners/lib/report-templates.js +848 -850
  12. package/bin/runners/lib/scan-output.js +545 -0
  13. package/bin/runners/lib/server-usage.js +0 -12
  14. package/bin/runners/lib/ship-output.js +641 -0
  15. package/bin/runners/lib/status-output.js +253 -0
  16. package/bin/runners/lib/terminal-ui.js +853 -0
  17. package/bin/runners/runCheckpoint.js +502 -0
  18. package/bin/runners/runContracts.js +105 -0
  19. package/bin/runners/runExport.js +93 -0
  20. package/bin/runners/runFix.js +31 -24
  21. package/bin/runners/runInit.js +377 -112
  22. package/bin/runners/runInstall.js +1 -5
  23. package/bin/runners/runLabs.js +3 -3
  24. package/bin/runners/runPolish.js +2452 -0
  25. package/bin/runners/runProve.js +2 -2
  26. package/bin/runners/runReport.js +251 -200
  27. package/bin/runners/runRuntime.js +110 -0
  28. package/bin/runners/runScan.js +477 -379
  29. package/bin/runners/runSecurity.js +92 -0
  30. package/bin/runners/runShip.js +137 -207
  31. package/bin/runners/runStatus.js +16 -68
  32. package/bin/runners/utils.js +5 -5
  33. package/bin/vibecheck.js +25 -11
  34. package/mcp-server/index.js +150 -18
  35. package/mcp-server/package.json +2 -2
  36. package/mcp-server/premium-tools.js +13 -13
  37. package/mcp-server/tier-auth.js +292 -27
  38. package/mcp-server/vibecheck-tools.js +9 -9
  39. package/package.json +1 -1
  40. package/bin/runners/runClaimVerifier.js +0 -483
  41. package/bin/runners/runContextCompiler.js +0 -385
  42. package/bin/runners/runGate.js +0 -17
  43. package/bin/runners/runInitGha.js +0 -164
  44. package/bin/runners/runInteractive.js +0 -388
  45. package/bin/runners/runMdc.js +0 -204
  46. package/bin/runners/runMissionGenerator.js +0 -282
  47. package/bin/runners/runTruthpack.js +0 -636
@@ -1,282 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Mission Generator v1
4
- *
5
- * Generates Assist Mission files from ship findings.
6
- * Each mission is a Markdown file with YAML frontmatter.
7
- *
8
- * Usage:
9
- * generateMissions(findings, projectPath)
10
- */
11
-
12
- import fs from 'fs/promises';
13
- import path from 'path';
14
- import yaml from 'js-yaml';
15
-
16
- /**
17
- * Generate mission files from findings
18
- *
19
- * @param {Object[]} findings - Array of findings from vibecheck ship
20
- * @param {string} projectPath - Project root path
21
- * @returns {Object} Generated missions info
22
- */
23
- export async function generateMissions(findings, projectPath = process.cwd()) {
24
- const assistDir = path.join(projectPath, '.vibecheck', 'assist');
25
- const missionsDir = path.join(assistDir, 'missions');
26
-
27
- await fs.mkdir(missionsDir, { recursive: true });
28
-
29
- // Group findings by category
30
- const grouped = groupFindings(findings);
31
-
32
- // Generate mission files
33
- const missions = [];
34
- let missionNumber = 1;
35
-
36
- for (const [category, categoryFindings] of Object.entries(grouped)) {
37
- for (const finding of categoryFindings) {
38
- const mission = createMission(finding, missionNumber, category);
39
- const filename = `${String(missionNumber).padStart(2, '0')}_${slugify(mission.title)}.md`;
40
- const filePath = path.join(missionsDir, filename);
41
-
42
- await fs.writeFile(filePath, formatMission(mission));
43
-
44
- missions.push({
45
- id: mission.missionId,
46
- title: mission.title,
47
- file: filename,
48
- severity: mission.severity,
49
- category: mission.category,
50
- });
51
-
52
- missionNumber++;
53
- }
54
- }
55
-
56
- // Write plan.json
57
- const plan = {
58
- generatedAt: new Date().toISOString(),
59
- totalMissions: missions.length,
60
- byCategory: Object.fromEntries(
61
- Object.entries(grouped).map(([cat, items]) => [cat, items.length])
62
- ),
63
- missions,
64
- };
65
-
66
- await fs.writeFile(
67
- path.join(assistDir, 'plan.json'),
68
- JSON.stringify(plan, null, 2)
69
- );
70
-
71
- console.log(`\n📋 Generated ${missions.length} missions in ${missionsDir}`);
72
-
73
- return plan;
74
- }
75
-
76
- /**
77
- * Group findings by category
78
- */
79
- function groupFindings(findings) {
80
- const groups = {};
81
-
82
- for (const finding of findings) {
83
- const category = finding.category || 'general';
84
- if (!groups[category]) groups[category] = [];
85
- groups[category].push(finding);
86
- }
87
-
88
- // Sort by severity within each category
89
- const severityOrder = { BLOCK: 0, WARN: 1, INFO: 2 };
90
- for (const category of Object.keys(groups)) {
91
- groups[category].sort((a, b) =>
92
- (severityOrder[a.severity] || 3) - (severityOrder[b.severity] || 3)
93
- );
94
- }
95
-
96
- return groups;
97
- }
98
-
99
- /**
100
- * Create a mission object from a finding
101
- */
102
- function createMission(finding, number, category) {
103
- const missionId = `M${String(number).padStart(2, '0')}`;
104
-
105
- // Determine required claims based on finding type
106
- const dependsOnClaims = [];
107
- if (finding.type === 'dead_ui' || finding.type === 'route_mismatch') {
108
- dependsOnClaims.push({
109
- type: 'route_exists',
110
- subject: { path: finding.route || finding.expectedRoute },
111
- });
112
- }
113
- if (finding.type === 'auth_gap') {
114
- dependsOnClaims.push({
115
- type: 'auth_enforced',
116
- subject: { path: finding.route },
117
- });
118
- }
119
-
120
- // Determine applicable invariants
121
- const invariants = [];
122
- if (category === 'DeadUI' || finding.type === 'dead_ui') {
123
- invariants.push('INV_NO_FAKE_SUCCESS', 'INV_NO_ROUTE_INVENTION');
124
- }
125
- if (category === 'Auth' || finding.type === 'auth_gap') {
126
- invariants.push('INV_NO_BYPASS_ENTITLEMENTS', 'INV_NO_SILENT_CATCH_AUTH');
127
- }
128
- if (category === 'Billing') {
129
- invariants.push('INV_NO_BYPASS_ENTITLEMENTS');
130
- }
131
-
132
- return {
133
- missionId,
134
- title: finding.title || `Fix ${category} issue`,
135
- severity: finding.severity || 'WARN',
136
- category,
137
- scopeFiles: finding.files || [],
138
- dependsOnClaims,
139
- invariants,
140
- assumptionBudget: 2,
141
- finding,
142
- };
143
- }
144
-
145
- /**
146
- * Format a mission as Markdown with YAML frontmatter
147
- */
148
- function formatMission(mission) {
149
- const frontmatter = {
150
- missionId: mission.missionId,
151
- title: mission.title,
152
- severity: mission.severity,
153
- category: mission.category,
154
- scopeFiles: mission.scopeFiles,
155
- dependsOnClaims: mission.dependsOnClaims,
156
- invariants: mission.invariants,
157
- assumptionBudget: mission.assumptionBudget,
158
- };
159
-
160
- const finding = mission.finding;
161
-
162
- const content = `---
163
- ${yaml.dump(frontmatter, { lineWidth: -1 })}---
164
-
165
- # Objective
166
- ${finding.description || finding.title || 'Fix the identified issue.'}
167
-
168
- # Truth Pack (authoritative)
169
- Use the provided context slice and do not invent endpoints, env vars, or auth assumptions.
170
-
171
- # Evidence Pack (must reference when editing)
172
- - Finding ${finding.id || mission.missionId}:
173
- ${mission.scopeFiles.map(f => ` - ${f}`).join('\n') || ' - (no specific files identified)'}
174
- - Reason: ${finding.reason || finding.description || 'See finding details'}
175
-
176
- # Required tool calls (before making claims)
177
- ${generateRequiredToolCalls(mission)}
178
-
179
- # Steps
180
- ${generateSteps(mission)}
181
-
182
- # Acceptance tests (must pass)
183
- - vibecheck ship
184
- - ${findTestCommand(mission)}
185
- - No new blockers introduced
186
-
187
- # Output requirements
188
- - List changed files
189
- - Explain each change with evidence refs
190
- - Provide final ship verdict result
191
- `;
192
-
193
- return content;
194
- }
195
-
196
- /**
197
- * Generate required tool calls for the mission
198
- */
199
- function generateRequiredToolCalls(mission) {
200
- const calls = [];
201
- let callNum = 1;
202
-
203
- for (const claim of mission.dependsOnClaims) {
204
- calls.push(`${callNum}) validate_claim(${claim.type} ${JSON.stringify(claim.subject)})`);
205
- callNum++;
206
- }
207
-
208
- if (calls.length === 0) {
209
- calls.push('1) vibecheck.get_truthpack() - Get current truth state');
210
- }
211
-
212
- calls.push(`${callNum}) search_evidence("${mission.category.toLowerCase()}", globs=["src/**","apps/**"])`);
213
-
214
- return calls.join('\n');
215
- }
216
-
217
- /**
218
- * Generate steps for the mission
219
- */
220
- function generateSteps(mission) {
221
- const steps = [];
222
- const finding = mission.finding;
223
-
224
- switch (mission.category) {
225
- case 'DeadUI':
226
- steps.push('1) Identify why the UI action is dead (early return / missing handler / missing await).');
227
- steps.push('2) If route mismatch exists, align client call to an existing proven route (do not invent).');
228
- steps.push('3) Ensure success UI happens only after response ok.');
229
- steps.push('4) Ensure errors surface (no empty catch).');
230
- break;
231
-
232
- case 'Auth':
233
- steps.push('1) Verify the auth gap is real by checking middleware/guard configuration.');
234
- steps.push('2) Add or fix the auth middleware on the affected route.');
235
- steps.push('3) Ensure auth errors are properly handled (no silent failures).');
236
- steps.push('4) Test both authenticated and unauthenticated access.');
237
- break;
238
-
239
- case 'Billing':
240
- steps.push('1) Verify the billing gate is missing or bypassable.');
241
- steps.push('2) Add server-side tier/entitlement check.');
242
- steps.push('3) Ensure client-side checks match server-side enforcement.');
243
- steps.push('4) Remove any bypass flags or dev-only overrides.');
244
- break;
245
-
246
- case 'Security':
247
- steps.push('1) Identify the security vulnerability.');
248
- steps.push('2) Apply the appropriate fix without breaking functionality.');
249
- steps.push('3) Add validation/sanitization as needed.');
250
- steps.push('4) Verify the fix does not introduce new vulnerabilities.');
251
- break;
252
-
253
- default:
254
- steps.push('1) Analyze the finding to understand the root cause.');
255
- steps.push('2) Identify the minimal change needed to fix the issue.');
256
- steps.push('3) Implement the fix with proper error handling.');
257
- steps.push('4) Verify the fix resolves the finding.');
258
- }
259
-
260
- return steps.join('\n');
261
- }
262
-
263
- /**
264
- * Find the appropriate test command
265
- */
266
- function findTestCommand(mission) {
267
- // This would ideally come from the truth pack's project.scripts
268
- return 'pnpm test OR npm test (if present)';
269
- }
270
-
271
- /**
272
- * Convert title to slug
273
- */
274
- function slugify(text) {
275
- return text
276
- .toLowerCase()
277
- .replace(/[^a-z0-9]+/g, '_')
278
- .replace(/^_+|_+$/g, '')
279
- .slice(0, 40);
280
- }
281
-
282
- export default { generateMissions };