diff --git a/actions/setup/js/check_daily_aic_workflow_guardrail.cjs b/actions/setup/js/check_daily_aic_workflow_guardrail.cjs index 34024b592f0..a61a5332309 100644 --- a/actions/setup/js/check_daily_aic_workflow_guardrail.cjs +++ b/actions/setup/js/check_daily_aic_workflow_guardrail.cjs @@ -223,6 +223,12 @@ function renderDailyAICSummary(workflowName, actorLogin, threshold, countedRuns, .join("\n") : "| _none_ | — | — | 0 |"; + const noRunData = stats.count === 0; + const totalAICFormatted = formatAICCredits(stats.total) || "0"; + const avgAICFormatted = noRunData ? "—" : formatAICCredits(stats.average) || "0"; + const stddevAICFormatted = noRunData ? "—" : formatAICCredits(stats.stddev) || "0"; + const minMaxAICFormatted = noRunData ? "— / —" : `${formatAICCredits(stats.min)} / ${formatAICCredits(stats.max)}`; + const noteLines = []; if (meta.truncatedByRateLimit) { noteLines.push(`- Stopped early to preserve GitHub API rate limit headroom (${rateLimit.remaining} remaining, reserve ${RATE_LIMIT_RESERVE}).`); @@ -236,14 +242,14 @@ function renderDailyAICSummary(workflowName, actorLogin, threshold, countedRuns, "", "| Statistic | Value |", "| --- | ---: |", - `| 24h total AIC | ${formatAICCredits(stats.total)} |`, + `| 24h total AIC | ${totalAICFormatted} |`, `| Threshold | ${formatAICCredits(threshold)} |`, `| Threshold used | ${usagePercent}% |`, - `| Remaining headroom | ${formatAICCredits(remainingBudget)} |`, + `| Remaining headroom | ${formatAICCredits(remainingBudget) || "0"} |`, `| Runs counted | ${formatInteger(stats.count)} |`, - `| Avg AIC / run | ${formatAICCredits(stats.average)} |`, - `| Std dev AIC | ${formatAICCredits(stats.stddev)} |`, - `| Min / Max AIC | ${formatAICCredits(stats.min)} / ${formatAICCredits(stats.max)} |`, + `| Avg AIC / run | ${avgAICFormatted} |`, + `| Std dev AIC | ${stddevAICFormatted} |`, + `| Min / Max AIC | ${minMaxAICFormatted} |`, `| API remaining | ${formatInteger(rateLimit.remaining)} / ${formatInteger(rateLimit.limit)} |`, `| API used | ${formatInteger(rateLimit.used)} |`, `| API reset | ${rateLimit.reset || "unknown"} |`, diff --git a/actions/setup/js/check_daily_aic_workflow_guardrail.test.cjs b/actions/setup/js/check_daily_aic_workflow_guardrail.test.cjs index 0d0da854603..4678888a504 100644 --- a/actions/setup/js/check_daily_aic_workflow_guardrail.test.cjs +++ b/actions/setup/js/check_daily_aic_workflow_guardrail.test.cjs @@ -98,6 +98,36 @@ describe("check_daily_aic_workflow_guardrail", () => { expect(exports.formatDailyGuardrailLogMessage("Completed AI Credits inspection window")).toBe("[daily-workflow-aic] Completed AI Credits inspection window"); }); + it("renders a daily AI Credits summary with zero counts when no prior runs are in the 24h window", () => { + const markdown = exports.renderDailyAICSummary( + "Impact Efficiency Report", + "mnkiefer", + 5000, + [], + { + remaining: 13194, + limit: 15000, + used: 1806, + reset: "2026-06-10T07:07:04.000Z", + }, + { + candidateRunsCount: 0, + inspectedRunsCount: 0, + truncatedByRateLimit: false, + } + ); + + expect(markdown).toContain("| 24h total AIC | 0 |"); + expect(markdown).toContain("| Runs counted | 0 |"); + expect(markdown).toContain("| Avg AIC / run | — |"); + expect(markdown).toContain("| Std dev AIC | — |"); + expect(markdown).toContain("| Min / Max AIC | — / — |"); + expect(markdown).toContain("| _none_ | — | — | 0 |"); + expect(markdown).not.toContain("| 24h total AIC | |"); + expect(markdown).not.toContain("| Avg AIC / run | |"); + expect(markdown).not.toContain("| Min / Max AIC | / |"); + }); + it("renders a daily AI Credits details summary with stats and prior runs", () => { const markdown = exports.renderDailyAICSummary( "Nightly triage",