Compare commits
6 Commits
0ab62a2752
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 0817d49dfc | |||
| 44cf2b3edc | |||
| 4acbd6b0b2 | |||
| 843bd145a8 | |||
| 98425b8fa8 | |||
| 5b6459a041 |
Vendored
+41
@@ -0,0 +1,41 @@
|
||||
## 🚀 Identität & Arbeitsmodus (Chamäleon-Modus)
|
||||
Du bist ein hochqualifizierter KI-Assistent für das Softwareprojekt "Meldestelle" von Stefan.
|
||||
Ich weise dir in meinen Prompts Aufgaben zu. Nimm sofort die entsprechende Rolle an, beginne deine Antwort zwingend mit dem passenden Badge und passe dein Vokabular an:
|
||||
|
||||
* 🏗️ **[Lead Architect]:** System-Design, Gradle-Build-Logik, Modulstruktur.
|
||||
* 📜 **[Rulebook Expert]:** Validiert Business-Rules gegen das ÖTO/FEI Regelwerk.
|
||||
* 👷 **[Backend Developer]:** Kotlin & Spring Boot Experte.
|
||||
* 🎨 **[Frontend Expert]:** KMP & Compose Desktop Spezialist.
|
||||
* 🐧 **[DevOps Engineer]:** Infrastruktur (Docker, CI/CD, Proxmox).
|
||||
|
||||
**Arbeitsanweisung:** Bearbeite pro Antwort immer nur EINE fachliche Aufgabe.
|
||||
|
||||
|
||||
|
||||
## 🏗️ Projekt-Strategie (Reality-Reset)
|
||||
1. **Desktop-First & Offline-First:** Das Primärziel ist eine autarke Compose Desktop App (KMP). Sie muss auf Turnieren ohne Internet funktionieren (lokale Persistenz).
|
||||
2. **Optionales Backend:** Ein Spring Boot Stack (PostgreSQL, Valkey, Keycloak) wird nur für Multi-Tenant-Verwaltung, Registrierung und P2P-Sync genutzt.
|
||||
3. **Domain-Driven Design (DDD):** Die absolute Business-Hierarchie lautet: Veranstaltung -> Turnier -> Bewerb/Abteilung.
|
||||
4. **Der System-Akteur:** Der primäre "Actor" in allen Use-Cases ist *nicht* der Veranstalter, sondern zwingend die Person, die die Meldestelle betreut (Actor = Meldestelle).
|
||||
|
||||
|
||||
|
||||
## 🛠️ Der verbindliche Tech-Stack
|
||||
Generiere Code ausschließlich für diese exakten Versionen und Paradigmen:
|
||||
* **Frontend (KMP):** Kotlin 2.3.21, Compose Multiplatform 1.10.3, Ktor Client 3.4.1, SQLDelight.
|
||||
* **Backend:** Spring Boot 3.5.9 (JDK 25), Ktor Server (wo spezifiziert), Exposed 1.1.1.
|
||||
* **Infrastruktur:** Gitea (CI/CD), Docker, Pangolin Tunnel. (KEIN GitHub, KEIN Cloudflare).
|
||||
|
||||
|
||||
|
||||
## 👁️ Anti-Halluzinations-Protokoll
|
||||
Du bist an strikte, evidenzbasierte Entwicklung gebunden:
|
||||
1. **Kein "Erledigt" ohne Beweis:** Ein Task ist erst abgeschlossen, wenn Test-Logs oder ein Build vorliegen.
|
||||
2. **Verifikation ausstehend:** Generierter, ungetesteter Code muss diesen Vermerk zwingend tragen.
|
||||
3. **Fakten-Check:** Wenn du den Code nicht im Kontext hast (z.B. eine spezifische Gradle-Datei), fordere sie aktiv vom User an, anstatt blind zu raten.
|
||||
|
||||
|
||||
|
||||
## 🛡️ DSGVO & Lokale Ausführung (Nolik-Spezifika)
|
||||
* Dein Name ist "Nolik". Du bist ein lokal gehosteter, datenschutzkonformer Senior-Architekt auf dem Server "Simka" (Proxmox VM 101).
|
||||
* **Datensouveränität:** Du bist der Hüter der lokalen Daten. Generiere niemals Code, der Telemetrie, Tracking oder Logging an externe Cloud-Anbieter sendet.
|
||||
@@ -0,0 +1,11 @@
|
||||
## 🚀 Identität & Arbeitsmodus (Chamäleon-Modus)
|
||||
Du bist ein hochqualifizierter KI-Assistent für das Softwareprojekt "Meldestelle" von Stefan.
|
||||
Ich weise dir in meinen Prompts Aufgaben zu. Nimm sofort die entsprechende Rolle an, beginne deine Antwort zwingend mit dem passenden Badge und passe dein Vokabular an:
|
||||
|
||||
* 🏗️ **[Lead Architect]:** System-Design, Gradle-Build-Logik, Modulstruktur.
|
||||
* 📜 **[Rulebook Expert]:** Validiert Business-Rules gegen das ÖTO/FEI Regelwerk.
|
||||
* 👷 **[Backend Developer]:** Kotlin & Spring Boot Experte.
|
||||
* 🎨 **[Frontend Expert]:** KMP & Compose Desktop Spezialist.
|
||||
* 🐧 **[DevOps Engineer]:** Infrastruktur (Docker, CI/CD, Proxmox).
|
||||
|
||||
**Arbeitsanweisung:** Bearbeite pro Antwort immer nur EINE fachliche Aufgabe.
|
||||
@@ -0,0 +1,3 @@
|
||||
## ⚙️ Provider-Spezifika (Google Gemini / Web-Meta-Modus)
|
||||
* Du agierst als "Gemini" über die Web-Oberfläche. Deine primäre Aufgabe ist die strategische Meta-Ebene, Architektur-Analyse, Review von CI/CD-Pipelines und das Sparring bei komplexen Refactoring-Plänen.
|
||||
* **Antwort-Stil:** Antworte prägnant, strukturiert und nutze das bereitgestellte Formatierungstoolkit (Markdown, klare Hierarchien, Code-Blöcke). Vermeide unnötige Floskeln und komm direkt auf den technischen Punkt.
|
||||
@@ -0,0 +1,4 @@
|
||||
## ⚙️ Provider-Spezifika (JetBrains Junie / IDE-Modus)
|
||||
* Dein Name ist "Junie". Du arbeitest als hochintegrierter KI-Assistent direkt innerhalb von IntelliJ IDEA.
|
||||
* **Kontext-Fokus:** Nutze die lokalen Projektdateien, Indizes und das Git-Log intensiv. Wenn Refactorings oder Code-Generierungen anstehen, achte penibel darauf, dass bestehende Datei-Imports (Kotlin-Packages) nicht zerschossen werden.
|
||||
* **Generierungs-Gate:** Halte dich strikt an die im Projekt hinterlegten Formatierungsregeln für Detekt und Ktlint.
|
||||
@@ -0,0 +1,3 @@
|
||||
## 🛡️ DSGVO & Lokale Ausführung (Nolik-Spezifika)
|
||||
* Dein Name ist "Nolik". Du bist ein lokal gehosteter, datenschutzkonformer Senior-Architekt auf dem Server "Simka" (Proxmox VM 101).
|
||||
* **Datensouveränität:** Du bist der Hüter der lokalen Daten. Generiere niemals Code, der Telemetrie, Tracking oder Logging an externe Cloud-Anbieter sendet.
|
||||
@@ -0,0 +1,5 @@
|
||||
## 🏗️ Projekt-Strategie (Reality-Reset)
|
||||
1. **Desktop-First & Offline-First:** Das Primärziel ist eine autarke Compose Desktop App (KMP). Sie muss auf Turnieren ohne Internet funktionieren (lokale Persistenz).
|
||||
2. **Optionales Backend:** Ein Spring Boot Stack (PostgreSQL, Valkey, Keycloak) wird nur für Multi-Tenant-Verwaltung, Registrierung und P2P-Sync genutzt.
|
||||
3. **Domain-Driven Design (DDD):** Die absolute Business-Hierarchie lautet: Veranstaltung -> Turnier -> Bewerb/Abteilung.
|
||||
4. **Der System-Akteur:** Der primäre "Actor" in allen Use-Cases ist *nicht* der Veranstalter, sondern zwingend die Person, die die Meldestelle betreut (Actor = Meldestelle).
|
||||
@@ -0,0 +1,5 @@
|
||||
## 🛠️ Der verbindliche Tech-Stack
|
||||
Generiere Code ausschließlich für diese exakten Versionen und Paradigmen:
|
||||
* **Frontend (KMP):** Kotlin 2.3.21, Compose Multiplatform 1.10.3, Ktor Client 3.4.1, SQLDelight.
|
||||
* **Backend:** Spring Boot 3.5.9 (JDK 25), Ktor Server (wo spezifiziert), Exposed 1.1.1.
|
||||
* **Infrastruktur:** Gitea (CI/CD), Docker, Pangolin Tunnel. (KEIN GitHub, KEIN Cloudflare).
|
||||
@@ -0,0 +1,5 @@
|
||||
## 👁️ Anti-Halluzinations-Protokoll
|
||||
Du bist an strikte, evidenzbasierte Entwicklung gebunden:
|
||||
1. **Kein "Erledigt" ohne Beweis:** Ein Task ist erst abgeschlossen, wenn Test-Logs oder ein Build vorliegen.
|
||||
2. **Verifikation ausstehend:** Generierter, ungetesteter Code muss diesen Vermerk zwingend tragen.
|
||||
3. **Fakten-Check:** Wenn du den Code nicht im Kontext hast (z.B. eine spezifische Gradle-Datei), fordere sie aktiv vom User an, anstatt blind zu raten.
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Nutze Junies robuste Pfad-Ermittlung
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/lib/common.sh"
|
||||
REPO_ROOT="$(resolve_repo_root)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
AI_DIR=".ai"
|
||||
DIST_DIR="$AI_DIR/dist"
|
||||
|
||||
mkdir -p "$DIST_DIR"
|
||||
|
||||
echo "[INFO] Generiere System-Prompts aus den Core-Rules..."
|
||||
|
||||
for PROVIDER_DIR in "$AI_DIR/providers/"*; do
|
||||
if [ -d "$PROVIDER_DIR" ]; then
|
||||
PROVIDER_NAME=$(basename "$PROVIDER_DIR")
|
||||
OUTPUT_FILE="$DIST_DIR/${PROVIDER_NAME}-system-prompt.md"
|
||||
|
||||
echo "-> Baue Prompt für: $PROVIDER_NAME"
|
||||
|
||||
# 1. Basis-Identität schreiben
|
||||
cat "$AI_DIR/prompts/system/base.md" > "$OUTPUT_FILE"
|
||||
echo -e "\n\n" >> "$OUTPUT_FILE"
|
||||
|
||||
# 2. Alle globalen Regeln anhängen
|
||||
for RULE_FILE in "$AI_DIR/rules/"*.md; do
|
||||
if [ -f "$RULE_FILE" ]; then
|
||||
cat "$RULE_FILE" >> "$OUTPUT_FILE"
|
||||
echo -e "\n\n" >> "$OUTPUT_FILE"
|
||||
fi
|
||||
done
|
||||
|
||||
# 3. Provider-Spezifika anhängen
|
||||
if [ -f "$PROVIDER_DIR/overlay.md" ]; then
|
||||
cat "$PROVIDER_DIR/overlay.md" >> "$OUTPUT_FILE"
|
||||
fi
|
||||
|
||||
echo "[OK] $OUTPUT_FILE erfolgreich erstellt."
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/lib/common.sh"
|
||||
|
||||
REPO_ROOT="$(resolve_repo_root)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# check-docs-drift.sh
|
||||
# Zweck: sehr schlanke Drift-Checks gegen die neue Doku-Struktur.
|
||||
# - Kein Guidelines-System mehr.
|
||||
# - Single Source of Truth: `docs/`
|
||||
|
||||
err=0
|
||||
|
||||
has() { grep -q "$2" "$1" || { echo "[DRIFT] '$2' fehlt in $1"; err=1; }; }
|
||||
miss() { grep -q "$2" "$1" && { echo "[DRIFT] Veralteter Begriff '$2' in $1"; err=1; }; }
|
||||
|
||||
# Harte Altlast-Pfade dürfen nicht mehr vorkommen
|
||||
if git grep -n "docs/00_Domain/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/00_Domain/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/adr/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/adr/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/c4/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/c4/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/how-to/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/how-to/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/reference/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/reference/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
|
||||
# Quelle der Wahrheit: Gateway-Technologie (sollte in Architektur/ADRs/C4 konsistent sein)
|
||||
has docs/01_Architecture/ARCHITECTURE.md "Spring Cloud Gateway"
|
||||
has docs/01_Architecture/adr/0007-api-gateway-pattern-de.md "Spring Cloud Gateway"
|
||||
miss docs/01_Architecture/adr/0007-api-gateway-pattern-de.md "Ktor"
|
||||
has docs/01_Architecture/c4/02-container-de.puml "Spring Cloud Gateway"
|
||||
miss docs/01_Architecture/c4/02-container-de.puml "Ktor"
|
||||
|
||||
exit $err
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Common helpers for AI guardrail scripts
|
||||
|
||||
# Robustly resolve the repository root directory.
|
||||
# Strategy: prefer Git; fallback to marker search upwards; last resort: current dir.
|
||||
resolve_repo_root() {
|
||||
local start
|
||||
start="${1:-$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)}"
|
||||
if command -v git >/dev/null 2>&1; then
|
||||
if git -C "$start" rev-parse --show-toplevel >/dev/null 2>&1; then
|
||||
git -C "$start" rev-parse --show-toplevel
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
local dir
|
||||
dir="$(cd "$start" && pwd)"
|
||||
while [ "$dir" != "/" ]; do
|
||||
if [ -f "$dir/gradlew" ] || [ -f "$dir/settings.gradle.kts" ] || [ -d "$dir/.git" ]; then
|
||||
echo "$dir"
|
||||
return 0
|
||||
fi
|
||||
dir="$(dirname "$dir")"
|
||||
done
|
||||
pwd
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/lib/common.sh"
|
||||
|
||||
REPO_ROOT="$(resolve_repo_root)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
mkdir -p build/diagrams
|
||||
shopt -s nullglob
|
||||
for f in docs/architecture/c4/*.puml; do
|
||||
docker run --rm -v "$PWD":/data plantuml/plantuml -tsvg "/data/$f" -o "/data/build/diagrams"
|
||||
echo "Rendered build/diagrams/$(basename "${f%.puml}").svg"
|
||||
done
|
||||
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/lib/common.sh"
|
||||
|
||||
REPO_ROOT="$(resolve_repo_root)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
QUICK_MODE=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--quick)
|
||||
QUICK_MODE=true
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
cat << 'EOF'
|
||||
Docs Link-Validierung
|
||||
|
||||
USAGE:
|
||||
./.ai/scripts/validate-links.sh [--quick]
|
||||
|
||||
BESCHREIBUNG:
|
||||
Prüft Markdown-Links in `docs/**/*.md` auf gebrochene relative Pfade.
|
||||
Ignoriert externe Links (http/https/mailto) sowie reine Anchors (#...).
|
||||
|
||||
OPTIONEN:
|
||||
--quick Führt nur eine Teilmenge der Prüfungen durch (aktuell nicht implementiert).
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "[ERROR] Unbekannter Parameter: $1" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
python3 - <<'PY'
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from urllib.parse import unquote
|
||||
|
||||
root = Path.cwd()
|
||||
docs_dir = root / "docs"
|
||||
|
||||
if not docs_dir.is_dir():
|
||||
print(f"[ERROR] docs-Verzeichnis nicht gefunden: {docs_dir}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
# Veraltete Pfad-Prüfungen wurden entfernt; Fokus auf Link-Integrität.
|
||||
FORBIDDEN_SUBSTRINGS = []
|
||||
|
||||
md_files = sorted(docs_dir.rglob("*.md"))
|
||||
|
||||
link_pattern = re.compile(r"\]\(([^)]+)\)")
|
||||
|
||||
errors = 0
|
||||
|
||||
def is_external(target: str) -> bool:
|
||||
t = target.lower()
|
||||
return t.startswith("http://") or t.startswith("https://") or t.startswith("mailto:")
|
||||
|
||||
def strip_fragment_and_query(target: str) -> str:
|
||||
target = target.split("#", 1)[0]
|
||||
target = target.split("?", 1)[0]
|
||||
return target
|
||||
|
||||
for f in md_files:
|
||||
text = f.read_text(encoding="utf-8", errors="replace")
|
||||
|
||||
for forbidden in FORBIDDEN_SUBSTRINGS:
|
||||
if forbidden in text:
|
||||
print(f"[ERROR] Veralteter Pfad '{forbidden}' in {f}")
|
||||
errors += 1
|
||||
|
||||
for match in link_pattern.finditer(text):
|
||||
target = match.group(1).strip()
|
||||
|
||||
if not target:
|
||||
continue
|
||||
if is_external(target):
|
||||
continue
|
||||
if target.startswith("#"):
|
||||
continue
|
||||
|
||||
if target.startswith("<") and target.endswith(">"):
|
||||
target = target[1:-1]
|
||||
|
||||
target = unquote(strip_fragment_and_query(target))
|
||||
|
||||
if target.startswith("/"):
|
||||
continue
|
||||
|
||||
if ":" in target.split("/", 1)[0]:
|
||||
# z.B. "vscode:..."
|
||||
continue
|
||||
|
||||
resolved = (f.parent / target).resolve()
|
||||
|
||||
try:
|
||||
resolved.relative_to(root.resolve())
|
||||
except ValueError:
|
||||
print(f"[ERROR] Link zeigt außerhalb des Repos: {f} -> {target}")
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
if resolved.is_dir():
|
||||
if not (resolved / "README.md").is_file():
|
||||
print(f"[ERROR] Verlinktes Verzeichnis ohne README.md: {f} -> {target}")
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
if not resolved.exists():
|
||||
print(f"[ERROR] Broken link: {f} -> {target}")
|
||||
errors += 1
|
||||
|
||||
if errors:
|
||||
print(f"[ERROR] Link-Validierung fehlgeschlagen: {errors} Fehler")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"[OK] Link-Validierung erfolgreich: {len(md_files)} Markdown-Dateien geprüft")
|
||||
PY
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
apply: always
|
||||
---
|
||||
|
||||
+1
-1
@@ -193,7 +193,7 @@ secrets/
|
||||
# ===================================================================
|
||||
TODO*.md
|
||||
NOTES*.md
|
||||
**/.junie/
|
||||
.junie/
|
||||
|
||||
# ===================================================================
|
||||
# Keep essential files (override exclusions)
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
desktop-tests:
|
||||
# Komplett deaktivierbar über Repo-Variable: Settings → Variables → DESKTOP_CI_ENABLED=true
|
||||
# Zusätzlich: Für Plan‑B‑Builds überspringen, wenn Commit-Message [planb] enthält
|
||||
if: ${{ vars.DESKTOP_CI_ENABLED == 'true' && !contains(github.event.head_commit.message, '[planb]') }}
|
||||
if: ${{ vars.DESKTOP_CI_ENABLED == 'true' && !contains(gitea.event.head_commit.message, '[planb]') }}
|
||||
name: Compose Desktop — Tests (headless) & Build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ on:
|
||||
jobs:
|
||||
no-hardcoded-versions:
|
||||
# Für Plan-B-Builds überspringen: Commit-Message enthält [planb]
|
||||
if: ${{ !contains(github.event.head_commit.message, '[planb]') }}
|
||||
if: ${{ !contains(gitea.event.head_commit.message, '[planb]') }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
tag-release:
|
||||
name: 🏷️ Git-Tag setzen
|
||||
# Für Plan-B-Builds überspringen: Commit-Message enthält [planb]
|
||||
if: ${{ !contains(github.event.head_commit.message, '[planb]') }}
|
||||
if: ${{ !contains(gitea.event.head_commit.message, '[planb]') }}
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.read-version.outputs.version }}
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Git-Tag erstellen & pushen
|
||||
if: steps.check-tag.outputs.already_tagged == 'false' && github.event.inputs.dry_run != 'true'
|
||||
if: steps.check-tag.outputs.already_tagged == 'false' && gitea.event.inputs.dry_run != 'true'
|
||||
run: |
|
||||
TAG="${{ steps.read-version.outputs.tag }}"
|
||||
VERSION="${{ steps.read-version.outputs.version }}"
|
||||
@@ -80,7 +80,7 @@ jobs:
|
||||
package-linux:
|
||||
name: 📦 Linux .deb Packaging
|
||||
# Nur ausführen, wenn Desktop-CI explizit aktiviert ist UND kein Plan‑B Commit
|
||||
if: ${{ vars.DESKTOP_CI_ENABLED == 'true' && !contains(github.event.head_commit.message, '[planb]') }}
|
||||
if: ${{ vars.DESKTOP_CI_ENABLED == 'true' && !contains(gitea.event.head_commit.message, '[planb]') }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: tag-release
|
||||
|
||||
@@ -88,11 +88,11 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup JDK 21 (Temurin)
|
||||
- name: Setup JDK 25 (Temurin)
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '21'
|
||||
java-version: '25'
|
||||
|
||||
- name: Gradle cache
|
||||
uses: actions/cache@v4
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
package-windows:
|
||||
name: 📦 Windows .msi Packaging
|
||||
# Nur ausführen, wenn Desktop-CI explizit aktiviert ist UND kein Plan‑B Commit
|
||||
if: ${{ vars.DESKTOP_CI_ENABLED == 'true' && !contains(github.event.head_commit.message, '[planb]') }}
|
||||
if: ${{ vars.DESKTOP_CI_ENABLED == 'true' && !contains(gitea.event.head_commit.message, '[planb]') }}
|
||||
runs-on: windows-latest
|
||||
needs: tag-release
|
||||
|
||||
@@ -136,11 +136,11 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup JDK 21 (Temurin)
|
||||
- name: Setup JDK 25 (Temurin)
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '21'
|
||||
java-version: '25'
|
||||
|
||||
- name: Gradle cache
|
||||
uses: actions/cache@v4
|
||||
@@ -179,11 +179,11 @@ jobs:
|
||||
steps:
|
||||
- name: Summary ausgeben
|
||||
run: |
|
||||
echo "## 🚀 Release ${{ needs.tag-release.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Artefakt | Status |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|----------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Linux .deb | ${{ needs.package-linux.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Windows .msi | ${{ needs.package-windows.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Git-Tag:** \`${{ needs.tag-release.outputs.tag }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "## 🚀 Release ${{ needs.tag-release.outputs.version }}" >> $GITEA_STEP_SUMMARY
|
||||
echo "" >> $GITEA_STEP_SUMMARY
|
||||
echo "| Artefakt | Status |" >> $GITEA_STEP_SUMMARY
|
||||
echo "|----------|--------|" >> $GITEA_STEP_SUMMARY
|
||||
echo "| Linux .deb | ${{ needs.package-linux.result }} |" >> $GITEA_STEP_SUMMARY
|
||||
echo "| Windows .msi | ${{ needs.package-windows.result }} |" >> $GITEA_STEP_SUMMARY
|
||||
echo "" >> $GITEA_STEP_SUMMARY
|
||||
echo "**Git-Tag:** \`${{ needs.tag-release.outputs.tag }}\`" >> $GITEA_STEP_SUMMARY
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# 🐧 [DevOps Engineer] Optimierte .gitignore für Meldestelle (KMP / Gradle / Docker)
|
||||
|
||||
# --- AI ---
|
||||
.ai/dist/
|
||||
|
||||
# --- IDE & Editor ---
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
@@ -1,43 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# check-docs-drift.sh
|
||||
# Zweck: sehr schlanke Drift-Checks gegen die neue Doku-Struktur.
|
||||
# - Kein Guidelines-System mehr.
|
||||
# - Single Source of Truth: `docs/`
|
||||
|
||||
err=0
|
||||
|
||||
has() { grep -q "$2" "$1" || { echo "[DRIFT] '$2' fehlt in $1"; err=1; }; }
|
||||
miss() { grep -q "$2" "$1" && { echo "[DRIFT] Veralteter Begriff '$2' in $1"; err=1; }; }
|
||||
|
||||
# Harte Altlast-Pfade dürfen nicht mehr vorkommen
|
||||
if git grep -n "docs/00_Domain/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/00_Domain/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/adr/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/adr/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/c4/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/c4/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/how-to/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/how-to/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/reference/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/reference/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
|
||||
# Quelle der Wahrheit: Gateway-Technologie (sollte in Architektur/ADRs/C4 konsistent sein)
|
||||
has docs/01_Architecture/ARCHITECTURE.md "Spring Cloud Gateway"
|
||||
has docs/01_Architecture/adr/0007-api-gateway-pattern-de.md "Spring Cloud Gateway"
|
||||
miss docs/01_Architecture/adr/0007-api-gateway-pattern-de.md "Ktor"
|
||||
has docs/01_Architecture/c4/02-container-de.puml "Spring Cloud Gateway"
|
||||
miss docs/01_Architecture/c4/02-container-de.puml "Ktor"
|
||||
|
||||
exit $err
|
||||
# Shim: Weiterleitung auf zentrale Guardrail in .ai/
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
|
||||
exec "$ROOT_DIR/.ai/scripts/check-docs-drift.sh" "$@"
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
mkdir -p build/diagrams
|
||||
shopt -s nullglob
|
||||
for f in docs/architecture/c4/*.puml; do
|
||||
docker run --rm -v "$PWD":/data plantuml/plantuml -tsvg "/data/$f" -o "/data/build/diagrams"
|
||||
echo "Rendered build/diagrams/$(basename "${f%.puml}").svg"
|
||||
done
|
||||
# Shim: Weiterleitung auf zentrale Guardrail in .ai/
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
|
||||
exec "$ROOT_DIR/.ai/scripts/render-plantuml.sh" "$@"
|
||||
|
||||
@@ -1,136 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# validate-links.sh - Link-Validierung für Projektdokumentation (`docs/**`).
|
||||
# Zweck: Guardrail für die "Docs-as-Code"-Strategie.
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
QUICK_MODE=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--quick)
|
||||
QUICK_MODE=true
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
cat << 'EOF'
|
||||
Docs Link-Validierung
|
||||
|
||||
USAGE:
|
||||
./.junie/scripts/validate-links.sh [--quick]
|
||||
|
||||
BESCHREIBUNG:
|
||||
Prüft Markdown-Links in `docs/**/*.md` auf gebrochene relative Pfade.
|
||||
Ignoriert externe Links (http/https/mailto) sowie reine Anchors (#...).
|
||||
|
||||
OPTIONEN:
|
||||
--quick Führt nur eine Teilmenge der Prüfungen durch (aktuell nicht implementiert).
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "[ERROR] Unbekannter Parameter: $1" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
python3 - <<'PY'
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from urllib.parse import unquote
|
||||
|
||||
root = Path.cwd()
|
||||
docs_dir = root / "docs"
|
||||
|
||||
if not docs_dir.is_dir():
|
||||
print(f"[ERROR] docs-Verzeichnis nicht gefunden: {docs_dir}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
# Veraltete Pfad-Prüfungen wurden entfernt, da sie zu wartungsintensiv waren.
|
||||
# Das Skript konzentriert sich nun auf die Validierung der Link-Integrität.
|
||||
FORBIDDEN_SUBSTRINGS = []
|
||||
|
||||
md_files = sorted(docs_dir.rglob("*.md"))
|
||||
|
||||
link_pattern = re.compile(r"\]\(([^)]+)\)")
|
||||
|
||||
errors = 0
|
||||
|
||||
def is_external(target: str) -> bool:
|
||||
t = target.lower()
|
||||
return t.startswith("http://") or t.startswith("https://") or t.startswith("mailto:")
|
||||
|
||||
def strip_fragment_and_query(target: str) -> str:
|
||||
# remove fragment and query parts
|
||||
target = target.split("#", 1)[0]
|
||||
target = target.split("?", 1)[0]
|
||||
return target
|
||||
|
||||
for f in md_files:
|
||||
text = f.read_text(encoding="utf-8", errors="replace")
|
||||
|
||||
for forbidden in FORBIDDEN_SUBSTRINGS:
|
||||
if forbidden in text:
|
||||
print(f"[ERROR] Veralteter Pfad '{forbidden}' in {f}")
|
||||
errors += 1
|
||||
|
||||
for match in link_pattern.finditer(text):
|
||||
target = match.group(1).strip()
|
||||
|
||||
if not target:
|
||||
continue
|
||||
if is_external(target):
|
||||
continue
|
||||
if target.startswith("#"):
|
||||
continue
|
||||
|
||||
# drop angle brackets <...> used in markdown for urls with spaces
|
||||
if target.startswith("<") and target.endswith(">"):
|
||||
target = target[1:-1]
|
||||
|
||||
target = unquote(strip_fragment_and_query(target))
|
||||
|
||||
# ignore absolute paths in the repo (we treat them as doc-style links; validate only if relative)
|
||||
if target.startswith("/"):
|
||||
continue
|
||||
|
||||
# ignore non-file targets (e.g. empty or protocol-less anchors)
|
||||
if ":" in target.split("/", 1)[0]:
|
||||
# things like "vscode:..." etc.
|
||||
continue
|
||||
|
||||
# treat as file path relative to markdown file
|
||||
resolved = (f.parent / target).resolve()
|
||||
|
||||
# keep validation within repo
|
||||
try:
|
||||
resolved.relative_to(root.resolve())
|
||||
except ValueError:
|
||||
print(f"[ERROR] Link zeigt außerhalb des Repos: {f} -> {target}")
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
# allow directories if they contain README.md
|
||||
if resolved.is_dir():
|
||||
if not (resolved / "README.md").is_file():
|
||||
print(f"[ERROR] Verlinktes Verzeichnis ohne README.md: {f} -> {target}")
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
if not resolved.exists():
|
||||
print(f"[ERROR] Broken link: {f} -> {target}")
|
||||
errors += 1
|
||||
|
||||
if errors:
|
||||
print(f"[ERROR] Link-Validierung fehlgeschlagen: {errors} Fehler")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"[OK] Link-Validierung erfolgreich: {len(md_files)} Markdown-Dateien geprüft")
|
||||
PY
|
||||
# Shim: Weiterleitung auf zentrale Guardrail in .ai/
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
|
||||
exec "$ROOT_DIR/.ai/scripts/validate-links.sh" "$@"
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# .aiignore - Verhindert Token-Waste für Nolik
|
||||
|
||||
# Abhängigkeiten & Binaries
|
||||
build/
|
||||
.gradle/
|
||||
*.jar
|
||||
*.deb
|
||||
*.msi
|
||||
|
||||
# Sensible Daten (auch lokal!)
|
||||
.env
|
||||
.env.*
|
||||
config/docker/certs/
|
||||
*.pem
|
||||
*.jks
|
||||
postgres-data/
|
||||
valkey-data/
|
||||
|
||||
# Doku-Builds (Nolik soll die Source-Files in docs/ lesen, nicht die HTML-Exporte)
|
||||
build/dokka/
|
||||
docs/Neumarkt2026/*.pdf
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Shim: Weiterleitung auf zentrale Guardrail in .ai/
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
|
||||
exec "$ROOT_DIR/.ai/scripts/check-docs-drift.sh" "$@"
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Shim: Weiterleitung auf zentrale Guardrail in .ai/
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
|
||||
exec "$ROOT_DIR/.ai/scripts/validate-links.sh" "$@"
|
||||
@@ -0,0 +1,26 @@
|
||||
# Journal Eintrag: 2026-06-09 - Gradle Configuration Cleanup
|
||||
|
||||
## 🏗️ [Lead Architect] & 🧹 [Curator]
|
||||
|
||||
### 🎯 Ziel
|
||||
|
||||
Entfernung veralteter Gradle-Properties, um Build-Warnungen zu reduzieren und die Kompatibilität mit zukünftigen
|
||||
Kotlin-Versionen sicherzustellen.
|
||||
|
||||
### 🛠️ Änderungen
|
||||
|
||||
- **`gradle.properties`**: Die Eigenschaft `kotlin.mpp.androidSourceSetLayoutVersion=2` wurde entfernt.
|
||||
- **Grund**: Die Warnung `w: ⚠️ Deprecated Gradle Property 'kotlin.mpp.androidSourceSetLayoutVersion' Used` im Modul
|
||||
`:contracts:ping-api` wies darauf hin, dass dieses Layout nun Standard ist und die explizite Setzung nicht mehr
|
||||
unterstützt wird.
|
||||
|
||||
### ✅ Verifikation
|
||||
|
||||
- `./gradlew :contracts:ping-api:help` wurde erfolgreich ohne die besagte Warnung ausgeführt.
|
||||
- Projektstruktur und andere Module wurden stichprobenartig auf ähnliche veraltete Einträge geprüft (keine weiteren
|
||||
Funde).
|
||||
|
||||
### 📝 Notizen
|
||||
|
||||
- Es sind noch diverse Compose-bezogene Deprecation-Warnungen in den Frontend-Modulen vorhanden. Diese sollten in einer
|
||||
separaten Session durch den **🎨 Frontend Expert** adressiert werden.
|
||||
@@ -40,7 +40,6 @@ org.gradle.dependency.locking.enabled=true
|
||||
io.ktor.development=true
|
||||
|
||||
# IDE Configuration
|
||||
kotlin.mpp.androidSourceSetLayoutVersion=2
|
||||
kotlin.mpp.enableCInteropCommonization=true
|
||||
org.jetbrains.kotlin.wasm.check.wasm.binary.format=false
|
||||
kotlin.native.ignoreDisabledTargets=true
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# === FRONTEND & KMP CORE ===
|
||||
# ==============================================================================
|
||||
# Kotlin & Tooling
|
||||
kotlin = "2.3.20"
|
||||
kotlin = "2.4.0"
|
||||
ksp = "2.3.4"
|
||||
|
||||
# KotlinX (Core Libraries)
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
Reference in New Issue
Block a user