docs(legibility): migrate CLAUDE.md rules into human docs — DOC-7 #445

Merged
marcel merged 3 commits from feat/issue-401-claude-migration into main 2026-05-06 07:41:05 +02:00
Owner

Closes #401

⚠️ Merge order constraint: this PR must merge AFTER DOC-2 (#441), DOC-4 (#442), DOC-5 (#443), DOC-6 (#444). Several pointer links point to files that exist on those branches but not yet on main.


What this does

Processes all 7 CLAUDE.md files through the 3-bucket classification from the decision queue:

  • Bucket 1 — Human-relevant conventions → migrated to the appropriate human doc, replaced with a Markdown-linked pointer + optional LLM reminder
  • Bucket 2 — LLM-only behavioral instructions / code-gen reference → kept in CLAUDE.md as-is
  • Bucket 3 — Stale/obsolete content → tagged <!-- TODO: rewrite post-REFACTOR-1 — see Epic 4 --> (not deleted, per decision queue option A)

Pointer format (standardised per decision queue D3): → See [Target §Section](path#anchor)

Dual-audience sections: canonical convention in the human doc; CLAUDE.md keeps a brief LLM reminder line for content that prevents common generation mistakes.


Per-file migration summary

File Sections migrated Sections kept (Bucket-2) Tagged TODO New file created
scripts/CLAUDE.md All 9 script descriptions scripts/README.md
.devcontainer/CLAUDE.md Configuration, usage, limitations .devcontainer/README.md
docs/CLAUDE.md Folder structure, ADR guide, specs ADR-before-architecture reminder docs/README.md
ocr-service/CLAUDE.md All (to ocr-service/README.md from DOC-6) Single-node + SSRF reminder
backend/CLAUDE.md Layering Rules → ARCHITECTURE.md; Error Handling → CONTRIBUTING.md; Security → ARCHITECTURE.md Key Entities, Entity Code Style, Services, OCR Integration, How to Run, Testing Package Structure
root CLAUDE.md Stack → README.md; Layering Rules, Error Handling, Security, OpenAPI → ARCHITECTURE.md/CONTRIBUTING.md; API Client, Date Handling, UI Components, Frontend Errors, Infrastructure, Dev Container → human docs Common Commands, Domain Model, Entity Code Style, Services, Form Actions, Styling, Route Structure, API Testing Package Structure
frontend/CLAUDE.md API Client → CONTRIBUTING.md; Date Handling → CONTRIBUTING.md; Key UI Components → domain READMEs Project Structure, Form Actions, Styling, How to Run, Vite Proxy, i18n

Security-relevant migrations (flagged per Nora's feedback)

Section Migration target Classification
Backend Security/Permissions (@RequirePermission, Permission enum) docs/ARCHITECTURE.md §Permission system Bucket-1; LLM reminder kept in both CLAUDE.md files
ALLOWED_PDF_HOSTS SSRF warning ocr-service/README.md (DOC-6) Bucket-1; LLM reminder kept in ocr-service/CLAUDE.md
TRAINING_TOKEN operational note ocr-service/README.md (DOC-6) + docs/DEPLOYMENT.md (DOC-5) Bucket-1; migrated
ErrorCode mirror process CONTRIBUTING.md §Error handling Bucket-1; LLM reminder kept in root + backend CLAUDE.md

Fixes applied during migration

  • backend/CLAUDE.md had stale errors.ts path (src/lib/errors.ts) → corrected to frontend/src/lib/shared/errors.ts
  • backend/CLAUDE.md permissions list was missing ANNOTATE_ALL and BLOG_WRITE → added
  • scripts/README.md preserves the ⚠️ destructive-operation warning on reset-db.sh with same visual emphasis (per Tobias's feedback)

All pointer links point to section headings that exist (or will exist when this merges after its dependencies):

Files that became pointer-only after migration

  • scripts/CLAUDE.md — 1-line pointer + reminder
  • .devcontainer/CLAUDE.md — 1-line pointer
  • ocr-service/CLAUDE.md — 2-line pointer + reminders
  • docs/CLAUDE.md — 1-line pointer + ADR reminder

None were deleted (kept for completeness and discoverability).

Test plan

  • All 7 CLAUDE.md files processed (bucket classification complete)
  • All Bucket-1 content replaced with Markdown-linked pointers
  • Bucket-2 content preserved in each CLAUDE.md
  • Bucket-3 sections tagged <!-- TODO: rewrite post-REFACTOR-1 -->, not deleted
  • scripts/README.md, .devcontainer/README.md, docs/README.md created
  • ⚠️ Destructive-operation warning preserved on reset-db.sh in scripts/README.md
  • Pointer links reviewed against target headings in DOC-2/4/5/6 branches
  • PR merged only after DOC-2 (#441), DOC-4 (#442), DOC-5 (#443), DOC-6 (#444)

🤖 Generated with Claude Code

Closes #401 **⚠️ Merge order constraint:** this PR must merge AFTER DOC-2 (#441), DOC-4 (#442), DOC-5 (#443), DOC-6 (#444). Several pointer links point to files that exist on those branches but not yet on `main`. --- ## What this does Processes all 7 CLAUDE.md files through the 3-bucket classification from the decision queue: - **Bucket 1** — Human-relevant conventions → migrated to the appropriate human doc, replaced with a Markdown-linked pointer + optional LLM reminder - **Bucket 2** — LLM-only behavioral instructions / code-gen reference → kept in CLAUDE.md as-is - **Bucket 3** — Stale/obsolete content → tagged `<!-- TODO: rewrite post-REFACTOR-1 — see Epic 4 -->` (not deleted, per decision queue option A) Pointer format (standardised per decision queue D3): `→ See [Target §Section](path#anchor)` Dual-audience sections: canonical convention in the human doc; CLAUDE.md keeps a brief **LLM reminder** line for content that prevents common generation mistakes. --- ## Per-file migration summary | File | Sections migrated | Sections kept (Bucket-2) | Tagged TODO | New file created | |---|---|---|---|---| | `scripts/CLAUDE.md` | All 9 script descriptions | — | — | `scripts/README.md` ✅ | | `.devcontainer/CLAUDE.md` | Configuration, usage, limitations | — | — | `.devcontainer/README.md` ✅ | | `docs/CLAUDE.md` | Folder structure, ADR guide, specs | ADR-before-architecture reminder | — | `docs/README.md` ✅ | | `ocr-service/CLAUDE.md` | All (to `ocr-service/README.md` from DOC-6) | Single-node + SSRF reminder | — | — | | `backend/CLAUDE.md` | Layering Rules → ARCHITECTURE.md; Error Handling → CONTRIBUTING.md; Security → ARCHITECTURE.md | Key Entities, Entity Code Style, Services, OCR Integration, How to Run, Testing | Package Structure | — | | `root CLAUDE.md` | Stack → README.md; Layering Rules, Error Handling, Security, OpenAPI → ARCHITECTURE.md/CONTRIBUTING.md; API Client, Date Handling, UI Components, Frontend Errors, Infrastructure, Dev Container → human docs | Common Commands, Domain Model, Entity Code Style, Services, Form Actions, Styling, Route Structure, API Testing | Package Structure | — | | `frontend/CLAUDE.md` | API Client → CONTRIBUTING.md; Date Handling → CONTRIBUTING.md; Key UI Components → domain READMEs | Project Structure, Form Actions, Styling, How to Run, Vite Proxy, i18n | — | — | ### Security-relevant migrations (flagged per Nora's feedback) | Section | Migration target | Classification | |---|---|---| | Backend Security/Permissions (`@RequirePermission`, `Permission` enum) | `docs/ARCHITECTURE.md §Permission system` | Bucket-1; LLM reminder kept in both CLAUDE.md files | | `ALLOWED_PDF_HOSTS` SSRF warning | `ocr-service/README.md` (DOC-6) | Bucket-1; LLM reminder kept in `ocr-service/CLAUDE.md` | | `TRAINING_TOKEN` operational note | `ocr-service/README.md` (DOC-6) + `docs/DEPLOYMENT.md` (DOC-5) | Bucket-1; migrated | | ErrorCode mirror process | `CONTRIBUTING.md §Error handling` | Bucket-1; LLM reminder kept in root + backend CLAUDE.md | ### Fixes applied during migration - `backend/CLAUDE.md` had stale `errors.ts` path (`src/lib/errors.ts`) → corrected to `frontend/src/lib/shared/errors.ts` - `backend/CLAUDE.md` permissions list was missing `ANNOTATE_ALL` and `BLOG_WRITE` → added - `scripts/README.md` preserves the ⚠️ **destructive-operation warning** on `reset-db.sh` with same visual emphasis (per Tobias's feedback) ### Pointer link resolution All pointer links point to section headings that exist (or will exist when this merges after its dependencies): - `docs/ARCHITECTURE.md#layering-rule` — in DOC-2 PR #441 - `docs/ARCHITECTURE.md#permission-system` — in DOC-2 PR #441 - `CONTRIBUTING.md#error-handling` — in DOC-4 PR #442 - `CONTRIBUTING.md#frontend-api-client` — in DOC-4 PR #442 - `CONTRIBUTING.md#date-handling` — in DOC-4 PR #442 - `docs/DEPLOYMENT.md` — in DOC-5 PR #443 - Domain READMEs — in DOC-6 PR #444 ### Files that became pointer-only after migration - `scripts/CLAUDE.md` — 1-line pointer + reminder - `.devcontainer/CLAUDE.md` — 1-line pointer - `ocr-service/CLAUDE.md` — 2-line pointer + reminders - `docs/CLAUDE.md` — 1-line pointer + ADR reminder None were deleted (kept for completeness and discoverability). ## Test plan - [ ] All 7 CLAUDE.md files processed (bucket classification complete) - [ ] All Bucket-1 content replaced with Markdown-linked pointers - [ ] Bucket-2 content preserved in each CLAUDE.md - [ ] Bucket-3 sections tagged `<!-- TODO: rewrite post-REFACTOR-1 -->`, not deleted - [ ] `scripts/README.md`, `.devcontainer/README.md`, `docs/README.md` created - [ ] ⚠️ Destructive-operation warning preserved on `reset-db.sh` in `scripts/README.md` - [ ] Pointer links reviewed against target headings in DOC-2/4/5/6 branches - [ ] PR merged only after DOC-2 (#441), DOC-4 (#442), DOC-5 (#443), DOC-6 (#444) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
marcel added 2 commits 2026-05-05 23:35:35 +02:00
Processes all 7 CLAUDE.md files according to the 3-bucket classification.
Migration targets (CONTRIBUTING.md, docs/ARCHITECTURE.md, docs/DEPLOYMENT.md,
domain READMEs) are introduced by DOC-2/4/5/6 — this PR must merge last.

### scripts/CLAUDE.md → scripts/README.md
New `scripts/README.md` with full script documentation (preserving the
⚠️ destructive-operation warning on reset-db.sh). `scripts/CLAUDE.md`
reduced to a pointer + "document new scripts in README.md" reminder.

### .devcontainer/CLAUDE.md → .devcontainer/README.md
New `.devcontainer/README.md` with all configuration, usage, and limitations.
`devcontainer/CLAUDE.md` reduced to a single pointer line.

### docs/CLAUDE.md → docs/README.md
New `docs/README.md` covering the folder structure, ADR guide, infrastructure
docs, and specs folder. `docs/CLAUDE.md` reduced to pointer + ADR reminder.

### ocr-service/CLAUDE.md
Reduced to pointer to `ocr-service/README.md` (content migrated in DOC-6).
Kept LLM reminders: single-node constraint, ALLOWED_PDF_HOSTS SSRF risk.

### backend/CLAUDE.md
- Layering Rules → pointer to docs/ARCHITECTURE.md
- Error Handling → pointer to CONTRIBUTING.md + reminder
- Security/Permissions → pointer to docs/ARCHITECTURE.md + reminder
- Package Structure → tagged TODO post-REFACTOR-1
- Fixed errors.ts path to frontend/src/lib/shared/errors.ts
- Added ANNOTATE_ALL + BLOG_WRITE to permission list
- Key Entities, Entity Code Style, Services → kept (Bucket-2)

### root CLAUDE.md
- Stack, Infrastructure, Dev Container → pointers
- Layering Rules, Error Handling, Security, OpenAPI, API Client,
  Date Handling, UI Components, Frontend Error Handling → pointers + reminders
- Package Structure → tagged TODO post-REFACTOR-1
- Domain Model, Entity Code Style, Form Actions, Styling → kept (Bucket-2)

### frontend/CLAUDE.md
- API Client Pattern, Date Handling → pointers + reminders
- Key UI Components → pointer to domain READMEs
- Styling, Form Actions, How to Run, Vite Proxy, i18n → kept (Bucket-2)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
chore: remove accidentally staged familienarchiv-408 submodule
Some checks failed
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / OCR Service Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 3m29s
CI / OCR Service Tests (pull_request) Successful in 32s
CI / Backend Unit Tests (pull_request) Failing after 3m13s
68c77c36dd
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Author
Owner

Review: Markus Keller (Senior Architect)

Verdict: Changes requested

Bucket classifications

Overall the classification is sound. The split between human-relevant conventions (Bucket 1) and LLM-only behavioral instructions (Bucket 2) is applied consistently across all 7 files. Bucket 3 usage is appropriately narrow — only Package Structure gets the TODO tag in both root and backend CLAUDE.md files, which matches the PR description.

One classification concern: the docs/CLAUDE.md section "How to Use" (check specs/ before implementing, write ADR before coding, follow production-compose for deployment, keep TODOs updated) reads as human-workflow guidance, not LLM instruction. It was fully removed with no pointer — only the ADR sequencing rule survived as an LLM reminder. The "check specs/ before implementing" step has clear human relevance and arguably belongs in docs/README.md. Minor — the README does include "Before implementing a feature, check specs/" so the substance is preserved.

The PR documents all 7 pointer targets and explains the merge-order dependency on DOC-2, DOC-4, DOC-5, DOC-6. I verified the dependent files do not yet exist on main:

  • docs/ARCHITECTURE.md — absent (DOC-2, #441) ✓ dependency documented
  • CONTRIBUTING.md — absent (DOC-4, #442) ✓ dependency documented
  • docs/DEPLOYMENT.md — absent (DOC-5, #443) ✓ dependency documented
  • ocr-service/README.md — absent (DOC-6, #444) ✓ dependency documented

All pointer paths use the correct relative path notation (./docs/ARCHITECTURE.md, ../CONTRIBUTING.md, etc.). The .devcontainer/CLAUDE.md pointer → See [.devcontainer/README.md](./README.md) correctly resolves to the sibling file.

Blocker: docs/README.md has a duplicate infrastructure/ entry in the folder tree

The folder structure tree in the new docs/README.md lists infrastructure/ twice:

├── infrastructure/          # Deployment, CI/CD, and ops guides        ← line 11
...
└── infrastructure/          # Production compose, CI config, S3 migration  ← line 18

The second entry should not exist. The original docs/CLAUDE.md listed infrastructure/ once in the tree (with description "Deployment, CI/CD, and ops guides"). The second entry appears to be a stray artifact from the migration rewrite. The tree also omits several real directories/files that exist in docs/: audits/, presentation/, mail.md, TODO-backend.md, TODO-frontend.md. The old CLAUDE.md listed the TODO files explicitly; they were dropped without comment.

What's done well

  • The dual-audience pattern (canonical in human doc + brief LLM reminder) is applied uniformly.
  • The merge-order constraint is prominently documented both in the PR description and enforced through the pointer strategy.
  • Removing the stale "JWT tokens" from backend tech stack is a correct and welcome fix.
  • The pointer format (→ See [Target §Section](path#anchor)) is consistent throughout.
  • Package Structure tagged as Bucket 3 in both root and backend CLAUDE.md is the right call — that content is pre-refactor stale.
## Review: Markus Keller (Senior Architect) **Verdict: Changes requested** ### Bucket classifications Overall the classification is sound. The split between human-relevant conventions (Bucket 1) and LLM-only behavioral instructions (Bucket 2) is applied consistently across all 7 files. Bucket 3 usage is appropriately narrow — only Package Structure gets the TODO tag in both root and backend CLAUDE.md files, which matches the PR description. One classification concern: the `docs/CLAUDE.md` section "How to Use" (check specs/ before implementing, write ADR before coding, follow production-compose for deployment, keep TODOs updated) reads as human-workflow guidance, not LLM instruction. It was fully removed with no pointer — only the ADR sequencing rule survived as an LLM reminder. The "check specs/ before implementing" step has clear human relevance and arguably belongs in `docs/README.md`. Minor — the README does include "Before implementing a feature, check `specs/`" so the substance is preserved. ### Pointer link resolution The PR documents all 7 pointer targets and explains the merge-order dependency on DOC-2, DOC-4, DOC-5, DOC-6. I verified the dependent files do not yet exist on `main`: - `docs/ARCHITECTURE.md` — absent (DOC-2, #441) ✓ dependency documented - `CONTRIBUTING.md` — absent (DOC-4, #442) ✓ dependency documented - `docs/DEPLOYMENT.md` — absent (DOC-5, #443) ✓ dependency documented - `ocr-service/README.md` — absent (DOC-6, #444) ✓ dependency documented All pointer paths use the correct relative path notation (`./docs/ARCHITECTURE.md`, `../CONTRIBUTING.md`, etc.). The `.devcontainer/CLAUDE.md` pointer `→ See [.devcontainer/README.md](./README.md)` correctly resolves to the sibling file. ### Blocker: `docs/README.md` has a duplicate `infrastructure/` entry in the folder tree The folder structure tree in the new `docs/README.md` lists `infrastructure/` **twice**: ``` ├── infrastructure/ # Deployment, CI/CD, and ops guides ← line 11 ... └── infrastructure/ # Production compose, CI config, S3 migration ← line 18 ``` The second entry should not exist. The original `docs/CLAUDE.md` listed `infrastructure/` once in the tree (with description "Deployment, CI/CD, and ops guides"). The second entry appears to be a stray artifact from the migration rewrite. The tree also omits several real directories/files that exist in `docs/`: `audits/`, `presentation/`, `mail.md`, `TODO-backend.md`, `TODO-frontend.md`. The old CLAUDE.md listed the TODO files explicitly; they were dropped without comment. ### What's done well - The dual-audience pattern (canonical in human doc + brief LLM reminder) is applied uniformly. - The merge-order constraint is prominently documented both in the PR description and enforced through the pointer strategy. - Removing the stale "JWT tokens" from backend tech stack is a correct and welcome fix. - The pointer format (`→ See [Target §Section](path#anchor)`) is consistent throughout. - Package Structure tagged as Bucket 3 in both root and backend CLAUDE.md is the right call — that content is pre-refactor stale.
Author
Owner

Review: Felix Brandt (Senior Developer)

Verdict: Approved (with a note)

LLM reminder accuracy

Checked all reminders for accuracy against the actual codebase:

frontend/src/lib/shared/errors.ts — verified to exist at exactly that path. The reminder in both root and backend CLAUDE.md correctly uses frontend/src/lib/shared/errors.ts. This is the fix documented in the PR description (old path was src/lib/errors.ts). ✓

$lib/shared/primitives/BackButton.svelte — verified to exist at /frontend/src/lib/shared/primitives/BackButton.svelte. The reminder is accurate. ✓

$lib/shared/api.server — the import alias resolves to frontend/src/lib/shared/api.server.ts, which exists. ✓

@RequirePermission reminder — the reminder says it is required on every POST, PUT, PATCH, DELETE. The enum check confirmed all 8 values are listed: READ_ALL, WRITE_ALL, ADMIN, ADMIN_USER, ADMIN_TAG, ADMIN_PERMISSION, ANNOTATE_ALL, BLOG_WRITE. Complete and accurate. ✓

API client reminder — "check !result.response.ok (not result.error)" is consistent across root CLAUDE.md and frontend/CLAUDE.md. In frontend/CLAUDE.md the reminder also adds "For multipart/form-data (file uploads), bypass the typed client and use raw fetch" — that extra sentence in frontend/CLAUDE.md but absent from root is intentional asymmetry (root has less frontend detail). Fine.

Date handling reminder — accurately says append T12:00:00 to prevent UTC off-by-one. ✓

OpenAPI generation reminder — "always run npm run generate:api in frontend/" — accurate. ✓

Note: api.server path format in reminder

The frontend/CLAUDE.md reminder says API client is at $lib/shared/api.server. The actual file is api.server.ts. When an LLM generates an import, it would write import { createApiClient } from '$lib/shared/api.server' (without the .ts), which is correct SvelteKit convention. No change needed — just noting it's intentionally extension-free.

Content not migrated / not kept — check

  • Profiles section (dev/prod) was removed from backend/CLAUDE.md without a pointer or reminder. The --spring.profiles.active=dev flag is still mentioned in the "How to Run" → "OpenAPI / TypeScript type generation" sub-section, so the essential usage is preserved. The prod vs dev distinction isn't LLM-relevant for code generation. Acceptable as Bucket 1 migrated to DEPLOYMENT.md (DOC-5).
  • ResponseStatusException usage for simple controller validation — was in the old backend Error Handling section, not in the new reminder. This is a minor loss: an LLM that doesn't know this may use DomainException for parameter validation (which is over-engineered). Low impact — not a blocker.
  • Existing Services table was removed from backend/CLAUDE.md and root CLAUDE.md without replacement. Fine — that's stale content (Bucket 3 material), but it wasn't tagged with a TODO, just silently deleted. Not a blocker since the package structure tree still shows all domains.

Domain README pointers

Both root CLAUDE.md and frontend/CLAUDE.md point to domain READMEs (src/lib/person/README.md etc.) that don't exist yet on main. These will exist after DOC-6 (#444). The merge-order dependency is documented. No issue.

What's done well

  • The path corrections (src/lib/errors.tsfrontend/src/lib/shared/errors.ts, adding ANNOTATE_ALL and BLOG_WRITE to the permission list) are exactly the kind of accuracy improvements this migration should deliver.
  • LLM reminders are kept sharp and action-oriented — no padding, no explanation of why, just what to do.
  • The FormData cast comment // cast needed — FormData returns FormDataEntryValue was correctly preserved in the frontend/CLAUDE.md Form Actions example.
## Review: Felix Brandt (Senior Developer) **Verdict: Approved (with a note)** ### LLM reminder accuracy Checked all reminders for accuracy against the actual codebase: **`frontend/src/lib/shared/errors.ts`** — verified to exist at exactly that path. The reminder in both root and backend CLAUDE.md correctly uses `frontend/src/lib/shared/errors.ts`. This is the fix documented in the PR description (old path was `src/lib/errors.ts`). ✓ **`$lib/shared/primitives/BackButton.svelte`** — verified to exist at `/frontend/src/lib/shared/primitives/BackButton.svelte`. The reminder is accurate. ✓ **`$lib/shared/api.server`** — the import alias resolves to `frontend/src/lib/shared/api.server.ts`, which exists. ✓ **`@RequirePermission` reminder** — the reminder says it is required on every `POST`, `PUT`, `PATCH`, `DELETE`. The enum check confirmed all 8 values are listed: `READ_ALL`, `WRITE_ALL`, `ADMIN`, `ADMIN_USER`, `ADMIN_TAG`, `ADMIN_PERMISSION`, `ANNOTATE_ALL`, `BLOG_WRITE`. Complete and accurate. ✓ **API client reminder** — "check `!result.response.ok` (not `result.error`)" is consistent across root CLAUDE.md and frontend/CLAUDE.md. In frontend/CLAUDE.md the reminder also adds "For multipart/form-data (file uploads), bypass the typed client and use raw `fetch`" — that extra sentence in frontend/CLAUDE.md but absent from root is intentional asymmetry (root has less frontend detail). Fine. **Date handling reminder** — accurately says append `T12:00:00` to prevent UTC off-by-one. ✓ **OpenAPI generation reminder** — "always run `npm run generate:api` in `frontend/`" — accurate. ✓ ### Note: `api.server` path format in reminder The `frontend/CLAUDE.md` reminder says `API client is at $lib/shared/api.server`. The actual file is `api.server.ts`. When an LLM generates an import, it would write `import { createApiClient } from '$lib/shared/api.server'` (without the `.ts`), which is correct SvelteKit convention. No change needed — just noting it's intentionally extension-free. ### Content not migrated / not kept — check - **Profiles section** (dev/prod) was removed from `backend/CLAUDE.md` without a pointer or reminder. The `--spring.profiles.active=dev` flag is still mentioned in the "How to Run" → "OpenAPI / TypeScript type generation" sub-section, so the essential usage is preserved. The prod vs dev distinction isn't LLM-relevant for code generation. Acceptable as Bucket 1 migrated to DEPLOYMENT.md (DOC-5). - **`ResponseStatusException` usage** for simple controller validation — was in the old backend Error Handling section, not in the new reminder. This is a minor loss: an LLM that doesn't know this may use `DomainException` for parameter validation (which is over-engineered). Low impact — not a blocker. - **Existing Services table** was removed from backend/CLAUDE.md and root CLAUDE.md without replacement. Fine — that's stale content (Bucket 3 material), but it wasn't tagged with a TODO, just silently deleted. Not a blocker since the package structure tree still shows all domains. ### Domain README pointers Both root CLAUDE.md and frontend/CLAUDE.md point to domain READMEs (`src/lib/person/README.md` etc.) that don't exist yet on `main`. These will exist after DOC-6 (#444). The merge-order dependency is documented. No issue. ### What's done well - The path corrections (`src/lib/errors.ts` → `frontend/src/lib/shared/errors.ts`, adding `ANNOTATE_ALL` and `BLOG_WRITE` to the permission list) are exactly the kind of accuracy improvements this migration should deliver. - LLM reminders are kept sharp and action-oriented — no padding, no explanation of why, just what to do. - The `FormData` cast comment `// cast needed — FormData returns FormDataEntryValue` was correctly preserved in the frontend/CLAUDE.md Form Actions example.
Author
Owner

Review: Nora Steiner (Security)

Verdict: Approved (with one concern)

Security-relevant sections audit

The PR description explicitly tables the security migrations. Here is my verification of each:

@RequirePermission + Permission enum
Both backend/CLAUDE.md and root CLAUDE.md have the LLM reminder: "@RequirePermission(Permission.WRITE_ALL) is required on every POST, PUT, PATCH, DELETE endpoint — not optional. Do not mix with Spring Security's @PreAuthorize."

The Permission enum in Permission.java has 8 values: READ_ALL, WRITE_ALL, ANNOTATE_ALL, BLOG_WRITE, ADMIN, ADMIN_USER, ADMIN_TAG, ADMIN_PERMISSION. The reminder lists all 8. The old backend/CLAUDE.md was missing ANNOTATE_ALL and BLOG_WRITE — both are now correctly added. ✓

ALLOWED_PDF_HOSTS SSRF warning
ocr-service/CLAUDE.md retains this as an LLM reminder: "ALLOWED_PDF_HOSTS must never be set to * — that opens SSRF." The warning is present and accurate. ✓

TRAINING_TOKEN
The PR description classifies TRAINING_TOKEN as Bucket 1 (migrated to ocr-service/README.md from DOC-6 and docs/DEPLOYMENT.md from DOC-5) with no LLM reminder retained. This is the right call: TRAINING_TOKEN is an operational deployment detail, not a code generation guardrail. An LLM working on the codebase doesn't need to know to set it — that's DevOps. ✓

ErrorCode mirror process
The reminder in both root and backend CLAUDE.md reads: "when adding a new ErrorCode: (1) add to ErrorCode.java, (2) mirror in frontend/src/lib/shared/errors.ts, (3) add i18n keys in messages/{de,en,es}.json." The frontend variant is identical. ✓

vscode user runs as non-root (.devcontainer)
This was in the original .devcontainer/CLAUDE.md as a factual statement under Configuration. It is faithfully carried into .devcontainer/README.md. ✓

Concern: SSRF reminder has no LLM reminder label

The ocr-service/CLAUDE.md has two separate blocks:

**LLM reminder:** the OCR service is a single-node container — training reloads the model ...

`ALLOWED_PDF_HOSTS` must never be set to `*` — that opens SSRF. ...

The second block is a security-critical instruction but does NOT carry the **LLM reminder:** prefix that every other LLM instruction in this PR uses. This is a formatting inconsistency: if a human reads the file and applies the convention that "LLM reminder = machine-readable", the SSRF warning appears ambiguous. Recommend prefixing it:

**LLM reminder:** \ALLOWED_PDF_HOSTS` must never be set to `*` — that opens SSRF.`

Not a blocker for merge since the content is present, but the labeling inconsistency should be fixed.

What's done well

  • Two previously missing permissions (ANNOTATE_ALL, BLOG_WRITE) were caught and added — a genuine security accuracy improvement.
  • The SSRF guard for PDF host allowlisting is preserved prominently in the file most likely to be opened when working on the OCR service.
  • The "Do not mix with Spring Security's @PreAuthorize" warning is retained — that's a real footgun that the reminder correctly calls out.
## Review: Nora Steiner (Security) **Verdict: Approved (with one concern)** ### Security-relevant sections audit The PR description explicitly tables the security migrations. Here is my verification of each: **`@RequirePermission` + Permission enum** Both `backend/CLAUDE.md` and root `CLAUDE.md` have the LLM reminder: "`@RequirePermission(Permission.WRITE_ALL)` is **required** on every `POST`, `PUT`, `PATCH`, `DELETE` endpoint — not optional. Do not mix with Spring Security's `@PreAuthorize`." The Permission enum in `Permission.java` has 8 values: `READ_ALL`, `WRITE_ALL`, `ANNOTATE_ALL`, `BLOG_WRITE`, `ADMIN`, `ADMIN_USER`, `ADMIN_TAG`, `ADMIN_PERMISSION`. The reminder lists all 8. The old backend/CLAUDE.md was missing `ANNOTATE_ALL` and `BLOG_WRITE` — both are now correctly added. ✓ **`ALLOWED_PDF_HOSTS` SSRF warning** `ocr-service/CLAUDE.md` retains this as an LLM reminder: "`ALLOWED_PDF_HOSTS` must never be set to `*` — that opens SSRF." The warning is present and accurate. ✓ **`TRAINING_TOKEN`** The PR description classifies TRAINING_TOKEN as Bucket 1 (migrated to `ocr-service/README.md` from DOC-6 and `docs/DEPLOYMENT.md` from DOC-5) with no LLM reminder retained. This is the right call: TRAINING_TOKEN is an operational deployment detail, not a code generation guardrail. An LLM working on the codebase doesn't need to know to set it — that's DevOps. ✓ **ErrorCode mirror process** The reminder in both root and backend CLAUDE.md reads: "when adding a new `ErrorCode`: (1) add to `ErrorCode.java`, (2) mirror in `frontend/src/lib/shared/errors.ts`, (3) add i18n keys in `messages/{de,en,es}.json`." The frontend variant is identical. ✓ **`vscode` user runs as non-root** (.devcontainer) This was in the original `.devcontainer/CLAUDE.md` as a factual statement under Configuration. It is faithfully carried into `.devcontainer/README.md`. ✓ ### Concern: SSRF reminder has no LLM reminder label The `ocr-service/CLAUDE.md` has two separate blocks: ``` **LLM reminder:** the OCR service is a single-node container — training reloads the model ... `ALLOWED_PDF_HOSTS` must never be set to `*` — that opens SSRF. ... ``` The second block is a security-critical instruction but does NOT carry the `**LLM reminder:**` prefix that every other LLM instruction in this PR uses. This is a formatting inconsistency: if a human reads the file and applies the convention that "LLM reminder = machine-readable", the SSRF warning appears ambiguous. Recommend prefixing it: > `**LLM reminder:** \`ALLOWED_PDF_HOSTS\` must never be set to \`*\` — that opens SSRF.` Not a blocker for merge since the content is present, but the labeling inconsistency should be fixed. ### What's done well - Two previously missing permissions (`ANNOTATE_ALL`, `BLOG_WRITE`) were caught and added — a genuine security accuracy improvement. - The SSRF guard for PDF host allowlisting is preserved prominently in the file most likely to be opened when working on the OCR service. - The "Do not mix with Spring Security's `@PreAuthorize`" warning is retained — that's a real footgun that the reminder correctly calls out.
Author
Owner

Review: Sara Holt (QA)

Verdict: Changes requested

Per-file migration table verification

Checked each row against the actual diff:

File PR claims Actual
scripts/CLAUDE.md All 9 script descriptions migrated to scripts/README.md ✓ 9 scripts present in README.md
.devcontainer/CLAUDE.md Config, usage, limitations migrated to .devcontainer/README.md ✓ all sections present
docs/CLAUDE.md Folder structure, ADR guide, specs migrated to docs/README.md; ADR-before-architecture reminder kept ✓ content confirmed
ocr-service/CLAUDE.md All migrated to ocr-service/README.md (DOC-6); single-node + SSRF reminder kept ✓ reminders present
backend/CLAUDE.md Layering Rules → ARCHITECTURE.md; Error Handling → CONTRIBUTING.md; Security → ARCHITECTURE.md; Key Entities / Entity Code Style / Services / OCR Integration / How to Run / Testing kept
root CLAUDE.md Per PR description ✓ all pointers verified
frontend/CLAUDE.md API Client, Date Handling, Key UI Components migrated; Project Structure, Form Actions, Styling, How to Run, Vite Proxy, i18n kept

Table matches the actual diff. No mismatches.

Destructive-operation warning on reset-db.sh

The warning is present and is actually stronger in the new scripts/README.md than in the original:

Original: > ⚠️ **Destructive operation** — only for development!

New: > ⚠️ **Destructive operation — only for development!** This wipes ALL data. Not reversible without a backup.

The emphasis is retained and the consequence ("Not reversible without a backup") has been added. ✓

Blocker: docs/README.md folder tree is incorrect

The folder tree in docs/README.md contains a duplicate infrastructure/ entry:

docs/
├── adr/
├── architecture/
├── infrastructure/          # Deployment, CI/CD, and ops guides     ← correct
├── specs/
├── ARCHITECTURE.md
├── DEPLOYMENT.md
├── GLOSSARY.md
├── security-guide.md
├── STYLEGUIDE.md
└── infrastructure/          # Production compose, CI config, S3 migration  ← wrong duplicate

The second infrastructure/ at the └── position is incorrect — the tree terminates with a directory that was already listed. The original docs/CLAUDE.md had infrastructure/ listed only once. This appears to be a rewrite artifact where the description "Production compose, CI config, S3 migration" (which belongs to the Infrastructure (infrastructure/) section below) was accidentally promoted into the tree.

Additionally, real files and folders that exist on disk are absent from the tree: TODO-backend.md, TODO-frontend.md, mail.md, audits/, presentation/. The old CLAUDE.md explicitly listed the TODO files. Their omission from the README means a human reading docs/README.md would not know they exist. Minor but worth noting.

Test plan checklist

Going through the PR's own test plan:

  • All 7 CLAUDE.md files processed — confirmed
  • All Bucket-1 content replaced with pointers — confirmed
  • Bucket-2 content preserved — confirmed
  • Bucket-3 sections tagged — confirmed (Package Structure in root + backend)
  • scripts/README.md, .devcontainer/README.md, docs/README.md created — confirmed (10 changed files)
  • Destructive-operation warning preserved — confirmed and strengthened
  • Pointer links reviewed against target headings — cannot fully verify until DOC-2/4/5/6 are merged; the PR documents the expected anchor names
  • PR merged only after DOC-2/4/5/6 — constraint documented in PR body

What's done well

  • The test plan in the PR description is clear and reviewable — each item is specific enough to check.
  • The per-file migration table is accurate (no claims that don't match the diff).
  • The strengthened destructive warning on reset-db.sh goes beyond the original spec — good catch.
## Review: Sara Holt (QA) **Verdict: Changes requested** ### Per-file migration table verification Checked each row against the actual diff: | File | PR claims | Actual | |---|---|---| | `scripts/CLAUDE.md` | All 9 script descriptions migrated to `scripts/README.md` | ✓ 9 scripts present in README.md | | `.devcontainer/CLAUDE.md` | Config, usage, limitations migrated to `.devcontainer/README.md` | ✓ all sections present | | `docs/CLAUDE.md` | Folder structure, ADR guide, specs migrated to `docs/README.md`; ADR-before-architecture reminder kept | ✓ content confirmed | | `ocr-service/CLAUDE.md` | All migrated to `ocr-service/README.md` (DOC-6); single-node + SSRF reminder kept | ✓ reminders present | | `backend/CLAUDE.md` | Layering Rules → ARCHITECTURE.md; Error Handling → CONTRIBUTING.md; Security → ARCHITECTURE.md; Key Entities / Entity Code Style / Services / OCR Integration / How to Run / Testing kept | ✓ | | `root CLAUDE.md` | Per PR description | ✓ all pointers verified | | `frontend/CLAUDE.md` | API Client, Date Handling, Key UI Components migrated; Project Structure, Form Actions, Styling, How to Run, Vite Proxy, i18n kept | ✓ | Table matches the actual diff. No mismatches. ### Destructive-operation warning on `reset-db.sh` The warning is present and is actually **stronger** in the new `scripts/README.md` than in the original: Original: `> ⚠️ **Destructive operation** — only for development!` New: `> ⚠️ **Destructive operation — only for development!** This wipes ALL data. Not reversible without a backup.` The emphasis is retained and the consequence ("Not reversible without a backup") has been added. ✓ ### Blocker: `docs/README.md` folder tree is incorrect The folder tree in `docs/README.md` contains a duplicate `infrastructure/` entry: ``` docs/ ├── adr/ ├── architecture/ ├── infrastructure/ # Deployment, CI/CD, and ops guides ← correct ├── specs/ ├── ARCHITECTURE.md ├── DEPLOYMENT.md ├── GLOSSARY.md ├── security-guide.md ├── STYLEGUIDE.md └── infrastructure/ # Production compose, CI config, S3 migration ← wrong duplicate ``` The second `infrastructure/` at the `└──` position is incorrect — the tree terminates with a directory that was already listed. The original `docs/CLAUDE.md` had `infrastructure/` listed only once. This appears to be a rewrite artifact where the description "Production compose, CI config, S3 migration" (which belongs to the `Infrastructure (infrastructure/)` section below) was accidentally promoted into the tree. Additionally, real files and folders that exist on disk are absent from the tree: `TODO-backend.md`, `TODO-frontend.md`, `mail.md`, `audits/`, `presentation/`. The old CLAUDE.md explicitly listed the TODO files. Their omission from the README means a human reading `docs/README.md` would not know they exist. Minor but worth noting. ### Test plan checklist Going through the PR's own test plan: - [x] All 7 CLAUDE.md files processed — confirmed - [x] All Bucket-1 content replaced with pointers — confirmed - [x] Bucket-2 content preserved — confirmed - [x] Bucket-3 sections tagged — confirmed (Package Structure in root + backend) - [x] `scripts/README.md`, `.devcontainer/README.md`, `docs/README.md` created — confirmed (10 changed files) - [x] Destructive-operation warning preserved — confirmed and strengthened - [ ] Pointer links reviewed against target headings — cannot fully verify until DOC-2/4/5/6 are merged; the PR documents the expected anchor names - [x] PR merged only after DOC-2/4/5/6 — constraint documented in PR body ### What's done well - The test plan in the PR description is clear and reviewable — each item is specific enough to check. - The per-file migration table is accurate (no claims that don't match the diff). - The strengthened destructive warning on `reset-db.sh` goes beyond the original spec — good catch.
Author
Owner

Review: Tobias Wendt (DevOps)

Verdict: Approved

scripts/README.md — completeness and accuracy

Verified against the original scripts/CLAUDE.md:

  • All 9 entries are present: reset-db.sh, rebuild-frontend.sh, download-kraken-models.sh, download-paperless.sh, flatten-paperless.sh, generate_data.py, prepare_historical_dict.py, schema.sql, large-data.sql. ✓
  • The "How to Use" section is preserved: run from repo root, chmod +x reminder, cd scripts && python generate_data.py for the Python script. ✓
  • The "Adding New Scripts" checklist is present and updated to reference README.md instead of CLAUDE.md. ✓
  • The large-data.sql Docker import command (docker exec -i archive-db psql -U archive_user -d family_archive_db < scripts/large-data.sql) is present and correct. ✓
  • The schema.sql "source of truth" caveat (Flyway migrations are canonical, schema.sql is snapshot only) is preserved. ✓

No operational detail was lost.

.devcontainer/README.md — completeness and accuracy

Verified against original .devcontainer/CLAUDE.md:

  • Feature table (Java 21, Maven, Node.js 24) ✓
  • VS Code extensions table (all 4 extensions) ✓
  • Port forwarding note (8080 forwarded, 5173/3000 need manual config) ✓
  • Non-root user note ✓
  • Prerequisites (Dev Containers extension + Docker running) ✓
  • Step-by-step "Open in Dev Container" instructions ✓
  • "Working Inside the Container" bash examples ✓
  • Limitations section (backend service inheritance, OCR side-start, no GPU passthrough) ✓
  • Customization JSON example ✓

Content is 1:1 with the original, reformatted with proper Markdown table alignment.

docs/README.md — completeness and accuracy

Content is substantially correct. The ADR table, ADR format guide, architecture diagram descriptions, infrastructure table, specs section, and style guide link are all present.

One operational issue: the folder tree has a duplicate infrastructure/ entry (last line of the tree). The tree ends with:

└── infrastructure/          # Production compose, CI config, S3 migration

This is wrong — infrastructure/ is already listed at line 11. The tree's last entry should likely be absent (the tree should end at STYLEGUIDE.md). A human following this README to understand the docs/ directory structure will be confused by seeing the same directory listed twice. Fix required before merge.

Also notable: the tree omits TODO-backend.md and TODO-frontend.md which exist on disk and serve as lightweight backlogs. The original CLAUDE.md called these out. If they're intentionally omitted (de-emphasising the TODO files in favour of Gitea issues), that's a valid choice — but it should be deliberate, not accidental.

No operational detail lost in migration

The only content that didn't make it into any human doc is the "Model Downloads" section from ocr-service/CLAUDE.md that calls ./scripts/download-kraken-models.sh. That instruction is now in scripts/README.md under the download-kraken-models.sh entry. ✓

The dev profile behavior (--spring.profiles.active=dev enables OpenAPI) was in the old backend/CLAUDE.md under a "Profiles" sub-section. The new version compresses it into the OpenAPI generation block ("Start backend with --spring.profiles.active=dev"). All essential operational detail is preserved, just more compact.

What's done well

  • scripts/README.md is genuinely better than the original CLAUDE.md: cleaner heading hierarchy, proper spacing between sections, and the destructive warning is stronger.
  • .devcontainer/README.md is a faithful and well-formatted copy — zero information loss.
  • The CLAUDE.mdREADME.md pattern means these files are now discoverable by any developer opening the directory in a file browser or on Gitea, not just by Claude.
## Review: Tobias Wendt (DevOps) **Verdict: Approved** ### `scripts/README.md` — completeness and accuracy Verified against the original `scripts/CLAUDE.md`: - All 9 entries are present: `reset-db.sh`, `rebuild-frontend.sh`, `download-kraken-models.sh`, `download-paperless.sh`, `flatten-paperless.sh`, `generate_data.py`, `prepare_historical_dict.py`, `schema.sql`, `large-data.sql`. ✓ - The "How to Use" section is preserved: run from repo root, `chmod +x` reminder, `cd scripts && python generate_data.py` for the Python script. ✓ - The "Adding New Scripts" checklist is present and updated to reference `README.md` instead of `CLAUDE.md`. ✓ - The `large-data.sql` Docker import command (`docker exec -i archive-db psql -U archive_user -d family_archive_db < scripts/large-data.sql`) is present and correct. ✓ - The `schema.sql` "source of truth" caveat (Flyway migrations are canonical, schema.sql is snapshot only) is preserved. ✓ No operational detail was lost. ### `.devcontainer/README.md` — completeness and accuracy Verified against original `.devcontainer/CLAUDE.md`: - Feature table (Java 21, Maven, Node.js 24) ✓ - VS Code extensions table (all 4 extensions) ✓ - Port forwarding note (8080 forwarded, 5173/3000 need manual config) ✓ - Non-root user note ✓ - Prerequisites (Dev Containers extension + Docker running) ✓ - Step-by-step "Open in Dev Container" instructions ✓ - "Working Inside the Container" bash examples ✓ - Limitations section (backend service inheritance, OCR side-start, no GPU passthrough) ✓ - Customization JSON example ✓ Content is 1:1 with the original, reformatted with proper Markdown table alignment. ### `docs/README.md` — completeness and accuracy Content is substantially correct. The ADR table, ADR format guide, architecture diagram descriptions, infrastructure table, specs section, and style guide link are all present. One operational issue: the folder tree has a duplicate `infrastructure/` entry (last line of the tree). The tree ends with: ``` └── infrastructure/ # Production compose, CI config, S3 migration ``` This is wrong — `infrastructure/` is already listed at line 11. The tree's last entry should likely be absent (the tree should end at `STYLEGUIDE.md`). A human following this README to understand the `docs/` directory structure will be confused by seeing the same directory listed twice. Fix required before merge. Also notable: the tree omits `TODO-backend.md` and `TODO-frontend.md` which exist on disk and serve as lightweight backlogs. The original CLAUDE.md called these out. If they're intentionally omitted (de-emphasising the TODO files in favour of Gitea issues), that's a valid choice — but it should be deliberate, not accidental. ### No operational detail lost in migration The only content that didn't make it into any human doc is the "Model Downloads" section from `ocr-service/CLAUDE.md` that calls `./scripts/download-kraken-models.sh`. That instruction is now in `scripts/README.md` under the `download-kraken-models.sh` entry. ✓ The dev profile behavior (`--spring.profiles.active=dev` enables OpenAPI) was in the old `backend/CLAUDE.md` under a "Profiles" sub-section. The new version compresses it into the OpenAPI generation block ("Start backend with `--spring.profiles.active=dev`"). All essential operational detail is preserved, just more compact. ### What's done well - `scripts/README.md` is genuinely better than the original CLAUDE.md: cleaner heading hierarchy, proper spacing between sections, and the destructive warning is stronger. - `.devcontainer/README.md` is a faithful and well-formatted copy — zero information loss. - The `CLAUDE.md` → `README.md` pattern means these files are now discoverable by any developer opening the directory in a file browser or on Gitea, not just by Claude.
marcel added 1 commit 2026-05-05 23:42:48 +02:00
docs(legibility): fix three review blockers in DOC-7
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 3m29s
CI / OCR Service Tests (pull_request) Successful in 29s
CI / Backend Unit Tests (pull_request) Failing after 3m14s
CI / Unit & Component Tests (push) Failing after 3m24s
CI / OCR Service Tests (push) Successful in 29s
CI / Backend Unit Tests (push) Failing after 3m16s
e6854e0ebd
- docs/README.md: remove duplicate infrastructure/ entry at end of folder tree
- ocr-service/CLAUDE.md: add **LLM reminder:** prefix to ALLOWED_PDF_HOSTS
  SSRF warning (consistent with all other machine-readable instructions)
- backend/CLAUDE.md: restore ResponseStatusException note for simple controller
  validation — avoids LLMs reaching for DomainException for trivial checks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Author
Owner

Blocker fixes (commit e6854e0e)

Fix File Issue
Remove duplicate infrastructure/ line at end of folder tree docs/README.md Stray artifact — infrastructure/ appeared twice in the tree
Add **LLM reminder:** prefix to ALLOWED_PDF_HOSTS warning ocr-service/CLAUDE.md Inconsistent labeling vs all other machine-readable instructions
Restore ResponseStatusException note for simple controller validation backend/CLAUDE.md Was silently dropped; avoids LLMs over-engineering to DomainException
## Blocker fixes (commit `e6854e0e`) | Fix | File | Issue | |---|---|---| | Remove duplicate `infrastructure/` line at end of folder tree | `docs/README.md` | Stray artifact — `infrastructure/` appeared twice in the tree | | Add `**LLM reminder:**` prefix to `ALLOWED_PDF_HOSTS` warning | `ocr-service/CLAUDE.md` | Inconsistent labeling vs all other machine-readable instructions | | Restore `ResponseStatusException` note for simple controller validation | `backend/CLAUDE.md` | Was silently dropped; avoids LLMs over-engineering to `DomainException` |
Author
Owner

👨‍💻 Felix Brandt — Senior Fullstack Developer

Verdict: Approved

This PR is purely a documentation migration — no production code is touched. My review focuses on whether the LLM-facing instructions in the CLAUDE.md files are correct, precise, and won't cause me to generate bad code.

What I checked

  1. LLM reminders for correctness — do the kept instructions match what the codebase actually requires?
  2. Pointer links — do they point to sections that will actually exist when this merges after its dependencies?
  3. Code examples in README files — are they accurate?

Findings

backend/CLAUDE.md — Error handling note (restored fix confirmed)

The restored ResponseStatusException note reads:

For simple controller validation (not domain logic), ResponseStatusException is acceptable: throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "…").

This is correctly scoped. The caveat "not domain logic" is the critical distinction. Good.

backend/CLAUDE.md — Permission list is now complete
ANNOTATE_ALL and BLOG_WRITE are present. Previously missing — confirmed fixed.

frontend/CLAUDE.md — API client reminder is accurate

check !result.response.ok (not result.error)

Correct and consistent with CONTRIBUTING.md target. The added note about multipart/form-data bypassing the typed client is a useful addition that wasn't in the root CLAUDE.md version.

scripts/README.md — destructive warning preserved
The reset-db.sh section has:

⚠️ Destructive operation — only for development! This wipes ALL data. Not reversible without a backup.

Consistent with Tobias's feedback requirement.

Minor observation (not a blocker):

docs/README.md lists STYLEGUIDE.md in the folder structure but does not list CONTRIBUTING.md. Since CONTRIBUTING.md lives at repo root (not in docs/), this is architecturally correct. No action needed.

frontend/CLAUDE.md — Route structure mentions briefwechsel/ not conversations/
This is actually more accurate than the root CLAUDE.md (which still says conversations/). The frontend file correctly reflects the actual route. The root CLAUDE.md Route Structure section is tagged as <!-- TODO: rewrite post-REFACTOR-1 --> which is the right call.

Verdict

All LLM-facing reminders are accurate, the code style instructions are consistent, and the pointer links point to the correct targets (dependent on DOC-2/4/5/6 merging first as documented). The merge order constraint in the PR description is the critical operational note here — this PR must not merge out of order.

No blockers. The migration is executed cleanly.

## 👨‍💻 Felix Brandt — Senior Fullstack Developer **Verdict: ✅ Approved** This PR is purely a documentation migration — no production code is touched. My review focuses on whether the LLM-facing instructions in the CLAUDE.md files are correct, precise, and won't cause me to generate bad code. ### What I checked 1. **LLM reminders for correctness** — do the kept instructions match what the codebase actually requires? 2. **Pointer links** — do they point to sections that will actually exist when this merges after its dependencies? 3. **Code examples in README files** — are they accurate? ### Findings **`backend/CLAUDE.md` — Error handling note (restored fix confirmed)** The restored `ResponseStatusException` note reads: > For simple controller validation (not domain logic), `ResponseStatusException` is acceptable: `throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "…")`. This is correctly scoped. The caveat "not domain logic" is the critical distinction. Good. **`backend/CLAUDE.md` — Permission list is now complete** `ANNOTATE_ALL` and `BLOG_WRITE` are present. Previously missing — confirmed fixed. **`frontend/CLAUDE.md` — API client reminder is accurate** > check `!result.response.ok` (not `result.error`) Correct and consistent with `CONTRIBUTING.md` target. The added note about multipart/form-data bypassing the typed client is a useful addition that wasn't in the root CLAUDE.md version. **`scripts/README.md` — destructive warning preserved** The `reset-db.sh` section has: > ⚠️ **Destructive operation — only for development!** This wipes ALL data. Not reversible without a backup. Consistent with Tobias's feedback requirement. **Minor observation (not a blocker):** `docs/README.md` lists `STYLEGUIDE.md` in the folder structure but does not list `CONTRIBUTING.md`. Since `CONTRIBUTING.md` lives at repo root (not in `docs/`), this is architecturally correct. No action needed. **`frontend/CLAUDE.md` — Route structure mentions `briefwechsel/` not `conversations/`** This is actually more accurate than the root CLAUDE.md (which still says `conversations/`). The frontend file correctly reflects the actual route. The root CLAUDE.md Route Structure section is tagged as `<!-- TODO: rewrite post-REFACTOR-1 -->` which is the right call. ### Verdict All LLM-facing reminders are accurate, the code style instructions are consistent, and the pointer links point to the correct targets (dependent on DOC-2/4/5/6 merging first as documented). The merge order constraint in the PR description is the critical operational note here — this PR must not merge out of order. No blockers. The migration is executed cleanly.
Author
Owner

🏛️ Markus Keller — Senior Application Architect

Verdict: Approved

A documentation-only PR. My concern is: does the new structure accurately reflect module ownership, does the pointer system hold up architecturally, and are the TODO tags on stale content appropriately scoped?

Layering rules — correctly preserved as LLM reminders

Both root CLAUDE.md and backend/CLAUDE.md keep the layering LLM reminder:

controllers never call repositories directly; services never reach into another domain's repository — always call the other domain's service instead.

This is exactly right to keep as an LLM reminder (Bucket-2). It's the most common cross-domain boundary violation I see in generated code. Pointer to docs/ARCHITECTURE.md §Layering rule is correct.

Package Structure tagged as TODO — good call

The package structure in both root and backend CLAUDE.md is tagged <!-- TODO: rewrite post-REFACTOR-1 — see Epic 4 -->. This is the right decision: the structure is likely to change during Epic 4, and keeping it in CLAUDE.md while it drifts would cause more harm than good. The TODO tag communicates intent without deleting potentially-still-useful context.

docs/README.md — structure is accurate

The folder structure in docs/README.md correctly lists adr/, architecture/, infrastructure/, specs/ sub-folders plus the key documents. The ADR guide correctly states "Do not reuse numbers" and references the sequential naming convention.

One observation: docs/README.md references docs/STYLEGUIDE.md and docs/GLOSSARY.md (DOC-3). The DOC-3 dependency isn't called out in the PR's merge order constraint (only DOC-2/4/5/6 are listed). If GLOSSARY.md doesn't exist on main at merge time, the link will be a dead link. This is a minor concern since it's in the human-readable docs/README.md, not in LLM-facing instructions, and is self-correcting once DOC-3 merges.

Suggestion (not a blocker): Add DOC-3 (#443 or whichever is the GLOSSARY PR) to the merge order constraint in the PR description for completeness.

OCR service — single-node constraint preserved correctly

ocr-service/CLAUDE.md keeps:

the OCR service is a single-node container — training reloads the model in-process, so multiple replicas cause model-state divergence (see ADR-001). All job tracking and business logic stay in Spring Boot; the Python service is stateless OCR only.

This architectural constraint is precisely the kind of thing that gets lost when someone "helpfully" removes CLAUDE.md content. Keeping it as an LLM reminder is the right call.

No blockers. Approved.

## 🏛️ Markus Keller — Senior Application Architect **Verdict: ✅ Approved** A documentation-only PR. My concern is: does the new structure accurately reflect module ownership, does the pointer system hold up architecturally, and are the TODO tags on stale content appropriately scoped? ### Layering rules — correctly preserved as LLM reminders Both root `CLAUDE.md` and `backend/CLAUDE.md` keep the layering LLM reminder: > controllers never call repositories directly; services never reach into another domain's repository — always call the other domain's service instead. This is exactly right to keep as an LLM reminder (Bucket-2). It's the most common cross-domain boundary violation I see in generated code. Pointer to `docs/ARCHITECTURE.md §Layering rule` is correct. ### Package Structure tagged as TODO — good call The package structure in both root and backend CLAUDE.md is tagged `<!-- TODO: rewrite post-REFACTOR-1 — see Epic 4 -->`. This is the right decision: the structure is likely to change during Epic 4, and keeping it in CLAUDE.md while it drifts would cause more harm than good. The TODO tag communicates intent without deleting potentially-still-useful context. ### docs/README.md — structure is accurate The folder structure in `docs/README.md` correctly lists `adr/`, `architecture/`, `infrastructure/`, `specs/` sub-folders plus the key documents. The ADR guide correctly states "Do not reuse numbers" and references the sequential naming convention. **One observation:** `docs/README.md` references `docs/STYLEGUIDE.md` and `docs/GLOSSARY.md (DOC-3)`. The DOC-3 dependency isn't called out in the PR's merge order constraint (only DOC-2/4/5/6 are listed). If `GLOSSARY.md` doesn't exist on `main` at merge time, the link will be a dead link. This is a minor concern since it's in the human-readable `docs/README.md`, not in LLM-facing instructions, and is self-correcting once DOC-3 merges. **Suggestion (not a blocker):** Add DOC-3 (#443 or whichever is the GLOSSARY PR) to the merge order constraint in the PR description for completeness. ### OCR service — single-node constraint preserved correctly `ocr-service/CLAUDE.md` keeps: > the OCR service is a **single-node container** — training reloads the model in-process, so multiple replicas cause model-state divergence (see ADR-001). All job tracking and business logic stay in Spring Boot; the Python service is stateless OCR only. This architectural constraint is precisely the kind of thing that gets lost when someone "helpfully" removes CLAUDE.md content. Keeping it as an LLM reminder is the right call. ### No blockers. Approved.
Author
Owner

🔒 Nora "NullX" Steiner — Application Security Engineer

Verdict: Approved

This is a documentation migration, not a code change. My review focuses on whether security-critical LLM instructions were correctly classified (Bucket-1 vs Bucket-2) and whether the SSRF/permission reminders are present, accurate, and prominently placed.

Security-critical content audit

1. SSRF protection — ocr-service/CLAUDE.md

**LLM reminder:** `ALLOWED_PDF_HOSTS` must never be set to `*` — that opens SSRF. The default (`minio,localhost,127.0.0.1`) is correct for dev.

This is correctly preserved as a Bucket-2 LLM reminder. The * wildcard risk is exactly the kind of thing that gets silently introduced when an LLM "simplifies" environment configuration. The reminder is present, accurate, and has the LLM reminder: prefix — confirmed fixed from the previous blocker.

2. @RequirePermission — both CLAUDE.md files

Root CLAUDE.md and backend/CLAUDE.md both retain:

@RequirePermission(Permission.WRITE_ALL) is required on every POST, PUT, PATCH, DELETE endpoint — not optional. Do not mix with Spring Security's @PreAuthorize.

This is the most security-relevant LLM instruction in the codebase. Correctly classified as Bucket-2. Presence in both the root and backend CLAUDE.md is appropriate — redundancy here is a feature, not a smell.

3. Permission enum completeness

ANNOTATE_ALL and BLOG_WRITE are now present in both CLAUDE.md permission lists. This was flagged as a previous blocker and is confirmed fixed. An LLM generating a new endpoint for blog/annotation features will now know to use the correct permission constant.

4. ResponseStatusException carve-out

backend/CLAUDE.md correctly notes:

For simple controller validation (not domain logic), ResponseStatusException is acceptable.

This is appropriately scoped. The security risk of using ResponseStatusException for auth/domain errors (losing structured error codes that the frontend maps to i18n) is mitigated by the explicit "(not domain logic)" qualifier.

5. ErrorCode mirror process — both CLAUDE.md files

Root and backend CLAUDE.md keep the full ErrorCode addition workflow including the correct path frontend/src/lib/shared/errors.ts. The stale path fix (src/lib/errors.tsfrontend/src/lib/shared/errors.ts) is confirmed applied.

One observation (not a blocker)

backend/CLAUDE.md points to docs/ARCHITECTURE.md §Permission system for the full security documentation. This file is being created in DOC-2 (PR #441). Until that PR merges, the link is dead. This is correctly called out in the merge order constraint and is acceptable.

No security regressions. Approved.

## 🔒 Nora "NullX" Steiner — Application Security Engineer **Verdict: ✅ Approved** This is a documentation migration, not a code change. My review focuses on whether security-critical LLM instructions were correctly classified (Bucket-1 vs Bucket-2) and whether the SSRF/permission reminders are present, accurate, and prominently placed. ### Security-critical content audit **1. SSRF protection — `ocr-service/CLAUDE.md`** ``` **LLM reminder:** `ALLOWED_PDF_HOSTS` must never be set to `*` — that opens SSRF. The default (`minio,localhost,127.0.0.1`) is correct for dev. ``` This is correctly preserved as a Bucket-2 LLM reminder. The `*` wildcard risk is exactly the kind of thing that gets silently introduced when an LLM "simplifies" environment configuration. The reminder is present, accurate, and has the `LLM reminder:` prefix — confirmed fixed from the previous blocker. **2. `@RequirePermission` — both CLAUDE.md files** Root `CLAUDE.md` and `backend/CLAUDE.md` both retain: > `@RequirePermission(Permission.WRITE_ALL)` is **required** on every `POST`, `PUT`, `PATCH`, `DELETE` endpoint — not optional. Do not mix with Spring Security's `@PreAuthorize`. This is the most security-relevant LLM instruction in the codebase. Correctly classified as Bucket-2. Presence in both the root and backend CLAUDE.md is appropriate — redundancy here is a feature, not a smell. **3. Permission enum completeness** `ANNOTATE_ALL` and `BLOG_WRITE` are now present in both CLAUDE.md permission lists. This was flagged as a previous blocker and is confirmed fixed. An LLM generating a new endpoint for blog/annotation features will now know to use the correct permission constant. **4. `ResponseStatusException` carve-out** `backend/CLAUDE.md` correctly notes: > For simple controller validation (not domain logic), `ResponseStatusException` is acceptable. This is appropriately scoped. The security risk of using `ResponseStatusException` for auth/domain errors (losing structured error codes that the frontend maps to i18n) is mitigated by the explicit "(not domain logic)" qualifier. **5. ErrorCode mirror process — both CLAUDE.md files** Root and backend CLAUDE.md keep the full ErrorCode addition workflow including the correct path `frontend/src/lib/shared/errors.ts`. The stale path fix (`src/lib/errors.ts` → `frontend/src/lib/shared/errors.ts`) is confirmed applied. ### One observation (not a blocker) `backend/CLAUDE.md` points to `docs/ARCHITECTURE.md §Permission system` for the full security documentation. This file is being created in DOC-2 (PR #441). Until that PR merges, the link is dead. This is correctly called out in the merge order constraint and is acceptable. ### No security regressions. Approved.
Author
Owner

🧪 Sara Holt — Senior QA Engineer

Verdict: Approved

Documentation-only PR. My review covers: does the migration preserve testability-related LLM instructions, are the test-relevant sections correctly classified, and does the PR description give enough information to verify the migration is complete?

Test plan in the PR description

The test plan is a manual checklist:

  • All 7 CLAUDE.md files processed
  • All Bucket-1 content replaced with Markdown-linked pointers
  • Bucket-2 content preserved
  • Bucket-3 sections tagged TODO, not deleted
  • New README files created
  • Destructive-operation warning preserved
  • Pointer links reviewed
  • PR merged only after dependencies

This is fit for purpose for a documentation PR. There's no automated test coverage for CLAUDE.md content (by nature), and a manual checklist is the appropriate verification method here.

backend/CLAUDE.md — Testing section preserved (Bucket-2)

The testing section in backend/CLAUDE.md is kept:

  • Unit tests: Mockito + JUnit, pure in-memory
  • Slice tests: @WebMvcTest, @DataJpaTest with Testcontainers PostgreSQL
  • Integration tests: Full Spring context with Testcontainers
  • Coverage gate: 88% branch coverage (JaCoCo)

This is correctly Bucket-2 (LLM code generation reference). The Testcontainers PostgreSQL requirement and the coverage gate threshold are the kind of facts an LLM needs when generating a new test class.

frontend/CLAUDE.md — Testing section preserved (Bucket-2)

The frontend CLAUDE.md retains the testing stack (Vitest, browser mode, Playwright e2e) and the npm run test:e2e commands. Correct.

One observation (not a blocker)

The scripts/README.md documents generate_data.py as generating "fake documents, persons, and tags suitable for load testing or UI development." This is useful for QA purposes — I'd eventually want to see this script integrated into a test fixture workflow. But that's a future issue, not a concern for this PR.

The migration is verifiable and complete from a QA perspective. Approved.

## 🧪 Sara Holt — Senior QA Engineer **Verdict: ✅ Approved** Documentation-only PR. My review covers: does the migration preserve testability-related LLM instructions, are the test-relevant sections correctly classified, and does the PR description give enough information to verify the migration is complete? ### Test plan in the PR description The test plan is a manual checklist: - [ ] All 7 CLAUDE.md files processed - [ ] All Bucket-1 content replaced with Markdown-linked pointers - [ ] Bucket-2 content preserved - [ ] Bucket-3 sections tagged TODO, not deleted - [ ] New README files created - [ ] Destructive-operation warning preserved - [ ] Pointer links reviewed - [ ] PR merged only after dependencies This is fit for purpose for a documentation PR. There's no automated test coverage for CLAUDE.md content (by nature), and a manual checklist is the appropriate verification method here. ### Testing-related content — correctly classified **`backend/CLAUDE.md` — Testing section preserved (Bucket-2)** The testing section in `backend/CLAUDE.md` is kept: - Unit tests: Mockito + JUnit, pure in-memory - Slice tests: `@WebMvcTest`, `@DataJpaTest` with Testcontainers PostgreSQL - Integration tests: Full Spring context with Testcontainers - Coverage gate: 88% branch coverage (JaCoCo) This is correctly Bucket-2 (LLM code generation reference). The Testcontainers PostgreSQL requirement and the coverage gate threshold are the kind of facts an LLM needs when generating a new test class. **`frontend/CLAUDE.md` — Testing section preserved (Bucket-2)** The frontend CLAUDE.md retains the testing stack (Vitest, browser mode, Playwright e2e) and the `npm run test:e2e` commands. Correct. ### One observation (not a blocker) The `scripts/README.md` documents `generate_data.py` as generating "fake documents, persons, and tags suitable for load testing or UI development." This is useful for QA purposes — I'd eventually want to see this script integrated into a test fixture workflow. But that's a future issue, not a concern for this PR. ### The migration is verifiable and complete from a QA perspective. Approved.
Author
Owner

🚀 Tobias Wendt — DevOps & Platform Engineer

Verdict: Approved

Documentation-only change. I'm checking: are the infrastructure-relevant LLM instructions preserved, is the devcontainer README accurate, and does the scripts README correctly document the operational scripts?

.devcontainer/README.md — accurate and complete

The devcontainer README is a clean migration of the original content. Key details confirmed correct:

  • Java 21, Maven (bundled), Node.js 24
  • Port 8080 forwarded by default
  • Frontend port (5173 or 3000) requires manual addition to forwardPorts — correctly documented
  • Runs as vscode user (not root) — security note preserved
  • GPU passthrough for OCR training is not configured — limitation correctly noted
  • OCR service must be started separately — operational constraint documented

The Customization section showing how to add Python 3.11 feature is a useful practical addition that wasn't in the original CLAUDE.md.

scripts/README.md — operationally complete

All 9 scripts documented with purpose, usage, and notes:

  • reset-db.sh — destructive warning with proper visual emphasis (⚠️ blockquote)
  • download-kraken-models.sh — model size noted (~100–500 MB each)
  • large-data.sql — correct docker exec import command documented

One detail I appreciate: the schema.sql entry correctly notes "Flyway migrations in backend/src/main/resources/db/migration/ are the source of truth for schema evolution. schema.sql is a snapshot for quick reference only." This prevents the common mistake of editing schema.sql instead of creating a Flyway migration.

Infrastructure pointer in root CLAUDE.md

Root CLAUDE.md now reads:

→ See docs/DEPLOYMENT.md

The DEPLOYMENT.md file is created in DOC-5 (PR #443). The merge order constraint handles this. Once all dependencies merge, this pointer will resolve correctly.

OCR single-node constraint — infrastructure perspective

The ocr-service/CLAUDE.md reminder about single-node deployment matches the production Compose configuration. Good. An LLM that reads this will not suggest adding replicas or configuring horizontal scaling for the OCR service.

No DevOps concerns. Approved.

## 🚀 Tobias Wendt — DevOps & Platform Engineer **Verdict: ✅ Approved** Documentation-only change. I'm checking: are the infrastructure-relevant LLM instructions preserved, is the devcontainer README accurate, and does the scripts README correctly document the operational scripts? ### `.devcontainer/README.md` — accurate and complete The devcontainer README is a clean migration of the original content. Key details confirmed correct: - Java 21, Maven (bundled), Node.js 24 - Port 8080 forwarded by default - Frontend port (5173 or 3000) requires manual addition to `forwardPorts` — correctly documented - Runs as `vscode` user (not root) — security note preserved - GPU passthrough for OCR training is not configured — limitation correctly noted - OCR service must be started separately — operational constraint documented The `Customization` section showing how to add Python 3.11 feature is a useful practical addition that wasn't in the original CLAUDE.md. ### `scripts/README.md` — operationally complete All 9 scripts documented with purpose, usage, and notes: - `reset-db.sh` — destructive warning with proper visual emphasis (`⚠️` blockquote) - `download-kraken-models.sh` — model size noted (~100–500 MB each) - `large-data.sql` — correct docker exec import command documented **One detail I appreciate:** the `schema.sql` entry correctly notes "Flyway migrations in `backend/src/main/resources/db/migration/` are the source of truth for schema evolution. `schema.sql` is a snapshot for quick reference only." This prevents the common mistake of editing `schema.sql` instead of creating a Flyway migration. ### Infrastructure pointer in root `CLAUDE.md` Root CLAUDE.md now reads: > → See [docs/DEPLOYMENT.md](./docs/DEPLOYMENT.md) The DEPLOYMENT.md file is created in DOC-5 (PR #443). The merge order constraint handles this. Once all dependencies merge, this pointer will resolve correctly. ### OCR single-node constraint — infrastructure perspective The `ocr-service/CLAUDE.md` reminder about single-node deployment matches the production Compose configuration. Good. An LLM that reads this will not suggest adding replicas or configuring horizontal scaling for the OCR service. ### No DevOps concerns. Approved.
Author
Owner

🎨 Leonie Voss — Senior UX Designer & Accessibility Strategist

Verdict: Approved

This PR touches documentation only. I'm checking whether the UI/UX and brand conventions in CLAUDE.md files were migrated correctly and whether the LLM reminders for styling are accurate and sufficiently specific.

Styling conventions — correctly preserved in both root and frontend CLAUDE.md

Both CLAUDE.md (root) and frontend/CLAUDE.md retain the brand color table and typography conventions:

Class Value Usage
brand-navy #002850 Primary text, buttons, headers
brand-mint #A6DAD8 Accents, hover underlines, icons
brand-sand #E4E2D7 Page background, card borders

Typography: font-serif (Merriweather) for body/titles, font-sans (Montserrat) for UI chrome.

The card pattern and Back Button pattern are correctly preserved in root CLAUDE.md. These are Bucket-2 — the right call. An LLM generating a new page without these reminders would create cards that don't match the established visual language.

frontend/CLAUDE.md — Styling section retained

The frontend CLAUDE.md keeps:

  • Brand color table
  • Typography reference
  • Card pattern (full Svelte markup example)

Good. The card pattern markup example is especially important — without it, LLMs tend to invent their own padding/shadow combinations that break visual consistency.

docs/README.md mentions STYLEGUIDE.md

The docs/README.md references docs/STYLEGUIDE.md covering "Color palette and typography" and "Accessibility standards (WCAG 2.1 AA)". This is a human-readable doc reference, not an LLM reminder. It's appropriate to reference it here. I'd expect the actual content to be comprehensive when that file is written.

One forward-looking note (suggestion, not a blocker)

The root CLAUDE.md Route Structure is tagged <!-- TODO: rewrite post-REFACTOR-1 -->. The current structure already has some inaccuracies (conversations/ vs the actual briefwechsel/ route in the frontend). The frontend/CLAUDE.md correctly uses briefwechsel/. This divergence is acceptable given the TODO tag, but whoever addresses REFACTOR-1 should use frontend/CLAUDE.md's structure as the source of truth for the actual routes.

Brand and UX instructions correctly migrated. Approved.

## 🎨 Leonie Voss — Senior UX Designer & Accessibility Strategist **Verdict: ✅ Approved** This PR touches documentation only. I'm checking whether the UI/UX and brand conventions in CLAUDE.md files were migrated correctly and whether the LLM reminders for styling are accurate and sufficiently specific. ### Styling conventions — correctly preserved in both root and frontend CLAUDE.md Both `CLAUDE.md` (root) and `frontend/CLAUDE.md` retain the brand color table and typography conventions: | Class | Value | Usage | |---|---|---| | `brand-navy` | `#002850` | Primary text, buttons, headers | | `brand-mint` | `#A6DAD8` | Accents, hover underlines, icons | | `brand-sand` | `#E4E2D7` | Page background, card borders | Typography: `font-serif` (Merriweather) for body/titles, `font-sans` (Montserrat) for UI chrome. The card pattern and Back Button pattern are correctly preserved in root `CLAUDE.md`. These are Bucket-2 — the right call. An LLM generating a new page without these reminders would create cards that don't match the established visual language. ### frontend/CLAUDE.md — Styling section retained The frontend CLAUDE.md keeps: - Brand color table - Typography reference - Card pattern (full Svelte markup example) Good. The card pattern markup example is especially important — without it, LLMs tend to invent their own padding/shadow combinations that break visual consistency. ### docs/README.md mentions `STYLEGUIDE.md` The `docs/README.md` references `docs/STYLEGUIDE.md` covering "Color palette and typography" and "Accessibility standards (WCAG 2.1 AA)". This is a human-readable doc reference, not an LLM reminder. It's appropriate to reference it here. I'd expect the actual content to be comprehensive when that file is written. ### One forward-looking note (suggestion, not a blocker) The root `CLAUDE.md` Route Structure is tagged `<!-- TODO: rewrite post-REFACTOR-1 -->`. The current structure already has some inaccuracies (`conversations/` vs the actual `briefwechsel/` route in the frontend). The `frontend/CLAUDE.md` correctly uses `briefwechsel/`. This divergence is acceptable given the TODO tag, but whoever addresses REFACTOR-1 should use `frontend/CLAUDE.md`'s structure as the source of truth for the actual routes. ### Brand and UX instructions correctly migrated. Approved.
Author
Owner

📋 Elicit — Requirements Engineer

Verdict: Approved

I'm reviewing this from a requirements and traceability perspective: does the migration preserve the information needed to generate correct code, are the TODO-tagged sections clearly scoped, and does the pointer system create the right expectation for how documentation should be maintained going forward?

Scope of issue #401 — migration is complete

The PR description maps each of the 7 CLAUDE.md files to their migration outcome with a clear table. Cross-referencing against the current file state:

  • scripts/CLAUDE.md → pointer-only + reminder ✓
  • .devcontainer/CLAUDE.md → pointer-only ✓
  • docs/CLAUDE.md → pointer + ADR reminder ✓
  • ocr-service/CLAUDE.md → pointer + 2 reminders ✓
  • backend/CLAUDE.md → mixed (substantial Bucket-2 content retained) ✓
  • Root CLAUDE.md → mixed (substantial Bucket-2 content retained) ✓
  • frontend/CLAUDE.md → mixed (substantial Bucket-2 content retained) ✓

Scope is fully delivered.

TODO tags — acceptably scoped

The <!-- TODO: rewrite post-REFACTOR-1 — see Epic 4 --> tags on Package Structure sections are clear:

  • The tagged sections are not deleted (per decision queue option A — correct)
  • The tags reference a specific epic (Epic 4) giving traceability to the work item
  • The content behind the TODO is still useful during the interim

One gap: the TODO doesn't reference a specific Gitea issue number. "Epic 4" is human-readable but not machine-traceable. If someone later searches for issues linked to these TODOs, they won't find them. Suggestion (not a blocker): add see #<issue_number> alongside "Epic 4" in the TODO tags when that epic issue exists.

Pointer standardization — consistent

The pointer format → See [Target §Section](path#anchor) is used consistently across all files. This is good for maintainability — when a target section is renamed, the broken link is immediately visible.

Dual-audience split is well-executed

The PR correctly identifies which content serves LLMs (kept as reminder) vs humans (moved to human docs with pointer). The classification table in the PR description is the clearest requirements artifact in this PR — it makes the decision rationale explicit and verifiable.

Merge order constraint — well-documented

The constraint "this PR must merge AFTER DOC-2 (#441), DOC-4 (#442), DOC-5 (#443), DOC-6 (#444)" is clearly stated. This is the only procedural risk in the PR, and it's well-documented.

Suggestion (not a blocker): Consider whether DOC-3 (GLOSSARY) also needs to be in the merge order constraint, as docs/README.md references GLOSSARY.md.

Requirements fully met. Approved.

## 📋 Elicit — Requirements Engineer **Verdict: ✅ Approved** I'm reviewing this from a requirements and traceability perspective: does the migration preserve the information needed to generate correct code, are the TODO-tagged sections clearly scoped, and does the pointer system create the right expectation for how documentation should be maintained going forward? ### Scope of issue #401 — migration is complete The PR description maps each of the 7 CLAUDE.md files to their migration outcome with a clear table. Cross-referencing against the current file state: - `scripts/CLAUDE.md` → pointer-only + reminder ✓ - `.devcontainer/CLAUDE.md` → pointer-only ✓ - `docs/CLAUDE.md` → pointer + ADR reminder ✓ - `ocr-service/CLAUDE.md` → pointer + 2 reminders ✓ - `backend/CLAUDE.md` → mixed (substantial Bucket-2 content retained) ✓ - Root `CLAUDE.md` → mixed (substantial Bucket-2 content retained) ✓ - `frontend/CLAUDE.md` → mixed (substantial Bucket-2 content retained) ✓ Scope is fully delivered. ### TODO tags — acceptably scoped The `<!-- TODO: rewrite post-REFACTOR-1 — see Epic 4 -->` tags on Package Structure sections are clear: - The tagged sections are not deleted (per decision queue option A — correct) - The tags reference a specific epic (Epic 4) giving traceability to the work item - The content behind the TODO is still useful during the interim **One gap:** the TODO doesn't reference a specific Gitea issue number. "Epic 4" is human-readable but not machine-traceable. If someone later searches for issues linked to these TODOs, they won't find them. **Suggestion (not a blocker):** add `see #<issue_number>` alongside "Epic 4" in the TODO tags when that epic issue exists. ### Pointer standardization — consistent The pointer format `→ See [Target §Section](path#anchor)` is used consistently across all files. This is good for maintainability — when a target section is renamed, the broken link is immediately visible. ### Dual-audience split is well-executed The PR correctly identifies which content serves LLMs (kept as reminder) vs humans (moved to human docs with pointer). The classification table in the PR description is the clearest requirements artifact in this PR — it makes the decision rationale explicit and verifiable. ### Merge order constraint — well-documented The constraint "this PR must merge AFTER DOC-2 (#441), DOC-4 (#442), DOC-5 (#443), DOC-6 (#444)" is clearly stated. This is the only procedural risk in the PR, and it's well-documented. **Suggestion (not a blocker):** Consider whether DOC-3 (GLOSSARY) also needs to be in the merge order constraint, as `docs/README.md` references `GLOSSARY.md`. ### Requirements fully met. Approved.
marcel merged commit 50b18f0849 into main 2026-05-06 07:41:05 +02:00
marcel deleted branch feat/issue-401-claude-migration 2026-05-06 07:41:08 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#445