# CLAUDE.md — übergreifende Arbeitskonventionen (kanonisch) Diese Datei gilt für **jede Claude-/Agenten-Session in allen Projekten** der Gruppe (axion1337.chat-Stack, ThreadNet-Repos, CFGMON/threadnet-operating, Homelab). Projekt-Repos haben eigene CLAUDE.mds für ihre Spezifika (z. B. die ESS-/Flux-Details in „ThreadNet Server Suite" = `axion1337.chat-gitops`) — bei Widerspruch gilt für Arbeitsweise und Prozess **diese** Datei. > **Für Sessions ohne Lab-Zugang** (CFGMON, MATRIX, …): dieses Repo ist als > Push-Mirror unter `https://rohana.axion1337.de/sorb/management` von überall > **lesbar** — dort diese Datei und die ADRs nachschlagen. Nur pushen ist tabu. > > 📋 **Kopierbare Kurzfassungen zum Voranstellen:** > [verfahren/textbloecke.md](verfahren/textbloecke.md) — Session-Start, Host-Session, > Deploy-Übergabe, Abschluss, Entscheidungsvorlage. Diese Datei hier bleibt die > Quelle; die Bausteine verweisen nur darauf. ## Projektrealitäten (Stand 2026-08-01) **Das Lab ist die Quelle der Wahrheit** ([ADR-0002](decisions/0002-issues-und-management-ins-lab.md)): - Kanonische Repos liegen auf `git.lab/axion1337.chat/*` (nur im Lab/VPN auflösbar). Gitea/rohana wird per **Push-Mirror** beliefert und bleibt Flux-Source, Container-/npm-Registry und Release-Download ([ADR-0001](decisions/0001-gitlab-kanonisch-push-mirror.md)). - **Warum überhaupt zwei Orte — und warum das kein Altbestand ist:** Auf git.lab liegen die *Baupläne*, auf Gitea eine Kopie, die der Cluster **ohne verfügbares Lab** erreicht. Der Hetzner-Cluster muss sich bauen und neu ausrollen lassen, wenn das Homelab aus ist, im Umbau steckt oder niemand zu Hause ist — er darf deshalb nicht von einem Host abhängen, der nur im Lab antwortet. ⚠️ **Die Flux-Quelle nicht „geradeziehen"** auf git.lab: Das sähe aufgeräumter aus und würde die Verfügbarkeit der Produktion an das Lab koppeln — genau das, was die Trennung verhindert. - **Nie direkt zu Gitea pushen** (gespiegelte Repos) — der Mirror überschreibt per Force. - **Gespiegelt wird nur die Gruppe `axion1337.chat`** (die fünf Produkt-Repos und `management`). Die Gruppe **`homelab`** (`docs`, `wiki`, `wiki-bookstack`) hat bewusst **keine Mirrors**: Sie beschreibt und konfiguriert ausschließlich Lab-Infrastruktur, und seit dem Site-to-Site-VPN ([ADR-0004](decisions/0004-site-to-site-vpn-hetzner-lab.md)) erreichen auch Host-Sessions git.lab direkt — Tunnel einschalten genügt. Betriebslehren, die von außen lesbar sein müssen, gehören deshalb in die **AARs** unter `verfahren/aar/` (dieses Repo ist gespiegelt), nicht nur in die READMEs der Lab-Repos. - Landet doch ein Commit auf Gitea (z. B. aus einer Host-Session ohne Lab-Route): **Kanonisierungs-Verfahren** in [verfahren/deploy-uebergabe.md](verfahren/deploy-uebergabe.md) — `.patch` von Gitea ziehen, `git am` (erhält Autorschaft), Push über git.lab. - **Issues leben auf git.lab.** Die alten Gitea-Issues sind geschlossen und verweisen dorthin. ⚠️ gitops-Nummern haben sich beim Umzug verschoben (Gitea zählte PRs mit; z. B. Gitea#48 → GitLab#46) — alte „gitops#N"-Verweise meinen die Gitea-Nummer; verbindlich ist der Migrations-Fußtext im Issue. - **Ausnahme** (bewusst entschieden, nur noch eine): der TURN-Rotations-CronJob schreibt weiter nach Gitea, weil er im Cluster läuft und git.lab nicht erreicht. **Die Rotation nicht von Hand nachziehen und den PR nie auf Gitea mergen** — das erledigt seit 2026-08-02 der geplante CI-Job `canonize_rotation` im gitops-Repo täglich von git.lab aus. Scheitert er, bleibt die Pipeline rot; diese rote Pipeline **ist** der Alarm, einen zusätzlichen Termin gibt es bewusst nicht. - **Dokumentation** ([ADR-0006](decisions/0006-wikis-konsolidieren-docusaurus.md)): Das gitops-Wiki liegt seit 2026-08-02 auf git.lab (*Wiki*-Reiter im Projekt); ⚠️ der `wiki`-**Branch** im gitops-Repo ist ein überholter Mai-Abzug von `docs/` und nicht die gepflegte Fassung. Alle Quellen zusammen erscheinen unter **axionwiki.lab** ([`homelab/wiki`](https://git.lab/homelab/wiki), Docusaurus) — Inhalte werden beim Bau geholt, **Änderungen gehören ins Quell-Repo**. ## Arbeitsframework ([ADR-0005](decisions/0005-pm-framework-kanban.md)) Kanban-Rückgrat mit leichten Scrum-Elementen: - **Alles Offene ist ein Issue** — host-/infra-Scope hier im management-Projekt (`host:`-Labels, alte IDs wie `CFGMON-01` bleiben im Titel), Projekt-Scope im jeweiligen Projekt. Kein neues Backlog-Markdown anlegen; `hosts/`/`shared/` sind nur Bestand + Historie. - **Status über Labels**, genau eins pro Issue: `status:next` (die einzige Zusage), `status:doing` (**WIP-Limit 2** — auch sessionübergreifend zu verteidigen), `status:wartet` (nur mit benanntem Grund). Ohne Label = Backlog. - **ADR-Pflicht** ([decisions/](decisions/)) bei Architektur-/Prozess- entscheidungen und **jeder dauerhaften Ausnahme von einer Regel**. Eine Ausnahme nur zu dokumentieren statt sie als Entscheidung vorzulegen, ist ein Fehler. - **Deploy-Übergaben** („einer baut, ein anderer rollt aus") laufen über das Issue-Template und die Pflichtfelder in [verfahren/deploy-uebergabe.md](verfahren/deploy-uebergabe.md) — das ist unsere Definition of Done für Deployments. Nach Deploys mit Übergabe und nach Incidents: **AAR** ([verfahren/aar/](verfahren/aar/), Vorlage liegt daneben). - Prioritäten über `priority:*`; Zeitkritisches bekommt ein **Datum** im Issue, nicht „bald". - **Der Titel trägt keine Priorität.** Präfixe wie `[HIGH]`/`[MEDIUM]`/`[LOW]` gehören nicht in den Titel — die Priorität steht im Label, und zwar nur dort. Alte Kennungen wie `CFGMON-01` bleiben, die benennen den Gegenstand, nicht die Dringlichkeit. ⚠️ Der Grund ist keine Ästhetik: Aus der Gitea-Migration trugen 34 Issues ein Präfix, davon **zwei mit einer anderen Aussage als ihr Label** — wer nach Titel sortierte, bekam ein anderes Bild als wer nach Label sortierte. Zwei Wahrheiten über dieselbe Sache sind schlimmer als eine unvollständige. Bereinigt 2026-08-06. - **Jedes Issue gehört zu genau einem Meilenstein** (Gruppen-Milestones M1–M4, siehe [roadmap.md](roadmap.md)). Label und Meilenstein beantworten verschiedene Fragen: `priority:*` sagt **wie dringend**, der Meilenstein sagt **worauf es einzahlt**. Ein Issue ohne Meilenstein taucht in keiner Roadmap-Ansicht auf und ist damit praktisch unsichtbar — es existiert nur noch für den, der es angelegt hat. M1–M4 haben **bewusst kein Enddatum**: Sie bündeln, sie simulieren keinen Termindruck. Termindruck steht als Datum am einzelnen Issue. ## Secrets & Credentials - **Token-/Secret-Werte niemals anzeigen, loggen oder in Dateien echoen** — anzeigen = Exposure = Rotation. Echte Credentials tippt/legt sorb selbst an; Sessions referenzieren sie nur über Dateipfade (z. B. `~/.config/gitlab-lab/token`) oder maskierte CI-Variablen. - Nicht-geheime Konfiguration wird direkt geschrieben und committet — die Trennung ist „Credential vs. Config", nicht „alles über den Menschen". ## Commit-Konventionen (seit 2026-08-07) Gilt für **alle** Repos der Gruppe `axion1337.chat` und die ThreadNet-Dienste. - **Nachrichten auf Englisch**, Conventional-Commit-Stil: `feat:`, `fix:`, `docs:`, `chore:`, `ci:`, `refactor:`. Der Betreff sagt *was*, der Rumpf *warum*. - **Zeitstempel anonymisieren.** Autor- **und** Committer-Datum werden auf **12:00:00 UTC des laufenden Tages** gesetzt, damit sich aus der Historie keine persönlichen Arbeitszeiten ablesen lassen: ```bash export GIT_AUTHOR_DATE="$(date -u +%Y-%m-%d)T12:00:00Z" \ GIT_COMMITTER_DATE="$(date -u +%Y-%m-%d)T12:00:00Z" git commit -m "…" ``` ⚠️ **Beide Variablen setzen.** Nur `GIT_AUTHOR_DATE` zu setzen bringt nichts — `git log` zeigt zwar das Autordatum, das Committer-Datum bleibt aber im Objekt und ist über `git log --format=%cd` und in jeder Weboberfläche sichtbar. 📎 Die Umstellung der Alt-Historie am 2026-08-07 hat 251 Commits neue SHAs gegeben. Ältere Verweise bleiben über [`shared/commit-zuordnung-2026-08-07.md`](shared/commit-zuordnung-2026-08-07.md) auflösbar — **statt** geschriebene Issue-Kommentare nachträglich zu ändern. Wer eine SHA nicht findet, hat einen Commit von vor der Grenze vor sich; der gilt unverändert. ⚠️ **Das schützt nur die Git-Historie.** Push-Zeiten, Issue- und Kommentar-Zeitstempel, Pipeline-Läufe und Paket-Veröffentlichungen tragen weiterhin die echte Uhrzeit und liegen im selben GitLab bzw. auf dem öffentlichen Gitea-Spiegel. Wer daraus wirklich keine Muster ableitbar haben will, muss dort ansetzen — die Commit-Datumsregel allein reicht dafür nicht. ## Redlichkeit & gelebte Lehren - **Aussagen mit Quelle:** Verifiziert (Messung/Konsole) klar von Vermutung trennen; nicht selbst Geprüftes als solches kennzeichnen. Korrelation ≠ Kausalität — ein plausibler Verdacht ist kein Befund. - **Config-Dateien textuell/chirurgisch editieren, nie re-dumpen** (YAML/JSON neu serialisieren hat zweimal real Schaden angerichtet). Compose-/YAML- Änderungen vor dem Push validieren (`docker compose config`, YAML-Parse). - Fehlschläge und übersprungene Schritte werden benannt, nicht geglättet; „fertig" heißt verifiziert. --- name: karpathy-guidelines description: Behavioral guidelines to reduce common LLM coding mistakes. Use when writing, reviewing, or refactoring code to avoid overcomplication, make surgical changes, surface assumptions, and define verifiable success criteria. license: MIT --- # Karpathy Guidelines Behavioral guidelines to reduce common LLM coding mistakes, derived from [Andrej Karpathy's observations](https://x.com/karpathy/status/2015883857489522876) on LLM coding pitfalls. **Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment. ## 1. Think Before Coding **Don't assume. Don't hide confusion. Surface tradeoffs.** Before implementing: - State your assumptions explicitly. If uncertain, ask. - If multiple interpretations exist, present them - don't pick silently. - If a simpler approach exists, say so. Push back when warranted. - If something is unclear, stop. Name what's confusing. Ask. ## 2. Simplicity First **Minimum code that solves the problem. Nothing speculative.** - No features beyond what was asked. - No abstractions for single-use code. - No "flexibility" or "configurability" that wasn't requested. - No error handling for impossible scenarios. - If you write 200 lines and it could be 50, rewrite it. Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify. ## 3. Surgical Changes **Touch only what you must. Clean up only your own mess.** When editing existing code: - Don't "improve" adjacent code, comments, or formatting. - Don't refactor things that aren't broken. - Match existing style, even if you'd do it differently. - If you notice unrelated dead code, mention it - don't delete it. When your changes create orphans: - Remove imports/variables/functions that YOUR changes made unused. - Don't remove pre-existing dead code unless asked. The test: Every changed line should trace directly to the user's request. ## 4. Goal-Driven Execution **Define success criteria. Loop until verified.** Transform tasks into verifiable goals: - "Add validation" → "Write tests for invalid inputs, then make them pass" - "Fix the bug" → "Write a test that reproduces it, then make it pass" - "Refactor X" → "Ensure tests pass before and after" For multi-step tasks, state a brief plan: ``` 1. [Step] → verify: [check] 2. [Step] → verify: [check] 3. [Step] → verify: [check] ``` Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification. --- *Der Karpathy-Block oben ist wortgleich aus der gitops-CLAUDE.md übernommen und darf nicht bearbeitet werden (stehende Regel von sorb). Änderungen an dieser Datei insgesamt: nur mit sorb abgestimmt — sie ist die gemeinsame Arbeitsgrundlage aller Sessions.*