// Package templates provides embedded templates for role contexts and messages. package templates import ( "bytes" "embed" "fmt" "text/template" ) //go:embed roles/*.md.tmpl messages/*.md.tmpl var templateFS embed.FS // Templates manages role and message templates. type Templates struct { roleTemplates *template.Template messageTemplates *template.Template } // RoleData contains information for rendering role contexts. type RoleData struct { Role string // mayor, witness, refinery, polecat, crew, deacon RigName string // e.g., "gastown" TownRoot string // e.g., "/Users/steve/ai" WorkDir string // current working directory Polecat string // polecat name (for polecat role) Polecats []string // list of polecats (for witness role) BeadsDir string // BEADS_DIR path IssuePrefix string // beads issue prefix } // SpawnData contains information for spawn assignment messages. type SpawnData struct { Issue string Title string Priority int Description string Branch string RigName string Polecat string } // NudgeData contains information for nudge messages. type NudgeData struct { Polecat string Reason string NudgeCount int MaxNudges int Issue string Status string } // EscalationData contains information for escalation messages. type EscalationData struct { Polecat string Issue string Reason string NudgeCount int LastStatus string Suggestions []string } // HandoffData contains information for session handoff messages. type HandoffData struct { Role string CurrentWork string Status string NextSteps []string Notes string PendingMail int GitBranch string GitDirty bool } // New creates a new Templates instance. func New() (*Templates, error) { t := &Templates{} // Parse role templates roleTempl, err := template.ParseFS(templateFS, "roles/*.md.tmpl") if err != nil { return nil, fmt.Errorf("parsing role templates: %w", err) } t.roleTemplates = roleTempl // Parse message templates msgTempl, err := template.ParseFS(templateFS, "messages/*.md.tmpl") if err != nil { return nil, fmt.Errorf("parsing message templates: %w", err) } t.messageTemplates = msgTempl return t, nil } // RenderRole renders a role context template. func (t *Templates) RenderRole(role string, data RoleData) (string, error) { templateName := role + ".md.tmpl" var buf bytes.Buffer if err := t.roleTemplates.ExecuteTemplate(&buf, templateName, data); err != nil { return "", fmt.Errorf("rendering role template %s: %w", templateName, err) } return buf.String(), nil } // RenderMessage renders a message template. func (t *Templates) RenderMessage(name string, data interface{}) (string, error) { templateName := name + ".md.tmpl" var buf bytes.Buffer if err := t.messageTemplates.ExecuteTemplate(&buf, templateName, data); err != nil { return "", fmt.Errorf("rendering message template %s: %w", templateName, err) } return buf.String(), nil } // RoleNames returns the list of available role templates. func (t *Templates) RoleNames() []string { return []string{"mayor", "witness", "refinery", "polecat", "crew", "deacon"} } // MessageNames returns the list of available message templates. func (t *Templates) MessageNames() []string { return []string{"spawn", "nudge", "escalation", "handoff"} }