@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.
- package/README.md +60 -33
- package/bin/registry.js +319 -34
- package/bin/runners/CLI_REFACTOR_SUMMARY.md +229 -0
- package/bin/runners/REPORT_AUDIT.md +64 -0
- package/bin/runners/lib/entitlements-v2.js +97 -28
- package/bin/runners/lib/entitlements.js +3 -6
- package/bin/runners/lib/init-wizard.js +1 -1
- package/bin/runners/lib/report-engine.js +459 -280
- package/bin/runners/lib/report-html.js +1154 -1423
- package/bin/runners/lib/report-output.js +187 -0
- package/bin/runners/lib/report-templates.js +848 -850
- package/bin/runners/lib/scan-output.js +545 -0
- package/bin/runners/lib/server-usage.js +0 -12
- package/bin/runners/lib/ship-output.js +641 -0
- package/bin/runners/lib/status-output.js +253 -0
- package/bin/runners/lib/terminal-ui.js +853 -0
- package/bin/runners/runCheckpoint.js +502 -0
- package/bin/runners/runContracts.js +105 -0
- package/bin/runners/runExport.js +93 -0
- package/bin/runners/runFix.js +31 -24
- package/bin/runners/runInit.js +377 -112
- package/bin/runners/runInstall.js +1 -5
- package/bin/runners/runLabs.js +3 -3
- package/bin/runners/runPolish.js +2452 -0
- package/bin/runners/runProve.js +2 -2
- package/bin/runners/runReport.js +251 -200
- package/bin/runners/runRuntime.js +110 -0
- package/bin/runners/runScan.js +477 -379
- package/bin/runners/runSecurity.js +92 -0
- package/bin/runners/runShip.js +137 -207
- package/bin/runners/runStatus.js +16 -68
- package/bin/runners/utils.js +5 -5
- package/bin/vibecheck.js +25 -11
- package/mcp-server/index.js +150 -18
- package/mcp-server/package.json +2 -2
- package/mcp-server/premium-tools.js +13 -13
- package/mcp-server/tier-auth.js +292 -27
- package/mcp-server/vibecheck-tools.js +9 -9
- package/package.json +1 -1
- package/bin/runners/runClaimVerifier.js +0 -483
- package/bin/runners/runContextCompiler.js +0 -385
- package/bin/runners/runGate.js +0 -17
- package/bin/runners/runInitGha.js +0 -164
- package/bin/runners/runInteractive.js +0 -388
- package/bin/runners/runMdc.js +0 -204
- package/bin/runners/runMissionGenerator.js +0 -282
- package/bin/runners/runTruthpack.js +0 -636
package/bin/runners/runInit.js
CHANGED
|
@@ -461,15 +461,25 @@ function printNextSteps(options = {}) {
|
|
|
461
461
|
printSection('NEXT STEPS', ICONS.arrow);
|
|
462
462
|
console.log();
|
|
463
463
|
|
|
464
|
-
const steps = [
|
|
465
|
-
{ num: 1, cmd: 'vibecheck scan', desc: 'Run your first scan' },
|
|
466
|
-
{ num: 2, cmd: 'vibecheck ship', desc: 'Check if ready to ship' },
|
|
467
|
-
];
|
|
464
|
+
const steps = [];
|
|
468
465
|
|
|
469
|
-
if (options.
|
|
470
|
-
steps.push(
|
|
466
|
+
if (options.mode === 'connect') {
|
|
467
|
+
steps.push(
|
|
468
|
+
{ num: 1, cmd: 'vibecheck scan', desc: 'Run baseline scan' },
|
|
469
|
+
{ num: 2, cmd: 'vibecheck checkpoint --save', desc: 'Save baseline for comparison' },
|
|
470
|
+
{ num: 3, cmd: 'git push', desc: 'CI will run automatically' },
|
|
471
|
+
);
|
|
471
472
|
} else {
|
|
472
|
-
steps.push(
|
|
473
|
+
steps.push(
|
|
474
|
+
{ num: 1, cmd: 'vibecheck scan', desc: 'Run your first scan' },
|
|
475
|
+
{ num: 2, cmd: 'vibecheck ship', desc: 'Check if ready to ship' },
|
|
476
|
+
);
|
|
477
|
+
|
|
478
|
+
if (options.hasCI) {
|
|
479
|
+
steps.push({ num: 3, cmd: 'git push', desc: 'CI will run automatically' });
|
|
480
|
+
} else {
|
|
481
|
+
steps.push({ num: 3, cmd: 'vibecheck init --connect', desc: 'Add GitHub integration [STARTER]' });
|
|
482
|
+
}
|
|
473
483
|
}
|
|
474
484
|
|
|
475
485
|
for (const step of steps) {
|
|
@@ -530,14 +540,18 @@ function printComplianceInfo(complianceType) {
|
|
|
530
540
|
function printHelp() {
|
|
531
541
|
console.log(BANNER_FULL);
|
|
532
542
|
console.log(`
|
|
533
|
-
${c.bold}Usage:${c.reset} vibecheck init [options]
|
|
543
|
+
${c.bold}Usage:${c.reset} vibecheck init [mode] [options]
|
|
534
544
|
|
|
535
|
-
${c.bold}
|
|
545
|
+
${c.bold}MODES${c.reset}
|
|
546
|
+
${colors.success}--local${c.reset} ${c.green}[FREE]${c.reset} Full local setup (default)
|
|
547
|
+
Creates truthpack, contracts, MDC/IDE rules
|
|
548
|
+
${colors.accent}--connect${c.reset} ${c.cyan}[STARTER]${c.reset} + GitHub Actions, PR comments, dashboard sync
|
|
536
549
|
|
|
537
550
|
${c.bold}Basic Options:${c.reset}
|
|
538
551
|
${colors.accent}--path, -p <dir>${c.reset} Project path ${c.dim}(default: current directory)${c.reset}
|
|
539
552
|
${colors.accent}--quick, -q${c.reset} Skip wizard, use defaults
|
|
540
553
|
${colors.accent}--git-hooks${c.reset} Install git pre-push hook
|
|
554
|
+
${colors.accent}--json${c.reset} Output results as JSON
|
|
541
555
|
${colors.accent}--help, -h${c.reset} Show this help
|
|
542
556
|
|
|
543
557
|
${colors.enterprise}${c.bold}Enterprise Options:${c.reset}
|
|
@@ -563,38 +577,29 @@ function printHelp() {
|
|
|
563
577
|
${colors.accent}--mcp${c.reset} Generate MCP server config
|
|
564
578
|
${colors.accent}--strict${c.reset} Enable strict mode
|
|
565
579
|
|
|
566
|
-
${c.bold}Created Files:${c.reset}
|
|
580
|
+
${c.bold}Created Files (--local):${c.reset}
|
|
567
581
|
${c.dim}.vibecheck/config.json${c.reset} Main configuration
|
|
568
|
-
${c.dim}.vibecheck/
|
|
569
|
-
${c.dim}.vibecheck/
|
|
570
|
-
${c.dim}.
|
|
571
|
-
${c.dim}.
|
|
572
|
-
${c.dim}.github/workflows/vibecheck.yml${c.reset} GitHub Actions
|
|
573
|
-
|
|
574
|
-
${c.bold}Detection Includes:${c.reset}
|
|
575
|
-
${colors.framework}Frameworks${c.reset} Next.js, Remix, Nuxt, SvelteKit, Fastify, Express
|
|
576
|
-
${colors.database}Databases${c.reset} Prisma, Drizzle, Mongoose, Supabase, Firebase
|
|
577
|
-
${colors.auth}Auth${c.reset} NextAuth, Clerk, Auth0, Lucia, Passport
|
|
578
|
-
${colors.payment}Payments${c.reset} Stripe, Lemon Squeezy, Paddle
|
|
579
|
-
${colors.ci}CI/CD${c.reset} GitHub Actions, GitLab CI, CircleCI
|
|
580
|
-
${colors.deploy}Deploy${c.reset} Vercel, Netlify, Railway, Docker, K8s
|
|
581
|
-
${colors.testing}Testing${c.reset} Jest, Vitest, Playwright, Cypress
|
|
582
|
+
${c.dim}.vibecheck/truthpack.json${c.reset} Routes, env, auth, billing truth
|
|
583
|
+
${c.dim}.vibecheck/contracts/${c.reset} Contract definitions
|
|
584
|
+
${c.dim}.cursor/rules/*.mdc${c.reset} Cursor IDE rules
|
|
585
|
+
${c.dim}.windsurf/rules.md${c.reset} Windsurf IDE rules
|
|
582
586
|
|
|
583
|
-
${c.bold}
|
|
584
|
-
${c.dim}
|
|
585
|
-
vibecheck
|
|
587
|
+
${c.bold}Additional Files (--connect):${c.reset}
|
|
588
|
+
${c.dim}.github/workflows/vibecheck.yml${c.reset} GitHub Actions workflow
|
|
589
|
+
${c.dim}.github/workflows/vibecheck-pr.yml${c.reset} PR check workflow
|
|
586
590
|
|
|
587
|
-
|
|
588
|
-
|
|
591
|
+
${c.bold}Examples:${c.reset}
|
|
592
|
+
${c.dim}# Full local setup (default)${c.reset}
|
|
593
|
+
vibecheck init --local
|
|
589
594
|
|
|
590
|
-
${c.dim}#
|
|
591
|
-
vibecheck init --
|
|
595
|
+
${c.dim}# Local + GitHub integration${c.reset}
|
|
596
|
+
vibecheck init --connect
|
|
592
597
|
|
|
593
|
-
${c.dim}#
|
|
594
|
-
vibecheck init --
|
|
598
|
+
${c.dim}# Quick setup${c.reset}
|
|
599
|
+
vibecheck init --quick
|
|
595
600
|
|
|
596
|
-
${c.dim}#
|
|
597
|
-
vibecheck init --
|
|
601
|
+
${c.dim}# Enterprise with compliance${c.reset}
|
|
602
|
+
vibecheck init --enterprise --soc2
|
|
598
603
|
`);
|
|
599
604
|
}
|
|
600
605
|
|
|
@@ -608,6 +613,10 @@ function parseArgs(args) {
|
|
|
608
613
|
gitHooks: false,
|
|
609
614
|
help: false,
|
|
610
615
|
quick: false,
|
|
616
|
+
json: false,
|
|
617
|
+
// Mode flags (--local is default, --connect requires STARTER)
|
|
618
|
+
local: false,
|
|
619
|
+
connect: false,
|
|
611
620
|
// Enterprise options
|
|
612
621
|
enterprise: false,
|
|
613
622
|
ci: false,
|
|
@@ -626,6 +635,11 @@ function parseArgs(args) {
|
|
|
626
635
|
if (a === "--git-hooks") out.gitHooks = true;
|
|
627
636
|
if (a === "--help" || a === "-h") out.help = true;
|
|
628
637
|
if (a === "--quick" || a === "-q") out.quick = true;
|
|
638
|
+
if (a === "--json") out.json = true;
|
|
639
|
+
|
|
640
|
+
// Mode flags
|
|
641
|
+
if (a === "--local" || a === "-l") out.local = true;
|
|
642
|
+
if (a === "--connect" || a === "-c") out.connect = true;
|
|
629
643
|
|
|
630
644
|
// Enterprise flags
|
|
631
645
|
if (a === "--enterprise" || a === "-e") out.enterprise = true;
|
|
@@ -661,8 +675,15 @@ function parseArgs(args) {
|
|
|
661
675
|
out.ci = true;
|
|
662
676
|
out.team = true;
|
|
663
677
|
out.mcp = true;
|
|
678
|
+
out.connect = true;
|
|
664
679
|
}
|
|
665
680
|
}
|
|
681
|
+
|
|
682
|
+
// Default to --local if neither mode specified
|
|
683
|
+
if (!out.local && !out.connect) {
|
|
684
|
+
out.local = true;
|
|
685
|
+
}
|
|
686
|
+
|
|
666
687
|
return out;
|
|
667
688
|
}
|
|
668
689
|
|
|
@@ -670,6 +691,236 @@ function parseArgs(args) {
|
|
|
670
691
|
// MAIN INIT FUNCTION
|
|
671
692
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
672
693
|
|
|
694
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
695
|
+
// LOCAL MODE SETUP - Full local initialization
|
|
696
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
697
|
+
|
|
698
|
+
async function runLocalSetup(targetDir, projectName, opts, filesCreated) {
|
|
699
|
+
printSection('LOCAL SETUP', ICONS.setup);
|
|
700
|
+
console.log();
|
|
701
|
+
|
|
702
|
+
const vibecheckDir = path.join(targetDir, ".vibecheck");
|
|
703
|
+
|
|
704
|
+
// 1. Create .vibecheck/ directory structure
|
|
705
|
+
const dirs = [
|
|
706
|
+
vibecheckDir,
|
|
707
|
+
path.join(vibecheckDir, "results"),
|
|
708
|
+
path.join(vibecheckDir, "reports"),
|
|
709
|
+
path.join(vibecheckDir, "contracts"),
|
|
710
|
+
path.join(vibecheckDir, "missions"),
|
|
711
|
+
path.join(vibecheckDir, "checkpoints"),
|
|
712
|
+
path.join(vibecheckDir, "runs"),
|
|
713
|
+
];
|
|
714
|
+
|
|
715
|
+
for (const dir of dirs) {
|
|
716
|
+
if (!fs.existsSync(dir)) {
|
|
717
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
printSetupStep('.vibecheck/', 'success', 'directory structure created');
|
|
721
|
+
filesCreated.push('.vibecheck/');
|
|
722
|
+
|
|
723
|
+
// 2. Create config.json
|
|
724
|
+
const configPath = path.join(vibecheckDir, "config.json");
|
|
725
|
+
if (!fs.existsSync(configPath)) {
|
|
726
|
+
const config = {
|
|
727
|
+
version: "2.0.0",
|
|
728
|
+
project: projectName,
|
|
729
|
+
createdAt: new Date().toISOString(),
|
|
730
|
+
checks: ["routes", "env", "auth", "security"],
|
|
731
|
+
output: ".vibecheck",
|
|
732
|
+
policy: {
|
|
733
|
+
allowlist: { domains: [], packages: [] },
|
|
734
|
+
ignore: { paths: ["node_modules", "__tests__", "*.test.*", "*.spec.*"] },
|
|
735
|
+
},
|
|
736
|
+
thresholds: {
|
|
737
|
+
minScore: 70,
|
|
738
|
+
maxBlockers: 0,
|
|
739
|
+
maxWarnings: 10,
|
|
740
|
+
},
|
|
741
|
+
};
|
|
742
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
743
|
+
printSetupStep('config.json', 'success', 'configuration created');
|
|
744
|
+
filesCreated.push('.vibecheck/config.json');
|
|
745
|
+
} else {
|
|
746
|
+
printSetupStep('config.json', 'exists', 'already exists');
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// 3. Generate truthpack
|
|
750
|
+
startSpinner('Building truthpack...', colors.accent);
|
|
751
|
+
try {
|
|
752
|
+
const { runCtx } = require("./runCtx");
|
|
753
|
+
await runCtx(["build", "--path", targetDir, "--quiet"]);
|
|
754
|
+
stopSpinner('Truthpack generated', true);
|
|
755
|
+
filesCreated.push('.vibecheck/truthpack.json');
|
|
756
|
+
} catch (e) {
|
|
757
|
+
stopSpinner('Truthpack generation failed (will retry on scan)', false);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// 4. Generate contracts
|
|
761
|
+
const contractsDir = path.join(vibecheckDir, "contracts");
|
|
762
|
+
|
|
763
|
+
// Routes contract
|
|
764
|
+
const routeContractPath = path.join(contractsDir, "routes.contract.json");
|
|
765
|
+
if (!fs.existsSync(routeContractPath)) {
|
|
766
|
+
const routeContract = {
|
|
767
|
+
version: "1.0.0",
|
|
768
|
+
generatedAt: new Date().toISOString(),
|
|
769
|
+
routes: [],
|
|
770
|
+
description: "Route contract - populated by scan",
|
|
771
|
+
};
|
|
772
|
+
fs.writeFileSync(routeContractPath, JSON.stringify(routeContract, null, 2));
|
|
773
|
+
printSetupStep('routes.contract.json', 'success', 'route contract created');
|
|
774
|
+
filesCreated.push('.vibecheck/contracts/routes.contract.json');
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// Env contract
|
|
778
|
+
const envContractPath = path.join(contractsDir, "env.contract.json");
|
|
779
|
+
if (!fs.existsSync(envContractPath)) {
|
|
780
|
+
const envContract = {
|
|
781
|
+
version: "1.0.0",
|
|
782
|
+
generatedAt: new Date().toISOString(),
|
|
783
|
+
required: [],
|
|
784
|
+
optional: [],
|
|
785
|
+
description: "Environment contract - populated by scan",
|
|
786
|
+
};
|
|
787
|
+
fs.writeFileSync(envContractPath, JSON.stringify(envContract, null, 2));
|
|
788
|
+
printSetupStep('env.contract.json', 'success', 'env contract created');
|
|
789
|
+
filesCreated.push('.vibecheck/contracts/env.contract.json');
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// 5. Generate IDE rules (MDC for Cursor, rules for others)
|
|
793
|
+
startSpinner('Generating IDE rules...', colors.accent);
|
|
794
|
+
try {
|
|
795
|
+
const { runContext } = require("./runContext");
|
|
796
|
+
await runContext(["--path", targetDir, "--quiet"]);
|
|
797
|
+
stopSpinner('IDE rules generated', true);
|
|
798
|
+
filesCreated.push('.cursor/rules/', '.windsurf/', '.github/copilot-instructions.md');
|
|
799
|
+
} catch (e) {
|
|
800
|
+
stopSpinner('IDE rules skipped (run vibecheck context later)', false);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// 6. Create .vibecheckrc at project root
|
|
804
|
+
const rcPath = path.join(targetDir, ".vibecheckrc.json");
|
|
805
|
+
if (!fs.existsSync(rcPath)) {
|
|
806
|
+
const rc = {
|
|
807
|
+
extends: ".vibecheck/config.json",
|
|
808
|
+
tier: "free",
|
|
809
|
+
};
|
|
810
|
+
fs.writeFileSync(rcPath, JSON.stringify(rc, null, 2));
|
|
811
|
+
printSetupStep('.vibecheckrc.json', 'success', 'root config created');
|
|
812
|
+
filesCreated.push('.vibecheckrc.json');
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
// 7. Update .gitignore
|
|
816
|
+
const gitignorePath = path.join(targetDir, ".gitignore");
|
|
817
|
+
if (fs.existsSync(gitignorePath)) {
|
|
818
|
+
let gitignore = fs.readFileSync(gitignorePath, "utf-8");
|
|
819
|
+
const additions = [];
|
|
820
|
+
if (!gitignore.includes(".vibecheck/results/")) additions.push(".vibecheck/results/");
|
|
821
|
+
if (!gitignore.includes(".vibecheck/runs/")) additions.push(".vibecheck/runs/");
|
|
822
|
+
if (!gitignore.includes(".vibecheck/checkpoints/")) additions.push(".vibecheck/checkpoints/");
|
|
823
|
+
|
|
824
|
+
if (additions.length > 0) {
|
|
825
|
+
gitignore += `\n# vibecheck (generated outputs)\n${additions.join("\n")}\n`;
|
|
826
|
+
fs.writeFileSync(gitignorePath, gitignore);
|
|
827
|
+
printSetupStep('.gitignore', 'success', 'updated with vibecheck paths');
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
return filesCreated;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
835
|
+
// CONNECT MODE SETUP - GitHub integration
|
|
836
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
837
|
+
|
|
838
|
+
async function runConnectSetup(targetDir, projectName, opts, filesCreated) {
|
|
839
|
+
// Check entitlement
|
|
840
|
+
const entitlements = require("./lib/entitlements-v2");
|
|
841
|
+
const access = await entitlements.enforce("init.connect", { silent: true });
|
|
842
|
+
|
|
843
|
+
if (!access.allowed) {
|
|
844
|
+
console.log();
|
|
845
|
+
console.log(` ${colors.warning}${ICONS.warning}${c.reset} ${c.bold}--connect requires STARTER plan${c.reset}`);
|
|
846
|
+
console.log(` ${c.dim}Upgrade at: https://vibecheckai.dev/pricing${c.reset}`);
|
|
847
|
+
console.log();
|
|
848
|
+
console.log(` ${c.dim}Local setup completed. Run 'vibecheck init --connect' after upgrading.${c.reset}`);
|
|
849
|
+
return filesCreated;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
printSection('GITHUB INTEGRATION', ICONS.ci);
|
|
853
|
+
console.log();
|
|
854
|
+
|
|
855
|
+
// 1. Create GitHub workflows directory
|
|
856
|
+
const workflowsDir = path.join(targetDir, ".github", "workflows");
|
|
857
|
+
if (!fs.existsSync(workflowsDir)) {
|
|
858
|
+
fs.mkdirSync(workflowsDir, { recursive: true });
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// 2. Copy main workflow template
|
|
862
|
+
const mainWorkflowPath = path.join(workflowsDir, "vibecheck.yml");
|
|
863
|
+
if (!fs.existsSync(mainWorkflowPath)) {
|
|
864
|
+
// Read template
|
|
865
|
+
const templatePath = path.join(__dirname, "..", "..", "templates", "github-actions", "vibecheck.yml");
|
|
866
|
+
if (fs.existsSync(templatePath)) {
|
|
867
|
+
fs.copyFileSync(templatePath, mainWorkflowPath);
|
|
868
|
+
printSetupStep('vibecheck.yml', 'success', 'main workflow created');
|
|
869
|
+
filesCreated.push('.github/workflows/vibecheck.yml');
|
|
870
|
+
} else {
|
|
871
|
+
// Inline template as fallback
|
|
872
|
+
const workflow = `# Vibecheck CI/CD Workflow
|
|
873
|
+
name: Vibecheck
|
|
874
|
+
on:
|
|
875
|
+
push:
|
|
876
|
+
branches: [main, master]
|
|
877
|
+
pull_request:
|
|
878
|
+
|
|
879
|
+
jobs:
|
|
880
|
+
vibecheck:
|
|
881
|
+
runs-on: ubuntu-latest
|
|
882
|
+
steps:
|
|
883
|
+
- uses: actions/checkout@v4
|
|
884
|
+
- uses: actions/setup-node@v4
|
|
885
|
+
with:
|
|
886
|
+
node-version: '20'
|
|
887
|
+
- run: npm ci
|
|
888
|
+
- run: npx vibecheck scan --json > .vibecheck/results/scan.json
|
|
889
|
+
- run: npx vibecheck ship --ci
|
|
890
|
+
`;
|
|
891
|
+
fs.writeFileSync(mainWorkflowPath, workflow);
|
|
892
|
+
printSetupStep('vibecheck.yml', 'success', 'main workflow created');
|
|
893
|
+
filesCreated.push('.github/workflows/vibecheck.yml');
|
|
894
|
+
}
|
|
895
|
+
} else {
|
|
896
|
+
printSetupStep('vibecheck.yml', 'exists', 'already exists');
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
// 3. Copy PR workflow template
|
|
900
|
+
const prWorkflowPath = path.join(workflowsDir, "vibecheck-pr.yml");
|
|
901
|
+
if (!fs.existsSync(prWorkflowPath)) {
|
|
902
|
+
const templatePath = path.join(__dirname, "..", "..", "templates", "github-actions", "vibecheck-pr.yml");
|
|
903
|
+
if (fs.existsSync(templatePath)) {
|
|
904
|
+
fs.copyFileSync(templatePath, prWorkflowPath);
|
|
905
|
+
printSetupStep('vibecheck-pr.yml', 'success', 'PR workflow created');
|
|
906
|
+
filesCreated.push('.github/workflows/vibecheck-pr.yml');
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
// 4. Provide setup instructions
|
|
911
|
+
console.log();
|
|
912
|
+
console.log(` ${colors.info}${ICONS.info}${c.reset} ${c.bold}GitHub Setup Required:${c.reset}`);
|
|
913
|
+
console.log(` 1. Add ${c.cyan}VIBECHECK_API_KEY${c.reset} to repository secrets`);
|
|
914
|
+
console.log(` 2. Push to trigger first workflow run`);
|
|
915
|
+
console.log();
|
|
916
|
+
|
|
917
|
+
return filesCreated;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
921
|
+
// MAIN INIT FUNCTION
|
|
922
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
923
|
+
|
|
673
924
|
async function runInit(args) {
|
|
674
925
|
const opts = parseArgs(args);
|
|
675
926
|
|
|
@@ -678,14 +929,20 @@ async function runInit(args) {
|
|
|
678
929
|
return 0;
|
|
679
930
|
}
|
|
680
931
|
|
|
932
|
+
// --quick mode delegates to runInstall (zero-friction onboarding)
|
|
933
|
+
if (opts.quick) {
|
|
934
|
+
const { runInstall } = require("./runInstall");
|
|
935
|
+
return await runInstall(args);
|
|
936
|
+
}
|
|
937
|
+
|
|
681
938
|
const targetDir = path.resolve(opts.path);
|
|
682
939
|
const projectName = path.basename(targetDir);
|
|
683
940
|
|
|
684
941
|
// Enterprise mode - comprehensive setup
|
|
685
942
|
const useEnterprise = opts.enterprise || opts.ci || opts.compliance ||
|
|
686
|
-
opts.team || opts.mcp || opts.detect
|
|
943
|
+
opts.team || opts.mcp || opts.detect;
|
|
687
944
|
|
|
688
|
-
if (EnterpriseInit && useEnterprise) {
|
|
945
|
+
if (EnterpriseInit && useEnterprise && !opts.local && !opts.connect) {
|
|
689
946
|
printBanner();
|
|
690
947
|
printEnterpriseHeader(opts);
|
|
691
948
|
|
|
@@ -706,112 +963,120 @@ async function runInit(args) {
|
|
|
706
963
|
|
|
707
964
|
startSpinner('Detecting project configuration...', colors.accent);
|
|
708
965
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
966
|
+
try {
|
|
967
|
+
const { detectAll } = require("./lib/enterprise-detect");
|
|
968
|
+
const detection = detectAll(targetDir);
|
|
969
|
+
stopSpinner('Detection complete', true);
|
|
970
|
+
printDetectionResults(detection);
|
|
971
|
+
console.log();
|
|
972
|
+
console.log(` ${c.dim}Full JSON output:${c.reset}`);
|
|
973
|
+
console.log(JSON.stringify(detection, null, 2));
|
|
974
|
+
} catch (e) {
|
|
975
|
+
stopSpinner('Detection failed', false);
|
|
976
|
+
console.log(` ${colors.error}Error:${c.reset} ${e.message}`);
|
|
977
|
+
}
|
|
719
978
|
return 0;
|
|
720
979
|
}
|
|
721
980
|
|
|
722
|
-
// Use wizard for interactive setup (unless --quick)
|
|
723
|
-
if (InitWizard && !opts.quick) {
|
|
724
|
-
const wizard = new InitWizard(targetDir, opts);
|
|
725
|
-
return await wizard.run();
|
|
726
|
-
}
|
|
727
|
-
|
|
728
981
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
729
|
-
//
|
|
982
|
+
// NEW: --local and --connect modes
|
|
730
983
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
731
984
|
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
985
|
+
if (!opts.json) {
|
|
986
|
+
printBanner();
|
|
987
|
+
|
|
988
|
+
const mode = opts.connect ? 'Local + Connect' : 'Local';
|
|
989
|
+
const tierBadge = opts.connect ? `${c.cyan}[STARTER]${c.reset}` : `${c.green}[FREE]${c.reset}`;
|
|
990
|
+
|
|
991
|
+
console.log(` ${c.dim}Project:${c.reset} ${c.bold}${projectName}${c.reset}`);
|
|
992
|
+
console.log(` ${c.dim}Path:${c.reset} ${targetDir}`);
|
|
993
|
+
console.log(` ${c.dim}Mode:${c.reset} ${colors.accent}${mode}${c.reset} ${tierBadge}`);
|
|
994
|
+
}
|
|
740
995
|
|
|
741
|
-
|
|
996
|
+
let filesCreated = [];
|
|
997
|
+
const result = {
|
|
998
|
+
success: true,
|
|
999
|
+
project: projectName,
|
|
1000
|
+
path: targetDir,
|
|
1001
|
+
mode: opts.connect ? 'connect' : 'local',
|
|
1002
|
+
filesCreated: [],
|
|
1003
|
+
errors: [],
|
|
1004
|
+
};
|
|
742
1005
|
|
|
743
|
-
//
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
},
|
|
754
|
-
};
|
|
755
|
-
fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
|
|
756
|
-
printSetupStep('.vibecheckrc', 'success', 'configuration created');
|
|
757
|
-
filesCreated.push('.vibecheckrc');
|
|
758
|
-
} else {
|
|
759
|
-
printSetupStep('.vibecheckrc', 'exists', 'already exists');
|
|
1006
|
+
// Always run local setup first
|
|
1007
|
+
if (opts.local || opts.connect) {
|
|
1008
|
+
try {
|
|
1009
|
+
filesCreated = await runLocalSetup(targetDir, projectName, opts, filesCreated);
|
|
1010
|
+
} catch (e) {
|
|
1011
|
+
result.errors.push({ step: 'local', error: e.message });
|
|
1012
|
+
if (!opts.json) {
|
|
1013
|
+
console.log(` ${colors.error}${ICONS.cross}${c.reset} Local setup error: ${e.message}`);
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
760
1016
|
}
|
|
761
|
-
|
|
762
|
-
//
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
1017
|
+
|
|
1018
|
+
// Run connect setup if requested
|
|
1019
|
+
if (opts.connect) {
|
|
1020
|
+
try {
|
|
1021
|
+
filesCreated = await runConnectSetup(targetDir, projectName, opts, filesCreated);
|
|
1022
|
+
} catch (e) {
|
|
1023
|
+
result.errors.push({ step: 'connect', error: e.message });
|
|
1024
|
+
if (!opts.json) {
|
|
1025
|
+
console.log(` ${colors.error}${ICONS.cross}${c.reset} Connect setup error: ${e.message}`);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
770
1028
|
}
|
|
771
|
-
|
|
772
|
-
//
|
|
1029
|
+
|
|
1030
|
+
// Git hooks if requested
|
|
773
1031
|
if (opts.gitHooks) {
|
|
774
1032
|
const huskyDir = path.join(targetDir, ".husky");
|
|
775
1033
|
if (!fs.existsSync(huskyDir)) {
|
|
776
1034
|
fs.mkdirSync(huskyDir, { recursive: true });
|
|
777
1035
|
}
|
|
778
|
-
|
|
779
1036
|
const prePushHook = `#!/usr/bin/env sh
|
|
780
1037
|
. "$(dirname -- "$0")/_/husky.sh"
|
|
781
1038
|
|
|
782
1039
|
echo "🚦 Running vibecheck gate..."
|
|
783
|
-
npx vibecheck
|
|
1040
|
+
npx vibecheck ship --ci
|
|
784
1041
|
|
|
785
1042
|
if [ $? -ne 0 ]; then
|
|
786
1043
|
echo "❌ Push blocked: Gate failed!"
|
|
787
1044
|
exit 1
|
|
788
1045
|
fi
|
|
789
1046
|
`;
|
|
790
|
-
fs.writeFileSync(path.join(huskyDir, "pre-push"), prePushHook, {
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
1047
|
+
fs.writeFileSync(path.join(huskyDir, "pre-push"), prePushHook, { mode: 0o755 });
|
|
1048
|
+
if (!opts.json) {
|
|
1049
|
+
printSetupStep('.husky/pre-push', 'success', 'git hook installed');
|
|
1050
|
+
}
|
|
794
1051
|
filesCreated.push('.husky/pre-push');
|
|
795
1052
|
}
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
fs.writeFileSync(gitignorePath, gitignore);
|
|
804
|
-
printSetupStep('.gitignore', 'success', 'added .vibecheck/');
|
|
805
|
-
} else {
|
|
806
|
-
printSetupStep('.gitignore', 'skipped', 'already configured');
|
|
807
|
-
}
|
|
1053
|
+
|
|
1054
|
+
result.filesCreated = filesCreated;
|
|
1055
|
+
|
|
1056
|
+
// JSON output
|
|
1057
|
+
if (opts.json) {
|
|
1058
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1059
|
+
return result.errors.length > 0 ? 1 : 0;
|
|
808
1060
|
}
|
|
809
|
-
|
|
1061
|
+
|
|
810
1062
|
// Success card
|
|
811
|
-
|
|
1063
|
+
const mode = opts.connect ? 'Local + Connect' : 'Local Setup';
|
|
1064
|
+
printSuccessCard(projectName, mode, filesCreated.length);
|
|
1065
|
+
|
|
1066
|
+
// Init summary
|
|
1067
|
+
printSection('INIT SUMMARY', ICONS.check);
|
|
1068
|
+
console.log();
|
|
1069
|
+
console.log(` ${colors.success}${ICONS.check}${c.reset} .vibecheck/ structure created`);
|
|
1070
|
+
console.log(` ${colors.success}${ICONS.check}${c.reset} Truthpack generated`);
|
|
1071
|
+
console.log(` ${colors.success}${ICONS.check}${c.reset} Contracts initialized`);
|
|
1072
|
+
console.log(` ${colors.success}${ICONS.check}${c.reset} IDE rules generated`);
|
|
1073
|
+
if (opts.connect) {
|
|
1074
|
+
console.log(` ${colors.success}${ICONS.check}${c.reset} GitHub Actions workflows installed`);
|
|
1075
|
+
}
|
|
1076
|
+
console.log();
|
|
812
1077
|
|
|
813
1078
|
// Next steps
|
|
814
|
-
printNextSteps({ hasCI:
|
|
1079
|
+
printNextSteps({ hasCI: opts.connect, mode: opts.connect ? 'connect' : 'local' });
|
|
815
1080
|
|
|
816
1081
|
return 0;
|
|
817
1082
|
}
|
|
@@ -264,11 +264,7 @@ async function runInstall(argsOrContext = {}) {
|
|
|
264
264
|
console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} ${ICONS.file} ${colors.accent}package.json${c.reset} ${c.dim}(${changedScripts.join(', ')})${c.reset}`);
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
-
//
|
|
268
|
-
const runner = pm === "pnpm" ? "pnpm" : pm === "yarn" ? "yarn" : "npm run";
|
|
269
|
-
printSection('NEXT STEP', ICONS.arrow);
|
|
270
|
-
console.log();
|
|
271
|
-
console.log(` ${colors.accent}${runner} vibecheck:ship${c.reset}`);
|
|
267
|
+
// Installation complete
|
|
272
268
|
console.log();
|
|
273
269
|
console.log(` ${colors.shipGreen}${ICONS.sparkle}${c.reset} Installation complete!`);
|
|
274
270
|
console.log();
|
package/bin/runners/runLabs.js
CHANGED
|
@@ -29,9 +29,9 @@ const LABS_FEATURES = {
|
|
|
29
29
|
runner: () => require("./runLaunch").runLaunch,
|
|
30
30
|
},
|
|
31
31
|
"dashboard": {
|
|
32
|
-
status: "
|
|
33
|
-
description: "Real-time monitoring dashboard",
|
|
34
|
-
|
|
32
|
+
status: "stub",
|
|
33
|
+
description: "Real-time monitoring dashboard (coming soon)",
|
|
34
|
+
eta: "Q2 2025",
|
|
35
35
|
},
|
|
36
36
|
"permissions": {
|
|
37
37
|
status: "experimental",
|