diff --git a/internal/cmd/molecule.go b/internal/cmd/molecule.go index a456aa22..95b46410 100644 --- a/internal/cmd/molecule.go +++ b/internal/cmd/molecule.go @@ -55,16 +55,20 @@ Example: } var moleculeAttachCmd = &cobra.Command{ - Use: "attach ", + Use: "attach [pinned-bead-id] ", Short: "Attach a molecule to a pinned bead", Long: `Attach a molecule to a pinned/handoff bead. This records which molecule an agent is currently working on. The attachment is stored in the pinned bead's description and visible via 'bd show'. -Example: - gt molecule attach gt-abc mol-xyz`, - Args: cobra.ExactArgs(2), +When called with a single argument from an agent working directory, the +pinned bead ID is auto-detected from the current agent's hook. + +Examples: + gt molecule attach gt-abc mol-xyz # Explicit pinned bead + gt molecule attach mol-xyz # Auto-detect from cwd`, + Args: cobra.RangeArgs(1, 2), RunE: runMoleculeAttach, } diff --git a/internal/cmd/molecule_attach.go b/internal/cmd/molecule_attach.go index b6eaffef..80ca7455 100644 --- a/internal/cmd/molecule_attach.go +++ b/internal/cmd/molecule_attach.go @@ -12,8 +12,24 @@ import ( ) func runMoleculeAttach(cmd *cobra.Command, args []string) error { - pinnedBeadID := args[0] - moleculeID := args[1] + var pinnedBeadID, moleculeID string + + if len(args) == 2 { + // Explicit: gt mol attach + pinnedBeadID = args[0] + moleculeID = args[1] + } else { + // Auto-detect: gt mol attach + moleculeID = args[0] + var err error + pinnedBeadID, err = detectAgentBeadID() + if err != nil { + return fmt.Errorf("auto-detecting agent: %w", err) + } + if pinnedBeadID == "" { + return fmt.Errorf("could not detect agent from current directory - provide explicit pinned bead ID") + } + } workDir, err := findLocalBeadsDir() if err != nil { @@ -37,6 +53,48 @@ func runMoleculeAttach(cmd *cobra.Command, args []string) error { return nil } +// detectAgentBeadID detects the current agent's bead ID from the working directory. +// Returns the agent bead ID (e.g., "gt-mayor", "gt-gastown-polecat-nux") or empty string if not detectable. +func detectAgentBeadID() (string, error) { + cwd, err := os.Getwd() + if err != nil { + return "", fmt.Errorf("getting current directory: %w", err) + } + + townRoot, err := workspace.FindFromCwd() + if err != nil { + return "", fmt.Errorf("finding workspace: %w", err) + } + if townRoot == "" { + return "", fmt.Errorf("not in a Gas Town workspace") + } + + roleInfo, err := GetRoleWithContext(cwd, townRoot) + if err != nil { + return "", fmt.Errorf("detecting role: %w", err) + } + + roleCtx := RoleContext{ + Role: roleInfo.Role, + Rig: roleInfo.Rig, + Polecat: roleInfo.Polecat, + TownRoot: townRoot, + WorkDir: cwd, + } + + identity := buildAgentIdentity(roleCtx) + if identity == "" { + return "", fmt.Errorf("cannot determine agent identity (role: %s)", roleCtx.Role) + } + + beadID := buildAgentBeadID(identity, roleCtx.Role) + if beadID == "" { + return "", fmt.Errorf("cannot build agent bead ID for identity: %s", identity) + } + + return beadID, nil +} + func runMoleculeDetach(cmd *cobra.Command, args []string) error { pinnedBeadID := args[0]