pr-readiness

star 351

Complete pre-merge checklist for opencode-swarm PRs. Covers lint, build, tests, security scans, CI verification, release fragments, invariant audit, PR body claim verification, placeholder cleanup, review state, and merge conflict detection.

zaxbysauce By zaxbysauce schedule Updated 6/16/2026

name: pr-readiness description: > Complete pre-merge checklist for opencode-swarm PRs. Covers lint, build, tests, security scans, CI verification, release fragments, invariant audit, PR body claim verification, placeholder cleanup, review state, and merge conflict detection. effort: small generated_from_knowledge: [] source_knowledge_ids: ['f07c1f4d-9bb0-4219-9804-26aa8efe8146', '20f7da40-02e0-4da8-9310-a78eb87ca81e'] generated_at: 2026-06-14T16:50:00Z confidence: 0.8 status: active version: 4 skill_origin: generated provenance_note: > Re-linked to current knowledge entries (version 4). The original source ID 1bed6ebf... is no longer present in the active knowledge store. The skill body and behavior are unchanged; only source_knowledge_ids metadata was updated to point to current lessons about verifying pre-existing state on parent commit and updating test data after fixes, both directly relevant to the PR readiness pre-merge checklist.

PR Readiness Skill

Activates when the user asks to verify PR readiness, run a pre-merge check, or confirm a PR is safe to merge.

When to Use

  • Before opening a pull request for the first time
  • Before merging an open PR
  • When asked "is this PR ready to merge?" or "pre-merge checklist"
  • After addressing review feedback — re-run this checklist before merging

Pre-Merge Checklist

Run each item in order. A PR is not merge-ready until every item passes.

1. Lint pass

Run the lint tool with mode="check". Must report 0 errors.

Tool: lint  |  mode: "check"
Expected: success, 0 errors

If lint fails, run with mode="fix" to auto-correct, then re-check.

2. Build pass

Run build_check to verify the project compiles without errors.

Tool: build_check  |  mode: "both"
Expected: success (both build and typecheck pass)

3. Test pass

Run tests for changed files only. Use test_runner with scope="convention" and explicit files: [...], or use the per-file shell isolation loop documented in TESTING.md.

Tool: test_runner  |  scope: "convention"  |  files: <changed files>
Expected: success, 0 failures

Do NOT use scope: "all" for interactive validation. See AGENTS.md invariant 6.

4. Pre-check batch green

Run pre_check_batch on the project directory. All gates must pass (gates_passed: true).

Tool: pre_check_batch  |  directory: <project root>
Expected: gates_passed === true

This runs lint, secretscan, SAST, and quality budget in a single pass.

5. CI green via gh CLI

Verify all remote CI checks are green on the PR head commit.

gh pr checks <PR_NUMBER>

Also inspect the structured check rollup:

gh pr view <PR_NUMBER> --json statusCheckRollup

All entries in statusCheckRollup must have "status": "completed" and "conclusion": "success". If any check is "conclusion": "failure", diagnose before proceeding.

6. Release fragment present

Every user-visible PR must ship a release note fragment under docs/releases/pending/. Verify one exists for this change.

ls docs/releases/pending/

Each fragment is a <unique-slug>.md file. Do NOT create version-numbered files — release-please owns the version number. See AGENTS.md invariant 12 and contributing.md.

7. Invariant audit section in PR description

The PR description must contain a ## Invariant audit section covering all 12 invariants. See the Invariant Audit Template section below.

For each invariant the PR touches, evidence must be a concrete artifact: a command output, a passing test, a grep result, or a spec citation. "Looks fine" is not evidence.

8. PR body claim verification

Verify that all quantitative claims in the PR description match the actual source code. Bot reviews (Codex, Copilot) and human reviewers trust PR body text — inaccurate claims waste review cycles and erode trust.

Check these claim types against source:

  • Test count: Count actual test cases from test runner output or grep for test declarations only (not describe blocks): grep -rE "^\s*(it|test)\(" --include="*.test.ts" | wc -l Compare to PR body count.
  • Pattern/validation count: If PR claims "12 regex patterns" or "3 validation gates", count the actual constants/patterns in the source file.
  • Storage format: If PR claims "individual JSON files" or "JSONL", verify the actual store implementation reads/writes that format.
  • Tool count: If PR claims "7 new tools", verify 7 tool files exist with src/tools/ entries.
  • Config field names: If PR shows config examples, verify field names match the Zod schema in src/config/schema.ts.
# Quick verification commands
grep -rE "^\s*(it|test)\(" tests/unit/tools/my-feature*.test.ts | wc -l   # actual test count
grep -c "PATTERN = " src/services/my-validator.ts                          # actual pattern count
ls src/tools/my-feature-*.ts | wc -l                                       # actual tool count

If any claim is inaccurate, fix the PR body before proceeding. Do not merge with incorrect claims.

9. No TODOs or placeholder code

Run placeholder_scan or todo_extract on changed files.

Tool: placeholder_scan  |  changed_files: <changed files>
Expected: 0 findings (TODOs referencing a future task ID are acceptable)

Alternatively:

Tool: todo_extract  |  paths: <changed files or directory>
Expected: no stale TODOs/FIXMEs/HACKs

10. Secret scan clean

Run secretscan to verify no leaked credentials.

Tool: secretscan  |  directory: <project root>
Expected: 0 findings

If findings appear, verify they are false positives before suppressing.

11. SAST scan clean

Run sast_scan to verify no security vulnerabilities.

Tool: sast_scan  |  directory: <project root>
Expected: no medium+ severity findings

12. Review state

All required reviews must be approved.

