refactor: move mol run semantics from bd into gt spawn (gt-r7jj2)

Replace bd mol run call with separate bd commands:
1. bd pour - creates issues from proto template
2. bd update --status=in_progress - claims work
3. bd pin - pins root for session recovery

This moves orchestration logic into gt (where it belongs) and keeps
bd as pure data operations. Coordinated with bd-00u3 which deprecates
bd mol run.

🤖 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-25 01:05:06 -08:00
parent ac3371f9ae
commit e8db866ddb

View File

@@ -259,54 +259,68 @@ func runSpawn(cmd *cobra.Command, args []string) error {
// Handle molecule instantiation if specified
if spawnMolecule != "" {
// Use bd mol run to create the molecule - this handles everything:
// - Creates child issues from proto template
// - Assigns root to polecat
// - Sets root status to in_progress
// - Pins root for session recovery
// Molecule instantiation uses three separate bd commands:
// 1. bd pour - creates issues from proto template
// 2. bd update - sets status to in_progress (claims work)
// 3. bd pin - pins root for session recovery
// This keeps bd as pure data operations and gt as orchestration.
fmt.Printf("Running molecule %s on %s...\n", spawnMolecule, spawnIssue)
cmd := exec.Command("bd", "--no-daemon", "mol", "run", spawnMolecule,
// Step 1: Pour the molecule (create issues from template)
pourCmd := exec.Command("bd", "--no-daemon", "pour", spawnMolecule,
"--var", "issue="+spawnIssue, "--json")
cmd.Dir = beadsPath
pourCmd.Dir = beadsPath
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
var pourStdout, pourStderr bytes.Buffer
pourCmd.Stdout = &pourStdout
pourCmd.Stderr = &pourStderr
if err := cmd.Run(); err != nil {
errMsg := strings.TrimSpace(stderr.String())
if err := pourCmd.Run(); err != nil {
errMsg := strings.TrimSpace(pourStderr.String())
if errMsg != "" {
return fmt.Errorf("running molecule: %s", errMsg)
return fmt.Errorf("pouring molecule: %s", errMsg)
}
return fmt.Errorf("running molecule: %w", err)
return fmt.Errorf("pouring molecule: %w", err)
}
// Parse mol run output
var molResult struct {
RootID string `json:"root_id"`
// Parse pour output to get root ID
var pourResult struct {
NewEpicID string `json:"new_epic_id"`
IDMapping map[string]string `json:"id_mapping"`
Created int `json:"created"`
Assignee string `json:"assignee"`
Pinned bool `json:"pinned"`
}
if err := json.Unmarshal(stdout.Bytes(), &molResult); err != nil {
return fmt.Errorf("parsing molecule result: %w", err)
if err := json.Unmarshal(pourStdout.Bytes(), &pourResult); err != nil {
return fmt.Errorf("parsing pour result: %w", err)
}
fmt.Printf("%s Molecule created: %s (%d steps)\n",
style.Bold.Render("✓"), molResult.RootID, molResult.Created-1) // -1 for root
rootID := pourResult.NewEpicID
fmt.Printf("%s Molecule poured: %s (%d steps)\n",
style.Bold.Render("✓"), rootID, pourResult.Created-1) // -1 for root
// Step 2: Set status to in_progress (claim work)
updateCmd := exec.Command("bd", "--no-daemon", "update", rootID, "--status=in_progress")
updateCmd.Dir = beadsPath
if err := updateCmd.Run(); err != nil {
return fmt.Errorf("setting molecule status: %w", err)
}
// Step 3: Pin the root for session recovery
pinCmd := exec.Command("bd", "--no-daemon", "pin", rootID)
pinCmd.Dir = beadsPath
if err := pinCmd.Run(); err != nil {
return fmt.Errorf("pinning molecule: %w", err)
}
// Build molecule context for work assignment
moleculeCtx = &MoleculeContext{
MoleculeID: spawnMolecule,
RootIssueID: molResult.RootID,
TotalSteps: molResult.Created - 1, // -1 for root
StepNumber: 1, // Starting on first step
RootIssueID: rootID,
TotalSteps: pourResult.Created - 1, // -1 for root
StepNumber: 1, // Starting on first step
}
// Update spawnIssue to be the molecule root (for assignment tracking)
spawnIssue = molResult.RootID
spawnIssue = rootID
}
// Get or create issue