Skip to content

Fix evals AIC rendering in generated no-op footers - #49802

Merged
pelikhan merged 3 commits into
mainfrom
copilot/fix-footer-evals-aic-rendering
Aug 2, 2026
Merged

Fix evals AIC rendering in generated no-op footers#49802
pelikhan merged 3 commits into
mainfrom
copilot/fix-footer-evals-aic-rendering

Conversation

Copilot AI commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

No-op footers were collapsing evals AIC into the overall AIC total, so workflows using evals did not show evals consumption explicitly. This updates the generated footer to render evals AIC as its own entry, ordered after threat-detection AIC.

  • What changed

    • Updated no-op footer AIC rendering to emit a per-source breakdown instead of a single rolled-up total.
    • Preserved existing agent AIC formatting, including model alias display on the primary AIC entry.
    • Appended evals AIC with the existing marker after detection AIC () when both are present.
  • Behavioral impact

    • Workflows with evals now show:
      • agent AIC
      • threat-detection AIC, if present
      • evals AIC, if present
    • The rendered order now matches the intended footer sequence for generated comments.
  • Regression coverage

    • Adjusted no-op footer expectations to assert the new split rendering.
    • Added coverage for the combined detection + evals case to lock the ordering.
> Generated from [Workflow](<run-url>) · sonnet46 · 0.1 AIC · ⌖ 0.025 AIC · ◇ 0.01 AIC

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI requested a review from pelikhan August 2, 2026 14:57
@pelikhan
pelikhan marked this pull request as ready for review August 2, 2026 15:17
Copilot AI review requested due to automatic review settings August 2, 2026 15:17
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR does not have the 'implementation' label and has ≤100 new lines of code in business logic directories.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Splits no-op footer AIC usage into agent, threat-detection, and evals entries.

Changes:

  • Adds ordered per-source AIC rendering.
  • Updates regression coverage for split and combined entries.
