Add AgentIdentity type for session name parsing (gt-ov2uv)

Create AgentIdentity type to parse and construct session names, replacing
duplicated logic in sling.go and handoff.go.

- Add internal/session/identity.go with AgentIdentity type
- ParseSessionName handles: mayor, deacon, witness, refinery, crew, polecat
- SessionName() reconstructs valid tmux session name
- Address() returns mail-style address (e.g., "gastown/crew/max")
- GTRole() returns GT_ROLE env var format
- Update sling.go:sessionToAgentID to use ParseSessionName
- Update handoff.go:sessionToGTRole to use ParseSessionName
- Add comprehensive unit tests with round-trip verification

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-28 16:23:15 -08:00
parent 6a5d7cb3ec
commit fa79d06d0e
4 changed files with 409 additions and 50 deletions

View File

@@ -8,6 +8,7 @@ import (
"strings"
"github.com/spf13/cobra"
"github.com/steveyegge/gastown/internal/session"
"github.com/steveyegge/gastown/internal/style"
"github.com/steveyegge/gastown/internal/tmux"
"github.com/steveyegge/gastown/internal/workspace"
@@ -371,34 +372,13 @@ func sessionWorkDir(sessionName, townRoot string) (string, error) {
}
// sessionToGTRole converts a session name to a GT_ROLE value.
// Uses session.ParseSessionName for consistent parsing across the codebase.
func sessionToGTRole(sessionName string) string {
switch {
case sessionName == "gt-mayor":
return "mayor"
case sessionName == "gt-deacon":
return "deacon"
case strings.Contains(sessionName, "-crew-"):
// gt-<rig>-crew-<name> -> <rig>/crew/<name>
parts := strings.Split(sessionName, "-")
for i, p := range parts {
if p == "crew" && i > 1 && i < len(parts)-1 {
rig := strings.Join(parts[1:i], "-")
name := strings.Join(parts[i+1:], "-")
return fmt.Sprintf("%s/crew/%s", rig, name)
}
}
return ""
case strings.HasSuffix(sessionName, "-witness"):
rig := strings.TrimPrefix(sessionName, "gt-")
rig = strings.TrimSuffix(rig, "-witness")
return fmt.Sprintf("%s/witness", rig)
case strings.HasSuffix(sessionName, "-refinery"):
rig := strings.TrimPrefix(sessionName, "gt-")
rig = strings.TrimSuffix(rig, "-refinery")
return fmt.Sprintf("%s/refinery", rig)
default:
identity, err := session.ParseSessionName(sessionName)
if err != nil {
return ""
}
return identity.GTRole()
}
// detectTownRootFromCwd walks up from the current directory to find the town root.