Skip to content

Collapse issue triage into a single agentic workflow - #68616

Merged
DeagleGross merged 1 commit into
mainfrom
deaglegross-collapse-triage-reviewer
Aug 18, 2026
Merged

Collapse issue triage into a single agentic workflow#68616
DeagleGross merged 1 commit into
mainfrom
deaglegross-collapse-triage-reviewer

Conversation

@DeagleGross

Copy link
Copy Markdown
Member

Problem

The issue triage agent runs as two gh-aw workflows: issue-triage-agent (orchestrator) classifies the issue, applies the area label and issue type, drafts a triage comment, and hands that comment to triage-comment-reviewer (worker) via the call-workflow safe output. The worker re-reads the issue, decides whether the comment is safe to post, and posts it.

That handoff is broken by an upstream gh-aw bug. Evidence chain, from the artifacts of run 31985189298:

  1. The agent correctly emits a well-formed item into safeoutputs.jsonl:
    {"type":"call_workflow","workflow_name":"triage-comment-reviewer","inputs":{…}}
  2. The ingestion step sanitizes each item against a per-type field schema shipped in the lock file as the GH_AW_VALIDATION_JSON env var. That schema has an entry for dispatch_workflow but none for call_workflow, so every field is whitelist-stripped. The collected agent_output.json ends up as literally {"type":"call_workflow"}.
  3. call_workflow.cjs in the safe_outputs job reads message.workflow_name, finds it undefined, and logs Workflow name is empty.
  4. safe_outputs goes to failure, the call-triage-comment-reviewer job is skipped, and gh-aw files an [aw] Failed jobs: Issue Triage Agent issue.

