({ recommendations = [], gated = [], abstentions = [], observations = [], signals = {}, candidates = [], opts = {} } = {})
| 13 | const GATED_TARGET_PREVIEW = 5; |
| 14 | |
| 15 | export function renderReport({ recommendations = [], gated = [], abstentions = [], observations = [], signals = {}, candidates = [], opts = {} } = {}) { |
| 16 | const safety = splitCustomerSafeObservations(observations, abstentions, signals); |
| 17 | observations = safety.observations; |
| 18 | abstentions = [...abstentions, ...safety.heldBackObservations]; |
| 19 | assertValidObservations(observations); |
| 20 | |
| 21 | const projectName = opts.projectName ?? signals.project?.name ?? '<project>'; |
| 22 | const stack = signals.stack ?? signals.codebase?.stack ?? {}; |
| 23 | const usage = signals.usage ?? null; |
| 24 | const plan = signals.plan ?? { plan: 'unknown', reason: '(not detected)' }; |
| 25 | |
| 26 | // Sub-agents don't always propagate o11ySignal/aliasRoutes — look them up by candidateRef and canonicalize the displayed ref. |
| 27 | recommendations = recommendations.map((r) => enrichRecFromCandidates(r, candidates)); |
| 28 | const { needsEvidenceRows, noChangeRows } = splitInvestigationOutcomes(abstentions); |
| 29 | |
| 30 | const lines = []; |
| 31 | lines.push(`# Vercel Optimization Report — ${projectName}`); |
| 32 | lines.push(''); |
| 33 | lines.push(renderMetadataLine(stack, plan, usage, signals)); |
| 34 | const coverageLine = renderCoverageLine(candidates, recommendations, signals, { |
| 35 | abstentions, |
| 36 | heldBackCount: opts.heldBackCount, |
| 37 | noChangeCount: opts.noChangeCount, |
| 38 | }); |
| 39 | if (coverageLine) lines.push(coverageLine); |
| 40 | if (opts.generatedAt) { |
| 41 | lines.push(''); |
| 42 | lines.push(`_Generated ${opts.generatedAt}_`); |
| 43 | } |
| 44 | lines.push(''); |
| 45 | |
| 46 | lines.push(...renderCostHeader(signals)); |
| 47 | lines.push(''); |
| 48 | lines.push(...renderCostBreakdown(usage, signals)); |
| 49 | if (usage) { |
| 50 | const coverage = computeCostCoverage(usage, registeredGates); |
| 51 | lines.push(...renderCostCoverageMarkdown(coverage)); |
| 52 | } |
| 53 | lines.push(''); |
| 54 | |
| 55 | const platformRecs = recommendations.filter(isPlatformScope).slice(0, PLATFORM_CAP); |
| 56 | const codeRecs = recommendations.filter((r) => !isPlatformScope(r)); |
| 57 | const sorted = sortRecs(codeRecs); |
| 58 | const high = sorted.filter((r) => r.impactTier === 'high'); |
| 59 | const medium = sorted.filter((r) => r.impactTier === 'medium'); |
| 60 | const low = sorted.filter((r) => r.impactTier === 'low' || !r.impactTier); |
| 61 | lines.push('## Highest-impact recommendations'); |
| 62 | lines.push(''); |
| 63 | if (sorted.length === 0) { |
| 64 | lines.push('_No recommendations are ready to apply from this run._'); |
| 65 | } else { |
| 66 | const top = sorted.slice(0, 5); |
| 67 | top.forEach((rec, i) => { |
| 68 | const candidate = candidateForDisplay(rec); |
| 69 | const signal = formatSignal(rec.o11ySignal ?? signalFromRec(rec) ?? '', candidate); |
| 70 | lines.push(`${i + 1}. **${formatCandidateLabel(candidate)}** — ${signal}`); |
| 71 | lines.push(` - **What to do**: ${formatRecommendationText(rec.what ?? '')}`); |
| 72 | lines.push(` - **Impact**: ${formatRecommendationText(impactString(rec, signals))}`); |
no test coverage detected