@vibecheckai/cli 3.0.10 → 3.1.1

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 (162) hide show
  1. package/bin/.generated +25 -0
  2. package/bin/dev/run-v2-torture.js +30 -30
  3. package/bin/registry.js +105 -0
  4. package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -295
  5. package/bin/runners/lib/analysis-core.js +271 -271
  6. package/bin/runners/lib/analyzers.js +579 -579
  7. package/bin/runners/lib/auth-truth.js +193 -193
  8. package/bin/runners/lib/backup.js +62 -62
  9. package/bin/runners/lib/billing.js +107 -107
  10. package/bin/runners/lib/claims.js +118 -118
  11. package/bin/runners/lib/cli-output.js +368 -0
  12. package/bin/runners/lib/cli-ui.js +540 -540
  13. package/bin/runners/lib/contracts/auth-contract.js +202 -202
  14. package/bin/runners/lib/contracts/env-contract.js +181 -181
  15. package/bin/runners/lib/contracts/external-contract.js +206 -206
  16. package/bin/runners/lib/contracts/guard.js +168 -168
  17. package/bin/runners/lib/contracts/index.js +89 -89
  18. package/bin/runners/lib/contracts/plan-validator.js +311 -311
  19. package/bin/runners/lib/contracts/route-contract.js +199 -199
  20. package/bin/runners/lib/contracts.js +804 -804
  21. package/bin/runners/lib/detect.js +89 -89
  22. package/bin/runners/lib/detectors-v2.js +703 -703
  23. package/bin/runners/lib/doctor/autofix.js +254 -254
  24. package/bin/runners/lib/doctor/index.js +37 -37
  25. package/bin/runners/lib/doctor/modules/dependencies.js +325 -325
  26. package/bin/runners/lib/doctor/modules/index.js +46 -46
  27. package/bin/runners/lib/doctor/modules/network.js +250 -250
  28. package/bin/runners/lib/doctor/modules/project.js +312 -312
  29. package/bin/runners/lib/doctor/modules/runtime.js +224 -224
  30. package/bin/runners/lib/doctor/modules/security.js +348 -348
  31. package/bin/runners/lib/doctor/modules/system.js +213 -213
  32. package/bin/runners/lib/doctor/modules/vibecheck.js +394 -394
  33. package/bin/runners/lib/doctor/reporter.js +262 -262
  34. package/bin/runners/lib/doctor/service.js +262 -262
  35. package/bin/runners/lib/doctor/types.js +113 -113
  36. package/bin/runners/lib/doctor/ui.js +263 -263
  37. package/bin/runners/lib/doctor-v2.js +608 -608
  38. package/bin/runners/lib/drift.js +425 -425
  39. package/bin/runners/lib/enforcement.js +72 -72
  40. package/bin/runners/lib/enterprise-detect.js +603 -603
  41. package/bin/runners/lib/enterprise-init.js +942 -942
  42. package/bin/runners/lib/entitlements-v2.js +490 -493
  43. package/bin/runners/lib/env-resolver.js +417 -417
  44. package/bin/runners/lib/env-template.js +66 -66
  45. package/bin/runners/lib/env.js +189 -189
  46. package/bin/runners/lib/extractors/client-calls.js +990 -990
  47. package/bin/runners/lib/extractors/fastify-route-dump.js +573 -573
  48. package/bin/runners/lib/extractors/fastify-routes.js +426 -426
  49. package/bin/runners/lib/extractors/index.js +363 -363
  50. package/bin/runners/lib/extractors/next-routes.js +524 -524
  51. package/bin/runners/lib/extractors/proof-graph.js +431 -431
  52. package/bin/runners/lib/extractors/route-matcher.js +451 -451
  53. package/bin/runners/lib/extractors/truthpack-v2.js +377 -377
  54. package/bin/runners/lib/extractors/ui-bindings.js +547 -547
  55. package/bin/runners/lib/findings-schema.js +281 -281
  56. package/bin/runners/lib/firewall-prompt.js +50 -50
  57. package/bin/runners/lib/graph/graph-builder.js +265 -265
  58. package/bin/runners/lib/graph/html-renderer.js +413 -413
  59. package/bin/runners/lib/graph/index.js +32 -32
  60. package/bin/runners/lib/graph/runtime-collector.js +215 -215
  61. package/bin/runners/lib/graph/static-extractor.js +518 -518
  62. package/bin/runners/lib/html-report.js +650 -650
  63. package/bin/runners/lib/init-wizard.js +308 -308
  64. package/bin/runners/lib/llm.js +75 -75
  65. package/bin/runners/lib/meter.js +61 -61
  66. package/bin/runners/lib/missions/evidence.js +126 -126
  67. package/bin/runners/lib/missions/plan.js +69 -69
  68. package/bin/runners/lib/missions/templates.js +192 -192
  69. package/bin/runners/lib/patch.js +40 -40
  70. package/bin/runners/lib/permissions/auth-model.js +213 -213
  71. package/bin/runners/lib/permissions/idor-prover.js +205 -205
  72. package/bin/runners/lib/permissions/index.js +45 -45
  73. package/bin/runners/lib/permissions/matrix-builder.js +198 -198
  74. package/bin/runners/lib/pkgjson.js +28 -28
  75. package/bin/runners/lib/policy.js +295 -295
  76. package/bin/runners/lib/preflight.js +142 -142
  77. package/bin/runners/lib/reality/correlation-detectors.js +359 -359
  78. package/bin/runners/lib/reality/index.js +318 -318
  79. package/bin/runners/lib/reality/request-hashing.js +416 -416
  80. package/bin/runners/lib/reality/request-mapper.js +453 -453
  81. package/bin/runners/lib/reality/safety-rails.js +463 -463
  82. package/bin/runners/lib/reality/semantic-snapshot.js +408 -408
  83. package/bin/runners/lib/reality/toast-detector.js +393 -393
  84. package/bin/runners/lib/reality-findings.js +84 -84
  85. package/bin/runners/lib/receipts.js +179 -0
  86. package/bin/runners/lib/redact.js +29 -29
  87. package/bin/runners/lib/replay/capsule-manager.js +154 -154
  88. package/bin/runners/lib/replay/index.js +263 -263
  89. package/bin/runners/lib/replay/player.js +348 -348
  90. package/bin/runners/lib/replay/recorder.js +331 -331
  91. package/bin/runners/lib/report-engine.js +447 -447
  92. package/bin/runners/lib/report-html.js +1499 -1499
  93. package/bin/runners/lib/report-templates.js +969 -969
  94. package/bin/runners/lib/report.js +135 -135
  95. package/bin/runners/lib/route-detection.js +1140 -1140
  96. package/bin/runners/lib/route-truth.js +477 -477
  97. package/bin/runners/lib/sandbox/index.js +59 -59
  98. package/bin/runners/lib/sandbox/proof-chain.js +399 -399
  99. package/bin/runners/lib/sandbox/sandbox-runner.js +205 -205
  100. package/bin/runners/lib/sandbox/worktree.js +174 -174
  101. package/bin/runners/lib/schema-validator.js +350 -350
  102. package/bin/runners/lib/schemas/contracts.schema.json +160 -160
  103. package/bin/runners/lib/schemas/finding.schema.json +100 -100
  104. package/bin/runners/lib/schemas/mission-pack.schema.json +206 -206
  105. package/bin/runners/lib/schemas/proof-graph.schema.json +176 -176
  106. package/bin/runners/lib/schemas/reality-report.schema.json +162 -162
  107. package/bin/runners/lib/schemas/share-pack.schema.json +180 -180
  108. package/bin/runners/lib/schemas/ship-report.schema.json +117 -117
  109. package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -303
  110. package/bin/runners/lib/schemas/validator.js +438 -438
  111. package/bin/runners/lib/score-history.js +282 -282
  112. package/bin/runners/lib/share-pack.js +239 -239
  113. package/bin/runners/lib/snippets.js +67 -67
  114. package/bin/runners/lib/truth.js +667 -667
  115. package/bin/runners/lib/upsell.js +510 -0
  116. package/bin/runners/lib/usage.js +153 -0
  117. package/bin/runners/lib/validate-patch.js +156 -156
  118. package/bin/runners/lib/verdict-engine.js +628 -628
  119. package/bin/runners/reality/engine.js +917 -917
  120. package/bin/runners/reality/flows.js +122 -122
  121. package/bin/runners/reality/report.js +378 -378
  122. package/bin/runners/reality/session.js +193 -193
  123. package/bin/runners/runAuth.js +51 -0
  124. package/bin/runners/runBadge.js +31 -4
  125. package/bin/runners/runClaimVerifier.js +483 -483
  126. package/bin/runners/runContext.js +56 -56
  127. package/bin/runners/runContextCompiler.js +385 -385
  128. package/bin/runners/runCtx.js +674 -674
  129. package/bin/runners/runCtxDiff.js +301 -301
  130. package/bin/runners/runCtxGuard.js +176 -176
  131. package/bin/runners/runCtxSync.js +116 -116
  132. package/bin/runners/runDoctor.js +72 -3
  133. package/bin/runners/runFix.js +13 -0
  134. package/bin/runners/runGate.js +17 -17
  135. package/bin/runners/runGraph.js +454 -440
  136. package/bin/runners/runGuard.js +168 -168
  137. package/bin/runners/runInitGha.js +164 -164
  138. package/bin/runners/runInstall.js +277 -277
  139. package/bin/runners/runInteractive.js +388 -388
  140. package/bin/runners/runLabs.js +340 -340
  141. package/bin/runners/runMcp.js +865 -42
  142. package/bin/runners/runMissionGenerator.js +282 -282
  143. package/bin/runners/runPR.js +255 -255
  144. package/bin/runners/runPermissions.js +304 -290
  145. package/bin/runners/runPreflight.js +580 -0
  146. package/bin/runners/runProve.js +1252 -1193
  147. package/bin/runners/runReality.js +1328 -1328
  148. package/bin/runners/runReplay.js +499 -499
  149. package/bin/runners/runReport.js +584 -584
  150. package/bin/runners/runShare.js +212 -212
  151. package/bin/runners/runShip.js +98 -19
  152. package/bin/runners/runStatus.js +138 -138
  153. package/bin/runners/runTruthpack.js +636 -636
  154. package/bin/runners/runVerify.js +272 -0
  155. package/bin/runners/runWatch.js +407 -407
  156. package/bin/vibecheck.js +110 -95
  157. package/mcp-server/consolidated-tools.js +804 -804
  158. package/mcp-server/tools/index.js +72 -72
  159. package/mcp-server/truth-context.js +581 -581
  160. package/mcp-server/truth-firewall-tools.js +1500 -1500
  161. package/package.json +1 -1
  162. package/bin/runners/runProof.zip +0 -0
