standards
Overview
My non-negotiable conventions — the floor every other skill stands on. When one
applies, follow it exactly; it overrides generic defaults. Flag a real conflict
once, then proceed (don't rehash).
Commits
- One line only:
type(scope): subject — English, imperative. No body unless I explicitly ask. Detail belongs in the PR description, not the commit.
- No trailers: never add
Co-Authored-By:, and never add a 🤖 Generated with Claude Code footer to commits or PR bodies.
- Pick the Conventional Commit type honestly:
feat/fix cut releases; chore/docs/refactor/test don't. Scaffolding is chore, not feat.
- In release-please + auto-merge repos the amend window is ~seconds. Get the one-line message right the first time.
- Bots are exempt: dependabot / release-please author their own commits with structured multi-line bodies (machine-readable footers, changelogs). That's expected — the one-line rule governs commits I write, not bot commits.
- Integrate PRs by rebase (squash only for a messy WIP branch) — never a merge commit.
main stays strictly linear; release-please keeps its release PR rebased on main automatically.
Branches
- Never commit straight to the default branch. Feature work goes on a short-lived branch (
feat/…, fix/…, chore/…), pushed and opened as a PR — even in a solo repo.
- One branch = one purpose; keep it small. Integrate by rebase (see Commits), then delete the branch.
main stays strictly linear.
- Bots are exempt: release-please and dependabot manage their own branches/PRs.
Pull Requests
- Title: same
type(scope): subject as a commit — English, imperative, one line.
- Body — clear and simple to read, by sections (the structure lives here, not in a repo template file): What & why (1-2 sentences) → Changes (short bullets) → Testing (commands run + result) → Notes (risks / screenshots / follow-ups). Drop any section that doesn't apply — scannable, no filler, no checklist boilerplate.
- No trailers, no footer: never a
🤖 Generated with Claude Code footer and never Co-Authored-By: — same rule as commits.
- Link the issue with
Closes #N when there is one.
Tests
Fewer, higher-signal tests over a high count. Before writing one, ask: "If I delete
this, what real bug could ship undetected?" If the answer is "none / TypeScript
catches it", don't write it.
- No mock-only tests. Don't
vi.fn()/spy a port and assert it was called — that tests wiring, not behavior. Build a small in-memory fake of the port and assert the observable outcome.
- Prefer integration-flavored tests: one test exercising use case → service → repository (memory repo) beats three mock-at-every-seam unit tests.
- Skip trivial passthroughs: a use case that just forwards to an already-tested service needs no test of its own.
- A VO getter is not a test. Test the behavior the value object enforces (validation, equality, immutability), not the generated property.
- Coverage % is not a target. 80% with rich behavioral assertions beats 100% of trivial ones.
Repo hygiene
- Never
git add -A / git add . / git add --all. Inspect git status --short and stage explicit paths.
- Repo holds only project code + README (+ LICENSE/config). Internal docs, specs, plans and checklists live outside the repo in a sibling
../<repo>-notes/ dir — never committed, and never .gitignore'd either (gitignoring a doc is itself the violation; just don't stage it).
- Skill defaults are wrong here — override them.
brainstorming, writing-plans and task-flow default to saving specs/plans at docs/superpowers/... inside the repo and then committing them. Do NOT follow that. When bootstrapping a project, create ../<repo>-notes/ as a sibling of the repo before the first spec/plan write, and target it from that very first Write. The first time a spec lands in docs/ inside the repo, the rule is already broken.
- If an internal doc reaches the repo anyway:
git rm it (or rewrite history with the user's OK if already pushed) and move it to ../<repo>-notes/. Never "fix" it by adding the path to .gitignore.
- Code, identifiers, log strings, file/var names, UI strings → English. Comments minimal — only the non-obvious "why".
Inclusive language
Applies to identifiers, comments, commits, log strings and user-facing copy in every
locale. Swap the term at write time; if a neutral genuinely reads worse, flag it once and
pick the least-bad rephrase — don't revert to the excluding form.
- Code / technical (English) — never introduce the legacy term in new code:
master/slave → primary/replica, leader/follower, or main/worker (by domain); the default branch is main.
whitelist/blacklist → allowlist/blocklist (or allowed/blocked).
grandfathered → legacy / pre-existing; sanity check → quick check / validation.
dummy → placeholder / sample; man-hours → person-hours; manned → staffed.
- Don't churn third-party/library names you don't control — fix what's yours.
- User-facing copy (ca/en/es/eu/gl/va) — neutral & collective, never split forms or neologisms:
- Don't assume the reader's gender: impersonal or neutral 2nd person — "te damos la bienvenida", not "bienvenidos".
- Don't assume family shape or roles: "la familia de…", not "los papás/padres de…"; "tu familia" / "persona adulta", not "mamá/papá".
- Neutralize with real words, not "/" splits and not "-x/-e": "peques" / "la infancia" (not "niños/as", not "niñes"); "participantes" / "quien juega" (not "usuarios/as"); "el equipo". If no neutral term fits, rephrase the sentence rather than gender it.
- Skip ableist/violent filler ("está de locos", "te vas a volver loco") when a plain neutral exists.
eskills:ux-bar enforces this for UI strings; eskills:standards for code, commits and identifiers.
IDs
- Default to UUID v7 (
uuidv7, RFC 9562) for any newly generated entity ID — no need to ask each time. The ~1 KB dependency is acceptable; time-ordering is worth it.
- No-flag exceptions: short URL-friendly slugs (not UUIDs at all). If a project already standardized on v4, follow it — don't refactor existing IDs unprompted.
Before pushing
Run all the gates CI runs, as one batched call — not just tests:
lint + typecheck + tests
- Prefer the project's single
verify/check script if it exposes one. Passing CI is the floor, not a stretch goal.
- Non-negotiable whenever the task ends in a push (especially "súbelo para que aplique release") — lint failures gate releases too.
Pushback discipline
Once I validate a decision ("OK, hazlo"), stop adding caveats or re-validation on the
same point. Group critical warnings once, up front. Push back again only for genuinely
new, un-flagged risks (security, data loss).
1---2name: standards3description: Use when about to commit, write or design tests, name identifiers, write user-facing copy, choose an ID type, or push — enforces my non-negotiable conventions for commits, test design, repo hygiene, inclusive language, IDs, and pre-push checks.4---56# standards78## Overview910My non-negotiable conventions — the floor every other skill stands on. When one11applies, follow it exactly; it overrides generic defaults. Flag a real conflict12once, then proceed (don't rehash).1314## Commits1516- **One line only:** `type(scope): subject` — English, imperative. **No body** unless I explicitly ask. Detail belongs in the PR description, not the commit.17- **No trailers:** never add `Co-Authored-By:`, and never add a `🤖 Generated with Claude Code` footer to commits or PR bodies.18- Pick the Conventional Commit type honestly: `feat`/`fix` cut releases; `chore`/`docs`/`refactor`/`test` don't. Scaffolding is `chore`, not `feat`.19- In release-please + auto-merge repos the amend window is ~seconds. Get the one-line message right the first time.20- **Bots are exempt:** dependabot / release-please author their own commits with structured multi-line bodies (machine-readable footers, changelogs). That's expected — the one-line rule governs commits I write, not bot commits.21- **Integrate PRs by rebase** (squash only for a messy WIP branch) — **never a merge commit**. `main` stays strictly linear; release-please keeps its release PR rebased on `main` automatically.2223## Branches2425- **Never commit straight to the default branch.** Feature work goes on a short-lived branch (`feat/…`, `fix/…`, `chore/…`), pushed and opened as a **PR** — even in a solo repo.26- One branch = one purpose; keep it small. Integrate by **rebase** (see Commits), then delete the branch. `main` stays strictly linear.27- **Bots are exempt:** release-please and dependabot manage their own branches/PRs.2829## Pull Requests3031- **Title:** same `type(scope): subject` as a commit — English, imperative, one line.32- **Body — clear and simple to read, by sections** (the structure lives here, not in a repo template file): **What & why** (1-2 sentences) → **Changes** (short bullets) → **Testing** (commands run + result) → **Notes** (risks / screenshots / follow-ups). **Drop any section that doesn't apply** — scannable, no filler, no checklist boilerplate.33- **No trailers, no footer:** never a `🤖 Generated with Claude Code` footer and never `Co-Authored-By:` — same rule as commits.34- Link the issue with `Closes #N` when there is one.3536## Tests3738Fewer, higher-signal tests over a high count. Before writing one, ask: _"If I delete39this, what real bug could ship undetected?"_ If the answer is "none / TypeScript40catches it", don't write it.4142- **No mock-only tests.** Don't `vi.fn()`/spy a port and assert it was called — that tests wiring, not behavior. Build a small in-memory fake of the port and assert the observable outcome.43- **Prefer integration-flavored tests:** one test exercising use case → service → repository (memory repo) beats three mock-at-every-seam unit tests.44- **Skip trivial passthroughs:** a use case that just forwards to an already-tested service needs no test of its own.45- **A VO getter is not a test.** Test the behavior the value object enforces (validation, equality, immutability), not the generated property.46- **Coverage % is not a target.** 80% with rich behavioral assertions beats 100% of trivial ones.4748## Repo hygiene4950- **Never `git add -A` / `git add .` / `git add --all`.** Inspect `git status --short` and stage explicit paths.51- Repo holds **only project code + README** (+ LICENSE/config). Internal docs, specs, plans and checklists live **outside the repo** in a sibling `../<repo>-notes/` dir — never committed, and **never `.gitignore`'d either** (gitignoring a doc is itself the violation; just don't stage it).52- **Skill defaults are wrong here — override them.** `brainstorming`, `writing-plans` and `task-flow` default to saving specs/plans at `docs/superpowers/...` _inside_ the repo and then committing them. Do NOT follow that. When bootstrapping a project, create `../<repo>-notes/` as a sibling of the repo **before the first spec/plan write**, and target it from that very first Write. The first time a spec lands in `docs/` inside the repo, the rule is already broken.53- If an internal doc reaches the repo anyway: `git rm` it (or rewrite history with the user's OK if already pushed) and move it to `../<repo>-notes/`. Never "fix" it by adding the path to `.gitignore`.54- Code, identifiers, log strings, file/var names, UI strings → **English**. Comments minimal — only the non-obvious "why".5556## Inclusive language5758Applies to identifiers, comments, commits, log strings **and** user-facing copy in every59locale. Swap the term at write time; if a neutral genuinely reads worse, flag it once and60pick the least-bad rephrase — don't revert to the excluding form.6162- **Code / technical (English) — never introduce the legacy term in new code:**63 - `master`/`slave` → `primary`/`replica`, `leader`/`follower`, or `main`/`worker` (by domain); the default branch is `main`.64 - `whitelist`/`blacklist` → `allowlist`/`blocklist` (or `allowed`/`blocked`).65 - `grandfathered` → `legacy` / `pre-existing`; `sanity check` → `quick check` / `validation`.66 - `dummy` → `placeholder` / `sample`; `man-hours` → `person-hours`; `manned` → `staffed`.67 - Don't churn third-party/library names you don't control — fix what's yours.68- **User-facing copy (ca/en/es/eu/gl/va) — neutral & collective, never split forms or neologisms:**69 - Don't assume the reader's gender: impersonal or neutral 2nd person — "te damos la bienvenida", not "bienvenidos".70 - Don't assume family shape or roles: "la familia de…", not "los papás/padres de…"; "tu familia" / "persona adulta", not "mamá/papá".71 - Neutralize with real words, **not** "/" splits and **not** "-x/-e": "peques" / "la infancia" (not "niños/as", not "niñes"); "participantes" / "quien juega" (not "usuarios/as"); "el equipo". If no neutral term fits, **rephrase the sentence** rather than gender it.72 - Skip ableist/violent filler ("está de locos", "te vas a volver loco") when a plain neutral exists.73- `eskills:ux-bar` enforces this for UI strings; `eskills:standards` for code, commits and identifiers.7475## IDs7677- Default to **UUID v7** (`uuidv7`, RFC 9562) for any newly generated entity ID — no need to ask each time. The ~1 KB dependency is acceptable; time-ordering is worth it.78- No-flag exceptions: short URL-friendly slugs (not UUIDs at all). If a project already standardized on v4, follow it — don't refactor existing IDs unprompted.7980## Before pushing8182Run **all** the gates CI runs, as one batched call — not just tests:8384> **lint + typecheck + tests**8586- Prefer the project's single `verify`/`check` script if it exposes one. Passing CI is the floor, not a stretch goal.87- Non-negotiable whenever the task ends in a push (especially "súbelo para que aplique release") — lint failures gate releases too.8889## Pushback discipline9091Once I validate a decision ("OK, hazlo"), stop adding caveats or re-validation on the92same point. Group critical warnings once, up front. Push back again only for genuinely93new, un-flagged risks (security, data loss).