138 lines
6.1 KiB
Markdown
138 lines
6.1 KiB
Markdown
# Shared rules
|
|
|
|
Rules that apply to both backend and frontend work in this repo. Stack-specific
|
|
guides (`backend-context.md`, `frontend-context.md`) extend these.
|
|
|
|
## Process (TDD)
|
|
|
|
0. Before editing any file, ensure you are on a feature branch
|
|
(`git status` to confirm). If on master/main, create a branch
|
|
first.
|
|
1. Write the test first
|
|
2. Run the test to confirm it fails
|
|
3. Commit the failing test (the "tests committed first" rule in
|
|
action - the test commit precedes the implementation commit, not
|
|
merely the implementation lines)
|
|
4. Implement the code to make the test pass
|
|
5. Run the test to confirm it passes
|
|
6. Commit the implementation
|
|
7. Repeat this red/green commit cycle for each new behavior. Do not
|
|
batch multiple behaviors into one failing-test commit and one
|
|
implementation commit when they can be reviewed separately.
|
|
|
|
## Code style
|
|
|
|
- Lines should not exceed 80 columns, but should use up to 80 columns when
|
|
possible - do not split lines unnecessarily. Applies to PHP, TypeScript,
|
|
and Vue SFCs.
|
|
- Variable names: use explicit, descriptive names - never single-letter or
|
|
abbreviated variables (e.g. `$text` not `$t`, `node` not `n`)
|
|
- Method/function/constructor parameters: do not use default values - every
|
|
call site must pass every argument explicitly. This eliminates a class of
|
|
bugs where an unintended default silently slips through (e.g. an
|
|
`isAdmin=false` or an empty `passwordHash`). Apply the same rule in tests
|
|
and fakes - if a helper accepts a value, every caller must supply it.
|
|
- First, explore the codebase to understand existing patterns - look at similar
|
|
files for reference before writing anything
|
|
- Never use em dash characters in code, comments, or docblocks - use
|
|
hyphens (-) instead
|
|
|
|
## Git commit style
|
|
|
|
- Present tense, imperative mood (add, create, wire, fix, test)
|
|
- Lowercase
|
|
- Short (3-6 words)
|
|
- Match patterns found in git history
|
|
- Do not add any section mentioning claude as a coauthor
|
|
- Add a commit body when the subject alone cannot convey the change - e.g.
|
|
non-obvious motivation, multi-file coordination, or notable complexity
|
|
- Body: wrap at ~72 columns, separated from subject by a blank line, explain
|
|
the why and any non-obvious what
|
|
- Skip the body for trivial or self-explanatory commits
|
|
|
|
## Git commits
|
|
|
|
- Tests should be committed first, before implementation
|
|
- Prefer small, reviewable commits. Commit each meaningful step as soon as
|
|
it is green and the pre-commit checklist passes.
|
|
- One logical change per commit - a commit may span multiple files when they
|
|
form a single logical unit (e.g. a use case with its request and exception,
|
|
or a Vue SFC with its Pinia store and route entry)
|
|
- Split commits by behavior, public contract, migration, wiring, docs, or
|
|
mechanical formatting when those parts can be reviewed independently.
|
|
- A multi-file commit is okay only when the files form one inseparable
|
|
change. Do not use "one logical change" to justify batching adjacent work.
|
|
- Do not batch several behaviors into one "tests" commit and one
|
|
"implementation" commit. Repeat the red/green cycle per behavior.
|
|
- Do not bundle backend and frontend changes unless both are required for
|
|
the same user-facing behavior.
|
|
- Do not bundle cleanup, refactors, renames, or formatting with feature
|
|
behavior.
|
|
- Keep commits focused: not one file per commit, not unrelated work batched
|
|
- Make commits frequent - commit each meaningful logical step as you go
|
|
- Commits are for reviewing and documenting the development of code
|
|
- When the formatter or linter modifies files outside your intended
|
|
change, either `git restore` them or land them as a separate
|
|
`format <area>` / `lint <area>` commit - never bundle drive-by
|
|
formatter churn into a feature commit
|
|
- If pre-commit lint fails on code you did not touch, do not bundle
|
|
the fix - either land the unrelated fix as its own commit first, or
|
|
note the pre-existing failure and proceed
|
|
|
|
## Branching
|
|
|
|
- Use kebab-case (e.g. `set-page`, `element-tree`, `media-upload`)
|
|
- Use descriptive feature names
|
|
- Or use type/description: `feature/set-page`, `fix/bug-name`
|
|
- NEVER work directly on master/main - always create and work on a branch
|
|
|
|
Do not push anything. Make commits as you go.
|
|
|
|
## Pre-commit checklist
|
|
|
|
Before EVERY commit (no exceptions), verify each item. Treat this as
|
|
mechanical, not aspirational - a "yes" to all is required.
|
|
|
|
**Branch + scope:**
|
|
- [ ] On a feature branch (not master/main).
|
|
- [ ] This commit is one logical change. If it spans unrelated changes,
|
|
stop and split it.
|
|
- [ ] This commit has been split as far as it can be while staying
|
|
reviewable. If any part can land independently, split it.
|
|
- [ ] Tests for new behavior were committed BEFORE this implementation
|
|
(or this commit IS the failing-test commit).
|
|
|
|
**Code rules** (see `backend-context.md` PHP rules,
|
|
`frontend-context.md` Vue/TS rules):
|
|
- [ ] No arrow functions in PHP (`fn () =>`).
|
|
- [ ] No inline FQCNs in type hints, return types, or `::class`
|
|
references (`\App\Foo\Bar` -> hoist to `use App\Foo\Bar;`).
|
|
- [ ] No default parameter values on methods/functions/constructors
|
|
(PHP or TS).
|
|
- [ ] Find/lookup repository methods return new instances, not stored
|
|
references.
|
|
- [ ] No em dashes (use hyphens).
|
|
- [ ] Variable names are explicit (no `$t`, `n`, `res`, `req`, `e`, etc.).
|
|
- [ ] No `any` in TypeScript - use concrete types or `unknown` with a
|
|
narrowing guard.
|
|
- [ ] Vue SFCs use `<script setup lang="ts">` and `<style scoped>`.
|
|
|
|
**Mechanical checks (backend, when PHP changed):**
|
|
- [ ] `phpcs <touched dirs>` reports clean (config to be added; flake
|
|
provides `php-codesniffer`).
|
|
- [ ] `./vendor/bin/phpunit tests` is green.
|
|
|
|
**Mechanical checks (frontend, when frontend changed; run from
|
|
`frontend/rabbi_gerzi/`):**
|
|
- [ ] `npm run format` (oxfmt) reports clean (or any fixes are
|
|
committed).
|
|
- [ ] `npm run lint` (oxlint + eslint) passes.
|
|
- [ ] `npm run type-check` (vue-tsc) passes.
|
|
|
|
**Commit metadata:**
|
|
- [ ] Subject is lowercase, imperative, 3-6 words.
|
|
- [ ] No claude/AI coauthor lines.
|
|
- [ ] Body present iff the subject alone cannot convey the change.
|
|
|
|
If any item fails, fix it before committing - do not bundle the fix
|
|
into a future commit.
|