Goal-Calibration/ai/backend-context.md
Yisroel Baum 5d6c9f7ec9
add llm anti-patterns to context files
name the LLM-default constructs this project forbids in
explicit before/after tables. catching the trap by pattern
match is more reliable than expecting a general rule to be
applied at write time. backend table covers PHP traps
(arrow fns, inline FQCNs, default params, stored refs, em
dashes, short names); frontend table covers JS/template/
cypress traps.
2026-05-02 22:15:23 +03:00

64 lines
3 KiB
Markdown

# Backend context
> Read `ai/shared.md` first. This file only covers backend-specific rules.
## Project Context
**Stack:** PHP 8.5, Slim 4, PHP-DI/Slim-Bridge, PHPUnit 13, Composer.
Persistence is JSON-file based (see `Json*Repository` classes); no ORM.
**Architecture:** Domain-Driven Design. Code is organized by domain entity
under `app/` (Auth, Node, Plan, ScheduledNode, Text, User, View,
ValueObjects) into Entities, DTOs, Repositories, Use Cases, and Fakes
(in-memory repos for tests).
## Code patterns
- Look at similar entities (e.g. `Node`, `Text`) for reference
- Entities: constructor with properties, getters
- DTOs: simple data containers for creation (e.g. `CreateTextDto`)
- Repositories: interfaces that define data access
- Do not write unit tests for concrete repository implementations
(e.g. `JsonNodeRepository`). 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
- Look at `tests/Fakes/` for examples
- Find/lookup methods must return a new instance of the entity, not the
stored reference
- Tests: follow existing patterns in `tests/Unit/[Entity]/UseCases/`
- In `setUp`, only use fake repositories for entities under test - construct
dependency objects directly with `new` (e.g.
`new Text(...)`) 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 `php-cs-fixer fix` on worked-on directories before committing (uses the
existing `.php-cs-fixer.dist.php` config).
## 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.