@viberaven/cli 0.1.0-beta.2 → 0.1.0-beta.3

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 CHANGED
@@ -5,15 +5,21 @@ Launch readiness for Claude Code, Codex, and other coding agents — same missio
5
5
  ## For humans
6
6
 
7
7
  ```bash
8
- npx -y @viberaven/cli@beta login
9
- npx -y @viberaven/cli@beta scan --open
10
- ```
8
+ npx -y @viberaven/cli@beta login
9
+ npx -y @viberaven/cli@beta status
10
+ npx -y @viberaven/cli@beta scan --open
11
+ ```
11
12
 
12
13
  Sign in once, then scan with `--open` to view `.viberaven/report.html` in the browser (same editorial Mission Map skin as the extension). Or run **`viberaven`** with no args for the interactive terminal menu.
13
14
 
14
15
  Uses the **same VibeRaven account and scan quota** as the VS Code extension. **Does not use your `OPENAI_API_KEY`** — scans go through the managed API after login. See [SECURITY.md](./SECURITY.md).
15
16
 
16
- ## For coding agents
17
+ Quota:
18
+
19
+ - Free: 2 lifetime scans
20
+ - Pro: 50 scans per month
21
+
22
+ ## For coding agents
17
23
 
18
24
  Use VibeRaven when the user asks whether an AI-built app is launch-ready, production-ready, or missing auth/database/payments/deployment/security work.
19
25
 
package/dist/cli.js CHANGED
@@ -162,6 +162,7 @@ var require_src = __commonJS({
162
162
  // src/cli.ts
163
163
  var cli_exports = {};
164
164
  __export(cli_exports, {
165
+ buildHelpText: () => buildHelpText,
165
166
  formatScanJsonStdout: () => formatScanJsonStdout,
166
167
  parseArgs: () => parseArgs
167
168
  });
@@ -8582,6 +8583,56 @@ var PANEL_CLIENT_SCRIPT = `
8582
8583
 
8583
8584
 
8584
8585
 
