72 lines
3.1 KiB
Go
72 lines
3.1 KiB
Go
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
|
|
}
|