
Pr Ready
- 1 installs
- Updated May 15, 2026
- erikagujari/marvel
Gate a pokedex iOS branch before opening a PR: run xcodebuild tests on the iPhone 17 simulator, run code review, sync README, push, and open the PR via gh.
About
A project-local build-test-review gate for the pokedex iOS repo that runs xcodebuild tests, an optional code-review pass, a parallel README-drift check, then pushes and opens a PR with gh. A developer uses it to validate an iOS branch before creating its pull request.
- Linear no-auto-fix flow that stops and surfaces failures
- Parallel Explore subagent does a soft-gate README drift check
Pr Ready by the numbers
- 1 all-time installs (skills.sh)
- Ranked #527 of 733 Git & Pull Requests skills by installs in the Skillselion catalog
- Data as of Jul 8, 2026 (Skillselion catalog sync)
npx skills add https://github.com/erikagujari/marvel --skill pr-readyAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| Last updated | May 15, 2026 |
| Repository | erikagujari/marvel ↗ |
What it does
Gate a pokedex iOS branch before opening a PR: run xcodebuild tests on the iPhone 17 simulator, run code review, sync README, push, and open the PR via gh.
Files
You are gating a pokedex iOS branch before opening a PR. The working tree is clean (/ship should have committed everything); your job is to run build+test, optionally run a code-review pass, push the branch, and open a PR via gh.
This is the project-local pr-ready (lives at .claude/skills/pr-ready/SKILL.md in this repo). It is intentionally simpler than the global ~/.claude/skills/pr-ready/: no Bazel/tente, no Marito-CR re-review loop, no Jira transitions, no auto-fix budget.
PHILOSOPHY
- Linear, no auto-fix loop. If build or test fails, surface the output and stop — the human decides whether to fix in this branch or elsewhere. The global
/pr-readyhas a 3-commit budget for auto-fixes; this fork doesn't. - Plain PR title and body. No team template. Title from the most-impactful commit subject, body summarises the commits.
- `gh` for PR creation, not the GitHub web UI. Repeatable from CLI.
- Never push to a protected branch. Hard guard at preflight.
ARGUMENTS
Parse $ARGUMENTS first.
--dry-run: run preflight + build + test + (optionally) code-review, but skip push and PR creation. Just print what would happen.--no-review: skip the code-review pass. Default is to run it.
STEP 0 — Preflight
1. Branch guard: BRANCH_NAME="$(git branch --show-current)". If empty (detached HEAD) or matches main, master, release/*, hotfix/*, stop. 2. Working tree must be clean: git status --porcelain. If non-empty, stop and suggest invoking /ship first. 3. Branch must be ahead of `origin/main`:
git fetch origin main --quietgit rev-list --count origin/main..HEAD— must be ≥ 1. If 0, stop with "nothing to PR".
4. Existing PR check: gh pr view --json url,state 2>/dev/null. If a PR is already open for this branch, surface its URL and ask the user whether to continue (which will refresh checks but not re-create the PR) or abort. 5. Create a task list via TaskCreate:
- "Build + test"
- "Code review" (omit if
--no-review) - "README sync"
- "Push branch"
- "Open PR" (omit if
--dry-run)
6. Fire the README-sync subagent in parallel (do not await it; build+test starts immediately afterwards). The subagent runs in its own context so the signal-file reads stay out of this thread. Use subagent_type: "Explore" — it is read-only by design (no Edit, no Write), so the subagent cannot mutate the working tree even if the prompt is misinterpreted.
Agent(
subagent_type: "Explore",
description: "README drift check",
run_in_background: true,
prompt: <see template below>
)Save the agent's id/name — you'll collect its result in STEP 2.5.
Prompt template (self-contained — the subagent has no session context. Do not interpolate any absolute path; the subagent inherits the cwd of this session, which is the repo root):
You are a README-drift detector for the pokedex iOS repo. Your cwd is the repo root. Determine whether README.md still matches reality, and if not, propose a minimal patch.>
1. Rungit fetch origin main --quietthen list changed files withgit diff --name-only origin/main..HEAD.
2. Filter to the signal set:pokedex/pokedex/**/*.swift,pokedex/pokedex/Data/Services/**,pokedex/pokedex.xcodeproj/project.pbxproj,.swiftlint.yml,.githooks/**,CLAUDE.md.
3. If the filtered set is empty, return exactly: STATUS: IN-SYNC (no signal files changed) and stop.4. Otherwise readREADME.mdin full, then read each changed signal file (truncate >200 lines; forproject.pbxproj, do not read the file — instead, rungrep -n IPHONEOS_DEPLOYMENT_TARGET pokedex/pokedex.xcodeproj/project.pbxproj | head -3to extract the deployment target).
5. Walk README sections (Architecture, UI Details, Testing, Stack, Linting). For each, check whether the current claim still matches the code. Common drift: "Xcode 13"/"iOS 15" lines vsIPHONEOS_DEPLOYMENT_TARGET; folder bullets vs actual subfolders; PokéAPI endpoint descriptions vsData/Services/enum cases; SwiftLint setup vs.swiftlint.ymland.githooks/pre-commit; build/test commands vsCLAUDE.md.
6. If everything still matches, return exactly: STATUS: NO-OP (README accurate).7. Otherwise return:
>
```
STATUS: DRIFT
SIGNALS_CHANGED: <comma-separated list of changed signal files>
DIFF:
```diff
<unified diff against README.md, minimal hunks only>
```
```
>
Return only the verdict described above. (The Explore subagent has no write tools, so this is enforced by capability — but state it for clarity.)
STEP 1 — Build + test
Run the test suite on the iPhone 17 simulator (matches CLAUDE.md):
xcodebuild -project pokedex/pokedex.xcodeproj -scheme pokedex \
-destination 'platform=iOS Simulator,name=iPhone 17' test- On success: continue.
- On failure: stop. Surface the test output verbatim (the failing
module::testidentifiers and the assertion messages). Do not attempt auto-fix. Leave commits in place. Update the task list to mark the step failed and exit.
If you suspect simulator flakiness (e.g. a single test failed once that has historically been stable), you may retry the failing tests once via -only-testing: before declaring failure. Don't loop.
STEP 2 — Code review (skip with --no-review)
Invoke the global /code-review skill via Skill. It is generic and reads the local diff against main. Surface its findings to the user.
- If the review reports only nits or no issues: continue.
- If the review reports a likely bug or correctness issue: stop, surface the finding, and ask the user whether to push anyway, fix in this branch (in which case they'd re-run
/shipthen/pr-ready), or abort.
STEP 2.5 — README sync (soft gate)
Collect the README-sync subagent result that was kicked off in STEP 0.
How to wait: when a background Agent(...) finishes, the harness pushes a <task-notification> system message containing a <result> block with the subagent's final output. By the time you reach STEP 2.5, that notification should already be in your context (build+test and code-review take long enough that the README check almost always finishes first). Scan back through the conversation for the <task-notification> whose <task-id> matches the id you saved in STEP 0 and read its <result>. If no such notification has arrived yet, do not block waiting — treat the outcome as "errored" (see below). This is a soft gate; a slow drift check must not delay the PR.
Branch on the STATUS: line at the top of the subagent's <result>:
STATUS: IN-SYNC (...)orSTATUS: NO-OP (...)— continue silently. Mark the "README sync" task completed; record the outcome ("in-sync" / "no-op") for STEP 5.
STATUS: DRIFT— the subagent returned a proposedREADME.mddiff. Surface it to the user:
1. Print the SIGNALS_CHANGED: line and the ``diff block from the subagent's output. 2. If --dry-run was passed: print "would apply README update and commit (dry-run, skipping)" and record outcome "drift-dry-run" for STEP 5. Do NOT call Edit or commit. 3. Otherwise ask: Apply this README update before pushing? (y/n)`
- On
y: apply each hunk viaEdittoREADME.md. After the lastEditsucceeds, rungit status --porcelain— if anything other thanREADME.mdis dirty, stop and surface (anEditpartial-failure or a stray write must not be silently committed). Otherwise:
git add README.md
git commit -m "docs: sync README after changes to <SIGNALS_CHANGED list>"Interpolate the SIGNALS_CHANGED: list from the subagent's output into the commit subject (truncate to ≤72 chars). The new commit will be included in the push. Record outcome "applied" (with the new commit hash) for STEP 5.
- On
n(or anything else): leaveREADME.mduntouched and continue. Record outcome "declined" for STEP 5.
- Subagent failed, timed out, produced unparseable output, or no notification arrived: record outcome "errored" for STEP 5 and continue. Do not block. This is a soft gate; a flaky drift check must not stop a PR.
Mark the "README sync" task completed regardless of outcome.
STEP 3 — Push
If --dry-run: print "would push <branch> to origin" and stop here.
Otherwise:
- If upstream is unset (
git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/nullfails):git push -u origin <BRANCH_NAME>. - Else:
git push. - If push is rejected as non-fast-forward, stop and report. Do not force-push without explicit user approval.
STEP 4 — Open PR
If --dry-run: print the title/body that would be used and stop.
Build the PR title and body:
- Title: subject of the most-impactful commit on the branch. Heuristic: the longest-prefix
prod+unitcommit (i.e.<module>: <subject>); if none, fall back to the first commit's subject. ≤72 chars. - Body: ```
Summary
<one-or-two-sentence synthesis of what this branch does, drawn from the commit bodies and the conversation context>
Commits
<bulleted list: git log --pretty=format:'- %s' origin/main..HEAD>
Test plan
- [ ] xcodebuild test passes on iPhone 17 simulator
- [ ] <any feature-specific manual check inferred from the diff>
Run:
gh pr create --base main --head <BRANCH_NAME> \ --title "<title>" \ --body "$(cat <<'EOF' <body> EOF )"
- On success: surface the PR URL returned by `gh`.
- On failure: surface stderr verbatim. Do not retry blindly.
## STEP 5 — Report
Print:
- The PR URL (or "dry-run, no PR created").
- The list of commits that landed in this run (`git log --oneline origin/main..HEAD`).
- A note if `--no-review` was used (so the user remembers they skipped that gate).
- README-sync outcome: `in-sync`, `no-op`, `applied` (and the docs commit hash), `declined` (drift surfaced but user said no), `drift-dry-run` (drift surfaced under `--dry-run`, no commit made), or `errored` (subagent failed or notification never arrived — drift state unknown).
Stop. The user's responsibility from here is to review the PR in the browser.
## FAILURE MODES
- **Build/test fails**: stop at Step 1, no push. Commits are still in place locally — the user can fix and re-run.
- **Code review reports a likely bug**: stop at Step 2, no push. Same recovery path.
- **Push rejected**: stop at Step 3. The user resolves manually (rebase or force-push with-lease — both require their explicit approval).
- **`gh pr create` fails**: stop at Step 4. The branch is already pushed; the user can re-attempt manually.
- **PR already open for branch**: surfaced in preflight; user decides whether to refresh checks (no-op here, but build+test ran) or abort.
Begin by parsing arguments and running Step 0 now.