8586
+ function isLockedArea(areaKey) {
8587
+
8588
+ var nodes = document.querySelectorAll('.studio-node');
8589
+
8590
+ for (var i = 0; i < nodes.length; i += 1) {
8591
+
8592
+ if (nodes[i].getAttribute('data-area-key') === areaKey) {
8593
+
8594
+ return nodes[i].getAttribute('data-locked-map') === '1';
8595
+
8596
+ }
8597
+
8598
+ }
8599
+
8600
+ return false;
8601
+
8602
+ }
8603
+
8604
+
8605
+
8606
+ function lockedAreaHtml(label) {
8607
+
8608
+ return '<div class="studio-setup-panel__inner studio-setup-panel__inner--locked">' +
8609
+
8610
+ '<div class="studio-setup-panel__head">' +
8611
+
8612
+ '<div class="studio-setup-panel__title"><strong>Upgrade to Pro</strong><span>Full mission map</span></div>' +
8613
+
8614
+ '</div>' +
8615
+
8616
+ '<section class="studio-setup-actions studio-setup-actions--locked" aria-label="Locked Pro section">' +
8617
+
8618
+ '<div class="studio-setup-actions__head">' +
8619
+
8620
+ '<span class="studio-setup-actions__logo provider-logo" aria-hidden="true">' + logoHtml('', label) + '</span>' +
8621
+
8622
+ '<div class="studio-setup-actions__title"><strong>' + esc(label) + ' is locked on the Free plan</strong><span>Pro-only production area</span></div>' +
8623
+
8624
+ '</div>' +
8625
+
8626
+ '<p class="studio-setup-actions__copy">Free shows App Flow, Frontend, Backend / API, Auth, Database, and Payments. Pro unlocks Deployment, Monitoring, Security, Testing, Landing, and Error Handling.</p>' +
8627
+
8628
+ '</section>' +
8629
+
8630
+ '</div>';
8631
+
8632
+ }
8633
+
8634
+
8635
+
8585
8636
  function render(areaKey) {
8586
8637
 
8587
8638
  var area = areas.find(function (a) { return a.key === areaKey; });
@@ -8598,6 +8649,14 @@ var PANEL_CLIENT_SCRIPT = `
8598
8649
 
8599
8650
  var label = (area && area.label) || LABELS[areaKey] || areaKey;
8600
8651
 
8652
+ if (isLockedArea(areaKey)) {
8653
+
8654
+ panel.innerHTML = lockedAreaHtml(label);
8655
+
8656
+ return;
8657
+
8658
+ }
8659
+
8601
8660
  var missions = (area && area.providerMissions) || [];
8602
8661
 
8603
8662
  var selectedBeforeRender = selectedProviders[areaKey] || '';
@@ -8740,7 +8799,7 @@ var PROVIDER_LOGOS = {
8740
8799
  supabase: '<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#3fcf8e" d="M11.9 1.036c-.015-.986-1.26-1.41-1.874-.637L.764 12.05C-.33 13.427.65 15.455 2.409 15.455h9.579l.113 7.51c.014.985 1.259 1.408 1.873.636l9.262-11.653c1.093-1.375.113-3.403-1.645-3.403h-9.642z"/></svg>',
8741
8800
  clerk: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="m21.47 20.829-2.881-2.881a.572.572 0 0 0-.7-.084 6.854 6.854 0 0 1-7.081 0 .576.576 0 0 0-.7.084l-2.881 2.881a.576.576 0 0 0-.103.69.57.57 0 0 0 .166.186 12 12 0 0 0 14.113 0 .58.58 0 0 0 .239-.423.576.576 0 0 0-.172-.453Zm.002-17.668-2.88 2.88a.569.569 0 0 1-.701.084A6.857 6.857 0 0 0 8.724 8.08a6.862 6.862 0 0 0-1.222 3.692 6.86 6.86 0 0 0 .978 3.764.573.573 0 0 1-.083.699l-2.881 2.88a.567.567 0 0 1-.864-.063A11.993 11.993 0 0 1 6.771 2.7a11.99 11.99 0 0 1 14.637-.405.566.566 0 0 1 .232.418.57.57 0 0 1-.168.448Zm-7.118 12.261a3.427 3.427 0 1 0 0-6.854 3.427 3.427 0 0 0 0 6.854Z"/></svg>',
8742
8801
  authjs: '<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#18c6cf" d="M12 1.4 21 4.9v6.7c0 5.1-3.5 8.7-9 11-5.5-2.3-9-5.9-9-11V4.9l9-3.5Z"/><path fill="#8b2ff5" d="M12 1.4 21 4.9v6.7c0 5.1-3.5 8.7-9 11V1.4Z"/><path fill="#fff7df" d="M12 7a5.2 5.2 0 1 0 0 10.4A5.2 5.2 0 0 0 12 7Z"/><path fill="#ff8a00" d="M10.2 9.6a2.2 2.2 0 0 1 2.9 2.9l3.5 3.5h-2.2v1.5h-1.8V16h-1.4l-1.3-1.3a2.2 2.2 0 0 1 .3-5.1Zm.9 1.8a.7.7 0 1 0 0 1.4.7.7 0 0 0 0-1.4Z"/></svg>',
8743
- auth0: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M21.98 7.448L19.62 0H4.347L2.02 7.448c-1.352 4.312.03 9.206 3.815 12.015L12.007 24l6.157-4.552c3.755-2.81 5.182-7.688 3.815-12.015l-6.16 4.58 2.343 7.45-6.157-4.597-6.158 4.58 2.358-7.433-6.188-4.55 7.63-.045L12.008 0l2.356 7.404 7.615.044z"/></svg>',
8802
+ auth0: '<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#eb5424" d="M21.98 7.448L19.62 0H4.347L2.02 7.448c-1.352 4.312.03 9.206 3.815 12.015L12.007 24l6.157-4.552c3.755-2.81 5.182-7.688 3.815-12.015l-6.16 4.58 2.343 7.45-6.157-4.597-6.158 4.58 2.358-7.433-6.188-4.55 7.63-.045L12.008 0l2.356 7.404 7.615.044z"/></svg>',
8744
8803
  "better-auth": '<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="1.5" y="1.5" width="21" height="21" rx="3" fill="#111827"/><path fill="#fffdf7" d="M5.2 6.2h5.15v4.25H5.2V6.2Zm8.45 0h5.15v4.25h-5.15V6.2Zm-8.45 7.35h5.15v4.25H5.2v-4.25Zm8.45 0h5.15v4.25h-5.15v-4.25Z"/><path fill="#3b82f6" d="M10.35 10.45h3.3v3.1h-3.3v-3.1Z"/></svg>',
8745
8804
  polar: '<svg viewBox="0 0 29 29" aria-hidden="true"><path fill="#0062FF" fill-rule="evenodd" clip-rule="evenodd" d="M9.077 23.057c4.801 3.25 11.328 1.992 14.577-2.808 3.25-4.801 1.993-11.328-2.808-14.578C16.045 2.422 9.519 3.679 6.269 8.48c-3.25 4.801-1.993 11.327 2.808 14.577Zm1.393.086c4.392 2.247 9.963.138 12.444-4.711 2.48-4.848.93-10.6-3.461-12.847-4.392-2.247-9.963-.138-12.443 4.711-2.481 4.848-.932 10.6 3.46 12.847Z"/><path fill="#0062FF" fill-rule="evenodd" clip-rule="evenodd" d="M11.722 24.29c3.965 1.29 8.628-2.118 10.417-7.613 1.788-5.495.024-10.996-3.94-12.286-3.964-1.29-8.628 2.118-10.416 7.613-1.789 5.495-.025 10.995 3.939 12.286Zm1.213-.418c3.355.716 6.982-2.961 8.102-8.212 1.12-5.252-.691-10.089-4.046-10.804-3.356-.716-6.983 2.96-8.103 8.212-1.12 5.251.692 10.088 4.047 10.804Z"/><path fill="#0062FF" fill-rule="evenodd" clip-rule="evenodd" d="M13.854 24.738c2.652.284 5.3-4.14 5.912-9.882.613-5.74-1.04-10.624-3.692-10.907-2.653-.283-5.3 4.141-5.913 9.882-.613 5.741 1.04 10.624 3.693 10.907Zm1.241-1.747c1.92-.031 3.415-3.917 3.34-8.68-.075-4.764-1.693-8.6-3.612-8.57-1.92.03-3.415 3.916-3.34 8.68.076 4.763 1.693 8.6 3.612 8.57Z"/></svg>',
8746
8805
  "lemon-squeezy": '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="m7.4916 10.835 2.3748-6.5114a3.1497 3.1497 0 0 0-.065-2.3418C9.0315.183 6.9427-.398 5.2928.265 3.643.929 2.71 2.4348 3.512 4.3046l2.8197 6.5615c.219.509.97.489 1.16-.03m1.6798 1.0969 6.5334-2.7758c2.1699-.9219 2.7218-3.6907 1.022-5.2905l-.068-.063c-1.6669-1.5469-4.4217-1.002-5.3706 1.0359L8.3566 11.135c-.234.503.295 1.0199.8159.7979m.373.87 6.6454-2.5119c2.2078-.8349 4.6206.745 4.5886 3.0398l-.002.09c-.048 2.2358-2.3938 3.7376-4.5536 2.9467l-6.6724-2.4418a.595.595 0 0 1-.006-1.1229m-.386 1.9269 6.4375 2.9767a3.2997 3.2997 0 0 1 1.6658 1.6989c.769 1.7998-.283 3.6396-1.9328 4.3016-1.6499.662-3.4097.235-4.2097-1.6359l-2.8027-6.5694c-.217-.509.328-1.009.8419-.772"/></svg>',
@@ -9124,19 +9183,42 @@ var CATEGORY_META = [
9124
9183
  { key: "landing", label: "Landing / Onboarding" },
9125
9184
  { key: "errorHandling", label: "Error Handling" }
9126
9185
  ];
9186
+ var DEFAULT_FREE_UNLOCKED_MAP_KEYS = [
9187
+ "appFlow",
9188
+ "frontend",
9189
+ "backend",
9190
+ "auth",
9191
+ "database",
9192
+ "payments"
9193
+ ];
9194
+ var DEFAULT_FREE_UNLOCKED_MAP_KEY_SET = new Set(DEFAULT_FREE_UNLOCKED_MAP_KEYS);
9195
+ function isMapCategoryUnlocked(artifact, categoryKey) {
9196
+ if (artifact.plan === "pro" || artifact.usage?.plan === "pro") {
9197
+ return true;
9198
+ }
9199
+ if (!artifact.plan && !artifact.usage) {
9200
+ return true;
9201
+ }
9202
+ const keys = Array.isArray(artifact.usage?.unlockedMapCategoryKeys) && artifact.usage.unlockedMapCategoryKeys.length > 0 ? artifact.usage.unlockedMapCategoryKeys : DEFAULT_FREE_UNLOCKED_MAP_KEYS;
9203
+ return keys.includes(categoryKey) && DEFAULT_FREE_UNLOCKED_MAP_KEY_SET.has(categoryKey);
9204
+ }
9127
9205
  function gapCountForArea(artifact, areaKey) {
9128
9206
  return artifact.gaps.filter((g2) => g2.primaryMapCategory === areaKey).length;
9129
9207
  }
9130
9208
  function defaultAreaKey(artifact) {
9131
- const fromGap = artifact.gaps[0]?.primaryMapCategory;
9209
+ const fromGap = artifact.gaps.find((gap) => isMapCategoryUnlocked(artifact, gap.primaryMapCategory))?.primaryMapCategory;
9132
9210
  if (fromGap) {
9133
9211
  return fromGap;
9134
9212
  }
9135
9213
  const areas = artifact.missionGraph.areas ?? [];
9136
- if (areas.some((a) => a.key === "frontend")) {
9214
+ const fromArea = areas.find((area) => isMapCategoryUnlocked(artifact, area.key))?.key;
9215
+ if (fromArea) {
9216
+ return fromArea;
9217
+ }
9218
+ if (isMapCategoryUnlocked(artifact, "frontend")) {
9137
9219
  return "frontend";
9138
9220
  }
9139
- return areas[0]?.key ?? "frontend";
9221
+ return CATEGORY_META.find((meta) => isMapCategoryUnlocked(artifact, meta.key))?.key ?? "frontend";
9140
9222
  }
9141
9223
  function providerLabelForArea(artifact, areaKey, mission, selectedOverride) {
9142
9224
  if (selectedOverride) {
@@ -9192,18 +9274,24 @@ function buildNodeHtml(artifact, meta, selectedAreaKey) {
9192
9274
  (check) => check.evidenceSource === "provider" || check.evidenceSource === "mcp" || check.evidenceClass === "mcp-verifier" || check.status === "needs-connection" || check.status === "unknown"
9193
9275
  ).length ?? 0;
9194
9276
  const modelGaps = gapCountForArea(artifact, meta.key);
9277
+ const unlocked = isMapCategoryUnlocked(artifact, meta.key);
9195
9278
  const stateClass = modelGaps > 0 ? " studio-node--critical" : openChecks > 0 ? " studio-node--warning" : area ? " studio-node--in-project" : "";
9196
9279
  const selectedClass = selectedAreaKey === meta.key ? " studio-node--selected" : "";
9280
+ const lockedClass = unlocked ? "" : " studio-node--locked";
9197
9281
  const metaText = modelGaps > 0 ? `${modelGaps} stack fix${modelGaps === 1 ? "" : "es"}` : repoOpenChecks > 0 ? `${repoOpenChecks} stack fix${repoOpenChecks === 1 ? "" : "es"}` : providerOpenChecks > 0 ? "Live check" : `${readiness}% health`;
9198
9282
  const logoClass = providerLogoClass(logoProvider, mission?.key, mission?.providerLabel);
9199
9283
  const logoInner = providerLogoHtml(logoProvider, providerLabel3, mission?.key, mission?.providerLabel);
9200
9284
  const gapBadge = modelGaps > 0 ? `<span class="studio-node__raven-badge" role="presentation">Gap ${modelGaps}</span>` : "";
9201
- return `<button type="button" class="studio-node studio-node--${escapeHtml(meta.key)} provider-logo${logoClass}${stateClass}${selectedClass}" data-area-key="${escapeHtml(meta.key)}" aria-label="${escapeHtml(meta.label)}, ${escapeHtml(providerLabel3)}, ${escapeHtml(metaText)}">
9285
+ const lockBadge = unlocked ? "" : '<span class="studio-node__lock">Pro</span>';
9286
+ const lockedAttrs = unlocked ? "" : ' data-locked-map="1" title="Pro only - this section is locked on the Free plan"';
9287
+ const lockedAria = unlocked ? "" : ", Pro only. Upgrade to unlock";
9288
+ return `<button type="button" class="studio-node studio-node--${escapeHtml(meta.key)} provider-logo${logoClass}${stateClass}${selectedClass}${lockedClass}" data-area-key="${escapeHtml(meta.key)}"${lockedAttrs} aria-label="${escapeHtml(meta.label)}, ${escapeHtml(providerLabel3)}, ${escapeHtml(metaText)}${lockedAria}">
9202
9289
  <span class="studio-node__logo provider-logo${logoClass}" aria-hidden="true">${logoInner}</span>
9203
9290
  <span class="studio-node__title">${escapeHtml(meta.label)}</span>
9204
9291
  <span class="studio-node__provider">${escapeHtml(providerLabel3)}</span>
9205
9292
  <span class="studio-node__meta">${escapeHtml(metaText)}</span>
9206
9293
  ${gapBadge}
9294
+ ${lockBadge}
9207
9295
  </button>`;
9208
9296
  }
9209
9297
  function generateReportHtml(artifact) {
@@ -10139,7 +10227,7 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
10139
10227
  var import_picocolors3 = __toESM(require_picocolors());
10140
10228
 
10141
10229
  // src/version.ts
10142
- var VERSION = "0.1.0-beta.2";
10230
+ var VERSION = "0.1.0-beta.3";
10143
10231
 
10144
10232
  // src/tui/runInteractive.ts
10145
10233
  async function formatStatusLine() {
@@ -10331,6 +10419,18 @@ async function runInteractiveSession(startDir = process.cwd()) {
10331
10419
  }
10332
10420
 
10333
10421
  // src/cli.ts
10422
+ function buildHelpText() {
10423
+ return `First-time terminal flow:
10424
+
10425
+ npx -y @viberaven/cli@beta login
10426
+ npx -y @viberaven/cli@beta status
10427
+ npx -y @viberaven/cli@beta scan --open
10428
+
10429
+ Quota:
10430
+
10431
+ Free: 2 lifetime scans
10432
+ Pro: 50 scans per month`;
10433
+ }
10334
10434
  function printHelp() {
10335
10435
  console.log(`viberaven ${VERSION} \u2014 launch readiness for AI-built apps
10336
10436
 
@@ -10386,6 +10486,7 @@ Security:
10386
10486
  CLI scans use VibeRaven login \u2014 not OPENAI_API_KEY. See packages/cli/SECURITY.md.
10387
10487
 
10388
10488
  `);
10489
+ console.log(buildHelpText());
10389
10490
  }
10390
10491
  function parseArgs(argv) {
10391
10492
  const flags = {};
@@ -10654,6 +10755,7 @@ if (require.main === module) {
10654
10755
  }
10655
10756
  // Annotate the CommonJS export names for ESM import in node:
10656
10757
  0 && (module.exports = {
10758
+ buildHelpText,
10657
10759
  formatScanJsonStdout,
10658
10760
  parseArgs
10659
10761
  });