adventure: author Pete's dispatches in his voice with the local LLM

emitFact now runs the final fact through authorDispatch, which asks the local
Ollama model for a warm-reporter headline and lede and ships them on the Fact.
Pete guards and publishes them, falling back to its own templates on anything
it rejects — so authoring is best-effort by design: LLM off, a timeout, a
malformed generation, or an over-length pair all return an empty prose pair and
Pete templates the fact. The names allowed in the prose are the fact's Actors,
built from the post-opt-out subject/opponent, so what the model may say and what
Pete's guard permits are the same list. Synchronous like the holdem tip rewrite,
but on a tight 15s budget: news facts are infrequent and a template now beats a
voiced dispatch late. With no route for Pete to call back into this box, the
voice lives in the prompt here rather than in a Pete-owned inference endpoint.
This commit is contained in:
prosolis
2026-07-17 09:28:13 -07:00
parent fbed45fc96
commit 22b7949791
4 changed files with 295 additions and 0 deletions

View File

@@ -48,6 +48,13 @@ type Fact struct {
Milestone string `json:"milestone,omitempty"`
OccurredAt int64 `json:"occurred_at"`
NoPush bool `json:"no_push,omitempty"` // backfill: suppress Pete web-push
// Headline/Lede are LLM-authored prose for this fact, both optional. Pete
// prefers them over its own template when present and past its prose-guard,
// and falls back to the template otherwise — so an empty pair (LLM off, or
// authoring failed) is the normal, safe case. Populated by emitFact; see
// authorDispatch. Names in the prose must come only from Actors.
Headline string `json:"headline,omitempty"`
Lede string `json:"lede,omitempty"`
}
// Config controls the seam. Enabled=false makes Emit a durable no-op (nothing