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>
5.3 KiB
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.jspermits; 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)
Person≠AppUser; do not add account guards to Person-domain operations. (constitution §1.5)- Every
POST/PUT/PATCH/DELETEendpoint has@RequirePermission(Permission.X). Use the enum, never@PreAuthorize. (constitution §2.1–2.2) - Throw only
DomainException.notFound/forbidden/conflict/internal()from services, each with anErrorCode. (CONTRIBUTING §Error handling) - Set
createdBy/updatedByfrom 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
Acceptedstatus. (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:00suffix. (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(infrontend/) after ANY backend model or endpoint change — most common cause of TS errors. - Run
npm run lintbefore every commit; a fresh frontend worktree needsnpm installfirst 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 -bin the main repo while another branch has in-flight work. Avoid+in worktree/branch names (breaks vitest browser mode). - Pull
mainas a separate explicit step before creating a branch. - Track work as Gitea issues (
http://192.168.178.71:3005, repomarcel/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
AcceptedADR — supersede it with a new one. actions/(upload|download)-artifactversion — 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/) anddata/— 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.