Files
gastown/internal/session/startup.go
T
splendid 2a789c8440 fix(prime): update sling prompts to use gt prime --hook
Polecats weren't getting full role context (including IDLE POLECAT
HERESY guidance) because start prompts said `gt hook` instead of
`gt prime --hook`. The SessionStart hook already runs `gt prime --hook`,
but manual nudge messages were inconsistent.

Changed:
- sling_helpers.go: nudge message now says `gt prime --hook`
- startup.go: assigned beacon now says `gt prime --hook`
- startup_test.go: updated test expectation

Fixes: hq-iqyu9

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 14:16:55 -08:00

100 lines
4.0 KiB
Go

// Package session provides polecat session lifecycle management.
package session
import (
"fmt"
"time"
)
// BeaconConfig configures a startup beacon message.
// The beacon is injected into the CLI prompt to identify sessions in /resume picker.
type BeaconConfig struct {
// Recipient is the address of the agent being nudged.
// Examples: "gastown/crew/gus", "deacon", "gastown/witness"
Recipient string
// Sender is the agent initiating the nudge.
// Examples: "mayor", "deacon", "self" (for handoff)
Sender string
// Topic describes why the session was started.
// Examples: "cold-start", "handoff", "assigned", or a mol-id
Topic string
// MolID is an optional molecule ID being worked.
// If provided, appended to topic as "topic:mol-id"
MolID string
}
// FormatStartupBeacon builds the formatted startup beacon message.
// The beacon is injected into the CLI prompt, making sessions identifiable
// in Claude Code's /resume picker for predecessor discovery.
//
// Format: [GAS TOWN] <recipient> <- <sender> • <timestamp> • <topic[:mol-id]>
//
// Examples:
// - [GAS TOWN] gastown/crew/gus <- deacon • 2025-12-30T15:42 • assigned:gt-abc12
// - [GAS TOWN] deacon <- daemon • 2025-12-30T08:00 • patrol
// - [GAS TOWN] gastown/witness <- deacon • 2025-12-30T14:00 • patrol
func FormatStartupBeacon(cfg BeaconConfig) string {
// Use local time in compact format
timestamp := time.Now().Format("2006-01-02T15:04")
// Build topic string - append mol-id if provided
topic := cfg.Topic
if cfg.MolID != "" && cfg.Topic != "" {
topic = fmt.Sprintf("%s:%s", cfg.Topic, cfg.MolID)
} else if cfg.MolID != "" {
topic = cfg.MolID
} else if topic == "" {
topic = "ready"
}
// Build the beacon: [GAS TOWN] recipient <- sender • timestamp • topic
beacon := fmt.Sprintf("[GAS TOWN] %s <- %s • %s • %s",
cfg.Recipient, cfg.Sender, timestamp, topic)
// For handoff, cold-start, and attach, add explicit instructions so the agent knows
// what to do even if hooks haven't loaded CLAUDE.md yet
if cfg.Topic == "handoff" || cfg.Topic == "cold-start" || cfg.Topic == "attach" {
beacon += "\n\nCheck your hook and mail, then act on the hook if present:\n" +
"1. `gt hook` - shows hooked work (if any)\n" +
"2. `gt mail inbox` - check for messages\n" +
"3. If work is hooked → execute it immediately\n" +
"4. If nothing hooked → wait for instructions"
}
// For assigned, work is already on the hook - just tell them to run it
// This prevents the "helpful assistant" exploration pattern (see PRIMING.md)
// Use `gt prime --hook` instead of `gt hook` so polecats get full role context
// including THE IDLE POLECAT HERESY guidance about running `gt done`.
if cfg.Topic == "assigned" {
beacon += "\n\nWork is on your hook. Run `gt prime --hook` now and begin immediately."
}
// For start/restart, add fallback instructions in case SessionStart hook fails
// to inject context via gt prime. This prevents the "No recent activity" state
// where agents sit idle because they received only metadata, no instructions.
// See: gt-uoc64 (crew workers starting without proper context injection)
if cfg.Topic == "start" || cfg.Topic == "restart" {
beacon += "\n\nRun `gt prime` now for full context, then check your hook and mail."
}
return beacon
}
// BuildStartupPrompt creates the CLI prompt for agent startup.
//
// GUPP (Gas Town Universal Propulsion Principle) implementation:
// - Beacon identifies session for /resume predecessor discovery
// - Instructions tell agent to start working immediately
// - SessionStart hook runs `gt prime` which injects full context including
// "AUTONOMOUS WORK MODE" instructions when work is hooked
//
// This replaces the old two-step StartupNudge + PropulsionNudge pattern.
// The beacon is processed in Claude's first turn along with gt prime context,
// so no separate propulsion nudge is needed.
func BuildStartupPrompt(cfg BeaconConfig, instructions string) string {
return FormatStartupBeacon(cfg) + "\n\n" + instructions
}