Files
gastown/internal/runtime/runtime.go
rictus 66f6e37844 docs: add godoc for isAutonomousRole explaining autonomous roles
Explains that autonomous roles (polecat, witness, refinery, deacon)
get automatic mail injection on startup since they operate without
human prompting. Non-autonomous roles (mayor, crew) skip this.

Closes: gt-pawy3
2026-01-11 21:44:30 -05:00

102 lines
2.8 KiB
Go

// Package runtime provides helpers for runtime-specific integration.
package runtime
import (
"os"
"strings"
"time"
"github.com/steveyegge/gastown/internal/claude"
"github.com/steveyegge/gastown/internal/config"
"github.com/steveyegge/gastown/internal/opencode"
"github.com/steveyegge/gastown/internal/tmux"
)
// EnsureSettingsForRole installs runtime hook settings when supported.
func EnsureSettingsForRole(workDir, role string, rc *config.RuntimeConfig) error {
if rc == nil {
rc = config.DefaultRuntimeConfig()
}
if rc.Hooks == nil {
return nil
}
switch rc.Hooks.Provider {
case "claude":
return claude.EnsureSettingsForRoleAt(workDir, role, rc.Hooks.Dir, rc.Hooks.SettingsFile)
case "opencode":
return opencode.EnsurePluginAt(workDir, rc.Hooks.Dir, rc.Hooks.SettingsFile)
default:
return nil
}
}
// SessionIDFromEnv returns the runtime session ID, if present.
// It checks GT_SESSION_ID_ENV first, then falls back to CLAUDE_SESSION_ID.
func SessionIDFromEnv() string {
if envName := os.Getenv("GT_SESSION_ID_ENV"); envName != "" {
if sessionID := os.Getenv(envName); sessionID != "" {
return sessionID
}
}
return os.Getenv("CLAUDE_SESSION_ID")
}
// SleepForReadyDelay sleeps for the runtime's configured readiness delay.
func SleepForReadyDelay(rc *config.RuntimeConfig) {
if rc == nil || rc.Tmux == nil {
return
}
if rc.Tmux.ReadyDelayMs <= 0 {
return
}
time.Sleep(time.Duration(rc.Tmux.ReadyDelayMs) * time.Millisecond)
}
// StartupFallbackCommands returns commands that approximate Claude hooks when hooks are unavailable.
func StartupFallbackCommands(role string, rc *config.RuntimeConfig) []string {
if rc == nil {
rc = config.DefaultRuntimeConfig()
}
if rc.Hooks != nil && rc.Hooks.Provider != "" && rc.Hooks.Provider != "none" {
return nil
}
role = strings.ToLower(role)
command := "gt prime"
if isAutonomousRole(role) {
command += " && gt mail check --inject"
}
command += " && gt nudge deacon session-started"
return []string{command}
}
// RunStartupFallback sends the startup fallback commands via tmux.
func RunStartupFallback(t *tmux.Tmux, sessionID, role string, rc *config.RuntimeConfig) error {
commands := StartupFallbackCommands(role, rc)
for _, cmd := range commands {
if err := t.NudgeSession(sessionID, cmd); err != nil {
return err
}
}
return nil
}
// isAutonomousRole returns true if the given role should automatically
// inject mail check on startup. Autonomous roles (polecat, witness,
// refinery, deacon) operate without human prompting and need mail injection
// to receive work assignments.
//
// Non-autonomous roles (mayor, crew) are human-guided and should not
// have automatic mail injection to avoid confusion.
func isAutonomousRole(role string) bool {
switch role {
case "polecat", "witness", "refinery", "deacon":
return true
default:
return false
}
}