Refinery as worktree: local MR integration (gt-4u5z)
Architecture changes: - Refinery created as worktree of mayor clone (shares .git) - Polecat branches stay local (never pushed to origin) - MRs stored as wisps in .beads-wisp/mq/ (ephemeral) - Only main gets pushed to origin after merge New mrqueue package for wisp-based MR storage. Updated spawn, done, mq_submit, refinery, molecule templates. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,12 +3,14 @@ package cmd
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/steveyegge/gastown/internal/beads"
|
||||
"github.com/steveyegge/gastown/internal/git"
|
||||
"github.com/steveyegge/gastown/internal/mail"
|
||||
"github.com/steveyegge/gastown/internal/mrqueue"
|
||||
"github.com/steveyegge/gastown/internal/style"
|
||||
"github.com/steveyegge/gastown/internal/workspace"
|
||||
)
|
||||
@@ -144,41 +146,31 @@ func runDone(cmd *cobra.Command, args []string) error {
|
||||
// Build title
|
||||
title := fmt.Sprintf("Merge: %s", issueID)
|
||||
|
||||
// CRITICAL: Push branch to origin BEFORE creating MR
|
||||
// Without this, the worktree can be deleted and the branch lost forever
|
||||
fmt.Printf("Pushing branch to origin...\n")
|
||||
if err := g.Push("origin", branch, false); err != nil {
|
||||
return fmt.Errorf("pushing branch to origin: %w", err)
|
||||
}
|
||||
fmt.Printf("%s Branch pushed to origin/%s\n", style.Bold.Render("✓"), branch)
|
||||
// Note: Branch stays local. Refinery sees it via shared .git (worktree).
|
||||
// Only main gets pushed to origin after merge.
|
||||
|
||||
// Build description with MR fields
|
||||
mrFields := &beads.MRFields{
|
||||
// Submit to MR queue (wisp storage - ephemeral, not synced)
|
||||
rigPath := filepath.Join(townRoot, rigName)
|
||||
queue := mrqueue.New(rigPath)
|
||||
|
||||
mr := &mrqueue.MR{
|
||||
Branch: branch,
|
||||
Target: target,
|
||||
SourceIssue: issueID,
|
||||
Worker: worker,
|
||||
Rig: rigName,
|
||||
}
|
||||
description := beads.FormatMRFields(mrFields)
|
||||
|
||||
// Create the merge-request issue
|
||||
createOpts := beads.CreateOptions{
|
||||
Title: title,
|
||||
Type: "merge-request",
|
||||
Priority: priority,
|
||||
Description: description,
|
||||
}
|
||||
|
||||
issue, err := bd.Create(createOpts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating merge request: %w", err)
|
||||
if err := queue.Submit(mr); err != nil {
|
||||
return fmt.Errorf("submitting to merge queue: %w", err)
|
||||
}
|
||||
mrID = issue.ID
|
||||
mrID = mr.ID
|
||||
|
||||
// Success output
|
||||
fmt.Printf("%s Work submitted to merge queue\n", style.Bold.Render("✓"))
|
||||
fmt.Printf(" MR ID: %s\n", style.Bold.Render(issue.ID))
|
||||
fmt.Printf(" MR ID: %s\n", style.Bold.Render(mr.ID))
|
||||
fmt.Printf(" Source: %s\n", branch)
|
||||
fmt.Printf(" Target: %s\n", target)
|
||||
fmt.Printf(" Issue: %s\n", issueID)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/steveyegge/gastown/internal/beads"
|
||||
"github.com/steveyegge/gastown/internal/git"
|
||||
"github.com/steveyegge/gastown/internal/mrqueue"
|
||||
"github.com/steveyegge/gastown/internal/style"
|
||||
"github.com/steveyegge/gastown/internal/workspace"
|
||||
)
|
||||
@@ -133,40 +135,30 @@ func runMqSubmit(cmd *cobra.Command, args []string) error {
|
||||
// Build title
|
||||
title := fmt.Sprintf("Merge: %s", issueID)
|
||||
|
||||
// CRITICAL: Push branch to origin BEFORE creating MR
|
||||
// Without this, the worktree can be deleted and the branch lost forever
|
||||
fmt.Printf("Pushing branch to origin...\n")
|
||||
if err := g.Push("origin", branch, false); err != nil {
|
||||
return fmt.Errorf("pushing branch to origin: %w", err)
|
||||
}
|
||||
fmt.Printf("%s Branch pushed to origin/%s\n", style.Bold.Render("✓"), branch)
|
||||
// Note: Branch stays local. Refinery sees it via shared .git (worktree).
|
||||
// Only main gets pushed to origin after merge.
|
||||
|
||||
// Build description with MR fields
|
||||
mrFields := &beads.MRFields{
|
||||
// Submit to MR queue (wisp storage - ephemeral, not synced)
|
||||
rigPath := filepath.Join(townRoot, rigName)
|
||||
queue := mrqueue.New(rigPath)
|
||||
|
||||
mr := &mrqueue.MR{
|
||||
Branch: branch,
|
||||
Target: target,
|
||||
SourceIssue: issueID,
|
||||
Worker: worker,
|
||||
Rig: rigName,
|
||||
}
|
||||
description := beads.FormatMRFields(mrFields)
|
||||
|
||||
// Create the merge-request issue
|
||||
createOpts := beads.CreateOptions{
|
||||
Title: title,
|
||||
Type: "merge-request",
|
||||
Priority: priority,
|
||||
Description: description,
|
||||
}
|
||||
|
||||
issue, err := bd.Create(createOpts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating merge request: %w", err)
|
||||
if err := queue.Submit(mr); err != nil {
|
||||
return fmt.Errorf("submitting to merge queue: %w", err)
|
||||
}
|
||||
|
||||
// Success output
|
||||
fmt.Printf("%s Created merge request\n", style.Bold.Render("✓"))
|
||||
fmt.Printf(" MR ID: %s\n", style.Bold.Render(issue.ID))
|
||||
fmt.Printf("%s Submitted to merge queue\n", style.Bold.Render("✓"))
|
||||
fmt.Printf(" MR ID: %s\n", style.Bold.Render(mr.ID))
|
||||
fmt.Printf(" Source: %s\n", branch)
|
||||
fmt.Printf(" Target: %s\n", target)
|
||||
fmt.Printf(" Issue: %s\n", issueID)
|
||||
|
||||
@@ -608,8 +608,7 @@ func buildSpawnContext(issue *BeadsIssue, message string) string {
|
||||
sb.WriteString("2. Work on your task, commit changes regularly\n")
|
||||
sb.WriteString("3. Run `bd close <issue-id>` when done\n")
|
||||
sb.WriteString("4. Run `bd sync` to push beads changes\n")
|
||||
sb.WriteString("5. Push code: `git push origin HEAD`\n")
|
||||
sb.WriteString("6. Run `gt done` to signal completion\n")
|
||||
sb.WriteString("5. Run `gt done` to signal completion (branch stays local)\n")
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
@@ -673,18 +672,16 @@ func buildWorkAssignmentMail(issue *BeadsIssue, message, polecatAddress string,
|
||||
if moleculeCtx != nil {
|
||||
body.WriteString("4. Check `bd ready --parent " + moleculeCtx.RootIssueID + "` for more steps\n")
|
||||
body.WriteString("5. Repeat steps 2-4 for each ready step\n")
|
||||
body.WriteString("6. When all steps done: run `bd sync`, push code, run `gt done`\n")
|
||||
body.WriteString("6. When all steps done: run `bd sync`, then `gt done`\n")
|
||||
} else {
|
||||
body.WriteString("4. Run `bd sync` to push beads changes\n")
|
||||
body.WriteString("5. Push code: `git push origin HEAD`\n")
|
||||
body.WriteString("6. Run `gt done` to signal completion\n")
|
||||
body.WriteString("5. Run `gt done` to signal completion (branch stays local)\n")
|
||||
}
|
||||
body.WriteString("\n## Handoff Protocol\n")
|
||||
body.WriteString("Before signaling done, ensure:\n")
|
||||
body.WriteString("- Git status is clean (no uncommitted changes)\n")
|
||||
body.WriteString("- Issue is closed with `bd close`\n")
|
||||
body.WriteString("- Beads are synced with `bd sync`\n")
|
||||
body.WriteString("- Code is pushed to origin\n")
|
||||
body.WriteString("\nThe `gt done` command verifies these and signals the Witness.\n")
|
||||
|
||||
return &mail.Message{
|
||||
|
||||
Reference in New Issue
Block a user