Net effect since 2026-08-14: labels and issue type were applied, the triage comment was never posted, and every triaged issue produced a noise failure issue — 21 so far (e.g. #68569, #68610).

This is not fixable on our side. The validation schema is compiled into gh-aw's Go source (pkg/workflow/safe_outputs_validation_config.go, which lists dispatch_workflow but not call_workflow), there is no frontmatter override, and hand-patching the generated .lock.yml would be silently reverted by the next gh aw compile. The bug is still present on gh-aw main.

What changed

Collapse the two workflows into one.

  • issue-triage-agent.md: dropped the call-workflow safe output, added add-comment (max: 1, target: "*", hide-older-comments: true), so the orchestrator posts the comment itself. add_comment's validation schema does include item_number, so it is not affected by the same stripping bug. target: "*" is required because the workflow also supports workflow_dispatch, which carries no issue payload; the prompt instructs the agent to pass item_number explicitly on both trigger paths.
  • Step 7 rewritten from "hand off the comment" to "post the comment", preserving the ordering: decide labels → apply area + sub-type label → set-issue-type exactly once → remove needs-area-label → vulnerability gate → draft → add-comment.
  • Dry-run behaviour is now in one place: no labels/type applied, and the comment is posted with ### [DRY RUN] Triage Summary.
  • Deleted triage-comment-reviewer.md and triage-comment-reviewer.lock.yml.
  • issue-triage-agent.lock.yml regenerated with the pinned v0.86.2 compiler — the version already recorded in its metadata header — so there is no unrelated version-bump noise in the diff.

This also halves the number of runs per triaged issue and the corresponding PAT-pool pressure, and makes triage immune to this class of gh-aw orchestration bug.

Rules preserved, not dropped

Removing the reviewer workflow does not weaken the rules. They were ported into the orchestrator prompt, rewritten from second-pass-reviewer voice ("strip this from the draft") into first-pass author voice ("do not write this").

Ported:

  • The issue-level vulnerability-report gate (the reviewer's only genuinely additive rule) survives intact: all four indicator categories (CVE identifier pattern CVE-\d{4}-\d{4,} including the note that the sequence number is not fixed-width; specific exploit / attack vector / PoC; vulnerability-class language describing a reported attack; explicit security-fix request framed as such), the "independent of whether the vulnerability is actually in aspnetcore" rule with its three mis-filed examples, and the full "NOT a vulnerability report just because" carve-out. The consequence changes from "reviewer verdict FAIL" to: labels and issue type are still applied, but no comment is posted at all — noop instead, and not even a polite "this isn't aspnetcore" explanation.
  • The comment-level ban-list, reconciled against the orchestrator's existing "Never Include" list into one authoritative set with no duplicated or contradictory bullets: constructed security analysis (keeping the carve-out that factually restating the reporter's own framing is allowed), third-party infrastructure comparisons used as a hardening argument, label recommendations in the comment body, .NET version-status claims, editorialising about issue validity, speculation, the #### Notes content constraints, and the duplicate-citation rules.
  • Section-shape rules: if a section would be empty, omit its heading — except #### Potential Duplicates, which keeps its heading with - _None found_. Plus the rule against leaving fragments or dangling punctuation.
  • The conservative bias: "when in doubt, suppress", with its original rationale (a missing triage comment costs a maintainer minutes; a bad comment on a public thread is a lasting mistake, and the labels remain either way).

Deliberately dropped, all of which are reviewer-specific machinery for editing someone else's draft and carry no meaning when the author applies the rules while writing:

  • Stripping mechanics (A), (C) and (D) — whole-line deletion, blank-line collapsing, and trailing-punctuation cleanup. The one authoring-relevant part, "don't leave a fragment", was kept.
  • Mechanic (E) — "FAIL rather than invent replacement wording". Its premise is the remove-only constraint on a second pass.
  • The PASS / REWRITE / FAIL verdict vocabulary and the "take exactly one action" step, replaced by a direct add-comment-or-noop instruction.
  • The "more than ~30% stripped" heuristic and the "wholly fabricated comment" check — both are quality signals about another agent's output, which a single agent that just read the issue cannot meaningfully apply to itself. What they protected against is covered by the no-speculation and verified-citation rules.
  • "Do not announce that the comment was rewritten" — subsumed by the rule against meta-commentary.

Verification

Before, on main: 21 consecutive runs failed, each with ✗ Message N (call_workflow) failed: Workflow name is empty, safe_outputs at failure, call-triage-comment-reviewer skipped, and no comment posted. Example: run 31985189298 on #68569.

After, on this branch: two manual workflow_dispatch runs, both with every job at success including safe_outputs, and no call-triage-comment-reviewer job present in the run graph at all.

The triage orchestrator handed its drafted comment to the
triage-comment-reviewer worker via the call-workflow safe output. That
handoff is broken by an upstream gh-aw bug: the ingestion step sanitizes
safe-output items against a per-type field schema, and that schema has no
entry for call_workflow, so every field is stripped. The item arrives at
the handler as {"type":"call_workflow"}, the handler reads an undefined
workflow_name, and the safe_outputs job fails.

As a result the reviewer job has been skipped on every triaged issue since
2026-08-14: labels and issue type were applied but the triage comment was
never posted, and each run filed an [aw] failure issue (21 so far).

Collapse the two workflows into one. The orchestrator now posts the comment
itself via add-comment, whose validation schema does include item_number, so
it is not affected by the same bug. The reviewer's rules are preserved in
the orchestrator prompt: the vulnerability-report gate now suppresses the
comment (labels are still applied), and its comment-level ban-list is merged
with the orchestrator's existing content rules into one list.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5956f28f-dc84-4eba-9f9a-d2941bca8610
Copilot AI lite review requested due to automatic review settings August 18, 2026 09:20
@DeagleGross
DeagleGross requested review from a team and wtgodbe as code owners August 18, 2026 09:20
@DeagleGross DeagleGross self-assigned this Aug 18, 2026
@DeagleGross DeagleGross added the area-infrastructure Includes: MSBuild projects/targets, build scripts, CI, Installers and shared framework label Aug 18, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Hey @dotnet/aspnet-build, looks like this PR is something you want to take a look at.

@DeagleGross
DeagleGross enabled auto-merge (squash) August 18, 2026 09:22

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

This PR collapses the issue triage automation from a two-workflow orchestrator/worker model into a single workflow so the triage agent can post its own comment directly, avoiding the upstream gh-aw sanitizer bug that strips call_workflow payload fields.

Changes:

  • Remove the separate triage-comment-reviewer workflow (and its lock file) and stop handing off triage comments via call_workflow.
  • Update issue-triage-agent to post the triage summary via an add_comment safe output and to suppress comments entirely for vulnerability-report issues.
  • Regenerate issue-triage-agent.lock.yml to reflect the new safe outputs and job graph.
Show a summary per file
File Description
.github/workflows/triage-comment-reviewer.md Deleted: removes the second-pass triage comment reviewer workflow.
.github/workflows/triage-comment-reviewer.lock.yml Deleted: removes the compiled lock workflow for the reviewer.
.github/workflows/issue-triage-agent.md Updated: agent now posts the triage comment itself via safe outputs and includes a vulnerability-report comment suppression gate.
.github/workflows/issue-triage-agent.lock.yml Updated: regenerated compiled workflow to remove call_workflow and add add_comment handling.

Review details

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

Suppressed comments (2)

.github/workflows/issue-triage-agent.md:668

  • The narrative instructions refer to add-comment, but the safe output tool name emitted by gh-aw is add_comment (underscore). Using the wrong name in this key decision point increases the risk of the agent emitting an invalid tool call and skipping comment posting/suppression. Recommend updating these instructions to consistently use add_comment when referring to the tool invocation.
5. **Apply the vulnerability gate.** If the issue is a vulnerability report
   per "Vulnerability Reports: Apply Labels, But Post No Comment" above,
   stop here: call `noop` and do **not** call `add-comment`. The labels and
   issue type you applied in steps 2–4 stay in place. Otherwise continue.

.github/workflows/issue-triage-agent.md:703

  • Same tool-name mismatch in the No-op fallback section: the compiled tool is add_comment, but the text says add-comment. Aligning here too reduces the chance the agent emits an invalid call when choosing between noop and posting a comment.
Call the `noop` tool — and do **not** call `add-comment` — in either of
these two cases:
  • Files reviewed: 3/4 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment on lines +219 to +222
**If the issue IS a vulnerability report:** still apply the area label, the
sub-type label, and the issue type exactly as you normally would (Step 7,
items 1–4), then **post no comment at all**. Skip Step 6, do **not** call
`add-comment`, and call `noop` instead:
@DeagleGross
DeagleGross merged commit a3f9cbd into main Aug 18, 2026
34 checks passed
@DeagleGross
DeagleGross deleted the deaglegross-collapse-triage-reviewer branch August 18, 2026 09:39
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-infrastructure Includes: MSBuild projects/targets, build scripts, CI, Installers and shared framework

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants