From 604fb7fc2c162b57dfc1f6d2e97b8230dbbc95b9 Mon Sep 17 00:00:00 2001 From: Ulas Date: Thu, 2 Apr 2026 14:29:17 +0200 Subject: [PATCH] docs: add CLAUDE.md audit and optimized proposal Audit identifies redundancies with CONTRIBUTING.md, missing paths (utils/ux.js, locales/, offline.html), incorrect info (node:20 vs 22, non-existent public/assets/), and informational sections that don't steer behavior. Proposed version reduces to 82 lines with clear hard constraints block and reference document table. Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md.proposed | 82 +++++++++++++++++++++++++++ docs/claude-md-audit.md | 120 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 CLAUDE.md.proposed create mode 100644 docs/claude-md-audit.md diff --git a/CLAUDE.md.proposed b/CLAUDE.md.proposed new file mode 100644 index 0000000..1be5c22 --- /dev/null +++ b/CLAUDE.md.proposed @@ -0,0 +1,82 @@ +# Oikos — Claude Code Guide + +Self-hosted family planner PWA. Node.js/Express, Vanilla JS (ES modules, no build step), SQLite/SQLCipher, Docker. + +## Quick Reference + +```bash +npm start # Production server (PORT from .env, default 3000) +npm run dev # Development with --watch +npm test # All test suites (requires Node ≥22) +docker compose up -d # Production deployment +``` + +## Hard Constraints + +These are non-negotiable. Every violation is a bug. + +- **No frameworks, no build tools.** Never add frontend frameworks (React, Vue, Svelte), bundlers (Webpack, Vite), transpilers (TypeScript, Babel), or CSS libraries (Tailwind, Bootstrap). This is a permanent architectural decision. +- **No external frontend dependencies.** The only exception is Lucide Icons (`public/lucide.min.js`, self-hosted). No CDN links at runtime. +- **ES modules everywhere.** `import`/`export` in all JS files. Never `require()`. +- **No `eval()`, no `innerHTML` with user data.** Use `textContent` or DOM API. +- **All UI text via i18n.** Call `t('key')` for every user-facing string. Never hardcode text in components. German (`de`) is the reference locale. +- **Migrations are append-only.** Add new entries to the `migrations` array in `server/db.js`. Never modify or reorder existing entries. +- **No unhandled promise rejections.** Every route handler wrapped in `try/catch`. +- **Design tokens from CSS only.** Never hardcode colors, radii, shadows, or font sizes — use variables from `public/styles/tokens.css`. + +## Project Structure + +``` +server/ + index.js # Express entry, middleware, static serving + db.js # SQLite connection + migrations (append-only array) + auth.js # Session auth + user management routes + middleware/ # csrf.js, validate.js + routes/ # One file per module (tasks, shopping, meals, calendar, notes, contacts, budget, dashboard, weather) + services/ # google-calendar.js, apple-calendar.js, recurrence.js +public/ + index.html # SPA shell (single entry point) + router.js # History API router (no library) + api.js # Fetch wrapper (auth, CSRF, error handling) + i18n.js # i18n system — t(), formatDate(), formatTime(), SUPPORTED_LOCALES + locales/ # de.json (reference), en.json + utils/ux.js # Shared UI utilities (used by most pages) + styles/ # tokens.css (design tokens), reset.css, layout.css, [module].css + components/ # Web Components: modal.js, oikos-install-prompt.js, oikos-locale-picker.js + pages/ # Page modules — each exports render() (dashboard, tasks, shopping, meals, calendar, notes, contacts, budget, settings, login) + offline.html # Offline fallback (served by service worker) + sw.js, sw-register.js, manifest.json +test-[module].js # Test files (project root, one per module) +``` + +**Pages are ES modules** that export a `render()` function. No side effects on import. Web Components use the `oikos-` prefix, one component per file. + +## Conventions + +- Semicolons: yes +- Header comment in every file: purpose, module, dependencies +- API responses: `{ data: ... }` on success, `{ error: string, code: number }` on failure +- DB schema: every table has `id INTEGER PRIMARY KEY`, `created_at TEXT`, `updated_at TEXT` +- Dates/times: use `formatDate()`/`formatTime()` from `i18n.js` — never manual formatting +- Tests: Node.js built-in test runner with `--experimental-sqlite`. Add new tests as `test-[module].js` in root + add `test:[module]` script to `package.json` +- Commits: [Conventional Commits](https://www.conventionalcommits.org/) — see `CONTRIBUTING.md` for format +- Changelog: update `CHANGELOG.md` `[Unreleased]` for every user-facing change. Keep a Changelog categories. English, imperative, user-oriented. + +## Reference Documents + +| What | Where | When to consult | +|------|-------|-----------------| +| Data model, UI specs, design system | `docs/SPEC.md` | Before modifying any module | +| Design tokens (colors, spacing, radii) | `public/styles/tokens.css` | When styling anything | +| Contribution workflow, code conventions | `CONTRIBUTING.md` | For detailed style rules and PR process | +| DB schema (source of truth) | `server/db.js` | Before any DB change | +| i18n keys | `public/locales/de.json` | When adding/changing UI text | +| Available locale functions | `public/i18n.js` | When formatting dates, times, or translating | + +## Request Flow + +Client → Express static (`public/`) or `/api/v1/*` → auth middleware (session check) → route handler → better-sqlite3 (sync) → JSON response. + +## Current State + +All core modules are implemented and stable: Dashboard, Tasks, Shopping, Meals, Calendar, Notes, Contacts, Budget, Settings, Login. PWA shell (service worker, manifest, icons) is in place. Security hardening (CSRF, rate limiting, CSP, input validation) is active. diff --git a/docs/claude-md-audit.md b/docs/claude-md-audit.md new file mode 100644 index 0000000..fbe087f --- /dev/null +++ b/docs/claude-md-audit.md @@ -0,0 +1,120 @@ +# CLAUDE.md Audit — Oikos + +**Datum:** 2026-04-02 +**Aktuelle Länge:** 109 Zeilen (exkl. Leerzeilen) +**Zielbudget:** 80–150 Zeilen + +--- + +## Phase 1: Ist-Analyse + +### 1.1 Zweckerfüllung + +**Teilweise erfüllt.** Die CLAUDE.md enthält eine Mischung aus verhaltenssteuernd und rein informativ: + +- **Verhaltenssteuernd (gut):** Code Conventions, Migration-Append-Only-Regel, Changelog-Anweisung, i18n-Konvention, SPEC.md-Verweis +- **Rein informativ (kein Verhaltenseffekt):** Security Model (liest sich wie Doku, nicht wie Anweisung), Backend-Dependency-Liste (steht in package.json), Deployment-Section (Ops-Doku), Implementation Status (Zustandsbeschreibung) + +**Fehlend:** +- Kein expliziter Hard-Constraints-Block. "No SPA framework" ist in einen Fließtext-Absatz eingebettet statt als nicht-verhandelbare Regel markiert. +- `public/utils/ux.js` wird von 7 Seiten importiert — kein Wort davon. +- `public/i18n.js` wird als System erwähnt, aber nicht als kanonische Datei referenziert. +- `offline.html` fehlt im Architecture-Tree. + +### 1.2 Informationsarchitektur + +**Keine klare Hierarchie.** Harte Constraints (kein Framework, kein innerHTML, Migration append-only) stehen verstreut in verschiedenen Sections auf gleicher Ebene wie weiche Konventionen (Semicolons: yes). + +**Redundanzen mit CONTRIBUTING.md:** +- Project Structure: fast identischer Tree in beiden Dateien +- Code Conventions: ES modules, Semicolons, Header comments, try/catch — alles doppelt +- Testing: identische Beschreibung in beiden +- Changelog: gleiche Anweisung in beiden +- Migration append-only: in beiden Dateien + +**Keine Widersprüche gefunden**, aber die Duplikation ist erheblich (~40% der CLAUDE.md-Inhalte finden sich auch in CONTRIBUTING.md). + +### 1.3 Signalqualität + +**Probleme:** +- "No SPA framework" ist deskriptiv formuliert statt imperativ — ein LLM könnte es als Kontextinfo statt als harte Regel lesen. +- Security Model ist eine Faktenbeschreibung. Kein Satz sagt "tu X" oder "tu niemals Y". +- Backend-Dependency-Liste ist reines Inventar — Claude kann `package.json` lesen. +- Deployment-Dockerfile-Snippet: rein informativ, kein Handlungsbezug. +- `node:20-slim` im CLAUDE.md-Deployment-Block, aber Dockerfile verwendet tatsächlich `node:22-slim` → **falsche Information**. + +### 1.4 Vollständigkeit vs. Projektrealität + +| Erwähnt in CLAUDE.md | Tatsächlicher Zustand | Problem | +|---|---|---| +| `public/assets/` (apple-touch-icon, favicons) | Verzeichnis existiert nicht — Icons in `public/icons/` | **Falscher Pfad** | +| `scripts/generate-icons.js` | Existiert ✅, aber `scripts/seed-demo.js` fehlt im Tree | Unvollständig | +| Dockerfile `node:20-slim` | Dockerfile nutzt `node:22-slim` | **Falsche Version** | +| Components: `modal.js`, `oikos-install-prompt.js` | Auch `oikos-locale-picker.js` existiert | Unvollständig | +| Keine Erwähnung von `public/utils/` | `public/utils/ux.js` wird von 7 Pages importiert | **Fehlt** | +| Keine Erwähnung von `public/offline.html` | Existiert, vom Service Worker referenziert | Fehlt im Tree | +| Keine Erwähnung von `public/locales/` | `de.json`, `en.json` existieren | Fehlt im Tree | +| Keine Erwähnung von `server/db-schema-test.js` | Existiert | Fehlt | + +--- + +## Phase 2: Bewertung + +| Kriterium | Status | Begründung | +|-----------|--------|------------| +| Nur verhaltenssteuernd, keine Spec-Duplikation | ⚠️ | Security Model, Deployment, Dependency-Liste sind rein informativ | +| Harte Constraints klar abgegrenzt | ❌ | Kein separater Block; "no framework" in Fließtext versteckt | +| Referenztabelle vollständig & aktuell | ❌ | Keine Referenztabelle vorhanden — nur ein Einzeiler zu SPEC.md | +| Pfade/Module korrekt | ❌ | `public/assets/` existiert nicht, Dockerfile-Version falsch | +| Keine Redundanz mit CONTRIBUTING.md | ❌ | ~40% Überlappung (Structure, Conventions, Testing, Changelog) | +| Keine Redundanz mit docs/ | ✅ | SPEC.md wird referenziert, nicht dupliziert | +| Keine vagen Formulierungen | ⚠️ | Deskriptive statt imperative Formulierungen bei Constraints | +| Signal-Rausch-Verhältnis | ⚠️ | ~30% der Zeilen sind informativ ohne Handlungsrelevanz | +| Fehlende verhaltensrelevante Info | ⚠️ | utils/ux.js, i18n.js als kanonische Dateien, offline.html | + +--- + +## Phase 3: Optimierungsvorschlag + +Siehe `CLAUDE.md.proposed` im Repo-Root. + +--- + +## Phase 4: Diff & Begründung + +### Entfernt + +| Was | Warum | +|-----|-------| +| Security Model (vollständiger Abschnitt) | Reine Dokumentation. Kein Satz steuert Verhalten. Steht implizit im Code (helmet, bcrypt, CSRF-Middleware). | +| Backend/Optional/Dev Dependencies Liste | Claude kann `package.json` lesen. Inventarlisten steuern kein Verhalten. | +| Deployment Section (Dockerfile-Snippet, env vars, Nginx-Verweis) | Ops-Dokumentation, kein Entwicklungsverhalten. Gehört in README oder docs/. | +| Implementation Status | Reine Zustandsbeschreibung ohne Handlungsanweisung. | +| Architecture Tree (erschöpfende Version) | 25-Zeilen-Tree dupliziert CONTRIBUTING.md. Ersetzt durch kompakten 10-Zeilen-Überblick der nur verhaltensrelevante Orte zeigt. | + +### Hinzugefügt + +| Was | Warum verhaltensrelevant | +|-----|--------------------------| +| Expliziter Hard Constraints Block | Claude muss sofort wissen, was nicht verhandelbar ist — nicht erst aus Fließtext erschließen. | +| `public/utils/ux.js` als kanonische Utility | Wird von 7 Pages importiert. Ohne dieses Wissen würde Claude Utility-Funktionen duplizieren. | +| `public/i18n.js` + `public/locales/` in Structure | Kanonische Orte für i18n — Claude muss wissen, wo Locale-Keys definiert werden. | +| `offline.html` im Tree | Existiert, wird vom Service Worker referenziert, fehlte komplett. | +| Reference Documents Tabelle | Claude muss wissen, wo welche kanonische Wahrheit liegt, statt zu raten. | +| `oikos-locale-picker.js` in Components | Existierende Komponente fehlte — Claude könnte sie unwissentlich neu bauen. | + +### Umformuliert + +| Alt | Neu | Grund | +|-----|-----|-------| +| "No SPA framework. Client-side routing via History API." (deskriptiv) | "Never add frontend frameworks, bundlers, transpilers, or CSS libraries." (imperativ) | Deskriptive Aussage könnte als Kontextinfo statt als Constraint gelesen werden. | +| "Web Component prefix: `oikos-` (not `fb-`)" | "Web Component prefix: always `oikos-`." | `(not fb-)` ist historischer Kontext ohne Verhaltensrelevanz. | +| "ES modules everywhere" (Konvention unter vielen) | In Hard Constraints verschoben | Ist nicht verhandelbar, stand aber auf gleicher Ebene wie "Semicolons: yes". | + +### Verschoben + +| Was | Von | Nach | Grund | +|-----|-----|------|-------| +| Security Model Details | CLAUDE.md | Bereits in Code (middleware, auth.js) | Kein eigenes Dokument nötig — Code ist die Wahrheit | +| Deployment env vars, Dockerfile | CLAUDE.md | README.md (bereits dort vorhanden) | Ops-Information, nicht Entwicklungsverhalten | +| Detaillierter Project Structure Tree | CLAUDE.md | CONTRIBUTING.md (bereits dort vorhanden) | Duplikation eliminieren — CONTRIBUTING.md hat den vollständigen Tree |