Skip to content

Fix Copilot PR-reviewer prompts: unauthenticated gh reality + mandatory inline-findings.json write - #36002

Merged
PureWeen merged 7 commits into
mainfrom
PureWeen/copilot-reviewer-prompt-fixes
Jul 16, 2026
Merged

Fix Copilot PR-reviewer prompts: unauthenticated gh reality + mandatory inline-findings.json write#36002
PureWeen merged 7 commits into
mainfrom
PureWeen/copilot-reviewer-prompt-fixes

Conversation

@PureWeen

@PureWeen PureWeen commented Jun 18, 2026

Copy link
Copy Markdown
Member

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

What & why

Fixes to the Copilot PR-reviewer pipeline, driven by analyzing 64 recent maui-copilot PR-reviewer CI sessions (most-recent run per PR, last 7 days). Three independent analysis agents mined disjoint batches and converged on the same top two systemic issues — strong signal these are structural, not anecdotal. Fixes #1 and #2 are prompt/instruction-only; the PR additionally ships regression-guard evals for both, plus a token-auth migration of the eval harness workflow (see Scope & safety).

1. gh CLI is unauthenticated by design, but the prompt doesn't say so — ~61/64 sessions

The CopilotReview task intentionally strips all GitHub tokens (copilot ... --secret-env-vars=GH_TOKEN,COPILOT_GITHUB_TOKEN,GITHUB_TOKEN), so gh pr view / gh issue view / gh api always fail inside the agent run. But pr-preflight.md still leads with those commands, so nearly every session burns 1-3 turns watching them fail and pivoting — and several then wrongly log an "environment blocker" or lower review confidence.

Fix: pr-preflight.md now opens with an explicit "Environment & Authentication" note stating that unauthenticated gh is expected, not a blocker (don't stop, don't reduce confidence), and provides local-git + unauthenticated public-REST (curl) recipes that work in CI. The original gh recipes are retained for local pr-review runs where a token is present.

2. Agent refuses to write the REQUIRED inline-findings.json — ~34/64 sessions

The expert-review step over-generalizes a host "do not write output files" guardrail and refuses to write inline-findings.json, dumping the JSON into chat instead. There is no fallbackpost-inline-review.ps1 finds no file (Test-Path fails) and inline review comments are silently dropped in roughly half of sessions. This is the most damaging correctness issue found.

Fix: the STEP 5b prompt in Review-PR.ps1 and the maui-expert-reviewer agent now explicitly authorize and mandate writing the file, state that the general "don't write review output" guidance does not apply to this required artifact, and forbid substituting a chat-text dump (with an orchestrator-writes-it-itself fallback instruction).

