Files
familienarchiv/.specify/AGENTS.md
Marcel c160ab3223 refactor(sdd): make the feature spec issue-only (no committed spec.md)
The Gitea issue body is the single source of truth for a spec; the only
per-feature artifact in git is the RTM row (REQ-ID -> issue # -> test). Drops
per-feature spec.md/tasks.md/checklist files from the workflow (the _example
stays as a template/reference). Updates the guide, ADR-041, AGENTS.md, CLAUDE.md,
templates, the RTM (adds an Issue column), the implement/review-pr skills, and
replaces the file-spec CI jobs with an rtm-check.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 12:55:26 +02:00

5.3 KiB
Raw Blame History

AGENTS.md

Machine-readable rules for AI coding agents (Claude Code, Copilot, Cursor, …) working in this repository. Read this on every invocation. These are executable constraints, not aspirations. The full rationale lives in constitution.md and the docs it links — this file does not duplicate it, it points to it.

If anything here conflicts with the user's explicit instruction, the user wins. Otherwise, constitution > this file > convenience.


Stack & Versions

Layer Tech Version
Backend Spring Boot (Java, Maven, Jetty, JPA/Hibernate, Flyway, Spring Security, Session JDBC) Boot 4.0.6 / Java 21
API docs springdoc-openapi (webmvc-ui), served at /v3/api-docs (dev profile only)
Frontend SvelteKit / Svelte 2.60 / 5.43
Frontend lang/style TypeScript / Tailwind CSS / Paraglide i18n (de/en/es) TS 5.9 / TW 4.1
API client openapi-fetch + openapi-typescript (types generated from the live spec)
DB PostgreSQL 16
Object storage MinIO (S3-compatible)
Sidecars ocr-service, nlp-service (Python / FastAPI) Python 3.11
Tests JUnit + Mockito + @WebMvcTest + Testcontainers (backend); Vitest + vitest-browser-svelte + Playwright (frontend); Pytest (services)
Lint/format ESLint 9 (+ eslint-plugin-boundaries) + Prettier; Semgrep (backend)
CI Gitea Actions (.gitea/workflows/)

App port 8080; management port 8081. Backend app id: org.raddatz.familienarchiv / 0.0.1-SNAPSHOT.

Architectural Constraints

  • Controllers call services only — never a repository. (constitution §1.2)
  • A service uses only its own domain's repository; reach other domains via their service. (constitution §1.3)
  • A new backend domain goes in its own package AND is added to ArchitectureTest's allow-lists in the same change. (constitution §1.7)
  • Frontend cross-domain imports are allowed only where frontend/eslint.config.js permits; otherwise move shared code to $lib/shared/. (constitution §1.4)
  • Never serialize a lazy-collection entity across the controller boundary — assemble a view in-transaction. (constitution §1.6 / ADR-036)
  • PersonAppUser; do not add account guards to Person-domain operations. (constitution §1.5)
  • Every POST/PUT/PATCH/DELETE endpoint has @RequirePermission(Permission.X). Use the enum, never @PreAuthorize. (constitution §2.12.2)
  • Throw only DomainException.notFound/forbidden/conflict/internal() from services, each with an ErrorCode. (CONTRIBUTING §Error handling)
  • Set createdBy/updatedBy from the session principal in the service — never bind them from a request body. (constitution §2.4)
  • Add an @Schema(requiredMode = REQUIRED) to every always-populated field. (constitution §3.5)
  • Never introduce a new runtime dependency without an ADR in Accepted status. (constitution §5.1)
  • Render untrusted text with {...}; never {@html} on user/import data. (constitution §2.5)
  • Build dates from ISO strings with a T12:00:00 suffix. (constitution §3.7)

Workflow Rules

  • Always write a failing test before implementation code; confirm it fails, then make it pass, then refactor. (constitution §3.1)
  • Run only the specific test file/class locally — never the full suite (it crashes the machine); leave the full sweep to CI.
  • Run npm run generate:api (in frontend/) after ANY backend model or endpoint change — most common cause of TS errors.
  • Run npm run lint before every commit; a fresh frontend worktree needs npm install first or the pre-commit hook fails.
  • When adding a new ErrorCode, update all four sites at once (constitution §3.6).
  • One logical change per commit; reference the Gitea issue (Closes #n / Refs #n) on the last line.
  • Create a git worktree for new issue work — never git checkout -b in the main repo while another branch has in-flight work. Avoid + in worktree/branch names (breaks vitest browser mode).
  • Pull main as a separate explicit step before creating a branch.
  • Track work as Gitea issues (http://192.168.178.71:3005, repo marcel/familienarchiv), not todo files.
  • Verify ADR and Flyway migration numbers against disk before using one — parallel worktrees make issue-body numbers go stale.

Do Not Touch

  • Generated: frontend/src/lib/generated/api.ts, frontend/src/lib/paraglide/, frontend/.svelte-kit/, frontend/build/, backend/target/.
  • Shipped Flyway migrations — add a new forward-only migration instead.
  • An Accepted ADR — supersede it with a new one.
  • actions/(upload|download)-artifact version — stays at @v3 (ADR-014).
  • CI guard steps — do not remove/weaken without an ADR.
  • main — never commit directly; branch + PR only.
  • Worktree copies (familienarchiv-*, .worktrees/) and data/ — never commit.

Spec-Driven Development

A feature's spec is its Gitea issue body — there is no committed spec.md. The issue's EARS requirements (REQ-NNN) and acceptance criteria are the contract; each maps to a test, traced in .specify/rtm.md (REQ-ID → issue # → test). Read the issue before implementing. The committed .specify/features/_example/ is a template/reference showing the full artifact set, not a live feature. Full workflow: SPEC_DRIVEN_DEVELOPMENT.md.