After mcs-lab-issue-filer has filed (or commented on) the audit issue for a lab, apply the findings' suggested_correction diffs to the lab markdown and copy any proposed_screenshot_replacement images into labs/<slug>/images/. If an OPEN fix-PR for this slug already exists (same author, mergeable), append the commit to it; otherwise open a NEW PR on a run-unique branch `{branch_prefix}/fix-<slug>-content-audit-<run-id>`. Title `<slug>: fix audit findings from #<issue-number>`, body `Closes #<issue-number>`. Dedup is scoped to OPEN PRs only — a merged or closed prior PR never blocks a new one. Should NOT be invoked directly by the user — the orchestrator calls it after mcs-lab-issue-filer returns the issue number.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
After mcs-lab-issue-filer has filed (or commented on) the audit issue for a lab, apply the findings' suggested_correction diffs to the lab markdown and copy any proposed_screenshot_replacement images into labs/<slug>/images/. If an OPEN fix-PR for this slug already exists (same author, mergeable), append the commit to it; otherwise open a NEW PR on a run-unique branch `{branch_prefix}/fix-<slug>-content-audit-<run-id>`. Title `<slug>: fix audit findings from #<issue-number>`, body `Closes #<issue-number>`. Dedup is scoped to OPEN PRs only — a merged or closed prior PR never blocks a new one. Should NOT be invoked directly by the user — the orchestrator calls it after mcs-lab-issue-filer returns the issue number.
Apply the audit's suggested corrections to the actual lab files in the active instance's repo ({repo}), then either open a new fix-PR on a run-unique branch or append to the lab's existing open fix-PR — whichever the dedup check resolves — and close (or reference) the audit issue.
PR dedup is scoped to OPEN PRs only. A merged or closed prior PR for the same lab never blocks a new one — each audit run that finds new problems gets its own PR. The only thing that suppresses a new PR is an already-open fix-PR for the same slug, in which case this run's fixes are appended to that PR instead of opening a duplicate. See [[feedback_fresh_branch_per_pr]].
Inputs (assumed present from the orchestrator)
runs/<run-id>/labs/<slug>/findings.json — same file the issue-filer read.
runs/<run-id>/labs/<slug>/screenshots/proposed/ — proposed replacement images keyed to findings[*].proposed_screenshot_replacement_for paths.
issues.pr_append.pr_branch_pattern (default {branch_prefix}/fix-{slug}-content-audit-{run_id}) — the run-unique branch name to CREATE when no open PR exists.
issues.pr_append.pr_match_head_prefix (default {branch_prefix}/fix-{slug}-content-audit) — the head-ref prefix used to find an existing open PR for the slug regardless of its run-id suffix.
runs/<run-id>/existing-state.yml — the orchestrator's Phase 1.4 probe. labs[<slug>].open_pr is non-null when an open fix-PR already exists for the slug.
the resolved clone of {repo} (from Resolve-LabRepo.ps1 -Instance).
issue_number — returned by mcs-lab-issue-filer. Required.
lab_slug, run_id — passed through.
Outputs
Either a new run-unique branch {branch_prefix}/fix-<slug>-content-audit-<run-id> on the active instance's repo ({repo}), OR a new commit on the existing open PR's branch — never both.
New or updated PR titled <slug>: fix audit findings from #<issue-number> with body containing Closes #<issue-number>.
runs/<run-id>/labs/<slug>/pr-url.txt — convenience file for the orchestrator's summary.
cd C:\Users\dewainr\mcs-labs
git fetch origin main
If there are uncommitted changes in the working tree, stash them with a clear label and restore the user's prior HEAD. (Never clobber unrelated in-flight work.)
2. Resolve the PR target — append to an open PR, else open a new one
Dedup is scoped to OPEN PRs only. First find whether an open fix-PR already exists for this slug; if so, append to it; otherwise open a brand-new PR on a run-unique branch. A merged or closed prior PR is irrelevant — it never blocks a new PR.
2a. Find an existing open PR for the slug.
If the orchestrator's probe wrote runs/<run-id>/existing-state.yml.labs[<slug>].open_pr (non-null), use it directly — it already carries number, branch (the actual head ref, run-id suffix and all), author, and mergeable.
Otherwise, query directly by head prefix (matches any run's branch for this slug), most-recently-updated first:
If the head query returns nothing, fall back to a title match: --search "\"<slug>: fix audit findings\" in:title". Only OPEN PRs count.
2b. If an open PR was found → append.
Verify it's authored by the current gh user (pr_append.require_same_author) and mergeable (pr_append.require_mergeable).
If guardrails pass: git fetch origin, then gh pr checkout <number> --repo {repo} (checks out the PR's actual branch whatever its name). Confirm with git rev-parse --abbrev-ref HEAD. Set pr_action: appended and remember <branch> = that head ref.
If guardrails fail (different author, or CONFLICTING): abort the PR step (the orchestrator records this as a soft failure: issue was filed but the open PR could not be appended; the user is told to inspect the PR). Do NOT open a competing second PR for the same lab.
2c. If no open PR exists → open a new one on a run-unique branch.
Render the create pattern: branch = {branch_prefix}/fix-<slug>-content-audit-<run-id> (from judge-config.yml.issues.pr_append.pr_branch_pattern, substituting {branch_prefix}, {slug}, and {run_id}). The {run_id} suffix guarantees the name can't collide with a leftover branch from a merged/closed prior PR — so there is no need to rename or delete any stale branch.
git fetch origin main, then git checkout -b <branch> origin/main. Set pr_action: created.
3. Apply markdown corrections
For each finding in findings.json where outcome ∈ {broken, unclear} AND suggested_correction is non-null:
Read the lab file _labs/<slug>.md.
Apply a literal string replacement:
old_string = suggested_correction.original_text
new_string = suggested_correction.proposed_text
If the old_string is no longer present (the lab has changed since the audit), record {finding_id, applied: false, reason: original_text_not_found} in runs/<run-id>/labs/<slug>/pr-apply-log.json and continue with the next finding.
If the replacement would match in multiple places, prefer the location with the line number closest to finding.evidence.line_number if recorded; otherwise apply once at the first match and warn.
Some corrections span multiple lines or require reordering content (new UC, scene swap, etc.). Findings whose suggested_correction.scope == "scene" should NOT be auto-applied — leave them for human review and record {finding_id, applied: false, reason: scope_scene_requires_manual}.
4. Apply screenshot replacements / additions
For each finding with non-null proposed_screenshot_replacement:
Resolve source path: runs/<run-id>/labs/<slug>/screenshots/proposed/<proposed_screenshot_replacement> (the audit subagents save replacements here).
Resolve destination:
If proposed_screenshot_replacement_for is non-null (replacing an existing image): destination is labs/<slug>/<proposed_screenshot_replacement_for> (e.g. labs/<slug>/images/foo.png).
If null (adding a new image): destination is labs/<slug>/images/<proposed_screenshot_replacement> and ensure the lab markdown is updated to reference it (the markdown reference should be in the same finding's suggested_correction.proposed_text if the parser caught it).
cp <source> <destination>.
Track screenshots_replaced count for the commit message.
4a. Detect missing screenshot replacements for UI-drift findings
Before moving on to step 5, scan applied findings for the case where the audit caught UI drift (a renamed control, moved button, re-organized dialog, changed label) but the finding does NOT have a proposed_screenshot_replacement populated. This is exactly the case where the lab's screenshot will be stale even after the markdown fix lands — the body text says the new label, the picture still shows the old one. See mcs-lab-auditor/references/playwright-cookbook.md → "Screenshot freshness" for the standing rule.
For each such finding, before committing:
Identify any image-ref in the same scene as the relabeled instruction line. Most labs put  one or two paragraphs after the instruction it depicts. Look for image references within the _labs/<slug>.md section being edited.
If an image-ref exists within the affected scene and the file at labs/<slug>/images/<file>.png shows the old UI state (i.e. the same surface the audit just observed has been relabeled), the screenshot is stale.
The audit driver should already have captured a fresh screenshot for this surface during the run — look for it in runs/<run-id>/labs/<slug>/screenshots/. If found, copy it over labs/<slug>/images/<file>.png.
If no fresh screenshot was captured (the driver missed the image-ref → instruction mapping during the run), open a separate audit-loop iteration to capture one before proceeding. Do not skip — record {finding_id, screenshot_refresh: pending_capture, image_path} in pr-apply-log.json and request the screenshot from the orchestrator before commit.
If the maintainer's fix PR explicitly defers the image refresh (e.g. an explicit "deferred to follow-up" annotation in the finding), record the deferral in the PR body's Test plan under an unchecked checkbox: - [ ] Refresh \images/.png` to show the current UI`. Never silently ship the markdown-only fix.
Track screenshots_implied_stale and screenshots_refreshed_from_audit_run counts for the commit message and PR body. If screenshots_implied_stale > screenshots_refreshed_from_audit_run + screenshots_deferred, the gap is a process failure — log it loudly so the orchestrator can flag it on the next run.
5. Sanity check
git diff --stat
If the working tree has NO changes after steps 3 and 4 (every correction failed to apply, every screenshot was already current), set pr_action: skipped_no_changes and abort the PR step. Record the reason in pr-apply-log.json.
6. Commit
git add _labs/<slug>.md labs/<slug>/images/
git commit -m "$(cat <<EOF
<slug>: fix audit findings from #<issue-number>
Auto-applied by mcs-lab-fix-pr-filer from audit run <run-id>.
Markdown corrections: <N applied> of <N total> findings.
Screenshot updates: <N replaced> + <N added>.
See issue #<issue-number> for full audit details and per-finding evidence.
Closes #<issue-number>
EOF
)"
Commit author: use the current gh auth status user (e.g. dewainr@microsoft.com / Dewain Robinson) via git -c user.email=... -c user.name=.... Never sign with a Claude / bot identity unless explicitly configured.
7. Push
git push -u origin <branch>
If push fails because the remote branch already exists and is ahead (concurrent run), git pull --rebase origin <branch> then re-push.
PR body template (runs/<run-id>/labs/<slug>/pr-body.md):
Closes #<issue-number>.
Implements the corrections from the mcs-lab-auditor run on `<slug>` (run id `<run-id>`).
## What changed<foreachappliedfinding:a1-2linebulletdescribingthefix>## How it was verified
Every change was driven by the audit run's Playwright execution on a fresh workshop-issued tenant account. Per-finding evidence (screenshots, accessibility snapshots, console + network logs) is stored locally under `~/.claude/plugins/mcs-lab-auditor/runtime/runs/<run-id>/labs/<slug>/`.
<ifanyfindingswereNOTauto-applied:>## Findings deferred to human review<foreachunappliedfinding:abulletwiththereasonfrompr-apply-log.json>
If pr_action: appended:
Just push (already done in step 7). Then gh pr comment <pr-number> --body "Appended fixes from audit run <run-id>: <N> markdown corrections, <N> screenshot updates.".
Write runs/<run-id>/labs/<slug>/pr-url.txt containing just the PR URL for the orchestrator's end-of-run summary.
Important rules
Never force-push.pr_append.allow_force_push is false and remains so.
Dedup is OPEN-PR-scoped. Only an open fix-PR for the slug suppresses a new PR. Merged/closed PRs never block a new one — that's the whole point of the run-unique branch name. See [[feedback_fresh_branch_per_pr]].
One open PR per lab. If an open fix-PR already exists, append to it; never open a second open PR for the same lab in the same breath.
Never modify a closed/merged PR's branch. Always check open-PR state before pushing. See [[feedback_no_push_to_merged_pr]].
Respect same-author guardrail. If the current gh user does not match the PR author on an existing open PR, abort the append step and leave the issue-filer's record as the only output for this lab.
Restore the user's working tree. If you stashed changes at the start, git stash pop (or leave the stash with a clear label and tell the user how to recover) — never silently lose work.
Defer scene-scope corrections. Anything bigger than a phrase- or step-scope replacement should land in the PR body's "Findings deferred to human review" section, not in the commit. Large rewrites (e.g., adding a whole new use case) should be handled by the orchestrator at audit time, not auto-applied here.
What to do when stuck
original_text not found in markdown: lab has drifted since the audit. Record in pr-apply-log.json and continue.
proposed_screenshot_replacement source missing: subagent didn't save the file. Skip the image update and record in pr-apply-log. The PR still ships the markdown corrections; the screenshot finding remains in the issue for human attention.
Branch is up-to-date with main and no changes apply: still no-op — set pr_action: skipped_no_changes and don't push an empty commit.
An open PR exists but the author/mergeable guardrail fails: abort the PR step with the reason recorded; do NOT open a competing second PR. The issue-filer's record stands and the user is told to inspect the open PR.
gh pr create fails: leave the branch pushed (the commits are valuable), record the error in pr-apply-log.json, and tell the user the manual PR-create command they can run.