skills/pr-ready/SKILL.md
Pre-PR flight check on the current branch. Reviews the diff against stated intent, flags scope creep, regression risks, and commit hygiene problems, and drafts a compact PR title (conventional-commit style) and description. Requires a clean working tree. Does not run tests, lint, or type-check.
npx skillsauth add data-fair/lib pr-readyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
A focused review pass before opening a pull request. The goal is a PR that is easy on the reviewer: tight scope, no bloat, surprises called out up front.
Do not auto-invoke on general "review my code" or "what do you think?" prompts.
Run git status --porcelain. If the output is non-empty (any modified, staged, or untracked files), stop and tell the user:
Commit or stash your changes first. A pre-PR review only makes sense on a clean state — otherwise we'd be reviewing a moving target.
Do not proceed until the tree is clean.
The whole review hinges on knowing what the change was supposed to do.
If the user passed an intent string with the invocation (e.g. /pr-ready add X to Y), use it as the intent. Skip to Phase 3.
Otherwise, gather signals:
git branch --show-currentgit log --oneline --no-merges $(git merge-base "$default_branch" HEAD)..HEADSynthesize a single sentence of inferred intent and present it:
Inferred intent: "<one sentence>". Correct as-is, or refine?
Wait for the user to confirm or correct. Lock the intent before moving on.
First, find the repo's default branch — it's usually main but older repos use master. Prefer the symbolic ref on the remote, fall back to whichever local branch exists:
default_branch=$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null | sed 's@^origin/@@')
[ -z "$default_branch" ] && git show-ref --verify --quiet refs/heads/main && default_branch=main
[ -z "$default_branch" ] && git show-ref --verify --quiet refs/heads/master && default_branch=master
If neither resolves, ask the user which branch to diff against rather than guessing.
Then scope the review to what this branch actually added (the merge-base sidesteps drift on the default branch):
base=$(git merge-base "$default_branch" HEAD)
git log --oneline --no-merges "$base..HEAD" # commit list with subjects
git diff --stat "$base..HEAD" # file-level overview
git diff "$base..HEAD" # full content diff
--no-merges drops commits like Merge branch 'main' that only pulled the default branch back into this one — they aren't this branch's own work and shouldn't be analyzed under commit hygiene or intent. The diff itself is already scoped via the merge-base, so changes brought in by those merges don't appear in git diff "$base..HEAD" either; only edits actually made on this branch (including any conflict resolutions in the merge commit) show up.
Read the full diff. For larger changes, use --stat first to plan where to look closest.
For each vector, note specific findings with file:line references when applicable.
console.log, print, leftover TODO/FIXME from this change, commented-out code, debug branches, unused imports, over-verbose logic, unnecessary new abstractions.Output a single compact report in this order. If a section has nothing to say, write "No issues" rather than omitting it.
## Summary
<two sentences max: what this branch does>
## Intent check
<aligned, or list deviations>
## Cleanup
- <bullets with file:line where useful>
## Regression flags
- <each one specific and actionable>
## Commit hygiene
- <bullets; include a squash plan if needed>
## Suggested PR title
<one line, ready to paste>
## Suggested PR description
<markdown block, ready to paste>
Follow Conventional Commits. Pick the prefix that best matches the dominant change in the diff:
feat: — new user-facing functionalityfix: — bug fixrefactor: — code change that neither fixes a bug nor adds a featureperf: — performance improvementdocs: — documentation onlytest: — adding or correcting testsbuild: / ci: — build system or CI changeschore: — tooling, deps, housekeeping that doesn't fit the aboverevert: — reverts a previous commitOptional scope in parentheses when the repo already uses it (look at recent git log to confirm style): feat(lib-node): add /heap-snapshot endpoint.
Style:
chore:.The PR description is the most important output. Reviewers read it first; if it's good, the rest of the review goes faster.
Required content:
Length guidance: as compact as the change allows. A typo fix is one sentence. A multi-part feature is a short summary plus a tight bullet list. No filler, no test-plan boilerplate, no marketing tone. If you find yourself padding, stop.
Line breaks: no superfluous line-breaks. Only insert double line breaks where it marks a genuine section delimitation (e.g. between the summary and a **Why:** block, or before a bullet list). Do not separate every sentence with a line-break, do not pad between bullets, and do not add leading or trailing blank lines.
Example, for a small feature:
Title: feat(import): add --dry-run flag to preview changes without writing
Add `--dry-run` flag to the import command so users can preview changes without writing.
**Why:** requested by ops to validate large imports before committing.
**Regression risks:**
- Default behavior unchanged, but the new flag short-circuits before the DB transaction — double-check no downstream code assumed the transaction always runs.
After printing the report, write the title and body to local files so the user can copy them without terminal soft-wraps inserting stray line breaks into the pasted text. Resolve the git directory via git rev-parse --git-dir — in a linked worktree, .git is a file (containing gitdir: ...), not a directory, so a hardcoded .git/PR_BODY.md path fails with "Not a directory":
git_dir=$(git rev-parse --git-dir)
printf '%s\n' "<title>" > "$git_dir/PR_TITLE"
cat > "$git_dir/PR_BODY.md" <<'EOF'
<body markdown>
EOF
The git directory is the right location: it's never committed, is scoped to this repo (or worktree, so parallel branches don't clobber each other), and persists across sessions. Don't write these files into the working tree — they'd risk being committed.
Then tell the user, in one short message, the resolved file paths and the platform-specific clipboard command. Substitute the actual value of $git_dir into the message — don't print the literal $git_dir:
Wrote
<git_dir>/PR_TITLEand<git_dir>/PR_BODY.md. To copy the body:
- Wayland:
wl-copy < <git_dir>/PR_BODY.md- X11:
xclip -selection clipboard < <git_dir>/PR_BODY.md- macOS:
pbcopy < <git_dir>/PR_BODY.md
development
How to add a database migration / upgrade script in a data-fair service that uses @data-fair/lib-node/upgrade-scripts (data-fair, processings, events, catalogs, etc.). Covers the gotcha that trips up most agents: which version goes in the folder name. Use this skill whenever the user asks to add an upgrade script, write a migration, backfill a field on existing documents, reshape a Mongo collection on deploy, or anything described as "needs to run once on production after deploy". Also use it when reading or modifying an existing `upgrade/X.Y.Z/` directory.
tools
How to implement real-time websocket communication in data-fair services. Covers the full stack: server-side setup with @data-fair/lib-express/ws-server, emitting events with @data-fair/lib-node/ws-emitter, subscribing from Vue components with @data-fair/lib-vue/ws, and using @data-fair/lib-node/ws-client for Node.js programmatic WS clients and integration tests. Use this skill whenever the user wants to add websocket support, emit real-time events, subscribe to channels, implement live updates, push notifications, any pub/sub pattern in a data-fair service, or write integration tests that verify websocket behavior — even if they just say "real-time", "live updates", or "test websockets".
development
How to use the @data-fair/lib session management system in services that consume sessions (not login/account management). Use this skill whenever the task involves reading user identity, checking permissions, protecting routes, accessing account/organization info, or implementing authorization logic in a data-fair service -- both on the Express/Node backend and in Vue frontend components. Also use it when the user mentions session middleware, account roles, admin mode, or organization switching in a data-fair context.
testing
Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, update or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy.