fix(done,mayor): push branch before MR creation, restart runtime on attach
done.go: Push branch to origin BEFORE creating MR bead (hq-6dk53, hq-a4ksk) - The MR bead triggers Refinery to process the branch - If branch isnt pushed, Refinery finds nothing to merge - The worktree gets nuked at end of gt done, losing commits forever - This is why polecats kept submitting MRs with empty branches mayor.go: Restart runtime with context when attaching (hq-95xfq) - When runtime has exited, gt may at now respawns with startup beacon - Previously, attaching to dead session left agent with no context - Now matches gt handoff behavior: hook check, inbox check, full prime Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -264,6 +264,16 @@ func runDone(cmd *cobra.Command, args []string) error {
|
|||||||
return fmt.Errorf("branch '%s' has 0 commits ahead of %s; nothing to merge\nMake and commit changes first, or use --status DEFERRED to exit without completing", branch, originDefault)
|
return fmt.Errorf("branch '%s' has 0 commits ahead of %s; nothing to merge\nMake and commit changes first, or use --status DEFERRED to exit without completing", branch, originDefault)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CRITICAL: Push branch BEFORE creating MR bead (hq-6dk53, hq-a4ksk)
|
||||||
|
// The MR bead triggers Refinery to process this branch. If the branch
|
||||||
|
// isn't pushed yet, Refinery finds nothing to merge. The worktree gets
|
||||||
|
// nuked at the end of gt done, so the commits are lost forever.
|
||||||
|
fmt.Printf("Pushing branch to remote...\n")
|
||||||
|
if err := g.Push("origin", branch, false); err != nil {
|
||||||
|
return fmt.Errorf("pushing branch '%s' to origin: %w\nCommits exist locally but failed to push. Fix the issue and retry.", branch, err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s Branch pushed to origin\n", style.Bold.Render("✓"))
|
||||||
|
|
||||||
if issueID == "" {
|
if issueID == "" {
|
||||||
return fmt.Errorf("cannot determine source issue from branch '%s'; use --issue to specify", branch)
|
return fmt.Errorf("cannot determine source issue from branch '%s'; use --issue to specify", branch)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/steveyegge/gastown/internal/config"
|
||||||
"github.com/steveyegge/gastown/internal/mayor"
|
"github.com/steveyegge/gastown/internal/mayor"
|
||||||
|
"github.com/steveyegge/gastown/internal/session"
|
||||||
"github.com/steveyegge/gastown/internal/style"
|
"github.com/steveyegge/gastown/internal/style"
|
||||||
|
"github.com/steveyegge/gastown/internal/tmux"
|
||||||
"github.com/steveyegge/gastown/internal/workspace"
|
"github.com/steveyegge/gastown/internal/workspace"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -142,6 +145,14 @@ func runMayorAttach(cmd *cobra.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
townRoot, err := workspace.FindFromCwdOrError()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("finding workspace: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t := tmux.NewTmux()
|
||||||
|
sessionID := mgr.SessionName()
|
||||||
|
|
||||||
running, err := mgr.IsRunning()
|
running, err := mgr.IsRunning()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("checking session: %w", err)
|
return fmt.Errorf("checking session: %w", err)
|
||||||
@@ -152,10 +163,45 @@ func runMayorAttach(cmd *cobra.Command, args []string) error {
|
|||||||
if err := mgr.Start(mayorAgentOverride); err != nil {
|
if err := mgr.Start(mayorAgentOverride); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Session exists - check if runtime is still running (hq-95xfq)
|
||||||
|
// If runtime exited or sitting at shell, restart with proper context
|
||||||
|
agentCfg, _, err := config.ResolveAgentConfigWithOverride(townRoot, townRoot, mayorAgentOverride)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("resolving agent: %w", err)
|
||||||
|
}
|
||||||
|
if !t.IsAgentRunning(sessionID, config.ExpectedPaneCommands(agentCfg)...) {
|
||||||
|
// Runtime has exited, restart it with proper context
|
||||||
|
fmt.Println("Runtime exited, restarting with context...")
|
||||||
|
|
||||||
|
paneID, err := t.GetPaneID(sessionID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting pane ID: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build startup beacon for context (like gt handoff does)
|
||||||
|
beacon := session.FormatStartupNudge(session.StartupNudgeConfig{
|
||||||
|
Recipient: "mayor",
|
||||||
|
Sender: "human",
|
||||||
|
Topic: "attach",
|
||||||
|
})
|
||||||
|
|
||||||
|
// Build startup command with beacon
|
||||||
|
startupCmd, err := config.BuildAgentStartupCommandWithAgentOverride("mayor", "mayor", "", beacon, mayorAgentOverride)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("building startup command: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := t.RespawnPane(paneID, startupCmd); err != nil {
|
||||||
|
return fmt.Errorf("restarting runtime: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%s Mayor restarted with context\n", style.Bold.Render("✓"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use shared attach helper (smart: links if inside tmux, attaches if outside)
|
// Use shared attach helper (smart: links if inside tmux, attaches if outside)
|
||||||
return attachToTmuxSession(mgr.SessionName())
|
return attachToTmuxSession(sessionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runMayorStatus(cmd *cobra.Command, args []string) error {
|
func runMayorStatus(cmd *cobra.Command, args []string) error {
|
||||||
|
|||||||
Reference in New Issue
Block a user