@viberaven/cli 1.2.3 → 1.3.0

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 (73) hide show
  1. package/AGENTS.md +42 -157
  2. package/README.md +73 -33
  3. package/SECURITY.md +52 -53
  4. package/assets/report/assets/provider-authjs.svg +5 -5
  5. package/assets/report/assets/provider-aws.svg +5 -5
  6. package/assets/report/assets/provider-logrocket.svg +4 -4
  7. package/assets/report/assets/viberaven-favicon.png +0 -0
  8. package/assets/report/station.js +2 -2
  9. package/dist/cli.js +744 -639
  10. package/dist/cli.js.map +4 -4
  11. package/dist/report/assets/provider-authjs.svg +5 -5
  12. package/dist/report/assets/provider-aws.svg +5 -5
  13. package/dist/report/assets/provider-logrocket.svg +4 -4
  14. package/dist/report/assets/viberaven-favicon.png +0 -0
  15. package/dist/report/station.js +2 -2
  16. package/package.json +73 -75
  17. package/templates/AGENTS.snippet.md +45 -52
  18. package/templates/CLAUDE.snippet.md +19 -17
  19. package/templates/CURSOR.snippet.md +29 -17
  20. package/assets/report/assets/provider-auth.png +0 -0
  21. package/assets/report/assets/provider-authjs.png +0 -0
  22. package/assets/report/assets/provider-clerk-mark.svg +0 -1
  23. package/assets/report/assets/provider-clerk.png +0 -0
  24. package/assets/report/assets/provider-database.png +0 -0
  25. package/assets/report/assets/provider-env.png +0 -0
  26. package/assets/report/assets/provider-github-mark.svg +0 -1
  27. package/assets/report/assets/provider-github.png +0 -0
  28. package/assets/report/assets/provider-posthog-mark.svg +0 -1
  29. package/assets/report/assets/provider-posthog.png +0 -0
  30. package/assets/report/assets/provider-resend-mark.svg +0 -1
  31. package/assets/report/assets/provider-resend.png +0 -0
  32. package/assets/report/assets/provider-sentry-mark.svg +0 -1
  33. package/assets/report/assets/provider-sentry.png +0 -0
  34. package/assets/report/assets/provider-stripe-mark.svg +0 -1
  35. package/assets/report/assets/provider-stripe.png +0 -0
  36. package/assets/report/assets/provider-supabase-mark.svg +0 -1
  37. package/assets/report/assets/provider-supabase.png +0 -0
  38. package/assets/report/assets/provider-upstash-mark.svg +0 -1
  39. package/assets/report/assets/provider-upstash.png +0 -0
  40. package/assets/report/assets/provider-vercel-mark.svg +0 -1
  41. package/assets/report/assets/provider-vercel.png +0 -0
  42. package/assets/report/assets/viberaven-agent-icon.png +0 -0
  43. package/assets/report/assets/viberaven-mascot-alert.png +0 -0
  44. package/assets/report/assets/viberaven-mascot-fixing.png +0 -0
  45. package/assets/report/assets/viberaven-mascot-verified.png +0 -0
  46. package/dist/report/assets/provider-auth.png +0 -0
  47. package/dist/report/assets/provider-authjs.png +0 -0
  48. package/dist/report/assets/provider-clerk-mark.svg +0 -1
  49. package/dist/report/assets/provider-clerk.png +0 -0
  50. package/dist/report/assets/provider-database.png +0 -0
  51. package/dist/report/assets/provider-env.png +0 -0
  52. package/dist/report/assets/provider-github-mark.svg +0 -1
  53. package/dist/report/assets/provider-github.png +0 -0
  54. package/dist/report/assets/provider-posthog-mark.svg +0 -1
  55. package/dist/report/assets/provider-posthog.png +0 -0
  56. package/dist/report/assets/provider-resend-mark.svg +0 -1
  57. package/dist/report/assets/provider-resend.png +0 -0
  58. package/dist/report/assets/provider-sentry-mark.svg +0 -1
  59. package/dist/report/assets/provider-sentry.png +0 -0
  60. package/dist/report/assets/provider-stripe-mark.svg +0 -1
  61. package/dist/report/assets/provider-stripe.png +0 -0
  62. package/dist/report/assets/provider-supabase-mark.svg +0 -1
  63. package/dist/report/assets/provider-supabase.png +0 -0
  64. package/dist/report/assets/provider-upstash-mark.svg +0 -1
  65. package/dist/report/assets/provider-upstash.png +0 -0
  66. package/dist/report/assets/provider-vercel-mark.svg +0 -1
  67. package/dist/report/assets/provider-vercel.png +0 -0
  68. package/dist/report/assets/viberaven-agent-icon.png +0 -0
  69. package/dist/report/assets/viberaven-mascot-alert.png +0 -0
  70. package/dist/report/assets/viberaven-mascot-fixing.png +0 -0
  71. package/dist/report/assets/viberaven-mascot-verified.png +0 -0
  72. /package/assets/report/assets/{viberaven-mascot-idle.png → viberaven-mascot.png} +0 -0
  73. /package/dist/report/assets/{viberaven-mascot-idle.png → viberaven-mascot.png} +0 -0
package/dist/cli.js CHANGED
@@ -394,6 +394,8 @@ var init_backendClient = __esm({
394
394
  this.status = status;
395
395
  this.upgradeUrl = upgradeUrl;
396
396
  }
397
+ status;
398
+ upgradeUrl;
397
399
  };
398
400
  }
399
401
  });
@@ -543,12 +545,12 @@ function createAppWindowOpenCommands(target, platform = process.platform, env =
543
545
  }
