diff --git "a/.claude/commands/aufr\303\244umen.md" "b/.claude/commands/aufr\303\244umen.md" index fd2bb4f..8180233 100644 --- "a/.claude/commands/aufr\303\244umen.md" +++ "b/.claude/commands/aufr\303\244umen.md" @@ -4,6 +4,13 @@ Führe den täglichen Cleanup-Workflow durch: ## 0. Branch-Übersicht: testing vs. main (alle Repos) +**Nur lokal anwendbar** — der Pfad `/Users/svenstrohkark/...` existiert nur auf +diesem Mac. In Remote-Execution-Sessions trifft `[ -d "$dir/.git" ]` nie zu, die +Schleife läuft ohne Ausgabe und ohne Fehler durch. Läuft die Session nicht lokal +auf diesem Rechner: Abschnitt überspringen und dem Nutzer explizit sagen, dass +diese Prüfung hier nicht durchgeführt werden konnte — nicht stillschweigend +weiterlaufen. + Erstelle zu Beginn eine Tabelle aller Repositories mit dem Stand von `testing` gegenüber `main`: ```bash @@ -40,9 +47,47 @@ Zeige das Ergebnis als Markdown-Tabelle: ## 2. Branches aufräumen -- Liste alle merged Feature Branches (lokal und remote) -- Frage ob diese gelöscht werden sollen -- Lösche approved Branches +**Wichtig:** `git branch --merged` und `git merge-base --is-ancestor` sind bei +Squash-Merge-Policy unbrauchbar — sie melden gemergte Branches als „nicht gemergt". +Maßgeblich ist die PR-Historie, und dort das Feld `merged_at` (nicht `merged`; +letzteres ist über MCP-GitHub-Tools unzuverlässig und liefert teils `false` +auch bei nachweislich gemergten PRs). + +```bash +git fetch --all --prune -q +for b in $(git branch -r --format='%(refname:short)' \ + | grep -vE 'origin/(HEAD|main|testing|staging|gh-pages)$'); do + br=${b#origin/} + pr=$(gh pr list --head "$br" --state merged --json number,mergedAt --limit 1) + if [ "$(echo "$pr" | jq 'length')" -gt 0 ]; then + echo "✅ $br → PR #$(echo "$pr" | jq -r '.[0].number') gemergt" + else + echo "⚠️ $br → kein gemergter PR — Inhalt prüfen" + fi +done +``` + +Bei `⚠️` zweite Stufe, bevor gelöscht wird — prüft, ob der Branch-Inhalt +inhaltlich schon im Ziel liegt (z.B. bei umbenanntem Squash-Commit): + +```bash +mb=$(git merge-base origin/testing origin/$br) +files=$(git diff --name-only $mb origin/$br) +[ -n "$files" ] && git diff --name-only origin/testing origin/$br -- $files +# leere Ausgabe = Inhalt vollständig in testing → löschbar +``` + +- **Vor dem Löschen fragen**, nur bestätigte Branches löschen +- `main`, `testing`, `staging`, `gh-pages` **nie** löschen — auch nicht beim Bulk-Delete +- Schlägt `git push --delete` mit HTTP 403 fehl (Remote-Execution-Umgebungen): + Exit-Code ist trotzdem 0 und die letzte Zeile lautet „Everything up-to-date". + Nicht als Erfolg werten — stattdessen den fertigen Löschbefehl für die lokale + Ausführung ausgeben. +- Feature-Branches nach Merge löschen: `gh pr merge --delete-branch` explizit + verwenden. `scripts/apply-rulesets.sh` setzt `delete_branch_on_merge=false` + zentral (seit Issue #122 Korrektur 4, siehe `dev-standards/global-policy.md`, + „Merge-Methode zentral erzwingen") — GitHubs Auto-Delete löscht sonst auch + den Head-Branch von Release-PRs (`testing → main`), also `testing` selbst ## 3. GitHub Actions Status @@ -62,6 +107,38 @@ Zeige das Ergebnis als Markdown-Tabelle: - Zeige kürzlich geschlossene Issues (heute) - Weise auf Issues ohne Label hin +### 5a. Erledigte Issues aufspüren (Issue #111) + +`Closes #X` schließt ein Issue nur beim Merge in den **Default-Branch** (`main`). +Da alle PRs nach `testing` gehen, greift das Keyword faktisch nie — Issues bleiben +offen, obwohl der Code längst gemergt ist. + +Gemergte `testing`-PRs gegen die offenen Issues abgleichen: + +```bash +SLUG=$(git remote get-url origin | sed -E 's#.*github.com[:/]##; s#\.git$##') +OPEN=$(gh issue list -R "$SLUG" --state open --limit 100 --json number -q '.[].number' | tr '\n' ' ') +gh pr list -R "$SLUG" --state merged --base testing --limit 60 --json number,body \ + --jq '.[] | (.body // "") as $b + | ($b|[scan("(?i)(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\\s+#(\\d+)")]|flatten|unique) as $r + | select($r|length>0) | "\(.number) \($r|join(" "))"' | +while read -r pr refs; do + for i in $refs; do + case " $OPEN " in *" $i "*) echo "Issue #$i erledigt durch PR #$pr";; esac + done +done +``` + +**Nur vorschlagen, nicht automatisch schließen.** Sammel-/Meta-Issues ("Backlog", +"Maßnahmenkatalog", "Tracking") werden von Teil-PRs oft fälschlich mit `Closes` +referenziert, sind aber nicht erledigt. Vor dem Schließen den Issue-Titel lesen. + +Beim Schließen den Grund vermerken, damit die Historie nachvollziehbar bleibt: + +```bash +gh issue close -R "$SLUG" -c "Umgesetzt in #, gemergt nach \`testing\`." +``` + ## 6. Dependencies & Security - Prüfe ob `package.json` Updates braucht (via npm outdated) diff --git a/CLAUDE.md b/CLAUDE.md index 7bf1277..51f7515 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -290,10 +290,24 @@ Ziel: max. 300 Zeilen. Vorfalls-Abschnitte (Datum, PR-Nummer, Diagnose-Verlauf) - **Gradle-Lock nach Absturz:** Bei "Cannot lock file hash cache"-Fehler Daemons stoppen: `pkill -f GradleDaemon`, dann Workingdir leeren und neu starten - **AAB-Archiv:** Gebaute Release-AABs in einem **gitignored** `aab-archive/`-Verzeichnis im Repo-Root ablegen (in `.gitignore` aufnehmen – AABs sind 3–110 MB und gehören nie in die Git-History). Benennung: `-vX.Y.Z-vc-YYYY-MM-DD.aab`. **Retention: max. 2 Dateien** (aktuelles Release + ein Vorgänger für schnelles Rollback); ältere AABs löschen. Der Git-Tag `vX.Y.Z` ist die eigentliche Release-Baseline – ältere AABs lassen sich daraus jederzeit neu bauen. +## [CLAUDE.MD-WARTUNG] + +- **CLAUDE.md bleibt bei maximal 300 Zeilen** (Issue #160): Sie wird bei jeder Session vollständig in den Kontext geladen. Beschreibt ein Abschnitt einen konkreten Vorfall, gehören maximal 2-3 Zeilen (Kernregel + kurzer Auslöser-Kontext) + ein Link auf `docs/private/INCIDENTS.md` hinein; aktuell gültiges Architektur-/Prozesswissen, das kein Vorfall ist, aber zu ausführlich für CLAUDE.md, gehört in versionierte `docs/*.md`-Dateien (z. B. `docs/ARCHITECTURE.md`). Die Schwelle ist ein Prüf-Auslöser, kein Zwang, bewusst dort gehaltenes, aktuelles Architekturwissen aus CLAUDE.md zu verdrängen. Aktiv gekürzt wird erst ab 500 Zeilen; Dateien zwischen 300 und 500 Zeilen werden im Turnus nicht angefasst. Ausführlicher Prozess, Checkliste und Stand pro Projekt: https://github.com/S540d/project-templates/blob/main/dev-standards/claude-md-maintenance.md +- **`docs/private/INCIDENTS.md` ist bewusst gitignored** — reine lokale Gedächtnisstütze wie Memory, kein Teil des geteilten Repo-Zustands. In jedem Projekt mit dieser Datei muss `.gitignore` einen Eintrag `docs/private/` enthalten; existiert die Datei bereits versioniert (z. B. als `docs/INCIDENTS.md`), gehört sie nach `docs/private/` verschoben und per `git rm --cached` aus dem Tracking genommen. +- **Regelmäßig `/simplify` auf CLAUDE.md ausführen**, nicht nur einmalig beim Überschreiten der Schwelle — Ziel ist dauerhaft niedriger Token-Verbrauch pro Session statt zyklischem Anwachsen und Zurückkürzen in großen Sprüngen. + ## [CODE HEALTH AUDIT] - **Wiederkehrendes Code-Health-Audit** (Ballast/Architektur: God Components, Boilerplate-Duplikation, toter Code, Dependency-Bloat, Test-Integrität, Design-Konsistenz, Bundle-Größe) alle ~3 Monate oder ~15 gemergte Feature-PRs (je nachdem was zuerst eintritt). Checkliste + Ablauf: https://github.com/S540d/project-templates/blob/main/dev-standards/code-health-audit.md — Ergebnis ist immer ein Issue im jeweiligen Projekt-Repo, nie in project-templates. +## [SIMPLIFY-AUDIT] + +- **Wiederkehrender `/simplify`-Durchlauf auf den Quellcode** (Reuse, Simplification, Efficiency, Altitude) alle ~3 Monate oder ~15 gemergte Feature-PRs (je nachdem was zuerst eintritt), gleiche Kadenz wie das Code-Health-Audit. Anders als dieses wendet er die Fixes direkt an: Ergebnis ist ein PR gegen den projektüblichen Ziel-Branch, nur kleine, verhaltensneutrale Refactorings (bei Unsicherheit Finding auslassen). Ablauf: https://github.com/S540d/project-templates/blob/main/dev-standards/simplify-audit.md + +## [ÜBER-ABSCHNITT] + +- **Einheitlicher „Über"-Abschnitt im Settingsmenü** (Issue #150): Jedes Web-Projekt zeigt „Über" als Eintrag in einem `⋮`-Settingsmenü (kein Footer — wird bei Bedarf neu angelegt, auch für aktuell menülose Projekte). Fester Vollausbau: App-Name, Version, Impressum, Datenschutz, Quellcode, Play Store, Feedback — nicht zutreffende Felder werden weggelassen, nie umsortiert. Spezifikation: https://github.com/S540d/project-templates/blob/main/dev-standards/about-section.md — Umsetzung ist immer ein Issue im jeweiligen Projekt-Repo, nie in project-templates. + ## [CI – CACHE-CLEANUP] - **Cache-Cleanup-Workflow** (`.github/workflows/cache-cleanup.yml`) in jedem Repo mit GitHub-Actions-Caches: löscht wöchentlich (So 03:00 UTC) bzw. on-demand alle Action-Caches älter als der jeweils letzte Lauf. GitHub-Limit ist 10 GB pro Repo – ohne Cleanup laufen Build-Caches (node_modules, Gradle, Expo) voll und verdrängen frische Einträge. Vorlage: `cache-cleanup.yml` in project-templates.