Merge branch 'ai-folder'
This commit is contained in:
commit
e5a9262db6
3 changed files with 257 additions and 0 deletions
65
ai/backend-context.md
Normal file
65
ai/backend-context.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# Backend context
|
||||
|
||||
> Read `ai/shared.md` first. This file only covers backend-specific rules.
|
||||
|
||||
## Project Context
|
||||
|
||||
**Stack:** PHP 8.x, Slim 4, PHP-DI/Slim-Bridge, PHPUnit (dev), Composer.
|
||||
Persistence: PostgreSQL.
|
||||
**Architecture:** Domain-Driven Design. Code is organized by domain entity
|
||||
under `backend/app/` (PSR-4 `App\\`) into Entities, DTOs, Repositories,
|
||||
Use Cases, and Fakes (in-memory repos for tests). The entity list is
|
||||
intentionally omitted here - update this section as entities land.
|
||||
|
||||
## Code patterns
|
||||
|
||||
- Look at similar entities for reference before writing anything new
|
||||
- Entities: constructor with properties, getters
|
||||
- DTOs: simple data containers for creation (e.g. `CreateSetDto`)
|
||||
- Repositories: interfaces that define data access
|
||||
- Do not write unit tests for concrete repository implementations
|
||||
(e.g. `Postgres*Repository`). They are exercised by e2e tests.
|
||||
Use cases are tested with fake repositories.
|
||||
- Use cases: business logic with Request objects
|
||||
- When throwing exceptions, add `@throws` docblock
|
||||
- Fakes: in-memory implementations for testing
|
||||
- Live under `tests/Fakes/`
|
||||
- Find/lookup methods must return a new instance of the entity, not
|
||||
the stored reference
|
||||
- Tests: follow `tests/Unit/[Entity]/UseCases/` layout
|
||||
- In `setUp`, only use fake repositories for entities under test -
|
||||
construct dependency objects directly with `new` (e.g.
|
||||
`new Set(...)`) instead of creating them through their fake
|
||||
repositories
|
||||
|
||||
## PHP rules
|
||||
|
||||
- Imports: always put `use` statements at the top of the file, never use
|
||||
inline imports (e.g. `\App\Foo\Bar::class`)
|
||||
- Closures: never use arrow functions (`fn () =>`) - always use regular
|
||||
anonymous functions (`function () { return ...; }`)
|
||||
|
||||
## Pre-commit
|
||||
|
||||
Run `phpcs` on worked-on directories before committing (phpcs ruleset
|
||||
to be added to the repo; the Nix flake already provides
|
||||
`php-codesniffer`). Run `./vendor/bin/phpunit tests` and confirm green.
|
||||
|
||||
## LLM anti-patterns
|
||||
|
||||
Constructs LLMs default to that this project forbids. Name the trap
|
||||
explicitly so you catch yourself before writing it.
|
||||
|
||||
| Anti-pattern | Forbidden | Required |
|
||||
|---|---|---|
|
||||
| Arrow function | `fn ($x) => $x->getId()` | `function ($x) { return $x->getId(); }` |
|
||||
| Inline FQCN type | `function f(): \Psr\Http\Message\ResponseInterface` | `use Psr\Http\Message\ResponseInterface;` then `function f(): ResponseInterface` |
|
||||
| Inline `::class` | `Container::get(\App\Foo\Bar::class)` | `use App\Foo\Bar;` then `Container::get(Bar::class)` |
|
||||
| Default param | `function f(int $count = 10)` | `function f(int $count)` |
|
||||
| Default in fake | `public function create(Dto $dto, bool $strict = true)` | no default; every caller passes a value |
|
||||
| Lookup returns stored ref | `return $this->items[$id] ?? null;` | rebuild a new instance with the stored fields |
|
||||
| Short variable name | `$t`, `$n`, `$res`, `$req`, `$e` | `$text`, `$node`, `$response`, `$request`, `$exception` |
|
||||
| Em dash | `// fetches user — by email` | `// fetches user - by email` |
|
||||
|
||||
When generating code, scan the diff for these patterns before writing it
|
||||
to disk. If you catch one mid-write, rewrite that line.
|
||||
70
ai/frontend-context.md
Normal file
70
ai/frontend-context.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# Frontend context
|
||||
|
||||
> Read `ai/shared.md` first. This file only covers frontend-specific rules.
|
||||
|
||||
## Project Context
|
||||
|
||||
**Stack:** Vue 3 (beta) + Vite + TypeScript + Pinia + vue-router. Tooling:
|
||||
oxlint, oxfmt, eslint. Cypress 15 for E2E (provided by the Nix devshell;
|
||||
project-level config still to be wired up - see Testing below).
|
||||
**Entry point:** `frontend/rabbi_gerzi/src/main.ts`; root component
|
||||
`src/App.vue`; routes in `src/router/`; stores in `src/stores/`.
|
||||
|
||||
All frontend paths below are relative to `frontend/rabbi_gerzi/`.
|
||||
|
||||
## Code patterns
|
||||
|
||||
- Look at existing files for reference before writing anything
|
||||
- **Components:** SFC `.vue` files using `<script setup lang="ts">` and
|
||||
`<style scoped>`
|
||||
- **Stores:** Pinia, one per domain area, under `src/stores/`
|
||||
- **Routes:** declared in `src/router/index.ts`
|
||||
- **Imports:** keep at the top of the file
|
||||
- **Variable names:** explicit, descriptive (e.g. `element` not `el`)
|
||||
- **Line width:** 80 columns, same as PHP
|
||||
|
||||
## Testing
|
||||
|
||||
- Cypress E2E only, at `frontend/rabbi_gerzi/cypress/e2e/*.cy.ts`
|
||||
- Cypress is available via the Nix devshell; project-level config
|
||||
(`cypress.config.ts`, `cypress/` folder) still needs to be wired up.
|
||||
Add it when the first E2E test lands and remove this note.
|
||||
- Tests must exercise the UI - drive via `cy.visit` / `cy.get`. Do not
|
||||
use `cy.request` to set up state or assert; if seeding is needed, add
|
||||
it via backend seed data.
|
||||
- Role matching: log in as the role appropriate to the page under test
|
||||
(e.g. admin spec uses admin login, user spec uses user login).
|
||||
|
||||
## Pre-commit
|
||||
|
||||
Run from `frontend/rabbi_gerzi/`:
|
||||
|
||||
- `npm run format` (oxfmt)
|
||||
- `npm run lint` (oxlint + eslint)
|
||||
- `npm run type-check` (vue-tsc)
|
||||
|
||||
All three must pass before committing.
|
||||
|
||||
## Note on commit granularity
|
||||
|
||||
A new view is often a `.vue` SFC plus a Pinia store plus a route entry -
|
||||
commit them together as a single logical unit, per the "one logical
|
||||
change per commit" rule in `shared.md`.
|
||||
|
||||
## LLM anti-patterns
|
||||
|
||||
Constructs LLMs default to that this project forbids on the frontend.
|
||||
|
||||
| Anti-pattern | Forbidden | Required |
|
||||
|---|---|---|
|
||||
| Short variable name | `t`, `n`, `res`, `req`, `e`, `el`, `ev` | `text`, `node`, `response`, `request`, `submitEvent`, `element`, `clickEvent` |
|
||||
| Em dash in code/comments | `// loads sets — owner only` | `// loads sets - owner only` |
|
||||
| Options API | `export default { data() { ... } }` | `<script setup lang="ts">` with composition API |
|
||||
| `any` type | `const value: any = ...` | concrete type, or `unknown` with a narrowing guard |
|
||||
| Default parameter value | `function load(limit: number = 10)` | `function load(limit: number)` - every call site passes it |
|
||||
| Unscoped styles | `<style>` (leaks globally) | `<style scoped>` |
|
||||
| `cy.request` in E2E | `cy.request('/api/...')` to set up state | drive via UI; seed via backend |
|
||||
| Cypress login role mismatch | logging in as wrong role for the page | match the role to the page under test |
|
||||
|
||||
When generating code, scan the diff for these patterns before writing it
|
||||
to disk.
|
||||
122
ai/shared.md
Normal file
122
ai/shared.md
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
# 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 for each new behavior
|
||||
|
||||
## 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 dashes (—) 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
|
||||
- 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)
|
||||
- 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.
|
||||
- [ ] 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue