Skip to content
Back to skills

Pr

ASecurity

Create a pull request for the DCC system. Handles branch verify, i18n translation, checks, E2E gate, simplify, commit, push, create/update PR, review, auto-fix. No version bump — that happens on main at release time.

  • 44 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
testinggobashtestinggitapidocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Scanned November 7, 2026

npx -y skills add foundryvtt-dcc/dcc --skill pr --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Pr?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Pr
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/foundryvtt-dcc-dcc/badge)](https://www.skillsdirectory.com/skills/foundryvtt-dcc-dcc)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: pr
description: Create a pull request for the DCC system. Handles branch verify, i18n translation, checks, E2E gate, simplify, commit, push, create/update PR, review, auto-fix. No version bump — that happens on main at release time.
---

# DCC PR Workflow

Execute each step below sequentially using your tools directly. Run everything
in the main context except for Step 12 (review agent).

If arguments are provided, treat them as the base branch (default: `main`).

**This repo is pnpm-only.** `package.json` has `"preinstall": "npx only-allow
pnpm"` and `packageManager: pnpm@11.25.0`, and only `pnpm-lock.yaml` is
committed. Every command below is `pnpm run ...`; never `npm`.

## Step 1: Branch Verification

Run `git branch --show-current` to get the current branch name.

- If on `main` or `master`: **STOP** and tell the user to create/checkout a feature branch.
- Otherwise, confirm the branch and proceed.

Tim does his own git work in this checkout, so re-verify `git status` right
before any branch operation and stop if the tree is mid-merge or mid-rebase.

## Step 2: i18n Translation Sync

If any `lang/*.json` files have been modified (check `git diff --name-only main...HEAD` and `git diff --name-only`):

1. **New keys in `lang/en.json`**: For every key added to `en.json`, add properly translated equivalents to ALL other language files (`cn.json`, `de.json`, `es.json`, `fr.json`, `it.json`, `pl.json`). Never leave English text in non-English files.
2. **Removed keys from `lang/en.json`**: Remove the same keys from all other language files.
3. **Renamed/moved keys**: Apply the same structural changes to all language files, preserving existing translations.
4. **Run `pnpm run compare-lang`** to verify all language files have matching keys. Fix any discrepancies before proceeding.

If NO lang files were modified in the diff, check whether any new `game.i18n.localize()` or `game.i18n.format()` calls were added in changed JS/HBS files that reference keys not present in `lang/en.json`. If so, add the missing keys to `en.json` and translate to all other languages.

## Step 3: Version Bump — NOT in the PR

Do **NOT** change `version.txt` in the PR. The bump always lands on `main` as
its **own commit**, after the PR merges (that's the `/release` skill's job —
see `docs/dev/RELEASE_PROCESS.md`).

Why: PRs are squash-merged, so a bump inside the PR gets folded into the
feature commit. The `foundry-release-action` builds release notes from commits
since the last release but **excludes the commit that carries the
`version.txt` change** — so the PR vanishes from its own release notes (this
bit #849 in v0.70.35 and #852 in v0.70.37).

If the diff already touches `version.txt`, revert that change before
committing and mention it in the final summary.

- Never update `system.json` or `package.json` versions either — the GitHub
  Action derives them from `version.txt`.

## Step 4: Vendored dcc-core-lib Check

`module/vendor/dcc-core-lib/` is generated output, synced by `pnpm run
sync-core-lib` (the `/sync-core-lib` skill). Check the diff for it:

```bash
git diff --name-only main...HEAD -- module/vendor/dcc-core-lib | head
```

- **Hand-edited vendor files** (a vendor diff without a matching
  `VERSION.json` bump, or a commit that isn't a `vendor: sync ...` commit):
  **STOP** and report. The fix belongs upstream in `moonloch/dcc-core-lib`,
  then flows in through the sync skill.
- **Temporary adapter workarounds**: if the branch added an adapter-side
  compensation for a lib bug while a lib PR was in flight, say so explicitly
  in the PR description — including the upstream PR link and the fact that
  the workaround must be removed after the next `sync-core-lib`. A permanent
  adapter workaround for a lib bug is not acceptable; if the lib PR has
  already merged, run the sync and drop the workaround in this PR instead.

## Step 5: Test Updates — Unit *and* E2E

CLAUDE.md requires that any behavior change updates the affected unit tests
**and** the `browser-tests/e2e/` Playwright specs in the *same* change.

1. Identify user-visible output the diff changed: DOM classes/text, button or
   action selectors, chat-card shape, flags, roll formulas, sheet markup,
   settings keys, data-model fields.
2. Grep for specs still asserting the old contract:
   ```bash
   grep -rn "<old class|old text|old flag|old selector>" browser-tests/e2e/ module/**/__tests__/
   ```
   Rewrite every stale assertion to the new contract.
3. Add at least one assertion covering the **new** behavior — in a unit test,
   and in an E2E spec when the change is user-visible.

A change to a chat card, roll, sheet, data model, or any user-visible output
that touches **no** spec almost always means one was missed. Say so in the
summary if you concluded none was needed, and why.

## Step 6: Pre-Flight Checks

Run `pnpm run check` (which runs `format`, `test`, and `compare-lang`).

- If checks **fail**: **STOP** and report the failures clearly. Do not proceed until all checks pass.
- If checks **pass**: proceed.

## Step 7: E2E Gate (attack / card / roll / sheet paths)

`pnpm run check` is Vitest-only. If the diff touches the attack, chat-card,
roll, or sheet paths (broadly: `module/*attack*`, `module/chat*`,
`module/*roll*`, `module/*sheet*`, `module/vendor/dcc-core-lib/`, `styles/`,
`templates/`), the **full** `browser-tests/e2e` suite must run before pushing.

```bash
pnpm run e2e:env test                          # full suite, isolated per-worktree env (#893)
pnpm run e2e:env test some-spec.spec.js        # single spec while iterating (no `--` separator)
```

Notes:
- Iterating on one spec is fine; run the full suite before the push.
- Do **not** edit files under `module/**` while a run is in flight — a run
  that spans an edit mixes code versions into one green summary. Batch edits
  between runs.
- Known flakes: rerun standalone before blaming the change —
  `v14-features` effect toggle and two-weapon primary in `adapter-dispatch.spec.js`
  (#867). (The fresh-world welcome-tour overlay is now suppressed at login by
  `prepareClientSettings` in `browser-tests/e2e/fixtures.js`.)
- If you push **without** running the suite on one of these paths, say so
  explicitly in the final summary.

## Step 8: Code Simplification

1. Run `git diff --stat` to identify modified files.
2. Review the changed code for:
  - Unnecessary complexity
  - Poor variable/function naming
  - Duplicate logic
  - Inconsistent code style
  - Hardcoded user-facing strings that should use `game.i18n.localize()`
  - New stylesheets under `styles/` are listed in `system.json`'s `styles` array (layer `system`) at the right source-order position
3. Make simplifications that improve clarity without changing behavior.
4. After simplification, re-run `pnpm run check`. If checks fail, revert those changes.

## Step 9: Documentation Update

Update the docs the diff actually invalidates. The usual suspects:

| Change | Doc |
|---|---|
| Public/extension surface (class registration, hooks, `CONFIG.DCC`) | `docs/dev/EXTENSION_API.md` — known to drift; check it every time |
| New/changed classes, data models, dispatch flow | `docs/dev/ARCHITECTURE.md` |
| New spec, fixture, or test command | `docs/dev/TESTING.md`, `docs/dev/TEST_COVERAGE.md` |
| New i18n conventions | `docs/dev/I18N.md` |
| Compendium/pack workflow | `docs/dev/PACKS.md`, `docs/dev/LEVELDB_WORKFLOW.md` |
| Release/versioning behavior | `docs/dev/RELEASE_PROCESS.md` |
| New setting or user-visible feature | `docs/user-guide/`, `README.md` |
| New rule for how Claude works in this repo | `CLAUDE.md` |

Include the doc updates in the same commits/PR.

## Step 10: Dependent Module Check

Grep for any class, function, constant, hook name, setting key, or template
path that was renamed or removed in the diff, then search for its usage in all
four dependent modules:

- `../../modules/dcc-qol`
- `../../modules/xcc`
- `../../modules/mcc-classes`
- `../../modules/dcc-crawl-classes`

`mcc-classes` and `dcc-crawl-classes` are real consumers of the class
registration / extension API, so extension-surface changes are most likely to
break there.

If a dependent module references something that was changed, **STOP** and report the potential breakage to the user before proceeding.

## Step 11: Atomic Commit Creation

1. Run `git status` and `git diff` to see all changes.
2. **The pre-commit hook runs `git add .`** (`.husky/pre-commit`: `pnpm run
   format && git add . && pnpm test`). It sweeps every untracked file into the
   commit, so staging specific paths is not enough on its own — before
   committing, confirm `git status` shows no stray untracked files, and move
   scratch files out of the repo (use the session scratchpad) if it does.
3. Group changes into logical, atomic commits. Each commit should:
  - Represent a single logical change
  - Be independently reversible
  - Have a clear commit message following conventional commits format
4. Recommended commit ordering:
  - Feature/fix commits first
  - i18n translation commits (e.g., `chore: translate new i18n keys to all languages`)
  - No version bump commit — `version.txt` is bumped on `main` after the merge (Step 3)
5. Stage with `git add <specific files>` — avoid `git add -A` (and see the hook caveat above).
6. End each commit message with **the attribution lines supplied for the
   current session** (the `Co-Authored-By:` / `Claude-Session:` lines from the
   session's attribution system-reminder). Do not hardcode a model version
   here — it goes stale every release.

## Step 12: Push Changes

```bash
git push -u origin $(git branch --show-current)
```

If push is rejected due to conflicts, **STOP** and report to user.

## Step 13: PR Creation or Update

1. Check if a PR already exists: `gh pr view --json number,title,url 2>/dev/null`
2. **If NO existing PR**: Create one with `gh pr create`:
  - Clear, descriptive title (under 70 chars)
  - Body with `## Summary` (bullet points) and `## Test plan` (checklist)
  - End the body with the session's PR attribution lines
  - Do not prompt user to accept PR description
3. **If PR EXISTS**: Update it with `gh pr edit --title "..." --body "..."`:
  - Always regenerate title and description from current diff
  - Never preserve stale descriptions
4. Use `git diff main...HEAD` (or the base branch passed as an argument) to understand the full scope of changes for the PR description.

## Step 14: Automated PR Review

Launch the `foundryvtt-dev:foundryvtt-reviewer` agent using the Agent tool, pointed at the current working directory. Do **not** use `isolation: "worktree"`: the reviewer is read-only (`Read`, `Grep`, `Glob`), so it cannot switch branches or modify anything — and when running inside a per-issue `work:start` worktree, a spawned worktree comes from the shared parent repo and lands on a stale `worktree-agent-*` branch that does not contain the PR's changes.

The reviewer will check for CLAUDE.md compliance, bugs, style issues, empty catches, swallowed errors, and test coverage gaps.

Collect and consolidate findings. Categorize as: Critical, High, Medium, Low.

## Step 15: Auto-Fix High-Priority Issues

Fix the findings categorized **Critical** or **High** in Step 14 (the reviewer
emits severities, not numeric confidence scores — judge by severity). For each:

1. Implement the fix directly (read the file, edit it).
2. Re-run `pnpm run check` — plus the affected E2E spec(s) if the fix touches an E2E-gated path (Step 7).
3. If the fix breaks checks, revert it and report instead.
4. Create a new atomic commit for the fixes.
5. Push the fix commit.

**Escalation**: If more than 3 issues need fixing, confirm with user before proceeding.

If a fix is complex or risky, **report it** instead of implementing it. Leave
Medium/Low findings for the summary.

## Step 16: Final Summary

Output a structured summary:

```
[PR SUMMARY]
PR URL: <url>
Version: unchanged (bump happens on main at release time)
i18n: <count> keys added/removed across <count> language files
Tests: unit <updated/added> | E2E <specs updated / suite run or "not required (paths untouched)">
Commits: <count> (<original> original + <fix> fixes)
Issues fixed: <count>
Remaining: <count> (manual review suggested)
Dependent modules: OK / <issues found>
core-lib: clean / <temporary workaround pending sync>
Status: Ready for review / Needs attention
```

## Escalation Criteria

**STOP and report** (do not proceed automatically) when:
- On main/master branch, or the tree is mid-merge/mid-rebase
- Pre-flight checks fail
- The E2E suite fails on a gated path and the failure is not one of the known flakes
- `module/vendor/dcc-core-lib/` was hand-edited
- i18n keys are missing translations and auto-translation confidence is low
- Push is rejected due to conflicts
- PR creation fails
- Critical issues found that are too complex to auto-fix
- More than 3 high-priority issues need fixing
- Dependent modules (`dcc-qol`, `xcc`, `mcc-classes`, `dcc-crawl-classes`) reference changed/removed APIs

## Edge Cases

- **No changes to commit**: Report this and ask if user wants to proceed.
- **Branch ahead of remote main**: Offer to rebase first.
- **PR already exists**: Update title AND description to match current changes.
- **Review finds no issues**: Report clean PR.
- **Auto-fixes fail checks**: Revert them and report the issue.
- **Language files out of sync**: Run `pnpm run compare-lang` and fix before proceeding.
- **E2E env won't boot**: a license-reconfirm screen can block autolaunch; `e2e:env` handles it since #898 — if it still hangs, report rather than retrying blindly.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.