Skip to content

Fix routing smoke assertions: attribute agent traffic by model instead of nonexistent purpose values - #67595

Open
SivaKesava1 with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-routing-smokes-assertions
Open

SivaKesava1 with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-routing-smokes-assertions

Conversation

Copilot AI commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Important

Before merging, a maintainer must add the smoke-routing label. That runs Smoke Copilot Routed, Smoke Pi Routed and Smoke Copilot SDK Routed on this PR's code. They have not run on it yet.

All three routing smokes fail on main in the post-step only. Routing and sub-agent delegation were correct. smoke_model_routing_assertions.cjs counted only token-usage records with purpose: "agent" or "subagent", but AWF never writes those values. The only purpose AWF records is routing_classification. As a result R3, M1 and S3 had nothing to match, and R4 passed on zero requests.

Request classification (smoke_model_routing_assertions.cjs)

  • Classifier vs. agent traffic: purpose: "routing_classification" is the classifier (R2). Every other record is agent traffic. x_initiator is only the billing class, so it is not used.
  • Attribution: agent traffic on a declared sub-agent's model goes to that sub-agent (S3). Everything else goes to the main agent (R3, R4, M1).
  • Correlation, if it ever exists: a session link takes precedence over model matching, either a request ID on subagent.* events or a sub-agent ID on proxy records. Today there is none, so model matching is what runs.
  • Empty input: R3, R4, M1 and S3 now fail when there are zero requests to check. The message names the check and the requests observed.
  • New C1 check: fails when a declared sub-agent model is also in allowedModels, because model-based attribution would then be ambiguous.
  • Normalization is unchanged: dated IDs and query strings were already handled but had never run on real records, because the old filter emptied the request sets first. Examples: claude-haiku-4-5-20251001 becomes claude-haiku-4.5, and /v1/messages?beta=true becomes /v1/messages.

Records as AWF writes them (from Smoke Pi Routed):

{"model":"gpt-5.6-luna","path":"/responses","status":200,"purpose":"routing_classification","x_initiator":"agent"}
{"model":"gpt-5.6-luna","path":"/responses","status":200,"x_initiator":"agent"}
{"model":"claude-haiku-4-5-20251001","path":"/v1/messages?beta=true","status":200,"x_initiator":"agent"}
{"model":"gpt-5.4-mini-2026-03-17","path":"/responses","status":200,"x_initiator":"agent"}

These now resolve to: the classifier (R2), the main agent (R3, R4), haiku-whoami (S3) and mini-whoami (S3).

smoke-pi-routed.md

  • allowed-models and the post-step allowedModels are reduced to [gpt-5.6-luna], matching smoke-copilot-sdk-routed. The sub-agent models can no longer be routing selections, which satisfies C1. The lock file is recompiled.
  • smoke-copilot-routed.md and smoke-copilot-sdk-routed.md are unchanged.

Tests

  • Fixtures are rebuilt from runs 38097181601, 38096990663 and 38100426674. Requests come from the agent artifact's token-usage.jsonl and events from usage/aw_session.jsonl. They include:
    • agent requests with no purpose
    • dated model IDs and query-string endpoints
    • SDK events keyed by agentId, with a second subagent.completed marked cancelled: true. S2 is deliberately not tightened.
  • Removed: the test asserting that requests without purpose cannot satisfy R3.
  • Negative variants, each asserting the check ID and the observed values:
    • wrong model
    • wrong endpoint
    • non-200 status
    • no agent requests
    • missing routing event
    • harness-only routing outcome
    • C1 overlap
    • request-ID and agent-ID correlation

Scope

Only the assertion helper, its tests and the Pi smoke config change. Routing, harness, AWF configuration and audit behavior are untouched.

… purpose

Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix routing smokes assertion helper filters on purpose values Fix routing smoke assertions: attribute agent traffic by model instead of nonexistent purpose values Oct 11, 2026
Copilot AI requested a review from SivaKesava1 October 11, 2026 03:16
@SivaKesava1
SivaKesava1 marked this pull request as ready for review October 11, 2026 04:31
Copilot AI balanced review requested due to automatic review settings October 11, 2026 04:31
@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

