diff --git a/.claude/agents/next-issue.md b/.claude/agents/next-issue.md index 0ade770..ae08a7d 100644 --- a/.claude/agents/next-issue.md +++ b/.claude/agents/next-issue.md @@ -4,7 +4,7 @@ description: Wählt das nächste zu bearbeitende Gitea-Issue und gibt nur die Ke tools: mcp__gitea__list_issues, mcp__gitea__issue_read model: haiku --- -Finde das nächste offene Issue im Repo / mit Label `ai-ready` +Finde das nächste offene Issue im Repo pitfriedrich/chart-app mit Label `ai-ready` und NICHT mit Label `ai-wip` oder `ai-blocked`. Priorisiere nach `prio/high` > `prio/medium` > `prio/low`, dann nach ältestem. diff --git a/.claude/commands/fix-issue.md b/.claude/commands/fix-issue.md index 04428c6..774d80e 100644 --- a/.claude/commands/fix-issue.md +++ b/.claude/commands/fix-issue.md @@ -5,7 +5,8 @@ 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 + mcp__gitea__pull_request_write, mcp__gitea__pull_request_read, + mcp__gitea__actions_run_read model: opus --- Bearbeite Gitea-Issue #$1 im aktuellen Repo. Schritt für Schritt: @@ -18,22 +19,36 @@ Name → ID für die gesamte Bearbeitung. Verwende ausschließlich `add_labels` Niemals `replace_labels` oder `clear_labels` benutzen — das löscht alle übrigen Labels des Issues (z.B. `prio/*`). +0. Vorbedingungen: Wenn Issue #$1 bereits `ai-wip` oder `ai-blocked` trägt, + abbrechen (kein Doppelstart). Prüfe `git status --porcelain` — ist der + Baum nicht sauber, abbrechen statt fremde Änderungen mitzucommitten. 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`). + Begründung, setze `ai-blocked`, entferne `ai-wip`, und beende ohne + Codeänderung. +4. Lege den Branch an: `git checkout main && git pull --ff-only`, dann + `git checkout -b ai/issue-$1-` (Slug aus dem Issue-Titel, + kleingeschrieben, Bindestriche statt Leerzeichen). +5. Implementiere den Fix. Halte den Diff minimal und fokussiert. +6. Führe die Tests aus (`./mvnw test`). Bei Rot: bis zu 2x nachbessern. + Wenn danach immer noch rot → `ai-blocked`, `ai-wip` entfernen, Issue + kommentieren, abbrechen. Hinweis: `e2e/*PlaywrightTest` überspringt sich + selbst per JUnit-Assumption, wenn der Browser-Download fehlschlägt — + übersprungen zählt nicht als rot und ist kein Abbruchgrund. +7. Commit mit Message: `fix: (#$1)`. +8. Push den Branch zum Remote. +9. Öffne via `pull_request_write` einen PR gegen `main`. Die + PR-Beschreibung MUSS `Closes #$1` enthalten. +10. Warte den CI-Lauf des PR-Branches ab (`actions_run_read`, PR läuft + automatisch gegen `.gitea/workflows/ci.yml`). + - Grün: kommentiere am Issue mit dem PR-Link, setze Label `ai-review` + (`add_labels`), entferne `ai-wip` (`remove_label`). + - Rot: setze `ai-blocked`, entferne `ai-wip`, kommentiere das Issue mit + einem kurzen Auszug aus dem CI-Log. Kein `ai-review`. 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 diff --git a/.claude/commands/work-queue.md b/.claude/commands/work-queue.md new file mode 100644 index 0000000..4fe36ca --- /dev/null +++ b/.claude/commands/work-queue.md @@ -0,0 +1,23 @@ +--- +description: Wählt das nächste ai-ready Issue und arbeitet es via /fix-issue ab. +allowed-tools: > + Bash, Edit, Read, Write, Grep, Glob, + mcp__gitea__list_issues, mcp__gitea__issue_read, mcp__gitea__issue_write, + mcp__gitea__label_read, + mcp__gitea__pull_request_write, mcp__gitea__pull_request_read, + mcp__gitea__actions_run_read +model: opus +--- +Arbeitet genau EIN Issue aus der Autofix-Warteschlange ab. Kein Loop +innerhalb dieses Commands — für wiederholte Läufe die `/loop`-Skill nutzen +(z.B. `/loop 30m /work-queue`). + +1. Rufe den Agenten `next-issue` auf. Er liefert entweder `ISSUE=` + oder `ISSUE=NONE`. +2. `ISSUE=NONE` → melde „Queue leer, kein `ai-ready`-Issue offen" und + beende ohne weitere Aktion. +3. `ISSUE=` → führe exakt den Ablauf aus `.claude/commands/fix-issue.md` + für Issue `` aus (Schritte 0–10 dort, unverändert, inklusive + Label-Regeln, Branch-Schema, Testkommando und CI-Gate). Diese Datei + beschreibt den Ablauf nicht erneut — Quelle der Wahrheit ist + `fix-issue.md`. diff --git a/.gitignore b/.gitignore index d0a4b0b..90a2773 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ node_modules/ src/main/frontend/generated/ vite.generated.ts /src/main/bundles/prod.bundle +/src/main/bundles/dev.bundle diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index 6ba2eda..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,39 +0,0 @@ -# AGENTS.md - -This file provides guidance to Codex (Codex.ai/code) when working with code in this repository. - -## Commands - -```bash -./mvnw spring-boot:run # run app (default goal) — http://localhost:8080, ~30s first start -./mvnw compile # compile only -./mvnw package # production build → target/*.jar -java -jar target/*.jar # run production jar -``` - -No test sources exist yet (`src/test` is empty) — `spring-boot-starter-test` and `browserless-test-spring` are on the classpath but unused. - -**Java 25 toolchain required** (`pom.xml` sets `java.version=25`). If the default JDK on PATH is older (check `java -version`), point `JAVA_HOME` at a Java 25 install for the Maven build, e.g.: -```bash -JAVA_HOME="/path/to/jdk-25" ./mvnw compile -``` - -Port 8080 conflicts: a prior `spring-boot:run` left running in the background is the usual cause (Vaadin dev mode keeps a second process/thread alive under a different PID than the launching Maven process — killing the Maven process alone may not free the port). Find and stop the actual listener before restarting. - -## Architecture - -Vaadin Flow (server-side Java UI, no hand-written HTML/JS for views) on Spring Boot 4.1, using the **Aura** theme (not Lumo — no `@Theme` annotation; Aura is wired via `@StyleSheet(Aura.STYLESHEET)` in `Application.java`). - -**Charts are ApexCharts, not Vaadin Charts.** The bridge lives in `components/`: -- `ApexChart` (abstract, `@Tag("apex-chart")`) — owns the JS module (`frontend/components/apex-chart.ts`, a Lit element rendering into light DOM), serializes an options `Map` to JSON via Jackson and calls `renderChart` client-side, and exposes point-click events back to the server via `@ClientCallable`. -- `AxisChart` (abstract) — builds `series`/`xaxis.categories` options for line/bar. -- `LineChart`, `BarChart` extend `AxisChart`; `PieChart` extends `ApexChart` directly (`series`/`labels` instead of axis-based). -- `DialectTheme` — single source of chart styling (categorical color palette, grid/legend/stroke option fragments). Every chart's `setData(...)` starts from `DialectTheme.baseOptions(chartType)` and merges in its data. Add new chart types here, not by duplicating option maps. - -Since `apex-chart.ts` renders into light DOM (`createRenderRoot()` returns `this`), global CSS can reach into the chart markup — but series/legend/grid colors are driven entirely by the options JSON, not CSS, because ApexCharts renders its own SVG/canvas. - -**Views** (`views/`): `MainLayout` (`@Layout`, applies to all routes) is the `AppLayout` shell — navbar + `SideNav` drawer, with one `SideNavItem` per route. Routes: `DashboardView` (`@Route("")`) wraps each chart in a `Card` (`components/Card.java`); `FormView` (`@Route("formular")`) demonstrates form controls bound via `Binder`; `TableView` (`@Route("tabelle")`) demonstrates a `Grid` over dummy data with a live text filter (`GridListDataView.addFilter`, `TextField` in `ValueChangeMode.EAGER`). New views should reuse `Card` to wrap their content rather than adding components directly, and get a matching `SideNavItem` in `MainLayout`. - -**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. diff --git a/CLAUDE.md b/CLAUDE.md index c98f5e7..3b288a4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -52,4 +52,5 @@ UI copy/data (chart labels, notifications) is in German. - 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. +- Keine Änderungen an kritischen Pfaden ohne Freigabe: `pom.xml`, `mvnw`/`mvnw.cmd`, + `.mvn/`, `.gitea/workflows/`, `.gitignore`. diff --git a/gitea-autofix-loop.sh b/gitea-autofix-loop.sh deleted file mode 100755 index b845193..0000000 --- a/gitea-autofix-loop.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/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 diff --git a/src/main/bundles/dev.bundle b/src/main/bundles/dev.bundle deleted file mode 100644 index db04b3b..0000000 Binary files a/src/main/bundles/dev.bundle and /dev/null differ