Some checks are pending
CI / Lint & self-test (push) Waiting to run
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.
163 lines
10 KiB
Markdown
163 lines
10 KiB
Markdown
# 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 |
|