251 verified pairs, reconstructed from the backup branches: every pair had to match on both tree hash and commit message before being accepted, and all 251 did. This keeps older references resolvable without editing what was written at the time. Rewriting historical issue comments would remove the record of what someone actually wrote, and a lookup table costs nothing by comparison.
234 lines
12 KiB
Markdown
234 lines
12 KiB
Markdown
# 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.*
|