package mcpserver // Kuratierte Einträge vor unbemerktem Überschreiben schützen. // // „Kuratiert" heißt: Ein Mensch hat den Inhalt geprüft. Schreibt ein Agent // einen solchen Eintrag um, ist der neue Text nicht mehr geprüft — die // Markierung fällt deshalb weg. Das ist richtig. Früher geschah es aber // still: Der Agent erfuhr nicht, dass er geprüftes Wissen ersetzt hatte, und // kein Mensch bekam es mit. // // Jetzt läuft es in zwei Schritten, wie bei den Dubletten (dubletten.go): // // 1. remember auf einen kuratierten Eintrag schreibt NICHT, sondern meldet // judgment_required mit einer Erklärung. // 2. Hält der Agent die Änderung für nötig, ruft er erneut auf, mit // override_curated: true und einer Begründung (reason). Dann wird // geschrieben, die Markierung fällt weg, und das Protokoll vermerkt den // Vorgang samt Begründung. Die Nutzungsseite listet solche Einträge, bis // ein Mensch sie wieder als kuratiert markiert. // // # Warum nicht ganz sperren? // // Weil kuratiertes Wissen auch veralten kann. Ein Agent, der nachweislich // sieht, dass ein Server umgezogen ist, soll das festhalten dürfen. Die // Hürde soll Fehlgriffe aufhalten, nicht berechtigte Korrekturen. // // Zwischen Prüfung und Schreiben könnte ein Mensch den Eintrag gerade // kuratieren. Dieses Zeitfenster ist Millisekunden breit; der Verlauf hält // den geprüften Stand in jedem Fall fest. import ( "context" "errors" "strings" "munin/internal/store" "munin/internal/workspace" ) // istKuratiert prüft, ob unter slug ein kuratierter Eintrag liegt. // Gibt es den Eintrag nicht, ist er auch nicht kuratiert. func istKuratiert(ctx context.Context, ws *workspace.Workspace, project store.Project, slug string) (bool, error) { e, err := ws.Store.EntryBySlug(ctx, project.ID, slug) if errors.Is(err, store.ErrNotFound) { return false, nil } if err != nil { return false, err } return e.Curated, nil } // kuratiertHinweis ist die Antwort an den Agenten, wenn er einen kuratierten // Eintrag ohne override_curated ändern will. Sie sagt ausdrücklich, was er // tun soll — wie alle Meldungen an Modelle. const kuratiertHinweis = "Nichts geschrieben: Dieser Eintrag ist kuratiert — ein Mensch hat ihn geprüft. " + "Geprüftes Wissen hat Vorrang vor eigenen Annahmen. Ändere ihn nur, wenn er nachweislich nicht " + "mehr stimmt (etwa weil du gerade das Gegenteil beobachtet hast). Dann denselben Aufruf mit " + "\"override_curated\": true und unter \"reason\" einer kurzen Begründung wiederholen. " + "Die Markierung \"kuratiert\" fällt dabei weg, und ein Mensch prüft die Änderung. " + "Sonst: nichts ändern, oder die Ergänzung in einem eigenen Eintrag festhalten und mit [[slug]] verweisen." // begruendungPruefen stellt sicher, dass ein override_curated eine // Begründung trägt. Ohne sie wüsste der prüfende Mensch nicht, warum der // geprüfte Stand ersetzt wurde. func begruendungPruefen(in rememberInput) error { if in.OverrideCurated && strings.TrimSpace(in.Reason) == "" { return errors.New("override_curated braucht eine Begründung unter \"reason\": " + "Warum stimmt der kuratierte Stand nicht mehr?") } return nil }