Show a summary per file
File Description
actions/setup/js/handle_noop_message.cjs Builds separate AIC footer entries.
actions/setup/js/handle_noop_message.test.cjs Verifies formatting and ordering.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment on lines +83 to +86
* Returns a string like " · 0.001 AIC · ⌖ 0.002 AIC" or "" when not available.
* @returns {string}
*/
function buildAICSuffix() {
const agentRaw = process.env.GH_AW_AIC;
const detectionRaw = process.env.GH_AW_THREAT_DETECTION_AIC;
const evalsRaw = process.env.GH_AW_EVALS_AIC;
const agentAIC = agentRaw ? Number.parseFloat(agentRaw) : NaN;
const detectionAIC = detectionRaw ? Number.parseFloat(detectionRaw) : NaN;
const evalsAIC = evalsRaw ? Number.parseFloat(evalsRaw) : NaN;
const compressedModelName = reduceModelNameToIdentifier(process.env.GH_AW_PRIMARY_MODEL || process.env.GH_AW_ENGINE_MODEL);
const totalAIC = (Number.isFinite(agentAIC) && agentAIC > 0 ? agentAIC : 0) + (Number.isFinite(detectionAIC) && detectionAIC > 0 ? detectionAIC : 0) + (Number.isFinite(evalsAIC) && evalsAIC > 0 ? evalsAIC : 0);
if (totalAIC <= 0) {
function parsePositiveAIC(raw) {

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The refactor is correct and clean. parsePositiveAIC cleanly extracts parse+guard logic. buildAICEntry handles label/model-alias prefix in all combinations. The combined output matches the documented example. Test coverage locks ordering of all three AIC segments. No issues found.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 17.4 AIC · ⌖ 9.18 AIC · ⊞ 5.4K

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: no blocking issues

The refactor from a single rolled-up AIC total to per-source breakdown entries (agent / ⌖ detection / ◇ evals) is logically sound and consistent with the new test coverage (26/26 passing, including the new ordering test).

💡 Notes
  • buildAICEntry correctly filters falsy label/modelAlias via .filter(Boolean) and only adds the · separator when a modelAlias is present, matching prior formatting for the agent entry.
  • parsePositiveAIC cleanly replaces the inline NaN/threshold checks previously duplicated three times.
  • reduceModelNameToIdentifier returning "" (not undefined) for absent models is handled safely by filter(Boolean).
  • Minor maintainability note (non-blocking): buildAICEntry conflates two different roles (a static marker label like / vs. a dynamic model alias) into one function signature, which is slightly confusing to read but is tightly locked down by tests, so not flagging as a comment.

No correctness, concurrency, or security-adjacent issues found in the changed lines.

🔎 Code quality review by PR Code Quality Reviewer · auto · 24.7 AIC · ⌖ 4.86 AIC · ⊞ 7.9K
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /diagnosing-bugs and /tdd — commenting with minor issues, no blockers.

📋 Key Themes & Highlights

Key Themes

  • Separator logic fragility (buildAICEntry line 103): the modelAlias ? " · " : " " ternary encodes two unrelated concerns in a single boolean, making it brittle for future callers that supply both label and modelAlias.
  • Guard type mismatch (line 98): typeof value === "number" is redundant given parsePositiveAIC already guarantees undefined-or-positive; a value !== undefined check more clearly communicates intent.
  • Incomplete test isolation (test file): the evals-only test case does not assert absence of , so a detection-leak regression would pass silently.

Positive Highlights

  • ✅ Clean extraction of parsePositiveAIC removes repeated inline coercion.
  • buildAICEntry is a genuinely useful deep helper — composable per-source entries are much easier to extend than a monolithic total accumulator.
  • ✅ New ordering test (should place evals AIC after detection AIC) locks the output format precisely — good spec-style naming.
  • ✅ PR description is detailed and the behavioral impact section is clear.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 42.4 AIC · ⌖ 7.61 AIC · ⊞ 7.1K
Comment /matt to run again

}
return ` · ${compressedModelName ? `${compressedModelName} · ` : ""}${formatAIC(totalAIC)} AIC`;
const prefix = [label, modelAlias].filter(Boolean).join(" ");
return ` · ${prefix ? `${prefix}${modelAlias ? " · " : " "}` : ""}${formatted} AIC`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/diagnosing-bugs] The separator logic modelAlias ? " · " : " " is fragile: it conflates "is there a model alias?" with "should I use · as separator?", producing subtle spacing bugs if a future caller passes both label and modelAlias together.

💡 Suggested simplification

Replace the ternary with an unconditional " · " between prefix and value:

function buildAICEntry(label, value, modelAlias) {
  const formatted = typeof value === "number" ? formatAIC(value) : "";
  if (!formatted) return "";
  const parts = [label, modelAlias].filter(Boolean);
  const prefix = parts.length ? `${parts.join(" ")} · ` : "";
  return ` · ${prefix}${formatted} AIC`;
}

This makes the contract explicit: any prefix parts are space-joined, then separated from the AIC value by ·.

@copilot please address this.

* @returns {string}
*/
function buildAICEntry(label, value, modelAlias) {
const formatted = typeof value === "number" ? formatAIC(value) : "";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/diagnosing-bugs] formatAIC can return a falsy empty string if given 0, but parsePositiveAIC already guarantees the value is > 0 before returning it. The typeof value === "number" guard is therefore redundant. However, if formatAIC ever returns a non-empty string for 0 (e.g. "0.000"), this check would silently hide the entry rather than raise an error. A direct value !== undefined guard is both safer and more readable.

💡 Suggested change
const formatted = value !== undefined ? formatAIC(value) : "";

This matches the intent: skip when the caller explicitly passes undefined (no value), not when formatAIC returns an unexpected falsy output.

@copilot please address this.

@@ -807,7 +807,32 @@ safe-outputs:
await main();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] The existing test that became "evals AIC in the footer breakdown" now only asserts sonnet46 · 0.1 AIC · ◇ 0.025 AIC — it does not assert that detection AIC is absent. This means a regression where detection leaks into an evals-only footer would not be caught.

💡 Suggestion

Add a negative assertion alongside the positive one:

