| name | git-wrapup |
| description | Land verified working-tree changes in `@cyanheads/pixoo-toolkit` as a stack of logical commits, bump the version, author the CHANGELOG entry, and cut an annotated tag. Stops at "committed and tagged locally" — no push, no publish; `release-and-publish` picks up from there.
|
| metadata | {"author":"cyanheads","version":"1.0","audience":"external","type":"workflow"} |
When to use
Changes in the working tree are complete and verified, and they are ready to become a released version of the npm package. Typical triggers: a bug fix landed against a tracked issue, a feature is finished, a dependency refresh is done.
This is not a "save my work" skill. A commit here means the version ships.
Pre-wrapup gates
Every item must be true before you touch a version number. If one is red, fix it first — starting wrapup on a broken tree burns the version number and forces an amend.
Steps
1. Review what is shipping
git status
git log v<latest-tag>..HEAD --oneline
git diff --stat
git diff
If the tree is clean and there are no commits since the last tag, halt — nothing to wrap up.
2. Pick the version
Read version from package.json and apply the bump. This package is pre-1.0 but is published and consumed, so treat the public surface as real.
| Bump | When |
|---|
| patch | Bug fixes, dependency updates, docs, packaging metadata |
| minor | New exported function, new option on an existing export, new script |
| major | Removed or renamed export, changed exported signature or return shape, behavior change a consumer must code around |
Default to patch. A change to an exported type — PixooResult, Canvas, RGB — is never a patch.
3. Bump the version everywhere
package.json — version
README.md — any version badge or install snippet that pins a version
CLAUDE.md and AGENTS.md — only if they pin a version string; they must stay byte-identical
Catch stragglers (substitute the outgoing version):
rg -n --hidden -g '!node_modules' -g '!dist' -g '!.git' -g '!CHANGELOG.md' '0\.7\.7' .
Historical CHANGELOG.md entries are correct as-is — that is why it is excluded. Resolve every other hit.
4. Author the CHANGELOG entry
CHANGELOG.md is a single hand-maintained file in Keep a Changelog order. Add the new entry directly under the header block, above the previous version.
## [0.7.8] — 2026-08-13
### Fixed
- **canvas:** `drawRect()` now ... (#N).
Rules:
- Never
[Unreleased]. Always a concrete version and an ISO date.
- Section order: Added / Changed / Deprecated / Removed / Fixed / Security. Include only sections with entries.
- Every bullet leads with a bold module symbol (
**canvas:**, **client:**, **svg-path:**) matching the src/ module it changed.
- One sentence per bullet, two at the absolute most. Name the exported function and what a consumer observes now. Backlink the issue as
(#N).
- The diff is the source of truth. Every concrete claim — function name, parameter, error type, threshold — is read out of the changed file, never recalled.
- Cut: mechanism walkthroughs, rationale defense, "X is unchanged" clauses, edge-case inventories.
5. Run the gate
The tree being committed must pass. Run both raw — do not filter the output:
bun run devcheck
bun run test:all
If either fails, halt. Fix, then re-run this step.
6. Commit — group by concern, release artifacts on top
Never git add -A into one blob. Stage each concern explicitly, commit, move on:
- The work — one commit per concern. Two unrelated fixes are two commits. Work commits do not carry the version.
- The release commit — last, on top:
package.json, CHANGELOG.md, and any README/docs version strings.
git add <paths-for-this-concern>
git commit -m "<subject>"
The file is the atomic boundary. Never split one file's changes across commits. When a file serves two concerns, it ships whole in the commit of its dominant concern.
Subjects — Conventional Commits, scope = the src/ module:
- Work:
fix(canvas): reject non-finite rect dimensions, feat(color): oklch parsing, docs: document discovery timeout
- Release:
fix(canvas): 0.7.8 — reject non-finite rect dimensions
When the change and its version bump are inseparable for a small patch, a single commit whose subject leads with the version is correct — that is the shape most of this repo's history takes.
Every commit carries a body of one or two lines — never subject-only, never a paragraph. One sentence of why or the load-bearing constraint:
fix(canvas): reject non-finite rect dimensions
A NaN width reached the fill loop and wrote nothing while reporting success.
Rules:
- Plain
-m strings only — no heredoc, no command substitution
- No
Co-authored-by or Generated with trailers
- No marketing adjectives ("comprehensive", "robust", "enhanced", "improved")
- No closing keywords (
Fixes #N, Closes #N) — they close the issue on push, before the close-out comment recording what shipped. Use bare (#N) backlinks; closing is a deliberate later step.
- Each message stands alone in
git log — no chat context, no "as discussed"
7. Cut an annotated tag
git tag -a v<version> --cleanup=whitespace -m "<subject>
- <notable change> (#N)
- <notable change> (#N)"
--cleanup=whitespace is load-bearing: the default strip mode deletes #-leading lines as comments, silently removing markdown headers from the tag body that release-and-publish renders as the GitHub Release.
Format — a headline digest, not a CHANGELOG mirror:
- Subject omits the version. GitHub prepends
v<VERSION>: to the release title, so including it stutters.
- Flat bullets only — never
Added: / Fixed: section headers.
- Complete at headline granularity: notable changes get a bullet, minor and internal items share one grouped bullet. The CHANGELOG carries depth; the tag carries existence.
- Deps get one line at most, naming only what earns it.
- Issue backlinks as
(#N) — they render as links in the Release body.
8. Verify the end state
git log --oneline -8
git show v<version> --stat | head -20
git status
The tag must point at HEAD and the tree must be clean. If not, investigate before going further.
Do not push. This skill stops here.
Constraints
- Local only. No
git push, no remote operations. release-and-publish owns those.
- Never
git stash — not for a quick check, not for a clean baseline, not for any reason.
- Never destructive — no
git reset --hard, git restore ., git clean -f, git checkout -- ..
- Drive every git operation through Bash
git.
- If
v<version> already exists as a tag, halt and report the version string, the existing tag SHA, and the current HEAD SHA. Do not move or delete tags without explicit authorization.
Checklist