gh pr view <PR_NUMBER> --json reviewDecision,latestReviews

reviewDecision summarizes the overall review outcome. It should be "APPROVED" to proceed. Historical COMMENTED or DISMISSED reviews do not block merge — only an unresolved "CHANGES_REQUESTED" in latestReviews will block. If reviewDecision is "CHANGES_REQUESTED" or "REVIEW_REQUIRED", address the outstanding feedback before merging.

13. No merge conflicts

gh pr view <PR_NUMBER> --json mergeable,mergeStateStatus

Must return "mergeable": "MERGEABLE" and "mergeStateStatus": "CLEAN". If "mergeable" is "UNKNOWN", wait for GitHub to recalculate mergeability, then re-check. If mergeStateStatus is "BEHIND", the PR needs a rebase. If it is "DIRTY" or "BLOCKED", resolve conflicts or blockers before merging.

Quick Commands

Reference set of gh CLI commands for CI and review status:

# Check CI status
gh pr checks <PR_NUMBER>

# Structured check rollup
gh pr view <PR_NUMBER> --json statusCheckRollup

# Review state
gh pr view <PR_NUMBER> --json reviewDecision,latestReviews

# Merge conflicts
gh pr view <PR_NUMBER> --json mergeable,mergeStateStatus

# List pending release fragments
ls docs/releases/pending/

# Combined status view
gh pr view <PR_NUMBER> --json title,state,mergeable,mergeStateStatus,statusCheckRollup,reviewDecision,latestReviews

Invariant Audit Template

Every PR description must include this section. For each invariant, mark it touched or not touched, and provide concrete evidence for any touched entry.

## Invariant audit
- 1 (plugin init):       touched / not touched — <evidence>
- 2 (runtime portability): touched / not touched — <evidence>
- 3 (subprocesses):       touched / not touched — <evidence>
- 4 (.swarm containment): touched / not touched — <evidence>
- 5 (plan durability):    touched / not touched — <evidence>
- 6 (test_runner safety): touched / not touched — <evidence>
- 7 (test writing):       touched / not touched — <evidence>
- 8 (session state):      touched / not touched — <evidence>
- 9 (guardrails/retry):   touched / not touched — <evidence>
- 10 (chat/system msg):   touched / not touched — <evidence>
- 11 (tool registration): touched / not touched — <evidence>
- 12 (release/cache):     touched / not touched — <evidence>

Invariant summary (for quick reference)

# Invariant Key trigger files
1 Plugin init bounded, fail-open src/index.ts, plugin entry, init hooks
2 Node-ESM-loadable, v1 plugin shape src/index.ts, package.json#main, dist/, bun build config
3 Subprocesses bounded, killable Any spawn/spawnSync/bunSpawn call
4 .swarm/ containment Any tool or hook creating files outside .swarm/
5 Plan ledger authoritative plan-ledger.jsonl, plan schema/status changes
6 No broad test_runner test_runner tool calls with scope: "all"
7 bun:test, mock isolation Any test file creation or modification
8 Session state keyed by sessionID Maps/arrays keyed by session in hooks or tools
9 Transient retry vs real failure Guardrail, retry, circuit-breaker code
10 Chat/system message shape System message hook code
11 Tool registration + agent-map coherence src/tools/index.ts, src/index.ts plugin block, src/config/constants.ts
12 Release/cache hygiene package.json#version, CHANGELOG.md, cache-deletion code, release fragments

Common Failures

dist/ not rebuilt after source change

Symptom: dist-check CI job fails with "source changed but dist/ not rebuilt". Fix: Run bun run build locally to verify the bundle, but do NOT commit dist/ — it is generated and NOT committed. Push the source fix only.

Version drift on stale branch

Symptom: dist-check fails even after rebuilding — branch is behind main and a release commit changed package.json#version. Fix: Rebase onto main, rebuild dist, force-push. Do NOT hand-edit version files — release-please owns them (invariant 12).

Missing release fragment

Symptom: No file found in docs/releases/pending/ for this change. Fix: Create a <unique-slug>.md fragment describing the change. Do NOT use version numbers in the filename.

Lint auto-fix introduces unrelated changes

Symptom: bunx biome format --write or bunx biome check --write reformats lines not part of the intended change. Fix: Run lint fix on only the changed files, not the whole project. Review the diff after fixing.

mock.module leaks in tests

Symptom: Tests pass individually but fail when run as a suite. Fix: Replace mock.module with the _internals DI seam pattern. See the mock-to-internals-migration skill.

test_runner scope exceeded

Symptom: test_runner returns outcome: 'scope_exceeded' with a SKIP instruction. Fix: Reduce scope — use explicit files: [...] or scope: "convention". Do not use scope: "all" interactively (invariant 6).

Merge conflicts after rebase

Symptom: gh pr view --json mergeable,mergeStateStatus returns false or "DIRTY" after rebasing. Fix: Resolve conflicts locally, commit, push. Re-run this checklist from step 1.

PR body claims inaccurate

Symptom: Bot reviews (Codex/Copilot) flag test count, pattern count, or storage format mismatches between PR body and source. Fix: Count from actual source files, update PR body to match. Common mismatches: test count inflation (counting describe blocks instead of test calls), JSONL vs file-based store confusion, pattern count including auxiliary checks that are not regex patterns. Prevention: Run step 8 (claim verification) before opening the PR.

Install via CLI
npx skills add https://github.com/zaxbysauce/opencode-swarm --skill pr-readiness
Repository Details
star Stars 351
call_split Forks 35
navigation Branch main
article Path SKILL.md
More from Creator