Files

80 lines
4.8 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.
# SPEC-maintenance: Pflege-Agent, Vorschläge, Freigabe-Richtlinie
Paket: `knaster.maintenance`, `knaster.policy`.
## 1. Vorschlag (`Proposal`)
```
id: "P-<laufende Nr>"
kind: request_graduation | promote_skill | demote_skill | merge_skills | retire_skill | mark_slot |
restart_container | restart_vm | reboot_host | notify | 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) -> auto | approve | deny`, dazu `Policy.in_window(kind, now)`.
Ausnahme unabhängig von der Richtlinie: `mark_slot` mit `status: ok` (Slot wieder freischalten) braucht immer eine Freigabe, weil es die unsichere Richtung ist. 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 ≥ `promote_min_rate` (0,95) | `request_graduation` (approve): Auftrag an Hermes, Varianten zu erzeugen und `POST /v1/skills/{name}/graduate` aufzurufen. Ein erfolgreicher Lauf erzeugt `promote_skill` (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) |
| Canary auswerten | Kandidat im Zustand `canary` mit ≥ `min_n` Fällen über das Canary-Modell | automatischer Report `canary` an die Pipeline |
| Offene Kandidaten | Lifecycle-Kandidat wartet auf Freigabe | `promote_candidate` (approve, Risiko hoch) |
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.