✅ Ponytail Reviewer completed successfully!

Generated by Ponytail Reviewer for #67595

@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

✅ PR Code Quality Reviewer completed the code quality review.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Design Decision Gate 🏗️ is checking for design decision records on this pull request...

@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

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

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

✅ Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff

🧪 Test quality analysis by Test Quality Sentinel

@SivaKesava1 SivaKesava1 added the smoke-routing Run the model-routing smoke workflows on this PR label Oct 11, 2026
@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

✅ Smoke Copilot Routed completed successfully!

Generated by Smoke Copilot Routed for #67595

@github-actions github-actions Bot removed the smoke-routing Run the model-routing smoke workflows on this PR label Oct 11, 2026
@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

✅ Smoke Pi Routed completed successfully!

Generated by Smoke Pi Routed for #67595

@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

✅ Smoke Copilot SDK Routed completed successfully!

Generated by Smoke Copilot SDK Routed for #67595

@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.

One removable speculative attribution layer found.

net: -20 lines possible.

Generated by ✂️ Ponytail Reviewer for #67595 · codex · gpt56 · 12 AIC · ⌖ 5.16 AIC · ⊞ 13.5K
Comment /ponytail to run again

const startedEvents = subagentEvents.filter(event => event.type === "subagent.started");
const observedNames = [...new Set(startedEvents.map(event => event.data?.agentName ?? "<none>"))];

// Attribute agent traffic to declared sub-agents: prefer session correlation

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.

L235: yagni: speculative request-ID/agent-ID attribution for links the PR says AWF does not emit. Attribute sub-agent traffic by declared model until real correlated records exist.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Leaving this as is. Issue #67594 asked for the request-ID/agent-ID correlation so that a real correlation from AWF or gh-aw takes precedence over the model fallback as soon as one is recorded. Tests cover it. Until correlated records exist, traffic is attributed by declared model, and C1 now makes that attribution unambiguous (d4d3b24).

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.

🟡 Changes recommended

Duplicate sub-agent models remain ambiguous and can let one request satisfy multiple S3 checks.

1 open finding
What changed in this PR

Fixes routing smoke assertions to classify real AWF traffic correctly and updates the Pi smoke configuration.

Changes:

  • Attributes non-classifier requests by correlation or model.
  • Adds real-shape fixtures and negative coverage.
  • Restricts Pi routing candidates and recompiles its lock file.
File Description
actions/​setup/​js/​smoke_model_routing_assertions.cjs Revises request attribution and checks.
actions/​setup/​js/​smoke_model_routing_assertions.test.cjs Expands realistic assertion coverage.
.github/​workflows/​smoke-pi-routed.md Restricts routed models to Luna.
.github/​workflows/​smoke-pi-routed.lock.yml Regenerates the compiled workflow.

🧠 Review effort: Balanced


💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +188 to +190
if (subAgents.length) {
const overlapping = subAgents.filter(agent => allowed.has(servedModel(agent.model)));
if (overlapping.length)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in d4d3b24. C1 now also fails when two declared sub-agents share a normalized model, for example FAIL C1 declared sub-agents share a model: claude-haiku-4.5 (haiku-whoami, mini-whoami); each sub-agent must declare a distinct model. When a config both overlaps allowed-models and has a duplicate model, both problems are reported in the same C1 line. A new test covers duplicates that only match after normalization (claude-haiku-4.5 vs copilot/claude-haiku-4-5-20251001).

@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.

Unable to submit full review body from the sandbox.

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 45.8 AIC · ⌖ 5.33 AIC · ⊞ 21.2K
Comment /review to run again

@SivaKesava1

Copy link
Copy Markdown
Collaborator

Ran the three routing smokes on this PR's code (f08249c) by adding the smoke-routing label. They started without needing workflow approval, and all three pass with every job green:

  • Smoke Copilot Routed 38111946761: R1-R4 pass (4 main-agent requests on gpt-5.6-luna /responses).
  • Smoke Pi Routed 38111946869: C1, R1-R4, and S1-S3 for haiku-whoami (claude-haiku-4.5 /v1/messages 200) and mini-whoami (gpt-5.4-mini /responses 200).
  • Smoke Copilot SDK Routed 38111946778: C1, R1-R4, M1 (all on /responses), and S1-S4 for haiku-whoami (claude-haiku-4.5 /chat/completions 200, declared name on events).

On the two open review threads:

  • Follow-up, small: C1 and duplicate sub-agent models (copilot-pull-request-reviewer). Valid: if two declared sub-agents share a normalized model, one request can satisfy both S3 checks. Please extend C1 to also fail when two declared sub-agents share a normalized model, with a test. The current smokes use distinct models, so nothing else changes.
  • Keep: request-ID/agent-ID correlation (yagni thread). The issue asked for it so that a real correlation takes precedence as soon as AWF or gh-aw records one, and it's covered by tests. Please reply on that thread and leave the code.

@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 (root-cause bug fix) and /tdd (test rebuild). The fix correctly diagnoses the root cause — AWF never writes purpose: "agent"/"subagent", only purpose: "routing_classification" for the classifier — and switches to model-based attribution with session-correlation fallback. Comprehensive negative-variant tests were rebuilt from real production fixtures (runs 38097181601/38096990663/38100426674), covering dated model IDs, query-string endpoints, empty-request failure modes, and the new C1 disjointness check.

📋 Key Themes & Highlights

Key Themes

  • One actionable correctness gap: model-based attribution (attributed in smoke_model_routing_assertions.cjs) doesn't guard against two declared sub-agents sharing the same model — left an inline comment with a concrete fix suggestion (extend C1, or add a regression test documenting the behavior).

Positive Highlights

  • ✅ Root cause correctly diagnosed against real AWF record shapes, not just symptom patched
  • ✅ Test suite rebuilt against actual production fixtures rather than synthetic approximations, closing the gap that let the original bug ship
  • ✅ New C1 check and empty-request failure modes (R3/R4/M1/S3) add real coverage that was previously silently passing on zero requests
  • ✅ Doc comment at the top of the file clearly explains the new attribution model for future maintainers

No blocking issues; approving with one actionable suggestion for the author to consider.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · 99.8 AIC · ⌖ 14.6 AIC · ⊞ 10.3K
Comment /matt to run again

});
const correlatedRequests = new Set(subAgentEvidence.flatMap(evidence => evidence.correlated));
const attributed = subAgentEvidence.map(evidence => (evidence.correlated.length ? evidence.correlated : agentTraffic.filter(request => !correlatedRequests.has(request) && servedModel(request.model) === evidence.model)));
const subagentRequests = new Set(attributed.flat());

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] Model-based attribution doesn't guard against two declared sub-agents sharing the same model — both would independently claim the same uncorrelated request via servedModel(request.model) === evidence.model, so each sub-agent's S3 check could pass on a request that actually belongs to the other.

💡 Why this matters and a suggested fix

subAgentEvidence is built per-agent (line 237), and when correlation is empty each entry independently filters agentTraffic by its own declared model (line 247). If two subAgents entries declare the same model, the same proxy record(s) would appear in both attributed[i] and attributed[j], letting S3 "pass" for both even though only one sub-agent actually made that call. C1 only checks sub-agent models against allowedModels, not sub-agent models against each other, so this slips through today.

Current workflows (smoke-pi-routed.md) happen to declare disjoint sub-agent models, so this doesn't manifest yet, but the new attribution logic makes it a latent correctness gap in a check that's meant to be deterministic evidence. Consider either:

  • extending C1 to also fail when two declared sub-agents share a model, or
  • adding a regression test that exercises duplicate sub-agent models and documents the current (ambiguous) behavior if it's intentionally out of scope.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in d4d3b24. C1 now fails when two declared sub-agents share a normalized model, so the same request can no longer count toward two sub-agents' S3 checks. A new regression test covers this.

Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>

This branch has not been deployed

No deployments
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.

Routing smokes fail on main: assertion helper filters on purpose values AWF never writes

3 participants