playbook/antigravity-awesome-skills/plugins/antigravity-awesome-skills-.../skills/vercel-optimize/lib/gates/platform-fluid-compute.mjs

84 lines
3.5 KiB
JavaScript

// Second branch (slow p95 + traffic floor) keeps the gate useful on teams where
// cold-start isn't directly observable — common on CLI v53 — trading specificity for coverage.
export const metadata = {
id: 'platform_fluid_compute',
threshold: 'fluid=false AND (any cold_start signal OR any route with p95>1000ms AND inv>1000)',
billingDimension: 'function-duration',
scope: 'account',
sourceCitation: 'vercel-optimize gate threshold',
description:
'When Fluid Compute is disabled on a project that shows cold-start pressure (high cold-start rate) or sustained slow function p95 on hot routes. Fluid Compute reduces cold starts via instance reuse — recommend turning it on at the project level rather than per-route.',
};
export function gate(signals) {
// If project config failed to load we can't tell if Fluid is on; recommending it when already-on
// erodes trust badly, so stay silent and let Strengths note the gap.
if (signals.project?.error) return [];
const fluidEnabled =
signals.project?.resourceConfig?.fluid === true
|| signals.project?.defaultResourceConfig?.fluid === true;
if (fluidEnabled) return [];
const cold = extractHighColdRoutes(signals);
const slow = extractSlowHotRoutes(signals);
if (cold.length === 0 && slow.length === 0) return [];
return [{
kind: metadata.id,
scope: 'account',
files: [],
priority: 50,
confidence: cold.length > 0 ? 0.85 : 0.65,
o11ySignal: cold.length > 0
? `${cold.length} route(s) with high cold-start rate`
: `${slow.length} hot route(s) with p95>1s; cold-start not directly observable`,
reason: cold.length > 0
? 'cold starts observed and Fluid Compute is disabled'
: 'slow hot routes and Fluid Compute is disabled',
question: 'Would enabling Fluid Compute reduce cold-start and warm-instance reuse overhead for the observed hot routes?',
evidence: { fluidEnabled, highColdRoutes: cold.slice(0, 5), slowHotRoutes: slow.slice(0, 5) },
}];
}
function extractHighColdRoutes(signals) {
const live = signals.metrics?.fnStartTypeByRoute?.rows;
if (Array.isArray(live) && live.some((r) => 'coldCount' in r || 'coldPct' in r)) {
return live.filter((r) => r.route && (r.coldPct ?? 0) > 0.3 && (r.total ?? 0) > 100);
}
// Legacy pre-derived fixture shape.
const direct = signals.metrics?.coldStartByRoute?.rows;
if (Array.isArray(direct)) {
return direct.filter((r) => r.route && (r.coldPct ?? 0) > 0.3 && (r.total ?? 0) > 100);
}
const legacy = signals.metrics?.coldStarts?.series;
if (Array.isArray(legacy)) {
return legacy
.map((s) => {
const total = s.summary?.count ?? 0;
const coldCount = s.summary?.coldCount ?? s.summary?.sum ?? 0;
return { route: s.groupValues?.route, total, coldPct: total > 0 ? coldCount / total : 0 };
})
.filter((r) => r.route && r.coldPct > 0.3 && r.total > 100);
}
return [];
}
function extractSlowHotRoutes(signals) {
const dur = signals.metrics?.fnDurationP95ByRoute?.rows;
const cache = signals.metrics?.requestsByRouteCache?.rows;
if (!Array.isArray(dur)) return [];
// Sum requests per route across cache_result.
const inv = new Map();
for (const r of (cache ?? [])) {
if (!r.route) continue;
inv.set(r.route, (inv.get(r.route) ?? 0) + (r.value ?? 0));
}
return dur
.filter((r) => r.route)
.map((r) => ({ route: r.route, p95Ms: Math.round(r.value ?? 0), invocations: inv.get(r.route) ?? 0 }))
// inv>500 floor is the 14d-window equivalent of the old 1000/30d.
.filter((r) => r.p95Ms > 1000 && r.invocations > 500);
}