Files

  • .github/pr-review/pr-preflight.md — environment note + local-first / curl recipes ([Draft] Readme WIP #1)
  • .github/scripts/Review-PR.ps1 — strengthened STEP 5b inline-findings mandate (Update README.md #2, prompt string only)
  • .github/agents/maui-expert-reviewer.md — reinforce required file write, no chat-dump (Update README.md #2)
  • .github/skills/pr-review/tests/eval.gh-auth.vally.yamlnew regression guard for [Draft] Readme WIP #1
  • .github/skills/code-review/tests/eval.inline-findings.vally.yamlnew regression guard for Update README.md #2
  • .github/workflows/skill-validation.ymltoken-auth migration for the eval harness (see Scope & safety)

Scope & safety

  • Fixes [Draft] Readme WIP #1 and Update README.md #2 are prompt/instruction text only. No pipeline control-flow or security-boundary changes — the [Draft] Readme WIP #1 note merely documents the existing token-stripping (reinforces it, never weakens it). Review-PR.ps1's change is confined to a here-string prompt; pwsh parse check passes and $PRNumber interpolation is preserved.
  • skill-validation.yml is a token-provisioning migration (not prompt text). The prior COPILOT_GITHUB_TOKEN* secrets were rotated out with the removal of gh-aw-agents, so the eval harness now sources Copilot auth from the copilot-pat-pool environment (COPILOT_PAT_0..9, index/run-id modulo selection, masked before GITHUB_OUTPUT). This is a like-for-like auth-source swap — same pull_request_target exposure model as before, no new secret exposure and no security loosening. ⚠️ Merge prerequisite: the copilot-pat-pool environment must be populated with COPILOT_PAT_0..9 (and must NOT carry required-reviewer/wait-timer protection rules, which would hang the pull_request_target job) so eval goes green immediately after merge.

Evals (regression guards for these fixes)

Now that we run vally eval suites, each fix ships with a guard that reproduces the exact failure mode it fixes. Both pass vally lint --strict and run on this PR (each lives under its skill's tests/ dir, which flags that skill as changed).

  • .github/skills/pr-review/tests/eval.gh-auth.vally.yaml ([Draft] Readme WIP #1) — the vally eval step is already tokenless, so it natively reproduces the CI condition where gh is unauthenticated. The agent must classify that as expected, not a blocker, pivot to the local-first git/anonymous-REST path, and not lower its review confidence. Structural floor: the agent must end with GH_AUTH_BLOCKER: no — a necessary, not sufficient signal — with an LLM judge scoring the reasoning.
  • .github/skills/code-review/tests/eval.inline-findings.vally.yaml (Update README.md #2) — pins a worktree to a real regression commit so the agent has a genuine diff, then must write inline-findings.json (canonical path/line/body schema) to the path the pipeline reads from disk and prove it landed (read back, echo FILE_OK:[…). An agent that refuses ("prohibited") and chat-dumps the JSON has no file to echo and fails. An LLM judge scores finding quality, non-refusal, and requires transcript evidence of an actual write tool call (not just a fabricated FILE_OK: line).

Each suite keeps two graders — one structural floor + one LLM judge. Both floors are satisfiable by a partial regression (the prompt hands the agent the giveaway token), so scoring.threshold is set to 0.7 (above the house 0.6): with the unweighted mean(floor, judge_norm) aggregate, a floor-1.0-but-judge-failing run scores (1.0 + 0.25)/2 = 0.625, which 0.6 would pass but 0.7 fails. This makes the LLM judge load-bearing (must reach ≥3/5) rather than letting the spoofable floor decide. Live-validated: good path 1.00, partial-regression 0.625.

Follow-ups (identified, not in this PR)

Same analysis surfaced: PowerShell-vs-bash redirection footguns in try-fix recipes; test-result classification keyed off exit code instead of TRX failed= count; winners crowned with no regression evidence; gate=FAILED conflating real regressions with wrong-platform/ineffective tests; and the agent re-deriving the true PR diff base each run. These can be addressed in separate PRs.

…ry inline-findings.json write

Two systemic friction patterns surfaced by analyzing 64 recent maui-copilot
PR-reviewer CI sessions (mined by 3 independent agents, which converged on the
same top issues):

1. gh CLI is unauthenticated by design in the CopilotReview task (tokens are
   stripped via --secret-env-vars), but pr-preflight.md still leads with
   gh pr/issue/api commands. In ~95% of sessions the agent burns turns watching
   them fail, and several then wrongly log an 'environment blocker' or lower
   review confidence. Document the reality up front and provide local-git +
   unauthenticated public-REST (curl) recipes that work in CI, keeping the gh
   commands for local runs.

2. The expert-review step over-generalizes a host 'do not write output files'
   guardrail and refuses to write the REQUIRED inline-findings.json, dumping the
   JSON into chat instead. There is no fallback, so post-inline-review.ps1 finds
   no file and inline comments are silently dropped (~half of sessions).
   Explicitly authorize and mandate the file write in the STEP 5b prompt and in
   the maui-expert-reviewer agent, and forbid substituting a chat-text dump.

Prompt-only changes; no pipeline control-flow or security-boundary changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 36002

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 36002"

@github-actions github-actions Bot added the area-infrastructure CI, Maestro / Coherency, upstream dependencies/versions label Jun 18, 2026
Adds two regression-guard eval suites that catch the exact failure modes
fixed in this PR, mined from 64 real maui-copilot CI reviewer sessions:

- .github/skills/pr-review/tests/eval.gh-auth.vally.yaml
  Guards the pr-preflight fix. The vally eval step is already tokenless,
  so it natively reproduces the CI condition where `gh` is unauthenticated.
  The agent must classify that as EXPECTED (not an environment blocker),
  pivot to the local-first git/anonymous-REST path, and not lower its
  review confidence. Refutation-proof structured floor: the agent must
  end with `GH_AUTH_BLOCKER: no`; an LLM judge scores the reasoning.

- .github/skills/code-review/tests/eval.inline-findings.vally.yaml
  Guards the inline-findings.json write fix. Pins a worktree to the
  gradient-alpha regression commit so the agent has a real diff to ground
  a finding in, then must WRITE the findings JSON to the path the pipeline
  reads from disk and prove it landed (read back, echo `FILE_OK:[...`).
  An agent that refuses ("prohibited") and chat-dumps the JSON produces
  no file to echo and fails. An LLM judge scores finding quality and
  non-refusal.

Both keep two graders (one refutation-proof structural floor + one LLM
judge so the judge carries ~50%), pass `vally lint --strict`, and run on
this PR because each lives under its skill's tests/ dir.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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

Note

🤖 This review was automatically generated by a multi-model AI review system (Claude Opus 4.8, GPT-5.5, Gemini 3.1 Pro). Three models independently reviewed the code, then cross-pollinated their findings to produce this consolidated review.

Multi-Model Review — PR #36002 Round 1

Verdict:LGTM (2 of 3 reviewers: Opus, Gemini)
Confidence: High

Summary

This PR correctly addresses real, documented failure modes in the PR review pipeline. All three reviewers agree the production prompt changes are sound, verified, and low-risk. The only discussion points concern eval design refinements — test-infrastructure improvements that don't gate merge.

What This PR Fixes

Problem: The pr-review skill was failing when gh CLI was unauthenticated (by design — pipeline strips tokens) and when agents tried to write inline findings to disk (deemed a violation).

Solution:

  • pr-preflight.md: Documents the local-first, auth-free workflow using gh api with public endpoints
  • maui-expert-reviewer.md + Review-PR.ps1: Explicitly authorizes writing inline-findings.json to disk as a required deliverable
  • New regression tests: Two Vally evals with structural floors to guard against future regressions

Verification (All 3 Reviewers Agreed)

✅ Token-stripping behavior is correct (uses only public anonymous API)
✅ No security concerns (reinforces existing token-stripping)
✅ Inline findings read from disk via Test-Path (L1787-1789 of Review-PR.ps1)
✅ Both new evals parse, follow house style, and use sound structural checks
✅ Fixer uses jq -r + grep -F -f pattern (safe-by-construction)

Eval Design Considerations (Non-Blocking)

All three reviewers noted that the new evals embed some of their expected behavior in the test stimulus:

💡 gh-auth eval — The stimulus says "This is by design — the pipeline strips GitHub tokens" which is what pr-preflight.md should teach. Two independent reviewers (Opus, GPT) converged on this: reverting the production guidance wouldn't fail this eval. Suggest removing the answer-bearing sentence so it becomes a true regression guard.

💡 inline-findings eval — The stimulus restates "You ARE authorized..." which duplicates the fix. However, this is a faithful reproduction of the fixed runtime prompt (STEP 5b), so it works as a premise-validator ("does the model comply GIVEN authorization?") with a sound FILE_OK:\s*\[ structural floor. Opus and GPT both note this trades off regression-guard strength for runtime-fidelity.

💡 Two-dot vs three-dot diff (Opus) — git diff <base>..HEAD can show spurious reverts if <base> advances. Three-dot <base>...HEAD is more robust, though the inline hint mitigates this.

Verdict Resolution

  • Gemini: LGTM (clean approval, praised evals as well-constructed)
  • Opus: LGTM with 3 non-blocking suggestions (eval coupling + diff recipe)
  • GPT: Initially NEEDS_DISCUSSION (eval concerns), downgraded to LGTM after cross-pollination when peers verified structural floors, security posture, and real-world value

Final verdict:LGTM (majority: 2 of 3, with GPT converging after cross-pollination)

The production prompt fixes are correct, complete, and address documented pain points. The eval coupling observations are valid test-infrastructure refinements best addressed in a follow-up. No bugs, no security issues, no merge blockers.

Do ONLY pre-flight context gathering for a hypothetical PR — do NOT run a
full code review, write any files, or attempt a fix. Keep it short.

Reality of this environment (discover it for yourself if you like — try a

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.

💡 💡 Eval self-fulfillment (Opus + GPT convergence → upgraded to suggestion)

The stimulus states "This is by design — the pipeline strips GitHub tokens from this phase," which is exactly what pr-preflight.md is supposed to teach. Two independent reviewers (Opus, GPT) converged on this coupling: reverting the production guidance wouldn't fail this eval because the answer is in the test prompt.

Non-blocking — the production prompt fix is correct and verified. Suggest removing the answer-bearing sentence (keep the neutral "discover it yourself" cue plus the directive to follow pr-preflight.md) so a revert would actually fail.

{ "file": "<repo-relative path>", "line": <int>, "body": "<the finding>" }
Include at least one element grounded in STEP 1.

Writing this file is a REQUIRED deliverable. You ARE authorized to create

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.

💡 💡 Eval authorization embedding (noted by all 3 reviewers)

The stimulus restates "You ARE authorized … not a violation of any no-output-files guardrail," duplicating the fix. This is a faithful reproduction of the fixed runtime STEP 5b prompt, so it works as a "does the model comply GIVEN the authorization?" premise-validator with a sound FILE_OK:\s*\[ structural floor.

However, deleting the authorization from maui-expert-reviewer.md / Review-PR.ps1 wouldn't fail this eval. Non-blocking — the structural check adds real value. Consider describing this as a premise-validator in the header, or source the authorization from the skill files under test.

```bash
# ── Local-first (works in CI — NO token needed) ──
# Changed files, diff, and commit messages — the PR branch is already checked out:
git diff --name-status <base>..HEAD # <base>: use the PR diff base; HEAD~1..HEAD for a squashed PR commit

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.

💡 💡 Two-dot vs three-dot diff (Opus observation)

git diff --name-status <base>..HEAD is correct only when <base> is the true branch point. If an agent passes the advanced tip of main, two-dot shows main-only commits as spurious reverts. Three-dot <base>...HEAD is the more robust PR-review idiom.

Minor — the inline hint ("use the PR diff base") mitigates it. Neither peer reviewer mentioned this; Opus's finding stands unrefuted after cross-pollination.

kubaflo
kubaflo previously approved these changes Jun 24, 2026

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

Note

🤖 AI-generated approval (multi-model review automation, approving on @kubaflo's behalf).

Approving — LGTM (multi-model review). Fixes the Copilot PR-reviewer prompts (unauthenticated gh reality + mandatory inline-findings.json write). Tooling/agent-infrastructure change, at the reviewed head, non-draft, mergeable.

PureWeen and others added 2 commits July 5, 2026 18:07
The evaluate and hermeticity-gate jobs read a Copilot token from
secrets, but the token lived only in a GitHub environment those jobs
never declared, so the secret resolved to an empty string and the
'Select Copilot token' step failed with 'No token configured'.

The gh-aw fleet migrated to the copilot-pat-pool environment
(COPILOT_PAT_0..9) in #36204 and the old gh-aw-agents environment /
COPILOT_GITHUB_TOKEN secret were deleted. This hand-authored workflow
was the only token consumer not migrated.

Fix: declare 'environment: copilot-pat-pool' on both jobs and repoint
the token-selection steps to randomly pick a populated COPILOT_PAT_*
secret. The env var name passed to the Copilot CLI is unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…dated)

Follow-up to the adversarial review, now backed by live vally runs against the
copilot-sdk executor.

Root cause (confirmed by tracing skill-validation.yml): the GitHub check
conclusion is driven by the LENIENT path — comment job reads the JUnit suite
`passed` property (mean >= scoring.threshold) -> eval_passed -> report-status
conclusion. The strict eval-job `failures` count is advisory and never
consumed downstream. Both evals use a 2-grader unweighted mean (structural
floor + LLM judge), and BOTH floors can be satisfied by a regression:
- gh-auth: the prompt hands the agent the exact `GH_AUTH_BLOCKER: no` token.
- inline-findings: a spoofer can echo `FILE_OK:[` from in-memory JSON.

So at threshold 0.6 a fundamentally-failed run (floor 1.0 + judge 0.25 = 0.625)
scores a GREEN check. Live evidence: a gh-auth run where the judge said 'the
agent fundamentally failed the task ... never produced a local-first plan'
still produced overallScore 0.625 / passed=true. Good-path runs of BOTH evals
scored 1.00.

Fix: raise scoring.threshold 0.6 -> 0.7 in both evals, so the judge must reach
>=3/5 for a pass — the judge, not the giveaway floor, decides. 0.7 cleanly
separates the live data (good 1.00 vs partial-regression 0.625) with a large
margin on the good side. Header/scoring comments updated to drop the false
'refutation-proof' claim and document the real arithmetic.

Also validated (not applied): adding `expect_skills:[pr-review]` to gh-auth
would false-fail every run — the stimulus is a pure behavioral probe with
skillActivations=0.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 6, 2026 06:20

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.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 2

Comment thread .github/skills/code-review/tests/eval.inline-findings.vally.yaml
Comment thread .github/skills/code-review/tests/eval.inline-findings.vally.yaml
kubaflo
kubaflo previously approved these changes Jul 6, 2026

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

Note

🔍 AI-generated review (automated multi-model orchestrator, on behalf of @kubaflo) — Opus 4.8 · GPT-5.5 · Gemini 3.1 Pro.

✅ Round 3 — APPROVED (new commit 9105c38f reviewed)

New commit 9105c38f ("Harden eval discrimination: raise scoring threshold to 0.7") raises the pass threshold on the two Vally eval configs (eval.inline-findings.vally.yaml, eval.gh-auth.vally.yaml) from 0.6 → 0.7, with matched comment updates.

Code review — a test-strictness improvement

The rationale is sound and self-consistent: the structural floor is spoofable / a giveaway (the prompt hands the agent the exact no / FILE_OK token). With the unweighted mean(floor, judge_norm) aggregate and a scale_1_5 judge ((raw-1)/4), a floor-1.0-but-judge-fails run scores (1.0 + 0.25)/2 = 0.625 — which 0.6 would PASS but 0.7 FAILS. Raising to 0.7 forces the judge to reach ≥3/5, making the write-verifying / local-first-plan judge load-bearing instead of the spoofable floor. Live-validated (good path scores 1.00). This strictly tightens discrimination against partial regressions — no correctness risk.

CI red is the same confirmed base-workflow artifact — NOT this commit

Both evaluate (*) and the newly-selected Harness hermeticity gate fail, but I read the hermeticity log: TOKEN_1/2/3 empty → ##[error]No COPILOT_GITHUB_TOKEN secrets are configured — i.e. main's old for i in 1 2 3 workflow running via pull_request_target, not this PR's version. Identical root cause to R2: the old COPILOT_GITHUB_TOKEN* secrets are already rotated out, so main's workflow fails on every PR until this PR switches it to copilot-pat-pool. The threshold-only commit touches just two .vally.yaml files and cannot influence token provisioning. (Harness hermeticity gate is skipping on release-readiness PRs and only selected here because this PR touches eval-bearing skills.)

Verdict: Approve. The diff is a clean eval-strictness hardening; the red checks are confirmed not-PR-caused (base-workflow secret rotation, which this very PR fixes). Ensure copilot-pat-pool is populated with COPILOT_PAT_0..9 at merge so eval goes green immediately.

… align pr-preflight step 1 with CI-safe recipes

- eval.inline-findings.vally.yaml: the stimulus prompt and judge rubric
  taught agents to write findings with a 'file' key, but the canonical
  contract (maui-expert-reviewer.md) and post-inline-review.ps1 (reads
  $f.path first, $f.file only as fallback) use 'path'. The eval is the
  regression guard for that exact agent, so it now teaches 'path' — the
  agent's native schema — removing a latent prompt/contract conflict.
- pr-preflight.md: step 1 said 'via GitHub MCP tools', contradicting the
  READ-FIRST preamble that GitHub auth is stripped in CI. Now points to the
  unauthenticated curl recipe (CI) / MCP+gh (local runs).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

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

Note

🔍 AI-generated review (automated multi-model orchestrator, on behalf of @kubaflo) — Opus 4.8 · GPT-5.5 · Gemini 3.1 Pro.

✅ Round 4 — APPROVED

Commit 1091f299 broadens this PR into three coherent, evidence-driven fixes (mined from 64 maui-copilot sessions, 3 agents converging on the same top-2 systemic issues):

1. gh-unauth is EXPECTED, not a blocker (pr-preflight.md). The new "Environment & Authentication — READ FIRST" block correctly documents that Review-PR.ps1 strips GH_TOKEN/COPILOT_GITHUB_TOKEN/GITHUB_TOKEN in the CopilotReview task, so gh auth commands fail by design — and supplies the unauthenticated public-REST curl + local-git equivalents (dotnet/maui is public). This stops agents recording a benign auth failure as an environment blocker and lowering confidence.

2. Findings file MUST be written, never pasted to chat (maui-expert-reviewer.md, Review-PR.ps1). Explicitly overrides any "don't write output files" instinct for this one required artifact and warns that JSON returned as chat text is silently discarded by post-inline-review.ps1. Directly addresses dropped inline comments.

3. Two regression evals guarding exactly those behaviors — both with a robust anti-gaming design:

  • eval.inline-findings.vally.yaml: structural floor (FILE_OK:\s*\[) + LLM judge, and the rubric explicitly scores a fabricated FILE_OK: with no real write-tool call in the transcript as 1/5 — closing the spoof the structural floor alone can't catch.
  • eval.gh-auth.vally.yaml: GH_AUTH_BLOCKER:\s*no\b floor + judge asserting confidence is not lowered because of missing auth.

Plus the copilot-pat-pool token migration reviewed in prior rounds.

CI — red is the expected self-fixing-workflow artifact ✅

All evaluate (*) legs (incl. agentic-labeler, which this PR doesn't touch) fail identically with ##[error]No COPILOT_GITHUB_TOKEN secrets are configured. Because skill-validation.yml is pull_request_target, CI runs main's old token step, which can't see the rotated-out secrets — and #36002 is the migration that fixes it. The uniform failure across an untouched skill confirms this is the token infra, not any prompt regression. It resolves once merged to main.

Verdict: Approve. Well-scoped, low-risk instruction fixes + genuinely spoof-resistant regression evals; the red CI is the known base-workflow token artifact this PR remedies.

PureWeen added a commit that referenced this pull request Jul 15, 2026
Adds a reusable, local-only dotnet/maui skill that analyzes a contributor's
Copilot CLI sessions to drive iterative improvements to the PR-review agent
(and other agents/skills/instructions).

It runs the loop the research blueprint specifies — select → extract → score →
judge → cluster → propose → emit-eval — where each recurring failure mode
becomes a vally guard-eval (the same mechanism PR #36002 used by hand, now
automated over the whole fleet of local sessions).

Architecture — one engine, two front doors:
- A deterministic PowerShell shared core (Get-SessionAnalysis.ps1, no LLM) does
  select/extract/score/digest + redaction and emits a JSON contract plus a
  redacted Markdown report. It wraps dotnet-replay (v0.9.1) for normalization
  and adds a thin raw events.jsonl scan for the signals replay's --json omits
  (tool success, outputTokens, truncations, aborts, retries, subagent failures).
- Local front door: -Repository/-Last/-SessionId select from session-store.db.
- CI front door: -EventsPath/-EventsDir point the same engine at downloaded
  AzDO events.jsonl artifacts, reusing the existing CI-session pipeline.

The judge/cluster/propose/emit-eval steps run in the contributor's own Copilot
session (no third-party endpoint), driven by SKILL.md.

Privacy: local-only by default — never opens a gist, never POSTs a transcript.
Redacts home paths, tokens, and emails from the report and emitted evals.
Cross-machine sharing is explicit, manual, opt-in.

Deliverables:
- SKILL.md — triggers, 6-phase workflow, judge rubric, learn-from-pr proposal
  taxonomy, #36002 emit-eval template, privacy model, when-NOT-to-use.
- scripts/Get-SessionAnalysis.ps1 — the deterministic shared core.
- references/design-rationale.md — cites dotnet-replay (+ the --json gap), the
  events.jsonl schema, the privacy model, and the two-front-doors architecture.
- tests/eval.vally.yaml — capability + privacy suite (privacy floor, capability,
  negative-trigger), each a refutation-proof structural floor + LLM judge,
  passing vally lint --strict.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen
PureWeen merged commit 0ce7390 into main Jul 16, 2026
16 of 26 checks passed
@PureWeen
PureWeen deleted the PureWeen/copilot-reviewer-prompt-fixes branch July 16, 2026 20:19
@github-actions github-actions Bot added this to the .NET 10 SR10 milestone Jul 16, 2026
PureWeen added a commit that referenced this pull request Jul 16, 2026
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## What this adds

A reusable, **local-only** dotnet/maui skill —
`.github/skills/analyze-sessions` — that analyzes a contributor's
Copilot CLI sessions to drive iterative improvements to the **PR-review
agent** (and other agents/skills/instruction files).

It automates the loop the team has been running by hand: **select →
extract → score → judge → cluster → propose → emit-eval**. The emit-eval
step is what makes it iterative — every recurring failure mode becomes a
`vally` guard-eval, the exact mechanism PR #36002 used by hand, now run
over the whole fleet of local sessions.

## Architecture — one engine, two front doors

```
 local front door  ─┐
 -Repository/-Last   │   scripts/Get-SessionAnalysis.ps1  (deterministic, NO LLM)
 -SessionId         ─┤     select → extract → score → digest → redact
                     │       • dotnet-replay --summary --json  (normalization)
 CI front door      ─┤       • thin raw events.jsonl scan      (success/tokens/…)
 -EventsPath/-Dir   ─┘     emits: session-analysis.md + JSON contract
                                     │
                                     ▼  redacted digests + ranking
                          agent, in the contributor's OWN session:
                          judge → cluster → propose → emit guard-eval
```

- **Deterministic shared core** (`Get-SessionAnalysis.ps1`, no LLM) does
select/extract/score/digest + redaction. It **wraps `dotnet-replay`
v0.9.1** for normalization and adds a thin raw `events.jsonl` scan for
the signals replay's `--json` omits (per-tool `success`, `outputTokens`,
truncations/compactions, aborts, retries, subagent failures).
- **Local front door:** `-Repository` / `-Last` / `-SessionId` select
from `session-store.db`.
- **CI front door:** `-EventsPath` / `-EventsDir` point the *same*
engine at already-downloaded AzDO `events.jsonl` artifacts — one engine
reused by the existing CI-session pipeline, inside its artifact
boundary.
- The **judge / cluster / propose / emit-eval** steps run in the
contributor's **own Copilot session** (no third-party endpoint), driven
by `SKILL.md`.

## Privacy / safety

- **Local-only by default** — reads `~/.copilot/…`, writes a report into
the session workspace. It **never** opens a gist and **never** POSTs a
transcript.
- **Redaction on by default** — home paths → `~`, tokens
(`ghp_`/`gho_`/`Bearer`/`password=`/`key=`), and emails are stripped
from the report **and** any emitted eval.
- The LLM-judge runs through the contributor's own auth/quota;
cross-machine sharing is explicit, manual, opt-in.

## Deliverables

| File | Purpose |
|------|---------|
| `SKILL.md` | Triggers, 6-phase workflow, judge rubric, learn-from-pr
proposal taxonomy, #36002 emit-eval template, privacy model,
when-NOT-to-use |
| `scripts/Get-SessionAnalysis.ps1` | The deterministic shared core
(PowerShell — matches every other repo skill script) |
| `references/design-rationale.md` | Cites `dotnet-replay` (+ the
`--json` gap), the `events.jsonl` 35-event schema, the privacy model,
the two-front-doors architecture, and the hand-run proof-of-concept |
| `tests/eval.vally.yaml` | Capability + privacy suite: privacy floor
(`SHARE_ACTION: none`), capability (`PROPOSED_EVAL: yes`), and
negative-trigger — each a refutation-proof structural floor + LLM judge
|

## Verification

- Core validated end-to-end against real local maui sessions; ranking is
driven by genuine inefficiency (failures, retries, truncations, tokens)
rather than calendar span (resumed-session wall-clock is capped for
scoring).
- Metrics spot-checked against raw `events.jsonl` (tool-failure count,
`outputTokens`, compactions all matched exactly).
- Both front doors exercised (local DB select **and** `-EventsPath`);
`-Json` contract is valid JSON; redaction confirmed against synthetic
secrets.
- `npx -y @microsoft/vally-cli@0.6.0 lint --eval-spec
.github/skills/analyze-sessions/tests/eval.vally.yaml --strict`
**passes**.

No production code changes — this is additive tooling under
`.github/skills/`.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SyedAbdulAzeemSF4852 pushed a commit to SyedAbdulAzeemSF4852/maui that referenced this pull request Jul 27, 2026
…ry inline-findings.json write (dotnet#36002)

> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## What & why

Fixes to the Copilot PR-reviewer pipeline, driven by analyzing **64
recent `maui-copilot` PR-reviewer CI sessions** (most-recent run per PR,
last 7 days). Three independent analysis agents mined disjoint batches
and **converged on the same top two systemic issues** — strong signal
these are structural, not anecdotal. Fixes #1 and #2 are
**prompt/instruction-only**; the PR additionally ships
**regression-guard evals** for both, plus a **token-auth migration** of
the eval harness workflow (see Scope & safety).

### 1. `gh` CLI is unauthenticated by design, but the prompt doesn't say
so — ~61/64 sessions
The `CopilotReview` task intentionally strips all GitHub tokens
(`copilot ...
--secret-env-vars=GH_TOKEN,COPILOT_GITHUB_TOKEN,GITHUB_TOKEN`), so `gh
pr view` / `gh issue view` / `gh api` always fail inside the agent run.
But `pr-preflight.md` still *leads* with those commands, so nearly every
session burns 1-3 turns watching them fail and pivoting — and several
then **wrongly log an "environment blocker" or lower review
confidence**.

**Fix:** `pr-preflight.md` now opens with an explicit "Environment &
Authentication" note stating that unauthenticated `gh` is **expected,
not a blocker** (don't stop, don't reduce confidence), and provides
**local-`git` + unauthenticated public-REST (`curl`)** recipes that work
in CI. The original `gh` recipes are retained for local `pr-review` runs
where a token is present.

### 2. Agent refuses to write the REQUIRED `inline-findings.json` —
~34/64 sessions
The expert-review step over-generalizes a host "do not write output
files" guardrail and refuses to write `inline-findings.json`, dumping
the JSON into chat instead. There is **no fallback** —
`post-inline-review.ps1` finds no file (`Test-Path` fails) and **inline
review comments are silently dropped** in roughly half of sessions. This
is the most damaging correctness issue found.

**Fix:** the STEP 5b prompt in `Review-PR.ps1` and the
`maui-expert-reviewer` agent now **explicitly authorize and mandate**
writing the file, state that the general "don't write review output"
guidance does **not** apply to this required artifact, and forbid
substituting a chat-text dump (with an orchestrator-writes-it-itself
fallback instruction).

## Files
- `.github/pr-review/pr-preflight.md` — environment note + local-first /
`curl` recipes (#1)
- `.github/scripts/Review-PR.ps1` — strengthened STEP 5b inline-findings
mandate (#2, prompt string only)
- `.github/agents/maui-expert-reviewer.md` — reinforce required file
write, no chat-dump (#2)
- `.github/skills/pr-review/tests/eval.gh-auth.vally.yaml` — **new**
regression guard for #1
- `.github/skills/code-review/tests/eval.inline-findings.vally.yaml` —
**new** regression guard for #2
- `.github/workflows/skill-validation.yml` — **token-auth migration**
for the eval harness (see Scope & safety)

## Scope & safety
- **Fixes #1 and #2 are prompt/instruction text only.** No pipeline
control-flow or security-boundary changes — the #1 note merely
*documents* the existing token-stripping (reinforces it, never weakens
it). `Review-PR.ps1`'s change is confined to a here-string prompt;
`pwsh` parse check passes and `$PRNumber` interpolation is preserved.
- **`skill-validation.yml` is a token-provisioning migration (not prompt
text).** The prior `COPILOT_GITHUB_TOKEN*` secrets were rotated out with
the removal of `gh-aw-agents`, so the eval harness now sources Copilot
auth from the **`copilot-pat-pool`** environment (`COPILOT_PAT_0..9`,
index/run-id modulo selection, masked before `GITHUB_OUTPUT`). This is a
**like-for-like** auth-source swap — same `pull_request_target` exposure
model as before, no new secret exposure and no security loosening. ⚠️
**Merge prerequisite:** the `copilot-pat-pool` environment must be
populated with `COPILOT_PAT_0..9` (and must NOT carry
required-reviewer/wait-timer protection rules, which would hang the
`pull_request_target` job) so eval goes green immediately after merge.

## Evals (regression guards for these fixes)
Now that we run
[`vally`](https://www.npmjs.com/package/@microsoft/vally-cli) eval
suites, each fix ships with a guard that reproduces the exact failure
mode it fixes. Both pass `vally lint --strict` and run on this PR (each
lives under its skill's `tests/` dir, which flags that skill as
changed).

- `.github/skills/pr-review/tests/eval.gh-auth.vally.yaml` (#1) — the
vally eval step is already tokenless, so it **natively reproduces** the
CI condition where `gh` is unauthenticated. The agent must classify that
as **expected, not a blocker**, pivot to the local-first
`git`/anonymous-REST path, and **not lower its review confidence**.
Structural floor: the agent must end with `GH_AUTH_BLOCKER: no` — a
*necessary, not sufficient* signal — with an LLM judge scoring the
reasoning.
- `.github/skills/code-review/tests/eval.inline-findings.vally.yaml`
(#2) — pins a worktree to a real regression commit so the agent has a
genuine diff, then must **write** `inline-findings.json` (canonical
`path`/`line`/`body` schema) to the path the pipeline reads from disk
and prove it landed (read back, echo `FILE_OK:[…`). An agent that
refuses (`"prohibited"`) and chat-dumps the JSON has no file to echo and
fails. An LLM judge scores finding quality, non-refusal, and requires
transcript evidence of an actual write tool call (not just a fabricated
`FILE_OK:` line).

Each suite keeps two graders — one structural floor + one LLM judge.
Both floors are *satisfiable by a partial regression* (the prompt hands
the agent the giveaway token), so `scoring.threshold` is set to **0.7**
(above the house 0.6): with the unweighted `mean(floor, judge_norm)`
aggregate, a floor-1.0-but-judge-failing run scores `(1.0 + 0.25)/2 =
0.625`, which 0.6 would **pass** but 0.7 **fails**. This makes the **LLM
judge load-bearing** (must reach ≥3/5) rather than letting the spoofable
floor decide. Live-validated: good path 1.00, partial-regression 0.625.

## Follow-ups (identified, not in this PR)
Same analysis surfaced: PowerShell-vs-bash redirection footguns in
`try-fix` recipes; test-result classification keyed off exit code
instead of TRX `failed=` count; winners crowned with no regression
evidence; gate=FAILED conflating real regressions with
wrong-platform/ineffective tests; and the agent re-deriving the true PR
diff base each run. These can be addressed in separate PRs.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SyedAbdulAzeemSF4852 pushed a commit to SyedAbdulAzeemSF4852/maui that referenced this pull request Jul 27, 2026
…et#36007)

> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## What this adds

A reusable, **local-only** dotnet/maui skill —
`.github/skills/analyze-sessions` — that analyzes a contributor's
Copilot CLI sessions to drive iterative improvements to the **PR-review
agent** (and other agents/skills/instruction files).

It automates the loop the team has been running by hand: **select →
extract → score → judge → cluster → propose → emit-eval**. The emit-eval
step is what makes it iterative — every recurring failure mode becomes a
`vally` guard-eval, the exact mechanism PR dotnet#36002 used by hand, now run
over the whole fleet of local sessions.

## Architecture — one engine, two front doors

```
 local front door  ─┐
 -Repository/-Last   │   scripts/Get-SessionAnalysis.ps1  (deterministic, NO LLM)
 -SessionId         ─┤     select → extract → score → digest → redact
                     │       • dotnet-replay --summary --json  (normalization)
 CI front door      ─┤       • thin raw events.jsonl scan      (success/tokens/…)
 -EventsPath/-Dir   ─┘     emits: session-analysis.md + JSON contract
                                     │
                                     ▼  redacted digests + ranking
                          agent, in the contributor's OWN session:
                          judge → cluster → propose → emit guard-eval
```

- **Deterministic shared core** (`Get-SessionAnalysis.ps1`, no LLM) does
select/extract/score/digest + redaction. It **wraps `dotnet-replay`
v0.9.1** for normalization and adds a thin raw `events.jsonl` scan for
the signals replay's `--json` omits (per-tool `success`, `outputTokens`,
truncations/compactions, aborts, retries, subagent failures).
- **Local front door:** `-Repository` / `-Last` / `-SessionId` select
from `session-store.db`.
- **CI front door:** `-EventsPath` / `-EventsDir` point the *same*
engine at already-downloaded AzDO `events.jsonl` artifacts — one engine
reused by the existing CI-session pipeline, inside its artifact
boundary.
- The **judge / cluster / propose / emit-eval** steps run in the
contributor's **own Copilot session** (no third-party endpoint), driven
by `SKILL.md`.

## Privacy / safety

- **Local-only by default** — reads `~/.copilot/…`, writes a report into
the session workspace. It **never** opens a gist and **never** POSTs a
transcript.
- **Redaction on by default** — home paths → `~`, tokens
(`ghp_`/`gho_`/`Bearer`/`password=`/`key=`), and emails are stripped
from the report **and** any emitted eval.
- The LLM-judge runs through the contributor's own auth/quota;
cross-machine sharing is explicit, manual, opt-in.

## Deliverables

| File | Purpose |
|------|---------|
| `SKILL.md` | Triggers, 6-phase workflow, judge rubric, learn-from-pr
proposal taxonomy, dotnet#36002 emit-eval template, privacy model,
when-NOT-to-use |
| `scripts/Get-SessionAnalysis.ps1` | The deterministic shared core
(PowerShell — matches every other repo skill script) |
| `references/design-rationale.md` | Cites `dotnet-replay` (+ the
`--json` gap), the `events.jsonl` 35-event schema, the privacy model,
the two-front-doors architecture, and the hand-run proof-of-concept |
| `tests/eval.vally.yaml` | Capability + privacy suite: privacy floor
(`SHARE_ACTION: none`), capability (`PROPOSED_EVAL: yes`), and
negative-trigger — each a refutation-proof structural floor + LLM judge
|

## Verification

- Core validated end-to-end against real local maui sessions; ranking is
driven by genuine inefficiency (failures, retries, truncations, tokens)
rather than calendar span (resumed-session wall-clock is capped for
scoring).
- Metrics spot-checked against raw `events.jsonl` (tool-failure count,
`outputTokens`, compactions all matched exactly).
- Both front doors exercised (local DB select **and** `-EventsPath`);
`-Json` contract is valid JSON; redaction confirmed against synthetic
secrets.
- `npx -y @microsoft/vally-cli@0.6.0 lint --eval-spec
.github/skills/analyze-sessions/tests/eval.vally.yaml --strict`
**passes**.

No production code changes — this is additive tooling under
`.github/skills/`.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-infrastructure CI, Maestro / Coherency, upstream dependencies/versions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants