From 3bfcdfd0cc15d455d0d22375e5b7c4717bf66559 Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Mon, 25 May 2026 08:14:16 +0300 Subject: [PATCH] document repository lookups --- ai/backend-context.md | 40 ++++++++++++++++++++++++++++++---------- ai/shared.md | 2 ++ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/ai/backend-context.md b/ai/backend-context.md index e7825fa..cedaa42 100644 --- a/ai/backend-context.md +++ b/ai/backend-context.md @@ -20,6 +20,9 @@ intentionally omitted here - update this section as entities land. - 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. + - Repository methods that find records by a foreign key should accept + the related entity, not a raw id (e.g. `findBySet(Set $set)`, not + `findBySetId(int $setId)`). - Use cases: business logic with Request objects - When throwing exceptions, add `@throws` docblock - Fakes: in-memory implementations for testing @@ -50,16 +53,33 @@ to be added to the repo; the Nix flake already provides 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` | +- Arrow function: + - Forbidden: `fn ($node) => $node->getId()` + - Required: `function ($node) { return $node->getId(); }` +- Inline FQCN type: + - Forbidden: `function f(): \Psr\Http\Message\ResponseInterface` + - Required: import `ResponseInterface`, then return `ResponseInterface` +- Inline `::class`: + - Forbidden: `Container::get(\App\Foo\Bar::class)` + - Required: import `Bar`, then call `Container::get(Bar::class)` +- Default param: + - Forbidden: `function f(int $count = 10)` + - Required: `function f(int $count)` +- Default in fake: + - Forbidden: `public function create(Dto $dto, bool $strict = true)` + - Required: no default; every caller passes a value +- Lookup returns stored ref: + - Forbidden: `return $this->items[$id] ?? null;` + - Required: rebuild a new instance with the stored fields +- FK lookup by id: + - Forbidden: `findBySetId(int $setId)` + - Required: `findBySet(Set $set)` +- Short variable name: + - Forbidden: one-letter or abbreviated names (`$t`, `$n`, `$res`) + - Required: explicit names (`$text`, `$node`, `$response`) +- Em dash: + - Forbidden: comment or docblock containing an em dash character + - Required: use `-` When generating code, scan the diff for these patterns before writing it to disk. If you catch one mid-write, rewrite that line. diff --git a/ai/shared.md b/ai/shared.md index 351c88b..3d0522e 100644 --- a/ai/shared.md +++ b/ai/shared.md @@ -111,6 +111,8 @@ mechanical, not aspirational - a "yes" to all is required. (PHP or TS). - [ ] Find/lookup repository methods return new instances, not stored references. +- [ ] Backend repository methods that find by a foreign key accept the + related entity, not a raw id. - [ ] 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