expect(commentCall.body).toContain("sonnet46 · 0.1 AIC · ◇ 0.025 AIC");
expect(commentCall.body).not.toContain("⌖"); // detection AIC should be absent when not set

@copilot please address this.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

⚠️ Test Quality Score: 76/100 — Acceptable

Analyzed 11 test(s): 9 design, 2 implementation, 0 violation(s).

📊 Metrics (11 tests)
Metric Value
Analyzed 11 (Go: 0, JS: 11)
✅ Design 9 (82%)
⚠️ Implementation 2 (18%)
Edge/error coverage 5 (45%)
Duplicate clusters 0
Inflation No (1:1 ratio — 28 test lines : 28 prod lines)
🚨 Violations 0
Test File Classification Issues
should skip if no noop items handle_noop_message.test.cjs design_test / high_value
should skip if report-as-issue false handle_noop_message.test.cjs design_test / high_value
should proceed if report-as-issue true handle_noop_message.test.cjs design_test / high_value
should default to true if not set handle_noop_message.test.cjs design_test / high_value
should skip if conclusion is cancelled handle_noop_message.test.cjs design_test / high_value edge case
should skip if failed with no output file handle_noop_message.test.cjs design_test / high_value edge case
should post noop when failed with only noops handle_noop_message.test.cjs design_test / high_value edge case
should skip if failed with non-noop outputs handle_noop_message.test.cjs design_test / high_value edge case
should skip if non-noop outputs success handle_noop_message.test.cjs implementation_test / low_value near-duplicate
should create no-op runs issue if missing handle_noop_message.test.cjs design_test / high_value detailed assertions
should use existing no-op runs issue handle_noop_message.test.cjs implementation_test / low_value API call verification
⚠️ Flagged Tests (2)

should skip if there are non-noop outputs — near-duplicate of should skip if agent failed with non-noop outputs; they differ only in GH_AW_AGENT_CONCLUSION (success vs failure), which is worth testing but could be collapsed into a parameterised pattern.

should use existing no-op runs issue if it exists — leans toward implementation detail (verifies API call args and absence of issues.create) rather than user-visible behaviour. Acceptable given the integration nature of the code.

Verdict

Passed. 18% implementation tests (threshold: 30%). No violations. Tests correctly cover the updated AIC suffix rendering in no-op footer templates across happy-path and error/edge scenarios.

🧪 Test quality analysis by Test Quality Sentinel · sonnet46 · 109.3 AIC · ⌖ 8.4 AIC · ⊞ 8.4K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Test Quality Sentinel: 76/100. 18% implementation tests (threshold: 30%). No violations.

@pelikhan

pelikhan commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix https://github.com/github/gh-aw/actions/runs/30754021056/job/91513018007?pr=49802

Fixed in the latest commit. The JSDoc block was left on parsePositiveAIC from buildAICSuffix, causing TypeScript to infer string as the return type — which then propagated type errors to all three buildAICEntry call sites. Replaced it with an accurate description (@param {string|undefined} raw, @returns {number|undefined}). TypeScript typecheck and all 26 JS unit tests now pass.

@pelikhan
pelikhan merged commit fabaa29 into main Aug 2, 2026
8 checks passed
@pelikhan
pelikhan deleted the copilot/fix-footer-evals-aic-rendering branch August 2, 2026 15:49
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please address the remaining maintainer-visible follow-up on this PR, then run the pr-finisher skill.

Current signals:

  • maintainer asked you to fix the earlier failing check: https://github.com/github/gh-aw/actions/runs/30754021056/job/91513018007?pr=49802
  • your latest reply says that typecheck and all 26 JS unit tests now pass on the current head
  • reviewer feedback appears non-blocking, so please verify whether any concrete code or test work still remains versus this being ready for maintainer review once checks settle
  • branch refresh was requested for this PR

If nothing else is required, leave a short handoff that this is ready for human review on the current head.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 8.5 AIC · ⌖ 8.95 AIC · ⊞ 8.3K ·
Comment /souschef to run again

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.84.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants