voice

import "github.com/jbcom/radioactive-ralph/internal/voice"

Package voice renders Ralph’s personality for each variant.

Every user-facing emission from the repo service — pre-flight questions, startup banners, status lines, attach-stream event renderings, shutdown messages, spend-cap notifications — gets voiced through this package. The same fact emits different copy per variant so the operator experiences the distinct personalities documented in docs/variants/.

Today the package ships a complete fallback library plus custom templates for green (the classic) and blue (the observer). Variants without bespoke voice copy currently fall back to the generic event templates.

Design: templates are plain Go string/template-literal pairs rather than text/template. We deliberately don’t use text/template — the interpolation surface is narrow (pr number, repo slug, count, reason, branch, usd) and the control-flow features of text/template are a foot-gun when operators can tweak voice via config.toml later.

Index

func Register

func Register(variant Variant, event Event, template string)

Register adds or replaces a template for one variant + event. Called by the variant package at init time; tests can also use it to override specific templates and inspect the output.

func RegisterFallback

func RegisterFallback(event Event, template string)

RegisterFallback sets the default template used when a variant lacks a specific event template.

func ResetForTesting

func ResetForTesting()

ResetForTesting clears the registry and re-registers the built-in variants. Tests that mutate the registry call this in a t.Cleanup to avoid bleeding state between tests.

func Say

func Say(variant Variant, event Event, f Fields) string

Say returns Ralph’s voiced message for a given variant + event. Falls back to the default template if the variant hasn’t registered one; falls back to a canonical event name if no template exists at all. Never panics.

type Event

Event is the kind-of-emission key. Small, documented set.

type Event string

Canonical events the runtime voices. Adding new events requires adding templates (or accepting fallbacks) for every variant you care about.

const (
    EventStartup        Event = "startup"
    EventShutdown       Event = "shutdown"
    EventCycleStart     Event = "cycle.start"
    EventCycleEnd       Event = "cycle.end"
    EventSessionSpawn   Event = "session.spawn"
    EventSessionDeath   Event = "session.death"
    EventSessionResume  Event = "session.resume"
    EventTaskClaim      Event = "task.claim"
    EventTaskDone       Event = "task.done"
    EventPRMerge        Event = "pr.merge"
    EventPRMergeFailed  Event = "pr.merge.failed"
    EventReviewApproved Event = "review.approved"
    EventReviewChanges  Event = "review.changes"
    EventSpendCapHit    Event = "spend.cap"
    EventGateRefusal    Event = "gate.refusal"
)

type Fields

Fields are the values substituted into templates. Only the subset relevant to the event is consulted — renderers gracefully tolerate zero values.

type Fields struct {
    Repo     string
    Branch   string
    PRNumber int
    TaskID   string
    Count    int    // severity count, cycle number, etc.
    Reason   string // exit reason, refusal reason, etc.
    USD      string // pre-formatted spend string (e.g. "$42.50")
    Extra    string // catch-all when one more string is needed
}

type Variant

Variant is an identifier matching the variant profile. It stays in this package so voice rendering can remain decoupled from the variant package’s runtime profile types.

type Variant string

Canonical variant names. Kept in sync with the variant registry and the operator-facing docs/variants pages.

const (
    VariantGreen        Variant = "green"
    VariantGrey         Variant = "grey"
    VariantRed          Variant = "red"
    VariantBlue         Variant = "blue"
    VariantProfessor    Variant = "professor"
    VariantFixit        Variant = "fixit"
    VariantImmortal     Variant = "immortal"
    VariantSavage       Variant = "savage"
    VariantOldMan       Variant = "old-man"
    VariantWorldBreaker Variant = "world-breaker"
)

Generated by gomarkdoc