@viberaven/cli 1.6.2 → 1.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +64 -64
- package/LICENSE +21 -21
- package/README.md +113 -113
- package/SECURITY.md +59 -59
- package/dist/cli.js +1201 -822
- package/dist/console/app.js +251 -251
- package/dist/console/index.html +46 -46
- package/dist/console/styles.css +267 -267
- package/dist/playbooks/_stack-default.json +11 -11
- package/dist/playbooks/auth-supabase.json +31 -31
- package/dist/playbooks/stripe.json +66 -66
- package/dist/playbooks/supabase.json +51 -51
- package/dist/playbooks/vercel.json +42 -42
- package/dist/report/assets/provider-authjs.svg +5 -5
- package/dist/report/assets/provider-aws.svg +5 -5
- package/dist/report/assets/provider-logrocket.svg +4 -4
- package/dist/report/report-cli.css +1466 -1466
- package/dist/report/station.css +11854 -11854
- package/dist/report/station.js +8319 -8319
- package/dist/stack/stack.css +1008 -1008
- package/dist/vendor/anime.umd.min.js +7 -7
- package/package.json +95 -84
- package/playbooks/_stack-default.json +11 -11
- package/playbooks/auth-supabase.json +31 -31
- package/playbooks/stripe.json +66 -66
- package/playbooks/supabase.json +51 -51
- package/playbooks/vercel.json +42 -42
- package/schemas/permissions-matrix.schema.json +90 -90
- package/templates/AGENTS.snippet.md +56 -56
- package/templates/CLAUDE.snippet.md +14 -14
- package/templates/CURSOR.snippet.md +14 -14
package/dist/cli.js
CHANGED
|
@@ -656,9 +656,30 @@ function normalizeGap(v) {
|
|
|
656
656
|
toolSuggestions,
|
|
657
657
|
mcpSuggestion: typeof v.mcpSuggestion === "string" ? v.mcpSuggestion : null,
|
|
658
658
|
primaryMapCategory: affectedMapCategories[0],
|
|
659
|
-
affectedMapCategories
|
|
659
|
+
affectedMapCategories,
|
|
660
|
+
...normalizeLocations(v.locations)
|
|
660
661
|
};
|
|
661
662
|
}
|
|
663
|
+
function normalizeLocations(v) {
|
|
664
|
+
if (!Array.isArray(v)) return {};
|
|
665
|
+
const locations = [];
|
|
666
|
+
for (const item4 of v) {
|
|
667
|
+
if (!isRecord(item4) || typeof item4.file !== "string" || !item4.file.trim()) continue;
|
|
668
|
+
const line = typeof item4.line === "number" && Number.isInteger(item4.line) && item4.line > 0 ? item4.line : void 0;
|
|
669
|
+
locations.push(line === void 0 ? { file: item4.file } : { file: item4.file, line });
|
|
670
|
+
}
|
|
671
|
+
return locations.length > 0 ? { locations } : {};
|
|
672
|
+
}
|
|
673
|
+
function mergeLocations(a, b3) {
|
|
674
|
+
const seen = /* @__PURE__ */ new Set();
|
|
675
|
+
const merged = [...a ?? [], ...b3 ?? []].filter((location) => {
|
|
676
|
+
const key = `${location.file}:${location.line ?? ""}`;
|
|
677
|
+
if (seen.has(key)) return false;
|
|
678
|
+
seen.add(key);
|
|
679
|
+
return true;
|
|
680
|
+
});
|
|
681
|
+
return merged.length > 0 ? { locations: merged } : {};
|
|
682
|
+
}
|
|
662
683
|
function rootGapKey(gap) {
|
|
663
684
|
const titleKey = slugify(gap.title);
|
|
664
685
|
if (titleKey) {
|
|
@@ -688,7 +709,8 @@ function mergeRootGaps(a, b3) {
|
|
|
688
709
|
toolSuggestions: mergeToolSuggestions(a.toolSuggestions, b3.toolSuggestions),
|
|
689
710
|
mcpSuggestion: a.mcpSuggestion ?? b3.mcpSuggestion,
|
|
690
711
|
primaryMapCategory: a.primaryMapCategory,
|
|
691
|
-
affectedMapCategories: a.affectedMapCategories
|
|
712
|
+
affectedMapCategories: a.affectedMapCategories,
|
|
713
|
+
...mergeLocations(a.locations, b3.locations)
|
|
692
714
|
};
|
|
693
715
|
}
|
|
694
716
|
function dedupeRootGaps(gaps) {
|
|
@@ -3304,11 +3326,11 @@ var init_providerTruth = __esm({
|
|
|
3304
3326
|
// ../../src/station/promptBuilder.ts
|
|
3305
3327
|
function buildAnalysisPrompt(scan, specContent, productionConnectionContext, scannerEvidenceContext, stackWiringContext, stackAutomationContext) {
|
|
3306
3328
|
const sections = [];
|
|
3307
|
-
const
|
|
3329
|
+
const detectedStack2 = Object.entries(scan.stackSignals).filter(([, v]) => v === true).map(([k3]) => k3).join(", ");
|
|
3308
3330
|
sections.push(`## PROJECT CONTEXT
|
|
3309
3331
|
Total files in repo: ${scan.totalFilesScanned}
|
|
3310
3332
|
Files analyzed: ${scan.files.length}
|
|
3311
|
-
Detected stack signals: ${
|
|
3333
|
+
Detected stack signals: ${detectedStack2 || "none detected"}
|
|
3312
3334
|
All dependencies: ${scan.packageDeps.join(", ") || "none found"}
|
|
3313
3335
|
Secret files found (contents not read): ${scan.secretsFound.join(", ") || "none"}
|
|
3314
3336
|
`);
|
|
@@ -8462,8 +8484,9 @@ function readFunctionAttributes(tokens) {
|
|
|
8462
8484
|
if (t.value === "security" && next?.kind === "word" && (next.value === "definer" || next.value === "invoker")) {
|
|
8463
8485
|
out.definer = next.value === "definer";
|
|
8464
8486
|
}
|
|
8465
|
-
if (t.value === "returns" && next?.kind === "word") {
|
|
8466
|
-
|
|
8487
|
+
if (t.value === "returns" && (next?.kind === "word" || next?.kind === "ident")) {
|
|
8488
|
+
const type = next.value;
|
|
8489
|
+
out.returnsTrigger = type === "trigger" || type === "event_trigger";
|
|
8467
8490
|
}
|
|
8468
8491
|
}
|
|
8469
8492
|
return out;
|
|
@@ -8591,7 +8614,7 @@ function analyzeRls(replay) {
|
|
|
8591
8614
|
}
|
|
8592
8615
|
if (!table2.rls && (table2.created || table2.disabledLoc)) {
|
|
8593
8616
|
const where = table2.disabledLoc ?? table2.arrivedLoc ?? table2.created;
|
|
8594
|
-
const risk = "
|
|
8617
|
+
const risk = "Without RLS, the Data API does not enforce row restrictions for roles and operations allowed by the table's grants. Verify those grants to determine who can read or change rows.";
|
|
8595
8618
|
const message = table2.disabledLoc ? `${table2.display} has row level security turned off at ${at(table2.disabledLoc)}. ${risk}` : table2.arrivedLoc ? `${table2.display} is moved into public at ${at(table2.arrivedLoc)} without row level security, and no later migration enables it. ${risk}` : `${table2.display} is created at ${at(table2.created)} and no migration enables row level security on it. ${risk}`;
|
|
8596
8619
|
missingRls.push({
|
|
8597
8620
|
id: "rls_disabled",
|
|
@@ -9417,7 +9440,7 @@ function buildRlsCheck(replay) {
|
|
|
9417
9440
|
id: "supabase-rls-policy-proof",
|
|
9418
9441
|
title: "Supabase RLS policy proof",
|
|
9419
9442
|
status: "needs_work",
|
|
9420
|
-
summary: `${plural(analysis.missingRls.length, "public table")} without row level security: ${names}.
|
|
9443
|
+
summary: `${plural(analysis.missingRls.length, "public table")} without row level security: ${names}. The Data API does not enforce row restrictions for roles and operations allowed by the table's grants. Verify those grants to determine who can read or change rows.`,
|
|
9421
9444
|
evidence: findingEvidence(analysis.missingRls),
|
|
9422
9445
|
findings
|
|
9423
9446
|
};
|
|
@@ -10437,6 +10460,18 @@ var init_databaseEvidence = __esm({
|
|
|
10437
10460
|
});
|
|
10438
10461
|
|
|
10439
10462
|
// src/localStation.ts
|
|
10463
|
+
function findingLocations(findings) {
|
|
10464
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10465
|
+
const out = [];
|
|
10466
|
+
for (const finding of findings) {
|
|
10467
|
+
if (!finding.file) continue;
|
|
10468
|
+
const key = `${finding.file}:${finding.line ?? ""}`;
|
|
10469
|
+
if (seen.has(key)) continue;
|
|
10470
|
+
seen.add(key);
|
|
10471
|
+
out.push(finding.line ? { file: finding.file, line: finding.line } : { file: finding.file });
|
|
10472
|
+
}
|
|
10473
|
+
return out.slice(0, DETAIL_MAX_FINDINGS);
|
|
10474
|
+
}
|
|
10440
10475
|
function hasFilePath(scan, pattern) {
|
|
10441
10476
|
return scan.files.some((f) => pattern.test(f.path));
|
|
10442
10477
|
}
|
|
@@ -10730,7 +10765,8 @@ function auditFindingSeeds(audit) {
|
|
|
10730
10765
|
detail: capLines(lines).join("\n"),
|
|
10731
10766
|
copyPrompt: fixes.length > 0 ? `${meta.prompt}
|
|
10732
10767
|
${capLines(fixes).join("\n")}` : meta.prompt,
|
|
10733
|
-
primaryMapCategory: meta.map
|
|
10768
|
+
primaryMapCategory: meta.map,
|
|
10769
|
+
locations: findingLocations(findings)
|
|
10734
10770
|
};
|
|
10735
10771
|
});
|
|
10736
10772
|
}
|
|
@@ -10929,6 +10965,7 @@ ${check.evidence.map((e2) => `- ${e2}`).join("\n")}` : "";
|
|
|
10929
10965
|
category: "SECURITY & AUTH",
|
|
10930
10966
|
severity: "warning",
|
|
10931
10967
|
title: "Stripe webhook does not verify the signature",
|
|
10968
|
+
locations: findingLocations(webhooks.unverified.map((u2) => ({ file: u2.path }))),
|
|
10932
10969
|
detail: `${webhooks.unverified.length} Stripe webhook handler${webhooks.unverified.length === 1 ? "" : "s"} without signature verification over the raw body: ${capLines(lines).join("; ")}. Anyone who finds the URL can post a fake event, for example a paid checkout.`,
|
|
10933
10970
|
copyPrompt: 'In each listed handler, read the raw request body (await req.text() in Next.js route handlers and Deno, express.raw({ type: "application/json" }) in Express), read the stripe-signature header, and pass both to stripe.webhooks.constructEvent (constructEventAsync on Deno or edge runtimes) with STRIPE_WEBHOOK_SECRET before trusting event.type. Return 400 when verification throws.',
|
|
10934
10971
|
primaryMapCategory: "payments"
|
|
@@ -10965,7 +11002,7 @@ ${check.evidence.map((e2) => `- ${e2}`).join("\n")}` : "";
|
|
|
10965
11002
|
severity: "warning",
|
|
10966
11003
|
title: `Env vars used in code but missing from ${target}`,
|
|
10967
11004
|
detail: `Code reads ${count} that ${contract.templates.length === 1 ? target : `no env template (${contract.templates.join(", ")})`} does not document (${shown}${more}). Fresh clones, CI, and the production deploy can silently run without them.`,
|
|
10968
|
-
copyPrompt: `Add placeholder entries for these variables to ${contract.templates.length === 1 ? target : contract.templates[0]} (never real values): ${shown}${drifted.length > 5 ? " and the rest" : ""}. Then confirm each one is set in the deployment environment (
|
|
11005
|
+
copyPrompt: `Add placeholder entries for these variables to ${contract.templates.length === 1 ? target : contract.templates[0]} (never real values): ${shown}${drifted.length > 5 ? " and the rest" : ""}. Then confirm each one is set in the deployment environment (the hosting provider's project settings).`,
|
|
10969
11006
|
primaryMapCategory: "deployment"
|
|
10970
11007
|
});
|
|
10971
11008
|
} else {
|
|
@@ -11032,9 +11069,9 @@ function scoreFrom(gaps) {
|
|
|
11032
11069
|
}
|
|
11033
11070
|
return Math.max(5, Math.min(96, score));
|
|
11034
11071
|
}
|
|
11035
|
-
function
|
|
11072
|
+
function scoreLabelFor(score, criticalCount, warningCount) {
|
|
11036
11073
|
if (criticalCount > 0) return "Blocked";
|
|
11037
|
-
if (
|
|
11074
|
+
if (warningCount === 0) return "No blockers in repo checks";
|
|
11038
11075
|
if (score >= 60) return "Almost there";
|
|
11039
11076
|
return "Needs work";
|
|
11040
11077
|
}
|
|
@@ -11133,11 +11170,12 @@ async function buildLocalStationOutput(input) {
|
|
|
11133
11170
|
toolSuggestions: [],
|
|
11134
11171
|
mcpSuggestion: null,
|
|
11135
11172
|
primaryMapCategory: seed.primaryMapCategory,
|
|
11136
|
-
affectedMapCategories: [seed.primaryMapCategory]
|
|
11173
|
+
affectedMapCategories: [seed.primaryMapCategory],
|
|
11174
|
+
...seed.locations?.length ? { locations: seed.locations } : {}
|
|
11137
11175
|
}));
|
|
11138
11176
|
return {
|
|
11139
11177
|
score,
|
|
11140
|
-
scoreLabel:
|
|
11178
|
+
scoreLabel: scoreLabelFor(score, criticalCount, warningCount),
|
|
11141
11179
|
summary,
|
|
11142
11180
|
archetype,
|
|
11143
11181
|
gaps,
|
|
@@ -11593,6 +11631,28 @@ var init_runScan = __esm({
|
|
|
11593
11631
|
}
|
|
11594
11632
|
});
|
|
11595
11633
|
|
|
11634
|
+
// src/contracts/detectedProviders.ts
|
|
11635
|
+
function isProviderInRepo(row) {
|
|
11636
|
+
if ((row.roles ?? []).includes("runtime-code")) return true;
|
|
11637
|
+
const evidence = (row.evidence ?? []).filter((item4) => item4.kind !== "docs-mention");
|
|
11638
|
+
if (!evidence.some((item4) => PACKAGE_OR_CONFIG.has(item4.kind))) return false;
|
|
11639
|
+
return !evidence.every((item4) => item4.kind === "package-installed");
|
|
11640
|
+
}
|
|
11641
|
+
function providersInRepo(artifact) {
|
|
11642
|
+
const areas = artifact.providerTruth?.areas;
|
|
11643
|
+
if (!Array.isArray(areas)) return void 0;
|
|
11644
|
+
return areas.flatMap(
|
|
11645
|
+
(area) => (area.rows ?? []).filter(isProviderInRepo).map((row) => ({ area: String(area.area), provider: String(row.provider) }))
|
|
11646
|
+
);
|
|
11647
|
+
}
|
|
11648
|
+
var PACKAGE_OR_CONFIG;
|
|
11649
|
+
var init_detectedProviders = __esm({
|
|
11650
|
+
"src/contracts/detectedProviders.ts"() {
|
|
11651
|
+
"use strict";
|
|
11652
|
+
PACKAGE_OR_CONFIG = /* @__PURE__ */ new Set(["package-installed", "deployment-config", "provider-config"]);
|
|
11653
|
+
}
|
|
11654
|
+
});
|
|
11655
|
+
|
|
11596
11656
|
// src/capabilities/classify.ts
|
|
11597
11657
|
function gapText(gap) {
|
|
11598
11658
|
return `${gap.id} ${gap.title} ${gap.detail} ${gap.primaryMapCategory}`.toLowerCase();
|
|
@@ -11780,6 +11840,37 @@ var init_capabilities = __esm({
|
|
|
11780
11840
|
}
|
|
11781
11841
|
});
|
|
11782
11842
|
|
|
11843
|
+
// src/contracts/packageManager.ts
|
|
11844
|
+
function detectPackageManager(workspacePath) {
|
|
11845
|
+
if (!workspacePath) return "unknown";
|
|
11846
|
+
try {
|
|
11847
|
+
const manifest = JSON.parse((0, import_node_fs4.readFileSync)((0, import_node_path8.join)(workspacePath, "package.json"), "utf8").replace(/^\uFEFF/, ""));
|
|
11848
|
+
const named = typeof manifest.packageManager === "string" ? manifest.packageManager.split("@")[0] : "";
|
|
11849
|
+
if (named === "npm" || named === "pnpm" || named === "yarn" || named === "bun") return named;
|
|
11850
|
+
} catch {
|
|
11851
|
+
}
|
|
11852
|
+
for (const [file, manager] of LOCKFILES) {
|
|
11853
|
+
if ((0, import_node_fs4.existsSync)((0, import_node_path8.join)(workspacePath, file))) return manager;
|
|
11854
|
+
}
|
|
11855
|
+
return "unknown";
|
|
11856
|
+
}
|
|
11857
|
+
var import_node_fs4, import_node_path8, LOCKFILES;
|
|
11858
|
+
var init_packageManager = __esm({
|
|
11859
|
+
"src/contracts/packageManager.ts"() {
|
|
11860
|
+
"use strict";
|
|
11861
|
+
import_node_fs4 = require("node:fs");
|
|
11862
|
+
import_node_path8 = require("node:path");
|
|
11863
|
+
LOCKFILES = [
|
|
11864
|
+
["pnpm-lock.yaml", "pnpm"],
|
|
11865
|
+
["yarn.lock", "yarn"],
|
|
11866
|
+
["bun.lock", "bun"],
|
|
11867
|
+
["bun.lockb", "bun"],
|
|
11868
|
+
["package-lock.json", "npm"],
|
|
11869
|
+
["npm-shrinkwrap.json", "npm"]
|
|
11870
|
+
];
|
|
11871
|
+
}
|
|
11872
|
+
});
|
|
11873
|
+
|
|
11783
11874
|
// src/contracts/commands.ts
|
|
11784
11875
|
function promptGapCommand(gapId) {
|
|
11785
11876
|
return `${PUBLIC_COMMAND} prompt --gap ${gapId}`;
|
|
@@ -11807,65 +11898,18 @@ var init_commands = __esm({
|
|
|
11807
11898
|
}
|
|
11808
11899
|
});
|
|
11809
11900
|
|
|
11810
|
-
// src/contracts/contextMap.ts
|
|
11811
|
-
function generateContextMap(artifact) {
|
|
11812
|
-
const criticalCount = artifact.gaps.filter((gap) => gap.severity === "critical").length;
|
|
11813
|
-
const warningCount = artifact.gaps.filter((gap) => gap.severity === "warning").length;
|
|
11814
|
-
return {
|
|
11815
|
-
$schema: "https://viberaven.dev/schemas/context-map.schema.json",
|
|
11816
|
-
schemaVersion: "v1",
|
|
11817
|
-
generatedAt: artifact.scannedAt,
|
|
11818
|
-
workspace: {
|
|
11819
|
-
root: artifact.workspacePath,
|
|
11820
|
-
packageManager: "unknown",
|
|
11821
|
-
languages: ["typescript"],
|
|
11822
|
-
frameworks: artifact.archetype ? [artifact.archetype] : []
|
|
11823
|
-
},
|
|
11824
|
-
agentContract: {
|
|
11825
|
-
readFirst: ".viberaven/agent-tasklist.md",
|
|
11826
|
-
machineResult: ".viberaven/gate-result.json",
|
|
11827
|
-
contextMap: ".viberaven/context-map.json",
|
|
11828
|
-
verifyCommand: PUBLIC_VERIFY_COMMAND,
|
|
11829
|
-
strictCommand: PUBLIC_STRICT_COMMAND,
|
|
11830
|
-
nextCommand: PUBLIC_NEXT_JSON_COMMAND
|
|
11831
|
-
},
|
|
11832
|
-
stack: {
|
|
11833
|
-
deployment: artifact.selectedProviders?.deployment ? [artifact.selectedProviders.deployment] : [],
|
|
11834
|
-
database: artifact.selectedProviders?.database ? [artifact.selectedProviders.database] : [],
|
|
11835
|
-
auth: artifact.selectedProviders?.auth ? [artifact.selectedProviders.auth] : [],
|
|
11836
|
-
payments: artifact.selectedProviders?.payments ? [artifact.selectedProviders.payments] : [],
|
|
11837
|
-
monitoring: artifact.selectedProviders?.monitoring ? [artifact.selectedProviders.monitoring] : []
|
|
11838
|
-
},
|
|
11839
|
-
capabilityGraph: summarizeCapabilities(artifact.gaps),
|
|
11840
|
-
productionGate: {
|
|
11841
|
-
status: criticalCount > 0 ? "not_clear" : warningCount > 0 ? "warning" : "clear",
|
|
11842
|
-
criticalCount,
|
|
11843
|
-
warningCount,
|
|
11844
|
-
providerDashboardChecksRequired: true
|
|
11845
|
-
},
|
|
11846
|
-
topGaps: artifact.gaps.slice(0, 10).map((gap) => ({
|
|
11847
|
-
id: gap.id,
|
|
11848
|
-
severity: gap.severity,
|
|
11849
|
-
title: gap.title,
|
|
11850
|
-
area: String(gap.primaryMapCategory),
|
|
11851
|
-
promptCommand: promptGapCommand(gap.id)
|
|
11852
|
-
}))
|
|
11853
|
-
};
|
|
11854
|
-
}
|
|
11855
|
-
var init_contextMap = __esm({
|
|
11856
|
-
"src/contracts/contextMap.ts"() {
|
|
11857
|
-
"use strict";
|
|
11858
|
-
init_capabilities();
|
|
11859
|
-
init_commands();
|
|
11860
|
-
}
|
|
11861
|
-
});
|
|
11862
|
-
|
|
11863
11901
|
// src/contracts/gateResult.ts
|
|
11864
11902
|
function gateStatus(criticalCount, warningCount) {
|
|
11865
11903
|
if (criticalCount > 0) return "not_clear";
|
|
11866
11904
|
if (warningCount > 0) return "warning";
|
|
11867
11905
|
return "clear";
|
|
11868
11906
|
}
|
|
11907
|
+
function gateStatusForGaps(gaps) {
|
|
11908
|
+
return gateStatus(
|
|
11909
|
+
gaps.filter((gap) => gap.severity === "critical").length,
|
|
11910
|
+
gaps.filter((gap) => gap.severity === "warning").length
|
|
11911
|
+
);
|
|
11912
|
+
}
|
|
11869
11913
|
function runIdFrom(scannedAt) {
|
|
11870
11914
|
return `vr_${scannedAt.replace(/\D/g, "").slice(0, 14) || "scan"}`;
|
|
11871
11915
|
}
|
|
@@ -11883,7 +11927,7 @@ function generateGateResult(artifact, options = {}) {
|
|
|
11883
11927
|
generatedAt: artifact.scannedAt,
|
|
11884
11928
|
workspace: {
|
|
11885
11929
|
root: artifact.workspacePath,
|
|
11886
|
-
packageManager:
|
|
11930
|
+
packageManager: options.packageManager ?? detectPackageManager(artifact.workspacePath),
|
|
11887
11931
|
languages: ["typescript"],
|
|
11888
11932
|
frameworks: artifact.archetype ? [artifact.archetype] : []
|
|
11889
11933
|
},
|
|
@@ -11924,101 +11968,246 @@ var init_gateResult = __esm({
|
|
|
11924
11968
|
"src/contracts/gateResult.ts"() {
|
|
11925
11969
|
"use strict";
|
|
11926
11970
|
init_capabilities();
|
|
11971
|
+
init_packageManager();
|
|
11927
11972
|
init_commands();
|
|
11928
11973
|
}
|
|
11929
11974
|
});
|
|
11930
11975
|
|
|
11931
|
-
// src/contracts/
|
|
11932
|
-
function
|
|
11933
|
-
|
|
11976
|
+
// src/contracts/contextMap.ts
|
|
11977
|
+
function detectedStack(artifact) {
|
|
11978
|
+
const stack = { deployment: [], database: [], auth: [], payments: [], monitoring: [] };
|
|
11979
|
+
const add = (area, provider2) => {
|
|
11980
|
+
if (!(area in stack) || typeof provider2 !== "string" || !provider2) return;
|
|
11981
|
+
const list = stack[area];
|
|
11982
|
+
if (!list.includes(provider2)) list.push(provider2);
|
|
11983
|
+
};
|
|
11984
|
+
for (const entry of providersInRepo(artifact) ?? []) add(entry.area, entry.provider);
|
|
11985
|
+
for (const [area, provider2] of Object.entries(artifact.selectedProviders ?? {})) add(area, provider2);
|
|
11986
|
+
return stack;
|
|
11934
11987
|
}
|
|
11935
|
-
function
|
|
11936
|
-
|
|
11937
|
-
|
|
11938
|
-
|
|
11939
|
-
|
|
11940
|
-
|
|
11988
|
+
function generateContextMap(artifact, options = {}) {
|
|
11989
|
+
const criticalCount = artifact.gaps.filter((gap) => gap.severity === "critical").length;
|
|
11990
|
+
const warningCount = artifact.gaps.filter((gap) => gap.severity === "warning").length;
|
|
11991
|
+
return {
|
|
11992
|
+
$schema: "https://viberaven.dev/schemas/context-map.schema.json",
|
|
11993
|
+
schemaVersion: "v1",
|
|
11994
|
+
generatedAt: artifact.scannedAt,
|
|
11995
|
+
workspace: {
|
|
11996
|
+
root: artifact.workspacePath,
|
|
11997
|
+
packageManager: options.packageManager ?? detectPackageManager(artifact.workspacePath),
|
|
11998
|
+
languages: ["typescript"],
|
|
11999
|
+
frameworks: artifact.archetype ? [artifact.archetype] : []
|
|
12000
|
+
},
|
|
12001
|
+
agentContract: {
|
|
12002
|
+
readFirst: ".viberaven/agent-tasklist.md",
|
|
12003
|
+
machineResult: ".viberaven/gate-result.json",
|
|
12004
|
+
contextMap: ".viberaven/context-map.json",
|
|
12005
|
+
verifyCommand: PUBLIC_VERIFY_COMMAND,
|
|
12006
|
+
strictCommand: PUBLIC_STRICT_COMMAND,
|
|
12007
|
+
nextCommand: PUBLIC_NEXT_JSON_COMMAND
|
|
12008
|
+
},
|
|
12009
|
+
stack: detectedStack(artifact),
|
|
12010
|
+
capabilityGraph: summarizeCapabilities(artifact.gaps),
|
|
12011
|
+
productionGate: {
|
|
12012
|
+
status: gateStatusForGaps(artifact.gaps),
|
|
12013
|
+
criticalCount,
|
|
12014
|
+
warningCount,
|
|
12015
|
+
providerDashboardChecksRequired: true
|
|
12016
|
+
},
|
|
12017
|
+
topGaps: artifact.gaps.slice(0, 10).map((gap) => ({
|
|
11941
12018
|
id: gap.id,
|
|
11942
12019
|
severity: gap.severity,
|
|
11943
|
-
capability: classifyGapCapability(gap),
|
|
11944
12020
|
title: gap.title,
|
|
11945
|
-
|
|
11946
|
-
|
|
11947
|
-
|
|
11948
|
-
|
|
11949
|
-
healPlan: healPlanGapCommand(gap.id),
|
|
11950
|
-
verify: PUBLIC_VERIFY_COMMAND
|
|
11951
|
-
},
|
|
11952
|
-
providerBoundary: {
|
|
11953
|
-
requiresDashboardCheck: true,
|
|
11954
|
-
reason: "Repo evidence cannot prove live provider dashboard state."
|
|
11955
|
-
}
|
|
11956
|
-
}
|
|
11957
|
-
}));
|
|
12021
|
+
area: String(gap.primaryMapCategory),
|
|
12022
|
+
promptCommand: promptGapCommand(gap.id)
|
|
12023
|
+
}))
|
|
12024
|
+
};
|
|
11958
12025
|
}
|
|
11959
|
-
var
|
|
11960
|
-
"src/contracts/
|
|
12026
|
+
var init_contextMap = __esm({
|
|
12027
|
+
"src/contracts/contextMap.ts"() {
|
|
11961
12028
|
"use strict";
|
|
12029
|
+
init_detectedProviders();
|
|
12030
|
+
init_gateResult();
|
|
11962
12031
|
init_capabilities();
|
|
12032
|
+
init_packageManager();
|
|
11963
12033
|
init_commands();
|
|
11964
12034
|
}
|
|
11965
12035
|
});
|
|
11966
12036
|
|
|
11967
|
-
// src/
|
|
11968
|
-
function
|
|
11969
|
-
|
|
11970
|
-
|
|
12037
|
+
// src/contracts/gapLocations.ts
|
|
12038
|
+
function locationsForGap(gap) {
|
|
12039
|
+
return gap.locations && gap.locations.length > 0 ? gap.locations : gapLocations(gap.detail);
|
|
12040
|
+
}
|
|
12041
|
+
function withoutUrlsAndAddresses(text) {
|
|
12042
|
+
return text.split(/(\s+)/).map((word) => /:\/\/|@|=/.test(word) ? " " : word).join("");
|
|
12043
|
+
}
|
|
12044
|
+
function gapLocations(detail) {
|
|
12045
|
+
if (typeof detail !== "string") return [];
|
|
12046
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12047
|
+
const out = [];
|
|
12048
|
+
for (const rawLine of detail.split(/\r?\n/)) {
|
|
12049
|
+
const text = withoutUrlsAndAddresses(rawLine.split(" Fix:")[0]);
|
|
12050
|
+
for (const match of text.matchAll(LOCATION)) {
|
|
12051
|
+
const folder = match[1].replace(/\\/g, "/");
|
|
12052
|
+
const name = match[2];
|
|
12053
|
+
const file = `${folder}${name}`;
|
|
12054
|
+
const line = match[3] ? Number(match[3]) : void 0;
|
|
12055
|
+
if (line !== void 0 && !(line > 0)) continue;
|
|
12056
|
+
const envFile = name.startsWith(".env");
|
|
12057
|
+
if (!envFile && (VERSION_LIKE.test(name) || VERSION_LIKE.test(name.replace(/\.[A-Za-z0-9]+$/, "")))) continue;
|
|
12058
|
+
const codeFile = CODE_EXTENSION.test(name) && !(folder === "" && PROSE_NAME.test(name));
|
|
12059
|
+
const configFile = CONFIG_EXTENSION.test(name);
|
|
12060
|
+
if (line !== void 0) {
|
|
12061
|
+
if (!envFile && !codeFile && !configFile) continue;
|
|
12062
|
+
} else if (!envFile && !codeFile && !(configFile && folder !== "")) {
|
|
12063
|
+
continue;
|
|
12064
|
+
}
|
|
12065
|
+
const key = `${file}:${line ?? ""}`;
|
|
12066
|
+
if (seen.has(key)) continue;
|
|
12067
|
+
seen.add(key);
|
|
12068
|
+
out.push(line === void 0 ? { file } : { file, line });
|
|
12069
|
+
}
|
|
11971
12070
|
}
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
12071
|
+
return out;
|
|
12072
|
+
}
|
|
12073
|
+
var SEGMENT, NAME, LOCATION, CODE_EXTENSION, CONFIG_EXTENSION, PROSE_NAME, VERSION_LIKE;
|
|
12074
|
+
var init_gapLocations = __esm({
|
|
12075
|
+
"src/contracts/gapLocations.ts"() {
|
|
12076
|
+
"use strict";
|
|
12077
|
+
SEGMENT = String.raw`(?:\([\w.-]+\)|\[[\w.-]+\]|[\w-][\w.-]*)`;
|
|
12078
|
+
NAME = String.raw`(\.env(?:\.[\w-]+)*|(?:\[[\w.-]+\]|[\w-][\w.-]*?)\.[A-Za-z0-9]+)`;
|
|
12079
|
+
LOCATION = new RegExp(
|
|
12080
|
+
String.raw`(?<![\w./\\:-])((?:[A-Za-z]:[\\/])?(?:${SEGMENT}[\\/])*)${NAME}(?::(\d+))?(?!\.?[\w\\/])`,
|
|
12081
|
+
"g"
|
|
12082
|
+
);
|
|
12083
|
+
CODE_EXTENSION = /\.(?:sql|[cm]?[jt]sx?|py|rb|php|go|rs|java|kt|cs|swift|ex|exs|vue|svelte|astro)$/i;
|
|
12084
|
+
CONFIG_EXTENSION = /\.(?:json|toml|ya?ml)$/i;
|
|
12085
|
+
PROSE_NAME = /^(?:next|node|nuxt|vue|express|nest|react|three|chart|solid|ember|backbone|angular|alpine|d3)\.js$/i;
|
|
12086
|
+
VERSION_LIKE = /^v?\d+(?:\.\d+)+$/i;
|
|
11975
12087
|
}
|
|
11976
|
-
|
|
11977
|
-
|
|
12088
|
+
});
|
|
12089
|
+
|
|
12090
|
+
// src/contracts/repoFixes.ts
|
|
12091
|
+
var APPLY_MIGRATION, ROTATE_KEY, REPO_FIX_GAPS, INFORMATIONAL_GAPS, REPO_ONLY_RECIPE_GAPS, RECIPE_GAPS_WITH_OUTSIDE_STEP, KNOWN_RECIPE_GAP_IDS, REPO_ONLY_GAPS;
|
|
12092
|
+
var init_repoFixes = __esm({
|
|
12093
|
+
"src/contracts/repoFixes.ts"() {
|
|
12094
|
+
"use strict";
|
|
12095
|
+
APPLY_MIGRATION = "Apply the new migration to the live database the way this project applies migrations.";
|
|
12096
|
+
ROTATE_KEY = "Rotate the service role key in the Supabase dashboard if this key was ever deployed or committed with a real value.";
|
|
12097
|
+
REPO_FIX_GAPS = {
|
|
12098
|
+
rls_policy_allows_all_write: [APPLY_MIGRATION],
|
|
12099
|
+
rls_policy_allows_all_read: [APPLY_MIGRATION],
|
|
12100
|
+
data_api_grant_without_rls: [APPLY_MIGRATION],
|
|
12101
|
+
data_api_grant_missing: [APPLY_MIGRATION],
|
|
12102
|
+
security_definer_function_executable: [APPLY_MIGRATION],
|
|
12103
|
+
service_role_key_in_client_env: [ROTATE_KEY],
|
|
12104
|
+
service_role_key_in_client_code: [ROTATE_KEY],
|
|
12105
|
+
env_var_drift: ["Set each of these variables in the environment where the app is deployed."],
|
|
12106
|
+
unverified_stripe_webhook: [
|
|
12107
|
+
"Set STRIPE_WEBHOOK_SECRET where the handler runs to the signing secret of this endpoint in the Stripe dashboard, then deploy the handler."
|
|
12108
|
+
]
|
|
12109
|
+
};
|
|
12110
|
+
INFORMATIONAL_GAPS = {
|
|
12111
|
+
rls_no_policies: "Informational. Nothing to change if only the server uses this table. If the frontend reads or writes it, add policies in a new migration."
|
|
12112
|
+
};
|
|
12113
|
+
REPO_ONLY_RECIPE_GAPS = [
|
|
12114
|
+
// emptyCatch (original recipe)
|
|
12115
|
+
"empty-catch",
|
|
12116
|
+
"empty_catch",
|
|
12117
|
+
"emptyCatch",
|
|
12118
|
+
// file-create recipes
|
|
12119
|
+
"missing_error_boundary",
|
|
12120
|
+
"missing_health_route",
|
|
12121
|
+
"missing_loading_state",
|
|
12122
|
+
"missing_404_page",
|
|
12123
|
+
// file-patch recipes
|
|
12124
|
+
"missing_csp_header",
|
|
12125
|
+
"eslint_restricted_imports"
|
|
12126
|
+
];
|
|
12127
|
+
RECIPE_GAPS_WITH_OUTSIDE_STEP = ["auth_secret_missing", "node_env_not_set", "database_url_missing", "missing_rate_limit"];
|
|
12128
|
+
KNOWN_RECIPE_GAP_IDS = /* @__PURE__ */ new Set([...REPO_ONLY_RECIPE_GAPS, ...RECIPE_GAPS_WITH_OUTSIDE_STEP]);
|
|
12129
|
+
REPO_ONLY_GAPS = /* @__PURE__ */ new Set([...Object.keys(INFORMATIONAL_GAPS), ...REPO_ONLY_RECIPE_GAPS]);
|
|
11978
12130
|
}
|
|
11979
|
-
|
|
11980
|
-
|
|
12131
|
+
});
|
|
12132
|
+
|
|
12133
|
+
// src/heal/rlsMigrationTarget.ts
|
|
12134
|
+
function rlsEnableStatements(tables) {
|
|
12135
|
+
return [...new Set(tables)].map((table2) => `alter table ${table2} enable row level security;`);
|
|
12136
|
+
}
|
|
12137
|
+
function migrationStamp(now) {
|
|
12138
|
+
return now.toISOString().replace(/\D/g, "").slice(0, 14);
|
|
12139
|
+
}
|
|
12140
|
+
function rlsMigrationTarget(cwd, evidence, now = /* @__PURE__ */ new Date()) {
|
|
12141
|
+
if (evidence.length === 0) return { ok: false, reason: "No table without row level security was found in the repo SQL." };
|
|
12142
|
+
const statementList = rlsEnableStatements(evidence.map((entry) => entry.table)).join(" ");
|
|
12143
|
+
const turnedOff = evidence.filter((entry) => entry.turnedOff);
|
|
12144
|
+
if (turnedOff.length > 0) {
|
|
12145
|
+
const where = turnedOff.map((entry) => `${entry.table} (${entry.file.replace(/\\/g, "/")})`).join(", ");
|
|
12146
|
+
return {
|
|
12147
|
+
ok: false,
|
|
12148
|
+
reason: `The latest migration that touches ${where} turns row level security off on purpose, so VibeRaven will not turn it back on automatically. If the user wants it on, add these statements by hand in a new migration, with the policies the app needs: ${statementList}`
|
|
12149
|
+
};
|
|
11981
12150
|
}
|
|
11982
|
-
|
|
11983
|
-
|
|
12151
|
+
const source = evidence[0].file.replace(/\\/g, "/");
|
|
12152
|
+
const dir = import_node_path9.posix.dirname(source);
|
|
12153
|
+
if (import_node_path9.posix.basename(dir) !== "migrations") {
|
|
12154
|
+
return {
|
|
12155
|
+
ok: false,
|
|
12156
|
+
reason: `The tables come from ${source}, which is not in a migrations folder, so VibeRaven will not guess where a migration goes. Add these statements by hand where this project keeps its schema: ${statementList}`
|
|
12157
|
+
};
|
|
11984
12158
|
}
|
|
11985
|
-
|
|
11986
|
-
|
|
12159
|
+
let existing;
|
|
12160
|
+
try {
|
|
12161
|
+
existing = (0, import_node_fs5.readdirSync)((0, import_node_path9.join)(cwd, dir)).filter((file) => file.endsWith(".sql")).sort();
|
|
12162
|
+
} catch {
|
|
12163
|
+
return { ok: false, reason: `VibeRaven could not read ${dir}. Add these statements by hand in a new migration: ${statementList}` };
|
|
12164
|
+
}
|
|
12165
|
+
const otherNaming = existing.find((file) => !TIMESTAMPED_MIGRATION.test(file));
|
|
12166
|
+
if (otherNaming) {
|
|
12167
|
+
return {
|
|
12168
|
+
ok: false,
|
|
12169
|
+
reason: `The migrations in ${dir} are not named <14-digit timestamp>_name.sql (for example ${otherNaming}), so a timestamped file from VibeRaven could run in the wrong order next to them. Add these statements by hand in a new migration that follows this project's naming: ${statementList}`
|
|
12170
|
+
};
|
|
12171
|
+
}
|
|
12172
|
+
const name = `${migrationStamp(now)}_viberaven_enable_rls.sql`;
|
|
12173
|
+
const last = existing[existing.length - 1];
|
|
12174
|
+
if (last && name <= last) {
|
|
12175
|
+
return {
|
|
12176
|
+
ok: false,
|
|
12177
|
+
reason: `A new migration named ${name} would not run after ${last} in ${dir}, so VibeRaven will not write it. Add these statements by hand in a migration that runs last: ${statementList}`
|
|
12178
|
+
};
|
|
11987
12179
|
}
|
|
11988
|
-
return
|
|
12180
|
+
return { ok: true, file: `${dir}/${name}` };
|
|
11989
12181
|
}
|
|
11990
|
-
var
|
|
11991
|
-
var
|
|
11992
|
-
"src/
|
|
12182
|
+
var import_node_fs5, import_node_path9, RLS_TURNED_OFF_PHRASE, RLS_ASK_FIRST, RLS_NO_POLICIES_WARNING, TIMESTAMPED_MIGRATION;
|
|
12183
|
+
var init_rlsMigrationTarget = __esm({
|
|
12184
|
+
"src/heal/rlsMigrationTarget.ts"() {
|
|
11993
12185
|
"use strict";
|
|
11994
|
-
|
|
11995
|
-
|
|
11996
|
-
|
|
11997
|
-
|
|
11998
|
-
|
|
11999
|
-
|
|
12000
|
-
"stripe-product": "stripe",
|
|
12001
|
-
"stripe-keys": "stripe"
|
|
12002
|
-
};
|
|
12186
|
+
import_node_fs5 = require("node:fs");
|
|
12187
|
+
import_node_path9 = require("node:path");
|
|
12188
|
+
RLS_TURNED_OFF_PHRASE = "has row level security turned off at";
|
|
12189
|
+
RLS_ASK_FIRST = "Ask the user first: enabling RLS without policies makes browser reads return no rows until policies exist.";
|
|
12190
|
+
RLS_NO_POLICIES_WARNING = "This migration enables row level security with no policies. Until you add policies, the anon and authenticated roles get no rows from these tables through the Data API, so browser reads return nothing and browser writes fail. `check` then reports the tables only as info (rls_no_policies), not as a blocker. Add the policies the app needs before you apply the migration to the database.";
|
|
12191
|
+
TIMESTAMPED_MIGRATION = /^\d{14}_.+\.sql$/;
|
|
12003
12192
|
}
|
|
12004
12193
|
});
|
|
12005
12194
|
|
|
12006
12195
|
// src/playbooks/playbooksRoot.ts
|
|
12007
12196
|
function playbooksRoot() {
|
|
12008
|
-
const candidates = [(0,
|
|
12197
|
+
const candidates = [(0, import_node_path10.join)(__dirname, "playbooks"), (0, import_node_path10.join)(__dirname, "..", "..", "playbooks")];
|
|
12009
12198
|
for (const dir of candidates) {
|
|
12010
|
-
if ((0,
|
|
12199
|
+
if ((0, import_node_fs6.existsSync)((0, import_node_path10.join)(dir, "vercel.json"))) {
|
|
12011
12200
|
return dir;
|
|
12012
12201
|
}
|
|
12013
12202
|
}
|
|
12014
12203
|
throw new Error("VibeRaven playbooks directory not found (expected vercel.json)");
|
|
12015
12204
|
}
|
|
12016
|
-
var
|
|
12205
|
+
var import_node_fs6, import_node_path10;
|
|
12017
12206
|
var init_playbooksRoot = __esm({
|
|
12018
12207
|
"src/playbooks/playbooksRoot.ts"() {
|
|
12019
12208
|
"use strict";
|
|
12020
|
-
|
|
12021
|
-
|
|
12209
|
+
import_node_fs6 = require("node:fs");
|
|
12210
|
+
import_node_path10 = require("node:path");
|
|
12022
12211
|
}
|
|
12023
12212
|
});
|
|
12024
12213
|
|
|
@@ -12125,7 +12314,7 @@ async function loadPlaybook(provider2) {
|
|
|
12125
12314
|
`Unknown provider "${provider2}". Available: ${PLAYBOOK_PROVIDERS.join(", ")}`
|
|
12126
12315
|
);
|
|
12127
12316
|
}
|
|
12128
|
-
const path = (0,
|
|
12317
|
+
const path = (0, import_node_path11.join)(playbooksRoot(), `${normalized}.json`);
|
|
12129
12318
|
const raw = JSON.parse(await (0, import_promises7.readFile)(path, "utf-8"));
|
|
12130
12319
|
const playbook = parsePlaybook(raw);
|
|
12131
12320
|
if (playbook.provider !== normalized) {
|
|
@@ -12140,59 +12329,30 @@ function loadPlaybookSync(provider2) {
|
|
|
12140
12329
|
`Unknown provider "${provider2}". Available: ${PLAYBOOK_PROVIDERS.join(", ")}`
|
|
12141
12330
|
);
|
|
12142
12331
|
}
|
|
12143
|
-
const path = (0,
|
|
12144
|
-
const raw = JSON.parse((0,
|
|
12332
|
+
const path = (0, import_node_path11.join)(playbooksRoot(), `${normalized}.json`);
|
|
12333
|
+
const raw = JSON.parse((0, import_node_fs7.readFileSync)(path, "utf-8"));
|
|
12145
12334
|
const playbook = parsePlaybook(raw);
|
|
12146
12335
|
if (playbook.provider !== normalized) {
|
|
12147
12336
|
throw new Error(`Playbook file ${normalized}.json has mismatched provider field`);
|
|
12148
12337
|
}
|
|
12149
12338
|
return playbook;
|
|
12150
12339
|
}
|
|
12151
|
-
var
|
|
12340
|
+
var import_node_fs7, import_promises7, import_node_path11;
|
|
12152
12341
|
var init_loadPlaybook = __esm({
|
|
12153
12342
|
"src/playbooks/loadPlaybook.ts"() {
|
|
12154
12343
|
"use strict";
|
|
12155
|
-
|
|
12344
|
+
import_node_fs7 = require("node:fs");
|
|
12156
12345
|
import_promises7 = require("node:fs/promises");
|
|
12157
|
-
|
|
12346
|
+
import_node_path11 = require("node:path");
|
|
12158
12347
|
init_playbooksRoot();
|
|
12159
12348
|
init_types2();
|
|
12160
12349
|
init_validate();
|
|
12161
12350
|
}
|
|
12162
12351
|
});
|
|
12163
12352
|
|
|
12164
|
-
// src/
|
|
12165
|
-
function
|
|
12166
|
-
return
|
|
12167
|
-
}
|
|
12168
|
-
function collectManualChecks(artifact) {
|
|
12169
|
-
const refs = [];
|
|
12170
|
-
for (const area of artifact.missionGraph.areas ?? []) {
|
|
12171
|
-
for (const mission of area.providerMissions) {
|
|
12172
|
-
for (const check of mission.checks) {
|
|
12173
|
-
if (!isManualProviderCheck(check)) {
|
|
12174
|
-
continue;
|
|
12175
|
-
}
|
|
12176
|
-
refs.push({
|
|
12177
|
-
areaLabel: area.label,
|
|
12178
|
-
providerLabel: mission.providerLabel,
|
|
12179
|
-
check,
|
|
12180
|
-
mapCategory: area.key
|
|
12181
|
-
});
|
|
12182
|
-
}
|
|
12183
|
-
}
|
|
12184
|
-
}
|
|
12185
|
-
return refs;
|
|
12186
|
-
}
|
|
12187
|
-
var init_manualChecks = __esm({
|
|
12188
|
-
"src/playbooks/manualChecks.ts"() {
|
|
12189
|
-
"use strict";
|
|
12190
|
-
}
|
|
12191
|
-
});
|
|
12192
|
-
|
|
12193
|
-
// src/tui/menu.ts
|
|
12194
|
-
function isScanNotFoundError(error) {
|
|
12195
|
-
return error instanceof ScanNotFoundError;
|
|
12353
|
+
// src/tui/menu.ts
|
|
12354
|
+
function isScanNotFoundError(error) {
|
|
12355
|
+
return error instanceof ScanNotFoundError;
|
|
12196
12356
|
}
|
|
12197
12357
|
function needsScanMessage(startDir) {
|
|
12198
12358
|
const cwd = startDir ?? process.cwd();
|
|
@@ -12239,7 +12399,7 @@ async function loadLastArtifact(startDir) {
|
|
|
12239
12399
|
if (!workspace) {
|
|
12240
12400
|
throw new ScanNotFoundError(needsScanMessage(startDir));
|
|
12241
12401
|
}
|
|
12242
|
-
const path = (0,
|
|
12402
|
+
const path = (0, import_node_path12.join)(getProjectArtifactsDir(workspace), "last-scan.json");
|
|
12243
12403
|
try {
|
|
12244
12404
|
const raw = await (0, import_promises8.readFile)(path, "utf-8");
|
|
12245
12405
|
return JSON.parse(raw);
|
|
@@ -12247,12 +12407,12 @@ async function loadLastArtifact(startDir) {
|
|
|
12247
12407
|
throw new ScanNotFoundError(needsScanMessage(startDir));
|
|
12248
12408
|
}
|
|
12249
12409
|
}
|
|
12250
|
-
var import_promises8,
|
|
12410
|
+
var import_promises8, import_node_path12, SEVERITY_RANK2, ScanNotFoundError;
|
|
12251
12411
|
var init_menu = __esm({
|
|
12252
12412
|
"src/tui/menu.ts"() {
|
|
12253
12413
|
"use strict";
|
|
12254
12414
|
import_promises8 = require("node:fs/promises");
|
|
12255
|
-
|
|
12415
|
+
import_node_path12 = require("node:path");
|
|
12256
12416
|
init_config();
|
|
12257
12417
|
SEVERITY_RANK2 = {
|
|
12258
12418
|
critical: 0,
|
|
@@ -12268,228 +12428,6 @@ var init_menu = __esm({
|
|
|
12268
12428
|
}
|
|
12269
12429
|
});
|
|
12270
12430
|
|
|
12271
|
-
// src/resolveNextAction.ts
|
|
12272
|
-
function resolveNextAction(artifact) {
|
|
12273
|
-
const repoGap = sortGapsByPriority(artifact.gaps)[0];
|
|
12274
|
-
if (repoGap) {
|
|
12275
|
-
return {
|
|
12276
|
-
type: "repo-fix",
|
|
12277
|
-
title: repoGap.title,
|
|
12278
|
-
detail: repoGap.detail,
|
|
12279
|
-
command: `viberaven prompt --gap ${repoGap.id}`
|
|
12280
|
-
};
|
|
12281
|
-
}
|
|
12282
|
-
const manual = collectManualChecks(artifact)[0];
|
|
12283
|
-
if (manual) {
|
|
12284
|
-
const provider2 = mapCheckToPlaybook(manual.check);
|
|
12285
|
-
let openUrl;
|
|
12286
|
-
try {
|
|
12287
|
-
const playbook = loadPlaybookSync(provider2);
|
|
12288
|
-
openUrl = playbook.steps[0]?.openUrl;
|
|
12289
|
-
} catch {
|
|
12290
|
-
openUrl = void 0;
|
|
12291
|
-
}
|
|
12292
|
-
return {
|
|
12293
|
-
type: "provider-guide",
|
|
12294
|
-
title: manual.check.label,
|
|
12295
|
-
detail: manual.check.promptHint || `Configure ${manual.providerLabel} in the provider dashboard (${manual.areaLabel}).`,
|
|
12296
|
-
provider: provider2,
|
|
12297
|
-
playbookStep: 1,
|
|
12298
|
-
command: `viberaven guide ${provider2} --step 1`,
|
|
12299
|
-
openUrl
|
|
12300
|
-
};
|
|
12301
|
-
}
|
|
12302
|
-
return {
|
|
12303
|
-
type: "done",
|
|
12304
|
-
title: "No blockers found",
|
|
12305
|
-
detail: "Re-scan after changes to confirm production readiness."
|
|
12306
|
-
};
|
|
12307
|
-
}
|
|
12308
|
-
var init_resolveNextAction = __esm({
|
|
12309
|
-
"src/resolveNextAction.ts"() {
|
|
12310
|
-
"use strict";
|
|
12311
|
-
init_checkMap();
|
|
12312
|
-
init_loadPlaybook();
|
|
12313
|
-
init_manualChecks();
|
|
12314
|
-
init_menu();
|
|
12315
|
-
}
|
|
12316
|
-
});
|
|
12317
|
-
|
|
12318
|
-
// src/report/agentSummary.ts
|
|
12319
|
-
function sortGaps(gaps) {
|
|
12320
|
-
return [...gaps].sort((a, b3) => {
|
|
12321
|
-
const sev = SEVERITY_ORDER2[a.severity] - SEVERITY_ORDER2[b3.severity];
|
|
12322
|
-
if (sev !== 0) {
|
|
12323
|
-
return sev;
|
|
12324
|
-
}
|
|
12325
|
-
return a.title.localeCompare(b3.title);
|
|
12326
|
-
});
|
|
12327
|
-
}
|
|
12328
|
-
function generateAgentSummary(artifact) {
|
|
12329
|
-
const lines = [];
|
|
12330
|
-
const topGaps = sortGaps(artifact.gaps).slice(0, 8);
|
|
12331
|
-
lines.push("# VibeRaven agent summary", "");
|
|
12332
|
-
lines.push(`Scanned: \`${artifact.workspacePath}\``);
|
|
12333
|
-
lines.push(`At: ${artifact.scannedAt}`);
|
|
12334
|
-
lines.push(
|
|
12335
|
-
`Production core: **${artifact.productionCorePercent}%** \xB7 Model score: **${artifact.score}** (${artifact.scoreLabel})`
|
|
12336
|
-
);
|
|
12337
|
-
lines.push("");
|
|
12338
|
-
const next = resolveNextAction(artifact);
|
|
12339
|
-
lines.push("## Next action", "");
|
|
12340
|
-
lines.push(`**${next.title}** \u2014 ${next.detail}`);
|
|
12341
|
-
if (next.command) {
|
|
12342
|
-
lines.push(`Command: \`${next.command}\``);
|
|
12343
|
-
}
|
|
12344
|
-
lines.push("");
|
|
12345
|
-
lines.push("## Suggested stack", "");
|
|
12346
|
-
lines.push(
|
|
12347
|
-
"React + Tailwind + shadcn/ui + Supabase + Vercel (agent-default stack for lowest launch friction)"
|
|
12348
|
-
);
|
|
12349
|
-
lines.push("");
|
|
12350
|
-
lines.push("## Summary");
|
|
12351
|
-
lines.push(artifact.summary || "_No summary returned._");
|
|
12352
|
-
lines.push("");
|
|
12353
|
-
lines.push("## Mission map (repo wiring)");
|
|
12354
|
-
lines.push("");
|
|
12355
|
-
lines.push("| Area | Provider | Readiness | Notes |");
|
|
12356
|
-
lines.push("|------|----------|-----------|-------|");
|
|
12357
|
-
for (const area of artifact.missionGraph.areas ?? []) {
|
|
12358
|
-
for (const mission of area.providerMissions) {
|
|
12359
|
-
const failed = mission.checks.filter(
|
|
12360
|
-
(c) => c.status === "missing" || c.status === "failed" || c.status === "needs-connection"
|
|
12361
|
-
).length;
|
|
12362
|
-
const notes = failed > 0 ? `${failed} open check${failed === 1 ? "" : "s"}` : `${mission.readinessPercent}% repo checks`;
|
|
12363
|
-
lines.push(
|
|
12364
|
-
`| ${area.label} | ${mission.providerLabel} | ${mission.readinessPercent}% | ${notes} |`
|
|
12365
|
-
);
|
|
12366
|
-
}
|
|
12367
|
-
}
|
|
12368
|
-
lines.push("");
|
|
12369
|
-
lines.push("## Agent-code actions");
|
|
12370
|
-
if (topGaps.length === 0) {
|
|
12371
|
-
lines.push("_No model gaps returned. Review mission map checks before changing code._");
|
|
12372
|
-
} else {
|
|
12373
|
-
topGaps.forEach((gap, index) => {
|
|
12374
|
-
lines.push(
|
|
12375
|
-
`${index + 1}. **${gap.title}** (\`${gap.id}\`, ${gap.severity}, map: \`${gap.primaryMapCategory}\`)`
|
|
12376
|
-
);
|
|
12377
|
-
lines.push(` - ${gap.detail}`);
|
|
12378
|
-
lines.push(` - Command: \`viberaven prompt --gap ${gap.id}\``);
|
|
12379
|
-
if (gap.copyPrompt) {
|
|
12380
|
-
lines.push(` - Prompt: ${gap.copyPrompt}`);
|
|
12381
|
-
}
|
|
12382
|
-
});
|
|
12383
|
-
}
|
|
12384
|
-
const manualChecks = (artifact.missionGraph.areas ?? []).flatMap(
|
|
12385
|
-
(area) => area.providerMissions.flatMap(
|
|
12386
|
-
(mission) => mission.checks.filter(
|
|
12387
|
-
(check) => check.evidenceClass === "manual-dashboard" || check.evidenceClass === "mcp-verifier" || check.evidenceSource === "provider" || check.evidenceSource === "mcp" || check.status === "needs-connection" || check.status === "unknown"
|
|
12388
|
-
).map((check) => ({ area: area.label, provider: mission.providerLabel, check }))
|
|
12389
|
-
)
|
|
12390
|
-
);
|
|
12391
|
-
lines.push("");
|
|
12392
|
-
lines.push("## Human-provider actions");
|
|
12393
|
-
if (manualChecks.length === 0) {
|
|
12394
|
-
lines.push("_No manual provider actions were identified in this scan._");
|
|
12395
|
-
} else {
|
|
12396
|
-
manualChecks.slice(0, 8).forEach((item4, index) => {
|
|
12397
|
-
lines.push(`${index + 1}. **${item4.check.label}** (${item4.area} / ${item4.provider})`);
|
|
12398
|
-
lines.push(
|
|
12399
|
-
` - ${item4.check.promptHint || "Ask the user to confirm this in the provider dashboard or through read-only MCP."}`
|
|
12400
|
-
);
|
|
12401
|
-
});
|
|
12402
|
-
}
|
|
12403
|
-
lines.push("");
|
|
12404
|
-
lines.push("Do not claim human-provider actions as repo-code fixes.");
|
|
12405
|
-
lines.push("");
|
|
12406
|
-
lines.push("## Agent workflow");
|
|
12407
|
-
lines.push("1. Read `.viberaven/agent-tasklist.md` first for the production gate.");
|
|
12408
|
-
lines.push("2. Read `.viberaven/launch-playbook.md` for the full checklist.");
|
|
12409
|
-
lines.push("3. Run `viberaven next --json` - one action at a time.");
|
|
12410
|
-
lines.push("4. Repo fix: `viberaven prompt --gap <id>` then implement.");
|
|
12411
|
-
lines.push("5. Provider: `viberaven guide <provider> --step N` and `viberaven open <provider>`.");
|
|
12412
|
-
lines.push(`6. Run \`${PUBLIC_VERIFY_COMMAND}\` to rescan and refresh \`.viberaven/agent-tasklist.md\`.`);
|
|
12413
|
-
lines.push("");
|
|
12414
|
-
return `${lines.join("\n")}
|
|
12415
|
-
`;
|
|
12416
|
-
}
|
|
12417
|
-
var SEVERITY_ORDER2;
|
|
12418
|
-
var init_agentSummary = __esm({
|
|
12419
|
-
"src/report/agentSummary.ts"() {
|
|
12420
|
-
"use strict";
|
|
12421
|
-
init_commands();
|
|
12422
|
-
init_resolveNextAction();
|
|
12423
|
-
SEVERITY_ORDER2 = {
|
|
12424
|
-
critical: 0,
|
|
12425
|
-
warning: 1,
|
|
12426
|
-
info: 2
|
|
12427
|
-
};
|
|
12428
|
-
}
|
|
12429
|
-
});
|
|
12430
|
-
|
|
12431
|
-
// src/heal/rlsMigrationTarget.ts
|
|
12432
|
-
function rlsEnableStatements(tables) {
|
|
12433
|
-
return [...new Set(tables)].map((table2) => `alter table ${table2} enable row level security;`);
|
|
12434
|
-
}
|
|
12435
|
-
function migrationStamp(now) {
|
|
12436
|
-
return now.toISOString().replace(/\D/g, "").slice(0, 14);
|
|
12437
|
-
}
|
|
12438
|
-
function rlsMigrationTarget(cwd, evidence, now = /* @__PURE__ */ new Date()) {
|
|
12439
|
-
if (evidence.length === 0) return { ok: false, reason: "No table without row level security was found in the repo SQL." };
|
|
12440
|
-
const statementList = rlsEnableStatements(evidence.map((entry) => entry.table)).join(" ");
|
|
12441
|
-
const turnedOff = evidence.filter((entry) => entry.turnedOff);
|
|
12442
|
-
if (turnedOff.length > 0) {
|
|
12443
|
-
const where = turnedOff.map((entry) => `${entry.table} (${entry.file.replace(/\\/g, "/")})`).join(", ");
|
|
12444
|
-
return {
|
|
12445
|
-
ok: false,
|
|
12446
|
-
reason: `The latest migration that touches ${where} turns row level security off on purpose, so VibeRaven will not turn it back on automatically. If the user wants it on, add these statements by hand in a new migration, with the policies the app needs: ${statementList}`
|
|
12447
|
-
};
|
|
12448
|
-
}
|
|
12449
|
-
const source = evidence[0].file.replace(/\\/g, "/");
|
|
12450
|
-
const dir = import_node_path11.posix.dirname(source);
|
|
12451
|
-
if (import_node_path11.posix.basename(dir) !== "migrations") {
|
|
12452
|
-
return {
|
|
12453
|
-
ok: false,
|
|
12454
|
-
reason: `The tables come from ${source}, which is not in a migrations folder, so VibeRaven will not guess where a migration goes. Add these statements by hand where this project keeps its schema: ${statementList}`
|
|
12455
|
-
};
|
|
12456
|
-
}
|
|
12457
|
-
let existing;
|
|
12458
|
-
try {
|
|
12459
|
-
existing = (0, import_node_fs6.readdirSync)((0, import_node_path11.join)(cwd, dir)).filter((file) => file.endsWith(".sql")).sort();
|
|
12460
|
-
} catch {
|
|
12461
|
-
return { ok: false, reason: `VibeRaven could not read ${dir}. Add these statements by hand in a new migration: ${statementList}` };
|
|
12462
|
-
}
|
|
12463
|
-
const otherNaming = existing.find((file) => !TIMESTAMPED_MIGRATION.test(file));
|
|
12464
|
-
if (otherNaming) {
|
|
12465
|
-
return {
|
|
12466
|
-
ok: false,
|
|
12467
|
-
reason: `The migrations in ${dir} are not named <14-digit timestamp>_name.sql (for example ${otherNaming}), so a timestamped file from VibeRaven could run in the wrong order next to them. Add these statements by hand in a new migration that follows this project's naming: ${statementList}`
|
|
12468
|
-
};
|
|
12469
|
-
}
|
|
12470
|
-
const name = `${migrationStamp(now)}_viberaven_enable_rls.sql`;
|
|
12471
|
-
const last = existing[existing.length - 1];
|
|
12472
|
-
if (last && name <= last) {
|
|
12473
|
-
return {
|
|
12474
|
-
ok: false,
|
|
12475
|
-
reason: `A new migration named ${name} would not run after ${last} in ${dir}, so VibeRaven will not write it. Add these statements by hand in a migration that runs last: ${statementList}`
|
|
12476
|
-
};
|
|
12477
|
-
}
|
|
12478
|
-
return { ok: true, file: `${dir}/${name}` };
|
|
12479
|
-
}
|
|
12480
|
-
var import_node_fs6, import_node_path11, RLS_TURNED_OFF_PHRASE, RLS_ASK_FIRST, RLS_NO_POLICIES_WARNING, TIMESTAMPED_MIGRATION;
|
|
12481
|
-
var init_rlsMigrationTarget = __esm({
|
|
12482
|
-
"src/heal/rlsMigrationTarget.ts"() {
|
|
12483
|
-
"use strict";
|
|
12484
|
-
import_node_fs6 = require("node:fs");
|
|
12485
|
-
import_node_path11 = require("node:path");
|
|
12486
|
-
RLS_TURNED_OFF_PHRASE = "has row level security turned off at";
|
|
12487
|
-
RLS_ASK_FIRST = "Ask the user first: enabling RLS without policies makes browser reads return no rows until policies exist.";
|
|
12488
|
-
RLS_NO_POLICIES_WARNING = "This migration enables row level security with no policies. Until you add policies, the anon and authenticated roles get no rows from these tables through the Data API, so browser reads return nothing and browser writes fail. `check` then reports the tables only as info (rls_no_policies), not as a blocker. Add the policies the app needs before you apply the migration to the database.";
|
|
12489
|
-
TIMESTAMPED_MIGRATION = /^\d{14}_.+\.sql$/;
|
|
12490
|
-
}
|
|
12491
|
-
});
|
|
12492
|
-
|
|
12493
12431
|
// src/buildTaskList.ts
|
|
12494
12432
|
function rlsMigrationFile(gap) {
|
|
12495
12433
|
if (gap.id !== "rls_disabled" || typeof gap.detail !== "string") return void 0;
|
|
@@ -12508,7 +12446,12 @@ function hasRecipe(gapId) {
|
|
|
12508
12446
|
const lower = gapId.toLowerCase();
|
|
12509
12447
|
return lower.includes("empty") && lower.includes("catch");
|
|
12510
12448
|
}
|
|
12511
|
-
function gapToPlaybookProvider(gap) {
|
|
12449
|
+
function gapToPlaybookProvider(gap, inRepo) {
|
|
12450
|
+
const provider2 = playbookByCategoryOrId(gap);
|
|
12451
|
+
if (!provider2 || !inRepo) return provider2;
|
|
12452
|
+
return inRepo.has(PLAYBOOK_TOKEN[provider2] ?? provider2) ? provider2 : void 0;
|
|
12453
|
+
}
|
|
12454
|
+
function playbookByCategoryOrId(gap) {
|
|
12512
12455
|
const cat = gap.primaryMapCategory.toLowerCase();
|
|
12513
12456
|
if (cat === "deployment") return "vercel";
|
|
12514
12457
|
if (cat === "payments") return "stripe";
|
|
@@ -12521,9 +12464,9 @@ function gapToPlaybookProvider(gap) {
|
|
|
12521
12464
|
if (id.includes("auth")) return "auth-supabase";
|
|
12522
12465
|
return void 0;
|
|
12523
12466
|
}
|
|
12524
|
-
function hasPlaybook(gap) {
|
|
12467
|
+
function hasPlaybook(gap, inRepo) {
|
|
12525
12468
|
try {
|
|
12526
|
-
const provider2 = gapToPlaybookProvider(gap);
|
|
12469
|
+
const provider2 = gapToPlaybookProvider(gap, inRepo);
|
|
12527
12470
|
if (!provider2) return false;
|
|
12528
12471
|
return PLAYBOOK_PROVIDERS.includes(provider2);
|
|
12529
12472
|
} catch {
|
|
@@ -12553,13 +12496,20 @@ function buildProviderAction(gap, provider2) {
|
|
|
12553
12496
|
}
|
|
12554
12497
|
function buildTaskList(artifact) {
|
|
12555
12498
|
const sorted = sortGapsByPriority(artifact.gaps);
|
|
12499
|
+
const providers = providersInRepo(artifact);
|
|
12500
|
+
const inRepo = providers ? new Set(providers.map((entry) => entry.provider.toLowerCase())) : void 0;
|
|
12556
12501
|
return sorted.map((gap, index) => {
|
|
12557
12502
|
const id = `TASK-${String(index + 1).padStart(3, "0")}`;
|
|
12558
12503
|
let fixType;
|
|
12559
12504
|
const migrationFile = rlsMigrationFile(gap);
|
|
12560
|
-
|
|
12505
|
+
const location = locationsForGap(gap)[0];
|
|
12506
|
+
const repoFixUserSteps = REPO_FIX_GAPS[gap.id];
|
|
12507
|
+
const informational = INFORMATIONAL_GAPS[gap.id];
|
|
12508
|
+
if (hasRecipe(gap.id) || migrationFile || repoFixUserSteps) {
|
|
12561
12509
|
fixType = "repo-code";
|
|
12562
|
-
} else if (
|
|
12510
|
+
} else if (informational) {
|
|
12511
|
+
fixType = "manual-verify";
|
|
12512
|
+
} else if (hasPlaybook(gap, inRepo)) {
|
|
12563
12513
|
fixType = "provider-action";
|
|
12564
12514
|
} else {
|
|
12565
12515
|
fixType = "manual-verify";
|
|
@@ -12576,6 +12526,8 @@ function buildTaskList(artifact) {
|
|
|
12576
12526
|
if (fixType === "repo-code" && !hasRecipe(gap.id) && migrationFile) {
|
|
12577
12527
|
base.requiresUserAction = true;
|
|
12578
12528
|
base.file = migrationFile;
|
|
12529
|
+
base.userSteps = [APPLY_MIGRATION];
|
|
12530
|
+
if (location?.file === migrationFile && location.line !== void 0) base.line = location.line;
|
|
12579
12531
|
const target = rlsMigrationTarget(artifact.workspacePath, rlsEvidence2(gap.detail));
|
|
12580
12532
|
if (target.ok) {
|
|
12581
12533
|
base.mcpTool = "viberaven_heal_apply";
|
|
@@ -12587,6 +12539,28 @@ function buildTaskList(artifact) {
|
|
|
12587
12539
|
if (gap.copyPrompt) {
|
|
12588
12540
|
base.exactFix = gap.copyPrompt.trim();
|
|
12589
12541
|
}
|
|
12542
|
+
} else if (fixType === "repo-code" && !hasRecipe(gap.id) && repoFixUserSteps) {
|
|
12543
|
+
base.requiresUserAction = false;
|
|
12544
|
+
if (location) {
|
|
12545
|
+
base.file = location.file;
|
|
12546
|
+
if (location.line !== void 0) base.line = location.line;
|
|
12547
|
+
} else {
|
|
12548
|
+
base.action = "Edit the files named in the gap detail (`npx -y viberaven prompt --gap " + gap.id + "`).";
|
|
12549
|
+
}
|
|
12550
|
+
if (gap.copyPrompt) {
|
|
12551
|
+
base.exactFix = gap.copyPrompt.trim();
|
|
12552
|
+
}
|
|
12553
|
+
base.userSteps = [...repoFixUserSteps];
|
|
12554
|
+
} else if (fixType === "manual-verify" && informational) {
|
|
12555
|
+
base.requiresUserAction = false;
|
|
12556
|
+
base.action = informational;
|
|
12557
|
+
if (location) {
|
|
12558
|
+
base.file = location.file;
|
|
12559
|
+
if (location.line !== void 0) base.line = location.line;
|
|
12560
|
+
}
|
|
12561
|
+
if (gap.copyPrompt) {
|
|
12562
|
+
base.exactFix = gap.copyPrompt.trim();
|
|
12563
|
+
}
|
|
12590
12564
|
} else if (fixType === "repo-code") {
|
|
12591
12565
|
base.mcpTool = "viberaven_heal_apply";
|
|
12592
12566
|
base.mcpArgs = { gap: gap.id, yes: true };
|
|
@@ -12596,7 +12570,7 @@ function buildTaskList(artifact) {
|
|
|
12596
12570
|
}
|
|
12597
12571
|
} else if (fixType === "provider-action") {
|
|
12598
12572
|
try {
|
|
12599
|
-
const provider2 = gapToPlaybookProvider(gap);
|
|
12573
|
+
const provider2 = gapToPlaybookProvider(gap, inRepo);
|
|
12600
12574
|
if (provider2) {
|
|
12601
12575
|
const pa = buildProviderAction(gap, provider2);
|
|
12602
12576
|
if (pa) {
|
|
@@ -12614,7 +12588,7 @@ function buildTaskList(artifact) {
|
|
|
12614
12588
|
}
|
|
12615
12589
|
function buildTaskListMarkdown(tasks) {
|
|
12616
12590
|
if (tasks.length === 0) {
|
|
12617
|
-
return "# VibeRaven Agent Tasklist\n\n_No gaps found
|
|
12591
|
+
return "# VibeRaven Agent Tasklist\n\n_No gaps found in this scan._\n";
|
|
12618
12592
|
}
|
|
12619
12593
|
const lines = ["# VibeRaven Agent Tasklist", ""];
|
|
12620
12594
|
for (const task of tasks) {
|
|
@@ -12622,7 +12596,7 @@ function buildTaskListMarkdown(tasks) {
|
|
|
12622
12596
|
lines.push(`## ${task.id} \xB7 ${task.gapId} \xB7 ${severityLabel}`, "");
|
|
12623
12597
|
lines.push(`**Fix type:** ${task.fixType} `);
|
|
12624
12598
|
if (task.file) {
|
|
12625
|
-
lines.push(`**File:** \`${task.file}\` `);
|
|
12599
|
+
lines.push(`**File:** \`${task.file}${task.line !== void 0 ? `:${task.line}` : ""}\` `);
|
|
12626
12600
|
}
|
|
12627
12601
|
if (task.action) {
|
|
12628
12602
|
lines.push(`**Action:** ${task.action} `);
|
|
@@ -12630,62 +12604,387 @@ function buildTaskListMarkdown(tasks) {
|
|
|
12630
12604
|
if (task.exactFix) {
|
|
12631
12605
|
lines.push(`**Exact fix:** ${task.exactFix} `);
|
|
12632
12606
|
} else {
|
|
12633
|
-
lines.push(`**Exact fix:** No automated recipe
|
|
12607
|
+
lines.push(`**Exact fix:** No automated recipe; see the scanner hint in the gap detail. `);
|
|
12634
12608
|
}
|
|
12635
12609
|
lines.push(`**Verify:** \`${task.verifyCommand}\` `);
|
|
12636
12610
|
if (task.mcpTool && task.mcpArgs) {
|
|
12637
12611
|
lines.push(
|
|
12638
|
-
`**MCP:** \`${task.mcpTool} ${JSON.stringify(task.mcpArgs)}\` `
|
|
12612
|
+
`**MCP:** \`${task.mcpTool} ${JSON.stringify(task.mcpArgs)}\` `
|
|
12613
|
+
);
|
|
12614
|
+
}
|
|
12615
|
+
lines.push(`**Requires user action:** ${task.requiresUserAction}`);
|
|
12616
|
+
if (task.userSteps && task.userSteps.length > 0) {
|
|
12617
|
+
lines.push("");
|
|
12618
|
+
lines.push("**Outside the repo (needs the user):**");
|
|
12619
|
+
for (const step of task.userSteps) lines.push(`- ${step}`);
|
|
12620
|
+
}
|
|
12621
|
+
if (task.providerAction) {
|
|
12622
|
+
const pa = task.providerAction;
|
|
12623
|
+
lines.push("");
|
|
12624
|
+
lines.push("**Provider action:**");
|
|
12625
|
+
lines.push(`- Provider: ${pa.provider}`);
|
|
12626
|
+
lines.push(`- Dashboard: ${pa.dashboardUrl}`);
|
|
12627
|
+
lines.push(`- Step: ${pa.exactStep}`);
|
|
12628
|
+
if (pa.envKeyName) lines.push(`- Env key: \`${pa.envKeyName}\``);
|
|
12629
|
+
if (pa.doneSignal) lines.push(`- Done when: ${pa.doneSignal}`);
|
|
12630
|
+
if (pa.mcpAlternative) lines.push(`- MCP alternative: \`${pa.mcpAlternative}\``);
|
|
12631
|
+
}
|
|
12632
|
+
lines.push("");
|
|
12633
|
+
}
|
|
12634
|
+
return `${lines.join("\n")}
|
|
12635
|
+
`;
|
|
12636
|
+
}
|
|
12637
|
+
var PLAYBOOK_TOKEN;
|
|
12638
|
+
var init_buildTaskList = __esm({
|
|
12639
|
+
"src/buildTaskList.ts"() {
|
|
12640
|
+
"use strict";
|
|
12641
|
+
init_commands();
|
|
12642
|
+
init_rlsMigrationTarget();
|
|
12643
|
+
init_gapLocations();
|
|
12644
|
+
init_repoFixes();
|
|
12645
|
+
init_detectedProviders();
|
|
12646
|
+
init_loadPlaybook();
|
|
12647
|
+
init_types2();
|
|
12648
|
+
init_menu();
|
|
12649
|
+
PLAYBOOK_TOKEN = { vercel: "vercel", stripe: "stripe", supabase: "supabase", "auth-supabase": "supabase" };
|
|
12650
|
+
}
|
|
12651
|
+
});
|
|
12652
|
+
|
|
12653
|
+
// src/contracts/gapEvidence.ts
|
|
12654
|
+
function summarizeGap(gap) {
|
|
12655
|
+
return `${gap.title}. See the tasklist and original scan for redacted detail.`;
|
|
12656
|
+
}
|
|
12657
|
+
function evidenceFor2(gap) {
|
|
12658
|
+
const kind = String(gap.primaryMapCategory);
|
|
12659
|
+
const located = locationsForGap(gap).map((location) => ({ kind, ...location, redacted: true }));
|
|
12660
|
+
return located.length > 0 ? located : [{ kind, redacted: true }];
|
|
12661
|
+
}
|
|
12662
|
+
function userStepsFor(gap) {
|
|
12663
|
+
if (REPO_FIX_GAPS[gap.id]) return { userSteps: [...REPO_FIX_GAPS[gap.id]] };
|
|
12664
|
+
if (rlsMigrationFile(gap)) return { userSteps: [APPLY_MIGRATION] };
|
|
12665
|
+
return {};
|
|
12666
|
+
}
|
|
12667
|
+
function generateGapEvidenceFiles(artifact) {
|
|
12668
|
+
return artifact.gaps.slice(0, 50).map((gap) => ({
|
|
12669
|
+
path: `.viberaven/gaps/${gap.id}.json`,
|
|
12670
|
+
content: {
|
|
12671
|
+
$schema: "https://viberaven.dev/schemas/gap.schema.json",
|
|
12672
|
+
schemaVersion: "v1",
|
|
12673
|
+
id: gap.id,
|
|
12674
|
+
severity: gap.severity,
|
|
12675
|
+
capability: classifyGapCapability(gap),
|
|
12676
|
+
title: gap.title,
|
|
12677
|
+
summary: summarizeGap(gap),
|
|
12678
|
+
evidence: evidenceFor2(gap),
|
|
12679
|
+
commands: {
|
|
12680
|
+
prompt: promptGapCommand(gap.id),
|
|
12681
|
+
healPlan: healPlanGapCommand(gap.id),
|
|
12682
|
+
verify: PUBLIC_VERIFY_COMMAND
|
|
12683
|
+
},
|
|
12684
|
+
...userStepsFor(gap),
|
|
12685
|
+
providerBoundary: REPO_ONLY_GAPS.has(gap.id) ? { requiresDashboardCheck: false, reason: "The fix is a repo change; no provider dashboard state is involved." } : { requiresDashboardCheck: true, reason: "Repo evidence cannot prove live provider dashboard state." }
|
|
12686
|
+
}
|
|
12687
|
+
}));
|
|
12688
|
+
}
|
|
12689
|
+
var init_gapEvidence = __esm({
|
|
12690
|
+
"src/contracts/gapEvidence.ts"() {
|
|
12691
|
+
"use strict";
|
|
12692
|
+
init_capabilities();
|
|
12693
|
+
init_gapLocations();
|
|
12694
|
+
init_repoFixes();
|
|
12695
|
+
init_buildTaskList();
|
|
12696
|
+
init_commands();
|
|
12697
|
+
}
|
|
12698
|
+
});
|
|
12699
|
+
|
|
12700
|
+
// src/playbooks/checkMap.ts
|
|
12701
|
+
function mapCheckToPlaybook(check) {
|
|
12702
|
+
if (CHECK_TO_PLAYBOOK[check.id]) {
|
|
12703
|
+
return CHECK_TO_PLAYBOOK[check.id];
|
|
12704
|
+
}
|
|
12705
|
+
const providerKey = String(check.providerKey ?? "").toLowerCase();
|
|
12706
|
+
if (providerKey.includes("vercel")) {
|
|
12707
|
+
return "vercel";
|
|
12708
|
+
}
|
|
12709
|
+
if (providerKey.includes("stripe")) {
|
|
12710
|
+
return "stripe";
|
|
12711
|
+
}
|
|
12712
|
+
if (providerKey.includes("supabase")) {
|
|
12713
|
+
return check.area === "auth" ? "auth-supabase" : "supabase";
|
|
12714
|
+
}
|
|
12715
|
+
return void 0;
|
|
12716
|
+
}
|
|
12717
|
+
var CHECK_TO_PLAYBOOK;
|
|
12718
|
+
var init_checkMap = __esm({
|
|
12719
|
+
"src/playbooks/checkMap.ts"() {
|
|
12720
|
+
"use strict";
|
|
12721
|
+
CHECK_TO_PLAYBOOK = {
|
|
12722
|
+
"vercel-deployment": "vercel",
|
|
12723
|
+
"vercel-project": "vercel",
|
|
12724
|
+
"supabase-project": "supabase",
|
|
12725
|
+
"supabase-env": "supabase",
|
|
12726
|
+
"stripe-webhook": "stripe",
|
|
12727
|
+
"stripe-product": "stripe",
|
|
12728
|
+
"stripe-keys": "stripe"
|
|
12729
|
+
};
|
|
12730
|
+
}
|
|
12731
|
+
});
|
|
12732
|
+
|
|
12733
|
+
// src/report/missionSelection.ts
|
|
12734
|
+
function normalizeProviderToken2(value) {
|
|
12735
|
+
return value.toLowerCase().replace(/&/g, "and").replace(/[^a-z0-9]+/g, "");
|
|
12736
|
+
}
|
|
12737
|
+
function missionMatchesProvider(mission, provider2) {
|
|
12738
|
+
const current = normalizeProviderToken2(provider2);
|
|
12739
|
+
return normalizeProviderToken2(mission.provider || mission.providerLabel || mission.key) === current || normalizeProviderToken2(mission.providerLabel || mission.provider || mission.key) === current;
|
|
12740
|
+
}
|
|
12741
|
+
function missionEvidenceScore(mission) {
|
|
12742
|
+
const repoVerified = mission.checks.filter((check) => check.evidenceClass === "repo-verified" || check.status === "passed").length;
|
|
12743
|
+
const missing = mission.checks.filter(
|
|
12744
|
+
(check) => check.evidenceClass === "missing-repo-fix" || check.status === "missing" || check.status === "failed"
|
|
12745
|
+
).length;
|
|
12746
|
+
return repoVerified * 100 + (mission.readinessPercent ?? 0) - missing;
|
|
12747
|
+
}
|
|
12748
|
+
function openChecksForMission(mission) {
|
|
12749
|
+
if (!mission) {
|
|
12750
|
+
return 0;
|
|
12751
|
+
}
|
|
12752
|
+
return mission.checks.filter(
|
|
12753
|
+
(check) => check.status === "missing" || check.status === "failed" || check.status === "needs-connection"
|
|
12754
|
+
).length;
|
|
12755
|
+
}
|
|
12756
|
+
var init_missionSelection = __esm({
|
|
12757
|
+
"src/report/missionSelection.ts"() {
|
|
12758
|
+
"use strict";
|
|
12759
|
+
}
|
|
12760
|
+
});
|
|
12761
|
+
|
|
12762
|
+
// src/report/inRepoMissions.ts
|
|
12763
|
+
function detectedProviderTokens(artifact) {
|
|
12764
|
+
const providers = providersInRepo(artifact);
|
|
12765
|
+
if (!providers) return void 0;
|
|
12766
|
+
return new Set(providers.map((entry) => normalizeProviderToken2(entry.provider)));
|
|
12767
|
+
}
|
|
12768
|
+
function missionInRepo(mission, detected) {
|
|
12769
|
+
const provider2 = String(mission.provider || mission.key || "");
|
|
12770
|
+
if (detected.has(normalizeProviderToken2(provider2))) return true;
|
|
12771
|
+
if (PRACTICES.has(provider2)) return true;
|
|
12772
|
+
const identity = mission.checks.find((check) => IDENTITY_CHECK.test(check.id));
|
|
12773
|
+
return identity?.status === "passed";
|
|
12774
|
+
}
|
|
12775
|
+
function inRepoMissions(artifact, area) {
|
|
12776
|
+
const missions = area.providerMissions ?? [];
|
|
12777
|
+
const detected = detectedProviderTokens(artifact);
|
|
12778
|
+
if (!detected) return missions;
|
|
12779
|
+
const selected = artifact.selectedProviders?.[area.key] ?? "";
|
|
12780
|
+
return missions.filter((mission) => missionInRepo(mission, detected) || selected && missionMatchesProvider(mission, selected));
|
|
12781
|
+
}
|
|
12782
|
+
function preferredInRepoMission(artifact, area) {
|
|
12783
|
+
const missions = inRepoMissions(artifact, area);
|
|
12784
|
+
if (missions.length === 0) return void 0;
|
|
12785
|
+
const selected = artifact.selectedProviders?.[area.key] ?? "";
|
|
12786
|
+
const picked = selected ? missions.find((mission) => missionMatchesProvider(mission, selected)) : void 0;
|
|
12787
|
+
return picked ?? [...missions].sort((a, b3) => missionEvidenceScore(b3) - missionEvidenceScore(a))[0];
|
|
12788
|
+
}
|
|
12789
|
+
var IDENTITY_CHECK, PRACTICES, NONE_FOUND;
|
|
12790
|
+
var init_inRepoMissions = __esm({
|
|
12791
|
+
"src/report/inRepoMissions.ts"() {
|
|
12792
|
+
"use strict";
|
|
12793
|
+
init_detectedProviders();
|
|
12794
|
+
init_missionSelection();
|
|
12795
|
+
IDENTITY_CHECK = /^(?:package-installed|package-or-config-found|package-or-widget-found|api-client-found|storybook-package-found|server-runtime-found|rails-runtime-found|go-runtime-found)$/;
|
|
12796
|
+
PRACTICES = /* @__PURE__ */ new Set(["route-map", "product-spec", "secrets-hygiene"]);
|
|
12797
|
+
NONE_FOUND = "none found";
|
|
12798
|
+
}
|
|
12799
|
+
});
|
|
12800
|
+
|
|
12801
|
+
// src/playbooks/manualChecks.ts
|
|
12802
|
+
function isManualProviderCheck(check) {
|
|
12803
|
+
return check.evidenceClass === "manual-dashboard" || check.evidenceClass === "mcp-verifier" || check.evidenceSource === "provider" || check.evidenceSource === "mcp" || check.status === "needs-connection" || check.status === "unknown";
|
|
12804
|
+
}
|
|
12805
|
+
function collectManualChecks(artifact) {
|
|
12806
|
+
const refs = [];
|
|
12807
|
+
for (const area of artifact.missionGraph.areas ?? []) {
|
|
12808
|
+
for (const mission of inRepoMissions(artifact, area)) {
|
|
12809
|
+
for (const check of mission.checks) {
|
|
12810
|
+
if (!isManualProviderCheck(check)) {
|
|
12811
|
+
continue;
|
|
12812
|
+
}
|
|
12813
|
+
refs.push({
|
|
12814
|
+
areaLabel: area.label,
|
|
12815
|
+
providerLabel: mission.providerLabel,
|
|
12816
|
+
check,
|
|
12817
|
+
mapCategory: area.key
|
|
12818
|
+
});
|
|
12819
|
+
}
|
|
12820
|
+
}
|
|
12821
|
+
}
|
|
12822
|
+
return refs;
|
|
12823
|
+
}
|
|
12824
|
+
var init_manualChecks = __esm({
|
|
12825
|
+
"src/playbooks/manualChecks.ts"() {
|
|
12826
|
+
"use strict";
|
|
12827
|
+
init_inRepoMissions();
|
|
12828
|
+
}
|
|
12829
|
+
});
|
|
12830
|
+
|
|
12831
|
+
// src/resolveNextAction.ts
|
|
12832
|
+
function resolveNextAction(artifact) {
|
|
12833
|
+
const repoGap = sortGapsByPriority(artifact.gaps)[0];
|
|
12834
|
+
if (repoGap) {
|
|
12835
|
+
return {
|
|
12836
|
+
type: "repo-fix",
|
|
12837
|
+
title: repoGap.title,
|
|
12838
|
+
detail: repoGap.detail,
|
|
12839
|
+
command: `viberaven prompt --gap ${repoGap.id}`
|
|
12840
|
+
};
|
|
12841
|
+
}
|
|
12842
|
+
const manual = collectManualChecks(artifact)[0];
|
|
12843
|
+
if (manual) {
|
|
12844
|
+
const provider2 = mapCheckToPlaybook(manual.check);
|
|
12845
|
+
let openUrl;
|
|
12846
|
+
try {
|
|
12847
|
+
openUrl = provider2 ? loadPlaybookSync(provider2).steps[0]?.openUrl : void 0;
|
|
12848
|
+
} catch {
|
|
12849
|
+
openUrl = void 0;
|
|
12850
|
+
}
|
|
12851
|
+
return {
|
|
12852
|
+
type: "provider-guide",
|
|
12853
|
+
title: manual.check.label,
|
|
12854
|
+
detail: manual.check.promptHint || `Configure ${manual.providerLabel} in the provider dashboard (${manual.areaLabel}).`,
|
|
12855
|
+
...provider2 ? { provider: provider2, playbookStep: 1, command: `viberaven guide ${provider2} --step 1` } : {},
|
|
12856
|
+
openUrl
|
|
12857
|
+
};
|
|
12858
|
+
}
|
|
12859
|
+
return {
|
|
12860
|
+
type: "done",
|
|
12861
|
+
title: "No blockers found",
|
|
12862
|
+
detail: "Re-scan after changes to confirm production readiness."
|
|
12863
|
+
};
|
|
12864
|
+
}
|
|
12865
|
+
var init_resolveNextAction = __esm({
|
|
12866
|
+
"src/resolveNextAction.ts"() {
|
|
12867
|
+
"use strict";
|
|
12868
|
+
init_checkMap();
|
|
12869
|
+
init_loadPlaybook();
|
|
12870
|
+
init_manualChecks();
|
|
12871
|
+
init_menu();
|
|
12872
|
+
}
|
|
12873
|
+
});
|
|
12874
|
+
|
|
12875
|
+
// src/report/agentSummary.ts
|
|
12876
|
+
function sortGaps(gaps) {
|
|
12877
|
+
return [...gaps].sort((a, b3) => {
|
|
12878
|
+
const sev = SEVERITY_ORDER2[a.severity] - SEVERITY_ORDER2[b3.severity];
|
|
12879
|
+
if (sev !== 0) {
|
|
12880
|
+
return sev;
|
|
12881
|
+
}
|
|
12882
|
+
return a.title.localeCompare(b3.title);
|
|
12883
|
+
});
|
|
12884
|
+
}
|
|
12885
|
+
function generateAgentSummary(artifact) {
|
|
12886
|
+
const lines = [];
|
|
12887
|
+
const topGaps = sortGaps(artifact.gaps).slice(0, 8);
|
|
12888
|
+
lines.push("# VibeRaven agent summary", "");
|
|
12889
|
+
lines.push(`Scanned: \`${artifact.workspacePath}\``);
|
|
12890
|
+
lines.push(`At: ${artifact.scannedAt}`);
|
|
12891
|
+
lines.push(
|
|
12892
|
+
`Production core: **${artifact.productionCorePercent}%** \xB7 Model score: **${artifact.score}** (${artifact.scoreLabel})`
|
|
12893
|
+
);
|
|
12894
|
+
lines.push("");
|
|
12895
|
+
const next = resolveNextAction(artifact);
|
|
12896
|
+
lines.push("## Next action", "");
|
|
12897
|
+
lines.push(`**${next.title}**: ${next.detail}`);
|
|
12898
|
+
if (next.command) {
|
|
12899
|
+
lines.push(`Command: \`${next.command}\``);
|
|
12900
|
+
}
|
|
12901
|
+
lines.push("");
|
|
12902
|
+
lines.push("## Stack", "");
|
|
12903
|
+
lines.push("The mission map below lists the providers detected in this repo. For a suggestion, run `npx -y viberaven stack recommend`.");
|
|
12904
|
+
lines.push("");
|
|
12905
|
+
lines.push("## Summary");
|
|
12906
|
+
lines.push(artifact.summary || "_No summary returned._");
|
|
12907
|
+
lines.push("");
|
|
12908
|
+
lines.push("## Mission map (repo wiring)");
|
|
12909
|
+
lines.push("");
|
|
12910
|
+
lines.push("| Area | Provider | Readiness | Notes |");
|
|
12911
|
+
lines.push("|------|----------|-----------|-------|");
|
|
12912
|
+
for (const area of artifact.missionGraph.areas ?? []) {
|
|
12913
|
+
const missions = inRepoMissions(artifact, area);
|
|
12914
|
+
if (missions.length === 0 && (area.providerMissions ?? []).length > 0) {
|
|
12915
|
+
lines.push(`| ${area.label} | ${NONE_FOUND} | - | - |`);
|
|
12916
|
+
}
|
|
12917
|
+
for (const mission of missions) {
|
|
12918
|
+
const failed = mission.checks.filter(
|
|
12919
|
+
(c) => c.status === "missing" || c.status === "failed" || c.status === "needs-connection"
|
|
12920
|
+
).length;
|
|
12921
|
+
const notes = failed > 0 ? `${failed} open check${failed === 1 ? "" : "s"}` : `${mission.readinessPercent}% repo checks`;
|
|
12922
|
+
lines.push(
|
|
12923
|
+
`| ${area.label} | ${mission.providerLabel} | ${mission.readinessPercent}% | ${notes} |`
|
|
12924
|
+
);
|
|
12925
|
+
}
|
|
12926
|
+
}
|
|
12927
|
+
lines.push("");
|
|
12928
|
+
lines.push("## Agent-code actions");
|
|
12929
|
+
if (topGaps.length === 0) {
|
|
12930
|
+
lines.push("_No model gaps returned. Review mission map checks before changing code._");
|
|
12931
|
+
} else {
|
|
12932
|
+
topGaps.forEach((gap, index) => {
|
|
12933
|
+
lines.push(
|
|
12934
|
+
`${index + 1}. **${gap.title}** (\`${gap.id}\`, ${gap.severity}, map: \`${gap.primaryMapCategory}\`)`
|
|
12639
12935
|
);
|
|
12640
|
-
|
|
12641
|
-
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
|
|
12936
|
+
lines.push(` - ${gap.detail}`);
|
|
12937
|
+
lines.push(` - Command: \`viberaven prompt --gap ${gap.id}\``);
|
|
12938
|
+
if (gap.copyPrompt) {
|
|
12939
|
+
lines.push(` - Prompt: ${gap.copyPrompt}`);
|
|
12940
|
+
}
|
|
12941
|
+
});
|
|
12942
|
+
}
|
|
12943
|
+
const manualChecks = (artifact.missionGraph.areas ?? []).flatMap(
|
|
12944
|
+
(area) => inRepoMissions(artifact, area).flatMap(
|
|
12945
|
+
(mission) => mission.checks.filter(
|
|
12946
|
+
(check) => check.evidenceClass === "manual-dashboard" || check.evidenceClass === "mcp-verifier" || check.evidenceSource === "provider" || check.evidenceSource === "mcp" || check.status === "needs-connection" || check.status === "unknown"
|
|
12947
|
+
).map((check) => ({ area: area.label, provider: mission.providerLabel, check }))
|
|
12948
|
+
)
|
|
12949
|
+
);
|
|
12950
|
+
lines.push("");
|
|
12951
|
+
lines.push("## Human-provider actions");
|
|
12952
|
+
if (manualChecks.length === 0) {
|
|
12953
|
+
lines.push("_No manual provider actions were identified in this scan._");
|
|
12954
|
+
} else {
|
|
12955
|
+
manualChecks.slice(0, 8).forEach((item4, index) => {
|
|
12956
|
+
lines.push(`${index + 1}. **${item4.check.label}** (${item4.area} / ${item4.provider})`);
|
|
12957
|
+
lines.push(
|
|
12958
|
+
` - ${item4.check.promptHint || "Ask the user to confirm this in the provider dashboard or through read-only MCP."}`
|
|
12959
|
+
);
|
|
12960
|
+
});
|
|
12654
12961
|
}
|
|
12962
|
+
lines.push("");
|
|
12963
|
+
lines.push("Do not claim human-provider actions as repo-code fixes.");
|
|
12964
|
+
lines.push("");
|
|
12965
|
+
lines.push("## Agent workflow");
|
|
12966
|
+
lines.push("1. Read `.viberaven/agent-tasklist.md` first for the production gate.");
|
|
12967
|
+
lines.push("2. Read `.viberaven/launch-playbook.md` for the full checklist.");
|
|
12968
|
+
lines.push("3. Run `viberaven next --json` - one action at a time.");
|
|
12969
|
+
lines.push("4. Repo fix: `viberaven prompt --gap <id>` then implement.");
|
|
12970
|
+
lines.push("5. Provider: `viberaven guide <provider> --step N` and `viberaven open <provider>`.");
|
|
12971
|
+
lines.push(`6. Run \`${PUBLIC_VERIFY_COMMAND}\` to rescan and refresh \`.viberaven/agent-tasklist.md\`.`);
|
|
12972
|
+
lines.push("");
|
|
12655
12973
|
return `${lines.join("\n")}
|
|
12656
12974
|
`;
|
|
12657
12975
|
}
|
|
12658
|
-
var
|
|
12659
|
-
var
|
|
12660
|
-
"src/
|
|
12976
|
+
var SEVERITY_ORDER2;
|
|
12977
|
+
var init_agentSummary = __esm({
|
|
12978
|
+
"src/report/agentSummary.ts"() {
|
|
12661
12979
|
"use strict";
|
|
12662
12980
|
init_commands();
|
|
12663
|
-
|
|
12664
|
-
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
|
|
12670
|
-
"empty_catch",
|
|
12671
|
-
"emptyCatch",
|
|
12672
|
-
// W3 env-add recipes
|
|
12673
|
-
"auth_secret_missing",
|
|
12674
|
-
"node_env_not_set",
|
|
12675
|
-
"database_url_missing",
|
|
12676
|
-
// W3 file-create recipes
|
|
12677
|
-
"missing_error_boundary",
|
|
12678
|
-
"missing_health_route",
|
|
12679
|
-
"missing_loading_state",
|
|
12680
|
-
"missing_404_page",
|
|
12681
|
-
// W3 file-patch recipes
|
|
12682
|
-
"missing_csp_header",
|
|
12683
|
-
"missing_rate_limit",
|
|
12684
|
-
"eslint_restricted_imports"
|
|
12685
|
-
// NOTE: 'rls_disabled' is intentionally NOT here. When the finding comes from repo SQL it is a repo action whose
|
|
12686
|
-
// recipe writes a new migration (see rlsMigrationFile and heal/recipes/supabaseRls.ts); without SQL evidence it
|
|
12687
|
-
// stays a provider action and heal refuses.
|
|
12688
|
-
]);
|
|
12981
|
+
init_resolveNextAction();
|
|
12982
|
+
init_inRepoMissions();
|
|
12983
|
+
SEVERITY_ORDER2 = {
|
|
12984
|
+
critical: 0,
|
|
12985
|
+
warning: 1,
|
|
12986
|
+
info: 2
|
|
12987
|
+
};
|
|
12689
12988
|
}
|
|
12690
12989
|
});
|
|
12691
12990
|
|
|
@@ -12695,12 +12994,21 @@ function generateLaunchPlaybook(artifact) {
|
|
|
12695
12994
|
lines.push("# VibeRaven launch playbook", "");
|
|
12696
12995
|
lines.push(`Generated from scan at ${artifact.scannedAt}. Work top to bottom.`, "");
|
|
12697
12996
|
lines.push("## Repo fixes (agent code)", "");
|
|
12698
|
-
const
|
|
12997
|
+
const sorted = sortGapsByPriority(artifact.gaps);
|
|
12998
|
+
const repoGaps = sorted.filter((gap) => !INFORMATIONAL_GAPS[gap.id]);
|
|
12999
|
+
const informational = sorted.filter((gap) => INFORMATIONAL_GAPS[gap.id]);
|
|
12699
13000
|
if (repoGaps.length === 0) {
|
|
12700
13001
|
lines.push("_No repo-code gaps found._", "");
|
|
12701
13002
|
} else {
|
|
12702
13003
|
for (const gap of repoGaps) {
|
|
12703
|
-
lines.push(`- [ ] ${gap.title}
|
|
13004
|
+
lines.push(`- [ ] ${gap.title}: \`viberaven prompt --gap ${gap.id}\``);
|
|
13005
|
+
}
|
|
13006
|
+
lines.push("");
|
|
13007
|
+
}
|
|
13008
|
+
if (informational.length > 0) {
|
|
13009
|
+
lines.push("## Informational", "");
|
|
13010
|
+
for (const gap of informational) {
|
|
13011
|
+
lines.push(`- ${gap.title} (\`${gap.id}\`): ${INFORMATIONAL_GAPS[gap.id]}`);
|
|
12704
13012
|
}
|
|
12705
13013
|
lines.push("");
|
|
12706
13014
|
}
|
|
@@ -12712,7 +13020,7 @@ function generateLaunchPlaybook(artifact) {
|
|
|
12712
13020
|
for (const item4 of manuals) {
|
|
12713
13021
|
const provider2 = mapCheckToPlaybook(item4.check);
|
|
12714
13022
|
lines.push(
|
|
12715
|
-
`- [ ] ${item4.check.label} (${item4.areaLabel})
|
|
13023
|
+
provider2 ? `- [ ] ${item4.check.label} (${item4.areaLabel}): \`viberaven guide ${provider2} --step 1\`` : `- [ ] ${item4.check.label} (${item4.areaLabel})`
|
|
12716
13024
|
);
|
|
12717
13025
|
}
|
|
12718
13026
|
lines.push("");
|
|
@@ -12733,6 +13041,7 @@ var init_launchPlaybook = __esm({
|
|
|
12733
13041
|
init_manualChecks();
|
|
12734
13042
|
init_menu();
|
|
12735
13043
|
init_commands();
|
|
13044
|
+
init_repoFixes();
|
|
12736
13045
|
}
|
|
12737
13046
|
});
|
|
12738
13047
|
|
|
@@ -13061,25 +13370,25 @@ var init_reportHtml = __esm({
|
|
|
13061
13370
|
function getBundledReportAssetsDir() {
|
|
13062
13371
|
const base = __dirname;
|
|
13063
13372
|
const candidates = [
|
|
13064
|
-
(0,
|
|
13065
|
-
(0,
|
|
13066
|
-
(0,
|
|
13067
|
-
(0,
|
|
13068
|
-
(0,
|
|
13373
|
+
(0, import_node_path13.join)(base, "report"),
|
|
13374
|
+
(0, import_node_path13.join)(base, "..", "assets", "report"),
|
|
13375
|
+
(0, import_node_path13.join)(base, "..", "..", "assets", "report"),
|
|
13376
|
+
(0, import_node_path13.join)(process.cwd(), "packages", "cli", "assets", "report"),
|
|
13377
|
+
(0, import_node_path13.join)(process.cwd(), "assets", "report")
|
|
13069
13378
|
];
|
|
13070
13379
|
for (const dir of candidates) {
|
|
13071
|
-
if ((0,
|
|
13380
|
+
if ((0, import_node_fs8.existsSync)((0, import_node_path13.join)(dir, "station.css"))) {
|
|
13072
13381
|
return dir;
|
|
13073
13382
|
}
|
|
13074
13383
|
}
|
|
13075
13384
|
throw new Error("Report assets missing. Run `npm run sync-report-assets` and `npm run build` in packages/cli.");
|
|
13076
13385
|
}
|
|
13077
|
-
var
|
|
13386
|
+
var import_node_fs8, import_node_path13, REPORT_ASSET_FILES;
|
|
13078
13387
|
var init_reportAssets = __esm({
|
|
13079
13388
|
"src/report/reportAssets.ts"() {
|
|
13080
13389
|
"use strict";
|
|
13081
|
-
|
|
13082
|
-
|
|
13390
|
+
import_node_fs8 = require("node:fs");
|
|
13391
|
+
import_node_path13 = require("node:path");
|
|
13083
13392
|
REPORT_ASSET_FILES = [
|
|
13084
13393
|
"station.css",
|
|
13085
13394
|
"station.js",
|
|
@@ -13267,9 +13576,10 @@ function deriveRepoCodeAction(task) {
|
|
|
13267
13576
|
gapId: task.gapId,
|
|
13268
13577
|
readiness: [...askFirst ? [askFirst] : [], task.exactFix ?? "Repo-code fix is available"],
|
|
13269
13578
|
target: task.file ? { type: "file", label: "Repo target", path: displayFile } : { type: "command", label: "Apply repo fix", command: task.mcpTool ?? `${PUBLIC_COMMAND} prompt --gap ${task.gapId}` },
|
|
13270
|
-
fileTargets: task.file ? [{ path: displayFile, reason: task.exactFix }] : void 0,
|
|
13579
|
+
fileTargets: task.file ? [{ path: displayFile, ...task.line !== void 0 ? { line: task.line } : {}, reason: task.exactFix }] : void 0,
|
|
13271
13580
|
verifyCommand: verifyActionCommand("pending"),
|
|
13272
|
-
resumeInstruction: `${task.title} is complete. Continue VibeRaven from pending
|
|
13581
|
+
resumeInstruction: `${task.title} is complete. Continue VibeRaven from pending.${task.userSteps?.length ? ` Then tell the user what is left outside the repo: ${task.userSteps.join(" ")}` : ""}`,
|
|
13582
|
+
...task.userSteps?.length ? { userSteps: [...task.userSteps] } : {},
|
|
13273
13583
|
mcpTool: task.mcpTool,
|
|
13274
13584
|
mcpArgs: task.mcpArgs,
|
|
13275
13585
|
// Only a gap with an automatic recipe has a heal-apply fallback, and a task that needs the user's yes keeps it
|
|
@@ -13278,7 +13588,7 @@ function deriveRepoCodeAction(task) {
|
|
|
13278
13588
|
...task.requiresUserAction ? { requiresUserAction: true } : {}
|
|
13279
13589
|
};
|
|
13280
13590
|
}
|
|
13281
|
-
function deriveVerifyAction() {
|
|
13591
|
+
function deriveVerifyAction(waiting) {
|
|
13282
13592
|
return {
|
|
13283
13593
|
id: "pending",
|
|
13284
13594
|
actionKey: buildActionKey({
|
|
@@ -13290,8 +13600,9 @@ function deriveVerifyAction() {
|
|
|
13290
13600
|
revision: 1,
|
|
13291
13601
|
kind: "verify",
|
|
13292
13602
|
title: "Run Final Verification",
|
|
13293
|
-
|
|
13294
|
-
|
|
13603
|
+
// Blocked only while repo-code or provider actions come first; with none left it is the next step.
|
|
13604
|
+
status: waiting ? "blocked" : "active",
|
|
13605
|
+
readiness: [waiting ? "Run after provider and repo-code actions are complete" : "No repo-code or provider actions left in this scan"],
|
|
13295
13606
|
target: { type: "command", label: "Final strict gate", command: `${PUBLIC_COMMAND} --strict` },
|
|
13296
13607
|
verifyCommand: `${PUBLIC_COMMAND} --strict`,
|
|
13297
13608
|
resumeInstruction: "Final verification finished. Continue VibeRaven from pending."
|
|
@@ -13299,7 +13610,7 @@ function deriveVerifyAction() {
|
|
|
13299
13610
|
}
|
|
13300
13611
|
function deriveCurrentActions(input) {
|
|
13301
13612
|
const primaryActions = input.tasks.filter((task) => task.fixType === "provider-action" || task.fixType === "repo-code").map((task) => task.fixType === "provider-action" ? deriveProviderAction(task) : deriveRepoCodeAction(task));
|
|
13302
|
-
return [...primaryActions, deriveVerifyAction()];
|
|
13613
|
+
return [...primaryActions, deriveVerifyAction(primaryActions.length > 0)];
|
|
13303
13614
|
}
|
|
13304
13615
|
var init_derive = __esm({
|
|
13305
13616
|
"src/actions/derive.ts"() {
|
|
@@ -13314,7 +13625,7 @@ function emptyActionRegistry() {
|
|
|
13314
13625
|
return { version: 1, nextId: 1, actions: {} };
|
|
13315
13626
|
}
|
|
13316
13627
|
function actionRegistryPath(cwd) {
|
|
13317
|
-
return (0,
|
|
13628
|
+
return (0, import_node_path14.join)(getProjectArtifactsDir(cwd), "action-registry.json");
|
|
13318
13629
|
}
|
|
13319
13630
|
async function loadActionRegistry(cwd) {
|
|
13320
13631
|
try {
|
|
@@ -13386,7 +13697,8 @@ async function assignActionIds(input) {
|
|
|
13386
13697
|
title: action.title,
|
|
13387
13698
|
gapId: action.gapId,
|
|
13388
13699
|
kind: action.kind,
|
|
13389
|
-
provider: action.provider
|
|
13700
|
+
provider: action.provider,
|
|
13701
|
+
...action.userSteps?.length ? { userSteps: [...action.userSteps] } : {}
|
|
13390
13702
|
};
|
|
13391
13703
|
} else {
|
|
13392
13704
|
entry.status = "active";
|
|
@@ -13395,6 +13707,9 @@ async function assignActionIds(input) {
|
|
|
13395
13707
|
entry.gapId = action.gapId;
|
|
13396
13708
|
entry.kind = action.kind;
|
|
13397
13709
|
entry.provider = action.provider;
|
|
13710
|
+
if (action.userSteps?.length) entry.userSteps = [...action.userSteps];
|
|
13711
|
+
else delete entry.userSteps;
|
|
13712
|
+
delete entry.followUpShownAt;
|
|
13398
13713
|
if (entry.fingerprint !== fingerprint) {
|
|
13399
13714
|
entry.revision += 1;
|
|
13400
13715
|
entry.fingerprint = fingerprint;
|
|
@@ -13418,16 +13733,27 @@ async function assignActionIds(input) {
|
|
|
13418
13733
|
await saveActionRegistry(input.cwd, registry);
|
|
13419
13734
|
return { actions, registry };
|
|
13420
13735
|
}
|
|
13736
|
+
function pendingUserFollowUps(registry) {
|
|
13737
|
+
return Object.values(registry.actions).filter((entry) => entry.status === "resolved" && entry.userSteps?.length && !entry.followUpShownAt).map((entry) => ({ id: entry.id, gapId: entry.gapId, title: entry.title, userSteps: [...entry.userSteps ?? []] }));
|
|
13738
|
+
}
|
|
13739
|
+
async function markUserFollowUpsShown(cwd, ids, now = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
13740
|
+
if (ids.length === 0) return;
|
|
13741
|
+
const registry = await loadActionRegistry(cwd);
|
|
13742
|
+
for (const entry of Object.values(registry.actions)) {
|
|
13743
|
+
if (ids.includes(entry.id)) entry.followUpShownAt = now;
|
|
13744
|
+
}
|
|
13745
|
+
await saveActionRegistry(cwd, registry);
|
|
13746
|
+
}
|
|
13421
13747
|
async function resolveActionById(cwd, id) {
|
|
13422
13748
|
const registry = await loadActionRegistry(cwd);
|
|
13423
13749
|
return Object.values(registry.actions).find((entry) => entry.id === id);
|
|
13424
13750
|
}
|
|
13425
|
-
var import_promises9,
|
|
13751
|
+
var import_promises9, import_node_path14;
|
|
13426
13752
|
var init_registry2 = __esm({
|
|
13427
13753
|
"src/actions/registry.ts"() {
|
|
13428
13754
|
"use strict";
|
|
13429
13755
|
import_promises9 = require("node:fs/promises");
|
|
13430
|
-
|
|
13756
|
+
import_node_path14 = require("node:path");
|
|
13431
13757
|
init_config();
|
|
13432
13758
|
init_canonical();
|
|
13433
13759
|
}
|
|
@@ -13438,7 +13764,7 @@ function gateStatus2(artifact) {
|
|
|
13438
13764
|
if (!Array.isArray(artifact.gaps)) {
|
|
13439
13765
|
return "unknown";
|
|
13440
13766
|
}
|
|
13441
|
-
return artifact.gaps
|
|
13767
|
+
return gateStatusForGaps(artifact.gaps);
|
|
13442
13768
|
}
|
|
13443
13769
|
async function writeActionArtifacts(input) {
|
|
13444
13770
|
const derived = deriveCurrentActions({
|
|
@@ -13459,7 +13785,9 @@ async function writeActionArtifacts(input) {
|
|
|
13459
13785
|
gateStatus: gateStatus2(input.artifact),
|
|
13460
13786
|
actions: assigned.actions
|
|
13461
13787
|
};
|
|
13462
|
-
const
|
|
13788
|
+
const followUps = pendingUserFollowUps(assigned.registry);
|
|
13789
|
+
if (followUps.length > 0) manifest.userFollowUps = followUps;
|
|
13790
|
+
const actionsPath = (0, import_node_path15.join)(getProjectArtifactsDir(input.cwd), "actions.json");
|
|
13463
13791
|
await (0, import_promises10.writeFile)(actionsPath, `${JSON.stringify(manifest, null, 2)}
|
|
13464
13792
|
`, "utf8");
|
|
13465
13793
|
return {
|
|
@@ -13468,13 +13796,14 @@ async function writeActionArtifacts(input) {
|
|
|
13468
13796
|
manifest
|
|
13469
13797
|
};
|
|
13470
13798
|
}
|
|
13471
|
-
var import_promises10,
|
|
13799
|
+
var import_promises10, import_node_path15;
|
|
13472
13800
|
var init_artifacts = __esm({
|
|
13473
13801
|
"src/actions/artifacts.ts"() {
|
|
13474
13802
|
"use strict";
|
|
13475
13803
|
import_promises10 = require("node:fs/promises");
|
|
13476
|
-
|
|
13804
|
+
import_node_path15 = require("node:path");
|
|
13477
13805
|
init_config();
|
|
13806
|
+
init_gateResult();
|
|
13478
13807
|
init_derive();
|
|
13479
13808
|
init_registry2();
|
|
13480
13809
|
}
|
|
@@ -13483,24 +13812,47 @@ var init_artifacts = __esm({
|
|
|
13483
13812
|
// src/artifacts.ts
|
|
13484
13813
|
async function copyReportAssets(reportAssetsDir) {
|
|
13485
13814
|
const sourceDir = getBundledReportAssetsDir();
|
|
13486
|
-
await (0, import_promises11.mkdir)((0,
|
|
13815
|
+
await (0, import_promises11.mkdir)((0, import_node_path16.join)(reportAssetsDir, "assets"), { recursive: true });
|
|
13487
13816
|
for (const rel of REPORT_ASSET_FILES) {
|
|
13488
|
-
await (0, import_promises11.copyFile)((0,
|
|
13817
|
+
await (0, import_promises11.copyFile)((0, import_node_path16.join)(sourceDir, rel), (0, import_node_path16.join)(reportAssetsDir, rel));
|
|
13818
|
+
}
|
|
13819
|
+
}
|
|
13820
|
+
async function isGapEvidenceFile(path) {
|
|
13821
|
+
try {
|
|
13822
|
+
return JSON.parse(await (0, import_promises11.readFile)(path, "utf8")).$schema === GAP_SCHEMA;
|
|
13823
|
+
} catch {
|
|
13824
|
+
return false;
|
|
13825
|
+
}
|
|
13826
|
+
}
|
|
13827
|
+
async function removeStaleGapFiles(gapsDir, current) {
|
|
13828
|
+
let entries;
|
|
13829
|
+
try {
|
|
13830
|
+
entries = await (0, import_promises11.readdir)(gapsDir, { withFileTypes: true });
|
|
13831
|
+
} catch {
|
|
13832
|
+
return;
|
|
13833
|
+
}
|
|
13834
|
+
for (const entry of entries) {
|
|
13835
|
+
if (!entry.isFile() || !entry.name.endsWith(".json") || current.has(entry.name)) continue;
|
|
13836
|
+
const path = (0, import_node_path16.join)(gapsDir, entry.name);
|
|
13837
|
+
try {
|
|
13838
|
+
if (await isGapEvidenceFile(path)) await (0, import_promises11.rm)(path, { force: true });
|
|
13839
|
+
} catch {
|
|
13840
|
+
}
|
|
13489
13841
|
}
|
|
13490
13842
|
}
|
|
13491
13843
|
async function writeScanArtifacts(options) {
|
|
13492
13844
|
const cwd = options.cwd ?? options.artifact.workspacePath;
|
|
13493
13845
|
const dir = getProjectArtifactsDir(cwd);
|
|
13494
13846
|
await (0, import_promises11.mkdir)(dir, { recursive: true });
|
|
13495
|
-
const jsonPath = (0,
|
|
13496
|
-
const gateResultPath = (0,
|
|
13497
|
-
const contextMapPath = (0,
|
|
13498
|
-
const gapsDir = (0,
|
|
13499
|
-
const tasklistPath = (0,
|
|
13500
|
-
const summaryPath = (0,
|
|
13501
|
-
const playbookPath = (0,
|
|
13502
|
-
const reportPath = (0,
|
|
13503
|
-
const reportAssetsDir = (0,
|
|
13847
|
+
const jsonPath = (0, import_node_path16.join)(dir, "last-scan.json");
|
|
13848
|
+
const gateResultPath = (0, import_node_path16.join)(dir, "gate-result.json");
|
|
13849
|
+
const contextMapPath = (0, import_node_path16.join)(dir, "context-map.json");
|
|
13850
|
+
const gapsDir = (0, import_node_path16.join)(dir, "gaps");
|
|
13851
|
+
const tasklistPath = (0, import_node_path16.join)(dir, "agent-tasklist.md");
|
|
13852
|
+
const summaryPath = (0, import_node_path16.join)(dir, "agent-summary.md");
|
|
13853
|
+
const playbookPath = (0, import_node_path16.join)(dir, "launch-playbook.md");
|
|
13854
|
+
const reportPath = (0, import_node_path16.join)(dir, "report.html");
|
|
13855
|
+
const reportAssetsDir = (0, import_node_path16.join)(dir, "report");
|
|
13504
13856
|
await (0, import_promises11.mkdir)(gapsDir, { recursive: true });
|
|
13505
13857
|
const safe2 = sanitizeArtifactForDisk(options.artifact);
|
|
13506
13858
|
const json = `${JSON.stringify(safe2, null, 2)}
|
|
@@ -13510,26 +13862,27 @@ async function writeScanArtifacts(options) {
|
|
|
13510
13862
|
const html = generateReportHtml(safe2);
|
|
13511
13863
|
const tasks = buildTaskList(safe2);
|
|
13512
13864
|
const tasklist = buildTaskListMarkdown(tasks);
|
|
13513
|
-
const
|
|
13865
|
+
const packageManager = detectPackageManager(options.artifact.workspacePath);
|
|
13866
|
+
const gateResult = `${JSON.stringify(generateGateResult(safe2, { packageManager }), null, 2)}
|
|
13514
13867
|
`;
|
|
13515
|
-
const contextMap = `${JSON.stringify(generateContextMap(safe2), null, 2)}
|
|
13868
|
+
const contextMap = `${JSON.stringify(generateContextMap(safe2, { packageManager }), null, 2)}
|
|
13516
13869
|
`;
|
|
13517
13870
|
const gapEvidenceFiles = generateGapEvidenceFiles(safe2);
|
|
13518
13871
|
await copyReportAssets(reportAssetsDir);
|
|
13519
13872
|
await (0, import_promises11.writeFile)(gateResultPath, gateResult, "utf-8");
|
|
13520
13873
|
await (0, import_promises11.writeFile)(contextMapPath, contextMap, "utf-8");
|
|
13521
13874
|
for (const gap of gapEvidenceFiles) {
|
|
13522
|
-
await (0, import_promises11.writeFile)((0,
|
|
13875
|
+
await (0, import_promises11.writeFile)((0, import_node_path16.join)(dir, "gaps", `${gap.content.id}.json`), `${JSON.stringify(gap.content, null, 2)}
|
|
13523
13876
|
`, "utf-8");
|
|
13524
13877
|
}
|
|
13525
13878
|
await (0, import_promises11.writeFile)(tasklistPath, tasklist, "utf-8");
|
|
13526
13879
|
let architectureMapPath;
|
|
13527
13880
|
if (typeof safe2.architectureMap === "string" && safe2.architectureMap.length > 0) {
|
|
13528
|
-
architectureMapPath = (0,
|
|
13881
|
+
architectureMapPath = (0, import_node_path16.join)(dir, "architecture-map.md");
|
|
13529
13882
|
await (0, import_promises11.writeFile)(architectureMapPath, safe2.architectureMap, "utf-8");
|
|
13530
13883
|
}
|
|
13531
13884
|
if (safe2.architectureData) {
|
|
13532
|
-
await (0, import_promises11.writeFile)((0,
|
|
13885
|
+
await (0, import_promises11.writeFile)((0, import_node_path16.join)(dir, "architecture-map.json"), `${JSON.stringify(safe2.architectureData, null, 2)}
|
|
13533
13886
|
`, "utf-8");
|
|
13534
13887
|
}
|
|
13535
13888
|
await (0, import_promises11.writeFile)(jsonPath, json, "utf-8");
|
|
@@ -13542,6 +13895,7 @@ async function writeScanArtifacts(options) {
|
|
|
13542
13895
|
tasks,
|
|
13543
13896
|
paths: { reportPath, playbookPath }
|
|
13544
13897
|
});
|
|
13898
|
+
await removeStaleGapFiles(gapsDir, new Set(gapEvidenceFiles.map((gap) => `${gap.content.id}.json`)));
|
|
13545
13899
|
return {
|
|
13546
13900
|
dir,
|
|
13547
13901
|
jsonPath,
|
|
@@ -13558,14 +13912,15 @@ async function writeScanArtifacts(options) {
|
|
|
13558
13912
|
...architectureMapPath ? { architectureMapPath } : {}
|
|
13559
13913
|
};
|
|
13560
13914
|
}
|
|
13561
|
-
var import_promises11,
|
|
13915
|
+
var import_promises11, import_node_path16, GAP_SCHEMA;
|
|
13562
13916
|
var init_artifacts2 = __esm({
|
|
13563
13917
|
"src/artifacts.ts"() {
|
|
13564
13918
|
"use strict";
|
|
13565
13919
|
import_promises11 = require("node:fs/promises");
|
|
13566
|
-
|
|
13920
|
+
import_node_path16 = require("node:path");
|
|
13567
13921
|
init_contextMap();
|
|
13568
13922
|
init_gateResult();
|
|
13923
|
+
init_packageManager();
|
|
13569
13924
|
init_gapEvidence();
|
|
13570
13925
|
init_agentSummary();
|
|
13571
13926
|
init_buildTaskList();
|
|
@@ -13575,6 +13930,7 @@ var init_artifacts2 = __esm({
|
|
|
13575
13930
|
init_config();
|
|
13576
13931
|
init_sanitizeArtifact();
|
|
13577
13932
|
init_artifacts();
|
|
13933
|
+
GAP_SCHEMA = "https://viberaven.dev/schemas/gap.schema.json";
|
|
13578
13934
|
}
|
|
13579
13935
|
});
|
|
13580
13936
|
|
|
@@ -13672,12 +14028,12 @@ function createAppWindowOpenCommands(target, platform = process.platform, env =
|
|
|
13672
14028
|
];
|
|
13673
14029
|
if (platform === "win32") {
|
|
13674
14030
|
const candidates = [
|
|
13675
|
-
env.LOCALAPPDATA ? (0,
|
|
13676
|
-
env.PROGRAMFILES ? (0,
|
|
13677
|
-
env["PROGRAMFILES(X86)"] ? (0,
|
|
13678
|
-
env.LOCALAPPDATA ? (0,
|
|
13679
|
-
env.PROGRAMFILES ? (0,
|
|
13680
|
-
env["PROGRAMFILES(X86)"] ? (0,
|
|
14031
|
+
env.LOCALAPPDATA ? (0, import_node_path17.join)(env.LOCALAPPDATA, "Google", "Chrome", "Application", "chrome.exe") : "",
|
|
14032
|
+
env.PROGRAMFILES ? (0, import_node_path17.join)(env.PROGRAMFILES, "Google", "Chrome", "Application", "chrome.exe") : "",
|
|
14033
|
+
env["PROGRAMFILES(X86)"] ? (0, import_node_path17.join)(env["PROGRAMFILES(X86)"], "Google", "Chrome", "Application", "chrome.exe") : "",
|
|
14034
|
+
env.LOCALAPPDATA ? (0, import_node_path17.join)(env.LOCALAPPDATA, "Microsoft", "Edge", "Application", "msedge.exe") : "",
|
|
14035
|
+
env.PROGRAMFILES ? (0, import_node_path17.join)(env.PROGRAMFILES, "Microsoft", "Edge", "Application", "msedge.exe") : "",
|
|
14036
|
+
env["PROGRAMFILES(X86)"] ? (0, import_node_path17.join)(env["PROGRAMFILES(X86)"], "Microsoft", "Edge", "Application", "msedge.exe") : "",
|
|
13681
14037
|
"chrome",
|
|
13682
14038
|
"msedge"
|
|
13683
14039
|
].filter(Boolean);
|
|
@@ -13711,7 +14067,7 @@ async function openWithSystemDefault(target) {
|
|
|
13711
14067
|
});
|
|
13712
14068
|
}
|
|
13713
14069
|
async function spawnDetached(command) {
|
|
13714
|
-
if (/^[A-Za-z]:[\\/]/.test(command.command) && !(0,
|
|
14070
|
+
if (/^[A-Za-z]:[\\/]/.test(command.command) && !(0, import_node_fs9.existsSync)(command.command)) {
|
|
13715
14071
|
throw new Error(`Browser not found: ${command.command}`);
|
|
13716
14072
|
}
|
|
13717
14073
|
await new Promise((resolve10, reject) => {
|
|
@@ -13754,13 +14110,13 @@ async function openUrlInBrowser(url) {
|
|
|
13754
14110
|
}
|
|
13755
14111
|
await openWithSystemDefault(trimmed);
|
|
13756
14112
|
}
|
|
13757
|
-
var import_node_child_process4,
|
|
14113
|
+
var import_node_child_process4, import_node_fs9, import_node_path17;
|
|
13758
14114
|
var init_openBrowser = __esm({
|
|
13759
14115
|
"src/openBrowser.ts"() {
|
|
13760
14116
|
"use strict";
|
|
13761
14117
|
import_node_child_process4 = require("node:child_process");
|
|
13762
|
-
|
|
13763
|
-
|
|
14118
|
+
import_node_fs9 = require("node:fs");
|
|
14119
|
+
import_node_path17 = require("node:path");
|
|
13764
14120
|
}
|
|
13765
14121
|
});
|
|
13766
14122
|
|
|
@@ -13817,9 +14173,9 @@ var init_clipboard = __esm({
|
|
|
13817
14173
|
}
|
|
13818
14174
|
});
|
|
13819
14175
|
|
|
13820
|
-
//
|
|
14176
|
+
// node_modules/picocolors/picocolors.js
|
|
13821
14177
|
var require_picocolors = __commonJS({
|
|
13822
|
-
"
|
|
14178
|
+
"node_modules/picocolors/picocolors.js"(exports2, module2) {
|
|
13823
14179
|
var p2 = process || {};
|
|
13824
14180
|
var argv = p2.argv || [];
|
|
13825
14181
|
var env = p2.env || {};
|
|
@@ -13889,46 +14245,6 @@ var require_picocolors = __commonJS({
|
|
|
13889
14245
|
}
|
|
13890
14246
|
});
|
|
13891
14247
|
|
|
13892
|
-
// src/report/missionSelection.ts
|
|
13893
|
-
function normalizeProviderToken2(value) {
|
|
13894
|
-
return value.toLowerCase().replace(/&/g, "and").replace(/[^a-z0-9]+/g, "");
|
|
13895
|
-
}
|
|
13896
|
-
function missionMatchesProvider(mission, provider2) {
|
|
13897
|
-
const current = normalizeProviderToken2(provider2);
|
|
13898
|
-
return normalizeProviderToken2(mission.provider || mission.providerLabel || mission.key) === current || normalizeProviderToken2(mission.providerLabel || mission.provider || mission.key) === current;
|
|
13899
|
-
}
|
|
13900
|
-
function missionEvidenceScore(mission) {
|
|
13901
|
-
const repoVerified = mission.checks.filter((check) => check.evidenceClass === "repo-verified" || check.status === "passed").length;
|
|
13902
|
-
const missing = mission.checks.filter(
|
|
13903
|
-
(check) => check.evidenceClass === "missing-repo-fix" || check.status === "missing" || check.status === "failed"
|
|
13904
|
-
).length;
|
|
13905
|
-
return repoVerified * 100 + (mission.readinessPercent ?? 0) - missing;
|
|
13906
|
-
}
|
|
13907
|
-
function preferredMissionForArea(area, selectedProvider) {
|
|
13908
|
-
const missions = area?.providerMissions ?? [];
|
|
13909
|
-
if (missions.length === 0) {
|
|
13910
|
-
return void 0;
|
|
13911
|
-
}
|
|
13912
|
-
const selected = selectedProvider ? missions.find((mission) => missionMatchesProvider(mission, selectedProvider)) : void 0;
|
|
13913
|
-
if (selected) {
|
|
13914
|
-
return selected;
|
|
13915
|
-
}
|
|
13916
|
-
return [...missions].sort((a, b3) => missionEvidenceScore(b3) - missionEvidenceScore(a))[0] ?? missions[0];
|
|
13917
|
-
}
|
|
13918
|
-
function openChecksForMission(mission) {
|
|
13919
|
-
if (!mission) {
|
|
13920
|
-
return 0;
|
|
13921
|
-
}
|
|
13922
|
-
return mission.checks.filter(
|
|
13923
|
-
(check) => check.status === "missing" || check.status === "failed" || check.status === "needs-connection"
|
|
13924
|
-
).length;
|
|
13925
|
-
}
|
|
13926
|
-
var init_missionSelection = __esm({
|
|
13927
|
-
"src/report/missionSelection.ts"() {
|
|
13928
|
-
"use strict";
|
|
13929
|
-
}
|
|
13930
|
-
});
|
|
13931
|
-
|
|
13932
14248
|
// src/statusLabels.ts
|
|
13933
14249
|
function formatAgentStatus(label, message) {
|
|
13934
14250
|
return `${label}: ${message}`;
|
|
@@ -13970,7 +14286,7 @@ function gapTagColor(modelGaps, open2) {
|
|
|
13970
14286
|
}
|
|
13971
14287
|
function manualActionCheckCount(artifact) {
|
|
13972
14288
|
return (artifact.missionGraph.areas ?? []).reduce((areaTotal, area) => {
|
|
13973
|
-
return areaTotal + area.
|
|
14289
|
+
return areaTotal + inRepoMissions(artifact, area).reduce((missionTotal, mission) => {
|
|
13974
14290
|
return missionTotal + mission.checks.filter(
|
|
13975
14291
|
(check) => check.evidenceClass === "manual-dashboard" || check.evidenceClass === "mcp-verifier" || check.evidenceSource === "provider" || check.evidenceSource === "mcp" || check.status === "needs-connection" || check.status === "unknown"
|
|
13976
14292
|
).length;
|
|
@@ -13991,8 +14307,14 @@ function printScanSummary(artifact, paths) {
|
|
|
13991
14307
|
console.log(import_picocolors.default.dim("\u2514") + import_picocolors.default.dim("\u2500".repeat(width - 2)) + import_picocolors.default.dim("\u2518"));
|
|
13992
14308
|
console.log("");
|
|
13993
14309
|
for (const area of artifact.missionGraph.areas ?? []) {
|
|
13994
|
-
|
|
14310
|
+
if ((area.providerMissions ?? []).length === 0) {
|
|
14311
|
+
continue;
|
|
14312
|
+
}
|
|
14313
|
+
const mission = preferredInRepoMission(artifact, area);
|
|
13995
14314
|
if (!mission) {
|
|
14315
|
+
const modelGaps2 = artifact.gaps.filter((g2) => g2.primaryMapCategory === area.key).length;
|
|
14316
|
+
const tag2 = modelGaps2 > 0 ? import_picocolors.default.red(` GAP ${modelGaps2}`) : "";
|
|
14317
|
+
console.log(` ${import_picocolors.default.dim(area.label.padEnd(18))} ${import_picocolors.default.dim(NONE_FOUND)}${tag2}`);
|
|
13996
14318
|
continue;
|
|
13997
14319
|
}
|
|
13998
14320
|
const open2 = openChecksForMission(mission);
|
|
@@ -14038,14 +14360,15 @@ var init_terminalSummary = __esm({
|
|
|
14038
14360
|
"use strict";
|
|
14039
14361
|
import_picocolors = __toESM(require_picocolors());
|
|
14040
14362
|
init_missionSelection();
|
|
14363
|
+
init_inRepoMissions();
|
|
14041
14364
|
init_statusLabels();
|
|
14042
14365
|
init_resolveNextAction();
|
|
14043
14366
|
}
|
|
14044
14367
|
});
|
|
14045
14368
|
|
|
14046
|
-
//
|
|
14369
|
+
// node_modules/sisteransi/src/index.js
|
|
14047
14370
|
var require_src = __commonJS({
|
|
14048
|
-
"
|
|
14371
|
+
"node_modules/sisteransi/src/index.js"(exports2, module2) {
|
|
14049
14372
|
"use strict";
|
|
14050
14373
|
var ESC = "\x1B";
|
|
14051
14374
|
var CSI = `${ESC}[`;
|
|
@@ -14099,7 +14422,7 @@ var require_src = __commonJS({
|
|
|
14099
14422
|
}
|
|
14100
14423
|
});
|
|
14101
14424
|
|
|
14102
|
-
//
|
|
14425
|
+
// node_modules/@clack/core/dist/index.mjs
|
|
14103
14426
|
function DD({ onlyFirst: e2 = false } = {}) {
|
|
14104
14427
|
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("|");
|
|
14105
14428
|
return new RegExp(t, e2 ? void 0 : "g");
|
|
@@ -14211,7 +14534,7 @@ function fD({ input: e2 = import_node_process.stdin, output: u2 = import_node_pr
|
|
|
14211
14534
|
}
|
|
14212
14535
|
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;
|
|
14213
14536
|
var init_dist = __esm({
|
|
14214
|
-
"
|
|
14537
|
+
"node_modules/@clack/core/dist/index.mjs"() {
|
|
14215
14538
|
import_sisteransi = __toESM(require_src(), 1);
|
|
14216
14539
|
import_node_process = require("node:process");
|
|
14217
14540
|
g = __toESM(require("node:readline"), 1);
|
|
@@ -14461,13 +14784,13 @@ var init_dist = __esm({
|
|
|
14461
14784
|
}
|
|
14462
14785
|
});
|
|
14463
14786
|
|
|
14464
|
-
//
|
|
14787
|
+
// node_modules/@clack/prompts/dist/index.mjs
|
|
14465
14788
|
function ce() {
|
|
14466
14789
|
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";
|
|
14467
14790
|
}
|
|
14468
14791
|
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;
|
|
14469
14792
|
var init_dist2 = __esm({
|
|
14470
|
-
"
|
|
14793
|
+
"node_modules/@clack/prompts/dist/index.mjs"() {
|
|
14471
14794
|
init_dist();
|
|
14472
14795
|
init_dist();
|
|
14473
14796
|
import_node_process2 = __toESM(require("node:process"), 1);
|
|
@@ -14700,7 +15023,7 @@ var VERSION;
|
|
|
14700
15023
|
var init_version = __esm({
|
|
14701
15024
|
"src/version.ts"() {
|
|
14702
15025
|
"use strict";
|
|
14703
|
-
VERSION = "1.6.
|
|
15026
|
+
VERSION = "1.6.4";
|
|
14704
15027
|
}
|
|
14705
15028
|
});
|
|
14706
15029
|
|
|
@@ -15072,17 +15395,17 @@ async function initCursorRulesPack(options) {
|
|
|
15072
15395
|
const pack = buildCursorRulesPack();
|
|
15073
15396
|
for (const rule of pack) {
|
|
15074
15397
|
const file = `${CURSOR_RULES_DIR}/${rule.filename}`;
|
|
15075
|
-
const path = (0,
|
|
15398
|
+
const path = (0, import_node_path18.join)(options.cwd, file);
|
|
15076
15399
|
const existing = await readExistingFile(path);
|
|
15077
15400
|
const changed = !existing.exists || existing.content !== rule.content;
|
|
15078
15401
|
const action = !existing.exists ? "created" : changed ? "updated" : "unchanged";
|
|
15079
15402
|
if (!options.dryRun && changed) {
|
|
15080
|
-
await (0, import_promises12.mkdir)((0,
|
|
15403
|
+
await (0, import_promises12.mkdir)((0, import_node_path18.join)(options.cwd, CURSOR_RULES_DIR), { recursive: true });
|
|
15081
15404
|
await (0, import_promises12.writeFile)(path, rule.content, "utf-8");
|
|
15082
15405
|
}
|
|
15083
15406
|
results.push({ target: "cursor", file, path, action });
|
|
15084
15407
|
}
|
|
15085
|
-
const legacyPath = (0,
|
|
15408
|
+
const legacyPath = (0, import_node_path18.join)(options.cwd, LEGACY_CURSOR_RULE_FILE);
|
|
15086
15409
|
if (!options.dryRun && await fileExists(legacyPath)) {
|
|
15087
15410
|
await (0, import_promises12.rm)(legacyPath, { force: true });
|
|
15088
15411
|
}
|
|
@@ -15109,12 +15432,12 @@ async function fileExists(path) {
|
|
|
15109
15432
|
function isFileNotFoundError(error) {
|
|
15110
15433
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
15111
15434
|
}
|
|
15112
|
-
var import_promises12,
|
|
15435
|
+
var import_promises12, import_node_path18, CURSOR_RULES_DIR, LEGACY_CURSOR_RULE_FILE, DOMAIN_PATH_POINTER;
|
|
15113
15436
|
var init_cursorRulesPack = __esm({
|
|
15114
15437
|
"src/commands/cursorRulesPack.ts"() {
|
|
15115
15438
|
"use strict";
|
|
15116
15439
|
import_promises12 = require("node:fs/promises");
|
|
15117
|
-
|
|
15440
|
+
import_node_path18 = require("node:path");
|
|
15118
15441
|
init_commands();
|
|
15119
15442
|
CURSOR_RULES_DIR = ".cursor/rules";
|
|
15120
15443
|
LEGACY_CURSOR_RULE_FILE = `${CURSOR_RULES_DIR}/viberaven.mdc`;
|
|
@@ -15214,8 +15537,8 @@ var init_agentTargets = __esm({
|
|
|
15214
15537
|
|
|
15215
15538
|
// src/commands/seedPackageJsonScripts.ts
|
|
15216
15539
|
async function seedPackageJsonScripts(options) {
|
|
15217
|
-
const packageJsonPath = (0,
|
|
15218
|
-
if (!(0,
|
|
15540
|
+
const packageJsonPath = (0, import_node_path19.join)(options.cwd, "package.json");
|
|
15541
|
+
if (!(0, import_node_fs10.existsSync)(packageJsonPath)) {
|
|
15219
15542
|
return null;
|
|
15220
15543
|
}
|
|
15221
15544
|
const raw = await (0, import_promises13.readFile)(packageJsonPath, "utf-8");
|
|
@@ -15252,13 +15575,13 @@ async function seedPackageJsonScripts(options) {
|
|
|
15252
15575
|
}
|
|
15253
15576
|
return { action: "updated", added, skipped, changed: true };
|
|
15254
15577
|
}
|
|
15255
|
-
var
|
|
15578
|
+
var import_node_fs10, import_promises13, import_node_path19, VIBERAVEN_PACKAGE_JSON_SCRIPTS;
|
|
15256
15579
|
var init_seedPackageJsonScripts = __esm({
|
|
15257
15580
|
"src/commands/seedPackageJsonScripts.ts"() {
|
|
15258
15581
|
"use strict";
|
|
15259
|
-
|
|
15582
|
+
import_node_fs10 = require("node:fs");
|
|
15260
15583
|
import_promises13 = require("node:fs/promises");
|
|
15261
|
-
|
|
15584
|
+
import_node_path19 = require("node:path");
|
|
15262
15585
|
init_commands();
|
|
15263
15586
|
VIBERAVEN_PACKAGE_JSON_SCRIPTS = {
|
|
15264
15587
|
"viberaven:gate": PUBLIC_AGENT_MODE_COMMAND,
|
|
@@ -15278,12 +15601,12 @@ async function initAgentRules(options) {
|
|
|
15278
15601
|
continue;
|
|
15279
15602
|
}
|
|
15280
15603
|
const file = AGENT_RULE_TARGETS[target].file;
|
|
15281
|
-
const path = (0,
|
|
15604
|
+
const path = (0, import_node_path20.join)(options.cwd, file);
|
|
15282
15605
|
const existing = await readExistingFile2(path);
|
|
15283
15606
|
const injected = injectAgentRulesBlock(existing.content, renderAgentRulesForTarget(target));
|
|
15284
15607
|
const action = !existing.exists ? "created" : injected.changed ? "updated" : "unchanged";
|
|
15285
15608
|
if (!options.dryRun && injected.changed) {
|
|
15286
|
-
await (0, import_promises14.mkdir)((0,
|
|
15609
|
+
await (0, import_promises14.mkdir)((0, import_node_path20.dirname)(path), { recursive: true });
|
|
15287
15610
|
await (0, import_promises14.writeFile)(path, injected.content, "utf-8");
|
|
15288
15611
|
}
|
|
15289
15612
|
results.push({ target, file, path, action });
|
|
@@ -15363,12 +15686,12 @@ async function readExistingFile2(path) {
|
|
|
15363
15686
|
function isFileNotFoundError2(error) {
|
|
15364
15687
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
15365
15688
|
}
|
|
15366
|
-
var import_promises14,
|
|
15689
|
+
var import_promises14, import_node_path20;
|
|
15367
15690
|
var init_initRules = __esm({
|
|
15368
15691
|
"src/commands/initRules.ts"() {
|
|
15369
15692
|
"use strict";
|
|
15370
15693
|
import_promises14 = require("node:fs/promises");
|
|
15371
|
-
|
|
15694
|
+
import_node_path20 = require("node:path");
|
|
15372
15695
|
init_agentRulesBlock();
|
|
15373
15696
|
init_agentTargets();
|
|
15374
15697
|
init_cursorRulesPack();
|
|
@@ -15631,7 +15954,7 @@ async function runInteractiveSession(startDir = process.cwd()) {
|
|
|
15631
15954
|
Ie(`${import_picocolors4.default.bold("VibeRaven")} ${import_picocolors4.default.dim(VERSION)}`);
|
|
15632
15955
|
const cwd = await resolveWorkspaceRoot(startDir);
|
|
15633
15956
|
const artifactsAt = await findArtifactsWorkspace(startDir);
|
|
15634
|
-
if (artifactsAt && (0,
|
|
15957
|
+
if (artifactsAt && (0, import_node_path21.resolve)(artifactsAt) !== (0, import_node_path21.resolve)(startDir)) {
|
|
15635
15958
|
M2.message(import_picocolors4.default.dim(`Using scan from: ${artifactsAt}`));
|
|
15636
15959
|
} else {
|
|
15637
15960
|
M2.message(import_picocolors4.default.dim(`Project folder: ${cwd}`));
|
|
@@ -15690,11 +16013,11 @@ async function runInteractiveSession(startDir = process.cwd()) {
|
|
|
15690
16013
|
}
|
|
15691
16014
|
Se(import_picocolors4.default.dim("Run viberaven anytime for the interactive menu."));
|
|
15692
16015
|
}
|
|
15693
|
-
var
|
|
16016
|
+
var import_node_path21, import_picocolors4;
|
|
15694
16017
|
var init_runInteractive = __esm({
|
|
15695
16018
|
"src/tui/runInteractive.ts"() {
|
|
15696
16019
|
"use strict";
|
|
15697
|
-
|
|
16020
|
+
import_node_path21 = require("node:path");
|
|
15698
16021
|
init_dist2();
|
|
15699
16022
|
import_picocolors4 = __toESM(require_picocolors());
|
|
15700
16023
|
init_config();
|
|
@@ -15719,18 +16042,18 @@ var init_runInteractive = __esm({
|
|
|
15719
16042
|
// src/commands/condense.ts
|
|
15720
16043
|
async function runCondenseCommand(options) {
|
|
15721
16044
|
const dir = getProjectArtifactsDir(options.cwd);
|
|
15722
|
-
const artifact = JSON.parse(await (0, import_promises15.readFile)((0,
|
|
15723
|
-
const contextMapPath = (0,
|
|
16045
|
+
const artifact = JSON.parse(await (0, import_promises15.readFile)((0, import_node_path22.join)(dir, "last-scan.json"), "utf8"));
|
|
16046
|
+
const contextMapPath = (0, import_node_path22.join)(dir, "context-map.json");
|
|
15724
16047
|
await (0, import_promises15.writeFile)(contextMapPath, `${JSON.stringify(generateContextMap(artifact), null, 2)}
|
|
15725
16048
|
`, "utf8");
|
|
15726
16049
|
return { contextMapPath };
|
|
15727
16050
|
}
|
|
15728
|
-
var import_promises15,
|
|
16051
|
+
var import_promises15, import_node_path22;
|
|
15729
16052
|
var init_condense = __esm({
|
|
15730
16053
|
"src/commands/condense.ts"() {
|
|
15731
16054
|
"use strict";
|
|
15732
16055
|
import_promises15 = require("node:fs/promises");
|
|
15733
|
-
|
|
16056
|
+
import_node_path22 = require("node:path");
|
|
15734
16057
|
init_config();
|
|
15735
16058
|
init_contextMap();
|
|
15736
16059
|
}
|
|
@@ -15738,9 +16061,9 @@ var init_condense = __esm({
|
|
|
15738
16061
|
|
|
15739
16062
|
// src/heal/pathSafety.ts
|
|
15740
16063
|
function assertSafeHealTarget(cwd, target) {
|
|
15741
|
-
const root = (0,
|
|
15742
|
-
const absolute = (0,
|
|
15743
|
-
const rel = (0,
|
|
16064
|
+
const root = (0, import_node_path23.resolve)(cwd);
|
|
16065
|
+
const absolute = (0, import_node_path23.resolve)(root, target);
|
|
16066
|
+
const rel = (0, import_node_path23.relative)(root, absolute);
|
|
15744
16067
|
if (rel.startsWith("..") || rel === "" || /^[A-Za-z]:/.test(rel)) {
|
|
15745
16068
|
throw new Error("Heal target must stay inside the workspace");
|
|
15746
16069
|
}
|
|
@@ -15750,11 +16073,11 @@ function assertSafeHealTarget(cwd, target) {
|
|
|
15750
16073
|
}
|
|
15751
16074
|
return absolute;
|
|
15752
16075
|
}
|
|
15753
|
-
var
|
|
16076
|
+
var import_node_path23, BLOCKED_SEGMENTS;
|
|
15754
16077
|
var init_pathSafety = __esm({
|
|
15755
16078
|
"src/heal/pathSafety.ts"() {
|
|
15756
16079
|
"use strict";
|
|
15757
|
-
|
|
16080
|
+
import_node_path23 = require("node:path");
|
|
15758
16081
|
BLOCKED_SEGMENTS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", ".next", ".viberaven"]);
|
|
15759
16082
|
}
|
|
15760
16083
|
});
|
|
@@ -15780,11 +16103,11 @@ function newHealId(now = /* @__PURE__ */ new Date()) {
|
|
|
15780
16103
|
return `heal_${now.toISOString().replace(/\D/g, "").slice(0, 17)}_${(0, import_node_crypto.randomBytes)(3).toString("hex")}`;
|
|
15781
16104
|
}
|
|
15782
16105
|
async function createHealDir(cwd, makeId = () => newHealId()) {
|
|
15783
|
-
const parent = (0,
|
|
16106
|
+
const parent = (0, import_node_path24.join)(cwd, ".viberaven", "heal");
|
|
15784
16107
|
await (0, import_promises16.mkdir)(parent, { recursive: true });
|
|
15785
16108
|
for (let attempt = 0; attempt < 10; attempt += 1) {
|
|
15786
16109
|
const id = makeId();
|
|
15787
|
-
const dir = (0,
|
|
16110
|
+
const dir = (0, import_node_path24.join)(parent, id);
|
|
15788
16111
|
try {
|
|
15789
16112
|
await (0, import_promises16.mkdir)(dir);
|
|
15790
16113
|
return { id, dir };
|
|
@@ -15794,13 +16117,13 @@ async function createHealDir(cwd, makeId = () => newHealId()) {
|
|
|
15794
16117
|
}
|
|
15795
16118
|
throw new Error("Could not create a new heal directory under .viberaven/heal.");
|
|
15796
16119
|
}
|
|
15797
|
-
var import_node_crypto, import_promises16,
|
|
16120
|
+
var import_node_crypto, import_promises16, import_node_path24;
|
|
15798
16121
|
var init_healId = __esm({
|
|
15799
16122
|
"src/heal/healId.ts"() {
|
|
15800
16123
|
"use strict";
|
|
15801
16124
|
import_node_crypto = require("node:crypto");
|
|
15802
16125
|
import_promises16 = require("node:fs/promises");
|
|
15803
|
-
|
|
16126
|
+
import_node_path24 = require("node:path");
|
|
15804
16127
|
}
|
|
15805
16128
|
});
|
|
15806
16129
|
|
|
@@ -16267,7 +16590,7 @@ export const config = {
|
|
|
16267
16590
|
// src/heal/recipes/eslintRestrictedImports.ts
|
|
16268
16591
|
function detectEslintConfigFile(cwd) {
|
|
16269
16592
|
for (const candidate of ESLINT_CONFIG_CANDIDATES) {
|
|
16270
|
-
if ((0,
|
|
16593
|
+
if ((0, import_node_fs11.existsSync)((0, import_node_path25.join)(cwd, candidate))) {
|
|
16271
16594
|
return candidate;
|
|
16272
16595
|
}
|
|
16273
16596
|
}
|
|
@@ -16422,12 +16745,12 @@ function applyEslintRestrictedImportsRecipe(source, configFile) {
|
|
|
16422
16745
|
}
|
|
16423
16746
|
return applyLegacyModuleRecipe(source);
|
|
16424
16747
|
}
|
|
16425
|
-
var
|
|
16748
|
+
var import_node_fs11, import_node_path25, VIBERAVEN_ESLINT_MARKER, RESTRICTED_IMPORTS_MESSAGE, RESTRICTED_PATHS, RESTRICTED_PATTERNS, ESLINT_CONFIG_CANDIDATES;
|
|
16426
16749
|
var init_eslintRestrictedImports = __esm({
|
|
16427
16750
|
"src/heal/recipes/eslintRestrictedImports.ts"() {
|
|
16428
16751
|
"use strict";
|
|
16429
|
-
|
|
16430
|
-
|
|
16752
|
+
import_node_fs11 = require("node:fs");
|
|
16753
|
+
import_node_path25 = require("node:path");
|
|
16431
16754
|
init_commands();
|
|
16432
16755
|
VIBERAVEN_ESLINT_MARKER = "VibeRaven heal: eslint_restricted_imports";
|
|
16433
16756
|
RESTRICTED_IMPORTS_MESSAGE = `Restricted import. Run ${PUBLIC_AGENT_MODE_COMMAND} before substituting packages.`;
|
|
@@ -16478,13 +16801,13 @@ function defaultTargetFile(gapId) {
|
|
|
16478
16801
|
return map[gapId];
|
|
16479
16802
|
}
|
|
16480
16803
|
async function readSourceOrEmpty(absolutePath) {
|
|
16481
|
-
if (!(0,
|
|
16804
|
+
if (!(0, import_node_fs12.existsSync)(absolutePath)) return "";
|
|
16482
16805
|
return (0, import_promises17.readFile)(absolutePath, "utf8");
|
|
16483
16806
|
}
|
|
16484
16807
|
async function detectUpstash(cwd) {
|
|
16485
16808
|
try {
|
|
16486
|
-
const pkgPath = (0,
|
|
16487
|
-
if (!(0,
|
|
16809
|
+
const pkgPath = (0, import_node_path26.join)(cwd, "package.json");
|
|
16810
|
+
if (!(0, import_node_fs12.existsSync)(pkgPath)) return false;
|
|
16488
16811
|
const raw = await (0, import_promises17.readFile)(pkgPath, "utf8");
|
|
16489
16812
|
const pkg = JSON.parse(raw);
|
|
16490
16813
|
const deps = {
|
|
@@ -16500,7 +16823,7 @@ async function dispatchRecipeByGapId(gapId, cwd, explicitTarget) {
|
|
|
16500
16823
|
const targetFile = explicitTarget ?? defaultTargetFile(gapId);
|
|
16501
16824
|
if (targetFile === void 0) return null;
|
|
16502
16825
|
if (gapId === "auth_secret_missing" || gapId === "node_env_not_set" || gapId === "database_url_missing") {
|
|
16503
|
-
const absolutePath = (0,
|
|
16826
|
+
const absolutePath = (0, import_node_path26.join)(cwd, targetFile);
|
|
16504
16827
|
const source = await readSourceOrEmpty(absolutePath);
|
|
16505
16828
|
let result;
|
|
16506
16829
|
if (gapId === "auth_secret_missing") result = applyAuthSecretRecipe(source);
|
|
@@ -16514,25 +16837,25 @@ async function dispatchRecipeByGapId(gapId, cwd, explicitTarget) {
|
|
|
16514
16837
|
};
|
|
16515
16838
|
}
|
|
16516
16839
|
if (gapId === "missing_error_boundary") {
|
|
16517
|
-
const absolutePath = (0,
|
|
16840
|
+
const absolutePath = (0, import_node_path26.join)(cwd, "app/error.tsx");
|
|
16518
16841
|
const source = await readSourceOrEmpty(absolutePath);
|
|
16519
16842
|
const result = applyErrorBoundaryRecipe(source);
|
|
16520
16843
|
return { ...result, canAutoApply: true, recipeName: gapId };
|
|
16521
16844
|
}
|
|
16522
16845
|
if (gapId === "missing_health_route") {
|
|
16523
|
-
const absolutePath = (0,
|
|
16846
|
+
const absolutePath = (0, import_node_path26.join)(cwd, "app/api/health/route.ts");
|
|
16524
16847
|
const source = await readSourceOrEmpty(absolutePath);
|
|
16525
16848
|
const result = applyHealthRouteRecipe(source);
|
|
16526
16849
|
return { ...result, canAutoApply: true, recipeName: gapId };
|
|
16527
16850
|
}
|
|
16528
16851
|
if (gapId === "missing_loading_state") {
|
|
16529
|
-
const absolutePath = (0,
|
|
16852
|
+
const absolutePath = (0, import_node_path26.join)(cwd, "app/loading.tsx");
|
|
16530
16853
|
const source = await readSourceOrEmpty(absolutePath);
|
|
16531
16854
|
const result = applyLoadingStateRecipe(source);
|
|
16532
16855
|
return { ...result, canAutoApply: true, recipeName: gapId };
|
|
16533
16856
|
}
|
|
16534
16857
|
if (gapId === "missing_404_page") {
|
|
16535
|
-
const absolutePath = (0,
|
|
16858
|
+
const absolutePath = (0, import_node_path26.join)(cwd, "app/not-found.tsx");
|
|
16536
16859
|
const source = await readSourceOrEmpty(absolutePath);
|
|
16537
16860
|
const result = applyNotFoundRecipe(source);
|
|
16538
16861
|
return { ...result, canAutoApply: true, recipeName: gapId };
|
|
@@ -16549,10 +16872,10 @@ async function dispatchRecipeByGapId(gapId, cwd, explicitTarget) {
|
|
|
16549
16872
|
}
|
|
16550
16873
|
if (gapId === "missing_csp_header") {
|
|
16551
16874
|
let configFile = "next.config.js";
|
|
16552
|
-
let absolutePath = (0,
|
|
16553
|
-
if (!(0,
|
|
16875
|
+
let absolutePath = (0, import_node_path26.join)(cwd, configFile);
|
|
16876
|
+
if (!(0, import_node_fs12.existsSync)(absolutePath)) {
|
|
16554
16877
|
configFile = "next.config.mjs";
|
|
16555
|
-
absolutePath = (0,
|
|
16878
|
+
absolutePath = (0, import_node_path26.join)(cwd, configFile);
|
|
16556
16879
|
}
|
|
16557
16880
|
const source = await readSourceOrEmpty(absolutePath);
|
|
16558
16881
|
const result = applyCspHeaderRecipe(source);
|
|
@@ -16564,7 +16887,7 @@ async function dispatchRecipeByGapId(gapId, cwd, explicitTarget) {
|
|
|
16564
16887
|
}
|
|
16565
16888
|
if (gapId === "missing_rate_limit") {
|
|
16566
16889
|
const hasUpstash = await detectUpstash(cwd);
|
|
16567
|
-
const middlewarePath = (0,
|
|
16890
|
+
const middlewarePath = (0, import_node_path26.join)(cwd, "middleware.ts");
|
|
16568
16891
|
const source = await readSourceOrEmpty(middlewarePath);
|
|
16569
16892
|
const result = applyRateLimitRecipe(source, hasUpstash);
|
|
16570
16893
|
return {
|
|
@@ -16586,7 +16909,7 @@ async function dispatchRecipeByGapId(gapId, cwd, explicitTarget) {
|
|
|
16586
16909
|
recipeName: gapId
|
|
16587
16910
|
};
|
|
16588
16911
|
}
|
|
16589
|
-
const absolutePath = (0,
|
|
16912
|
+
const absolutePath = (0, import_node_path26.join)(cwd, configFile);
|
|
16590
16913
|
const source = await readSourceOrEmpty(absolutePath);
|
|
16591
16914
|
const result = applyEslintRestrictedImportsRecipe(source, configFile);
|
|
16592
16915
|
return {
|
|
@@ -16600,13 +16923,13 @@ async function dispatchRecipeByGapId(gapId, cwd, explicitTarget) {
|
|
|
16600
16923
|
}
|
|
16601
16924
|
return null;
|
|
16602
16925
|
}
|
|
16603
|
-
var
|
|
16926
|
+
var import_node_fs12, import_promises17, import_node_path26;
|
|
16604
16927
|
var init_recipes = __esm({
|
|
16605
16928
|
"src/heal/recipes/index.ts"() {
|
|
16606
16929
|
"use strict";
|
|
16607
|
-
|
|
16930
|
+
import_node_fs12 = require("node:fs");
|
|
16608
16931
|
import_promises17 = require("node:fs/promises");
|
|
16609
|
-
|
|
16932
|
+
import_node_path26 = require("node:path");
|
|
16610
16933
|
init_envAuthSecret();
|
|
16611
16934
|
init_envNodeEnv();
|
|
16612
16935
|
init_envDatabaseUrl();
|
|
@@ -16683,16 +17006,16 @@ async function applyHeal(options) {
|
|
|
16683
17006
|
rollback: { available: false, instructions: "Recipe matched but no change was needed (already applied or file already exists)." }
|
|
16684
17007
|
};
|
|
16685
17008
|
}
|
|
16686
|
-
const absoluteTarget = (0,
|
|
17009
|
+
const absoluteTarget = (0, import_node_path27.join)(options.cwd, dispatched.targetFile);
|
|
16687
17010
|
assertSafeHealTarget(options.cwd, dispatched.targetFile);
|
|
16688
|
-
await (0, import_promises18.mkdir)((0,
|
|
17011
|
+
await (0, import_promises18.mkdir)((0, import_node_path27.dirname)(absoluteTarget), { recursive: true });
|
|
16689
17012
|
const created2 = await createHealDir(options.cwd);
|
|
16690
17013
|
id = created2.id;
|
|
16691
17014
|
const healDir2 = created2.dir;
|
|
16692
|
-
await (0, import_promises18.mkdir)((0,
|
|
16693
|
-
const existedBefore = (0,
|
|
17015
|
+
await (0, import_promises18.mkdir)((0, import_node_path27.join)(healDir2, "before"));
|
|
17016
|
+
const existedBefore = (0, import_node_fs13.existsSync)(absoluteTarget);
|
|
16694
17017
|
const beforeContent = existedBefore ? await (0, import_promises18.readFile)(absoluteTarget, "utf8") : "";
|
|
16695
|
-
await (0, import_promises18.writeFile)((0,
|
|
17018
|
+
await (0, import_promises18.writeFile)((0, import_node_path27.join)(healDir2, "before", "target.txt"), beforeContent, "utf8");
|
|
16696
17019
|
await (0, import_promises18.writeFile)(absoluteTarget, dispatched.output, "utf8");
|
|
16697
17020
|
const patch2 = [
|
|
16698
17021
|
`--- ${dispatched.targetFile}`,
|
|
@@ -16703,7 +17026,7 @@ async function applyHeal(options) {
|
|
|
16703
17026
|
dispatched.output,
|
|
16704
17027
|
""
|
|
16705
17028
|
].join("\n");
|
|
16706
|
-
await (0, import_promises18.writeFile)((0,
|
|
17029
|
+
await (0, import_promises18.writeFile)((0, import_node_path27.join)(healDir2, "patch.diff"), patch2, "utf8");
|
|
16707
17030
|
const result2 = {
|
|
16708
17031
|
$schema: "https://viberaven.dev/schemas/heal-result.schema.json",
|
|
16709
17032
|
schemaVersion: "v1",
|
|
@@ -16715,17 +17038,17 @@ async function applyHeal(options) {
|
|
|
16715
17038
|
recipe: dispatched.recipeName,
|
|
16716
17039
|
...dispatched.warnings?.length ? { warnings: dispatched.warnings } : {},
|
|
16717
17040
|
target: dispatched.targetFile,
|
|
16718
|
-
changedFiles: [(0,
|
|
17041
|
+
changedFiles: [(0, import_node_path27.relative)(options.cwd, absoluteTarget).replace(/\\/g, "/")],
|
|
16719
17042
|
artifacts: {
|
|
16720
17043
|
patch: `.viberaven/heal/${id}/patch.diff`,
|
|
16721
17044
|
result: `.viberaven/heal/${id}/result.json`
|
|
16722
17045
|
},
|
|
16723
17046
|
rollback: {
|
|
16724
17047
|
available: true,
|
|
16725
|
-
instructions: rollbackInstructions(id, (0,
|
|
17048
|
+
instructions: rollbackInstructions(id, (0, import_node_path27.relative)(options.cwd, absoluteTarget).replace(/\\/g, "/"), existedBefore)
|
|
16726
17049
|
}
|
|
16727
17050
|
};
|
|
16728
|
-
await (0, import_promises18.writeFile)((0,
|
|
17051
|
+
await (0, import_promises18.writeFile)((0, import_node_path27.join)(healDir2, "result.json"), `${JSON.stringify(result2, null, 2)}
|
|
16729
17052
|
`, "utf8");
|
|
16730
17053
|
return result2;
|
|
16731
17054
|
}
|
|
@@ -16765,8 +17088,8 @@ async function applyHeal(options) {
|
|
|
16765
17088
|
const created = await createHealDir(options.cwd);
|
|
16766
17089
|
id = created.id;
|
|
16767
17090
|
const healDir = created.dir;
|
|
16768
|
-
await (0, import_promises18.mkdir)((0,
|
|
16769
|
-
await (0, import_promises18.writeFile)((0,
|
|
17091
|
+
await (0, import_promises18.mkdir)((0, import_node_path27.join)(healDir, "before"));
|
|
17092
|
+
await (0, import_promises18.writeFile)((0, import_node_path27.join)(healDir, "before", "target.txt"), before, "utf8");
|
|
16770
17093
|
await (0, import_promises18.writeFile)(absolute, recipe.output, "utf8");
|
|
16771
17094
|
const patch = [
|
|
16772
17095
|
`--- ${options.target}`,
|
|
@@ -16777,7 +17100,7 @@ async function applyHeal(options) {
|
|
|
16777
17100
|
recipe.output,
|
|
16778
17101
|
""
|
|
16779
17102
|
].join("\n");
|
|
16780
|
-
await (0, import_promises18.writeFile)((0,
|
|
17103
|
+
await (0, import_promises18.writeFile)((0, import_node_path27.join)(healDir, "patch.diff"), patch, "utf8");
|
|
16781
17104
|
const result = {
|
|
16782
17105
|
$schema: "https://viberaven.dev/schemas/heal-result.schema.json",
|
|
16783
17106
|
schemaVersion: "v1",
|
|
@@ -16788,7 +17111,7 @@ async function applyHeal(options) {
|
|
|
16788
17111
|
gapId: options.gapId,
|
|
16789
17112
|
recipe: "empty-catch-safe-response",
|
|
16790
17113
|
target: options.target,
|
|
16791
|
-
changedFiles: [(0,
|
|
17114
|
+
changedFiles: [(0, import_node_path27.relative)(options.cwd, absolute).replace(/\\/g, "/")],
|
|
16792
17115
|
artifacts: {
|
|
16793
17116
|
patch: `.viberaven/heal/${id}/patch.diff`,
|
|
16794
17117
|
result: `.viberaven/heal/${id}/result.json`
|
|
@@ -16796,20 +17119,20 @@ async function applyHeal(options) {
|
|
|
16796
17119
|
rollback: {
|
|
16797
17120
|
available: true,
|
|
16798
17121
|
// The empty-catch recipe only edits a file that already exists.
|
|
16799
|
-
instructions: rollbackInstructions(id, (0,
|
|
17122
|
+
instructions: rollbackInstructions(id, (0, import_node_path27.relative)(options.cwd, absolute).replace(/\\/g, "/"), true)
|
|
16800
17123
|
}
|
|
16801
17124
|
};
|
|
16802
|
-
await (0, import_promises18.writeFile)((0,
|
|
17125
|
+
await (0, import_promises18.writeFile)((0, import_node_path27.join)(healDir, "result.json"), `${JSON.stringify(result, null, 2)}
|
|
16803
17126
|
`, "utf8");
|
|
16804
17127
|
return result;
|
|
16805
17128
|
}
|
|
16806
|
-
var import_promises18,
|
|
17129
|
+
var import_promises18, import_node_fs13, import_node_path27;
|
|
16807
17130
|
var init_apply = __esm({
|
|
16808
17131
|
"src/heal/apply.ts"() {
|
|
16809
17132
|
"use strict";
|
|
16810
17133
|
import_promises18 = require("node:fs/promises");
|
|
16811
|
-
|
|
16812
|
-
|
|
17134
|
+
import_node_fs13 = require("node:fs");
|
|
17135
|
+
import_node_path27 = require("node:path");
|
|
16813
17136
|
init_pathSafety();
|
|
16814
17137
|
init_emptyCatch();
|
|
16815
17138
|
init_healId();
|
|
@@ -16819,7 +17142,7 @@ var init_apply = __esm({
|
|
|
16819
17142
|
|
|
16820
17143
|
// src/heal/plan.ts
|
|
16821
17144
|
async function writeHealPlan(options) {
|
|
16822
|
-
const dir = (0,
|
|
17145
|
+
const dir = (0, import_node_path28.join)(options.cwd, ".viberaven");
|
|
16823
17146
|
await (0, import_promises19.mkdir)(dir, { recursive: true });
|
|
16824
17147
|
const id = newHealId();
|
|
16825
17148
|
const target = options.target ?? `gap:${options.gapId}`;
|
|
@@ -16872,18 +17195,18 @@ async function writeHealPlan(options) {
|
|
|
16872
17195
|
artifacts: { plan: ".viberaven/heal-plan.md" },
|
|
16873
17196
|
rollback: { available: false, instructions: "No source files were changed." }
|
|
16874
17197
|
};
|
|
16875
|
-
await (0, import_promises19.writeFile)((0,
|
|
16876
|
-
await (0, import_promises19.writeFile)((0,
|
|
17198
|
+
await (0, import_promises19.writeFile)((0, import_node_path28.join)(dir, "heal-plan.md"), markdown, "utf8");
|
|
17199
|
+
await (0, import_promises19.writeFile)((0, import_node_path28.join)(dir, "heal-plan.json"), `${JSON.stringify(result, null, 2)}
|
|
16877
17200
|
`, "utf8");
|
|
16878
17201
|
return result;
|
|
16879
17202
|
}
|
|
16880
|
-
var import_promises19,
|
|
17203
|
+
var import_promises19, import_node_path28;
|
|
16881
17204
|
var init_plan = __esm({
|
|
16882
17205
|
"src/heal/plan.ts"() {
|
|
16883
17206
|
"use strict";
|
|
16884
17207
|
import_promises19 = require("node:fs/promises");
|
|
16885
17208
|
init_healId();
|
|
16886
|
-
|
|
17209
|
+
import_node_path28 = require("node:path");
|
|
16887
17210
|
init_commands();
|
|
16888
17211
|
init_supabaseRls2();
|
|
16889
17212
|
}
|
|
@@ -16891,7 +17214,7 @@ var init_plan = __esm({
|
|
|
16891
17214
|
|
|
16892
17215
|
// src/heal/prompt.ts
|
|
16893
17216
|
async function writeHealPrompt(options) {
|
|
16894
|
-
const dir = (0,
|
|
17217
|
+
const dir = (0, import_node_path29.join)(options.cwd, ".viberaven");
|
|
16895
17218
|
await (0, import_promises20.mkdir)(dir, { recursive: true });
|
|
16896
17219
|
const id = newHealId();
|
|
16897
17220
|
const target = options.target ?? `gap:${options.gapId}`;
|
|
@@ -16919,16 +17242,16 @@ async function writeHealPrompt(options) {
|
|
|
16919
17242
|
artifacts: { prompt: ".viberaven/heal-prompt.md" },
|
|
16920
17243
|
rollback: { available: false, instructions: "No source files were changed." }
|
|
16921
17244
|
};
|
|
16922
|
-
await (0, import_promises20.writeFile)((0,
|
|
17245
|
+
await (0, import_promises20.writeFile)((0, import_node_path29.join)(dir, "heal-prompt.md"), prompt, "utf8");
|
|
16923
17246
|
return result;
|
|
16924
17247
|
}
|
|
16925
|
-
var import_promises20,
|
|
17248
|
+
var import_promises20, import_node_path29;
|
|
16926
17249
|
var init_prompt = __esm({
|
|
16927
17250
|
"src/heal/prompt.ts"() {
|
|
16928
17251
|
"use strict";
|
|
16929
17252
|
import_promises20 = require("node:fs/promises");
|
|
16930
17253
|
init_healId();
|
|
16931
|
-
|
|
17254
|
+
import_node_path29 = require("node:path");
|
|
16932
17255
|
init_commands();
|
|
16933
17256
|
}
|
|
16934
17257
|
});
|
|
@@ -17031,8 +17354,8 @@ var init_heal = __esm({
|
|
|
17031
17354
|
|
|
17032
17355
|
// src/stackRecommend.ts
|
|
17033
17356
|
async function recommendStack(cwd = process.cwd()) {
|
|
17034
|
-
const pkgPath = (0,
|
|
17035
|
-
if (!(0,
|
|
17357
|
+
const pkgPath = (0, import_node_path30.join)(cwd, "package.json");
|
|
17358
|
+
if (!(0, import_node_fs14.existsSync)(pkgPath)) {
|
|
17036
17359
|
return DEFAULT_STACK;
|
|
17037
17360
|
}
|
|
17038
17361
|
const pkg = JSON.parse(await (0, import_promises22.readFile)(pkgPath, "utf-8"));
|
|
@@ -17063,13 +17386,13 @@ async function recommendStack(cwd = process.cwd()) {
|
|
|
17063
17386
|
}
|
|
17064
17387
|
return rec;
|
|
17065
17388
|
}
|
|
17066
|
-
var import_promises22,
|
|
17389
|
+
var import_promises22, import_node_fs14, import_node_path30, DEFAULT_STACK;
|
|
17067
17390
|
var init_stackRecommend = __esm({
|
|
17068
17391
|
"src/stackRecommend.ts"() {
|
|
17069
17392
|
"use strict";
|
|
17070
17393
|
import_promises22 = require("node:fs/promises");
|
|
17071
|
-
|
|
17072
|
-
|
|
17394
|
+
import_node_fs14 = require("node:fs");
|
|
17395
|
+
import_node_path30 = require("node:path");
|
|
17073
17396
|
DEFAULT_STACK = {
|
|
17074
17397
|
frontend: "react",
|
|
17075
17398
|
ui: "tailwind + shadcn/ui",
|
|
@@ -17212,13 +17535,13 @@ async function readBlobs(cwd, shas) {
|
|
|
17212
17535
|
async function exportCommit(cwd, commit) {
|
|
17213
17536
|
const entries = parseTree(await git(cwd, ["ls-tree", "-r", "-z", "-l", "--full-tree", commit])).filter(wanted);
|
|
17214
17537
|
const blobs = await readBlobs(cwd, [...new Set(entries.map((entry) => entry.sha))]);
|
|
17215
|
-
const root = await (0, import_promises23.mkdtemp)((0,
|
|
17538
|
+
const root = await (0, import_promises23.mkdtemp)((0, import_node_path31.join)((0, import_node_os.tmpdir)(), "viberaven-base-"));
|
|
17216
17539
|
for (const entry of entries) {
|
|
17217
|
-
const target = (0,
|
|
17218
|
-
if (!target.startsWith(root +
|
|
17540
|
+
const target = (0, import_node_path31.resolve)(root, ...entry.path.split("/"));
|
|
17541
|
+
if (!target.startsWith(root + import_node_path31.sep)) continue;
|
|
17219
17542
|
const content = blobs.get(entry.sha);
|
|
17220
17543
|
if (!content) continue;
|
|
17221
|
-
await (0, import_promises23.mkdir)((0,
|
|
17544
|
+
await (0, import_promises23.mkdir)((0, import_node_path31.dirname)(target), { recursive: true });
|
|
17222
17545
|
await (0, import_promises23.writeFile)(target, content);
|
|
17223
17546
|
}
|
|
17224
17547
|
return root;
|
|
@@ -17288,14 +17611,14 @@ function renderCheckMarkdown({ head, change, version, score }) {
|
|
|
17288
17611
|
return `${lines.join("\n")}
|
|
17289
17612
|
`;
|
|
17290
17613
|
}
|
|
17291
|
-
var import_node_child_process6, import_promises23, import_node_os,
|
|
17614
|
+
var import_node_child_process6, import_promises23, import_node_os, import_node_path31, import_node_util4, execFileAsync4, MAX_BLOB_BYTES, SKIP_SEGMENTS, SEVERITY_RANK3, LOCATION_TEXT, SUBJECT, COMMENT_MARKER, DOT;
|
|
17292
17615
|
var init_checkChange = __esm({
|
|
17293
17616
|
"src/commands/checkChange.ts"() {
|
|
17294
17617
|
"use strict";
|
|
17295
17618
|
import_node_child_process6 = require("node:child_process");
|
|
17296
17619
|
import_promises23 = require("node:fs/promises");
|
|
17297
17620
|
import_node_os = require("node:os");
|
|
17298
|
-
|
|
17621
|
+
import_node_path31 = require("node:path");
|
|
17299
17622
|
import_node_util4 = require("node:util");
|
|
17300
17623
|
init_runScan();
|
|
17301
17624
|
init_safeGit();
|
|
@@ -17379,12 +17702,12 @@ async function hasGithubRemote(cwd) {
|
|
|
17379
17702
|
}
|
|
17380
17703
|
}
|
|
17381
17704
|
async function githubWorkflowStatus(cwd) {
|
|
17382
|
-
return { exists: (0,
|
|
17705
|
+
return { exists: (0, import_node_fs15.existsSync)((0, import_node_path32.join)(cwd, WORKFLOW_PATH)), path: DISPLAY_PATH, onGithub: await hasGithubRemote(cwd) };
|
|
17383
17706
|
}
|
|
17384
17707
|
async function writeGithubWorkflow(cwd, options = {}) {
|
|
17385
|
-
const target = (0,
|
|
17386
|
-
if ((0,
|
|
17387
|
-
await (0, import_promises24.mkdir)((0,
|
|
17708
|
+
const target = (0, import_node_path32.join)(cwd, WORKFLOW_PATH);
|
|
17709
|
+
if ((0, import_node_fs15.existsSync)(target) && !options.force) return { written: false, status: await githubWorkflowStatus(cwd) };
|
|
17710
|
+
await (0, import_promises24.mkdir)((0, import_node_path32.dirname)(target), { recursive: true });
|
|
17388
17711
|
await (0, import_promises24.writeFile)(target, renderWorkflow(), "utf8");
|
|
17389
17712
|
return { written: true, status: await githubWorkflowStatus(cwd) };
|
|
17390
17713
|
}
|
|
@@ -17409,20 +17732,20 @@ async function runInitGithubCommand(options) {
|
|
|
17409
17732
|
if (!status.onGithub) console.log("This repository has no github.com remote yet: the workflow runs once it is pushed to GitHub.");
|
|
17410
17733
|
return 0;
|
|
17411
17734
|
}
|
|
17412
|
-
var import_node_child_process7,
|
|
17735
|
+
var import_node_child_process7, import_node_fs15, import_promises24, import_node_path32, import_node_util5, execFileAsync5, WORKFLOW_PATH, DISPLAY_PATH;
|
|
17413
17736
|
var init_initGithub = __esm({
|
|
17414
17737
|
"src/commands/initGithub.ts"() {
|
|
17415
17738
|
"use strict";
|
|
17416
17739
|
import_node_child_process7 = require("node:child_process");
|
|
17417
|
-
|
|
17740
|
+
import_node_fs15 = require("node:fs");
|
|
17418
17741
|
import_promises24 = require("node:fs/promises");
|
|
17419
|
-
|
|
17742
|
+
import_node_path32 = require("node:path");
|
|
17420
17743
|
import_node_util5 = require("node:util");
|
|
17421
17744
|
init_safeGit();
|
|
17422
17745
|
init_version();
|
|
17423
17746
|
init_checkChange();
|
|
17424
17747
|
execFileAsync5 = (0, import_node_util5.promisify)(import_node_child_process7.execFile);
|
|
17425
|
-
WORKFLOW_PATH = (0,
|
|
17748
|
+
WORKFLOW_PATH = (0, import_node_path32.join)(".github", "workflows", "viberaven.yml");
|
|
17426
17749
|
DISPLAY_PATH = ".github/workflows/viberaven.yml";
|
|
17427
17750
|
}
|
|
17428
17751
|
});
|
|
@@ -17446,7 +17769,7 @@ function managedBlocks(content) {
|
|
|
17446
17769
|
async function checkAgentInjection(cwd) {
|
|
17447
17770
|
const checks = [];
|
|
17448
17771
|
for (const item4 of REQUIRED_EXISTENCE_CHECKS) {
|
|
17449
|
-
const exists = await fileExists2((0,
|
|
17772
|
+
const exists = await fileExists2((0, import_node_path33.join)(cwd, item4.file));
|
|
17450
17773
|
checks.push({
|
|
17451
17774
|
id: item4.id,
|
|
17452
17775
|
status: exists ? "pass" : "fail",
|
|
@@ -17454,17 +17777,17 @@ async function checkAgentInjection(cwd) {
|
|
|
17454
17777
|
});
|
|
17455
17778
|
}
|
|
17456
17779
|
for (const item4 of OPTIONAL_CURSOR_PACK_CHECKS) {
|
|
17457
|
-
const exists = await fileExists2((0,
|
|
17780
|
+
const exists = await fileExists2((0, import_node_path33.join)(cwd, item4.file));
|
|
17458
17781
|
checks.push({
|
|
17459
17782
|
id: item4.id,
|
|
17460
17783
|
status: exists ? "pass" : "fail",
|
|
17461
17784
|
message: exists ? `${item4.file} exists` : `Missing ${item4.file} \u2014 run npx -y viberaven init --agents all`
|
|
17462
17785
|
});
|
|
17463
17786
|
}
|
|
17464
|
-
const legacyCursorPath = (0,
|
|
17787
|
+
const legacyCursorPath = (0, import_node_path33.join)(cwd, ".cursor/rules/viberaven.mdc");
|
|
17465
17788
|
if (await fileExists2(legacyCursorPath)) {
|
|
17466
17789
|
const legacyContent = await (0, import_promises25.readFile)(legacyCursorPath, "utf-8");
|
|
17467
|
-
const hasCoreSplit = await fileExists2((0,
|
|
17790
|
+
const hasCoreSplit = await fileExists2((0, import_node_path33.join)(cwd, ".cursor/rules/viberaven-core.mdc"));
|
|
17468
17791
|
if (!hasCoreSplit || legacyContent.includes("alwaysApply: true")) {
|
|
17469
17792
|
checks.push({
|
|
17470
17793
|
id: "cursor-legacy-mdc",
|
|
@@ -17475,7 +17798,7 @@ async function checkAgentInjection(cwd) {
|
|
|
17475
17798
|
}
|
|
17476
17799
|
for (const target of CORE_AGENT_INJECTION_TARGETS) {
|
|
17477
17800
|
const file = target === "cursor" ? ".cursor/rules/viberaven-core.mdc" : AGENT_RULE_TARGETS[target].file;
|
|
17478
|
-
const path = (0,
|
|
17801
|
+
const path = (0, import_node_path33.join)(cwd, file);
|
|
17479
17802
|
const exists = await fileExists2(path);
|
|
17480
17803
|
if (!exists) {
|
|
17481
17804
|
checks.push({
|
|
@@ -17534,12 +17857,12 @@ async function fileExists2(path) {
|
|
|
17534
17857
|
return false;
|
|
17535
17858
|
}
|
|
17536
17859
|
}
|
|
17537
|
-
var import_promises25,
|
|
17860
|
+
var import_promises25, import_node_path33, REQUIRED_EXISTENCE_CHECKS, OPTIONAL_CURSOR_PACK_CHECKS, STALE_PATTERNS, GATE_RULE_PHRASES_1_5_2;
|
|
17538
17861
|
var init_doctorAgents = __esm({
|
|
17539
17862
|
"src/commands/doctorAgents.ts"() {
|
|
17540
17863
|
"use strict";
|
|
17541
17864
|
import_promises25 = require("node:fs/promises");
|
|
17542
|
-
|
|
17865
|
+
import_node_path33 = require("node:path");
|
|
17543
17866
|
init_commands();
|
|
17544
17867
|
init_agentTargets();
|
|
17545
17868
|
REQUIRED_EXISTENCE_CHECKS = [
|
|
@@ -17810,7 +18133,7 @@ function buildContextCleanupPlan(input) {
|
|
|
17810
18133
|
const items = [];
|
|
17811
18134
|
const seen = /* @__PURE__ */ new Set();
|
|
17812
18135
|
for (const file of input.files) {
|
|
17813
|
-
const path = normalizePath5((0,
|
|
18136
|
+
const path = normalizePath5((0, import_node_path34.relative)(input.projectRoot, file.path) || file.path);
|
|
17814
18137
|
const fullPath = normalizePath5(file.path);
|
|
17815
18138
|
const category = categorizeCleanupFile(path, fullPath, file);
|
|
17816
18139
|
if (!category || seen.has(path)) {
|
|
@@ -17836,8 +18159,8 @@ async function collectCleanupFiles(projectRoot) {
|
|
|
17836
18159
|
return files;
|
|
17837
18160
|
}
|
|
17838
18161
|
async function writeCleanupPlan(projectRoot, plan) {
|
|
17839
|
-
const outputDir = (0,
|
|
17840
|
-
const outputPath = (0,
|
|
18162
|
+
const outputDir = (0, import_node_path34.join)(projectRoot, ".viberaven");
|
|
18163
|
+
const outputPath = (0, import_node_path34.join)(outputDir, "context-cleanup.md");
|
|
17841
18164
|
await (0, import_promises26.mkdir)(outputDir, { recursive: true });
|
|
17842
18165
|
await (0, import_promises26.writeFile)(outputPath, renderCleanupPlan(plan), "utf8");
|
|
17843
18166
|
return outputPath;
|
|
@@ -17895,9 +18218,9 @@ async function walkCleanupFiles(root, dir, result, depth) {
|
|
|
17895
18218
|
if (SKIP_DIRECTORIES.has(entry.name)) {
|
|
17896
18219
|
continue;
|
|
17897
18220
|
}
|
|
17898
|
-
const absolute = (0,
|
|
18221
|
+
const absolute = (0, import_node_path34.join)(dir, entry.name);
|
|
17899
18222
|
if (entry.isDirectory()) {
|
|
17900
|
-
if (isCachePath(normalizePath5((0,
|
|
18223
|
+
if (isCachePath(normalizePath5((0, import_node_path34.relative)(root, absolute)))) {
|
|
17901
18224
|
result.push({ path: absolute, sizeBytes: 0, kind: "directory" });
|
|
17902
18225
|
continue;
|
|
17903
18226
|
}
|
|
@@ -17918,12 +18241,12 @@ async function walkCleanupFiles(root, dir, result, depth) {
|
|
|
17918
18241
|
function normalizePath5(path) {
|
|
17919
18242
|
return path.replace(/\\/g, "/");
|
|
17920
18243
|
}
|
|
17921
|
-
var import_promises26,
|
|
18244
|
+
var import_promises26, import_node_path34, MAX_WALK_DEPTH, LARGE_LOG_BYTES, SKIP_DIRECTORIES;
|
|
17922
18245
|
var init_cleanPlan = __esm({
|
|
17923
18246
|
"src/commands/cleanPlan.ts"() {
|
|
17924
18247
|
"use strict";
|
|
17925
18248
|
import_promises26 = require("node:fs/promises");
|
|
17926
|
-
|
|
18249
|
+
import_node_path34 = require("node:path");
|
|
17927
18250
|
MAX_WALK_DEPTH = 5;
|
|
17928
18251
|
LARGE_LOG_BYTES = 8192;
|
|
17929
18252
|
SKIP_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
@@ -18001,6 +18324,9 @@ function renderVerifyCommand(action) {
|
|
|
18001
18324
|
}
|
|
18002
18325
|
return ["Verify:", "```bash", redact(action.verifyCommand), "```"];
|
|
18003
18326
|
}
|
|
18327
|
+
function renderUserSteps(steps) {
|
|
18328
|
+
return steps?.length ? ["Outside the repo (tell the user):", ...steps.map((step) => `- ${redact(step)}`)] : [];
|
|
18329
|
+
}
|
|
18004
18330
|
function renderAction(action) {
|
|
18005
18331
|
return [
|
|
18006
18332
|
`[${action.id}] ${redact(action.title)}`,
|
|
@@ -18009,6 +18335,7 @@ function renderAction(action) {
|
|
|
18009
18335
|
...renderTarget(action.target),
|
|
18010
18336
|
...renderCopyPayload(action),
|
|
18011
18337
|
...renderVerifyCommand(action),
|
|
18338
|
+
...renderUserSteps(action.userSteps),
|
|
18012
18339
|
action.resumeInstruction ? `Resume: "${redact(action.resumeInstruction)}"` : void 0
|
|
18013
18340
|
].filter((line) => Boolean(line));
|
|
18014
18341
|
}
|
|
@@ -18024,6 +18351,9 @@ function renderActionSurface(manifest, options = {}) {
|
|
|
18024
18351
|
for (const action of visibleActions) {
|
|
18025
18352
|
lines.push(...renderAction(action), "");
|
|
18026
18353
|
}
|
|
18354
|
+
for (const followUp of options.followUps === false ? [] : manifest.userFollowUps ?? []) {
|
|
18355
|
+
lines.push(`[${followUp.id}] ${redact(followUp.title ?? followUp.gapId ?? "Fixed in the repo")}`, "Status: resolved in the repo", ...renderUserSteps(followUp.userSteps), "");
|
|
18356
|
+
}
|
|
18027
18357
|
return `${lines.join("\n").trimEnd()}
|
|
18028
18358
|
`;
|
|
18029
18359
|
}
|
|
@@ -18036,7 +18366,7 @@ var init_render = __esm({
|
|
|
18036
18366
|
|
|
18037
18367
|
// src/commands/actions.ts
|
|
18038
18368
|
async function runActionsCommand(input) {
|
|
18039
|
-
const actionsPath = (0,
|
|
18369
|
+
const actionsPath = (0, import_node_path35.join)(getProjectArtifactsDir(input.cwd), "actions.json");
|
|
18040
18370
|
let raw;
|
|
18041
18371
|
try {
|
|
18042
18372
|
raw = await (0, import_promises27.readFile)(actionsPath, "utf8");
|
|
@@ -18053,12 +18383,12 @@ async function runActionsCommand(input) {
|
|
|
18053
18383
|
process.stdout.write(renderActionSurface(manifest));
|
|
18054
18384
|
return 0;
|
|
18055
18385
|
}
|
|
18056
|
-
var import_promises27,
|
|
18386
|
+
var import_promises27, import_node_path35;
|
|
18057
18387
|
var init_actions = __esm({
|
|
18058
18388
|
"src/commands/actions.ts"() {
|
|
18059
18389
|
"use strict";
|
|
18060
18390
|
import_promises27 = require("node:fs/promises");
|
|
18061
|
-
|
|
18391
|
+
import_node_path35 = require("node:path");
|
|
18062
18392
|
init_render();
|
|
18063
18393
|
init_config();
|
|
18064
18394
|
}
|
|
@@ -18067,7 +18397,7 @@ var init_actions = __esm({
|
|
|
18067
18397
|
// src/commands/verifyAction.ts
|
|
18068
18398
|
async function currentActionExists(cwd, actionId) {
|
|
18069
18399
|
try {
|
|
18070
|
-
const raw = await (0, import_promises28.readFile)((0,
|
|
18400
|
+
const raw = await (0, import_promises28.readFile)((0, import_node_path36.join)(getProjectArtifactsDir(cwd), "actions.json"), "utf8");
|
|
18071
18401
|
const manifest = JSON.parse(raw);
|
|
18072
18402
|
return manifest.actions.some((action) => action.id === actionId);
|
|
18073
18403
|
} catch {
|
|
@@ -18111,12 +18441,12 @@ This only looks the action up. Run \`npx -y viberaven --verify\` to scan the rep
|
|
|
18111
18441
|
);
|
|
18112
18442
|
return 0;
|
|
18113
18443
|
}
|
|
18114
|
-
var import_promises28,
|
|
18444
|
+
var import_promises28, import_node_path36;
|
|
18115
18445
|
var init_verifyAction = __esm({
|
|
18116
18446
|
"src/commands/verifyAction.ts"() {
|
|
18117
18447
|
"use strict";
|
|
18118
18448
|
import_promises28 = require("node:fs/promises");
|
|
18119
|
-
|
|
18449
|
+
import_node_path36 = require("node:path");
|
|
18120
18450
|
init_registry2();
|
|
18121
18451
|
init_config();
|
|
18122
18452
|
}
|
|
@@ -18271,6 +18601,7 @@ ${message}
|
|
|
18271
18601
|
return failing ? 1 : 0;
|
|
18272
18602
|
}
|
|
18273
18603
|
if (options.json) {
|
|
18604
|
+
const userFollowUps = await readUserFollowUps(paths.actionsPath);
|
|
18274
18605
|
console.log(
|
|
18275
18606
|
JSON.stringify(
|
|
18276
18607
|
{
|
|
@@ -18293,6 +18624,8 @@ ${message}
|
|
|
18293
18624
|
unchanged: change.unchanged.map((gap) => gap.id)
|
|
18294
18625
|
}
|
|
18295
18626
|
} : {},
|
|
18627
|
+
// Steps outside the repo for fixes already in it (MCP check and verify read this). Read only.
|
|
18628
|
+
...userFollowUps.length > 0 ? { userFollowUps } : {},
|
|
18296
18629
|
artifacts: paths
|
|
18297
18630
|
},
|
|
18298
18631
|
null,
|
|
@@ -18347,14 +18680,31 @@ ${message}
|
|
|
18347
18680
|
console.log(
|
|
18348
18681
|
critical > 0 ? `Verdict: \u274C ${critical} blocker${critical === 1 ? "" : "s"}, ${warnings} warning${warnings === 1 ? "" : "s"} \xB7 score ${artifact.score}` : `Verdict: \u2705 no blockers, ${warnings} warning${warnings === 1 ? "" : "s"} \xB7 score ${artifact.score}`
|
|
18349
18682
|
);
|
|
18683
|
+
await printUserFollowUps(paths.actionsPath);
|
|
18350
18684
|
console.log(`Fix: viberaven fix \xB7 Details: ${paths.tasklistPath}`);
|
|
18351
18685
|
console.log("");
|
|
18352
18686
|
return critical > 0 ? 1 : 0;
|
|
18353
18687
|
}
|
|
18354
|
-
|
|
18688
|
+
async function readUserFollowUps(actionsPath) {
|
|
18689
|
+
try {
|
|
18690
|
+
return JSON.parse(await (0, import_promises29.readFile)(actionsPath, "utf8")).userFollowUps ?? [];
|
|
18691
|
+
} catch {
|
|
18692
|
+
return [];
|
|
18693
|
+
}
|
|
18694
|
+
}
|
|
18695
|
+
async function printUserFollowUps(actionsPath) {
|
|
18696
|
+
const followUps = await readUserFollowUps(actionsPath);
|
|
18697
|
+
if (followUps.length === 0) return;
|
|
18698
|
+
console.log("Outside the repo, still on you:");
|
|
18699
|
+
for (const followUp of followUps) {
|
|
18700
|
+
for (const step of followUp.userSteps) console.log(` - ${step} (${followUp.gapId ?? followUp.id})`);
|
|
18701
|
+
}
|
|
18702
|
+
}
|
|
18703
|
+
var import_promises29, SEVERITY_ICON, SEVERITY_ORDER3;
|
|
18355
18704
|
var init_check = __esm({
|
|
18356
18705
|
"src/commands/check.ts"() {
|
|
18357
18706
|
"use strict";
|
|
18707
|
+
import_promises29 = require("node:fs/promises");
|
|
18358
18708
|
init_runScan();
|
|
18359
18709
|
init_artifacts2();
|
|
18360
18710
|
init_statusLabels();
|
|
@@ -18803,8 +19153,8 @@ function isSqlError(error) {
|
|
|
18803
19153
|
}
|
|
18804
19154
|
function displayPath(projectDir, path) {
|
|
18805
19155
|
for (const base of [projectDir, process.cwd()]) {
|
|
18806
|
-
const rel = (0,
|
|
18807
|
-
if (rel && !rel.startsWith("..") && !(0,
|
|
19156
|
+
const rel = (0, import_node_path37.relative)(base, path);
|
|
19157
|
+
if (rel && !rel.startsWith("..") && !(0, import_node_path37.isAbsolute)(rel)) return rel.split("\\").join("/");
|
|
18808
19158
|
}
|
|
18809
19159
|
return path;
|
|
18810
19160
|
}
|
|
@@ -19408,26 +19758,26 @@ function verdictFor(summary) {
|
|
|
19408
19758
|
}
|
|
19409
19759
|
async function listMigrations(dir) {
|
|
19410
19760
|
try {
|
|
19411
|
-
const entries = await (0,
|
|
19761
|
+
const entries = await (0, import_promises30.readdir)(dir, { withFileTypes: true });
|
|
19412
19762
|
return entries.filter((e2) => e2.isFile() && /\.sql$/i.test(e2.name) && !e2.name.startsWith(".")).map((e2) => e2.name).sort((a, b3) => a < b3 ? -1 : a > b3 ? 1 : 0);
|
|
19413
19763
|
} catch {
|
|
19414
19764
|
return [];
|
|
19415
19765
|
}
|
|
19416
19766
|
}
|
|
19417
19767
|
async function runRlsTest(options) {
|
|
19418
|
-
const projectDir = (0,
|
|
19419
|
-
const matrixPath = (0,
|
|
19420
|
-
const migrationsDir = (0,
|
|
19768
|
+
const projectDir = (0, import_node_path37.resolve)(options.projectDir);
|
|
19769
|
+
const matrixPath = (0, import_node_path37.resolve)(projectDir, options.matrixPath ?? DEFAULT_MATRIX_FILE);
|
|
19770
|
+
const migrationsDir = (0, import_node_path37.resolve)(projectDir, options.migrationsDir ?? (0, import_node_path37.join)("supabase", "migrations"));
|
|
19421
19771
|
const timeouts = { ...DEFAULT_TIMEOUTS, ...options.timeouts };
|
|
19422
|
-
if ((0,
|
|
19423
|
-
throw new RlsInputError(`Refusing to read ${(0,
|
|
19772
|
+
if ((0, import_node_path37.basename)(matrixPath).toLowerCase().startsWith(".env")) {
|
|
19773
|
+
throw new RlsInputError(`Refusing to read ${(0, import_node_path37.basename)(matrixPath)}: rls-test never reads .env files. Point --matrix at a viberaven.permissions.json.`);
|
|
19424
19774
|
}
|
|
19425
19775
|
const filesRead = [];
|
|
19426
19776
|
let matrixText;
|
|
19427
19777
|
try {
|
|
19428
|
-
const info = await (0,
|
|
19778
|
+
const info = await (0, import_promises30.stat)(matrixPath);
|
|
19429
19779
|
if (!info.isFile()) throw new Error("not a file");
|
|
19430
|
-
matrixText = normalise(await (0,
|
|
19780
|
+
matrixText = normalise(await (0, import_promises30.readFile)(matrixPath, "utf8"));
|
|
19431
19781
|
} catch {
|
|
19432
19782
|
throw new RlsInputError(
|
|
19433
19783
|
`No permissions matrix at ${matrixPath}. Write one by hand (schema: schemas/permissions-matrix.schema.json in the @viberaven/cli package); rls-test never infers it from your policies.`
|
|
@@ -19438,8 +19788,8 @@ async function runRlsTest(options) {
|
|
|
19438
19788
|
const names = await listMigrations(migrationsDir);
|
|
19439
19789
|
const migrationFiles = [];
|
|
19440
19790
|
for (const name of names) {
|
|
19441
|
-
const sql = normalise(await (0,
|
|
19442
|
-
filesRead.push(displayPath(projectDir, (0,
|
|
19791
|
+
const sql = normalise(await (0, import_promises30.readFile)((0, import_node_path37.join)(migrationsDir, name), "utf8"));
|
|
19792
|
+
filesRead.push(displayPath(projectDir, (0, import_node_path37.join)(migrationsDir, name)));
|
|
19443
19793
|
migrationFiles.push({ name, sha256: sha256(sql), sql });
|
|
19444
19794
|
}
|
|
19445
19795
|
const migrationsHash = sha256(migrationFiles.map((f) => `${f.name}\0${f.sha256}`).join("\n"));
|
|
@@ -19639,15 +19989,15 @@ async function runTable(db, table2, badRoles, roleChecks) {
|
|
|
19639
19989
|
cells
|
|
19640
19990
|
};
|
|
19641
19991
|
}
|
|
19642
|
-
var import_node_child_process8, import_node_crypto3,
|
|
19992
|
+
var import_node_child_process8, import_node_crypto3, import_promises30, import_node_net, import_node_path37, import_node_util6, NON_AUTHORITATIVE_LABEL, PGLITE_INSTALL_HINT, ENV_ALLOWLIST, PERMISSION_DENIED, RLS_REFUSAL, DEFAULT_TIMEOUTS, RlsInputError, normalise, quoteIdent2, firstLine2, plural3, NUMBERS, ACTOR_SESSION, changedRows, isRlsRefusal, isPrivilegeRefusal, SELF, PROBE_EXCLUSIONS, SEED_HINTS;
|
|
19643
19993
|
var init_rlsRunner = __esm({
|
|
19644
19994
|
"src/rls/rlsRunner.ts"() {
|
|
19645
19995
|
"use strict";
|
|
19646
19996
|
import_node_child_process8 = require("node:child_process");
|
|
19647
19997
|
import_node_crypto3 = require("node:crypto");
|
|
19648
|
-
|
|
19998
|
+
import_promises30 = require("node:fs/promises");
|
|
19649
19999
|
import_node_net = __toESM(require("node:net"));
|
|
19650
|
-
|
|
20000
|
+
import_node_path37 = require("node:path");
|
|
19651
20001
|
import_node_util6 = require("node:util");
|
|
19652
20002
|
init_safeGit();
|
|
19653
20003
|
init_permissionsMatrix();
|
|
@@ -20475,7 +20825,7 @@ function buildMissionCards(artifact, providers) {
|
|
|
20475
20825
|
};
|
|
20476
20826
|
}
|
|
20477
20827
|
function projectNameFromPath(pathValue) {
|
|
20478
|
-
return (0,
|
|
20828
|
+
return (0, import_node_path38.basename)(pathValue.replace(/[\\/]$/, "")) || "current repo";
|
|
20479
20829
|
}
|
|
20480
20830
|
function gapSearchText(gap) {
|
|
20481
20831
|
return [
|
|
@@ -20666,7 +21016,7 @@ function mapProvider(template, artifact, projectName) {
|
|
|
20666
21016
|
const gaps = providerGaps(artifact, template.id);
|
|
20667
21017
|
const primaryGap2 = gaps[0];
|
|
20668
21018
|
const state = providerState(gaps);
|
|
20669
|
-
const launchGateClear = artifact.gaps
|
|
21019
|
+
const launchGateClear = gateStatusForGaps(artifact.gaps) === "clear";
|
|
20670
21020
|
const launchPath = template.items.map((item4, index) => ({
|
|
20671
21021
|
...item4,
|
|
20672
21022
|
state: itemState(primaryGap2, index, item4, launchGateClear),
|
|
@@ -20875,8 +21225,9 @@ function mapArtifactToLocalUiState(artifact, presentProviderIds) {
|
|
|
20875
21225
|
scannedAt: artifact.scannedAt
|
|
20876
21226
|
},
|
|
20877
21227
|
gate: {
|
|
20878
|
-
|
|
20879
|
-
|
|
21228
|
+
// The same rule as gate-result.json, so the Studio never shows a different verdict.
|
|
21229
|
+
status: gateStatusForGaps(artifact.gaps),
|
|
21230
|
+
label: GATE_LABEL[gateStatusForGaps(artifact.gaps)],
|
|
20880
21231
|
score: artifact.score,
|
|
20881
21232
|
productionCorePercent: artifact.productionCorePercent
|
|
20882
21233
|
},
|
|
@@ -20886,25 +21237,31 @@ function mapArtifactToLocalUiState(artifact, presentProviderIds) {
|
|
|
20886
21237
|
selectedProviderId: selectedProvider.id,
|
|
20887
21238
|
currentPrompt: selectedProvider.nextFix?.prompt ?? "",
|
|
20888
21239
|
artifacts: {
|
|
20889
|
-
tasklist: (0,
|
|
20890
|
-
contextMap: (0,
|
|
20891
|
-
gateResult: (0,
|
|
20892
|
-
lastScan: (0,
|
|
21240
|
+
tasklist: (0, import_node_path38.join)(".viberaven", "agent-tasklist.md"),
|
|
21241
|
+
contextMap: (0, import_node_path38.join)(".viberaven", "context-map.json"),
|
|
21242
|
+
gateResult: (0, import_node_path38.join)(".viberaven", "gate-result.json"),
|
|
21243
|
+
lastScan: (0, import_node_path38.join)(".viberaven", "last-scan.json")
|
|
20893
21244
|
},
|
|
20894
21245
|
empty: false
|
|
20895
21246
|
};
|
|
20896
21247
|
}
|
|
20897
|
-
var
|
|
21248
|
+
var import_node_path38, GATE_LABEL, CONNECT_PROVIDER_PRIORITY, providerDashboardUrls, providerHints, PROVIDER_OWNED_GAP;
|
|
20898
21249
|
var init_artifactAdapter = __esm({
|
|
20899
21250
|
"src/local-ui/artifactAdapter.ts"() {
|
|
20900
21251
|
"use strict";
|
|
20901
|
-
|
|
21252
|
+
import_node_path38 = require("node:path");
|
|
20902
21253
|
init_providerLogos();
|
|
20903
21254
|
init_buildTaskList();
|
|
20904
21255
|
init_prompts();
|
|
20905
21256
|
init_providerLaunchPaths();
|
|
20906
21257
|
init_launchRunway();
|
|
20907
21258
|
init_providerGrade();
|
|
21259
|
+
init_gateResult();
|
|
21260
|
+
GATE_LABEL = {
|
|
21261
|
+
clear: "No blockers in repo checks",
|
|
21262
|
+
warning: "Warnings to review",
|
|
21263
|
+
not_clear: "Gate not clear"
|
|
21264
|
+
};
|
|
20908
21265
|
CONNECT_PROVIDER_PRIORITY = ["supabase", "vercel", "stripe"];
|
|
20909
21266
|
providerDashboardUrls = {
|
|
20910
21267
|
supabase: "https://supabase.com/dashboard/projects",
|
|
@@ -21201,18 +21558,18 @@ var init_planLimits = __esm({
|
|
|
21201
21558
|
// src/hosted/credentials.ts
|
|
21202
21559
|
function defaultConfigDir(env = process.env, platform = process.platform) {
|
|
21203
21560
|
const override = env.VIBERAVEN_CONFIG_DIR?.trim();
|
|
21204
|
-
if (override) return (0,
|
|
21561
|
+
if (override) return (0, import_node_path39.resolve)(override);
|
|
21205
21562
|
if (platform === "win32") {
|
|
21206
|
-
return (0,
|
|
21563
|
+
return (0, import_node_path39.join)(env.APPDATA?.trim() || (0, import_node_path39.join)((0, import_node_os2.homedir)(), "AppData", "Roaming"), "viberaven");
|
|
21207
21564
|
}
|
|
21208
21565
|
if (platform === "darwin") {
|
|
21209
|
-
return (0,
|
|
21566
|
+
return (0, import_node_path39.join)((0, import_node_os2.homedir)(), "Library", "Application Support", "viberaven");
|
|
21210
21567
|
}
|
|
21211
|
-
return (0,
|
|
21568
|
+
return (0, import_node_path39.join)(env.XDG_CONFIG_HOME?.trim() || (0, import_node_path39.join)((0, import_node_os2.homedir)(), ".config"), "viberaven");
|
|
21212
21569
|
}
|
|
21213
21570
|
function isInside(child, parent) {
|
|
21214
|
-
const rel = (0,
|
|
21215
|
-
return rel === "" || !rel.startsWith("..") && !(0,
|
|
21571
|
+
const rel = (0, import_node_path39.relative)((0, import_node_path39.resolve)(parent), (0, import_node_path39.resolve)(child));
|
|
21572
|
+
return rel === "" || !rel.startsWith("..") && !(0, import_node_path39.isAbsolute)(rel);
|
|
21216
21573
|
}
|
|
21217
21574
|
async function retryTransient(work) {
|
|
21218
21575
|
for (let attempt = 1; ; attempt += 1) {
|
|
@@ -21225,15 +21582,15 @@ async function retryTransient(work) {
|
|
|
21225
21582
|
}
|
|
21226
21583
|
}
|
|
21227
21584
|
}
|
|
21228
|
-
var import_node_child_process9, import_node_crypto4,
|
|
21585
|
+
var import_node_child_process9, import_node_crypto4, import_promises31, import_node_os2, import_node_path39, CREDENTIALS_FILE_NAME, CredentialLocationError, CredentialPermissionError, restrictWithIcacls, TRANSIENT_FS_CODES, FS_ATTEMPTS, FS_BACKOFF_MS, CredentialStore;
|
|
21229
21586
|
var init_credentials = __esm({
|
|
21230
21587
|
"src/hosted/credentials.ts"() {
|
|
21231
21588
|
"use strict";
|
|
21232
21589
|
import_node_child_process9 = require("node:child_process");
|
|
21233
21590
|
import_node_crypto4 = require("node:crypto");
|
|
21234
|
-
|
|
21591
|
+
import_promises31 = require("node:fs/promises");
|
|
21235
21592
|
import_node_os2 = require("node:os");
|
|
21236
|
-
|
|
21593
|
+
import_node_path39 = require("node:path");
|
|
21237
21594
|
CREDENTIALS_FILE_NAME = "credentials.json";
|
|
21238
21595
|
CredentialLocationError = class extends Error {
|
|
21239
21596
|
};
|
|
@@ -21260,9 +21617,9 @@ var init_credentials = __esm({
|
|
|
21260
21617
|
constructor(configDir, workspacePath, options = {}) {
|
|
21261
21618
|
this.configDir = configDir;
|
|
21262
21619
|
this.workspacePath = workspacePath;
|
|
21263
|
-
this.path = (0,
|
|
21620
|
+
this.path = (0, import_node_path39.join)(configDir, CREDENTIALS_FILE_NAME);
|
|
21264
21621
|
this.restrict = options.restrict !== void 0 ? options.restrict : process.platform === "win32" ? restrictWithIcacls : null;
|
|
21265
|
-
this.fs = { readFile: (path, encoding) => (0,
|
|
21622
|
+
this.fs = { readFile: (path, encoding) => (0, import_promises31.readFile)(path, encoding), rename: (from, to) => (0, import_promises31.rename)(from, to), rm: (path) => (0, import_promises31.rm)(path, { force: true }), ...options.fs };
|
|
21266
21623
|
}
|
|
21267
21624
|
path;
|
|
21268
21625
|
restrict;
|
|
@@ -21311,15 +21668,15 @@ var init_credentials = __esm({
|
|
|
21311
21668
|
`Refusing to store the VibeRaven sign-in inside this project (${this.configDir}). Set VIBERAVEN_CONFIG_DIR to a folder outside the repo.`
|
|
21312
21669
|
);
|
|
21313
21670
|
}
|
|
21314
|
-
await (0,
|
|
21671
|
+
await (0, import_promises31.mkdir)(this.configDir, { recursive: true, mode: 448 });
|
|
21315
21672
|
const temp = `${this.path}.${(0, import_node_crypto4.randomUUID)()}.tmp`;
|
|
21316
|
-
await (0,
|
|
21673
|
+
await (0, import_promises31.writeFile)(temp, `${JSON.stringify(body, null, 2)}
|
|
21317
21674
|
`, { encoding: "utf8", mode: 384 });
|
|
21318
|
-
await (0,
|
|
21675
|
+
await (0, import_promises31.chmod)(temp, 384).catch(() => void 0);
|
|
21319
21676
|
try {
|
|
21320
21677
|
if (this.restrict) await this.restrict(temp);
|
|
21321
21678
|
} catch (error) {
|
|
21322
|
-
await (0,
|
|
21679
|
+
await (0, import_promises31.rm)(temp, { force: true });
|
|
21323
21680
|
const code = error?.code;
|
|
21324
21681
|
const toolMissing = code === "ENOENT";
|
|
21325
21682
|
throw new CredentialPermissionError(
|
|
@@ -21330,17 +21687,17 @@ var init_credentials = __esm({
|
|
|
21330
21687
|
if (guard) {
|
|
21331
21688
|
const onDisk = await this.readFor(guard.apiBaseUrl);
|
|
21332
21689
|
if (onDisk?.accessToken !== guard.accessToken || guard.isCurrent && !guard.isCurrent()) {
|
|
21333
|
-
await (0,
|
|
21690
|
+
await (0, import_promises31.rm)(temp, { force: true });
|
|
21334
21691
|
return false;
|
|
21335
21692
|
}
|
|
21336
21693
|
}
|
|
21337
21694
|
try {
|
|
21338
21695
|
await retryTransient(() => this.fs.rename(temp, this.path));
|
|
21339
21696
|
} catch (error) {
|
|
21340
|
-
await (0,
|
|
21697
|
+
await (0, import_promises31.rm)(temp, { force: true });
|
|
21341
21698
|
throw error;
|
|
21342
21699
|
}
|
|
21343
|
-
await (0,
|
|
21700
|
+
await (0, import_promises31.chmod)(this.path, 384).catch(() => void 0);
|
|
21344
21701
|
return true;
|
|
21345
21702
|
}
|
|
21346
21703
|
/** Keeps the stored plan label in step with what the API last said. */
|
|
@@ -21709,7 +22066,7 @@ async function buildHostedCheckPayload(workspacePath) {
|
|
|
21709
22066
|
throw new Error("Could not assemble the full check request.");
|
|
21710
22067
|
}
|
|
21711
22068
|
function finalizePayload(payload) {
|
|
21712
|
-
const folder = (0,
|
|
22069
|
+
const folder = (0, import_node_path40.basename)(payload.workspacePath.split("\\").join("/").replace(/\/+$/, "")) || "project";
|
|
21713
22070
|
const redacted = redactPayload({ ...payload, workspacePath: folder });
|
|
21714
22071
|
return { payload: redacted.payload, redactions: redacted.count };
|
|
21715
22072
|
}
|
|
@@ -21740,13 +22097,13 @@ function splitSections(prompt) {
|
|
|
21740
22097
|
chars: section.length
|
|
21741
22098
|
}));
|
|
21742
22099
|
}
|
|
21743
|
-
var
|
|
22100
|
+
var import_node_path40, PayloadCaptured;
|
|
21744
22101
|
var init_payload = __esm({
|
|
21745
22102
|
"src/hosted/payload.ts"() {
|
|
21746
22103
|
"use strict";
|
|
21747
22104
|
init_fileScanner();
|
|
21748
22105
|
init_orchestrator();
|
|
21749
|
-
|
|
22106
|
+
import_node_path40 = require("node:path");
|
|
21750
22107
|
init_config();
|
|
21751
22108
|
init_redact();
|
|
21752
22109
|
PayloadCaptured = class extends Error {
|
|
@@ -22212,10 +22569,10 @@ async function connectProviderMcp(cwd, providerId) {
|
|
|
22212
22569
|
if (!recipe) {
|
|
22213
22570
|
return { ok: false, message: `No known MCP server for ${providerId} yet. Add one manually to .mcp.json.` };
|
|
22214
22571
|
}
|
|
22215
|
-
const configPath = (0,
|
|
22572
|
+
const configPath = (0, import_node_path41.join)(cwd, ".mcp.json");
|
|
22216
22573
|
let config = {};
|
|
22217
22574
|
try {
|
|
22218
|
-
const raw = await (0,
|
|
22575
|
+
const raw = await (0, import_promises32.readFile)(configPath, "utf8");
|
|
22219
22576
|
const parsed = JSON.parse(raw.replace(/^\uFEFF/, ""));
|
|
22220
22577
|
if (!isRecord5(parsed) || parsed.mcpServers !== void 0 && !isRecord5(parsed.mcpServers)) {
|
|
22221
22578
|
return { ok: false, message: "Existing .mcp.json has an unsupported structure. It was left unchanged." };
|
|
@@ -22232,7 +22589,7 @@ async function connectProviderMcp(cwd, providerId) {
|
|
|
22232
22589
|
}
|
|
22233
22590
|
servers[providerId] = recipe.entry;
|
|
22234
22591
|
const next = { ...config, mcpServers: servers };
|
|
22235
|
-
await (0,
|
|
22592
|
+
await (0, import_promises32.writeFile)(configPath, `${JSON.stringify(next, null, 2)}
|
|
22236
22593
|
`, "utf8");
|
|
22237
22594
|
const suffix = recipe.note ? ` ${recipe.note}` : "";
|
|
22238
22595
|
return { ok: true, message: `Added ${providerId} MCP server to .mcp.json.${suffix}`, path: ".mcp.json" };
|
|
@@ -22285,7 +22642,7 @@ async function defaultScanRunner(flags, positional) {
|
|
|
22285
22642
|
}
|
|
22286
22643
|
async function readPackageJson(cwd) {
|
|
22287
22644
|
try {
|
|
22288
|
-
const raw = await (0,
|
|
22645
|
+
const raw = await (0, import_promises32.readFile)((0, import_node_path41.join)(cwd, "package.json"), "utf8");
|
|
22289
22646
|
const parsed = JSON.parse(raw.replace(/^\uFEFF/, ""));
|
|
22290
22647
|
return isRecord5(parsed) ? parsed : {};
|
|
22291
22648
|
} catch {
|
|
@@ -22308,7 +22665,7 @@ async function listProjectFiles(cwd, maxFiles = 1800) {
|
|
|
22308
22665
|
if (files.length >= maxFiles) return;
|
|
22309
22666
|
let entries;
|
|
22310
22667
|
try {
|
|
22311
|
-
entries = await (0,
|
|
22668
|
+
entries = await (0, import_promises32.readdir)(dir, { withFileTypes: true });
|
|
22312
22669
|
} catch {
|
|
22313
22670
|
return;
|
|
22314
22671
|
}
|
|
@@ -22316,7 +22673,7 @@ async function listProjectFiles(cwd, maxFiles = 1800) {
|
|
|
22316
22673
|
if (files.length >= maxFiles) return;
|
|
22317
22674
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
22318
22675
|
if (entry.isDirectory()) {
|
|
22319
|
-
if (!skipped.has(entry.name)) await walk((0,
|
|
22676
|
+
if (!skipped.has(entry.name)) await walk((0, import_node_path41.join)(dir, entry.name), rel);
|
|
22320
22677
|
continue;
|
|
22321
22678
|
}
|
|
22322
22679
|
if (entry.isFile()) files.push(rel.toLowerCase());
|
|
@@ -22335,7 +22692,7 @@ async function readEnvKeys(cwd) {
|
|
|
22335
22692
|
const keys = /* @__PURE__ */ new Set();
|
|
22336
22693
|
for (const name of [".env.example", ".env"]) {
|
|
22337
22694
|
try {
|
|
22338
|
-
const raw = await (0,
|
|
22695
|
+
const raw = await (0, import_promises32.readFile)((0, import_node_path41.join)(cwd, name), "utf8");
|
|
22339
22696
|
for (const line of raw.split(/\r?\n/)) {
|
|
22340
22697
|
const trimmed = line.trim();
|
|
22341
22698
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -22653,7 +23010,7 @@ async function codexModelOptions() {
|
|
|
22653
23010
|
{ id: "gpt-5.4-mini", label: "GPT-5.4 Mini" }
|
|
22654
23011
|
];
|
|
22655
23012
|
try {
|
|
22656
|
-
const raw = await (0,
|
|
23013
|
+
const raw = await (0, import_promises32.readFile)((0, import_node_path41.join)((0, import_node_os3.homedir)(), ".codex", "models_cache.json"), "utf8");
|
|
22657
23014
|
const parsed = JSON.parse(raw);
|
|
22658
23015
|
const list = Array.isArray(parsed) ? parsed : parsed.models ?? [];
|
|
22659
23016
|
const options = list.filter((model) => typeof model?.slug === "string").filter((model) => !/auto-review|reserve/i.test(model.slug)).map((model) => ({ id: model.slug, label: model.display_name?.trim() || model.slug }));
|
|
@@ -22856,19 +23213,19 @@ function isPlaceholderProjectName(value) {
|
|
|
22856
23213
|
async function readMcpEvidence(cwd) {
|
|
22857
23214
|
const candidates = MCP_CONFIG_PATHS.map((relativePath) => ({
|
|
22858
23215
|
source: relativePath.replace(/\\/g, "/"),
|
|
22859
|
-
path: (0,
|
|
23216
|
+
path: (0, import_node_path41.resolve)(cwd, relativePath)
|
|
22860
23217
|
}));
|
|
22861
23218
|
const home = process.env.USERPROFILE || process.env.HOME;
|
|
22862
23219
|
if (home) {
|
|
22863
23220
|
candidates.push({
|
|
22864
23221
|
source: "~/.codex/config.toml",
|
|
22865
|
-
path: (0,
|
|
23222
|
+
path: (0, import_node_path41.resolve)(home, ".codex", "config.toml")
|
|
22866
23223
|
});
|
|
22867
23224
|
}
|
|
22868
23225
|
const evidence = [];
|
|
22869
23226
|
for (const candidate of candidates) {
|
|
22870
23227
|
try {
|
|
22871
|
-
const text = await (0,
|
|
23228
|
+
const text = await (0, import_promises32.readFile)(candidate.path, "utf8");
|
|
22872
23229
|
if (/mcp/i.test(text)) evidence.push({ source: candidate.source, text });
|
|
22873
23230
|
} catch {
|
|
22874
23231
|
}
|
|
@@ -22959,7 +23316,7 @@ async function enrichProjectMetadata(state, cwd) {
|
|
|
22959
23316
|
async function readState(cwd) {
|
|
22960
23317
|
let state;
|
|
22961
23318
|
try {
|
|
22962
|
-
const raw = await (0,
|
|
23319
|
+
const raw = await (0, import_promises32.readFile)((0, import_node_path41.join)(cwd, ".viberaven", "last-scan.json"), "utf8");
|
|
22963
23320
|
const packageJson = await readPackageJson(cwd);
|
|
22964
23321
|
const deps = dependencyNames(packageJson);
|
|
22965
23322
|
const files = await listProjectFiles(cwd);
|
|
@@ -23226,7 +23583,7 @@ async function whereExe(command, cwd) {
|
|
|
23226
23583
|
}
|
|
23227
23584
|
function expandShimPath(value, base) {
|
|
23228
23585
|
const relative8 = value.replace(/^%(?:dp0%\\+|~dp0\\*)/i, "");
|
|
23229
|
-
return relative8 === value ? value : (0,
|
|
23586
|
+
return relative8 === value ? value : (0, import_node_path41.join)(base, ...relative8.split(/[\\/]+/));
|
|
23230
23587
|
}
|
|
23231
23588
|
function findShimTarget(lines, pattern, accept = () => true) {
|
|
23232
23589
|
for (const line of lines) {
|
|
@@ -23237,21 +23594,21 @@ function findShimTarget(lines, pattern, accept = () => true) {
|
|
|
23237
23594
|
}
|
|
23238
23595
|
async function resolveWindowsShimTarget(shimPath) {
|
|
23239
23596
|
try {
|
|
23240
|
-
const content = await (0,
|
|
23241
|
-
const base = (0,
|
|
23597
|
+
const content = await (0, import_promises32.readFile)(shimPath, "utf8");
|
|
23598
|
+
const base = (0, import_node_path41.dirname)(shimPath);
|
|
23242
23599
|
const lines = content.split(/\r?\n/);
|
|
23243
23600
|
const trailingArgs = (line, after) => [...line.slice(after).split("%*")[0].matchAll(/"([^"]*)"|([^\s"&|<>]+)/g)].map((token) => expandShimPath(token[1] ?? token[2], base)).filter((value) => value.length > 0 && !value.includes("%"));
|
|
23244
23601
|
const script = findShimTarget(lines, /"%(?:dp0%\\+|~dp0\\*)([^"]+\.js)"/i);
|
|
23245
23602
|
if (script) {
|
|
23246
23603
|
return {
|
|
23247
23604
|
command: process.execPath,
|
|
23248
|
-
args: [(0,
|
|
23605
|
+
args: [(0, import_node_path41.join)(base, ...script.match[1].split(/[\\/]+/)), ...trailingArgs(script.line, script.match.index + script.match[0].length)]
|
|
23249
23606
|
};
|
|
23250
23607
|
}
|
|
23251
|
-
const binary = findShimTarget(lines, /"%(?:dp0%\\+|~dp0\\*)([^"]+\.exe)"/i, (target) => (0,
|
|
23608
|
+
const binary = findShimTarget(lines, /"%(?:dp0%\\+|~dp0\\*)([^"]+\.exe)"/i, (target) => (0, import_node_path41.basename)(target).toLowerCase() !== "node.exe");
|
|
23252
23609
|
if (binary) {
|
|
23253
23610
|
return {
|
|
23254
|
-
command: (0,
|
|
23611
|
+
command: (0, import_node_path41.join)(base, ...binary.match[1].split(/[\\/]+/)),
|
|
23255
23612
|
args: trailingArgs(binary.line, binary.match.index + binary.match[0].length)
|
|
23256
23613
|
};
|
|
23257
23614
|
}
|
|
@@ -23376,8 +23733,8 @@ async function writeChatContextArtifact(cwd, request, prompt) {
|
|
|
23376
23733
|
"",
|
|
23377
23734
|
prompt
|
|
23378
23735
|
].filter((line) => typeof line === "string");
|
|
23379
|
-
await (0,
|
|
23380
|
-
await (0,
|
|
23736
|
+
await (0, import_promises32.mkdir)((0, import_node_path41.join)(cwd, ".viberaven"), { recursive: true });
|
|
23737
|
+
await (0, import_promises32.writeFile)((0, import_node_path41.join)(cwd, ".viberaven", "chat-context.md"), `${lines.join("\n")}
|
|
23381
23738
|
`, "utf8");
|
|
23382
23739
|
} catch {
|
|
23383
23740
|
}
|
|
@@ -23397,13 +23754,13 @@ async function runAgentChat(cwd, request) {
|
|
|
23397
23754
|
}
|
|
23398
23755
|
const prompt = await buildAgentChatPrompt(request, cwd);
|
|
23399
23756
|
await writeChatContextArtifact(cwd, request, prompt);
|
|
23400
|
-
const outputPath = request.cliId === "codex" ? (0,
|
|
23401
|
-
if (outputPath) await (0,
|
|
23757
|
+
const outputPath = request.cliId === "codex" ? (0, import_node_path41.join)(cwd, ".viberaven", `studio-agent-${Date.now()}-${Math.random().toString(36).slice(2)}.md`) : void 0;
|
|
23758
|
+
if (outputPath) await (0, import_promises32.mkdir)((0, import_node_path41.dirname)(outputPath), { recursive: true });
|
|
23402
23759
|
const { command, args, stdin } = commandForAgentChat(request, prompt, cwd, outputPath);
|
|
23403
23760
|
const result = await runAgentCommand(command, args, cwd, stdin, request.runId);
|
|
23404
23761
|
if (outputPath) {
|
|
23405
23762
|
try {
|
|
23406
|
-
const finalMessage = (await (0,
|
|
23763
|
+
const finalMessage = (await (0, import_promises32.readFile)(outputPath, "utf8")).trim();
|
|
23407
23764
|
if (finalMessage) return { ...result, output: finalMessage };
|
|
23408
23765
|
} catch {
|
|
23409
23766
|
}
|
|
@@ -23415,8 +23772,8 @@ function firstGapId(state) {
|
|
|
23415
23772
|
return state.providers.find((provider2) => provider2.nextFix?.id)?.nextFix?.id;
|
|
23416
23773
|
}
|
|
23417
23774
|
async function runLocalAction(cwd, intent) {
|
|
23418
|
-
const artifactDir = (0,
|
|
23419
|
-
await (0,
|
|
23775
|
+
const artifactDir = (0, import_node_path41.join)(cwd, ".viberaven");
|
|
23776
|
+
await (0, import_promises32.mkdir)(artifactDir, { recursive: true });
|
|
23420
23777
|
if (intent === "preview_rehearsal") {
|
|
23421
23778
|
const state2 = await readState(cwd);
|
|
23422
23779
|
const topProvider = state2.providers[0];
|
|
@@ -23457,7 +23814,7 @@ async function runLocalAction(cwd, intent) {
|
|
|
23457
23814
|
proof,
|
|
23458
23815
|
""
|
|
23459
23816
|
].join("\n");
|
|
23460
|
-
await (0,
|
|
23817
|
+
await (0, import_promises32.writeFile)((0, import_node_path41.join)(artifactDir, "preview-rehearsal.md"), markdown, "utf8");
|
|
23461
23818
|
return {
|
|
23462
23819
|
title: "Preview rehearsal ready",
|
|
23463
23820
|
summary: `${projectName}: ${gateLabel} with ${state2.providers.length} provider beat${state2.providers.length === 1 ? "" : "s"}`,
|
|
@@ -23467,7 +23824,7 @@ async function runLocalAction(cwd, intent) {
|
|
|
23467
23824
|
if (intent === "audit_vercel_supabase") {
|
|
23468
23825
|
const auditInput = await collectVercelSupabaseAuditInput(cwd);
|
|
23469
23826
|
const result2 = buildVercelSupabaseAudit(auditInput);
|
|
23470
|
-
await (0,
|
|
23827
|
+
await (0, import_promises32.writeFile)((0, import_node_path41.join)(artifactDir, "audit-vercel-supabase.txt"), `${renderVercelSupabaseAudit(result2)}
|
|
23471
23828
|
`, "utf8");
|
|
23472
23829
|
return {
|
|
23473
23830
|
title: result2.status === "pass" ? "Audit passed" : "Audit needs work",
|
|
@@ -23495,7 +23852,7 @@ async function runLocalAction(cwd, intent) {
|
|
|
23495
23852
|
const mode = intent === "heal_prompt" ? "prompt" : intent === "heal_apply" ? "apply" : "plan";
|
|
23496
23853
|
const result = await runHealCommand({ cwd, mode, gapId, yes: mode === "apply", noVerify: true });
|
|
23497
23854
|
if (mode === "apply") {
|
|
23498
|
-
await (0,
|
|
23855
|
+
await (0, import_promises32.writeFile)((0, import_node_path41.join)(artifactDir, "heal-apply-result.json"), `${JSON.stringify(result, null, 2)}
|
|
23499
23856
|
`, "utf8");
|
|
23500
23857
|
}
|
|
23501
23858
|
return {
|
|
@@ -23505,14 +23862,14 @@ async function runLocalAction(cwd, intent) {
|
|
|
23505
23862
|
};
|
|
23506
23863
|
}
|
|
23507
23864
|
async function sendArtifact(cwd, rel, response, contentType = "text/plain; charset=utf-8") {
|
|
23508
|
-
const absolute = (0,
|
|
23509
|
-
const root = (0,
|
|
23865
|
+
const absolute = (0, import_node_path41.resolve)(cwd, rel);
|
|
23866
|
+
const root = (0, import_node_path41.resolve)(cwd);
|
|
23510
23867
|
if (!absolute.startsWith(root)) {
|
|
23511
23868
|
sendText(response, 403, "Forbidden");
|
|
23512
23869
|
return;
|
|
23513
23870
|
}
|
|
23514
23871
|
try {
|
|
23515
|
-
const text = await (0,
|
|
23872
|
+
const text = await (0, import_promises32.readFile)(absolute, "utf8");
|
|
23516
23873
|
response.writeHead(200, { "content-type": contentType });
|
|
23517
23874
|
response.end(text);
|
|
23518
23875
|
} catch {
|
|
@@ -23521,7 +23878,7 @@ async function sendArtifact(cwd, rel, response, contentType = "text/plain; chars
|
|
|
23521
23878
|
}
|
|
23522
23879
|
async function sendReportArtifact(cwd, response) {
|
|
23523
23880
|
try {
|
|
23524
|
-
const text = await (0,
|
|
23881
|
+
const text = await (0, import_promises32.readFile)((0, import_node_path41.join)(cwd, ".viberaven", "report.html"), "utf8");
|
|
23525
23882
|
response.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
|
23526
23883
|
response.end(text);
|
|
23527
23884
|
return;
|
|
@@ -23648,7 +24005,7 @@ async function sendReportArtifact(cwd, response) {
|
|
|
23648
24005
|
}
|
|
23649
24006
|
async function sendExtensionIcon(cwd, response) {
|
|
23650
24007
|
try {
|
|
23651
|
-
const body = await (0,
|
|
24008
|
+
const body = await (0, import_promises32.readFile)((0, import_node_path41.join)(cwd, "media", "extension-icon.png"));
|
|
23652
24009
|
sendBinary(response, 200, "image/png", body);
|
|
23653
24010
|
} catch {
|
|
23654
24011
|
sendText(response, 404, "Icon not found");
|
|
@@ -23661,15 +24018,15 @@ async function sendMangaAsset(pathname, response) {
|
|
|
23661
24018
|
return;
|
|
23662
24019
|
}
|
|
23663
24020
|
const candidates = [
|
|
23664
|
-
(0,
|
|
24021
|
+
(0, import_node_path41.join)(__dirname, "manga", name),
|
|
23665
24022
|
// installed + dev: <pkg>/dist/manga
|
|
23666
|
-
(0,
|
|
24023
|
+
(0, import_node_path41.join)(__dirname, "..", "assets", "manga", name),
|
|
23667
24024
|
// fallback: <pkg>/assets/manga (source)
|
|
23668
|
-
(0,
|
|
24025
|
+
(0, import_node_path41.join)(__dirname, "..", "..", "assets", "manga", name)
|
|
23669
24026
|
];
|
|
23670
24027
|
for (const candidate of candidates) {
|
|
23671
24028
|
try {
|
|
23672
|
-
const body = await (0,
|
|
24029
|
+
const body = await (0, import_promises32.readFile)(candidate);
|
|
23673
24030
|
response.setHeader("cache-control", "no-cache");
|
|
23674
24031
|
sendBinary(response, 200, contentTypeForAsset(candidate), body);
|
|
23675
24032
|
return;
|
|
@@ -23679,7 +24036,7 @@ async function sendMangaAsset(pathname, response) {
|
|
|
23679
24036
|
sendText(response, 404, "Asset not found");
|
|
23680
24037
|
}
|
|
23681
24038
|
function contentTypeForAsset(pathname) {
|
|
23682
|
-
switch ((0,
|
|
24039
|
+
switch ((0, import_node_path41.extname)(pathname).toLowerCase()) {
|
|
23683
24040
|
case ".svg":
|
|
23684
24041
|
return "image/svg+xml; charset=utf-8";
|
|
23685
24042
|
case ".png":
|
|
@@ -23696,14 +24053,14 @@ function contentTypeForAsset(pathname) {
|
|
|
23696
24053
|
}
|
|
23697
24054
|
async function sendBundledReportAsset(pathname, response) {
|
|
23698
24055
|
const rel = decodeURIComponent(pathname.replace(/^\/report\//, ""));
|
|
23699
|
-
const assetRoot = (0,
|
|
23700
|
-
const absolute = (0,
|
|
24056
|
+
const assetRoot = (0, import_node_path41.resolve)(getBundledReportAssetsDir());
|
|
24057
|
+
const absolute = (0, import_node_path41.resolve)(assetRoot, rel);
|
|
23701
24058
|
if (!absolute.startsWith(assetRoot)) {
|
|
23702
24059
|
sendText(response, 403, "Forbidden");
|
|
23703
24060
|
return;
|
|
23704
24061
|
}
|
|
23705
24062
|
try {
|
|
23706
|
-
const body = await (0,
|
|
24063
|
+
const body = await (0, import_promises32.readFile)(absolute);
|
|
23707
24064
|
sendBinary(response, 200, contentTypeForAsset(absolute), body);
|
|
23708
24065
|
} catch {
|
|
23709
24066
|
sendText(response, 404, "Asset not found");
|
|
@@ -23725,18 +24082,18 @@ async function bundleStackClient(entryPath) {
|
|
|
23725
24082
|
return output.text;
|
|
23726
24083
|
}
|
|
23727
24084
|
async function sendStackAppJs(response) {
|
|
23728
|
-
const distPath = (0,
|
|
24085
|
+
const distPath = (0, import_node_path41.join)(__dirname, "stack", "app.js");
|
|
23729
24086
|
try {
|
|
23730
|
-
const body = await (0,
|
|
24087
|
+
const body = await (0, import_promises32.readFile)(distPath);
|
|
23731
24088
|
response.writeHead(200, { "content-type": "application/javascript; charset=utf-8", "cache-control": "no-store" });
|
|
23732
24089
|
response.end(body);
|
|
23733
24090
|
return;
|
|
23734
24091
|
} catch {
|
|
23735
24092
|
}
|
|
23736
|
-
const entryPath = (0,
|
|
24093
|
+
const entryPath = (0, import_node_path41.join)(__dirname, "stack", "main.ts");
|
|
23737
24094
|
let mtimeMs;
|
|
23738
24095
|
try {
|
|
23739
|
-
mtimeMs = (await (0,
|
|
24096
|
+
mtimeMs = (await (0, import_promises32.stat)(entryPath)).mtimeMs;
|
|
23740
24097
|
} catch {
|
|
23741
24098
|
sendText(response, 404, "Stack client entry not found: src/local-ui/stack/main.ts is missing.");
|
|
23742
24099
|
return;
|
|
@@ -23755,7 +24112,7 @@ async function sendStackAppJs(response) {
|
|
|
23755
24112
|
}
|
|
23756
24113
|
async function sendStackAppCss(response) {
|
|
23757
24114
|
try {
|
|
23758
|
-
const body = await (0,
|
|
24115
|
+
const body = await (0, import_promises32.readFile)((0, import_node_path41.join)(__dirname, "stack", "stack.css"));
|
|
23759
24116
|
response.writeHead(200, { "content-type": "text/css; charset=utf-8", "cache-control": "no-store" });
|
|
23760
24117
|
response.end(body);
|
|
23761
24118
|
} catch {
|
|
@@ -23764,7 +24121,7 @@ async function sendStackAppCss(response) {
|
|
|
23764
24121
|
}
|
|
23765
24122
|
async function readProviderVerifyLedger(cwd) {
|
|
23766
24123
|
try {
|
|
23767
|
-
const raw = await (0,
|
|
24124
|
+
const raw = await (0, import_promises32.readFile)((0, import_node_path41.join)(cwd, ".viberaven", "provider-verify.json"), "utf8");
|
|
23768
24125
|
const parsed = JSON.parse(raw.replace(/^\uFEFF/, ""));
|
|
23769
24126
|
return isRecord5(parsed) ? parsed : {};
|
|
23770
24127
|
} catch {
|
|
@@ -23774,8 +24131,8 @@ async function readProviderVerifyLedger(cwd) {
|
|
|
23774
24131
|
async function writeProviderVerifyEntry(cwd, providerId, entry) {
|
|
23775
24132
|
const ledger = await readProviderVerifyLedger(cwd);
|
|
23776
24133
|
ledger[providerId] = entry;
|
|
23777
|
-
await (0,
|
|
23778
|
-
await (0,
|
|
24134
|
+
await (0, import_promises32.mkdir)((0, import_node_path41.join)(cwd, ".viberaven"), { recursive: true });
|
|
24135
|
+
await (0, import_promises32.writeFile)((0, import_node_path41.join)(cwd, ".viberaven", "provider-verify.json"), `${JSON.stringify(ledger, null, 2)}
|
|
23779
24136
|
`, "utf8");
|
|
23780
24137
|
}
|
|
23781
24138
|
async function handleRequest(request, response, options) {
|
|
@@ -23848,13 +24205,13 @@ async function handleRequest(request, response, options) {
|
|
|
23848
24205
|
return;
|
|
23849
24206
|
}
|
|
23850
24207
|
if (request.method === "GET" && url.pathname === "/api/architecture-map") {
|
|
23851
|
-
const mapPath = (0,
|
|
23852
|
-
const markdown = await (0,
|
|
24208
|
+
const mapPath = (0, import_node_path41.join)(options.cwd, ".viberaven", "architecture-map.md");
|
|
24209
|
+
const markdown = await (0, import_promises32.readFile)(mapPath, "utf8").catch(() => null);
|
|
23853
24210
|
if (markdown === null) {
|
|
23854
24211
|
sendJsonStatus(response, 404, { error: "No architecture map yet. Run a scan first (it is written on every scan)." });
|
|
23855
24212
|
return;
|
|
23856
24213
|
}
|
|
23857
|
-
const dataRaw = await (0,
|
|
24214
|
+
const dataRaw = await (0, import_promises32.readFile)((0, import_node_path41.join)(options.cwd, ".viberaven", "architecture-map.json"), "utf8").catch(() => null);
|
|
23858
24215
|
let data = null;
|
|
23859
24216
|
if (dataRaw) {
|
|
23860
24217
|
try {
|
|
@@ -23863,7 +24220,7 @@ async function handleRequest(request, response, options) {
|
|
|
23863
24220
|
data = null;
|
|
23864
24221
|
}
|
|
23865
24222
|
}
|
|
23866
|
-
const contextRaw = await (0,
|
|
24223
|
+
const contextRaw = await (0, import_promises32.readFile)((0, import_node_path41.join)(options.cwd, ".viberaven", "context-map.json"), "utf8").catch(() => null);
|
|
23867
24224
|
let gaps = [];
|
|
23868
24225
|
if (contextRaw) {
|
|
23869
24226
|
try {
|
|
@@ -24129,35 +24486,35 @@ async function handleRequest(request, response, options) {
|
|
|
24129
24486
|
return;
|
|
24130
24487
|
}
|
|
24131
24488
|
if (request.method === "GET" && url.pathname === "/api/artifacts/tasklist") {
|
|
24132
|
-
await sendArtifact(options.cwd, (0,
|
|
24489
|
+
await sendArtifact(options.cwd, (0, import_node_path41.join)(".viberaven", "agent-tasklist.md"), response);
|
|
24133
24490
|
return;
|
|
24134
24491
|
}
|
|
24135
24492
|
if (request.method === "GET" && url.pathname === "/api/artifacts/playbook") {
|
|
24136
|
-
await sendArtifact(options.cwd, (0,
|
|
24493
|
+
await sendArtifact(options.cwd, (0, import_node_path41.join)(".viberaven", "launch-playbook.md"), response);
|
|
24137
24494
|
return;
|
|
24138
24495
|
}
|
|
24139
24496
|
if (request.method === "GET" && url.pathname === "/api/artifacts/audit") {
|
|
24140
|
-
await sendArtifact(options.cwd, (0,
|
|
24497
|
+
await sendArtifact(options.cwd, (0, import_node_path41.join)(".viberaven", "audit-vercel-supabase.txt"), response);
|
|
24141
24498
|
return;
|
|
24142
24499
|
}
|
|
24143
24500
|
if (request.method === "GET" && url.pathname === "/api/artifacts/cleanup") {
|
|
24144
|
-
await sendArtifact(options.cwd, (0,
|
|
24501
|
+
await sendArtifact(options.cwd, (0, import_node_path41.join)(".viberaven", "context-cleanup.md"), response);
|
|
24145
24502
|
return;
|
|
24146
24503
|
}
|
|
24147
24504
|
if (request.method === "GET" && url.pathname === "/api/artifacts/preview") {
|
|
24148
|
-
await sendArtifact(options.cwd, (0,
|
|
24505
|
+
await sendArtifact(options.cwd, (0, import_node_path41.join)(".viberaven", "preview-rehearsal.md"), response);
|
|
24149
24506
|
return;
|
|
24150
24507
|
}
|
|
24151
24508
|
if (request.method === "GET" && url.pathname === "/api/artifacts/heal-plan") {
|
|
24152
|
-
await sendArtifact(options.cwd, (0,
|
|
24509
|
+
await sendArtifact(options.cwd, (0, import_node_path41.join)(".viberaven", "heal-plan.md"), response);
|
|
24153
24510
|
return;
|
|
24154
24511
|
}
|
|
24155
24512
|
if (request.method === "GET" && url.pathname === "/api/artifacts/heal-prompt") {
|
|
24156
|
-
await sendArtifact(options.cwd, (0,
|
|
24513
|
+
await sendArtifact(options.cwd, (0, import_node_path41.join)(".viberaven", "heal-prompt.md"), response);
|
|
24157
24514
|
return;
|
|
24158
24515
|
}
|
|
24159
24516
|
if (request.method === "GET" && url.pathname === "/api/artifacts/heal-apply") {
|
|
24160
|
-
await sendArtifact(options.cwd, (0,
|
|
24517
|
+
await sendArtifact(options.cwd, (0, import_node_path41.join)(".viberaven", "heal-apply-result.json"), response, "application/json; charset=utf-8");
|
|
24161
24518
|
return;
|
|
24162
24519
|
}
|
|
24163
24520
|
if (request.method === "GET" && url.pathname === "/api/artifacts/report") {
|
|
@@ -24183,12 +24540,12 @@ async function handleRequest(request, response, options) {
|
|
|
24183
24540
|
}
|
|
24184
24541
|
if (request.method === "GET" && url.pathname === "/vendor/anime.umd.min.js") {
|
|
24185
24542
|
for (const candidate of [
|
|
24186
|
-
(0,
|
|
24187
|
-
(0,
|
|
24188
|
-
(0,
|
|
24543
|
+
(0, import_node_path41.join)(__dirname, "vendor", "anime.umd.min.js"),
|
|
24544
|
+
(0, import_node_path41.join)(__dirname, "..", "assets", "vendor", "anime.umd.min.js"),
|
|
24545
|
+
(0, import_node_path41.join)(__dirname, "..", "..", "assets", "vendor", "anime.umd.min.js")
|
|
24189
24546
|
]) {
|
|
24190
24547
|
try {
|
|
24191
|
-
const body = await (0,
|
|
24548
|
+
const body = await (0, import_promises32.readFile)(candidate);
|
|
24192
24549
|
response.setHeader("cache-control", "public, max-age=604800, immutable");
|
|
24193
24550
|
sendBinary(response, 200, "text/javascript; charset=utf-8", body);
|
|
24194
24551
|
return;
|
|
@@ -24405,7 +24762,7 @@ function listen(server, startPort) {
|
|
|
24405
24762
|
});
|
|
24406
24763
|
}
|
|
24407
24764
|
async function startLocalUiServer(options) {
|
|
24408
|
-
const cwd = (0,
|
|
24765
|
+
const cwd = (0, import_node_path41.resolve)(options.cwd);
|
|
24409
24766
|
const scanRunner = options.scanRunner ?? defaultScanRunner;
|
|
24410
24767
|
const autoScan = { state: "idle" };
|
|
24411
24768
|
const fullCheck = new FullCheckService(cwd, options.fullCheck);
|
|
@@ -24422,7 +24779,7 @@ async function startLocalUiServer(options) {
|
|
|
24422
24779
|
});
|
|
24423
24780
|
const port = await listen(server, options.port ?? 4177);
|
|
24424
24781
|
guard.port = port;
|
|
24425
|
-
const hasArtifact = await (0,
|
|
24782
|
+
const hasArtifact = await (0, import_promises32.readFile)((0, import_node_path41.join)(cwd, ".viberaven", "last-scan.json"), "utf8").then(
|
|
24426
24783
|
() => true,
|
|
24427
24784
|
() => false
|
|
24428
24785
|
);
|
|
@@ -24461,16 +24818,16 @@ async function waitForServerShutdown() {
|
|
|
24461
24818
|
process.once("SIGTERM", done);
|
|
24462
24819
|
});
|
|
24463
24820
|
}
|
|
24464
|
-
var import_node_http, import_node_child_process10, import_node_crypto6,
|
|
24821
|
+
var import_node_http, import_node_child_process10, import_node_crypto6, import_promises32, import_node_os3, import_node_path41, CLI_AGENT_SETUP, MCP_CONFIG_PATHS, MCP_PROVIDER_NEEDLES, MCP_CONNECT_COMMANDS, MCP_SERVER_RECIPES, STUDIO_TOKEN_HEADER, PROVIDER_IDS, STUDIO_STATUS_ARGS, CLI_AUTH_PROBE, AGENT_RUN_TIMEOUT_MS, activeAgentRuns, stackBundleCache;
|
|
24465
24822
|
var init_server = __esm({
|
|
24466
24823
|
"src/local-ui/server.ts"() {
|
|
24467
24824
|
"use strict";
|
|
24468
24825
|
import_node_http = require("node:http");
|
|
24469
24826
|
import_node_child_process10 = require("node:child_process");
|
|
24470
24827
|
import_node_crypto6 = require("node:crypto");
|
|
24471
|
-
|
|
24828
|
+
import_promises32 = require("node:fs/promises");
|
|
24472
24829
|
import_node_os3 = require("node:os");
|
|
24473
|
-
|
|
24830
|
+
import_node_path41 = require("node:path");
|
|
24474
24831
|
init_initGithub();
|
|
24475
24832
|
init_cleanPlan();
|
|
24476
24833
|
init_audit();
|
|
@@ -24512,8 +24869,8 @@ var init_server = __esm({
|
|
|
24512
24869
|
MCP_CONFIG_PATHS = [
|
|
24513
24870
|
".mcp.json",
|
|
24514
24871
|
"mcp.json",
|
|
24515
|
-
(0,
|
|
24516
|
-
(0,
|
|
24872
|
+
(0, import_node_path41.join)(".cursor", "mcp.json"),
|
|
24873
|
+
(0, import_node_path41.join)(".vscode", "mcp.json")
|
|
24517
24874
|
];
|
|
24518
24875
|
MCP_PROVIDER_NEEDLES = {
|
|
24519
24876
|
supabase: ["supabase", "@supabase/mcp", "mcp-server-supabase"],
|
|
@@ -24595,6 +24952,7 @@ function buildNextActionBlock(tasks, loopState) {
|
|
|
24595
24952
|
mcpTool: repoCodeTask.mcpTool,
|
|
24596
24953
|
mcpArgs: repoCodeTask.mcpArgs,
|
|
24597
24954
|
fallbackCommand: repoCodeTask.mcpArgs ? `npx -y viberaven --heal --apply --gap ${repoCodeTask.gapId} --yes` : void 0,
|
|
24955
|
+
...whereAndAfter(repoCodeTask),
|
|
24598
24956
|
requiresUserAction: false
|
|
24599
24957
|
};
|
|
24600
24958
|
}
|
|
@@ -24608,6 +24966,7 @@ function buildNextActionBlock(tasks, loopState) {
|
|
|
24608
24966
|
mcpTool: userTask.mcpTool,
|
|
24609
24967
|
mcpArgs: userTask.mcpArgs,
|
|
24610
24968
|
fallbackCommand: userTask.mcpArgs ? `npx -y viberaven --heal --apply --gap ${userTask.gapId} --yes` : void 0,
|
|
24969
|
+
...whereAndAfter(userTask),
|
|
24611
24970
|
requiresUserAction: true
|
|
24612
24971
|
};
|
|
24613
24972
|
}
|
|
@@ -24623,10 +24982,17 @@ function buildNextActionBlock(tasks, loopState) {
|
|
|
24623
24982
|
return {
|
|
24624
24983
|
...base,
|
|
24625
24984
|
type: "done",
|
|
24626
|
-
title: "
|
|
24985
|
+
title: "No repo-code or provider tasks left; gate-result.json has the verdict",
|
|
24627
24986
|
requiresUserAction: false
|
|
24628
24987
|
};
|
|
24629
24988
|
}
|
|
24989
|
+
function whereAndAfter(task) {
|
|
24990
|
+
return {
|
|
24991
|
+
...task.file ? { file: task.file } : {},
|
|
24992
|
+
...task.line !== void 0 ? { line: task.line } : {},
|
|
24993
|
+
...task.userSteps?.length ? { userSteps: [...task.userSteps] } : {}
|
|
24994
|
+
};
|
|
24995
|
+
}
|
|
24630
24996
|
function resolveStallReason(tasks) {
|
|
24631
24997
|
if (tasks.length === 0) return "no-recipes";
|
|
24632
24998
|
const allProviderAction = tasks.every((t) => t.fixType === "provider-action");
|
|
@@ -24684,9 +25050,9 @@ var init_nextActionBlock = __esm({
|
|
|
24684
25050
|
function defaultMcpConfigPaths() {
|
|
24685
25051
|
const home = (0, import_node_os4.homedir)();
|
|
24686
25052
|
return [
|
|
24687
|
-
(0,
|
|
24688
|
-
(0,
|
|
24689
|
-
(0,
|
|
25053
|
+
(0, import_node_path42.join)(home, ".config", "claude", "claude_desktop_config.json"),
|
|
25054
|
+
(0, import_node_path42.join)(home, ".cursor", "mcp.json"),
|
|
25055
|
+
(0, import_node_path42.join)(home, ".gemini", "antigravity", "mcp_config.json")
|
|
24690
25056
|
];
|
|
24691
25057
|
}
|
|
24692
25058
|
function resolveConfigPaths() {
|
|
@@ -24715,11 +25081,11 @@ function findServerEntry(servers, provider2) {
|
|
|
24715
25081
|
function findProviderMcpConfig(provider2, configPaths) {
|
|
24716
25082
|
const paths = configPaths ?? resolveConfigPaths();
|
|
24717
25083
|
for (const path of paths) {
|
|
24718
|
-
if (!(0,
|
|
25084
|
+
if (!(0, import_node_fs16.existsSync)(path)) {
|
|
24719
25085
|
continue;
|
|
24720
25086
|
}
|
|
24721
25087
|
try {
|
|
24722
|
-
const raw = JSON.parse((0,
|
|
25088
|
+
const raw = JSON.parse((0, import_node_fs16.readFileSync)(path, "utf8"));
|
|
24723
25089
|
const servers = parseMcpServers(raw);
|
|
24724
25090
|
if (!servers) {
|
|
24725
25091
|
continue;
|
|
@@ -24763,13 +25129,13 @@ async function verifyProviderGap(options) {
|
|
|
24763
25129
|
fallbackCommand: FALLBACK_COMMAND
|
|
24764
25130
|
};
|
|
24765
25131
|
}
|
|
24766
|
-
var
|
|
25132
|
+
var import_node_fs16, import_node_os4, import_node_path42, FALLBACK_COMMAND, SUPPORTED_PROVIDERS, configPathsOverride;
|
|
24767
25133
|
var init_providerMcpBridge = __esm({
|
|
24768
25134
|
"src/providerMcpBridge.ts"() {
|
|
24769
25135
|
"use strict";
|
|
24770
|
-
|
|
25136
|
+
import_node_fs16 = require("node:fs");
|
|
24771
25137
|
import_node_os4 = require("node:os");
|
|
24772
|
-
|
|
25138
|
+
import_node_path42 = require("node:path");
|
|
24773
25139
|
FALLBACK_COMMAND = "npx -y viberaven audit --vercel-supabase --json";
|
|
24774
25140
|
SUPPORTED_PROVIDERS = /* @__PURE__ */ new Set(["supabase", "vercel"]);
|
|
24775
25141
|
}
|
|
@@ -24992,7 +25358,7 @@ async function cmdProviderVerify(flags, positional) {
|
|
|
24992
25358
|
return result.verified ? 0 : 1;
|
|
24993
25359
|
}
|
|
24994
25360
|
async function cmdStatus(flags, positional) {
|
|
24995
|
-
const startDir = positional[0] ? (0,
|
|
25361
|
+
const startDir = positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd();
|
|
24996
25362
|
let artifact;
|
|
24997
25363
|
try {
|
|
24998
25364
|
artifact = await loadLastArtifact(startDir);
|
|
@@ -25031,7 +25397,7 @@ async function cmdStatus(flags, positional) {
|
|
|
25031
25397
|
return 0;
|
|
25032
25398
|
}
|
|
25033
25399
|
async function runScanCommand(flags, positional, options) {
|
|
25034
|
-
const workspacePath = positional[0] ? (0,
|
|
25400
|
+
const workspacePath = positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : await resolveWorkspaceRoot(process.cwd());
|
|
25035
25401
|
if (!options?.deferMachineOutput) {
|
|
25036
25402
|
console.log(`Scanning ${workspacePath}\u2026 (local, offline)`);
|
|
25037
25403
|
}
|
|
@@ -25055,15 +25421,27 @@ async function runScanCommand(flags, positional, options) {
|
|
|
25055
25421
|
const updatedState = resetBatch(loopState, openGapCount);
|
|
25056
25422
|
const tasks = buildTaskList(artifact);
|
|
25057
25423
|
const block = buildNextActionBlock(tasks, updatedState);
|
|
25058
|
-
|
|
25059
|
-
printProviderActionBlock(tasks);
|
|
25424
|
+
let manifest;
|
|
25060
25425
|
try {
|
|
25061
|
-
|
|
25062
|
-
console.log(renderActionSurface(manifest, { limit: 5 }).trimEnd());
|
|
25426
|
+
manifest = JSON.parse(await (0, import_promises33.readFile)(paths.actionsPath, "utf8"));
|
|
25063
25427
|
} catch (error) {
|
|
25064
25428
|
console.warn(error instanceof Error ? error.message : String(error));
|
|
25065
25429
|
}
|
|
25430
|
+
const followUps = manifest?.userFollowUps ?? [];
|
|
25431
|
+
if (followUps.length > 0) block.userFollowUps = followUps;
|
|
25432
|
+
printNextActionBlock(block);
|
|
25433
|
+
printProviderActionBlock(tasks);
|
|
25434
|
+
if (manifest) {
|
|
25435
|
+
console.log(renderActionSurface(manifest, { limit: 5, followUps: false }).trimEnd());
|
|
25436
|
+
}
|
|
25066
25437
|
await saveLoopState(workspacePath, updatedState);
|
|
25438
|
+
if (options?.markFollowUpsShown && followUps.length > 0) {
|
|
25439
|
+
try {
|
|
25440
|
+
await markUserFollowUpsShown(workspacePath, followUps.map((followUp) => followUp.id));
|
|
25441
|
+
} catch (error) {
|
|
25442
|
+
console.warn(`Could not record that the outside-the-repo steps were shown (${error instanceof Error ? error.message : String(error)}); they will be shown again.`);
|
|
25443
|
+
}
|
|
25444
|
+
}
|
|
25067
25445
|
}
|
|
25068
25446
|
if (flags.open) {
|
|
25069
25447
|
try {
|
|
@@ -25075,7 +25453,7 @@ async function runScanCommand(flags, positional, options) {
|
|
|
25075
25453
|
return { exitCode: 0, artifacts: paths };
|
|
25076
25454
|
}
|
|
25077
25455
|
async function cmdReport(flags, positional) {
|
|
25078
|
-
const startDir = positional[0] ? (0,
|
|
25456
|
+
const startDir = positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd();
|
|
25079
25457
|
try {
|
|
25080
25458
|
const paths = await refreshReportFromDisk(startDir);
|
|
25081
25459
|
console.log(`Report refreshed: ${paths.reportPath}`);
|
|
@@ -25097,7 +25475,7 @@ async function cmdReport(flags, positional) {
|
|
|
25097
25475
|
}
|
|
25098
25476
|
}
|
|
25099
25477
|
async function cmdPrompt(flags, positional) {
|
|
25100
|
-
const startDir = positional[0] ? (0,
|
|
25478
|
+
const startDir = positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd();
|
|
25101
25479
|
let artifact;
|
|
25102
25480
|
try {
|
|
25103
25481
|
artifact = await loadLastArtifact(startDir);
|
|
@@ -25194,7 +25572,7 @@ async function main() {
|
|
|
25194
25572
|
const wantsJsonl = hasFlag(flags, "jsonl");
|
|
25195
25573
|
const wantsStrict = hasFlag(flags, "strict");
|
|
25196
25574
|
if (flags.condense) {
|
|
25197
|
-
const cwd = positional[0] ? (0,
|
|
25575
|
+
const cwd = positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd();
|
|
25198
25576
|
const result = await runCondenseCommand({ cwd });
|
|
25199
25577
|
console.log(`VibeRaven context map refreshed: ${result.contextMapPath}`);
|
|
25200
25578
|
return 0;
|
|
@@ -25214,18 +25592,18 @@ async function main() {
|
|
|
25214
25592
|
}
|
|
25215
25593
|
if (!command && flags.verify === true && typeof flags.action === "string") {
|
|
25216
25594
|
return runVerifyActionCommand({
|
|
25217
|
-
cwd: positional[0] ? (0,
|
|
25595
|
+
cwd: positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd(),
|
|
25218
25596
|
actionId: flags.action
|
|
25219
25597
|
});
|
|
25220
25598
|
}
|
|
25221
25599
|
if (!command && (isAgentMode || flags.verify === true || wantsJson || wantsJsonl || wantsStrict)) {
|
|
25222
25600
|
const deferMachineOutput = wantsJson || wantsJsonl;
|
|
25223
|
-
const scanResult = await runScanCommand(flags, positional, { deferMachineOutput });
|
|
25601
|
+
const scanResult = await runScanCommand(flags, positional, { deferMachineOutput, markFollowUpsShown: true });
|
|
25224
25602
|
if ((wantsJson || wantsJsonl) && !scanResult.artifacts) {
|
|
25225
25603
|
console.error("VibeRaven could not produce machine output because scan artifacts were not written.");
|
|
25226
25604
|
return 3;
|
|
25227
25605
|
}
|
|
25228
|
-
const gateResult = scanResult.artifacts && (wantsJson || wantsJsonl || wantsStrict) ? JSON.parse(await (0,
|
|
25606
|
+
const gateResult = scanResult.artifacts && (wantsJson || wantsJsonl || wantsStrict) ? JSON.parse(await (0, import_promises33.readFile)(scanResult.artifacts.gateResultPath, "utf8")) : void 0;
|
|
25229
25607
|
const strictExitCode = wantsStrict && gateResult ? exitCodeForStrictGate(gateResult, { failOnWarnings: flags.strict === "warning" }) : scanResult.exitCode;
|
|
25230
25608
|
if (wantsJson && gateResult) {
|
|
25231
25609
|
process.stdout.write(renderGateResultJson(gateResult));
|
|
@@ -25247,7 +25625,7 @@ async function main() {
|
|
|
25247
25625
|
env: process.env
|
|
25248
25626
|
});
|
|
25249
25627
|
if (mode === "local-ui") {
|
|
25250
|
-
const cwd = positional[0] ? (0,
|
|
25628
|
+
const cwd = positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd();
|
|
25251
25629
|
const handle = await startLocalUiServer({ cwd, initialPath: stackInitialPath(flags) });
|
|
25252
25630
|
console.log(`VibeRaven local UI: ${handle.url}`);
|
|
25253
25631
|
await waitForServerShutdown();
|
|
@@ -25258,7 +25636,7 @@ async function main() {
|
|
|
25258
25636
|
await runInteractiveSession();
|
|
25259
25637
|
return 0;
|
|
25260
25638
|
}
|
|
25261
|
-
const scanResult = await runScanCommand({ "agent-mode": true }, positional);
|
|
25639
|
+
const scanResult = await runScanCommand({ "agent-mode": true }, positional, { markFollowUpsShown: true });
|
|
25262
25640
|
return scanResult.exitCode;
|
|
25263
25641
|
}
|
|
25264
25642
|
switch (command) {
|
|
@@ -25267,7 +25645,7 @@ async function main() {
|
|
|
25267
25645
|
await runInteractiveSession();
|
|
25268
25646
|
return 0;
|
|
25269
25647
|
case "ui": {
|
|
25270
|
-
const cwd = positional[0] ? (0,
|
|
25648
|
+
const cwd = positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd();
|
|
25271
25649
|
const envPort = Number(process.env.PORT);
|
|
25272
25650
|
const handle = await startLocalUiServer({ cwd, port: Number.isFinite(envPort) && envPort > 0 ? envPort : void 0, initialPath: stackInitialPath(flags) });
|
|
25273
25651
|
console.log(`VibeRaven local UI: ${handle.url}`);
|
|
@@ -25279,14 +25657,14 @@ async function main() {
|
|
|
25279
25657
|
return cmdStatus(flags, positional);
|
|
25280
25658
|
case "check":
|
|
25281
25659
|
return runCheckCommand({
|
|
25282
|
-
cwd: positional[0] ? (0,
|
|
25660
|
+
cwd: positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd(),
|
|
25283
25661
|
json: Boolean(flags.json),
|
|
25284
25662
|
quiet: Boolean(flags.quiet),
|
|
25285
25663
|
base: typeof flags.base === "string" ? flags.base : void 0,
|
|
25286
25664
|
markdown: flags.markdown === true
|
|
25287
25665
|
});
|
|
25288
25666
|
case "fix": {
|
|
25289
|
-
const fixCwd = positional[0] ? (0,
|
|
25667
|
+
const fixCwd = positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd();
|
|
25290
25668
|
const gapId = typeof flags.gap === "string" ? flags.gap : void 0;
|
|
25291
25669
|
if (!gapId) {
|
|
25292
25670
|
const artifact = await loadLastArtifact(fixCwd).catch(() => void 0);
|
|
@@ -25315,19 +25693,19 @@ async function main() {
|
|
|
25315
25693
|
}
|
|
25316
25694
|
case "actions":
|
|
25317
25695
|
return runActionsCommand({
|
|
25318
|
-
cwd: positional[0] ? (0,
|
|
25696
|
+
cwd: positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd(),
|
|
25319
25697
|
json: Boolean(flags.json)
|
|
25320
25698
|
});
|
|
25321
25699
|
case "preview":
|
|
25322
25700
|
return runPreviewCommand({
|
|
25323
|
-
cwd: positional[0] ? (0,
|
|
25701
|
+
cwd: positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd(),
|
|
25324
25702
|
agentMode: flags["agent-mode"] === true,
|
|
25325
25703
|
json: Boolean(flags.json)
|
|
25326
25704
|
});
|
|
25327
25705
|
case "next":
|
|
25328
25706
|
return runNextCommand({
|
|
25329
25707
|
json: Boolean(flags.json),
|
|
25330
|
-
cwd: positional[0] ? (0,
|
|
25708
|
+
cwd: positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd()
|
|
25331
25709
|
});
|
|
25332
25710
|
case "guide": {
|
|
25333
25711
|
const provider2 = positional[0];
|
|
@@ -25349,7 +25727,7 @@ async function main() {
|
|
|
25349
25727
|
cwd: process.cwd()
|
|
25350
25728
|
});
|
|
25351
25729
|
case "scan": {
|
|
25352
|
-
const scanResult = await runScanCommand(flags, positional);
|
|
25730
|
+
const scanResult = await runScanCommand(flags, positional, { markFollowUpsShown: true });
|
|
25353
25731
|
return scanResult.exitCode;
|
|
25354
25732
|
}
|
|
25355
25733
|
case "report":
|
|
@@ -25361,7 +25739,7 @@ async function main() {
|
|
|
25361
25739
|
case "provider-verify":
|
|
25362
25740
|
return cmdProviderVerify(flags, positional);
|
|
25363
25741
|
case "init": {
|
|
25364
|
-
const cwd = positional[0] ? (0,
|
|
25742
|
+
const cwd = positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd();
|
|
25365
25743
|
const agents = typeof flags.agents === "string" ? flags.agents : void 0;
|
|
25366
25744
|
if (flags.github === true) {
|
|
25367
25745
|
return runInitGithubCommand({ cwd, dryRun: flags["dry-run"] === true, force: flags.force === true });
|
|
@@ -25378,7 +25756,7 @@ async function main() {
|
|
|
25378
25756
|
return 1;
|
|
25379
25757
|
}
|
|
25380
25758
|
return runDoctorAgentsCommand({
|
|
25381
|
-
cwd: positional[0] ? (0,
|
|
25759
|
+
cwd: positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd()
|
|
25382
25760
|
});
|
|
25383
25761
|
case "validate-npm-package":
|
|
25384
25762
|
return runValidateNpmPackageCommand({
|
|
@@ -25391,7 +25769,7 @@ async function main() {
|
|
|
25391
25769
|
return 1;
|
|
25392
25770
|
}
|
|
25393
25771
|
return runAuditCommand({
|
|
25394
|
-
cwd: positional[0] ? (0,
|
|
25772
|
+
cwd: positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd(),
|
|
25395
25773
|
json: Boolean(flags.json)
|
|
25396
25774
|
});
|
|
25397
25775
|
case "clean": {
|
|
@@ -25399,7 +25777,7 @@ async function main() {
|
|
|
25399
25777
|
console.error("Usage: viberaven clean --plan [path]");
|
|
25400
25778
|
return 1;
|
|
25401
25779
|
}
|
|
25402
|
-
const cwd = positional[0] ? (0,
|
|
25780
|
+
const cwd = positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd();
|
|
25403
25781
|
const plan = buildContextCleanupPlan({ projectRoot: cwd, files: await collectCleanupFiles(cwd) });
|
|
25404
25782
|
const outputPath = await writeCleanupPlan(cwd, plan);
|
|
25405
25783
|
console.log(`Wrote ${outputPath}
|
|
@@ -25409,9 +25787,9 @@ async function main() {
|
|
|
25409
25787
|
}
|
|
25410
25788
|
case "rls-test":
|
|
25411
25789
|
return runRlsTestCommand({
|
|
25412
|
-
cwd: positional[0] ? (0,
|
|
25413
|
-
matrix: typeof flags.matrix === "string" ? (0,
|
|
25414
|
-
migrations: typeof flags.migrations === "string" ? (0,
|
|
25790
|
+
cwd: positional[0] ? (0, import_node_path43.resolve)(process.cwd(), positional[0]) : process.cwd(),
|
|
25791
|
+
matrix: typeof flags.matrix === "string" ? (0, import_node_path43.resolve)(process.cwd(), flags.matrix) : void 0,
|
|
25792
|
+
migrations: typeof flags.migrations === "string" ? (0, import_node_path43.resolve)(process.cwd(), flags.migrations) : void 0,
|
|
25415
25793
|
json: Boolean(flags.json)
|
|
25416
25794
|
});
|
|
25417
25795
|
default:
|
|
@@ -25420,11 +25798,11 @@ async function main() {
|
|
|
25420
25798
|
return 1;
|
|
25421
25799
|
}
|
|
25422
25800
|
}
|
|
25423
|
-
var
|
|
25801
|
+
var import_promises33, import_node_path43, STACK_AREAS;
|
|
25424
25802
|
var init_cli = __esm({
|
|
25425
25803
|
"src/cli.ts"() {
|
|
25426
|
-
|
|
25427
|
-
|
|
25804
|
+
import_promises33 = require("node:fs/promises");
|
|
25805
|
+
import_node_path43 = require("node:path");
|
|
25428
25806
|
init_config();
|
|
25429
25807
|
init_runScan();
|
|
25430
25808
|
init_artifacts2();
|
|
@@ -25466,6 +25844,7 @@ var init_cli = __esm({
|
|
|
25466
25844
|
init_buildTaskList();
|
|
25467
25845
|
init_providerMcpBridge();
|
|
25468
25846
|
init_render();
|
|
25847
|
+
init_registry2();
|
|
25469
25848
|
STACK_AREAS = /* @__PURE__ */ new Set(["database", "auth", "payments", "deployment", "monitoring", "security"]);
|
|
25470
25849
|
if (require.main === module) {
|
|
25471
25850
|
main().then((code) => {
|