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.
3 KiB
Backend context
Read
ai/shared.mdfirst. 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.
- Do not write unit tests for concrete repository implementations
(e.g.
- Use cases: business logic with Request objects
- When throwing exceptions, add
@throwsdocblock
- When throwing exceptions, add
- 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
- Look at
- Tests: follow existing patterns in
tests/Unit/[Entity]/UseCases/- In
setUp, only use fake repositories for entities under test - construct dependency objects directly withnew(e.g.new Text(...)) instead of creating them through their fake repositories
- In
PHP rules
- Imports: always put
usestatements 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.