| name | review-learning-path |
| description | Guide a reviewer through a full learning path PR review in interactive-tutorials — per-milestone audit, path consistency, Playwright, Pathfinder PR review tool, and GitHub submit. Use when the user runs /review-learning-path-pr. |
Review learning path PR
Interactive, phase-by-phase review of a {slug}-lj/ pull request. The agent narrates each step, runs automated checks, and prompts the reviewer for input at checkpoints. Read-only on guide JSON.
Entry command: /review-learning-path-pr
Do NOT read external reference files upfront. Each phase loads its own references on demand. Everything the orchestrator needs to start is inline below.
Skill memory: Review-owned state lives in .cursor/pr-review-state/ (gitignored). Phase 1 dispatches audit-guide, which writes {milestone}/assets/ inside package directories on the checked-out PR branch. Those files are not review-owned state — see Commit safety. Snapshot before audit, delete new audit files before leaving Phase 1, and verify git status stays clean.
Severity: finding severity routing in this skill supersedes audit-guide/severity-rubric.md for Phase 3 bucketing and Phase 7 inline vs body decisions. audit-guide blocking/warning/info still applies during Phase 1; re-tag findings with this skill's routing before Phase 7.
Checklists: reference-checks.md · GitHub API: github-review.md
Related: audit-guide · review-guide-pr.mdc
Example: PR #403 (monitor-azure-resources-lj)
Workflow overview
Input (PR URL or number)
│
├─ Phase 0: Get PR & checkout ── orchestrator (gh, infer path_dir)
│
├─ Phase 1: Per-milestone audit ── dispatch audit-guide per milestone (parallel OK)
│
├─ Phase 2: Path consistency ──── orchestrator (manifest, framing, website.yaml)
│
├─ Phase 3: Findings doc ──────── orchestrator → pr-{n}-findings.md
│ Checkpoint: reviewer approves live testing
│
├─ Phase 4: Pending GitHub review
│
├─ Phase 5: Playwright DOM ────── orchestrator (reviewer logs in first)
│
├─ Phase 6: Pathfinder PR tool ── reviewer reports pass/fail/N/A per milestone
│
├─ Phase 7: Consolidate comments ─ orchestrator → inline + review-body.md
│
├─ Phase 8: Reviewer approval ─── orchestrator
│
└─ Phase 9: Submit ────────────── orchestrator (workflow ends)
Phase 10: optional post-submit follow-ups
Inputs
- Required:
pr_number or GitHub PR URL for grafana/interactive-tutorials — supplied by the reviewer at Phase 0.
- Optional:
path_dir — {slug}-lj/ package directory. Inferred from changed files; confirm with reviewer if ambiguous.
- Optional:
website_slug — companion path slug ({path_dir} minus -lj). Inferred when website repo is in workspace.
- Optional:
learn_host — live test host (default learn.grafana.net).
- Optional:
waive_live_testing — reviewer explicitly accepts static-only review; skip Phases 5–6.
If the user invokes /review-learning-path-pr with no arguments, start Phase 0 and ask for the PR.
Safety invariants
These rules are inviolable during a review run:
- Never modify author
content.json or manifest.json. Read-only on guide JSON.
- Never post GitHub inline comments before Phase 7 (unless reviewer waives live testing and approves static-only inline at Phase 3).
- Never submit a review before Phase 8 approval from the reviewer.
- Never commit review artifacts —
.cursor/pr-review-state/ (gitignored) or audit-guide output under {milestone}/assets/. Mandatory cleanup and verification: Commit safety.
- One pending GitHub review per PR review cycle — workflow ends at Phase 9 submit.
Commit safety
This skill runs on the author's checked-out branch (gh pr checkout). Ask: under what circumstances could a review artifact get committed?
| Artifact | Where written | Risk | Mitigation |
|---|
| Findings, review body, state JSON | .cursor/pr-review-state/ | Staged by mistake | .gitignore |
| audit-guide reports | {milestone}/assets/ | Untracked ?? files staged with PR fixes | Snapshot + mandatory cleanup (Phase 1); gitignore audit filenames |
Pre-existing package assets/ | Author/migrate (e.g. migration-notes.md) | Deleted by careless cleanup | Snapshot — never delete files that existed before Phase 1 |
Never commit: audit-guide outputs, .cursor/pr-review-state/, or any file created only during this review run.
Phase 1 snapshot (before audit-guide)
For each milestone directory to audit, record existing asset paths in state:
find {milestone}/assets -type f 2>/dev/null | sort
Store as pre_review_assets.{milestone-slug} in pr-{n}.json.
Phase 1 cleanup (mandatory — before Phase 1 checkpoint)
After extracting findings from each audit report:
- Copy
audit-report.md to .cursor/pr-review-state/pr-{n}/audits/{milestone-slug}/ if you need a local audit trail (optional).
- Under each audited
{milestone}/assets/, delete every file not listed in that milestone's pre_review_assets snapshot (includes all audit-guide outputs: audit-input.json, *-report.md, manifest.yaml when new, history/).
- Remove empty
assets/ directories only if the directory did not exist in the snapshot.
Do not advance past Phase 1 until verification passes:
git status --porcelain -- {path_dir}
Must show no untracked (??) audit-guide paths under milestone assets/. Report remaining paths to the reviewer and clean up before continuing.
Re-verify before Phase 4
Run the same git status check on {path_dir} after Phase 3. Live testing does not write into package dirs, but confirm no audit artifacts reappeared.
How this skill runs
- Agent announces the current phase, what it is doing, and why.
- Agent executes agent-side work (audit,
gh, Playwright, draft files).
- Agent stops at the checkpoint and prompts the reviewer for input or approval.
- Do not advance until the checkpoint is satisfied.
- Do not post GitHub review comments until Phase 7 (after Phases 1–6 unless reviewer waives live testing).
Reviewer voice
Use short, direct prompts. One ask per checkpoint. Address the reviewer as you. Include the phase number. Say what you need and what happens next.
| Phase | Agent | You |
|---|
| 0 | Fetch PR, checkout branch | Share PR URL/number; confirm path |
| 1–2 | Audit + consistency checks | Skim summary; flag anything missed |
| 3 | Write findings doc | Approve live testing |
| 4 | Create pending GitHub review | — |
| 5 | Playwright DOM (after you log in) | Log in to Playwright browser; reply ready |
| 6 | Record Pathfinder results | Set up PR review tool; test each milestone; report pass/fail/N/A |
| 7 | Draft inline comments + body | — |
| 8 | — | Review draft; confirm verdict |
| 9 | Submit review | Reply submit |
| 10 | Optional follow-ups | — |
Resume
If .cursor/pr-review-state/pr-{n}.json exists, read phase and status. Tell the reviewer:
I found an in-progress review for PR #{n} (phase {phase}, status {status}). Would you like to resume from phase {phase + 1}, or start fresh?
Phase 0: Get the PR and checkout branch
Goal: Identify the PR, check out its branch, infer the path package, initialize state.
Tell the reviewer
Phase 0 — Get the PR
Share the GitHub PR for this learning path — a URL or number (for example #403) in grafana/interactive-tutorials. I'll fetch it and check out the branch.
Wait for the PR before continuing.
Agent steps
- Parse PR number from URL or
#403 input.
- Run
gh pr view {n} --repo grafana/interactive-tutorials --json number,title,headRefName,headRefOid,url,files,id.
- Tell the reviewer: PR title, number, branch, HEAD sha.
- Check out:
gh pr checkout {n} (or fetch + checkout).
- Infer
{path_dir} from changed files (directory ending in -lj). If ambiguous, ask.
- Infer
website_slug = {path_dir} minus -lj if website repo is in workspace.
- List milestones under
{path_dir}/ and path root files.
- Write
.cursor/pr-review-state/pr-{n}.json with pull_request_node_id from the id field (GraphQL node ID for Phase 4). See github-review.md.
Checkpoint
Confirm with reviewer:
Phase 0 complete
- Branch:
{head_branch} @ {short_sha}
- Path:
{path_dir} ({M} milestones)
- Website slug:
{website_slug} (or none in workspace)
Does that look right? Reply yes to start the static audit, or tell me what to fix.
Phase 1: Per-milestone audit
Goal: Run audit-guide on every milestone; apply content checks.
Tell the reviewer
Phase 1 — Static audit
I'm running audit-guide on each milestone under {path_dir}. This is read-only — nothing goes to GitHub yet.
Agent steps
- List milestones from path
manifest.json milestones array plus any changed milestone dirs.
- Snapshot — for each milestone, record existing
assets/ file paths in state (pre_review_assets). See Commit safety.
- Dispatch audit-guide on each milestone directory (Explore sub-agent or Task, parallel OK). Skip framing-only packages not in path
milestones unless PR changed them.
- Apply every row in reference-checks.md § content.
- Tag each finding with severity from finding severity routing (
inline / defer / body).
- Summarize per milestone: verdict, blocking count, top issues (file + rule + fix + severity).
- Mandatory cleanup — remove audit-guide files not in the Phase 1 snapshot. Verify
git status on {path_dir}. See Commit safety.
- Do not post to GitHub. Do not use
FROM AUDIT: prefixes anywhere.
Checkpoint
Tell the reviewer:
Phase 1 complete — {X} milestones audited, {B} blocking patterns across {N} milestones.
Top findings:
[bullet list]
Anything you already know is wrong or out of scope?
Wait for: acknowledgment or additions, then Phase 2.
Phase 2: Path-level consistency
Goal: Validate path root content.json, manifests, website.yaml, depends chain, framing rules, targeting, website alignment, CODEOWNERS.
Tell the reviewer
Phase 2 — Path consistency
I'm checking path root content, manifests, website.yaml, the dependency chain, framing rules, targeting, and companion website alignment.
Agent steps
- Run Pathfinder CLI if available:
validate --packages {path_dir} (record pass/fail).
- Walk reference-checks.md: path root content.json, website.yaml, framing, valid manifests, depends chain, targeting, companion website, CODEOWNERS.
- Compare path
milestones to peer LPs (depends chain, no framing in array, first hands-on depends: []).
- Tag each finding with severity routing.
- Note companion website gaps separately (body later, not package blockers unless PR claims sync done).
Checkpoint
Tell the reviewer:
Phase 2 complete
[pass/fail bullets — framing, depends chain, targeting, website.yaml, companion website]
Ready for me to write the findings doc?
Wait for: yes.
Phase 3: Internal findings document
Goal: Merge Phases 1–2 into one reviewer-facing doc. Still no GitHub comments.
Tell the reviewer
Phase 3 — Findings doc
I'm merging the audit and consistency results into .cursor/pr-review-state/pr-{n}-findings.md.
Agent steps
Write pr-{n}-findings.md using finding severity routing:
- Runtime blockers (always inline) — dedupe by root cause; Phase 5–6 failures; manifest/depends/framing breaks; selector fails live
- Selector notes — audit rule 2 /
:contains() findings; apply selector decision tree — body-only when Pathfinder passed and fallback is justified
- Live-test candidates — selectors and milestones for Playwright + Pathfinder
- Defer until after Pathfinder — findings in the Defer column only
- Review body only — companion website, CODEOWNERS, editorial, passed-milestone notes
- Waived / N/A — terminal milestones; fresh-stack retest notes e.g. install
Each listed finding includes severity tag and source phase (1, 2, 5, or 6).
Apply the generated-file frontmatter to pr-{n}-findings.md.
Update state: "phase": 3.
Re-verify commit safety — git status --porcelain -- {path_dir} shows no untracked audit-guide files under milestone assets/. See Commit safety.
Checkpoint
Tell the reviewer:
Phase 3 complete — findings doc is ready.
- Blockers before live test: [short list or none]
- Milestones to live-test: [list]
- Deferring until Pathfinder: [list]
Open pr-{n}-findings.md for full detail. Reply yes to create the pending GitHub review and start live testing.
Wait for: yes. Offer to skip Phases 5–6 only if you explicitly accept a static-only review.
Phase 4: Pending GitHub review
Goal: One pending review to hold all inline comments until submit.
Tell the reviewer
Phase 4 — Pending GitHub review
I'm creating a pending review on PR #{n}. Inline comments stay hidden from the author until we submit at the end.
Agent steps
- GraphQL
addPullRequestReview (no event), body: Review in progress. Use pullRequestId: {pull_request_node_id} from state (set in Phase 0).
- Store
pending_review_id and pending_review_node_id from the mutation response in state file.
- Do not add inline comments yet (Phase 7).
See github-review.md.
Checkpoint
Tell the reviewer:
Phase 4 complete — pending review is created.
Next up is live testing on {learn_host}. Reply yes when you're ready for the Playwright pass.
Wait for: yes before starting Phase 5.
Phase 5: Playwright DOM verification
Goal: Verify selectors exist on learn.grafana.net @ PR HEAD.
Tell the reviewer
Phase 5 — Playwright DOM check
I'll verify selectors in the Playwright browser (separate from your normal browser — you'll need to log in with Okta).
Reply ready when you're logged in to {learn_host} in Playwright.
Wait for: ready. Do not navigate or run Playwright until the reviewer replies.
Agent steps
For each interactive milestone in path order:
- Navigate to
startingLocation.
- Check each
reftarget: exists / missing / below-fold.
- Record results @
{head_sha}.
Do not post pass-only GitHub comments. Do not open Block Editor, load guides, or start Pathfinder testing — that is Phase 6 only.
Checkpoint
Tell the reviewer:
Phase 5 complete
- Failures: [list or none]
- Below fold (may still pass Pathfinder): [list or none]
Next is Pathfinder testing with the PR review tool. Reply yes when you want setup instructions.
Wait for: yes before opening Phase 6. Do not preview, navigate to, or load any milestone in Block Builder yet.
Phase 6: Pathfinder interactivity (PR review tool)
Goal: You exercise Show me / Do it for each milestone; the agent records results.
Tell the reviewer (setup only — no milestone testing yet)
Phase 6 — Pathfinder (PR review tool)
Set this up in your browser (not Playwright):
- Open
{learn_host}/plugins/grafana-pathfinder-app?dev=true
- Block Editor → dev tools → PR review tool
- Point it at PR #{n} in
grafana/interactive-tutorials
Reply ready when the PR review tool is loaded. I won't ask you to test any milestone until you do.
Wait for: ready.
Do not before ready: navigate to a milestone startingLocation, load a guide in Block Builder, run Show me / Do it, or repeat setup instructions. Do not smoke-test the first milestone during Phase 5 or between phases.
Per-milestone loop
Start only after setup ready. For each milestone in path milestones (skip terminal-only, e.g. external CLI):
Prompt reviewer (one milestone at a time — never repeat a milestone already reported):
Milestone {i} of {M}: {milestone-id}
Open {startingLocation} in learn, then run every Show me and Do it in the PR review tool.
Reply when you're done:
- pass — all steps worked
- fail step N — what happened
- N/A — reason (for example, resource already on your stack)
Agent: record in pr-{n}.json → pathfinder.{milestone-slug}. Advance to the next milestone only after the reviewer replies.
Do not post inline pass/N/A comments. N/A with stack caveat → note for review body (author fresh-stack retest).
Checkpoint
Tell the reviewer:
Phase 6 complete
- Passed: [list]
- Failed: [list]
- N/A: [list]
Next I'll draft GitHub comments (failures only). Reply yes to continue.
Wait for: yes.
Phase 7: Consolidate GitHub comments
Goal: Add inline comments + draft review body. Apply severity routing and comment policy.
Tell the reviewer
Phase 7 — Draft GitHub comments
I'm adding inline comments for blockers and writing the review body. Pass-only and deferred nits won't get inline comments.
Agent steps
- Re-fetch PR HEAD if author may have pushed; reconcile resolved threads.
- From
pr-{n}-findings.md, promote Defer items to inline only if Phase 5–6 failed; drop deferred items Pathfinder passed.
- Re-tag audit-only
:contains() findings with the selector decision tree — do not inline when Pathfinder passed and no stable selector exists in DOM.
- Dedupe to one comment per root cause before posting.
- Add inline comments via GraphQL
addPullRequestReviewComment — Always inline + runtime failures only. Ask the reviewer to confirm before inlining any finding that is audit-only (no live failure).
- Merge Playwright + Pathfinder evidence, and merge code fix + runtime symptom when they share a root cause (never two inline threads on the same file for the same bug).
- Write
.cursor/pr-review-state/pr-{n}-review-body.md with Review body only findings, passed milestones, and retest notes. List runtime merge blockers under Must fix before merge; put justified :contains() fallbacks and selector polish under Optional follow-ups. Apply the generated-file frontmatter.
- Recommend a default verdict from findings (
REQUEST_CHANGES, COMMENT, or APPROVE) with a one-sentence reason. If all Pathfinder milestones passed and no runtime blockers remain, default to COMMENT or APPROVE, not REQUEST_CHANGES. Store in state: "recommended_verdict".
- Update state:
comment_count, "phase": 7.
Comment tone (required)
Write like a human reviewer, not an audit dump.
- Lead with what you tested and the outcome (pass/fail), not rule numbers.
- Use Blocker only for runtime failures or broken manifest/depends/framing — not for audit-only
:contains() when Pathfinder passed.
- For selector polish: one plain sentence; link docs/selectors-and-testids.md when relevant; default to review body, not inline, when the step passed live.
- Do not use a fixed template such as
verified on learn.grafana.net @ {sha} (Playwright DOM + Pathfinder PR review tool) on every comment — mention the host/sha once in the review body if useful.
- Acknowledge author context when known (e.g. test IDs tried first and failed).
Bad (canned):
Blocker — verified on learn.grafana.net @ 934a2c3 (Playwright DOM + Pathfinder PR review tool). Replace h2:contains('Total Cost')…
Good (human):
This step passed on learn, but if you have a data-testid on this heading from Block Editor, prefer that over :contains() — otherwise the current selector matches our fallback order in the selectors doc.
Checkpoint
Tell the reviewer:
Phase 7 complete
- {comment_count} inline comments drafted
- Review body saved to
pr-{n}-review-body.md
- Recommended verdict: {recommended_verdict} — {reason}
GitHub won't show the pending body in the UI. Reply show body to read it here, or open the file. Then we'll confirm at Phase 8.
Wait for: body review, then Phase 8.
Phase 8: Reviewer approval
Goal: Reviewer confirms or overrides the recommended verdict and final body text.
Tell the reviewer
Phase 8 — Approve and submit
Recommended verdict: {recommended_verdict} — {reason}
Please confirm:
- Inline comments look right on GitHub Files changed
- Review body text (here or in
pr-{n}-review-body.md)
- Verdict — keep {recommended_verdict} or choose
REQUEST_CHANGES / COMMENT / APPROVE
Reply submit with your final verdict when you're ready to publish.
Agent steps
- Apply verdict selection rules — do not recommend APPROVE if Always inline blockers were inlined in Phase 7.
- Print full review body in chat if requested.
- Apply reviewer edits to
-review-body.md.
- Store confirmed verdict in state:
"verdict" (may differ from recommended_verdict).
- Do not submit until reviewer says submit or publish with explicit verdict.
Checkpoint
Wait for: explicit "submit" / "publish" with verdict.
Phase 9: Submit (workflow ends)
Goal: Publish pending review + body.
Tell the reviewer
Phase 9 — Submitting review
Publishing as {verdict}…
Agent steps
- GraphQL
submitPullRequestReview with final body from -review-body.md.
- Update state:
"status": "submitted", verdict, submitted_at, review_url.
- Share review URL with reviewer.
Tell the reviewer
Review submitted: {url}
This review cycle is complete. For follow-up after the author pushes, use Phase 10 or start a new review.
Stop. Do not add to the same pending review after submit.
Phase 10: Post-submit (optional)
Goal: Ad-hoc comments after submit — new cycle if author rebases significantly.
When to use
- Slack/colleague feedback (e.g. Pathfinder UX, stale
depends)
- Product issues → conversation comment + follow-up issues
- Code fixes on new commits → new inline comment
Prompt reviewer:
Phase 10 — Post-submit follow-up
What would you like to add — an inline comment on a file, or a general PR comment?
Anti-patterns
Do not: submit mid-process · FROM AUDIT: on GitHub · pass/N/A inline comments · cap comment count · assume Playwright = main browser · manual JSON paste when PR review tool works · UI submit without pasting body · continue after Phase 9 on same pending review · duplicate inline threads on the same file for the same root cause · navigate to or load Block Builder milestones before Phase 6 setup ready · smoke-test or repeat the first milestone before the formal Phase 6 loop · start Phase 6 milestone prompts before the reviewer confirms PR review tool setup · leave Phase 1 without audit cleanup and git status verification · delete pre-existing author assets/ files (e.g. migration-notes.md).
Do: one pending review · defer authoring nits when Pathfinder passed · fresh-stack retest in body · GraphQL submit · save body locally for preview.
Generated files
Deliverables for the reviewer. Write under .cursor/pr-review-state/ — never commit to the PR branch.
| File | Phase | Purpose |
|---|
pr-{n}.json | 0+ | Machine-readable review state (schema) |
pr-{n}-findings.md | 3 | Merged static + consistency findings |
pr-{n}-review-body.md | 7 → 9 | Final review body (GitHub UI does not show pending body) |
pr-{n}/audits/{milestone}/ | 1 (optional) | Copied audit reports before milestone cleanup |
Every generated markdown file in .cursor/pr-review-state/ must start with:
---
disclaimer: Auto-generated by review-learning-path skill. Do not edit manually.
notice: To regenerate, re-run the skill from the relevant phase.
pr_number: {n}
---
Do not add this frontmatter to pr-{n}.json.
Deep references