gt-975: Molecule execution support for polecats and crew
Added molecule workflow integration to Gas Town: 1. spawn.go: MoleculeContext in work assignment mail - Shows step N/M and molecule ID in subject - Includes molecule workflow instructions - Guides polecat through DAG execution 2. prime.go: outputMoleculeContext() - Detects if in-progress issue is a molecule step - Shows molecule progress and next steps - Displays molecule work loop instructions 3. molecule.go: 'gt molecule progress' command - Shows execution progress for molecule root - Displays done/in-progress/ready/blocked steps - Progress bar and completion percentage - JSON output for Witness automation This enables polecats to work through molecule DAGs: - Receive molecule-aware work assignments - See context in gt prime output - Follow DAG with 'bd ready --parent <root>' - Witness can monitor with 'gt molecule progress' 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -242,6 +242,9 @@ func runSpawn(cmd *cobra.Command, args []string) error {
|
||||
fmt.Printf("%s beads sync: %v\n", style.Dim.Render("Warning:"), err)
|
||||
}
|
||||
|
||||
// Track molecule context for work assignment mail
|
||||
var moleculeCtx *MoleculeContext
|
||||
|
||||
// Handle molecule instantiation if specified
|
||||
if spawnMolecule != "" {
|
||||
b := beads.New(beadsPath)
|
||||
@@ -281,9 +284,11 @@ func runSpawn(cmd *cobra.Command, args []string) error {
|
||||
|
||||
// Find the first ready step (one with no dependencies)
|
||||
var firstReadyStep *beads.Issue
|
||||
for _, step := range steps {
|
||||
var stepNumber int
|
||||
for i, step := range steps {
|
||||
if len(step.DependsOn) == 0 {
|
||||
firstReadyStep = step
|
||||
stepNumber = i + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -292,6 +297,14 @@ func runSpawn(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("no ready step found in molecule (all steps have dependencies)")
|
||||
}
|
||||
|
||||
// Build molecule context for work assignment
|
||||
moleculeCtx = &MoleculeContext{
|
||||
MoleculeID: spawnMolecule,
|
||||
RootIssueID: spawnIssue, // Original issue is the molecule root
|
||||
TotalSteps: len(steps),
|
||||
StepNumber: stepNumber,
|
||||
}
|
||||
|
||||
// Switch to spawning on the first ready step
|
||||
fmt.Printf("\nSpawning on first ready step: %s\n", firstReadyStep.ID)
|
||||
spawnIssue = firstReadyStep.ID
|
||||
@@ -340,7 +353,7 @@ func runSpawn(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
// Send work assignment mail to polecat inbox (before starting session)
|
||||
workMsg := buildWorkAssignmentMail(issue, spawnMessage, polecatAddress)
|
||||
workMsg := buildWorkAssignmentMail(issue, spawnMessage, polecatAddress, moleculeCtx)
|
||||
|
||||
fmt.Printf("Sending work assignment to %s inbox...\n", polecatAddress)
|
||||
if err := router.Send(workMsg); err != nil {
|
||||
@@ -579,14 +592,27 @@ func buildSpawnContext(issue *BeadsIssue, message string) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// MoleculeContext contains information about a molecule workflow assignment.
|
||||
type MoleculeContext struct {
|
||||
MoleculeID string // The molecule template ID
|
||||
RootIssueID string // The parent issue (molecule root)
|
||||
TotalSteps int // Total number of steps in the molecule
|
||||
StepNumber int // Which step this is (1-indexed)
|
||||
}
|
||||
|
||||
// buildWorkAssignmentMail creates a work assignment mail message for a polecat.
|
||||
// This replaces tmux-based context injection with persistent mailbox delivery.
|
||||
func buildWorkAssignmentMail(issue *BeadsIssue, message, polecatAddress string) *mail.Message {
|
||||
// If moleculeCtx is non-nil, includes molecule workflow instructions.
|
||||
func buildWorkAssignmentMail(issue *BeadsIssue, message, polecatAddress string, moleculeCtx *MoleculeContext) *mail.Message {
|
||||
var subject string
|
||||
var body strings.Builder
|
||||
|
||||
if issue != nil {
|
||||
subject = fmt.Sprintf("📋 Work Assignment: %s", issue.Title)
|
||||
if moleculeCtx != nil {
|
||||
subject = fmt.Sprintf("🧬 Molecule Step %d/%d: %s", moleculeCtx.StepNumber, moleculeCtx.TotalSteps, issue.Title)
|
||||
} else {
|
||||
subject = fmt.Sprintf("📋 Work Assignment: %s", issue.Title)
|
||||
}
|
||||
|
||||
body.WriteString(fmt.Sprintf("Issue: %s\n", issue.ID))
|
||||
body.WriteString(fmt.Sprintf("Title: %s\n", issue.Title))
|
||||
@@ -605,14 +631,32 @@ func buildWorkAssignmentMail(issue *BeadsIssue, message, polecatAddress string)
|
||||
body.WriteString(fmt.Sprintf("Task: %s\n", message))
|
||||
}
|
||||
|
||||
// Add molecule context if present
|
||||
if moleculeCtx != nil {
|
||||
body.WriteString("\n## Molecule Workflow\n")
|
||||
body.WriteString(fmt.Sprintf("You are working on step %d of %d in molecule %s.\n", moleculeCtx.StepNumber, moleculeCtx.TotalSteps, moleculeCtx.MoleculeID))
|
||||
body.WriteString(fmt.Sprintf("Root issue: %s\n\n", moleculeCtx.RootIssueID))
|
||||
body.WriteString("**IMPORTANT**: This is part of a molecule workflow. After completing this step:\n")
|
||||
body.WriteString("1. Run `bd close " + issue.ID + "`\n")
|
||||
body.WriteString("2. Run `bd ready --parent " + moleculeCtx.RootIssueID + "` to find next ready steps\n")
|
||||
body.WriteString("3. If more steps are ready, continue working on them\n")
|
||||
body.WriteString("4. When all steps are done, run `gt done` to signal completion\n\n")
|
||||
}
|
||||
|
||||
body.WriteString("\n## Workflow\n")
|
||||
body.WriteString("1. Run `gt prime` to load polecat context\n")
|
||||
body.WriteString("2. Run `bd sync --from-main` to get fresh beads\n")
|
||||
body.WriteString("3. Work on your task, commit changes regularly\n")
|
||||
body.WriteString("4. Run `bd close <issue-id>` when done\n")
|
||||
body.WriteString("5. Run `bd sync` to push beads changes\n")
|
||||
body.WriteString("6. Push code: `git push origin HEAD`\n")
|
||||
body.WriteString("7. Run `gt done` to signal completion\n")
|
||||
if moleculeCtx != nil {
|
||||
body.WriteString("5. Check `bd ready --parent " + moleculeCtx.RootIssueID + "` for more steps\n")
|
||||
body.WriteString("6. Repeat steps 3-5 for each ready step\n")
|
||||
body.WriteString("7. When all steps done: run `bd sync`, push code, run `gt done`\n")
|
||||
} else {
|
||||
body.WriteString("5. Run `bd sync` to push beads changes\n")
|
||||
body.WriteString("6. Push code: `git push origin HEAD`\n")
|
||||
body.WriteString("7. Run `gt done` to signal completion\n")
|
||||
}
|
||||
body.WriteString("\n## Handoff Protocol\n")
|
||||
body.WriteString("Before signaling done, ensure:\n")
|
||||
body.WriteString("- Git status is clean (no uncommitted changes)\n")
|
||||
|
||||
Reference in New Issue
Block a user