From mcs-lab-auditor
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.
How this skill is triggered — by the user, by Claude, or both
Slash command
/mcs-lab-auditor:mcs-lab-fix-pr-filerThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
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.
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]].
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.<plugin>/config/judge-config.yml — branch conventions:
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.{repo} (from Resolve-LabRepo.ps1 -Instance).issue_number — returned by mcs-lab-issue-filer. Required.lab_slug, run_id — passed through.{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.<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.manifest.yml.labs[<slug>]: status: issue_and_pr_filed, pr_url, pr_action: created | appended | skipped_no_changes.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.)
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.
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.prefix="{branch_prefix}/fix-<slug>-content-audit" # judge-config.yml.issues.pr_append.pr_match_head_prefix
gh pr list --repo {repo} --state open --author "@me" \
--json number,headRefName,author,mergeable,url,updatedAt \
--search "head:$prefix" | jq 'sort_by(.updatedAt) | reverse | .[0] // empty'
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.
gh user (pr_append.require_same_author) and mergeable (pr_append.require_mergeable).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.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.
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.For each finding in findings.json where outcome ∈ {broken, unclear} AND suggested_correction is non-null:
_labs/<slug>.md.old_string = suggested_correction.original_textnew_string = suggested_correction.proposed_textold_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.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}.
For each finding with non-null proposed_screenshot_replacement:
runs/<run-id>/labs/<slug>/screenshots/proposed/<proposed_screenshot_replacement> (the audit subagents save replacements here).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).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.
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:
 one or two paragraphs after the instruction it depicts. Look for image references within the _labs/<slug>.md section being edited.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.runs/<run-id>/labs/<slug>/screenshots/. If found, copy it over labs/<slug>/images/<file>.png.{finding_id, screenshot_refresh: pending_capture, image_path} in pr-apply-log.json and request the screenshot from the orchestrator before commit.- [ ] 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.
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.
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. [email protected] / Dewain Robinson) via git -c user.email=... -c user.name=.... Never sign with a Claude / bot identity unless explicitly configured.
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.
If pr_action: created:
gh pr create \
--repo {repo} \
--base main \
--head <branch> \
--title "<slug>: fix audit findings from #<issue-number>" \
--body-file <pr-body.md>
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
<for each applied finding: a 1-2 line bullet describing the fix>
## 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>/`.
<if any findings were NOT auto-applied:>
## Findings deferred to human review
<for each unapplied finding: a bullet with the reason from pr-apply-log.json>
If pr_action: appended:
gh pr comment <pr-number> --body "Appended fixes from audit run <run-id>: <N> markdown corrections, <N> screenshot updates.".Capture the resulting PR URL.
Update runs/<run-id>/manifest.yml:
labs:
<slug>:
status: issue_and_pr_filed
issue_url: <from issue-filer>
issue_action: created | commented
pr_url: <captured above>
pr_action: created | appended | skipped_no_changes
finished_at: <iso-timestamp>
Append to runtime/audit-history.yml:
- run_id: <run-id>
lab_slug: <slug>
status: issue_and_pr_filed
issue_url: <...>
pr_url: <...>
findings_applied: <N>
findings_deferred: <N>
Write runs/<run-id>/labs/<slug>/pr-url.txt containing just the PR URL for the orchestrator's end-of-run summary.
pr_append.allow_force_push is false and remains so.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.git stash pop (or leave the stash with a clear label and tell the user how to recover) — never silently lose work.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.pr_action: skipped_no_changes and don't push an empty commit.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.Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub microsoft/bootcamplabtestplugin --plugin mcs-lab-auditor