@viberaven/cli 1.0.6 → 1.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.
- package/README.md +10 -38
- package/assets/report/station.css +146 -9
- package/assets/report/station.js +106 -22
- package/dist/cli.js +2244 -1604
- package/dist/cli.js.map +4 -4
- package/dist/report/station.css +146 -9
- package/dist/report/station.js +106 -22
- package/fixtures/demo-saas/.env.example +3 -0
- package/fixtures/demo-saas/app/api/stripe/webhook/route.ts +12 -0
- package/fixtures/demo-saas/package.json +11 -0
- package/fixtures/demo-saas/supabase/migrations/0001_init.sql +6 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -28,16 +28,13 @@ If running from the `viberaven` monorepo root, run:
|
|
|
28
28
|
node packages/cli/dist/cli.js --agent-mode
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
Then read artifacts in this order:
|
|
32
|
-
|
|
33
|
-
1. `.viberaven/agent-tasklist.md`
|
|
34
|
-
2. `.viberaven/gate-result.json`
|
|
35
|
-
3. `.viberaven/context-map.json`
|
|
36
|
-
4. `.viberaven/agent-summary.md`
|
|
37
|
-
5. `.viberaven/launch-playbook.md`
|
|
38
|
-
6. `.viberaven/launch-plan.json`
|
|
39
|
-
7. `.viberaven/launch-tasklist.md`
|
|
40
|
-
8. `.viberaven/provider-actions.json`
|
|
31
|
+
Then read artifacts in this order:
|
|
32
|
+
|
|
33
|
+
1. `.viberaven/agent-tasklist.md`
|
|
34
|
+
2. `.viberaven/gate-result.json`
|
|
35
|
+
3. `.viberaven/context-map.json`
|
|
36
|
+
4. `.viberaven/agent-summary.md`
|
|
37
|
+
5. `.viberaven/launch-playbook.md`
|
|
41
38
|
|
|
42
39
|
Fix one repo-code gap, then run:
|
|
43
40
|
|
|
@@ -54,34 +51,9 @@ npx -y viberaven prompt --gap <id>
|
|
|
54
51
|
npx -y viberaven audit --vercel-supabase
|
|
55
52
|
```
|
|
56
53
|
|
|
57
|
-
Provider dashboard checks are not cleared by repo-code edits. Billing/product configuration, DNS, webhooks, credentials, quotas, and live provider verification must be completed or verified in the provider dashboard or through read-only provider evidence.
|
|
58
|
-
|
|
59
|
-
##
|
|
60
|
-
|
|
61
|
-
The canonical agent command is still:
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
npx -y viberaven --agent-mode
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
Agent mode now behaves like a launch autopilot for AI-built apps:
|
|
68
|
-
|
|
69
|
-
1. Detect the launch recipe, such as Next.js + Supabase + Vercel.
|
|
70
|
-
2. Queue safe local launch-gap fixes first.
|
|
71
|
-
3. Protect scan usage by batching local fixes before verify.
|
|
72
|
-
4. Guide Vercel preview deploy before production promotion.
|
|
73
|
-
5. Guide Supabase, Stripe, analytics, and monitoring setup through MCP/plugin/CLI/dashboard/manual fallback actions.
|
|
74
|
-
6. Require approval before provider writes, database migrations, secret writes, preview deploys, and production deploys.
|
|
75
|
-
|
|
76
|
-
Optional permission mode:
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
npx -y viberaven --agent-mode --launch-mode ask
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
Modes: `manual`, `ask`, `safe`, `full`. The default is `ask`.
|
|
83
|
-
|
|
84
|
-
## Production Copilot Loop
|
|
54
|
+
Provider dashboard checks are not cleared by repo-code edits. Billing/product configuration, DNS, webhooks, credentials, quotas, and live provider verification must be completed or verified in the provider dashboard or through read-only provider evidence.
|
|
55
|
+
|
|
56
|
+
## Production Copilot Loop
|
|
85
57
|
|
|
86
58
|
VibeRaven runs a batch-disciplined loop until the production gate clears. Do not stop at "scan complete."
|
|
87
59
|
|
|
@@ -5402,15 +5402,152 @@ body.station-results-active .studio-node__logo:not(.provider-logo--brand) svg pa
|
|
|
5402
5402
|
background: rgba(3, 8, 13, 0.94);
|
|
5403
5403
|
}
|
|
5404
5404
|
|
|
5405
|
-
.studio-top-rail__build,
|
|
5406
|
-
.studio-top-rail__brand {
|
|
5407
|
-
color: rgba(63, 224, 244, 0.9);
|
|
5408
|
-
}
|
|
5409
|
-
|
|
5410
|
-
.studio-
|
|
5411
|
-
|
|
5412
|
-
grid-template-columns:
|
|
5413
|
-
|
|
5405
|
+
.studio-top-rail__build,
|
|
5406
|
+
.studio-top-rail__brand {
|
|
5407
|
+
color: rgba(63, 224, 244, 0.9);
|
|
5408
|
+
}
|
|
5409
|
+
|
|
5410
|
+
.studio-launch-hero {
|
|
5411
|
+
display: grid;
|
|
5412
|
+
grid-template-columns: minmax(0, 1fr) minmax(180px, 0.78fr);
|
|
5413
|
+
gap: 14px;
|
|
5414
|
+
align-items: stretch;
|
|
5415
|
+
padding: 12px 14px;
|
|
5416
|
+
border-bottom: 1px solid rgba(32, 214, 237, 0.16);
|
|
5417
|
+
background:
|
|
5418
|
+
radial-gradient(circle at 8% 20%, rgba(63, 224, 244, 0.15), transparent 34%),
|
|
5419
|
+
linear-gradient(135deg, rgba(5, 18, 28, 0.96), rgba(2, 8, 13, 0.98));
|
|
5420
|
+
}
|
|
5421
|
+
|
|
5422
|
+
.studio-launch-hero__main,
|
|
5423
|
+
.studio-launch-hero__next {
|
|
5424
|
+
display: grid;
|
|
5425
|
+
min-width: 0;
|
|
5426
|
+
align-content: center;
|
|
5427
|
+
}
|
|
5428
|
+
|
|
5429
|
+
.studio-launch-hero__main {
|
|
5430
|
+
gap: 8px;
|
|
5431
|
+
}
|
|
5432
|
+
|
|
5433
|
+
.studio-launch-hero__next {
|
|
5434
|
+
gap: 7px;
|
|
5435
|
+
padding: 10px 11px;
|
|
5436
|
+
border: 1px solid rgba(63, 224, 244, 0.16);
|
|
5437
|
+
border-radius: 8px;
|
|
5438
|
+
background: rgba(1, 6, 10, 0.62);
|
|
5439
|
+
}
|
|
5440
|
+
|
|
5441
|
+
.studio-launch-hero__wordmark {
|
|
5442
|
+
margin: 0;
|
|
5443
|
+
color: rgba(232, 250, 255, 0.92);
|
|
5444
|
+
font-size: 11px;
|
|
5445
|
+
font-weight: 900;
|
|
5446
|
+
letter-spacing: 0.14em;
|
|
5447
|
+
text-transform: uppercase;
|
|
5448
|
+
}
|
|
5449
|
+
|
|
5450
|
+
.studio-launch-hero__decision {
|
|
5451
|
+
display: inline-flex;
|
|
5452
|
+
align-items: center;
|
|
5453
|
+
width: max-content;
|
|
5454
|
+
max-width: 100%;
|
|
5455
|
+
min-height: 30px;
|
|
5456
|
+
padding: 6px 11px;
|
|
5457
|
+
border: 1px solid rgba(239, 68, 68, 0.35);
|
|
5458
|
+
border-radius: 999px;
|
|
5459
|
+
background: rgba(40, 12, 12, 0.46);
|
|
5460
|
+
color: #fecaca;
|
|
5461
|
+
font-size: 12px;
|
|
5462
|
+
font-weight: 900;
|
|
5463
|
+
letter-spacing: 0.08em;
|
|
5464
|
+
line-height: 1;
|
|
5465
|
+
text-transform: uppercase;
|
|
5466
|
+
overflow-wrap: anywhere;
|
|
5467
|
+
}
|
|
5468
|
+
|
|
5469
|
+
.studio-launch-hero__decision--warning {
|
|
5470
|
+
border-color: rgba(245, 158, 11, 0.42);
|
|
5471
|
+
background: rgba(40, 28, 8, 0.5);
|
|
5472
|
+
color: #fde68a;
|
|
5473
|
+
}
|
|
5474
|
+
|
|
5475
|
+
.studio-launch-hero__decision--clear {
|
|
5476
|
+
border-color: rgba(74, 222, 128, 0.38);
|
|
5477
|
+
background: rgba(8, 32, 18, 0.52);
|
|
5478
|
+
color: #bbf7d0;
|
|
5479
|
+
}
|
|
5480
|
+
|
|
5481
|
+
.studio-launch-hero__gauge {
|
|
5482
|
+
height: 8px;
|
|
5483
|
+
overflow: hidden;
|
|
5484
|
+
border-radius: 999px;
|
|
5485
|
+
background: rgba(255, 255, 255, 0.08);
|
|
5486
|
+
}
|
|
5487
|
+
|
|
5488
|
+
.studio-launch-hero__gauge-fill {
|
|
5489
|
+
display: block;
|
|
5490
|
+
height: 100%;
|
|
5491
|
+
border-radius: inherit;
|
|
5492
|
+
background: #ef4444;
|
|
5493
|
+
transition: width 0.35s var(--vr-ease-out);
|
|
5494
|
+
}
|
|
5495
|
+
|
|
5496
|
+
.studio-launch-hero__gauge-fill--warning {
|
|
5497
|
+
background: #f59e0b;
|
|
5498
|
+
}
|
|
5499
|
+
|
|
5500
|
+
.studio-launch-hero__gauge-fill--clear {
|
|
5501
|
+
background: #4ade80;
|
|
5502
|
+
}
|
|
5503
|
+
|
|
5504
|
+
.studio-launch-hero__next-label {
|
|
5505
|
+
color: rgba(232, 250, 255, 0.58);
|
|
5506
|
+
font-size: 9px;
|
|
5507
|
+
font-weight: 900;
|
|
5508
|
+
letter-spacing: 0.12em;
|
|
5509
|
+
line-height: 1;
|
|
5510
|
+
text-transform: uppercase;
|
|
5511
|
+
}
|
|
5512
|
+
|
|
5513
|
+
.studio-launch-hero__next strong {
|
|
5514
|
+
min-width: 0;
|
|
5515
|
+
color: rgba(248, 252, 255, 0.95);
|
|
5516
|
+
font-size: 12px;
|
|
5517
|
+
font-weight: 850;
|
|
5518
|
+
line-height: 1.25;
|
|
5519
|
+
overflow-wrap: anywhere;
|
|
5520
|
+
}
|
|
5521
|
+
|
|
5522
|
+
.studio-launch-hero__verify {
|
|
5523
|
+
justify-self: start;
|
|
5524
|
+
min-height: 30px;
|
|
5525
|
+
padding: 0 10px;
|
|
5526
|
+
border: 1px solid rgba(63, 224, 244, 0.32);
|
|
5527
|
+
border-radius: 7px;
|
|
5528
|
+
background: rgba(63, 224, 244, 0.1);
|
|
5529
|
+
color: rgba(232, 250, 255, 0.92);
|
|
5530
|
+
font: 800 10px/1 var(--font-ui);
|
|
5531
|
+
letter-spacing: 0.07em;
|
|
5532
|
+
text-transform: uppercase;
|
|
5533
|
+
}
|
|
5534
|
+
|
|
5535
|
+
.studio-launch-hero__verify:hover,
|
|
5536
|
+
.studio-launch-hero__verify:focus-visible {
|
|
5537
|
+
border-color: rgba(63, 224, 244, 0.52);
|
|
5538
|
+
background: rgba(63, 224, 244, 0.16);
|
|
5539
|
+
}
|
|
5540
|
+
|
|
5541
|
+
@media (max-width: 620px) {
|
|
5542
|
+
.studio-launch-hero {
|
|
5543
|
+
grid-template-columns: minmax(0, 1fr);
|
|
5544
|
+
}
|
|
5545
|
+
}
|
|
5546
|
+
|
|
5547
|
+
.studio-workspace {
|
|
5548
|
+
position: relative;
|
|
5549
|
+
grid-template-columns: 52px minmax(0, 1fr);
|
|
5550
|
+
}
|
|
5414
5551
|
|
|
5415
5552
|
.studio-nav-rail {
|
|
5416
5553
|
border-right-color: rgba(32, 214, 237, 0.14);
|
package/assets/report/station.js
CHANGED
|
@@ -6670,18 +6670,99 @@ function applyScanStage(stage) {
|
|
|
6670
6670
|
}
|
|
6671
6671
|
}
|
|
6672
6672
|
|
|
6673
|
-
function setTextById(id, text) {
|
|
6674
|
-
const element = document.getElementById(id);
|
|
6675
|
-
if (element) {
|
|
6676
|
-
element.textContent = String(text || '');
|
|
6677
|
-
}
|
|
6678
|
-
}
|
|
6679
|
-
|
|
6680
|
-
function
|
|
6681
|
-
const
|
|
6682
|
-
if (
|
|
6683
|
-
return;
|
|
6684
|
-
}
|
|
6673
|
+
function setTextById(id, text) {
|
|
6674
|
+
const element = document.getElementById(id);
|
|
6675
|
+
if (element) {
|
|
6676
|
+
element.textContent = String(text || '');
|
|
6677
|
+
}
|
|
6678
|
+
}
|
|
6679
|
+
|
|
6680
|
+
function normalizeLaunchHeroDecision(value) {
|
|
6681
|
+
const raw = readString(value).toLowerCase();
|
|
6682
|
+
if (raw === 'clear') {
|
|
6683
|
+
return 'CLEAR';
|
|
6684
|
+
}
|
|
6685
|
+
if (raw === 'warning' || raw === 'warn') {
|
|
6686
|
+
return 'WARNING';
|
|
6687
|
+
}
|
|
6688
|
+
if (raw === 'blocked' || raw === 'block' || raw === 'not_clear' || raw === 'needs_work' || raw === 'fail' || raw === 'failed') {
|
|
6689
|
+
return 'BLOCKED';
|
|
6690
|
+
}
|
|
6691
|
+
return '';
|
|
6692
|
+
}
|
|
6693
|
+
|
|
6694
|
+
function resolveLaunchHeroDecision(payload, score, gaps) {
|
|
6695
|
+
const explicitDecision = isRecord(payload)
|
|
6696
|
+
? normalizeLaunchHeroDecision(payload.decision) ||
|
|
6697
|
+
normalizeLaunchHeroDecision(payload.gateStatus) ||
|
|
6698
|
+
normalizeLaunchHeroDecision(payload.status) ||
|
|
6699
|
+
(isRecord(payload.productionGate) ? normalizeLaunchHeroDecision(payload.productionGate.status) : '') ||
|
|
6700
|
+
(isRecord(payload.gateResult)
|
|
6701
|
+
? normalizeLaunchHeroDecision(payload.gateResult.status) ||
|
|
6702
|
+
(isRecord(payload.gateResult.gate) ? normalizeLaunchHeroDecision(payload.gateResult.gate.status) : '')
|
|
6703
|
+
: '')
|
|
6704
|
+
: '';
|
|
6705
|
+
if (explicitDecision) {
|
|
6706
|
+
return explicitDecision;
|
|
6707
|
+
}
|
|
6708
|
+
|
|
6709
|
+
const gapCount = Array.isArray(gaps) ? gaps.length : 0;
|
|
6710
|
+
if (Array.isArray(gaps) && gaps.some(function (gap) { return isRecord(gap) && readString(gap.severity).toLowerCase() === 'critical'; })) {
|
|
6711
|
+
return 'BLOCKED';
|
|
6712
|
+
}
|
|
6713
|
+
if (gapCount > 0) {
|
|
6714
|
+
return 'WARNING';
|
|
6715
|
+
}
|
|
6716
|
+
if (score >= 90 && gapCount === 0) {
|
|
6717
|
+
return 'CLEAR';
|
|
6718
|
+
}
|
|
6719
|
+
if (score >= 70) {
|
|
6720
|
+
return 'WARNING';
|
|
6721
|
+
}
|
|
6722
|
+
return 'BLOCKED';
|
|
6723
|
+
}
|
|
6724
|
+
|
|
6725
|
+
function resolveLaunchHeroNextAction(decision, gaps) {
|
|
6726
|
+
const firstGap = Array.isArray(gaps) && isRecord(gaps[0]) ? gaps[0] : null;
|
|
6727
|
+
const firstTitle = firstGap ? readString(firstGap.title) : '';
|
|
6728
|
+
if (firstTitle) {
|
|
6729
|
+
return firstTitle;
|
|
6730
|
+
}
|
|
6731
|
+
if (decision === 'CLEAR') {
|
|
6732
|
+
return 'Share the VibeRaven proof card.';
|
|
6733
|
+
}
|
|
6734
|
+
if (decision === 'WARNING') {
|
|
6735
|
+
return 'Run verify after applying the remaining fixes.';
|
|
6736
|
+
}
|
|
6737
|
+
return 'Run a scan to map production gaps.';
|
|
6738
|
+
}
|
|
6739
|
+
|
|
6740
|
+
function updateLaunchHero(decision, score, nextAction) {
|
|
6741
|
+
const normalizedDecision = decision === 'CLEAR' || decision === 'WARNING' ? decision : 'BLOCKED';
|
|
6742
|
+
const normalizedScore = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
|
|
6743
|
+
const toneClass = normalizedDecision === 'CLEAR'
|
|
6744
|
+
? 'clear'
|
|
6745
|
+
: normalizedDecision === 'WARNING'
|
|
6746
|
+
? 'warning'
|
|
6747
|
+
: 'blocked';
|
|
6748
|
+
const decisionEl = document.getElementById('studio-launch-decision');
|
|
6749
|
+
if (decisionEl) {
|
|
6750
|
+
decisionEl.className = 'studio-launch-hero__decision studio-launch-hero__decision--' + toneClass;
|
|
6751
|
+
decisionEl.textContent = (normalizedDecision === 'CLEAR' ? '\u25c6 ' : '\u25c7 ') + normalizedDecision;
|
|
6752
|
+
}
|
|
6753
|
+
const gaugeFill = document.getElementById('studio-launch-gauge-fill');
|
|
6754
|
+
if (gaugeFill) {
|
|
6755
|
+
gaugeFill.className = 'studio-launch-hero__gauge-fill studio-launch-hero__gauge-fill--' + toneClass;
|
|
6756
|
+
gaugeFill.style.width = normalizedScore + '%';
|
|
6757
|
+
}
|
|
6758
|
+
setTextById('studio-launch-next-action', nextAction || resolveLaunchHeroNextAction(normalizedDecision, []));
|
|
6759
|
+
}
|
|
6760
|
+
|
|
6761
|
+
function setResultsBar(score) {
|
|
6762
|
+
const bar = document.getElementById('mc-results-bar');
|
|
6763
|
+
if (!bar) {
|
|
6764
|
+
return;
|
|
6765
|
+
}
|
|
6685
6766
|
bar.style.width = score + '%';
|
|
6686
6767
|
bar.setAttribute('aria-valuenow', String(score));
|
|
6687
6768
|
bar.classList.remove('mc-bar-fill--amber', 'mc-bar-fill--green');
|
|
@@ -6747,13 +6828,14 @@ function renderMissionControl(payload, options) {
|
|
|
6747
6828
|
}
|
|
6748
6829
|
clearProductionChrome();
|
|
6749
6830
|
setSection('spec-update', null);
|
|
6750
|
-
if (specNotes instanceof HTMLElement) {
|
|
6751
|
-
specNotes.hidden = true;
|
|
6752
|
-
}
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6831
|
+
if (specNotes instanceof HTMLElement) {
|
|
6832
|
+
specNotes.hidden = true;
|
|
6833
|
+
}
|
|
6834
|
+
updateLaunchHero('BLOCKED', 0, 'Fix the scan failure, then run verify.');
|
|
6835
|
+
announceMissionControlReadout(payload, 0, true);
|
|
6836
|
+
showMcState('results');
|
|
6837
|
+
return;
|
|
6838
|
+
}
|
|
6757
6839
|
|
|
6758
6840
|
// Success path — new schema
|
|
6759
6841
|
if (mcResults instanceof HTMLElement) {
|
|
@@ -6776,9 +6858,11 @@ function renderMissionControl(payload, options) {
|
|
|
6776
6858
|
mainBar.setAttribute('aria-valuenow', String(score));
|
|
6777
6859
|
mainBar.classList.remove('mc-bar-fill--amber', 'mc-bar-fill--green');
|
|
6778
6860
|
}
|
|
6779
|
-
|
|
6780
|
-
const gaps = Array.isArray(payload.gaps) ? payload.gaps : [];
|
|
6781
|
-
const
|
|
6861
|
+
|
|
6862
|
+
const gaps = Array.isArray(payload.gaps) ? payload.gaps : [];
|
|
6863
|
+
const launchDecision = resolveLaunchHeroDecision(payload, score, gaps);
|
|
6864
|
+
updateLaunchHero(launchDecision, score, resolveLaunchHeroNextAction(launchDecision, gaps));
|
|
6865
|
+
const fullSummary = typeof payload.summary === 'string' ? payload.summary.replace(/\s+/g, ' ').trim() : '';
|
|
6782
6866
|
/* Cap only for pathological payload size; normal summaries show in full in the panel. */
|
|
6783
6867
|
const maxSummary = 4000;
|
|
6784
6868
|
const summary = fullSummary.length > maxSummary ? fullSummary.slice(0, maxSummary - 1).replace(/\s+\S*$/, '') + '\u2026' : fullSummary;
|