544
546
  async function openWithSystemDefault(target) {
545
547
  const { command, args, shell } = createOpenCommand(target);
546
- await new Promise((resolve7, reject) => {
548
+ await new Promise((resolve6, reject) => {
547
549
  const child = (0, import_node_child_process.spawn)(command, args, { stdio: "ignore", shell });
548
550
  child.on("error", reject);
549
551
  child.on("exit", (code) => {
550
552
  if (code === 0) {
551
- resolve7();
553
+ resolve6();
552
554
  } else {
553
555
  reject(new Error(`Could not open browser (exit ${code ?? "unknown"}). Open manually: ${target}`));
554
556
  }
@@ -559,7 +561,7 @@ async function spawnDetached(command) {
559
561
  if (/^[A-Za-z]:[\\/]/.test(command.command) && !(0, import_node_fs2.existsSync)(command.command)) {
560
562
  throw new Error(`Browser not found: ${command.command}`);
561
563
  }
562
- await new Promise((resolve7, reject) => {
564
+ await new Promise((resolve6, reject) => {
563
565
  const child = (0, import_node_child_process.spawn)(command.command, command.args, {
564
566
  detached: true,
565
567
  stdio: "ignore",
@@ -567,7 +569,7 @@ async function spawnDetached(command) {
567
569
  });
568
570
  child.once("spawn", () => {
569
571
  child.unref();
570
- resolve7();
572
+ resolve6();
571
573
  });
572
574
  child.once("error", reject);
573
575
  });
@@ -636,7 +638,7 @@ var init_commands = __esm({
636
638
 
637
639
  // src/auth.ts
638
640
  function sleep(ms) {
639
- return new Promise((resolve7) => setTimeout(resolve7, ms));
641
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
640
642
  }
641
643
  async function runDeviceLogin(apiBaseUrl) {
642
644
  const signIn = await startManagedSignIn(apiBaseUrl);
@@ -9143,7 +9145,7 @@ function generateAgentSummary(artifact) {
9143
9145
  lines.push("Do not claim human-provider actions as repo-code fixes.");
9144
9146
  lines.push("");
9145
9147
  lines.push("## Agent workflow");
9146
- lines.push("1. Read `.viberaven/agent-tasklist.md` first for the production gate.");
9148
+ lines.push("1. Read `.viberaven/agent-tasklist.md` first for the what-changed map.");
9147
9149
  lines.push("2. Read `.viberaven/launch-playbook.md` for the full checklist.");
9148
9150
  lines.push("3. Run `viberaven next --json` - one action at a time.");
9149
9151
  lines.push("4. Repo fix: `viberaven prompt --gap <id>` then implement.");
@@ -9417,7 +9419,7 @@ function generateLaunchPlaybook(artifact) {
9417
9419
  }
9418
9420
  }
9419
9421
  lines.push("## Agent loop", "");
9420
- lines.push("1. Read `.viberaven/agent-tasklist.md` for the current production gate.");
9422
+ lines.push("1. Read `.viberaven/agent-tasklist.md` for the current what-changed map.");
9421
9423
  lines.push("2. `viberaven next --json`");
9422
9424
  lines.push("3. Fix repo or run `viberaven guide <provider>`");
9423
9425
  lines.push(`4. Run \`${PUBLIC_VERIFY_COMMAND}\` to refresh the gate and \`.viberaven/agent-tasklist.md\`.`);
@@ -9790,36 +9792,11 @@ var init_reportAssets = __esm({
9790
9792
  "station.js",
9791
9793
  "report-cli.css",
9792
9794
  "assets/viberaven-logo.png",
9793
- "assets/viberaven-agent-icon.png",
9794
- "assets/viberaven-mascot-idle.png",
9795
- "assets/viberaven-mascot-fixing.png",
9796
- "assets/viberaven-mascot-verified.png",
9797
- "assets/viberaven-mascot-alert.png",
9795
+ "assets/viberaven-favicon.png",
9796
+ "assets/viberaven-mascot.png",
9798
9797
  "assets/provider-authjs.svg",
9799
9798
  "assets/provider-aws.svg",
9800
- "assets/provider-logrocket.svg",
9801
- "assets/provider-auth.png",
9802
- "assets/provider-authjs.png",
9803
- "assets/provider-clerk.png",
9804
- "assets/provider-clerk-mark.svg",
9805
- "assets/provider-database.png",
9806
- "assets/provider-env.png",
9807
- "assets/provider-github.png",
9808
- "assets/provider-github-mark.svg",
9809
- "assets/provider-posthog.png",
9810
- "assets/provider-posthog-mark.svg",
9811
- "assets/provider-resend.png",
9812
- "assets/provider-resend-mark.svg",
9813
- "assets/provider-sentry.png",
9814
- "assets/provider-sentry-mark.svg",
9815
- "assets/provider-stripe.png",
9816
- "assets/provider-stripe-mark.svg",
9817
- "assets/provider-supabase.png",
9818
- "assets/provider-supabase-mark.svg",
9819
- "assets/provider-upstash.png",
9820
- "assets/provider-upstash-mark.svg",
9821
- "assets/provider-vercel.png",
9822
- "assets/provider-vercel-mark.svg"
9799
+ "assets/provider-logrocket.svg"
9823
9800
  ];
9824
9801
  }
9825
9802
  });
@@ -10440,12 +10417,12 @@ async function copyToClipboard(text) {
10440
10417
  }
10441
10418
  }
10442
10419
  function pipeToCommand(command, text, extraArgs = []) {
10443
- return new Promise((resolve7, reject) => {
10420
+ return new Promise((resolve6, reject) => {
10444
10421
  const child = (0, import_node_child_process2.spawn)(command, extraArgs, { stdio: ["pipe", "ignore", "ignore"] });
10445
10422
  child.on("error", reject);
10446
10423
  child.on("close", (code) => {
10447
10424
  if (code === 0) {
10448
- resolve7();
10425
+ resolve6();
10449
10426
  } else {
10450
10427
  reject(new Error(`${command} exited with code ${code ?? "unknown"}`));
10451
10428
  }
@@ -10467,9 +10444,9 @@ var init_clipboard = __esm({
10467
10444
  }
10468
10445
  });
10469
10446
 
10470
- // node_modules/picocolors/picocolors.js
10447
+ // ../../node_modules/picocolors/picocolors.js
10471
10448
  var require_picocolors = __commonJS({
10472
- "node_modules/picocolors/picocolors.js"(exports2, module2) {
10449
+ "../../node_modules/picocolors/picocolors.js"(exports2, module2) {
10473
10450
  var p2 = process || {};
10474
10451
  var argv = p2.argv || [];
10475
10452
  var env = p2.env || {};
@@ -10659,7 +10636,7 @@ function printScanSummary(artifact, paths) {
10659
10636
  if (next.upgradeUrl) {
10660
10637
  console.log(`Upgrade: ${next.upgradeUrl}`);
10661
10638
  }
10662
- console.log(formatAgentStatus(AGENT_ACTION, "Keep operating: read .viberaven/agent-tasklist.md, apply the next safe repo fix, then continue the VibeRaven loop."));
10639
+ console.log(formatAgentStatus(AGENT_ACTION, "Read .viberaven/agent-tasklist.md, run the next command above, then rescan."));
10663
10640
  console.log("");
10664
10641
  if (artifact.usage) {
10665
10642
  const lanes = artifact.usage.unlockedMapCategoryKeys.length;
@@ -10923,10 +10900,10 @@ function sleepForRunnerPoll(ms, signal) {
10923
10900
  if (signal?.aborted) {
10924
10901
  return Promise.reject(createRunnerWatchAbortError());
10925
10902
  }
10926
- return new Promise((resolve7, reject) => {
10903
+ return new Promise((resolve6, reject) => {
10927
10904
  const timer = setTimeout(() => {
10928
10905
  cleanup();
10929
- resolve7();
10906
+ resolve6();
10930
10907
  }, ms);
10931
10908
  const onAbort = () => {
10932
10909
  cleanup();
@@ -11498,9 +11475,9 @@ function formatRepoMatch(repoMatch) {
11498
11475
  }
11499
11476
  }
11500
11477
  async function runCommand(command, args, cwd) {
11501
- return new Promise((resolve7) => {
11478
+ return new Promise((resolve6) => {
11502
11479
  (0, import_node_child_process3.execFile)(command, args, { cwd, windowsHide: true }, (error, stdout, stderr) => {
11503
- resolve7({
11480
+ resolve6({
11504
11481
  ok: !error,
11505
11482
  stdout: String(stdout ?? ""),
11506
11483
  stderr: String(stderr ?? "")
@@ -11645,9 +11622,9 @@ var init_runnerConnect = __esm({
11645
11622
  }
11646
11623
  });
11647
11624
 
11648
- // node_modules/sisteransi/src/index.js
11625
+ // ../../node_modules/sisteransi/src/index.js
11649
11626
  var require_src = __commonJS({
11650
- "node_modules/sisteransi/src/index.js"(exports2, module2) {
11627
+ "../../node_modules/sisteransi/src/index.js"(exports2, module2) {
11651
11628
  "use strict";
11652
11629
  var ESC = "\x1B";
11653
11630
  var CSI = `${ESC}[`;
@@ -11701,7 +11678,7 @@ var require_src = __commonJS({
11701
11678
  }
11702
11679
  });
11703
11680
 
11704
- // node_modules/@clack/core/dist/index.mjs
11681
+ // ../../node_modules/@clack/core/dist/index.mjs
11705
11682
  function DD({ onlyFirst: e2 = false } = {}) {
11706
11683
  const t = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");
11707
11684
  return new RegExp(t, e2 ? void 0 : "g");
@@ -11813,7 +11790,7 @@ function fD({ input: e2 = import_node_process.stdin, output: u2 = import_node_pr
11813
11790
  }
11814
11791
  var import_sisteransi, import_node_process, g, import_node_readline, import_node_stream, uD, W, tD, eD, FD, sD, w, N, I, R, C, iD, rD, ED, d, oD, y, V, nD, G, _, z, K, aD, k, hD, lD, xD, B, AD, S, gD, vD, h, x, A, OD, PD, J, LD;
11815
11792
  var init_dist = __esm({
11816
- "node_modules/@clack/core/dist/index.mjs"() {
11793
+ "../../node_modules/@clack/core/dist/index.mjs"() {
11817
11794
  import_sisteransi = __toESM(require_src(), 1);
11818
11795
  import_node_process = require("node:process");
11819
11796
  g = __toESM(require("node:readline"), 1);
@@ -11939,7 +11916,7 @@ var init_dist = __esm({
11939
11916
  xD = ["up", "down", "left", "right", "space", "enter", "cancel"];
11940
11917
  B = { actions: new Set(xD), aliases: /* @__PURE__ */ new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["", "cancel"], ["escape", "cancel"]]) };
11941
11918
  AD = globalThis.process.platform.startsWith("win");
11942
- S = Symbol("clack:cancel");
11919
+ S = /* @__PURE__ */ Symbol("clack:cancel");
11943
11920
  gD = Object.defineProperty;
11944
11921
  vD = (e2, u2, t) => u2 in e2 ? gD(e2, u2, { enumerable: true, configurable: true, writable: true, value: t }) : e2[u2] = t;
11945
11922
  h = (e2, u2, t) => (vD(e2, typeof u2 != "symbol" ? u2 + "" : u2, t), t);
@@ -12063,13 +12040,13 @@ var init_dist = __esm({
12063
12040
  }
12064
12041
  });
12065
12042
 
12066
- // node_modules/@clack/prompts/dist/index.mjs
12043
+ // ../../node_modules/@clack/prompts/dist/index.mjs
12067
12044
  function ce() {
12068
12045
  return import_node_process2.default.platform !== "win32" ? import_node_process2.default.env.TERM !== "linux" : !!import_node_process2.default.env.CI || !!import_node_process2.default.env.WT_SESSION || !!import_node_process2.default.env.TERMINUS_SUBLIME || import_node_process2.default.env.ConEmuTask === "{cmd::Cmder}" || import_node_process2.default.env.TERM_PROGRAM === "Terminus-Sublime" || import_node_process2.default.env.TERM_PROGRAM === "vscode" || import_node_process2.default.env.TERM === "xterm-256color" || import_node_process2.default.env.TERM === "alacritty" || import_node_process2.default.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
12069
12046
  }
12070
12047
  var import_node_process2, import_picocolors2, import_sisteransi2, V2, u, le, L2, W2, C2, ue, o, d2, k2, P2, A2, T, F, $e, _2, me, de, pe, q, D, U, K2, b2, G2, ve, xe, Ie, Se, M2, J2, Y2;
12071
12048
  var init_dist2 = __esm({
12072
- "node_modules/@clack/prompts/dist/index.mjs"() {
12049
+ "../../node_modules/@clack/prompts/dist/index.mjs"() {
12073
12050
  init_dist();
12074
12051
  init_dist();
12075
12052
  import_node_process2 = __toESM(require("node:process"), 1);
@@ -12253,16 +12230,16 @@ function originalHint(gap) {
12253
12230
  function buildAgentFixPrompt(artifact, gap) {
12254
12231
  const affected = [gap.primaryMapCategory, ...gap.affectedMapCategories ?? []].filter(Boolean).filter((value, index, all) => all.indexOf(value) === index).join(", ");
12255
12232
  return [
12256
- "You are an AI coding agent using VibeRaven as the production-readiness map.",
12233
+ "You are an AI coding agent using VibeRaven as the what-changed layer for a real app.",
12257
12234
  "",
12258
- "Goal: turn this demo/MVP into a more production-ready app by fixing one repo-code gap at a time.",
12235
+ "Goal: understand what changed, which provider context matters, and fix one repo-code gap at a time.",
12259
12236
  "",
12260
12237
  `Project: ${artifact.workspacePath}`,
12261
- `Current VibeRaven state: production core ${artifact.productionCorePercent}% | score ${artifact.score} (${artifact.scoreLabel})`,
12238
+ `Current VibeRaven state: context core ${artifact.productionCorePercent}% | score ${artifact.score} (${artifact.scoreLabel})`,
12262
12239
  `Gap: ${gap.title}`,
12263
12240
  `Gap id: ${gap.id}`,
12264
12241
  `Severity: ${gap.severity}`,
12265
- `Production area: ${gap.primaryMapCategory}${affected ? ` | affected: ${affected}` : ""}`,
12242
+ `Context area: ${gap.primaryMapCategory}${affected ? ` | affected: ${affected}` : ""}`,
12266
12243
  `Scanner detail: ${compact(gap.detail)}`,
12267
12244
  "",
12268
12245
  "Required workflow:",
@@ -12272,7 +12249,7 @@ function buildAgentFixPrompt(artifact, gap) {
12272
12249
  "4. Inspect the real implementation files. Do not assume framework/provider wiring from package names alone.",
12273
12250
  "5. Make the smallest durable repo-code change that addresses this specific gap.",
12274
12251
  "6. Keep provider dashboard work separate. Open provider dashboards only when VibeRaven asks for a provider/manual action, and explain why you opened them.",
12275
- `7. For Vercel + Supabase apps, run \`${PUBLIC_AUDIT_COMMAND}\` before claiming production readiness.`,
12252
+ `7. For Vercel + Supabase apps, run \`${PUBLIC_AUDIT_COMMAND}\` before claiming the fix is grounded.`,
12276
12253
  "8. Treat that audit as local repo evidence only; do not claim provider dashboard settings are fixed unless the user verifies them or read-only provider MCP confirms them.",
12277
12254
  "9. Do not claim provider dashboard or read-only MCP checks as repo-code fixes.",
12278
12255
  `10. VibeRaven cleanup is non-destructive. You may run \`${PUBLIC_CLEAN_PLAN_COMMAND}\` only to create a reviewable context cleanup plan, not to delete code.`,
@@ -12304,7 +12281,7 @@ var VERSION;
12304
12281
  var init_version = __esm({
12305
12282
  "src/version.ts"() {
12306
12283
  "use strict";
12307
- VERSION = "1.2.3";
12284
+ VERSION = "1.3.0";
12308
12285
  }
12309
12286
  });
12310
12287
 
@@ -12400,186 +12377,20 @@ function redactEvidenceLine(line) {
12400
12377
  function lineEvidence(file, pattern) {
12401
12378
  return file.content.split(/\r?\n/).map((line, index) => ({ line: line.trim(), lineNumber: index + 1 })).filter(({ line }) => pattern.test(line)).map(({ line, lineNumber }) => `${file.path}:${lineNumber}: ${redactEvidenceLine(line)}`);
12402
12379
  }
12403
- function lineNumberAt(content, index) {
12404
- return content.slice(0, index).split(/\r?\n/).length;
12405
- }
12406
- function statementEvidence(file, pattern) {
12407
- const evidence = [];
12408
- for (const match of file.content.matchAll(pattern)) {
12409
- evidence.push(
12410
- `${file.path}:${lineNumberAt(file.content, match.index ?? 0)}: ${redactEvidenceLine(
12411
- String(match[0]).replace(/\s+/g, " ").trim()
12412
- )}`
12413
- );
12414
- }
12415
- return evidence;
12416
- }
12417
- function normalizeIdent(value) {
12418
- return (value ?? "").replace(/^"|"$/g, "").toLowerCase();
12419
- }
12420
- function canonicalPublicTable(schema, table) {
12421
- const normalizedSchema = normalizeIdent(schema);
12422
- if (normalizedSchema && normalizedSchema !== "public") {
12423
- return void 0;
12424
- }
12425
- return `public.${normalizeIdent(table)}`;
12426
- }
12427
- function parseRelationRef(ref) {
12428
- const parts = ref.split(".").map((part) => normalizeIdent(part.trim()));
12429
- if (parts.length === 1) {
12430
- return `public.${parts[0]}`;
12431
- }
12432
- if (parts.length === 2 && parts[0] === "public") {
12433
- return `public.${parts[1]}`;
12434
- }
12435
- return void 0;
12436
- }
12437
- function relationEvidence(files, pattern, relationGroup = "relation") {
12438
- const evidence = [];
12439
- for (const file of files) {
12440
- for (const match of file.content.matchAll(pattern)) {
12441
- const groups = match.groups ?? {};
12442
- const relation = parseRelationRef(String(groups[relationGroup] ?? ""));
12443
- if (!relation) {
12444
- continue;
12445
- }
12446
- evidence.push({
12447
- relation,
12448
- evidence: `${file.path}:${lineNumberAt(file.content, match.index ?? 0)}: ${redactEvidenceLine(
12449
- String(match[0]).replace(/\s+/g, " ").trim()
12450
- )}`
12451
- });
12452
- }
12453
- }
12454
- return evidence;
12455
- }
12456
12380
  function sqlFiles(files) {
12457
12381
  return files.filter((file) => file.path.toLowerCase().endsWith(".sql"));
12458
12382
  }
12459
12383
  function buildRlsCheck(files) {
12460
12384
  const sql = sqlFiles(files);
12461
- const createdTables = [];
12462
- for (const file of sql) {
12463
- const pattern = /\bcreate\s+table\s+(?:if\s+not\s+exists\s+)?(?:(?<schema>"?[A-Za-z_][\w$]*"?)\.)?(?<table>"?[A-Za-z_][\w$]*"?)/gi;
12464
- for (const match of file.content.matchAll(pattern)) {
12465
- const relation = canonicalPublicTable(match.groups?.schema, String(match.groups?.table ?? ""));
12466
- if (!relation) {
12467
- continue;
12468
- }
12469
- createdTables.push({
12470
- relation,
12471
- evidence: `${file.path}:${lineNumberAt(file.content, match.index ?? 0)}: ${redactEvidenceLine(
12472
- String(match[0]).replace(/\s+/g, " ").trim()
12473
- )}`
12474
- });
12475
- }
12476
- }
12477
- const enabledTables = new Set(
12478
- relationEvidence(
12479
- sql,
12480
- /\balter\s+table\s+(?:if\s+exists\s+)?(?:only\s+)?(?<relation>(?:"?[A-Za-z_][\w$]*"?\.)?"?[A-Za-z_][\w$]*"?)\s+enable\s+row\s+level\s+security\b/gi
12481
- ).map((item4) => item4.relation)
12482
- );
12483
- const policyTables = new Set(
12484
- relationEvidence(
12485
- sql,
12486
- /\bcreate\s+policy\b[\s\S]*?\bon\s+(?<relation>(?:"?[A-Za-z_][\w$]*"?\.)?"?[A-Za-z_][\w$]*"?)[\s\S]*?;/gi
12487
- ).map((item4) => item4.relation)
12488
- );
12489
12385
  const rlsEvidence2 = sql.flatMap((file) => lineEvidence(file, /\benable\s+row\s+level\s+security\b/i));
12490
12386
  const policyEvidence = sql.flatMap((file) => lineEvidence(file, /\bcreate\s+policy\b/i));
12491
- const missingTableEvidence = createdTables.filter(({ relation }) => !enabledTables.has(relation) || !policyTables.has(relation)).map(({ relation, evidence }) => `Missing RLS/policy coverage for ${relation}; created at ${evidence}`);
12492
- const status = createdTables.length > 0 ? missingTableEvidence.length === 0 ? "pass" : "needs_work" : rlsEvidence2.length > 0 && policyEvidence.length > 0 ? "pass" : "needs_work";
12387
+ const status = rlsEvidence2.length > 0 && policyEvidence.length > 0 ? "pass" : "needs_work";
12493
12388
  return {
12494
12389
  id: "supabase-rls-policy-proof",
12495
12390
  title: "Supabase RLS policy proof",
12496
12391
  status,
12497
- summary: status === "pass" ? createdTables.length > 0 ? "Found table-level SQL evidence for row level security and matching policies on public tables." : "Found SQL evidence for row level security and at least one policy." : missingTableEvidence.length > 0 ? `Missing table-level RLS or policy evidence: ${missingTableEvidence.map((item4) => item4.match(/for ([^;]+)/)?.[1] ?? item4).join(", ")}.` : "Missing SQL evidence for both `enable row level security` and `create policy`.",
12498
- evidence: [...missingTableEvidence.slice(0, 5), ...rlsEvidence2.slice(0, 5), ...policyEvidence.slice(0, 5)]
12499
- };
12500
- }
12501
- function buildRlsPolicyQualityCheck(files) {
12502
- const sql = sqlFiles(files);
12503
- const evidence = sql.flatMap(
12504
- (file) => statementEvidence(file, /\bcreate\s+policy\b[\s\S]*?\b(?:using|with\s+check)\s*\(\s*true\s*\)[\s\S]*?;/gi)
12505
- );
12506
- const status = evidence.length === 0 ? "pass" : "needs_work";
12507
- return {
12508
- id: "supabase-rls-policy-quality",
12509
- title: "Supabase RLS policy quality",
12510
- status,
12511
- summary: status === "pass" ? "No permissive `using (true)` or `with check (true)` policy evidence found." : "Found RLS policies that allow every row. Public access may be intentional, but it must be reviewed before production.",
12512
- evidence: evidence.slice(0, 5)
12513
- };
12514
- }
12515
- function buildViewSecurityInvokerCheck(files) {
12516
- const sql = sqlFiles(files);
12517
- const secureViews = /* @__PURE__ */ new Set();
12518
- const insecureEvidence = [];
12519
- for (const file of sql) {
12520
- for (const match of file.content.matchAll(
12521
- /\bcreate\s+(?:or\s+replace\s+)?view\s+(?<relation>(?:"?[A-Za-z_][\w$]*"?\.)?"?[A-Za-z_][\w$]*"?)[\s\S]*?;/gi
12522
- )) {
12523
- const relation = parseRelationRef(String(match.groups?.relation ?? ""));
12524
- if (!relation) {
12525
- continue;
12526
- }
12527
- const statement = String(match[0]);
12528
- if (/\bsecurity_invoker\b/i.test(statement)) {
12529
- secureViews.add(relation);
12530
- continue;
12531
- }
12532
- insecureEvidence.push({
12533
- relation,
12534
- evidence: `${file.path}:${lineNumberAt(file.content, match.index ?? 0)}: ${redactEvidenceLine(
12535
- statement.replace(/\s+/g, " ").trim()
12536
- )}`
12537
- });
12538
- }
12539
- for (const match of file.content.matchAll(
12540
- /\balter\s+view\s+(?<relation>(?:"?[A-Za-z_][\w$]*"?\.)?"?[A-Za-z_][\w$]*"?)[\s\S]*?\bsecurity_invoker\s*=\s*true\b[\s\S]*?;/gi
12541
- )) {
12542
- const relation = parseRelationRef(String(match.groups?.relation ?? ""));
12543
- if (relation) {
12544
- secureViews.add(relation);
12545
- }
12546
- }
12547
- }
12548
- const evidence = insecureEvidence.filter(({ relation }) => !secureViews.has(relation)).map(({ evidence: evidence2 }) => evidence2);
12549
- const status = evidence.length === 0 ? "pass" : "needs_work";
12550
- return {
12551
- id: "supabase-view-security-invoker",
12552
- title: "Supabase view security invoker",
12553
- status,
12554
- summary: status === "pass" ? "No public view evidence without `security_invoker` found." : "Found public Supabase views without `security_invoker` evidence. Views can bypass underlying RLS by default.",
12555
- evidence: evidence.slice(0, 5)
12556
- };
12557
- }
12558
- function buildSecurityDefinerBoundaryCheck(files) {
12559
- const sql = sqlFiles(files);
12560
- const evidence = [];
12561
- for (const file of sql) {
12562
- for (const match of file.content.matchAll(
12563
- /\bcreate\s+(?:or\s+replace\s+)?function\s+(?<relation>(?:"?[A-Za-z_][\w$]*"?\.)?"?[A-Za-z_][\w$]*"?)[\s\S]*?\bsecurity\s+definer\b[\s\S]*?;/gi
12564
- )) {
12565
- const relation = parseRelationRef(String(match.groups?.relation ?? ""));
12566
- if (!relation) {
12567
- continue;
12568
- }
12569
- evidence.push(
12570
- `${file.path}:${lineNumberAt(file.content, match.index ?? 0)}: ${redactEvidenceLine(
12571
- String(match[0]).replace(/\s+/g, " ").trim()
12572
- )}`
12573
- );
12574
- }
12575
- }
12576
- const status = evidence.length === 0 ? "pass" : "needs_work";
12577
- return {
12578
- id: "supabase-security-definer-boundary",
12579
- title: "Supabase security definer boundary",
12580
- status,
12581
- summary: status === "pass" ? "No `security definer` functions in the public schema were found." : "Found `security definer` functions in the public schema. Keep privileged functions in a private, unexposed schema.",
12582
- evidence: evidence.slice(0, 5)
12392
+ summary: status === "pass" ? "Found SQL evidence for row level security and at least one policy." : "Missing SQL evidence for both `enable row level security` and `create policy`.",
12393
+ evidence: [...rlsEvidence2.slice(0, 5), ...policyEvidence.slice(0, 5)]
12583
12394
  };
12584
12395
  }
12585
12396
  function buildPoolerCheck(files) {
@@ -12623,9 +12434,6 @@ function buildServiceRoleCheck(files) {
12623
12434
  function buildVercelSupabaseAudit(input) {
12624
12435
  const checks = [
12625
12436
  buildRlsCheck(input.files),
12626
- buildRlsPolicyQualityCheck(input.files),
12627
- buildViewSecurityInvokerCheck(input.files),
12628
- buildSecurityDefinerBoundaryCheck(input.files),
12629
12437
  buildPoolerCheck(input.files),
12630
12438
  buildServiceRoleCheck(input.files)
12631
12439
  ];
@@ -12874,7 +12682,7 @@ function normalizeLineEndings(value) {
12874
12682
  function escapeRegExp3(value) {
12875
12683
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
12876
12684
  }
12877
- var VIBERAVEN_BLOCK_START, VIBERAVEN_BLOCK_END, VIBERAVEN_LEGACY_BLOCK_START, VIBERAVEN_LEGACY_BLOCK_END, HEAL_PLAN_GAP_COMMAND, PROMPT_GAP_COMMAND, HEAL_APPLY_GAP_COMMAND, AGENT_RULES_PREAMBLE, STACK_FRAMING, PRODUCTION_PROTOCOL, AGENT_NEGATIVE_CONSTRAINTS, ANCHOR_FOOTER, AGENT_RULES_BODY, AGENT_CONTEXT_BODY, MISSION_MAP_BODY, BLOCK_MARKER_PAIRS;
12685
+ var VIBERAVEN_BLOCK_START, VIBERAVEN_BLOCK_END, VIBERAVEN_LEGACY_BLOCK_START, VIBERAVEN_LEGACY_BLOCK_END, HEAL_PLAN_GAP_COMMAND, PROMPT_GAP_COMMAND, HEAL_APPLY_GAP_COMMAND, AGENT_RULES_PREAMBLE, STACK_FRAMING, ARCHITECTURE_ORIENTATION, AGENT_NEGATIVE_CONSTRAINTS, ANCHOR_FOOTER, AGENT_RULES_BODY, AGENT_CONTEXT_BODY, MISSION_MAP_BODY, BLOCK_MARKER_PAIRS;
12878
12686
  var init_agentRulesBlock = __esm({
12879
12687
  "src/commands/agentRulesBlock.ts"() {
12880
12688
  "use strict";
@@ -12886,65 +12694,88 @@ var init_agentRulesBlock = __esm({
12886
12694
  HEAL_PLAN_GAP_COMMAND = healPlanGapCommand("<id>");
12887
12695
  PROMPT_GAP_COMMAND = promptGapCommand("<id>");
12888
12696
  HEAL_APPLY_GAP_COMMAND = `${PUBLIC_COMMAND} --heal --apply --gap <id> --yes`;
12889
- AGENT_RULES_PREAMBLE = `VibeRaven provides production readiness for AI-built apps.
12697
+ AGENT_RULES_PREAMBLE = `AI agents can code. They still need senior-engineer context before they change real apps.
12890
12698
 
12891
- Canonical command: \`${PUBLIC_AGENT_MODE_COMMAND}\`
12699
+ Canonical Studio command: \`${PUBLIC_COMMAND}\`
12892
12700
 
12893
- Use VibeRaven before launch, deployment, real users, auth, billing, database, RLS, env vars, webhooks, monitoring, or tests.
12701
+ Non-interactive artifact loop: \`${PUBLIC_AGENT_MODE_COMMAND}\`
12894
12702
 
12895
- Agent loop: run VibeRaven, read Mission Map (\`.viberaven/mission-map.md\`), fix one launch gap, re-run VibeRaven.
12703
+ Use VibeRaven at the start of production-sensitive coding work, feature work, provider work, release/version debugging, or launch work, including when the agent needs to know which version broke or what provider context matters.
12896
12704
 
12897
- Maps repo evidence to OWASP LLM Top 10 launch risks. Supports SAFECode-style deployment readiness checks.`;
12705
+ Default loop: orient the architecture, ask only the missing questions needed for a safe plan, inspect release/provider context, choose the right VibeRaven skill, fix one evidenced change, then verify.
12706
+
12707
+ Maps repo evidence, release drift, architecture boundaries, and provider boundaries into agent-readable context.`;
12898
12708
  STACK_FRAMING = `Stack context for this repo: Next.js, Supabase, Vercel, VibeRaven.
12899
- Do NOT deploy to Vercel or ship to production users without running \`${PUBLIC_AGENT_MODE_COMMAND}\`.
12900
- Do NOT rely on manual production checklists when VibeRaven gate artifacts exist in \`.viberaven/\`.`;
12901
- PRODUCTION_PROTOCOL = `## VibeRaven Production Protocol
12709
+ Do NOT deploy to Vercel or ship to production users without VibeRaven architecture/release/provider context.
12710
+ Do NOT rely on manual checklists when VibeRaven artifacts exist in \`.viberaven/\`.`;
12711
+ ARCHITECTURE_ORIENTATION = `## VibeRaven Architecture Orientation
12712
+
12713
+ At the start of a real app task, before writing a plan or editing code:
12714
+
12715
+ 1. Identify the product surface, user path, and desired outcome.
12716
+ 2. Map the architecture boundary involved: UI/API, auth/session, data/schema/RLS, provider dashboard, deploy/env, background job/webhook, billing, storage, or release/version drift.
12717
+ 3. Check existing VibeRaven context: \`.viberaven/production-context.md\`, \`.viberaven/agent-context.md\`, \`.viberaven/mission-map.md\`, and recent git history when present.
12718
+ 4. Ask concise questions only when the missing answer changes the plan, such as last working version, provider involved, production symptom, deploy target, or whether dashboard proof exists.
12719
+ 5. Build the plan around the architecture boundary first, then the code change. Do not start from the nearest file.
12720
+ 6. Route to the suited VibeRaven skill:
12721
+ - \`what-broke\` for regressions, version drift, or "worked yesterday" bugs.
12722
+ - \`production-context\` for release notes, architecture memory, provider boundaries, migrations, incidents, and rollback notes.
12723
+ - \`viberaven\` for Studio, MCP context, provider cards, connected agents, access modes, and release/version context.
12724
+ - \`go-live\` for push, deploy, live URL proof, and provider/human launch boundaries.
12902
12725
 
12903
- Before making deploy, auth, database, payment, API, or scaling changes:
12726
+ Output shape before implementation:
12904
12727
 
12905
- 1. Read \`.viberaven/prp.json\`.
12906
- 2. Follow \`.viberaven/mission-map.md\`.
12907
- 3. Do not deploy if \`decision.status\` is \`blocked\`.
12908
- 4. Fix \`nextActions\` in order.
12909
- 5. Re-run \`${PUBLIC_AGENT_MODE_COMMAND}\`.`;
12910
- AGENT_NEGATIVE_CONSTRAINTS = `## Event-Triggered Production Verification
12728
+ \`\`\`text
12729
+ Architecture boundary:
12730
+ - ...
12911
12731
 
12912
- Trigger: modifications to \`package.json\`, \`vercel.json\`, \`supabase/migrations/**/*\`, \`.env.example\`, auth/billing/webhook paths, or deploy workflow files.
12732
+ Questions/blockers:
12733
+ - ... or none
12913
12734
 
12914
- 1. Do NOT claim "production ready" or close a deploy checklist until \`gate.status === "clear"\` in \`.viberaven/gate-result.json\`.
12735
+ Plan:
12736
+ - ...
12737
+
12738
+ VibeRaven skill/context:
12739
+ - ...
12740
+ \`\`\``;
12741
+ AGENT_NEGATIVE_CONSTRAINTS = `## Event-Triggered Context Check
12742
+
12743
+ Trigger: modifications to \`package.json\`, \`vercel.json\`, \`supabase/migrations/**/*\`, \`.env.example\`, provider-sensitive paths, or deploy workflow files.
12744
+
12745
+ 1. Do NOT claim the app is ready to ship until \`decision.status\` is not \`blocked\` and \`gate.status === "clear"\` in \`.viberaven/gate-result.json\`.
12915
12746
  2. Do NOT run verify after every file patch. Batch heals, then \`${PUBLIC_VERIFY_COMMAND}\` once per loop.
12916
- 3. Do NOT \`git push\` or deploy after auth, RLS, billing, or webhook changes without \`${PUBLIC_AGENT_MODE_COMMAND}\`.
12747
+ 3. Do NOT \`git push\` or deploy after provider-sensitive changes without VibeRaven architecture/release/provider context.
12917
12748
  4. If anomalies appear, read \`.viberaven/agent-tasklist.md\` fully before writing new repo logic.
12918
- 5. Do NOT mark production-ready because the local dev server starts successfully; INSTEAD run \`${PUBLIC_AGENT_MODE_COMMAND}\` and read \`.viberaven/gate-result.json\`.
12749
+ 5. Do NOT mark the app ready because the local dev server starts successfully; INSTEAD open Studio or run the artifact loop and read \`.viberaven/gate-result.json\`.
12919
12750
  6. Do NOT treat the Supabase dashboard UI as proof of RLS; INSTEAD fix repo evidence gaps from \`.viberaven/agent-tasklist.md\`.
12920
- 7. Do NOT add or change npm dependencies without calling \`viberaven_validate_npm_package\` (MCP) or verifying the package exists on the public npm registry; INSTEAD run \`${PUBLIC_AGENT_MODE_COMMAND}\` after dependency changes.
12751
+ 7. Do NOT add or change npm dependencies without calling \`viberaven_validate_npm_package\` (MCP) or verifying the package exists on the public npm registry; INSTEAD refresh architecture/release/provider context after dependency changes.
12921
12752
  8. Do NOT refactor or edit files unrelated to the current TASK-001 gap; INSTEAD make minimal, targeted changes.
12922
12753
  9. Do NOT install new dependencies unless TASK-001 or the user explicitly requires them.
12923
- 10. Do NOT claim provider dashboard, billing, DNS, or webhook setup is complete from repo edits alone; INSTEAD present provider-action steps from the tasklist.
12754
+ 10. Do NOT claim live provider state is complete from repo edits alone; INSTEAD name the provider proof or dashboard action still needed.
12924
12755
 
12925
- Prefer \`viberaven_check_readiness\` when MCP is configured; otherwise \`${PUBLIC_AGENT_MODE_COMMAND}\`.`;
12756
+ Prefer \`viberaven_check_readiness\` when MCP is configured; otherwise \`${PUBLIC_COMMAND}\` for Studio or \`${PUBLIC_AGENT_MODE_COMMAND}\` for artifacts.`;
12926
12757
  ANCHOR_FOOTER = `## Anchor (mandatory)
12927
12758
 
12928
- Before ending any deploy, auth, RLS, webhook, or dependency task, run:
12929
- \`${PUBLIC_AGENT_MODE_COMMAND}\`
12930
- Gate is not clear until \`gate.status === "clear"\` in \`.viberaven/gate-result.json\`.`;
12759
+ Before ending any deploy, provider-sensitive, database-policy, or dependency task, open Studio or run the artifact loop:
12760
+ \`${PUBLIC_COMMAND}\`
12761
+ Context is not clear until \`gate.status === "clear"\` in \`.viberaven/gate-result.json\`.`;
12931
12762
  AGENT_RULES_BODY = `${AGENT_RULES_PREAMBLE}
12932
12763
 
12933
12764
  ${STACK_FRAMING}
12934
12765
 
12935
- ${PRODUCTION_PROTOCOL}
12766
+ ${ARCHITECTURE_ORIENTATION}
12936
12767
 
12937
12768
  ${AGENT_NEGATIVE_CONSTRAINTS}
12938
12769
 
12939
- ## VibeRaven Production-Readiness Gate
12770
+ ## VibeRaven What-Changed Layer
12940
12771
 
12941
- - Before running build, compile, cleanup, deployment, vercel, or supabase commands, run \`${PUBLIC_AGENT_MODE_COMMAND}\` first from the project root.
12942
- - Treat VibeRaven as the Agent Context + Production Gate for AI-built apps, especially apps using Vercel, Supabase, auth, database, payments, webhooks, monitoring, rate limits, or environment variables.
12943
- - Read \`.viberaven/agent-tasklist.md\` first. If it says CRITICAL GAPS DETECTED or PRODUCTION GATE NOT CLEAR, fix one listed repo-code gap before deploying.
12772
+ - Before running build, compile, cleanup, deployment, vercel, or supabase commands, open Studio with \`${PUBLIC_COMMAND}\` or run the artifact loop when non-interactive context is needed.
12773
+ - Treat VibeRaven as senior-engineer architecture, release drift, and provider context for AI-built apps: identify the boundary, what changed, which version broke, and what provider state matters before editing.
12774
+ - Read \`.viberaven/agent-tasklist.md\` first. If it says CRITICAL GAPS DETECTED or the decision is not clear, fix one listed repo-code gap before deploying.
12944
12775
  - Read \`.viberaven/gate-result.json\` for the machine verdict.
12945
12776
  - Read \`.viberaven/context-map.json\` for compact agent context.
12946
12777
  - Read \`.viberaven/agent-summary.md\` second for scan context.
12947
- - Read \`.viberaven/launch-playbook.md\` third for the full checklist.
12778
+ - Read \`.viberaven/launch-playbook.md\` third for the full context map.
12948
12779
  - Use \`${PUBLIC_NEXT_JSON_COMMAND}\` or \`${PROMPT_GAP_COMMAND}\` for one focused repo-code fix at a time.
12949
12780
  - For Vercel + Supabase launch checks, run \`${PUBLIC_AUDIT_COMMAND}\`.
12950
12781
  - Run \`${PUBLIC_VERIFY_COMMAND}\` after one fix.
@@ -12953,11 +12784,11 @@ ${AGENT_NEGATIVE_CONSTRAINTS}
12953
12784
  - Only use \`${HEAL_APPLY_GAP_COMMAND}\` for supported low-risk repo-code recipes.
12954
12785
  - Preview local rule installation with \`${PUBLIC_INIT_ALL_COMMAND} --dry-run\`.
12955
12786
  - Cleanup is non-destructive: only run \`${PUBLIC_CLEAN_PLAN_COMMAND}\` to create a reviewable cleanup plan.
12956
- - 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 MCP evidence.
12787
+ - Provider dashboard checks are not cleared by repo-code edits. Database rules, storage behavior, deployment/runtime behavior, quotas, dashboard toggles, and live provider proof must be completed or verified in the provider dashboard or through read-only provider MCP evidence.
12957
12788
  - Do not claim provider dashboard work is fixed by repo-code edits.
12958
12789
  - If VibeRaven prints \`LOGIN_URL_READY\`, open that URL for the user using the available browser tool or system browser. Tell the user: "I opened VibeRaven sign-in so you can approve access; I will continue after approval." Do not ask for passwords, tokens, cookies, or secrets. Keep the terminal process alive while the user approves.
12959
12790
 
12960
- ## VibeRaven Production Copilot Loop
12791
+ ## VibeRaven What-Changed Loop
12961
12792
 
12962
12793
  After every scan, read \`.viberaven/agent-tasklist.md\` for the prioritized task list.
12963
12794
 
@@ -12978,23 +12809,24 @@ The loop is:
12978
12809
  - Wait for user confirmation, then verify.
12979
12810
  9. If \`fixType === 'upgrade-required'\`, provide upgradeUrl and move on.
12980
12811
 
12981
- Do not stop at "scan complete." The loop is not done until \`gate.status === 'clear'\`.`;
12812
+ Do not stop at "scan complete." The loop is not done until the agent knows what changed, \`gate.status === 'clear'\`, and the next fix is grounded in evidence.`;
12982
12813
  AGENT_CONTEXT_BODY = `${AGENT_RULES_PREAMBLE}
12983
12814
 
12984
12815
  After \`--agent-mode\`, read these artifacts in order:
12985
12816
 
12986
- 1. \`.viberaven/prp.json\`
12987
- 2. \`.viberaven/mission-map.md\`
12988
- 3. \`.viberaven/agent-tasklist.md\`
12989
- 4. \`.viberaven/gate-result.json\`
12990
- 5. \`.viberaven/context-map.json\``;
12817
+ 1. \`.viberaven/mission-map.md\`
12818
+ 2. \`.viberaven/agent-tasklist.md\`
12819
+ 3. \`.viberaven/gate-result.json\`
12820
+ 4. \`.viberaven/context-map.json\`
12821
+
12822
+ Before editing, summarize the architecture boundary and missing questions from those artifacts.`;
12991
12823
  MISSION_MAP_BODY = `${AGENT_RULES_PREAMBLE}
12992
12824
 
12993
12825
  ## Mission Map loop
12994
12826
 
12995
12827
  1. Run \`${PUBLIC_AGENT_MODE_COMMAND}\` from the project root.
12996
12828
  2. Read \`.viberaven/agent-tasklist.md\` and \`.viberaven/gate-result.json\`.
12997
- 3. Fix one launch gap.
12829
+ 3. Fix one evidenced change with architecture/release/provider context.
12998
12830
  4. Re-run VibeRaven until \`gate.status === 'clear'\`.`;
12999
12831
  BLOCK_MARKER_PAIRS = [
13000
12832
  [VIBERAVEN_BLOCK_START, VIBERAVEN_BLOCK_END],
@@ -13010,20 +12842,24 @@ function buildCursorRulesPack() {
13010
12842
  filename: "viberaven-core.mdc",
13011
12843
  content: [
13012
12844
  "---",
13013
- "description: VibeRaven production gate \u2014 canonical agent commands and gate loop",
12845
+ "description: VibeRaven what-changed layer for architecture, release, and provider context",
13014
12846
  "alwaysApply: true",
13015
12847
  "---",
13016
12848
  "",
13017
- `Run \`${PUBLIC_AGENT_MODE_COMMAND}\` before deploy, auth, RLS, webhooks, or dependency changes.`,
12849
+ "At the start of real app work, map the architecture boundary before editing: UI/API, auth/session, data/schema/RLS, provider dashboard, deploy/env, background job/webhook, billing, storage, or release/version drift.",
12850
+ "",
12851
+ "Ask concise questions only when the answer changes the plan: last working version, production symptom, provider involved, deploy target, or provider/dashboard proof.",
12852
+ "",
12853
+ `Open Studio with \`npx -y viberaven\` for context. Run \`${PUBLIC_AGENT_MODE_COMMAND}\` before deploy, provider-sensitive, database-policy, or dependency changes when artifact context is needed.`,
13018
12854
  "",
13019
12855
  "Read `.viberaven/agent-tasklist.md` first, then `.viberaven/gate-result.json` and `.viberaven/mission-map.md`.",
13020
- `Fix one gap, then \`${PUBLIC_VERIFY_COMMAND}\`. Before CI or production promote: \`${PUBLIC_STRICT_COMMAND}\`.`,
12856
+ `Fix one scoped gap, then \`${PUBLIC_VERIFY_COMMAND}\`. Before CI or production promote: \`${PUBLIC_STRICT_COMMAND}\`.`,
13021
12857
  "",
13022
- 'Gate is not clear until `gate.status === "clear"`.',
12858
+ 'Context is not clear until the architecture boundary, release/version context, and provider proof boundary are understood. For launch gates, `gate.status === "clear"` is required.',
13023
12859
  "",
13024
12860
  DOMAIN_PATH_POINTER,
13025
12861
  "",
13026
- "Full production rules: `AGENTS.md` / `CLAUDE.md` (installed by `npx -y viberaven init --agents all`)."
12862
+ "Full VibeRaven rules: `AGENTS.md` / `CLAUDE.md` (installed by `npx -y viberaven init --agents all`)."
13027
12863
  ].join("\n")
13028
12864
  },
13029
12865
  {
@@ -13130,7 +12966,7 @@ var init_cursorRulesPack = __esm({
13130
12966
  init_commands();
13131
12967
  CURSOR_RULES_DIR = ".cursor/rules";
13132
12968
  LEGACY_CURSOR_RULE_FILE = `${CURSOR_RULES_DIR}/viberaven.mdc`;
13133
- DOMAIN_PATH_POINTER = "Before editing these files, read `.viberaven/agent-context.md` and `.viberaven/mission-map.md`.";
12969
+ DOMAIN_PATH_POINTER = "Before editing these files, read `.viberaven/agent-context.md` and `.viberaven/mission-map.md` for what changed, which architecture boundary is affected, and which provider context matters.";
13134
12970
  }
13135
12971
  });
13136
12972
 
@@ -13683,7 +13519,7 @@ async function handleOpenDashboard(cwd) {
13683
13519
  function buildMenuOptions(isSignedIn) {
13684
13520
  return [
13685
13521
  { value: "next", label: "What's next?", hint: "One action from last scan" },
13686
- { value: "scan", label: "Scan project", hint: "Map launch readiness" },
13522
+ { value: "scan", label: "Scan project", hint: "Map what changed" },
13687
13523
  { value: "open-report", label: "Open report in browser", hint: "Rebuilds UI from last scan" },
13688
13524
  { value: "guide", label: "Provider guide", hint: "Vercel, Supabase, Stripe steps" },
13689
13525
  { value: "open-dashboard", label: "Open dashboard", hint: "Browser link for next step" },
@@ -15623,7 +15459,7 @@ async function runVerifyActionCommand(input) {
15623
15459
  }
15624
15460
  process.stdout.write(
15625
15461
  `Verifying ${entry.id} (${entry.title ?? "untitled action"}).
15626
- Run \`npx -y viberaven --verify\` to refresh the production gate for this action.
15462
+ Run \`npx -y viberaven --verify\` to refresh VibeRaven context for this action.
15627
15463
  `
15628
15464
  );
15629
15465
  return 0;
@@ -15959,10 +15795,6 @@ function providerLogoHtml(providerOrLabel, labelFallback, ...moreCandidates) {
15959
15795
  }
15960
15796
  function providerRailLogoHtml(providerOrLabel, labelFallback, ...moreCandidates) {
15961
15797
  const key = resolveProviderLogoKey(providerOrLabel, labelFallback, ...moreCandidates) || normalizeProviderKey2(providerOrLabel);
15962
- const assetUrl = key ? providerAssetUrl(key) : void 0;
15963
- if (assetUrl) {
15964
- return providerIconImgHtml(assetUrl, key);
15965
- }
15966
15798
  const iconUrl = key && LOCAL_UI_BRAND_ICON_KEYS.has(key) ? PROVIDER_ICON_URLS[key] : void 0;
15967
15799
  if (iconUrl) {
15968
15800
  return providerIconImgHtml(iconUrl, key);
@@ -16098,18 +15930,6 @@ var init_providerLogos = __esm({
16098
15930
  "svelte"
16099
15931
  ]);
16100
15932
  PROVIDER_ASSET_FILES = {
16101
- auth: "provider-auth.png",
16102
- clerk: "provider-clerk.png",
16103
- database: "provider-database.png",
16104
- env: "provider-env.png",
16105
- github: "provider-github.png",
16106
- posthog: "provider-posthog.png",
16107
- resend: "provider-resend.png",
16108
- sentry: "provider-sentry.png",
16109
- stripe: "provider-stripe.png",
16110
- supabase: "provider-supabase.png",
16111
- upstash: "provider-upstash.png",
16112
- vercel: "provider-vercel.png",
16113
15933
  authjs: "provider-authjs.svg",
16114
15934
  logrocket: "provider-logrocket.svg",
16115
15935
  aws: "provider-aws.svg"
@@ -16127,16 +15947,16 @@ var init_providerLogos = __esm({
16127
15947
  turso: "https://cdn.simpleicons.org/turso/4FF8D2",
16128
15948
  "lemon-squeezy": "https://cdn.simpleicons.org/lemonsqueezy/FFC233",
16129
15949
  stripe: "https://cdn.simpleicons.org/stripe/635BFF",
16130
- github: "https://cdn.simpleicons.org/github/181717",
15950
+ github: "https://cdn.simpleicons.org/github/FFFFFF",
16131
15951
  gitlab: "https://cdn.simpleicons.org/gitlab/FC6D26",
16132
- vercel: "https://cdn.simpleicons.org/vercel/000000",
15952
+ vercel: "https://cdn.simpleicons.org/vercel/FFFFFF",
16133
15953
  netlify: "https://cdn.simpleicons.org/netlify/00C7B7",
16134
15954
  render: "https://cdn.simpleicons.org/render/46E3B7",
16135
15955
  railway: "https://cdn.simpleicons.org/railway/0B0D0E",
16136
15956
  cloudflare: "https://cdn.simpleicons.org/cloudflare/F38020",
16137
- sentry: "https://cdn.simpleicons.org/sentry/362D59",
15957
+ sentry: "https://cdn.simpleicons.org/sentry/8B5CF6",
16138
15958
  posthog: "https://cdn.simpleicons.org/posthog/F54E00",
16139
- resend: "https://cdn.simpleicons.org/resend/000000",
15959
+ resend: "https://cdn.simpleicons.org/resend/FFFFFF",
16140
15960
  upstash: "https://cdn.simpleicons.org/upstash/00E9A3",
16141
15961
  playwright: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/playwright/playwright-original.svg",
16142
15962
  figma: "https://cdn.simpleicons.org/figma/F24E1E",
@@ -16170,7 +15990,7 @@ var init_providerLogos = __esm({
16170
15990
  // src/local-ui/prompts.ts
16171
15991
  function buildLocalUiPrompt(input) {
16172
15992
  const lines = [
16173
- "You are fixing one VibeRaven production-readiness gap.",
15993
+ "You are fixing one VibeRaven what-changed gap.",
16174
15994
  "",
16175
15995
  `Project: ${input.projectName}`,
16176
15996
  `Provider: ${input.providerName}`,
@@ -16184,7 +16004,7 @@ function buildLocalUiPrompt(input) {
16184
16004
  "- .viberaven/gate-result.json",
16185
16005
  "",
16186
16006
  "Fix only this repo-code gap.",
16187
- "Do not claim production-ready until VibeRaven verify is clear.",
16007
+ "Do not claim the app is ready until VibeRaven verify is clear.",
16188
16008
  "Provider dashboard setup remains manual unless VibeRaven has live provider evidence.",
16189
16009
  "After the fix, run:",
16190
16010
  "npx -y viberaven --verify"
@@ -16506,7 +16326,7 @@ function buildMissionCards(artifact, providers) {
16506
16326
  const connectProviders = buildConnectProviders(providers);
16507
16327
  const blockerCount = blockers.length;
16508
16328
  const hasScan = Boolean(artifact.scannedAt);
16509
- const summary = !hasScan ? "Run `npx -y viberaven --agent-mode` to scan this project and surface production blockers." : blockerCount === 0 ? "No launch blockers detected in the latest scan." : `I analyzed the production rollout and found ${blockerCount} blocker${blockerCount === 1 ? "" : "s"} preventing a safe deploy.`;
16329
+ const summary = !hasScan ? "Open VibeRaven Studio to inspect what changed and surface missing release or provider context." : blockerCount === 0 ? "No context blockers detected in the latest evidence." : `I analyzed the release evidence and found ${blockerCount} context blocker${blockerCount === 1 ? "" : "s"} to resolve before the next fix.`;
16510
16330
  return {
16511
16331
  summary,
16512
16332
  blockerCount,
@@ -16964,7 +16784,6 @@ const demo = {
16964
16784
  activeModal: null,
16965
16785
  activeStudioTab: 'chat',
16966
16786
  selectedCliId: 'codex',
16967
- agentPermissionMode: 'ask',
16968
16787
  cliConnected: false,
16969
16788
  cliSetupComplete: false,
16970
16789
  cliConnectTargetId: null,
@@ -16983,11 +16802,13 @@ const demo = {
16983
16802
  selectedModelId: 'gpt-5.5',
16984
16803
  selectedReasoning: 'High',
16985
16804
  selectedContext: 'Production',
16805
+ selectedAccessMode: 'approve',
16986
16806
  modelMenuOpen: false,
16987
16807
  reasoningMenuOpen: false,
16988
16808
  contextMenuOpen: false,
16809
+ accessMenuOpen: false,
16989
16810
  pickerChatIndex: 0,
16990
- chatContexts: [{ providerId: null, releaseId: null, cliId: 'codex', modelId: 'gpt-5.5', reasoning: 'High', context: 'Production', messages: [], activeTask: null }],
16811
+ chatContexts: [{ providerId: null, releaseId: null, cliId: 'codex', modelId: 'gpt-5.5', reasoning: 'High', context: 'Production', accessMode: 'approve', messages: [], activeTask: null }],
16991
16812
  activeRecentChatId: null,
16992
16813
  droppedProviderId: null,
16993
16814
  dragKind: null,
@@ -17001,23 +16822,6 @@ const demo = {
17001
16822
  releaseChangelog: { entries: [], from: '', to: '', fromLabel: '', toLabel: '', loading: false, error: '' },
17002
16823
  };
17003
16824
 
17004
- function readPermissionMode() {
17005
- try {
17006
- const raw = localStorage.getItem('viberaven:agentChatPermissionMode');
17007
- return raw === 'full-access' ? 'full-access' : 'ask';
17008
- } catch {
17009
- return 'ask';
17010
- }
17011
- }
17012
-
17013
- function savePermissionMode(mode) {
17014
- try {
17015
- localStorage.setItem('viberaven:agentChatPermissionMode', mode);
17016
- } catch {
17017
- // Ignore storage failures in preview shells.
17018
- }
17019
- }
17020
-
17021
16825
  function readCliSessionReady() {
17022
16826
  try {
17023
16827
  let raw = localStorage.getItem('viberaven-cli-ready');
@@ -17040,7 +16844,6 @@ function writeCliSessionReady(value) {
17040
16844
  }
17041
16845
 
17042
16846
  demo.cliSessionReady = readCliSessionReady();
17043
- demo.agentPermissionMode = readPermissionMode();
17044
16847
 
17045
16848
  function cliAgentInstalled(agent) {
17046
16849
  if (!agent) return false;
@@ -17123,17 +16926,17 @@ const providerMarkAssets = {
17123
16926
  };
17124
16927
 
17125
16928
  const mascotAssets = {
17126
- idle: '/report/assets/viberaven-mascot-idle.png',
17127
- fixing: '/report/assets/viberaven-mascot-fixing.png',
17128
- verified: '/report/assets/viberaven-mascot-verified.png',
17129
- alert: '/report/assets/viberaven-mascot-alert.png',
16929
+ idle: '/report/assets/viberaven-mascot.png',
16930
+ fixing: '/report/assets/viberaven-mascot.png',
16931
+ verified: '/report/assets/viberaven-mascot.png',
16932
+ alert: '/report/assets/viberaven-mascot.png',
17130
16933
  };
17131
16934
 
17132
16935
  const providerDashboardUrls = {
17133
16936
  supabase: 'https://supabase.com/dashboard/projects',
17134
16937
  vercel: 'https://vercel.com/dashboard',
17135
16938
  stripe: 'https://dashboard.stripe.com',
17136
- github: 'https://github.com/ohad6k/VibeRaven',
16939
+ github: 'https://github.com/new',
17137
16940
  sentry: 'https://sentry.io',
17138
16941
  posthog: 'https://app.posthog.com',
17139
16942
  clerk: 'https://dashboard.clerk.com',
@@ -17146,6 +16949,14 @@ const publicGithubUrl = 'https://github.com/ohad6k/VibeRaven';
17146
16949
  const publicGithubApiUrl = 'https://api.github.com/repos/ohad6k/VibeRaven';
17147
16950
  const docsUrl = 'https://viberaven.dev';
17148
16951
  const communityUrl = 'https://github.com/ohad6k/VibeRaven/discussions/7';
16952
+ const goLiveUrls = {
16953
+ githubLogin: 'https://github.com/login',
16954
+ githubNew: 'https://github.com/new',
16955
+ githubCliAuth: 'https://cli.github.com/manual/gh_auth_login',
16956
+ vercelLogin: 'https://vercel.com/login',
16957
+ vercelNew: 'https://vercel.com/new',
16958
+ vercelDashboard: 'https://vercel.com/dashboard',
16959
+ };
17149
16960
 
17150
16961
  const githubStats = {
17151
16962
  loading: false,
@@ -17335,6 +17146,52 @@ function providerHealthIcon(health) {
17335
17146
  return Icon('refresh');
17336
17147
  }
17337
17148
 
17149
+ function providerMcp(provider) {
17150
+ return provider && provider.mcp ? provider.mcp : {
17151
+ status: 'disconnected',
17152
+ label: 'Connect MCP',
17153
+ connectCommand: 'Add this provider to your local MCP config, then drag it into chat.',
17154
+ capabilities: [],
17155
+ };
17156
+ }
17157
+
17158
+ function providerMcpChip(provider) {
17159
+ const mcp = providerMcp(provider);
17160
+ const connected = mcp.status === 'connected';
17161
+ const label = connected ? 'MCP connected' : 'MCP not connected';
17162
+ return '<span class="vr-provider-mcp-chip ' + (connected ? 'is-connected' : 'is-disconnected') + '" title="' + escapeHtml(label) + '" aria-label="' + escapeHtml(label) + '">' +
17163
+ '<i></i><span>' + escapeHtml(label) + '</span>' +
17164
+ '</span>';
17165
+ }
17166
+
17167
+ function providerAssetSrc(provider) {
17168
+ if (!provider) return providerAssets.supabase;
17169
+ return providerMarkAssets[provider.id] || providerAssets[provider.id] || providerAssets.supabase;
17170
+ }
17171
+
17172
+ function ProviderToken(provider, extraClass) {
17173
+ const className = 'vr-provider-token' + (extraClass ? ' ' + extraClass : '');
17174
+ const iconHtml = provider && provider.iconHtml ? String(provider.iconHtml) : '';
17175
+ return '<span class="' + className + '">' + (iconHtml.trim() ? iconHtml : '<img src="' + providerAssetSrc(provider) + '" alt="" />') + '</span>';
17176
+ }
17177
+
17178
+ function ProviderLogo(provider, className) {
17179
+ const iconHtml = provider && provider.iconHtml ? String(provider.iconHtml) : '';
17180
+ return iconHtml.trim()
17181
+ ? '<span class="' + className + ' is-logo-html">' + iconHtml + '</span>'
17182
+ : '<img class="' + className + '" src="' + providerAssetSrc(provider) + '" alt="" />';
17183
+ }
17184
+
17185
+ function ProviderMcpPanel(provider) {
17186
+ const mcp = providerMcp(provider);
17187
+ const connected = mcp.status === 'connected';
17188
+ const capabilities = Array.isArray(mcp.capabilities) && mcp.capabilities.length ? mcp.capabilities : ['provider context', 'repo-aware chat'];
17189
+ return '<section class="vr-provider-mcp-panel ' + (connected ? 'is-connected' : 'is-disconnected') + '">' +
17190
+ '<header><span>' + Icon('agent') + '</span><div><strong>' + escapeHtml(connected ? 'MCP connected' : 'Connect MCP') + '</strong><em>' + escapeHtml(connected ? (mcp.source || 'local MCP config') : (mcp.connectCommand || 'Add this provider MCP server in your local MCP config.')) + '</em></div></header>' +
17191
+ '<div>' + capabilities.map((item) => '<small>' + escapeHtml(item) + '</small>').join('') + '</div>' +
17192
+ '</section>';
17193
+ }
17194
+
17338
17195
  function normalizeProvider(provider) {
17339
17196
  const missing = provider.state === 'not_detected';
17340
17197
  return {
@@ -17348,6 +17205,8 @@ function normalizeProvider(provider) {
17348
17205
  lastSync: currentState.project && currentState.project.scannedAt ? 'scan artifact' : 'startup',
17349
17206
  checks: providerChecks(provider),
17350
17207
  state: provider.state || 'not_detected',
17208
+ mcp: provider.mcp || null,
17209
+ iconHtml: provider.iconHtml || '',
17351
17210
  };
17352
17211
  }
17353
17212
 
@@ -17552,6 +17411,11 @@ let cliModels = {
17552
17411
 
17553
17412
  const reasoningLevels = ['Low', 'Medium', 'High', 'Extra High'];
17554
17413
  const contextLevels = ['Production', 'Provider', 'Release', 'Security'];
17414
+ const accessModes = [
17415
+ { id: 'ask', label: 'Ask approval', description: 'Confirm edits and external access' },
17416
+ { id: 'approve', label: 'Approve for me', description: 'Run safe repo actions automatically' },
17417
+ { id: 'full', label: 'Full access', description: 'Unrestricted local project access' },
17418
+ ];
17555
17419
  const topStages = [
17556
17420
  { id: 'provider', number: '1', label: 'Provider Proof', state: 'Waiting' },
17557
17421
  { id: 'agent', number: '2', label: 'Agent Fix', state: 'Ready' },
@@ -17653,6 +17517,7 @@ function buildRecentChatEntry(prompt, provider, release, chat, existing) {
17653
17517
  modelId: lane.modelId || base.modelId || demo.selectedModelId || 'gpt-5.5',
17654
17518
  reasoning: lane.reasoning || base.reasoning || demo.selectedReasoning || 'High',
17655
17519
  context: lane.context || base.context || demo.selectedContext || 'Production',
17520
+ accessMode: lane.accessMode || base.accessMode || demo.selectedAccessMode || 'approve',
17656
17521
  messages: serializeChatMessages(lane.messages),
17657
17522
  };
17658
17523
  }
@@ -17680,6 +17545,7 @@ function syncDemoFromChatContext(context) {
17680
17545
  demo.selectedModelId = context.modelId;
17681
17546
  demo.selectedReasoning = context.reasoning;
17682
17547
  demo.selectedContext = context.context;
17548
+ demo.selectedAccessMode = context.accessMode || 'approve';
17683
17549
  if (context.providerId) demo.selectedProviderId = context.providerId;
17684
17550
  if (context.releaseId) demo.selectedReleaseId = context.releaseId;
17685
17551
  syncPrimaryContext();
@@ -17694,6 +17560,7 @@ function restoreRecentChat(recent) {
17694
17560
  modelId: recent.modelId,
17695
17561
  reasoning: recent.reasoning,
17696
17562
  context: recent.context,
17563
+ accessMode: recent.accessMode,
17697
17564
  messages: recent.messages || [],
17698
17565
  draft: '',
17699
17566
  activeTask: null,
@@ -17802,14 +17669,14 @@ function GitHubStats() {
17802
17669
  function agentPromptText() {
17803
17670
  const provider = providers.find((item) => item.id === demo.selectedProviderId) || providers[0];
17804
17671
  return [
17805
- 'You are fixing one VibeRaven launch-readiness gap.',
17672
+ 'You are fixing one VibeRaven what-changed gap.',
17806
17673
  '',
17807
17674
  'Project: ' + projectName(),
17808
17675
  'Focus: ' + provider.name + ' ' + provider.area,
17809
17676
  'Stage: ' + (demo.activeStepId || 'agent'),
17810
17677
  '',
17811
17678
  'Goal:',
17812
- '- Find the smallest repo-side fix that improves launch readiness.',
17679
+ '- Find the smallest repo-side fix grounded in what changed.',
17813
17680
  '- Do not claim provider dashboard work from code alone.',
17814
17681
  '- Keep the change scoped and verify through the VibeRaven UI action.',
17815
17682
  '',
@@ -17913,6 +17780,9 @@ function contextIconChip(iconName, size) {
17913
17780
  }
17914
17781
 
17915
17782
  function BrandMark(id) {
17783
+ if (id === 'github') {
17784
+ return '<span class="vr-inline-brand-mark is-github"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 2C6.48 2 2 6.58 2 12.26c0 4.52 2.87 8.35 6.86 9.71.5.1.69-.22.69-.49 0-.24-.01-.87-.01-1.7-2.78.62-3.37-1.36-3.37-1.36-.45-1.17-1.11-1.48-1.11-1.48-.91-.64.07-.63.07-.63 1 .07 1.53 1.05 1.53 1.05.9 1.56 2.36 1.11 2.94.85.09-.67.35-1.11.63-1.37-2.22-.26-4.56-1.14-4.56-5.07 0-1.12.39-2.03 1.03-2.75-.1-.26-.45-1.3.1-2.7 0 0 .84-.28 2.75 1.05A9.2 9.2 0 0 1 12 6.84c.85 0 1.71.12 2.51.34 1.91-1.33 2.75-1.05 2.75-1.05.55 1.4.2 2.44.1 2.7.64.72 1.03 1.63 1.03 2.75 0 3.94-2.34 4.8-4.57 5.06.36.32.68.94.68 1.9 0 1.37-.01 2.47-.01 2.8 0 .27.18.6.7.49A10.03 10.03 0 0 0 22 12.26C22 6.58 17.52 2 12 2Z"/></svg></span>';
17785
+ }
17916
17786
  return '<span class="vr-inline-brand-mark"><img src="' + escapeHtml(providerMarkAssets[id] || providerAssets[id]) + '" alt="" /></span>';
17917
17787
  }
17918
17788
 
@@ -17938,6 +17808,7 @@ function defaultChatContext(seed) {
17938
17808
  modelId: source.modelId || demo.selectedModelId || normalizeModelId(models[0]),
17939
17809
  reasoning: source.reasoning || demo.selectedReasoning || 'High',
17940
17810
  context: source.context || demo.selectedContext || 'Production',
17811
+ accessMode: source.accessMode || demo.selectedAccessMode || 'approve',
17941
17812
  draft: source.draft || '',
17942
17813
  messages: Array.isArray(source.messages) ? source.messages.slice() : [],
17943
17814
  activeTask: source.activeTask || null,
@@ -18053,7 +17924,7 @@ function resolveQuickActionMission(kind, chatIndex, promptOverride) {
18053
17924
  const topBlocker = blockers[0];
18054
17925
  const gateClear = gate.status === 'clear';
18055
17926
  const gateLabel = gate.label || 'Waiting for project evidence';
18056
- const mainBlocker = mc.mainBlocker || topBlocker?.title || 'Run a scan to find launch blockers';
17927
+ const mainBlocker = mc.mainBlocker || topBlocker?.title || 'Open context to find what changed';
18057
17928
  const blockerText = formatBlockerLines(blockers, 6);
18058
17929
  const planText = formatPlanLines(planSteps, 8);
18059
17930
  const connectText = connectProviders.slice(0, 5).map((item) => '- ' + item.name + ' (' + item.status + ')').join('\\n');
@@ -18062,12 +17933,12 @@ function resolveQuickActionMission(kind, chatIndex, promptOverride) {
18062
17933
 
18063
17934
  const missions = {
18064
17935
  analyze: {
18065
- title: 'Analyzing launch blockers',
18066
- label: blockers.length ? 'Analyze ' + blockers.length + ' blocker' + (blockers.length === 1 ? '' : 's') : 'Analyze launch readiness',
17936
+ title: 'Analyzing what changed',
17937
+ label: blockers.length ? 'Analyze ' + blockers.length + ' blocker' + (blockers.length === 1 ? '' : 's') : 'Analyze what changed',
18067
17938
  prompt: [
18068
- 'Analyze production launch readiness in this project folder.',
17939
+ 'Analyze what changed in this project folder.',
18069
17940
  '',
18070
- 'Gate: ' + gateLabel + ' (' + (gate.status || 'unknown') + ')',
17941
+ 'Project status: ' + gateLabel + ' (' + (gate.status || 'unknown') + ')',
18071
17942
  'Main blocker: ' + mainBlocker,
18072
17943
  blockers.length ? 'Known blockers from the latest scan:\\n' + blockerText : 'No blockers loaded yet \u2014 inspect .viberaven/gate-result.json and agent-tasklist.md if present.',
18073
17944
  connectText ? '\\nProviders needing connect:\\n' + connectText : '',
@@ -18079,15 +17950,15 @@ function resolveQuickActionMission(kind, chatIndex, promptOverride) {
18079
17950
  ].filter(Boolean).join('\\n'),
18080
17951
  line: 'Reading repo evidence, provider proof, and release context.',
18081
17952
  steps: ['Scan evidence', 'Rank risks', 'Prepare fix plan'],
18082
- notice: blockers.length ? 'Analyzing ' + blockers.length + ' launch blocker' + (blockers.length === 1 ? '' : 's') + '.' : 'Analyzing launch readiness.',
17953
+ notice: blockers.length ? 'Analyzing ' + blockers.length + ' blocker' + (blockers.length === 1 ? '' : 's') + '.' : 'Analyzing what changed.',
18083
17954
  },
18084
17955
  plan: {
18085
17956
  title: 'Building fix plan',
18086
- label: planSteps.length ? 'Production fix plan \xB7 ' + planSteps.length + ' step' + (planSteps.length === 1 ? '' : 's') : 'Build production fix plan',
17957
+ label: planSteps.length ? 'Fix plan \xB7 ' + planSteps.length + ' action' + (planSteps.length === 1 ? '' : 's') : 'Build fix plan',
18087
17958
  prompt: [
18088
- 'Build a safe, ordered production fix plan for this launch.',
17959
+ 'Build a safe, ordered fix plan from the current what-changed context.',
18089
17960
  '',
18090
- 'Gate: ' + gateLabel,
17961
+ 'Project status: ' + gateLabel,
18091
17962
  'Main blocker: ' + mainBlocker,
18092
17963
  blockers.length ? 'Blockers (' + blockers.length + '):\\n' + blockerText : 'No scan blockers loaded \u2014 inspect .viberaven artifacts first.',
18093
17964
  planSteps.length ? '\\nSuggested steps from scan:\\n' + planText : '',
@@ -18106,7 +17977,7 @@ function resolveQuickActionMission(kind, chatIndex, promptOverride) {
18106
17977
  title: 'Applying scoped fix',
18107
17978
  label: topBlocker ? 'Agent fix \xB7 ' + truncateMissionLabel(topBlocker.title, 34) : 'Apply next repo fix',
18108
17979
  prompt: [
18109
- 'Apply ONE scoped repo fix for the highest-priority launch blocker.',
17980
+ 'Apply ONE scoped repo fix for the highest-priority what-changed blocker.',
18110
17981
  '',
18111
17982
  topBlocker ? 'Target blocker: ' + topBlocker.title : 'Target: ' + mainBlocker,
18112
17983
  topBlocker?.detail ? 'Detail: ' + topBlocker.detail : '',
@@ -18121,17 +17992,17 @@ function resolveQuickActionMission(kind, chatIndex, promptOverride) {
18121
17992
  '- Do not claim provider dashboard setup is complete from repo edits alone.',
18122
17993
  '- After edits, list files touched and recommend verify.',
18123
17994
  ].filter(Boolean).join('\\n'),
18124
- line: 'Patching only the selected production gap, then preparing verification.',
17995
+ line: 'Patching only the selected what-changed gap, then preparing verification.',
18125
17996
  steps: ['Patch code', 'Update proof', 'Prepare verify'],
18126
17997
  notice: topBlocker ? 'Agent fix started for: ' + truncateMissionLabel(topBlocker.title, 48) + '.' : 'Agent fix mission started.',
18127
17998
  },
18128
17999
  verify: {
18129
18000
  title: 'Running verification',
18130
- label: gateClear ? 'Re-verify launch gate' : 'Verify launch gate',
18001
+ label: gateClear ? 'Re-verify context' : 'Verify context',
18131
18002
  prompt: [
18132
- 'Verify production launch readiness for this project.',
18003
+ 'Verify the current what-changed context for this project.',
18133
18004
  '',
18134
- 'Gate: ' + gateLabel + ' (' + (gate.status || 'unknown') + ')',
18005
+ 'Project status: ' + gateLabel + ' (' + (gate.status || 'unknown') + ')',
18135
18006
  'Main blocker: ' + mainBlocker,
18136
18007
  blockers.length ? 'Open blockers:\\n' + blockerText : '',
18137
18008
  '',
@@ -18142,15 +18013,15 @@ function resolveQuickActionMission(kind, chatIndex, promptOverride) {
18142
18013
  ].filter(Boolean).join('\\n'),
18143
18014
  line: 'Checking evidence, provider state, and release readiness.',
18144
18015
  steps: ['Run checks', 'Read proof', 'Mark status'],
18145
- notice: gateClear ? 'Re-verifying launch proof.' : 'Running launch gate verification.',
18016
+ notice: gateClear ? 'Re-checking release proof.' : 'Checking evidence, provider state, and release context.',
18146
18017
  },
18147
18018
  diff: {
18148
18019
  title: 'Reviewing diff',
18149
- label: 'Review production diff',
18020
+ label: 'Review release diff',
18150
18021
  prompt: [
18151
- 'Review the current production diff for this project.',
18022
+ 'Review the current release diff for this project.',
18152
18023
  '',
18153
- 'Gate: ' + gateLabel,
18024
+ 'Project status: ' + gateLabel,
18154
18025
  topBlocker ? 'Top blocker context: ' + topBlocker.title : '',
18155
18026
  '',
18156
18027
  'Show grouped changes, flag risky edits, and say what still needs verify before release.',
@@ -18163,9 +18034,9 @@ function resolveQuickActionMission(kind, chatIndex, promptOverride) {
18163
18034
  title: 'Explaining changes',
18164
18035
  label: 'Explain changes & next steps',
18165
18036
  prompt: [
18166
- 'Explain recent production changes and what to verify next.',
18037
+ 'Explain what changed and what to verify next.',
18167
18038
  '',
18168
- 'Gate: ' + gateLabel,
18039
+ 'Project status: ' + gateLabel,
18169
18040
  mainBlocker ? 'Main blocker: ' + mainBlocker : '',
18170
18041
  blockers.length ? 'Active blockers:\\n' + blockerText : '',
18171
18042
  '',
@@ -18206,6 +18077,38 @@ function resolveQuickActionMission(kind, chatIndex, promptOverride) {
18206
18077
  steps: missingProvider ? ['Check repo', 'List env', 'Dashboard steps'] : ['Read provider', 'Check proof', 'Attach context'],
18207
18078
  notice: missingProvider ? provider.name + ' connect mission started.' : provider.name + ' proof check started.',
18208
18079
  },
18080
+ 'go-live': {
18081
+ title: 'Preparing GitHub and Vercel launch',
18082
+ label: 'Go live on GitHub + Vercel',
18083
+ prompt: [
18084
+ 'Take this local project live through GitHub and Vercel with explicit proof.',
18085
+ '',
18086
+ 'Project status: ' + gateLabel + ' (' + (gate.status || 'unknown') + ')',
18087
+ 'Main blocker: ' + mainBlocker,
18088
+ blockers.length ? 'Known blockers from the latest scan:\\n' + blockerText : 'No scan blockers loaded yet - inspect the repo and .viberaven artifacts if present.',
18089
+ connectText ? '\\nProviders needing connect:\\n' + connectText : '',
18090
+ '',
18091
+ 'Launch path:',
18092
+ '1. Inspect git status, branch, remotes, package scripts, Vercel config, and deploy notes before changing anything.',
18093
+ '2. Detect GitHub/Vercel tools with gh --version, gh auth status, vercel --version or npx vercel --version, and vercel whoami or npx vercel whoami.',
18094
+ '3. Run the narrowest local build/typecheck/test command that proves the app can ship.',
18095
+ '4. If no GitHub remote exists and gh is authenticated, create the repo and push after repo name/visibility are clear. If auth/manual setup is needed, open ' + goLiveUrls.githubLogin + ' or ' + goLiveUrls.githubNew + '.',
18096
+ '5. Connect or verify Vercel project linkage, framework/build settings, env var names, and production deploy command. If auth/manual setup is needed, open ' + goLiveUrls.vercelLogin + ', ' + goLiveUrls.vercelNew + ', or ' + goLiveUrls.vercelDashboard + '.',
18097
+ '6. Deploy when auth and intent are clear for the selected access mode. Capture deployment URL and verify it if possible.',
18098
+ '',
18099
+ 'Rules:',
18100
+ '- Do every safe step directly. Do not stop at a checklist if commands or official pages can move the launch forward.',
18101
+ '- Do not include .env files, secrets, build output, or unrelated dirty work in commits.',
18102
+ '- Do not ask for passwords, cookies, tokens, API keys, or secret values.',
18103
+ '- Do not claim GitHub or Vercel dashboard state is complete without CLI, MCP, dashboard, or live URL proof.',
18104
+ '- Avoid destructive git operations and force pushes unless the user explicitly asks and the risk is explained.',
18105
+ '',
18106
+ 'Return a launch receipt with GitHub repo/branch/SHA, Vercel project/deployment URL, local proof command, live proof result, links opened, and remaining dashboard actions.',
18107
+ ].filter(Boolean).join('\\n'),
18108
+ line: 'Connecting repo evidence to GitHub, Vercel, and live deployment proof.',
18109
+ steps: ['Check repo', 'Push GitHub', 'Deploy Vercel', 'Verify live'],
18110
+ notice: 'Go Live mission started for GitHub and Vercel.',
18111
+ },
18209
18112
  };
18210
18113
 
18211
18114
  const mission = missions[kind] || missions.analyze;
@@ -18269,7 +18172,7 @@ function quickActionButtonSpec(index) {
18269
18172
  action: 'plan',
18270
18173
  icon: 'report',
18271
18174
  label: planSteps.length ? 'Plan \xB7 ' + planSteps.length : 'Plan',
18272
- hint: planSteps.length ? 'Build production fix plan \xB7 ' + planSteps.length + ' steps' : 'Build production fix plan',
18175
+ hint: planSteps.length ? 'Build fix plan \xB7 ' + planSteps.length + ' actions' : 'Build fix plan',
18273
18176
  primary: true,
18274
18177
  },
18275
18178
  {
@@ -18284,7 +18187,14 @@ function quickActionButtonSpec(index) {
18284
18187
  action: 'verify-now',
18285
18188
  icon: 'shield',
18286
18189
  label: gateClear ? 'Re-verify' : 'Verify',
18287
- hint: gateClear ? 'Re-verify launch gate' : 'Verify launch gate',
18190
+ hint: gateClear ? 'Re-verify readiness' : 'Verify readiness',
18191
+ primary: true,
18192
+ },
18193
+ {
18194
+ action: 'go-live',
18195
+ icon: 'cloud',
18196
+ label: 'Go live',
18197
+ hint: 'Push GitHub + deploy Vercel',
18288
18198
  primary: true,
18289
18199
  },
18290
18200
  {
@@ -18348,7 +18258,7 @@ function runChatTask(kind, promptOverride) {
18348
18258
  const responseText = isError
18349
18259
  ? (message || 'The connected CLI did not return a usable response.')
18350
18260
  : (message || 'Ready for the next safe action.');
18351
- const attachKinds = ['analyze', 'plan', 'provider', 'verify'];
18261
+ const attachKinds = ['analyze', 'plan', 'provider', 'verify', 'go-live'];
18352
18262
  const cards = attachKinds.includes(kind)
18353
18263
  ? (cardsPayload || missionCards)
18354
18264
  : (cardsPayload && ['diff', 'explain'].includes(kind) ? cardsPayload : null);
@@ -18373,7 +18283,7 @@ function runChatTask(kind, promptOverride) {
18373
18283
  demo.notice = 'Verification finished in chat. Launch proof is green.';
18374
18284
  } else if (kind === 'fix') {
18375
18285
  demo.activeStepId = 'verify';
18376
- demo.notice = 'Fix prepared in chat. Run Verify to clear the launch gate.';
18286
+ demo.notice = 'Fix prepared in chat. Run Verify to update release proof.';
18377
18287
  } else {
18378
18288
  demo.notice = taskMeta(kind).title + ' finished in chat.';
18379
18289
  }
@@ -18395,12 +18305,12 @@ function runChatTask(kind, promptOverride) {
18395
18305
  modelId: selectedModelLabel(chatIndex),
18396
18306
  reasoning: chat.reasoning,
18397
18307
  context: chat.context,
18308
+ accessMode: chat.accessMode || 'approve',
18398
18309
  prompt,
18399
18310
  displayPrompt: label,
18400
18311
  taskKind: kind,
18401
- permissionMode: demo.agentPermissionMode,
18402
- provider: { area: provider.area, name: provider.name },
18403
- release: release ? { label: release.label } : undefined
18312
+ provider: { id: provider.id, area: provider.area, name: provider.name },
18313
+ release: release ? { id: release.id, label: release.label } : undefined
18404
18314
  })
18405
18315
  })
18406
18316
  .then(async (response) => {
@@ -18429,7 +18339,7 @@ function sendChatInput(chatIndex) {
18429
18339
  }
18430
18340
  chat.draft = '';
18431
18341
  if (input && 'value' in input) input.value = '';
18432
- runChatTask(chat.providerId ? 'provider' : 'analyze', value);
18342
+ runChatTask(chat.releaseId ? 'diff' : chat.providerId ? 'provider' : 'analyze', value);
18433
18343
  }
18434
18344
 
18435
18345
  function resetLaunchPreview() {
@@ -18449,11 +18359,13 @@ function resetLaunchPreview() {
18449
18359
  demo.selectedModelId = 'gpt-5.5';
18450
18360
  demo.selectedReasoning = 'High';
18451
18361
  demo.selectedContext = 'Production';
18362
+ demo.selectedAccessMode = 'approve';
18452
18363
  demo.modelMenuOpen = false;
18453
18364
  demo.reasoningMenuOpen = false;
18454
18365
  demo.contextMenuOpen = false;
18366
+ demo.accessMenuOpen = false;
18455
18367
  demo.pickerChatIndex = 0;
18456
- demo.chatContexts = [defaultChatContext({ cliId: 'codex', modelId: 'gpt-5.5', reasoning: 'High', context: 'Production' })];
18368
+ demo.chatContexts = [defaultChatContext({ cliId: 'codex', modelId: 'gpt-5.5', reasoning: 'High', context: 'Production', accessMode: 'approve' })];
18457
18369
  demo.droppedProviderId = null;
18458
18370
  demo.droppedReleaseId = null;
18459
18371
  clearChatTaskTimer();
@@ -18523,10 +18435,10 @@ function RecentChatRail() {
18523
18435
 
18524
18436
  function ProviderCard(provider) {
18525
18437
  const slot = stackSlots[provider.id] || provider.area;
18526
- return '<button class="vr-provider-card ' + (provider.id === demo.selectedProviderId ? 'is-selected' : '') + '" type="button" draggable="true" data-provider="' + escapeHtml(provider.id) + '" aria-label="Open ' + escapeHtml(provider.name) + ' stack slot">' +
18527
- '<span class="vr-provider-token"><img src="' + (providerMarkAssets[provider.id] || providerAssets[provider.id]) + '" alt="" /></span>' +
18528
- '<span class="vr-provider-light"></span>' +
18438
+ return '<button class="vr-provider-card ' + (provider.id === demo.selectedProviderId ? 'is-selected' : '') + '" type="button" draggable="true" data-provider="' + escapeHtml(provider.id) + '" data-provider-tone="' + escapeHtml(provider.tone || 'neutral') + '" aria-label="Open ' + escapeHtml(provider.name) + ' stack slot">' +
18439
+ ProviderToken(provider) +
18529
18440
  '<div><small>' + escapeHtml(slot) + '</small><strong>' + escapeHtml(provider.name) + '</strong><em>' + escapeHtml(provider.status) + '</em></div>' +
18441
+ providerMcpChip(provider) +
18530
18442
  '<span class="vr-provider-proof-chip"><span>Open</span>' + Icon('chevronRight') + '</span>' +
18531
18443
  '</button>';
18532
18444
  }
@@ -18534,9 +18446,10 @@ function ProviderCard(provider) {
18534
18446
  function ProviderDetailPanel() {
18535
18447
  const provider = providers.find((item) => item.id === demo.selectedProviderId) || providers[0];
18536
18448
  return '<aside class="vr-provider-detail-panel">' +
18537
- '<div class="vr-detail-head"><span class="vr-provider-token is-large"><img src="' + (providerMarkAssets[provider.id] || providerAssets[provider.id]) + '" alt="" /></span><div><span>' + escapeHtml(provider.area) + '</span><strong>' + escapeHtml(provider.name) + '</strong></div>' + StatusBadge(provider.status, provider.tone) + '</div>' +
18449
+ '<div class="vr-detail-head">' + ProviderToken(provider, 'is-large') + '<div><span>' + escapeHtml(provider.area) + '</span><strong>' + escapeHtml(provider.name) + '</strong></div>' + StatusBadge(provider.status, provider.tone) + '</div>' +
18538
18450
  '<p>' + escapeHtml(provider.detail) + '</p>' +
18539
18451
  '<div class="vr-provider-stats"><span><b>Checks</b><em>' + escapeHtml(provider.checks) + '</em></span><span><b>Region</b><em>' + escapeHtml(provider.region) + '</em></span><span><b>Last sync</b><em>' + escapeHtml(provider.lastSync) + '</em></span></div>' +
18452
+ ProviderMcpPanel(provider) +
18540
18453
  '<a class="vr-provider-dashboard" href="' + escapeHtml(providerDashboardUrls[provider.id] || docsUrl) + '" target="_blank" rel="noreferrer">Open dashboard ' + Icon('external') + '</a>' +
18541
18454
  '</aside>';
18542
18455
  }
@@ -18557,7 +18470,7 @@ function ProviderPicker() {
18557
18470
  return '<div class="vr-provider-picker" aria-label="Provider picker">' +
18558
18471
  '<div><strong>Connector picker</strong><span>Select one provider. VibeRaven opens its proof panel and next action.</span></div>' +
18559
18472
  '<div class="vr-provider-picker-list">' + boardProviders.map((provider) =>
18560
- '<button type="button" data-provider="' + escapeHtml(provider.id) + '"><span class="vr-provider-token is-picker"><img src="' + (providerMarkAssets[provider.id] || providerAssets[provider.id]) + '" alt="" /></span><span>' + escapeHtml(provider.name) + '</span></button>'
18473
+ '<button type="button" data-provider="' + escapeHtml(provider.id) + '">' + ProviderToken(provider, 'is-picker') + '<span>' + escapeHtml(provider.name) + '</span></button>'
18561
18474
  ).join('') + '</div>' +
18562
18475
  '</div>';
18563
18476
  }
@@ -18613,11 +18526,12 @@ function ProviderModal() {
18613
18526
  const checkRows = providerModalCheckRows(raw);
18614
18527
  return ModalShell('provider',
18615
18528
  '<header class="vr-modal-provider-head">' +
18616
- '<img class="vr-modal-provider-logo" src="' + (providerMarkAssets[provider.id] || providerAssets[provider.id]) + '" alt="" />' +
18529
+ ProviderLogo(provider, 'vr-modal-provider-logo') +
18617
18530
  '<div><h2>' + escapeHtml(provider.name) + '</h2>' + StatusBadge(provider.status, provider.tone) + '<p>' + escapeHtml(provider.area) + ' provider</p></div>' +
18618
18531
  '<img class="vr-modal-mascot" src="' + providerModalMascot(health) + '" alt="" />' +
18619
18532
  '</header>' +
18620
18533
  '<section class="vr-modal-health is-' + escapeHtml(health.tone) + '"><span>' + providerHealthIcon(health) + '</span><div><strong>' + escapeHtml(health.label) + '</strong><em>' + escapeHtml(health.summary) + '</em></div><b>' + escapeHtml(health.meta) + '</b></section>' +
18534
+ ProviderMcpPanel(provider) +
18621
18535
  '<div class="vr-modal-action-grid">' +
18622
18536
  GlowButton('Open slot', { action: 'guide', tone: 'purple' }) +
18623
18537
  '<button type="button" data-action="recheck">' + Icon('refresh') + 'Re-check</button>' +
@@ -18644,7 +18558,7 @@ function AddProviderModal() {
18644
18558
  '</header>' +
18645
18559
  '<section class="vr-modal-provider-options">' + featured.map((item) => {
18646
18560
  const provider = providers.find((candidate) => candidate.id === item.icon) || providers[0];
18647
- return '<button type="button" data-provider="' + escapeHtml(provider.id) + '"><span class="vr-provider-token is-large"><img src="' + (providerMarkAssets[provider.id] || providerAssets[provider.id]) + '" alt="" /></span><div><small>' + escapeHtml(item.slot) + '</small><strong>' + escapeHtml(item.provider) + '</strong><em>' + escapeHtml(item.caption) + '</em></div><b>Connect</b></button>';
18561
+ return '<button type="button" data-provider="' + escapeHtml(provider.id) + '">' + ProviderToken(provider, 'is-large') + '<div><small>' + escapeHtml(item.slot) + '</small><strong>' + escapeHtml(item.provider) + '</strong><em>' + escapeHtml(item.caption) + '</em></div><b>Connect</b></button>';
18648
18562
  }).join('') + '</section>' +
18649
18563
  '<section class="vr-modal-connect-note">' + Icon('lock') + '<span>VibeRaven only opens setup guidance here. Real credentials stay in your local runner or provider dashboard.</span></section>'
18650
18564
  );
@@ -18674,16 +18588,16 @@ function AgentModal() {
18674
18588
  return ModalShell('agent',
18675
18589
  '<header class="vr-modal-agent-head">' +
18676
18590
  '<img class="vr-modal-agent-avatar" src="' + mascotUrl() + '" alt="" />' +
18677
- '<div><p>Agent Action</p><h2>VibeRaven</h2><em>' + (verified ? 'Everything is verified in preview mode.' : fixing ? 'I am fixing the selected launch gap now.' : 'I will fix the issue and verify everything works as expected.') + '</em></div>' +
18591
+ '<div><p>Agent Action</p><h2>VibeRaven</h2><em>' + (verified ? 'Everything is verified in preview mode.' : fixing ? 'I am fixing the evidenced change now.' : 'I will fix the issue with release and provider context.') + '</em></div>' +
18678
18592
  '<aside>' + Icon('clock') + '<span>' + (verified ? 'Status' : 'Estimated time') + '</span><strong>' + (verified ? 'Complete' : fixing ? 'Running' : '2 - 4 min') + '</strong></aside>' +
18679
18593
  '</header>' +
18680
18594
  '<section class="vr-modal-tasklist"><h3>Task checklist</h3><ul>' +
18681
- ModalCheck('Diagnose issue', 'Find the highest-impact launch blocker.', fixing || verified ? 'done' : 'active', fixing || verified ? 'OK' : 'Ready') +
18682
- ModalCheck('Apply focused fix', 'Patch only the selected launch gap.', verified ? 'done' : fixing ? 'running' : 'pending', verified ? 'OK' : fixing ? 'Running' : 'Pending') +
18595
+ ModalCheck('Diagnose issue', 'Find the highest-impact context gap.', fixing || verified ? 'done' : 'active', fixing || verified ? 'OK' : 'Ready') +
18596
+ ModalCheck('Apply focused fix', 'Patch only the evidenced change.', verified ? 'done' : fixing ? 'running' : 'pending', verified ? 'OK' : fixing ? 'Running' : 'Pending') +
18683
18597
  ModalCheck('Run verification tests', 'Confirm the flow is safe after the fix.', verified ? 'done' : fixing ? 'active' : 'pending', verified ? 'OK' : fixing ? 'Queued' : 'Pending') +
18684
18598
  ModalCheck('Confirm systems operational', 'Move the launch flow to clear.', verified ? 'done' : 'pending') +
18685
18599
  '</ul></section>' +
18686
- '<section class="vr-modal-progress ' + (!verified && !fixing ? 'is-ready' : '') + '">' + Icon('shield') + '<div><strong>' + (verified ? 'Verification complete' : fixing ? 'Fix in progress' : 'Ready for focused fix') + '</strong><p>' + (verified ? 'The launch flow is green in preview mode.' : fixing ? 'Running checks to ensure a safe and reliable fix.' : 'Start the agent when you are ready to patch one selected launch gap.') + '</p></div>' + Icon('spark') + '</section>' +
18600
+ '<section class="vr-modal-progress ' + (!verified && !fixing ? 'is-ready' : '') + '">' + Icon('shield') + '<div><strong>' + (verified ? 'Verification complete' : fixing ? 'Fix in progress' : 'Ready for focused fix') + '</strong><p>' + (verified ? 'The launch flow is green in preview mode.' : fixing ? 'Running checks to keep the fix grounded.' : 'Start the agent when you are ready to patch the evidenced change.') + '</p></div>' + Icon('spark') + '</section>' +
18687
18601
  '<div class="vr-modal-button-row">' +
18688
18602
  GlowButton(fixing ? 'Fixing...' : verified ? 'Complete' : 'Start Agent Fix', { action: 'start-agent-fix', tone: verified ? 'green' : 'purple' }) +
18689
18603
  '<button type="button" data-action="verify-now">Verify Now</button>' +
@@ -18702,7 +18616,7 @@ function GuideModal() {
18702
18616
  '</header>' +
18703
18617
  '<section class="vr-modal-flow-list">' +
18704
18618
  '<button type="button" data-provider="' + escapeHtml(provider.id) + '"><span>1</span><div><strong>Review provider proof</strong><em>Open ' + escapeHtml(provider.name) + ' status and dashboard action.</em></div>' + Icon('external') + '</button>' +
18705
- '<button type="button" data-action="prompt"><span>2</span><div><strong>Open agent mission</strong><em>Give the connected CLI one scoped launch gap, not the whole app.</em></div>' + Icon('prompt') + '</button>' +
18619
+ '<button type="button" data-action="prompt"><span>2</span><div><strong>Open agent mission</strong><em>Give the connected CLI one evidenced change, not the whole app.</em></div>' + Icon('prompt') + '</button>' +
18706
18620
  '<button type="button" data-action="verify-now"><span>3</span><div><strong>Verify the flow</strong><em>Turn the launch path green after the focused fix.</em></div>' + Icon('check') + '</button>' +
18707
18621
  '</section>'
18708
18622
  );
@@ -18729,13 +18643,13 @@ function PlanModal() {
18729
18643
  return ModalShell('plan',
18730
18644
  '<header class="vr-modal-guide-head">' +
18731
18645
  '<img class="vr-modal-agent-avatar" src="' + mascotAssets.idle + '" alt="" />' +
18732
- '<div><p>Production Plan</p><h2>Safe fix path</h2><em>One scoped mission: fix the highest-risk launch blocker, verify it, then prepare release proof.</em></div>' +
18646
+ '<div><p>Release Plan</p><h2>Safe fix path</h2><em>One scoped mission: understand what changed, fix it, then prepare release proof.</em></div>' +
18733
18647
  '<aside>' + Icon('shield') + '<span>Context</span><strong>' + escapeHtml(provider.name) + '</strong></aside>' +
18734
18648
  '</header>' +
18735
18649
  '<section class="vr-modal-flow-list">' +
18736
18650
  '<button type="button" data-action="add-context"><span>1</span><div><strong>Add launch context</strong><em>Drag a provider or version into chat so the agent has the exact proof target.</em></div>' + Icon('plus') + '</button>' +
18737
- '<button type="button" data-action="prompt"><span>2</span><div><strong>Open scoped mission</strong><em>Use a production-safe prompt tied to ' + escapeHtml(provider.area) + ' evidence.</em></div>' + Icon('prompt') + '</button>' +
18738
- '<button type="button" data-action="start-agent-fix"><span>3</span><div><strong>Apply one fix</strong><em>Send the connected model to patch the selected launch gap only.</em></div>' + Icon('agent') + '</button>' +
18651
+ '<button type="button" data-action="prompt"><span>2</span><div><strong>Open scoped mission</strong><em>Use a context-aware prompt tied to ' + escapeHtml(provider.area) + ' evidence.</em></div>' + Icon('prompt') + '</button>' +
18652
+ '<button type="button" data-action="start-agent-fix"><span>3</span><div><strong>Apply one fix</strong><em>Send the connected model to patch the evidenced change only.</em></div>' + Icon('agent') + '</button>' +
18739
18653
  '<button type="button" data-action="show-diff"><span>4</span><div><strong>Review diff</strong><em>Inspect repo changes before accepting verification.</em></div>' + Icon('code') + '</button>' +
18740
18654
  '<button type="button" data-action="verify-now"><span>5</span><div><strong>Run verify</strong><em>Move the mission into a green verified state after review.</em></div>' + Icon('check') + '</button>' +
18741
18655
  '</section>' +
@@ -18846,21 +18760,18 @@ function connectCliAgent(agentId, chatIndex, options) {
18846
18760
  }
18847
18761
 
18848
18762
  function cliSetupProbeLabel() {
18849
- return demo.cliProbeStatus === 'probing' ? 'Testing\u2026' : demo.cliProbeStatus === 'success' ? 'Connected' : demo.cliProbeStatus === 'failed' ? 'Try again' : 'Test connection';
18763
+ return demo.cliProbeStatus === 'probing' ? 'Testing...' : demo.cliProbeStatus === 'success' ? 'Connected' : demo.cliProbeStatus === 'failed' ? 'Try again' : 'Test connection';
18850
18764
  }
18851
18765
 
18852
18766
  function CliSetupActions(targetId, index) {
18853
18767
  const setup = cliSetupFor(targetId);
18854
18768
  const probeLabel = cliSetupProbeLabel();
18855
- const ctaPending = demo.cliProbeStatus !== 'success' && demo.cliProbeStatus !== 'probing';
18856
- const ctaClass = 'vr-cli-action-button is-primary' + (ctaPending ? ' is-pending' : '');
18857
- return '<p class="vr-cli-setup-cta-hint">After sign-in, click <strong>Test connection</strong> \u2014 chat only works once verified.</p>' +
18858
- '<div class="vr-cli-connect-expand-actions">' +
18769
+ return '<div class="vr-cli-connect-expand-actions">' +
18859
18770
  '<button class="vr-cli-action-button" type="button" data-action="run-cli-install" data-cli-agent="' + escapeHtml(targetId) + '" data-chat-index="' + String(index) + '">' + Icon('shell') + 'Run install</button>' +
18860
18771
  '<button class="vr-cli-action-button" type="button" data-action="run-cli-signin" data-cli-agent="' + escapeHtml(targetId) + '" data-chat-index="' + String(index) + '">' + Icon('shell') + 'Run sign in</button>' +
18861
- '<button class="' + ctaClass + '" type="button" data-action="test-cli-connection" data-cli-agent="' + escapeHtml(targetId) + '" data-chat-index="' + String(index) + '">' + Icon('refresh') + escapeHtml(probeLabel) + '</button>' +
18772
+ '<button class="vr-cli-action-button is-primary" type="button" data-action="test-cli-connection" data-cli-agent="' + escapeHtml(targetId) + '" data-chat-index="' + String(index) + '">' + Icon('refresh') + escapeHtml(probeLabel) + '</button>' +
18862
18773
  '</div>' +
18863
- '<p class="vr-cli-setup-hint">Type commands in the Studio terminal below, or run: <code>' + escapeHtml(setup.installCommand) + '</code> then <code>' + escapeHtml(setup.signInCommand) + '</code></p>';
18774
+ '<p class="vr-cli-setup-hint">Run install and sign in, then use <strong>Test connection</strong> to unlock chat control. Commands: <code>' + escapeHtml(setup.installCommand) + '</code> then <code>' + escapeHtml(setup.signInCommand) + '</code></p>';
18864
18775
  }
18865
18776
 
18866
18777
  function appendTerminalLines(lines) {
@@ -18924,7 +18835,7 @@ function selectTerminalCli(agentId) {
18924
18835
  if (!demo.cliTerminalLines.length) {
18925
18836
  demo.cliTerminalLines = [
18926
18837
  'VibeRaven Studio shell',
18927
- 'Run install, run sign in, then test connection using the buttons below.',
18838
+ 'Run install, run sign in, then use Test connection to continue.',
18928
18839
  ''
18929
18840
  ];
18930
18841
  } else {
@@ -18956,8 +18867,8 @@ function StudioTerminalView() {
18956
18867
  const lines = demo.cliTerminalLines.length
18957
18868
  ? demo.cliTerminalLines
18958
18869
  : [
18959
- 'VibeRaven Studio shell',
18960
- 'Type commands at the $ prompt. Use the buttons below to install, sign in, and test.',
18870
+ 'VibeRaven Studio shell',
18871
+ 'Type commands at the $ prompt. Use Test connection after sign-in.',
18961
18872
  ''
18962
18873
  ];
18963
18874
  const title = terminalConnectTitle(agent);
@@ -19011,7 +18922,7 @@ function ChatFirstTimeConnect(index) {
19011
18922
  : '<p class="vr-chat-first-connect-note">Click Connect to open the Terminal tab \u2014 install, sign in, then test connection.</p>';
19012
18923
  return '<section class="vr-chat-empty-state vr-chat-first-connect" data-chat-index="' + String(index) + '">' +
19013
18924
  '<strong>First time</strong>' +
19014
- '<span>Connect Codex, Claude Code, or Gemini through VibeRaven Studio.</span>' +
18925
+ '<span>Connect your repo agent through VibeRaven Studio.</span>' +
19015
18926
  '<div class="vr-cli-strip is-inline">' + codingAgents.map((agent) => CliAgentButton(agent, index)).join('') + '</div>' +
19016
18927
  hintLine +
19017
18928
  '</section>';
@@ -19300,7 +19211,7 @@ async function runCliSignInInStudio(agentId, chatIndex) {
19300
19211
  String(payload?.output || payload?.message || 'Sign-in command finished.'),
19301
19212
  payload?.interactiveNote ? String(payload.interactiveNote) : '',
19302
19213
  '',
19303
- 'Complete any browser login, then click Test connection below to verify.'
19214
+ 'Complete any browser login, then click Test connection.'
19304
19215
  ]);
19305
19216
  demo.cliTerminalDraft = setupCommandFallback(agentId, 'sign-in');
19306
19217
  demo.notice = 'Sign-in ran in Studio terminal. Finish login if prompted, then test the connection.';
@@ -19332,7 +19243,7 @@ async function openCliOsTerminal(agentId, chatIndex) {
19332
19243
  '',
19333
19244
  String(payload?.message || 'Complete sign-in in the OS terminal window that opened.'),
19334
19245
  '',
19335
- 'When login finishes, return here and click Test connection below to verify.'
19246
+ 'When login finishes, return here and click Test connection.'
19336
19247
  ]);
19337
19248
  demo.notice = payload?.ok ? 'OS terminal opened for sign-in fallback.' : 'Could not open an OS terminal window.';
19338
19249
  } catch {
@@ -19347,11 +19258,12 @@ function ModelPicker(index) {
19347
19258
  const models = allModelOptions(index);
19348
19259
  const selectedModel = selectedModelLabel(index);
19349
19260
  const scoped = demo.pickerChatIndex === index;
19261
+ const access = accessModes.find((mode) => mode.id === chat.accessMode) || accessModes[1];
19350
19262
  return '<div class="vr-model-picker">' +
19351
19263
  '<button type="button" data-action="toggle-reasoning" data-chat-index="' + String(index) + '"><span>Reasoning</span><strong>' + escapeHtml(chat.reasoning) + '</strong><i></i></button>' +
19352
19264
  '<button type="button" data-action="toggle-models" data-chat-index="' + String(index) + '"><span>Model</span><strong>' + escapeHtml(selectedModel) + '</strong><i></i></button>' +
19353
19265
  '<button type="button" data-action="toggle-context" data-chat-index="' + String(index) + '"><span>Context</span><strong>' + escapeHtml(chat.context) + '</strong><i></i></button>' +
19354
- PermissionModeToggle(index) +
19266
+ '<button type="button" data-action="toggle-access" data-chat-index="' + String(index) + '"><span>Access</span><strong>' + escapeHtml(access.label) + '</strong><i></i></button>' +
19355
19267
  (scoped && demo.reasoningMenuOpen ? '<div class="vr-model-menu is-reasoning" role="menu"><p>Reasoning</p>' + reasoningLevels.map((level) =>
19356
19268
  '<button type="button" data-reasoning="' + escapeHtml(level) + '" data-chat-index="' + String(index) + '">' + escapeHtml(level) + (chat.reasoning === level ? '<b></b>' : '') + '</button>'
19357
19269
  ).join('') + '</div>' : '') +
@@ -19361,14 +19273,9 @@ function ModelPicker(index) {
19361
19273
  (scoped && demo.contextMenuOpen ? '<div class="vr-model-menu is-context" role="menu"><p>Context</p>' + contextLevels.map((level) =>
19362
19274
  '<button type="button" data-context="' + escapeHtml(level) + '" data-chat-index="' + String(index) + '">' + escapeHtml(level) + (chat.context === level ? '<b></b>' : '') + '</button>'
19363
19275
  ).join('') + '</div>' : '') +
19364
- '</div>';
19365
- }
19366
-
19367
- function PermissionModeToggle(index) {
19368
- const isFullAccess = demo.agentPermissionMode === 'full-access';
19369
- return '<div class="vr-permission-toggle" role="group" aria-label="Agent permission mode">' +
19370
- '<button type="button" class="vr-permission-btn' + (!isFullAccess ? ' is-active' : '') + '" data-permission-mode="ask" data-chat-index="' + String(index) + '" aria-pressed="' + String(!isFullAccess) + '" title="Ask for approval before each risky action">Ask each change</button>' +
19371
- '<button type="button" class="vr-permission-btn is-danger' + (isFullAccess ? ' is-active' : '') + '" data-permission-mode="full-access" data-chat-index="' + String(index) + '" aria-pressed="' + String(isFullAccess) + '" title="Run without per-action approval prompts \u2014 use with care">Full access</button>' +
19276
+ (scoped && demo.accessMenuOpen ? '<div class="vr-model-menu is-access" role="menu"><p>Access</p>' + accessModes.map((mode) =>
19277
+ '<button type="button" data-access-mode="' + escapeHtml(mode.id) + '" data-chat-index="' + String(index) + '"><span><strong>' + escapeHtml(mode.label) + '</strong><em>' + escapeHtml(mode.description) + '</em></span>' + (chat.accessMode === mode.id ? '<b></b>' : '') + '</button>'
19278
+ ).join('') + '</div>' : '') +
19372
19279
  '</div>';
19373
19280
  }
19374
19281
 
@@ -19388,10 +19295,10 @@ function ChatBlockersSummary(cards) {
19388
19295
  function ChatPlanCard(steps, chatIndex) {
19389
19296
  const rows = Array.isArray(steps) ? steps : [];
19390
19297
  if (!rows.length) return '';
19391
- return '<section class="vr-chat-card vr-chat-plan-card"><header><strong>Production Fix Plan</strong><b>' + String(rows.length) + ' steps</b></header><ol class="vr-chat-plan-list">' +
19298
+ return '<section class="vr-chat-card vr-chat-plan-card"><header><strong>Fix plan</strong><b>' + String(rows.length) + ' actions</b></header><ol class="vr-chat-plan-list">' +
19392
19299
  rows.map((step, index) =>
19393
19300
  '<li><button class="vr-plan-step" type="button" data-action="mission-step" data-step-id="' + escapeHtml(step.id || ('step-' + String(index))) + '" data-chat-index="' + String(chatIndex) + '">' +
19394
- '<span class="vr-plan-step-num">' + String(index + 1) + '</span>' +
19301
+ '<span class="vr-plan-step-num"></span>' +
19395
19302
  '<span class="vr-plan-step-body">' +
19396
19303
  '<span class="vr-plan-step-title">' + escapeHtml(step.title || 'Fix step') + '</span>' +
19397
19304
  '<span class="vr-plan-step-tag">' + escapeHtml(step.category || 'Quality') + '</span>' +
@@ -19428,7 +19335,7 @@ function ChatMissionCards(cards, chatIndex, options) {
19428
19335
  if (showPlan && planSteps.length) html += ChatPlanCard(planSteps, chatIndex);
19429
19336
  if (connectProviders.length) html += ChatProviderConnectCard(connectProviders, chatIndex);
19430
19337
  if (planSteps.length && !showPlan) {
19431
- html += '<button class="vr-chat-plan-row" type="button" data-action="view-fix-plan" data-chat-index="' + String(chatIndex) + '">' + Icon('report') + '<strong>View Production Fix Plan</strong><em>' + String(planSteps.length) + ' steps</em><b></b></button>';
19338
+ html += '<button class="vr-chat-plan-row" type="button" data-action="view-fix-plan" data-chat-index="' + String(chatIndex) + '">' + Icon('report') + '<strong>View fix plan</strong><em>' + String(planSteps.length) + ' actions</em><b></b></button>';
19432
19339
  }
19433
19340
  html += '</div>';
19434
19341
  return html;
@@ -19497,7 +19404,9 @@ function linkLabelForUrl(url) {
19497
19404
  if (lower.includes('sentry.io')) return 'Open Sentry';
19498
19405
  if (lower.includes('supabase.com')) return 'Open Supabase';
19499
19406
  if (lower.includes('vercel.com')) return 'Open Vercel';
19407
+ if (lower.includes('github.com')) return 'Open GitHub';
19500
19408
  if (lower.includes('stripe.com')) return 'Open Stripe';
19409
+ if (lower.includes('cli.github.com')) return 'Open GitHub CLI docs';
19501
19410
  if (lower.includes('dashboard')) return 'Open dashboard';
19502
19411
  return 'Open link';
19503
19412
  }
@@ -19555,9 +19464,9 @@ function renderAgentListItems(items, chatIndex) {
19555
19464
 
19556
19465
  function normalizeAgentSectionKey(raw) {
19557
19466
  const key = String(raw || '').trim().toLowerCase().replace(/\\s*\\(\\d+\\)\\s*$/, '').trim();
19558
- if (/^(gate|launch gate|production gate)$/.test(key)) return 'Gate';
19559
- if (/^(blockers?|launch blockers?)$/.test(key)) return 'Blockers';
19560
- if (/^(suggested steps?|fix plan|production fix plan)$/.test(key)) return 'Suggested steps';
19467
+ if (/^(gate|production gate)$/.test(key)) return null;
19468
+ if (/^(blockers?|context gaps?)$/.test(key)) return 'Context gaps';
19469
+ if (/^(suggested steps?|fix plan)$/.test(key)) return 'Suggested steps';
19561
19470
  if (/^(summary|tl;dr|tldr)$/.test(key)) return 'Summary';
19562
19471
  if (key === 'findings') return 'Findings';
19563
19472
  if (key === 'changes made') return 'Changes made';
@@ -19590,15 +19499,7 @@ function dedupeAgentMarkdownBody(text, cards) {
19590
19499
  }
19591
19500
 
19592
19501
  function AgentGateStrip(gateText, gateState) {
19593
- const gate = gateState || currentState.gate || {};
19594
- const parsed = String(gateText || '').trim();
19595
- const status = gate.status || 'unknown';
19596
- const label = parsed || gate.label || 'Waiting for project evidence';
19597
- const tone = status === 'clear' ? 'clear' : (status === 'blocked' || status === 'not_clear' ? 'blocked' : 'unknown');
19598
- return '<div class="vr-agent-gate-strip" data-tone="' + escapeHtml(tone) + '">' +
19599
- Icon('shield') +
19600
- '<span><strong>Launch gate</strong><em>' + escapeHtml(label) + '</em></span>' +
19601
- '</div>';
19502
+ return '';
19602
19503
  }
19603
19504
 
19604
19505
  function parseAgentSections(text, options) {
@@ -19645,8 +19546,7 @@ function renderAgentSectionCard(section, chatIndex) {
19645
19546
  const name = section.name;
19646
19547
  const lower = name.toLowerCase();
19647
19548
  if (lower === 'gate') {
19648
- const gateText = section.paragraphs.concat(section.items).join(' ');
19649
- return AgentGateStrip(gateText, currentState.gate || null);
19549
+ return '';
19650
19550
  }
19651
19551
  const isNext = lower === 'next step';
19652
19552
  const isBlockers = lower === 'blockers';
@@ -19664,6 +19564,7 @@ function renderAgentSectionCard(section, chatIndex) {
19664
19564
  const blob = section.items.concat(section.paragraphs).join(' ').toLowerCase();
19665
19565
  const actions = [];
19666
19566
  if (/fix|wire|implement|add|configure|apply|sentry|monitor/.test(blob)) actions.push(agentApplyFixButton(chatIndex));
19567
+ if (blob.includes('github')) actions.push(agentLinkButton('Open GitHub', providerDashboardUrls.github || goLiveUrls.githubNew));
19667
19568
  if (blob.includes('sentry')) actions.push(agentLinkButton('Open Sentry', providerDashboardUrls.sentry || 'https://sentry.io'));
19668
19569
  if (blob.includes('supabase')) actions.push(agentLinkButton('Open Supabase', providerDashboardUrls.supabase || 'https://supabase.com/dashboard/projects'));
19669
19570
  if (blob.includes('vercel')) actions.push(agentLinkButton('Open Vercel', providerDashboardUrls.vercel || 'https://vercel.com/dashboard'));
@@ -19835,7 +19736,7 @@ function readOnlyContextChipsHtml(providerId, releaseId) {
19835
19736
  kind: 'provider',
19836
19737
  index: 0,
19837
19738
  id: provider.id,
19838
- iconHtml: '<img src="' + (providerMarkAssets[provider.id] || providerAssets[provider.id]) + '" alt="" />',
19739
+ iconHtml: provider.iconHtml || '<img src="' + providerAssetSrc(provider) + '" alt="" />',
19839
19740
  mutedLabel: provider.area,
19840
19741
  label: provider.name,
19841
19742
  readOnly: true,
@@ -19926,7 +19827,7 @@ function ContextDropZone(index, showAttached) {
19926
19827
  kind: 'provider',
19927
19828
  index,
19928
19829
  id: provider.id,
19929
- iconHtml: '<img src="' + (providerMarkAssets[provider.id] || providerAssets[provider.id]) + '" alt="" />',
19830
+ iconHtml: provider.iconHtml || '<img src="' + providerAssetSrc(provider) + '" alt="" />',
19930
19831
  mutedLabel: provider.area,
19931
19832
  label: provider.name,
19932
19833
  }) : '') +
@@ -20038,12 +19939,13 @@ function AgentActionPanel() {
20038
19939
  return '<aside class="vr-agent-panel" aria-label="VibeRaven AI Agent panel">' +
20039
19940
  '<div class="vr-agent-control">' +
20040
19941
  '<section class="vr-agent-hero ' + (fixing ? 'is-fixing' : '') + (verified ? ' is-verified' : '') + '">' +
20041
- '<div><p>VibeRaven Agent</p><h2>' + (verified ? 'Ready to launch' : fixing ? 'Fixing launch gap' : 'Ready') + '</h2><em>' + (verified ? 'High confidence. Safe to proceed.' : fixing ? 'Patching proof now.' : 'High confidence. Safe to proceed.') + '</em></div>' +
19942
+ '<div><p>VibeRaven Agent</p><h2>' + (verified ? 'Ready with proof' : fixing ? 'Fixing what changed' : 'Ready') + '</h2><em>' + (verified ? 'High confidence. Safe to proceed.' : fixing ? 'Patching proof now.' : 'High confidence. Safe to proceed.') + '</em></div>' +
20042
19943
  '<img src="' + mascotUrl() + '" alt="" />' +
20043
19944
  '</section>' +
20044
19945
  '<section class="vr-quick-actions"><h3>Quick Actions</h3>' +
20045
19946
  [
20046
- { id: 'guide', icon: 'guide', title: 'Analyze Issues', caption: 'Find launch blockers' },
19947
+ { id: 'go-live', icon: 'cloud', title: 'Go Live', caption: 'GitHub + Vercel' },
19948
+ { id: 'guide', icon: 'guide', title: 'Analyze Issues', caption: 'Find what changed' },
20047
19949
  { id: 'show-diff', icon: 'code', title: 'View Diff', caption: 'Review changes' },
20048
19950
  { id: 'recheck', icon: 'refresh', title: 'Run Verify', caption: 'Run checks again' },
20049
19951
  { id: 'explain-changes', icon: 'prompt', title: 'Explain Changes', caption: 'Summarize the fix' },
@@ -20204,7 +20106,7 @@ app.addEventListener('click', async (event) => {
20204
20106
  if (demo.activeStudioTab === 'terminal' && !demo.cliTerminalLines.length) {
20205
20107
  demo.cliTerminalLines = [
20206
20108
  'VibeRaven Studio shell',
20207
- 'Type commands at the $ prompt. Use the buttons below to install, sign in, and test.',
20109
+ 'Type commands at the $ prompt. Use Test connection after sign-in.',
20208
20110
  ''
20209
20111
  ];
20210
20112
  }
@@ -20302,6 +20204,7 @@ app.addEventListener('click', async (event) => {
20302
20204
  demo.modelMenuOpen = false;
20303
20205
  demo.reasoningMenuOpen = false;
20304
20206
  demo.contextMenuOpen = false;
20207
+ demo.accessMenuOpen = false;
20305
20208
  demo.cliProbeStatus = 'idle';
20306
20209
  demo.cliProbeMessage = '';
20307
20210
  demo.pickerChatIndex = chatIndex;
@@ -20329,6 +20232,7 @@ app.addEventListener('click', async (event) => {
20329
20232
  demo.modelMenuOpen = false;
20330
20233
  demo.reasoningMenuOpen = false;
20331
20234
  demo.contextMenuOpen = false;
20235
+ demo.accessMenuOpen = false;
20332
20236
  demo.notice = (cliAgents.find((item) => item.id === chat.cliId)?.label || chat.cliId) + ' selected for this chat.';
20333
20237
  render();
20334
20238
  return;
@@ -20346,6 +20250,7 @@ app.addEventListener('click', async (event) => {
20346
20250
  demo.modelMenuOpen = false;
20347
20251
  demo.reasoningMenuOpen = false;
20348
20252
  demo.contextMenuOpen = false;
20253
+ demo.accessMenuOpen = false;
20349
20254
  demo.activeStudioTab = 'chat';
20350
20255
  demo.pickerChatIndex = chatIndex;
20351
20256
  demo.notice = selectedModelLabel(chatIndex) + ' selected for this chat.';
@@ -20364,6 +20269,7 @@ app.addEventListener('click', async (event) => {
20364
20269
  demo.reasoningMenuOpen = false;
20365
20270
  demo.modelMenuOpen = false;
20366
20271
  demo.contextMenuOpen = false;
20272
+ demo.accessMenuOpen = false;
20367
20273
  demo.activeStudioTab = 'chat';
20368
20274
  demo.pickerChatIndex = chatIndex;
20369
20275
  demo.notice = chat.reasoning + ' reasoning selected for this chat.';
@@ -20382,6 +20288,7 @@ app.addEventListener('click', async (event) => {
20382
20288
  demo.contextMenuOpen = false;
20383
20289
  demo.modelMenuOpen = false;
20384
20290
  demo.reasoningMenuOpen = false;
20291
+ demo.accessMenuOpen = false;
20385
20292
  demo.activeStudioTab = 'chat';
20386
20293
  demo.pickerChatIndex = chatIndex;
20387
20294
  demo.notice = chat.context + ' context selected for this chat.';
@@ -20390,21 +20297,23 @@ app.addEventListener('click', async (event) => {
20390
20297
  return;
20391
20298
  }
20392
20299
 
20393
- const permissionButton = event.target.closest('[data-permission-mode]');
20394
- if (permissionButton) {
20300
+ const accessButton = event.target.closest('[data-access-mode]');
20301
+ if (accessButton) {
20395
20302
  event.preventDefault();
20396
- const mode = permissionButton.getAttribute('data-permission-mode');
20397
- demo.agentPermissionMode = mode === 'full-access' ? 'full-access' : 'ask';
20398
- savePermissionMode(demo.agentPermissionMode);
20399
- const chatIndex = Number(permissionButton.getAttribute('data-chat-index') || String(demo.pickerChatIndex || 0));
20400
- demo.pickerChatIndex = chatIndex;
20303
+ const chatIndex = Number(accessButton.getAttribute('data-chat-index') || String(demo.pickerChatIndex || 0));
20304
+ const chat = chatContext(chatIndex);
20305
+ const selected = accessModes.find((mode) => mode.id === accessButton.getAttribute('data-access-mode')) || accessModes[1];
20306
+ chat.accessMode = selected.id;
20307
+ demo.selectedAccessMode = selected.id;
20308
+ demo.accessMenuOpen = false;
20309
+ demo.contextMenuOpen = false;
20401
20310
  demo.modelMenuOpen = false;
20402
20311
  demo.reasoningMenuOpen = false;
20403
- demo.contextMenuOpen = false;
20404
- demo.notice = demo.agentPermissionMode === 'full-access'
20405
- ? 'Full access mode: agent runs without per-action approval prompts.'
20406
- : 'Ask mode: agent will request approval before each risky action.';
20407
- render();
20312
+ demo.activeStudioTab = 'chat';
20313
+ demo.pickerChatIndex = chatIndex;
20314
+ demo.notice = selected.label + ' selected for this chat.';
20315
+ refreshPickerMenus();
20316
+ refreshBottomTip();
20408
20317
  return;
20409
20318
  }
20410
20319
 
@@ -20415,6 +20324,7 @@ app.addEventListener('click', async (event) => {
20415
20324
  demo.modelMenuOpen = false;
20416
20325
  demo.reasoningMenuOpen = false;
20417
20326
  demo.contextMenuOpen = false;
20327
+ demo.accessMenuOpen = false;
20418
20328
  if (stage === 'provider') {
20419
20329
  demo.activeStudioTab = 'chat';
20420
20330
  demo.providerPickerOpen = true;
@@ -20588,7 +20498,7 @@ app.addEventListener('click', async (event) => {
20588
20498
  }
20589
20499
  if (action === 'copy-prompt') {
20590
20500
  const copied = await copyText(agentPromptText());
20591
- demo.notice = copied ? 'Agent mission ready. Keep the connected CLI scoped to this launch gap.' : 'Mission is still visible; clipboard permission was not available.';
20501
+ demo.notice = copied ? 'Agent mission ready. Keep the connected CLI scoped to the evidenced change.' : 'Mission is still visible; clipboard permission was not available.';
20592
20502
  render();
20593
20503
  return;
20594
20504
  }
@@ -20601,6 +20511,7 @@ app.addEventListener('click', async (event) => {
20601
20511
  demo.modelMenuOpen = !samePicker;
20602
20512
  demo.reasoningMenuOpen = false;
20603
20513
  demo.contextMenuOpen = false;
20514
+ demo.accessMenuOpen = false;
20604
20515
  refreshPickerMenus();
20605
20516
  return;
20606
20517
  }
@@ -20613,6 +20524,7 @@ app.addEventListener('click', async (event) => {
20613
20524
  demo.reasoningMenuOpen = !samePicker;
20614
20525
  demo.modelMenuOpen = false;
20615
20526
  demo.contextMenuOpen = false;
20527
+ demo.accessMenuOpen = false;
20616
20528
  refreshPickerMenus();
20617
20529
  return;
20618
20530
  }
@@ -20625,6 +20537,20 @@ app.addEventListener('click', async (event) => {
20625
20537
  demo.contextMenuOpen = !samePicker;
20626
20538
  demo.modelMenuOpen = false;
20627
20539
  demo.reasoningMenuOpen = false;
20540
+ demo.accessMenuOpen = false;
20541
+ refreshPickerMenus();
20542
+ return;
20543
+ }
20544
+ if (action === 'toggle-access') {
20545
+ event.preventDefault();
20546
+ const chatIndex = Number(actionButton.getAttribute('data-chat-index') || '0');
20547
+ const samePicker = demo.pickerChatIndex === chatIndex && demo.accessMenuOpen;
20548
+ demo.activeStudioTab = 'chat';
20549
+ demo.pickerChatIndex = chatIndex;
20550
+ demo.accessMenuOpen = !samePicker;
20551
+ demo.modelMenuOpen = false;
20552
+ demo.reasoningMenuOpen = false;
20553
+ demo.contextMenuOpen = false;
20628
20554
  refreshPickerMenus();
20629
20555
  return;
20630
20556
  }
@@ -20728,6 +20654,7 @@ app.addEventListener('click', async (event) => {
20728
20654
  demo.modelMenuOpen = false;
20729
20655
  demo.reasoningMenuOpen = false;
20730
20656
  demo.contextMenuOpen = false;
20657
+ demo.accessMenuOpen = false;
20731
20658
  demo.notice = 'New chat opened.';
20732
20659
  render();
20733
20660
  return;
@@ -20801,12 +20728,17 @@ app.addEventListener('click', async (event) => {
20801
20728
  runChatTask('analyze');
20802
20729
  return;
20803
20730
  }
20731
+ if (action === 'go-live') {
20732
+ demo.pickerChatIndex = actionChatIndex;
20733
+ runChatTask('go-live');
20734
+ return;
20735
+ }
20804
20736
  if (action === 'prompt') {
20805
20737
  demo.activeNavId = 'agents';
20806
20738
  demo.activeStepId = 'agent';
20807
20739
  demo.providerPickerOpen = false;
20808
20740
  demo.activeModal = 'prompt';
20809
- demo.notice = 'Agent mission is ready. Keep the fix scoped to the selected launch gap.';
20741
+ demo.notice = 'Agent mission is ready. Keep the fix scoped to the evidenced change.';
20810
20742
  render();
20811
20743
  return;
20812
20744
  }
@@ -20833,7 +20765,7 @@ app.addEventListener('click', async (event) => {
20833
20765
  const chatIndex = Number(actionButton.getAttribute('data-chat-index') || String(actionChatIndex));
20834
20766
  demo.fixPlanExpandedChatIndex = demo.fixPlanExpandedChatIndex === chatIndex ? null : chatIndex;
20835
20767
  demo.pickerChatIndex = chatIndex;
20836
- demo.notice = demo.fixPlanExpandedChatIndex === chatIndex ? 'Production fix plan expanded in chat.' : 'Production fix plan collapsed.';
20768
+ demo.notice = demo.fixPlanExpandedChatIndex === chatIndex ? 'Fix plan expanded in chat.' : 'Fix plan collapsed.';
20837
20769
  render();
20838
20770
  return;
20839
20771
  }
@@ -20890,7 +20822,7 @@ app.addEventListener('click', async (event) => {
20890
20822
  environment: 'Environment selector is scoped to the local Studio preview.',
20891
20823
  account: 'VibeRaven agent opened from the header mascot.',
20892
20824
  'all-releases': 'Release history view opens next; this preview keeps the timeline focused.',
20893
- 'explain-changes': 'Change summary opened for production-safe review wording.',
20825
+ 'explain-changes': 'Change summary opened with release-context wording.',
20894
20826
  };
20895
20827
  if (actionMessages[action]) {
20896
20828
  if (action === 'all-releases') {
@@ -20973,7 +20905,7 @@ app.addEventListener('dragstart', (event) => {
20973
20905
  event,
20974
20906
  provider ? provider.name : 'Provider',
20975
20907
  provider ? provider.area : 'Drop into VibeRaven chat',
20976
- provider ? '<img src="' + escapeHtml(providerMarkAssets[provider.id] || providerAssets[provider.id]) + '" alt="" />' : ''
20908
+ provider ? (provider.iconHtml || '<img src="' + providerAssetSrc(provider) + '" alt="" />') : ''
20977
20909
  );
20978
20910
  providerButton.classList.add('is-being-dragged');
20979
20911
  demo.notice = 'Dragging provider context. Drop it into a chat composer or Split chat.';
@@ -21063,7 +20995,7 @@ app.addEventListener('drop', (event) => {
21063
20995
  if (newChatTarget) demo.activeRecentChatId = null;
21064
20996
  if (chatIndex === 0) syncPrimaryContext();
21065
20997
  if (provider && provider.state === 'not_detected') {
21066
- context.draft = 'Help me connect ' + provider.name + ' for production. What env vars and dashboard steps do I need?';
20998
+ context.draft = 'Help me connect ' + provider.name + ' with context. What provider state, runtime behavior, or dashboard proof does this repo need?';
21067
20999
  demo.notice = provider.name + ' is missing \u2014 connect steps prefilled. Send when ready.';
21068
21000
  } else {
21069
21001
  demo.notice = provider ? provider.name + ' context attached to chat ' + String(chatIndex + 1) + '. Suggested actions updated for ' + (stackSlots[provider.id] || provider.area) + '.' : 'Provider context attached.';
@@ -23768,21 +23700,6 @@ body:has(.vr-app.is-dragging) {
23768
23700
  background: rgba(124, 58, 237, 0.92);
23769
23701
  color: #fff;
23770
23702
  }
23771
- .vr-cli-setup-cta-hint {
23772
- margin: 0 0 6px;
23773
- color: #94a3b8;
23774
- font-size: 11px;
23775
- font-weight: 500;
23776
- line-height: 1.35;
23777
- }
23778
- .vr-cli-setup-cta-hint strong {
23779
- color: #c4b5fd;
23780
- font-weight: 650;
23781
- }
23782
- .vr-cli-action-button.is-primary.is-pending {
23783
- border-color: rgba(168, 85, 247, 0.55);
23784
- box-shadow: 0 0 0 1px rgba(168, 85, 247, 0.25);
23785
- }
23786
23703
  .vr-cli-strip button.is-connect-target {
23787
23704
  border-color: rgba(248, 250, 252, 0.34);
23788
23705
  box-shadow: inset 0 0 0 1px rgba(248, 250, 252, 0.08);
@@ -24507,16 +24424,15 @@ body:has(.vr-app.is-dragging) {
24507
24424
  border-color: rgba(168, 85, 247, 0.38);
24508
24425
  }
24509
24426
  .vr-plan-step-num {
24510
- width: 28px;
24511
- height: 28px;
24427
+ width: 10px;
24428
+ height: 10px;
24512
24429
  flex: 0 0 auto;
24513
24430
  display: grid;
24514
24431
  place-items: center;
24515
- border: 1px solid rgba(168, 85, 247, 0.35);
24432
+ border: 1px solid rgba(168, 85, 247, 0.5);
24516
24433
  border-radius: 999px;
24517
- color: #e9d5ff;
24518
- font-size: 12px;
24519
- font-weight: 700;
24434
+ background: rgba(168, 85, 247, 0.28);
24435
+ box-shadow: 0 0 10px rgba(168, 85, 247, 0.22);
24520
24436
  }
24521
24437
  .vr-plan-step-body {
24522
24438
  flex: 1 1 0;
@@ -25128,6 +25044,10 @@ body:has(.vr-app.is-dragging) {
25128
25044
  .vr-model-menu.is-context {
25129
25045
  right: 0;
25130
25046
  }
25047
+ .vr-model-menu.is-access {
25048
+ right: 0;
25049
+ min-width: 270px;
25050
+ }
25131
25051
  .vr-studio-chat.is-split .vr-model-menu {
25132
25052
  bottom: calc(100% + 10px);
25133
25053
  min-width: min(245px, calc(100vw - 32px));
@@ -25144,6 +25064,10 @@ body:has(.vr-app.is-dragging) {
25144
25064
  left: auto;
25145
25065
  right: 0;
25146
25066
  }
25067
+ .vr-studio-chat.is-split .vr-model-menu.is-access {
25068
+ left: auto;
25069
+ right: 0;
25070
+ }
25147
25071
  .vr-model-menu p {
25148
25072
  margin: 2px 4px 6px;
25149
25073
  color: #a8a29e;
@@ -25288,7 +25212,7 @@ body:has(.vr-app.is-dragging) {
25288
25212
  }
25289
25213
  .vr-bottom-inventory .vr-provider-card {
25290
25214
  min-height: 48px;
25291
- grid-template-columns: 34px minmax(0, 1fr) auto 28px;
25215
+ grid-template-columns: 34px minmax(0, 1fr) 18px 22px;
25292
25216
  grid-template-rows: 1fr;
25293
25217
  align-items: center;
25294
25218
  gap: 8px;
@@ -25345,14 +25269,6 @@ body:has(.vr-app.is-dragging) {
25345
25269
  fill: none !important;
25346
25270
  stroke: currentColor !important;
25347
25271
  }
25348
- .vr-bottom-inventory .vr-provider-light {
25349
- right: 36px;
25350
- top: 50%;
25351
- width: 7px;
25352
- height: 7px;
25353
- transform: translateY(-50%);
25354
- box-shadow: 0 0 9px rgba(34, 197, 94, 0.42);
25355
- }
25356
25272
  .vr-bottom-inventory .vr-provider-card .vr-status-badge {
25357
25273
  grid-column: 3;
25358
25274
  min-height: 18px;
@@ -25639,8 +25555,35 @@ body:has(.vr-app.is-dragging) {
25639
25555
  filter: saturate(1.04) contrast(1.02);
25640
25556
  transition: transform 180ms cubic-bezier(0.23, 1, 0.32, 1);
25641
25557
  }
25558
+ .vr-provider-token .provider-logo__img {
25559
+ filter: saturate(1.22) contrast(1.14);
25560
+ }
25561
+ .vr-provider-token .provider-logo__img[data-provider-logo-key="github"],
25562
+ .vr-provider-token .provider-logo__img[data-provider-logo-key="vercel"],
25563
+ .vr-provider-token .provider-logo__img[data-provider-logo-key="resend"] {
25564
+ filter: drop-shadow(0 0 8px rgba(255, 255, 255, 0.18));
25565
+ }
25566
+ .vr-provider-token .provider-logo__img[data-provider-logo-key="sentry"] {
25567
+ filter: saturate(1.34) contrast(1.16) drop-shadow(0 0 9px rgba(139, 92, 246, 0.26));
25568
+ }
25569
+ .vr-provider-token svg {
25570
+ position: relative;
25571
+ z-index: 1;
25572
+ width: 26px;
25573
+ height: 26px;
25574
+ display: block;
25575
+ }
25576
+ .vr-provider-token .vr-provider-logo,
25577
+ .vr-provider-token .vr-provider-logo img {
25578
+ width: 26px;
25579
+ height: 26px;
25580
+ display: block;
25581
+ object-fit: contain;
25582
+ }
25642
25583
  .vr-provider-card:hover .vr-provider-token img,
25643
- .vr-provider-card.is-selected .vr-provider-token img {
25584
+ .vr-provider-card.is-selected .vr-provider-token img,
25585
+ .vr-provider-card:hover .vr-provider-token svg,
25586
+ .vr-provider-card.is-selected .vr-provider-token svg {
25644
25587
  transform: scale(1.08);
25645
25588
  }
25646
25589
  .vr-provider-token.is-picker {
@@ -25661,15 +25604,11 @@ body:has(.vr-app.is-dragging) {
25661
25604
  width: 34px;
25662
25605
  height: 34px;
25663
25606
  }
25664
- .vr-provider-light {
25665
- position: absolute;
25666
- right: 42px;
25667
- top: 18px;
25668
- width: 8px;
25669
- height: 8px;
25670
- border-radius: 999px;
25671
- background: var(--vr-green);
25672
- box-shadow: 0 0 8px rgba(34, 197, 94, 0.36);
25607
+ .vr-provider-token.is-large svg,
25608
+ .vr-provider-token.is-large .vr-provider-logo,
25609
+ .vr-provider-token.is-large .vr-provider-logo img {
25610
+ width: 34px;
25611
+ height: 34px;
25673
25612
  }
25674
25613
  .vr-provider-card small,
25675
25614
  .vr-provider-card strong,
@@ -25699,6 +25638,15 @@ body:has(.vr-app.is-dragging) {
25699
25638
  font-size: 11px;
25700
25639
  font-weight: 520;
25701
25640
  }
25641
+ .vr-provider-card[data-provider-tone="orange"] em {
25642
+ color: #fbbf24;
25643
+ }
25644
+ .vr-provider-card[data-provider-tone="red"] em {
25645
+ color: #fb7185;
25646
+ }
25647
+ .vr-provider-card[data-provider-tone="neutral"] em {
25648
+ color: #aeb7c6;
25649
+ }
25702
25650
  .vr-provider-proof-chip {
25703
25651
  grid-column: 1 / -1;
25704
25652
  display: inline-flex;
@@ -25730,6 +25678,130 @@ body:has(.vr-app.is-dragging) {
25730
25678
  height: 13px;
25731
25679
  stroke: currentColor;
25732
25680
  }
25681
+ .vr-provider-mcp-chip {
25682
+ grid-column: 2;
25683
+ grid-row: 2;
25684
+ justify-self: end;
25685
+ min-width: 0;
25686
+ width: 8px;
25687
+ height: 8px;
25688
+ display: inline-flex;
25689
+ align-items: center;
25690
+ justify-content: center;
25691
+ gap: 0;
25692
+ border: 0;
25693
+ border-radius: 999px;
25694
+ padding: 0;
25695
+ color: #fbbf24;
25696
+ font-size: 10px;
25697
+ font-weight: 720;
25698
+ line-height: 1;
25699
+ background: transparent;
25700
+ }
25701
+ .vr-provider-mcp-chip i {
25702
+ width: 8px;
25703
+ height: 8px;
25704
+ flex: 0 0 auto;
25705
+ border-radius: 999px;
25706
+ background: #f59e0b;
25707
+ box-shadow: 0 0 8px rgba(245, 158, 11, 0.36);
25708
+ animation: vrStatusPulse 2.7s ease-in-out infinite;
25709
+ }
25710
+ .vr-provider-mcp-chip span {
25711
+ position: absolute;
25712
+ width: 1px;
25713
+ height: 1px;
25714
+ overflow: hidden;
25715
+ clip: rect(0 0 0 0);
25716
+ }
25717
+ .vr-provider-mcp-chip.is-connected {
25718
+ border-color: transparent;
25719
+ background: transparent;
25720
+ color: #bbf7d0;
25721
+ }
25722
+ .vr-provider-mcp-chip.is-connected i {
25723
+ background: #22c55e;
25724
+ box-shadow: 0 0 8px rgba(34, 197, 94, 0.42);
25725
+ }
25726
+ @keyframes vrStatusPulse {
25727
+ 0%, 100% {
25728
+ opacity: 0.72;
25729
+ transform: scale(0.92);
25730
+ }
25731
+ 50% {
25732
+ opacity: 1;
25733
+ transform: scale(1.08);
25734
+ }
25735
+ }
25736
+ .vr-provider-mcp-panel {
25737
+ display: grid;
25738
+ gap: 10px;
25739
+ border: 1px solid rgba(148, 163, 184, 0.13);
25740
+ border-radius: 10px;
25741
+ padding: 10px;
25742
+ background: rgba(255, 255, 255, 0.035);
25743
+ }
25744
+ .vr-provider-mcp-panel header {
25745
+ display: grid;
25746
+ grid-template-columns: 30px minmax(0, 1fr);
25747
+ gap: 10px;
25748
+ align-items: center;
25749
+ }
25750
+ .vr-provider-mcp-panel header > span {
25751
+ width: 30px;
25752
+ height: 30px;
25753
+ display: inline-grid;
25754
+ place-items: center;
25755
+ border-radius: 8px;
25756
+ background: rgba(245, 158, 11, 0.11);
25757
+ color: #fbbf24;
25758
+ }
25759
+ .vr-provider-mcp-panel strong,
25760
+ .vr-provider-mcp-panel em {
25761
+ display: block;
25762
+ min-width: 0;
25763
+ }
25764
+ .vr-provider-mcp-panel strong {
25765
+ color: #f8fafc;
25766
+ font-size: 13px;
25767
+ }
25768
+ .vr-provider-mcp-panel em {
25769
+ margin-top: 2px;
25770
+ color: #98a2b3;
25771
+ font-size: 11px;
25772
+ font-style: normal;
25773
+ }
25774
+ .vr-provider-mcp-panel > div {
25775
+ display: flex;
25776
+ flex-wrap: wrap;
25777
+ gap: 6px;
25778
+ }
25779
+ .vr-provider-mcp-panel small {
25780
+ border-radius: 999px;
25781
+ border: 1px solid rgba(148, 163, 184, 0.13);
25782
+ padding: 4px 7px;
25783
+ color: #b9c2cf;
25784
+ font-size: 10px;
25785
+ font-weight: 680;
25786
+ }
25787
+ .vr-provider-mcp-panel.is-connected {
25788
+ border-color: rgba(34, 197, 94, 0.24);
25789
+ background: rgba(34, 197, 94, 0.055);
25790
+ }
25791
+ .vr-provider-mcp-panel.is-connected header > span {
25792
+ background: rgba(34, 197, 94, 0.12);
25793
+ color: #86efac;
25794
+ }
25795
+ .vr-bottom-inventory .vr-provider-mcp-chip {
25796
+ grid-column: 3;
25797
+ grid-row: 1;
25798
+ justify-self: end;
25799
+ min-width: 0;
25800
+ width: 8px;
25801
+ height: 8px;
25802
+ padding: 0;
25803
+ font-size: 0;
25804
+ }
25733
25805
  .vr-bottom-inventory .vr-provider-proof-chip {
25734
25806
  grid-column: 4;
25735
25807
  justify-self: end;
@@ -25751,13 +25823,6 @@ body:has(.vr-app.is-dragging) {
25751
25823
  height: 15px;
25752
25824
  stroke-width: 2.35;
25753
25825
  }
25754
- .vr-bottom-inventory .vr-provider-light {
25755
- right: 36px;
25756
- top: 50%;
25757
- width: 7px;
25758
- height: 7px;
25759
- transform: translateY(-50%);
25760
- }
25761
25826
  .vr-bottom-inventory .vr-provider-card:hover .vr-provider-proof-chip,
25762
25827
  .vr-bottom-inventory .vr-provider-card.is-selected .vr-provider-proof-chip {
25763
25828
  background: transparent;
@@ -26352,33 +26417,48 @@ body:has(.vr-app.is-dragging) {
26352
26417
  width: 18px;
26353
26418
  height: 18px;
26354
26419
  }
26420
+ .vr-bottom-tip-bar .vr-inline-brand-mark.is-github {
26421
+ display: inline-grid;
26422
+ place-items: center;
26423
+ color: #f8fafc;
26424
+ }
26425
+ .vr-bottom-tip-bar .vr-inline-brand-mark.is-github svg {
26426
+ width: 17px;
26427
+ height: 17px;
26428
+ display: block;
26429
+ fill: currentColor;
26430
+ }
26355
26431
  .vr-tip-mascot {
26432
+ width: 34px;
26433
+ height: 34px;
26356
26434
  align-self: stretch;
26357
26435
  position: relative;
26358
26436
  display: grid;
26359
26437
  place-items: end center;
26360
26438
  overflow: hidden;
26439
+ border-right: 1px solid rgba(148, 163, 184, 0.16);
26361
26440
  }
26362
26441
  .vr-tip-mascot::before {
26363
26442
  content: "";
26364
26443
  position: absolute;
26365
- left: 9px;
26366
- right: 9px;
26367
- bottom: 4px;
26368
- height: 12px;
26444
+ left: 8px;
26445
+ right: 8px;
26446
+ bottom: 2px;
26447
+ height: 10px;
26369
26448
  border-radius: 999px;
26370
- background: rgba(124, 58, 237, 0.3);
26371
- filter: blur(10px);
26449
+ background: rgba(124, 58, 237, 0.24);
26450
+ filter: blur(8px);
26372
26451
  }
26373
26452
  .vr-tip-mascot img {
26374
26453
  position: relative;
26454
+ z-index: 1;
26375
26455
  align-self: end;
26376
- width: 46px;
26377
- height: 42px;
26456
+ width: 32px;
26457
+ height: 32px;
26378
26458
  object-fit: contain;
26379
26459
  object-position: bottom;
26380
- transform: translateY(4px) scale(1.02);
26381
- filter: saturate(1.18) drop-shadow(0 0 22px rgba(168, 85, 247, 0.6));
26460
+ transform: translateY(3px);
26461
+ filter: saturate(1.16) drop-shadow(0 0 12px rgba(168, 85, 247, 0.46));
26382
26462
  }
26383
26463
  .vr-bottom-tip-bar span {
26384
26464
  color: #cbd5e1;
@@ -26701,6 +26781,18 @@ body:has(.vr-app.is-dragging) {
26701
26781
  box-shadow: var(--vr-glow-purple);
26702
26782
  transition: transform 200ms cubic-bezier(0.23, 1, 0.32, 1), box-shadow 200ms ease;
26703
26783
  }
26784
+ .vr-modal-provider-logo.is-logo-html {
26785
+ display: grid;
26786
+ place-items: center;
26787
+ }
26788
+ .vr-modal-provider-logo.is-logo-html img,
26789
+ .vr-modal-provider-logo.is-logo-html svg,
26790
+ .vr-modal-provider-logo.is-logo-html .vr-provider-logo {
26791
+ width: 74px;
26792
+ height: 74px;
26793
+ display: block;
26794
+ object-fit: contain;
26795
+ }
26704
26796
 
26705
26797
  .vr-modal-provider-logo:hover {
26706
26798
  transform: translateY(-3px) rotate(-2deg);
@@ -28046,46 +28138,6 @@ body:has(.vr-app.is-dragging) {
28046
28138
  display: none;
28047
28139
  }
28048
28140
  }
28049
- .vr-permission-toggle {
28050
- display: inline-flex;
28051
- align-items: center;
28052
- gap: 0;
28053
- border: 1px solid rgba(148, 163, 184, 0.18);
28054
- border-radius: 8px;
28055
- overflow: hidden;
28056
- background: rgba(39, 40, 44, 0.92);
28057
- }
28058
- .vr-permission-btn {
28059
- min-height: 28px;
28060
- padding: 0 10px;
28061
- font-size: 11px;
28062
- font-weight: 640;
28063
- color: #94a3b8;
28064
- background: transparent;
28065
- border: none;
28066
- border-radius: 0;
28067
- cursor: pointer;
28068
- transition: background 0.12s, color 0.12s;
28069
- white-space: nowrap;
28070
- }
28071
- .vr-permission-btn + .vr-permission-btn {
28072
- border-left: 1px solid rgba(148, 163, 184, 0.14);
28073
- }
28074
- .vr-permission-btn.is-active {
28075
- background: rgba(100, 116, 139, 0.28);
28076
- color: #f1f5f9;
28077
- }
28078
- .vr-permission-btn.is-danger {
28079
- color: #f59e0b;
28080
- }
28081
- .vr-permission-btn.is-danger.is-active {
28082
- background: rgba(245, 158, 11, 0.18);
28083
- color: #fbbf24;
28084
- }
28085
- .vr-permission-btn:hover:not(.is-active) {
28086
- background: rgba(148, 163, 184, 0.1);
28087
- color: #e2e8f0;
28088
- }
28089
28141
  `;
28090
28142
  }
28091
28143
  });
@@ -28102,8 +28154,9 @@ function renderLocalUiHtml(state) {
28102
28154
  <meta name="viewport" content="width=device-width, initial-scale=1" />
28103
28155
  <meta name="theme-color" content="#050816" />
28104
28156
  <title>VibeRaven</title>
28105
- <link rel="icon" type="image/png" href="/report/assets/viberaven-mascot-idle.png" />
28106
- <link rel="apple-touch-icon" href="/report/assets/viberaven-mascot-idle.png" />
28157
+ <link rel="icon" type="image/png" sizes="64x64" href="/report/assets/viberaven-favicon.png" />
28158
+ <link rel="shortcut icon" type="image/png" href="/report/assets/viberaven-favicon.png" />
28159
+ <link rel="apple-touch-icon" href="/report/assets/viberaven-mascot.png" />
28107
28160
  <style>${localUiCss}</style>
28108
28161
  </head>
28109
28162
  <body>
@@ -28366,6 +28419,19 @@ async function releaseChangelogBetween(cwd, fromRef, toRef) {
28366
28419
  });
28367
28420
  return { from: fromRef, to: toRef, fromLabel: fromRef, toLabel: toRef, entries };
28368
28421
  }
28422
+ async function releaseDiffContextBlock(cwd, releaseId) {
28423
+ const ref = safeGitRef(releaseId);
28424
+ if (!ref || ref === "workspace") return void 0;
28425
+ if (!await gitRefExists(cwd, ref)) return void 0;
28426
+ const comparison = await compareReleaseRefs(cwd, ref, "HEAD");
28427
+ const stats = comparison.stats;
28428
+ const diffPreview = comparison.diff.length > 6e3 ? comparison.diff.slice(0, 6e3) + "\n[diff truncated]" : comparison.diff;
28429
+ return [
28430
+ `Attached release diff (${comparison.fromLabel} -> ${comparison.toLabel}):`,
28431
+ `Files changed: ${stats.files}; insertions: ${stats.insertions}; deletions: ${stats.deletions}`,
28432
+ diffPreview
28433
+ ].join("\n");
28434
+ }
28369
28435
  async function rollbackReleaseRef(cwd, targetRef) {
28370
28436
  if (!await gitRefExists(cwd, targetRef)) {
28371
28437
  return { ok: false, message: `Release ref "${targetRef}" was not found in this repo.`, checkedOut: "" };
@@ -28558,7 +28624,7 @@ async function detectLocalCliAgents(cwd, options = {}) {
28558
28624
  return {
28559
28625
  ...agent,
28560
28626
  installed,
28561
- connected: installed,
28627
+ connected: agent.id === "terminal",
28562
28628
  source: simulateDisconnected ? "simulated" : installed ? "detected" : "fallback",
28563
28629
  models: cliModelDefaults(agent.id),
28564
28630
  setup: CLI_AGENT_SETUP[agent.id]
@@ -28576,6 +28642,60 @@ function isPlaceholderProjectName(value) {
28576
28642
  const normalized = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
28577
28643
  return normalized === "" || normalized === "project" || normalized === "npx-open-source-check" || normalized.startsWith("viberaven-local-ui");
28578
28644
  }
28645
+ async function readMcpEvidence(cwd) {
28646
+ const candidates = MCP_CONFIG_PATHS.map((relativePath) => ({
28647
+ source: relativePath.replace(/\\/g, "/"),
28648
+ path: (0, import_node_path31.resolve)(cwd, relativePath)
28649
+ }));
28650
+ const home = process.env.USERPROFILE || process.env.HOME;
28651
+ if (home) {
28652
+ candidates.push({
28653
+ source: "~/.codex/config.toml",
28654
+ path: (0, import_node_path31.resolve)(home, ".codex", "config.toml")
28655
+ });
28656
+ }
28657
+ const evidence = [];
28658
+ for (const candidate of candidates) {
28659
+ try {
28660
+ const text = await (0, import_promises24.readFile)(candidate.path, "utf8");
28661
+ if (/mcp/i.test(text)) evidence.push({ source: candidate.source, text });
28662
+ } catch {
28663
+ }
28664
+ }
28665
+ return evidence;
28666
+ }
28667
+ function mcpForProvider(provider2, evidence) {
28668
+ const needles = MCP_PROVIDER_NEEDLES[provider2.id] ?? [provider2.id];
28669
+ const match = evidence.find((item4) => {
28670
+ const lower = item4.text.toLowerCase();
28671
+ return needles.some((needle) => lower.includes(needle.toLowerCase()));
28672
+ });
28673
+ if (match) {
28674
+ return {
28675
+ status: "connected",
28676
+ label: "MCP connected",
28677
+ source: match.source,
28678
+ connectCommand: MCP_CONNECT_COMMANDS[provider2.id],
28679
+ capabilities: ["repo context", provider2.area, "provider-aware chat"]
28680
+ };
28681
+ }
28682
+ return {
28683
+ status: "disconnected",
28684
+ label: "Connect MCP",
28685
+ connectCommand: MCP_CONNECT_COMMANDS[provider2.id] ?? `Add a ${provider2.name} MCP server entry, then drag ${provider2.name} into chat.`,
28686
+ capabilities: []
28687
+ };
28688
+ }
28689
+ async function applyMcpDetection(state, cwd) {
28690
+ const evidence = await readMcpEvidence(cwd);
28691
+ return {
28692
+ ...state,
28693
+ providers: state.providers.map((provider2) => ({
28694
+ ...provider2,
28695
+ mcp: mcpForProvider(provider2, evidence)
28696
+ }))
28697
+ };
28698
+ }
28579
28699
  async function enrichProjectMetadata(state, cwd) {
28580
28700
  const packageJson = await readPackageJson2(cwd);
28581
28701
  const metadata = {
@@ -28584,7 +28704,7 @@ async function enrichProjectMetadata(state, cwd) {
28584
28704
  };
28585
28705
  const files = await listProjectFiles(cwd);
28586
28706
  const deps = dependencyNames(packageJson);
28587
- const detectedState = state.empty ? applyProviderDetection(state, deps, files) : state;
28707
+ const detectedState = await applyMcpDetection(state.empty ? applyProviderDetection(state, deps, files) : state, cwd);
28588
28708
  const releases = await detectReleases(cwd, metadata.version);
28589
28709
  const missionCards = state.empty ? buildMissionCards(
28590
28710
  {
@@ -28695,19 +28815,19 @@ function parseAgentChatRequest(value) {
28695
28815
  if (rawCliId !== "codex" && rawCliId !== "claude" && rawCliId !== "gemini") return { error: "Unsupported coding CLI" };
28696
28816
  const prompt = stringField(value.prompt, 12e3);
28697
28817
  if (!prompt) return { error: "Agent chat prompt is required" };
28698
- const provider2 = isRecord7(value.provider) ? { area: stringField(value.provider.area, 120), name: stringField(value.provider.name, 120) } : void 0;
28699
- const release = isRecord7(value.release) ? { label: stringField(value.release.label, 120) } : void 0;
28700
- const rawPermMode = stringField(value.permissionMode, 20);
28701
- const permissionMode = rawPermMode === "full-access" ? "full-access" : "ask";
28818
+ const provider2 = isRecord7(value.provider) ? { id: stringField(value.provider.id, 80), area: stringField(value.provider.area, 120), name: stringField(value.provider.name, 120) } : void 0;
28819
+ const release = isRecord7(value.release) ? { id: stringField(value.release.id, 200), label: stringField(value.release.label, 120) } : void 0;
28820
+ const requestedAccessMode = stringField(value.accessMode, 40);
28821
+ const accessMode = requestedAccessMode === "ask" || requestedAccessMode === "approve" || requestedAccessMode === "full" ? requestedAccessMode : "approve";
28702
28822
  return {
28703
28823
  cliId: rawCliId,
28704
28824
  modelId: stringField(value.modelId, 120),
28705
28825
  reasoning: stringField(value.reasoning, 80),
28706
28826
  context: stringField(value.context, 80),
28827
+ accessMode,
28707
28828
  prompt,
28708
28829
  displayPrompt: stringField(value.displayPrompt, 240),
28709
28830
  taskKind: stringField(value.taskKind, 40),
28710
- permissionMode,
28711
28831
  provider: provider2,
28712
28832
  release
28713
28833
  };
@@ -28715,17 +28835,17 @@ function parseAgentChatRequest(value) {
28715
28835
  function taskKindExecutionBlock(taskKind) {
28716
28836
  switch (taskKind) {
28717
28837
  case "analyze":
28718
- return "Execution mode: analyze launch readiness. Read repo files and .viberaven artifacts; return concise findings with paths. Do not dump CLI install manuals or numbered manual runbooks.";
28838
+ return "Execution mode: analyze what changed. Read repo files and .viberaven artifacts; return concise findings with paths. Do not dump CLI install manuals or numbered manual runbooks.";
28719
28839
  case "plan":
28720
28840
  return "Execution mode: build an ordered fix plan from repo evidence. If the top blocker is repo-code, apply that fix in the project before answering. Do not reply with only manual instructions when code edits are possible.";
28721
28841
  case "fix":
28722
28842
  return "Execution mode: apply one minimal scoped repo fix IN CODE NOW. Read existing files, edit the project, save changes, then summarize. Forbidden: telling the user what to do manually when you can patch the repo yourself.";
28723
28843
  case "verify":
28724
- return "Execution mode: verify launch readiness. Prefer `npx -y viberaven --verify` or read .viberaven/gate-result.json and agent-tasklist.md.";
28844
+ return "Execution mode: verify the what-changed context. Prefer `npx -y viberaven --verify` or read .viberaven/gate-result.json and agent-tasklist.md.";
28725
28845
  case "provider":
28726
28846
  return "Execution mode: provider proof or connect mission. Edit repo wiring when missing; separate dashboard-only steps from code changes; never claim live connection without proof.";
28727
28847
  case "diff":
28728
- return "Execution mode: review production diff and flag risky changes.";
28848
+ return "Execution mode: review the release diff and flag risky changes.";
28729
28849
  case "explain":
28730
28850
  return "Execution mode: explain recent changes and next verification steps.";
28731
28851
  default:
@@ -28750,24 +28870,30 @@ async function buildAgentChatPrompt(request, cwd) {
28750
28870
  const state = await readState(cwd);
28751
28871
  const executionBlock = taskKindExecutionBlock(request.taskKind);
28752
28872
  const cardsBlock = missionCardsContextBlock(state);
28873
+ const providerState2 = request.provider?.id ? state.providers.find((provider2) => provider2.id === request.provider?.id) : state.providers.find((provider2) => provider2.name === request.provider?.name);
28874
+ const mcp = providerState2?.mcp;
28875
+ const releaseDiffBlock = await releaseDiffContextBlock(cwd, request.release?.id);
28753
28876
  const lines = [
28754
- "You are VibeRaven Studio, a production-readiness coding agent for an open-source local runner.",
28877
+ "You are VibeRaven Studio, a what-changed coding agent for an open-source local runner.",
28755
28878
  `Project folder: ${cwd}`,
28756
28879
  request.modelId ? `Selected model label: ${request.modelId}` : void 0,
28757
28880
  request.reasoning ? `Reasoning: ${request.reasoning}` : void 0,
28758
28881
  request.context ? `Context: ${request.context}` : void 0,
28882
+ `Access mode: ${request.accessMode ?? "approve"}`,
28759
28883
  request.provider?.name ? `Provider context: ${request.provider.area ?? "Provider"} / ${request.provider.name}` : void 0,
28884
+ mcp ? `Provider MCP: ${mcp.label}${mcp.source ? ` (${mcp.source})` : ""}` : void 0,
28760
28885
  request.release?.label ? `Release context: ${request.release.label}` : void 0,
28761
- state.gate?.label ? `Gate: ${state.gate.label} (${state.gate.status ?? "unknown"})` : void 0,
28886
+ releaseDiffBlock,
28887
+ state.gate?.label ? `Project status: ${state.gate.label} (${state.gate.status ?? "unknown"})` : void 0,
28762
28888
  state.missionControl?.mainBlocker ? `Main blocker: ${state.missionControl.mainBlocker}` : void 0,
28763
28889
  executionBlock,
28764
28890
  cardsBlock,
28765
28891
  "",
28766
28892
  "Safety rules:",
28767
28893
  "- Stay scoped to this project folder.",
28768
- "- Explain risky or destructive changes before making them.",
28894
+ (request.accessMode ?? "approve") === "ask" ? "- Ask before editing files, using the internet, running destructive commands, or changing provider settings." : (request.accessMode ?? "approve") === "full" ? "- Full access is enabled for this local project; still explain destructive changes before running them." : "- Edit project files when needed, but explain risky or destructive changes before making them.",
28769
28895
  "- Do not claim provider dashboard setup is complete from repo edits alone.",
28770
- "- Keep the answer focused on production readiness.",
28896
+ "- Keep the answer focused on what changed, provider context, and the next grounded action.",
28771
28897
  "- Return only the final user-facing answer. Do not echo this prompt, session metadata, logs, or command transcripts.",
28772
28898
  "- For fix/plan/provider repo gaps: edit files in this project before answering. Manual dashboard steps are only for gaps that cannot be solved in repo code.",
28773
28899
  "- Never paste long VibeRaven operator manuals, heal loops, or PowerShell command blocks unless the user explicitly asked how to run verify.",
@@ -28799,24 +28925,19 @@ function insertCodexExecOptions(codexArgs, pairs) {
28799
28925
  const insertAt = execIndex >= 0 ? execIndex + 1 : codexArgs.length;
28800
28926
  codexArgs.splice(insertAt, 0, ...pairs);
28801
28927
  }
28802
- function resolveCodexSandboxArgs(permissionMode, platform) {
28803
- if (permissionMode === "full-access") {
28804
- return ["--sandbox", "danger-full-access", "--ask-for-approval", "never"];
28805
- }
28806
- if (platform === "win32") {
28807
- return ["--sandbox", "danger-full-access", "--ask-for-approval", "on-request"];
28808
- }
28809
- return ["--sandbox", "workspace-write", "--ask-for-approval", "on-request"];
28928
+ function codexAccessFlags(accessMode) {
28929
+ if (accessMode === "ask") return ["--sandbox", "workspace-write", "--ask-for-approval", "on-request"];
28930
+ if (accessMode === "full") return ["--sandbox", "danger-full-access", "--ask-for-approval", "never"];
28931
+ return ["--sandbox", "workspace-write", "--ask-for-approval", "on-failure"];
28810
28932
  }
28811
- function commandForAgentChat(request, prompt, cwd, outputPath, platform = process.platform) {
28812
- const command = platform === "win32" ? `${request.cliId}.cmd` : request.cliId;
28933
+ function commandForAgentChat(request, prompt, cwd, outputPath) {
28934
+ const command = process.platform === "win32" ? `${request.cliId}.cmd` : request.cliId;
28813
28935
  const promptArg = prompt.replace(/\s*\r?\n\s*/g, " ");
28814
28936
  const model = normalizeCliModelId(request.modelId);
28815
28937
  const effort = resolveCliReasoningEffort(request.cliId, request.reasoning);
28816
- const permissionMode = request.permissionMode ?? "ask";
28817
28938
  if (request.cliId === "gemini") {
28818
28939
  const geminiArgs = ["-p", promptArg, "--output-format", "text"];
28819
- if (permissionMode === "full-access") geminiArgs.push("--skip-trust");
28940
+ if (request.accessMode !== "ask") geminiArgs.push("--skip-trust");
28820
28941
  if (model) geminiArgs.splice(0, 0, "-m", model);
28821
28942
  return { command, args: geminiArgs };
28822
28943
  }
@@ -28824,13 +28945,12 @@ function commandForAgentChat(request, prompt, cwd, outputPath, platform = proces
28824
28945
  const claudeArgs = ["-p", promptArg];
28825
28946
  if (model) claudeArgs.unshift("--model", model);
28826
28947
  if (effort) claudeArgs.unshift("--effort", effort);
28827
- if (permissionMode === "full-access") {
28948
+ if (request.accessMode === "full") {
28828
28949
  claudeArgs.push("--dangerously-skip-permissions");
28829
28950
  }
28830
28951
  return { command, args: claudeArgs };
28831
28952
  }
28832
- const sandboxArgs = resolveCodexSandboxArgs(permissionMode, platform);
28833
- const codexArgs = ["--cd", cwd, ...sandboxArgs, "exec", "--color", "never"];
28953
+ const codexArgs = ["--cd", cwd, ...codexAccessFlags(request.accessMode), "exec", "--color", "never"];
28834
28954
  const codexExecOptions = [];
28835
28955
  if (model) codexExecOptions.push("-m", model);
28836
28956
  if (effort) codexExecOptions.push("-c", `model_reasoning_effort="${effort}"`);
@@ -28971,7 +29091,7 @@ async function runLocalAction(cwd, intent) {
28971
29091
  "# VibeRaven preview rehearsal",
28972
29092
  "",
28973
29093
  `Project: ${projectName}`,
28974
- `Gate: ${gateLabel}`,
29094
+ `Project status: ${gateLabel}`,
28975
29095
  `Blocker: ${blocker}`,
28976
29096
  "",
28977
29097
  "## Recording flow",
@@ -29171,7 +29291,7 @@ async function sendReportArtifact(cwd, response) {
29171
29291
  </div>
29172
29292
  <section class="steps" aria-label="Report next steps">
29173
29293
  <div class="step"><b>1. Manage providers</b><span>Use the Provider Control Board to review each slot and open the right dashboard.</span></div>
29174
- <div class="step"><b>2. Start agent fix</b><span>Preview the handoff flow and keep the fix scoped to one launch gap.</span></div>
29294
+ <div class="step"><b>2. Start agent fix</b><span>Preview the handoff flow and keep the fix scoped to one evidenced change.</span></div>
29175
29295
  <div class="step"><b>3. Verify</b><span>Use Verify Now in the launch screen when you are ready to check the flow.</span></div>
29176
29296
  </section>
29177
29297
  <div class="actions">
@@ -29571,7 +29691,7 @@ async function waitForServerShutdown() {
29571
29691
  process.once("SIGTERM", done);
29572
29692
  });
29573
29693
  }
29574
- var import_node_http, import_node_child_process4, import_promises24, import_node_path31, CLI_AGENT_SETUP, CLI_AUTH_PROBE;
29694
+ var import_node_http, import_node_child_process4, import_promises24, import_node_path31, CLI_AGENT_SETUP, MCP_CONFIG_PATHS, MCP_PROVIDER_NEEDLES, MCP_CONNECT_COMMANDS, CLI_AUTH_PROBE;
29575
29695
  var init_server = __esm({
29576
29696
  "src/local-ui/server.ts"() {
29577
29697
  "use strict";
@@ -29612,6 +29732,30 @@ var init_server = __esm({
29612
29732
  docsUrl: "https://viberaven.dev"
29613
29733
  }
29614
29734
  };
29735
+ MCP_CONFIG_PATHS = [
29736
+ ".mcp.json",
29737
+ "mcp.json",
29738
+ (0, import_node_path31.join)(".cursor", "mcp.json"),
29739
+ (0, import_node_path31.join)(".vscode", "mcp.json")
29740
+ ];
29741
+ MCP_PROVIDER_NEEDLES = {
29742
+ supabase: ["supabase", "@supabase/mcp", "mcp-server-supabase"],
29743
+ vercel: ["vercel"],
29744
+ stripe: ["stripe"],
29745
+ github: ["github"],
29746
+ sentry: ["sentry"],
29747
+ posthog: ["posthog"],
29748
+ clerk: ["clerk"],
29749
+ authjs: ["authjs", "next-auth", "nextauth"],
29750
+ resend: ["resend"],
29751
+ upstash: ["upstash"]
29752
+ };
29753
+ MCP_CONNECT_COMMANDS = {
29754
+ supabase: "Add the Supabase MCP server to your local MCP config, then drag Supabase into chat.",
29755
+ vercel: "Add a Vercel MCP server entry to your local MCP config, then drag Vercel into chat.",
29756
+ stripe: "Add a Stripe MCP server entry to your local MCP config, then drag Stripe into chat.",
29757
+ github: "Add the GitHub MCP server to your local MCP config, then drag GitHub into chat."
29758
+ };
29615
29759
  CLI_AUTH_PROBE = {
29616
29760
  codex: "codex login status",
29617
29761
  claude: "claude auth status",
@@ -29634,11 +29778,7 @@ function buildNextActionBlock(tasks, loopState, plan) {
29634
29778
  return {
29635
29779
  ...base,
29636
29780
  type: "stalled",
29637
- title: "Loop stalled - no gap reduction after 2+ consecutive scans",
29638
- agentInstruction: "Stop the scan loop. Explain the blocker plainly, then either guide the provider/user action or report that no safe repo-code recipe is available.",
29639
- executionPlan: [
29640
- { kind: "stop", note: "Do not keep spending scans while the loop is stalled." }
29641
- ],
29781
+ title: "Loop stalled \xE2\u20AC\u201D no gap reduction after 2+ consecutive scans",
29642
29782
  requiresUserAction: true,
29643
29783
  stallReason
29644
29784
  };
@@ -29647,67 +29787,42 @@ function buildNextActionBlock(tasks, loopState, plan) {
29647
29787
  return {
29648
29788
  ...base,
29649
29789
  type: "verify",
29650
- title: "Batch complete - run verify to rescan before next batch",
29651
- agentInstruction: "Run verify now, read the refreshed VibeRaven artifacts, then continue with the next safe repo fix or provider step. Do not stop at a summary.",
29652
- executionPlan: [
29653
- { kind: "verify", command: "viberaven_verify" },
29654
- { kind: "continue-loop", note: "After verify, continue until the gate is clear or a provider/user blocker remains." }
29655
- ],
29790
+ title: "Batch complete \xE2\u20AC\u201D run verify to rescan before next batch",
29656
29791
  mcpTool: "viberaven_verify",
29657
29792
  mcpArgs: {},
29658
29793
  requiresUserAction: false
29659
29794
  };
29660
29795
  }
29661
- const repoCodeTask = tasks.find((task) => task.fixType === "repo-code" && !task.requiresUserAction);
29796
+ const repoCodeTask = tasks.find((t) => t.fixType === "repo-code" && !t.requiresUserAction);
29662
29797
  if (repoCodeTask) {
29663
- const fallbackCommand = repoCodeTask.mcpArgs ? `npx -y viberaven --heal --apply --gap ${repoCodeTask.gapId} --yes` : void 0;
29664
29798
  return {
29665
29799
  ...base,
29666
29800
  type: "repo-code",
29667
29801
  gapId: repoCodeTask.gapId,
29668
29802
  title: repoCodeTask.title,
29669
- agentInstruction: "Apply this repo-code fix now using the MCP tool or fallback command, then continue the local VibeRaven loop. Do not stop at a summary.",
29670
- executionPlan: [
29671
- {
29672
- kind: "apply-repo-fix",
29673
- command: repoCodeTask.mcpTool ?? fallbackCommand,
29674
- note: "Patch only this gap and preserve unrelated user changes."
29675
- },
29676
- { kind: "continue-loop", note: "Apply remaining safe repo fixes until the batch is full, then verify once." }
29677
- ],
29678
29803
  mcpTool: repoCodeTask.mcpTool,
29679
29804
  mcpArgs: repoCodeTask.mcpArgs,
29680
- fallbackCommand,
29805
+ fallbackCommand: repoCodeTask.mcpArgs ? `npx -y viberaven --heal --apply --gap ${repoCodeTask.gapId} --yes` : void 0,
29681
29806
  requiresUserAction: false
29682
29807
  };
29683
29808
  }
29684
- const providerTask = tasks.find((task) => task.fixType === "provider-action");
29809
+ const providerTask = tasks.find((t) => t.fixType === "provider-action");
29685
29810
  if (providerTask) {
29686
29811
  return {
29687
29812
  ...base,
29688
29813
  type: "provider-action",
29689
29814
  gapId: providerTask.gapId,
29690
29815
  title: providerTask.title,
29691
- agentInstruction: "Open or present the provider step now. If browser/tool access is available, open the dashboard link for the user; otherwise show the exact step and copy values. Do not keep telling the user to verify until the provider step is done.",
29692
- executionPlan: [
29693
- { kind: "open-provider-step", note: "Use VIBERAVEN_PROVIDER_ACTION for the exact dashboard step and URL." },
29694
- { kind: "wait-for-user", note: "Wait for confirmation or read-only MCP evidence before verifying." }
29695
- ],
29696
29816
  requiresUserAction: true
29697
29817
  };
29698
29818
  }
29699
- const upgradeTask = tasks.find((task) => task.fixType === "upgrade-required");
29819
+ const upgradeTask = tasks.find((t) => t.fixType === "upgrade-required");
29700
29820
  if (upgradeTask) {
29701
29821
  return {
29702
29822
  ...base,
29703
29823
  type: "upgrade-required",
29704
29824
  gapId: upgradeTask.gapId,
29705
29825
  title: upgradeTask.title,
29706
- agentInstruction: "Explain that this production lane needs an upgrade or connected provider evidence. Continue with any remaining unlocked repo-code fixes if present; otherwise stop cleanly.",
29707
- executionPlan: [
29708
- { kind: "upgrade", command: "https://viberaven.dev/pricing" },
29709
- { kind: "stop", note: "Do not pretend locked lanes or provider state were fixed locally." }
29710
- ],
29711
29826
  requiresUserAction: true,
29712
29827
  upgradeUrl: "https://viberaven.dev/pricing"
29713
29828
  };
@@ -29715,20 +29830,15 @@ function buildNextActionBlock(tasks, loopState, plan) {
29715
29830
  return {
29716
29831
  ...base,
29717
29832
  type: "done",
29718
- title: "All gaps resolved - production gate is clear",
29719
- agentInstruction: "The repo-code gate is clear. Run strict before deploy and still verify provider dashboard state through MCP or the provider dashboard.",
29720
- executionPlan: [
29721
- { kind: "verify", command: "npx -y viberaven --strict" },
29722
- { kind: "stop", note: "Do not deploy until provider dashboard state is verified where applicable." }
29723
- ],
29833
+ title: "All gaps resolved - what-changed context is clear",
29724
29834
  requiresUserAction: false
29725
29835
  };
29726
29836
  }
29727
29837
  function resolveStallReason(tasks) {
29728
29838
  if (tasks.length === 0) return "no-recipes";
29729
- const allUpgradeOrEmpty = tasks.every((task) => task.fixType === "upgrade-required");
29839
+ const allUpgradeOrEmpty = tasks.every((t) => t.fixType === "upgrade-required");
29730
29840
  if (allUpgradeOrEmpty) return "no-recipes";
29731
- const allProviderAction = tasks.every((task) => task.fixType === "provider-action");
29841
+ const allProviderAction = tasks.every((t) => t.fixType === "provider-action");
29732
29842
  if (allProviderAction) return "provider-action-required";
29733
29843
  return "unknown";
29734
29844
  }
@@ -29753,7 +29863,7 @@ function buildProviderActionBlock(task) {
29753
29863
  }
29754
29864
  function printProviderActionBlock(tasks) {
29755
29865
  const task = tasks.find(
29756
- (entry) => entry.fixType === "provider-action" && entry.requiresUserAction === true
29866
+ (t) => t.fixType === "provider-action" && t.requiresUserAction === true
29757
29867
  );
29758
29868
  if (!task) return;
29759
29869
  const block = buildProviderActionBlock(task);
@@ -29893,15 +30003,16 @@ __export(cli_exports, {
29893
30003
  });
29894
30004
  module.exports = __toCommonJS(cli_exports);
29895
30005
  function printHelp() {
29896
- console.log(`viberaven ${VERSION} \u2014 launch readiness for AI-built apps
30006
+ console.log(`viberaven ${VERSION} - what changed for AI-built apps
29897
30007
 
29898
30008
 
29899
30009
 
29900
30010
  Usage:
29901
30011
 
29902
- viberaven Open the local launch console for human TTY use
30012
+ viberaven Open the local Studio for human TTY use
30013
+
30014
+ viberaven ui [path] Open the local Studio
29903
30015
 
29904
- viberaven ui [path] Open the local launch console
29905
30016
  viberaven tui Same interactive menu
29906
30017
 
29907
30018
  viberaven login [--api-url <url>]
@@ -29911,7 +30022,7 @@ Usage:
29911
30022
  viberaven status
29912
30023
 
29913
30024
  viberaven actions [--json] [path]
29914
- Print current chat-native production action surface
30025
+ Print current chat-native action surface
29915
30026
 
29916
30027
  viberaven preview [--agent-mode] [--json]
29917
30028
  Local production rehearsal for videos and onboarding; no login or API spend
@@ -29928,7 +30039,7 @@ Usage:
29928
30039
  Agent-first scan; writes tasklist, gate-result, context-map, and per-gap JSON
29929
30040
 
29930
30041
  viberaven --strict[=warning] [path]
29931
- Fail when production gate is not clear; warning mode also fails on warnings
30042
+ Fail when what-changed context is not clear; warning mode also fails on warnings
29932
30043
 
29933
30044
  viberaven --condense [path]
29934
30045
  Refresh .viberaven/context-map.json from the last scan
@@ -29973,7 +30084,7 @@ Agent workflow (Claude Code / Codex):
29973
30084
 
29974
30085
  Read .viberaven/agent-tasklist.md first, .viberaven/gate-result.json for the machine verdict, then .viberaven/context-map.json
29975
30086
 
29976
- viberaven next --json \u2192 guide/open \u2192 scan again
30087
+ viberaven next --json \xE2\u2020\u2019 guide/open \xE2\u2020\u2019 scan again
29977
30088
 
29978
30089
 
29979
30090
 
@@ -29989,7 +30100,7 @@ Environment:
29989
30100
 
29990
30101
  Security:
29991
30102
 
29992
- CLI scans use VibeRaven login \u2014 not OPENAI_API_KEY. See packages/cli/SECURITY.md.
30103
+ CLI scans use VibeRaven login \xE2\u20AC\u201D not OPENAI_API_KEY. See packages/cli/SECURITY.md.
29993
30104
 
29994
30105
  `);
29995
30106
  }
@@ -30010,9 +30121,6 @@ function parseArgs(argv) {
30010
30121
  if (arg.startsWith("--")) {
30011
30122
  const equalsIndex = arg.indexOf("=");
30012
30123
  const key = equalsIndex === -1 ? arg.slice(2) : arg.slice(2, equalsIndex);
30013
- if (key === "pet") {
30014
- continue;
30015
- }
30016
30124
  if (equalsIndex !== -1) {
30017
30125
  flags[key] = arg.slice(equalsIndex + 1);
30018
30126
  continue;
@@ -30108,9 +30216,6 @@ function resolveDefaultEntrypointMode(options) {
30108
30216
  if (options.env.VIBERAVEN_AGENT === "1") return "agent-scan";
30109
30217
  return "local-ui";
30110
30218
  }
30111
- function resolvePositionalCwd(positional) {
30112
- return positional[0] ? (0, import_node_path33.resolve)(process.cwd(), positional[0]) : process.cwd();
30113
- }
30114
30219
  function formatScanJsonStdout(artifact) {
30115
30220
  return JSON.stringify(sanitizeArtifactForDisk(artifact), null, 2);
30116
30221
  }
@@ -30151,7 +30256,7 @@ async function cmdStatus(flags, positional) {
30151
30256
  console.log("Not signed in. Run: viberaven login");
30152
30257
  return 1;
30153
30258
  }
30154
- const startDir = resolvePositionalCwd(positional);
30259
+ const startDir = positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : process.cwd();
30155
30260
  let artifact;
30156
30261
  try {
30157
30262
  artifact = await loadLastArtifact(startDir);
@@ -30188,7 +30293,7 @@ async function cmdStatus(flags, positional) {
30188
30293
  console.log(`Plan: ${synced.plan ?? "unknown"}`);
30189
30294
  console.log(formatUsageLine(usage));
30190
30295
  if (artifact) {
30191
- console.log(`Production core: ${artifact.productionCorePercent}% \xB7 Score ${artifact.score}`);
30296
+ console.log(`Production core: ${artifact.productionCorePercent}% \xC2\xB7 Score ${artifact.score}`);
30192
30297
  console.log(
30193
30298
  `Lanes: ${usage.unlockedMapCategoryKeys.length}/${PRODUCTION_MAP_CATEGORY_KEYS_ALL.length} unlocked`
30194
30299
  );
@@ -30305,7 +30410,7 @@ async function cmdWatch(flags) {
30305
30410
  }
30306
30411
  }
30307
30412
  async function runScanCommand(flags, positional, options) {
30308
- const workspacePath = positional[0] ? resolvePositionalCwd(positional) : await resolveWorkspaceRoot(process.cwd());
30413
+ const workspacePath = positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : await resolveWorkspaceRoot(process.cwd());
30309
30414
  const apiBaseUrl = resolveApiBaseUrl(typeof flags["api-url"] === "string" ? flags["api-url"] : void 0);
30310
30415
  let accessToken;
30311
30416
  try {
@@ -30329,7 +30434,7 @@ async function runScanCommand(flags, positional, options) {
30329
30434
  }
30330
30435
  }
30331
30436
  if (!options?.deferMachineOutput) {
30332
- console.log(`Scanning ${workspacePath}\u2026`);
30437
+ console.log(`Scanning ${workspacePath}\xE2\u20AC\xA6`);
30333
30438
  }
30334
30439
  const result = await runProjectScan({ workspacePath, accessToken, apiBaseUrl });
30335
30440
  if (!result.ok) {
@@ -30389,7 +30494,7 @@ async function runScanCommand(flags, positional, options) {
30389
30494
  return { exitCode: 0, artifacts: paths };
30390
30495
  }
30391
30496
  async function cmdReport(flags, positional) {
30392
- const startDir = resolvePositionalCwd(positional);
30497
+ const startDir = positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : process.cwd();
30393
30498
  try {
30394
30499
  const paths = await refreshReportFromDisk(startDir);
30395
30500
  console.log(`Report refreshed: ${paths.reportPath}`);
@@ -30411,7 +30516,7 @@ async function cmdReport(flags, positional) {
30411
30516
  }
30412
30517
  }
30413
30518
  async function cmdPrompt(flags, positional) {
30414
- const startDir = resolvePositionalCwd(positional);
30519
+ const startDir = positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : process.cwd();
30415
30520
  let artifact;
30416
30521
  try {
30417
30522
  artifact = await loadLastArtifact(startDir);
@@ -30475,7 +30580,7 @@ async function cmdStack(positional) {
30475
30580
  const file = await loadStackChoicesFile(cwd);
30476
30581
  file.choices[area] = { provider: provider2, selectedAt: (/* @__PURE__ */ new Date()).toISOString() };
30477
30582
  await saveStackChoicesFile(cwd, file);
30478
- console.log(`Set ${area} \u2192 ${provider2}. Run \`viberaven scan\` to re-map.`);
30583
+ console.log(`Set ${area} \xE2\u2020\u2019 ${provider2}. Run \`viberaven scan\` to re-map.`);
30479
30584
  return 0;
30480
30585
  }
30481
30586
  if (sub === "clear") {
@@ -30508,7 +30613,7 @@ async function main() {
30508
30613
  const wantsJsonl = hasFlag(flags, "jsonl");
30509
30614
  const wantsStrict = hasFlag(flags, "strict");
30510
30615
  if (flags.condense) {
30511
- const cwd = resolvePositionalCwd(positional);
30616
+ const cwd = positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : process.cwd();
30512
30617
  const result = await runCondenseCommand({ cwd });
30513
30618
  console.log(`VibeRaven context map refreshed: ${result.contextMapPath}`);
30514
30619
  return 0;
@@ -30528,7 +30633,7 @@ async function main() {
30528
30633
  }
30529
30634
  if (!command && flags.verify === true && typeof flags.action === "string") {
30530
30635
  return runVerifyActionCommand({
30531
- cwd: resolvePositionalCwd(positional),
30636
+ cwd: positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : process.cwd(),
30532
30637
  actionId: flags.action
30533
30638
  });
30534
30639
  }
@@ -30565,7 +30670,7 @@ async function main() {
30565
30670
  env: process.env
30566
30671
  });
30567
30672
  if (mode === "local-ui") {
30568
- const cwd = resolvePositionalCwd(positional);
30673
+ const cwd = positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : process.cwd();
30569
30674
  const handle = await startLocalUiServer({ cwd });
30570
30675
  console.log(`VibeRaven local UI: ${handle.url}`);
30571
30676
  await waitForServerShutdown();
@@ -30585,7 +30690,7 @@ async function main() {
30585
30690
  await runInteractiveSession();
30586
30691
  return 0;
30587
30692
  case "ui": {
30588
- const cwd = resolvePositionalCwd(positional);
30693
+ const cwd = positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : process.cwd();
30589
30694
  const handle = await startLocalUiServer({ cwd });
30590
30695
  console.log(`VibeRaven local UI: ${handle.url}`);
30591
30696
  await waitForServerShutdown();
@@ -30602,19 +30707,19 @@ async function main() {
30602
30707
  return cmdStatus(flags, positional);
30603
30708
  case "actions":
30604
30709
  return runActionsCommand({
30605
- cwd: resolvePositionalCwd(positional),
30710
+ cwd: positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : process.cwd(),
30606
30711
  json: Boolean(flags.json)
30607
30712
  });
30608
30713
  case "preview":
30609
30714
  return runPreviewCommand({
30610
- cwd: resolvePositionalCwd(positional),
30715
+ cwd: positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : process.cwd(),
30611
30716
  agentMode: flags["agent-mode"] === true,
30612
30717
  json: Boolean(flags.json)
30613
30718
  });
30614
30719
  case "next":
30615
30720
  return runNextCommand({
30616
30721
  json: Boolean(flags.json),
30617
- cwd: resolvePositionalCwd(positional)
30722
+ cwd: positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : process.cwd()
30618
30723
  });
30619
30724
  case "guide": {
30620
30725
  const provider2 = positional[0];
@@ -30652,7 +30757,7 @@ async function main() {
30652
30757
  case "provider-verify":
30653
30758
  return cmdProviderVerify(flags, positional);
30654
30759
  case "init": {
30655
- const cwd = resolvePositionalCwd(positional);
30760
+ const cwd = positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : process.cwd();
30656
30761
  const agents = typeof flags.agents === "string" ? flags.agents : void 0;
30657
30762
  return runInitCommand({
30658
30763
  cwd,
@@ -30666,7 +30771,7 @@ async function main() {
30666
30771
  return 1;
30667
30772
  }
30668
30773
  return runDoctorAgentsCommand({
30669
- cwd: resolvePositionalCwd(positional)
30774
+ cwd: positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : process.cwd()
30670
30775
  });
30671
30776
  case "validate-npm-package":
30672
30777
  return runValidateNpmPackageCommand({
@@ -30679,7 +30784,7 @@ async function main() {
30679
30784
  return 1;
30680
30785
  }
30681
30786
  return runAuditCommand({
30682
- cwd: resolvePositionalCwd(positional),
30787
+ cwd: positional[0] ? (0, import_node_path33.join)(process.cwd(), positional[0]) : process.cwd(),
30683
30788
  json: Boolean(flags.json)
30684
30789
  });
30685
30790
  default: