Migrate startup paths from SessionBeacon to StartupNudge (gt-7pp3l)

All 12 startup paths now use session.StartupNudge instead of the
older SessionBeacon pattern. The key difference is that StartupNudge
includes sender information, enabling better predecessor discovery
via gt seance.

Files updated:
- crew_lifecycle.go: 3 locations (refresh, restart)
- start.go: 2 locations (crew start)
- deacon.go: 1 location (deacon start)
- witness.go: 1 location (witness start)
- up.go: 4 locations (mayor, witness, crew, polecat)
- mayor.go: 1 location (mayor start)
- session/manager.go: 1 location (polecat spawn)

Format change:
Old: [GAS TOWN] address • molID • timestamp
New: [GAS TOWN] recipient <- sender • timestamp • topic[:mol-id]

This completes the Agent Startup Consolidation epic (gt-85whr).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gastown/crew/gus
2025-12-31 11:52:34 -08:00
committed by Steve Yegge
parent 6f1b6269b1
commit b7c26d52e1
7 changed files with 79 additions and 46 deletions

View File

@@ -197,10 +197,13 @@ func runCrewRefresh(cmd *cobra.Command, args []string) error {
}
time.Sleep(constants.ShutdownNotifyDelay)
// Inject session beacon for predecessor discovery via /resume
// Inject startup nudge for predecessor discovery via /resume
address := fmt.Sprintf("%s/crew/%s", r.Name, name)
beacon := session.SessionBeacon(address, "")
_ = t.NudgeSession(sessionID, beacon) // Non-fatal
_ = session.StartupNudge(t, sessionID, session.StartupNudgeConfig{
Recipient: address,
Sender: "human",
Topic: "refresh",
}) // Non-fatal
fmt.Printf("%s Refreshed crew workspace: %s/%s\n",
style.Bold.Render("✓"), r.Name, name)
@@ -351,12 +354,13 @@ func runCrewRestart(cmd *cobra.Command, args []string) error {
// Give Claude time to initialize after process starts
time.Sleep(constants.ShutdownNotifyDelay)
// Inject session beacon for predecessor discovery via /resume
// Inject startup nudge for predecessor discovery via /resume
address := fmt.Sprintf("%s/crew/%s", r.Name, name)
beacon := session.SessionBeacon(address, "")
if err := t.NudgeSession(sessionID, beacon); err != nil {
// Non-fatal: session works without beacon
}
_ = session.StartupNudge(t, sessionID, session.StartupNudgeConfig{
Recipient: address,
Sender: "human",
Topic: "restart",
}) // Non-fatal: session works without nudge
if err := t.NudgeSession(sessionID, "gt prime"); err != nil {
// Non-fatal: Claude started but priming failed
@@ -523,10 +527,13 @@ func restartCrewSession(rigName, crewName, clonePath string) error {
}
time.Sleep(constants.ShutdownNotifyDelay)
// Inject session beacon for predecessor discovery via /resume
// Inject startup nudge for predecessor discovery via /resume
address := fmt.Sprintf("%s/crew/%s", rigName, crewName)
beacon := session.SessionBeacon(address, "")
_ = t.NudgeSession(sessionID, beacon) // Non-fatal
_ = session.StartupNudge(t, sessionID, session.StartupNudgeConfig{
Recipient: address,
Sender: "human",
Topic: "restart",
}) // Non-fatal
if err := t.NudgeSession(sessionID, "gt prime"); err != nil {
// Non-fatal

View File

@@ -302,9 +302,12 @@ func startDeaconSession(t *tmux.Tmux) error {
}
time.Sleep(constants.ShutdownNotifyDelay)
// Inject session beacon for predecessor discovery via /resume
beacon := session.SessionBeacon("deacon", "patrol")
_ = t.NudgeSession(DeaconSessionName, beacon) // Non-fatal
// Inject startup nudge for predecessor discovery via /resume
_ = session.StartupNudge(t, DeaconSessionName, session.StartupNudgeConfig{
Recipient: "deacon",
Sender: "daemon",
Topic: "patrol",
}) // Non-fatal
return nil
}

View File

@@ -146,9 +146,12 @@ func startMayorSession(t *tmux.Tmux) error {
}
time.Sleep(constants.ShutdownNotifyDelay)
// Inject session beacon for predecessor discovery via /resume
beacon := session.SessionBeacon("mayor", "")
_ = t.NudgeSession(MayorSessionName, beacon) // Non-fatal
// Inject startup nudge for predecessor discovery via /resume
_ = session.StartupNudge(t, MayorSessionName, session.StartupNudgeConfig{
Recipient: "mayor",
Sender: "human",
Topic: "cold-start",
}) // Non-fatal
return nil
}

View File

@@ -799,12 +799,13 @@ func runStartCrew(cmd *cobra.Command, args []string) error {
// Give Claude time to initialize after process starts
time.Sleep(constants.ShutdownNotifyDelay)
// Inject session beacon for predecessor discovery via /resume
// Inject startup nudge for predecessor discovery via /resume
address := fmt.Sprintf("%s/crew/%s", rigName, name)
beacon := session.SessionBeacon(address, "")
if err := t.NudgeSession(sessionID, beacon); err != nil {
// Non-fatal: session works without beacon
}
_ = session.StartupNudge(t, sessionID, session.StartupNudgeConfig{
Recipient: address,
Sender: "human",
Topic: "cold-start",
}) // Non-fatal: session works without nudge
// Send gt prime to initialize context
if err := t.NudgeSession(sessionID, "gt prime"); err != nil {
@@ -940,10 +941,13 @@ func startCrewMember(rigName, crewName, townRoot string) error {
// Give Claude time to initialize
time.Sleep(constants.ShutdownNotifyDelay)
// Inject session beacon for predecessor discovery via /resume
// Inject startup nudge for predecessor discovery via /resume
address := fmt.Sprintf("%s/crew/%s", rigName, crewName)
beacon := session.SessionBeacon(address, "")
_ = t.NudgeSession(sessionID, beacon) // Non-fatal
_ = session.StartupNudge(t, sessionID, session.StartupNudgeConfig{
Recipient: address,
Sender: "human",
Topic: "cold-start",
}) // Non-fatal
// Send gt prime to initialize context (non-fatal: session works without priming)
_ = t.NudgeSession(sessionID, "gt prime")

View File

@@ -283,9 +283,12 @@ func ensureSession(t *tmux.Tmux, sessionName, workDir, role string) error {
}
time.Sleep(constants.ShutdownNotifyDelay)
// Inject session beacon for predecessor discovery via /resume
beacon := session.SessionBeacon(role, "")
_ = t.NudgeSession(sessionName, beacon) // Non-fatal
// Inject startup nudge for predecessor discovery via /resume
_ = session.StartupNudge(t, sessionName, session.StartupNudgeConfig{
Recipient: role,
Sender: "human",
Topic: "cold-start",
}) // Non-fatal
}
return nil
@@ -329,10 +332,13 @@ func ensureWitness(t *tmux.Tmux, sessionName, rigPath, rigName string) error {
}
time.Sleep(constants.ShutdownNotifyDelay)
// Inject session beacon for predecessor discovery via /resume
// Inject startup nudge for predecessor discovery via /resume
address := fmt.Sprintf("%s/witness", rigName)
beacon := session.SessionBeacon(address, "patrol")
_ = t.NudgeSession(sessionName, beacon) // Non-fatal
_ = session.StartupNudge(t, sessionName, session.StartupNudgeConfig{
Recipient: address,
Sender: "deacon",
Topic: "patrol",
}) // Non-fatal
return nil
}
@@ -553,10 +559,13 @@ func ensureCrewSession(t *tmux.Tmux, sessionName, crewPath, rigName, crewName st
}
time.Sleep(constants.ShutdownNotifyDelay)
// Inject session beacon for predecessor discovery via /resume
// Inject startup nudge for predecessor discovery via /resume
address := fmt.Sprintf("%s/crew/%s", rigName, crewName)
beacon := session.SessionBeacon(address, "")
_ = t.NudgeSession(sessionName, beacon) // Non-fatal
_ = session.StartupNudge(t, sessionName, session.StartupNudgeConfig{
Recipient: address,
Sender: "human",
Topic: "cold-start",
}) // Non-fatal
return nil
}
@@ -654,10 +663,13 @@ func ensurePolecatSession(t *tmux.Tmux, sessionName, polecatPath, rigName, polec
}
time.Sleep(constants.ShutdownNotifyDelay)
// Inject session beacon for predecessor discovery via /resume
// Inject startup nudge for predecessor discovery via /resume
address := fmt.Sprintf("%s/polecats/%s", rigName, polecatName)
beacon := session.SessionBeacon(address, "")
_ = t.NudgeSession(sessionName, beacon) // Non-fatal
_ = session.StartupNudge(t, sessionName, session.StartupNudgeConfig{
Recipient: address,
Sender: "witness",
Topic: "dispatch",
}) // Non-fatal
return nil
}

View File

@@ -344,10 +344,13 @@ func ensureWitnessSession(rigName string, r *rig.Rig) (bool, error) {
}
time.Sleep(constants.ShutdownNotifyDelay)
// Inject session beacon for predecessor discovery via /resume
// Inject startup nudge for predecessor discovery via /resume
address := fmt.Sprintf("%s/witness", rigName)
beacon := session.SessionBeacon(address, "patrol")
_ = t.NudgeSession(sessionName, beacon) // Non-fatal
_ = session.StartupNudge(t, sessionName, session.StartupNudgeConfig{
Recipient: address,
Sender: "deacon",
Topic: "patrol",
}) // Non-fatal
return true, nil
}

View File

@@ -197,14 +197,15 @@ func (m *Manager) Start(polecat string, opts StartOptions) error {
// 10 second delay is conservative but reliable.
time.Sleep(10 * time.Second)
// Inject session beacon for predecessor discovery via /resume
// Inject startup nudge for predecessor discovery via /resume
// This becomes the session title in Claude Code's session picker
address := fmt.Sprintf("%s/polecats/%s", m.rig.Name, polecat)
molID := opts.Issue // Use issue ID if provided
beacon := SessionBeacon(address, molID)
if err := m.tmux.NudgeSession(sessionID, beacon); err != nil {
// Non-fatal: session works without beacon
}
_ = StartupNudge(m.tmux, sessionID, StartupNudgeConfig{
Recipient: address,
Sender: "witness",
Topic: "assigned",
MolID: opts.Issue,
}) // Non-fatal: session works without nudge
// GUPP: Gas Town Universal Propulsion Principle
// Send the propulsion nudge to trigger autonomous work execution.