Merge remote-tracking branch 'origin/polecat/polecat-01'
This commit is contained in:
@@ -16,6 +16,7 @@ func BuiltinMolecules() []BuiltinMolecule {
|
|||||||
ResearchMolecule(),
|
ResearchMolecule(),
|
||||||
InstallGoBinaryMolecule(),
|
InstallGoBinaryMolecule(),
|
||||||
BootstrapGasTownMolecule(),
|
BootstrapGasTownMolecule(),
|
||||||
|
PolecatWorkMolecule(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,6 +300,97 @@ Needs: sync-beads, install-paths`,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PolecatWorkMolecule returns the polecat-work molecule definition.
|
||||||
|
// This is the full polecat lifecycle from assignment to decommission.
|
||||||
|
// It's an operational molecule that enables crash recovery and context survival.
|
||||||
|
func PolecatWorkMolecule() BuiltinMolecule {
|
||||||
|
return BuiltinMolecule{
|
||||||
|
ID: "mol-polecat-work",
|
||||||
|
Title: "Polecat Work",
|
||||||
|
Description: `Full polecat lifecycle from assignment to decommission.
|
||||||
|
|
||||||
|
This molecule enables nondeterministic idempotence for polecat work.
|
||||||
|
A polecat that crashes after any step can restart, read its molecule state,
|
||||||
|
and continue from the last completed step. No work is lost.
|
||||||
|
|
||||||
|
## Step: load-context
|
||||||
|
Run gt prime and bd prime. Verify issue assignment.
|
||||||
|
Check inbox for any relevant messages.
|
||||||
|
|
||||||
|
Read the assigned issue and understand the requirements.
|
||||||
|
Identify any blockers or missing information.
|
||||||
|
|
||||||
|
## Step: implement
|
||||||
|
Implement the solution. Follow codebase conventions.
|
||||||
|
File discovered work as new issues with bd create.
|
||||||
|
|
||||||
|
Make regular commits with clear messages.
|
||||||
|
Keep changes focused on the assigned issue.
|
||||||
|
Needs: load-context
|
||||||
|
|
||||||
|
## Step: self-review
|
||||||
|
Review your own changes. Look for:
|
||||||
|
- Bugs and edge cases
|
||||||
|
- Style issues
|
||||||
|
- Missing error handling
|
||||||
|
- Security concerns
|
||||||
|
|
||||||
|
Fix any issues found before proceeding.
|
||||||
|
Needs: implement
|
||||||
|
|
||||||
|
## Step: verify-tests
|
||||||
|
Run existing tests. Add new tests for new functionality.
|
||||||
|
Ensure adequate coverage.
|
||||||
|
|
||||||
|
` + "```" + `bash
|
||||||
|
go test ./...
|
||||||
|
` + "```" + `
|
||||||
|
|
||||||
|
Fix any test failures before proceeding.
|
||||||
|
Needs: implement
|
||||||
|
|
||||||
|
## Step: rebase-main
|
||||||
|
Rebase against main to incorporate any changes.
|
||||||
|
Resolve conflicts if needed.
|
||||||
|
|
||||||
|
` + "```" + `bash
|
||||||
|
git fetch origin main
|
||||||
|
git rebase origin/main
|
||||||
|
` + "```" + `
|
||||||
|
|
||||||
|
If there are conflicts, resolve them carefully and
|
||||||
|
continue the rebase.
|
||||||
|
Needs: self-review, verify-tests
|
||||||
|
|
||||||
|
## Step: submit-merge
|
||||||
|
Submit to merge queue. Create PR if needed.
|
||||||
|
Verify CI passes.
|
||||||
|
|
||||||
|
` + "```" + `bash
|
||||||
|
gt done # Signal work ready for merge queue
|
||||||
|
` + "```" + `
|
||||||
|
|
||||||
|
If there are CI failures, fix them before proceeding.
|
||||||
|
Needs: rebase-main
|
||||||
|
|
||||||
|
## Step: update-handoff
|
||||||
|
Update handoff bead with final state.
|
||||||
|
File any remaining work as issues.
|
||||||
|
|
||||||
|
Document any important context for the next session
|
||||||
|
or for anyone reviewing the work.
|
||||||
|
Needs: submit-merge
|
||||||
|
|
||||||
|
## Step: request-shutdown
|
||||||
|
Send shutdown request to Witness.
|
||||||
|
Wait for termination.
|
||||||
|
|
||||||
|
The polecat is now ready to be cleaned up.
|
||||||
|
Do not exit directly - wait for Witness to kill the session.
|
||||||
|
Needs: update-handoff`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SeedBuiltinMolecules creates all built-in molecules in the beads database.
|
// SeedBuiltinMolecules creates all built-in molecules in the beads database.
|
||||||
// It skips molecules that already exist (by title match).
|
// It skips molecules that already exist (by title match).
|
||||||
// Returns the number of molecules created.
|
// Returns the number of molecules created.
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import "testing"
|
|||||||
func TestBuiltinMolecules(t *testing.T) {
|
func TestBuiltinMolecules(t *testing.T) {
|
||||||
molecules := BuiltinMolecules()
|
molecules := BuiltinMolecules()
|
||||||
|
|
||||||
if len(molecules) != 4 {
|
if len(molecules) != 6 {
|
||||||
t.Errorf("expected 4 built-in molecules, got %d", len(molecules))
|
t.Errorf("expected 6 built-in molecules, got %d", len(molecules))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify each molecule can be parsed and validated
|
// Verify each molecule can be parsed and validated
|
||||||
@@ -172,3 +172,61 @@ func TestInstallGoBinaryMolecule(t *testing.T) {
|
|||||||
t.Errorf("install should have no deps, got %v", steps[0].Needs)
|
t.Errorf("install should have no deps, got %v", steps[0].Needs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPolecatWorkMolecule(t *testing.T) {
|
||||||
|
mol := PolecatWorkMolecule()
|
||||||
|
|
||||||
|
if mol.ID != "mol-polecat-work" {
|
||||||
|
t.Errorf("expected ID 'mol-polecat-work', got %q", mol.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mol.Title != "Polecat Work" {
|
||||||
|
t.Errorf("expected Title 'Polecat Work', got %q", mol.Title)
|
||||||
|
}
|
||||||
|
|
||||||
|
steps, err := ParseMoleculeSteps(mol.Description)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to parse: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should have 8 steps: load-context, implement, self-review, verify-tests,
|
||||||
|
// rebase-main, submit-merge, update-handoff, request-shutdown
|
||||||
|
if len(steps) != 8 {
|
||||||
|
t.Errorf("expected 8 steps, got %d", len(steps))
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedRefs := []string{
|
||||||
|
"load-context", "implement", "self-review", "verify-tests",
|
||||||
|
"rebase-main", "submit-merge", "update-handoff", "request-shutdown",
|
||||||
|
}
|
||||||
|
for i, expected := range expectedRefs {
|
||||||
|
if i >= len(steps) {
|
||||||
|
t.Errorf("missing step %d: expected %q", i, expected)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if steps[i].Ref != expected {
|
||||||
|
t.Errorf("step %d: expected ref %q, got %q", i, expected, steps[i].Ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify key dependencies
|
||||||
|
// load-context has no deps
|
||||||
|
if len(steps[0].Needs) != 0 {
|
||||||
|
t.Errorf("load-context should have no deps, got %v", steps[0].Needs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// implement needs load-context
|
||||||
|
if len(steps[1].Needs) != 1 || steps[1].Needs[0] != "load-context" {
|
||||||
|
t.Errorf("implement should need load-context, got %v", steps[1].Needs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// rebase-main needs self-review and verify-tests
|
||||||
|
if len(steps[4].Needs) != 2 {
|
||||||
|
t.Errorf("rebase-main should need 2 deps, got %v", steps[4].Needs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// request-shutdown needs update-handoff
|
||||||
|
if len(steps[7].Needs) != 1 || steps[7].Needs[0] != "update-handoff" {
|
||||||
|
t.Errorf("request-shutdown should need update-handoff, got %v", steps[7].Needs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user