rd13_copilot_setup/docs/MAINTAINER.md
Conrad Schulz 5d0194a7b8
Some checks are pending
CI / Lint & self-test (push) Waiting to run
feat(bootstrap): auto-detect dev shell into copilot-instructions
Neues Default-Shell-Feld in der Projekt-Sektion (nach ---), damit der Agent die richtige Shell-Syntax waehlt. Bootstrap erkennt $SHELL (Fallback fish, Whitelist gegen sed-Injection) und schreibt es in frisch erzeugte copilot-instructions.md; manuell aenderbar und ueberlebt copilot-update. selftest +3 Faelle (sh & fish), beide MAINTAINER.md dokumentiert.
2026-06-18 10:05:46 +02:00

163 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Maintainer-Handbuch rd13_copilot_setup
Dieses Dokument beschreibt Architektur, Designentscheidungen und wie das Projekt erweitert wird.
---
## Architektur: 3-Schichten-Modell
```
┌─────────────────────────────────────────────────────────┐
│ Layer 1: Immer aktiv (User settings.json) │
│ • Senior-Dev-Grundregeln in codeGeneration.instructions │
│ • Commit-Format, Review-Standard, Test-Standard │
│ • Copilot Feature-Flags │
├─────────────────────────────────────────────────────────┤
│ Layer 2: Auf Abruf (Prompt Files ~/.vscode-server/…) │
│ • /requirements /architecture /new-feature │
│ • /code-review /debug /refactor │
│ • /write-tests /done-check /docker │
├─────────────────────────────────────────────────────────┤
│ Layer 3: Repo-spezifisch (.github/copilot-instructions) │
│ • Stack, Konventionen, ADR-Entscheidungen │
│ • Definition of Done für dieses Projekt │
│ • NFRs (Performance, Availability, Security) │
└─────────────────────────────────────────────────────────┘
```
Für Repos mit einem Namen beginnend mit `rd13_` gilt als Grundannahme:
- Der Runner läuft in Docker.
- Alle Services werden über Caddy als Proxy bereitgestellt.
- Die zentrale Proxy-Infrastruktur liegt im Repo `rd13_system_proxy`.
---
## Dateistruktur
```
rd13_copilot_setup/
├── docs/
│ ├── USER.md ← Endnutzer-Dokumentation
│ ├── ADMIN.md ← Administrator-Dokumentation (Deploy, Hooks, PATH)
│ └── MAINTAINER.md ← Dieses Dokument
├── git-templates/ ← Template-Quellen für neue Repos
│ ├── .github/
│ │ └── copilot-instructions.md ← Wird pro Repo individualisiert (TODO-Felder)
│ ├── .vscode/
│ │ ├── settings.json ← Repo-spezifische VS Code Einstellungen
│ │ └── extensions.json ← Empfohlene Extensions für neue Repos
│ ├── hooks/
│ │ ├── pre-commit ← Agent Quality Gate (6 Checks)
│ │ └── post-merge ← Opt-in: copilot-update.sh nach git pull
│ ├── docs/
│ │ ├── USER.md ← Template Endnutzer-Doku
│ │ ├── ADMIN.md ← Template Admin-Doku
│ │ ├── MAINTAINER.md ← Template Maintainer-Doku
│ │ ├── requirements/
│ │ │ └── REQUIREMENTS.md ← Template für persistente Anforderungen
│ │ └── history/
│ │ └── summary/
│ │ └── PROJECT_CONTEXT.md ← Template Agent-Kontext-Summary
├── prompts/ ← Wiederverwendbare Copilot-Workflows
│ └── *.prompt.md ← /requirements /history /check-consistency ...
├── scripts/
│ ├── deploy.sh ← Bash-Deploy (macOS + Linux)
│ ├── deploy.fish ← Fish-Deploy (Linux)
│ ├── copilot-bootstrap.sh ← POSIX-sh Bootstrap für einzelne Repos
│ ├── copilot-bootstrap.fish ← Fish-Variante (voll funktionsgleich)
│ ├── copilot-update.sh ← Aktualisiert Templates + Hooks in Repos
│ ├── copilot-update.fish ← Fish-Variante
│ └── selftest.sh ← CI/lokaler Bootstrap-Dry-Run (sh+fish)
└── user-settings/
└── settings.json ← VS Code User-Level Settings (Layer 1)
```
---
## Wie `git init-copilot` funktioniert (Opt-in)
Git hat keinen `post-init` Hook `.github/` und `.vscode/` befinden sich im Working Tree, nicht in `.git/`, weshalb `init.templateDir` allein nicht ausreicht. Statt den globalen `git init` zu überschreiben (invasiv würde auch bei `git clone` fremder Repos greifen), gibt es einen **separaten Opt-in-Alias** `init-copilot`.
**Git-Alias mit Rekursionsschutz**
In `~/.gitconfig` (wird von deploy.sh/.fish gesetzt):
```ini
[alias]
init-copilot = !f() { dir=.; for a in "$@"; do case "$a" in -*) ;; *) dir="$a" ;; esac; done; "$(git --exec-path)/git-init" "$@" && "$HOME/.local/bin/copilot-bootstrap.sh" "$dir"; }; f
```
- `!` → externer Shell-Befehl (via `/bin/sh`), kein Git-Subcommand
- `$(git --exec-path)/git-init` → ruft das echte `git-init`-Binary direkt auf → **kein Rekursions-Loop**
- Letztes Nicht-Flag-Argument wird als Zielverzeichnis erkannt (`dir=.` als Default)
- Nach erfolgreichem `git init` wird `copilot-bootstrap.sh` ausgeführt
- Der Standard-`git init` bleibt unverändert; frühere invasive `alias.init`/`init.templateDir` werden von deploy.sh gezielt entfernt
---
## Neuen Prompt hinzufügen
1. Datei `prompts/mein-workflow.prompt.md` anlegen
2. Format:
```markdown
---
mode: agent
description: Kurzbeschreibung für den Chat-Slash-Command
---
# Mein Workflow
```
3. `deploy.sh` erneut ausführen → deployed die neue Datei in `~/.vscode-server/…/prompts/`
4. In `README.md` und `docs/USER.md` in der Prompt-Tabelle eintragen
5. Committen
## Template-Dateien ändern
Dateien unter `git-templates/` bearbeiten → `deploy.sh` ausführen → neue Repos bekommen die neue Version. Bestehende Repos werden **nicht** automatisch aktualisiert (Bootstrap überschreibt nicht).
**Wichtig beim Ändern von `git-templates/hooks/pre-commit`:** Die Datei muss nach dem Deployen ausführbar sein (`chmod +x`). `deploy.sh` erledigt das automatisch.
## Shell-Skripte ändern
Alle Skripte gibt es paarweise (POSIX/bash + fish) und müssen synchron bleiben:
`deploy`, `copilot-bootstrap`, `copilot-update`. Die `.sh`-Variante ist jeweils die
Referenz, die `.fish`-Variante bildet dieselben Schritte in Fish-Syntax ab.
CI (`.github/workflows/ci.yml`) prüft bei jedem Push/PR:
- `shellcheck` für alle `*.sh` + git-Hooks
- `fish -n` für alle `*.fish`
- `scripts/selftest.sh` (Bootstrap-Dry-Run sh+fish gegen isoliertes Fake-HOME)
Lokal vor dem Commit: `sh scripts/selftest.sh` ausführen.
---
## Designentscheidungen
| Entscheidung | Begründung |
|---|---|
| POSIX sh für Bootstrap-Script | Läuft auf jedem System ohne extra Dependencies (kein fish nötig) |
| Git-Alias statt Fish-Wrapper | Portabel: funktioniert in bash, sh, CI, GUI-Clients nicht nur in fish |
| `git --exec-path` statt `command git` | `command` umgeht Aliases in fish/zsh, aber nicht in POSIX sh; `--exec-path` ist universell |
| Templates nicht auto-updaten | Idempotenz: Bootstrap überschreibt nie Nutzer können Templates nach Init anpassen |
| 3 Zielgruppen-Docs (USER/ADMIN/MAINTAINER) | Klare Trennung: Nutzer ≠ Ops ≠ Dev; jede Gruppe findet ihren Kontext direkt |
| `data/` gitignored, Ordner-Struktur tracked | Persistente Daten gehören nie ins Git; Struktur als Konvention dokumentiert |
| `docs/history/prompts/` committed | Vollständige Agent-History bleibt im Repo erhalten; ermöglicht lückenlose Nachvollziehbarkeit |
| pre-commit Hook als Quality Gate (6 Checks) | Automatisches Netz: Tests, Doku, 3-Zielgruppen, PROJECT_CONTEXT, Requirements, Session-Datei; Opt-outs via `.copilot-no-tests` / `.copilot-no-docs` / `.copilot-no-requirements` |
| Check 6: Session-Datei muss in jedem Commit gestaged sein | Jeder Commit ist mit Agent-Session verknüpft; kein Opt-out; erzwingt `/history` vor `git commit` |
| Check 6 prüft Datum + `### Prompt`-Inhalt | Verhindert reine Nachtrag-Blöcke ohne echte Prompt-Einträge; Session-Datei muss heutiges Datum im Namen tragen |
| Kein globales `init.templateDir`, Opt-in `git init-copilot` | Standard-`git init`/`git clone` bleiben unberührt; Quality Gate landet nur in bewusst gewählten Repos |
| Remote-Quelle konfigurierbar (env/Config) + Offline-Modus | Keine hartkodierte Infrastruktur; `git copilot-update` läuft auch ohne Netz und endet graceful (exit 0) |
| `detect_vscode_user_dir` in jedem Skript dupliziert | Skripte laufen standalone aus `~/.local/bin` → keine gemeinsame Lib sourcebar; bewusst kopiert statt geteilt |
| Default-Shell-Feld in der Projekt-Sektion (nach `---`) | Bootstrap erkennt `$SHELL` und schreibt es nach `.github/copilot-instructions.md`; liegt bewusst **nach** dem `---`, damit `copilot-update` die Framework-Sektion neu schreiben kann, ohne den repo-/maschinenspezifischen Shell-Wert zu überschreiben |
## Bekannte Fallstricke
| Problem | Ursache | Fix |
|---|---|---|
| `Syntax error: word unexpected` in `copilot-update.sh` Zeile ~60 | Box-Drawing-Zeichen (`────`) direkt ans `fi` angehängt statt auf eigener Zeile | `fi` allein auf Zeile, Kommentar-Linie separat (`# ──`) |
| Self-Update überschreibt manuell deployten Fix | Self-Update holt Version aus Remote-Cache, der noch kaputten Stand hat | Erst committen + pushen, dann manuell deployen: `cp scripts/copilot-update.sh ~/.local/bin/` |
| Leerzeile vor `---` in `copilot-instructions.md` wird entfernt | `$(awk ...)` strippt trailing newlines; `printf '%s\n%s\n'` setzt Blöcke direkt zusammen | `printf '%s\n\n%s\n'` verwenden |
| `$USER` unbound unter `set -u` | `deploy.sh` nutzt `set -euo pipefail`; `$USER` fehlt in minimalen Envs (`env -i`, CI) | In `detect_vscode_user_dir` `${USER:-}` statt `$USER` |
| fish: Funktion ändert Skript-Variable nicht | fish-Funktionen sehen Caller-Locals nicht | `set -g` für Zähler/Flags die eine Funktion schreibt (z. B. `_append_gitignore`) |
| Anpassbares Feld wird von `copilot-update` überschrieben | Inhalt stand **vor** dem ersten `---` (Framework-Sektion wird immer aus Template neu geschrieben) | Repo-/maschinenspezifische, anpassbare Felder immer **nach** `---` platzieren (Projekt-Sektion bleibt erhalten) siehe Default-Shell-Feld |