docs: Architekturplan, ADRs, Spezifikationen und Umsetzungsplan

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-11 14:00:36 +02:00
co-authored by Claude Opus 5.5
commit fef930d176
15 changed files with 854 additions and 0 deletions
+77
View File
@@ -0,0 +1,77 @@
# SPEC-maintenance: Pflege-Agent, Vorschläge, Freigabe-Richtlinie
Paket: `knaster.maintenance`, `knaster.policy`.
## 1. Vorschlag (`Proposal`)
```
id: "P-<laufende Nr>"
kind: promote_skill | demote_skill | merge_skills | retire_skill | mark_slot | restart_container |
restart_vm | reboot_host | create_candidate | promote_candidate | rollback_candidate |
train_adapter | recalibrate_context
params: {...}
summary: str # menschenlesbar
reason: str
risk: low | medium | high
state: open | approved | rejected | executed | failed | expired
source: routine | command | healer | lifecycle
created_at, decided_at, decided_by, result
```
## 2. Freigabe-Richtlinie (`config/policy.yaml`)
```yaml
default: approve
actions:
demote_skill: {mode: auto}
mark_slot: {mode: auto}
restart_container: {mode: auto}
restart_vm: {mode: auto}
recalibrate_context:{mode: auto}
promote_skill: {mode: approve}
...
reboot_host: {mode: approve, window: "02:00-05:00"}
```
`Policy.decide(kind, now) -> auto | approve | deny`. Liegt eine Aktion mit `window` außerhalb des Zeitfensters, wird sie zwar freigegeben, aber erst im nächsten Fenster ausgeführt (`deferred`). Ein Vorschlag mit Modus `auto` wird sofort ausgeführt und mit `decided_by = policy` protokolliert.
## 3. Service-Routine (`MaintenanceAgent.run_routine`)
Befunde werden aus diesen Quellen gesammelt (alle Grenzwerte in `config/maintenance.yaml`):
| Befund | Bedingung | Vorschlag |
|---|---|---|
| Skill-Drift | Pass-Rate der letzten N Fälle auf Stufe ≥ 1 < `demote_below` (0,80), n ≥ `min_cases` (20) | `demote_skill` (auto) |
| Graduierungs-Kandidat | Skill auf Stufe 0, ≥ `min_cases` Fälle, Pass-Rate auf Stufe 0 ≥ 0,95 | `promote_skill` → Graduierungslauf (approve) |
| Ähnliche Skills | cos(description_a, description_b) ≥ `merge_similarity` (0,92) | `merge_skills` (approve) |
| Slot degradiert | Laufzeitzustand ≠ ok seit > 1 h | Hinweis + `mark_slot ok` nach Prüfung (approve) |
| Kontext-Ausweicher | Signal `context_exceeded` oder `output_truncated` ≥ `context_signal_limit` (10) pro Slot/Woche | `recalibrate_context` (auto) |
| Adapter-Bedarf | Cluster mit ≥ `adapter_min_cases` (300) verifizierten Train-Fällen und Pass-Rate auf Stufe 1 < 0,9 | `train_adapter` (approve) |
| Offene Kandidaten | Lifecycle-Kandidat wartet auf Freigabe | Verweis auf `promote_candidate` |
Das Ergebnis ist ein `RoutineReport{findings[], proposals[], auto_executed[], text}`. `text` ist ein deutscher Bericht für den Chat.
## 4. Befehle per Prompt (`MaintenanceAgent.handle_command`)
Feste Grammatik (Groß-/Kleinschreibung egal, deutsch und kurze englische Synonyme):
| Muster | Wirkung |
|---|---|
| `status` / `hilfe` | Überblick bzw. Befehlsliste |
| `routine` / `starte (die) service-routine` | Service-Routine |
| `vorschläge` / `zeige vorschläge` | offene Vorschläge |
| `genehmige P-3 [P-5 …]` / `approve P-3` | Freigabe und Ausführung |
| `genehmige alle (mit )?risiko niedrig` | alle offenen Vorschläge mit `risk == low` |
| `lehne P-3 ab[: Grund]` / `reject P-3` | Ablehnung |
| `wechsle <slot> auf <base_model>` | Vorschlag `create_candidate{kind: base_model}` |
| `trainiere adapter für <cluster>` | Vorschlag `train_adapter` |
| `rollback <slot>` | Vorschlag `rollback_candidate` |
| `stufe <skill> zurück` / `degradiere <skill>` | Vorschlag `demote_skill` |
| `markiere <slot> (als)? (ok\|degraded\|unavailable)` | Vorschlag `mark_slot` |
Bei unbekanntem Text wird, falls konfiguriert, ein `IntentMapper` (LLM, Slot `tier1-general`) gefragt, der **nur** einen der obigen Befehle als String zurückgeben darf. Der Agent antwortet dann: „Meinst du: `<befehl>`? Antworte mit ‚ja‘.“ Ein nachfolgendes `ja` in derselben Sitzung führt den Befehl aus, einen neu erzeugten Vorschlag aber ebenfalls nur bis zur Freigabestufe.
Aus Prompt-Aufträgen erzeugte Vorschläge werden **nie** sofort ausgeführt, auch wenn die Richtlinie `auto` sagt. Der Mensch bestätigt sie mit `genehmige`.
## 5. Ausführung
`ActionExecutor.execute(proposal) -> result`. Aktionen sind registrierte Handler. Infrastruktur-Aktionen (`restart_*`, `reboot_host`) gehen an dieselben Treiber wie beim Healer (SPEC-healer §4). Standard ist **Dry-Run**: Das Ergebnis beschreibt dann, was getan worden wäre.