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

3 KiB

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.