diff --git a/.claude/agents/next-issue.md b/.claude/agents/next-issue.md new file mode 100644 index 0000000..0ade770 --- /dev/null +++ b/.claude/agents/next-issue.md @@ -0,0 +1,13 @@ +--- +name: next-issue +description: Wählt das nächste zu bearbeitende Gitea-Issue und gibt nur die Kerndaten zurück. +tools: mcp__gitea__list_issues, mcp__gitea__issue_read +model: haiku +--- +Finde das nächste offene Issue im Repo / mit Label `ai-ready` +und NICHT mit Label `ai-wip` oder `ai-blocked`. +Priorisiere nach `prio/high` > `prio/medium` > `prio/low`, dann nach ältestem. + +Gib AUSSCHLIESSLICH eine Zeile aus, sonst nichts: +- Wenn eins gefunden: `ISSUE=` +- Wenn keins offen: `ISSUE=NONE` \ No newline at end of file diff --git a/.claude/commands/fix-issue.md b/.claude/commands/fix-issue.md new file mode 100644 index 0000000..04428c6 --- /dev/null +++ b/.claude/commands/fix-issue.md @@ -0,0 +1,40 @@ +--- +description: Behebt ein einzelnes Gitea-Issue Ende-zu-Ende. +argument-hint: +allowed-tools: > + Bash, Edit, Read, Write, Grep, Glob, + mcp__gitea__issue_read, mcp__gitea__issue_write, + mcp__gitea__label_read, + mcp__gitea__pull_request_write +model: opus +--- +Bearbeite Gitea-Issue #$1 im aktuellen Repo. Schritt für Schritt: + +**Label-Regeln (wichtig):** Die Gitea-Label-API arbeitet mit numerischen +Label-IDs, nicht mit Namen. Hole daher ZUERST einmalig die Label-Liste über +`label_read` (`method: list_repo_labels`) und merke dir die Zuordnung +Name → ID für die gesamte Bearbeitung. Verwende ausschließlich `add_labels` +(mit `labels: []`) und `remove_label` (mit `label_id: `). +Niemals `replace_labels` oder `clear_labels` benutzen — das löscht alle +übrigen Labels des Issues (z.B. `prio/*`). + +1. Lies Issue #$1 (Titel, Beschreibung, Kommentare) über `issue_read`. + Notiere die aktuell gesetzten Labels, damit du sie nicht verlierst. +2. Hole die Label-Liste via `label_read`. Setze Label `ai-wip` + (`add_labels`), entferne `ai-ready` (`remove_label`). +3. Analysiere das Repo und finde die Ursache. Wenn der Scope zu groß/unklar + ist (siehe CLAUDE.md), brich ab: kommentiere das Issue mit einer kurzen + Begründung, setze `ai-blocked`, und beende ohne Codeänderung. +4. Implementiere den Fix. Halte den Diff minimal und fokussiert. +5. Führe die Tests aus (``). Bei Rot: bis zu 2x nachbessern. + Wenn danach immer noch rot → `ai-blocked`, Issue kommentieren, abbrechen. +6. Commit mit Message: `fix: (#$1)`. +7. Push den aktuellen Branch zum Remote. +8. Öffne via `pull_request_write` einen PR gegen `main` (bzw. `develop`). + Die PR-Beschreibung MUSS `Closes #$1` enthalten. +9. Kommentiere am Issue mit dem PR-Link, setze Label `ai-review` + (`add_labels`) und entferne `ai-wip` (`remove_label`). + +Wenn du in einem Schritt `ai-blocked` setzt, entferne ebenfalls `ai-wip`. +Existiert ein benötigtes Label nicht im Repo, kommentiere das am Issue statt +zu raten — erfinde keine Label-IDs. \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..a018834 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,12 @@ +# Normalize line endings independent of core.autocrlf. +* text=auto + +# Maven wrapper: POSIX shell script must stay LF, even on Windows checkouts. +mvnw text eol=lf +*.sh text eol=lf + +# Windows batch wrapper needs CRLF. +mvnw.cmd text eol=crlf + +# Binaries: never convert. +*.jar binary diff --git a/CLAUDE.md b/CLAUDE.md index 2ed1160..ce6b462 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -37,3 +37,12 @@ Since `apex-chart.ts` renders into light DOM (`createRenderRoot()` returns `this **Styling**: `src/main/resources/META-INF/resources/styles.css` is the one project-level stylesheet (loaded via `@StyleSheet("styles.css")` in `Application.java`). It defines `--dialect-*` design tokens (Dialect design system: primary orange `#E86C00`, cool-gray background, card radius/shadow) and aliases them onto Aura's own CSS custom properties (`--aura-accent-color-*`, `--aura-background-color-*`, `--aura-orange`, `--aura-yellow`) rather than fighting the theme. Aura tokens use OKLCH + relative-color syntax and accept plain hex overrides. When restyling, prefer extending this alias layer over hardcoding new colors in components. UI copy/data (chart labels, notifications) is in German. + +## AI-Autofix – Regeln +- Nur Issues mit Label `ai-ready` bearbeiten. +- Branch-Namensschema: `ai/issue--`. +- Kein Fix ohne grüne Tests. Test-Befehl: ``. +- Bei Unklarheit / Scope > ~200 Zeilen Diff: NICHT fixen, + stattdessen Issue kommentieren ("needs human") und Label `ai-blocked` setzen. +- PR-Beschreibung MUSS `Closes #` enthalten. +- Keine Änderungen an ohne Freigabe. diff --git a/gitea-autofix-loop.sh b/gitea-autofix-loop.sh new file mode 100755 index 0000000..b845193 --- /dev/null +++ b/gitea-autofix-loop.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +set -euo pipefail + +source .env + +REPO_DIR="$HOME/codebase/chart-app" # Haupt-Klon +BASE_BRANCH="main" +TEST_CMD="./mvnw test" # z.B. ./gradlew test +MAX_ISSUES=5 # pro Durchlauf, damit du nicht davonläufst +POLL_INTERVAL=120 # Sekunden zwischen Polls (0 = einmal laufen) + +cd "$REPO_DIR" + +process_next() { + git -C "$REPO_DIR" fetch origin "$BASE_BRANCH" --quiet + git -C "$REPO_DIR" checkout "$BASE_BRANCH" --quiet + git -C "$REPO_DIR" pull --quiet + + # 1) Nächstes Issue holen (Sub-Agent, minimaler Output) + local out + out=$(claude -p "Nutze den Sub-Agent 'next-issue'. Gib NUR dessen Rueckgabezeile aus (ISSUE= oder ISSUE=NONE), keinen weiteren Text." \ + --allowedTools "Agent,mcp__gitea__list_issues,mcp__gitea__issue_read" \ + --output-format text) + local nr + nr=$(echo "$out" | grep -oE 'ISSUE=[0-9NONE]+' | cut -d= -f2) + + if [[ "$nr" == "NONE" || -z "$nr" ]]; then + echo "Keine offenen ai-ready Issues." + return 1 + fi + + echo ">>> Bearbeite Issue #$nr" + local wt="../wt-issue-$nr" + local branch="ai/issue-$nr" + + # 2) Isolierter Worktree + Branch + git worktree add -b "$branch" "$wt" "$BASE_BRANCH" --quiet + + # 3) Worker im Worktree ausführen (autonom) + ( + cd "$wt" + claude -p "/fix-issue $nr" \ + --allowedTools "Bash($TEST_CMD),Bash(git *),Edit,Read,Write,Grep,Glob,mcp__gitea__issue_read,mcp__gitea__issue_write,mcp__gitea__label_read,mcp__gitea__pull_request_write" \ + --output-format text + ) || echo "!!! Worker für #$nr mit Fehler beendet" + + # 4) Aufräumen + git worktree remove "$wt" --force || true + return 0 +} + +# --- Hauptschleife --- +while true; do + count=0 + while (( count < MAX_ISSUES )); do + if process_next; then ((count++)); else break; fi + done + echo "Durchlauf fertig ($count Issues)." + (( POLL_INTERVAL == 0 )) && break + sleep "$POLL_INTERVAL" +done \ No newline at end of file