@@ -1,942 +1,942 @@
1
- // bin/runners/lib/enterprise-init.js
2
- // Enterprise-grade initialization: security policies, compliance, CI/CD, team configs
3
- const fs = require("fs");
4
- const path = require("path");
5
- const { detectAll, CI_PROVIDERS, DEPLOY_PLATFORMS } = require("./enterprise-detect");
6
-
7
- // ANSI colors
8
- const c = {
9
- reset: "\x1b[0m",
10
- bold: "\x1b[1m",
11
- dim: "\x1b[2m",
12
- red: "\x1b[31m",
13
- green: "\x1b[32m",
14
- yellow: "\x1b[33m",
15
- blue: "\x1b[34m",
16
- cyan: "\x1b[36m",
17
- magenta: "\x1b[35m",
18
- };
19
-
20
- function ensureDir(p) {
21
- fs.mkdirSync(p, { recursive: true });
22
- }
23
-
24
- // ============================================================================
25
- // INVARIANTS CONFIGURATION
26
- // ============================================================================
27
- const INVARIANT_DEFINITIONS = {
28
- INV_NO_FAKE_SUCCESS: {
29
- id: "INV_NO_FAKE_SUCCESS",
30
- severity: "BLOCK",
31
- description: "No success UI without confirmed success (awaited network + ok check)",
32
- category: "reliability",
33
- },
34
- INV_NO_ROUTE_INVENTION: {
35
- id: "INV_NO_ROUTE_INVENTION",
36
- severity: "BLOCK",
37
- description: "No route references without matching server route",
38
- category: "integrity",
39
- },
40
- INV_NO_BYPASS_ENTITLEMENTS: {
41
- id: "INV_NO_BYPASS_ENTITLEMENTS",
42
- severity: "BLOCK",
43
- description: "No bypass flags (OWNER_MODE, skipBilling, etc)",
44
- category: "billing",
45
- },
46
- INV_NO_SILENT_CATCH_AUTH: {
47
- id: "INV_NO_SILENT_CATCH_AUTH",
48
- severity: "BLOCK",
49
- description: "No silent catch blocks in auth/billing code paths",
50
- category: "security",
51
- },
52
- INV_NO_HARDCODED_SECRETS: {
53
- id: "INV_NO_HARDCODED_SECRETS",
54
- severity: "BLOCK",
55
- description: "No hardcoded secrets, API keys, or credentials in code",
56
- category: "security",
57
- },
58
- INV_NO_GHOST_AUTH: {
59
- id: "INV_NO_GHOST_AUTH",
60
- severity: "BLOCK",
61
- description: "No sensitive endpoints without auth enforcement",
62
- category: "security",
63
- },
64
- INV_STRIPE_WEBHOOK_VERIFIED: {
65
- id: "INV_STRIPE_WEBHOOK_VERIFIED",
66
- severity: "BLOCK",
67
- description: "All Stripe webhook handlers must verify signature",
68
- category: "billing",
69
- },
70
- INV_STRIPE_IDEMPOTENT: {
71
- id: "INV_STRIPE_IDEMPOTENT",
72
- severity: "WARN",
73
- description: "Stripe webhook handlers should be idempotent",
74
- category: "billing",
75
- },
76
- INV_ENV_VARS_DECLARED: {
77
- id: "INV_ENV_VARS_DECLARED",
78
- severity: "WARN",
79
- description: "All used env vars must be declared in .env.example",
80
- category: "operations",
81
- },
82
- };
83
-
84
- // ============================================================================
85
- // COMPLIANCE TEMPLATES
86
- // ============================================================================
87
- const COMPLIANCE_TEMPLATES = {
88
- soc2: {
89
- name: "SOC 2 Type II",
90
- description: "Service Organization Control 2 compliance baseline",
91
- policies: {
92
- accessControl: true,
93
- changeManagement: true,
94
- riskAssessment: true,
95
- incidentResponse: true,
96
- vendorManagement: true,
97
- },
98
- invariants: [
99
- "INV_NO_HARDCODED_SECRETS",
100
- "INV_NO_GHOST_AUTH",
101
- "INV_NO_SILENT_CATCH_AUTH",
102
- ],
103
- },
104
- hipaa: {
105
- name: "HIPAA",
106
- description: "Health Insurance Portability and Accountability Act baseline",
107
- policies: {
108
- phi_protection: true,
109
- accessControl: true,
110
- auditLogging: true,
111
- encryption: true,
112
- },
113
- invariants: [
114
- "INV_NO_HARDCODED_SECRETS",
115
- "INV_NO_GHOST_AUTH",
116
- ],
117
- },
118
- gdpr: {
119
- name: "GDPR",
120
- description: "General Data Protection Regulation baseline",
121
- policies: {
122
- dataMinimization: true,
123
- consentManagement: true,
124
- rightToErasure: true,
125
- dataPortability: true,
126
- },
127
- invariants: [
128
- "INV_NO_HARDCODED_SECRETS",
129
- ],
130
- },
131
- pci: {
132
- name: "PCI-DSS",
133
- description: "Payment Card Industry Data Security Standard baseline",
134
- policies: {
135
- cardDataProtection: true,
136
- accessControl: true,
137
- encryption: true,
138
- monitoring: true,
139
- },
140
- invariants: [
141
- "INV_NO_HARDCODED_SECRETS",
142
- "INV_STRIPE_WEBHOOK_VERIFIED",
143
- "INV_NO_BYPASS_ENTITLEMENTS",
144
- ],
145
- },
146
- };
147
-
148
- // ============================================================================
149
- // SECURITY POLICY TEMPLATES
150
- // ============================================================================
151
- function generateSecurityPolicy(detection) {
152
- const hasPayments = Object.keys(detection.payments).length > 0;
153
- const hasAuth = Object.keys(detection.auth).length > 0;
154
-
155
- return {
156
- version: "1.0.0",
157
- headers: {
158
- strictTransportSecurity: "max-age=31536000; includeSubDomains",
159
- contentSecurityPolicy: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'",
160
- xFrameOptions: "DENY",
161
- xContentTypeOptions: "nosniff",
162
- referrerPolicy: "strict-origin-when-cross-origin",
163
- permissionsPolicy: "camera=(), microphone=(), geolocation=()",
164
- },
165
- cors: {
166
- allowedOrigins: ["${ALLOWED_ORIGINS}"],
167
- allowedMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
168
- allowCredentials: true,
169
- maxAge: 86400,
170
- },
171
- rateLimit: {
172
- enabled: true,
173
- windowMs: 60000,
174
- max: 100,
175
- message: "Too many requests, please try again later",
176
- },
177
- secrets: {
178
- scanEnabled: true,
179
- blockOnDetection: true,
180
- patterns: [
181
- "sk_live_",
182
- "pk_live_",
183
- "AKIA",
184
- "ghp_",
185
- "gho_",
186
- "eyJ",
187
- ],
188
- },
189
- auth: hasAuth ? {
190
- sessionTimeout: 3600,
191
- mfaRecommended: true,
192
- passwordMinLength: 12,
193
- } : null,
194
- payments: hasPayments ? {
195
- webhookVerification: true,
196
- idempotencyRequired: true,
197
- testModeBlockProduction: true,
198
- } : null,
199
- };
200
- }
201
-
202
- // ============================================================================
203
- // CI/CD TEMPLATES
204
- // ============================================================================
205
- function generateGitHubActionsWorkflow(detection, options = {}) {
206
- const pm = detection.packageManager;
207
- const installCmd = pm === "pnpm" ? "pnpm install --frozen-lockfile" :
208
- pm === "yarn" ? "yarn install --frozen-lockfile" :
209
- pm === "bun" ? "bun install --frozen-lockfile" : "npm ci";
210
-
211
- const runPrefix = pm === "pnpm" ? "pnpm" : pm === "yarn" ? "yarn" : pm === "bun" ? "bun" : "npx";
212
-
213
- return `name: vibecheck
214
-
215
- on:
216
- push:
217
- branches: [main, master]
218
- pull_request:
219
- branches: [main, master]
220
-
221
- permissions:
222
- contents: read
223
- pull-requests: write
224
- security-events: write
225
-
226
- env:
227
- CI: true
228
- NODE_ENV: test
229
-
230
- jobs:
231
- vibecheck:
232
- name: Ship Decision
233
- runs-on: ubuntu-latest
234
- timeout-minutes: 15
235
-
236
- steps:
237
- - name: Checkout
238
- uses: actions/checkout@v4
239
- with:
240
- fetch-depth: 0
241
-
242
- - name: Setup Node.js
243
- uses: actions/setup-node@v4
244
- with:
245
- node-version: 20
246
- cache: '${pm}'
247
-
248
- - name: Install dependencies
249
- run: ${installCmd}
250
-
251
- - name: Generate Truth Pack
252
- run: ${runPrefix} vibecheck ctx
253
- continue-on-error: true
254
-
255
- - name: Ship Decision
256
- id: ship
257
- run: |
258
- set +e
259
- mkdir -p .vibecheck
260
- ${runPrefix} vibecheck pr --out .vibecheck/pr_comment.md ${options.failOnWarn ? "--fail-on-warn" : ""}
261
- code=$?
262
- echo "exit_code=$code" >> $GITHUB_OUTPUT
263
- exit 0
264
-
265
- - name: Upload Artifacts
266
- uses: actions/upload-artifact@v4
267
- if: always()
268
- with:
269
- name: vibecheck-report
270
- path: .vibecheck/
271
- retention-days: 30
272
-
273
- - name: Comment on PR
274
- if: github.event_name == 'pull_request'
275
- uses: actions/github-script@v7
276
- with:
277
- script: |
278
- const fs = require('fs');
279
- const commentPath = '.vibecheck/pr_comment.md';
280
- if (!fs.existsSync(commentPath)) {
281
- console.log('No comment file found');
282
- return;
283
- }
284
- const body = fs.readFileSync(commentPath, 'utf8');
285
-
286
- // Find existing vibecheck comment
287
- const { data: comments } = await github.rest.issues.listComments({
288
- owner: context.repo.owner,
289
- repo: context.repo.repo,
290
- issue_number: context.issue.number,
291
- });
292
-
293
- const existingComment = comments.find(c =>
294
- c.user.type === 'Bot' && c.body.includes('vibecheck')
295
- );
296
-
297
- if (existingComment) {
298
- await github.rest.issues.updateComment({
299
- owner: context.repo.owner,
300
- repo: context.repo.repo,
301
- comment_id: existingComment.id,
302
- body
303
- });
304
- } else {
305
- await github.rest.issues.createComment({
306
- owner: context.repo.owner,
307
- repo: context.repo.repo,
308
- issue_number: context.issue.number,
309
- body
310
- });
311
- }
312
-
313
- - name: Enforce Verdict
314
- run: |
315
- code="\${{ steps.ship.outputs.exit_code }}"
316
- echo "vibecheck exit code: $code"
317
- if [ "$code" = "2" ]; then
318
- echo "::error::BLOCK verdict - deployment blocked"
319
- exit 1
320
- fi
321
- ${options.failOnWarn ? 'if [ "$code" = "1" ]; then echo "::error::WARN verdict (policy: fail-on-warn)"; exit 1; fi' : ''}
322
- echo "✅ Ship decision passed"
323
- `;
324
- }
325
-
326
- function generateGitLabCI(detection, options = {}) {
327
- const pm = detection.packageManager;
328
- const installCmd = pm === "pnpm" ? "pnpm install --frozen-lockfile" :
329
- pm === "yarn" ? "yarn install --frozen-lockfile" : "npm ci";
330
-
331
- return `stages:
332
- - test
333
- - deploy
334
-
335
- variables:
336
- CI: "true"
337
- NODE_ENV: test
338
-
339
- vibecheck:
340
- stage: test
341
- image: node:20
342
- cache:
343
- key: \${CI_COMMIT_REF_SLUG}
344
- paths:
345
- - node_modules/
346
- - .pnpm-store/
347
- before_script:
348
- - ${pm === "pnpm" ? "corepack enable && " : ""}${installCmd}
349
- script:
350
- - npx vibecheck ctx
351
- - npx vibecheck ship ${options.failOnWarn ? "--fail-on-warn" : ""}
352
- artifacts:
353
- when: always
354
- paths:
355
- - .vibecheck/
356
- expire_in: 30 days
357
- rules:
358
- - if: $CI_PIPELINE_SOURCE == "merge_request_event"
359
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
360
- `;
361
- }
362
-
363
- // ============================================================================
364
- // TEAM CONFIG TEMPLATES
365
- // ============================================================================
366
- function generateTeamConfig(detection, options = {}) {
367
- const environments = options.environments || ["development", "staging", "production"];
368
-
369
- return {
370
- version: "1.0.0",
371
- team: {
372
- name: options.teamName || detection.pkg?.name || "unnamed",
373
- environments,
374
- },
375
- policies: {
376
- development: {
377
- verdict: { warnAsPass: true, blockAsBlock: true },
378
- autoFix: { enabled: true, requireApproval: false },
379
- },
380
- staging: {
381
- verdict: { warnAsPass: true, blockAsBlock: true },
382
- autoFix: { enabled: true, requireApproval: true },
383
- },
384
- production: {
385
- verdict: { warnAsPass: false, blockAsBlock: true },
386
- autoFix: { enabled: false, requireApproval: true },
387
- additionalInvariants: ["INV_NO_BYPASS_ENTITLEMENTS"],
388
- },
389
- },
390
- notifications: {
391
- slack: { webhook: "${SLACK_WEBHOOK_URL}", enabled: false },
392
- email: { recipients: [], enabled: false },
393
- },
394
- reporting: {
395
- frequency: "weekly",
396
- recipients: [],
397
- includeMetrics: true,
398
- },
399
- };
400
- }
401
-
402
- // ============================================================================
403
- // MCP SERVER CONFIG
404
- // ============================================================================
405
- function generateMCPConfig(detection) {
406
- return {
407
- name: "vibecheck",
408
- version: "1.0.0",
409
- description: "Vibecheck MCP server for AI agent integration",
410
- capabilities: {
411
- tools: true,
412
- resources: true,
413
- prompts: true,
414
- },
415
- tools: [
416
- "validate_claim",
417
- "get_truthpack",
418
- "get_route_map",
419
- "verify_auth",
420
- "check_invariant",
421
- ],
422
- security: {
423
- requireAuth: false,
424
- allowedOrigins: ["*"],
425
- },
426
- };
427
- }
428
-
429
- // ============================================================================
430
- // INVARIANTS FILE
431
- // ============================================================================
432
- function generateInvariantsYml(invariants) {
433
- const lines = ["# vibecheck invariants - ship killers and warnings", ""];
434
-
435
- const blocks = invariants.filter(id => INVARIANT_DEFINITIONS[id]?.severity === "BLOCK");
436
- const warns = invariants.filter(id => INVARIANT_DEFINITIONS[id]?.severity === "WARN");
437
-
438
- if (blocks.length) {
439
- lines.push("ship_killers:");
440
- for (const id of blocks) {
441
- const def = INVARIANT_DEFINITIONS[id];
442
- lines.push(` - id: ${id}`);
443
- lines.push(` description: "${def?.description || id}"`);
444
- lines.push(` category: ${def?.category || "general"}`);
445
- lines.push("");
446
- }
447
- }
448
-
449
- if (warns.length) {
450
- lines.push("warnings:");
451
- for (const id of warns) {
452
- const def = INVARIANT_DEFINITIONS[id];
453
- lines.push(` - id: ${id}`);
454
- lines.push(` description: "${def?.description || id}"`);
455
- lines.push(` category: ${def?.category || "general"}`);
456
- lines.push("");
457
- }
458
- }
459
-
460
- return lines.join("\n");
461
- }
462
-
463
- // ============================================================================
464
- // MAIN CONFIG FILE
465
- // ============================================================================
466
- function generateVibecheckConfig(detection, options = {}) {
467
- const primaryFramework = Object.keys(detection.frameworks)[0] || "node";
468
- const primaryDb = Object.keys(detection.databases)[0];
469
- const primaryAuth = Object.keys(detection.auth)[0];
470
- const primaryPayment = Object.keys(detection.payments)[0];
471
-
472
- return {
473
- $schema: "https://vibecheck.dev/schemas/config.json",
474
- version: "2.0.0",
475
- project: {
476
- name: detection.pkg?.name || "unnamed",
477
- framework: primaryFramework,
478
- packageManager: detection.packageManager,
479
- },
480
- detection: {
481
- frameworks: Object.keys(detection.frameworks),
482
- databases: Object.keys(detection.databases),
483
- auth: Object.keys(detection.auth),
484
- payments: Object.keys(detection.payments),
485
- ci: Object.keys(detection.ci),
486
- deploy: Object.keys(detection.deploy),
487
- testing: Object.keys(detection.testing),
488
- },
489
- checks: detection.checks,
490
- invariants: detection.invariants,
491
- policy: {
492
- strict: options.strict || false,
493
- failOnWarn: options.failOnWarn || false,
494
- allowlist: {
495
- domains: [],
496
- packages: [],
497
- },
498
- ignore: {
499
- paths: [
500
- "node_modules",
501
- "__tests__",
502
- "*.test.*",
503
- "*.spec.*",
504
- "**/*.d.ts",
505
- "**/fixtures/**",
506
- "**/mocks/**",
507
- ],
508
- },
509
- },
510
- output: {
511
- dir: ".vibecheck",
512
- reports: ["json", "html"],
513
- badges: true,
514
- },
515
- integrations: {
516
- mcp: { enabled: true },
517
- ci: Object.keys(detection.ci).length > 0 ? Object.keys(detection.ci)[0] : null,
518
- },
519
- };
520
- }
521
-
522
- // ============================================================================
523
- // ENTERPRISE INIT ORCHESTRATOR
524
- // ============================================================================
525
- class EnterpriseInit {
526
- constructor(projectPath, options = {}) {
527
- this.projectPath = projectPath;
528
- this.options = options;
529
- this.detection = null;
530
- this.created = [];
531
- this.updated = [];
532
- this.skipped = [];
533
- }
534
-
535
- async run() {
536
- this.printHeader();
537
-
538
- // Step 1: Detect everything
539
- await this.detectProject();
540
-
541
- if (this.detection.error) {
542
- console.log(`\n${c.red}✗ ${this.detection.error}${c.reset}\n`);
543
- return 1;
544
- }
545
-
546
- // Step 2: Print detection results
547
- this.printDetectionResults();
548
-
549
- // Step 3: Generate configurations
550
- await this.generateConfigs();
551
-
552
- // Step 4: Setup CI/CD if requested
553
- if (this.options.ci) {
554
- await this.setupCI();
555
- }
556
-
557
- // Step 5: Setup compliance if requested
558
- if (this.options.compliance) {
559
- await this.setupCompliance();
560
- }
561
-
562
- // Step 6: Print summary
563
- this.printSummary();
564
-
565
- return 0;
566
- }
567
-
568
- printHeader() {
569
- console.log("");
570
- console.log(`${c.cyan}╔══════════════════════════════════════════════════════════════════════════╗${c.reset}`);
571
- console.log(`${c.cyan}║${c.reset} ${c.cyan}║${c.reset}`);
572
- console.log(`${c.cyan}║${c.reset} ${c.bold}🛡️ VIBECHECK ENTERPRISE INIT${c.reset} ${c.cyan}║${c.reset}`);
573
- console.log(`${c.cyan}║${c.reset} ${c.dim}Production-grade project configuration${c.reset} ${c.cyan}║${c.reset}`);
574
- console.log(`${c.cyan}║${c.reset} ${c.cyan}║${c.reset}`);
575
- console.log(`${c.cyan}╚══════════════════════════════════════════════════════════════════════════╝${c.reset}`);
576
- console.log("");
577
- }
578
-
579
- async detectProject() {
580
- process.stdout.write(`${c.dim}Analyzing project...${c.reset}`);
581
- this.detection = detectAll(this.projectPath);
582
- process.stdout.write(`\r${c.green}✓${c.reset} Project analyzed \n`);
583
- }
584
-
585
- printDetectionResults() {
586
- const d = this.detection;
587
-
588
- console.log("");
589
- console.log(`${c.cyan}┌─ Detection Results ──────────────────────────────────────────────────────┐${c.reset}`);
590
-
591
- // Project info
592
- console.log(`${c.cyan}│${c.reset}`);
593
- console.log(`${c.cyan}│${c.reset} ${c.bold}Project:${c.reset} ${d.pkg?.name || "unnamed"} ${c.dim}v${d.pkg?.version || "0.0.0"}${c.reset}`);
594
- console.log(`${c.cyan}│${c.reset} ${c.bold}Package Manager:${c.reset} ${d.packageManager}`);
595
- if (d.monorepo.isMonorepo) {
596
- console.log(`${c.cyan}│${c.reset} ${c.bold}Monorepo:${c.reset} ${c.green}Yes${c.reset}`);
597
- }
598
-
599
- // Frameworks
600
- const frameworks = Object.values(d.frameworks);
601
- if (frameworks.length) {
602
- console.log(`${c.cyan}│${c.reset}`);
603
- console.log(`${c.cyan}│${c.reset} ${c.bold}Frameworks:${c.reset}`);
604
- for (const fw of frameworks) {
605
- console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${fw.icon} ${fw.name}`);
606
- }
607
- }
608
-
609
- // Databases
610
- const databases = Object.values(d.databases);
611
- if (databases.length) {
612
- console.log(`${c.cyan}│${c.reset}`);
613
- console.log(`${c.cyan}│${c.reset} ${c.bold}Databases:${c.reset}`);
614
- for (const db of databases) {
615
- console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${db.icon} ${db.name}`);
616
- }
617
- }
618
-
619
- // Auth
620
- const auth = Object.values(d.auth);
621
- if (auth.length) {
622
- console.log(`${c.cyan}│${c.reset}`);
623
- console.log(`${c.cyan}│${c.reset} ${c.bold}Authentication:${c.reset}`);
624
- for (const a of auth) {
625
- console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${a.icon} ${a.name}`);
626
- }
627
- }
628
-
629
- // Payments
630
- const payments = Object.values(d.payments);
631
- if (payments.length) {
632
- console.log(`${c.cyan}│${c.reset}`);
633
- console.log(`${c.cyan}│${c.reset} ${c.bold}Payments:${c.reset}`);
634
- for (const p of payments) {
635
- console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${p.icon} ${p.name}`);
636
- }
637
- }
638
-
639
- // CI/CD
640
- const ci = Object.values(d.ci);
641
- if (ci.length) {
642
- console.log(`${c.cyan}│${c.reset}`);
643
- console.log(`${c.cyan}│${c.reset} ${c.bold}CI/CD:${c.reset}`);
644
- for (const c2 of ci) {
645
- console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${c2.icon} ${c2.name}`);
646
- }
647
- }
648
-
649
- // Deploy
650
- const deploy = Object.values(d.deploy);
651
- if (deploy.length) {
652
- console.log(`${c.cyan}│${c.reset}`);
653
- console.log(`${c.cyan}│${c.reset} ${c.bold}Deployment:${c.reset}`);
654
- for (const dp of deploy) {
655
- console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${dp.icon} ${dp.name}`);
656
- }
657
- }
658
-
659
- // Testing
660
- const testing = Object.values(d.testing);
661
- if (testing.length) {
662
- console.log(`${c.cyan}│${c.reset}`);
663
- console.log(`${c.cyan}│${c.reset} ${c.bold}Testing:${c.reset}`);
664
- for (const t of testing) {
665
- console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${t.icon} ${t.name}`);
666
- }
667
- }
668
-
669
- // Invariants
670
- console.log(`${c.cyan}│${c.reset}`);
671
- console.log(`${c.cyan}│${c.reset} ${c.bold}Ship Killers:${c.reset} ${c.magenta}${d.invariants.length} invariants${c.reset}`);
672
-
673
- console.log(`${c.cyan}│${c.reset}`);
674
- console.log(`${c.cyan}└───────────────────────────────────────────────────────────────────────────┘${c.reset}`);
675
- console.log("");
676
- }
677
-
678
- async generateConfigs() {
679
- console.log(`${c.cyan}┌─ Generating Configuration ───────────────────────────────────────────────┐${c.reset}`);
680
- console.log(`${c.cyan}│${c.reset}`);
681
-
682
- const tasks = [
683
- { name: ".vibecheck/config.json", fn: () => this.writeConfig() },
684
- { name: ".vibecheck/invariants.yml", fn: () => this.writeInvariants() },
685
- { name: ".vibecheck/security-policy.json", fn: () => this.writeSecurityPolicy() },
686
- { name: ".vibecheck/schemas/", fn: () => this.writeSchemas() },
687
- { name: ".gitignore update", fn: () => this.updateGitignore() },
688
- ];
689
-
690
- if (this.options.team) {
691
- tasks.push({ name: ".vibecheck/team.json", fn: () => this.writeTeamConfig() });
692
- }
693
-
694
- if (this.options.mcp) {
695
- tasks.push({ name: ".vibecheck/mcp.json", fn: () => this.writeMCPConfig() });
696
- }
697
-
698
- for (const task of tasks) {
699
- process.stdout.write(`${c.cyan}│${c.reset} ○ ${task.name}...`);
700
- try {
701
- const result = await task.fn();
702
- const status = result === "created" ? `${c.green}created${c.reset}` :
703
- result === "updated" ? `${c.yellow}updated${c.reset}` :
704
- `${c.dim}skipped${c.reset}`;
705
- process.stdout.write(`\r${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${task.name} ${status}\n`);
706
-
707
- if (result === "created") this.created.push(task.name);
708
- else if (result === "updated") this.updated.push(task.name);
709
- else this.skipped.push(task.name);
710
- } catch (err) {
711
- process.stdout.write(`\r${c.cyan}│${c.reset} ${c.red}✗${c.reset} ${task.name} ${c.red}${err.message}${c.reset}\n`);
712
- }
713
- }
714
-
715
- console.log(`${c.cyan}│${c.reset}`);
716
- console.log(`${c.cyan}└───────────────────────────────────────────────────────────────────────────┘${c.reset}`);
717
- console.log("");
718
- }
719
-
720
- writeConfig() {
721
- const configDir = path.join(this.projectPath, ".vibecheck");
722
- ensureDir(configDir);
723
-
724
- const configPath = path.join(configDir, "config.json");
725
- const config = generateVibecheckConfig(this.detection, this.options);
726
-
727
- const exists = fs.existsSync(configPath);
728
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf8");
729
- return exists ? "updated" : "created";
730
- }
731
-
732
- writeInvariants() {
733
- const configDir = path.join(this.projectPath, ".vibecheck");
734
- ensureDir(configDir);
735
-
736
- const invPath = path.join(configDir, "invariants.yml");
737
- const content = generateInvariantsYml(this.detection.invariants);
738
-
739
- const exists = fs.existsSync(invPath);
740
- fs.writeFileSync(invPath, content, "utf8");
741
- return exists ? "updated" : "created";
742
- }
743
-
744
- writeSecurityPolicy() {
745
- const configDir = path.join(this.projectPath, ".vibecheck");
746
- ensureDir(configDir);
747
-
748
- const policyPath = path.join(configDir, "security-policy.json");
749
- const policy = generateSecurityPolicy(this.detection);
750
-
751
- const exists = fs.existsSync(policyPath);
752
- fs.writeFileSync(policyPath, JSON.stringify(policy, null, 2), "utf8");
753
- return exists ? "updated" : "created";
754
- }
755
-
756
- writeSchemas() {
757
- const schemasDir = path.join(this.projectPath, ".vibecheck", "schemas");
758
- ensureDir(schemasDir);
759
-
760
- const schemas = {
761
- "config.schema.json": {
762
- "$schema": "https://json-schema.org/draft/2020-12/schema",
763
- "$id": "https://vibecheck.dev/schemas/config.json",
764
- "title": "Vibecheck Configuration",
765
- "type": "object",
766
- },
767
- "truthpack.schema.json": {
768
- "$schema": "https://json-schema.org/draft/2020-12/schema",
769
- "$id": "https://vibecheck.dev/schemas/truthpack.json",
770
- "title": "Vibecheck Truthpack",
771
- "type": "object",
772
- },
773
- };
774
-
775
- for (const [name, schema] of Object.entries(schemas)) {
776
- fs.writeFileSync(path.join(schemasDir, name), JSON.stringify(schema, null, 2), "utf8");
777
- }
778
-
779
- return "created";
780
- }
781
-
782
- writeTeamConfig() {
783
- const configDir = path.join(this.projectPath, ".vibecheck");
784
- ensureDir(configDir);
785
-
786
- const teamPath = path.join(configDir, "team.json");
787
- const config = generateTeamConfig(this.detection, this.options);
788
-
789
- const exists = fs.existsSync(teamPath);
790
- fs.writeFileSync(teamPath, JSON.stringify(config, null, 2), "utf8");
791
- return exists ? "updated" : "created";
792
- }
793
-
794
- writeMCPConfig() {
795
- const configDir = path.join(this.projectPath, ".vibecheck");
796
- ensureDir(configDir);
797
-
798
- const mcpPath = path.join(configDir, "mcp.json");
799
- const config = generateMCPConfig(this.detection);
800
-
801
- const exists = fs.existsSync(mcpPath);
802
- fs.writeFileSync(mcpPath, JSON.stringify(config, null, 2), "utf8");
803
- return exists ? "updated" : "created";
804
- }
805
-
806
- updateGitignore() {
807
- const gitignorePath = path.join(this.projectPath, ".gitignore");
808
- const entries = [
809
- "",
810
- "# vibecheck",
811
- ".vibecheck/truth/",
812
- ".vibecheck/reality/",
813
- ".vibecheck/missions/",
814
- ".vibecheck/prove/",
815
- ".vibecheck/cache/",
816
- "",
817
- ].join("\n");
818
-
819
- if (fs.existsSync(gitignorePath)) {
820
- const content = fs.readFileSync(gitignorePath, "utf8");
821
- if (content.includes(".vibecheck/")) {
822
- return "skipped";
823
- }
824
- fs.appendFileSync(gitignorePath, entries);
825
- return "updated";
826
- } else {
827
- fs.writeFileSync(gitignorePath, entries.trim() + "\n");
828
- return "created";
829
- }
830
- }
831
-
832
- async setupCI() {
833
- console.log(`${c.cyan}┌─ CI/CD Integration ──────────────────────────────────────────────────────┐${c.reset}`);
834
- console.log(`${c.cyan}│${c.reset}`);
835
-
836
- const ciType = this.options.ci === true ? "github" : this.options.ci;
837
-
838
- if (ciType === "github" || ciType === "github-actions") {
839
- const wfDir = path.join(this.projectPath, ".github", "workflows");
840
- ensureDir(wfDir);
841
-
842
- const wfPath = path.join(wfDir, "vibecheck.yml");
843
- const workflow = generateGitHubActionsWorkflow(this.detection, this.options);
844
-
845
- fs.writeFileSync(wfPath, workflow, "utf8");
846
- console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} Created .github/workflows/vibecheck.yml`);
847
- this.created.push(".github/workflows/vibecheck.yml");
848
- } else if (ciType === "gitlab") {
849
- const ciPath = path.join(this.projectPath, ".gitlab-ci.vibecheck.yml");
850
- const config = generateGitLabCI(this.detection, this.options);
851
-
852
- fs.writeFileSync(ciPath, config, "utf8");
853
- console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} Created .gitlab-ci.vibecheck.yml`);
854
- console.log(`${c.cyan}│${c.reset} ${c.dim}Include this in your main .gitlab-ci.yml${c.reset}`);
855
- this.created.push(".gitlab-ci.vibecheck.yml");
856
- }
857
-
858
- console.log(`${c.cyan}│${c.reset}`);
859
- console.log(`${c.cyan}└───────────────────────────────────────────────────────────────────────────┘${c.reset}`);
860
- console.log("");
861
- }
862
-
863
- async setupCompliance() {
864
- console.log(`${c.cyan}┌─ Compliance Templates ───────────────────────────────────────────────────┐${c.reset}`);
865
- console.log(`${c.cyan}│${c.reset}`);
866
-
867
- const complianceDir = path.join(this.projectPath, ".vibecheck", "compliance");
868
- ensureDir(complianceDir);
869
-
870
- const templates = typeof this.options.compliance === "string"
871
- ? [this.options.compliance]
872
- : Object.keys(COMPLIANCE_TEMPLATES);
873
-
874
- for (const key of templates) {
875
- const template = COMPLIANCE_TEMPLATES[key];
876
- if (!template) continue;
877
-
878
- const filePath = path.join(complianceDir, `${key}.json`);
879
- fs.writeFileSync(filePath, JSON.stringify({
880
- name: template.name,
881
- description: template.description,
882
- policies: template.policies,
883
- invariants: template.invariants,
884
- status: "not_started",
885
- lastAudit: null,
886
- }, null, 2), "utf8");
887
-
888
- console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} Created compliance/${key}.json (${template.name})`);
889
- this.created.push(`compliance/${key}.json`);
890
- }
891
-
892
- console.log(`${c.cyan}│${c.reset}`);
893
- console.log(`${c.cyan}└───────────────────────────────────────────────────────────────────────────┘${c.reset}`);
894
- console.log("");
895
- }
896
-
897
- printSummary() {
898
- console.log(`${c.green}${c.bold}✓ Enterprise init complete${c.reset}`);
899
- console.log("");
900
-
901
- if (this.created.length) {
902
- console.log(`${c.green}Created:${c.reset} ${this.created.length} files`);
903
- }
904
- if (this.updated.length) {
905
- console.log(`${c.yellow}Updated:${c.reset} ${this.updated.length} files`);
906
- }
907
-
908
- console.log("");
909
- console.log(`${c.cyan}╔══════════════════════════════════════════════════════════════════════════╗${c.reset}`);
910
- console.log(`${c.cyan}║${c.reset} ${c.bold}Next Steps${c.reset} ${c.cyan}║${c.reset}`);
911
- console.log(`${c.cyan}╠══════════════════════════════════════════════════════════════════════════╣${c.reset}`);
912
- console.log(`${c.cyan}║${c.reset} ${c.cyan}║${c.reset}`);
913
- console.log(`${c.cyan}║${c.reset} ${c.bold}1.${c.reset} Generate truth pack: ${c.cyan}║${c.reset}`);
914
- console.log(`${c.cyan}║${c.reset} ${c.cyan}vibecheck ctx${c.reset} ${c.cyan}║${c.reset}`);
915
- console.log(`${c.cyan}║${c.reset} ${c.cyan}║${c.reset}`);
916
- console.log(`${c.cyan}║${c.reset} ${c.bold}2.${c.reset} Run ship decision: ${c.cyan}║${c.reset}`);
917
- console.log(`${c.cyan}║${c.reset} ${c.cyan}vibecheck ship${c.reset} ${c.cyan}║${c.reset}`);
918
- console.log(`${c.cyan}║${c.reset} ${c.cyan}║${c.reset}`);
919
- console.log(`${c.cyan}║${c.reset} ${c.bold}3.${c.reset} Start MCP server for AI agents: ${c.cyan}║${c.reset}`);
920
- console.log(`${c.cyan}║${c.reset} ${c.cyan}vibecheck mcp${c.reset} ${c.cyan}║${c.reset}`);
921
- console.log(`${c.cyan}║${c.reset} ${c.cyan}║${c.reset}`);
922
- console.log(`${c.cyan}╚══════════════════════════════════════════════════════════════════════════╝${c.reset}`);
923
- console.log("");
924
- console.log(`${c.dim}Tip: Run ${c.cyan}vibecheck prove --url http://localhost:3000${c.dim} for full reality verification${c.reset}`);
925
- console.log("");
926
- }
927
- }
928
-
929
- // ============================================================================
930
- // EXPORTS
931
- // ============================================================================
932
- module.exports = {
933
- EnterpriseInit,
934
- generateGitHubActionsWorkflow,
935
- generateGitLabCI,
936
- generateSecurityPolicy,
937
- generateTeamConfig,
938
- generateVibecheckConfig,
939
- generateInvariantsYml,
940
- INVARIANT_DEFINITIONS,
941
- COMPLIANCE_TEMPLATES,
942
- };
1
+ // bin/runners/lib/enterprise-init.js
2
+ // Enterprise-grade initialization: security policies, compliance, CI/CD, team configs
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const { detectAll, CI_PROVIDERS, DEPLOY_PLATFORMS } = require("./enterprise-detect");
6
+
7
+ // ANSI colors
8
+ const c = {
9
+ reset: "\x1b[0m",
10
+ bold: "\x1b[1m",
11
+ dim: "\x1b[2m",
12
+ red: "\x1b[31m",
13
+ green: "\x1b[32m",
14
+ yellow: "\x1b[33m",
15
+ blue: "\x1b[34m",
16
+ cyan: "\x1b[36m",
17
+ magenta: "\x1b[35m",
18
+ };
19
+
20
+ function ensureDir(p) {
21
+ fs.mkdirSync(p, { recursive: true });
22
+ }
23
+
24
+ // ============================================================================
25
+ // INVARIANTS CONFIGURATION
26
+ // ============================================================================
27
+ const INVARIANT_DEFINITIONS = {
28
+ INV_NO_FAKE_SUCCESS: {
29
+ id: "INV_NO_FAKE_SUCCESS",
30
+ severity: "BLOCK",
31
+ description: "No success UI without confirmed success (awaited network + ok check)",
32
+ category: "reliability",
33
+ },
34
+ INV_NO_ROUTE_INVENTION: {
35
+ id: "INV_NO_ROUTE_INVENTION",
36
+ severity: "BLOCK",
37
+ description: "No route references without matching server route",
38
+ category: "integrity",
39
+ },
40
+ INV_NO_BYPASS_ENTITLEMENTS: {
41
+ id: "INV_NO_BYPASS_ENTITLEMENTS",
42
+ severity: "BLOCK",
43
+ description: "No bypass flags (OWNER_MODE, skipBilling, etc)",
44
+ category: "billing",
45
+ },
46
+ INV_NO_SILENT_CATCH_AUTH: {
47
+ id: "INV_NO_SILENT_CATCH_AUTH",
48
+ severity: "BLOCK",
49
+ description: "No silent catch blocks in auth/billing code paths",
50
+ category: "security",
51
+ },
52
+ INV_NO_HARDCODED_SECRETS: {
53
+ id: "INV_NO_HARDCODED_SECRETS",
54
+ severity: "BLOCK",
55
+ description: "No hardcoded secrets, API keys, or credentials in code",
56
+ category: "security",
57
+ },
58
+ INV_NO_GHOST_AUTH: {
59
+ id: "INV_NO_GHOST_AUTH",
60
+ severity: "BLOCK",
61
+ description: "No sensitive endpoints without auth enforcement",
62
+ category: "security",
63
+ },
64
+ INV_STRIPE_WEBHOOK_VERIFIED: {
65
+ id: "INV_STRIPE_WEBHOOK_VERIFIED",
66
+ severity: "BLOCK",
67
+ description: "All Stripe webhook handlers must verify signature",
68
+ category: "billing",
69
+ },
70
+ INV_STRIPE_IDEMPOTENT: {
71
+ id: "INV_STRIPE_IDEMPOTENT",
72
+ severity: "WARN",
73
+ description: "Stripe webhook handlers should be idempotent",
74
+ category: "billing",
75
+ },
76
+ INV_ENV_VARS_DECLARED: {
77
+ id: "INV_ENV_VARS_DECLARED",
78
+ severity: "WARN",
79
+ description: "All used env vars must be declared in .env.example",
80
+ category: "operations",
81
+ },
82
+ };
83
+
84
+ // ============================================================================
85
+ // COMPLIANCE TEMPLATES
86
+ // ============================================================================
87
+ const COMPLIANCE_TEMPLATES = {
88
+ soc2: {
89
+ name: "SOC 2 Type II",
90
+ description: "Service Organization Control 2 compliance baseline",
91
+ policies: {
92
+ accessControl: true,
93
+ changeManagement: true,
94
+ riskAssessment: true,
95
+ incidentResponse: true,
96
+ vendorManagement: true,
97
+ },
98
+ invariants: [
99
+ "INV_NO_HARDCODED_SECRETS",
100
+ "INV_NO_GHOST_AUTH",
101
+ "INV_NO_SILENT_CATCH_AUTH",
102
+ ],
103
+ },
104
+ hipaa: {
105
+ name: "HIPAA",
106
+ description: "Health Insurance Portability and Accountability Act baseline",
107
+ policies: {
108
+ phi_protection: true,
109
+ accessControl: true,
110
+ auditLogging: true,
111
+ encryption: true,
112
+ },
113
+ invariants: [
114
+ "INV_NO_HARDCODED_SECRETS",
115
+ "INV_NO_GHOST_AUTH",
116
+ ],
117
+ },
118
+ gdpr: {
119
+ name: "GDPR",
120
+ description: "General Data Protection Regulation baseline",
121
+ policies: {
122
+ dataMinimization: true,
123
+ consentManagement: true,
124
+ rightToErasure: true,
125
+ dataPortability: true,
126
+ },
127
+ invariants: [
128
+ "INV_NO_HARDCODED_SECRETS",
129
+ ],
130
+ },
131
+ pci: {
132
+ name: "PCI-DSS",
133
+ description: "Payment Card Industry Data Security Standard baseline",
134
+ policies: {
135
+ cardDataProtection: true,
136
+ accessControl: true,
137
+ encryption: true,
138
+ monitoring: true,
139
+ },
140
+ invariants: [
141
+ "INV_NO_HARDCODED_SECRETS",
142
+ "INV_STRIPE_WEBHOOK_VERIFIED",
143
+ "INV_NO_BYPASS_ENTITLEMENTS",
144
+ ],
145
+ },
146
+ };
147
+
148
+ // ============================================================================
149
+ // SECURITY POLICY TEMPLATES
150
+ // ============================================================================
151
+ function generateSecurityPolicy(detection) {
152
+ const hasPayments = Object.keys(detection.payments).length > 0;
153
+ const hasAuth = Object.keys(detection.auth).length > 0;
154
+
155
+ return {
156
+ version: "1.0.0",
157
+ headers: {
158
+ strictTransportSecurity: "max-age=31536000; includeSubDomains",
159
+ contentSecurityPolicy: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'",
160
+ xFrameOptions: "DENY",
161
+ xContentTypeOptions: "nosniff",
162
+ referrerPolicy: "strict-origin-when-cross-origin",
163
+ permissionsPolicy: "camera=(), microphone=(), geolocation=()",
164
+ },
165
+ cors: {
166
+ allowedOrigins: ["${ALLOWED_ORIGINS}"],
167
+ allowedMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
168
+ allowCredentials: true,
169
+ maxAge: 86400,
170
+ },
171
+ rateLimit: {
172
+ enabled: true,
173
+ windowMs: 60000,
174
+ max: 100,
175
+ message: "Too many requests, please try again later",
176
+ },
177
+ secrets: {
178
+ scanEnabled: true,
179
+ blockOnDetection: true,
180
+ patterns: [
181
+ "sk_live_",
182
+ "pk_live_",
183
+ "AKIA",
184
+ "ghp_",
185
+ "gho_",
186
+ "eyJ",
187
+ ],
188
+ },
189
+ auth: hasAuth ? {
190
+ sessionTimeout: 3600,
191
+ mfaRecommended: true,
192
+ passwordMinLength: 12,
193
+ } : null,
194
+ payments: hasPayments ? {
195
+ webhookVerification: true,
196
+ idempotencyRequired: true,
197
+ testModeBlockProduction: true,
198
+ } : null,
199
+ };
200
+ }
201
+
202
+ // ============================================================================
203
+ // CI/CD TEMPLATES
204
+ // ============================================================================
205
+ function generateGitHubActionsWorkflow(detection, options = {}) {
206
+ const pm = detection.packageManager;
207
+ const installCmd = pm === "pnpm" ? "pnpm install --frozen-lockfile" :
208
+ pm === "yarn" ? "yarn install --frozen-lockfile" :
209
+ pm === "bun" ? "bun install --frozen-lockfile" : "npm ci";
210
+
211
+ const runPrefix = pm === "pnpm" ? "pnpm" : pm === "yarn" ? "yarn" : pm === "bun" ? "bun" : "npx";
212
+
213
+ return `name: vibecheck
214
+
215
+ on:
216
+ push:
217
+ branches: [main, master]
218
+ pull_request:
219
+ branches: [main, master]
220
+
221
+ permissions:
222
+ contents: read
223
+ pull-requests: write
224
+ security-events: write
225
+
226
+ env:
227
+ CI: true
228
+ NODE_ENV: test
229
+
230
+ jobs:
231
+ vibecheck:
232
+ name: Ship Decision
233
+ runs-on: ubuntu-latest
234
+ timeout-minutes: 15
235
+
236
+ steps:
237
+ - name: Checkout
238
+ uses: actions/checkout@v4
239
+ with:
240
+ fetch-depth: 0
241
+
242
+ - name: Setup Node.js
243
+ uses: actions/setup-node@v4
244
+ with:
245
+ node-version: 20
246
+ cache: '${pm}'
247
+
248
+ - name: Install dependencies
249
+ run: ${installCmd}
250
+
251
+ - name: Generate Truth Pack
252
+ run: ${runPrefix} vibecheck ctx
253
+ continue-on-error: true
254
+
255
+ - name: Ship Decision
256
+ id: ship
257
+ run: |
258
+ set +e
259
+ mkdir -p .vibecheck
260
+ ${runPrefix} vibecheck pr --out .vibecheck/pr_comment.md ${options.failOnWarn ? "--fail-on-warn" : ""}
261
+ code=$?
262
+ echo "exit_code=$code" >> $GITHUB_OUTPUT
263
+ exit 0
264
+
265
+ - name: Upload Artifacts
266
+ uses: actions/upload-artifact@v4
267
+ if: always()
268
+ with:
269
+ name: vibecheck-report
270
+ path: .vibecheck/
271
+ retention-days: 30
272
+
273
+ - name: Comment on PR
274
+ if: github.event_name == 'pull_request'
275
+ uses: actions/github-script@v7
276
+ with:
277
+ script: |
278
+ const fs = require('fs');
279
+ const commentPath = '.vibecheck/pr_comment.md';
280
+ if (!fs.existsSync(commentPath)) {
281
+ console.log('No comment file found');
282
+ return;
283
+ }
284
+ const body = fs.readFileSync(commentPath, 'utf8');
285
+
286
+ // Find existing vibecheck comment
287
+ const { data: comments } = await github.rest.issues.listComments({
288
+ owner: context.repo.owner,
289
+ repo: context.repo.repo,
290
+ issue_number: context.issue.number,
291
+ });
292
+
293
+ const existingComment = comments.find(c =>
294
+ c.user.type === 'Bot' && c.body.includes('vibecheck')
295
+ );
296
+
297
+ if (existingComment) {
298
+ await github.rest.issues.updateComment({
299
+ owner: context.repo.owner,
300
+ repo: context.repo.repo,
301
+ comment_id: existingComment.id,
302
+ body
303
+ });
304
+ } else {
305
+ await github.rest.issues.createComment({
306
+ owner: context.repo.owner,
307
+ repo: context.repo.repo,
308
+ issue_number: context.issue.number,
309
+ body
310
+ });
311
+ }
312
+
313
+ - name: Enforce Verdict
314
+ run: |
315
+ code="\${{ steps.ship.outputs.exit_code }}"
316
+ echo "vibecheck exit code: $code"
317
+ if [ "$code" = "2" ]; then
318
+ echo "::error::BLOCK verdict - deployment blocked"
319
+ exit 1
320
+ fi
321
+ ${options.failOnWarn ? 'if [ "$code" = "1" ]; then echo "::error::WARN verdict (policy: fail-on-warn)"; exit 1; fi' : ''}
322
+ echo "✅ Ship decision passed"
323
+ `;
324
+ }
325
+
326
+ function generateGitLabCI(detection, options = {}) {
327
+ const pm = detection.packageManager;
328
+ const installCmd = pm === "pnpm" ? "pnpm install --frozen-lockfile" :
329
+ pm === "yarn" ? "yarn install --frozen-lockfile" : "npm ci";
330
+
331
+ return `stages:
332
+ - test
333
+ - deploy
334
+
335
+ variables:
336
+ CI: "true"
337
+ NODE_ENV: test
338
+
339
+ vibecheck:
340
+ stage: test
341
+ image: node:20
342
+ cache:
343
+ key: \${CI_COMMIT_REF_SLUG}
344
+ paths:
345
+ - node_modules/
346
+ - .pnpm-store/
347
+ before_script:
348
+ - ${pm === "pnpm" ? "corepack enable && " : ""}${installCmd}
349
+ script:
350
+ - npx vibecheck ctx
351
+ - npx vibecheck ship ${options.failOnWarn ? "--fail-on-warn" : ""}
352
+ artifacts:
353
+ when: always
354
+ paths:
355
+ - .vibecheck/
356
+ expire_in: 30 days
357
+ rules:
358
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
359
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
360
+ `;
361
+ }
362
+
363
+ // ============================================================================
364
+ // TEAM CONFIG TEMPLATES
365
+ // ============================================================================
366
+ function generateTeamConfig(detection, options = {}) {
367
+ const environments = options.environments || ["development", "staging", "production"];
368
+
369
+ return {
370
+ version: "1.0.0",
371
+ team: {
372
+ name: options.teamName || detection.pkg?.name || "unnamed",
373
+ environments,
374
+ },
375
+ policies: {
376
+ development: {
377
+ verdict: { warnAsPass: true, blockAsBlock: true },
378
+ autoFix: { enabled: true, requireApproval: false },
379
+ },
380
+ staging: {
381
+ verdict: { warnAsPass: true, blockAsBlock: true },
382
+ autoFix: { enabled: true, requireApproval: true },
383
+ },
384
+ production: {
385
+ verdict: { warnAsPass: false, blockAsBlock: true },
386
+ autoFix: { enabled: false, requireApproval: true },
387
+ additionalInvariants: ["INV_NO_BYPASS_ENTITLEMENTS"],
388
+ },
389
+ },
390
+ notifications: {
391
+ slack: { webhook: "${SLACK_WEBHOOK_URL}", enabled: false },
392
+ email: { recipients: [], enabled: false },
393
+ },
394
+ reporting: {
395
+ frequency: "weekly",
396
+ recipients: [],
397
+ includeMetrics: true,
398
+ },
399
+ };
400
+ }
401
+
402
+ // ============================================================================
403
+ // MCP SERVER CONFIG
404
+ // ============================================================================
405
+ function generateMCPConfig(detection) {
406
+ return {
407
+ name: "vibecheck",
408
+ version: "1.0.0",
409
+ description: "Vibecheck MCP server for AI agent integration",
410
+ capabilities: {
411
+ tools: true,
412
+ resources: true,
413
+ prompts: true,
414
+ },
415
+ tools: [
416
+ "validate_claim",
417
+ "get_truthpack",
418
+ "get_route_map",
419
+ "verify_auth",
420
+ "check_invariant",
421
+ ],
422
+ security: {
423
+ requireAuth: false,
424
+ allowedOrigins: ["*"],
425
+ },
426
+ };
427
+ }
428
+
429
+ // ============================================================================
430
+ // INVARIANTS FILE
431
+ // ============================================================================
432
+ function generateInvariantsYml(invariants) {
433
+ const lines = ["# vibecheck invariants - ship killers and warnings", ""];
434
+
435
+ const blocks = invariants.filter(id => INVARIANT_DEFINITIONS[id]?.severity === "BLOCK");
436
+ const warns = invariants.filter(id => INVARIANT_DEFINITIONS[id]?.severity === "WARN");
437
+
438
+ if (blocks.length) {
439
+ lines.push("ship_killers:");
440
+ for (const id of blocks) {
441
+ const def = INVARIANT_DEFINITIONS[id];
442
+ lines.push(` - id: ${id}`);
443
+ lines.push(` description: "${def?.description || id}"`);
444
+ lines.push(` category: ${def?.category || "general"}`);
445
+ lines.push("");
446
+ }
447
+ }
448
+
449
+ if (warns.length) {
450
+ lines.push("warnings:");
451
+ for (const id of warns) {
452
+ const def = INVARIANT_DEFINITIONS[id];
453
+ lines.push(` - id: ${id}`);
454
+ lines.push(` description: "${def?.description || id}"`);
455
+ lines.push(` category: ${def?.category || "general"}`);
456
+ lines.push("");
457
+ }
458
+ }
459
+
460
+ return lines.join("\n");
461
+ }
462
+
463
+ // ============================================================================
464
+ // MAIN CONFIG FILE
465
+ // ============================================================================
466
+ function generateVibecheckConfig(detection, options = {}) {
467
+ const primaryFramework = Object.keys(detection.frameworks)[0] || "node";
468
+ const primaryDb = Object.keys(detection.databases)[0];
469
+ const primaryAuth = Object.keys(detection.auth)[0];
470
+ const primaryPayment = Object.keys(detection.payments)[0];
471
+
472
+ return {
473
+ $schema: "https://vibecheck.dev/schemas/config.json",
474
+ version: "2.0.0",
475
+ project: {
476
+ name: detection.pkg?.name || "unnamed",
477
+ framework: primaryFramework,
478
+ packageManager: detection.packageManager,
479
+ },
480
+ detection: {
481
+ frameworks: Object.keys(detection.frameworks),
482
+ databases: Object.keys(detection.databases),
483
+ auth: Object.keys(detection.auth),
484
+ payments: Object.keys(detection.payments),
485
+ ci: Object.keys(detection.ci),
486
+ deploy: Object.keys(detection.deploy),
487
+ testing: Object.keys(detection.testing),
488
+ },
489
+ checks: detection.checks,
490
+ invariants: detection.invariants,
491
+ policy: {
492
+ strict: options.strict || false,
493
+ failOnWarn: options.failOnWarn || false,
494
+ allowlist: {
495
+ domains: [],
496
+ packages: [],
497
+ },
498
+ ignore: {
499
+ paths: [
500
+ "node_modules",
501
+ "__tests__",
502
+ "*.test.*",
503
+ "*.spec.*",
504
+ "**/*.d.ts",
505
+ "**/fixtures/**",
506
+ "**/mocks/**",
507
+ ],
508
+ },
509
+ },
510
+ output: {
511
+ dir: ".vibecheck",
512
+ reports: ["json", "html"],
513
+ badges: true,
514
+ },
515
+ integrations: {
516
+ mcp: { enabled: true },
517
+ ci: Object.keys(detection.ci).length > 0 ? Object.keys(detection.ci)[0] : null,
518
+ },
519
+ };
520
+ }
521
+
522
+ // ============================================================================
523
+ // ENTERPRISE INIT ORCHESTRATOR
524
+ // ============================================================================
525
+ class EnterpriseInit {
526
+ constructor(projectPath, options = {}) {
527
+ this.projectPath = projectPath;
528
+ this.options = options;
529
+ this.detection = null;
530
+ this.created = [];
531
+ this.updated = [];
532
+ this.skipped = [];
533
+ }
534
+
535
+ async run() {
536
+ this.printHeader();
537
+
538
+ // Step 1: Detect everything
539
+ await this.detectProject();
540
+
541
+ if (this.detection.error) {
542
+ console.log(`\n${c.red}✗ ${this.detection.error}${c.reset}\n`);
543
+ return 1;
544
+ }
545
+
546
+ // Step 2: Print detection results
547
+ this.printDetectionResults();
548
+
549
+ // Step 3: Generate configurations
550
+ await this.generateConfigs();
551
+
552
+ // Step 4: Setup CI/CD if requested
553
+ if (this.options.ci) {
554
+ await this.setupCI();
555
+ }
556
+
557
+ // Step 5: Setup compliance if requested
558
+ if (this.options.compliance) {
559
+ await this.setupCompliance();
560
+ }
561
+
562
+ // Step 6: Print summary
563
+ this.printSummary();
564
+
565
+ return 0;
566
+ }
567
+
568
+ printHeader() {
569
+ console.log("");
570
+ console.log(`${c.cyan}╔══════════════════════════════════════════════════════════════════════════╗${c.reset}`);
571
+ console.log(`${c.cyan}║${c.reset} ${c.cyan}║${c.reset}`);
572
+ console.log(`${c.cyan}║${c.reset} ${c.bold}🛡️ VIBECHECK ENTERPRISE INIT${c.reset} ${c.cyan}║${c.reset}`);
573
+ console.log(`${c.cyan}║${c.reset} ${c.dim}Production-grade project configuration${c.reset} ${c.cyan}║${c.reset}`);
574
+ console.log(`${c.cyan}║${c.reset} ${c.cyan}║${c.reset}`);
575
+ console.log(`${c.cyan}╚══════════════════════════════════════════════════════════════════════════╝${c.reset}`);
576
+ console.log("");
577
+ }
578
+
579
+ async detectProject() {
580
+ process.stdout.write(`${c.dim}Analyzing project...${c.reset}`);
581
+ this.detection = detectAll(this.projectPath);
582
+ process.stdout.write(`\r${c.green}✓${c.reset} Project analyzed \n`);
583
+ }
584
+
585
+ printDetectionResults() {
586
+ const d = this.detection;
587
+
588
+ console.log("");
589
+ console.log(`${c.cyan}┌─ Detection Results ──────────────────────────────────────────────────────┐${c.reset}`);
590
+
591
+ // Project info
592
+ console.log(`${c.cyan}│${c.reset}`);
593
+ console.log(`${c.cyan}│${c.reset} ${c.bold}Project:${c.reset} ${d.pkg?.name || "unnamed"} ${c.dim}v${d.pkg?.version || "0.0.0"}${c.reset}`);
594
+ console.log(`${c.cyan}│${c.reset} ${c.bold}Package Manager:${c.reset} ${d.packageManager}`);
595
+ if (d.monorepo.isMonorepo) {
596
+ console.log(`${c.cyan}│${c.reset} ${c.bold}Monorepo:${c.reset} ${c.green}Yes${c.reset}`);
597
+ }
598
+
599
+ // Frameworks
600
+ const frameworks = Object.values(d.frameworks);
601
+ if (frameworks.length) {
602
+ console.log(`${c.cyan}│${c.reset}`);
603
+ console.log(`${c.cyan}│${c.reset} ${c.bold}Frameworks:${c.reset}`);
604
+ for (const fw of frameworks) {
605
+ console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${fw.icon} ${fw.name}`);
606
+ }
607
+ }
608
+
609
+ // Databases
610
+ const databases = Object.values(d.databases);
611
+ if (databases.length) {
612
+ console.log(`${c.cyan}│${c.reset}`);
613
+ console.log(`${c.cyan}│${c.reset} ${c.bold}Databases:${c.reset}`);
614
+ for (const db of databases) {
615
+ console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${db.icon} ${db.name}`);
616
+ }
617
+ }
618
+
619
+ // Auth
620
+ const auth = Object.values(d.auth);
621
+ if (auth.length) {
622
+ console.log(`${c.cyan}│${c.reset}`);
623
+ console.log(`${c.cyan}│${c.reset} ${c.bold}Authentication:${c.reset}`);
624
+ for (const a of auth) {
625
+ console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${a.icon} ${a.name}`);
626
+ }
627
+ }
628
+
629
+ // Payments
630
+ const payments = Object.values(d.payments);
631
+ if (payments.length) {
632
+ console.log(`${c.cyan}│${c.reset}`);
633
+ console.log(`${c.cyan}│${c.reset} ${c.bold}Payments:${c.reset}`);
634
+ for (const p of payments) {
635
+ console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${p.icon} ${p.name}`);
636
+ }
637
+ }
638
+
639
+ // CI/CD
640
+ const ci = Object.values(d.ci);
641
+ if (ci.length) {
642
+ console.log(`${c.cyan}│${c.reset}`);
643
+ console.log(`${c.cyan}│${c.reset} ${c.bold}CI/CD:${c.reset}`);
644
+ for (const c2 of ci) {
645
+ console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${c2.icon} ${c2.name}`);
646
+ }
647
+ }
648
+
649
+ // Deploy
650
+ const deploy = Object.values(d.deploy);
651
+ if (deploy.length) {
652
+ console.log(`${c.cyan}│${c.reset}`);
653
+ console.log(`${c.cyan}│${c.reset} ${c.bold}Deployment:${c.reset}`);
654
+ for (const dp of deploy) {
655
+ console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${dp.icon} ${dp.name}`);
656
+ }
657
+ }
658
+
659
+ // Testing
660
+ const testing = Object.values(d.testing);
661
+ if (testing.length) {
662
+ console.log(`${c.cyan}│${c.reset}`);
663
+ console.log(`${c.cyan}│${c.reset} ${c.bold}Testing:${c.reset}`);
664
+ for (const t of testing) {
665
+ console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${t.icon} ${t.name}`);
666
+ }
667
+ }
668
+
669
+ // Invariants
670
+ console.log(`${c.cyan}│${c.reset}`);
671
+ console.log(`${c.cyan}│${c.reset} ${c.bold}Ship Killers:${c.reset} ${c.magenta}${d.invariants.length} invariants${c.reset}`);
672
+
673
+ console.log(`${c.cyan}│${c.reset}`);
674
+ console.log(`${c.cyan}└───────────────────────────────────────────────────────────────────────────┘${c.reset}`);
675
+ console.log("");
676
+ }
677
+
678
+ async generateConfigs() {
679
+ console.log(`${c.cyan}┌─ Generating Configuration ───────────────────────────────────────────────┐${c.reset}`);
680
+ console.log(`${c.cyan}│${c.reset}`);
681
+
682
+ const tasks = [
683
+ { name: ".vibecheck/config.json", fn: () => this.writeConfig() },
684
+ { name: ".vibecheck/invariants.yml", fn: () => this.writeInvariants() },
685
+ { name: ".vibecheck/security-policy.json", fn: () => this.writeSecurityPolicy() },
686
+ { name: ".vibecheck/schemas/", fn: () => this.writeSchemas() },
687
+ { name: ".gitignore update", fn: () => this.updateGitignore() },
688
+ ];
689
+
690
+ if (this.options.team) {
691
+ tasks.push({ name: ".vibecheck/team.json", fn: () => this.writeTeamConfig() });
692
+ }
693
+
694
+ if (this.options.mcp) {
695
+ tasks.push({ name: ".vibecheck/mcp.json", fn: () => this.writeMCPConfig() });
696
+ }
697
+
698
+ for (const task of tasks) {
699
+ process.stdout.write(`${c.cyan}│${c.reset} ○ ${task.name}...`);
700
+ try {
701
+ const result = await task.fn();
702
+ const status = result === "created" ? `${c.green}created${c.reset}` :
703
+ result === "updated" ? `${c.yellow}updated${c.reset}` :
704
+ `${c.dim}skipped${c.reset}`;
705
+ process.stdout.write(`\r${c.cyan}│${c.reset} ${c.green}✓${c.reset} ${task.name} ${status}\n`);
706
+
707
+ if (result === "created") this.created.push(task.name);
708
+ else if (result === "updated") this.updated.push(task.name);
709
+ else this.skipped.push(task.name);
710
+ } catch (err) {
711
+ process.stdout.write(`\r${c.cyan}│${c.reset} ${c.red}✗${c.reset} ${task.name} ${c.red}${err.message}${c.reset}\n`);
712
+ }
713
+ }
714
+
715
+ console.log(`${c.cyan}│${c.reset}`);
716
+ console.log(`${c.cyan}└───────────────────────────────────────────────────────────────────────────┘${c.reset}`);
717
+ console.log("");
718
+ }
719
+
720
+ writeConfig() {
721
+ const configDir = path.join(this.projectPath, ".vibecheck");
722
+ ensureDir(configDir);
723
+
724
+ const configPath = path.join(configDir, "config.json");
725
+ const config = generateVibecheckConfig(this.detection, this.options);
726
+
727
+ const exists = fs.existsSync(configPath);
728
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf8");
729
+ return exists ? "updated" : "created";
730
+ }
731
+
732
+ writeInvariants() {
733
+ const configDir = path.join(this.projectPath, ".vibecheck");
734
+ ensureDir(configDir);
735
+
736
+ const invPath = path.join(configDir, "invariants.yml");
737
+ const content = generateInvariantsYml(this.detection.invariants);
738
+
739
+ const exists = fs.existsSync(invPath);
740
+ fs.writeFileSync(invPath, content, "utf8");
741
+ return exists ? "updated" : "created";
742
+ }
743
+
744
+ writeSecurityPolicy() {
745
+ const configDir = path.join(this.projectPath, ".vibecheck");
746
+ ensureDir(configDir);
747
+
748
+ const policyPath = path.join(configDir, "security-policy.json");
749
+ const policy = generateSecurityPolicy(this.detection);
750
+
751
+ const exists = fs.existsSync(policyPath);
752
+ fs.writeFileSync(policyPath, JSON.stringify(policy, null, 2), "utf8");
753
+ return exists ? "updated" : "created";
754
+ }
755
+
756
+ writeSchemas() {
757
+ const schemasDir = path.join(this.projectPath, ".vibecheck", "schemas");
758
+ ensureDir(schemasDir);
759
+
760
+ const schemas = {
761
+ "config.schema.json": {
762
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
763
+ "$id": "https://vibecheck.dev/schemas/config.json",
764
+ "title": "Vibecheck Configuration",
765
+ "type": "object",
766
+ },
767
+ "truthpack.schema.json": {
768
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
769
+ "$id": "https://vibecheck.dev/schemas/truthpack.json",
770
+ "title": "Vibecheck Truthpack",
771
+ "type": "object",
772
+ },
773
+ };
774
+
775
+ for (const [name, schema] of Object.entries(schemas)) {
776
+ fs.writeFileSync(path.join(schemasDir, name), JSON.stringify(schema, null, 2), "utf8");
777
+ }
778
+
779
+ return "created";
780
+ }
781
+
782
+ writeTeamConfig() {
783
+ const configDir = path.join(this.projectPath, ".vibecheck");
784
+ ensureDir(configDir);
785
+
786
+ const teamPath = path.join(configDir, "team.json");
787
+ const config = generateTeamConfig(this.detection, this.options);
788
+
789
+ const exists = fs.existsSync(teamPath);
790
+ fs.writeFileSync(teamPath, JSON.stringify(config, null, 2), "utf8");
791
+ return exists ? "updated" : "created";
792
+ }
793
+
794
+ writeMCPConfig() {
795
+ const configDir = path.join(this.projectPath, ".vibecheck");
796
+ ensureDir(configDir);
797
+
798
+ const mcpPath = path.join(configDir, "mcp.json");
799
+ const config = generateMCPConfig(this.detection);
800
+
801
+ const exists = fs.existsSync(mcpPath);
802
+ fs.writeFileSync(mcpPath, JSON.stringify(config, null, 2), "utf8");
803
+ return exists ? "updated" : "created";
804
+ }
805
+
806
+ updateGitignore() {
807
+ const gitignorePath = path.join(this.projectPath, ".gitignore");
808
+ const entries = [
809
+ "",
810
+ "# vibecheck",
811
+ ".vibecheck/truth/",
812
+ ".vibecheck/reality/",
813
+ ".vibecheck/missions/",
814
+ ".vibecheck/prove/",
815
+ ".vibecheck/cache/",
816
+ "",
817
+ ].join("\n");
818
+
819
+ if (fs.existsSync(gitignorePath)) {
820
+ const content = fs.readFileSync(gitignorePath, "utf8");
821
+ if (content.includes(".vibecheck/")) {
822
+ return "skipped";
823
+ }
824
+ fs.appendFileSync(gitignorePath, entries);
825
+ return "updated";
826
+ } else {
827
+ fs.writeFileSync(gitignorePath, entries.trim() + "\n");
828
+ return "created";
829
+ }
830
+ }
831
+
832
+ async setupCI() {
833
+ console.log(`${c.cyan}┌─ CI/CD Integration ──────────────────────────────────────────────────────┐${c.reset}`);
834
+ console.log(`${c.cyan}│${c.reset}`);
835
+
836
+ const ciType = this.options.ci === true ? "github" : this.options.ci;
837
+
838
+ if (ciType === "github" || ciType === "github-actions") {
839
+ const wfDir = path.join(this.projectPath, ".github", "workflows");
840
+ ensureDir(wfDir);
841
+
842
+ const wfPath = path.join(wfDir, "vibecheck.yml");
843
+ const workflow = generateGitHubActionsWorkflow(this.detection, this.options);
844
+
845
+ fs.writeFileSync(wfPath, workflow, "utf8");
846
+ console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} Created .github/workflows/vibecheck.yml`);
847
+ this.created.push(".github/workflows/vibecheck.yml");
848
+ } else if (ciType === "gitlab") {
849
+ const ciPath = path.join(this.projectPath, ".gitlab-ci.vibecheck.yml");
850
+ const config = generateGitLabCI(this.detection, this.options);
851
+
852
+ fs.writeFileSync(ciPath, config, "utf8");
853
+ console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} Created .gitlab-ci.vibecheck.yml`);
854
+ console.log(`${c.cyan}│${c.reset} ${c.dim}Include this in your main .gitlab-ci.yml${c.reset}`);
855
+ this.created.push(".gitlab-ci.vibecheck.yml");
856
+ }
857
+
858
+ console.log(`${c.cyan}│${c.reset}`);
859
+ console.log(`${c.cyan}└───────────────────────────────────────────────────────────────────────────┘${c.reset}`);
860
+ console.log("");
861
+ }
862
+
863
+ async setupCompliance() {
864
+ console.log(`${c.cyan}┌─ Compliance Templates ───────────────────────────────────────────────────┐${c.reset}`);
865
+ console.log(`${c.cyan}│${c.reset}`);
866
+
867
+ const complianceDir = path.join(this.projectPath, ".vibecheck", "compliance");
868
+ ensureDir(complianceDir);
869
+
870
+ const templates = typeof this.options.compliance === "string"
871
+ ? [this.options.compliance]
872
+ : Object.keys(COMPLIANCE_TEMPLATES);
873
+
874
+ for (const key of templates) {
875
+ const template = COMPLIANCE_TEMPLATES[key];
876
+ if (!template) continue;
877
+
878
+ const filePath = path.join(complianceDir, `${key}.json`);
879
+ fs.writeFileSync(filePath, JSON.stringify({
880
+ name: template.name,
881
+ description: template.description,
882
+ policies: template.policies,
883
+ invariants: template.invariants,
884
+ status: "not_started",
885
+ lastAudit: null,
886
+ }, null, 2), "utf8");
887
+
888
+ console.log(`${c.cyan}│${c.reset} ${c.green}✓${c.reset} Created compliance/${key}.json (${template.name})`);
889
+ this.created.push(`compliance/${key}.json`);
890
+ }
891
+
892
+ console.log(`${c.cyan}│${c.reset}`);
893
+ console.log(`${c.cyan}└───────────────────────────────────────────────────────────────────────────┘${c.reset}`);
894
+ console.log("");
895
+ }
896
+
897
+ printSummary() {
898
+ console.log(`${c.green}${c.bold}✓ Enterprise init complete${c.reset}`);
899
+ console.log("");
900
+
901
+ if (this.created.length) {
902
+ console.log(`${c.green}Created:${c.reset} ${this.created.length} files`);
903
+ }
904
+ if (this.updated.length) {
905
+ console.log(`${c.yellow}Updated:${c.reset} ${this.updated.length} files`);
906
+ }
907
+
908
+ console.log("");
909
+ console.log(`${c.cyan}╔══════════════════════════════════════════════════════════════════════════╗${c.reset}`);
910
+ console.log(`${c.cyan}║${c.reset} ${c.bold}Next Steps${c.reset} ${c.cyan}║${c.reset}`);
911
+ console.log(`${c.cyan}╠══════════════════════════════════════════════════════════════════════════╣${c.reset}`);
912
+ console.log(`${c.cyan}║${c.reset} ${c.cyan}║${c.reset}`);
913
+ console.log(`${c.cyan}║${c.reset} ${c.bold}1.${c.reset} Generate truth pack: ${c.cyan}║${c.reset}`);
914
+ console.log(`${c.cyan}║${c.reset} ${c.cyan}vibecheck ctx${c.reset} ${c.cyan}║${c.reset}`);
915
+ console.log(`${c.cyan}║${c.reset} ${c.cyan}║${c.reset}`);
916
+ console.log(`${c.cyan}║${c.reset} ${c.bold}2.${c.reset} Run ship decision: ${c.cyan}║${c.reset}`);
917
+ console.log(`${c.cyan}║${c.reset} ${c.cyan}vibecheck ship${c.reset} ${c.cyan}║${c.reset}`);
918
+ console.log(`${c.cyan}║${c.reset} ${c.cyan}║${c.reset}`);
919
+ console.log(`${c.cyan}║${c.reset} ${c.bold}3.${c.reset} Start MCP server for AI agents: ${c.cyan}║${c.reset}`);
920
+ console.log(`${c.cyan}║${c.reset} ${c.cyan}vibecheck mcp${c.reset} ${c.cyan}║${c.reset}`);
921
+ console.log(`${c.cyan}║${c.reset} ${c.cyan}║${c.reset}`);
922
+ console.log(`${c.cyan}╚══════════════════════════════════════════════════════════════════════════╝${c.reset}`);
923
+ console.log("");
924
+ console.log(`${c.dim}Tip: Run ${c.cyan}vibecheck prove --url http://localhost:3000${c.dim} for full reality verification${c.reset}`);
925
+ console.log("");
926
+ }
927
+ }
928
+
929
+ // ============================================================================
930
+ // EXPORTS
931
+ // ============================================================================
932
+ module.exports = {
933
+ EnterpriseInit,
934
+ generateGitHubActionsWorkflow,
935
+ generateGitLabCI,
936
+ generateSecurityPolicy,
937
+ generateTeamConfig,
938
+ generateVibecheckConfig,
939
+ generateInvariantsYml,
940
+ INVARIANT_DEFINITIONS,
941
+ COMPLIANCE_TEMPLATES,
942
+ };